Compare commits

...

290 Commits

Author SHA1 Message Date
cora 04f0ea260d Merge pull request 'Add shields and offhand (Fix #295)' (#2073) from NO11/MineClone2:shields2 into master
Reviewed-on: MineClone2/MineClone2#2073
Reviewed-by: AFCMS <afcm.contact@gmail.com>
Reviewed-by: kabou <kabou@noreply.git.minetest.land>
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-03-28 14:55:11 +00:00
NO11 5974b6f609 Merge branch 'master' into shields2 2022-03-28 12:27:57 +00:00
NO411 148be4ea39 Fix shield behavior 2022-03-27 19:52:36 +02:00
NO411 6afe7cfb58 Fix typo and interact bug? 2022-03-27 18:08:43 +02:00
cora 8e24e6edfe Merge pull request 'Fix Barrel protection and add proper log for interactions (#2086)' (#2087) from barrel_fix into master
Reviewed-on: MineClone2/MineClone2#2087
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-03-25 13:16:52 +00:00
AFCMS 909b77ce4d
barrel protection fix + log 2022-03-25 13:28:33 +01:00
cora 1dde51dd0b Merge pull request 'Fix passive mobs not spawning in certain biomes ( #2069 )' (#2085) from fix-mobs-spawning into master
Reviewed-on: MineClone2/MineClone2#2085
2022-03-24 16:00:24 +00:00
NO11 63a156c30c Fix typo/crash 2022-03-23 18:30:34 +00:00
cora 1c9f0c3238 don't spawn mobs on non opaque nodes or leaves
with the preliminary jordanspaning mobs would spawn on trees
and water regularly.
2022-03-22 22:02:15 +01:00
cora 50e99f470e fix certain mobs not spawning in certain biomes 2022-03-22 15:16:48 +01:00
NO411 aeff7cf1a4 Remove offhand item on death 2022-03-22 12:48:41 +01:00
cora bc723616ea Merge pull request 'Fix undefined luaentity crash.' (#2084) from fix-unregistered-collisions into master
Reviewed-on: MineClone2/MineClone2#2084
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-03-21 10:31:20 +00:00
kabou 46ee5aaa59 Fix undefined luaentity crash.
* Add nil check to get_luaentity() access.
* Cache get_luaentity() call in local var.
2022-03-21 01:39:02 +00:00
cora 3dd4eec4e8 Merge pull request 'Add `group:supported_node` (for carpets).' (#2077) from kabou/MineClone2:add-group-supported_nodes into master
Reviewed-on: MineClone2/MineClone2#2077
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-03-21 00:31:53 +00:00
NO411 019dd45381 Check for damager 2022-03-19 16:50:19 +01:00
NO411 d481f7b720 Fix showing shield hud at the wrong side for half a second 2022-03-19 15:59:59 +01:00
NO411 c94964d10a Remove debug line 2022-03-19 15:26:41 +01:00
kabou a9a3f01a0e Tiny comment fix. 2022-03-19 03:16:15 +01:00
kabou ae6bea73fd Make carpets `supported_node`.
* Change carpet from `group:attached_node` to `group:supported_node`,
  allowing carpets to be placed on top of torches, water source blocks
  and other non-walkable nodes, like in MC.
2022-03-19 02:32:46 +01:00
kabou 2002872af8 Add group `supported_node` to GROUPS.md. 2022-03-19 02:32:29 +01:00
kabou 8518ce2c19 Add support for `group:supported_node`
* Add support for `group:supported_node` to CORE/mcl_attached.
  Supported nodes are nodes that can be placed on any node that does not
  have the `drawtype = "airlike"` attribute.
* Copy the `drop_attached_node()` function from minetest/builtin, so
  that the override function provides the same behavior when nodes drop.
* Add comments to CORE/mcl_attached and to the functions defined in it.
* Add more local aliases for global minetest.* functions.
* If the original function returns true, it is not necessary anymore
  to perform more tests and the override function can simply return true
  immediately.
2022-03-19 02:32:13 +01:00
NO411 6158e4e50d Don't always update shield texture using set_properties 2022-03-18 23:23:01 +01:00
NO411 7c0a48bebf Remove some code ... 2022-03-18 23:08:50 +01:00
NO411 5bdf83cbfc Revert weird changes 2022-03-18 23:07:25 +01:00
NO411 976cfba53a Make it possible to xraft a banner on an enchanted shield 2022-03-18 23:02:51 +01:00
NO411 fc9e83c059 Make it possible to craft a banner on an enchanted shield 2022-03-18 23:02:25 +01:00
NO411 60d877b718 Fix enchanting shield on enchanting table possible 2022-03-18 22:45:12 +01:00
cora 81a1b9973a Merge pull request 'More burning HUD fixes (kabou)' (#2076) from fix-burning-hud into master
Reviewed-on: MineClone2/MineClone2#2076
2022-03-18 10:52:07 +00:00
kabou 9eba0e4860 Remove unused code.
* Remove unused code that was commented out.  The code tried to find
  fire luaentities in the same spot as the newly created fire luaentity.
  It may have been intended to optimize getting set on fire multiple
  times, but it makes no sense as it does not discriminate between fire
  luaentities attached to the object set on fire and those attached to
  other objects.  The function that this code was in also has a better
  way to prevent adding multiple fire luaentities in the first place.
2022-03-18 11:39:11 +01:00
kabou 90311da514 Preempt possible crash on nil in on_joinplayer.
* In mineclone5 a crash was reported to occur when deserialization of
  storage returned nil in on_joinplayer.    https://git.minetest.land/
  MineClone5/MineClone5/commit/96c4fb60d8641b4181edb902ed24dbf173828d09
  This commit uses a different, but equally effective fix.
2022-03-18 11:36:33 +01:00
kabou e9ff2ba32a Minor changes to mcl_burning.
* Remove animation_frame from fire entity state, it is now kept in the
  storage table of the parent entity.
* Rename animation_timer in fire entity table to _mcl_animation_timer,
  in line with mineclone2 policy on adding custom members to minetest
  tables.
* Comment out code that does nothing sensible.  Scheduled for deletion
  at a later time.
2022-03-18 11:36:23 +01:00
cora 0b89149fe2 Merge pull request 'Update readme to reflect correct MT version, bump version to 0.73 (dev)' (#2074) from fix_readme_compat into master
Reviewed-on: MineClone2/MineClone2#2074
2022-03-17 21:07:44 +00:00
cora 7df6c8739e update version to 0.73.0 (in development) 2022-03-16 12:48:02 +01:00
cora cd725137ae update readme to reflect correct MT version 2022-03-16 12:38:04 +01:00
NO411 0f8f5a41d2 Fix dependencies 2022-03-15 16:30:03 +01:00
NO411 db68c0e26b Add shield 2022-03-15 15:58:27 +01:00
NO11 627da6d305 Merge pull request 'master' (#16) from MineClone2/MineClone2:master into master
Reviewed-on: NO11/MineClone2#16
2022-03-15 14:22:26 +00:00
cora 1803cc560d Merge pull request 'Remove stray work notes files.' (#2071) from delete-temp-notes into master
Reviewed-on: MineClone2/MineClone2#2071
2022-03-15 11:05:46 +00:00
kabou 3f787f8305 Remove stray work notes files.
* These temp files accidentally got added during the unregistered nodes
  fixes.
2022-03-15 07:42:11 +01:00
epCode 9534624b21 Merge pull request 'fix #2068' (#2070) from epcode-patch-1 into master
Reviewed-on: MineClone2/MineClone2#2070
2022-03-15 02:18:32 +00:00
epCode 4483f4b6b6 fix #2068 2022-03-15 02:18:02 +00:00
cora d3bfdb190e Merge pull request 'Fix frost walker enchant not protecting from magma block damage (#2064)' (#2065) from frost_walker_fix into master
Reviewed-on: MineClone2/MineClone2#2065
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-03-13 19:03:06 +00:00
AFCMS 47b1eeda74
fix frost walker enchant not protecting from magma block damage 2022-03-13 19:11:28 +01:00
cora ba0e2cbf29 Merge pull request 'item pickup sound gain more MC like' (#2054) from pepebotella/MineClone2:pop_sound into master
Reviewed-on: MineClone2/MineClone2#2054
2022-03-13 14:08:48 +00:00
Freedom f430aec0cd
item pickup sound gain more MC like 2022-03-13 14:58:01 +01:00
NO11 a44846a82c Merge pull request 'master' (#15) from MineClone2/MineClone2:master into master
Reviewed-on: NO11/MineClone2#15
2022-03-12 22:42:24 +00:00
cora 22edd08387 Merge pull request 'Make carpets walkable.' (#2060) from fix-carpets-walkable into master
Reviewed-on: MineClone2/MineClone2#2060
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-03-12 13:37:29 +00:00
kabou 17b8eab368 Make carpets walkable.
* Make carpets walkable.  When a carpet is placed on top of a fence or a
  wall, the carpet can be jumped upon, allowing to in effect jump over
  fences and walls.
2022-03-12 13:35:12 +00:00
cora 119b4aa82c Merge pull request 'Update version and credits for release' (#2059) from update_docs_for_073 into master
Reviewed-on: MineClone2/MineClone2#2059
Reviewed-by: AFCMS <afcm.contact@gmail.com>
Reviewed-by: NO11 <no11@noreply.git.minetest.land>
Reviewed-by: kabou <kabou@noreply.git.minetest.land>
2022-03-11 11:47:03 +00:00
cora 181c3f0c0f Remove kay27 from (previous) maintainers 2022-03-10 21:28:37 +01:00
cora 21e7ab1f2a Update mcl5 contributors, add mineclonia 2022-03-10 19:04:00 +01:00
cora 6f284c0c95 Update Credits 2022-03-10 19:04:00 +01:00
cora e0801ba7e4 Remove in development from readme 2022-03-10 19:03:06 +01:00
cora 267031793d Merge pull request 'Fix composters, & barrels not being able to be used as smelting fuel.' (#2057) from make_barrels_composters_furnace_fuel into master
Reviewed-on: MineClone2/MineClone2#2057
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-03-10 11:31:32 +00:00
MysticTempest de3cdee09e Make composters & barrels fuel for furnaces with the same burntime as chests. 2022-03-10 00:47:54 -06:00
cora c5993a60ae Merge pull request 'Fix daylight sensor.' (#2041) from fix-daylight-sensor into master
Reviewed-on: MineClone2/MineClone2#2041
2022-03-09 22:50:29 +00:00
Nils Dagsson Moskopp 77f8ecd6e8 Make daylight detector work in Minetest 5.3.0
This patch contains a function that searches for a path to a node with
light level 15, which is guaranteed to be sunlight.
2022-03-09 22:33:08 +00:00
Nils Dagsson Moskopp 4da5084daf Make daylight detector ignore artificial light
The daylight detector code used get_node_light(), which detects both
natural and artificial light. This patch improves the code to use
get_natural_light(), which was introduced with Minetest 5.4.0.
2022-03-09 22:33:08 +00:00
cora dca653651c Merge pull request 'Fix potential crashes due to unregistered nodes.' (#2055) from fix-unregistered-nodes into master
Reviewed-on: MineClone2/MineClone2#2055
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-03-09 22:16:27 +00:00
kabou deed231f28 Fix typos. 2022-03-09 18:50:41 +01:00
kabou 11ee1d133f Fix cut-n-paste error.
* Swap misplaced lines.
* Concatenate conditional expression.
2022-03-09 18:26:51 +01:00
kabou 1326b9e7e7 Add check for unknown nodes.
* Check if node has a definition table before attempting to evaluate its
  attributes.  By application of De Morgan's law, the compound logic
  expression can be rewritten so that the existence of the table is
  checked before all following attribute references.
2022-03-09 15:14:22 +01:00
kabou 6a69f49fa0 Add check for unknown nodes.
* Check if node has a definition table before attempting to evaluate its
  attributes.
2022-03-09 14:59:49 +01:00
kabou f5a8d6d17a Add check for unknown nodes.
* Check if node has a definition table before attempting to evaluate its
  attributes.
* Define local variable to cache multiple accesses to `registered_nodes[]`
  and improve readability.
* Clarify code flow.
2022-03-09 14:40:37 +01:00
kabou 3f4dafc68f Add check for unknown nodes.
* Check if node has a definition table before attempting to evaluate its
  attributes.
* Define local variable to cache multiple accesses to `registered_nodes[]`
  and improve readability.
2022-03-09 14:14:45 +01:00
kabou 9bac0da01a Fix registered_items oddity and add check for unknown nodes.
* Mobs redo uses `registered_items[]` where clearly the proper table
  accessed should be `registered_nodes[]`.  Perhaps this magically
  works, but it looks nonsensical.  Switch to the use the more
  sensible `registered_nodes[]` table.
* Check if node has a definition table before attempting to evaluate its
  attributes.
* Define local variable to cache multiple accesses to `registered_nodes[]`
  and improve readability.
2022-03-09 13:11:53 +01:00
kabou 818cbb2f48 Add check for unknown nodes.
* Check if node has a definition table before attempting to evaluate its
  attributes.
* Define local variable to cache multiple accesses to `registered_nodes[]`
  and improve readability.
2022-03-09 12:11:59 +01:00
kabou 88f7a150c7 Add check for unknown nodes.
* Add check for unknown node in `handle_node_drops()` and return
  immediately if the dug node has no definition table.
2022-03-09 04:00:48 +01:00
kabou 962500b189 Add check for unknown nodes.
* Check if node has a definition table before attempting to evaluate its
  attributes.
* Define local variable to cache multiple accesses to `registered_nodes[]`
  and improve readability.
2022-03-09 02:23:18 +01:00
kabou 95cfa43483 Add check for unknown nodes.
* Check if node has a definition table before attempting to evaluate its
  attributes.
* Define local variable to cache multiple accesses to `registered_nodes[]`
  and improve readability.
2022-03-09 02:15:33 +01:00
kabou 4a1b93bbfa Add check for unknown nodes.
* Check if node has a definition table before attempting to evaluate its
  attributes.
* Define local variable to cache multiple accesses to `registered_nodes[]`
  and improve readability.
2022-03-09 02:05:38 +01:00
kabou b9c2c3bd0a Add check for unknown nodes.
* Check if node has a definition table before attempting to evaluate
  attributes.
* Define local variable to cache multiple accesses to `registered_nodes[]`
  and improve readability.
* Reduce redundant `== false` condition check.
2022-03-09 00:01:23 +01:00
cora 52333cea0f Merge pull request 'ITEMS/mcl_anvils: fix renaming items without description' (#1914) from fix-anvil-renaming into master
Reviewed-on: MineClone2/MineClone2#1914
Reviewed-by: MysticTempest <mystictempest@noreply.git.minetest.land>
2022-03-07 01:43:47 +00:00
Dieter44 f8c60b5f75 ITEMS/mcl_anvils: fix renaming items w/o desc… 2022-03-05 15:35:39 +00:00
cora bcf302ceb0 Merge pull request 'Rename a few textures to help support texture packs.' (#2045) from MysticTempest/MineClone2:Texture_pack_support into master
Reviewed-on: MineClone2/MineClone2#2045
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-03-05 02:57:00 +00:00
MysticTempest 7a53ea8b70 Rename a few textures to help support texture packs. 2022-03-02 20:13:24 -06:00
cora e8ff33a741 Merge pull request 'Alternative solution to fix crash on nether portal destruction' (#2029) from ryvnf-portal-removal into master
Reviewed-on: MineClone2/MineClone2#2029
2022-03-03 01:51:49 +00:00
Elias Åström 3c10f0e970 Rewrite portal removal to avoid stack overflow
This solves a problem were nether portal removal would trigger deep
recursion through node callbacks.  For large portals this could result
in stack overflow crashes on LuaJIT.  The issue is solved by rewriting
the portal removal to avoid recursion and removing the portal in one
operation using minetest.bulk_set_node.
2022-03-03 01:42:49 +00:00
cora f7d712543f Merge pull request 'Fix fire HUD' (#2042) from kabou/MineClone2:fix-burning-HUD into master
Reviewed-on: MineClone2/MineClone2#2042
2022-03-03 01:40:05 +00:00
kabou c3e0996902 Fix fire HUD not showing on join while burning.
* Add the fire HUD to a player who joins the server while still burning
  from the previous session.
2022-03-02 17:15:05 +01:00
kabou d424d4f10e Add comments to mcl_burning.update_hud(). 2022-03-02 16:39:27 +01:00
kabou e80006f4ea Do not set fire to objects that are already burning.
Changes to mcl_burning.set_on_fire():
* Add logic that only updates the burn time, but skips adding fire
  entities to objects that are already burning.
* Condense code a little, remove single use variables.
* Add a comment to a questionable piece of code.
* Add comments to the function.
2022-03-02 16:25:40 +01:00
kabou b17776699e Add comments to "storage" table.
* Document attributes of the "storage" table.
2022-03-02 15:40:29 +01:00
kabou 86a4ece7d2 Add local copy of minetest.find_nodes_in_area. 2022-03-02 15:25:03 +01:00
kabou df5d24104d Make player burning HUD work without csm.
* Add update_hud() function.
* Remove the client channels.
* Unglobalize animation_frames variable.
* Fix bug where player state was not stored on shutdown of singleplayer
  game.
* Remove superfluous sanity_check() function, this code could easily be
  inlined in its only caller.
2022-03-02 15:21:55 +01:00
cora 8dd540269c Merge pull request 'Fix burning entity animation.' (#2039) from kabou/MineClone2:fix-burning-entities into master
Reviewed-on: MineClone2/MineClone2#2039
2022-03-02 11:34:37 +00:00
kabou 56b63463a5 Fix burning entity animation.
The parameters for the flames sprite were incorrect, causing the reverse
side of the sprite to appear as an opaque black rectangle.  Use the
correct incantation.
2022-03-02 10:47:46 +01:00
cora c2ae28aec1 Merge pull request 'Fix TGA file writing on Windows' (#1985) from fix-tga-file-writing-on-windows into master
Reviewed-on: MineClone2/MineClone2#1985
Reviewed-by: AFCMS <afcms@noreply.git.minetest.land>
2022-02-28 17:10:51 +00:00
Nils Dagsson Moskopp 66bb209ad1 Fix TGA file writing on Windows
Before this patch, the tga_encoder mod would write corrupted TGA files
on Windows: Bytes that looked like newlines were replaced by a carriage
return and a newline.
2022-02-28 16:58:59 +00:00
cora a3e01e6dbe Merge pull request 'Add Target' (#2033) from AFCMS/MineClone2:target into master
Reviewed-on: MineClone2/MineClone2#2033
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-02-27 17:25:16 +00:00
AFCMS 5a7b1cc382
make all arrow types activate target (+ depends and code fixes) 2022-02-26 23:52:03 +01:00
AFCMS 210a0d8ee1
make lingering potions activate target (+ indentation fix) 2022-02-26 22:44:50 +01:00
AFCMS eae8effd57
make splash potions activate target 2022-02-26 22:42:27 +01:00
AFCMS b51e322304
make fire charges activate target (+ fix possible crash) 2022-02-26 22:38:34 +01:00
AFCMS 096d46152e
make bottle o enchanting activate target 2022-02-26 22:20:05 +01:00
AFCMS d89687984b
make ender pearls activate target 2022-02-26 22:16:10 +01:00
AFCMS c6f72c473f
make eggs activate target 2022-02-26 22:12:26 +01:00
AFCMS 540b72f1d6
add target help text 2022-02-26 19:12:02 +01:00
AFCMS 7449725a56
add target crafting receipe 2022-02-26 19:12:01 +01:00
AFCMS 9e7a525a0a
make snowballs activate target 2022-02-26 19:12:01 +01:00
AFCMS 4bd91750bc
add target with API 2022-02-26 19:12:01 +01:00
cora 8e1a9e1785 Merge pull request 'mapgen/mcl_mapgen_core: move set_node decorations a node callback' (#2028) from fix-nether-wart into master
Reviewed-on: MineClone2/MineClone2#2028
2022-02-25 21:28:40 +00:00
E 87e494f42b mapgen/mcl_mapgen_core: move set_node decorations a node callback
During the rewrite in 89e55e9065, a queue system was added to allow
using both VoxelManip-based generation steps, and set_node-based steps,
however some set_node-based steps (underground mushrooms, nether
decorations, and structures) were missed and remained in a VoxelManip
step. The result is that the changes made by the set_node stages were
overwritten after the (now-stale) VoxelManip data was committed later.

(ref. Mineclonia/Mineclonia#26)
2022-02-25 18:38:50 +01:00
cora dfed21ee14 Merge pull request 'Revert mob rewrite' (#1992) from revert-to-oldmobs into master
Reviewed-on: MineClone2/MineClone2#1992
2022-02-25 16:47:47 +00:00
cora 3feca330c9 fix the other 2 throw_xp occurences 2022-02-25 00:40:26 +00:00
cora caacb378de fix api change in enchanting 2022-02-25 00:40:26 +00:00
cora 379972ea11 fix crash when blaze attacks logged off player 2022-02-25 00:40:26 +00:00
cora 414e2e7725 fix crash on opening villager formspec 2022-02-25 00:40:26 +00:00
cora 435b5d756d throw_experience->throw_xp (api change) 2022-02-25 00:40:26 +00:00
cora 2bb416765c revert to old mobs ( 32c03dc27e )
This reverts the hierarchies ENTITIES/mcl_mobs, ENTITIES/mobs_mc
and ENTITIES/mobs_mc_gameconfig to the state of commit
32c03dc27e
2022-02-25 00:40:26 +00:00
cora 02361b2d01 Merge pull request 'ITEMS/mcl_fire: fix laggy fire spread' (#1998) from fix-fire into master
Reviewed-on: MineClone2/MineClone2#1998
2022-02-25 00:17:47 +00:00
cora 86ca401e4e do not randomseed twice 2022-02-25 00:08:26 +00:00
cora 378b5b30c9 fix beds dropping when burning up 2022-02-25 00:08:26 +00:00
cora 840b705a22 make fire use abms instead of laggy node timers 2022-02-25 00:08:26 +00:00
cora 80c79dde1c Merge pull request 'Fix handheld maps not displaying in Minetest 5.5.0' (#2010) from fix-mcl-maps-in-minetest-5.5 into master
Reviewed-on: MineClone2/MineClone2#2010
2022-02-24 22:47:26 +00:00
Nils Dagsson Moskopp 27842aa2f5 Fix handheld maps not displaying in Minetest 5.5.0
The function dynamic_add_media() was changed in incompatible ways in
several minor versions of Minetest, breaking the display of handheld
maps in Minetest 5.5.0. This patch makes handheld maps display there.

The function was blocking with one argument in Minetest 5.3. It was also
blocking in Minetest 5.4, but took an additional argument for a function
to execute once the media had been received. Calling dynamic_add_media()
with a single argument had been deprecated; a function that did nothing
was provided in mcl_maps to satisfy the changed argument requirements.

In Minetest 5.5, dynamic_add_media() was changed to non-blocking. This
introduced a race condition in mcl_maps, where a client often tried to
display a map before it had received the map texture from the server.

Opening an issue on the Minetest issue tracker led to it being closed in
about 20 minutes: <https://github.com/minetest/minetest/issues/11997>
2022-02-24 22:43:45 +00:00
cora 85e0e23c76 Merge pull request 'Fix redstone comparator flooding crash by erlehmann' (#2027) from fix-comparator-crash into master
Reviewed-on: MineClone2/MineClone2#2027
2022-02-24 21:35:12 +00:00
Nils Dagsson Moskopp 41550da87b Fix redstone comparator flooding crash
Redstone comparators have two modes, comparison mode & subtraction mode.
Before this patch, the functions to turn comparators on or off attempted
to swap nodes with comparators in the same mode, but failed to determine
the correct replacement node, if the existing node was not a comparator.

When a comparator in an on state (e.g. powered by a filled cauldron) was
flooded, the flooding dropped the comparator and replaced the comparator
node that was to be swapped out with air, which lead to a server crash.

This patch changes the functions that turn comparators on or off so they
only swap existing nodes with comparators in the same mode if the name
of the replacement node can be determined – i.e. if it is not nil.
2022-02-24 15:52:01 +01:00
cora a4e541bcd2 Merge pull request 'remove blend1 file / add blend1 files to gitignore (fix #2015)' (#2024) from AFCMS/MineClone2:remove-blend1 into master
Reviewed-on: MineClone2/MineClone2#2024
Reviewed-by: Nicu <kneekoo@noreply.git.minetest.land>
2022-02-24 14:48:51 +00:00
AFCMS 89a930ace3
add `.blend2` and `.blend3` files to gitignore 2022-02-24 10:16:48 +01:00
AFCMS 129117efb3
add `.blend1` files to gitignore 2022-02-24 10:16:47 +01:00
AFCMS cbfc71705d
remove blender backup file 2022-02-24 10:16:47 +01:00
cora 4b89398b3b Merge pull request 'Fix hopper breakage in get_item_group return value. (Fixes: #2022)' (#2023) from kabou/MineClone2:fix-hoppers into master
Reviewed-on: MineClone2/MineClone2#2023
Reviewed-by: AFCMS <afcms@noreply.git.minetest.land>
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-02-24 02:23:09 +00:00
kabou 5431e206b0 Fix hopper breakage in get_item_group return value.
In commit 55009c257e that added vectors to
mcl_composters, mcl_hoppers was accidentally patched with a unrelated
change, updating it to get_item_group().  This mostly works, but in one
particular case the semantics of the return value differs.  Instead of
returning 'nil' it returns '0'.  That altered the evaluation of an if
condition, breaking the abm that sucks in items.

This commit fixes the conditional by explicitly comparing  '~= 0'.
2022-02-24 03:18:25 +01:00
cora c60fd92638 Merge pull request 'Traditional chinese by emojigit (partial)' (#2026) from emojigit-zh-trans into master
Reviewed-on: MineClone2/MineClone2#2026
2022-02-23 23:29:52 +00:00
1F616EMO 06deb92dd6 mcl_tools 2022-02-23 23:58:05 +01:00
1F616EMO 7685b4758f mcl_flowers 2022-02-23 23:58:05 +01:00
1F616EMO 9944abb328 mcl_books 2022-02-23 23:58:05 +01:00
1F616EMO 5ce1852c1d mcl_dye 2022-02-23 23:58:05 +01:00
1F616EMO 56a70025b8 mcl_flowerpots 2022-02-23 23:58:05 +01:00
1F616EMO 9fe3bbd2fa mcl_mushrooms 2022-02-23 23:58:05 +01:00
1F616EMO fb1d189d40 mcl_doors 2022-02-23 23:58:05 +01:00
1F616EMO 9cd24f4af5 mcl_commands 2022-02-23 23:58:05 +01:00
1F616EMO a64c3f87bc xpanes 2022-02-23 23:58:05 +01:00
1F616EMO 5075f2ca56 mcl_armor 2022-02-23 23:58:05 +01:00
1F616EMO 249dfac319 mcl_inventory 2022-02-23 23:58:05 +01:00
1F616EMO 2b5a0242db mcl_fire 2022-02-23 23:58:05 +01:00
1F616EMO 790ccf0812 mcl_fishing 2022-02-23 23:58:05 +01:00
1F616EMO 8d639794f3 mcl_fences 2022-02-23 23:58:05 +01:00
1F616EMO af8681c143 mcl_buckets 2022-02-23 23:58:05 +01:00
1F616EMO 1ef58f7250 mcl_walls 2022-02-23 23:58:05 +01:00
1F616EMO 15747220f2 mcl_hoppers 2022-02-23 23:58:05 +01:00
1F616EMO 925dad7f5e mcl_anvils 2022-02-23 23:58:05 +01:00
1F616EMO 729f653c85 mcl_portals 2022-02-23 23:58:05 +01:00
1F616EMO d1e328e57a mcl_bows 2022-02-23 23:58:05 +01:00
1F616EMO 615a968fbb mcl_skins 2022-02-23 23:58:05 +01:00
1F616EMO 7e5a9bd8b6 mcl_throwing 2022-02-23 23:58:05 +01:00
1F616EMO d018bee00a mcl_cake 2022-02-23 23:58:05 +01:00
1F616EMO 1365d0b257 mcl_jukebox 2022-02-23 23:58:05 +01:00
1F616EMO a289a00427 mcl_heads 2022-02-23 23:58:05 +01:00
1F616EMO a238aabbb0 mcl_cauldrons 2022-02-23 23:58:05 +01:00
1F616EMO b02f7cd974 mcl_mobs 2022-02-23 23:58:05 +01:00
1F616EMO e19113d4e0 findbiome 2022-02-23 23:58:05 +01:00
1F616EMO 4deac632e6 mcl_sponges 2022-02-23 23:58:05 +01:00
1F616EMO c480e6891d mcl_maps 2022-02-23 23:58:05 +01:00
1F616EMO 844eb3fb7c mcl_brewing 2022-02-23 23:58:05 +01:00
1F616EMO fc768cb1ad mcl_signs 2022-02-23 23:58:05 +01:00
1F616EMO 1f9a919459 mcl_monster_eggs 2022-02-23 23:58:05 +01:00
1F616EMO 70007e3453 mcl_furnaces 2022-02-23 23:58:05 +01:00
1F616EMO 3aff1f8981 mcl_hunger 2022-02-23 23:58:05 +01:00
1F616EMO c86a506672 mcl_tnt 2022-02-23 23:58:05 +01:00
1F616EMO f348223da2 mcl_crafting_table 2022-02-23 23:58:05 +01:00
1F616EMO ca6469b959 mcl_weather 2022-02-23 23:58:05 +01:00
1F616EMO c52e09ddcd mcl_structures 2022-02-23 23:58:05 +01:00
1F616EMO bb55120adc mcl_experience 2022-02-23 23:58:05 +01:00
1F616EMO 77339afbe2 mcl_cocoas 2022-02-23 23:58:05 +01:00
1F616EMO 9b15599bee hudbars 2022-02-23 23:58:05 +01:00
1F616EMO a685c3bc83 mclx_core 2022-02-23 23:58:05 +01:00
1F616EMO b01d4eba88 mcl_paintings 2022-02-23 23:58:05 +01:00
1F616EMO 952747d4da mcl_mobspawners 2022-02-23 23:58:05 +01:00
1F616EMO 430f5b05ab mcl_itemframes 2022-02-23 23:58:05 +01:00
1F616EMO e4a311e28a mcl_clock 2022-02-23 23:58:05 +01:00
1F616EMO 6a115a68ef mcl_armor_stand 2022-02-23 23:58:05 +01:00
1F616EMO f3d0ec845c mcl_spawn 2022-02-23 23:58:05 +01:00
1F616EMO 563daeed8a mcl_wip 2022-02-23 23:58:05 +01:00
1F616EMO a6c3cab791 mclx_fences 2022-02-23 23:58:05 +01:00
1F616EMO bb4ddee570 mcl_compass 2022-02-23 23:58:05 +01:00
1F616EMO fe3e80bc0e lightning 2022-02-23 23:58:05 +01:00
1F616EMO 59fe078fd7 mcl_playerplus 2022-02-23 23:58:05 +01:00
1F616EMO dba08ddc1f mcl_torches 2022-02-23 23:58:05 +01:00
1F616EMO 551bf917e2 mcl_void_damage 2022-02-23 23:58:05 +01:00
1F616EMO 26dadb1846 mcl_falling_nodes 2022-02-23 23:58:05 +01:00
1F616EMO 33a353e20d mcl_privs 2022-02-23 23:58:05 +01:00
1F616EMO f02f3c9f40 screwdriver 2022-02-23 23:58:05 +01:00
1F616EMO 410c1ecd1f mcl_hbarmor 2022-02-23 23:58:05 +01:00
1F616EMO ba172f0847 mcl_explosions 2022-02-23 23:58:05 +01:00
1F616EMO ad42c3588b mcl_farming 2022-02-23 23:58:05 +01:00
1F616EMO 9734c74c56 (WIP) mcl_farming 2022-02-23 23:58:05 +01:00
1F616EMO c3dd5e6c2c MORE MESS SORRY XD 2022-02-23 23:58:05 +01:00
1F616EMO 21808390f9 Revert "add translates for `mcl_boats`"
This reverts commit 2ee84f2ad3bd1f067a43c9382d7fc70f30fab9f0.
2022-02-23 23:58:05 +01:00
1F616EMO cc87791327 add translates for `mcl_boats`
Co-authored-by: Emojigit <emojigit@noreply.git.minetest.land>
2022-02-23 23:58:04 +01:00
1F616EMO f8cd01a15e add translate of README.md 2022-02-23 23:58:04 +01:00
1F616EMO a8aabb2329 add translate for `doc_identifier` 2022-02-23 23:58:04 +01:00
1F616EMO 4f00b62a18 add zh_TW translate to `mcl_beds` and `mcl_core` 2022-02-23 23:58:04 +01:00
cora 97412b139a Merge pull request 'Add @epCode logo (fix #1955)' (#2021) from AFCMS/MineClone2:epCode-logo into master
Reviewed-on: MineClone2/MineClone2#2021
2022-02-23 17:55:50 +00:00
AFCMS ceb27b6929
obtimize icons again
`optipng -strip all -o9`
2022-02-23 16:30:08 +01:00
AFCMS b2614f8d78
make menu icon smaller (128x) 2022-02-23 16:30:07 +01:00
AFCMS 84596b2ebb
add @epCode logo 2022-02-23 16:30:07 +01:00
cora 6bb6966752 Merge pull request 'Add Barrel' (#1977) from AFCMS/MineClone2:barrels into master
Reviewed-on: MineClone2/MineClone2#1977
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-02-22 19:38:04 +00:00
AFCMS 360a1604ba
Revert "move barrels to mcl_chests"
This reverts commit a272322cb5.
2022-02-22 20:20:21 +01:00
AFCMS 61f4c5b885
apply @kay27 fix to `mcl_util.drop_items_from_meta_container` 2022-02-22 18:08:26 +01:00
AFCMS a272322cb5
move barrels to mcl_chests 2022-02-22 18:08:25 +01:00
AFCMS 9112915ddd
fix barrel top texture rotation 2022-02-22 18:08:25 +01:00
AFCMS 397c243e89
cleanup barrel TODO list 2022-02-22 18:08:25 +01:00
AFCMS c64d0e4558
simplify random dropping position code 2022-02-22 18:08:24 +01:00
AFCMS 61e54ed617
rename `mcl_util.drop_items_container_get` to `drop_items_from_meta_container` 2022-02-22 18:08:24 +01:00
AFCMS 0988637ea1
add barrel tooltip help text 2022-02-22 18:08:24 +01:00
AFCMS b88060dbfb
add doc description to barrels 2022-02-22 18:08:23 +01:00
AFCMS e3e06b4a4b
fix broken tree placement 2022-02-22 18:08:23 +01:00
AFCMS 34b445b04a
fixes 2022-02-22 18:08:22 +01:00
AFCMS d41a836514
add craft 2022-02-22 18:08:22 +01:00
AFCMS 80fb59f9ac
add barrel 2022-02-22 18:08:22 +01:00
cora dae7c22dd9 Merge pull request 'PLAYER/mcl_playerplus: Do not send redundant bone position and properties' (#1990) from fix-playerplus-packetspam into master
Reviewed-on: MineClone2/MineClone2#1990
2022-02-22 17:00:29 +00:00
cora a9357f7380 Do not send redundant bone position and properties 2022-02-22 11:15:56 +00:00
cora dcfbfd67b8 Merge pull request 'Quick fix: Reinstate nil check in on_place_bucket.' (#2018) from kabou/MineClone2:fix-buckets-cauldrons into master
Reviewed-on: MineClone2/MineClone2#2018
Reviewed-by: AFCMS <afcms@noreply.git.minetest.land>
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-02-21 19:54:35 +00:00
kabou af132cc523 Reinstate nil check in on_place_bucket.
* Oops, nil checks on registered_node[name] were erroneously optimized
  away, risking crashes.  Reinstate those checks.
2022-02-21 18:00:56 +01:00
cora a0b5e4dd0b Merge pull request 'fix filling cauldrons with water buckets and some minor refactoring.' (#2011) from kabou/MineClone2:fix-buckets-cauldrons into master
Reviewed-on: MineClone2/MineClone2#2011
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-02-21 15:18:02 +00:00
kabou e54502edd6 Add more local aliases for minetest.* namespace functions
* Add locals for
  - minetest.is_creative_enabled
  - minetest.is_protected
  - minetest.record_protection_violation
2022-02-20 20:24:55 +01:00
kabou 639bf936c5 Use alias for minetest.* namespace function call.
* Fix one missed minetest.get_node use in earlier commit.
2022-02-20 19:52:05 +01:00
kabou d2261426c3 Remove redundant variables in on_place_bucket.
The function on_place_bucket defined a couple of variables that were
used only once or in a redundant check.  After removal of the redundant
check in a previous commit, all use-once variables can now be substituted
with their assignment expressions.
2022-02-20 18:46:23 +01:00
kabou 88ce1e3662 Remove redundant logic.
The function on_place_bucket contains the following logic:
  if not a and not b then return x end
  if a then
    foo(a)
  elseif b then
    foo(b)
  else
    return x
  end

The "if not a and not b then .." is removed because the case is handled
by the else case later on.  This will allow some further simplifications.
2022-02-20 18:46:23 +01:00
kabou b3aed9d6b8 Use proper get_item_group accessor.
Instead of directly accessing the group table in node definitions, use
the proper minetest.get_item_group accessor to test for "cauldron"
group.
Also adds local alias get_item_group for the global minetest call.
2022-02-20 18:46:23 +01:00
kabou 13baa68b67 Fixed missed alias uses and added set_node alias.
Two instances of add_node and add_item still used the full minetest
call, substitute the alias.
Added a set_node alias for several minetest.set_node calls.
2022-02-20 18:46:23 +01:00
kabou 315f251584 Add local to speedup global function access.
The minetest.registered_nodes function is called from multiple places.
Define a local alias registered_nodes and substitute it in all calls.
2022-02-20 18:46:23 +01:00
kabou 584a75df76 Fix filling cauldrons with water.
When using a bucket of water on a cauldron, this would not fill the
cauldron as expected, but deposit a water source block on top of the
cauldron instead.

Applied patch from mineclone5 #38 (commit #
698c29733f06a7fcb7e755bf26ee46b33b00699b) from mineclone5 that fixes
this problem.
2022-02-20 18:46:23 +01:00
cora c392fd0269 Merge pull request 'mcl_composters initial commit' (#2005) from kabou/MineClone2:composters into master
Reviewed-on: MineClone2/MineClone2#2005
Reviewed-by: cora <cora@noreply.git.minetest.land>
Reviewed-by: NO11 <no11@noreply.git.minetest.land>
Reviewed-by: AFCMS <afcms@noreply.git.minetest.land>
2022-02-19 23:42:45 +00:00
kabou 8d18ab8a7a Optimize texture files.
* Texture files were optimized with 'optipng  -o7 -zm9 -strip all' .
2022-02-19 21:18:01 +01:00
kabou f81980da51 Fix hardness and blast resistance.
* Use correct MC values for hardness and blast resistance.
2022-02-19 21:18:01 +01:00
kabou 55009c257e Use new vectors
* Use vector.new instead of xyz table.
2022-02-19 21:18:01 +01:00
kabou 51ca60c097 Change custom node attribute name.
* Rename _compost_level to _mcl_compost_level
2022-02-19 21:18:01 +01:00
kabou f22baafaa6 Add player object check.
* Add one more check if player object is an actual player.
2022-02-19 21:18:01 +01:00
kabou ffc2c94096 Add help alias
* Add help alias for the ready type composter
2022-02-19 21:18:01 +01:00
kabou cea821b2fa Comment fixes.
* Improve comments, some typo fixes.
2022-02-19 21:18:01 +01:00
kabou 64608f50f8 Update mod description and fix comment.
* Make mod description more descriptive.
* Minor comment tweak.
2022-02-19 21:18:01 +01:00
kabou 3257014e00 Add missing melon block.
* Add melon block to the compostabiles list.
2022-02-19 21:18:01 +01:00
kabou 06274518bf Add player object check.
* Handle the case where a mob somehow "clicks" on a composter and we get
  an invalid player object passed.
2022-02-19 21:18:01 +01:00
kabou 8d79d16531 Update mod deps.
* Add dpendency on mcl_dye for the bone meal particle spawner
2022-02-19 21:18:01 +01:00
kabou 1f7697b6f5 Typo fix.
* it's a spruceSapling (thanks NO11)
2022-02-19 21:18:01 +01:00
kabou 64203c38a6 Update documentation.
* Make a mention of the one second delay before composter readies.
2022-02-19 21:18:01 +01:00
kabou 4cf88abe4c Fix composter item image.
* Less is more (thanks AFCMS)
2022-02-19 21:18:01 +01:00
kabou df8576e77c mcl_composters initial commit
Implements a composter block with crafting recipe, and some more
uncraftable blocks representing various stages of filling.

Adds a list of items that can be used with the composter and the chances
of these items adding a layer to the composter.

Implements methods to add compostable items to the composter, to update
the composter to various levels of compost and to harvest an item of
bone meal when the composter is ready.

Textures were taken from XSSheep/Nova_Wostra Pixel Perfection texture
pack.
2022-02-19 21:18:01 +01:00
cora 6493f2885b Merge pull request 'Correct bucket behavior' (#2007) from NO11/MineClone2:buckets+ into master
Reviewed-on: MineClone2/MineClone2#2007
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-02-18 00:17:50 +00:00
NO11 c40c05f594 Exact MC behavior 2022-02-17 15:32:58 +00:00
NO11 8db28c1337 Update get_pointed_thing function 2022-02-17 15:30:41 +00:00
NO11 d46a96c43a Merge branch 'master' into buckets+ 2022-02-17 14:48:07 +00:00
NO11 3cfcd1355f Add missing dependency 2022-02-17 14:42:01 +00:00
NO11 4707cd4526 Correct bucket behavior 2022-02-17 14:36:48 +00:00
NO11 ad99746d99 Add get_pointed_thing function 2022-02-17 14:35:51 +00:00
cora cabf6e8cd1 Merge pull request 'Fix mob-in-boat crash in Minetest 5.5-dev' (#2000) from fix-boat-crash-2 into master
Reviewed-on: MineClone2/MineClone2#2000
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-02-15 12:00:03 +00:00
Nils Dagsson Moskopp adf738854a
Fix mob-in-boat crash in Minetest 5.5-dev
In Minetest 5.4.1, calling get_player_control() on a mob returned the
empty string. Minetest commit 5eb45e1ea03c6104f007efec6dd9c351f310193d
changed this, so now calling get_player_control() on a mob returns nil.

As mcl_boats defines boats that can have a player or a mob as a driver,
code like the following crashes with a changed get_player_control() API:

local ctrl = driver:get_player_control()
if ctrl.sneak then
    detach_object(driver, true)
end

Furthermore, once a world has crashed, joining it near a mob that is the
driver of a boat with such control code immediately crashes again.

When I reported this bug to Minetest, several Minetest core developers
stated that they disliked the old API and proposed other return values
for calling a mob's get_player_control() function – all different from
the empty string. Since I have some doubts that this bug will be fixed
in Minetest 5.5.0, boat code must take into account a nil return value.

Minetest issue: https://github.com/minetest/minetest/issues/11989
2022-02-15 11:17:01 +01:00
cora 87427cb8af Merge pull request '`mcl_armor` documentation' (#1917) from AFCMS/MineClone2:armor-doc into master
Reviewed-on: MineClone2/MineClone2#1917
2022-02-13 20:49:37 +00:00
AFCMS da4952a125
wip mcl_damage documentation 2022-02-13 21:31:04 +01:00
AFCMS c59bea211d
fix some typos 2022-02-13 21:31:03 +01:00
AFCMS 5aa18d573e
document mcl_armor function (WIP) 2022-02-13 21:31:03 +01:00
AFCMS 13f8fd457c
document manual armor creation 2022-02-13 21:31:03 +01:00
AFCMS 2b820d7756
`mcl_armor.register_set()` documentation 2022-02-13 21:31:02 +01:00
cora f803a25aea Merge pull request 'Fix bug when applying another enchantment to a renamed item' (#1989) from fix-1922 into master
Reviewed-on: MineClone2/MineClone2#1989
2022-02-12 20:37:48 +00:00
Elias Åström 4ca89cfcae Update groupcaps_hash function to minetest.sha1 2022-02-12 20:08:03 +01:00
Elias Åström a6c5c8a72a Call update_groupcaps from load_enchantments
This avoids the need to call the function from on_enchant for unbreaking
and efficiency.
2022-02-12 19:43:01 +01:00
Elias Åström d898b02c8b Fix #1922 2022-02-12 19:43:01 +01:00
NO11 f3c814bf8f Merge pull request 'Add lanterns and chains' (#1983) from AFCMS/MineClone2:lanterns into master
Reviewed-on: MineClone2/MineClone2#1983
2022-02-11 13:28:55 +00:00
AFCMS 2690094a95 allow placement of lanterns on chains 2022-02-10 11:45:08 +01:00
AFCMS 23873f31f1 add french translation of `mcl_lanterns` 2022-02-09 22:19:24 +01:00
AFCMS 749d4f1a4b add lanterns translation template 2022-02-09 22:15:44 +01:00
AFCMS 8817d51d64 minecraft like lanterns placement limitations 2022-02-09 22:11:50 +01:00
AFCMS 9b375aa9e8 attemp to fix lanterns placement 2022-02-09 18:19:46 +01:00
AFCMS 6b9d4d445f Merge branch 'lanterns' of ssh://git.minetest.land:29418/AFCMS/MineClone2 into lanterns 2022-02-09 12:21:39 +01:00
AFCMS 7fbdd71081 obtimize glass detail images 2022-02-09 12:21:28 +01:00
AFCMS e138d998ef `walkover` fixes 2022-02-09 12:21:28 +01:00
AFCMS 8ca3d311fd nothing 2022-02-09 12:20:54 +01:00
AFCMS e8c3de80f4 Merge branch 'master' into lanterns 2022-02-09 11:19:45 +00:00
AFCMS 9cc088c940 fix lantern light value to fit minetest limit 2022-02-08 23:00:45 +01:00
AFCMS 6572a8c908 add lanterns, crafts, placement mechanism, doc entries 2022-02-08 22:56:20 +01:00
AFCMS ffa9d2d0fd add basic chains and lantern model and API 2022-02-08 10:58:25 +01:00
AFCMS e4f2618a69 Merge pull request 'fixes to `walkover` mod' (#1979) from AFCMS/MineClone2:walkover_fixes into master
Reviewed-on: MineClone2/MineClone2#1979
2022-01-21 09:56:59 +00:00
AFCMS 5f279e68e1 Merge branch 'walkover_fixes' of ssh://git.minetest.land:29418/AFCMS/MineClone2 into walkover_fixes 2022-01-21 09:05:09 +01:00
AFCMS 90f9f2d98d nothing, but gitea is bad 2022-01-21 09:05:01 +01:00
AFCMS a301ecf7a0 Merge branch 'master' into walkover_fixes 2022-01-21 08:04:19 +00:00
AFCMS 5bedae49d6 `walkover` fixes 2022-01-20 22:55:36 +01:00
kay27 7328549d94 Merge pull request 'Obtimize connected glass detail images' (#1978) from AFCMS/MineClone2:glass_opt into master
Reviewed-on: MineClone2/MineClone2#1978

*optimize
2022-01-20 09:31:59 +00:00
AFCMS d2fa69d4ed obtimize glass detail images 2022-01-20 10:01:59 +01:00
NO11 6f44278414 Merge pull request 'Remove lines about looking at Minecraft source code in CONTRIBUTING.md' (#1973) from GuyLiner/MineClone2:clean_room into master
Reviewed-on: MineClone2/MineClone2#1973
2022-01-19 15:58:54 +00:00
Guy Liner 9792cb5391 The project's name is Minestom, not Minestorm 2022-01-18 23:33:27 -05:00
Guy Liner 4ae323f8f8 Added back line about Minestorm 2022-01-16 21:19:03 -05:00
GuyLiner 92efe78c6f Merge branch 'master' into clean_room 2022-01-16 19:49:02 +00:00
Guy Liner 1995055d0f Removed lines about looking at Minecraft source code 2022-01-16 14:45:20 -05:00
epCode 9b881df465 Temporarily remove glitchy Elytra crash-damage
If you fly in certain directions with this damage system, you will die. also if you speed up too fast.
2022-01-06 21:55:01 +00:00
NO11 4dce90543d Merge pull request 'master' (#13) from MineClone2/MineClone2:master into master
Reviewed-on: NO11/MineClone2#13
2022-01-06 16:06:36 +00:00
Lizzy Fleckenstein a8b974266c Merge pull request 'Add 1024x1024 logo (basic and small versions)' (#1947) from AFCMS/MineClone2:new_logo into master
Reviewed-on: MineClone2/MineClone2#1947
2022-01-03 17:49:54 +00:00
AFCMS 11f3ad15ba add logo 2022-01-02 18:50:15 +01:00
358 changed files with 8580 additions and 8073 deletions

3
.gitignore vendored
View File

@ -1,2 +1,5 @@
# Text Editor TMP Files
*.swp
*.blend1
*.blend2
*.blend3

View File

@ -245,13 +245,9 @@ need to state their sources. These PRs also need Fleckenstein's approval
before they are merged.
You can use these sources:
* Minecraft code (Name the source file and line, however DONT post any
proprietary code). You can use
[MCP](https://minecraft.fandom.com/wiki/Programs_and_editors/Mod_Coder_Pack)
to decompile Minecraft or look at
[Minestorm](https://github.com/Minestom/Minestom) code.
* Testing things inside of Minecraft (Attach screenshots / video footage
of the results)
* Looking at [Minestom](https://github.com/Minestom/Minestom) code. An open source Minecraft Server implementation
* [Official Minecraft Wiki](https://minecraft.fandom.com/wiki/Minecraft_Wiki)
(Include a link to the specific page you used)

View File

@ -6,10 +6,14 @@
## Creator of MineClone2
* Wuzzy
## Maintainers
* Fleckenstein
* Nicu
* kay27
* cora
## Previous Maintainers
* Fleckenstein
* jordan4ibanez
## Developers
* bzoss
@ -22,8 +26,7 @@
* aligator
* Code-Sploit
* NO11
* cora
* jordan4ibanez
* kabou
## Contributors
* Laurent Rocher
@ -75,6 +78,16 @@
* epCode
* NO11
* j45
* 3raven
* PrarieWind
* Gustavo1
* CableGuy67
## Mineclonia
* erlehmann
* Li0n
* E
* n_to
## Original Mod Authors
* Wuzzy

View File

@ -56,6 +56,7 @@ Please read <http://minecraft.gamepedia.com/Breaking> to learn how digging times
* `no_eat_delay=1`: Only for foodstuffs. When eating this, all eating delays are ignored.
* `can_eat_when_full=1`: Only for foodstuffs. This item can be eaten when the user has a full hunger bar
* `attached_node_facedir=1`: Like `attached_node`, but for facedir nodes
* `supported_node=1`: Like `attached_node`, but can be placed on any nodes that do not have the `drawtype="airlike"` attribute.
* `cauldron`: Cauldron. 1: Empty. 2-4: Water height
* `anvil`: Anvil. 1: No damage. 2-3: Higher damage levels
* `no_rename=1`: Item cannot be renamed by anvil

View File

@ -2,7 +2,7 @@
An unofficial Minecraft-like game for Minetest. Forked from MineClone by davedevils.
Developed by many people. Not developed or endorsed by Mojang AB.
Version: 0.72.0 (in development)
Version: 0.73.0 (in development)
### Gameplay
You start in a randomly-generated world made entirely of cubes. You can explore
@ -66,7 +66,7 @@ Use the `/giveme` chat command to obtain them. See the in-game help for
an explanation.
## Installation
This game requires [Minetest](http://minetest.net) to run (version 5.3.0 or
This game requires [Minetest](http://minetest.net) to run (version 5.4.1 or
later). So you need to install Minetest first. Only stable versions of Minetest
are officially supported.
There is no support for running MineClone2 in development versions of Minetest.

View File

@ -0,0 +1,324 @@
# MineClone 2
一個非官方的Minetest遊戲遊玩方式和Minecraft類似。由davedevils從MineClone分拆。
由許多人開發。並非由Mojang Studios開發。<!-- "Mojang AB"'s Name changed at 2020/05, main README should change too -->
版本0.71.0
### 遊玩
你開始在一個完全由方塊隨機生成的世界裡。你可以探索這個世界,挖掘和建造世界上幾乎所有的方塊,以創造新的結構。你可以選擇在「生存模式」中進行遊戲,在這個模式中,你必須與怪物戰鬥,飢餓求生,並在遊戲的其他各個環節中慢慢進步,如採礦、養殖、建造機器等等。
或者你也可以在「創造模式」中玩,在這個模式中,你可以瞬間建造大部分東西。
#### Gameplay summary
* 沙盒式遊戲,沒有明確目標
* 生存:與怪物和飢餓搏鬥
* 挖礦來獲得礦物和寶物
* 附魔:獲得經驗值並以附魔強化你的工具
* 使用收集的方塊來創造偉大的建築
* 收集鮮花(和其他染料來源),令世界多姿多彩
* 找些種子並開始耕種
* 尋找或合成數百個物品之一
* 建立一個鐵路系統,並從礦車中得到樂趣
* 用紅石電路建造複雜的機器
* 在創造模式下,你幾乎可以免費建造任何東西,而且沒有限制。
## 如何開始
### 開始生存
* **挖樹幹**直到其破裂並收集木材
* 將木頭**放入2×2的格子中**你的物品欄中的「合成格子」然後製作4塊木材。
* 將4塊木材按2×2的形狀擺放在合成格子裡製作成合成臺。
* **右鍵單擊製作臺**以獲得3×3製作網格製作更複雜的東西
* 使用**合成指南**(書形圖標)了解所有可能的合成方式
* **製作一個木鎬**,這樣你就可以挖石頭了。
* 不同的工具可以打破不同種類的方塊。試試吧!
* 繼續玩你想玩的。盡情享受吧!
### 耕種
* 找到種子
* 合成鋤頭
* 用鋤頭右鍵點擊泥土或類似的方塊,創建農田
* 將種子放在農田上,看著它們長出來
* Collect plant when fully grown
* If near water, farmland becomes wet and speeds up growth
### Furnace
* Craft furnace
* Furnace allows you to obtain more items
* Upper slot must contain a smeltable item (example: iron ore)
* Lower slot must contain a fuel item (example: coal)
* See tooltips in crafting guide to learn about fuels and smeltable items
### Additional help
More help about the gameplay, blocks items and much more can be found from inside
the game. You can access the help from your inventory menu.
### Special items
The following items are interesting for Creative Mode and for adventure
map builders. They can not be obtained in-game or in the creative inventory.
* Barrier: `mcl_core:barrier`
Use the `/giveme` chat command to obtain them. See the in-game help for
an explanation.
#### Incomplete items
These items do not work yet, but you can get them with `/giveme` for testing:
* Minecart with Chest: `mcl_minecarts:chest_minecart`
* Minecart with Furnace: `mcl_minecarts:furnace_minecart`
* Minecart with Hopper: `mcl_minecarts:hopper_minecart`
* Minecart with Command Block: `mcl_minecarts:command_block_minecart`
## Installation
This game requires [Minetest](http://minetest.net) to run (version 5.0.0 or
later). So you need to install Minetest first. Only stable versions of Minetest
are officially supported.
There is no support for running MineClone 2 in development versions of Minetest.
To install MineClone 2 (if you haven't already), move this directory into the
“games” directory of your Minetest data directory. Consult the help of
Minetest to learn more.
## Project description
The main goal of **MineClone 2** is to be a clone of Minecraft and to be released as free software.
* **開發目標:我的世界, Java版, 版本 1.12**
* MineClone2還包括Minetest支持的Optifine功能。
* 後期Minecraft版本的功能可能會偷偷加入但它們的優先級較低。
* 總的來說Minecraft的目標是在Minetest目前允許的情況下進行克隆。
* 克隆Minecraft是最優先的。
* MineClone2將使用不同的圖形和聲音但風格相似。
* 克隆界面沒有優先權。只會被粗略地模仿。
* 在Minetest中發現的局限性將在開發過程中被記錄和報告。
## 完成程度
該遊戲目前處於**alpha**階段。
它是可玩的,但尚未完成,預計會出現許多錯誤。
向後兼容性是**不能保證的**更新你的世界可能會造成大大小小的bug比如「缺少節點」的錯誤甚至崩潰
已經實現以下功能:
* 工具,武器
* 盔甲
* 合成和熔煉系統2×2 合成格, 合成臺 (3×3 合成格), 熔爐, 合成教學
* 儲物箱,大型儲物箱,終界箱和界伏盒
* 熔爐, 漏斗
* 飢餓和飽食
* 大多數怪物和動物
* Minecraft 1.12中的所有礦物<!-- Minecraft 1.17 added copper, so here must mark the version is 1.12, then main README should also add this -->
* 主世界的大部分方塊
* 水和岩漿
* 天氣
* 28個生態域
* 地獄,熾熱的維度
* 紅石電路(部分)
* 礦車(部分)
* 狀態效果(部分)
* 經驗系統
* 附魔
* 釀造,藥水,藥水箭(部分)
* 船
* 火
* 建築方塊:樓梯、半磚、門、地板門、柵欄、柵欄門、牆。
* 時鐘
* 指南針
* 海綿
* 史萊姆方塊(不與紅石互動)
* 小植物和樹苗
* 染料
* 旗幟
* 裝飾方塊:玻璃、染色玻璃、玻璃片、鐵柵欄、陶土(和染色版本)、頭顱等
* 物品展示框
* 唱片機
* 床
* 物品欄
* 創造模式物品欄
* 生產
* 書和羽毛筆
* 一些服務器命令
* 還有更多!
以下是不完整的特性:
* 生成結構(特別是村莊)
* 一些怪物和動物
* 紅石系統
* 終界
* 特殊的礦車
* 一些不簡單的方塊和物品。
額外功能在Minecraft 1.11中沒有)。
* 內置合成指南,向你展示製作和熔煉的配方
* 遊戲中的幫助系統包含了大量關於遊戲基礎知識、方塊、物品等方面的幫助。
* 臨時製作配方。它們的存在只是為了在你不在創造模式下時,提供一些其他無法獲得的物品。這些配方將隨著開發的進行和更多功能的出現而被移除。
* v6地圖生成器中箱子裡的樹苗。
* 完全可修改得益於Minetest強大的Lua API
* 新的方塊和物品:
* 查找工具,顯示觸及事物的幫助
* 更多的半磚和樓梯
* 地獄磚柵欄門
* 紅地獄磚柵欄
* 紅地獄磚柵欄門
與Minecraft的技性術差異
* 高度限制為31000格(遠高於Minecraft)
* 水平世界大小約為62000×62000格比Minecraft中的小得多但仍然非常大
* 仍然非常不完整和有問題
* 塊、物品、敵人和其他功能缺失。
* 一些項目的名稱略有不同,以便於區分。
* 唱片機的音樂不同
* 不同的材質(像素完美)
* 不同的聲音(各種來源)
* 不同的引擎Minetest
...最後MineClone2是自由軟件
## 錯誤報告
請在此處報告所有錯誤和缺少的功能:
<https://git.minetest.land/MineClone2/MineClone2/issues>
## Chating with the community
我們有Discord交流羣
<https://discord.gg/84GKcxczG3>
## Other readme files
* `LICENSE.txt`GPLv3許可文本
* `CONTRIBUTING.md`: 為那些想參與貢獻的人提供資訊
* `MISSING_ENGINE_FEATURES.md`: MineClone2需要改进Minetest中缺失的功能列表。
* `API.md`: 關於MineClone2的API
## 參與者
有這麼多人要列出抱歉。詳情請查看各mod目錄。本節只是粗略地介紹了本遊戲的核心作者。
### 程式碼
* [Wuzzy](https://forum.minetest.net/memberlist.php?mode=viewprofile&u=3082)大多數mod的主要程序員已退休
* davedevilsMineClone 2的原型——「MineClone」的創造者
* [ex-bart](https://github.com/ex-bart):紅石比較器
* [Rootyjr](https://github.com/Rootyjr):釣竿和錯誤修復
* [aligator](https://github.com/aligator):改進門
* [ryvnf](https://github.com/ryvnf):爆炸物理
* MysticTempest錯誤修復
* [bzoss](https://github.com/bzoss):狀態效果,釀造,藥水
* kay27 <kay27@bk.ru>:經驗系統,錯誤修復和優化(當前維護者)
* [EliasFleckenstein03](https://github.com/EliasFleckenstein03):終界水晶,附魔,燃燒的怪物/玩家,箱子的動畫和錯誤修復(當前維護者)
* epCode更好的玩家動畫新徽標
* 2mac修復動力鐵軌的錯誤
* 更多:待篇寫 (請查看各mod目錄)
#### Mod概括
* `controls`: Arcelmi
* `flowlib`: Qwertymine13
* `walkover`: lordfingle
* `drippingwater`: kddekadenz
* `mobs_mc`: maikerumine, 22i and others
* `awards`: rubenwardy
* `screwdriver`: RealBadAngel, Maciej Kastakin, Minetest contributors
* `xpanes`: Minetest contributors
* `mesecons` mods: Jeija and contributors
* `wieldview`: Stuart Jones
* `mcl_meshhand`: Based on `newhand` by jordan4ibanez
* `mcl_mobs`: Based on Mobs Redo [`mobs`] by TenPlus1 and contributors
* 大多其他的Mod: Wuzzy
每个mod的详细參與者可以在各个mod目录中找到。
### 圖形
* [XSSheep](http://www.minecraftforum.net/members/XSSheep)主要作者Minecraft 1.11的Pixel Perfection资源包的制作者
* [Wuzzy](https://forum.minetest.net/memberlist.php?mode=viewprofile&u=3082):主菜單圖像和各種編輯和添加的材質包
* [kingoscargames](https://github.com/kingoscargames):現有材質的各種編輯和添加
* [leorockway](https://github.com/leorockway):怪物紋理的一些編輯
* [xMrVizzy](https://minecraft.curseforge.com/members/xMrVizzy):釉陶(材質以後會被替換)
* yutyo <tanakinci2002@gmail.com>MineClone2標志
* 其他GUI圖片
### 翻譯
* Wuzzy德語
* Rocher Laurent <rocherl@club-internet.fr>:法語
* wuniversales西班牙語
* kay27 <kay27@bk.ru>:俄語
* [Emoji](https://toyshost2.ddns.net):繁體中文<!-- Hi, after the translate finish, this name should add to the main README too! -->
### 模型
* [22i](https://github.com/22i):所有模型的作者
* [tobyplowy](https://github.com/tobyplowy)對上述模型進行UV映射修復
### 聲音和音樂
多種來源。 有關詳細信息請參見相應的mod目錄。
### 特殊感謝
* Wuzzy感謝他啟動和維護MineClone2多年。
* celeron55創建Minetest。
* Minetest的社區提供了大量的mods選擇其中一些最終被納入MineClone 2。
* Jordach為《Big Freaking Dig》的唱片機音樂合輯而來
* 花了太多時間為Minecraft Wiki寫作的工作狂。它是創建這個遊戲的寶貴資源。
* Notch和Jeb是Minecraft背后的主要力量
* XSSheep用於創建Pixel Perfection資源包。
* [22i](https://github.com/22i) 提供出色的模型和支持
* [maikerumine](http://github.com/maikerumine) 揭開生物和生物群落的序幕
## 給程序員的信息
你可以在「API.md」中找到有趣和有用的信息。
## 法律信息
這是一款粉絲開發的遊戲並非由Mojang AB開發或認可。
複製是一種愛的行為。請複制和分享! <3
下面是詳細的法律條文,有需要的朋友可以參考。
### License of source code
```
MineClone 2 (by kay27, EliasFleckenstein, Wuzzy, davedevils and countless others)
is an imitation of Minecraft.
MineClone 2 is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License (in the LICENSE.txt file) for more
details.
In the mods you might find in the read-me or license
text files a different license. This counts as dual-licensing.
You can choose which license applies to you: Either the
license of MineClone 2 (GNU GPLv3) or the mod's license.
MineClone 2 is a direct continuation of the discontinued MineClone
project by davedevils.
Mod credits:
See `README.txt` or `README.md` in each mod directory for information about other authors.
For mods that do not have such a file, the license is the source code license
of MineClone 2 and the author is Wuzzy.
```
### License of media (textures and sounds)
```
No non-free licenses are used anywhere.
The textures, unless otherwise noted, are based on the Pixel Perfection resource pack for Minecraft 1.11,
authored by XSSheep. Most textures are verbatim copies, while some textures have been changed or redone
from scratch.
The glazed terracotta textures have been created by (MysticTempest)[https://github.com/MysticTempest].
Source: <https://www.planetminecraft.com/texture_pack/131pixel-perfection/>
License: [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)
The main menu images are release under: [CC0](https://creativecommons.org/publicdomain/zero/1.0/)
All other files, unless mentioned otherwise, fall under:
Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
http://creativecommons.org/licenses/by-sa/3.0/
See README.txt in each mod directory for detailed information about other authors.
```

BIN
menu/Logo.blend Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 51 KiB

BIN
menu/icon_big.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
menu/icon_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 KiB

View File

@ -1,29 +1,93 @@
-- Overrides the builtin minetest.check_single_for_falling.
-- We need to do this in order to handle nodes in mineclone specific groups
-- "supported_node" and "attached_node_facedir".
--
-- Nodes in group "supported_node" can be placed on any node that does not
-- have the "airlike" drawtype. Carpets are an example of this type.
local vector = vector
local facedir_to_dir = minetest.facedir_to_dir
local get_item_group = minetest.get_item_group
local remove_node = minetest.remove_node
local get_node = minetest.get_node
local get_meta = minetest.get_meta
local registered_nodes = minetest.registered_nodes
local get_node_drops = minetest.get_node_drops
local add_item = minetest.add_item
-- drop_attached_node(p)
--
-- This function is copied verbatim from minetest/builtin/game/falling.lua
-- We need this to do the exact same dropping node handling in our override
-- minetest.check_single_for_falling() function as in the builtin function.
--
local function drop_attached_node(p)
local n = get_node(p)
local drops = get_node_drops(n, "")
local def = registered_nodes[n.name]
if def and def.preserve_metadata then
local oldmeta = get_meta(p):to_table().fields
-- Copy pos and node because the callback can modify them.
local pos_copy = vector.new(p)
local node_copy = {name=n.name, param1=n.param1, param2=n.param2}
local drop_stacks = {}
for k, v in pairs(drops) do
drop_stacks[k] = ItemStack(v)
end
drops = drop_stacks
def.preserve_metadata(pos_copy, node_copy, oldmeta, drops)
end
if def and def.sounds and def.sounds.fall then
core.sound_play(def.sounds.fall, {pos = p}, true)
end
remove_node(p)
for _, item in pairs(drops) do
local pos = {
x = p.x + math.random()/2 - 0.25,
y = p.y + math.random()/2 - 0.25,
z = p.z + math.random()/2 - 0.25,
}
add_item(pos, item)
end
end
-- minetest.check_single_for_falling(pos)
--
-- * causes an unsupported `group:falling_node` node to fall and causes an
-- unattached `group:attached_node` or `group:attached_node_facedir` node
-- or unsupported `group:supported_node` node to drop.
-- * does not spread these updates to neighbours.
--
-- Returns true if the node at <pos> has spawned a falling node or has been
-- dropped as item(s).
--
local original_function = minetest.check_single_for_falling
function minetest.check_single_for_falling(pos)
local ret_o = original_function(pos)
local ret = false
local node = minetest.get_node(pos)
if original_function(pos) then
return true
end
local node = get_node(pos)
if get_item_group(node.name, "attached_node_facedir") ~= 0 then
local dir = facedir_to_dir(node.param2)
if dir then
if get_item_group(get_node(vector.add(pos, dir)).name, "solid") == 0 then
remove_node(pos)
local drops = minetest.get_node_drops(node.name, "")
for dr=1, #drops do
minetest.add_item(pos, drops[dr])
end
ret = true
drop_attached_node(pos)
return true
end
end
end
return ret_o or ret
if get_item_group(node.name, "supported_node") ~= 0 then
local def = registered_nodes[get_node(vector.offset(pos, 0, -1, 0)).name]
if def and def.drawtype == "airlike" then
drop_attached_node(pos)
return true
end
end
return false
end

View File

@ -0,0 +1,15 @@
# mcl_damage
This mod is intended to overall minetest's native damage system, to provide a better integration between features that deals with entities' health.
WARNING: Not using it inside your mods may cause strange bugs (using the native damage system may cause conflicts with this system).
## Callbacks
To modify the amount of damage made by something:
```lua
--obj: an ObjectRef
mcl_damage.register_modifier(function(obj, damage, reason)
end, 0)
```

View File

@ -0,0 +1,2 @@
# textdomain:mcl_explosions
@1 was caught in an explosion.=@1 被炸飛了

View File

@ -357,6 +357,32 @@ function mcl_util.get_first_occupied_inventory_slot(inventory, listname)
return mcl_util.get_eligible_transfer_item_slot(inventory, listname)
end
local function drop_item_stack(pos, stack)
if not stack or stack:is_empty() then return end
local drop_offset = vector.new(math.random() - 0.5, 0, math.random() - 0.5)
minetest.add_item(vector.add(pos, drop_offset), stack)
end
function mcl_util.drop_items_from_meta_container(listname)
return function(pos, oldnode, oldmetadata)
if oldmetadata and oldmetadata.inventory then
-- process in after_dig_node callback
local main = oldmetadata.inventory.main
if not main then return end
for _, stack in pairs(main) do
drop_item_stack(pos, stack)
end
else
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
for i = 1, inv:get_size("main") do
drop_item_stack(pos, inv:get_stack("main", i))
end
meta:from_table()
end
end
end
-- Returns true if item (itemstring or ItemStack) can be used as a furnace fuel.
-- Returns false otherwise
function mcl_util.is_fuel(item)
@ -571,3 +597,16 @@ function mcl_util.replace_mob(obj, mob)
obj:set_yaw(rot)
return obj
end
function mcl_util.get_pointed_thing(player, liquid)
local pos = vector.offset(player:get_pos(), 0, player:get_properties().eye_height, 0)
local look_dir = vector.multiply(player:get_look_dir(), 5)
local pos2 = vector.add(pos, look_dir)
local ray = minetest.raycast(pos, pos2, false, liquid)
if ray then
for pointed_thing in ray do
return pointed_thing
end
end
end

View File

@ -84,7 +84,7 @@ function image:encode()
end
function image:save(filename)
local f = assert(io.open(filename, "w"))
local f = assert(io.open(filename, "wb"))
f:write(self.data)
f:close()
end

View File

@ -2,47 +2,45 @@
local get_connected_players = minetest.get_connected_players
local get_node = minetest.get_node
local vector_add = vector.add
local vector = vector
local ceil = math.ceil
local pairs = pairs
walkover = {}
walkover.registered_globals = {}
function walkover.register_global(func)
table.insert(walkover.registered_globals, func)
end
local on_walk = {}
local registered_globals = {}
walkover.registered_globals = registered_globals
function walkover.register_global(func)
table.insert(registered_globals, func)
end
minetest.register_on_mods_loaded(function()
for name,def in pairs(minetest.registered_nodes) do
if def.on_walk_over then
on_walk[name] = def.on_walk_over
end
end
for _,func in ipairs(walkover.registered_globals) do --cache registered globals
table.insert(registered_globals, func)
end
end)
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime;
timer = timer + dtime
if timer >= 0.3 then
for _,player in pairs(get_connected_players()) do
local pp = player:get_pos()
pp.y = ceil(pp.y)
local loc = vector_add(pp, {x=0,y=-1,z=0})
if loc then
local nodeiamon = get_node(loc)
if nodeiamon then
if on_walk[nodeiamon.name] then
on_walk[nodeiamon.name](loc, nodeiamon, player)
for _, player in pairs(get_connected_players()) do
local ppos = player:get_pos()
ppos.y = ceil(ppos.y)
local npos = vector.add(ppos, vector.new(0, -1, 0))
if npos then
local node = get_node(npos)
if node then
if on_walk[node.name] then
on_walk[node.name](npos, node, player)
end
for i = 1, #registered_globals do
registered_globals[i](loc, nodeiamon, player)
registered_globals[i](npos, node, player)
end
end
end

View File

@ -267,7 +267,7 @@ function boat.on_step(self, dtime, moveresult)
return
end
local yaw = self.object:get_yaw()
if ctrl.up then
if ctrl and ctrl.up then
-- Forwards
self._v = self._v + 0.1 * v_factor
@ -276,7 +276,7 @@ function boat.on_step(self, dtime, moveresult)
self.object:set_animation({x=0, y=40}, paddling_speed, 0, true)
self._animation = 1
end
elseif ctrl.down then
elseif ctrl and ctrl.down then
-- Backwards
self._v = self._v - 0.1 * v_factor

View File

@ -0,0 +1,11 @@
# textdomain: mcl_boats
Acacia Boat=相思木船
Birch Boat=白樺木船
Boat=船
Boats are used to travel on the surface of water.=船是用來在水上行走的交通工具。
Dark Oak Boat=黑橡木船
Jungle Boat=叢林木船
Oak Boat=橡木船
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Rightclick the boat again to leave it, punch the boat to make it drop as an item.=右鍵單擊水源以放置船。右鍵單擊船以搭乘它。使用[左]和[右]進行轉向,[向前]加快速度,[向後]減速或向後移動。再次右鍵單擊船以離開它,打擊船以使其掉落為物品。
Spruce Boat=杉木船
Water vehicle=水上交通工具

View File

@ -26,20 +26,64 @@ function mcl_burning.get_collisionbox(obj, smaller, storage)
end
end
local find_nodes_in_area = minetest.find_nodes_in_area
function mcl_burning.get_touching_nodes(obj, nodenames, storage)
local pos = obj:get_pos()
local minp, maxp = mcl_burning.get_collisionbox(obj, true, storage)
local nodes = minetest.find_nodes_in_area(vector.add(pos, minp), vector.add(pos, maxp), nodenames)
local nodes = find_nodes_in_area(vector.add(pos, minp), vector.add(pos, maxp), nodenames)
return nodes
end
-- Manages the fire animation on a burning player's HUD
--
-- Parameters:
-- player - a valid player object;
--
-- If the player already has a fire HUD, updates the burning animation.
-- If the fire does not have a fire HUD, initializes the HUD.
--
function mcl_burning.update_hud(player)
local animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8
local hud_flame_animated = "mcl_burning_hud_flame_animated.png^[opacity:180^[verticalframe:" .. animation_frames .. ":"
local storage = mcl_burning.get_storage(player)
if not storage.fire_hud_id then
storage.animation_frame = 1
storage.fire_hud_id = player:hud_add({
hud_elem_type = "image",
position = {x = 0.5, y = 0.5},
scale = {x = -100, y = -100},
text = hud_flame_animated .. storage.animation_frame,
z_index = 1000,
})
else
storage.animation_frame = storage.animation_frame + 1
if storage.animation_frame > animation_frames - 1 then
storage.animation_frame = 0
end
player:hud_change(storage.fire_hud_id, "text", hud_flame_animated .. storage.animation_frame)
end
end
-- Sets and object state as burning and adds a fire animation to the object.
--
-- Parameters:
-- obj - may be a player or a lua_entity;
-- burn_time - sets the object's burn duration;
--
-- If obj is a player, adds a fire animation to the HUD, if obj is a
-- lua_entity, adds an animated fire entity to obj.
-- The effective burn duration is modified by obj's armor protection.
-- If obj was already burning, its burn duration is updated if the current
-- duration is less than burn_time.
-- If obj is dead, fireproof or a creative player, this function does nothing.
--
function mcl_burning.set_on_fire(obj, burn_time)
if obj:get_hp() < 0 then
return
end
local storage = mcl_burning.get_storage(obj)
local luaentity = obj:get_luaentity()
if luaentity and luaentity.fire_resistant then
return
@ -60,44 +104,32 @@ function mcl_burning.set_on_fire(obj, burn_time)
end
end
end
if max_fire_prot_lvl > 0 then
burn_time = burn_time - math.floor(burn_time * max_fire_prot_lvl * 0.15)
end
end
if not storage.burn_time or burn_time >= storage.burn_time then
if obj:is_player() then
mcl_burning.channels[obj]:send_all(tostring(mcl_burning.animation_frames))
mcl_burning.channels[obj]:send_all("start")
local storage = mcl_burning.get_storage(obj)
if storage.burn_time then
if burn_time > storage.burn_time then
storage.burn_time = burn_time
end
storage.burn_time = burn_time
storage.fire_damage_timer = 0
return
end
storage.burn_time = burn_time
storage.fire_damage_timer = 0
local fire_entity = minetest.add_entity(obj:get_pos(), "mcl_burning:fire")
local minp, maxp = mcl_burning.get_collisionbox(obj, false, storage)
local obj_size = obj:get_properties().visual_size
local minp, maxp = mcl_burning.get_collisionbox(obj, false, storage)
local size = vector.subtract(maxp, minp)
size = vector.multiply(size, vector.new(1.1, 1.2, 1.1))
size = vector.divide(size, obj:get_properties().visual_size)
local vertical_grow_factor = 1.2
local horizontal_grow_factor = 1.1
local grow_vector = vector.new(horizontal_grow_factor, vertical_grow_factor, horizontal_grow_factor)
local fire_entity = minetest.add_entity(obj:get_pos(), "mcl_burning:fire")
fire_entity:set_properties({visual_size = size})
fire_entity:set_attach(obj, "", vector.new(0, size.y * 5, 0), vector.new(0, 0, 0))
local size = vector.subtract(maxp, minp)
size = vector.multiply(size, grow_vector)
size = vector.divide(size, obj_size)
local offset = vector.new(0, size.y * 10 / 2, 0)
fire_entity:set_properties({visual_size = size})
fire_entity:set_attach(obj, "", offset, {x = 0, y = 0, z = 0})
local fire_luaentity = fire_entity:get_luaentity()
for _, other in pairs(minetest.get_objects_inside_radius(fire_entity:get_pos(), 0)) do
local other_luaentity = other:get_luaentity()
if other_luaentity and other_luaentity.name == "mcl_burning:fire" and other_luaentity ~= fire_luaentity then
other:remove()
break
end
end
if obj:is_player() then
mcl_burning.update_hud(obj)
end
end
@ -105,7 +137,9 @@ function mcl_burning.extinguish(obj)
if mcl_burning.is_burning(obj) then
local storage = mcl_burning.get_storage(obj)
if obj:is_player() then
mcl_burning.channels[obj]:send_all("stop")
if storage.fire_hud_id then
obj:hud_remove(storage.fire_hud_id)
end
mcl_burning.storage[obj] = {}
else
storage.burn_time = nil

View File

@ -1,18 +1,27 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
local pairs = pairs
local get_connected_players = minetest.get_connected_players
local get_item_group = minetest.get_item_group
mcl_burning = {
storage = {},
channels = {},
animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8
-- the storage table holds a list of objects (players,luaentities) and tables
-- associated with these objects. These tables have the following attributes:
-- burn_time:
-- Remaining time that object will burn.
-- fire_damage_timer:
-- Timer for dealing damage every second while burning.
-- fire_hud_id:
-- HUD id of the flames animation on a burning player's HUD.
-- animation_frame:
-- The HUD's current animation frame, used by update_hud().
-- collisionbox_cache:
-- Used by mcl_burning.get_collisionbox() to avoid recalculations.
storage = {}
}
dofile(modpath .. "/api.lua")
local pairs = pairs
local get_connected_players = minetest.get_connected_players
local get_item_group = minetest.get_item_group
minetest.register_globalstep(function(dtime)
for _, player in pairs(get_connected_players()) do
local storage = mcl_burning.storage[player]
@ -44,25 +53,36 @@ minetest.register_on_respawnplayer(function(player)
mcl_burning.extinguish(player)
end)
function mcl_burning.init_player(player)
local meta = player:get_meta()
-- NOTE: mcl_burning:data may be "return nil" (which deserialize into nil) for reasons unknown.
if meta:get_string("mcl_burning:data"):find("return nil", 1, true) then
minetest.log("warning", "[mcl_burning] 'mcl_burning:data' player meta field is invalid! Please report this bug")
minetest.register_on_joinplayer(function(player)
local storage = {}
local burn_data = player:get_meta():get_string("mcl_burning:data")
if burn_data ~= "" then
storage = minetest.deserialize(burn_data) or storage
end
mcl_burning.storage[player] = meta:contains("mcl_burning:data") and minetest.deserialize(meta:get_string("mcl_burning:data")) or {}
mcl_burning.channels[player] = minetest.mod_channel_join("mcl_burning:" .. player:get_player_name())
mcl_burning.storage[player] = storage
if storage.burn_time and storage.burn_time > 0 then
mcl_burning.update_hud(player)
end
end)
local function on_leaveplayer(player)
local storage = mcl_burning.storage[player]
storage.fire_hud_id = nil
player:get_meta():set_string("mcl_burning:data", minetest.serialize(storage))
mcl_burning.storage[player] = nil
end
minetest.register_on_joinplayer(function(player)
mcl_burning.init_player(player)
end)
minetest.register_on_leaveplayer(function(player)
player:get_meta():set_string("mcl_burning:data", minetest.serialize(mcl_burning.storage[player]))
mcl_burning.storage[player] = nil
on_leaveplayer(player)
end)
minetest.register_on_shutdown(function()
for _,player in ipairs(minetest.get_connected_players()) do
on_leaveplayer(player)
end
end)
local animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8
minetest.register_entity("mcl_burning:fire", {
initial_properties = {
@ -70,42 +90,35 @@ minetest.register_entity("mcl_burning:fire", {
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "upright_sprite",
textures = {
name = "mcl_burning_entity_flame_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.0,
},
"mcl_burning_entity_flame_animated.png",
"mcl_burning_entity_flame_animated.png"
},
spritediv = {x = 1, y = mcl_burning.animation_frames},
spritediv = {x = 1, y = animation_frames},
pointable = false,
glow = -1,
backface_culling = false,
},
animation_frame = 0,
animation_timer = 0,
_mcl_animation_timer = 0,
on_activate = function(self)
self.object:set_sprite({x = 0, y = 0}, mcl_burning.animation_frames, 1.0 / mcl_burning.animation_frames)
self.object:set_sprite({x = 0, y = 0}, animation_frames, 1.0 / animation_frames)
end,
on_step = function(self)
if not self:sanity_check() then
self.object:remove()
end
end,
sanity_check = function(self)
on_step = function(self, dtime)
local parent = self.object:get_attach()
if not parent then
return false
self.object:remove()
return
end
local storage = mcl_burning.get_storage(parent)
if not storage or not storage.burn_time then
return false
self.object:remove()
return
end
if parent:is_player() then
self._mcl_animation_timer = self._mcl_animation_timer + dtime
if self._mcl_animation_timer >= 0.1 then
self._mcl_animation_timer = 0
mcl_burning.update_hud(parent)
end
end
return true
end,
})

View File

@ -0,0 +1,3 @@
# textdomain: mcl_falling_nodes
@1 was smashed by a falling anvil.=@1 被鐵砧壓扁了。
@1 was smashed by a falling block.=@1 被掉下來的方塊壓扁了。

View File

@ -110,7 +110,7 @@ minetest.register_globalstep(function(dtime)
if tick == true and pool[name] > 0 then
minetest.sound_play("item_drop_pickup", {
pos = pos,
gain = 0.7,
gain = 0.3,
max_hear_distance = 16,
pitch = math.random(70,110)/100
})
@ -256,6 +256,8 @@ function minetest.handle_node_drops(pos, drops, digger)
local silk_touch_drop = false
local nodedef = minetest.registered_nodes[dug_node.name]
if not nodedef then return end
if shearsy_level and shearsy_level > 0 and nodedef._mcl_shears_drop then
if nodedef._mcl_shears_drop == true then
drops = { dug_node.name }

View File

@ -432,7 +432,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
-- Slow down or speed up
local acc = dir.y * -1.8
local friction = 0.4
local speed_mod = minetest.registered_nodes[minetest.get_node(pos).name]._rail_acceleration
local ndef = minetest.registered_nodes[minetest.get_node(pos).name]
local speed_mod = ndef and ndef._rail_acceleration
acc = acc - friction
@ -860,4 +861,4 @@ if has_mcl_wip then
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
end

View File

@ -502,6 +502,20 @@ and damages any entity caught inside the blast radius. Protection will limit
node destruction but not entity damage.
mobs:capture_mob
----------------
mobs:capture_mob(...)
Does nothing and returns false.
This function is provided for compability with Mobs Redo for an attempt to
capture a mob.
Mobs cannot be captured in MineClone 2.
In Mobs Redo, this is generally called inside the on_rightclick section of the mob
api code, it provides a chance of capturing the mob. See Mobs Redo documentation
of parameters.
Feeding and Taming/Breeding
---------------------------
@ -521,6 +535,19 @@ Will return true when mob is fed with item it likes.
them up
Protecting Mobs
---------------
mobs:protect(self, clicker)
This function can be used to right-click any tamed mob with mobs:protector item,
this will protect the mob from harm inside of a protected area from other
players. Will return true when mob right-clicked with mobs:protector item.
'self' mob information
'clicker' player information
Riding Mobs
-----------
@ -578,7 +605,7 @@ Note: animation names above are from the pre-defined animation lists inside mob
registry without extensions.
mobs.set_mob_animation(self, name)
mobs:set_animation(self, name)
This function sets the current animation for mob, defaulting to "stand" if not
found.
@ -754,5 +781,8 @@ mobs:register_mob("mob_horse:horse", {
inv:remove_item("main", "mobs:saddle")
end
end
-- used to capture horse with magic lasso
mobs:capture_mob(self, clicker, 0, 0, 80, false, nil)
end
})

View File

@ -1,736 +0,0 @@
-- API for Mobs Redo: MineClone 2 Delux 2.0 DRM Free Early Access Super Extreme Edition
-- mobs library
mobs = {}
-- lua locals - can grab from this to easily plop them into the api lua files
--localize minetest functions
local minetest_settings = minetest.settings
local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius
local minetest_get_modpath = minetest.get_modpath
local minetest_registered_nodes = minetest.registered_nodes
local minetest_get_node = minetest.get_node
--local minetest_get_item_group = minetest.get_item_group
local minetest_registered_entities = minetest.registered_entities
--local minetest_line_of_sight = minetest.line_of_sight
--local minetest_after = minetest.after
--local minetest_sound_play = minetest.sound_play
--local minetest_add_particlespawner = minetest.add_particlespawner
--local minetest_registered_items = minetest.registered_items
--local minetest_set_node = minetest.set_node
local minetest_add_item = minetest.add_item
--local minetest_get_craft_result = minetest.get_craft_result
--local minetest_find_path = minetest.find_path
local minetest_is_creative_enabled = minetest.is_creative_enabled
--local minetest_find_node_near = minetest.find_node_near
--local minetest_find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air
--local minetest_raycast = minetest.raycast
--local minetest_get_us_time = minetest.get_us_time
local minetest_add_entity = minetest.add_entity
--local minetest_get_natural_light = minetest.get_natural_light
--local minetest_get_node_or_nil = minetest.get_node_or_nil
-- localize math functions
local math = math
-- localize vector functions
local vector = vector
local string = string
-- mob constants
--local BREED_TIME = 30
--local BREED_TIME_AGAIN = 300
--local CHILD_GROW_TIME = 60*20
--local DEATH_DELAY = 0.5
local DEFAULT_FALL_SPEED = -10
--local FLOP_HEIGHT = 5.0
--local FLOP_HOR_SPEED = 1.5
local GRAVITY = minetest_settings:get("movement_gravity")-- + 9.81
local MAX_MOB_NAME_LENGTH = 30
--[[local MOB_CAP = {}
MOB_CAP.hostile = 70
MOB_CAP.passive = 10
MOB_CAP.ambient = 15
MOB_CAP.water = 15
]]
-- Load main settings
--local damage_enabled = minetest_settings:get_bool("enable_damage")
--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
--local spawn_protected = minetest_settings:get_bool("mobs_spawn_protected") ~= false
--local remove_far = true
local difficulty = tonumber(minetest_settings:get("mob_difficulty")) or 1.0
--local show_health = false
--local max_per_block = tonumber(minetest_settings:get("max_objects_per_block") or 64)
---local mobs_spawn_chance = tonumber(minetest_settings:get("mobs_spawn_chance") or 2.5)
-- pathfinding settings
--local enable_pathfinding = true
--local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching
--local stuck_path_timeout = 10 -- how long will mob follow path before giving up
-- default nodes
--local node_ice = "mcl_core:ice"
--local node_snowblock = "mcl_core:snowblock"
--local node_snow = "mcl_core:snow"
mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt"
--local mod_weather = minetest_get_modpath("mcl_weather")
--local mod_explosions = minetest_get_modpath("mcl_explosions")
local mod_mobspawners = minetest_get_modpath("mcl_mobspawners")
--local mod_hunger = minetest_get_modpath("mcl_hunger")
--local mod_worlds = minetest_get_modpath("mcl_worlds")
--local mod_armor = minetest_get_modpath("mcl_armor")
--local mod_experience = minetest_get_modpath("mcl_experience")
-- random locals I found
--local los_switcher = false
--local height_switcher = false
-- Get translator
local S = minetest.get_translator(minetest.get_current_modname())
-- CMI support check
--local use_cmi = minetest.global_exists("cmi")
-- creative check
function mobs.is_creative(name)
return minetest_is_creative_enabled(name)
end
--[[local function atan(x)
if not x or x ~= x then
return 0
else
return math.atan(x)
end
end]]
-- Shows helpful debug info above each mob
--local mobs_debug = minetest_settings:get_bool("mobs_debug", false)
-- Peaceful mode message so players will know there are no monsters
if minetest_settings:get_bool("only_peaceful_mobs", false) then
minetest.register_on_joinplayer(function(player)
minetest.chat_send_player(player:get_player_name(),
S("Peaceful mode active! No monsters will spawn."))
end)
end
local api_path = minetest.get_modpath(minetest.get_current_modname()).."/api/mob_functions/"
--ignite all parts of the api
dofile(api_path .. "flow_lib.lua")
dofile(api_path .. "ai.lua")
dofile(api_path .. "animation.lua")
dofile(api_path .. "collision.lua")
dofile(api_path .. "environment.lua")
dofile(api_path .. "interaction.lua")
dofile(api_path .. "movement.lua")
dofile(api_path .. "set_up.lua")
dofile(api_path .. "attack_type_instructions.lua")
dofile(api_path .. "sound_handling.lua")
dofile(api_path .. "death_logic.lua")
dofile(api_path .. "mob_effects.lua")
dofile(api_path .. "projectile_handling.lua")
dofile(api_path .. "breeding.lua")
dofile(api_path .. "head_logic.lua")
mobs.spawning_mobs = {}
-- register mob entity
function mobs:register_mob(name, def)
local collisionbox = def.collisionbox or {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25}
-- Workaround for <https://github.com/minetest/minetest/issues/5966>:
-- Increase upper Y limit to avoid mobs glitching through solid nodes.
-- FIXME: Remove workaround if it's no longer needed.
if collisionbox[5] < 0.79 then
collisionbox[5] = 0.79
end
mobs.spawning_mobs[name] = true
local function scale_difficulty(value, default, min, special)
if (not value) or (value == default) or (value == special) then
return default
else
return math.max(min, value * difficulty)
end
end
minetest.register_entity(name, {
description = def.description,
use_texture_alpha = def.use_texture_alpha,
stepheight = def.stepheight or 0.6,
stepheight_backup = def.stepheight or 0.6,
name = name,
type = def.type,
attack_type = def.attack_type,
fly = def.fly,
fly_in = def.fly_in or {"air", "__airlike"},
owner = def.owner or "",
order = def.order or "",
on_die = def.on_die,
spawn_small_alternative = def.spawn_small_alternative,
do_custom = def.do_custom,
jump_height = def.jump_height or 4, -- was 6
rotate = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2
hp_min = scale_difficulty(def.hp_min, 5, 1),
hp_max = scale_difficulty(def.hp_max, 10, 1),
xp_min = def.xp_min or 1,
xp_max = def.xp_max or 5,
breath_max = def.breath_max or 6,
breathes_in_water = def.breathes_in_water or false,
physical = true,
collisionbox = collisionbox,
collide_with_objects = def.collide_with_objects or false,
selectionbox = def.selectionbox or def.collisionbox,
visual = def.visual,
visual_size = def.visual_size or {x = 1, y = 1},
mesh = def.mesh,
makes_footstep_sound = def.makes_footstep_sound or false,
view_range = def.view_range or 16,
walk_velocity = def.walk_velocity or 1,
run_velocity = def.run_velocity or 2,
damage = scale_difficulty(def.damage, 0, 0),
light_damage = def.light_damage or 0,
sunlight_damage = def.sunlight_damage or 0,
water_damage = def.water_damage or 0,
lava_damage = def.lava_damage or 8,
fire_damage = def.fire_damage or 1,
suffocation = def.suffocation or true,
fall_damage = def.fall_damage or 1,
fall_speed = def.fall_speed or DEFAULT_FALL_SPEED, -- must be lower than -2
drops = def.drops or {},
armor = def.armor or 100,
on_rightclick = mobs.create_mob_on_rightclick(def.on_rightclick),
arrow = def.arrow,
shoot_interval = def.shoot_interval,
sounds = def.sounds or {},
animation = def.animation,
jump = def.jump ~= false,
walk_chance = def.walk_chance or 50,
attacks_monsters = def.attacks_monsters or false,
group_attack = def.group_attack or false,
passive = def.passive or false,
knock_back = def.knock_back ~= false,
shoot_offset = def.shoot_offset or 0,
floats = def.floats or 1, -- floats in water by default
floats_on_lava = def.floats_on_lava or 0,
replace_rate = def.replace_rate,
replace_what = def.replace_what,
replace_with = def.replace_with,
replace_offset = def.replace_offset or 0,
on_replace = def.on_replace,
timer = 0,
state_timer = 0,
env_damage_timer = 0,
tamed = false,
pause_timer = 0,
gotten = false,
reach = def.reach or 3,
htimer = 0,
texture_list = def.textures,
child_texture = def.child_texture,
docile_by_day = def.docile_by_day or false,
time_of_day = 0.5,
fear_height = def.fear_height or 0,
runaway = def.runaway,
runaway_timer = 0,
pathfinding = def.pathfinding,
immune_to = def.immune_to or {},
explosion_radius = def.explosion_radius, -- LEGACY
explosion_damage_radius = def.explosion_damage_radius, -- LEGACY
explosiontimer_reset_radius = def.explosiontimer_reset_radius,
explosion_timer = def.explosion_timer or 3,
allow_fuse_reset = def.allow_fuse_reset ~= false,
stop_to_explode = def.stop_to_explode ~= false,
custom_attack = def.custom_attack,
double_melee_attack = def.double_melee_attack,
dogshoot_switch = def.dogshoot_switch,
dogshoot_count = 0,
dogshoot_count_max = def.dogshoot_count_max or 5,
dogshoot_count2_max = def.dogshoot_count2_max or (def.dogshoot_count_max or 5),
attack_animals = def.attack_animals or false,
specific_attack = def.specific_attack,
runaway_from = def.runaway_from,
owner_loyal = def.owner_loyal,
facing_fence = false,
_cmi_is_mob = true,
pushable = def.pushable or true,
--j4i stuff
yaw = 0,
automatic_face_movement_dir = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2
automatic_face_movement_max_rotation_per_sec = 360, --degrees
backface_culling = true,
walk_timer = 0,
stand_timer = 0,
current_animation = "",
gravity = GRAVITY,
swim = def.swim,
swim_in = def.swim_in or {mobs_mc.items.water_source, "mcl_core:water_flowing", mobs_mc.items.river_water_source},
pitch_switch = "static",
jump_only = def.jump_only,
hostile = def.hostile,
neutral = def.neutral,
attacking = nil,
visual_size_origin = def.visual_size or {x = 1, y = 1, z = 1},
punch_timer_cooloff = def.punch_timer_cooloff or 0.5,
death_animation_timer = 0,
hostile_cooldown = def.hostile_cooldown or 15,
tilt_fly = def.tilt_fly,
tilt_swim = def.tilt_swim,
fall_slow = def.fall_slow,
projectile_cooldown_min = def.projectile_cooldown_min or 2,
projectile_cooldown_max = def.projectile_cooldown_max or 6,
skittish = def.skittish,
minimum_follow_distance = def.minimum_follow_distance or 0.5, --make mobs not freak out when underneath
memory = 0, -- memory timer if chasing/following
fly_random_while_attack = def.fly_random_while_attack,
--for spiders
always_climb = def.always_climb,
--despawn mechanic variables
lifetimer_reset = 30, --30 seconds
lifetimer = 30, --30 seconds
--breeding stuff
breed_timer = 0,
breed_lookout_timer = 0,
breed_distance = def.breed_distance or 1.5, --how far away mobs have to be to begin actual breeding
breed_lookout_timer_goal = 30, --30 seconds (this timer is for how long the mob looks for a mate)
breed_timer_cooloff = 5*60, -- 5 minutes (this timer is for how long the mob has to wait before being bred again)
bred = false,
follow = def.follow, --this item is also used for the breeding mechanism
follow_distance = def.follow_distance or 2,
baby_size = def.baby_size or 0.5,
baby = false,
grow_up_timer = 0,
grow_up_goal = 20*60, --in 20 minutes the mob grows up
special_breed_timer = 0, --this is used for the AHEM AHEM part of breeding
backup_visual_size = def.visual_size,
backup_collisionbox = collisionbox,
backup_selectionbox = def.selectionbox or def.collisionbox,
--fire timer
burn_timer = 0,
ignores_cobwebs = def.ignores_cobwebs,
breath = def.breath_max or 6,
random_sound_timer_min = 3,
random_sound_timer_max = 10,
--head code variables
--defaults are for the cow's default
--because I don't know what else to set them
--to :P
--you must use these to adjust the mob's head positions
--has_head is used as a logic gate (quick easy check)
has_head = def.has_head or false,
--head_bone is the actual bone in the model which the head
--is attached to for animation
head_bone = def.head_bone or "head",
--this part controls the base position of the head calculations
--localized to the mob's visual yaw when gotten (self.object:get_yaw())
--you can enable the debug in /mob_functions/head_logic.lua by uncommenting the
--particle spawner code
head_height_offset = def.head_height_offset or 1.0525,
head_direction_offset = def.head_direction_offset or 0.5,
--this part controls the visual of the head
head_bone_pos_y = def.head_bone_pos_y or 3.6,
head_bone_pos_z = def.head_bone_pos_z or -0.6,
head_pitch_modifier = def.head_pitch_modifier or 0,
--these variables are switches in case the model
--moves the wrong way
swap_y_with_x = def.swap_y_with_x or false,
reverse_head_yaw = def.reverse_head_yaw or false,
--END HEAD CODE VARIABLES
--end j4i stuff
-- MCL2 extensions
teleport = mobs.teleport,
do_teleport = def.do_teleport,
spawn_class = def.spawn_class,
ignores_nametag = def.ignores_nametag or false,
rain_damage = def.rain_damage or 0,
glow = def.glow,
--can_despawn = can_despawn,
child = def.child or false,
texture_mods = {},
shoot_arrow = def.shoot_arrow,
sounds_child = def.sounds_child,
explosion_strength = def.explosion_strength,
suffocation_timer = 0,
follow_velocity = def.follow_velocity or 2.4,
instant_death = def.instant_death or false,
fire_resistant = def.fire_resistant or false,
fire_damage_resistant = def.fire_damage_resistant or false,
ignited_by_sunlight = def.ignited_by_sunlight or false,
eye_height = def.eye_height or 1.5,
defuse_reach = def.defuse_reach or 4,
-- End of MCL2 extensions
on_spawn = def.on_spawn,
--on_blast = def.on_blast or do_tnt,
on_step = mobs.mob_step,
--do_punch = def.do_punch,
on_punch = mobs.mob_punch,
--on_breed = def.on_breed,
--on_grown = def.on_grown,
--on_detach_child = mob_detach_child,
on_activate = function(self, staticdata, dtime)
self.object:set_acceleration(vector.new(0,-GRAVITY, 0))
return mobs.mob_activate(self, staticdata, def, dtime)
end,
get_staticdata = function(self)
return mobs.mob_staticdata(self)
end,
--harmed_by_heal = def.harmed_by_heal,
})
if minetest_get_modpath("doc_identifier") then
doc.sub.identifier.register_object(name, "basics", "mobs")
end
end -- END mobs:register_mob function
-- register arrow for shoot attack
function mobs:register_arrow(name, def)
-- errorcheck
if not name or not def then
print("failed to register arrow entity")
return
end
minetest.register_entity(name.."_entity", {
physical = false,
visual = def.visual,
visual_size = def.visual_size,
textures = def.textures,
velocity = def.velocity,
hit_player = def.hit_player,
hit_node = def.hit_node,
hit_mob = def.hit_mob,
hit_object = def.hit_object,
drop = def.drop or false, -- drops arrow as registered item when true
collisionbox = {0, 0, 0, 0, 0, 0}, -- remove box around arrows
timer = 0,
switch = 0,
owner_id = def.owner_id,
rotate = def.rotate,
speed = def.speed or nil,
on_step = function(self)
local vel = self.object:get_velocity()
local pos = self.object:get_pos()
if self.timer > 150
or not mobs.within_limits(pos, 0) then
mcl_burning.extinguish(self.object)
self.object:remove();
return
end
-- does arrow have a tail (fireball)
if def.tail
and def.tail == 1
and def.tail_texture then
--do this to prevent clipping through main entity sprite
local pos_adjustment = vector.multiply(vector.normalize(vel), -1)
local divider = def.tail_distance_divider or 1
pos_adjustment = vector.divide(pos_adjustment, divider)
local new_pos = vector.add(pos, pos_adjustment)
minetest.add_particle({
pos = new_pos,
velocity = {x = 0, y = 0, z = 0},
acceleration = {x = 0, y = 0, z = 0},
expirationtime = def.expire or 0.25,
collisiondetection = false,
texture = def.tail_texture,
size = def.tail_size or 5,
glow = def.glow or 0,
})
end
if self.hit_node then
local node = minetest_get_node(pos).name
if minetest_registered_nodes[node].walkable then
self.hit_node(self, pos, node)
if self.drop == true then
pos.y = pos.y + 1
self.lastpos = (self.lastpos or pos)
minetest_add_item(self.lastpos, self.object:get_luaentity().name)
end
self.object:remove();
return
end
end
if self.hit_player or self.hit_mob or self.hit_object then
for _,player in pairs(minetest_get_objects_inside_radius(pos, 1.5)) do
if self.hit_player
and player:is_player() then
if self.hit_player then
self.hit_player(self, player)
else
mobs.arrow_hit(self, player)
end
self.object:remove();
return
end
--[[
local entity = player:get_luaentity()
if entity
and self.hit_mob
and entity._cmi_is_mob == true
and tostring(player) ~= self.owner_id
and entity.name ~= self.object:get_luaentity().name
and (self._shooter and entity.name ~= self._shooter:get_luaentity().name) then
--self.hit_mob(self, player)
self.object:remove();
return
end
]]--
--[[
if entity
and self.hit_object
and (not entity._cmi_is_mob)
and tostring(player) ~= self.owner_id
and entity.name ~= self.object:get_luaentity().name
and (self._shooter and entity.name ~= self._shooter:get_luaentity().name) then
--self.hit_object(self, player)
self.object:remove();
return
end
]]--
end
end
self.lastpos = pos
end
})
end
-- Register spawn eggs
-- Note: This also introduces the “spawn_egg” group:
-- * spawn_egg=1: Spawn egg (generic mob, no metadata)
-- * spawn_egg=2: Spawn egg (captured/tamed mob, metadata)
function mobs:register_egg(mob, desc, background, addegg, no_creative)
local grp = {spawn_egg = 1}
-- do NOT add this egg to creative inventory (e.g. dungeon master)
if no_creative == true then
grp.not_in_creative_inventory = 1
end
local invimg = background
if addegg == 1 then
invimg = "mobs_chicken_egg.png^(" .. invimg ..
"^[mask:mobs_chicken_egg_overlay.png)"
end
-- register old stackable mob egg
minetest.register_craftitem(mob, {
description = desc,
inventory_image = invimg,
groups = grp,
_doc_items_longdesc = S("This allows you to place a single mob."),
_doc_items_usagehelp = S("Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns."),
on_place = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.above
-- am I clicking on something with existing on_rightclick function?
local under = minetest_get_node(pointed_thing.under)
local def = minetest_registered_nodes[under.name]
if def and def.on_rightclick then
return def.on_rightclick(pointed_thing.under, under, placer, itemstack)
end
if pos
--and within_limits(pos, 0)
and not minetest.is_protected(pos, placer:get_player_name()) then
local name = placer:get_player_name()
local privs = minetest.get_player_privs(name)
if mod_mobspawners and under.name == "mcl_mobspawners:spawner" then
if minetest.is_protected(pointed_thing.under, name) then
minetest.record_protection_violation(pointed_thing.under, name)
return itemstack
end
if not privs.maphack then
minetest.chat_send_player(name, S("You need the “maphack” privilege to change the mob spawner."))
return itemstack
end
mcl_mobspawners.setup_spawner(pointed_thing.under, itemstack:get_name())
if not mobs.is_creative(name) then
itemstack:take_item()
end
return itemstack
end
if not minetest_registered_entities[mob] then
return itemstack
end
if minetest_settings:get_bool("only_peaceful_mobs", false)
and minetest_registered_entities[mob].type == "monster" then
minetest.chat_send_player(name, S("Only peaceful mobs allowed!"))
return itemstack
end
local mob = minetest_add_entity(pos, mob)
minetest.log("action", "Mob spawned: "..name.." at "..minetest.pos_to_string(pos))
local ent = mob:get_luaentity()
-- don't set owner if monster or sneak pressed
--[[
if ent.type ~= "monster"
and not placer:get_player_control().sneak then
ent.owner = placer:get_player_name()
ent.tamed = true
end
]]--
-- set nametag
local nametag = itemstack:get_meta():get_string("name")
if nametag ~= "" then
if string.len(nametag) > MAX_MOB_NAME_LENGTH then
nametag = string.sub(nametag, 1, MAX_MOB_NAME_LENGTH)
end
ent.nametag = nametag
--update_tag(ent)
end
-- if not in creative then take item
if not mobs.is_creative(placer:get_player_name()) then
itemstack:take_item()
end
end
return itemstack
end,
})
end

File diff suppressed because it is too large Load Diff

View File

@ -1,257 +0,0 @@
local math = math
local vector = vector
local HALF_PI = math.pi/2
local vector_direction = vector.direction
local vector_distance = vector.distance
local vector_new = vector.new
local minetest_dir_to_yaw = minetest.dir_to_yaw
-- set defined animation
mobs.set_mob_animation = function(self, anim, fixed_frame)
if not self.animation or not anim then
return
end
if self.state == "die" and anim ~= "die" and anim ~= "stand" then
return
end
if (not self.animation[anim .. "_start"] or not self.animation[anim .. "_end"]) then
return
end
--animations break if they are constantly set
--so we put this return gate to check if it is
--already at the animation we are trying to implement
if self.current_animation == anim then
return
end
local a_start = self.animation[anim .. "_start"]
local a_end
if fixed_frame then
a_end = a_start
else
a_end = self.animation[anim .. "_end"]
end
self.object:set_animation({
x = a_start,
y = a_end},
self.animation[anim .. "_speed"] or self.animation.speed_normal or 15,
0, self.animation[anim .. "_loop"] ~= false)
self.current_animation = anim
end
mobs.death_effect = function(pos, yaw, collisionbox, rotate)
local min, max
if collisionbox then
min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]}
max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]}
else
min = { x = -0.5, y = 0, z = -0.5 }
max = { x = 0.5, y = 0.5, z = 0.5 }
end
if rotate then
min = vector.rotate(min, {x=0, y=yaw, z=math.pi/2})
max = vector.rotate(max, {x=0, y=yaw, z=math.pi/2})
min, max = vector.sort(min, max)
min = vector.multiply(min, 0.5)
max = vector.multiply(max, 0.5)
end
minetest.add_particlespawner({
amount = 50,
time = 0.001,
minpos = vector.add(pos, min),
maxpos = vector.add(pos, max),
minvel = vector_new(-5,-5,-5),
maxvel = vector_new(5,5,5),
minexptime = 1.1,
maxexptime = 1.5,
minsize = 1,
maxsize = 2,
collisiondetection = false,
vertical = false,
texture = "mcl_particles_mob_death.png^[colorize:#000000:255",
})
minetest.sound_play("mcl_mobs_mob_poof", {
pos = pos,
gain = 1.0,
max_hear_distance = 8,
}, true)
end
--this allows auto facedir rotation while making it so mobs
--don't look like wet noodles flopping around
mobs.movement_rotation_lock = function(self)
local current_engine_yaw = self.object:get_yaw()
local current_lua_yaw = self.yaw
if current_engine_yaw > math.pi * 2 then
current_engine_yaw = current_engine_yaw - (math.pi * 2)
end
if math.abs(current_engine_yaw - current_lua_yaw) <= 0.05 and self.object:get_properties().automatic_face_movement_dir then
self.object:set_properties{automatic_face_movement_dir = false}
elseif math.abs(current_engine_yaw - current_lua_yaw) > 0.05 and self.object:get_properties().automatic_face_movement_dir == false then
self.object:set_properties{automatic_face_movement_dir = self.rotate}
end
end
--this is used when a mob is chasing a player
mobs.set_yaw_while_attacking = function(self)
if self.object:get_properties().automatic_face_movement_dir then
self.object:set_properties{automatic_face_movement_dir = false}
end
--turn positions into pseudo 2d vectors
local pos1 = self.object:get_pos()
pos1.y = 0
local pos2 = self.attacking:get_pos()
pos2.y = 0
local new_direction = vector_direction(pos1,pos2)
local new_yaw = minetest_dir_to_yaw(new_direction)
self.object:set_yaw(new_yaw)
self.yaw = new_yaw
end
--this is used to unlock a mob's yaw after attacking
mobs.unlock_yaw = function(self)
if self.object:get_properties().automatic_face_movement_dir == false then
self.object:set_properties{automatic_face_movement_dir = self.rotate}
end
end
--this is used to lock a mob's yaw when they're standing
mobs.lock_yaw = function(self)
if self.object:get_properties().automatic_face_movement_dir then
self.object:set_properties{automatic_face_movement_dir = false}
end
end
local calculate_pitch = function(self)
local pos = self.object:get_pos()
local pos2 = self.old_pos
if pos == nil or pos2 == nil then
return false
end
return minetest_dir_to_yaw(vector_new(vector_distance(vector_new(pos.x,0,pos.z),vector_new(pos2.x,0,pos2.z)),0,pos.y - pos2.y)) + HALF_PI
end
--this is a helper function used to make mobs pitch rotation dynamically flow when flying/swimming
mobs.set_dynamic_pitch = function(self)
local pitch = calculate_pitch(self)
if not pitch then
return
end
local current_rotation = self.object:get_rotation()
current_rotation.x = pitch
self.object:set_rotation(current_rotation)
self.pitch_switch = "dynamic"
end
--this is a helper function used to make mobs pitch rotation reset when flying/swimming
mobs.set_static_pitch = function(self)
if self.pitch_switch == "static" then
return
end
local current_rotation = self.object:get_rotation()
current_rotation.x = 0
self.object:set_rotation(current_rotation)
self.pitch_switch = "static"
end
--this is a helper function for mobs explosion animation
mobs.handle_explosion_animation = function(self)
--secondary catch-all
if not self.explosion_animation then
self.explosion_animation = 0
end
--the timer works from 0 for sense of a 0 based counting
--but this just bumps it up so it's usable in here
local explosion_timer_adjust = self.explosion_animation + 1
local visual_size_modified = table.copy(self.visual_size_origin)
visual_size_modified.x = visual_size_modified.x * (explosion_timer_adjust ^ 3)
visual_size_modified.y = visual_size_modified.y * explosion_timer_adjust
self.object:set_properties({visual_size = visual_size_modified})
end
--this is used when a mob is following player
mobs.set_yaw_while_following = function(self)
if self.object:get_properties().automatic_face_movement_dir then
self.object:set_properties{automatic_face_movement_dir = false}
end
--turn positions into pseudo 2d vectors
local pos1 = self.object:get_pos()
pos1.y = 0
local pos2 = self.following_person:get_pos()
pos2.y = 0
local new_direction = vector_direction(pos1,pos2)
local new_yaw = minetest_dir_to_yaw(new_direction)
self.object:set_yaw(new_yaw)
self.yaw = new_yaw
end
--this is used for when mobs breed
mobs.set_yaw_while_breeding = function(self, mate)
if self.object:get_properties().automatic_face_movement_dir then
self.object:set_properties{automatic_face_movement_dir = false}
end
--turn positions into pseudo 2d vectors
local pos1 = self.object:get_pos()
pos1.y = 0
local pos2 = mate:get_pos()
pos2.y = 0
local new_direction = vector_direction(pos1,pos2)
local new_yaw = minetest_dir_to_yaw(new_direction)
self.object:set_yaw(new_yaw)
self.yaw = new_yaw
end

View File

@ -1,347 +0,0 @@
local vector_direction = vector.direction
--local minetest_dir_to_yaw = minetest.dir_to_yaw
local vector_distance = vector.distance
local vector_multiply = vector.multiply
local math_random = math.random
--[[
_ _ _ _
| | | | | | | |
| | | | __ _ _ __ __| | | |
| | | | / _` | '_ \ / _` | | |
|_| | |___| (_| | | | | (_| | |_|
(_) \_____/\__,_|_| |_|\__,_| (_)
]]--
--[[
_____ _ _
| ___| | | | |
| |____ ___ __ | | ___ __| | ___
| __\ \/ / '_ \| |/ _ \ / _` |/ _ \
| |___> <| |_) | | (_) | (_| | __/
\____/_/\_\ .__/|_|\___/ \__,_|\___|
| |
|_|
]]--
mobs.explode_attack_walk = function(self,dtime)
--this needs an exception
if self.attacking == nil or not self.attacking:is_player() then
self.attacking = nil
return
end
mobs.set_yaw_while_attacking(self)
local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos())
--make mob walk up to player within 2 nodes distance then start exploding
if distance_from_attacking >= self.reach and
--don't allow explosion to cancel unless out of the reach boundary
not (self.explosion_animation and self.explosion_animation > 0 and distance_from_attacking <= self.defuse_reach) then
mobs.set_velocity(self, self.run_velocity)
mobs.set_mob_animation(self,"run")
mobs.reverse_explosion_animation(self,dtime)
else
mobs.set_velocity(self,0)
--this is the only way I can reference this without dumping extra data on all mobs
if not self.explosion_animation then
self.explosion_animation = 0
end
--play ignite sound
if self.explosion_animation == 0 then
mobs.play_sound(self,"attack")
end
mobs.set_mob_animation(self,"stand")
mobs.handle_explosion_animation(self)
self.explosion_animation = self.explosion_animation + (dtime/2.5)
end
--make explosive mobs jump
--check for nodes to jump over
--explosive mobs will just ride against walls for now
local node_in_front_of = mobs.jump_check(self)
if node_in_front_of == 1 then
mobs.jump(self)
end
--do biggening explosion thing
if self.explosion_animation and self.explosion_animation > self.explosion_timer then
mcl_explosions.explode(self.object:get_pos(), self.explosion_strength,{ drop_chance = 1.0 })
self.object:remove()
end
end
--this is a small helper function to make working with explosion animations easier
mobs.reverse_explosion_animation = function(self,dtime)
--if explosion animation was greater than 0 then reverse it
if self.explosion_animation and self.explosion_animation > 0 then
self.explosion_animation = self.explosion_animation - dtime
if self.explosion_animation < 0 then
self.explosion_animation = 0
end
end
mobs.handle_explosion_animation(self)
end
--[[
______ _
| ___ \ | |
| |_/ / _ _ __ ___| |__
| __/ | | | '_ \ / __| '_ \
| | | |_| | | | | (__| | | |
\_| \__,_|_| |_|\___|_| |_|
]]--
mobs.punch_attack_walk = function(self,dtime)
--this needs an exception
if self.attacking == nil or not self.attacking:is_player() then
self.attacking = nil
return
end
local distance_from_attacking = mobs.get_2d_distance(self.object:get_pos(), self.attacking:get_pos())
if distance_from_attacking >= self.minimum_follow_distance then
mobs.set_velocity(self, self.run_velocity)
mobs.set_mob_animation(self, "run")
else
mobs.set_velocity(self, 0)
mobs.set_mob_animation(self, "stand")
end
mobs.set_yaw_while_attacking(self)
--make punchy mobs jump
--check for nodes to jump over
--explosive mobs will just ride against walls for now
local node_in_front_of = mobs.jump_check(self)
if node_in_front_of == 1 then
mobs.jump(self)
end
--mobs that can climb over stuff
if self.always_climb and node_in_front_of > 0 then
mobs.climb(self)
end
--auto reset punch_timer
if not self.punch_timer then
self.punch_timer = 0
end
if self.punch_timer > 0 then
self.punch_timer = self.punch_timer - dtime
end
end
mobs.punch_attack = function(self)
self.attacking:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = self.damage}
}, nil)
self.punch_timer = self.punch_timer_cooloff
--knockback
local pos1 = self.object:get_pos()
pos1.y = 0
local pos2 = self.attacking:get_pos()
pos2.y = 0
local dir = vector_direction(pos1,pos2)
dir = vector_multiply(dir,3)
if self.attacking:get_velocity().y <= 1 then
dir.y = 5
end
self.attacking:add_velocity(dir)
end
--[[
______ _ _ _ _
| ___ \ (_) | | (_) |
| |_/ / __ ___ _ ___ ___| |_ _| | ___
| __/ '__/ _ \| |/ _ \/ __| __| | |/ _ \
| | | | | (_) | | __/ (__| |_| | | __/
\_| |_| \___/| |\___|\___|\__|_|_|\___|
_/ |
|__/
]]--
mobs.projectile_attack_walk = function(self,dtime)
--this needs an exception
if self.attacking == nil or not self.attacking:is_player() then
self.attacking = nil
return
end
mobs.set_yaw_while_attacking(self)
local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos())
if distance_from_attacking >= self.reach then
mobs.set_velocity(self, self.run_velocity)
mobs.set_mob_animation(self,"run")
else
mobs.set_velocity(self,0)
mobs.set_mob_animation(self,"stand")
end
--do this to not load data into other mobs
if not self.projectile_timer then
self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max)
end
--run projectile timer
if self.projectile_timer > 0 then
self.projectile_timer = self.projectile_timer - dtime
--shoot
if self.projectile_timer <= 0 then
--reset timer
self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max)
mobs.shoot_projectile(self)
end
end
--make shooty mobs jump
--check for nodes to jump over
--explosive mobs will just ride against walls for now
local node_in_front_of = mobs.jump_check(self)
if node_in_front_of == 1 then
mobs.jump(self)
end
end
--[[
_ ______ _ _
| | | ___| | | |
| | | |_ | |_ _ | |
| | | _| | | | | | | |
|_| | | | | |_| | |_|
(_) \_| |_|\__, | (_)
__/ |
|___/
]]--
--[[
______ _ _ _ _
| ___ \ (_) | | (_) |
| |_/ / __ ___ _ ___ ___| |_ _| | ___
| __/ '__/ _ \| |/ _ \/ __| __| | |/ _ \
| | | | | (_) | | __/ (__| |_| | | __/
\_| |_| \___/| |\___|\___|\__|_|_|\___|
_/ |
|__/
]]--
local random_pitch_multiplier = {-1,1}
mobs.projectile_attack_fly = function(self, dtime)
--this needs an exception
if self.attacking == nil or not self.attacking:is_player() then
self.attacking = nil
return
end
--this is specifically for random ghast movement
if self.fly_random_while_attack then
--enable rotation locking
mobs.movement_rotation_lock(self)
self.walk_timer = self.walk_timer - dtime
--reset the walk timer
if self.walk_timer <= 0 then
--re-randomize the walk timer
self.walk_timer = math.random(1,6) + math.random()
--set the mob into a random direction
self.yaw = (math_random() * (math.pi * 2))
--create a truly random pitch, since there is no easy access to pitch math that I can find
self.pitch = math_random() * math.random(1,3) * random_pitch_multiplier[math_random(1,2)]
end
mobs.set_fly_velocity(self, self.run_velocity)
else
mobs.set_yaw_while_attacking(self)
local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos())
if distance_from_attacking >= self.reach then
mobs.set_pitch_while_attacking(self)
mobs.set_fly_velocity(self, self.run_velocity)
mobs.set_mob_animation(self,"run")
else
mobs.set_pitch_while_attacking(self)
mobs.set_fly_velocity(self, 0)
mobs.set_mob_animation(self,"stand")
end
end
--do this to not load data into other mobs
if not self.projectile_timer then
self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max)
end
--run projectile timer
if self.projectile_timer > 0 then
self.projectile_timer = self.projectile_timer - dtime
--shoot
if self.projectile_timer <= 0 then
if self.fly_random_while_attack then
mobs.set_yaw_while_attacking(self)
self.walk_timer = 0
end
--reset timer
self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max)
mobs.shoot_projectile(self)
end
end
end

View File

@ -1,179 +0,0 @@
local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius
local vector = vector
--check to see if someone nearby has some tasty food
mobs.check_following = function(self) -- returns true or false
--ignore
if not self.follow then
self.following_person = nil
return false
end
--hey look, this thing works for passive mobs too!
local follower = mobs.detect_closest_player_within_radius(self,true,self.view_range,self.eye_height)
--check if the follower is a player incase they log out
if follower and follower:is_player() then
local stack = follower:get_wielded_item()
--safety check
if not stack then
self.following_person = nil
return false
end
local item_name = stack:get_name()
--all checks have passed, that guy has some good looking food
if item_name == self.follow then
self.following_person = follower
return true
end
end
--everything failed
self.following_person = nil
return false
end
--a function which attempts to make mobs enter
--the breeding state
mobs.enter_breed_state = function(self,clicker)
--do not breed if baby
if self.baby then
return false
end
--do not do anything if looking for mate or
--if cooling off from breeding
if self.breed_lookout_timer > 0 or self.breed_timer > 0 then
return false
end
--if this is caught, that means something has gone
--seriously wrong
if not clicker or not clicker:is_player() then
return false
end
local stack = clicker:get_wielded_item()
--safety check
if not stack then
return false
end
local item_name = stack:get_name()
--all checks have passed, that guy has some good looking food
if item_name == self.follow then
if not minetest.is_creative_enabled(clicker:get_player_name()) then
stack:take_item()
clicker:set_wielded_item(stack)
end
self.breed_lookout_timer = self.breed_lookout_timer_goal
self.bred = true
mobs.play_sound_specific(self,"mobs_mc_animal_eat_generic")
return true
end
--everything failed
return false
end
--find the closest mate in the area
mobs.look_for_mate = function(self)
local pos1 = self.object:get_pos()
pos1.y = pos1.y + self.eye_height
local mates_in_area = {}
local winner_mate = nil
local mates_detected = 0
local radius = self.view_range
--get mates in radius
for _,mate in pairs(minetest_get_objects_inside_radius(pos1, radius)) do
--look for a breeding mate
if mate and mate:get_luaentity()
and mate:get_luaentity()._cmi_is_mob
and mate:get_luaentity().name == self.name
and mate:get_luaentity().breed_lookout_timer > 0
and mate:get_luaentity() ~= self then
local pos2 = mate:get_pos()
local distance = vector.distance(pos1,pos2)
if distance <= radius then
if minetest.line_of_sight then
--must add eye height or stuff breaks randomly because of
--seethrough nodes being a blocker (like grass)
if minetest.line_of_sight(
vector.new(pos1.x, pos1.y, pos1.z),
vector.new(pos2.x, pos2.y + mate:get_properties().eye_height, pos2.z)
) then
mates_detected = mates_detected + 1
mates_in_area[mate] = distance
end
else
mates_detected = mates_detected + 1
mates_in_area[mate] = distance
end
end
end
end
--return if there's no one near by
if mates_detected <= 0 then --handle negative numbers for some crazy error that could possibly happen
return nil
end
--do a default radius max
local shortest_distance = radius + 1
--sort through mates and find the closest mate
for mate,distance in pairs(mates_in_area) do
if distance < shortest_distance then
shortest_distance = distance
winner_mate = mate
end
end
return winner_mate
end
--make the baby grow up
mobs.baby_grow_up = function(self)
self.baby = nil
self.visual_size = self.backup_visual_size
self.collisionbox = self.backup_collisionbox
self.selectionbox = self.backup_selectionbox
self.object:set_properties(self)
end
--makes the baby grow up faster with diminishing returns
mobs.make_baby_grow_faster = function(self,clicker)
if clicker and clicker:is_player() then
local stack = clicker:get_wielded_item()
--safety check
if not stack then
return false
end
local item_name = stack:get_name()
--all checks have passed, that guy has some good looking food
if item_name == self.follow then
self.grow_up_timer = self.grow_up_timer - (self.grow_up_timer * 0.10) --take 10 percent off - diminishing returns
if not minetest.is_creative_enabled(clicker:get_player_name()) then
stack:take_item()
clicker:set_wielded_item(stack)
end
mobs.play_sound_specific(self,"mobs_mc_animal_eat_generic")
return true
end
end
return false
end

View File

@ -1,135 +0,0 @@
local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius
local math_random = math.random
local vector_multiply = vector.multiply
local vector_direction = vector.direction
local integer_test = {-1,1}
mobs.collision = function(self)
local pos = self.object:get_pos()
if not self or not self.object or not self.object:get_luaentity() then
return
end
--do collision detection from the base of the mob
local collisionbox = self.object:get_properties().collisionbox
pos.y = pos.y + collisionbox[2]
local collision_boundary = collisionbox[4]
local radius = collision_boundary
if collisionbox[5] > collision_boundary then
radius = collisionbox[5]
end
local collision_count = 0
local check_for_attack = false
if self.attack_type == "punch" and self.hostile and self.attacking then
check_for_attack = true
end
for _,object in ipairs(minetest_get_objects_inside_radius(pos, radius*1.25)) do
if object and object ~= self.object and (object:is_player() or (object:get_luaentity() and object:get_luaentity()._cmi_is_mob == true and object:get_luaentity().health > 0)) and
--don't collide with rider, rider don't collide with thing
(not object:get_attach() or (object:get_attach() and object:get_attach() ~= self.object)) and
(not self.object:get_attach() or (self.object:get_attach() and self.object:get_attach() ~= object)) then
--stop infinite loop
collision_count = collision_count + 1
--mob cramming
if collision_count > 30 then
self.health = -20
break
end
local pos2 = object:get_pos()
local object_collisionbox = object:get_properties().collisionbox
pos2.y = pos2.y + object_collisionbox[2]
local object_collision_boundary = object_collisionbox[4]
--this is checking the difference of the object collided with's possision
--if positive top of other object is inside (y axis) of current object
local y_base_diff = (pos2.y + object_collisionbox[5]) - pos.y
local y_top_diff = (pos.y + collisionbox[5]) - pos2.y
local distance = vector.distance(vector.new(pos.x,0,pos.z),vector.new(pos2.x,0,pos2.z))
if distance <= collision_boundary + object_collision_boundary and y_base_diff >= 0 and y_top_diff >= 0 then
local dir = vector.direction(pos,pos2)
dir.y = 0
--eliminate mob being stuck in corners
if dir.x == 0 and dir.z == 0 then
--slightly adjust mob position to prevent equal length
--corner/wall sticking
dir.x = dir.x + ((math_random()/10)*integer_test[math.random(1,2)])
dir.z = dir.z + ((math_random()/10)*integer_test[math.random(1,2)])
end
local velocity = dir
--0.5 is the max force multiplier
local force = 0.5 - (0.5 * distance / (collision_boundary + object_collision_boundary))
local vel1 = vector.multiply(velocity, -1.5)
local vel2 = vector.multiply(velocity, 1.5)
vel1 = vector.multiply(vel1, force * 10)
vel2 = vector.multiply(vel2, force)
if object:is_player() then
vel2 = vector_multiply(vel2, 2.5)
--integrate mob punching into collision detection
if check_for_attack and self.punch_timer <= 0 then
if object == self.attacking then
mobs.punch_attack(self)
end
end
end
self.object:add_velocity(vel1)
object:add_velocity(vel2)
end
end
end
end
--this is used for arrow collisions
mobs.arrow_hit = function(self, player)
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = self._damage}
}, nil)
--knockback
local pos1 = self.object:get_pos()
pos1.y = 0
local pos2 = player:get_pos()
pos2.y = 0
local dir = vector_direction(pos1,pos2)
dir = vector_multiply(dir,3)
if player:get_velocity().y <= 1 then
dir.y = 5
end
player:add_velocity(dir)
end

View File

@ -1,161 +0,0 @@
local minetest_add_item = minetest.add_item
--local minetest_sound_play = minetest.sound_play
local math_pi = math.pi
local math_random = math.random
local math_floor = math.floor
local HALF_PI = math_pi / 2
local vector_new = vector.new
-- drop items
local item_drop = function(self, cooked, looting_level)
looting_level = looting_level or 0
-- no drops for child mobs (except monster)
if (self.child and self.type ~= "monster") then
return
end
local obj, item
local pos = self.object:get_pos()
self.drops = self.drops or {} -- nil check
for n = 1, #self.drops do
local dropdef = self.drops[n]
local chance = 1 / dropdef.chance
local looting_type = dropdef.looting
if looting_level > 0 then
local chance_function = dropdef.looting_chance_function
if chance_function then
chance = chance_function(looting_level)
elseif looting_type == "rare" then
chance = chance + (dropdef.looting_factor or 0.01) * looting_level
end
end
local num = 0
local do_common_looting = (looting_level > 0 and looting_type == "common")
if math_random() < chance then
num = math_random(dropdef.min or 1, dropdef.max or 1)
elseif not dropdef.looting_ignore_chance then
do_common_looting = false
end
if do_common_looting then
num = num + math_floor(math_random(0, looting_level) + 0.5)
end
if num > 0 then
item = dropdef.name
-- cook items when true
if cooked then
local output = minetest.get_craft_result({
method = "cooking",
width = 1,
items = {item},
})
if output and output.item and not output.item:is_empty() then
item = output.item:get_name()
end
end
-- add item if it exists
for x = 1, num do
obj = minetest_add_item(pos, ItemStack(item .. " " .. 1))
end
if obj and obj:get_luaentity() then
obj:set_velocity({
x = math_random(-10, 10) / 9,
y = 6,
z = math_random(-10, 10) / 9,
})
elseif obj then
obj:remove() -- item does not exist
end
end
end
self.drops = {}
end
mobs.death_logic = function(self, dtime)
--stop crashing game when object is nil
if not self or not self.object or not self.object:get_luaentity() then
return
end
self.death_animation_timer = self.death_animation_timer + dtime
--get all attached entities and sort through them
local attached_entities = self.object:get_children()
if #attached_entities > 0 then
for _,entity in pairs(attached_entities) do
--kick the player off
if entity:is_player() then
mobs.detach(entity)
--kick mobs off
--if there is scaling issues, this needs an additional check
else
entity:set_detach()
end
end
end
--stop mob from getting in the way of other mobs you're fighting
if self.object:get_properties().pointable then
self.object:set_properties({pointable = false})
end
--the final POOF of a mob despawning
if self.death_animation_timer >= 1.25 then
item_drop(self,false,1)
mobs.death_effect(self)
mcl_experience.throw_xp(self.object:get_pos(), math_random(self.xp_min, self.xp_max))
if self.on_die then
self.on_die(self, self.object:get_pos())
end
self.object:remove()
return
end
--I'm sure there's a more efficient way to do this
--but this is the easiest, easier to work with 1 variable synced
--this is also not smooth
local death_animation_roll = self.death_animation_timer * 2 -- * 2 to make it faster
if death_animation_roll > 1 then
death_animation_roll = 1
end
local rot = self.object:get_rotation() --(no pun intended)
rot.z = death_animation_roll * HALF_PI
self.object:set_rotation(rot)
mobs.set_mob_animation(self,"stand", true)
--flying and swimming mobs just fall down
if self.fly or self.swim then
if self.object:get_acceleration().y ~= -self.gravity then
self.object:set_acceleration(vector_new(0,-self.gravity,0))
end
end
--when landing allow mob to slow down and just fall if in air
if self.pause_timer <= 0 then
mobs.set_velocity(self,0)
end
end

View File

@ -1,250 +0,0 @@
local minetest_line_of_sight = minetest.line_of_sight
--local minetest_dir_to_yaw = minetest.dir_to_yaw
local minetest_yaw_to_dir = minetest.yaw_to_dir
local minetest_get_node = minetest.get_node
local minetest_get_item_group = minetest.get_item_group
local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius
local minetest_get_node_or_nil = minetest.get_node_or_nil
local minetest_registered_nodes = minetest.registered_nodes
local minetest_get_connected_players = minetest.get_connected_players
local vector_new = vector.new
local vector_add = vector.add
local vector_multiply = vector.multiply
local vector_distance = vector.distance
local table_copy = table.copy
local math_abs = math.abs
-- default function when mobs are blown up with TNT
--[[local function do_tnt(obj, damage)
obj.object:punch(obj.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = damage},
}, nil)
return false, true, {}
end]]
--a fast function to be able to detect only players without using objects_in_radius
mobs.detect_closest_player_within_radius = function(self, line_of_sight, radius, object_height_adder)
local pos1 = self.object:get_pos()
local players_in_area = {}
local winner_player = nil
local players_detected = 0
--get players in radius
for _,player in pairs(minetest.get_connected_players()) do
if player and player:get_hp() > 0 then
local pos2 = player:get_pos()
local distance = vector_distance(pos1,pos2)
if distance <= radius then
if line_of_sight then
--must add eye height or stuff breaks randomly because of
--seethrough nodes being a blocker (like grass)
if minetest_line_of_sight(
vector_new(pos1.x, pos1.y + object_height_adder, pos1.z),
vector_new(pos2.x, pos2.y + player:get_properties().eye_height, pos2.z)
) then
players_detected = players_detected + 1
players_in_area[player] = distance
end
else
players_detected = players_detected + 1
players_in_area[player] = distance
end
end
end
end
--return if there's no one near by
if players_detected <= 0 then --handle negative numbers for some crazy error that could possibly happen
return nil
end
--do a default radius max
local shortest_distance = radius + 1
--sort through players and find the closest player
for player,distance in pairs(players_in_area) do
if distance < shortest_distance then
shortest_distance = distance
winner_player = player
end
end
return winner_player
end
--check if a mob needs to jump
mobs.jump_check = function(self,dtime)
local pos = self.object:get_pos()
pos.y = pos.y + 0.1
local dir = minetest_yaw_to_dir(self.yaw)
local collisionbox = self.object:get_properties().collisionbox
local radius = collisionbox[4] + 0.5
vector_multiply(dir, radius)
--only jump if there's a node and a non-solid node above it
local test_dir = vector_add(pos,dir)
local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0
test_dir.y = test_dir.y + 1
local green_flag_2 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") == 0
if green_flag_1 and green_flag_2 then
--can jump over node
return 1
elseif green_flag_1 and not green_flag_2 then
--wall in front of mob
return 2
end
--nothing to jump over
return 0
end
-- a helper function to quickly turn neutral passive mobs hostile
local turn_hostile = function(self,detected_mob)
--drop in variables for attacking (stops crash)
detected_mob.punch_timer = 0
--set to hostile
detected_mob.hostile = true
--hostile_cooldown timer is initialized here
detected_mob.hostile_cooldown_timer = detected_mob.hostile_cooldown
--set target to the same
detected_mob.attacking = self.attacking
end
--allow hostile mobs to signal to other mobs
--to switch from neutal passive to neutral hostile
mobs.group_attack_initialization = function(self)
--get basic data
local friends_list
if self.group_attack == true then
friends_list = {self.name}
else
friends_list = table_copy(self.group_attack)
end
local objects_in_area = minetest_get_objects_inside_radius(self.object:get_pos(), self.view_range)
--get the player's name
local name = self.attacking:get_player_name()
--re-use local variable
local detected_mob
--run through mobs in viewing distance
for _,object in pairs(objects_in_area) do
if object and object:get_luaentity() then
detected_mob = object:get_luaentity()
-- only alert members of same mob or friends
if detected_mob._cmi_is_mob and detected_mob.state ~= "attack" and detected_mob.owner ~= name then
if detected_mob.name == self.name then
turn_hostile(self,detected_mob)
else
for _,id in pairs(friends_list) do
if detected_mob.name == id then
turn_hostile(self,detected_mob)
break
end
end
end
end
--THIS NEEDS TO BE RE-IMPLEMENTED AS A GLOBAL HIT IN MOB_PUNCH!!
-- have owned mobs attack player threat
--if obj.owner == name and obj.owner_loyal then
-- do_attack(obj, self.object)
--end
end
end
end
-- check if within physical map limits (-30911 to 30927)
-- within_limits, wmin, wmax = nil, -30913, 30928
mobs.within_limits = function(pos, radius)
local wmin, wmax
if mcl_vars then
if mcl_vars.mapgen_edge_min and mcl_vars.mapgen_edge_max then
wmin, wmax = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max
end
end
return pos
and (pos.x - radius) > wmin and (pos.x + radius) < wmax
and (pos.y - radius) > wmin and (pos.y + radius) < wmax
and (pos.z - radius) > wmin and (pos.z + radius) < wmax
end
-- get node but use fallback for nil or unknown
mobs.node_ok = function(pos, fallback)
fallback = fallback or mobs.fallback_node
local node = minetest_get_node_or_nil(pos)
if node and minetest_registered_nodes[node.name] then
return node
end
return minetest_registered_nodes[fallback]
end
--a teleport functoin
mobs.teleport = function(self, target)
if self.do_teleport then
if self.do_teleport(self, target) == false then
return
end
end
end
--a function used for despawning mobs
mobs.check_for_player_within_area = function(self, radius)
local pos1 = self.object:get_pos()
--get players in radius
for _,player in pairs(minetest_get_connected_players()) do
if player and player:get_hp() > 0 then
local pos2 = player:get_pos()
local distance = vector_distance(pos1,pos2)
if distance < radius then
--found a player
return true
end
end
end
--did not find a player
return false
end
--a simple helper function for mobs following
mobs.get_2d_distance = function(pos1,pos2)
pos1.y = 0
pos2.y = 0
return vector_distance(pos1, pos2)
end
-- fall damage onto solid ground
mobs.calculate_fall_damage = function(self)
if self.old_velocity and self.old_velocity.y < -7 and self.object:get_velocity().y == 0 then
local vel = self.object:get_velocity()
if vel then
local damage = math_abs(self.old_velocity.y + 7) * 2
self.pause_timer = 0.4
self.health = self.health - damage
end
end
end

View File

@ -1,78 +0,0 @@
--this is from https://github.com/HybridDog/builtin_item/blob/e6dfd9dce86503b3cbd1474257eca5f6f6ca71c2/init.lua#L50
local
minetest,vector,math,pairs,minetest_get_node,vector_subtract,minetest_registered_nodes
=
minetest,vector,math,pairs,minetest.get_node,vector.subtract,minetest.registered_nodes
local tab
local n
local function get_nodes(pos)
tab,n = {},1
for i = -1,1,2 do
for _,p in pairs({
{x=pos.x+i, y=pos.y, z=pos.z},
{x=pos.x, y=pos.y, z=pos.z+i}
}) do
tab[n] = {p, minetest_get_node(p)}
n = n+1
end
end
return tab
end
local data
local param2
local nd
local par2
local name
local tmp
local c_node
function mobs.get_flowing_dir(pos)
c_node = minetest_get_node(pos).name
if c_node ~= "mcl_core:water_flowing" and c_node ~= "mcl_core:water" then
return nil
end
data = get_nodes(pos)
param2 = minetest_get_node(pos).param2
if param2 > 7 then
return nil
end
if c_node == "mcl_core:water" then
for _,i in pairs(data) do
nd = i[2]
name = nd.name
par2 = nd.param2
if name == "mcl_core:water_flowing" and par2 == 7 then
return(vector_subtract(i[1],pos))
end
end
end
for _,i in pairs(data) do
nd = i[2]
name = nd.name
par2 = nd.param2
if name == "mcl_core:water_flowing" and par2 < param2 then
return(vector_subtract(i[1],pos))
end
end
for _,i in pairs(data) do
nd = i[2]
name = nd.name
par2 = nd.param2
if name == "mcl_core:water_flowing" and par2 >= 11 then
return(vector_subtract(i[1],pos))
end
end
for _,i in pairs(data) do
nd = i[2]
name = nd.name
par2 = nd.param2
tmp = minetest_registered_nodes[name]
if tmp and not tmp.walkable and name ~= "mcl_core:water_flowing" and name ~= "mcl_core:water" then
return(vector_subtract(i[1],pos))
end
end
return nil
end

View File

@ -1,98 +0,0 @@
local math = math
local vector = vector
--converts yaw to degrees
local degrees = function(yaw)
return yaw*180.0/math.pi
end
mobs.do_head_logic = function(self,dtime)
local player = minetest.get_player_by_name("singleplayer")
local look_at = player:get_pos()
look_at.y = look_at.y + player:get_properties().eye_height
local pos = self.object:get_pos()
local body_yaw = self.object:get_yaw()
local body_dir = minetest.yaw_to_dir(body_yaw)
pos.y = pos.y + self.head_height_offset
local head_offset = vector.multiply(body_dir, self.head_direction_offset)
pos = vector.add(pos, head_offset)
minetest.add_particle({
pos = pos,
velocity = {x=0, y=0, z=0},
acceleration = {x=0, y=0, z=0},
expirationtime = 0.2,
size = 1,
texture = "default_dirt.png",
})
local bone_pos = vector.new(0,0,0)
--(horizontal)
bone_pos.y = self.head_bone_pos_y
--(vertical)
bone_pos.z = self.head_bone_pos_z
--print(yaw)
--local _, bone_rot = self.object:get_bone_position("head")
--bone_rot.x = bone_rot.x + (dtime * 10)
--bone_rot.z = bone_rot.z + (dtime * 10)
local head_yaw = minetest.dir_to_yaw(vector.direction(pos,look_at)) - body_yaw
if self.reverse_head_yaw then
head_yaw = head_yaw * -1
end
--over rotation protection
--stops radians from going out of spec
if head_yaw > math.pi then
head_yaw = head_yaw - (math.pi * 2)
elseif head_yaw < -math.pi then
head_yaw = head_yaw + (math.pi * 2)
end
local check_failed = false
--upper check + 90 degrees or upper math.radians (3.14/2)
if head_yaw > math.pi - (math.pi/2) then
head_yaw = 0
check_failed = true
--lower check - 90 degrees or lower negative math.radians (-3.14/2)
elseif head_yaw < -math.pi + (math.pi/2) then
head_yaw = 0
check_failed = true
end
local head_pitch = 0
--DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG
--head_yaw = 0
--DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG
if not check_failed then
head_pitch = minetest.dir_to_yaw(vector.new(vector.distance(vector.new(pos.x,0,pos.z),vector.new(look_at.x,0,look_at.z)),0,pos.y-look_at.y))+(math.pi/2)
end
if self.head_pitch_modifier then
head_pitch = head_pitch + self.head_pitch_modifier
end
if self.swap_y_with_x then
self.object:set_bone_position(self.head_bone, bone_pos, vector.new(degrees(head_pitch),degrees(head_yaw),0))
else
self.object:set_bone_position(self.head_bone, bone_pos, vector.new(degrees(head_pitch),0,degrees(head_yaw)))
end
--set_bone_position([bone, position, rotation])
end

View File

@ -1,276 +0,0 @@
local minetest_after = minetest.after
local minetest_sound_play = minetest.sound_play
local minetest_dir_to_yaw = minetest.dir_to_yaw
local math = math
local vector = vector
local MAX_MOB_NAME_LENGTH = 30
local mod_hunger = minetest.get_modpath("mcl_hunger")
mobs.feed_tame = function(self)
return nil
end
-- Code to execute before custom on_rightclick handling
local function on_rightclick_prefix(self, clicker)
local item = clicker:get_wielded_item()
-- Name mob with nametag
if not self.ignores_nametag and item:get_name() == "mcl_mobs:nametag" then
local tag = item:get_meta():get_string("name")
if tag ~= "" then
if string.len(tag) > MAX_MOB_NAME_LENGTH then
tag = string.sub(tag, 1, MAX_MOB_NAME_LENGTH)
end
self.nametag = tag
mobs.update_tag(self)
if not mobs.is_creative(clicker:get_player_name()) then
item:take_item()
clicker:set_wielded_item(item)
end
return true
end
end
return false
end
-- I have no idea what this does
mobs.create_mob_on_rightclick = function(on_rightclick)
return function(self, clicker)
--don't allow rightclicking dead mobs
if self.health <= 0 then
return
end
local stop = on_rightclick_prefix(self, clicker)
if (not stop) and (on_rightclick) then
on_rightclick(self, clicker)
end
end
end
-- deal damage and effects when mob punched
mobs.mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
--don't do anything if the mob is already dead
if self.health <= 0 then
return
end
--neutral passive mobs switch to neutral hostile
if self.neutral then
--drop in variables for attacking (stops crash)
self.attacking = hitter
self.punch_timer = 0
self.hostile = true
--hostile_cooldown timer is initialized here
self.hostile_cooldown_timer = self.hostile_cooldown
--initialize the group attack (check for other mobs in area, make them neutral hostile)
if self.group_attack then
mobs.group_attack_initialization(self)
end
end
--turn skittish mobs away and RUN
if self.skittish then
self.state = "run"
self.run_timer = 5 --arbitrary 5 seconds
local pos1 = self.object:get_pos()
pos1.y = 0
local pos2 = hitter:get_pos()
pos2.y = 0
local dir = vector.direction(pos2,pos1)
local yaw = minetest_dir_to_yaw(dir)
self.yaw = yaw
end
-- custom punch function
if self.do_punch then
-- when false skip going any further
if self.do_punch(self, hitter, tflp, tool_capabilities, dir) == false then
return
end
end
--don't do damage until pause timer resets
if self.pause_timer > 0 then
return
end
-- error checking when mod profiling is enabled
if not tool_capabilities then
minetest.log("warning", "[mobs_mc] Mod profiling enabled, damage not enabled")
return
end
local is_player = hitter:is_player()
-- punch interval
local weapon = hitter:get_wielded_item()
--local punch_interval = 1.4
-- exhaust attacker
if mod_hunger and is_player then
mcl_hunger.exhaust(hitter:get_player_name(), mcl_hunger.EXHAUST_ATTACK)
end
-- calculate mob damage
local damage = 0
local armor = self.object:get_armor_groups() or {}
--calculate damage groups
for group,_ in pairs( (tool_capabilities.damage_groups or {}) ) do
damage = damage + (tool_capabilities.damage_groups[group] or 0) * ((armor[group] or 0) / 100.0)
end
if weapon then
local fire_aspect_level = mcl_enchanting.get_enchantment(weapon, "fire_aspect")
if fire_aspect_level > 0 then
mcl_burning.set_on_fire(self.object, fire_aspect_level * 4)
end
end
-- check for tool immunity or special damage
for n = 1, #self.immune_to do
if self.immune_to[n][1] == weapon:get_name() then
damage = self.immune_to[n][2] or 0
break
end
end
-- healing
if damage <= -1 then
self.health = self.health - math.floor(damage)
return
end
--if tool_capabilities then
-- punch_interval = tool_capabilities.full_punch_interval or 1.4
--end
-- add weapon wear manually
-- Required because we have custom health handling ("health" property)
--minetest_is_creative_enabled("") ~= true --removed for now
if tool_capabilities then
if tool_capabilities.punch_attack_uses then
-- Without this delay, the wear does not work. Quite hacky ...
minetest_after(0, function(name)
local player = minetest.get_player_by_name(name)
if not player then return end
local weapon = hitter:get_wielded_item(player)
local def = weapon:get_definition()
if def.tool_capabilities and def.tool_capabilities.punch_attack_uses then
local wear = math.floor(65535/tool_capabilities.punch_attack_uses)
weapon:add_wear(wear)
hitter:set_wielded_item(weapon)
end
end, hitter:get_player_name())
end
end
--if player is falling multiply damage by 1.5
--critical hit
if hitter:get_velocity().y < 0 then
damage = damage * 1.5
mobs.critical_effect(self)
end
-- only play hit sound and show blood effects if damage is 1 or over; lower to 0.1 to ensure armor works appropriately.
if damage >= 0.1 then
minetest_sound_play("default_punch", {
object = self.object,
max_hear_distance = 16
}, true)
-- do damage
self.health = self.health - damage
--0.4 seconds until you can hurt the mob again
self.pause_timer = 0.4
--don't do knockback from a rider
for _,obj in pairs(self.object:get_children()) do
if obj == hitter then
return
end
end
-- knock back effect
local velocity = self.object:get_velocity()
--2d direction
local pos1 = self.object:get_pos()
pos1.y = 0
local pos2 = hitter:get_pos()
pos2.y = 0
local dir = vector.direction(pos2,pos1)
local up = 3
-- if already in air then dont go up anymore when hit
if velocity.y ~= 0 then
up = 0
end
--0.75 for perfect distance to not be too easy, and not be too hard
local multiplier = 0.75
-- check if tool already has specific knockback value
local knockback_enchant = mcl_enchanting.get_enchantment(hitter:get_wielded_item(), "knockback")
if knockback_enchant and knockback_enchant > 0 then
multiplier = knockback_enchant + 1 --(starts from 1, 1 would be no change)
end
--do this to sure you can punch a mob back when
--it's coming for you
if self.hostile then
multiplier = multiplier + 2
end
dir = vector.multiply(dir,multiplier)
dir.y = up
--add the velocity
self.object:add_velocity(dir)
end
end
--do internal per mob projectile calculations
mobs.shoot_projectile = function(self)
local pos1 = self.object:get_pos()
--add mob eye height
pos1.y = pos1.y + self.eye_height
local pos2 = self.attacking:get_pos()
--add player eye height
pos2.y = pos2.y + self.attacking:get_properties().eye_height
--get direction
local dir = vector.direction(pos1,pos2)
--call internal shoot_arrow function
self.shoot_arrow(self,pos1,dir)
end
mobs.update_tag = function(self)
self.object:set_properties({
nametag = self.nametag,
})
end

View File

@ -1,150 +0,0 @@
local minetest_add_particlespawner = minetest.add_particlespawner
mobs.death_effect = function(self)
local pos = self.object:get_pos()
--local yaw = self.object:get_yaw()
local collisionbox = self.object:get_properties().collisionbox
local min, max
if collisionbox then
min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]}
max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]}
end
minetest_add_particlespawner({
amount = 50,
time = 0.0001,
minpos = vector.add(pos, min),
maxpos = vector.add(pos, max),
minvel = vector.new(-0.5,0.5,-0.5),
maxvel = vector.new(0.5,1,0.5),
minexptime = 1.1,
maxexptime = 1.5,
minsize = 1,
maxsize = 2,
collisiondetection = false,
vertical = false,
texture = "mcl_particles_mob_death.png", -- this particle looks strange
})
end
mobs.critical_effect = function(self)
local pos = self.object:get_pos()
--local yaw = self.object:get_yaw()
local collisionbox = self.object:get_properties().collisionbox
local min, max
if collisionbox then
min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]}
max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]}
end
minetest_add_particlespawner({
amount = 10,
time = 0.0001,
minpos = vector.add(pos, min),
maxpos = vector.add(pos, max),
minvel = vector.new(-1,1,-1),
maxvel = vector.new(1,3,1),
minexptime = 0.7,
maxexptime = 1,
minsize = 1,
maxsize = 2,
collisiondetection = false,
vertical = false,
texture = "heart.png^[colorize:black:255",
})
end
--when feeding a mob
mobs.feed_effect = function(self)
local pos = self.object:get_pos()
--local yaw = self.object:get_yaw()
local collisionbox = self.object:get_properties().collisionbox
local min, max
if collisionbox then
min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]}
max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]}
end
minetest_add_particlespawner({
amount = 10,
time = 0.0001,
minpos = vector.add(pos, min),
maxpos = vector.add(pos, max),
minvel = vector.new(-1,1,-1),
maxvel = vector.new(1,3,1),
minexptime = 0.7,
maxexptime = 1,
minsize = 1,
maxsize = 2,
collisiondetection = false,
vertical = false,
texture = "heart.png^[colorize:gray:255",
})
end
--hearts when tamed
mobs.tamed_effect = function(self)
local pos = self.object:get_pos()
--local yaw = self.object:get_yaw()
local collisionbox = self.object:get_properties().collisionbox
local min, max
if collisionbox then
min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]}
max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]}
end
minetest_add_particlespawner({
amount = 30,
time = 0.0001,
minpos = vector.add(pos, min),
maxpos = vector.add(pos, max),
minvel = vector.new(-1,1,-1),
maxvel = vector.new(1,3,1),
minexptime = 0.7,
maxexptime = 1,
minsize = 1,
maxsize = 2,
collisiondetection = false,
vertical = false,
texture = "heart.png",
})
end
--hearts when breeding
mobs.breeding_effect = function(self)
local pos = self.object:get_pos()
--local yaw = self.object:get_yaw()
local collisionbox = self.object:get_properties().collisionbox
local min, max
if collisionbox then
min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]}
max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]}
end
minetest_add_particlespawner({
amount = 2,
time = 0.0001,
minpos = vector.add(pos, min),
maxpos = vector.add(pos, max),
minvel = vector.new(-1,1,-1),
maxvel = vector.new(1,3,1),
minexptime = 0.7,
maxexptime = 1,
minsize = 1,
maxsize = 2,
collisiondetection = false,
vertical = false,
texture = "heart.png",
})
end

View File

@ -1,390 +0,0 @@
-- localize math functions
local math = math
local HALF_PI = math.pi / 2
local DOUBLE_PI = math.pi * 2
-- localize vector functions
local vector = vector
local minetest_yaw_to_dir = minetest.yaw_to_dir
local minetest_dir_to_yaw = minetest.dir_to_yaw
local DEFAULT_JUMP_HEIGHT = 5
local DEFAULT_FLOAT_SPEED = 4
local DEFAULT_CLIMB_SPEED = 3
mobs.stick_in_cobweb = function(self)
local current_velocity = self.object:get_velocity()
local goal_velocity = vector.multiply(vector.normalize(current_velocity), 0.4)
goal_velocity.y = -0.5
local new_velocity_addition = vector.subtract(goal_velocity,current_velocity)
--smooths out mobs a bit
if vector.length(new_velocity_addition) >= 0.0001 then
self.object:add_velocity(new_velocity_addition)
end
end
--this is a generic float function
mobs.float = function(self)
local acceleration = self.object:get_acceleration()
if not acceleration then
return
end
if acceleration.y ~= 0 then
self.object:set_acceleration({x=0, y=0, z=0})
end
local current_velocity = self.object:get_velocity()
local goal_velocity = {
x = 0,
y = DEFAULT_FLOAT_SPEED,
z = 0,
}
local new_velocity_addition = vector.subtract(goal_velocity, current_velocity)
new_velocity_addition.x = 0
new_velocity_addition.z = 0
--smooths out mobs a bit
if vector.length(new_velocity_addition) >= 0.0001 then
self.object:add_velocity(new_velocity_addition)
end
end
--this is a generic climb function
mobs.climb = function(self)
local current_velocity = self.object:get_velocity()
local goal_velocity = {
x = 0,
y = DEFAULT_CLIMB_SPEED,
z = 0,
}
local new_velocity_addition = vector.subtract(goal_velocity,current_velocity)
new_velocity_addition.x = 0
new_velocity_addition.z = 0
--smooths out mobs a bit
if vector.length(new_velocity_addition) >= 0.0001 then
self.object:add_velocity(new_velocity_addition)
end
end
--[[
_ _
| | | |
| | __ _ _ __ __| |
| | / _` | '_ \ / _` |
| |___| (_| | | | | (_| |
\_____/\__,_|_| |_|\__,_|
]]
-- move mob in facing direction
--this has been modified to be internal
--internal = lua (self.yaw)
--engine = c++ (self.object:get_yaw())
mobs.set_velocity = function(self, v)
local yaw = (self.yaw or 0)
local current_velocity = self.object:get_velocity()
local goal_velocity = {
x = (math.sin(yaw) * -v),
y = 0,
z = (math.cos(yaw) * v),
}
local new_velocity_addition = vector.subtract(goal_velocity,current_velocity)
if vector.length(new_velocity_addition) > vector.length(goal_velocity) then
vector.multiply(new_velocity_addition, (vector.length(goal_velocity) / vector.length(new_velocity_addition)))
end
new_velocity_addition.y = 0
--smooths out mobs a bit
if vector.length(new_velocity_addition) >= 0.0001 then
self.object:add_velocity(new_velocity_addition)
end
end
-- calculate mob velocity
mobs.get_velocity = function(self)
local v = self.object:get_velocity()
v.y = 0
if v then
return vector.length(v)
end
return 0
end
--make mobs jump
mobs.jump = function(self, velocity)
if self.object:get_velocity().y ~= 0 or not self.old_velocity or (self.old_velocity and self.old_velocity.y > 0) then
return
end
--fallback velocity to allow modularity
velocity = velocity or DEFAULT_JUMP_HEIGHT
self.object:add_velocity(vector.new(0,velocity,0))
end
--make mobs fall slowly
mobs.mob_fall_slow = function(self)
local current_velocity = self.object:get_velocity()
local goal_velocity = {
x = 0,
y = -2,
z = 0,
}
local new_velocity_addition = vector.subtract(goal_velocity,current_velocity)
new_velocity_addition.x = 0
new_velocity_addition.z = 0
if vector.length(new_velocity_addition) > vector.length(goal_velocity) then
vector.multiply(new_velocity_addition, (vector.length(goal_velocity) / vector.length(new_velocity_addition)))
end
new_velocity_addition.x = 0
new_velocity_addition.z = 0
--smooths out mobs a bit
if vector.length(new_velocity_addition) >= 0.0001 then
self.object:add_velocity(new_velocity_addition)
end
end
--[[
_____ _
/ ___| (_)
\ `--.__ ___ _ __ ___
`--. \ \ /\ / / | '_ ` _ \
/\__/ /\ V V /| | | | | | |
\____/ \_/\_/ |_|_| |_| |_|
]]--
--make mobs flop
mobs.flop = function(self, velocity)
if self.object:get_velocity().y ~= 0 or not self.old_velocity or (self.old_velocity and self.old_velocity.y > 0) then
return false
end
mobs.set_velocity(self, 0)
--fallback velocity to allow modularity
velocity = velocity or DEFAULT_JUMP_HEIGHT
--create a random direction (2d yaw)
local dir = DOUBLE_PI * math.random()
--create a random force value
local force = math.random(0,3) + math.random()
--convert the yaw to a direction vector then multiply it times the force
local final_additional_force = vector.multiply(minetest_yaw_to_dir(dir), force)
--place in the "flop" velocity to make the mob flop
final_additional_force.y = velocity
self.object:add_velocity(final_additional_force)
return true
end
-- move mob in facing direction
--this has been modified to be internal
--internal = lua (self.yaw)
--engine = c++ (self.object:get_yaw())
mobs.set_swim_velocity = function(self, v)
local yaw = (self.yaw or 0)
local pitch = (self.pitch or 0)
if v == 0 then
pitch = 0
end
local current_velocity = self.object:get_velocity()
local goal_velocity = {
x = (math.sin(yaw) * -v),
y = pitch,
z = (math.cos(yaw) * v),
}
local new_velocity_addition = vector.subtract(goal_velocity,current_velocity)
if vector.length(new_velocity_addition) > vector.length(goal_velocity) then
vector.multiply(new_velocity_addition, (vector.length(goal_velocity) / vector.length(new_velocity_addition)))
end
--smooths out mobs a bit
if vector.length(new_velocity_addition) >= 0.0001 then
self.object:add_velocity(new_velocity_addition)
end
end
--[[
______ _
| ___| |
| |_ | |_ _
| _| | | | | |
| | | | |_| |
\_| |_|\__, |
__/ |
|___/
]]--
-- move mob in facing direction
--this has been modified to be internal
--internal = lua (self.yaw)
--engine = c++ (self.object:get_yaw())
mobs.set_fly_velocity = function(self, v)
local yaw = (self.yaw or 0)
local pitch = (self.pitch or 0)
if v == 0 then
pitch = 0
end
local current_velocity = self.object:get_velocity()
local goal_velocity = {
x = (math.sin(yaw) * -v),
y = pitch,
z = (math.cos(yaw) * v),
}
local new_velocity_addition = vector.subtract(goal_velocity,current_velocity)
if vector.length(new_velocity_addition) > vector.length(goal_velocity) then
vector.multiply(new_velocity_addition, (vector.length(goal_velocity) / vector.length(new_velocity_addition)))
end
--smooths out mobs a bit
if vector.length(new_velocity_addition) >= 0.0001 then
self.object:add_velocity(new_velocity_addition)
end
end
--a quick and simple pitch calculation between two vector positions
mobs.calculate_pitch = function(pos1, pos2)
if pos1 == nil or pos2 == nil then
return false
end
return minetest_dir_to_yaw(vector.new(vector.distance(vector.new(pos1.x,0,pos1.z),vector.new(pos2.x,0,pos2.z)),0,pos1.y - pos2.y)) + HALF_PI
end
--make mobs fly up or down based on their y difference
mobs.set_pitch_while_attacking = function(self)
local pos1 = self.object:get_pos()
local pos2 = self.attacking:get_pos()
local pitch = mobs.calculate_pitch(pos2,pos1)
self.pitch = pitch
end
--[[
___
|_ |
| |_ _ _ __ ___ _ __
| | | | | '_ ` _ \| '_ \
/\__/ / |_| | | | | | | |_) |
\____/ \__,_|_| |_| |_| .__/
| |
|_|
]]--
--special mob jump movement
mobs.jump_move = function(self, velocity)
if self.object:get_velocity().y ~= 0 or not self.old_velocity or (self.old_velocity and self.old_velocity.y > 0) then
return
end
--make the mob stick for a split second
mobs.set_velocity(self,0)
--fallback velocity to allow modularity
local jump_height = DEFAULT_JUMP_HEIGHT
local yaw = (self.yaw or 0)
local current_velocity = self.object:get_velocity()
local goal_velocity = {
x = (math.sin(yaw) * -velocity),
y = jump_height,
z = (math.cos(yaw) * velocity),
}
local new_velocity_addition = vector.subtract(goal_velocity,current_velocity)
if vector.length(new_velocity_addition) > vector.length(goal_velocity) then
vector.multiply(new_velocity_addition, (vector.length(goal_velocity) / vector.length(new_velocity_addition)))
end
--smooths out mobs a bit
if vector.length(new_velocity_addition) >= 0.0001 then
self.object:add_velocity(new_velocity_addition)
end
end
--make it so mobs do not glitch out and freak out
--when moving around over nodes
mobs.swap_auto_step_height_adjust = function(self)
local y_vel = self.object:get_velocity().y
if y_vel == 0 and self.stepheight ~= self.stepheight_backup then
self.stepheight = self.stepheight_backup
elseif y_vel ~= 0 and self.stepheight ~= 0 then
self.stepheight = 0
end
end

View File

@ -1,43 +0,0 @@
local GRAVITY = minetest.settings:get("movement_gravity")-- + 9.81
mobs.shoot_projectile_handling = function(arrow_item, pos, dir, yaw, shooter, power, damage, is_critical, bow_stack, collectable, gravity)
local obj = minetest.add_entity({x=pos.x,y=pos.y,z=pos.z}, arrow_item.."_entity")
if power == nil then
power = 19
end
if damage == nil then
damage = 3
end
gravity = gravity or -GRAVITY
local knockback
if bow_stack then
local enchantments = mcl_enchanting.get_enchantments(bow_stack)
if enchantments.power then
damage = damage + (enchantments.power + 1) / 4
end
if enchantments.punch then
knockback = enchantments.punch * 3
end
if enchantments.flame then
mcl_burning.set_on_fire(obj, math.huge)
end
end
obj:set_velocity({x=dir.x*power, y=dir.y*power, z=dir.z*power})
obj:set_acceleration({x=0, y=gravity, z=0})
obj:set_yaw(yaw-math.pi/2)
local le = obj:get_luaentity()
le._shooter = shooter
le._damage = damage
le._is_critical = is_critical
le._startpos = pos
le._knockback = knockback
le._collectable = collectable
--play custom shoot sound
if shooter and shooter.shoot_sound then
minetest.sound_play(shooter.shoot_sound, {pos=pos, max_hear_distance=16}, true)
end
return obj
end

View File

@ -1,224 +0,0 @@
local math_random = math.random
local minetest_settings = minetest.settings
-- CMI support check
local use_cmi = minetest.global_exists("cmi")
-- get entity staticdata
mobs.mob_staticdata = function(self)
--despawn mechanism
--don't despawned tamed or bred mobs
if not self.tamed and not self.bred then
if not mobs.check_for_player_within_area(self, 64) then
--print("removing SERIALIZED!")
self.object:remove()
return
end
end
self.remove_ok = true
self.attack = nil
self.following = nil
if use_cmi then
self.serialized_cmi_components = cmi.serialize_components(self._cmi_components)
end
local tmp = {}
for _,stat in pairs(self) do
local t = type(stat)
if t ~= "function"
and t ~= "nil"
and t ~= "userdata"
and _ ~= "_cmi_components" then
tmp[_] = self[_]
end
end
return minetest.serialize(tmp)
end
-- activate mob and reload settings
mobs.mob_activate = function(self, staticdata, def, dtime)
-- remove monsters in peaceful mode
if self.type == "monster" and minetest_settings:get_bool("only_peaceful_mobs", false) then
mcl_burning.extinguish(self.object)
self.object:remove()
return
end
-- load entity variables
local tmp = minetest.deserialize(staticdata)
if tmp then
for _,stat in pairs(tmp) do
self[_] = stat
end
end
--set up wandering
if not self.wandering then
self.wandering = true
end
--clear animation
self.current_animation = nil
-- select random texture, set model and size
if not self.base_texture then
-- compatiblity with old simple mobs textures
if type(def.textures[1]) == "string" then
def.textures = {def.textures}
end
self.base_texture = def.textures[math_random(1, #def.textures)]
self.base_mesh = def.mesh
self.base_size = self.visual_size
self.base_colbox = self.collisionbox
self.base_selbox = self.selectionbox
end
-- for current mobs that dont have this set
if not self.base_selbox then
self.base_selbox = self.selectionbox or self.base_colbox
end
-- set texture, model and size
local textures = self.base_texture
local mesh = self.base_mesh
local vis_size = self.base_size
local colbox = self.base_colbox
local selbox = self.base_selbox
-- specific texture if gotten
if self.gotten == true
and def.gotten_texture then
textures = def.gotten_texture
end
-- specific mesh if gotten
if self.gotten == true
and def.gotten_mesh then
mesh = def.gotten_mesh
end
-- set baby mobs to half size
if self.baby == true then
vis_size = {
x = self.base_size.x * self.baby_size,
y = self.base_size.y * self.baby_size,
}
if def.child_texture then
textures = def.child_texture[1]
end
colbox = {
self.base_colbox[1] * self.baby_size,
self.base_colbox[2] * self.baby_size,
self.base_colbox[3] * self.baby_size,
self.base_colbox[4] * self.baby_size,
self.base_colbox[5] * self.baby_size,
self.base_colbox[6] * self.baby_size
}
selbox = {
self.base_selbox[1] * self.baby_size,
self.base_selbox[2] * self.baby_size,
self.base_selbox[3] * self.baby_size,
self.base_selbox[4] * self.baby_size,
self.base_selbox[5] * self.baby_size,
self.base_selbox[6] * self.baby_size
}
end
--stop mobs from reviving
if not self.dead and not self.health then
self.health = math_random (self.hp_min, self.hp_max)
end
if not self.random_sound_timer then
self.random_sound_timer = math_random(self.random_sound_timer_min,self.random_sound_timer_max)
end
if self.breath == nil then
self.breath = self.breath_max
end
-- pathfinding init
self.path = {}
self.path.way = {} -- path to follow, table of positions
self.path.lastpos = {x = 0, y = 0, z = 0}
self.path.stuck = false
self.path.following = false -- currently following path?
self.path.stuck_timer = 0 -- if stuck for too long search for path
-- Armor groups
-- immortal=1 because we use custom health
-- handling (using "health" property)
local armor
if type(self.armor) == "table" then
armor = table.copy(self.armor)
armor.immortal = 1
else
armor = {immortal=1, fleshy = self.armor}
end
self.object:set_armor_groups(armor)
self.old_y = self.object:get_pos().y
self.old_health = self.health
self.sounds.distance = self.sounds.distance or 10
self.textures = textures
self.mesh = mesh
self.collisionbox = colbox
self.selectionbox = selbox
self.visual_size = vis_size
self.standing_in = "ignore"
self.standing_on = "ignore"
self.jump_sound_cooloff = 0 -- used to prevent jump sound from being played too often in short time
self.opinion_sound_cooloff = 0 -- used to prevent sound spam of particular sound types
self.texture_mods = {}
self.v_start = false
self.timer = 0
self.blinktimer = 0
self.blinkstatus = false
--continue mob effect on server restart
if self.dead or self.health <= 0 then
self.object:set_texture_mod("^[colorize:red:120")
else
self.object:set_texture_mod("")
end
-- set anything changed above
self.object:set_properties(self)
--update_tag(self)
--mobs.set_animation(self, "stand")
-- run on_spawn function if found
if self.on_spawn and not self.on_spawn_run then
if self.on_spawn(self) then
self.on_spawn_run = true -- if true, set flag to run once only
end
end
-- run after_activate
if def.after_activate then
def.after_activate(self, staticdata, def, dtime)
end
if use_cmi then
self._cmi_components = cmi.activate_components(self.serialized_cmi_components)
cmi.notify_activate(self.object, dtime)
end
end

View File

@ -1,59 +0,0 @@
local math_random = math.random
--generic call for sound handler for mobs (data access)
mobs.play_sound = function(self,sound)
local soundinfo = self.sounds
if not soundinfo then
return
end
local play_sound = soundinfo[sound]
if not play_sound then
return
end
mobs.play_sound_handler(self, play_sound)
end
--generic sound handler for mobs
mobs.play_sound_handler = function(self, sound)
local pitch = (100 + math_random(-15,15) + math_random()) / 100
local distance = self.sounds.distance or 16
minetest.sound_play(sound, {
object = self.object,
gain = 1.0,
max_hear_distance = distance,
pitch = pitch,
}, true)
end
--random sound timing handler
mobs.random_sound_handling = function(self,dtime)
self.random_sound_timer = self.random_sound_timer - dtime
--play sound and reset timer
if self.random_sound_timer <= 0 then
mobs.play_sound(self,"random")
self.random_sound_timer = math_random(self.random_sound_timer_min,self.random_sound_timer_max)
end
end
--used for playing a non-mob internal sound at random pitches
mobs.play_sound_specific = function(self,soundname)
local pitch = (100 + math_random(-15,15) + math_random()) / 100
local distance = self.sounds.distance or 16
minetest.sound_play(soundname, {
object = self.object,
gain = 1.0,
max_hear_distance = distance,
pitch = pitch,
}, true)
end

View File

@ -1,5 +1,5 @@
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mcl_mobs")
-- name tag
minetest.register_craftitem("mcl_mobs:nametag", {

View File

@ -1,16 +1,14 @@
local path = minetest.get_modpath(minetest.get_current_modname())
local api_path = path.."/api"
-- Mob API
dofile(api_path .. "/api.lua")
dofile(path .. "/api.lua")
-- Spawning Algorithm
dofile(api_path .. "/spawning.lua")
dofile(path .. "/spawning.lua")
-- Rideable Mobs
dofile(api_path .. "/mount.lua")
dofile(path .. "/mount.lua")
-- Mob Items
dofile(path .. "/crafts.lua")

View File

@ -1,11 +0,0 @@
# textdomain: mcl_mobs
Peaceful mode active! No monsters will spawn.=Tryb pokojowy aktywowany! Potwory nie będą się pojawiać.
This allows you to place a single mob.=To pozwala na przywołanie jednego moba.
Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns.=Postaw to w miejscu w którym chcesz aby pojawił się mob. Zwierzęta pojawią się jako oswojone chyba, że będziesz się skradał podczas stawiania. Jeśli postawisz to na spawnerze to zmienisz którego moba przywołuje.
You need the “maphack” privilege to change the mob spawner.=Potrzebujesz przywileju "maphack", aby zmienić spawner.
Name Tag=Znacznik
A name tag is an item to name a mob.=Znacznik jest przedmiotem pozwalającym nazwać moba.
Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag.=Zanim użyjesz znacznika musisz wybrać imię przy kowadle. Następnie możesz użyć znacznika by nazwać moba. To zużywa znacznik.
Only peaceful mobs allowed!=Tylko pokojowe moby są dozwolone!
Give names to mobs=Nazwij moby
Set name at anvil=Wybierz imię przy kowadle

View File

@ -0,0 +1,11 @@
# textdomain: mcl_mobs
Peaceful mode active! No monsters will spawn.=和平模式已啓用!不會生成怪物。
This allows you to place a single mob.=允許你放置一個生物。
Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns.=把它放在你希望生物出現的地方。除非你在放置的時候按住潛行鍵,否則動物會被馴服地產生。如果你把它放在一個生怪磚上,你就會改變它所產的生物。
You need the “maphack” privilege to change the mob spawner.=你要「maphack」權限來修改生怪磚。
Name Tag=命名牌
A name tag is an item to name a mob.=命名牌是一個用於命名生物的物品
Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag.=在使用名字標籤之前,你需要在一個鐵砧上設置一個名字。然後你就可以用名字標籤來給生物命名。這會消耗命名牌。
Only peaceful mobs allowed!=只允許和平生物!
Give names to mobs=替生物命名
Set name at anvil=在鐵砧上設置名字

View File

@ -0,0 +1,8 @@
if minetest.get_modpath("lucky_block") then
lucky_block:add_blocks({
{"dro", {"mcl_mobs:nametag"}, 1},
{"lig"},
})
end

View File

@ -2,4 +2,4 @@ name = mcl_mobs
author = PilzAdam
description = Adds a mob API for mods to add animals or monsters, etc.
depends = mcl_particles
optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience
optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, invisibility, lucky_block, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience

View File

@ -1,11 +1,8 @@
-- lib_mount by Blert2112 (edited by TenPlus1)
--local enable_crash = false
--local crash_threshold = 6.5 -- ignored if enable_crash=false
local math = math
local vector = vector
local enable_crash = false
local crash_threshold = 6.5 -- ignored if enable_crash=false
------------------------------------------------------------------------------
@ -13,7 +10,7 @@ local vector = vector
-- Helper functions
--
--[[local function node_ok(pos, fallback)
local node_ok = function(pos, fallback)
fallback = fallback or mobs.fallback_node
@ -24,10 +21,10 @@ local vector = vector
end
return {name = fallback}
end]]
end
--[[local function node_is(pos)
local function node_is(pos)
local node = node_ok(pos)
@ -48,7 +45,7 @@ end]]
end
return "other"
end]]
end
local function get_sign(i)
@ -63,11 +60,13 @@ local function get_sign(i)
end
--[[local function get_velocity(v, yaw, y)
local function get_velocity(v, yaw, y)
local x = -math.sin(yaw) * v
local z = math.cos(yaw) * v
return {x = x, y = y, z = z}
end]]
end
local function get_v(v)
@ -173,7 +172,7 @@ function mobs.detach(player, offset)
--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
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)
@ -188,13 +187,13 @@ end
function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
--local rot_view = 0
local rot_view = 0
--if entity.player_rotation.y == 90 then
-- rot_view = math.pi/2
--end
if entity.player_rotation.y == 90 then
rot_view = math.pi/2
end
--local acce_y = 0
local acce_y = 0
local velo = entity.object:get_velocity()
entity.v = get_v(velo) * get_sign(entity.v)
@ -207,30 +206,21 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
-- move forwards
if ctrl.up then
mobs.set_velocity(entity, entity.run_velocity)
mobs.set_mob_animation(entity, moving_anim)
entity.v = entity.v + entity.accel / 10
-- move backwards
elseif ctrl.down then
mobs.set_velocity(entity, -entity.run_velocity)
if entity.max_speed_reverse == 0 and entity.v == 0 then
return
end
mobs.set_mob_animation(entity, moving_anim)
--halt
else
mobs.set_velocity(entity, 0)
mobs.set_mob_animation(entity, stand_anim)
entity.v = entity.v - entity.accel / 10
end
-- mob rotation
-- fix mob rotation
entity.object:set_yaw(entity.driver:get_look_horizontal() - entity.rotate)
entity.yaw = entity.driver:get_look_horizontal() - entity.rotate
--[[
if can_fly then
-- fly up
@ -254,21 +244,32 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end
else
]]--
-- jump
if ctrl.jump then
-- jump
if ctrl.jump then
if velo.y == 0 then
velo.y = velo.y + entity.jump_height
acce_y = acce_y + (acce_y * 3) + 1
end
end
mobs.jump(entity)
end
--end
end
--[[
-- if not moving then set animation and return
if entity.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
if stand_anim then
mobs:set_animation(entity, stand_anim)
end
return
end
-- set moving animation
if moving_anim then
mobs:set_mob_animation(entity, moving_anim)
mobs:set_animation(entity, moving_anim)
end
-- Stop!
@ -382,17 +383,13 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end
entity.v2 = v
]]--
end
-- directional flying routine by D00Med (edited by TenPlus1)
function mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim)
if true then
print("succ")
return
end
local ctrl = entity.driver:get_player_control()
local velo = entity.object:get_velocity()
local dir = entity.driver:get_look_dir()
@ -443,9 +440,9 @@ function mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim)
-- change animation if stopped
if velo.x == 0 and velo.y == 0 and velo.z == 0 then
mobs:set_mob_animation(entity, stand_anim)
mobs:set_animation(entity, stand_anim)
else
-- moving animation
mobs:set_mob_animation(entity, moving_anim)
mobs:set_animation(entity, moving_anim)
end
end

View File

@ -1,4 +0,0 @@
default_punch.1 = https://freesound.org/people/Merrick079/sounds/566436/
default_punch.2 = https://freesound.org/people/Merrick079/sounds/566435/
default_punch.3 = https://freesound.org/people/Merrick079/sounds/566434/

Binary file not shown.

View File

@ -1,32 +1,17 @@
--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 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 get_biome_name = minetest.get_biome_name
local get_objects_inside_radius = minetest.get_objects_inside_radius
local get_connected_players = minetest.get_connected_players
local new_vector = vector.new
local math_random = math.random
local math_floor = math.floor
--local max = math.max
--local vector_distance = vector.distance
local vector_new = vector.new
local vector_floor = vector.floor
local table_copy = table.copy
local table_remove = table.remove
local pairs = pairs
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 = 48
--do mobs spawn?
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
local aoc_range = 32
--[[
THIS IS THE BIG LIST OF ALL BIOMES - used for programming/updating mobs
@ -168,14 +153,28 @@ Overworld regular:
-- count how many mobs are in an area
local function count_mobs(pos)
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)
local num = 0
for _,object in pairs(get_objects_inside_radius(pos, aoc_range)) do
if object and object:get_luaentity() and object:get_luaentity()._cmi_is_mob then
num = num + 1
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
@ -244,7 +243,8 @@ function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_ligh
end
--[[
local function spawn_action(pos, node, active_object_count, active_object_count_wider, name)
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?
@ -281,7 +281,7 @@ function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_ligh
end
-- if toggle set to nil then ignore day/night check
if day_toggle then
if day_toggle ~= nil then
local tod = (minetest.get_timeofday() or 0) * 24000
@ -371,7 +371,7 @@ function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_ligh
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 and (not minetest.registered_nodes[node_ok(pos).name].walkable) then
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
@ -484,26 +484,25 @@ end
local axis
--inner and outer part of square donut radius
local inner = 15
local outer = 64
local inner = 1
local outer = 65
local int = {-1,1}
local position_calculation = function(pos)
local function position_calculation(pos)
pos = vector_floor(pos)
pos = vector.floor(pos)
--this is used to determine the axis buffer from the player
axis = math_random(0,1)
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)
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)
pos.z = pos.z + math.random(inner,outer)*int[math.random(1,2)]
pos.x = pos.x + math.random(-outer,outer)
end
return pos
return(pos)
end
--[[
@ -517,7 +516,7 @@ local decypher_limits_dictionary = {
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)
posy = math.floor(posy)
return posy - 32, posy + 32
end
@ -540,169 +539,118 @@ if mobs_spawn then
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer >= 10 then
if timer >= 8 then
timer = 0
for _,player in pairs(get_connected_players()) do
-- after this line each "break" means "continue"
local do_mob_spawning = true
repeat
--don't need to get these variables more than once
--they happen in a single server step
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 player_pos = player:get_pos()
local dimension = mcl_worlds.pos_to_dimension(player_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
if dimension == "void" or dimension == "default" then
break -- ignore void and unloaded area
end
local min, max = decypher_limits(player_pos.y)
local min,max = decypher_limits(player_pos.y)
for i = 1, math_random(1,4) do
-- after this line each "break" means "continue"
local do_mob_algorithm = true
repeat
local goal_pos = position_calculation(player_pos)
local goal_pos = position_calculation(player_pos)
local spawning_position_list = find_nodes_in_area_under_air(vector_new(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 --- this is commented out: /too close to player --fixed with inner circle
if not spawning_position then -- or vector_distance(player_pos, spawning_position) < 15
break
end
--hard code mob limit in area to 5 for now
if count_mobs(spawning_position) >= 5 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
--add this so mobs don't spawn inside nodes
spawning_position.y = spawning_position.y + 1
--only need to poll for node light if everything else worked
local gotten_light = get_node_light(spawning_position)
local is_water = get_item_group(gotten_node, "water") ~= 0
local is_lava = get_item_group(gotten_node, "lava") ~= 0
local mob_def = nil
--create a disconnected clone of the spawn dictionary
--prevents memory leak
local mob_library_worker_table = table_copy(spawn_dictionary)
--grab mob that fits into the spawning location
--randomly grab a mob, don't exclude any possibilities
local repeat_mob_search = true
repeat
--do not infinite loop
if #mob_library_worker_table <= 0 then
--print("breaking infinite loop")
break
end
local skip = false
--use this for removing table elements of mobs that do not match
local temp_index = math_random(1,#mob_library_worker_table)
local temp_def = mob_library_worker_table[temp_index]
--skip if something ridiculous happens (nil mob def)
--something truly horrible has happened if skip gets
--activated at this point
if not temp_def then
skip = true
end
if not skip and (spawning_position.y < temp_def.min_height or spawning_position.y > temp_def.max_height) then
skip = true
end
--skip if not correct dimension
if not skip and (temp_def.dimension ~= dimension) then
skip = true
end
--skip if not in correct biome
if not skip and (not biome_check(temp_def.biomes, gotten_biome)) then
skip = true
end
--don't spawn if not in light limits
if not skip and (gotten_light < temp_def.min_light or gotten_light > temp_def.max_light) then
skip = true
end
--skip if not in correct spawning type
if not skip and (temp_def.type_of_spawning == "ground" and is_water) then
skip = true
end
if not skip and (temp_def.type_of_spawning == "ground" and is_lava) then
skip = true
end
--found a mob, exit out of loop
if not skip then
--minetest.log("warning", "found mob:"..temp_def.name)
--print("found mob:"..temp_def.name)
mob_def = table_copy(temp_def)
break
else
--minetest.log("warning", "deleting temp index "..temp_index)
--print("deleting temp index")
table_remove(mob_library_worker_table, temp_index)
end
until repeat_mob_search == false --this is needed to sort through mobs randomly
--catch if went through all mobs and something went horribly wrong
--could not find a valid mob to spawn that fits the environment
if not mob_def 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
--print("spawning: " .. mob_def.name)
--everything is correct, spawn mob
minetest.add_entity(spawning_position, mob_def.name)
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
until do_mob_algorithm == false --this is a safety catch
end
end
break
until do_mob_spawning == false --this is a performance catch
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)
local gotten_node_name = gotten_node.name
local gotten_node_def = minetest.registered_nodes[gotten_node_name]
if not gotten_node_name or not gotten_node_def or gotten_node_name == "air" then --skip air nodes
break
end
if gotten_node_def.use_texture_alpha and gotten_node_def.use_texture_alpha ~= "opaque" then
break
end --don't spawn on nonopaque nodes
local leaf = minetest.get_item_group(gotten_node_name,"leaves")
if leaf ~= 0 then
break end --don't spawn on treetops
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_name, "water") ~= 0
local is_lava = get_item_group(gotten_node_name, "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)

View File

@ -1 +0,0 @@
--use vector.distance to count down mob despawn timer

View File

@ -0,0 +1,2 @@
# textdomain:mcl_paintings
Painting=畫

View File

@ -15,7 +15,7 @@ with name "mobs_mc_gameconfig". ]]
-- Set to false in your gameconfig mod if you create your own monster egg nodes.
mobs_mc.create_monster_egg_nodes = true
--mobs_mc.items = {}
mobs_mc.items = {}
mobs_mc.items = {
-- Items defined in mobs_mc
@ -81,9 +81,7 @@ mobs_mc.items = {
gunpowder = "tnt:gunpowder",
flint_and_steel = "fire:flint_and_steel",
water_source = "default:water_source",
water_flowing = "default:water_flowing",
river_water_source = "default:river_water_source",
--water_flowing = "default:river_water_flowing",
black_dye = "dye:black",
poppy = "flowers:rose",
dandelion = "flowers:dandelion_yellow",
@ -128,6 +126,7 @@ mobs_mc.items = {
nether_portal = "nether:portal",
netherrack = "nether:rack",
nether_brick_block = "nether:brick",
-- Wool (Minecraft color scheme)
wool_white = "wool:white",

View File

@ -525,7 +525,7 @@ if c("totem") then
inventory_image = "mcl_totems_totem.png",
wield_image = "mcl_totems_totem.png",
stack_max = 1,
groups = {combat_item=1},
groups = {combat_item = 1, offhand_item = 1},
})
end

View File

@ -6,7 +6,7 @@
-- NOTE: Strings intentionally not marked for translation, other mods already have these items.
-- TODO: Remove this file eventually, all items here are already outsourced in other mods.
--local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--maikerumines throwing code
--arrow (weapon)
@ -83,7 +83,7 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime)
if self.timer>0.2 then
local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 1.5)
for k, obj in pairs(objs) do
if obj:get_luaentity() then
if obj:get_luaentity() ~= nil then
if obj:get_luaentity().name ~= "mobs_mc:arrow_entity" and obj:get_luaentity().name ~= "__builtin:item" then
local damage = 3
minetest.sound_play("damage", {pos = pos}, true)
@ -108,7 +108,7 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime)
if self.lastpos.x~=nil then
if node.name ~= "air" then
minetest.sound_play("bowhit1", {pos = pos}, true)
minetest.add_item(self.lastpos, "mobs_mc:arrow")
minetest.add_item(self.lastpos, 'mobs_mc:arrow')
self.object:remove()
end
end
@ -155,7 +155,7 @@ end
if c("arrow") and c("flint") and c("feather") and c("stick") then
minetest.register_craft({
output = "mobs_mc:arrow 4",
output = 'mobs_mc:arrow 4',
recipe = {
{mobs_mc.items.flint},
{mobs_mc.items.stick},
@ -181,11 +181,11 @@ if c("bow") then
})
minetest.register_craft({
output = "mobs_mc:bow_wood",
output = 'mobs_mc:bow_wood',
recipe = {
{mobs_mc.items.string, mobs_mc.items.stick, ""},
{mobs_mc.items.string, "", mobs_mc.items.stick},
{mobs_mc.items.string, mobs_mc.items.stick, ""},
{mobs_mc.items.string, mobs_mc.items.stick, ''},
{mobs_mc.items.string, '', mobs_mc.items.stick},
{mobs_mc.items.string, mobs_mc.items.stick, ''},
}
})
end
@ -259,7 +259,7 @@ if c("egg") then
})
-- shoot egg
local function mobs_shoot_egg(item, player, pointed_thing)
local mobs_shoot_egg = function (item, player, pointed_thing)
local playerpos = player:get_pos()
@ -349,7 +349,7 @@ mobs:register_arrow("mobs_mc:snowball_entity", {
if c("snowball") then
-- shoot snowball
local function mobs_shoot_snowball(item, player, pointed_thing)
local mobs_shoot_snowball = function (item, player, pointed_thing)
local playerpos = player:get_pos()

View File

@ -50,8 +50,10 @@ mobs_mc.make_owner_teleport_function = function(dist, teleport_check_interval)
local telepos_below = {x=telepos.x, y=telepos.y-1, z=telepos.z}
table.remove(check_offsets, r)
-- Long story short, spawn on a platform
if minetest.registered_nodes[minetest.get_node(telepos).name].walkable == false and
minetest.registered_nodes[minetest.get_node(telepos_below).name].walkable == true then
local trynode = minetest.registered_nodes[minetest.get_node(telepos).name]
local trybelownode = minetest.registered_nodes[minetest.get_node(telepos_below).name]
if trynode and not trynode.walkable and
trybelownode and trybelownode.walkable then
-- Correct position found! Let's teleport.
self.object:set_pos(telepos)
return

View File

@ -3,9 +3,8 @@
-- NOTE: Strings intentionally not marked for translation, other mods already have these items.
-- TODO: Remove this file eventually, all items here are already outsourced in other mods.
-- TODO: Add translation.
--local S = local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
-- Heads system

View File

@ -190,10 +190,9 @@ Origin of those models:
* [Spennnyyy](https://freesound.org/people/Spennnyyy/) (CC0)
* `mcl_totems_totem.ogg`
* Source: <https://freesound.org/people/Spennnyyy/sounds/323502/>
* [Baŝto](https://opengameart.org/users/ba%C5%9Dto) (remixer) and [kantouth](https://freesound.org/people/kantouth/) (original author)
* [Baŝto](https://opengameart.org/users/ba%C5%9Dto)
* `mobs_mc_skeleton_random.*.ogg` (CC BY 3.0)
* Source: <https://opengameart.org/content/walking-skeleton>
* Based on: <https://freesound.org/people/kantouth/sounds/115113/>
* [spookymodem](https://freesound.org/people/spookymodem/)
* `mobs_mc_skeleton_death.ogg` (CC0)
* <https://freesound.org/people/spookymodem/sounds/202091/>
@ -307,4 +306,4 @@ Origin of those models:
Note: Many of these sounds have been more or less modified to fit the game.
Sounds not mentioned here are licensed under CC0.
Sounds not mentioned hre are licensed under CC0.

View File

@ -2,7 +2,7 @@
--################### AGENT - seemingly unused
--###################
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
mobs:register_mob("mobs_mc:agent", {
type = "npc",

View File

@ -1,6 +1,6 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
mobs:register_mob("mobs_mc:bat", {
description = S("Bat"),
@ -8,9 +8,6 @@ mobs:register_mob("mobs_mc:bat", {
spawn_class = "ambient",
can_despawn = true,
passive = true,
rotate = 270,
tilt_fly = true,
fly = true,
hp_min = 6,
hp_max = 6,
collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.89, 0.25},
@ -48,7 +45,9 @@ mobs:register_mob("mobs_mc:bat", {
fall_damage = 0,
view_range = 16,
fear_height = 0,
jump = false,
fly = true,
makes_footstep_sound = false,
})

View File

@ -3,7 +3,9 @@
-- 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(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
local mod_target = minetest.get_modpath("mcl_target")
--###################
--################### BLAZE
@ -18,9 +20,6 @@ mobs:register_mob("mobs_mc:blaze", {
hp_max = 20,
xp_min = 10,
xp_max = 10,
tilt_fly = false,
hostile = true,
--rotate = 270,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.79, 0.3},
rotate = -180,
visual = "mesh",
@ -39,7 +38,7 @@ mobs:register_mob("mobs_mc:blaze", {
walk_velocity = .8,
run_velocity = 1.6,
damage = 6,
reach = 4, -- don't want blaze getting too close
reach = 2,
pathfinding = 1,
drops = {
{name = mobs_mc.items.blaze_rod,
@ -67,7 +66,7 @@ mobs:register_mob("mobs_mc:blaze", {
fall_speed = -2.25,
light_damage = 0,
view_range = 16,
attack_type = "projectile",
attack_type = "dogshoot",
arrow = "mobs_mc:blaze_fireball",
shoot_interval = 3.5,
shoot_offset = 1.0,
@ -79,18 +78,9 @@ mobs:register_mob("mobs_mc:blaze", {
fear_height = 0,
glow = 14,
fire_resistant = true,
eye_height = 0.75,
projectile_cooldown_min = 2,
projectile_cooldown_max = 3,
shoot_arrow = function(self, pos, dir)
-- 2-4 damage per arrow
local dmg = math.random(2,4)
mobs.shoot_projectile_handling("mobs_mc:blaze_fireball", pos, dir, self.object:get_yaw(), self.object, 7, dmg,nil,nil,nil,-0.4)
end,
do_custom = function(self)
if self.attacking and self.state == "attack" and vector.distance(self.object:get_pos(), self.attacking:get_pos()) < 1.2 then
mcl_burning.set_on_fire(self.attacking, 5)
if self.state == "attack" and self.attack:get_pos() 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({
@ -160,11 +150,6 @@ mobs:register_arrow("mobs_mc:blaze_fireball", {
visual_size = {x = 0.3, y = 0.3},
textures = {"mcl_fire_fire_charge.png"},
velocity = 15,
speed = 5,
tail = 1,
tail_texture = "mobs_mc_spit.png^[colorize:black:255", --repurpose spit texture
tail_size = 2,
tail_distance_divider = 3,
_is_fireball = true,
-- Direct hit, no fire... just plenty of pain
@ -172,7 +157,7 @@ mobs:register_arrow("mobs_mc:blaze_fireball", {
mcl_burning.set_on_fire(player, 5)
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = self._damage},
damage_groups = {fleshy = 5},
}, nil)
end,
@ -180,7 +165,7 @@ mobs:register_arrow("mobs_mc:blaze_fireball", {
mcl_burning.set_on_fire(mob, 5)
mob:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = self._damage},
damage_groups = {fleshy = 5},
}, nil)
end,
@ -195,19 +180,20 @@ mobs:register_arrow("mobs_mc:blaze_fireball", {
-- Node hit, make fire
hit_node = function(self, pos, node)
if node.name ~= "air" then
local pos_above = table.copy(pos)
pos_above.y = pos_above.y + 1
minetest.set_node(pos_above, {name=mobs_mc.items.fire})
if node == "air" then
minetest.set_node(pos, {name = mobs_mc.items.fire})
else
local v = self.object:get_velocity()
v = vector.normalize(v)
if self._shot_from_dispenser and mod_target and node == "mcl_target:target_off" then
mcl_target.hit(vector.round(pos), 0.4) --4 redstone ticks
end
local v = vector.normalize(self.object:get_velocity())
local crashpos = vector.subtract(pos, v)
local crashnode = minetest.get_node(crashpos)
local cndef = minetest.registered_nodes[crashnode.name]
-- Set fire if node is air, or a replacable flammable node (e.g. a plant)
if crashnode.name == "air" or
(minetest.registered_nodes[crashnode.name].buildable_to and minetest.get_item_group(crashnode.name, "flammable") >= 1) then
minetest.set_node(crashpos, {name=mobs_mc.items.fire})
(cndef and cndef.buildable_to and minetest.get_item_group(crashnode.name, "flammable") >= 1) then
minetest.set_node(crashpos, {name = mobs_mc.items.fire})
end
end
end

View File

@ -1,6 +1,6 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### CHICKEN
@ -18,8 +18,7 @@ mobs:register_mob("mobs_mc:chicken", {
xp_min = 1,
xp_max = 3,
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.69, 0.2},
skittish = true,
fall_slow = true,
runaway = true,
floats = 1,
visual = "mesh",
mesh = "mobs_mc_chicken.b3d",
@ -27,10 +26,9 @@ mobs:register_mob("mobs_mc:chicken", {
{"mobs_mc_chicken.png"},
},
visual_size = {x=2.2, y=2.2},
rotate = 270,
makes_footstep_sound = true,
walk_velocity = 1,
run_velocity = 3,
drops = {
{name = mobs_mc.items.chicken_raw,
chance = 1,
@ -66,25 +64,14 @@ mobs:register_mob("mobs_mc:chicken", {
run_start = 0, run_end = 40,
},
follow = "mcl_farming:wheat_seeds",
breed_distance = 1.5,
baby_size = 0.5,
follow_distance = 2,
follow = mobs_mc.follow.chicken,
view_range = 16,
fear_height = 4,
--why do chickend breed if they lay eggs??
on_rightclick = function(self, clicker)
--attempt to enter breed state
if mobs.enter_breed_state(self,clicker) then
return
end
--make baby grow faster
if self.baby then
mobs.make_baby_grow_faster(self,clicker)
return
end
if mobs:feed_tame(self, clicker, 1, true, true) then return end
if mobs:protect(self, clicker) then return end
if mobs:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end
end,
do_custom = function(self, dtime)
@ -111,21 +98,6 @@ mobs:register_mob("mobs_mc:chicken", {
}, true)
end,
--head code
has_head = true,
head_bone = "head",
swap_y_with_x = false,
reverse_head_yaw = false,
head_bone_pos_y = 1.675,
head_bone_pos_z = 0,
head_height_offset = 0.55,
head_direction_offset = 0.0925,
head_pitch_modifier = -math.pi/2,
--end head code
})
--spawn
@ -134,53 +106,42 @@ mobs:spawn_specific(
"overworld",
"ground",
{
"FlowerForest_beach",
"Forest_beach",
"StoneBeach",
"ColdTaiga_beach_water",
"Taiga_beach",
"Savanna_beach",
"Plains_beach",
"ExtremeHills_beach",
"ColdTaiga_beach",
"Swampland_shore",
"JungleM_shore",
"Jungle_shore",
"MesaPlateauFM_sandlevel",
"MesaPlateauF_sandlevel",
"MesaBryce_sandlevel",
"Mesa_sandlevel",
"Mesa",
"FlowerForest",
"Swampland",
"Taiga",
"ExtremeHills",
"Jungle",
"Savanna",
"BirchForest",
"MegaSpruceTaiga",
"MegaTaiga",
"ExtremeHills+",
"Forest",
"Plains",
"Desert",
"ColdTaiga",
"flat",
"IcePlainsSpikes",
"SunflowerPlains",
"IcePlains",
"RoofedForest",
"ExtremeHills+_snowtop",
"MesaPlateauFM_grasstop",
"JungleEdgeM",
"ColdTaiga",
"ColdTaiga_beach",
"ColdTaiga_beach_water",
"MegaTaiga",
"MegaSpruceTaiga",
"ExtremeHills",
"ExtremeHills_beach",
"ExtremeHillsM",
"JungleM",
"ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach",
"Plains",
"Plains_beach",
"SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"JungleEdge",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
},
9,
minetest.LIGHT_MAX+1,

View File

@ -1,6 +1,6 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
local cow_def = {
description = S("Cow"),
@ -10,7 +10,6 @@ local cow_def = {
hp_max = 10,
xp_min = 1,
xp_max = 3,
rotate = 270,
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.39, 0.45},
visual = "mesh",
mesh = "mobs_mc_cow.b3d",
@ -21,7 +20,6 @@ local cow_def = {
visual_size = {x=2.8, y=2.8},
makes_footstep_sound = true,
walk_velocity = 1,
run_velocity = 3,
drops = {
{name = mobs_mc.items.beef_raw,
chance = 1,
@ -34,7 +32,7 @@ local cow_def = {
max = 2,
looting = "common",},
},
skittish = true,
runaway = true,
sounds = {
random = "mobs_mc_cow",
damage = "mobs_mc_cow_hurt",
@ -49,17 +47,12 @@ local cow_def = {
walk_end = 40, run_start = 0,
run_end = 40,
},
--follow = mobs_mc.follow.cow,
follow = mobs_mc.follow.cow,
on_rightclick = function(self, clicker)
if mobs:feed_tame(self, clicker, 1, true, true) then return end
if mobs:protect(self, clicker) then return end
--attempt to enter breed state
if mobs.enter_breed_state(self,clicker) then
return
end
--make baby grow faster
if self.baby then
mobs.make_baby_grow_faster(self,clicker)
if self.child then
return
end
@ -78,28 +71,11 @@ local cow_def = {
end
return
end
mobs:capture_mob(self, clicker, 0, 5, 60, false, nil)
end,
breed_distance = 1.5,
baby_size = 0.5,
follow_distance = 2,
follow = mobs_mc.items.wheat,
view_range = 10,
fear_height = 4,
--head code
has_head = true,
head_bone = "head",
swap_y_with_x = false,
reverse_head_yaw = false,
head_bone_pos_y = 3.6,
head_bone_pos_z = -0.6,
head_height_offset = 1.0525,
head_direction_offset = 0.5,
head_pitch_modifier = 0,
--end head code
}
mobs:register_mob("mobs_mc:cow", cow_def)
@ -110,17 +86,12 @@ mooshroom_def.description = S("Mooshroom")
mooshroom_def.mesh = "mobs_mc_cow.b3d"
mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } }
mooshroom_def.on_rightclick = function(self, clicker)
--attempt to enter breed state
if mobs.enter_breed_state(self,clicker) then
if mobs:feed_tame(self, clicker, 1, true, true) then return end
if mobs:protect(self, clicker) then return end
if self.child then
return
end
--make baby grow faster
if self.baby then
mobs.make_baby_grow_faster(self,clicker)
return
end
local item = clicker:get_wielded_item()
-- Use shears to get mushrooms and turn mooshroom into cow
if item:get_name() == mobs_mc.items.shears then
@ -169,6 +140,7 @@ mooshroom_def.on_rightclick = function(self, clicker)
minetest.add_item(pos, {name = mobs_mc.items.mushroom_stew})
end
end
mobs:capture_mob(self, clicker, 0, 5, 60, false, nil)
end
mobs:register_mob("mobs_mc:mooshroom", mooshroom_def)
@ -179,53 +151,42 @@ mobs:spawn_specific(
"overworld",
"ground",
{
"FlowerForest_beach",
"Forest_beach",
"StoneBeach",
"ColdTaiga_beach_water",
"Taiga_beach",
"Savanna_beach",
"Plains_beach",
"ExtremeHills_beach",
"ColdTaiga_beach",
"Swampland_shore",
"JungleM_shore",
"Jungle_shore",
"MesaPlateauFM_sandlevel",
"MesaPlateauF_sandlevel",
"MesaBryce_sandlevel",
"Mesa_sandlevel",
"Mesa",
"FlowerForest",
"Swampland",
"Taiga",
"ExtremeHills",
"Jungle",
"Savanna",
"BirchForest",
"MegaSpruceTaiga",
"MegaTaiga",
"ExtremeHills+",
"Forest",
"Plains",
"Desert",
"ColdTaiga",
"flat",
"IcePlainsSpikes",
"SunflowerPlains",
"IcePlains",
"RoofedForest",
"ExtremeHills+_snowtop",
"MesaPlateauFM_grasstop",
"JungleEdgeM",
"ColdTaiga",
"ColdTaiga_beach",
"ColdTaiga_beach_water",
"MegaTaiga",
"MegaSpruceTaiga",
"ExtremeHills",
"ExtremeHills_beach",
"ExtremeHillsM",
"JungleM",
"ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach",
"Plains",
"Plains_beach",
"SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"JungleEdge",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
},
9,
minetest.LIGHT_MAX+1,

View File

@ -1,6 +1,6 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### CREEPER
@ -12,8 +12,6 @@ local S = minetest.get_translator(minetest.get_current_modname())
mobs:register_mob("mobs_mc:creeper", {
type = "monster",
spawn_class = "hostile",
hostile = true,
rotate = 270,
hp_min = 20,
hp_max = 20,
xp_min = 5,
@ -35,44 +33,28 @@ mobs:register_mob("mobs_mc:creeper", {
explode = "tnt_explode",
distance = 16,
},
makes_footstep_sound = false,
makes_footstep_sound = true,
walk_velocity = 1.05,
run_velocity = 2.1,
runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" },
attack_type = "explode",
eye_height = 1.25,
--hssssssssssss
explosion_strength = 3,
--explosion_radius = 3,
--explosion_damage_radius = 6,
--explosiontimer_reset_radius = 6,
explosion_radius = 3.5,
explosion_damage_radius = 3.5,
explosiontimer_reset_radius = 6,
reach = 3,
defuse_reach = 5.2,
explosion_timer = 0.3,
explosion_timer = 1.5,
allow_fuse_reset = true,
stop_to_explode = true,
--head code
has_head = true,
head_bone = "head",
swap_y_with_x = true,
reverse_head_yaw = true,
head_bone_pos_y = 2.4,
head_bone_pos_z = 0,
head_height_offset = 1.1,
head_direction_offset = 0,
head_pitch_modifier = 0,
--end head code
-- Force-ignite creeper with flint and steel and explode after 1.5 seconds.
-- TODO: Make creeper flash after doing this as well.
-- TODO: Test and debug this code.
on_rightclick = function(self, clicker)
if self._forced_explosion_countdown_timer then
if self._forced_explosion_countdown_timer ~= nil then
return
end
local item = clicker:get_wielded_item()
@ -92,11 +74,10 @@ mobs:register_mob("mobs_mc:creeper", {
end
end,
do_custom = function(self, dtime)
if self._forced_explosion_countdown_timer then
if self._forced_explosion_countdown_timer ~= nil then
self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime
if self._forced_explosion_countdown_timer <= 0 then
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { griefing = mobs_griefing, drop_chance = 1.0}, self.object)
mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
end
end
end,
@ -149,10 +130,9 @@ mobs:register_mob("mobs_mc:creeper", {
})
mobs:register_mob("mobs_mc:creeper_charged", {
description = S("Charged Creeper"),
description = S("Creeper"),
type = "monster",
spawn_class = "hostile",
hostile = true,
hp_min = 20,
hp_max = 20,
xp_min = 5,
@ -169,7 +149,6 @@ mobs:register_mob("mobs_mc:creeper_charged", {
"mobs_mc_creeper_charge.png"},
},
visual_size = {x=3, y=3},
rotate = 270,
sounds = {
attack = "tnt_ignite",
death = "mobs_mc_creeper_death",
@ -178,19 +157,18 @@ mobs:register_mob("mobs_mc:creeper_charged", {
explode = "tnt_explode",
distance = 16,
},
makes_footstep_sound = false,
makes_footstep_sound = true,
walk_velocity = 1.05,
run_velocity = 2.1,
runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" },
attack_type = "explode",
explosion_strength = 6,
--explosion_radius = 3,
--explosion_damage_radius = 6,
--explosiontimer_reset_radius = 3,
explosion_radius = 8,
explosion_damage_radius = 8,
explosiontimer_reset_radius = 6,
reach = 3,
defuse_reach = 5.2,
explosion_timer = 0.3,
explosion_timer = 1.5,
allow_fuse_reset = true,
stop_to_explode = true,
@ -198,7 +176,7 @@ mobs:register_mob("mobs_mc:creeper_charged", {
-- TODO: Make creeper flash after doing this as well.
-- TODO: Test and debug this code.
on_rightclick = function(self, clicker)
if self._forced_explosion_countdown_timer then
if self._forced_explosion_countdown_timer ~= nil then
return
end
local item = clicker:get_wielded_item()
@ -218,11 +196,10 @@ mobs:register_mob("mobs_mc:creeper_charged", {
end
end,
do_custom = function(self, dtime)
if self._forced_explosion_countdown_timer then
if self._forced_explosion_countdown_timer ~= nil then
self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime
if self._forced_explosion_countdown_timer <= 0 then
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { griefing = mobs_griefing, drop_chance = 1.0}, self.object)
mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
end
end
end,

View File

@ -2,28 +2,21 @@
--################### ENDERDRAGON
--###################
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
mobs:register_mob("mobs_mc:enderdragon", {
description = S("Ender Dragon"),
type = "monster",
spawn_class = "hostile",
pathfinding = 1,
attacks_animals = true,
walk_chance = 100,
rotate = 270,
tilt_fly = true,
hostile = true,
shoot_arrow = function(self, pos, dir)
-- 2-4 damage per arrow
local dmg = math.random(2,4)
mobs.shoot_projectile_handling("mobs_mc:dragon_fireball", pos, dir, self.object:get_yaw(), self.object, nil, dmg)
end,
hp_max = 200,
hp_min = 200,
xp_min = 500,
xp_max = 500,
collisionbox = {-2, 0, -2, 2, 2, 2},
eye_height = 1,
collisionbox = {-2, 3, -2, 2, 5, 2},
physical = false,
visual = "mesh",
mesh = "mobs_mc_dragon.b3d",
textures = {
@ -31,7 +24,6 @@ mobs:register_mob("mobs_mc:enderdragon", {
},
visual_size = {x=3, y=3},
view_range = 35,
reach = 20,
walk_velocity = 6,
run_velocity = 6,
can_despawn = false,
@ -55,10 +47,12 @@ mobs:register_mob("mobs_mc:enderdragon", {
lava_damage = 0,
fire_damage = 0,
on_rightclick = nil,
attack_type = "projectile",
attack_type = "dogshoot",
arrow = "mobs_mc:dragon_fireball",
shoot_interval = 0.5,
shoot_offset = -1.0,
xp_min = 500,
xp_max = 500,
animation = {
fly_speed = 8, stand_speed = 8,
stand_start = 0, stand_end = 20,
@ -111,8 +105,8 @@ mobs:register_mob("mobs_mc:enderdragon", {
fire_resistant = true,
})
--TODO: replace this setting by a proper gamerules system
local mobs_griefing = minetest.settings:get_bool("mobs_griefing", true)
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
-- dragon fireball (projectile)
mobs:register_arrow("mobs_mc:dragon_fireball", {
@ -139,13 +133,10 @@ mobs:register_arrow("mobs_mc:dragon_fireball", {
-- node hit, explode
hit_node = function(self, pos, node)
--mobs:boom(self, pos, 2)
if mobs_griefing then
mcl_explosions.explode(self.object:get_pos(), 2, { drop_chance = 1.0 })
end
mobs:boom(self, pos, 2)
end
})
mobs:register_egg("mobs_mc:enderdragon", S("Ender Dragon"), "mobs_mc_spawn_icon_dragon.png", 0, true)
--mcl_wip.register_wip_item("mobs_mc:enderdragon")
mcl_wip.register_wip_item("mobs_mc:enderdragon")

View File

@ -24,11 +24,9 @@
-- added rain damage.
-- fixed the grass_with_dirt issue.
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
local vector = vector
local function telesound(pos, is_source)
local telesound = function(pos, is_source)
local snd
if is_source then
snd = "mobs_mc_enderman_teleport_src"
@ -195,19 +193,18 @@ mobs:register_mob("mobs_mc:enderman", {
description = S("Enderman"),
type = "monster",
spawn_class = "passive",
neutral = true,
passive = true,
pathfinding = 1,
hp_min = 40,
hp_max = 40,
xp_min = 5,
xp_max = 5,
rotate = 270,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 2.89, 0.3},
visual = "mesh",
mesh = "mobs_mc_enderman.b3d",
textures = create_enderman_textures(),
visual_size = {x=3, y=3},
makes_footstep_sound = true,
eye_height = 2.5,
sounds = {
-- TODO: Custom war cry sound
war_cry = "mobs_sandmonster",
@ -216,8 +213,8 @@ mobs:register_mob("mobs_mc:enderman", {
random = {name="mobs_mc_enderman_random", gain=0.5},
distance = 16,
},
walk_velocity = 1,
run_velocity = 4,
walk_velocity = 0.2,
run_velocity = 3.4,
damage = 7,
reach = 2,
drops = {
@ -227,22 +224,6 @@ mobs:register_mob("mobs_mc:enderman", {
max = 1,
looting = "common"},
},
--head code
has_head = false,
head_bone = "head.low",
swap_y_with_x = false,
reverse_head_yaw = false,
head_bone_pos_y = 2.4,
head_bone_pos_z = 0,
head_height_offset = 1.1,
head_direction_offset = 0,
head_pitch_modifier = 0,
--end head code
animation = select_enderman_animation("normal"),
_taken_node = "",
do_custom = function(self, dtime)
@ -301,10 +282,10 @@ mobs:register_mob("mobs_mc:enderman", {
--self:teleport(nil)
--self.state = ""
--else
if self.attacking then
local target = self.attacking
if self.attack then
local target = self.attack
local pos = target:get_pos()
if pos then
if pos ~= nil then
if vector.distance(self.object:get_pos(), target:get_pos()) > 10 then
self:teleport(target)
end
@ -320,12 +301,12 @@ mobs:register_mob("mobs_mc:enderman", {
for n = 1, #objs do
local obj = objs[n]
if obj then
--if minetest.is_player(obj) then
if minetest.is_player(obj) then
-- Warp from players during day.
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
-- self:teleport(nil)
--end
if not obj:is_player() then
else
local lua = obj:get_luaentity()
if lua then
if lua.name == "mcl_bows:arrow_entity" or lua.name == "mcl_throwing:snowball_entity" then
@ -343,8 +324,8 @@ mobs:register_mob("mobs_mc:enderman", {
-- self:teleport(nil)
-- self.state = ""
--else
if self.attack and not minetest.settings:get_bool("creative_mode") then
self.state = "attack"
if self.attack ~= nil and not minetest.settings:get_bool("creative_mode") then
self.state = 'attack'
end
--end
end
@ -379,16 +360,11 @@ mobs:register_mob("mobs_mc:enderman", {
--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.state = "stand"
self.hostile = false
self.attack = minetest.get_player_by_name(obj:get_player_name())
break
--begin attacking the player
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"
self.hostile = true
self.state = "attack"
self.attacking = obj
end
end
@ -454,14 +430,14 @@ mobs:register_mob("mobs_mc:enderman", {
self.base_texture = create_enderman_textures(block_type, self._taken_node)
self.object:set_properties({ textures = self.base_texture })
self.animation = select_enderman_animation("block")
mobs.set_mob_animation(self, self.animation.current)
mobs:set_animation(self, self.animation.current)
if def.sounds and def.sounds.dug then
minetest.sound_play(def.sounds.dug, {pos = take_pos, max_hear_distance = 16}, true)
end
end
end
end
elseif self._taken_node and self._taken_node ~= "" and self._take_place_timer >= self._next_take_place_time then
elseif self._taken_node ~= nil and self._taken_node ~= "" and self._take_place_timer >= self._next_take_place_time then
-- Place taken node
self._take_place_timer = 0
self._next_take_place_time = math.random(take_frequency_min, take_frequency_max)
@ -477,7 +453,7 @@ mobs:register_mob("mobs_mc:enderman", {
local def = minetest.registered_nodes[self._taken_node]
-- Update animation accordingly (removes visible block)
self.animation = select_enderman_animation("normal")
mobs.set_mob_animation(self, self.animation.current)
mobs:set_animation(self, self.animation.current)
if def.sounds and def.sounds.place then
minetest.sound_play(def.sounds.place, {pos = place_pos, max_hear_distance = 16}, true)
end
@ -487,12 +463,12 @@ mobs:register_mob("mobs_mc:enderman", {
end
end,
do_teleport = function(self, target)
if target then
if target ~= nil then
local target_pos = target:get_pos()
-- Find all solid nodes below air in a 10×10×10 cuboid centered on the target
local nodes = minetest.find_nodes_in_area_under_air(vector.subtract(target_pos, 5), vector.add(target_pos, 5), {"group:solid", "group:cracky", "group:crumbly"})
local telepos
if nodes then
if nodes ~= nil then
if #nodes > 0 then
-- Up to 64 attempts to teleport
for n=1, math.min(64, #nodes) do
@ -502,7 +478,8 @@ mobs:register_mob("mobs_mc:enderman", {
-- Selected node needs to have 3 nodes of free space above
for u=1, 3 do
local node = minetest.get_node({x=nodepos.x, y=nodepos.y+u, z=nodepos.z})
if minetest.registered_nodes[node.name].walkable then
local ndef = minetest.registered_nodes[node.name]
if ndef and ndef.walkable then
node_ok = false
break
end
@ -527,7 +504,7 @@ mobs:register_mob("mobs_mc:enderman", {
-- We need to add (or subtract) different random numbers to each vector component, so it couldn't be done with a nice single vector.add() or .subtract():
local randomCube = vector.new( pos.x + 8*(pr:next(0,16)-8), pos.y + 8*(pr:next(0,16)-8), pos.z + 8*(pr:next(0,16)-8) )
local nodes = minetest.find_nodes_in_area_under_air(vector.subtract(randomCube, 4), vector.add(randomCube, 4), {"group:solid", "group:cracky", "group:crumbly"})
if nodes then
if nodes ~= nil then
if #nodes > 0 then
-- Up to 8 low-level (in total up to 8*8 = 64) attempts to teleport
for n=1, math.min(8, #nodes) do
@ -536,7 +513,8 @@ mobs:register_mob("mobs_mc:enderman", {
node_ok = true
for u=1, 3 do
local node = minetest.get_node({x=nodepos.x, y=nodepos.y+u, z=nodepos.z})
if minetest.registered_nodes[node.name].walkable then
local ndef = minetest.registered_nodes[node.name]
if ndef and ndef.walkable then
node_ok = false
break
end
@ -559,13 +537,13 @@ mobs:register_mob("mobs_mc:enderman", {
end,
on_die = function(self, pos)
-- Drop carried node on death
if self._taken_node and self._taken_node ~= "" then
if self._taken_node ~= nil and self._taken_node ~= "" then
minetest.add_item(pos, self._taken_node)
end
end,
do_punch = function(self, hitter, tflp, tool_caps, dir)
-- damage from rain caused by itself so we don't want it to attack itself.
if hitter ~= self.object and hitter then
if hitter ~= self.object and hitter ~= nil then
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
-- self:teleport(nil)
--else
@ -581,7 +559,7 @@ mobs:register_mob("mobs_mc:enderman", {
water_damage = 8,
view_range = 64,
fear_height = 4,
attack_type = "punch",
attack_type = "dogfight",
})

View File

@ -2,22 +2,19 @@
--################### ENDERMITE
--###################
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
mobs:register_mob("mobs_mc:endermite", {
description = S("Endermite"),
type = "monster",
spawn_class = "hostile",
passive = false,
rotate = 270,
hostile = true,
hp_min = 8,
hp_max = 8,
xp_min = 3,
xp_max = 3,
armor = {fleshy = 100, arthropod = 100},
group_attack = true,
attack_type = "punch",
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.29, 0.2},
visual = "mesh",
mesh = "mobs_mc_endermite.b3d",

View File

@ -3,7 +3,7 @@
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### GHAST
@ -14,17 +14,13 @@ mobs:register_mob("mobs_mc:ghast", {
description = S("Ghast"),
type = "monster",
spawn_class = "hostile",
pathfinding = 1,
group_attack = true,
hostile = true,
fly_random_while_attack = true,
hp_min = 10,
hp_max = 10,
rotate = 270,
xp_min = 5,
xp_max = 5,
reach = 20,
eye_height = 2.5,
collisionbox = {-2, 0, -2, 2, 4, 2},
collisionbox = {-2, 5, -2, 2, 9, 2},
visual = "mesh",
mesh = "mobs_mc_ghast.b3d",
textures = {
@ -40,10 +36,8 @@ mobs:register_mob("mobs_mc:ghast", {
-- TODO: damage
-- TODO: better death
},
walk_velocity = 1.6,
run_velocity = 3.2,
drops = {
{name = mobs_mc.items.gunpowder, chance = 1, min = 0, max = 2, looting = "common"},
{name = mobs_mc.items.ghast_tear, chance = 10/6, min = 0, max = 1, looting = "common", looting_ignore_chance = true},
@ -54,23 +48,22 @@ mobs:register_mob("mobs_mc:ghast", {
walk_start = 0, walk_end = 40,
run_start = 0, run_end = 40,
},
fall_damage = 0,
view_range = 28,
attack_type = "projectile",
arrow = "mobs_mc:ghast_fireball",
view_range = 100,
attack_type = "dogshoot",
arrow = "mobs_mc:fireball",
shoot_interval = 3.5,
shoot_offset = -5,
dogshoot_switch = 1,
dogshoot_count_max =1,
passive = false,
jump = true,
jump_height = 4,
floats=1,
fly = true,
makes_footstep_sound = false,
instant_death = true,
fire_resistant = true,
projectile_cooldown_min = 5,
projectile_cooldown_max = 7,
shoot_arrow = function(self, pos, dir)
-- 2-4 damage per arrow
local dmg = math.random(2,4)
mobs.shoot_projectile_handling("mobs_mc:ghast_fireball", pos, dir, self.object:get_yaw(), self.object, 11, dmg,nil,nil,nil,-0.6)
end,
--[[
do_custom = function(self)
if self.firing == true then
self.base_texture = {"mobs_mc_ghast_firing.png"}
@ -80,7 +73,6 @@ mobs:register_mob("mobs_mc:ghast", {
self.object:set_properties({textures=self.base_texture})
end
end,
]]--
})
@ -100,40 +92,32 @@ mobs_mc.spawn_height.nether_min,
mobs_mc.spawn_height.nether_max)
-- fireball (projectile)
mobs:register_arrow("mobs_mc:ghast_fireball", {
mobs:register_arrow("mobs_mc:fireball", {
visual = "sprite",
visual_size = {x = 1, y = 1},
textures = {"mcl_fire_fire_charge.png"},
velocity = 15,
collisionbox = {-.5, -.5, -.5, .5, .5, .5},
tail = 1,
tail_texture = "mobs_mc_spit.png^[colorize:black:255", --repurpose spit texture
tail_size = 5,
_is_fireball = true,
hit_player = function(self, player)
--[[
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 6},
}, nil)
]]--
--mobs:boom(self, self.object:get_pos(), 1, true)
mcl_explosions.explode(self.object:get_pos(), 3,{ drop_chance = 1.0 })
mobs:boom(self, self.object:get_pos(), 1, true)
end,
hit_mob = function(self, mob)
mob:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = self._damage},
damage_groups = {fleshy = 6},
}, nil)
--mobs:boom(self, self.object:get_pos(), 1, true)
mcl_explosions.explode(self.object:get_pos(), 3,{ drop_chance = 1.0 })
mobs:boom(self, self.object:get_pos(), 1, true)
end,
hit_node = function(self, pos, node)
--mobs:boom(self, pos, 1, true)
mcl_explosions.explode(self.object:get_pos(), 3,{ drop_chance = 1.0 })
mobs:boom(self, pos, 1, true)
end
})

View File

@ -2,7 +2,7 @@
--################### GUARDIAN
--###################
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
mobs:register_mob("mobs_mc:guardian", {
description = S("Guardian"),
@ -13,8 +13,8 @@ mobs:register_mob("mobs_mc:guardian", {
xp_min = 10,
xp_max = 10,
breath_max = -1,
passive = false,
attack_type = "punch",
passive = false,
attack_type = "dogfight",
pathfinding = 1,
view_range = 16,
walk_velocity = 2,
@ -94,6 +94,7 @@ mobs:register_mob("mobs_mc:guardian", {
makes_footstep_sound = false,
fly_in = { mobs_mc.items.water_source, mobs_mc.items.river_water_source },
jump = false,
view_range = 16,
})
-- Spawning disabled due to size issues

View File

@ -4,7 +4,7 @@
--################### GUARDIAN
--###################
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
mobs:register_mob("mobs_mc:guardian_elder", {
description = S("Elder Guardian"),
@ -15,8 +15,8 @@ mobs:register_mob("mobs_mc:guardian_elder", {
xp_min = 10,
xp_max = 10,
breath_max = -1,
passive = false,
attack_type = "punch",
passive = false,
attack_type = "dogfight",
pathfinding = 1,
view_range = 16,
walk_velocity = 2,
@ -104,6 +104,7 @@ mobs:register_mob("mobs_mc:guardian_elder", {
makes_footstep_sound = false,
fly_in = { mobs_mc.items.water_source, mobs_mc.items.river_water_source },
jump = false,
view_range = 16,
})
-- Spawning disabled due to size issues <- what do you mean? -j4i

View File

@ -3,7 +3,7 @@
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### HORSE
@ -38,9 +38,9 @@ end
local can_equip_horse_armor = function(entity_id)
return entity_id == "mobs_mc:horse" or entity_id == "mobs_mc:skeleton_horse" or entity_id == "mobs_mc:zombie_horse"
end
--[[local can_equip_chest = function(entity_id)
local can_equip_chest = function(entity_id)
return entity_id == "mobs_mc:mule" or entity_id == "mobs_mc:donkey"
end]]
end
local can_breed = function(entity_id)
return entity_id == "mobs_mc:horse" or "mobs_mc:mule" or entity_id == "mobs_mc:donkey"
end
@ -88,10 +88,6 @@ local horse = {
spawn_class = "passive",
visual = "mesh",
mesh = "mobs_mc_horse.b3d",
rotate = 270,
walk_velocity = 1,
run_velocity = 8,
skittish = true,
visual_size = {x=3.0, y=3.0},
collisionbox = {-0.69825, -0.01, -0.69825, 0.69825, 1.59, 0.69825},
animation = {
@ -101,7 +97,7 @@ local horse = {
walk_speed = 25,
walk_start = 0,
walk_end = 40,
run_speed = 120,
run_speed = 60,
run_start = 0,
run_end = 40,
},
@ -118,8 +114,7 @@ local horse = {
fly = false,
walk_chance = 60,
view_range = 16,
follow = "mcl_farming:wheat_item",
follow_distance = 3,
follow = mobs_mc.follow.horse,
passive = true,
hp_min = 15,
hp_max = 30,
@ -187,7 +182,7 @@ local horse = {
-- if driver present and horse has a saddle allow control of horse
if self.driver and self._saddle then
mobs.drive(self, "run", "stand", false, dtime)
mobs.drive(self, "walk", "stand", false, dtime)
return false -- skip rest of mob functions
end
@ -219,21 +214,6 @@ local horse = {
local iname = item:get_name()
local heal = 0
--sneak click to breed the horse/feed it
if self.owner and self.owner == clicker:get_player_name() then
--attempt to enter breed state
if mobs.enter_breed_state(self,clicker) then
return
end
end
--don't do any other logic with the baby
--make baby grow faster
if self.baby then
mobs.make_baby_grow_faster(self,clicker)
return
end
-- Taming
self.temper = self.temper or (math.random(1,100))
@ -259,7 +239,6 @@ local horse = {
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
mobs.tamed_effect(self)
if not self.owner or self.owner == "" then
self.owner = clicker:get_player_name()
end
@ -274,14 +253,6 @@ local horse = {
-- If nothing happened temper_increase = 0 and addition does nothing
self.temper = self.temper + temper_increase
--give the player some kind of idea
--of what's happening with the horse's temper
if self.temper <= 100 then
mobs.feed_effect(self)
else
mobs.tamed_effect(self)
end
return
end
@ -311,10 +282,14 @@ local horse = {
return
end
if mobs:protect(self, clicker) then
return
end
-- Make sure tamed horse is mature and being clicked by owner only
if self.tamed and not self.child and self.owner == clicker:get_player_name() then
--local inv = clicker:get_inventory()
local inv = clicker:get_inventory()
-- detatch player already riding horse
if self.driver and clicker == self.driver then
@ -382,6 +357,9 @@ local horse = {
self.object:set_properties({stepheight = 1.1})
mobs.attach(self, clicker)
-- Used to capture horse
elseif not self.driver and iname ~= "" then
mobs:capture_mob(self, clicker, 0, 5, 60, false, nil)
end
end
end,
@ -542,53 +520,42 @@ mobs:spawn_specific(
"overworld",
"ground",
{
"FlowerForest_beach",
"Forest_beach",
"StoneBeach",
"ColdTaiga_beach_water",
"Taiga_beach",
"Savanna_beach",
"Plains_beach",
"ExtremeHills_beach",
"ColdTaiga_beach",
"Swampland_shore",
"JungleM_shore",
"Jungle_shore",
"MesaPlateauFM_sandlevel",
"MesaPlateauF_sandlevel",
"MesaBryce_sandlevel",
"Mesa_sandlevel",
"Mesa",
"FlowerForest",
"Swampland",
"Taiga",
"ExtremeHills",
"Jungle",
"Savanna",
"BirchForest",
"MegaSpruceTaiga",
"MegaTaiga",
"ExtremeHills+",
"Forest",
"Plains",
"Desert",
"ColdTaiga",
"flat",
"IcePlainsSpikes",
"SunflowerPlains",
"IcePlains",
"RoofedForest",
"ExtremeHills+_snowtop",
"MesaPlateauFM_grasstop",
"JungleEdgeM",
"ColdTaiga",
"ColdTaiga_beach",
"ColdTaiga_beach_water",
"MegaTaiga",
"MegaSpruceTaiga",
"ExtremeHills",
"ExtremeHills_beach",
"ExtremeHillsM",
"JungleM",
"ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach",
"Plains",
"Plains_beach",
"SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"JungleEdge",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
},
0,
minetest.LIGHT_MAX+1,

View File

@ -3,7 +3,7 @@
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local path = minetest.get_modpath(minetest.get_current_modname())
local path = minetest.get_modpath("mobs_mc")
if not minetest.get_modpath("mobs_mc_gameconfig") then
mobs_mc = {}

View File

@ -3,7 +3,7 @@
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### IRON GOLEM
@ -16,11 +16,8 @@ mobs:register_mob("mobs_mc:iron_golem", {
type = "npc",
spawn_class = "passive",
passive = true,
rotate = 270,
hp_min = 100,
hp_max = 100,
protect = true,
neutral = true,
breath_max = -1,
collisionbox = {-0.7, -0.01, -0.7, 0.7, 2.69, 0.7},
visual = "mesh",
@ -43,7 +40,7 @@ mobs:register_mob("mobs_mc:iron_golem", {
reach = 3,
group_attack = true,
attacks_monsters = true,
attack_type = "punch",
attack_type = "dogfight",
drops = {
{name = mobs_mc.items.iron_ingot,
chance = 1,
@ -158,11 +155,11 @@ mobs_mc.tools.check_iron_golem_summon = function(pos)
if ok then
-- Remove the nodes
minetest.remove_node(pos)
minetest.check_for_falling(pos)
core.check_for_falling(pos)
for i=1, 4 do
local cpos = vector.add(pos, checks[c][i])
minetest.remove_node(cpos)
minetest.check_for_falling(cpos)
core.check_for_falling(cpos)
end
-- Summon iron golem
local place

View File

@ -1,4 +1,4 @@
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### LLAMA
@ -28,15 +28,6 @@ mobs:register_mob("mobs_mc:llama", {
description = S("Llama"),
type = "animal",
spawn_class = "passive",
rotate = 270,
neutral = true,
group_attack = true,
attack_type = "projectile",
shoot_arrow = function(self, pos, dir)
-- 2-4 damage per arrow
local dmg = 1
mobs.shoot_projectile_handling("mobs_mc:spit", pos, dir, self.object:get_yaw(), self.object, nil, dmg)
end,
hp_min = 15,
hp_max = 30,
xp_min = 1,
@ -59,11 +50,7 @@ mobs:register_mob("mobs_mc:llama", {
walk_velocity = 1,
run_velocity = 4.4,
follow_velocity = 4.4,
breed_distance = 1.5,
baby_size = 0.5,
follow_distance = 2,
floats = 1,
reach = 6,
drops = {
{name = mobs_mc.items.leather,
chance = 1,
@ -96,7 +83,7 @@ mobs:register_mob("mobs_mc:llama", {
look_start = 78,
look_end = 108,
},
follow = mobs_mc.items.hay_bale,
follow = mobs_mc.follow.llama,
view_range = 16,
do_custom = function(self, dtime)
@ -139,71 +126,30 @@ mobs:register_mob("mobs_mc:llama", {
return
end
--owner is broken for this
--we'll make the owner this guy
--attempt to enter breed state
if mobs.enter_breed_state(self,clicker) then
self.tamed = true
self.owner = clicker:get_player_name()
return
local item = clicker:get_wielded_item()
if item:get_name() == mobs_mc.items.hay_bale then
-- Breed with hay bale
if mobs:feed_tame(self, clicker, 1, true, false) then return end
else
-- Feed with anything else
if mobs:feed_tame(self, clicker, 1, false, true) then return end
end
--ignore other logic
--make baby grow faster
if self.baby then
mobs.make_baby_grow_faster(self,clicker)
return
end
if mobs:protect(self, clicker) then return end
-- Make sure tamed llama is mature and being clicked by owner only
if self.tamed and not self.child and self.owner == clicker:get_player_name() then
local item = clicker:get_wielded_item()
--safety catch
if not item then
return
end
--put chest on carpeted llama
if self.carpet and not self.chest and item:get_name() == "mcl_chests:chest" then
if not minetest.is_creative_enabled(clicker:get_player_name()) then
item:take_item()
clicker:set_wielded_item(item)
end
self.base_texture = table.copy(self.base_texture)
self.base_texture[1] = "mobs_mc_llama_chest.png"
self.object:set_properties({
textures = self.base_texture,
})
self.chest = true
return --don't attempt to ride
end
-- Place carpet
--TODO: Re-enable this code when carpet textures arrived.
if minetest.get_item_group(item:get_name(), "carpet") == 1 then
--[[ TODO: Re-enable this code when carpet textures arrived.
if minetest.get_item_group(item:get_name(), "carpet") == 1 and not self.carpet then
for group, carpetdata in pairs(carpets) do
if minetest.get_item_group(item:get_name(), group) == 1 then
if not minetest.is_creative_enabled(clicker:get_player_name()) then
item:take_item()
clicker:set_wielded_item(item)
--shoot off old carpet
if self.carpet then
minetest.add_item(self.object:get_pos(), self.carpet)
end
end
local substr = carpetdata[2]
local tex_carpet = "mobs_mc_llama_decor_"..substr..".png"
self.base_texture = table.copy(self.base_texture)
self.base_texture[2] = tex_carpet
self.object:set_properties({
@ -224,21 +170,23 @@ mobs:register_mob("mobs_mc:llama", {
end
end
end
]]
if self.carpet then
-- detatch player already riding llama
if self.driver and clicker == self.driver then
-- detatch player already riding llama
if self.driver and clicker == self.driver then
mobs.detach(clicker, {x = 1, y = 0, z = 1})
mobs.detach(clicker, {x = 1, y = 0, z = 1})
-- attach player to llama
elseif not self.driver then
-- attach player to llama
elseif not self.driver then
self.object:set_properties({stepheight = 1.1})
mobs.attach(self, clicker)
end
self.object:set_properties({stepheight = 1.1})
mobs.attach(self, clicker)
end
-- Used to capture llama
elseif not self.driver and clicker:get_wielded_item():get_name() ~= "" then
mobs:capture_mob(self, clicker, 0, 5, 60, false, nil)
end
end,
@ -275,12 +223,18 @@ mobs:spawn_specific(
"overworld",
"ground",
{
"Mesa",
"MesaPlateauFM_grasstop",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"Mesa",
"MesaPlateauFM_grasstop",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
},
0,
minetest.LIGHT_MAX+1,
@ -292,38 +246,3 @@ mobs_mc.spawn_height.overworld_max)
-- spawn eggs
mobs:register_egg("mobs_mc:llama", S("Llama"), "mobs_mc_spawn_icon_llama.png", 0)
-- llama spit
mobs:register_arrow("mobs_mc:spit", {
visual = "sprite",
visual_size = {x = 0.3, y = 0.3},
textures = {"mobs_mc_spit.png"},
velocity = 1,
speed = 1,
tail = 1,
tail_texture = "mobs_mc_spit.png",
tail_size = 2,
tail_distance_divider = 4,
hit_player = function(self, player)
--[[if rawget(_G, "armor") and armor.last_damage_types then
armor.last_damage_types[player:get_player_name()] = "spit"
end]]
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = self._damage},
}, nil)
end,
hit_mob = function(self, mob)
mob:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = self._damage},
}, nil)
end,
hit_node = function(self, pos, node)
--does nothing
end
})

View File

@ -28,7 +28,6 @@ Pig=Schwein
Polar Bear=Eisbär
Rabbit=Kaninchen
Killer Bunny=Killerkaninchen
The Killer Bunny=Das Killerkaninchen
Sheep=Schaf
Shulker=Shulker
Silverfish=Silberfischchen

View File

@ -28,7 +28,6 @@ Pig=Cerdo
Polar Bear=Oso polar
Rabbit=Conejo
Killer Bunny=Conejo asesino
The Killer Bunny=El Conejo asesino
Sheep=Oveja
Shulker=Shulker
Silverfish=Lepisma

View File

@ -28,7 +28,6 @@ Pig=Cochon
Polar Bear=Ours blanc
Rabbit=Lapin
Killer Bunny=Lapin tueur
The Killer Bunny=Le Lapin tueur
Sheep=Mouton
Shulker=Shulker
Silverfish=Poisson d'argent

View File

@ -1,75 +0,0 @@
# textdomain: mobs_mc
Totem of Undying=Token nieśmiertelności
A totem of undying is a rare artifact which may safe you from certain death.=Totem nieśmiertelności to rzadki artefakt, który może uchronić cię przed pewną śmiercią.
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.=Totem działa tylko kiedy trzymasz go w dłoni. Jeśli otrzymasz obrażenia od upadku zostaniesz oszczędzony i pozostanie ci 1 HP, jednak totem zostanie wtedy zniszczony.
Agent=Agent
Bat=Nietoperz
Blaze=Płomyk
Chicken=Kurczak
Cow=Krowa
Mooshroom=Muuuchomor
Creeper=Creeper
Ender Dragon=Smok kresu
Enderman=Enderman
Endermite=Endermit
Ghast=Ghast
Elder Guardian=Prastrażnik
Guardian=Strażnik
Horse=Koń
Skeleton Horse=Koń szkielet
Zombie Horse=Koń zombie
Donkey=Osioł
Mule=Muł
Iron Golem=Żelazny golem
Llama=Lama
Ocelot=Ocelot
Parrot=Papuga
Pig=Świnia
Polar Bear=Niedźwiedź polarny
Rabbit=Królik
Killer Bunny=Królik zabójca
Sheep=Owca
Shulker=Shulker
Silverfish=Rybik cukrowy
Skeleton=Szkielet
Stray=Tułacz
Wither Skeleton=Witherowy szkielet
Magma Cube=Kostka magmy
Slime=Szlam
Snow Golem=Śnieżny golem
Spider=Pająk
Cave Spider=Pająk jaskiniowy
Squid=Kałamarnica
Vex=Dręczyciel
Evoker=Przywoływacz
Illusioner=Iluzjonista
Villager=Osadnik
Vindicator=Obrońca
Zombie Villager=Osadnik zombie
Witch=Wiedźma
Wither=Wither
Wolf=Wilk
Husk=Posuch
Zombie=Zombie
Zombie Pigman=Świniak zombie
Iron Horse Armor=Żelazna zbroja dla konia
Iron horse armor can be worn by horses to increase their protection from harm a bit.=Żelazna zbroja dla konia może być noszona przez konie aby nieco zwiększyć ich odporność na obrażenia.
Golden Horse Armor=Złota zbroja dla konia
Golden horse armor can be worn by horses to increase their protection from harm.=Złota zbroja dla konia może być noszona przez konie aby zwiększyć ich odporność na obrażenia.
Diamond Horse Armor=Diamentowa zbroja dla konia
Diamond horse armor can be worn by horses to greatly increase their protection from harm.=Diamentowa zbroja dla konia może być noszona przez konie aby istotnie zwiększyć ich odporność na obrażenia.
Place it on a horse to put on the horse armor. Donkeys and mules can't wear horse armor.=Połóż ją na koniu aby założyć zbroję dla konia. Osły i muły nie mogą nosić zbroi dla konia.
Farmer=Rolnik
Fisherman=Rybak
Fletcher=Łuczarz
Shepherd=Pasterz
Librarian=Bibliotekarz
Cartographer=Kartograf
Armorer=Płatnerz
Leatherworker=Rymarz
Butcher=Rzeźnik
Weapon Smith=Zbrojmistrz
Tool Smith=Narzędziarz
Cleric=Kapłan
Nitwit=Głupiec
Protects you from death while wielding it=Chroni przed śmiercią gdy go trzymasz

View File

@ -28,7 +28,6 @@ Pig=Свинья
Polar Bear=Полярный медведь
Rabbit=Кролик
Killer Bunny=Кролик-убийца
The Killer Bunny=Кролик-убийца
Sheep=Овца
Shulker=Шалкер
Silverfish=Чешуйница

View File

@ -28,7 +28,6 @@ Pig=
Polar Bear=
Rabbit=
Killer Bunny=
The Killer Bunny=
Sheep=
Shulker=
Silverfish=

View File

@ -1 +0,0 @@
Ghast fixed by epCode - Thanks!

View File

@ -3,7 +3,7 @@
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### OCELOT AND CAT
@ -31,8 +31,6 @@ local ocelot = {
type = "animal",
spawn_class = "passive",
can_despawn = true,
rotate = 270,
skittish = true,
hp_min = 10,
hp_max = 10,
xp_min = 1,
@ -45,7 +43,7 @@ local ocelot = {
makes_footstep_sound = true,
walk_chance = default_walk_chance,
walk_velocity = 1,
run_velocity = 10,
run_velocity = 3,
follow_velocity = 1,
floats = 1,
runaway = true,
@ -59,7 +57,7 @@ local ocelot = {
},
animation = {
speed_normal = 25,
run_speed = 150,
run_speed = 50,
stand_start = 0,
stand_end = 0,
walk_start = 0,
@ -125,6 +123,8 @@ cat.sounds = {
}
cat.on_rightclick = function(self, clicker)
if mobs:feed_tame(self, clicker, 1, true, false) then return end
if mobs:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end
if mobs:protect(self, clicker) then return end
if self.child then return end
@ -151,7 +151,7 @@ end
mobs:register_mob("mobs_mc:cat", cat)
--local base_spawn_chance = 5000
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

View File

@ -3,7 +3,7 @@
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### PARROT
@ -20,14 +20,11 @@ mobs:register_mob("mobs_mc:parrot", {
hp_max = 6,
xp_min = 1,
xp_max = 3,
tilt_fly = true,
collisionbox = {-0.25, 0, -0.25, 0.25, 0.9, 0.25},
eye_height = 0.45,
collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.89, 0.25},
visual = "mesh",
mesh = "mobs_mc_parrot.b3d",
textures = {{"mobs_mc_parrot_blue.png"},{"mobs_mc_parrot_green.png"},{"mobs_mc_parrot_grey.png"},{"mobs_mc_parrot_red_blue.png"},{"mobs_mc_parrot_yellow_blue.png"}},
visual_size = {x=3, y=3},
rotate = 270,
walk_velocity = 3,
run_velocity = 5,
sounds = {
@ -44,7 +41,7 @@ mobs:register_mob("mobs_mc:parrot", {
max = 2,
looting = "common",},
},
animation = {
animation = {
stand_speed = 50,
walk_speed = 50,
fly_speed = 50,
@ -88,6 +85,8 @@ mobs:register_mob("mobs_mc:parrot", {
-- Feed to tame, but not breed
if mobs:feed_tame(self, clicker, 1, false, true) then return end
if mobs:protect(self, clicker) then return end
if mobs:capture_mob(self, clicker, 0, 50, 80, false, nil) then return end
end,
})

View File

@ -1,13 +1,12 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
mobs:register_mob("mobs_mc:pig", {
description = S("Pig"),
type = "animal",
spawn_class = "passive",
skittish = true,
rotate = 270,
runaway = true,
hp_min = 10,
hp_max = 10,
xp_min = 1,
@ -20,30 +19,11 @@ mobs:register_mob("mobs_mc:pig", {
"mobs_mc_pig.png", -- base
"blank.png", -- saddle
}},
--head code
has_head = true,
head_bone = "head",
swap_y_with_x = false,
reverse_head_yaw = false,
head_bone_pos_y = 2.4,
head_bone_pos_z = 0,
head_height_offset = 1.1,
head_direction_offset = 0,
head_pitch_modifier = 0,
--end head code
visual_size = {x=2.5, y=2.5},
makes_footstep_sound = true,
walk_velocity = 1,
run_velocity = 3,
follow_velocity = 3.4,
breed_distance = 1.5,
baby_size = 0.5,
follow_distance = 2,
drops = {
{name = mobs_mc.items.porkchop_raw,
chance = 1,
@ -70,7 +50,7 @@ mobs:register_mob("mobs_mc:pig", {
run_start = 0,
run_end = 40,
},
follow = "mcl_farming:carrot_item",
follow = mobs_mc.follow.pig,
view_range = 8,
do_custom = function(self, dtime)
@ -111,17 +91,12 @@ mobs:register_mob("mobs_mc:pig", {
return
end
--attempt to enter breed state
if mobs.enter_breed_state(self,clicker) then
return
end
--ignore other logic
--make baby grow faster
if self.baby then
mobs.make_baby_grow_faster(self,clicker)
return
local wielditem = clicker:get_wielded_item()
-- Feed pig
if wielditem:get_name() ~= mobs_mc.items.carrot_on_a_stick then
if mobs:feed_tame(self, clicker, 1, true, true) then return end
end
if mobs:protect(self, clicker) then return end
if self.child then
return
@ -129,8 +104,6 @@ mobs:register_mob("mobs_mc:pig", {
-- Put saddle on pig
local item = clicker:get_wielded_item()
local wielditem = item
if item:get_name() == mobs_mc.items.saddle and self.saddle ~= "yes" then
self.base_texture = {
"blank.png", -- baby
@ -163,7 +136,7 @@ mobs:register_mob("mobs_mc:pig", {
end
-- Mount or detach player
--local name = clicker:get_player_name()
local name = clicker:get_player_name()
if self.driver and clicker == self.driver then
-- Detach if already attached
mobs.detach(clicker, {x=1, y=0, z=0})
@ -191,6 +164,10 @@ mobs:register_mob("mobs_mc:pig", {
inv:set_stack("main",self.driver:get_wield_index(), wielditem)
end
return
-- Capture pig
elseif not self.driver and clicker:get_wielded_item():get_name() ~= "" then
mobs:capture_mob(self, clicker, 0, 5, 60, false, nil)
end
end,
@ -211,53 +188,42 @@ mobs:spawn_specific(
"overworld",
"ground",
{
"FlowerForest_beach",
"Forest_beach",
"StoneBeach",
"ColdTaiga_beach_water",
"Taiga_beach",
"Savanna_beach",
"Plains_beach",
"ExtremeHills_beach",
"ColdTaiga_beach",
"Swampland_shore",
"JungleM_shore",
"Jungle_shore",
"MesaPlateauFM_sandlevel",
"MesaPlateauF_sandlevel",
"MesaBryce_sandlevel",
"Mesa_sandlevel",
"Mesa",
"FlowerForest",
"Swampland",
"Taiga",
"ExtremeHills",
"Jungle",
"Savanna",
"BirchForest",
"MegaSpruceTaiga",
"MegaTaiga",
"ExtremeHills+",
"Forest",
"Plains",
"Desert",
"ColdTaiga",
"flat",
"IcePlainsSpikes",
"SunflowerPlains",
"IcePlains",
"RoofedForest",
"ExtremeHills+_snowtop",
"MesaPlateauFM_grasstop",
"JungleEdgeM",
"ColdTaiga",
"ColdTaiga_beach",
"ColdTaiga_beach_water",
"MegaTaiga",
"MegaSpruceTaiga",
"ExtremeHills",
"ExtremeHills_beach",
"ExtremeHillsM",
"JungleM",
"ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach",
"Plains",
"Plains_beach",
"SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"JungleEdge",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
},
9,
minetest.LIGHT_MAX+1,

View File

@ -1,6 +1,6 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### POLARBEAR
@ -31,7 +31,7 @@ mobs:register_mob("mobs_mc:polar_bear", {
walk_velocity = 1.2,
run_velocity = 2.4,
group_attack = true,
attack_type = "punch",
attack_type = "dogfight",
drops = {
-- 3/4 chance to drop raw fish (poor approximation)
{name = mobs_mc.items.fish_raw,

View File

@ -1,6 +1,6 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
local rabbit = {
description = S("Rabbit"),
@ -8,7 +8,7 @@ local rabbit = {
spawn_class = "passive",
passive = true,
reach = 1,
rotate = 270,
hp_min = 3,
hp_max = 3,
xp_min = 1,
@ -62,6 +62,8 @@ local rabbit = {
on_rightclick = function(self, clicker)
-- Feed, tame protect or capture
if mobs:feed_tame(self, clicker, 1, true, true) then return end
if mobs:protect(self, clicker) then return end
if mobs:capture_mob(self, clicker, 0, 50, 80, false, nil) then return end
end,
do_custom = function(self)
-- Easter egg: Change texture if rabbit is named “Toast”
@ -99,7 +101,7 @@ killer_bunny.on_rightclick = nil
killer_bunny.run_velocity = 6
killer_bunny.do_custom = function(self)
if not self._killer_bunny_nametag_set then
self.nametag = S("The Killer Bunny")
self.nametag = "The Killer Bunny"
self._killer_bunny_nametag_set = true
end
end
@ -114,53 +116,22 @@ mobs:spawn_specific(
"overworld",
"ground",
{
"FlowerForest_beach",
"Forest_beach",
"StoneBeach",
"ColdTaiga_beach_water",
"Taiga_beach",
"Savanna_beach",
"Plains_beach",
"ExtremeHills_beach",
"ColdTaiga_beach",
"Swampland_shore",
"JungleM_shore",
"Jungle_shore",
"MesaPlateauFM_sandlevel",
"MesaPlateauF_sandlevel",
"MesaBryce_sandlevel",
"Mesa_sandlevel",
"Mesa",
"FlowerForest",
"Swampland",
"Taiga",
"ExtremeHills",
"Jungle",
"Savanna",
"BirchForest",
"MegaSpruceTaiga",
"MegaTaiga",
"ExtremeHills+",
"Forest",
"Plains",
"Desert",
"ColdTaiga",
"IcePlainsSpikes",
"SunflowerPlains",
"IcePlains",
"RoofedForest",
"ExtremeHills+_snowtop",
"MesaPlateauFM_grasstop",
"JungleEdgeM",
"ExtremeHillsM",
"JungleM",
"BirchForestM",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"JungleEdge",
"SavannaM",
"FlowerForest",
"Swampland",
"Taiga",
"ExtremeHills",
"BirchForest",
"MegaSpruceTaiga",
"MegaTaiga",
"ExtremeHills+",
"Forest",
"Plains",
"ColdTaiga",
"SunflowerPlains",
"RoofedForest",
"MesaPlateauFM_grasstop",
"ExtremeHillsM",
"BirchForestM",
},
9,
minetest.LIGHT_MAX+1,
@ -233,4 +204,4 @@ mobs:spawn(spawn_grass)
mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0)
-- Note: This spawn egg does not exist in Minecraft
mobs:register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "mobs_mc_spawn_icon_rabbit_caerbannog.png", 0)
mobs:register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "mobs_mc_spawn_icon_rabbit.png^[colorize:#FF0000:192", 0) -- TODO: Update inventory image

View File

@ -1,6 +1,6 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### SHEEP
@ -38,7 +38,7 @@ local rainbow_colors = {
"unicolor_red_violet"
}
if minetest.get_modpath("mcl_wool") then
if minetest.get_modpath("mcl_wool") ~= nil then
colors["unicolor_light_blue"] = { mobs_mc.items.wool_light_blue, "#5050FFD0" }
end
@ -63,13 +63,8 @@ mobs:register_mob("mobs_mc:sheep", {
hp_max = 8,
xp_min = 1,
xp_max = 3,
skittish = true,
breed_distance = 1.5,
baby_size = 0.5,
follow_distance = 2,
follow = mobs_mc.items.wheat,
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.29, 0.45},
rotate = 270,
visual = "mesh",
visual_size = {x=3, y=3},
mesh = "mobs_mc_sheepfur.b3d",
@ -78,23 +73,6 @@ mobs:register_mob("mobs_mc:sheep", {
color = "unicolor_white",
makes_footstep_sound = true,
walk_velocity = 1,
run_velocity = 3,
--head code
has_head = true,
head_bone = "head",
swap_y_with_x = false,
reverse_head_yaw = false,
head_bone_pos_y = 3.6,
head_bone_pos_z = -0.6,
head_height_offset = 1.0525,
head_direction_offset = 0.5,
head_pitch_modifier = 0,
--end head code
drops = {
{name = mobs_mc.items.mutton_raw,
chance = 1,
@ -121,6 +99,7 @@ mobs:register_mob("mobs_mc:sheep", {
walk_start = 0, walk_end = 40,
run_start = 0, run_end = 40,
},
follow = mobs_mc.follow.sheep,
view_range = 12,
-- Eat grass
@ -150,6 +129,7 @@ mobs:register_mob("mobs_mc:sheep", {
do_custom = function(self, dtime)
if not self.initial_color_set then
local r = math.random(0,100000)
local textures
if r <= 81836 then
-- 81.836%
self.color = "unicolor_white"
@ -215,16 +195,8 @@ mobs:register_mob("mobs_mc:sheep", {
on_rightclick = function(self, clicker)
local item = clicker:get_wielded_item()
--attempt to enter breed state
if mobs.enter_breed_state(self,clicker) then
return
end
--make baby grow faster
if self.baby then
mobs.make_baby_grow_faster(self,clicker)
return
end
if mobs:feed_tame(self, clicker, 1, true, true) then return end
if mobs:protect(self, clicker) then return end
if item:get_name() == mobs_mc.items.shears and not self.gotten and not self.child then
self.gotten = true
@ -280,6 +252,7 @@ mobs:register_mob("mobs_mc:sheep", {
end
return
end
if mobs:capture_mob(self, clicker, 0, 5, 70, false, nil) then return end
end,
on_breed = function(parent1, parent2)
-- Breed sheep and choose a fur color for the child.
@ -336,53 +309,42 @@ mobs:spawn_specific(
"overworld",
"ground",
{
"FlowerForest_beach",
"Forest_beach",
"StoneBeach",
"ColdTaiga_beach_water",
"Taiga_beach",
"Savanna_beach",
"Plains_beach",
"ExtremeHills_beach",
"ColdTaiga_beach",
"Swampland_shore",
"JungleM_shore",
"Jungle_shore",
"MesaPlateauFM_sandlevel",
"MesaPlateauF_sandlevel",
"MesaBryce_sandlevel",
"Mesa_sandlevel",
"Mesa",
"FlowerForest",
"Swampland",
"Taiga",
"ExtremeHills",
"Jungle",
"Savanna",
"BirchForest",
"MegaSpruceTaiga",
"MegaTaiga",
"ExtremeHills+",
"Forest",
"Plains",
"Desert",
"ColdTaiga",
"flat",
"IcePlainsSpikes",
"SunflowerPlains",
"IcePlains",
"RoofedForest",
"ExtremeHills+_snowtop",
"MesaPlateauFM_grasstop",
"JungleEdgeM",
"ColdTaiga",
"ColdTaiga_beach",
"ColdTaiga_beach_water",
"MegaTaiga",
"MegaSpruceTaiga",
"ExtremeHills",
"ExtremeHills_beach",
"ExtremeHillsM",
"JungleM",
"ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach",
"Plains",
"Plains_beach",
"SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"JungleEdge",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
},
0,
minetest.LIGHT_MAX+1,
@ -394,4 +356,3 @@ mobs_mc.spawn_height.overworld_max)
-- spawn eggs
mobs:register_egg("mobs_mc:sheep", S("Sheep"), "mobs_mc_spawn_icon_sheep.png", 0)

View File

@ -3,7 +3,7 @@
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### SHULKER
@ -15,7 +15,7 @@ mobs:register_mob("mobs_mc:shulker", {
description = S("Shulker"),
type = "monster",
spawn_class = "hostile",
attack_type = "projectile",
attack_type = "shoot",
shoot_interval = 0.5,
arrow = "mobs_mc:shulkerbullet",
shoot_offset = 0.5,

View File

@ -2,7 +2,7 @@
--################### SILVERFISH
--###################
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
mobs:register_mob("mobs_mc:silverfish", {
description = S("Silverfish"),
@ -44,8 +44,9 @@ mobs:register_mob("mobs_mc:silverfish", {
run_start = 0, run_end = 20,
},
view_range = 16,
attack_type = "punch",
attack_type = "dogfight",
damage = 1,
reach = 1,
})
mobs:register_egg("mobs_mc:silverfish", S("Silverfish"), "mobs_mc_spawn_icon_silverfish.png", 0)
@ -61,7 +62,7 @@ if minetest.get_modpath("default") and mobs_mc.create_monster_egg_nodes then
description = "Stone Monster Egg",
tiles = {"default_stone.png"},
groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1},
drop = "",
drop = '',
is_ground_content = true,
sounds = default.node_sound_stone_defaults(),
after_dig_node = spawn_silverfish,
@ -72,7 +73,7 @@ if minetest.get_modpath("default") and mobs_mc.create_monster_egg_nodes then
tiles = {"default_cobble.png"},
is_ground_content = false,
groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1},
drop = "",
drop = '',
sounds = default.node_sound_stone_defaults(),
after_dig_node = spawn_silverfish,
})
@ -82,7 +83,7 @@ if minetest.get_modpath("default") and mobs_mc.create_monster_egg_nodes then
tiles = {"default_mossycobble.png"},
is_ground_content = false,
groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1},
drop = "",
drop = '',
sounds = default.node_sound_stone_defaults(),
after_dig_node = spawn_silverfish,
})
@ -94,7 +95,7 @@ if minetest.get_modpath("default") and mobs_mc.create_monster_egg_nodes then
tiles = {"default_stone_brick.png"},
is_ground_content = false,
groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1},
drop = "",
drop = '',
sounds = default.node_sound_stone_defaults(),
after_dig_node = spawn_silverfish,
})
@ -104,7 +105,7 @@ if minetest.get_modpath("default") and mobs_mc.create_monster_egg_nodes then
tiles = {"default_stone_block.png"},
is_ground_content = false,
groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1},
drop = "",
drop = '',
sounds = default.node_sound_stone_defaults(),
after_dig_node = spawn_silverfish,
})

View File

@ -3,8 +3,8 @@
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local mod_bows = minetest.get_modpath("mcl_bows")
local S = minetest.get_translator("mobs_mc")
local mod_bows = minetest.get_modpath("mcl_bows") ~= nil
--###################
--################### SKELETON
@ -16,37 +16,21 @@ local skeleton = {
description = S("Skeleton"),
type = "monster",
spawn_class = "hostile",
hostile = true,
rotate = 270,
hp_min = 20,
hp_max = 20,
xp_min = 6,
xp_max = 6,
breath_max = -1,
eye_height = 1.5,
projectile_cooldown = 1.5,
armor = {undead = 100, fleshy = 100},
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.98, 0.3},
pathfinding = 1,
group_attack = true,
visual = "mesh",
mesh = "mobs_mc_skeleton.b3d",
--head code
has_head = false,
head_bone = "head",
swap_y_with_x = true,
reverse_head_yaw = true,
head_bone_pos_y = 2.4,
head_bone_pos_z = 0,
head_height_offset = 1.1,
head_direction_offset = 0,
head_pitch_modifier = 0,
--end head code
textures = { {
"mcl_bows_bow_0.png", -- bow
"mobs_mc_skeleton.png", -- skeleton
} },
visual_size = {x=1, y=1},
makes_footstep_sound = true,
textures = {
@ -59,7 +43,7 @@ local skeleton = {
walk_velocity = 1.2,
run_velocity = 2.4,
damage = 2,
reach = 3,
reach = 2,
drops = {
{name = mobs_mc.items.arrow,
chance = 1,
@ -91,8 +75,6 @@ local skeleton = {
walk_speed = 15,
walk_start = 40,
walk_end = 60,
run_start = 40,
run_end = 60,
run_speed = 30,
shoot_start = 70,
shoot_end = 90,
@ -104,13 +86,13 @@ local skeleton = {
ignited_by_sunlight = true,
view_range = 16,
fear_height = 4,
attack_type = "projectile",
attack_type = "dogshoot",
arrow = "mcl_bows:arrow_entity",
shoot_arrow = function(self, pos, dir)
if mod_bows then
-- 2-4 damage per arrow
local dmg = math.random(2,4)
mobs.shoot_projectile_handling("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg)
local dmg = math.max(4, math.random(2, 8))
mcl_bows.shoot_arrow("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg)
end
end,
shoot_interval = 2,

View File

@ -3,7 +3,7 @@
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
--###################
--################### WITHER SKELETON
@ -87,7 +87,7 @@ mobs:register_mob("mobs_mc:witherskeleton", {
fire_damage = 0,
light_damage = 0,
view_range = 16,
attack_type = "punch",
attack_type = "dogfight",
dogshoot_switch = 1,
dogshoot_count_max =0.5,
fear_height = 4,

View File

@ -1,6 +1,6 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
-- Returns a function that spawns children in a circle around pos.
-- To be used as on_die callback.
@ -16,7 +16,8 @@ local spawn_children_on_die = function(child_mob, children_count, spawn_distance
if not eject_speed then
eject_speed = 1
end
local mother_stuck = minetest.registered_nodes[minetest.get_node(pos).name].walkable
local mndef = minetest.registered_nodes[minetest.get_node(pos).name]
local mother_stuck = mndef and mndef.walkable
angle = math.random(0, math.pi*2)
local children = {}
for i=1,children_count do
@ -26,27 +27,26 @@ local spawn_children_on_die = function(child_mob, children_count, spawn_distance
-- If child would end up in a wall, use position of the "mother", unless
-- the "mother" was stuck as well
local speed_penalty = 1
if (not mother_stuck) and minetest.registered_nodes[minetest.get_node(newpos).name].walkable then
local cndef = minetest.registered_nodes[minetest.get_node(newpos).name]
if (not mother_stuck) and cndef and cndef.walkable then
newpos = pos
speed_penalty = 0.5
end
local mob = minetest.add_entity(newpos, child_mob)
if mob then
if (not mother_stuck) then
mob:set_velocity(vector.multiply(dir, eject_speed * speed_penalty))
end
mob:set_yaw(angle - math.pi/2)
table.insert(children, mob)
angle = angle + (math.pi*2)/children_count
if (not mother_stuck) then
mob:set_velocity(vector.multiply(dir, eject_speed * speed_penalty))
end
mob:set_yaw(angle - math.pi/2)
table.insert(children, mob)
angle = angle + (math.pi*2)/children_count
end
-- If mother was murdered, children attack the killer after 1 second
if self.state == "attack" then
minetest.after(1.0, function(children, enemy)
for c = 1, #children do
for c=1, #children do
local child = children[c]
local le = child:get_luaentity()
if le then
if le ~= nil then
le.state = "attack"
le.attack = enemy
end
@ -66,7 +66,6 @@ local slime_big = {
hp_max = 16,
xp_min = 4,
xp_max = 4,
rotate = 270,
collisionbox = {-1.02, -0.01, -1.02, 1.02, 2.03, 1.02},
visual_size = {x=12.5, y=12.5},
textures = {{"mobs_mc_slime.png", "mobs_mc_slime.png"}},
@ -98,9 +97,8 @@ local slime_big = {
},
fall_damage = 0,
view_range = 16,
attack_type = "jump_punch",
attack_type = "dogfight",
passive = false,
jump_only = true,
jump = true,
walk_velocity = 2.5,
run_velocity = 2.5,
@ -313,7 +311,6 @@ local magma_cube_big = {
},
walk_velocity = 4,
run_velocity = 4,
rotate = 270,
damage = 6,
reach = 3,
armor = 53,
@ -337,13 +334,12 @@ local magma_cube_big = {
},
water_damage = 0,
lava_damage = 0,
fire_damage = 0,
fire_damage = 0,
light_damage = 0,
fall_damage = 0,
view_range = 16,
attack_type = "jump_punch",
attack_type = "dogfight",
passive = false,
jump_only = true,
jump = true,
jump_height = 8,
walk_chance = 0,

View File

@ -3,12 +3,12 @@
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mobs_mc")
local snow_trail_frequency = 0.5 -- Time in seconds for checking to add a new snow trail
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
local mod_throwing = minetest.get_modpath("mcl_throwing")
local mod_throwing = minetest.get_modpath("mcl_throwing") ~= nil
local gotten_texture = {
"mobs_mc_snowman.png",
@ -179,9 +179,9 @@ mobs_mc.tools.check_snow_golem_summon = function(pos)
minetest.remove_node(pos)
minetest.remove_node(b1)
minetest.remove_node(b2)
minetest.check_for_falling(pos)
minetest.check_for_falling(b1)
minetest.check_for_falling(b2)
core.check_for_falling(pos)
core.check_for_falling(b1)
core.check_for_falling(b2)
local obj = minetest.add_entity(place, "mobs_mc:snowman")
if obj then
summon_particles(obj)

Some files were not shown because too many files have changed in this diff Show More