Compare commits
838 Commits
bzoss_play
...
master
Author | SHA1 | Date |
---|---|---|
pitchum | 73927cb0cb | |
pitchum | d0e789daf2 | |
pitchum | b0f389eb9f | |
pitchum | 390f877230 | |
kay27 | 2ce5c5415a | |
epCode | 2b513aa592 | |
kay27 | 3a2300382b | |
Elias Fleckenstein | d859d94a63 | |
AFCMS | 41e715ef39 | |
Lizzy Fleckenstein | 37ef792c9d | |
Lizzy Fleckenstein | 524b3343bd | |
MysticTempest | 2ace4ccc68 | |
epCode | 73616453a4 | |
kay27 | c1880d26c8 | |
kay27 | 23a023d87d | |
kay27 | 0e37188ad1 | |
epCode | 3406342ed0 | |
epCode | 8f2a588059 | |
kay27 | 44d3f25767 | |
epCode | fb5f86d829 | |
epCode | 8c1444a1a8 | |
Lizzy Fleckenstein | d4401a6c3e | |
kay27 | a5168721b1 | |
Lizzy Fleckenstein | 1274884a9e | |
Lizzy Fleckenstein | f04a5a4cc9 | |
kay27 | e23ad6cabf | |
Lizzy Fleckenstein | 360436cf19 | |
Lizzy Fleckenstein | 51ace85d4e | |
epCode | fbb79635eb | |
kay27 | 3ceb2b0a4d | |
epCode | c1c3dbfaec | |
epCode | d1fd3cc827 | |
kay27 | 54cd5007ed | |
Lizzy Fleckenstein | da606fa9d2 | |
Lizzy Fleckenstein | 62171b9cf9 | |
Lizzy Fleckenstein | 0c3ab5843d | |
Lizzy Fleckenstein | 0d2950228a | |
Lizzy Fleckenstein | 6780031454 | |
epCode | 4334339ba3 | |
epCode | 5a6810aa6a | |
Lizzy Fleckenstein | 2d4b8a8232 | |
epCode | 9caf6f2904 | |
AFCMS | f0348d99d9 | |
kay27 | 47db5c5917 | |
Elias Fleckenstein | eb62db441b | |
Code-Sploit | 89a048e335 | |
AFCMS | a15765e647 | |
AFCMS | 0e6177ee1f | |
Lizzy Fleckenstein | 2d0612fa81 | |
Lizzy Fleckenstein | 86dc33c12f | |
Lizzy Fleckenstein | 5de9d90569 | |
Lizzy Fleckenstein | 3d0f5a4de5 | |
Lizzy Fleckenstein | a86d3fa22c | |
Lizzy Fleckenstein | 152d49ef20 | |
kay27 | 0ba7e4fc4d | |
epCode | 512765a37d | |
kay27 | 89e55e9065 | |
epCode | d8b5620115 | |
epCode | 38cb2fdeec | |
epCode | 98f6e05cdc | |
Code-Sploit | 8135110fd4 | |
Lizzy Fleckenstein | 30b1d58e67 | |
epCode | ecb70aaf55 | |
epCode | af89b95316 | |
epCode | 393bc195fb | |
epCode | d29c045ad8 | |
Code-Sploit | f5d2a32e6b | |
Code-Sploit | 84bfa87fdf | |
Code-Sploit | c4633db21d | |
Code-Sploit | ae7c4d7a8b | |
Elias Fleckenstein | 793b5f616e | |
AFCMS | fa0ea94433 | |
AFCMS | 4c3954959c | |
AFCMS | 25653e6178 | |
AFCMS | 0531aae687 | |
AFCMS | 35d55376a9 | |
AFCMS | 63d1661e08 | |
AFCMS | 9819b713c9 | |
AFCMS | 2e2d0b49ea | |
Lizzy Fleckenstein | c9e589b931 | |
Lizzy Fleckenstein | aeb7078c05 | |
Lizzy Fleckenstein | 100e37183d | |
Lizzy Fleckenstein | 82e113f0fc | |
Lizzy Fleckenstein | bec5339fc6 | |
Lizzy Fleckenstein | eddef41e6b | |
Lizzy Fleckenstein | 9b349a1684 | |
Lizzy Fleckenstein | 69959fe816 | |
epCode | 18a8d011a2 | |
epCode | a49e144911 | |
epCode | 0d8744d9a0 | |
epCode | c238fd9ba7 | |
kay27 | 0e026c187e | |
Rocher Laurent | 529f799cc2 | |
Elias Åström | 5972322639 | |
Elias Åström | d5ea06bb47 | |
epCode | 24c14e7f15 | |
Elias Fleckenstein | 98b00898a5 | |
Code-Sploit | 9cbfaf012e | |
Lizzy Fleckenstein | ef41b54387 | |
Lizzy Fleckenstein | 574ced80a3 | |
Lizzy Fleckenstein | 47d9c23c7a | |
epCode | 3b775c38cd | |
epCode | 164aad4ff9 | |
Lizzy Fleckenstein | b0c1aea881 | |
Lizzy Fleckenstein | e5caef3440 | |
epCode | 52c36d45da | |
epCode | ba86cf1d8b | |
epCode | 903a29f949 | |
kay27 | 3e584cdfb7 | |
Laurent Rocher | cf413635bf | |
Laurent Rocher | 303d286603 | |
Laurent Rocher | 9944498952 | |
kay27 | cbc5299bff | |
kay27 | 2f206a0640 | |
TechDudie | 10d3c62690 | |
TechDudie | a1e8685faf | |
TechDudie | b2d53e9e39 | |
TechDudie | 1022449ace | |
epCode | 0bde0aabf6 | |
epCode | a9fe8d58e5 | |
Midgard | f27fbd866e | |
Lizzy Fleckenstein | b2e2120b9e | |
Lizzy Fleckenstein | 0dd0c3623e | |
Lizzy Fleckenstein | 778ddd555f | |
MysticTempest | 846b1d273d | |
MysticTempest | 0ec64189dc | |
epCode | d7cfe54eb4 | |
Lizzy Fleckenstein | 6ebafe7735 | |
Lizzy Fleckenstein | 7932f4e470 | |
Lizzy Fleckenstein | e492c83cb5 | |
kay27 | a73f5dabbd | |
kay27 | 1d792a650f | |
kay27 | 3b196da12f | |
Lizzy Fleckenstein | 735bfc88c4 | |
kay27 | ba9ad48114 | |
epCode | cf95239fe5 | |
epCode | 7e2e96672b | |
epCode | b749de4ced | |
epCode | 0fe02b5a69 | |
epCode | 6a3a0362a3 | |
Lizzy Fleckenstein | 1571f2e0d9 | |
Lizzy Fleckenstein | 484ffc924a | |
MysticTempest | dc9ca16321 | |
Lizzy Fleckenstein | b36db2044f | |
kay27 | bd1e4187a0 | |
Elias Fleckenstein | 26037157f8 | |
epCode | 29d43b9709 | |
epCode | c5169e48a1 | |
epCode | dbe009f376 | |
epCode | 38f70561c5 | |
epCode | adbfd6b55d | |
epCode | df8bdfbc36 | |
kay27 | 84289a3a11 | |
Elias Fleckenstein | a42bd72edf | |
epCode | b5353c060f | |
Lizzy Fleckenstein | 88ed1aaa87 | |
Elias Fleckenstein | 50c901c2b7 | |
HimbeerserverDE | fbb5f7464c | |
epCode | 282af37555 | |
epCode | 1868f31673 | |
epCode | 729c60cd4b | |
epCode | 6f8d728035 | |
kay27 | 696ae8e6fe | |
kay27 | fa3e37c604 | |
Code-Sploit | 95b0a27213 | |
epCode | 403c174722 | |
epCode | 37baf5e69a | |
epCode | f37096cb4b | |
epCode | cf837247a7 | |
epCode | bd98529945 | |
kay27 | 13a9dbed3e | |
Lizzy Fleckenstein | 18dd3ac9bd | |
kay27 | 9492f276fc | |
kay27 | e8f8d4cb1e | |
kay27 | 32cf25dc17 | |
epCode | e0ad09900c | |
MysticTempest | e716ebd911 | |
HimbeerserverDE | ee6d8451d2 | |
Lizzy Fleckenstein | b5d92f3078 | |
Lizzy Fleckenstein | 9956e267aa | |
Lizzy Fleckenstein | 3d8d630a9e | |
Lizzy Fleckenstein | 4200dbdaa4 | |
Lizzy Fleckenstein | da7dfb1ea4 | |
HimbeerserverDE | a654db7684 | |
kay27 | b0f151147c | |
kay27 | 948265fd6b | |
kay27 | 30b4b9661c | |
Lizzy Fleckenstein | b61ae6a61f | |
MysticTempest | 2fe5ac8569 | |
Lizzy Fleckenstein | 65219d34a2 | |
HimbeerserverDE | 8ae233ba36 | |
HimbeerserverDE | 000dd3cbc9 | |
kay27 | 9a668204cb | |
Lizzy Fleckenstein | e66d66caf9 | |
Lizzy Fleckenstein | 4fe944445b | |
Lizzy Fleckenstein | 89ce072621 | |
kay27 | 5e65307819 | |
kay27 | f20f9f9a88 | |
MysticTempest | ff38a44454 | |
kay27 | ff2cd808d5 | |
kay27 | 1f18c2438c | |
HimbeerserverDE | a3ccb54376 | |
HimbeerserverDE | 00df587bf7 | |
Lizzy Fleckenstein | dbd6ebd4b5 | |
Lizzy Fleckenstein | 85f3fb7ea1 | |
Lizzy Fleckenstein | 248272a128 | |
Lizzy Fleckenstein | 5ede42bbe7 | |
Lizzy Fleckenstein | db3a31c2c4 | |
kay27 | 7210dfcc1c | |
MysticTempest | 0c23406531 | |
MysticTempest | 9feee980f8 | |
Lizzy Fleckenstein | 97594c89fb | |
Lizzy Fleckenstein | e05576b3f3 | |
Lizzy Fleckenstein | e9f9d96eb1 | |
Lizzy Fleckenstein | 953a2f2cd1 | |
Lizzy Fleckenstein | 757da9cd7e | |
Elias Åström | 1d27a18578 | |
Elias Åström | 948438bd1c | |
Elias Åström | 34274486c7 | |
Elias Åström | e3d2284485 | |
Elias Åström | 4a07b0607f | |
Elias Åström | c907df9669 | |
Elias Åström | 5ecb56452e | |
MysticTempest | 41bd803185 | |
MysticTempest | d571d62863 | |
Lizzy Fleckenstein | 0dd059d60d | |
Lizzy Fleckenstein | 503686380b | |
Elias Åström | 174a3a2968 | |
MysticTempest | cbd3a491f6 | |
Lizzy Fleckenstein | 0022c9902b | |
MysticTempest | c1c5ed4869 | |
Lizzy Fleckenstein | 9b1b1504fd | |
Lizzy Fleckenstein | a514b97880 | |
Lizzy Fleckenstein | 467683a7f9 | |
Lizzy Fleckenstein | 76bd139f1b | |
Lizzy Fleckenstein | 4a3916236c | |
Lizzy Fleckenstein | 9ce8c95f8c | |
Lizzy Fleckenstein | 745b7063a5 | |
Lizzy Fleckenstein | fdfcf9ca70 | |
Lizzy Fleckenstein | eb01c8e9f8 | |
Lizzy Fleckenstein | 73d6533aff | |
Lizzy Fleckenstein | f9a82aab05 | |
kay27 | 94840ec2ef | |
Lizzy Fleckenstein | b7c3096364 | |
Lizzy Fleckenstein | 4a4a834bf8 | |
Lizzy Fleckenstein | 291991c745 | |
Lizzy Fleckenstein | a92273b930 | |
kay27 | c9294a4d8a | |
kay27 | 2e898b3113 | |
MysticTempest | 689e6edac2 | |
kay27 | c4dce1df25 | |
kay27 | a41e0628e5 | |
Lizzy Fleckenstein | b6aabfc853 | |
Lizzy Fleckenstein | 0e0628bcc5 | |
Lizzy Fleckenstein | 3d7e89811d | |
kay27 | 1a2c500873 | |
Lizzy Fleckenstein | 088f2eecae | |
Lizzy Fleckenstein | 02305c914d | |
Lizzy Fleckenstein | 9cc3b5ccda | |
Lizzy Fleckenstein | 09ab1482b5 | |
kay27 | 81c27363a3 | |
Lizzy Fleckenstein | 427ac03a4d | |
Lizzy Fleckenstein | bb0e5af6d0 | |
Lizzy Fleckenstein | 4b61b3b4e5 | |
Lizzy Fleckenstein | 6e6f994a43 | |
Lizzy Fleckenstein | fa9d4402c7 | |
Lizzy Fleckenstein | b54b6c4c97 | |
Lizzy Fleckenstein | c70d33fc8e | |
Lizzy Fleckenstein | be5a228bad | |
Lizzy Fleckenstein | c024bc43d0 | |
kay27 | 5b44eeb611 | |
kay27 | 5400cdba35 | |
kay27 | fe33f172d4 | |
Wuzzy | 51b97ca289 | |
Lizzy Fleckenstein | 15dd969adf | |
Lizzy Fleckenstein | 50e90e8c23 | |
Elias Fleckenstein | b338d36d63 | |
Lizzy Fleckenstein | 1f05d8f876 | |
Lizzy Fleckenstein | 68f5d1c0fb | |
Lizzy Fleckenstein | 41246f61f2 | |
Lizzy Fleckenstein | c9427e0421 | |
Lizzy Fleckenstein | 95cc6ba532 | |
Lizzy Fleckenstein | c4c3fc1c8c | |
Lizzy Fleckenstein | a9bdb7b509 | |
Lizzy Fleckenstein | 20ab04dfc0 | |
Lizzy Fleckenstein | 7a1e6246d6 | |
kay27 | eef5f2cc5b | |
kay27 | fd4ce3c688 | |
Lizzy Fleckenstein | 5ce1fd6821 | |
Lizzy Fleckenstein | 2f1a918667 | |
Lizzy Fleckenstein | 9a31252c5d | |
Lizzy Fleckenstein | 7bcc8c1534 | |
Lizzy Fleckenstein | 7d4688b70c | |
Lizzy Fleckenstein | 2be8a550dc | |
Lizzy Fleckenstein | aee607800e | |
Lizzy Fleckenstein | a49e3c9068 | |
Lizzy Fleckenstein | b616ce734f | |
Lizzy Fleckenstein | f68a75f184 | |
Lizzy Fleckenstein | 3787b95e0f | |
Lizzy Fleckenstein | 034174390d | |
Lizzy Fleckenstein | 08a8b155d7 | |
Lizzy Fleckenstein | 3a02e90c3a | |
Lizzy Fleckenstein | f2c978c892 | |
Lizzy Fleckenstein | fd5f3a8df7 | |
kay27 | bdd0123c77 | |
Lizzy Fleckenstein | 52ed7f668e | |
Lizzy Fleckenstein | bc15c9c22d | |
kay27 | faa944193a | |
Lizzy Fleckenstein | 823ff7e22e | |
Lizzy Fleckenstein | 059629c51f | |
Lizzy Fleckenstein | cd1b8e9d2f | |
Lizzy Fleckenstein | c405242fa2 | |
Lizzy Fleckenstein | 8b92d795d2 | |
Lizzy Fleckenstein | 5899c2059f | |
Lizzy Fleckenstein | 6f49a3d535 | |
Lizzy Fleckenstein | e7721b91a0 | |
Lizzy Fleckenstein | 7bdce54048 | |
Lizzy Fleckenstein | 8ef14dd81f | |
Lizzy Fleckenstein | 96ca23419a | |
Lizzy Fleckenstein | 14551edcd2 | |
Lizzy Fleckenstein | f253d49a8d | |
Lizzy Fleckenstein | d88b548ddb | |
Lizzy Fleckenstein | fcc485a8e3 | |
Lizzy Fleckenstein | a0ffe92587 | |
Lizzy Fleckenstein | 139a4d94d0 | |
Lizzy Fleckenstein | 90f1fde8c8 | |
Lizzy Fleckenstein | 49c70560a5 | |
Lizzy Fleckenstein | 37f256648b | |
Lizzy Fleckenstein | ebc2ec9f72 | |
kay27 | 6fcf1cf09f | |
kay27 | 4d54766590 | |
kay27 | c2a14e2eae | |
Lizzy Fleckenstein | dc5ff37449 | |
Lizzy Fleckenstein | b0b23b7532 | |
Lizzy Fleckenstein | cfc86bcf3d | |
Lizzy Fleckenstein | 796c80b2d1 | |
Lizzy Fleckenstein | 0a482cc0cf | |
Lizzy Fleckenstein | a7c42306a7 | |
Lizzy Fleckenstein | aea051fe37 | |
Lizzy Fleckenstein | 378dca593e | |
Lizzy Fleckenstein | 17ff0c9be5 | |
Lizzy Fleckenstein | de810cee81 | |
Lizzy Fleckenstein | e26a644df0 | |
Lizzy Fleckenstein | 6d16c2e348 | |
Lizzy Fleckenstein | ac54e3caf3 | |
Lizzy Fleckenstein | a4d7bd03e1 | |
Lizzy Fleckenstein | 7d1ce8bc07 | |
Lizzy Fleckenstein | 9dc0d103a1 | |
Lizzy Fleckenstein | 507f2d872b | |
Lizzy Fleckenstein | 269ebc2718 | |
Lizzy Fleckenstein | f86cf37ac9 | |
Lizzy Fleckenstein | 5939baee52 | |
Lizzy Fleckenstein | cfa6937df4 | |
Lizzy Fleckenstein | ce4e86549b | |
Lizzy Fleckenstein | c36dc16527 | |
Lizzy Fleckenstein | abdb76c2a0 | |
Lizzy Fleckenstein | 41a364b319 | |
Lizzy Fleckenstein | 0cfb60a826 | |
Lizzy Fleckenstein | 84cd8195c6 | |
Lizzy Fleckenstein | 2d9ec679c0 | |
Lizzy Fleckenstein | 978aa38196 | |
Lizzy Fleckenstein | 5ce8c229db | |
Lizzy Fleckenstein | 10d6ca4107 | |
Lizzy Fleckenstein | ae59f9fd3c | |
Lizzy Fleckenstein | 54f7d76298 | |
Lizzy Fleckenstein | 02777b1f65 | |
Lizzy Fleckenstein | 1fda78667f | |
Lizzy Fleckenstein | 6b2416b211 | |
Lizzy Fleckenstein | 9e97331bdc | |
Lizzy Fleckenstein | 0fe1707c2f | |
Lizzy Fleckenstein | 6cc029a6e4 | |
Wuzzy | 4c2f3f2b7c | |
Wuzzy | 3390370441 | |
Lizzy Fleckenstein | ea938237d5 | |
kay27 | 30379c823c | |
Lizzy Fleckenstein | c2521885ff | |
Lizzy Fleckenstein | 7d45055a59 | |
Lizzy Fleckenstein | 081ae7fbff | |
Lizzy Fleckenstein | 8ba8f62527 | |
Lizzy Fleckenstein | 7d805ff789 | |
Lizzy Fleckenstein | 64e510a730 | |
Lizzy Fleckenstein | ab079d0c9b | |
Lizzy Fleckenstein | 939a73dd77 | |
Lizzy Fleckenstein | 883056bbc2 | |
Lizzy Fleckenstein | 84708c3870 | |
Lizzy Fleckenstein | 2bc5a281f5 | |
Lizzy Fleckenstein | fbd4a3a516 | |
kay27 | d42ee00290 | |
Lizzy Fleckenstein | 212e895c1a | |
Lizzy Fleckenstein | 2932837951 | |
Lizzy Fleckenstein | 92bf864807 | |
Lizzy Fleckenstein | 071ba77bb0 | |
Lizzy Fleckenstein | a6eed5c5b3 | |
Wuzzy | e8573189d8 | |
Wuzzy | a4b2172ac5 | |
kay27 | 5385a3f202 | |
Lizzy Fleckenstein | 758a3470f3 | |
Lizzy Fleckenstein | 7545e29f58 | |
Wuzzy | c85f2f6064 | |
Lizzy Fleckenstein | b017fd7405 | |
Lizzy Fleckenstein | da7240d6c1 | |
Lizzy Fleckenstein | a7ff5be28b | |
MysticTempest | 38f89fc963 | |
Lizzy Fleckenstein | 8f62a3fe0c | |
MysticTempest | b56ae38939 | |
Lizzy Fleckenstein | 6ba3fc869c | |
Lizzy Fleckenstein | 3161668d26 | |
Lizzy Fleckenstein | e152e346ea | |
Lizzy Fleckenstein | 213f62ac06 | |
Lizzy Fleckenstein | ef9a54872e | |
Lizzy Fleckenstein | 5fe64ff6f1 | |
Lizzy Fleckenstein | a4d9d22bb0 | |
Lizzy Fleckenstein | fdbfd4c654 | |
Wuzzy | b0dc0ecc9c | |
epCode | f62a003163 | |
epCode | a228899fc9 | |
epCode | 2b2e0914d4 | |
epCode | c5412dd2a7 | |
epCode | 12564b573b | |
epCode | 76e7b8f637 | |
Lizzy Fleckenstein | d820c35937 | |
Lizzy Fleckenstein | b91b587876 | |
Wuzzy | fd53198c9a | |
Wuzzy | 39a0fdd24c | |
Wuzzy | 821af93675 | |
Wuzzy | e22b766ffa | |
Lizzy Fleckenstein | 6eeeb83c0d | |
Lizzy Fleckenstein | 4f18f77db0 | |
Lizzy Fleckenstein | 753be59d95 | |
Wuzzy | 1f124476f2 | |
epCode | 0d53c946ce | |
epCode | eee88adcd1 | |
epCode | 2e2b22dc15 | |
epCode | f6ce027441 | |
epCode | 39dfc72ac5 | |
epCode | acda2ba9bf | |
epCode | fec3085593 | |
Lizzy Fleckenstein | 1f0fc01d20 | |
Lizzy Fleckenstein | 977489de04 | |
Lizzy Fleckenstein | 66eb5c35da | |
epCode | 771964863b | |
epCode | d893c07edc | |
MysticTempest | cb3fa6cd09 | |
epCode | 44c757ba6e | |
Lizzy Fleckenstein | 0477e729f5 | |
Lizzy Fleckenstein | 19726241c3 | |
MysticTempest | fb51ab05ea | |
Lizzy Fleckenstein | 6c3588bad8 | |
Lizzy Fleckenstein | f1a4c493c8 | |
Lizzy Fleckenstein | 28239ec0fb | |
epCode | ef8d7b1e6a | |
epCode | 20cc845940 | |
kay27 | 8eed6eaf4e | |
Wuzzy | f6f2037e6a | |
Wuzzy | e6d99b8b18 | |
Wuzzy | 73cb6b7a22 | |
Wuzzy | 4be2f2f76d | |
Wuzzy | e154919b34 | |
Wuzzy | 7d8c33c647 | |
Wuzzy | 9028902a87 | |
Wuzzy | 70b078cdaf | |
Wuzzy | 5a7fc3774f | |
kay27 | e7aa873968 | |
kay27 | 5da02bb8cc | |
Wuzzy | 0cbbe451d4 | |
Wuzzy | 1ca89f699a | |
Wuzzy | d699459bac | |
Wuzzy | d17c53cb0c | |
Wuzzy | 9324c43d8d | |
Wuzzy | 63e8b8cb63 | |
Wuzzy | 6532148f2f | |
Wuzzy | 8e65876fdf | |
Wuzzy | 7abffc5df9 | |
kay27 | a7c4d4ebd9 | |
Wuzzy | ac782bac90 | |
Wuzzy | 8dae3e3460 | |
Wuzzy | 9fd27db688 | |
Wuzzy | 938f62c7c1 | |
Wuzzy | 9b9ee66b00 | |
Wuzzy | 42155c6bdc | |
Wuzzy | 5bd3ebda17 | |
Wuzzy | e49e75ece2 | |
Wuzzy | 1ab90c58a6 | |
Wuzzy | 91071e9bc2 | |
kay27 | 827d7ec538 | |
Wuzzy | 839c22dcfb | |
Wuzzy | e8cb8a789e | |
Wuzzy | 92785f7411 | |
Wuzzy | b163d17a53 | |
Wuzzy | c2fe18def7 | |
Wuzzy | 29d46a5949 | |
Wuzzy | 52681658ef | |
Wuzzy | e894775943 | |
Wuzzy | 9d31ddb30d | |
Wuzzy | b70e58ab05 | |
Wuzzy | da7214bafa | |
Wuzzy | 376e1c32c5 | |
Wuzzy | 22a0b107ba | |
Wuzzy | c7084cb79a | |
Wuzzy | a764298923 | |
Wuzzy | bccd91e08f | |
Wuzzy | 99b4ba65c2 | |
Wuzzy | 48582e10d2 | |
Wuzzy | 73744b4fc8 | |
Wuzzy | eee892d78e | |
Wuzzy | 389135f87f | |
Wuzzy | 1d0ecd5708 | |
Wuzzy | 8b09cccfd4 | |
Wuzzy | 312bae6a17 | |
Wuzzy | c0ef6e3d5a | |
Wuzzy | e23bdca570 | |
Wuzzy | c48371e859 | |
Wuzzy | a9b59816c4 | |
Wuzzy | cb08062926 | |
Wuzzy | 3a28081683 | |
Wuzzy | 21310aad59 | |
Wuzzy | 57e24fc705 | |
Wuzzy | b6c6602d13 | |
Wuzzy | ed3afc6e49 | |
Wuzzy | 411e180477 | |
Wuzzy | ab7cfa1e43 | |
Wuzzy | 9b519cb665 | |
Wuzzy | 1362730dbf | |
Wuzzy | 0d7e957694 | |
Wuzzy | 855fd6b279 | |
Wuzzy | a56df1e533 | |
Wuzzy | 7913e72e07 | |
Wuzzy | 6f9f7a2cb9 | |
kay27 | 945260fa29 | |
MysticTempest | 09ccfc9802 | |
Wuzzy | 356977531e | |
Wuzzy | 8dddfe17db | |
Wuzzy | 257d7803a4 | |
Wuzzy | 51fea93905 | |
Wuzzy | 30b915b5c2 | |
Wuzzy | 2638d91785 | |
Wuzzy | 7e8c3aebd5 | |
Wuzzy | d60a0a0949 | |
kay27 | 06c97be4a2 | |
kay27 | e0734952ce | |
kay27 | 2958d96967 | |
Wuzzy | 439ed00a20 | |
Wuzzy | c40e97aa2e | |
Wuzzy | c2a8a5c74b | |
Lizzy Fleckenstein | ed738da016 | |
Laurent Rocher | af26f18bd6 | |
Laurent Rocher | 9010cf514d | |
Laurent Rocher | 7f12c246b5 | |
kay27 | 2b1d21a5b5 | |
Lizzy Fleckenstein | a3cf6b0e5d | |
Lizzy Fleckenstein | b53ae0df19 | |
Wuzzy | bd2d0f717a | |
Wuzzy | 9365493696 | |
Wuzzy | 124274053d | |
Wuzzy | c3861bad85 | |
Wuzzy | c5a27ee47a | |
Wuzzy | 027b240cac | |
Wuzzy | 51085fd6b8 | |
Wuzzy | 41a1a3167d | |
Wuzzy | 271cdbcf03 | |
Wuzzy | d952c79cb7 | |
Wuzzy | 41af1eddba | |
Wuzzy | 8512b7c2e0 | |
Wuzzy | daff07269a | |
Wuzzy | 132db02011 | |
Lizzy Fleckenstein | b9e5a991e2 | |
kay27 | 47c834a809 | |
Lizzy Fleckenstein | 3d7bb69e81 | |
Lizzy Fleckenstein | 479dfd6c0d | |
Wuzzy | c7a4f7cbfb | |
Lizzy Fleckenstein | 494ffb41d3 | |
Lizzy Fleckenstein | 86b2cd70f9 | |
Lizzy Fleckenstein | 4d37e309e7 | |
Lizzy Fleckenstein | bbc6db489e | |
Lizzy Fleckenstein | cdafb1a07e | |
Lizzy Fleckenstein | 2b55dac7d2 | |
Lizzy Fleckenstein | 7c28bf8507 | |
Lizzy Fleckenstein | 8a406ad968 | |
Lizzy Fleckenstein | b89ffb12f2 | |
Lizzy Fleckenstein | 22083a0ff5 | |
Lizzy Fleckenstein | afa11c0723 | |
Lizzy Fleckenstein | a516eccd6d | |
Lizzy Fleckenstein | 04d8d999e2 | |
Lizzy Fleckenstein | e09ecb5431 | |
Lizzy Fleckenstein | 3791f8983e | |
Lizzy Fleckenstein | 3fd1963da9 | |
Lizzy Fleckenstein | 26f3d821a4 | |
Lizzy Fleckenstein | 76303ae194 | |
Lizzy Fleckenstein | a76fb8dd57 | |
Lizzy Fleckenstein | 1cef707c6c | |
Lizzy Fleckenstein | 64e62486e2 | |
Lizzy Fleckenstein | 8ef39f405f | |
Lizzy Fleckenstein | 79b624bc5c | |
kay27 | 38ad237d92 | |
kay27 | 9f98117328 | |
kay27 | 1965696829 | |
kay27 | c4f038ab77 | |
Wuzzy | 730e5f6998 | |
Wuzzy | a4c2211d87 | |
kay27 | 30d9e54803 | |
Wuzzy | 529e3be802 | |
Wuzzy | 5374376e24 | |
Wuzzy | 3236dc0d8e | |
Wuzzy | fe1c8ca758 | |
Wuzzy | 6706104c3a | |
Wuzzy | 53dbd4e2c2 | |
Wuzzy | 3fde86eff6 | |
Wuzzy | 280f284867 | |
kay27 | 290893355b | |
Wuzzy | 4ad1adb850 | |
Wuzzy | 6b30553707 | |
Wuzzy | d2518c91e8 | |
Wuzzy | 4c39224e6f | |
Wuzzy | a05938db5d | |
kay27 | dbe631409c | |
kay27 | a127136c60 | |
kay27 | 4c2e28836c | |
kay27 | abef71f317 | |
Lizzy Fleckenstein | 299099116b | |
kay27 | f0afebea38 | |
kay27 | d1807b5844 | |
kay27 | a78c613322 | |
Wuzzy | 5f820c6bf9 | |
Wuzzy | b0ee0a475b | |
Wuzzy | 81b33d7df3 | |
Wuzzy | 3bed1c5bf8 | |
kay27 | c01c53af49 | |
kay27 | 3cd30a559e | |
kay27 | a511152cdf | |
kay27 | 339f7c6359 | |
kay27 | 4eb42c3a9a | |
kay27 | 446b0e6602 | |
kay27 | 8df2aebd31 | |
kay27 | 15cb94b9b3 | |
kay27 | 7678bf9b9f | |
kay27 | fa97aca76a | |
Wuzzy | b47ff2b9be | |
kay27 | daede2a183 | |
kay27 | 7bbb7438ae | |
kay27 | a2281f384b | |
kay27 | 28f19fdbb4 | |
kay27 | f2d68d909e | |
kay27 | 766c76831d | |
Wuzzy | 9d101ce923 | |
Wuzzy | e361b35724 | |
Wuzzy | 09ee912096 | |
Wuzzy | ae4ede757a | |
MysticTempest | 2f6afe34ba | |
Wuzzy | 8453dac1db | |
Wuzzy | e5d6e90913 | |
Wuzzy | 87ffe2e8f5 | |
Wuzzy | 4fb0ead10e | |
Wuzzy | 5787b43117 | |
Wuzzy | b726dd7689 | |
Wuzzy | 3a57a5800b | |
kay27 | 82c3142913 | |
kay27 | 81cf500611 | |
Wuzzy | 92c01628a9 | |
kay27 | a672d901f8 | |
kay27 | e4ca1beacb | |
kay27 | a728974d8a | |
kay27 | 6efed85866 | |
kay27 | 9c8098c203 | |
Wuzzy | 1878870886 | |
Wuzzy | 723a306e1e | |
Wuzzy | c7627f0517 | |
Wuzzy | ce0b31123b | |
Wuzzy | c2afc82754 | |
Wuzzy | c0aeb2f15f | |
Wuzzy | 101391cbcc | |
Wuzzy | 8a39474793 | |
Wuzzy | 731f42ac88 | |
Wuzzy | f00dc21252 | |
Wuzzy | 28aead0a60 | |
Wuzzy | 7c0c0d4d0c | |
Wuzzy | 91d174b437 | |
Wuzzy | 9f43d6a5a5 | |
Wuzzy | 2a1273b7e3 | |
Wuzzy | b14eb70241 | |
Wuzzy | 988056ad08 | |
Wuzzy | de8183f07a | |
Wuzzy | 4acf953334 | |
Wuzzy | fa9ce11ddd | |
Wuzzy | 7f1e90ada9 | |
Wuzzy | f91ae540c2 | |
Wuzzy | 80e54bf44d | |
Wuzzy | b2e2f27935 | |
Wuzzy | 1816324fe5 | |
Wuzzy | 3bdd95fe47 | |
Wuzzy | b2ad6b79bd | |
kay27 | ff24052e7f | |
Wuzzy | 2cc76fb9f3 | |
Wuzzy | eff6c4c476 | |
Wuzzy | 152d69f91f | |
Wuzzy | cef20edd53 | |
Wuzzy | 12ca804488 | |
kay27 | b8caa2581f | |
kay27 | 9537eaead0 | |
kay27 | c424b036b2 | |
Wuzzy | 89b294f8c1 | |
Wuzzy | 8573dd69b7 | |
Wuzzy | 578fbf999e | |
Wuzzy | 2a7edbde49 | |
Wuzzy | f4f976a7a5 | |
Brandon | 5637701c4b | |
Brandon | d6c7c9dcd0 | |
Brandon | 9024c8084d | |
Wuzzy | db1cc2e012 | |
Wuzzy | aaa13878c1 | |
Wuzzy | a472c30163 | |
Wuzzy | 7104bbd2df | |
Wuzzy | c373c972b3 | |
Brandon | 48fae05040 | |
Brandon | 0cfd16fb17 | |
Brandon | 128e98ca4d | |
Brandon | 0e462ef883 | |
kay27 | 6ba7ba981d | |
Brandon | 49a5f765bd | |
Brandon | cfcaa4fa12 | |
Wuzzy | 2e9231ac56 | |
Wuzzy | fd724f4c1c | |
Wuzzy | 3deac5a1c6 | |
Wuzzy | ed6604ee56 | |
Wuzzy | 402205d1ed | |
Wuzzy | 92591b37dc | |
Wuzzy | f5032503d0 | |
Wuzzy | e310de1754 | |
Wuzzy | 53c83a3479 | |
Wuzzy | 1834be9e46 | |
Wuzzy | 50bd1b9d5e | |
Wuzzy | ff476c29b6 | |
Wuzzy | 9c304105e9 | |
Wuzzy | 20455a259f | |
Wuzzy | 1f8488aba5 | |
Wuzzy | 13963d00e5 | |
Wuzzy | e2735e0081 | |
Wuzzy | b1b50df9ab | |
Wuzzy | f1616e522a | |
Wuzzy | 41cf1a4362 | |
Wuzzy | b49bcda0ac | |
Wuzzy | cbf545ee12 | |
Wuzzy | e519c62c8b | |
Wuzzy | 87bf6c12b2 | |
Wuzzy | e20a630a19 | |
Wuzzy | 431cd63865 | |
Wuzzy | fe40936065 | |
Wuzzy | c051a95dae | |
Brandon | b9a9b1b814 | |
MysticTempest | 460d6e837a | |
Brandon | 4c05c2e70c | |
Brandon | 67e4e814f4 | |
Brandon | af1ab424fc | |
kay27 | 125840c9e4 | |
kay27 | afc6a1bb0f | |
Brandon | 0a5cb628c5 | |
Brandon | 5e26cfcf3d | |
Brandon | 2ca2f25e58 | |
Brandon | acea309564 | |
Wuzzy | 5345dc9eb1 | |
Wuzzy | c63028801b | |
Wuzzy | fb3fade4eb | |
MysticTempest | c63c92f597 | |
Wuzzy | 23dc977cec | |
Wuzzy | eec9cd9012 | |
Wuzzy | 5af124d732 | |
Wuzzy | 3b95498092 | |
kay27 | 64f9e39ebd | |
kay27 | 92385364e5 | |
Wuzzy | 50fa36aa2c | |
Brandon | 1563fc7b96 | |
Brandon | 78bee21a82 | |
Brandon | fd6028e451 | |
Brandon | 9a32bdc967 | |
Brandon | bdd92c6cdb | |
Elias Åström | a8eca09822 | |
Elias Åström | 91b6213e0b | |
Elias Åström | e85c00ea02 | |
Wuzzy | 0cc179acc6 | |
kay27 | 7d1f8ac314 | |
kay27 | c78270e70b | |
Brandon | 6eb810339b | |
Elias Åström | 37c05cb840 | |
Elias Åström | 6095ae17b1 | |
Elias Åström | 4827d2a83a | |
Brandon | 9ef57692ba | |
Lizzy Fleckenstein | a31ed90a81 | |
Brandon | 9dce5581be | |
Brandon | d22805cecd | |
Brandon | 834ce1f611 | |
Brandon | e5f0370c17 | |
Brandon | e603a08f3c | |
Lizzy Fleckenstein | 21c6815839 | |
MysticTempest | 56958ab0c9 | |
Brandon | bf38131520 | |
Brandon | a53a98fff6 | |
Brandon | 8c5943b34c | |
Brandon | ebfe9674e1 | |
Brandon | c37e43df4e | |
Brandon | d228da1da7 | |
kay27 | d76b1a9065 | |
kay27 | e19c00cd44 | |
dBeans | f961a72c33 | |
Wuzzy | cd3e87bf57 | |
Wuzzy | e3c22cb072 | |
Wuzzy | fa76f81f92 | |
Wuzzy | 49d5e49999 | |
Wuzzy | a430772c16 | |
Wuzzy | ee52990db1 | |
Wuzzy | 7c93f3f9f7 | |
Wuzzy | ac518fa548 | |
Wuzzy | a3d70e45d1 | |
Brandon | dc3a991705 | |
Brandon | 8ac54febba | |
Brandon | f2906bee3a | |
Brandon | 927ba10c34 | |
Brandon | b45b4a44e5 | |
Brandon | c4271cf13d | |
Brandon | 623f60ab79 | |
Brandon | 31f57a51e0 | |
Brandon | 843f2d2a80 | |
Brandon | 43c4b355ce | |
Brandon | bb5aa33bad | |
kay27 | 0b05431285 | |
Brandon | 26315d44cf | |
kay27 | ba51686e6c | |
Brandon | 0f5b6b7ce0 | |
Brandon | 1eeb0511de | |
Brandon | fa86a09fd5 | |
Brandon | 2b4b37a439 | |
Brandon | 787769cb92 | |
Brandon | 5e77c90bb7 | |
Brandon | 850edb564d | |
Brandon | 64a2a6bb53 | |
Brandon | 1dda98fa4c | |
Elias Åström | ea1ad14f72 | |
Elias Åström | ca9578d50c | |
Wuzzy | 90cc3b9659 | |
David McMackins II | 59b6385d10 |
|
@ -5,47 +5,47 @@ Wow, thank you! :-)
|
|||
But first, some things to note:
|
||||
|
||||
MineClone 2's development target is to make a free software clone of Minecraft,
|
||||
***version 1.11***, ***PC edition***.
|
||||
***version 1.12***, ***PC edition***, *** + Optifine features supported by the Minetest Engine ***.
|
||||
|
||||
MineClone 2 is maintained by one person. Namely, Wuzzy. You can find me,
|
||||
Wuzzy, in the Minetest forums (forums.minetest.net), in IRC in the #minetest
|
||||
MineClone 2 is maintained by two persons. Namely, kay27 and EliasFleckenstein. You can find us
|
||||
in the Minetest forums (forums.minetest.net), in IRC in the #minetest
|
||||
channel on irc.freenode.net. And finally, you can send e-mails to
|
||||
<Wuzzy2@mail.ru>.
|
||||
<eliasfleckenstein@web.de> or <kay27@bk.ru>.
|
||||
|
||||
There is **no** guarantee I will accept anything from anybody.
|
||||
There is **no** guarantee we will accept anything from anybody.
|
||||
|
||||
By sending me patches or asking me to include your changes in this game,
|
||||
By sending us patches or asking us to include your changes in this game,
|
||||
you agree that they fall under the terms of the LGPLv2.1, which basically
|
||||
means they will become part of a free software.
|
||||
|
||||
## The suggested workflow
|
||||
I don't **dictate** your workflow, but in order to work with me in an efficient
|
||||
way, you can follow my suggestions.
|
||||
We don't **dictate** your workflow, but in order to work with us in an efficient
|
||||
way, you can follow these suggestions:
|
||||
|
||||
For small and medium changes:
|
||||
|
||||
* Fork the repository
|
||||
* Do your change in a new branch
|
||||
* Upload the repository somewhere where it can be accessed from the Internet and
|
||||
notify me
|
||||
notify us
|
||||
|
||||
For small changes, sending me a patch is also good.
|
||||
For small changes, sending us a patch is also good.
|
||||
|
||||
For big changes: Same as above, but consider notifying me first to avoid
|
||||
For big changes: Same as above, but consider notifying us first to avoid
|
||||
duplicate work and possible tears of rejection. ;-)
|
||||
|
||||
For people that I trust, I might give them direct commit access to this
|
||||
For trusted people, we might give them direct commit access to this
|
||||
repository. In this case, you obviously don't need to fork, but you still
|
||||
need to show your contributions align with the project goals. I still
|
||||
reserve the right to revert everything that I don't like.
|
||||
For bigger changes, I strongly recommend to use feature branches and
|
||||
need to show your contributions align with the project goals. We still
|
||||
reserve the right to revert everything that we don't like.
|
||||
For bigger changes, we strongly recommend to use feature branches and
|
||||
discuss with me first.
|
||||
|
||||
Contributors will be credited in `README.md`.
|
||||
|
||||
## Quality remarks
|
||||
Again: There is ***no*** guarantee I will accept anything from anybody.
|
||||
But I will gladly take in code from others when I feel it saves me work
|
||||
Again: There is ***no*** guarantee we will accept anything from anybody.
|
||||
But we will gladly take in code from others when we feel it saves us work
|
||||
in the long run.
|
||||
|
||||
### Inclusion criteria
|
||||
|
@ -79,4 +79,18 @@ Depending on what you add, the chances for inclusion vary:
|
|||
## Reporting bugs
|
||||
Report all bugs and missing Minecraft features here:
|
||||
|
||||
<https://git.minetest.land/Wuzzy/MineClone2/issues>
|
||||
<https://git.minetest.land/MineClone2/MineClone2/issues>
|
||||
|
||||
## Direct discussion
|
||||
We have an IRC channel! Join us on #mineclone2 in freenode.net.
|
||||
|
||||
<ircs://irc.freenode.net:6697/#mineclone2>
|
||||
|
||||
## Creating releases
|
||||
* Launch MineClone2 to make sure it still runs
|
||||
* Update the version number in README.md
|
||||
* Use `git tag <version number>` to tag the latest commit with the version number
|
||||
* Push to repo (don't forget `--tags`!)
|
||||
* Update ContentDB (https://content.minetest.net/packages/Wuzzy/mineclone2/)
|
||||
* Update first post in forum thread (https://forum.minetest.net/viewtopic.php?f=50&t=16407)
|
||||
* Post release announcement and changelog in forums
|
||||
|
|
|
@ -70,6 +70,7 @@ Please read <http://minecraft.gamepedia.com/Breaking> to learn how digging times
|
|||
* `coral_fan=X`: Coral fan (1 = alive, 2 = dead)
|
||||
* `coral_block=X`: Coral block (1 = alive, 2 = dead)
|
||||
* `coral_species=X`: Specifies the species of a coral; equal X means equal species
|
||||
* `set_on_fire=X`: Sets any (not fire-resistant) mob or player on fire for X seconds when touching
|
||||
|
||||
#### Footnotes
|
||||
|
||||
|
@ -96,6 +97,8 @@ Please read <http://minecraft.gamepedia.com/Breaking> to learn how digging times
|
|||
* `carpet=1:` (Wool) carpet
|
||||
* `stick=1`: Stick
|
||||
* `water_bucket=1`: Bucket containing a liquid of group “water”
|
||||
* `enchantability=X`: How good the enchantments are the item gets (1 equals book)
|
||||
* `enchanted=1`: The item is already enchanted, meaning that it can't be enchanted using an enchanting table
|
||||
|
||||
### Material groups
|
||||
|
||||
|
@ -197,6 +200,7 @@ These groups are used mostly for informational purposes
|
|||
* `building_block=1`: Block is a building block
|
||||
* `deco_block=1`: Block is a decorational block
|
||||
|
||||
|
||||
## Fake item groups
|
||||
These groups put similar items together which should all be treated by the gameplay or the GUI as a single item.
|
||||
You should not add custom items to these groups for no good reason, this is likely to cause a ton of conflicts.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Missing features in Minetest to recreate Minecraft features
|
||||
|
||||
A side goal of the MineClone 2 project is to find any shortcomings of Minetest which make it impossible to recreate a Minecraft feature exactly.
|
||||
This file lists some of the missing features in Minetest which MineClone 2 would require.MineClone 2 would require.MineClone 2 would require.MineClone 2 would require.
|
||||
This file lists some of the missing features in Minetest which MineClone 2 would require.
|
||||
|
||||
## No workaround possible
|
||||
For these features, no easy Lua workaround could be found.
|
||||
|
@ -20,7 +20,6 @@ For these features, no easy Lua workaround could be found.
|
|||
## Interface
|
||||
- Inventory: Hold down right mouse button while holding an item stack to drop items into the slots as you move the mouse. Makes crafting MUCH faster
|
||||
- Sneak+Leftclick on crafting output crafts as many items as possible and immediately puts it into the player inventory ([issue 5211](https://github.com/minetest/minetest/issues/5211))
|
||||
- Sneak+click on inventory slot should be able to put items into additional “fallback inventories” if the first inventory is full. Required for large chests
|
||||
- Sneak+click puts items in different inventories depending on the item type (maybe group-based)? Required for sneak-clicking to armor slots
|
||||
|
||||
## Workaround theoretically possible
|
||||
|
@ -35,6 +34,7 @@ For these features, a workaround (or hack ;-)) by using Lua is theoretically pos
|
|||
- Set frequency in which players lose breath. 2 seconds are hardcoded in Minetest, in Minecraft it's 1 second
|
||||
- Set damage frequency of `damage_per_second`. In Minecraft many things damage players every half-second rather than every second
|
||||
- Possible to damage players directly when they are with the head inside. This allows to add Minecraft-like suffocation
|
||||
- Sneak+click on inventory slot should be able to put items into additional “fallback inventories” if the first inventory is full. Useful for large chests
|
||||
|
||||
#### Nice-to-haye
|
||||
- Utility function to rotate pillar-like nodes, requiring only 3 possible orientations (X, Y, Z). Basically this is `minetest.rotate_node` but with less orientations; the purpur pillar would mess up if a mirrored rotation would be possible. This is already implemented in MCL2, See `mcl_util` for more infos
|
||||
|
|
32
README.md
|
@ -1,8 +1,8 @@
|
|||
# MineClone 2
|
||||
An unofficial Minecraft-like game for Minetest. Forked from MineClone by davedevils.
|
||||
Developed by Wuzzy and contributors. Not developed or endorsed by Mojang AB.
|
||||
Developed by many people. Not developed or endorsed by Mojang AB.
|
||||
|
||||
Version: 0.66.2
|
||||
Version: 0.70.0
|
||||
|
||||
### Gameplay
|
||||
You start in a randomly-generated world made entirely of cubes. You can explore
|
||||
|
@ -14,9 +14,10 @@ Or you can play in “creative mode” in which you can build almost anything in
|
|||
|
||||
#### Gameplay summary
|
||||
|
||||
* Sandbox-style gameplay, no goals (for now)
|
||||
* Sandbox-style gameplay, no goals
|
||||
* Survive: Fight against hostile monsters and hunger
|
||||
* Mine for ores and other treasures
|
||||
* Magic: Gain experience and enchant your tools
|
||||
* Use the collected blocks to create great buildings, your imagination is the limit
|
||||
* Collect flowers (and other dye sources) and colorize your world
|
||||
* Find some seeds and start farming
|
||||
|
@ -85,7 +86,8 @@ 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.
|
||||
|
||||
* **Target of development: Minecraft, PC Edition, version 1.11** (later known as “Java Edition”)
|
||||
* **Target of development: Minecraft, PC Edition, version 1.12** (later known as “Java Edition”)
|
||||
* MineClone2 also includes Optifine features supported by the Minetest
|
||||
* Features of later Minecraft versions might sneak in, but they have a low priority
|
||||
* In general, Minecraft is aimed to be cloned as good as Minetest currently permits (no hacks)
|
||||
* Cloning the gameplay has highest priority
|
||||
|
@ -102,7 +104,7 @@ big bugs (such as “missing node” errors or even crashes).
|
|||
The following main features are available:
|
||||
|
||||
* Tools, weapons
|
||||
* Armor (unbalanced)
|
||||
* Armor
|
||||
* Crafting system: 2×2 grid, crafting table (3×3 grid), furnace, including a crafting guide
|
||||
* Chests, large chests, ender chests, shulker boxes
|
||||
* Furnaces, hoppers
|
||||
|
@ -116,6 +118,10 @@ The following main features are available:
|
|||
* The Nether, a fiery underworld in another dimension
|
||||
* Redstone circuits (partially)
|
||||
* Minecarts (partial)
|
||||
* Status effects (partial)
|
||||
* Experience
|
||||
* Enchanting
|
||||
* Brewing, potions, tipped arrow (partial)
|
||||
* Boats
|
||||
* Fire
|
||||
* Buidling blocks: Stairs, slabs, doors, trapdoors, fences, fence gates, walls
|
||||
|
@ -140,14 +146,9 @@ The following main features are available:
|
|||
The following features are incomplete:
|
||||
|
||||
* Generated structures (especially villages)
|
||||
* NPCs
|
||||
* Some monsters and animals
|
||||
* Redstone-related things
|
||||
* The End
|
||||
* Enchanting
|
||||
* Experience
|
||||
* Status effects
|
||||
* Brewing, potions, tipped arrows
|
||||
* Special minecarts
|
||||
* A couple of non-trivial blocks and items
|
||||
|
||||
|
@ -182,7 +183,7 @@ Technical differences from Minecraft:
|
|||
## Reporting bugs
|
||||
Please report all bugs and missing Minecraft features here:
|
||||
|
||||
<https://git.minetest.land/Wuzzy/MineClone2/issues>
|
||||
<https://git.minetest.land/MineClone2/MineClone2/issues>
|
||||
|
||||
## Other readme files
|
||||
|
||||
|
@ -195,7 +196,7 @@ Please report all bugs and missing Minecraft features here:
|
|||
There are so many people to list (sorry). Check out the respective mod directories for details. This section is only a rough overview of the core authors of this game.
|
||||
|
||||
### Coding
|
||||
* [Wuzzy](https://forum.minetest.net/memberlist.php?mode=viewprofile&u=3082): Main programmer of most mods
|
||||
* [Wuzzy](https://forum.minetest.net/memberlist.php?mode=viewprofile&u=3082): Main programmer of most mods (retired)
|
||||
* davedevils: Creator of MineClone on which MineClone 2 is based on
|
||||
* [ex-bart](https://github.com/ex-bart): Redstone comparators
|
||||
* [Rootyjr](https://github.com/Rootyjr): Fishing rod and bugfixes
|
||||
|
@ -203,6 +204,9 @@ There are so many people to list (sorry). Check out the respective mod directori
|
|||
* [ryvnf](https://github.com/ryvnf): Explosion mechanics
|
||||
* MysticTempest: Bugfixes
|
||||
* [bzoss](https://github.com/bzoss): Status effects, potions, brewing stand
|
||||
* kay27 <kay27@bk.ru>: Experience system, bugfixes, optimizations (Current maintainer)
|
||||
* [EliasFleckenstein03](https://github.com/EliasFleckenstein03): End crystals, enchanting, burning mobs / players, animated chests, bugfixes (Current maintainer)
|
||||
* 2mac: Fix bug with powered rail
|
||||
* Lots of other people: TO BE WRITTEN (see mod directories for details)
|
||||
|
||||
#### Mod credits (summary)
|
||||
|
@ -248,6 +252,7 @@ Various sources. See the respective mod directories for details.
|
|||
### Special thanks
|
||||
|
||||
* davedevils for starting MineClone, the original version of this game
|
||||
* Wuzzy for starting and maintaining MineClone2 for several years
|
||||
* celeron55 for creating Minetest
|
||||
* Minetest's modding community for providing a huge selection of mods, some of which ended up in MineClone 2
|
||||
* Jordach for the jukebox music compilation from Big Freaking Dig
|
||||
|
@ -259,7 +264,6 @@ Various sources. See the respective mod directories for details.
|
|||
|
||||
## Info for programmers
|
||||
You find interesting and useful infos in `API.md`.
|
||||
This project is currently mostly a one-person project.
|
||||
|
||||
## Legal information
|
||||
This is a fan game, not developed or endorsed by Mojang AB.
|
||||
|
@ -268,7 +272,7 @@ Copying is an act of love. Please copy and share! <3
|
|||
Here's the detailed legalese for those who need it:
|
||||
|
||||
### License of source code
|
||||
MineClone 2 (by Wuzzy, davedevils and countless others)
|
||||
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
|
||||
|
|
|
@ -31,3 +31,5 @@ mgvalleys_spflags = noaltitude_chill,noaltitude_dry,nohumid_rivers,vary_river_de
|
|||
|
||||
# MCL2-specific stuff
|
||||
keepInventory = false
|
||||
|
||||
dedicated_server_step = 0.001
|
||||
|
|
|
@ -18,7 +18,7 @@ digging times in seconds. These digging times can be then added verbatim into th
|
|||
Example:
|
||||
mcl_autogroup.digtimes.pickaxey_dig_diamond[1] = 0.2
|
||||
|
||||
→ This menas that when a node has been assigned the group “pickaxey_dig_diamond=1”, it can be dug by the
|
||||
→ This means that when a node has been assigned the group “pickaxey_dig_diamond=1”, it can be dug by the
|
||||
diamond pickaxe in 0.2 seconds.
|
||||
|
||||
|
||||
|
@ -44,6 +44,7 @@ local divisors = {
|
|||
["shearsy_wool"] = 5,
|
||||
["swordy_cobweb"] = 15,
|
||||
}
|
||||
local max_efficiency_level = 5
|
||||
|
||||
mcl_autogroup = {}
|
||||
mcl_autogroup.digtimes = {}
|
||||
|
@ -53,11 +54,18 @@ for m=1, #materials do
|
|||
for g=1, #basegroups do
|
||||
mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m]] = {}
|
||||
mcl_autogroup.creativetimes[basegroups[g].."_dig_"..materials[m]] = {}
|
||||
for e=1, max_efficiency_level do
|
||||
mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m].."_efficiency_"..e] = {}
|
||||
end
|
||||
end
|
||||
end
|
||||
for g=1, #minigroups do
|
||||
mcl_autogroup.digtimes[minigroups[g].."_dig"] = {}
|
||||
mcl_autogroup.creativetimes[minigroups[g].."_dig"] = {}
|
||||
for e=1, max_efficiency_level do
|
||||
mcl_autogroup.digtimes[minigroups[g].."_dig_efficiency_"..e] = {}
|
||||
mcl_autogroup.creativetimes[minigroups[g].."_dig_efficiency_"..e] = {}
|
||||
end
|
||||
end
|
||||
|
||||
local overwrite = function()
|
||||
|
@ -80,7 +88,7 @@ local overwrite = function()
|
|||
groups_changed = true
|
||||
end
|
||||
|
||||
local function calculate_group(hardness, material, diggroup, newgroups, actual_rating, expected_rating)
|
||||
local function calculate_group(hardness, material, diggroup, newgroups, actual_rating, expected_rating, efficiency)
|
||||
local time, validity_factor
|
||||
if actual_rating >= expected_rating then
|
||||
-- Valid tool
|
||||
|
@ -89,14 +97,20 @@ local overwrite = function()
|
|||
-- Wrong tool (higher digging time)
|
||||
validity_factor = 5
|
||||
end
|
||||
time = (hardness * validity_factor) / divisors[material]
|
||||
local speed_multiplier = divisors[material]
|
||||
if efficiency then
|
||||
speed_multiplier = speed_multiplier + efficiency * efficiency + 1
|
||||
end
|
||||
time = (hardness * validity_factor) / speed_multiplier
|
||||
if time <= 0.05 then
|
||||
time = 0
|
||||
else
|
||||
time = math.ceil(time * 20) / 20
|
||||
end
|
||||
table.insert(mcl_autogroup.digtimes[diggroup], time)
|
||||
table.insert(mcl_autogroup.creativetimes[diggroup], 0)
|
||||
if not efficiency then
|
||||
table.insert(mcl_autogroup.creativetimes[diggroup], 0)
|
||||
end
|
||||
newgroups[diggroup] = #mcl_autogroup.digtimes[diggroup]
|
||||
return newgroups
|
||||
end
|
||||
|
@ -113,6 +127,9 @@ local overwrite = function()
|
|||
for g=1,#materials do
|
||||
local diggroup = basegroup.."_dig_"..materials[g]
|
||||
newgroups = calculate_group(hardness, materials[g], diggroup, newgroups, g, ndef.groups[basegroup])
|
||||
for e=1,max_efficiency_level do
|
||||
newgroups = calculate_group(hardness, materials[g], diggroup .. "_efficiency_" .. e, newgroups, g, ndef.groups[basegroup], e)
|
||||
end
|
||||
groups_changed = true
|
||||
end
|
||||
end
|
||||
|
@ -134,6 +151,9 @@ local overwrite = function()
|
|||
or
|
||||
(ndef.groups[minigroup] and minigroup ~= "swordy_cobweb" and minigroup ~= "shearsy_wool") then
|
||||
newgroups = calculate_group(hardness, minigroup, diggroup, newgroups, ar, 1)
|
||||
for e=1,max_efficiency_level do
|
||||
newgroups = calculate_group(hardness, minigroup, diggroup .. "_efficiency_" .. e, newgroups, ar, 1, e)
|
||||
end
|
||||
groups_changed = true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,6 +32,10 @@ local STEP_LENGTH = 0.3
|
|||
-- How many rays to compute entity exposure to explosion
|
||||
local N_EXPOSURE_RAYS = 16
|
||||
|
||||
-- Nodes having a blast resistance of this value or higher are treated as
|
||||
-- indestructible
|
||||
local INDESTRUCT_BLASTRES = 1000000
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
-- Store blast resistance values by content ids to improve performance.
|
||||
for name, def in pairs(minetest.registered_nodes) do
|
||||
|
@ -124,7 +128,7 @@ local function add_particles(pos, radius)
|
|||
maxexptime = 1.0,
|
||||
minsize = radius * 0.5,
|
||||
maxsize = radius * 1.0,
|
||||
texture = "tnt_smoke.png",
|
||||
texture = "mcl_particles_smoke.png",
|
||||
})
|
||||
end
|
||||
|
||||
|
@ -135,14 +139,21 @@ end
|
|||
-- strength - The strength of each ray
|
||||
-- raydirs - The directions for each ray
|
||||
-- radius - The maximum distance each ray will go
|
||||
-- drop_chance - The chance that destroyed nodes will drop their items
|
||||
-- fire - If true, 1/3 of destroyed nodes become fire
|
||||
-- info - Table containing information about explosion
|
||||
-- puncher - object that punches other objects (optional)
|
||||
--
|
||||
-- Values in info:
|
||||
-- drop_chance - The chance that destroyed nodes will drop their items
|
||||
-- fire - If true, 1/3 nodes become fire
|
||||
-- griefing - If true, the explosion will destroy nodes (default: true)
|
||||
-- max_blast_resistance - The explosion will treat all non-indestructible nodes
|
||||
-- as having a blast resistance of no more than this
|
||||
-- value
|
||||
--
|
||||
-- Note that this function has been optimized, it contains code which has been
|
||||
-- inlined to avoid function calls and unnecessary table creation. This was
|
||||
-- measured to give a significant performance increase.
|
||||
local function trace_explode(pos, strength, raydirs, radius, drop_chance, fire, puncher, creative_enabled)
|
||||
local function trace_explode(pos, strength, raydirs, radius, info, puncher)
|
||||
local vm = minetest.get_voxel_manip()
|
||||
|
||||
local emin, emax = vm:read_from_map(vector.subtract(pos, radius),
|
||||
|
@ -164,39 +175,49 @@ local function trace_explode(pos, strength, raydirs, radius, drop_chance, fire,
|
|||
local data = vm:get_data()
|
||||
local destroy = {}
|
||||
|
||||
local drop_chance = info.drop_chance
|
||||
local fire = info.fire
|
||||
local max_blast_resistance = info.max_blast_resistance
|
||||
|
||||
-- Trace rays for environment destruction
|
||||
for i = 1, #raydirs do
|
||||
local rpos_x = pos.x
|
||||
local rpos_y = pos.y
|
||||
local rpos_z = pos.z
|
||||
local rdir_x = raydirs[i].x
|
||||
local rdir_y = raydirs[i].y
|
||||
local rdir_z = raydirs[i].z
|
||||
local rstr = (0.7 + math.random() * 0.6) * strength
|
||||
if info.griefing then
|
||||
for i = 1, #raydirs do
|
||||
local rpos_x = pos.x
|
||||
local rpos_y = pos.y
|
||||
local rpos_z = pos.z
|
||||
local rdir_x = raydirs[i].x
|
||||
local rdir_y = raydirs[i].y
|
||||
local rdir_z = raydirs[i].z
|
||||
local rstr = (0.7 + math.random() * 0.6) * strength
|
||||
|
||||
for r = 0, math.ceil(radius * (1.0 / STEP_LENGTH)) do
|
||||
local npos_x = math.floor(rpos_x + 0.5)
|
||||
local npos_y = math.floor(rpos_y + 0.5)
|
||||
local npos_z = math.floor(rpos_z + 0.5)
|
||||
local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride +
|
||||
npos_x - emin_x + 1
|
||||
for r = 0, math.ceil(radius * (1.0 / STEP_LENGTH)) do
|
||||
local npos_x = math.floor(rpos_x + 0.5)
|
||||
local npos_y = math.floor(rpos_y + 0.5)
|
||||
local npos_z = math.floor(rpos_z + 0.5)
|
||||
local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride +
|
||||
npos_x - emin_x + 1
|
||||
|
||||
local cid = data[idx]
|
||||
local br = node_blastres[cid]
|
||||
local hash = minetest.hash_node_position({x=npos_x, y=npos_y, z=npos_z})
|
||||
local cid = data[idx]
|
||||
local br = node_blastres[cid]
|
||||
if br < INDESTRUCT_BLASTRES and br > max_blast_resistance then
|
||||
br = max_blast_resistance
|
||||
end
|
||||
|
||||
rpos_x = rpos_x + STEP_LENGTH * rdir_x
|
||||
rpos_y = rpos_y + STEP_LENGTH * rdir_y
|
||||
rpos_z = rpos_z + STEP_LENGTH * rdir_z
|
||||
local hash = minetest.hash_node_position({x=npos_x, y=npos_y, z=npos_z})
|
||||
|
||||
rstr = rstr - 0.75 * STEP_LENGTH - (br + 0.3) * STEP_LENGTH
|
||||
rpos_x = rpos_x + STEP_LENGTH * rdir_x
|
||||
rpos_y = rpos_y + STEP_LENGTH * rdir_y
|
||||
rpos_z = rpos_z + STEP_LENGTH * rdir_z
|
||||
|
||||
if rstr <= 0 then
|
||||
break
|
||||
end
|
||||
rstr = rstr - 0.75 * STEP_LENGTH - (br + 0.3) * STEP_LENGTH
|
||||
|
||||
if cid ~= minetest.CONTENT_AIR then
|
||||
destroy[hash] = idx
|
||||
if rstr <= 0 then
|
||||
break
|
||||
end
|
||||
|
||||
if cid ~= minetest.CONTENT_AIR and not minetest.is_protected({x = npos_x, y = npos_y, z = npos_z}, "") then
|
||||
destroy[hash] = idx
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -234,9 +255,9 @@ local function trace_explode(pos, strength, raydirs, radius, drop_chance, fire,
|
|||
local z_len = math.abs(z2 - z1)
|
||||
|
||||
-- Move object position to the center of its bounding box
|
||||
opos.x = opos.x + x1 + x2
|
||||
opos.y = opos.y + y1 + y2
|
||||
opos.z = opos.z + z1 + z2
|
||||
opos.x = opos.x + 0.5 * (x1 + x2)
|
||||
opos.y = opos.y + 0.5 * (y1 + y2)
|
||||
opos.z = opos.z + 0.5 * (z1 + z2)
|
||||
|
||||
-- Count number of rays from collision box which are unobstructed
|
||||
local count = N_EXPOSURE_RAYS
|
||||
|
@ -284,20 +305,40 @@ local function trace_explode(pos, strength, raydirs, radius, drop_chance, fire,
|
|||
impact = 0
|
||||
end
|
||||
local damage = math.floor((impact * impact + impact) * 7 * strength + 1)
|
||||
if mod_death_messages and obj:is_player() then
|
||||
mcl_death_messages.player_damage(obj, S("@1 was caught in an explosion.", obj:get_player_name()))
|
||||
end
|
||||
local source = puncher
|
||||
if not source then
|
||||
source = obj
|
||||
end
|
||||
obj:punch(source, 10, { damage_groups = { full_punch_interval = 1,
|
||||
fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
|
||||
local source = puncher or obj
|
||||
|
||||
local sleep_formspec_doesnt_close_mt53 = false
|
||||
if obj:is_player() then
|
||||
obj:add_player_velocity(vector.multiply(punch_dir, impact * 20))
|
||||
elseif ent.tnt_knockback then
|
||||
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
|
||||
local name = obj:get_player_name()
|
||||
if mcl_beds then
|
||||
local meta = obj:get_meta()
|
||||
if meta:get_string("mcl_beds:sleeping") == "true" then
|
||||
minetest.close_formspec(name, "") -- ABSOLUTELY NECESSARY FOR MT5.3 -- TODO: REMOVE THIS IN THE FUTURE
|
||||
sleep_formspec_doesnt_close_mt53 = true
|
||||
end
|
||||
end
|
||||
if mod_death_messages then
|
||||
mcl_death_messages.player_damage(obj, S("@1 was caught in an explosion.", name))
|
||||
end
|
||||
if rawget(_G, "armor") and armor.last_damage_types then
|
||||
armor.last_damage_types[name] = "explosion"
|
||||
end
|
||||
end
|
||||
|
||||
if sleep_formspec_doesnt_close_mt53 then
|
||||
minetest.after(0.3, function(obj, damage, impact, punch_dir) -- 0.2 is minimum delay for closing old formspec and open died formspec -- TODO: REMOVE THIS IN THE FUTURE
|
||||
if not obj then return end
|
||||
obj:punch(obj, 10, { damage_groups = { full_punch_interval = 1, fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
|
||||
obj:add_player_velocity(vector.multiply(punch_dir, impact * 20))
|
||||
end, obj, damage, impact, vector.new(punch_dir))
|
||||
else
|
||||
obj:punch(source, 10, { damage_groups = { full_punch_interval = 1, fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
|
||||
|
||||
if obj:is_player() then
|
||||
obj:add_player_velocity(vector.multiply(punch_dir, impact * 20))
|
||||
elseif ent.tnt_knockback then
|
||||
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -307,14 +348,14 @@ local function trace_explode(pos, strength, raydirs, radius, drop_chance, fire,
|
|||
|
||||
-- Remove destroyed blocks and drop items
|
||||
for hash, idx in pairs(destroy) do
|
||||
local do_drop = not creative_enabled and math.random() <= drop_chance
|
||||
local do_drop = math.random() <= drop_chance
|
||||
local on_blast = node_on_blast[data[idx]]
|
||||
local remove = true
|
||||
|
||||
if do_drop or on_blast ~= nil then
|
||||
local npos = minetest.get_position_from_hash(hash)
|
||||
if on_blast ~= nil then
|
||||
on_blast(npos, 1.0)
|
||||
on_blast(npos, 1.0, do_drop)
|
||||
remove = false
|
||||
else
|
||||
local name = minetest.get_name_from_content_id(data[idx])
|
||||
|
@ -357,7 +398,6 @@ local function trace_explode(pos, strength, raydirs, radius, drop_chance, fire,
|
|||
-- Log explosion
|
||||
minetest.log('action', 'Explosion at ' .. minetest.pos_to_string(pos) ..
|
||||
' with strength ' .. strength .. ' and radius ' .. radius)
|
||||
|
||||
end
|
||||
|
||||
-- Create an explosion with strength at pos.
|
||||
|
@ -365,16 +405,24 @@ end
|
|||
-- Parameters:
|
||||
-- pos - The position where the explosion originates from
|
||||
-- strength - The blast strength of the explosion (a TNT explosion uses 4)
|
||||
-- info - Table containing information about explosion.
|
||||
-- info - Table containing information about explosion
|
||||
-- puncher - object that is reported as source of punches/damage (optional)
|
||||
--
|
||||
-- Values in info:
|
||||
-- drop_chance - If specified becomes the drop chance of all nodes in the
|
||||
-- explosion (defaults to 1.0 / strength)
|
||||
-- no_sound - If true then the explosion will not play a sound
|
||||
-- no_particle - If true then the explosion will not create particles
|
||||
-- explosion (default: 1.0 / strength)
|
||||
-- max_blast_resistance - If specified the explosion will treat all
|
||||
-- non-indestructible nodes as having a blast resistance
|
||||
-- of no more than this value
|
||||
-- sound - If true, the explosion will play a sound (default: true)
|
||||
-- particles - If true, the explosion will create particles (default: true)
|
||||
-- fire - If true, 1/3 nodes become fire (default: false)
|
||||
-- griefing - If true, the explosion will destroy nodes (default: true)
|
||||
function mcl_explosions.explode(pos, strength, info, puncher)
|
||||
if info == nil then
|
||||
info = {}
|
||||
end
|
||||
|
||||
-- The maximum blast radius (in the air)
|
||||
local radius = math.ceil(1.3 * strength / (0.3 * 0.75) * 0.3)
|
||||
|
||||
|
@ -383,13 +431,27 @@ function mcl_explosions.explode(pos, strength, info, puncher)
|
|||
end
|
||||
local shape = sphere_shapes[radius]
|
||||
|
||||
local creative_enabled = minetest.is_creative_enabled("")
|
||||
trace_explode(pos, strength, shape, radius, (info and info.drop_chance) or 1 / strength, info.fire == true, puncher, creative_enabled)
|
||||
-- Default values
|
||||
if info.drop_chance == nil then info.drop_chance = 1 / strength end
|
||||
if info.particles == nil then info.particles = true end
|
||||
if info.sound == nil then info.sound = true end
|
||||
if info.fire == nil then info.fire = false end
|
||||
if info.griefing == nil then info.griefing = true end
|
||||
if info.max_blast_resistance == nil then
|
||||
info.max_blast_resistance = INDESTRUCT_BLASTRES
|
||||
end
|
||||
|
||||
if not (info and info.no_sound) then
|
||||
-- Dont do drops in creative mode
|
||||
if minetest.is_creative_enabled("") then
|
||||
info.drop_chance = 0
|
||||
end
|
||||
|
||||
trace_explode(pos, strength, shape, radius, info, puncher)
|
||||
|
||||
if info.particles then
|
||||
add_particles(pos, radius)
|
||||
end
|
||||
if not (info and info.no_particle) then
|
||||
if info.sound then
|
||||
minetest.sound_play("tnt_explode", {
|
||||
pos = pos, gain = 1.0,
|
||||
max_hear_distance = strength * 16
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
# textdomain:mcl_explosions
|
||||
@1 was caught in an explosion.=@1 a été pris dans une explosion.
|
|
@ -0,0 +1,2 @@
|
|||
# textdomain:mcl_explosions
|
||||
@1 was caught in an explosion.=@1 не удалось пережить взрыва.
|
|
@ -1,3 +1,4 @@
|
|||
name = mcl_explosions
|
||||
description = A common API to create explosions.
|
||||
depends = mcl_particles
|
||||
optional_depends = mcl_fire
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
-- Some global variables (don't overwrite them!)
|
||||
mcl_vars = {}
|
||||
|
||||
mcl_vars.redstone_tick = 0.1
|
||||
|
||||
--- GUI / inventory menu settings
|
||||
mcl_vars.gui_slots = "listcolors[#9990;#FFF7;#FFF0;#000;#FFF]"
|
||||
-- nonbg is added as formspec prepend in mcl_formspec_prepend
|
||||
|
@ -23,8 +25,64 @@ mcl_vars.inventory_header = ""
|
|||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||
local minecraft_height_limit = 256
|
||||
local superflat = mg_name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true"
|
||||
local singlenode = mg_name == "singlenode"
|
||||
|
||||
if not superflat then
|
||||
-- Calculate mapgen_edge_min/mapgen_edge_max
|
||||
mcl_vars.chunksize = math.max(1, tonumber(minetest.get_mapgen_setting("chunksize")) or 5)
|
||||
mcl_vars.MAP_BLOCKSIZE = math.max(1, core.MAP_BLOCKSIZE or 16)
|
||||
mcl_vars.mapgen_limit = math.max(1, tonumber(minetest.get_mapgen_setting("mapgen_limit")) or 31000)
|
||||
mcl_vars.MAX_MAP_GENERATION_LIMIT = math.max(1, core.MAX_MAP_GENERATION_LIMIT or 31000)
|
||||
local central_chunk_offset = -math.floor(mcl_vars.chunksize / 2)
|
||||
local chunk_size_in_nodes = mcl_vars.chunksize * mcl_vars.MAP_BLOCKSIZE
|
||||
local central_chunk_min_pos = central_chunk_offset * mcl_vars.MAP_BLOCKSIZE
|
||||
local central_chunk_max_pos = central_chunk_min_pos + chunk_size_in_nodes - 1
|
||||
local ccfmin = central_chunk_min_pos - mcl_vars.MAP_BLOCKSIZE -- Fullminp/fullmaxp of central chunk, in nodes
|
||||
local ccfmax = central_chunk_max_pos + mcl_vars.MAP_BLOCKSIZE
|
||||
local mapgen_limit_b = math.floor(math.min(mcl_vars.mapgen_limit, mcl_vars.MAX_MAP_GENERATION_LIMIT) / mcl_vars.MAP_BLOCKSIZE)
|
||||
local mapgen_limit_min = -mapgen_limit_b * mcl_vars.MAP_BLOCKSIZE
|
||||
local mapgen_limit_max = (mapgen_limit_b + 1) * mcl_vars.MAP_BLOCKSIZE - 1
|
||||
local numcmin = math.max(math.floor((ccfmin - mapgen_limit_min) / chunk_size_in_nodes), 0) -- Number of complete chunks from central chunk
|
||||
local numcmax = math.max(math.floor((mapgen_limit_max - ccfmax) / chunk_size_in_nodes), 0) -- fullminp/fullmaxp to effective mapgen limits.
|
||||
mcl_vars.mapgen_edge_min = central_chunk_min_pos - numcmin * chunk_size_in_nodes
|
||||
mcl_vars.mapgen_edge_max = central_chunk_max_pos + numcmax * chunk_size_in_nodes
|
||||
|
||||
local function coordinate_to_block(x)
|
||||
return math.floor(x / mcl_vars.MAP_BLOCKSIZE)
|
||||
end
|
||||
|
||||
local function coordinate_to_chunk(x)
|
||||
return math.floor((coordinate_to_block(x) + central_chunk_offset) / mcl_vars.chunksize)
|
||||
end
|
||||
|
||||
function mcl_vars.pos_to_block(pos)
|
||||
return {
|
||||
x = coordinate_to_block(pos.x),
|
||||
y = coordinate_to_block(pos.y),
|
||||
z = coordinate_to_block(pos.z)
|
||||
}
|
||||
end
|
||||
|
||||
function mcl_vars.pos_to_chunk(pos)
|
||||
return {
|
||||
x = coordinate_to_chunk(pos.x),
|
||||
y = coordinate_to_chunk(pos.y),
|
||||
z = coordinate_to_chunk(pos.z)
|
||||
}
|
||||
end
|
||||
|
||||
local k_positive = math.ceil(mcl_vars.MAX_MAP_GENERATION_LIMIT / chunk_size_in_nodes)
|
||||
local k_positive_z = k_positive * 2
|
||||
local k_positive_y = k_positive_z * k_positive_z
|
||||
|
||||
function mcl_vars.get_chunk_number(pos) -- unsigned int
|
||||
local c = mcl_vars.pos_to_chunk(pos)
|
||||
return
|
||||
(c.y + k_positive) * k_positive_y +
|
||||
(c.z + k_positive) * k_positive_z +
|
||||
c.x + k_positive
|
||||
end
|
||||
|
||||
if not superflat and not singlenode then
|
||||
-- Normal mode
|
||||
--[[ Realm stacking (h is for height)
|
||||
- Overworld (h>=256)
|
||||
|
@ -45,6 +103,14 @@ if not superflat then
|
|||
mcl_vars.mg_lava = true
|
||||
mcl_vars.mg_bedrock_is_rough = true
|
||||
|
||||
elseif singlenode then
|
||||
mcl_vars.mg_overworld_min = -66
|
||||
mcl_vars.mg_overworld_max_official = mcl_vars.mg_overworld_min + minecraft_height_limit
|
||||
mcl_vars.mg_bedrock_overworld_min = mcl_vars.mg_overworld_min
|
||||
mcl_vars.mg_bedrock_overworld_max = mcl_vars.mg_bedrock_overworld_min
|
||||
mcl_vars.mg_lava = false
|
||||
mcl_vars.mg_lava_overworld_max = mcl_vars.mg_overworld_min
|
||||
mcl_vars.mg_bedrock_is_rough = false
|
||||
else
|
||||
-- Classic superflat
|
||||
local ground = minetest.get_mapgen_setting("mgflat_ground_level")
|
||||
|
@ -61,7 +127,7 @@ else
|
|||
mcl_vars.mg_bedrock_is_rough = false
|
||||
end
|
||||
|
||||
mcl_vars.mg_overworld_max = 31000
|
||||
mcl_vars.mg_overworld_max = mcl_vars.mapgen_edge_max
|
||||
|
||||
-- The Nether (around Y = -29000)
|
||||
mcl_vars.mg_nether_min = -29067 -- Carefully chosen to be at a mapchunk border
|
||||
|
@ -108,4 +174,3 @@ minetest.craftitemdef_default.stack_max = 64
|
|||
-- Set random seed for all other mods (Remember to make sure no other mod calls this function)
|
||||
math.randomseed(os.time())
|
||||
|
||||
|
||||
|
|
|
@ -11,12 +11,15 @@ Parameters:
|
|||
stacks_max = 3, -- Maximum number of item stacks to get. Default: 1
|
||||
items = { -- Table of possible loot items. This function selects between stacks_min and stacks_max of these.
|
||||
{
|
||||
weight = 5, -- Likelihood of this item being selected (see below). Optional (default: 1)
|
||||
|
||||
itemstack = ItemStack("example:item1"), -- Itemstack to select
|
||||
-- OR
|
||||
itemstring = "example:item1", -- Which item to select
|
||||
amount_min = 1, -- Minimum size of itemstack. Must not be larger than 6553. Optional (default: 1)
|
||||
amount_max = 10, -- Maximum size of item stack. Must not be larger than item definition's stack_max or 6553. Optional (default: 1)
|
||||
wear_min = 1, -- Minimum wear value. Must be at least 1. Optional (default: no wear)
|
||||
wear_max = 1, -- Maxiumum wear value. Must be at least 1. Optional (default: no wear)
|
||||
weight = 5, -- Likelihood of this item being selected (see below). Optional (default: 1)
|
||||
},
|
||||
{ -- more tables like above, one table per item stack }
|
||||
}
|
||||
|
@ -56,24 +59,29 @@ function mcl_loot.get_loot(loot_definitions, pr)
|
|||
end
|
||||
if item then
|
||||
local itemstring = item.itemstring
|
||||
if item.amount_min and item.amount_max then
|
||||
itemstring = itemstring .. " " .. pr:next(item.amount_min, item.amount_max)
|
||||
end
|
||||
if item.wear_min and item.wear_max then
|
||||
-- Sadly, PseudoRandom only allows very narrow ranges, so we set wear in steps of 10
|
||||
local wear_min = math.floor(item.wear_min / 10)
|
||||
local wear_max = math.floor(item.wear_max / 10)
|
||||
local wear = pr:next(wear_min, wear_max) * 10
|
||||
|
||||
if not item.amount_min and not item.amount_max then
|
||||
itemstring = itemstring .. " 1"
|
||||
local itemstack = item.itemstack
|
||||
if itemstring then
|
||||
if item.amount_min and item.amount_max then
|
||||
itemstring = itemstring .. " " .. pr:next(item.amount_min, item.amount_max)
|
||||
end
|
||||
if item.wear_min and item.wear_max then
|
||||
-- Sadly, PseudoRandom only allows very narrow ranges, so we set wear in steps of 10
|
||||
local wear_min = math.floor(item.wear_min / 10)
|
||||
local wear_max = math.floor(item.wear_max / 10)
|
||||
local wear = pr:next(wear_min, wear_max) * 10
|
||||
|
||||
itemstring = itemstring .. " " .. tostring(wear)
|
||||
if not item.amount_min and not item.amount_max then
|
||||
itemstring = itemstring .. " 1"
|
||||
end
|
||||
|
||||
itemstring = itemstring .. " " .. tostring(wear)
|
||||
end
|
||||
table.insert(items, itemstring)
|
||||
elseif itemstack then
|
||||
table.insert(items, itemstack)
|
||||
else
|
||||
minetest.log("error", "[mcl_loot] INTERNAL ERROR! Failed to select random loot item!")
|
||||
end
|
||||
table.insert(items, itemstring)
|
||||
else
|
||||
minetest.log("error", "[mcl_loot] INTERNAL ERROR! Failed to select random loot item!")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -103,14 +111,14 @@ end
|
|||
Returns a table of length `max_slot` and all natural numbers between 1 and `max_slot`
|
||||
in a random order.
|
||||
]]
|
||||
local function get_random_slots(max_slot)
|
||||
local function get_random_slots(max_slot, pr)
|
||||
local slots = {}
|
||||
for s=1, max_slot do
|
||||
slots[s] = s
|
||||
end
|
||||
local slots_out = {}
|
||||
while #slots > 0 do
|
||||
local r = math.random(1, #slots)
|
||||
local r = pr and pr:next(1, #slots) or math.random(1, #slots)
|
||||
table.insert(slots_out, slots[r])
|
||||
table.remove(slots, r)
|
||||
end
|
||||
|
@ -127,9 +135,9 @@ Items will be added from start of the table to end.
|
|||
If the inventory already has occupied slots, or is
|
||||
too small, placement of some items might fail.
|
||||
]]
|
||||
function mcl_loot.fill_inventory(inv, listname, items)
|
||||
function mcl_loot.fill_inventory(inv, listname, items, pr)
|
||||
local size = inv:get_size(listname)
|
||||
local slots = get_random_slots(size)
|
||||
local slots = get_random_slots(size, pr)
|
||||
local leftovers = {}
|
||||
-- 1st pass: Add items into random slots
|
||||
for i=1, math.min(#items, size) do
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
mcl_particles = {}
|
||||
|
||||
-- Table of particlespawner IDs on a per-node hash basis
|
||||
-- Keys: node position hashes
|
||||
-- Values: Tables of particlespawner IDs (each node pos can have an arbitrary number of particlespawners)
|
||||
local particle_nodes = {}
|
||||
|
||||
-- Node particles can be disabled via setting
|
||||
local node_particles_allowed = minetest.settings:get("mcl_node_particles") or "none"
|
||||
|
||||
local levels = {
|
||||
high = 3,
|
||||
medium = 2,
|
||||
low = 1,
|
||||
none = 0,
|
||||
}
|
||||
|
||||
allowed_level = levels[node_particles_allowed]
|
||||
if not allowed_level then
|
||||
allowed_level = levels["none"]
|
||||
end
|
||||
|
||||
|
||||
-- Add a particlespawner that is assigned to a given node position.
|
||||
-- * pos: Node positon. MUST use integer values!
|
||||
-- * particlespawner_definition: definition for minetest.add_particlespawner
|
||||
-- * level: detail level of particles. "high", "medium", "low" or "none". High detail levels are for
|
||||
-- CPU-demanding particles, like smoke of fire (which occurs frequently)
|
||||
-- NOTE: All particlespawners are automatically removed on shutdown.
|
||||
-- Returns particlespawner ID on succcess and nil on failure
|
||||
function mcl_particles.add_node_particlespawner(pos, particlespawner_definition, level)
|
||||
if allowed_level == 0 or levels[level] > allowed_level then
|
||||
return
|
||||
end
|
||||
local poshash = minetest.hash_node_position(pos)
|
||||
if not poshash then
|
||||
return
|
||||
end
|
||||
local id = minetest.add_particlespawner(particlespawner_definition)
|
||||
if id == -1 then
|
||||
return
|
||||
end
|
||||
if not particle_nodes[poshash] then
|
||||
particle_nodes[poshash] = {}
|
||||
end
|
||||
table.insert(particle_nodes[poshash], id)
|
||||
return id
|
||||
end
|
||||
|
||||
-- Deletes all particlespawners that are assigned to a node position.
|
||||
-- If no particlespawners exist for this position, nothing happens.
|
||||
-- pos: Node positon. MUST use integer values!
|
||||
-- Returns true if particlespawner could be removed and false if not
|
||||
function mcl_particles.delete_node_particlespawners(pos)
|
||||
if allowed_level == 0 then
|
||||
return false
|
||||
end
|
||||
local poshash = minetest.hash_node_position(pos)
|
||||
local ids = particle_nodes[poshash]
|
||||
if ids then
|
||||
for i=1, #ids do
|
||||
minetest.delete_particlespawner(ids[i])
|
||||
end
|
||||
particle_nodes[poshash] = nil
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
Before Width: | Height: | Size: 938 B After Width: | Height: | Size: 126 B |
After Width: | Height: | Size: 127 B |
After Width: | Height: | Size: 91 B |
After Width: | Height: | Size: 137 B |
After Width: | Height: | Size: 145 B |
After Width: | Height: | Size: 125 B |
After Width: | Height: | Size: 183 B |
After Width: | Height: | Size: 262 B |
After Width: | Height: | Size: 126 B |
After Width: | Height: | Size: 126 B |
After Width: | Height: | Size: 216 B |
|
@ -114,9 +114,9 @@ end
|
|||
function mcl_sounds.node_sound_leaves_defaults(table)
|
||||
table = table or {}
|
||||
table.footstep = table.footstep or
|
||||
{name="default_grass_footstep", gain=0.35}
|
||||
{name="default_grass_footstep", gain=0.1325}
|
||||
table.dug = table.dug or
|
||||
{name="default_grass_footstep", gain=0.85}
|
||||
{name="default_grass_footstep", gain=0.425}
|
||||
table.dig = table.dig or
|
||||
{name="default_dig_snappy", gain=0.4}
|
||||
table.place = table.place or
|
||||
|
|
|
@ -395,4 +395,13 @@ function mcl_util.generate_on_place_plant_function(condition)
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
-- adjust the y level of an object to the center of its collisionbox
|
||||
-- used to get the origin position of entity explosions
|
||||
function mcl_util.get_object_center(obj)
|
||||
local collisionbox = obj:get_properties().collisionbox
|
||||
local pos = obj:get_pos()
|
||||
local ymin = collisionbox[2]
|
||||
local ymax = collisionbox[5]
|
||||
pos.y = pos.y + (ymax - ymin) / 2.0
|
||||
return pos
|
||||
end
|
||||
|
|
|
@ -70,6 +70,12 @@ function mcl_worlds.has_weather(pos)
|
|||
return pos.y <= mcl_vars.mg_overworld_max and pos.y >= mcl_vars.mg_overworld_min - 64
|
||||
end
|
||||
|
||||
-- Takes a position and returns true if this position can have Nether dust
|
||||
function mcl_worlds.has_dust(pos)
|
||||
-- Weather in the Overworld and the high part of the void below
|
||||
return pos.y <= mcl_vars.mg_nether_max + 64 and pos.y >= mcl_vars.mg_nether_min - 64
|
||||
end
|
||||
|
||||
-- Takes a position (pos) and returns true if compasses are working here
|
||||
function mcl_worlds.compass_works(pos)
|
||||
-- It doesn't work in Nether and the End, but it works in the Overworld and in the high part of the void below
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
-- register extra flavours of a base nodedef
|
||||
walkover = {}
|
||||
walkover.registered_globals = {}
|
||||
|
||||
function walkover.register_global(func)
|
||||
table.insert(walkover.registered_globals, func)
|
||||
end
|
||||
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
timer = timer + dtime;
|
||||
|
@ -10,11 +17,15 @@ minetest.register_globalstep(function(dtime)
|
|||
if loc ~= nil then
|
||||
|
||||
local nodeiamon = minetest.get_node(loc)
|
||||
|
||||
if nodeiamon ~= nil then
|
||||
local def = minetest.registered_nodes[nodeiamon.name]
|
||||
if def ~= nil and def.on_walk_over ~= nil then
|
||||
def.on_walk_over(loc, nodeiamon, player)
|
||||
end
|
||||
for _, func in ipairs(walkover.registered_globals) do
|
||||
func(loc, nodeiamon, player)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,13 +1,24 @@
|
|||
local S = minetest.get_translator("mcl_boats")
|
||||
--
|
||||
-- Helper functions
|
||||
--
|
||||
|
||||
local function is_water(pos)
|
||||
local boat_visual_size = {x = 3, y = 3, z = 3}
|
||||
local paddling_speed = 22
|
||||
local boat_y_offset = 0.35
|
||||
local boat_y_offset_ground = boat_y_offset + 0.6
|
||||
local boat_side_offset = 1.001
|
||||
local boat_max_hp = 4
|
||||
|
||||
local function is_group(pos, group)
|
||||
local nn = minetest.get_node(pos).name
|
||||
return minetest.get_item_group(nn, "water") ~= 0
|
||||
return minetest.get_item_group(nn, group) ~= 0
|
||||
end
|
||||
|
||||
local function is_water(pos)
|
||||
return is_group(pos, "water")
|
||||
end
|
||||
|
||||
local function is_ice(pos)
|
||||
return is_group(pos, "ice")
|
||||
end
|
||||
|
||||
local function get_sign(i)
|
||||
if i == 0 then
|
||||
|
@ -17,25 +28,83 @@ local function get_sign(i)
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
local function get_v(v)
|
||||
return math.sqrt(v.x ^ 2 + v.z ^ 2)
|
||||
end
|
||||
|
||||
local boat_visual_size = {x = 3, y = 3}
|
||||
-- Note: This mod assumes the default player visual_size is {x=1, y=1}
|
||||
local driver_visual_size = { x = 1/boat_visual_size.x, y = 1/boat_visual_size.y }
|
||||
local paddling_speed = 22
|
||||
local boat_y_offset = 0.35
|
||||
local boat_y_offset_ground = boat_y_offset + 0.6
|
||||
local boat_side_offset = 1.001
|
||||
local function check_object(obj)
|
||||
return obj and (obj:is_player() or obj:get_luaentity()) and obj
|
||||
end
|
||||
|
||||
local function get_visual_size(obj)
|
||||
return obj:is_player() and {x = 1, y = 1, z = 1} or obj:get_luaentity()._old_visual_size or obj:get_properties().visual_size
|
||||
end
|
||||
|
||||
local function set_attach(boat)
|
||||
boat._driver:set_attach(boat.object, "",
|
||||
{x = 0, y = 0.42, z = -1}, {x = 0, y = 0, z = 0})
|
||||
end
|
||||
|
||||
local function set_double_attach(boat)
|
||||
boat._driver:set_attach(boat.object, "",
|
||||
{x = 0, y = 0.42, z = 0.8}, {x = 0, y = 0, z = 0})
|
||||
boat._passenger:set_attach(boat.object, "",
|
||||
{x = 0, y = 0.42, z = -2.2}, {x = 0, y = 0, z = 0})
|
||||
end
|
||||
|
||||
local function attach_object(self, obj)
|
||||
if self._driver then
|
||||
if self._driver:is_player() then
|
||||
self._passenger = obj
|
||||
else
|
||||
self._passenger = self._driver
|
||||
self._driver = obj
|
||||
end
|
||||
set_double_attach(self)
|
||||
else
|
||||
self._driver = obj
|
||||
set_attach(self)
|
||||
end
|
||||
|
||||
local visual_size = get_visual_size(obj)
|
||||
local yaw = self.object:get_yaw()
|
||||
obj:set_properties({visual_size = vector.divide(visual_size, boat_visual_size)})
|
||||
|
||||
if obj:is_player() then
|
||||
local name = obj:get_player_name()
|
||||
mcl_player.player_attached[name] = true
|
||||
minetest.after(0.2, function(name)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
mcl_player.player_set_animation(player, "sit" , 30)
|
||||
end
|
||||
end, name)
|
||||
obj:set_look_horizontal(yaw)
|
||||
mcl_tmp_message.message(obj, S("Sneak to dismount"))
|
||||
else
|
||||
obj:get_luaentity()._old_visual_size = visual_size
|
||||
end
|
||||
end
|
||||
|
||||
local function detach_object(obj, change_pos)
|
||||
obj:set_detach()
|
||||
obj:set_properties({visual_size = get_visual_size(obj)})
|
||||
if obj:is_player() then
|
||||
mcl_player.player_attached[obj:get_player_name()] = false
|
||||
mcl_player.player_set_animation(obj, "stand" , 30)
|
||||
else
|
||||
obj:get_luaentity()._old_visual_size = nil
|
||||
end
|
||||
if change_pos then
|
||||
obj:set_pos(vector.add(obj:get_pos(), vector.new(0, 0.2, 0)))
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Boat entity
|
||||
|
@ -50,67 +119,41 @@ local boat = {
|
|||
mesh = "mcl_boats_boat.b3d",
|
||||
textures = {"mcl_boats_texture_oak_boat.png"},
|
||||
visual_size = boat_visual_size,
|
||||
hp_max = boat_max_hp,
|
||||
damage_texture_modifier = "^[colorize:white:0",
|
||||
|
||||
_driver = nil, -- Attached driver (player) or nil if none
|
||||
_passenger = nil,
|
||||
_v = 0, -- Speed
|
||||
_last_v = 0, -- Temporary speed variable
|
||||
_removed = false, -- If true, boat entity is considered removed (e.g. after punch) and should be ignored
|
||||
_itemstring = "mcl_boats:boat", -- Itemstring of the boat item (implies boat type)
|
||||
_animation = 0, -- 0: not animated; 1: paddling forwards; -1: paddling forwards
|
||||
_regen_timer = 0,
|
||||
_damage_anim = 0,
|
||||
}
|
||||
|
||||
minetest.register_on_respawnplayer(detach_object)
|
||||
|
||||
function boat.on_rightclick(self, clicker)
|
||||
if not clicker or not clicker:is_player() then
|
||||
if self._passenger or not clicker or clicker:get_attach() then
|
||||
return
|
||||
end
|
||||
local name = clicker:get_player_name()
|
||||
if self._driver and clicker == self._driver then
|
||||
self._driver = nil
|
||||
clicker:set_detach()
|
||||
clicker:set_properties({visual_size = {x=1, y=1}})
|
||||
mcl_player.player_attached[name] = false
|
||||
mcl_player.player_set_animation(clicker, "stand" , 30)
|
||||
local pos = clicker:get_pos()
|
||||
pos = {x = pos.x, y = pos.y + 0.2, z = pos.z}
|
||||
clicker:set_pos(pos)
|
||||
elseif not self._driver then
|
||||
local attach = clicker:get_attach()
|
||||
if attach and attach:get_luaentity() then
|
||||
local luaentity = attach:get_luaentity()
|
||||
if luaentity._driver then
|
||||
luaentity._driver = nil
|
||||
end
|
||||
clicker:set_detach()
|
||||
clicker:set_properties({visual_size = {x=1, y=1}})
|
||||
end
|
||||
self._driver = clicker
|
||||
clicker:set_attach(self.object, "",
|
||||
{x = 0, y = 0.42, z = -1}, {x = 0, y = 0, z = 0})
|
||||
clicker:set_properties({ visual_size = driver_visual_size })
|
||||
mcl_player.player_attached[name] = true
|
||||
minetest.after(0.2, function(name)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
mcl_player.player_set_animation(player, "sit" , 30)
|
||||
end
|
||||
end, name)
|
||||
clicker:set_look_horizontal(self.object:get_yaw())
|
||||
end
|
||||
attach_object(self, clicker)
|
||||
end
|
||||
|
||||
|
||||
function boat.on_activate(self, staticdata, dtime_s)
|
||||
self.object:set_armor_groups({immortal = 1})
|
||||
self.object:set_armor_groups({fleshy = 100})
|
||||
local data = minetest.deserialize(staticdata)
|
||||
if type(data) == "table" then
|
||||
self._v = data.v
|
||||
self._last_v = self._v
|
||||
self._itemstring = data.itemstring
|
||||
self.object:set_properties({textures=data.textures})
|
||||
self.object:set_properties({textures = data.textures})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function boat.get_staticdata(self)
|
||||
return minetest.serialize({
|
||||
v = self._v,
|
||||
|
@ -119,52 +162,104 @@ function boat.get_staticdata(self)
|
|||
})
|
||||
end
|
||||
|
||||
|
||||
function boat.on_punch(self, puncher)
|
||||
if not puncher or not puncher:is_player() or self._removed then
|
||||
return
|
||||
end
|
||||
if self._driver and puncher == self._driver then
|
||||
self._driver = nil
|
||||
puncher:set_detach()
|
||||
puncher:set_properties({visual_size = {x=1, y=1}})
|
||||
mcl_player.player_attached[puncher:get_player_name()] = false
|
||||
end
|
||||
if not self._driver then
|
||||
self._removed = true
|
||||
-- Drop boat as item on the ground after punching
|
||||
if not minetest.is_creative_enabled(puncher:get_player_name()) then
|
||||
minetest.add_item(self.object:get_pos(), self._itemstring)
|
||||
else
|
||||
local inv = puncher:get_inventory()
|
||||
if not inv:contains_item("main", self._itemstring) then
|
||||
inv:add_item("main", self._itemstring)
|
||||
end
|
||||
function boat.on_death(self, killer)
|
||||
if killer and killer:is_player() and minetest.is_creative_enabled(killer:get_player_name()) then
|
||||
local inv = killer:get_inventory()
|
||||
if not inv:contains_item("main", self._itemstring) then
|
||||
inv:add_item("main", self._itemstring)
|
||||
end
|
||||
self.object:remove()
|
||||
else
|
||||
minetest.add_item(self.object:get_pos(), self._itemstring)
|
||||
end
|
||||
if self._driver then
|
||||
detach_object(self._driver)
|
||||
end
|
||||
if self._passenger then
|
||||
detach_object(self._passenger)
|
||||
end
|
||||
self._driver = nil
|
||||
self._passenger = nil
|
||||
end
|
||||
|
||||
function boat.on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
|
||||
if damage > 0 then
|
||||
self._regen_timer = 0
|
||||
end
|
||||
end
|
||||
|
||||
function boat.on_step(self, dtime)
|
||||
function boat.on_step(self, dtime, moveresult)
|
||||
self._v = get_v(self.object:get_velocity()) * get_sign(self._v)
|
||||
local on_water = true
|
||||
local in_water = false
|
||||
local v_factor = 1
|
||||
local v_slowdown = 0.02
|
||||
local p = self.object:get_pos()
|
||||
if (not is_water({x=p.x, y=p.y-boat_y_offset, z=p.z})) then
|
||||
local on_water = true
|
||||
local on_ice = false
|
||||
local in_water = is_water({x=p.x, y=p.y-boat_y_offset+1, z=p.z})
|
||||
local waterp = {x=p.x, y=p.y-boat_y_offset - 0.1, z=p.z}
|
||||
if not is_water(waterp) then
|
||||
on_water = false
|
||||
if not in_water and is_ice(waterp) then
|
||||
on_ice = true
|
||||
else
|
||||
v_slowdown = 0.04
|
||||
end
|
||||
|
||||
v_factor = 0.5
|
||||
v_slowdown = 0.04
|
||||
elseif (is_water({x=p.x, y=p.y-boat_y_offset+1, z=p.z})) then
|
||||
elseif in_water then
|
||||
on_water = false
|
||||
in_water = true
|
||||
v_factor = 0.75
|
||||
v_slowdown = 0.05
|
||||
end
|
||||
|
||||
local hp = self.object:get_hp()
|
||||
local regen_timer = self._regen_timer + dtime
|
||||
if hp >= boat_max_hp then
|
||||
regen_timer = 0
|
||||
elseif regen_timer >= 0.5 then
|
||||
hp = hp + 1
|
||||
self.object:set_hp(hp)
|
||||
regen_timer = 0
|
||||
end
|
||||
self._regen_timer = regen_timer
|
||||
|
||||
if moveresult and moveresult.collides then
|
||||
for _, collision in ipairs(moveresult.collisions) do
|
||||
local pos = collision.node_pos
|
||||
if collision.type == "node" and minetest.get_item_group(minetest.get_node(pos).name, "dig_by_boat") > 0 then
|
||||
minetest.dig_node(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local had_passenger = self._passenger
|
||||
|
||||
self._driver = check_object(self._driver)
|
||||
self._passenger = check_object(self._passenger)
|
||||
|
||||
if self._passenger then
|
||||
if not self._driver then
|
||||
self._driver = self._passenger
|
||||
self._passenger = nil
|
||||
else
|
||||
local ctrl = self._passenger:get_player_control()
|
||||
if ctrl and ctrl.sneak then
|
||||
detach_player(self._passenger, true)
|
||||
self._passenger = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self._driver then
|
||||
if had_passenger and not self._passenger then
|
||||
set_attach(self)
|
||||
end
|
||||
local ctrl = self._driver:get_player_control()
|
||||
if ctrl and ctrl.sneak then
|
||||
detach_object(self._driver, true)
|
||||
self._driver = nil
|
||||
return
|
||||
end
|
||||
local yaw = self.object:get_yaw()
|
||||
if ctrl.up then
|
||||
-- Forwards
|
||||
|
@ -191,13 +286,13 @@ function boat.on_step(self, dtime)
|
|||
self._animation = 0
|
||||
end
|
||||
end
|
||||
if ctrl.left then
|
||||
if ctrl and ctrl.left then
|
||||
if self._v < 0 then
|
||||
self.object:set_yaw(yaw - (1 + dtime) * 0.03 * v_factor)
|
||||
else
|
||||
self.object:set_yaw(yaw + (1 + dtime) * 0.03 * v_factor)
|
||||
end
|
||||
elseif ctrl.right then
|
||||
elseif ctrl and ctrl.right then
|
||||
if self._v < 0 then
|
||||
self.object:set_yaw(yaw + (1 + dtime) * 0.03 * v_factor)
|
||||
else
|
||||
|
@ -210,11 +305,19 @@ function boat.on_step(self, dtime)
|
|||
self.object:set_animation({x=0, y=40}, 0, 0, true)
|
||||
self._animation = 0
|
||||
end
|
||||
|
||||
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1.3)) do
|
||||
local entity = obj:get_luaentity()
|
||||
if entity and entity._cmi_is_mob then
|
||||
attach_object(self, obj)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
local s = get_sign(self._v)
|
||||
if not on_water and not in_water and math.abs(self._v) > 1.0 then
|
||||
v_slowdown = math.min(math.abs(self._v) - 1.0, v_slowdown * 5)
|
||||
elseif in_water and math.abs(self._v) > 1.5 then
|
||||
if not on_ice and not on_water and not in_water and math.abs(self._v) > 2.0 then
|
||||
v_slowdown = math.min(math.abs(self._v) - 2.0, v_slowdown * 5)
|
||||
elseif not on_ice and in_water and math.abs(self._v) > 1.5 then
|
||||
v_slowdown = math.min(math.abs(self._v) - 1.5, v_slowdown * 5)
|
||||
end
|
||||
self._v = self._v - v_slowdown * s
|
||||
|
@ -225,7 +328,7 @@ function boat.on_step(self, dtime)
|
|||
p.y = p.y - boat_y_offset
|
||||
local new_velo
|
||||
local new_acce = {x = 0, y = 0, z = 0}
|
||||
if not is_water(p) then
|
||||
if not is_water(p) and not on_ice then
|
||||
-- Not on water or inside water: Free fall
|
||||
local nodedef = minetest.registered_nodes[minetest.get_node(p).name]
|
||||
new_acce = {x = 0, y = -9.8, z = 0}
|
||||
|
@ -255,12 +358,17 @@ function boat.on_step(self, dtime)
|
|||
end
|
||||
|
||||
-- Terminal velocity: 8 m/s per axis of travel
|
||||
local terminal_velocity = on_ice and 57.1 or 8.0
|
||||
for _,axis in pairs({"z","y","x"}) do
|
||||
if math.abs(new_velo[axis]) > 8 then
|
||||
new_velo[axis] = 8 * get_sign(new_velo[axis])
|
||||
if math.abs(new_velo[axis]) > terminal_velocity then
|
||||
new_velo[axis] = terminal_velocity * get_sign(new_velo[axis])
|
||||
end
|
||||
end
|
||||
|
||||
local yaw = self.object:get_yaw()
|
||||
local anim = (boat_max_hp - hp - regen_timer * 2) / boat_max_hp * math.pi / 4
|
||||
|
||||
self.object:set_rotation(vector.new(anim, yaw, anim))
|
||||
self.object:set_velocity(new_velo)
|
||||
self.object:set_acceleration(new_acce)
|
||||
end
|
||||
|
|
|
@ -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=Водный транспорт
|
|
@ -0,0 +1,298 @@
|
|||
local S = minetest.get_translator("mcl_burning")
|
||||
|
||||
function mcl_burning.get_default(datatype)
|
||||
local default_table = {string = "", float = 0.0, int = 0, bool = false}
|
||||
return default_table[datatype]
|
||||
end
|
||||
|
||||
function mcl_burning.get(obj, datatype, name)
|
||||
local key
|
||||
if obj:is_player() then
|
||||
local meta = obj:get_meta()
|
||||
return meta["get_" .. datatype](meta, "mcl_burning:" .. name)
|
||||
else
|
||||
local luaentity = obj:get_luaentity()
|
||||
return luaentity and luaentity["mcl_burning_" .. name] or mcl_burning.get_default(datatype)
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.set(obj, datatype, name, value)
|
||||
if obj:is_player() then
|
||||
local meta = obj:get_meta()
|
||||
meta["set_" .. datatype](meta, "mcl_burning:" .. name, value or mcl_burning.get_default(datatype))
|
||||
else
|
||||
local luaentity = obj:get_luaentity()
|
||||
if mcl_burning.get_default(datatype) == value then
|
||||
value = nil
|
||||
end
|
||||
luaentity["mcl_burning_" .. name] = value
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.is_burning(obj)
|
||||
return mcl_burning.get(obj, "float", "burn_time") > 0
|
||||
end
|
||||
|
||||
function mcl_burning.is_affected_by_rain(obj)
|
||||
return mcl_weather.get_weather() == "rain" and mcl_weather.is_outdoor(obj:get_pos())
|
||||
end
|
||||
|
||||
function mcl_burning.get_collisionbox(obj, smaller)
|
||||
local box = obj:get_properties().collisionbox
|
||||
local minp, maxp = vector.new(box[1], box[2], box[3]), vector.new(box[4], box[5], box[6])
|
||||
if smaller then
|
||||
local s_vec = vector.new(0.1, 0.1, 0.1)
|
||||
minp = vector.add(minp, s_vec)
|
||||
maxp = vector.subtract(maxp, s_vec)
|
||||
end
|
||||
return minp, maxp
|
||||
end
|
||||
|
||||
function mcl_burning.get_touching_nodes(obj, nodenames)
|
||||
local pos = obj:get_pos()
|
||||
local box = obj:get_properties().collisionbox
|
||||
local minp, maxp = mcl_burning.get_collisionbox(obj, true)
|
||||
local nodes = minetest.find_nodes_in_area(vector.add(pos, minp), vector.add(pos, maxp), nodenames)
|
||||
return nodes
|
||||
end
|
||||
|
||||
function mcl_burning.get_highest_group_value(obj, groupname)
|
||||
local nodes = mcl_burning.get_touching_nodes(obj, "group:" .. groupname, true)
|
||||
local highest_group_value = 0
|
||||
|
||||
for _, pos in pairs(nodes) do
|
||||
local node = minetest.get_node(pos)
|
||||
local group_value = minetest.get_item_group(node.name, groupname)
|
||||
if group_value > highest_group_value then
|
||||
highest_group_value = group_value
|
||||
end
|
||||
end
|
||||
|
||||
return highest_group_value
|
||||
end
|
||||
|
||||
function mcl_burning.damage(obj)
|
||||
local luaentity = obj:get_luaentity()
|
||||
local health
|
||||
|
||||
if luaentity then
|
||||
health = luaentity.health
|
||||
end
|
||||
|
||||
local hp = health or obj:get_hp()
|
||||
|
||||
if hp <= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local do_damage = true
|
||||
|
||||
if obj:is_player() then
|
||||
if mcl_potions.player_has_effect(obj, "fire_proof") then
|
||||
do_damage = false
|
||||
else
|
||||
local name = obj:get_player_name()
|
||||
armor.last_damage_types[name] = "fire"
|
||||
local deathmsg = S("@1 burned to death.", name)
|
||||
local reason = mcl_burning.get(obj, "string", "reason")
|
||||
if reason ~= "" then
|
||||
deathmsg = S("@1 was burned by @2.", name, reason)
|
||||
end
|
||||
mcl_death_messages.player_damage(obj, deathmsg)
|
||||
end
|
||||
else
|
||||
if luaentity.fire_damage_resistant then
|
||||
do_damage = false
|
||||
end
|
||||
end
|
||||
|
||||
if do_damage then
|
||||
local new_hp = hp - 1
|
||||
if health then
|
||||
luaentity.health = new_hp
|
||||
else
|
||||
obj:set_hp(new_hp)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.set_on_fire(obj, burn_time, reason)
|
||||
local luaentity = obj:get_luaentity()
|
||||
if luaentity and luaentity.fire_resistant then
|
||||
return
|
||||
end
|
||||
|
||||
local old_burn_time = mcl_burning.get(obj, "float", "burn_time")
|
||||
local max_fire_prot_lvl = 0
|
||||
|
||||
if obj:is_player() then
|
||||
if minetest.is_creative_enabled(obj:get_player_name()) then
|
||||
burn_time = burn_time / 100
|
||||
end
|
||||
|
||||
local inv = obj:get_inventory()
|
||||
|
||||
for i = 2, 5 do
|
||||
local stack = inv:get_stack("armor", i)
|
||||
|
||||
local fire_prot_lvl = mcl_enchanting.get_enchantment(stack, "fire_protection")
|
||||
max_fire_prot_lvl = math.max(max_fire_prot_lvl, fire_prot_lvl)
|
||||
end
|
||||
end
|
||||
|
||||
if max_fire_prot_lvl > 0 then
|
||||
burn_time = burn_time - math.floor(burn_time * max_fire_prot_lvl * 0.15)
|
||||
end
|
||||
|
||||
if old_burn_time <= burn_time then
|
||||
local sound_id = mcl_burning.get(obj, "int", "sound_id")
|
||||
if sound_id == 0 then
|
||||
sound_id = minetest.sound_play("fire_fire", {
|
||||
object = obj,
|
||||
gain = 0.18,
|
||||
max_hear_distance = 16,
|
||||
loop = true,
|
||||
}) + 1
|
||||
end
|
||||
|
||||
local hud_id
|
||||
if obj:is_player() then
|
||||
hud_id = mcl_burning.get(obj, "int", "hud_id")
|
||||
if hud_id == 0 then
|
||||
hud_id = obj:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0.5, y = 0.5},
|
||||
scale = {x = -100, y = -100},
|
||||
text = "fire_basic_flame.png",
|
||||
z_index = 1000,
|
||||
}) + 1
|
||||
end
|
||||
end
|
||||
mcl_burning.set(obj, "float", "burn_time", burn_time)
|
||||
mcl_burning.set(obj, "string", "reason", reason)
|
||||
mcl_burning.set(obj, "int", "hud_id", hud_id)
|
||||
mcl_burning.set(obj, "int", "sound_id", sound_id)
|
||||
|
||||
local fire_entity = minetest.add_entity(obj:get_pos(), "mcl_burning:fire")
|
||||
local minp, maxp = mcl_burning.get_collisionbox(obj)
|
||||
local obj_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 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})
|
||||
mcl_burning.update_animation_frame(obj, fire_entity, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.extinguish(obj)
|
||||
if mcl_burning.is_burning(obj) then
|
||||
local sound_id = mcl_burning.get(obj, "int", "sound_id") - 1
|
||||
minetest.sound_stop(sound_id)
|
||||
|
||||
if obj:is_player() then
|
||||
local hud_id = mcl_burning.get(obj, "int", "hud_id") - 1
|
||||
obj:hud_remove(hud_id)
|
||||
end
|
||||
|
||||
mcl_burning.set(obj, "string", "reason")
|
||||
mcl_burning.set(obj, "float", "burn_time")
|
||||
mcl_burning.set(obj, "float", "damage_timer")
|
||||
mcl_burning.set(obj, "int", "hud_id")
|
||||
mcl_burning.set(obj, "int", "sound_id")
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.catch_fire_tick(obj, dtime)
|
||||
if mcl_burning.is_affected_by_rain(obj) or #mcl_burning.get_touching_nodes(obj, "group:puts_out_fire") > 0 then
|
||||
mcl_burning.extinguish(obj)
|
||||
else
|
||||
local set_on_fire_value = mcl_burning.get_highest_group_value(obj, "set_on_fire")
|
||||
|
||||
if set_on_fire_value > 0 then
|
||||
mcl_burning.set_on_fire(obj, set_on_fire_value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.tick(obj, dtime)
|
||||
local burn_time = mcl_burning.get(obj, "float", "burn_time") - dtime
|
||||
|
||||
if burn_time <= 0 then
|
||||
mcl_burning.extinguish(obj)
|
||||
else
|
||||
mcl_burning.set(obj, "float", "burn_time", burn_time)
|
||||
|
||||
local damage_timer = mcl_burning.get(obj, "float", "damage_timer") + dtime
|
||||
|
||||
if damage_timer >= 1 then
|
||||
damage_timer = 0
|
||||
mcl_burning.damage(obj)
|
||||
end
|
||||
|
||||
mcl_burning.set(obj, "float", "damage_timer", damage_timer)
|
||||
end
|
||||
|
||||
mcl_burning.catch_fire_tick(obj, dtime)
|
||||
end
|
||||
|
||||
function mcl_burning.update_animation_frame(obj, fire_entity, animation_frame)
|
||||
local fire_texture = "mcl_burning_entity_flame_animated.png^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. animation_frame
|
||||
local fire_HUD_texture = "mcl_burning_hud_flame_animated.png^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. animation_frame
|
||||
fire_entity:set_properties({textures = {"blank.png", "blank.png", fire_texture, fire_texture, fire_texture, fire_texture}})
|
||||
if obj:is_player() then
|
||||
local hud_id = mcl_burning.get(obj, "int", "hud_id") - 1
|
||||
obj:hud_change(hud_id, "text", fire_HUD_texture)
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.fire_entity_step(self, dtime)
|
||||
if self.removed then
|
||||
return
|
||||
end
|
||||
|
||||
local obj = self.object
|
||||
local parent = obj:get_attach()
|
||||
local do_remove
|
||||
|
||||
self.doing_step = true
|
||||
|
||||
if not parent or not mcl_burning.is_burning(parent) then
|
||||
do_remove = true
|
||||
else
|
||||
for _, other in ipairs(minetest.get_objects_inside_radius(obj:get_pos(), 0)) do
|
||||
local luaentity = obj:get_luaentity()
|
||||
if luaentity and luaentity.name == "mcl_burning:fire" and not luaentity.doing_step and not luaentity.removed then
|
||||
do_remove = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.doing_step = false
|
||||
|
||||
if do_remove then
|
||||
self.removed = true
|
||||
obj:remove()
|
||||
return
|
||||
end
|
||||
|
||||
local animation_timer = self.animation_timer + dtime
|
||||
if animation_timer >= 0.015 then
|
||||
animation_timer = 0
|
||||
local animation_frame = self.animation_frame + 1
|
||||
if animation_frame > mcl_burning.animation_frames - 1 then
|
||||
animation_frame = 0
|
||||
end
|
||||
mcl_burning.update_animation_frame(parent, obj, animation_frame)
|
||||
self.animation_frame = animation_frame
|
||||
end
|
||||
self.animation_timer = animation_timer
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
local S = minetest.get_translator("mcl_burning")
|
||||
local modpath = minetest.get_modpath("mcl_burning")
|
||||
|
||||
mcl_burning = {
|
||||
animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8
|
||||
}
|
||||
|
||||
dofile(modpath .. "/api.lua")
|
||||
|
||||
minetest.register_entity("mcl_burning:fire", {
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
collisionbox = {0, 0, 0, 0, 0, 0},
|
||||
visual = "cube",
|
||||
pointable = false,
|
||||
glow = -1,
|
||||
},
|
||||
|
||||
animation_frame = 0,
|
||||
animation_timer = 0,
|
||||
on_step = mcl_burning.fire_entity_step,
|
||||
})
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
mcl_burning.tick(player, dtime)
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_respawnplayer(function(player)
|
||||
mcl_burning.extinguish(player)
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
mcl_burning.set(player, "int", "hud_id")
|
||||
end)
|
|
@ -0,0 +1,3 @@
|
|||
name = mcl_burning
|
||||
description = Burning Objects for MineClone2
|
||||
author = Fleckenstein
|
|
@ -0,0 +1,3 @@
|
|||
# textdomain: mcl_falling_nodes
|
||||
@1 was smashed by a falling anvil.=@1 придавило падающей наковальней.
|
||||
@1 was smashed by a falling block.=@1 раздавило падающим блоком.
|
|
@ -1 +1,2 @@
|
|||
flowlib
|
||||
mcl_enchanting
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
local item_drop_settings = {} --settings table
|
||||
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
|
||||
item_drop_settings.radius_magnet = 2.0 --radius of item magnet. MUST BE LARGER THAN radius_collect!
|
||||
item_drop_settings.xp_radius_magnet = 7.25 --radius of xp magnet. MUST BE LARGER THAN radius_collect!
|
||||
item_drop_settings.radius_collect = 0.2 --radius of collection
|
||||
item_drop_settings.player_collect_height = 1.0 --added to their pos y value
|
||||
item_drop_settings.collection_safety = false --do this to prevent items from flying away on laggy servers
|
||||
|
@ -60,8 +61,8 @@ minetest.register_globalstep(function(dtime)
|
|||
local checkpos = {x=pos.x,y=pos.y + item_drop_settings.player_collect_height,z=pos.z}
|
||||
|
||||
--magnet and collection
|
||||
for _,object in ipairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.radius_magnet)) do
|
||||
if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then
|
||||
for _,object in ipairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.xp_radius_magnet)) do
|
||||
if not object:is_player() and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then
|
||||
object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime
|
||||
local collected = false
|
||||
if object:get_luaentity()._magnet_timer >= 0 and object:get_luaentity()._magnet_timer < item_drop_settings.magnet_time and inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
|
||||
|
@ -152,6 +153,11 @@ minetest.register_globalstep(function(dtime)
|
|||
end
|
||||
end
|
||||
|
||||
elseif not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "mcl_experience:orb" then
|
||||
local entity = object:get_luaentity()
|
||||
entity.collector = player:get_player_name()
|
||||
entity.collected = true
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -188,6 +194,12 @@ local check_can_drop = function(node_name, tool_capabilities)
|
|||
if toolgroupcaps[plus] then
|
||||
return true
|
||||
end
|
||||
for e=1,5 do
|
||||
local effplus = plus .. "_efficiency_" .. e
|
||||
if toolgroupcaps[effplus] then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for b=1, #basegroups do
|
||||
|
@ -199,6 +211,12 @@ local check_can_drop = function(node_name, tool_capabilities)
|
|||
if toolgroupcaps[plus] then
|
||||
return true
|
||||
end
|
||||
for e=1,5 do
|
||||
local effplus = plus .. "_efficiency_" .. e
|
||||
if toolgroupcaps[effplus] then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -207,21 +225,66 @@ local check_can_drop = function(node_name, tool_capabilities)
|
|||
end
|
||||
end
|
||||
|
||||
-- Stupid workaround to get drops from a drop table:
|
||||
-- Create a temporary table in minetest.registered_nodes that contains the proper drops,
|
||||
-- because unfortunately minetest.get_node_drops needs the drop table to be inside a registered node definition
|
||||
-- (very ugly)
|
||||
|
||||
local tmp_id = 0
|
||||
|
||||
local function get_drops(drop, toolname, param2, paramtype2)
|
||||
tmp_id = tmp_id + 1
|
||||
local tmp_node_name = "mcl_item_entity:" .. tmp_id
|
||||
minetest.registered_nodes[tmp_node_name] = {
|
||||
name = tmp_node_name,
|
||||
drop = drop,
|
||||
paramtype2 = paramtype2
|
||||
}
|
||||
local drops = minetest.get_node_drops({name = tmp_node_name, param2 = param2}, toolname)
|
||||
minetest.registered_nodes[tmp_node_name] = nil
|
||||
return drops
|
||||
end
|
||||
|
||||
local function discrete_uniform_distribution(drops, min_count, max_count, cap)
|
||||
local new_drops = table.copy(drops)
|
||||
for i, item in ipairs(drops) do
|
||||
local new_item = ItemStack(item)
|
||||
local multiplier = math.random(min_count, max_count)
|
||||
if cap then
|
||||
multiplier = math.min(cap, multiplier)
|
||||
end
|
||||
new_item:set_count(multiplier * new_item:get_count())
|
||||
new_drops[i] = new_item
|
||||
end
|
||||
return new_drops
|
||||
end
|
||||
|
||||
local function get_fortune_drops(fortune_drops, fortune_level)
|
||||
local drop
|
||||
local i = fortune_level
|
||||
repeat
|
||||
drop = fortune_drops[i]
|
||||
i = i - 1
|
||||
until drop or i < 1
|
||||
return drop or {}
|
||||
end
|
||||
|
||||
function minetest.handle_node_drops(pos, drops, digger)
|
||||
-- NOTE: This function override allows digger to be nil.
|
||||
-- This means there is no digger. This is a special case which allows this function to be called
|
||||
-- by hand. Creative Mode is intentionally ignored in this case.
|
||||
|
||||
local doTileDrops = minetest.settings:get_bool("mcl_doTileDrops", true)
|
||||
if (digger ~= nil and minetest.is_creative_enabled(digger:get_player_name())) or doTileDrops == false then
|
||||
if (digger and digger:is_player() and minetest.is_creative_enabled(digger:get_player_name())) or doTileDrops == false then
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if node will yield its useful drop by the digger's tool
|
||||
local dug_node = minetest.get_node(pos)
|
||||
local toolcaps
|
||||
local tool
|
||||
if digger ~= nil then
|
||||
local tool = digger:get_wielded_item()
|
||||
tool = digger:get_wielded_item()
|
||||
toolcaps = tool:get_tool_capabilities()
|
||||
|
||||
if not check_can_drop(dug_node.name, toolcaps) then
|
||||
|
@ -229,12 +292,16 @@ function minetest.handle_node_drops(pos, drops, digger)
|
|||
end
|
||||
end
|
||||
|
||||
--[[ Special node drops when dug by shears by reading _mcl_shears_drop
|
||||
--[[ Special node drops when dug by shears by reading _mcl_shears_drop or with a silk touch tool reading _mcl_silk_touch_drop
|
||||
from the node definition.
|
||||
Definition of _mcl_shears_drop:
|
||||
* true: Drop itself when dug by shears
|
||||
* table: Drop every itemstring in this table when dub by shears
|
||||
Definition of _mcl_shears_drop / _mcl_silk_touch_drop:
|
||||
* true: Drop itself when dug by shears / silk touch tool
|
||||
* table: Drop every itemstring in this table when dug by shears _mcl_silk_touch_drop
|
||||
]]
|
||||
|
||||
local enchantments = tool and mcl_enchanting.get_enchantments(tool, "silk_touch")
|
||||
|
||||
local silk_touch_drop = false
|
||||
local nodedef = minetest.registered_nodes[dug_node.name]
|
||||
if toolcaps ~= nil and toolcaps.groupcaps and toolcaps.groupcaps.shearsy_dig and nodedef._mcl_shears_drop then
|
||||
if nodedef._mcl_shears_drop == true then
|
||||
|
@ -242,6 +309,39 @@ function minetest.handle_node_drops(pos, drops, digger)
|
|||
else
|
||||
drops = nodedef._mcl_shears_drop
|
||||
end
|
||||
elseif tool and enchantments.silk_touch and nodedef._mcl_silk_touch_drop then
|
||||
silk_touch_drop = true
|
||||
if nodedef._mcl_silk_touch_drop == true then
|
||||
drops = { dug_node.name }
|
||||
else
|
||||
drops = nodedef._mcl_silk_touch_drop
|
||||
end
|
||||
end
|
||||
|
||||
if tool and nodedef._mcl_fortune_drop and enchantments.fortune then
|
||||
local fortune_level = enchantments.fortune
|
||||
local fortune_drop = nodedef._mcl_fortune_drop
|
||||
if fortune_drop.discrete_uniform_distribution then
|
||||
local min_count = fortune_drop.min_count
|
||||
local max_count = fortune_drop.max_count + fortune_level * (fortune_drop.factor or 1)
|
||||
local chance = fortune_drop.chance or fortune_drop.get_chance and fortune_drop.get_chance(fortune_level)
|
||||
if not chance or math.random() < chance then
|
||||
drops = discrete_uniform_distribution(fortune_drop.multiply and drops or fortune_drop.items, min_count, max_count, fortune_drop.cap)
|
||||
elseif fortune_drop.override then
|
||||
drops = {}
|
||||
end
|
||||
else
|
||||
-- Fixed Behavior
|
||||
local drop = get_fortune_drops(fortune_drop, fortune_level)
|
||||
drops = get_drops(drop, tool:get_name(), dug_node.param2, nodedef.paramtype2)
|
||||
end
|
||||
end
|
||||
|
||||
if digger and mcl_experience.throw_experience and not silk_touch_drop then
|
||||
local experience_amount = minetest.get_item_group(dug_node.name,"xp")
|
||||
if experience_amount > 0 then
|
||||
mcl_experience.throw_experience(pos, experience_amount)
|
||||
end
|
||||
end
|
||||
|
||||
for _,item in ipairs(drops) do
|
||||
|
@ -519,6 +619,7 @@ minetest.register_entity(":__builtin:item", {
|
|||
minetest.log("warning", "Item entity with empty itemstring found at "..minetest.pos_to_string(self.object:get_pos()).. "! Deleting it now.")
|
||||
self._removed = true
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
local p = self.object:get_pos()
|
||||
|
@ -544,12 +645,15 @@ minetest.register_entity(":__builtin:item", {
|
|||
local fg = minetest.get_item_group(nn, "fire")
|
||||
local dg = minetest.get_item_group(nn, "destroys_items")
|
||||
if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then
|
||||
if dg ~= 2 then
|
||||
minetest.sound_play("builtin_item_lava", {pos = self.object:get_pos(), gain = 0.5}, true)
|
||||
--Wait 2 seconds to allow mob drops to be cooked, & picked up instead of instantly destroyed.
|
||||
if self.age > 2 then
|
||||
if dg ~= 2 then
|
||||
minetest.sound_play("builtin_item_lava", {pos = self.object:get_pos(), gain = 0.5})
|
||||
end
|
||||
self._removed = true
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
self._removed = true
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
-- Push item out when stuck inside solid opaque node
|
||||
|
|
|
@ -175,6 +175,19 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
|||
cart.on_activate_by_rail = on_activate_by_rail
|
||||
|
||||
function cart:on_step(dtime)
|
||||
local ctrl, player = nil, nil
|
||||
if self._driver then
|
||||
player = minetest.get_player_by_name(self._driver)
|
||||
if player then
|
||||
ctrl = player:get_player_control()
|
||||
-- player detach
|
||||
if ctrl.sneak then
|
||||
detach_driver(self)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local vel = self.object:get_velocity()
|
||||
local update = {}
|
||||
if self._last_float_check == nil then
|
||||
|
@ -190,18 +203,14 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
|||
node = minetest.get_node(rou_pos)
|
||||
local g = minetest.get_item_group(node.name, "connect_to_raillike")
|
||||
if g ~= self._railtype and self._railtype ~= nil then
|
||||
local player
|
||||
-- Detach driver
|
||||
if self._driver then
|
||||
if player then
|
||||
if self._old_pos then
|
||||
self.object:set_pos(self._old_pos)
|
||||
end
|
||||
mcl_player.player_attached[self._driver] = nil
|
||||
player = minetest.get_player_by_name(self._driver)
|
||||
if player then
|
||||
player:set_detach()
|
||||
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
|
||||
end
|
||||
player:set_detach()
|
||||
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
|
||||
end
|
||||
|
||||
-- Explode if already ignited
|
||||
|
@ -337,14 +346,6 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
|||
end
|
||||
end
|
||||
|
||||
local ctrl, player = nil, nil
|
||||
if self._driver then
|
||||
player = minetest.get_player_by_name(self._driver)
|
||||
if player then
|
||||
ctrl = player:get_player_control()
|
||||
end
|
||||
end
|
||||
|
||||
-- Stop cart if velocity vector flips
|
||||
if self._old_vel and self._old_vel.y == 0 and
|
||||
(self._old_vel.x * vel.x < 0 or self._old_vel.z * vel.z < 0) then
|
||||
|
@ -414,14 +415,17 @@ 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
|
||||
|
||||
acc = acc - friction
|
||||
|
||||
if has_fuel then
|
||||
acc = acc + 0.2
|
||||
elseif speed_mod and speed_mod ~= 0 then
|
||||
acc = acc + speed_mod
|
||||
else
|
||||
acc = acc - 0.4
|
||||
acc = acc + 0.6
|
||||
end
|
||||
|
||||
if speed_mod and speed_mod ~= 0 then
|
||||
acc = acc + speed_mod + friction
|
||||
end
|
||||
|
||||
new_acc = vector.multiply(dir, acc)
|
||||
|
@ -640,6 +644,7 @@ register_minecart(
|
|||
if player then
|
||||
mcl_player.player_set_animation(player, "sit" , 30)
|
||||
player:set_eye_offset({x=0, y=-5.5, z=0},{x=0, y=-4, z=0})
|
||||
mcl_tmp_message.message(clicker, S("Sneak to dismount"))
|
||||
end
|
||||
end, name)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# textdomain: mcl_minecarts
|
||||
Minecart=Вагонетка
|
||||
Minecarts can be used for a quick transportion on rails.=Вагонетки нужны, чтобы быстро перемещаться по рельсам.
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Вагонетки едут строго по проложенному железнодорожному пути. На Т-образной развилке они поворачивают налево. Скорость зависит от типа рельсов.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Вы ставите вагонетку на рельсы. Правым кликом садитесь в неё. Стукаете, чтобы начать движение.
|
||||
To obtain the minecart, punch it while holding down the sneak key.=Чтобы взять вагонетку, стукните её, удерживая клавишу [Красться].
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Вагон тротила это подрывной железнодорожный транспорт.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Поместите его на рельсы. Стукните, чтобы он поехал. Тротил воспламеняется, если его поджечь огнивом, либо при попадании на подключенный рельсовый активатор.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Чтобы взять вагон тротила, стукните его, удерживая клавишу [Красться]. Если тротил воспламенён, сделать это нельзя.
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Вагон с печью - это железнодорожный транспорт. Он может двигаться за счёт топлива.
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Поставьте его на рельсы. Если добавить немного угля, то печь зажжётся на продолжительное время и вагон сможет ехать. Стукните вагон для начала движения.
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=Чтобы взять вагон с печью, стукните его, удерживая клавишу [Красться].
|
||||
Minecart with Chest=Вагон с сундуком
|
||||
Minecart with Furnace=Вагон с печью
|
||||
Minecart with Command Block=Вагон с командным блоком
|
||||
Minecart with Hopper=Вагон с бункером
|
||||
Minecart with TNT=Вагон тротила
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Поместите на землю, чтобы сделать железную дорогу, рельсы автоматически соединятся между собой и будут превращаться в плавный повороты, T-образные развилки, перекрёстки и уклоны там, где это потребуется.
|
||||
Rail=Рельсы
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Рельсы используются для строительства железной дороги. Обычные рельсы немного замедляют движение вагонеток из-за трения.
|
||||
Powered Rail=Подключаемые рельсы
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Рельсы используются для строительства железной дороги. Подключённые рельсы могут разгонять и тормозить вагонетки.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Без энергии редстоуна рельсы будут тормозить вагонетки.
|
||||
Activator Rail=Рельсовый активатор
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Рельсы используются для строительства железной дороги. Рельсовый активатор активирует особые вагонетки.
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Чтобы этот блок рельсов активировал вагонетку, подключите его к энергии редстоуна и направьте вагонетку через него.
|
||||
Detector Rail=Рельсовый детектор
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Рельсы используются для строительства железной дороги. Рельсовый детектор может обнаруживать вагонетку у себя наверху и подключать механизмы редстоуна.
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Чтобы обнаруживать вагонетку и подавать энергию редстоуна, подключите его к дорожке редстоуна или механизму редстоуна, после чего направьте любую вагонетку через него.
|
||||
Track for minecarts=Железная дорога
|
||||
Speed up when powered, slow down when not powered=Разгоняет, если подключён, тормозит, если не подключён
|
||||
Activates minecarts when powered=Активирует особые вагонетки, если подключён
|
||||
Emits redstone power when a minecart is detected=Испускает энергию редстоуна при обнаружении вагонетки
|
||||
Vehicle for fast travel on rails=Быстрый железнодорожный транспорт
|
||||
Can be ignited by tools or powered activator rail=Можно воспламенить с помощью инструмента или подключенного рельсового активатора
|
||||
Sneak to dismount=Нажмите [Красться] для высадки
|
|
@ -33,3 +33,4 @@ Activates minecarts when powered=
|
|||
Emits redstone power when a minecart is detected=
|
||||
Vehicle for fast travel on rails=
|
||||
Can be ignited by tools or powered activator rail=
|
||||
Sneak to dismount=
|
||||
|
|
|
@ -108,6 +108,7 @@ functions needed for the mob to work properly which contains the following:
|
|||
'explosion_timer' number of seconds before mob explodes while its target
|
||||
is still inside reach or explosion_damage_radius,
|
||||
defaults to 3.
|
||||
'explosiontimer_reset_radius' The distance you must travel before the timer will be reset.
|
||||
'allow_fuse_reset' Allow 'explode' attack_type to reset fuse and resume
|
||||
chasing if target leaves the blast radius or line of
|
||||
sight. Defaults to true.
|
||||
|
@ -145,12 +146,14 @@ functions needed for the mob to work properly which contains the following:
|
|||
'base_pitch' base pitch to use adult mobs, default is 1.0 (MCL2 extension)
|
||||
'random' played randomly from time to time.
|
||||
also played for overfeeding animal.
|
||||
'eat' played when mob eats something
|
||||
'war_cry' what you hear when mob starts to attack player. (currently disabled)
|
||||
'attack' what you hear when being attacked.
|
||||
'shoot_attack' sound played when mob shoots.
|
||||
'damage' sound heard when mob is hurt.
|
||||
'death' played when mob is killed.
|
||||
'jump' played when mob jumps. There's a built-in cooloff timer to avoid sound spam
|
||||
'flop' played when mob flops (like a stranded fish)
|
||||
'fuse' sound played when mob explode timer starts.
|
||||
'explode' sound played when mob explodes.
|
||||
|
||||
|
@ -222,6 +225,8 @@ functions needed for the mob to work properly which contains the following:
|
|||
|
||||
'speed_normal' is used for animation speed for compatibility with some
|
||||
older mobs.
|
||||
'pushable' Allows players, & other mobs to push the mob.
|
||||
|
||||
|
||||
|
||||
MineClone 2 extensions:
|
||||
|
@ -241,6 +246,14 @@ functions needed for the mob to work properly which contains the following:
|
|||
dir is mob's aiming direction
|
||||
'sounds_child' same as sounds, but for childs. If not defined, childs will use same
|
||||
sound as adults but with higher pitch
|
||||
'follow_velocity' The speed at which a mob moves toward the player when they're holding the appropriate follow item.
|
||||
'instant_death' If true, mob dies instantly (no death animation or delay) (default: false)
|
||||
'xp_min' the minimum XP it drops on death (default: 0)
|
||||
'xp_max' the maximum XP it drops on death (default: 0)
|
||||
'fire_resistant' If true, the mob can't burn
|
||||
'fire_damage_resistant' If true the mob will not take damage when burning
|
||||
'ignited_by_sunlight' If true the mod will burn at daytime. (Takes sunlight_damage per second)
|
||||
|
||||
|
||||
|
||||
Node Replacement
|
||||
|
@ -281,8 +294,9 @@ Custom Definition Functions
|
|||
Along with the above mob registry settings we can also use custom functions to
|
||||
enhance mob functionality and have them do many interesting things:
|
||||
|
||||
'on_die' a function that is called when the mob is killed the
|
||||
parameters are (self, pos)
|
||||
'on_die' a function that is called when the mob is killed; the
|
||||
parameters are (self, pos). Return true to skip the builtin
|
||||
death animation and death effects
|
||||
'on_rightclick' its same as in minetest.register_entity()
|
||||
'on_blast' is called when an explosion happens near mob when using TNT
|
||||
functions, parameters are (object, damage) and returns
|
||||
|
@ -339,6 +353,14 @@ for each mob.
|
|||
dogs
|
||||
'self.order' set to "follow" or "stand" so that npc will follow owner
|
||||
or stand it's ground
|
||||
'self.state' Current mob state.
|
||||
"stand": no movement (except turning around)
|
||||
"walk": walk or move around aimlessly
|
||||
"attack": chase and attack enemy
|
||||
"runaway": flee from target
|
||||
"flop": bounce around aimlessly
|
||||
(for swimming mobs that have stranded)
|
||||
"die": during death
|
||||
'self.nametag' contains the name of the mob which it can show above
|
||||
|
||||
|
||||
|
@ -409,6 +431,10 @@ This function spawns a mob as a child. The parameter mob_type is the
|
|||
entitystring of the new mob.
|
||||
This function returns the mob on success and nil otherwise.
|
||||
|
||||
mobs:death_effect(pos, collisionbox)
|
||||
|
||||
Create death particles at pos with the given collisionbox.
|
||||
|
||||
|
||||
Making Arrows
|
||||
-------------
|
||||
|
|
|
@ -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=Задайте имя при помощи наковальни
|
|
@ -1,2 +1,3 @@
|
|||
name = mcl_mobs
|
||||
optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, invisibility, lucky_block, cmi, doc_identifier, mcl_armor
|
||||
depends = mcl_particles
|
||||
optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, invisibility, lucky_block, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience
|
||||
|
|
|
@ -10,13 +10,14 @@ This mod contains the API only for adding your own mobs into the world, so pleas
|
|||
|
||||
https://forum.minetest.net/viewtopic.php?f=11&t=9917
|
||||
|
||||
------------
|
||||
Credits:
|
||||
|
||||
Items:
|
||||
|
||||
- Nametag (paper, black dye, string) can be used right-click on a tamed mob to give them a name.
|
||||
|
||||
Lucky Block items: 1
|
||||
mcl_mobs_mob_poof.ogg:
|
||||
- by Planman (license: Creative Commons Zero)
|
||||
- Source: <https://freesound.org/people/Planman/sounds/208111/>
|
||||
|
||||
------------
|
||||
|
||||
Changelog from original Mobs Redo mod:
|
||||
- 1.41- Mob pathfinding has been updated thanks to Elkien3
|
||||
|
|
|
@ -143,6 +143,7 @@ minetest.register_entity("mcl_paintings:painting", {
|
|||
_xsize = 1,
|
||||
_ysize = 1,
|
||||
on_activate = function(self, staticdata)
|
||||
self.object:set_armor_groups({immortal = 1})
|
||||
if staticdata and staticdata ~= "" then
|
||||
local data = minetest.deserialize(staticdata)
|
||||
if data then
|
||||
|
@ -165,18 +166,20 @@ minetest.register_entity("mcl_paintings:painting", {
|
|||
}
|
||||
return minetest.serialize(data)
|
||||
end,
|
||||
on_death = function(self, killer)
|
||||
-- Drop as item on death
|
||||
local kname = ""
|
||||
if killer and killer:is_player() then
|
||||
kname = killer:get_player_name()
|
||||
end
|
||||
if not minetest.is_creative_enabled(kname) then
|
||||
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
|
||||
-- Drop as item on punch
|
||||
if puncher and puncher:is_player() then
|
||||
kname = puncher:get_player_name()
|
||||
local pos = self._pos
|
||||
if not pos then
|
||||
pos = self.object:get_pos()
|
||||
end
|
||||
minetest.add_item(pos, "mcl_paintings:painting")
|
||||
if not minetest.is_protected(pos, kname) then
|
||||
self.object:remove()
|
||||
if not minetest.is_creative_enabled(kname) then
|
||||
minetest.add_item(pos, "mcl_paintings:painting")
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
# textdomain:mcl_paintings
|
||||
Painting=Peinture
|
|
@ -0,0 +1,2 @@
|
|||
# textdomain:mcl_paintings
|
||||
Painting=Рисование
|
|
@ -39,6 +39,7 @@ minetest.register_node("mobs_mc:arrow_box", {
|
|||
}
|
||||
},
|
||||
tiles = {"mcl_bows_arrow.png^[transformFX", "mcl_bows_arrow.png^[transformFX", "mcl_bows_arrow_back.png", "mcl_bows_arrow_front.png", "mcl_bows_arrow.png", "mcl_bows_arrow.png^[transformFX"},
|
||||
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
sunlight_propagates = true,
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
local function is_forbidden_node(pos, node)
|
||||
node = node or minetest.get_node(pos)
|
||||
return minetest.get_item_group(node.name, "stair") > 0 or minetest.get_item_group(node.name, "slab") > 0 or minetest.get_item_group(node.name, "carpet") > 0
|
||||
end
|
||||
|
||||
function mobs:spawn_abm_check(pos, node, name)
|
||||
-- Don't spawn monsters on mycelium
|
||||
if (node.name == "mcl_core:mycelium" or node.name == "mcl_core:mycelium_snow") and minetest.registered_entities[name].type == "monster" then
|
||||
return true
|
||||
--Don't Spawn mobs on stairs, slabs, or carpets
|
||||
elseif is_forbidden_node(pos, node) or is_forbidden_node(vector.add(pos, vector.new(0, 1, 0))) then
|
||||
return true
|
||||
-- Spawn on opaque or liquid nodes
|
||||
elseif minetest.get_item_group(node.name, "opaque") ~= 0 or minetest.registered_nodes[node.name].liquidtype ~= "none" then
|
||||
elseif minetest.get_item_group(node.name, "opaque") ~= 0 or minetest.registered_nodes[node.name].liquidtype ~= "none" or node.name == "mcl_core:grass_path" then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Reject everything else
|
||||
return true
|
||||
end
|
||||
|
|
|
@ -84,6 +84,12 @@ Origin of those models:
|
|||
* [AGFX](http://www.freesound.org/people/DrMinky/sounds/) (CC0)
|
||||
* `mobs_mc_chicken_child.ogg`
|
||||
* Source: <https://freesound.org/people/AGFX/sounds/43380/>
|
||||
* [evsecrets](https://freesound.org/people/evsecrets/sounds/) (CC0)
|
||||
* `mobs_mc_chicken_*.ogg`
|
||||
* Source: <https://freesound.org/people/evsecrets/sounds/346961/>
|
||||
* [contramundum](https://freesound.org/people/contramundum/sounds/)
|
||||
* `mobs_mc_parrot_*.ogg`
|
||||
* Source: <https://freesound.org/people/contramundum/sounds/388417/>
|
||||
* Randomation (CC0)
|
||||
* `green_slime_damage.ogg`
|
||||
* `green_slime_attack.ogg`
|
||||
|
@ -99,27 +105,78 @@ Origin of those models:
|
|||
* `mobs_mc_cow_hurt.ogg` (CC0)
|
||||
* Heavily modified
|
||||
* Source: <https://freesound.org/people/Bird_man/packs/16972/>
|
||||
* [Klaraschick](https://freesound.org/people/Klaraschick/)
|
||||
* `mobs_mc_cow_milk.ogg` (CC0)
|
||||
* shortened
|
||||
* Source: <https://freesound.org/people/Klaraschick/sounds/415312/>
|
||||
* [Hitrison](https://freesound.org/people/Hitrison/)
|
||||
* `mobs_mc_cow_mushroom_stew.ogg` (CC BY 3.0)
|
||||
* sound was modified
|
||||
* Source: <https://freesound.org/people/Hitrison/sounds/251411/>
|
||||
* [NPXcoot](https://github.com/NPXcoot1) (CC BY-SA 4.0)
|
||||
* `mobs_mc_ender_dragon_*`
|
||||
* [bevibeldesign](https://freesound.org/people/bevibeldesign/)
|
||||
* `mobs_mc_wither_spawn.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/bevibeldesign/sounds/366095/>
|
||||
* [rubberduck](https://opengameart.org/users/rubberduck)
|
||||
* `mobs_mc_endermite_*.ogg` (CC0)
|
||||
* `mobs_mc_zombiepig_*.ogg` (CC0)
|
||||
* `mobs_mc_enderman_teleport_*.ogg` (CC0)
|
||||
* Source 1: <https://opengameart.org/content/80-cc0-creature-sfx>
|
||||
* Source 2: <https://opengameart.org/content/80-cc0-creture-sfx-2>
|
||||
* [Soundscapes55](https://freesound.org/people/Soundscapes55/)
|
||||
* `mobs_mc_enderman_random.1.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/Soundscapes55/sounds/434973/>
|
||||
* [griffinjennings](https://freesound.org/people/griffinjennings/)
|
||||
* `mobs_mc_enderman_death.*.ogg` (CC BY 3.0)
|
||||
* `mobs_mc_enderman_hurt.*.ogg` (CC BY 3.0)
|
||||
* Sounds were heavily modified
|
||||
* Source: <https://freesound.org/people/griffinjennings/sounds/463972/>
|
||||
* [pointparkcinema](https://freesound.org/people/pointparkcinema/)
|
||||
* `mobs_mc_guardian_random.1.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/pointparkcinema/sounds/407252/>
|
||||
* [nornalbion](https://freesound.org/people/nornalbion/)
|
||||
* `mobs_mc_guardian_random.2.ogg` (CC BY 3.0)
|
||||
* `mobs_mc_guardian_random.3.ogg` (CC BY 3.0)
|
||||
* `mobs_mc_guardian_hurt.*.ogg` (CC BY 3.0)
|
||||
* Sounds were modified
|
||||
* Source: <https://freesound.org/people/nornalbion/sounds/195733/>
|
||||
* [TheBuilder15](https://freesound.org/people/TheBuilder15/)
|
||||
* `mobs_mc_guardian_death.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/pointparkcinema/sounds/407252/>
|
||||
* Blender Foundation (CC BY 3.0)
|
||||
* `mobs_sheep.ogg`,
|
||||
* daufinsyd (MIT License)
|
||||
* `mobs_mc_blaze_breath.ogg`
|
||||
* `mobs_mc_blaze_died.ogg`
|
||||
* `mobs_mc_squid_hurt.ogg`
|
||||
* [qubodup](https://opengameart.org/content/slime-monster)
|
||||
* `mobs_mc_squid_hurt.*.ogg` (CC BY 3.0)
|
||||
* `mobs_mc_squid_death.*.ogg` (CC BY 3.0)
|
||||
* Changes were made
|
||||
* Source: <https://opengameart.org/content/slime-monster>
|
||||
* [kyles](https://freesound.org/people/kyles/)
|
||||
* `mobs_mc_squid_flop.*.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/kyles/sounds/450830/>
|
||||
* `mobs_mc_snowman_hurt.1.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/kyles/sounds/450848/>
|
||||
* [thefilmbakery](https://freesound.org/people/thefilmbakery/) (CC0)
|
||||
* `mobs_mc_blaze_hurt.ogg`
|
||||
* Source: <https://freesound.org/people/thefilmbakery/sounds/137836/>
|
||||
* TenPlus1, from `mobs_monster` or `mobs_animal` mod (MIT License)
|
||||
* `mobs_chicken.ogg`
|
||||
* `mobs_fireball.ogg`
|
||||
* `mobs_mc_cat_idle.1.ogg`
|
||||
* `mobs_mc_llama.ogg`
|
||||
* `mobs_pig.ogg`
|
||||
* `mobs_pig_angry.ogg`
|
||||
* `mobs_rat.ogg`
|
||||
* `mobs_sandmonster.ogg`
|
||||
* `mobs_spider.ogg`
|
||||
* [Daysycho](https://freesound.org/people/Darsycho/)
|
||||
* `mobs_mc_spider_hurt.*.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/Darsycho/sounds/505185/>
|
||||
* [columbia23](https://freesound.org/people/columbia23/)
|
||||
* `mobs_mc_spider_death.ogg` (CC BY 3.0)
|
||||
* `mobs_mc_spider_random.*.ogg` (CC BY 3.0)
|
||||
* `mobs_mc_spider_attack.*.ogg` (CC BY 3.0)
|
||||
* Source: <https://freesound.org/people/columbia23/sounds/395395/>
|
||||
* BrandonReese (LGPL v2.1)
|
||||
* `mobs_eerie.ogg`
|
||||
* [Under7dude](https://freesound.org/people/Under7dude/) (CC0)
|
||||
|
@ -147,6 +204,13 @@ Origin of those models:
|
|||
* Source: <https://freesound.org/people/GoodListener/sounds/322454/>
|
||||
* `mobs_mc_horse_death.ogg` (CC BY 3.0)
|
||||
* Source: <https://freesound.org/people/GoodListener/sounds/322445/>
|
||||
* [Garuda1982](https://freesound.org/people/Garuda1982/)
|
||||
* `mobs_mc_donkey_random.1.ogg` (CC BY 3.0)
|
||||
* `mobs_mc_donkey_hurt.ogg` (CC BY 3.0)
|
||||
* `mobs_mc_donkey_death.ogg` (CC BY 3.0)
|
||||
* Source: <https://freesound.org/people/Garuda1982/sounds/539505/>
|
||||
* [JarredGibb](https://freesound.org/people/JarredGibb/sounds/233131/)
|
||||
* `mobs_mc_donkey_random.2.ogg` (CC0)
|
||||
* [ERH](https://freesound.org/people/ERH/)
|
||||
* `mobs_mc_horse_random.2.ogg` (CC BY 3.0)
|
||||
* Source: <https://freesound.org/people/ERH/sounds/32043/>
|
||||
|
@ -164,6 +228,10 @@ Origin of those models:
|
|||
* [suonho](https://freesound.org/people/suonho/)
|
||||
* `mobs_mc_bat_idle.ogg` (CC BY 3.0)
|
||||
* Source: <https://freesound.org/people/suonho/sounds/59344/>
|
||||
* [toefur](https://freesound.org/people/toefur/)
|
||||
* `mobs_mc_bat_hurt.*.ogg` (CC0)
|
||||
* `mobs_mc_bat_death.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/toefur/sounds/288941/>
|
||||
* [cmusounddesign](https://freesound.org/people/cmusounddesign/)
|
||||
* `mobs_mc_cat_hiss.ogg` (CC BY 3.0)
|
||||
* Source: <https://freesound.org/people/cmusounddesign/sounds/71899/>
|
||||
|
@ -173,6 +241,16 @@ Origin of those models:
|
|||
* [ebcrosby](https://freesound.org/people/ebcrosby/)
|
||||
* `mobs_mc_ocelot_hurt.ogg` (CC BY 3.0)
|
||||
* Source: <https://freesound.org/people/ebcrosby/sounds/332979/>
|
||||
* Hybrid Dog (forum.minetest.net)
|
||||
* `mobs_mc_wolf_hurt.*.ogg` (CC0)
|
||||
* `mobs_mc_wolf_bark.*.ogg` (CC0)
|
||||
* `mobs_mc_wolf_death.*.ogg` (CC0)
|
||||
* `mobs_mc_wolf_growl.*.ogg` (CC0)
|
||||
* Sounds modified and simplified
|
||||
* Source: "dogblocks" mod by Hybrid Dog <https://github.com/HybridDog/dogblocks/>
|
||||
* [cliftoncarlson](https://freesound.org/people/cliftonmcarlson/)
|
||||
* `mobs_mc_wolf_take_bone.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/cliftonmcarlson/sounds/392883/>
|
||||
* [Inocodum](https://forum.minetest.net/memberlist.php?mode=viewprofile&u=3115)
|
||||
* `mobs_mc_silverfish_hurt.ogg` (CC BY-SA 4.0)
|
||||
* `mobs_mc_silverfish_death.ogg` (CC BY-SA 4.0)
|
||||
|
@ -186,6 +264,45 @@ Origin of those models:
|
|||
* [kbnevel](https://freesound.org/people/kbnevel/)
|
||||
* `mobs_mc_magma_cube_attack.ogg` (CC0)
|
||||
* Derived from: <https://freesound.org/people/kbnevel/sounds/119863/>
|
||||
* [InspectorJ](https://freesound.org/people/InspectorJ/sounds/429591/)
|
||||
* `mobs_mc_animal_eat_generic.ogg` (CC BY 3.0)
|
||||
* Source: <https://freesound.org/people/InspectorJ/>
|
||||
* [tbsounddesigns](https://freesound.org/people/tbsounddesigns/)
|
||||
* `mobs_mc_bear_random.*.ogg` (CC BY 3.0)
|
||||
* Source 1: <https://freesound.org/people/tbsounddesigns/sounds/416853/>
|
||||
* Source 2: <https://freesound.org/people/tbsounddesigns/sounds/416857/>
|
||||
* Source 3: <https://freesound.org/people/tbsounddesigns/sounds/416855/>
|
||||
* `mobs_mc_bear_growl.*.ogg` (CC BY 3.0)
|
||||
* Source 1: <https://freesound.org/people/tbsounddesigns/sounds/416861/>
|
||||
* Source 2: <https://freesound.org/people/tbsounddesigns/sounds/416859/>
|
||||
* Source 3: <https://freesound.org/people/tbsounddesigns/sounds/416862/>
|
||||
* [YleArkisto](https://freesound.org/people/YleArkisto/)
|
||||
* `mobs_mc_bear_attack.*.ogg` (CC BY 3.0)
|
||||
* `mobs_mc_bear_death.*.ogg` (CC BY 3.0)
|
||||
* `mobs_mc_bear_hurt.1.ogg` (CC BY 3.0)
|
||||
* Changes were made
|
||||
* Source: <https://freesound.org/people/YleArkisto/sounds/249441/>
|
||||
* [alexo400](https://freesound.org/people/alexo400/)
|
||||
* `mobs_mc_snowman_death.*.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/alexo400/sounds/543385/>
|
||||
* [cabled\_mess](https://freesound.org/people/cabled_mess/)
|
||||
* `mobs_mc_snowman_hurt.2.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/cabled_mess/sounds/384424/>
|
||||
* `mobs_mc_snowman_hurt.3.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/cabled_mess/sounds/384421/>
|
||||
* [kessir](https://freesound.org/people/kessir/sounds/)
|
||||
* `mobs_mc_rabbit_hurt.*.ogg` (CC0)
|
||||
* `mobs_mc_rabbit_death.2.ogg` (CC0)
|
||||
* `mobs_mc_rabbit_death.3.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/kessir/sounds/372075/>
|
||||
* `mobs_mc_rabbit_attack.*.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/kessir/sounds/372076/>
|
||||
* `mobs_mc_rabbit_death.1.ogg` (CC0)
|
||||
* Source: <https://freesound.org/people/kessir/sounds/385850/>
|
||||
* [Alshred](https://freesound.org/people/Alshred/sounds/403773/)
|
||||
* `mobs_mc_rabbit_random.*.ogg` (CC0)
|
||||
* Changes were made.
|
||||
* Source: <https://freesound.org/people/Alshred/>
|
||||
|
||||
Note: Many of these sounds have been more or less modified to fit the game.
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ mobs:register_mob("mobs_mc:bat", {
|
|||
visual_size = {x=1, y=1},
|
||||
sounds = {
|
||||
random = "mobs_mc_bat_idle",
|
||||
damage = "mobs_mc_bat_hurt",
|
||||
death = "mobs_mc_bat_death",
|
||||
distance = 16,
|
||||
},
|
||||
walk_velocity = 4.5,
|
||||
|
@ -33,18 +35,19 @@ mobs:register_mob("mobs_mc:bat", {
|
|||
run_speed = 80,
|
||||
run_start = 0,
|
||||
run_end = 40,
|
||||
-- TODO: Less ugly death animation
|
||||
--[[ die_speed = 60,
|
||||
die_speed = 60,
|
||||
die_start = 40,
|
||||
die_end = 80,
|
||||
die_loop = false,
|
||||
]]
|
||||
},
|
||||
|
||||
walk_chance = 100,
|
||||
fall_damage = 0,
|
||||
view_range = 16,
|
||||
fear_height = 0,
|
||||
|
||||
jump = false,
|
||||
fly = true,
|
||||
makes_footstep_sound = false,
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ mobs:register_mob("mobs_mc:blaze", {
|
|||
spawn_class = "hostile",
|
||||
hp_min = 20,
|
||||
hp_max = 20,
|
||||
xp_min = 10,
|
||||
xp_max = 10,
|
||||
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.79, 0.3},
|
||||
rotate = -180,
|
||||
visual = "mesh",
|
||||
|
@ -22,7 +24,7 @@ mobs:register_mob("mobs_mc:blaze", {
|
|||
textures = {
|
||||
{"mobs_mc_blaze.png"},
|
||||
},
|
||||
armor = { fleshy = 100, snowball_vulnerable = 100 },
|
||||
armor = { fleshy = 100, snowball_vulnerable = 100, water_vulnerable = 100 },
|
||||
visual_size = {x=3, y=3},
|
||||
sounds = {
|
||||
random = "mobs_mc_blaze_breath",
|
||||
|
@ -39,7 +41,8 @@ mobs:register_mob("mobs_mc:blaze", {
|
|||
{name = mobs_mc.items.blaze_rod,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "common",},
|
||||
},
|
||||
animation = {
|
||||
stand_speed = 25,
|
||||
|
@ -68,8 +71,10 @@ mobs:register_mob("mobs_mc:blaze", {
|
|||
jump = true,
|
||||
jump_height = 4,
|
||||
fly = true,
|
||||
makes_footstep_sound = false,
|
||||
fear_height = 0,
|
||||
glow = 14,
|
||||
fire_resistant = true,
|
||||
})
|
||||
|
||||
mobs:spawn_specific("mobs_mc:blaze", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 5000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
|
@ -83,6 +88,10 @@ mobs:register_arrow("mobs_mc:blaze_fireball", {
|
|||
|
||||
-- Direct hit, no fire... just plenty of pain
|
||||
hit_player = function(self, player)
|
||||
if rawget(_G, "armor") and armor.last_damage_types then
|
||||
armor.last_damage_types[player:get_player_name()] = "fireball"
|
||||
end
|
||||
mcl_burning.set_on_fire(player, 5, "blaze")
|
||||
player:punch(self.object, 1.0, {
|
||||
full_punch_interval = 1.0,
|
||||
damage_groups = {fleshy = 5},
|
||||
|
@ -90,6 +99,7 @@ mobs:register_arrow("mobs_mc:blaze_fireball", {
|
|||
end,
|
||||
|
||||
hit_mob = function(self, mob)
|
||||
mcl_burning.set_on_fire(mob, 5)
|
||||
mob:punch(self.object, 1.0, {
|
||||
full_punch_interval = 1.0,
|
||||
damage_groups = {fleshy = 5},
|
||||
|
|
|
@ -14,6 +14,8 @@ mobs:register_mob("mobs_mc:chicken", {
|
|||
|
||||
hp_min = 4,
|
||||
hp_max = 4,
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.69, 0.2},
|
||||
runaway = true,
|
||||
floats = 1,
|
||||
|
@ -30,23 +32,28 @@ mobs:register_mob("mobs_mc:chicken", {
|
|||
{name = mobs_mc.items.chicken_raw,
|
||||
chance = 1,
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "common",},
|
||||
{name = mobs_mc.items.feather,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
},
|
||||
fall_damage = 0,
|
||||
fall_speed = -2.25,
|
||||
sounds = {
|
||||
random = "mobs_chicken",
|
||||
-- TODO: death, damage
|
||||
random = "mobs_mc_chicken_buck",
|
||||
damage = "mobs_mc_chicken_hurt",
|
||||
death = "mobs_mc_chicken_hurt",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
distance = 16,
|
||||
},
|
||||
sounds_child = {
|
||||
random = "mobs_mc_chicken_child",
|
||||
damage = "mobs_mc_chicken_child",
|
||||
death = "mobs_mc_chicken_child",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
distance = 16,
|
||||
},
|
||||
animation = {
|
||||
|
|
|
@ -7,6 +7,8 @@ local cow_def = {
|
|||
spawn_class = "passive",
|
||||
hp_min = 10,
|
||||
hp_max = 10,
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.39, 0.45},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_cow.b3d",
|
||||
|
@ -21,24 +23,28 @@ local cow_def = {
|
|||
{name = mobs_mc.items.beef_raw,
|
||||
chance = 1,
|
||||
min = 1,
|
||||
max = 3,},
|
||||
max = 3,
|
||||
looting = "common",},
|
||||
{name = mobs_mc.items.leather,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
},
|
||||
runaway = true,
|
||||
sounds = {
|
||||
random = "mobs_mc_cow",
|
||||
damage = "mobs_mc_cow_hurt",
|
||||
death = "mobs_mc_cow_hurt",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
distance = 16,
|
||||
},
|
||||
animation = {
|
||||
stand_speed = 25, walk_speed = 25, run_speed = 50,
|
||||
stand_start = 0, stand_end = 0,
|
||||
walk_start = 0, walk_end = 40,
|
||||
run_start = 0, run_end = 40,
|
||||
stand_speed = 25, walk_speed = 40,
|
||||
run_speed = 60, stand_start = 0,
|
||||
stand_end = 0, walk_start = 0,
|
||||
walk_end = 40, run_start = 0,
|
||||
run_end = 40,
|
||||
},
|
||||
follow = mobs_mc.follow.cow,
|
||||
on_rightclick = function(self, clicker)
|
||||
|
@ -53,6 +59,7 @@ local cow_def = {
|
|||
if item:get_name() == mobs_mc.items.bucket and clicker:get_inventory() then
|
||||
local inv = clicker:get_inventory()
|
||||
inv:remove_item("main", mobs_mc.items.bucket)
|
||||
minetest.sound_play("mobs_mc_cow_milk", {pos=self.object:get_pos(), gain=0.6})
|
||||
-- if room add bucket of milk to inventory, otherwise drop as item
|
||||
if inv:room_for_item("main", {name=mobs_mc.items.milk}) then
|
||||
clicker:get_inventory():add_item("main", mobs_mc.items.milk)
|
||||
|
@ -88,7 +95,7 @@ mooshroom_def.on_rightclick = function(self, clicker)
|
|||
-- Use shears to get mushrooms and turn mooshroom into cow
|
||||
if item:get_name() == mobs_mc.items.shears then
|
||||
local pos = self.object:get_pos()
|
||||
minetest.sound_play("shears", {pos = pos}, true)
|
||||
minetest.sound_play("mcl_tools_shears_cut", {pos = pos}, true)
|
||||
|
||||
if self.base_texture[1] == "mobs_mc_mooshroom_brown.png" then
|
||||
minetest.add_item({x=pos.x, y=pos.y+1.4, z=pos.z}, mobs_mc.items.mushroom_brown .. " 5")
|
||||
|
@ -109,6 +116,7 @@ mooshroom_def.on_rightclick = function(self, clicker)
|
|||
elseif item:get_name() == mobs_mc.items.bucket and clicker:get_inventory() then
|
||||
local inv = clicker:get_inventory()
|
||||
inv:remove_item("main", mobs_mc.items.bucket)
|
||||
minetest.sound_play("mobs_mc_cow_milk", {pos=self.object:get_pos(), gain=0.6})
|
||||
-- If room, add milk to inventory, otherwise drop as item
|
||||
if inv:room_for_item("main", {name=mobs_mc.items.milk}) then
|
||||
clicker:get_inventory():add_item("main", mobs_mc.items.milk)
|
||||
|
@ -121,6 +129,7 @@ mooshroom_def.on_rightclick = function(self, clicker)
|
|||
elseif item:get_name() == mobs_mc.items.bowl and clicker:get_inventory() then
|
||||
local inv = clicker:get_inventory()
|
||||
inv:remove_item("main", mobs_mc.items.bowl)
|
||||
minetest.sound_play("mobs_mc_cow_mushroom_stew", {pos=self.object:get_pos(), gain=0.6})
|
||||
-- If room, add mushroom stew to inventory, otherwise drop as item
|
||||
if inv:room_for_item("main", {name=mobs_mc.items.mushroom_stew}) then
|
||||
clicker:get_inventory():add_item("main", mobs_mc.items.mushroom_stew)
|
||||
|
|
|
@ -14,12 +14,15 @@ mobs:register_mob("mobs_mc:creeper", {
|
|||
spawn_class = "hostile",
|
||||
hp_min = 20,
|
||||
hp_max = 20,
|
||||
xp_min = 5,
|
||||
xp_max = 5,
|
||||
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.69, 0.3},
|
||||
pathfinding = 1,
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_creeper.b3d",
|
||||
textures = {
|
||||
{"mobs_mc_creeper.png"},
|
||||
{"mobs_mc_creeper.png",
|
||||
"mobs_mc_empty.png"},
|
||||
},
|
||||
visual_size = {x=3, y=3},
|
||||
sounds = {
|
||||
|
@ -35,9 +38,12 @@ mobs:register_mob("mobs_mc:creeper", {
|
|||
run_velocity = 2.1,
|
||||
runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" },
|
||||
attack_type = "explode",
|
||||
|
||||
|
||||
explosion_strength = 3,
|
||||
reach = 4,
|
||||
explosion_radius = 3.5,
|
||||
explosion_damage_radius = 3.5,
|
||||
explosiontimer_reset_radius = 6,
|
||||
reach = 3,
|
||||
explosion_timer = 1.5,
|
||||
allow_fuse_reset = true,
|
||||
stop_to_explode = true,
|
||||
|
@ -69,17 +75,21 @@ mobs:register_mob("mobs_mc:creeper", {
|
|||
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
|
||||
mobs:boom(self, self.object:get_pos(), self.explosion_strength)
|
||||
mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_die = function(self, pos)
|
||||
-- Drop a random music disc
|
||||
-- TODO: Only do this if killed by skeleton
|
||||
if math.random(1, 200) == 1 then
|
||||
local r = math.random(1, #mobs_mc.items.music_discs)
|
||||
minetest.add_item({x=pos.x, y=pos.y+1, z=pos.z}, mobs_mc.items.music_discs[r])
|
||||
on_die = function(self, pos, cmi_cause)
|
||||
-- Drop a random music disc when killed by skeleton or stray
|
||||
if cmi_cause and cmi_cause.type == "punch" then
|
||||
local luaentity = cmi_cause.puncher and cmi_cause.puncher:get_luaentity()
|
||||
if luaentity and luaentity.name:find("arrow") then
|
||||
local shooter_luaentity = luaentity._shooter and luaentity._shooter:get_luaentity()
|
||||
if shooter_luaentity and (shooter_luaentity.name == "mobs_mc:skeleton" or shooter_luaentity.name == "mobs_mc:stray") then
|
||||
minetest.add_item({x=pos.x, y=pos.y+1, z=pos.z}, mobs_mc.items.music_discs[math.random(1, #mobs_mc.items.music_discs)])
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
maxdrops = 2,
|
||||
|
@ -87,7 +97,8 @@ mobs:register_mob("mobs_mc:creeper", {
|
|||
{name = mobs_mc.items.gunpowder,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
|
||||
-- Head
|
||||
-- TODO: Only drop if killed by charged creeper
|
||||
|
@ -117,6 +128,127 @@ mobs:register_mob("mobs_mc:creeper", {
|
|||
view_range = 16,
|
||||
})
|
||||
|
||||
mobs:register_mob("mobs_mc:creeper_charged", {
|
||||
type = "monster",
|
||||
spawn_class = "hostile",
|
||||
hp_min = 20,
|
||||
hp_max = 20,
|
||||
xp_min = 5,
|
||||
xp_max = 5,
|
||||
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.69, 0.3},
|
||||
pathfinding = 1,
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_creeper.b3d",
|
||||
textures = {
|
||||
{"mobs_mc_creeper.png",
|
||||
"mobs_mc_creeper_charge.png"},
|
||||
},
|
||||
visual_size = {x=3, y=3},
|
||||
sounds = {
|
||||
attack = "tnt_ignite",
|
||||
death = "mobs_mc_creeper_death",
|
||||
damage = "mobs_mc_creeper_hurt",
|
||||
fuse = "tnt_ignite",
|
||||
explode = "tnt_explode",
|
||||
distance = 16,
|
||||
},
|
||||
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 = 8,
|
||||
explosion_damage_radius = 8,
|
||||
explosiontimer_reset_radius = 6,
|
||||
reach = 3,
|
||||
explosion_timer = 1.5,
|
||||
allow_fuse_reset = true,
|
||||
stop_to_explode = true,
|
||||
|
||||
-- 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 ~= nil then
|
||||
return
|
||||
end
|
||||
local item = clicker:get_wielded_item()
|
||||
if item:get_name() == mobs_mc.items.flint_and_steel then
|
||||
if not minetest.is_creative_enabled(clicker:get_player_name()) then
|
||||
-- Wear tool
|
||||
local wdef = item:get_definition()
|
||||
item:add_wear(1000)
|
||||
-- Tool break sound
|
||||
if item:get_count() == 0 and wdef.sound and wdef.sound.breaks then
|
||||
minetest.sound_play(wdef.sound.breaks, {pos = clicker:get_pos(), gain = 0.5}, true)
|
||||
end
|
||||
clicker:set_wielded_item(item)
|
||||
end
|
||||
self._forced_explosion_countdown_timer = self.explosion_timer
|
||||
minetest.sound_play(self.sounds.attack, {pos = self.object:get_pos(), gain = 1, max_hear_distance = 16}, true)
|
||||
end
|
||||
end,
|
||||
do_custom = function(self, dtime)
|
||||
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
|
||||
mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_die = function(self, pos, cmi_cause)
|
||||
-- Drop a random music disc when killed by skeleton or stray
|
||||
if cmi_cause and cmi_cause.type == "punch" then
|
||||
local luaentity = cmi_cause.puncher and cmi_cause.puncher:get_luaentity()
|
||||
if luaentity and luaentity.name:find("arrow") then
|
||||
local shooter_luaentity = luaentity._shooter and luaentity._shooter:get_luaentity()
|
||||
if shooter_luaentity and (shooter_luaentity.name == "mobs_mc:skeleton" or shooter_luaentity.name == "mobs_mc:stray") then
|
||||
minetest.add_item({x=pos.x, y=pos.y+1, z=pos.z}, mobs_mc.items.music_discs[math.random(1, #mobs_mc.items.music_discs)])
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
maxdrops = 2,
|
||||
drops = {
|
||||
{name = mobs_mc.items.gunpowder,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
|
||||
-- Head
|
||||
-- TODO: Only drop if killed by charged creeper
|
||||
{name = mobs_mc.items.head_creeper,
|
||||
chance = 200, -- 0.5%
|
||||
min = 1,
|
||||
max = 1,},
|
||||
},
|
||||
animation = {
|
||||
speed_normal = 24,
|
||||
speed_run = 48,
|
||||
stand_start = 0,
|
||||
stand_end = 23,
|
||||
walk_start = 24,
|
||||
walk_end = 49,
|
||||
run_start = 24,
|
||||
run_end = 49,
|
||||
hurt_start = 110,
|
||||
hurt_end = 139,
|
||||
death_start = 140,
|
||||
death_end = 189,
|
||||
look_start = 50,
|
||||
look_end = 108,
|
||||
},
|
||||
floats = 1,
|
||||
fear_height = 4,
|
||||
view_range = 16,
|
||||
--Having trouble when fire is placed with lightning
|
||||
fire_resistant = true,
|
||||
glow = 3,
|
||||
})
|
||||
|
||||
mobs:spawn_specific("mobs_mc:creeper", mobs_mc.spawn.solid, {"air"}, 0, 7, 20, 16500, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
mcl_init
|
||||
mcl_particles
|
||||
default?
|
||||
mcl_mobs
|
||||
mcl_tnt?
|
||||
|
|
|
@ -12,6 +12,8 @@ mobs:register_mob("mobs_mc:enderdragon", {
|
|||
walk_chance = 100,
|
||||
hp_max = 200,
|
||||
hp_min = 200,
|
||||
xp_min = 500,
|
||||
xp_max = 500,
|
||||
collisionbox = {-2, 3, -2, 2, 5, 2},
|
||||
physical = false,
|
||||
visual = "mesh",
|
||||
|
@ -23,6 +25,7 @@ mobs:register_mob("mobs_mc:enderdragon", {
|
|||
view_range = 35,
|
||||
walk_velocity = 6,
|
||||
run_velocity = 6,
|
||||
can_despawn = false,
|
||||
sounds = {
|
||||
-- TODO: more sounds
|
||||
shoot_attack = "mobs_mc_ender_dragon_shoot",
|
||||
|
@ -34,17 +37,12 @@ mobs:register_mob("mobs_mc:enderdragon", {
|
|||
jump = true,
|
||||
jump_height = 14,
|
||||
fly = true,
|
||||
makes_footstep_sound = false,
|
||||
dogshoot_switch = 1,
|
||||
dogshoot_count_max =5,
|
||||
dogshoot_count2_max = 5,
|
||||
passive = false,
|
||||
attack_animals = true,
|
||||
drops = {
|
||||
{name = mobs_mc.items.dragon_egg,
|
||||
chance = 1,
|
||||
min = 1,
|
||||
max = 1},
|
||||
},
|
||||
lava_damage = 0,
|
||||
fire_damage = 0,
|
||||
on_rightclick = nil,
|
||||
|
@ -52,14 +50,26 @@ mobs:register_mob("mobs_mc:enderdragon", {
|
|||
arrow = "mobs_mc:dragon_fireball",
|
||||
shoot_interval = 0.5,
|
||||
shoot_offset = -1.0,
|
||||
xp_min = 12000,
|
||||
xp_max = 12000,
|
||||
animation = {
|
||||
fly_speed = 8, stand_speed = 8,
|
||||
stand_start = 0, stand_end = 20,
|
||||
walk_start = 0, walk_end = 20,
|
||||
run_start = 0, run_end = 20,
|
||||
},
|
||||
|
||||
ignores_nametag = true,
|
||||
on_die = function(self, own_pos)
|
||||
if self._egg_spawn_pos then
|
||||
local pos = minetest.string_to_pos(self._egg_spawn_pos)
|
||||
--if minetest.get_node(pos).buildable_to then
|
||||
minetest.set_node(pos, {name = mobs_mc.items.dragon_egg})
|
||||
return
|
||||
--end
|
||||
end
|
||||
minetest.add_item(own_pos, mobs_mc.items.dragon_egg)
|
||||
end,
|
||||
fire_resistant = true,
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
-- However, they have a reduced viewing range to make them less dangerous.
|
||||
-- This differs from MC, in which endermen only become hostile when provoked,
|
||||
-- and they are provoked by looking directly at them.
|
||||
-- TODO: Implement MC behaviour.
|
||||
|
||||
-- Rootyjr
|
||||
-----------------------------
|
||||
|
@ -27,6 +26,16 @@
|
|||
|
||||
local S = minetest.get_translator("mobs_mc")
|
||||
|
||||
local telesound = function(pos, is_source)
|
||||
local snd
|
||||
if is_source then
|
||||
snd = "mobs_mc_enderman_teleport_src"
|
||||
else
|
||||
snd = "mobs_mc_enderman_teleport_dst"
|
||||
end
|
||||
minetest.sound_play(snd, {pos=pos, max_hear_distance=16}, true)
|
||||
end
|
||||
|
||||
--###################
|
||||
--################### ENDERMAN
|
||||
--###################
|
||||
|
@ -34,10 +43,10 @@ local S = minetest.get_translator("mobs_mc")
|
|||
local pr = PseudoRandom(os.time()*(-334))
|
||||
|
||||
-- How freqeuntly to take and place blocks, in seconds
|
||||
local take_frequency_min = 25
|
||||
local take_frequency_max = 90
|
||||
local place_frequency_min = 10
|
||||
local place_frequency_max = 30
|
||||
local take_frequency_min = 235
|
||||
local take_frequency_max = 245
|
||||
local place_frequency_min = 235
|
||||
local place_frequency_max = 245
|
||||
|
||||
-- Create the textures table for the enderman, depending on which kind of block
|
||||
-- the enderman holds (if any).
|
||||
|
@ -178,16 +187,17 @@ local select_enderman_animation = function(animation_type)
|
|||
end
|
||||
end
|
||||
|
||||
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
|
||||
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
|
||||
|
||||
mobs:register_mob("mobs_mc:enderman", {
|
||||
-- TODO: Endermen should be classified as passive
|
||||
type = "monster",
|
||||
spawn_class = "passive",
|
||||
passive = true,
|
||||
pathfinding = 1,
|
||||
hp_min = 40,
|
||||
hp_max = 40,
|
||||
xp_min = 5,
|
||||
xp_max = 5,
|
||||
collisionbox = {-0.3, -0.01, -0.3, 0.3, 2.89, 0.3},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_enderman.b3d",
|
||||
|
@ -195,9 +205,11 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
visual_size = {x=3, y=3},
|
||||
makes_footstep_sound = true,
|
||||
sounds = {
|
||||
-- TODO: Custom war cry sound
|
||||
war_cry = "mobs_sandmonster",
|
||||
death = "green_slime_death",
|
||||
-- TODO: damage, random
|
||||
death = {name="mobs_mc_enderman_death", gain=0.7},
|
||||
damage = {name="mobs_mc_enderman_hurt", gain=0.5},
|
||||
random = {name="mobs_mc_enderman_random", gain=0.5},
|
||||
distance = 16,
|
||||
},
|
||||
walk_velocity = 0.2,
|
||||
|
@ -208,11 +220,11 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
{name = mobs_mc.items.ender_pearl,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "common"},
|
||||
},
|
||||
animation = select_enderman_animation("normal"),
|
||||
_taken_node = "",
|
||||
-- TODO: Teleport enderman on damage, etc.
|
||||
do_custom = function(self, dtime)
|
||||
-- PARTICLE BEHAVIOUR HERE.
|
||||
local enderpos = self.object:get_pos()
|
||||
|
@ -230,52 +242,55 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
})
|
||||
end
|
||||
-- RAIN DAMAGE / EVASIVE WARP BEHAVIOUR HERE.
|
||||
if mcl_weather.state == "rain" or mcl_weather.state == "lightning" then
|
||||
local damage = true
|
||||
local enderpos = self.object:get_pos()
|
||||
enderpos.y = enderpos.y+2.89
|
||||
local height = {x=enderpos.x, y=enderpos.y+512,z=enderpos.z}
|
||||
local ray = minetest.raycast(enderpos, height, true)
|
||||
-- Check for blocks above enderman.
|
||||
for pointed_thing in ray do
|
||||
if pointed_thing.type == "node" then
|
||||
local nn = minetest.get_node(minetest.get_pointed_thing_position(pointed_thing)).name
|
||||
local def = minetest.registered_nodes[nn]
|
||||
if (not def) or def.walkable then
|
||||
-- There's a node in the way. Delete arrow without damage
|
||||
damage = false
|
||||
break
|
||||
local dim = mcl_worlds.pos_to_dimension(enderpos)
|
||||
if dim == "overworld" then
|
||||
if mcl_weather.state == "rain" or mcl_weather.state == "lightning" then
|
||||
local damage = true
|
||||
local enderpos = self.object:get_pos()
|
||||
enderpos.y = enderpos.y+2.89
|
||||
local height = {x=enderpos.x, y=enderpos.y+512,z=enderpos.z}
|
||||
local ray = minetest.raycast(enderpos, height, true)
|
||||
-- Check for blocks above enderman.
|
||||
for pointed_thing in ray do
|
||||
if pointed_thing.type == "node" then
|
||||
local nn = minetest.get_node(minetest.get_pointed_thing_position(pointed_thing)).name
|
||||
local def = minetest.registered_nodes[nn]
|
||||
if (not def) or def.walkable then
|
||||
-- There's a node in the way. Delete arrow without damage
|
||||
damage = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if damage == true then
|
||||
self.state = ""
|
||||
--rain hurts enderman
|
||||
self.object:punch(self.object, 1.0, {
|
||||
full_punch_interval=1.0,
|
||||
damage_groups={fleshy=self._damage},
|
||||
}, nil)
|
||||
--randomly teleport hopefully under something.
|
||||
self:teleport(nil)
|
||||
end
|
||||
end
|
||||
|
||||
if damage == true then
|
||||
self.state = ""
|
||||
--rain hurts enderman
|
||||
self.object:punch(self.object, 1.0, {
|
||||
full_punch_interval=1.0,
|
||||
damage_groups={fleshy=self._damage},
|
||||
}, nil)
|
||||
--randomly teleport hopefully under something.
|
||||
self:teleport(nil)
|
||||
end
|
||||
end
|
||||
else return end
|
||||
-- AGRESSIVELY WARP/CHASE PLAYER BEHAVIOUR HERE.
|
||||
if self.state == "attack" then
|
||||
if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
|
||||
self:teleport(nil)
|
||||
self.state = ""
|
||||
else
|
||||
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
|
||||
--self:teleport(nil)
|
||||
--self.state = ""
|
||||
--else
|
||||
if self.attack then
|
||||
target = self.attack
|
||||
pos = target:get_pos()
|
||||
local target = self.attack
|
||||
local pos = target:get_pos()
|
||||
if pos ~= nil then
|
||||
if vector.distance(self.object:get_pos(), target:get_pos()) > 10 then
|
||||
self:teleport(target)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--end
|
||||
end
|
||||
-- ARROW / DAYTIME PEOPLE AVOIDANCE BEHAVIOUR HERE.
|
||||
-- Check for arrows and people nearby.
|
||||
|
@ -286,9 +301,9 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
if 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 (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
|
||||
-- self:teleport(nil)
|
||||
--end
|
||||
else
|
||||
local lua = obj:get_luaentity()
|
||||
if lua then
|
||||
|
@ -303,17 +318,18 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
local enderpos = self.object:get_pos()
|
||||
if self.provoked == "broke_contact" then
|
||||
self.provoked = "false"
|
||||
if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
|
||||
self:teleport(nil)
|
||||
self.state = ""
|
||||
else
|
||||
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
|
||||
-- self:teleport(nil)
|
||||
-- self.state = ""
|
||||
--else
|
||||
if self.attack ~= nil then
|
||||
self.state = 'attack'
|
||||
end
|
||||
end
|
||||
--end
|
||||
end
|
||||
-- Check to see if people are near by enough to look at us.
|
||||
local objs = minetest.get_objects_inside_radius(enderpos, 64)
|
||||
local obj
|
||||
for n = 1, #objs do
|
||||
obj = objs[n]
|
||||
if obj then
|
||||
|
@ -326,7 +342,7 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
-- Cast up to 64 to see if player is looking at enderman.
|
||||
for n = 1,64,.25 do
|
||||
local node = minetest.get_node(look_pos)
|
||||
if node.name ~= "air" then
|
||||
if node.name ~= "air" then
|
||||
break
|
||||
end
|
||||
if look_pos.x-1<enderpos.x and look_pos.x+1>enderpos.x and look_pos.y-2.89<enderpos.y and look_pos.y-2>enderpos.y and look_pos.z-1<enderpos.z and look_pos.z+1>enderpos.z then
|
||||
|
@ -344,7 +360,7 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- TAKE AND PLACE STUFF BEHAVIOUR BELOW.
|
||||
if not mobs_griefing then
|
||||
return
|
||||
|
@ -361,7 +377,7 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
self._take_place_timer = 0
|
||||
self._next_take_place_time = math.random(place_frequency_min, place_frequency_max)
|
||||
local pos = self.object:get_pos()
|
||||
local takable_nodes = minetest.find_nodes_in_area({x=pos.x-2, y=pos.y-1, z=pos.z-2}, {x=pos.x+2, y=pos.y+1, z=pos.z+2}, mobs_mc.enderman_takable)
|
||||
local takable_nodes = minetest.find_nodes_in_area_under_air({x=pos.x-2, y=pos.y-1, z=pos.z-2}, {x=pos.x+2, y=pos.y+1, z=pos.z+2}, mobs_mc.enderman_takable)
|
||||
if #takable_nodes >= 1 then
|
||||
local r = pr:next(1, #takable_nodes)
|
||||
local take_pos = takable_nodes[r]
|
||||
|
@ -461,7 +477,9 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
end
|
||||
end
|
||||
if telepos then
|
||||
telesound(self.object:get_pos(), false)
|
||||
self.object:set_pos(telepos)
|
||||
telesound(telepos, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -489,7 +507,10 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
end
|
||||
end
|
||||
if node_ok then
|
||||
self.object:set_pos({x=nodepos.x, y=nodepos.y+1, z=nodepos.z})
|
||||
telesound(self.object:get_pos(), false)
|
||||
local telepos = {x=nodepos.x, y=nodepos.y+1, z=nodepos.z}
|
||||
self.object:set_pos(telepos)
|
||||
telesound(telepos, true)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
@ -510,15 +531,16 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
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 ~= nil then
|
||||
if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
|
||||
self:teleport(nil)
|
||||
else
|
||||
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
|
||||
-- self:teleport(nil)
|
||||
--else
|
||||
self:teleport(hitter)
|
||||
self.attack=hitter
|
||||
self.state="attack"
|
||||
end
|
||||
--end
|
||||
end
|
||||
end,
|
||||
armor = { fleshy = 100, water_vulnerable = 100 },
|
||||
water_damage = 8,
|
||||
view_range = 64,
|
||||
fear_height = 4,
|
||||
|
|
|
@ -10,7 +10,9 @@ mobs:register_mob("mobs_mc:endermite", {
|
|||
passive = false,
|
||||
hp_min = 8,
|
||||
hp_max = 8,
|
||||
armor = 100,
|
||||
xp_min = 3,
|
||||
xp_max = 3,
|
||||
armor = {fleshy = 100, arthropod = 100},
|
||||
group_attack = true,
|
||||
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.29, 0.2},
|
||||
visual = "mesh",
|
||||
|
@ -21,9 +23,10 @@ mobs:register_mob("mobs_mc:endermite", {
|
|||
visual_size = {x=3, y=3},
|
||||
makes_footstep_sound = false,
|
||||
sounds = {
|
||||
random = "mobs_rat",
|
||||
random = "mobs_mc_endermite_random",
|
||||
damage = "mobs_mc_endermite_hurt",
|
||||
death = "mobs_mc_endermite_death",
|
||||
distance = 16,
|
||||
-- TODO: more sounds
|
||||
},
|
||||
walk_velocity = 1,
|
||||
run_velocity = 2,
|
||||
|
|
|
@ -17,6 +17,8 @@ mobs:register_mob("mobs_mc:ghast", {
|
|||
group_attack = true,
|
||||
hp_min = 10,
|
||||
hp_max = 10,
|
||||
xp_min = 5,
|
||||
xp_max = 5,
|
||||
collisionbox = {-2, 5, -2, 2, 9, 2},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_ghast.b3d",
|
||||
|
@ -36,8 +38,8 @@ mobs:register_mob("mobs_mc:ghast", {
|
|||
walk_velocity = 1.6,
|
||||
run_velocity = 3.2,
|
||||
drops = {
|
||||
{name = mobs_mc.items.gunpowder, chance = 1, min = 0, max = 2,},
|
||||
{name = mobs_mc.items.ghast_tear, chance = 3,min = 0,max = 1,},
|
||||
{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},
|
||||
},
|
||||
animation = {
|
||||
stand_speed = 50, walk_speed = 50, run_speed = 50,
|
||||
|
@ -58,6 +60,9 @@ mobs:register_mob("mobs_mc:ghast", {
|
|||
jump_height = 4,
|
||||
floats=1,
|
||||
fly = true,
|
||||
makes_footstep_sound = false,
|
||||
instant_death = true,
|
||||
fire_resistant = true,
|
||||
})
|
||||
|
||||
|
||||
|
@ -71,6 +76,9 @@ mobs:register_arrow("mobs_mc:fireball", {
|
|||
velocity = 15,
|
||||
|
||||
hit_player = function(self, player)
|
||||
if rawget(_G, "armor") and armor.last_damage_types then
|
||||
armor.last_damage_types[player:get_player_name()] = "fireball"
|
||||
end
|
||||
player:punch(self.object, 1.0, {
|
||||
full_punch_interval = 1.0,
|
||||
damage_groups = {fleshy = 6},
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
-- v1.4
|
||||
|
||||
--###################
|
||||
--################### GUARDIAN
|
||||
--###################
|
||||
|
@ -11,6 +9,8 @@ mobs:register_mob("mobs_mc:guardian", {
|
|||
spawn_class = "hostile",
|
||||
hp_min = 30,
|
||||
hp_max = 30,
|
||||
xp_min = 10,
|
||||
xp_max = 10,
|
||||
breath_max = -1,
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
|
@ -28,8 +28,11 @@ mobs:register_mob("mobs_mc:guardian", {
|
|||
},
|
||||
visual_size = {x=3, y=3},
|
||||
sounds = {
|
||||
damage = "mobs_mc_squid_hurt",
|
||||
-- TODO: more and better sounds
|
||||
random = "mobs_mc_guardian_random",
|
||||
war_cry = "mobs_mc_guardian_random",
|
||||
damage = {name="mobs_mc_guardian_hurt", gain=0.3},
|
||||
death = "mobs_mc_guardian_death",
|
||||
flop = "mobs_mc_squid_flop",
|
||||
distance = 16,
|
||||
},
|
||||
animation = {
|
||||
|
@ -43,7 +46,8 @@ mobs:register_mob("mobs_mc:guardian", {
|
|||
{name = mobs_mc.items.prismarine_shard,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 32,},
|
||||
max = 32,
|
||||
looting = "common",},
|
||||
-- TODO: Reduce of drops when ocean monument is ready.
|
||||
|
||||
-- The following drops are approximations
|
||||
|
@ -51,31 +55,42 @@ mobs:register_mob("mobs_mc:guardian", {
|
|||
{name = mobs_mc.items.fish_raw,
|
||||
chance = 4,
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "common",},
|
||||
{name = mobs_mc.items.prismarine_crystals,
|
||||
chance = 4,
|
||||
min = 1,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
|
||||
-- Rare drop: fish
|
||||
{name = mobs_mc.items.fish_raw,
|
||||
chance = 160, -- 2.5% / 4
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "rare",
|
||||
looting_factor = 0.0025,},
|
||||
{name = mobs_mc.items.salmon_raw,
|
||||
chance = 160,
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "rare",
|
||||
looting_factor = 0.0025,},
|
||||
{name = mobs_mc.items.clownfish_raw,
|
||||
chance = 160,
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "rare",
|
||||
looting_factor = 0.0025,},
|
||||
{name = mobs_mc.items.pufferfish_raw,
|
||||
chance = 160,
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "rare",
|
||||
looting_factor = 0.0025,},
|
||||
},
|
||||
fly = true,
|
||||
makes_footstep_sound = false,
|
||||
fly_in = { mobs_mc.items.water_source, mobs_mc.items.river_water_source },
|
||||
jump = false,
|
||||
view_range = 16,
|
||||
|
|
|
@ -11,6 +11,8 @@ mobs:register_mob("mobs_mc:guardian_elder", {
|
|||
spawn_class = "hostile",
|
||||
hp_min = 80,
|
||||
hp_max = 80,
|
||||
xp_min = 10,
|
||||
xp_max = 10,
|
||||
breath_max = -1,
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
|
@ -28,8 +30,12 @@ mobs:register_mob("mobs_mc:guardian_elder", {
|
|||
},
|
||||
visual_size = {x=7, y=7},
|
||||
sounds = {
|
||||
damage = "mobs_mc_squid_hurt",
|
||||
-- TODO: more and better sounds
|
||||
random = "mobs_mc_guardian_random",
|
||||
war_cry = "mobs_mc_guardian_random",
|
||||
damage = {name="mobs_mc_guardian_hurt", gain=0.3},
|
||||
death = "mobs_mc_guardian_death",
|
||||
flop = "mobs_mc_squid_flop",
|
||||
base_pitch = 0.6,
|
||||
distance = 16,
|
||||
},
|
||||
animation = {
|
||||
|
@ -45,7 +51,8 @@ mobs:register_mob("mobs_mc:guardian_elder", {
|
|||
{name = mobs_mc.items.prismarine_shard,
|
||||
chance = 1,
|
||||
min = 1,
|
||||
max = 64,},
|
||||
max = 64,
|
||||
looting = "common",},
|
||||
|
||||
-- TODO: Only drop if killed by player
|
||||
{name = mobs_mc.items.wet_sponge,
|
||||
|
@ -58,31 +65,42 @@ mobs:register_mob("mobs_mc:guardian_elder", {
|
|||
{name = mobs_mc.items.fish_raw,
|
||||
chance = 4,
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "common",},
|
||||
{name = mobs_mc.items.prismarine_crystals,
|
||||
chance = 1,
|
||||
min = 1,
|
||||
max = 10,},
|
||||
max = 10,
|
||||
looting = "common",},
|
||||
|
||||
-- Rare drop: fish
|
||||
{name = mobs_mc.items.fish_raw,
|
||||
chance = 160, -- 2.5% / 4
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "rare",
|
||||
looting_factor = 0.01 / 4,},
|
||||
{name = mobs_mc.items.salmon_raw,
|
||||
chance = 160,
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "rare",
|
||||
looting_factor = 0.01 / 4,},
|
||||
{name = mobs_mc.items.clownfish_raw,
|
||||
chance = 160,
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "rare",
|
||||
looting_factor = 0.01 / 4,},
|
||||
{name = mobs_mc.items.pufferfish_raw,
|
||||
chance = 160,
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "rare",
|
||||
looting_factor = 0.01 / 4,},
|
||||
},
|
||||
fly = true,
|
||||
makes_footstep_sound = false,
|
||||
fly_in = { mobs_mc.items.water_source, mobs_mc.items.river_water_source },
|
||||
jump = false,
|
||||
view_range = 16,
|
||||
|
|
|
@ -96,7 +96,7 @@ local horse = {
|
|||
walk_speed = 25,
|
||||
walk_start = 0,
|
||||
walk_end = 40,
|
||||
run_speed = 50,
|
||||
run_speed = 60,
|
||||
run_start = 0,
|
||||
run_end = 40,
|
||||
},
|
||||
|
@ -106,6 +106,7 @@ local horse = {
|
|||
-- TODO: Separate damage sound
|
||||
damage = "mobs_mc_horse_death",
|
||||
death = "mobs_mc_horse_death",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
distance = 16,
|
||||
},
|
||||
fear_height = 4,
|
||||
|
@ -116,6 +117,8 @@ local horse = {
|
|||
passive = true,
|
||||
hp_min = 15,
|
||||
hp_max = 30,
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
floats = 1,
|
||||
makes_footstep_sound = true,
|
||||
jump = true,
|
||||
|
@ -124,7 +127,8 @@ local horse = {
|
|||
{name = mobs_mc.items.leather,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
},
|
||||
|
||||
do_custom = function(self, dtime)
|
||||
|
@ -350,6 +354,7 @@ mobs:register_mob("mobs_mc:horse", horse)
|
|||
-- Skeleton horse
|
||||
local skeleton_horse = table.copy(horse)
|
||||
skeleton_horse.breath_max = -1
|
||||
skeleton_horse.armor = {undead = 100, fleshy = 100}
|
||||
skeleton_horse.textures = {{"blank.png", "mobs_mc_horse_skeleton.png", "blank.png"}}
|
||||
skeleton_horse.drops = {
|
||||
{name = mobs_mc.items.bone,
|
||||
|
@ -361,6 +366,8 @@ skeleton_horse.sounds = {
|
|||
random = "mobs_mc_skeleton_random",
|
||||
death = "mobs_mc_skeleton_death",
|
||||
damage = "mobs_mc_skeleton_hurt",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
base_pitch = 0.95,
|
||||
distance = 16,
|
||||
}
|
||||
skeleton_horse.harmed_by_heal = true
|
||||
|
@ -369,6 +376,7 @@ mobs:register_mob("mobs_mc:skeleton_horse", skeleton_horse)
|
|||
-- Zombie horse
|
||||
local zombie_horse = table.copy(horse)
|
||||
zombie_horse.breath_max = -1
|
||||
zombie_horse.armor = {undead = 100, fleshy = 100}
|
||||
zombie_horse.textures = {{"blank.png", "mobs_mc_horse_zombie.png", "blank.png"}}
|
||||
zombie_horse.drops = {
|
||||
{name = mobs_mc.items.rotten_flesh,
|
||||
|
@ -377,9 +385,12 @@ zombie_horse.drops = {
|
|||
max = 2,},
|
||||
}
|
||||
zombie_horse.sounds = {
|
||||
random = "mobs_mc_zombie_growl",
|
||||
death = "mobs_mc_zombie_death",
|
||||
damage = "mobs_mc_zombie_hurt",
|
||||
random = "mobs_mc_horse_random",
|
||||
-- TODO: Separate damage sound
|
||||
damage = "mobs_mc_horse_death",
|
||||
death = "mobs_mc_horse_death",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
base_pitch = 0.5,
|
||||
distance = 16,
|
||||
}
|
||||
zombie_horse.harmed_by_heal = true
|
||||
|
@ -394,8 +405,13 @@ donkey.animation = {
|
|||
stand_start = 0, stand_end = 0,
|
||||
walk_start = 0, walk_end = 40,
|
||||
}
|
||||
-- TODO: donkey sounds
|
||||
donkey.sounds = nil
|
||||
donkey.sounds = {
|
||||
random = "mobs_mc_donkey_random",
|
||||
damage = "mobs_mc_donkey_hurt",
|
||||
death = "mobs_mc_donkey_death",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
distance = 16,
|
||||
}
|
||||
donkey.visual_size = { x=horse.visual_size.x*d, y=horse.visual_size.y*d }
|
||||
donkey.collisionbox = {
|
||||
horse.collisionbox[1] * d,
|
||||
|
@ -415,7 +431,8 @@ local m = 0.94
|
|||
local mule = table.copy(donkey)
|
||||
mule.textures = {{"blank.png", "mobs_mc_mule.png", "blank.png"}}
|
||||
mule.visual_size = { x=horse.visual_size.x*m, y=horse.visual_size.y*m }
|
||||
mule.sounds = horse.sounds
|
||||
mule.sounds = table.copy(donkey.sounds)
|
||||
mule.sounds.base_pitch = 1.15
|
||||
mule.collisionbox = {
|
||||
horse.collisionbox[1] * m,
|
||||
horse.collisionbox[2] * m,
|
||||
|
|
|
@ -29,6 +29,8 @@ mobs:register_mob("mobs_mc:llama", {
|
|||
spawn_class = "passive",
|
||||
hp_min = 15,
|
||||
hp_max = 30,
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
passive = false,
|
||||
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.86, 0.45},
|
||||
visual = "mesh",
|
||||
|
@ -46,21 +48,27 @@ mobs:register_mob("mobs_mc:llama", {
|
|||
runaway = true,
|
||||
walk_velocity = 1,
|
||||
run_velocity = 4.4,
|
||||
follow_velocity = 4.4,
|
||||
floats = 1,
|
||||
drops = {
|
||||
{name = mobs_mc.items.leather,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
},
|
||||
fear_height = 4,
|
||||
sounds = {
|
||||
random = "mobs_mc_llama",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
-- TODO: Death and damage sounds
|
||||
distance = 16,
|
||||
},
|
||||
animation = {
|
||||
speed_normal = 24,
|
||||
run_speed = 60,
|
||||
run_start = 0,
|
||||
run_end = 40,
|
||||
stand_start = 0,
|
||||
stand_end = 0,
|
||||
walk_start = 0,
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
# textdomain: mobs_mc
|
||||
Totem of Undying=Тотем бессмертия
|
||||
A totem of undying is a rare artifact which may safe you from certain death.=Тотем бессмертия это редкий артефакт, способный спасти вас от смерти.
|
||||
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.=Тотем работает только когда вы держите его в руке. Если вы получаете смертельный урон, вы спасаетесь от смерти и получаете второй шанс с 1 HP. Однако тотем при этом уничтожается.
|
||||
Agent=Агент
|
||||
Bat=Летучая мышь
|
||||
Blaze=Ифрит
|
||||
Chicken=Курица
|
||||
Cow=Корова
|
||||
Mooshroom=Гриб
|
||||
Creeper=Крипер
|
||||
Ender Dragon=Дракон Предела
|
||||
Enderman=Эндермен
|
||||
Endermite=Эндермит
|
||||
Ghast=Гаст
|
||||
Elder Guardian=Древний страж
|
||||
Guardian=Страж
|
||||
Horse=Лошадь
|
||||
Skeleton Horse=Скелет лошади
|
||||
Zombie Horse=Зомби-лошадь
|
||||
Donkey=Ослик
|
||||
Mule=Мул
|
||||
Iron Golem=Железный голем
|
||||
Llama=Лама
|
||||
Ocelot=Оцелот
|
||||
Parrot=Попугай
|
||||
Pig=Свинья
|
||||
Polar Bear=Полярный медведь
|
||||
Rabbit=Кролик
|
||||
Killer Bunny=Кролик-убийца
|
||||
Sheep=Овца
|
||||
Shulker=Шалкер
|
||||
Silverfish=Чешуйница
|
||||
Skeleton=Скелет
|
||||
Stray=Странник
|
||||
Wither Skeleton=Скелет-иссушитель
|
||||
Magma Cube=Лавовый куб
|
||||
Slime=Слизняк
|
||||
Snow Golem=Снежный голем
|
||||
Spider=Паук
|
||||
Cave Spider=Пещерный паук
|
||||
Squid=Кальмар
|
||||
Vex=Досаждатель
|
||||
Evoker=Маг
|
||||
Illusioner=Иллюзор
|
||||
Villager=Житель
|
||||
Vindicator=Поборник
|
||||
Zombie Villager=Зомби-житель
|
||||
Witch=Ведьма
|
||||
Wither=Иссушитель
|
||||
Wolf=Волк
|
||||
Husk=Кадавр
|
||||
Zombie=Зомби
|
||||
Zombie Pigman=Зомби-свиночеловек
|
||||
Iron Horse Armor=Железные доспехи лошади
|
||||
Iron horse armor can be worn by horses to increase their protection from harm a bit.=Железные доспехи лошади, надетые на лошадь, немного защищают её от вреда.
|
||||
Golden Horse Armor=Золотые доспехи лошади
|
||||
Golden horse armor can be worn by horses to increase their protection from harm.=Золотые доспехи лошади, надетые на лошадь, защищают её от вреда.
|
||||
Diamond Horse Armor=Алмазные доспехи лошади
|
||||
Diamond horse armor can be worn by horses to greatly increase their protection from harm.=Алмазные доспехи лошади, надетые на лошадь, отлично защищают её от вреда.
|
||||
Place it on a horse to put on the horse armor. Donkeys and mules can't wear horse armor.=Поместите это на лошадь, чтобы одеть лошадь в доспехи. Ослики и мулы не могут носить лошадиные доспехи.
|
||||
Farmer=Фермер
|
||||
Fisherman=Рыбак
|
||||
Fletcher=Лучник
|
||||
Shepherd=Пастух
|
||||
Librarian=Библиотекарь
|
||||
Cartographer=Картограф
|
||||
Armorer=Бронник
|
||||
Leatherworker=Кожевник
|
||||
Butcher=Мясник
|
||||
Weapon Smith=Оружейник
|
||||
Tool Smith=Инструментальщик
|
||||
Cleric=Церковник
|
||||
Nitwit=Нищий
|
||||
Protects you from death while wielding it=Защищает вас от смерти, пока вы владеете им
|
|
@ -32,6 +32,8 @@ local ocelot = {
|
|||
can_despawn = true,
|
||||
hp_min = 10,
|
||||
hp_max = 10,
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
collisionbox = {-0.3, -0.01, -0.3, 0.3, 0.69, 0.3},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_cat.b3d",
|
||||
|
@ -41,6 +43,7 @@ local ocelot = {
|
|||
walk_chance = default_walk_chance,
|
||||
walk_velocity = 1,
|
||||
run_velocity = 3,
|
||||
follow_velocity = 1,
|
||||
floats = 1,
|
||||
runaway = true,
|
||||
fall_damage = 0,
|
||||
|
@ -48,11 +51,12 @@ local ocelot = {
|
|||
sounds = {
|
||||
damage = "mobs_mc_ocelot_hurt",
|
||||
death = "mobs_mc_ocelot_hurt",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
distance = 16,
|
||||
},
|
||||
animation = {
|
||||
speed_normal = 25,
|
||||
speed_run = 50,
|
||||
run_speed = 50,
|
||||
stand_start = 0,
|
||||
stand_end = 0,
|
||||
walk_start = 0,
|
||||
|
@ -105,12 +109,14 @@ cat.order = "roam" -- "sit" or "roam"
|
|||
cat.owner_loyal = true
|
||||
cat.tamed = true
|
||||
cat.runaway = false
|
||||
cat.follow_velocity = 2.4
|
||||
-- Automatically teleport cat to owner
|
||||
cat.do_custom = mobs_mc.make_owner_teleport_function(12)
|
||||
cat.sounds = {
|
||||
random = "mobs_mc_cat_idle",
|
||||
damage = "mobs_mc_cat_hiss",
|
||||
death = "mobs_mc_ocelot_hurt",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
distance = 16,
|
||||
}
|
||||
cat.on_rightclick = function(self, clicker)
|
||||
|
|
|
@ -17,43 +17,53 @@ mobs:register_mob("mobs_mc:parrot", {
|
|||
pathfinding = 1,
|
||||
hp_min = 6,
|
||||
hp_max = 6,
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
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},
|
||||
makes_footstep_sound = true,
|
||||
walk_velocity = 3,
|
||||
run_velocity = 5,
|
||||
-- TODO: sounds
|
||||
sounds = {
|
||||
random = "mobs_mc_parrot_random",
|
||||
damage = {name="mobs_mc_parrot_hurt", gain=0.3},
|
||||
death = {name="mobs_mc_parrot_death", gain=0.6},
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
distance = 16,
|
||||
},
|
||||
drops = {
|
||||
{name = mobs_mc.items.feather,
|
||||
chance = 1,
|
||||
min = 1,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
},
|
||||
animation = {
|
||||
stand_speed = 50,
|
||||
walk_speed = 50,
|
||||
stand_start = 0,
|
||||
stand_end = 0,
|
||||
walk_start = 0,
|
||||
walk_end = 130,
|
||||
--run_start = 0,
|
||||
--run_end = 20,
|
||||
--fly_start = 30,
|
||||
--fly_end = 45,
|
||||
fly_speed = 50,
|
||||
stand_start = 30,
|
||||
stand_end = 45,
|
||||
fly_start = 30,
|
||||
fly_end = 45,
|
||||
walk_start = 30,
|
||||
walk_end = 45,
|
||||
-- TODO: actual walk animation
|
||||
--walk_start = 0,
|
||||
--walk_end = 20,
|
||||
|
||||
-- TODO: more unused animations between 45 and 130
|
||||
},
|
||||
walk_chance = 100,
|
||||
fall_damage = 0,
|
||||
fall_speed = -2.25,
|
||||
attack_type = "dogfight",
|
||||
jump = true,
|
||||
jump_height = 4,
|
||||
floats = 1,
|
||||
physical = true,
|
||||
fly = true,
|
||||
fear_height = 4,
|
||||
makes_footstep_sound = false,
|
||||
fear_height = 0,
|
||||
view_range = 16,
|
||||
follow = mobs_mc.follow.parrot,
|
||||
on_rightclick = function(self, clicker)
|
||||
|
@ -61,6 +71,7 @@ mobs:register_mob("mobs_mc:parrot", {
|
|||
local item = clicker:get_wielded_item()
|
||||
-- Kill parrot if fed with cookie
|
||||
if item:get_name() == mobs_mc.items.cookie then
|
||||
minetest.sound_play("mobs_mc_animal_eat_generic", {object = self.object, max_hear_distance=16}, true)
|
||||
self.health = 0
|
||||
-- Doomed to die
|
||||
self._doomed = true
|
||||
|
@ -79,10 +90,8 @@ mobs:register_mob("mobs_mc:parrot", {
|
|||
|
||||
})
|
||||
|
||||
|
||||
-- Spawn disabled because parrots are not very smart.
|
||||
-- TODO: Re-enable when parrots are finished
|
||||
--mobs:spawn_specific("mobs_mc:parrot", mobs_mc.spawn.jungle, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 30000, 1, mobs_mc.spawn_height.water+1, mobs_mc.spawn_height.overworld_max)
|
||||
-- Parrots spawn rarely in jungles. TODO: Also check for jungle *biome*
|
||||
mobs:spawn_specific("mobs_mc:parrot", {"mcl_core:jungletree", "mcl_core:jungleleaves"}, {"air"}, 0, minetest.LIGHT_MAX+1, 7, 30000, 1, mobs_mc.spawn_height.water+7, mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:parrot", S("Parrot"), "mobs_mc_spawn_icon_parrot.png", 0, true)
|
||||
mobs:register_egg("mobs_mc:parrot", S("Parrot"), "mobs_mc_spawn_icon_parrot.png", 0)
|
||||
|
|
|
@ -8,6 +8,8 @@ mobs:register_mob("mobs_mc:pig", {
|
|||
runaway = true,
|
||||
hp_min = 10,
|
||||
hp_max = 10,
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
collisionbox = {-0.45, -0.01, -0.45, 0.45, 0.865, 0.45},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_pig.b3d",
|
||||
|
@ -20,23 +22,26 @@ mobs:register_mob("mobs_mc:pig", {
|
|||
makes_footstep_sound = true,
|
||||
walk_velocity = 1,
|
||||
run_velocity = 3,
|
||||
follow_velocity = 3.4,
|
||||
drops = {
|
||||
{name = mobs_mc.items.porkchop_raw,
|
||||
chance = 1,
|
||||
min = 1,
|
||||
max = 3,},
|
||||
max = 3,
|
||||
looting = "common",},
|
||||
},
|
||||
fear_height = 4,
|
||||
sounds = {
|
||||
random = "mobs_pig",
|
||||
death = "mobs_pig_angry",
|
||||
damage = "mobs_pig",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
distance = 16,
|
||||
},
|
||||
animation = {
|
||||
stand_speed = 40,
|
||||
walk_speed = 40,
|
||||
run_speed = 50,
|
||||
run_speed = 90,
|
||||
stand_start = 0,
|
||||
stand_end = 0,
|
||||
walk_start = 0,
|
||||
|
@ -45,7 +50,7 @@ mobs:register_mob("mobs_mc:pig", {
|
|||
run_end = 40,
|
||||
},
|
||||
follow = mobs_mc.follow.pig,
|
||||
view_range = 5,
|
||||
view_range = 8,
|
||||
do_custom = function(self, dtime)
|
||||
|
||||
-- set needed values if not already present
|
||||
|
@ -78,7 +83,6 @@ mobs:register_mob("mobs_mc:pig", {
|
|||
if self.driver then
|
||||
mobs.detach(self.driver, {x = 1, y = 0, z = 1})
|
||||
end
|
||||
|
||||
end,
|
||||
|
||||
on_rightclick = function(self, clicker)
|
||||
|
|
|
@ -14,6 +14,8 @@ mobs:register_mob("mobs_mc:polar_bear", {
|
|||
passive = false,
|
||||
hp_min = 30,
|
||||
hp_max = 30,
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
breath_max = -1,
|
||||
collisionbox = {-0.7, -0.01, -0.7, 0.7, 1.39, 0.7},
|
||||
visual = "mesh",
|
||||
|
@ -34,17 +36,26 @@ mobs:register_mob("mobs_mc:polar_bear", {
|
|||
{name = mobs_mc.items.fish_raw,
|
||||
chance = 2,
|
||||
min = 0,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
-- 1/4 to drop raw salmon
|
||||
{name = mobs_mc.items.salmon_raw,
|
||||
chance = 4,
|
||||
min = 0,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
|
||||
},
|
||||
floats = 1,
|
||||
fear_height = 4,
|
||||
-- TODO: sounds
|
||||
sounds = {
|
||||
random = "mobs_mc_bear_random",
|
||||
attack = "mobs_mc_bear_attack",
|
||||
damage = "mobs_mc_bear_hurt",
|
||||
death = "mobs_mc_bear_death",
|
||||
war_cry = "mobs_mc_bear_growl",
|
||||
distance = 16,
|
||||
},
|
||||
animation = {
|
||||
speed_normal = 25, speed_run = 50,
|
||||
stand_start = 0, stand_end = 0,
|
||||
|
|
|
@ -10,6 +10,8 @@ local rabbit = {
|
|||
|
||||
hp_min = 3,
|
||||
hp_max = 3,
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.49, 0.2},
|
||||
|
||||
visual = "mesh",
|
||||
|
@ -23,19 +25,25 @@ local rabbit = {
|
|||
{"mobs_mc_rabbit_black.png"},
|
||||
},
|
||||
visual_size = {x=1.5, y=1.5},
|
||||
-- TODO: sounds: random, damage, death
|
||||
sounds = {
|
||||
random = "mobs_mc_rabbit_random",
|
||||
damage = "mobs_mc_rabbit_hurt",
|
||||
death = "mobs_mc_rabbit_death",
|
||||
attack = "mobs_mc_rabbit_attack",
|
||||
eat = "mobs_mc_animal_eat_generic",
|
||||
distance = 16,
|
||||
},
|
||||
makes_footstep_sound = false,
|
||||
walk_velocity = 1,
|
||||
run_velocity = 3.7,
|
||||
follow_velocity = 1.1,
|
||||
floats = 1,
|
||||
runaway = true,
|
||||
jump = true,
|
||||
drops = {
|
||||
{name = mobs_mc.items.rabbit_raw, chance = 1, min = 0, max = 1},
|
||||
{name = mobs_mc.items.rabbit_hide, chance = 1, min = 0, max = 1},
|
||||
{name = mobs_mc.items.rabbit_foot, chance = 10, min = 0, max = 1},
|
||||
-- TODO: Drop rabbit's foot when it's useful
|
||||
--{name = mobs_mc.items.rabbit_foot, chance = 10, min = 1, max = 1},
|
||||
{name = mobs_mc.items.rabbit_raw, chance = 1, min = 0, max = 1, looting = "common",},
|
||||
{name = mobs_mc.items.rabbit_hide, chance = 1, min = 0, max = 1, looting = "common",},
|
||||
{name = mobs_mc.items.rabbit_foot, chance = 10, min = 0, max = 1, looting = "rare", looting_factor = 0.03,},
|
||||
},
|
||||
fear_height = 4,
|
||||
animation = {
|
||||
|
|
|
@ -47,7 +47,8 @@ mobs:register_mob("mobs_mc:sheep", {
|
|||
spawn_class = "passive",
|
||||
hp_min = 8,
|
||||
hp_max = 8,
|
||||
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.29, 0.45},
|
||||
|
||||
visual = "mesh",
|
||||
|
@ -62,22 +63,25 @@ mobs:register_mob("mobs_mc:sheep", {
|
|||
{name = mobs_mc.items.mutton_raw,
|
||||
chance = 1,
|
||||
min = 1,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
{name = colors["unicolor_white"][1],
|
||||
chance = 1,
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "common",},
|
||||
},
|
||||
fear_height = 4,
|
||||
sounds = {
|
||||
random = "mobs_sheep",
|
||||
death = "mobs_sheep",
|
||||
damage = "mobs_sheep",
|
||||
sounds = "mobs_mc_animal_eat_generic",
|
||||
distance = 16,
|
||||
},
|
||||
animation = {
|
||||
speed_normal = 25, speed_run = 50,
|
||||
stand_start = 40, stand_end = 80,
|
||||
speed_normal = 25, run_speed = 65,
|
||||
stand_start = 40, stand_end = 80,
|
||||
walk_start = 0, walk_end = 40,
|
||||
run_start = 0, run_end = 40,
|
||||
},
|
||||
|
@ -156,7 +160,7 @@ mobs:register_mob("mobs_mc:sheep", {
|
|||
if item:get_name() == mobs_mc.items.shears and not self.gotten and not self.child then
|
||||
self.gotten = true
|
||||
local pos = self.object:get_pos()
|
||||
minetest.sound_play("shears", {pos = pos}, true)
|
||||
minetest.sound_play("mcl_tools_shears_cut", {pos = pos}, true)
|
||||
pos.y = pos.y + 0.5
|
||||
if not self.color then
|
||||
self.color = "unicolor_white"
|
||||
|
|
|
@ -21,6 +21,8 @@ mobs:register_mob("mobs_mc:shulker", {
|
|||
passive = false,
|
||||
hp_min = 30,
|
||||
hp_max = 30,
|
||||
xp_min = 5,
|
||||
xp_max = 5,
|
||||
armor = 150,
|
||||
collisionbox = {-0.5, -0.01, -0.5, 0.5, 0.99, 0.5},
|
||||
visual = "mesh",
|
||||
|
@ -33,9 +35,11 @@ mobs:register_mob("mobs_mc:shulker", {
|
|||
jump = false,
|
||||
drops = {
|
||||
{name = mobs_mc.items.shulker_shell,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 1,},
|
||||
chance = 2,
|
||||
min = 1,
|
||||
max = 1,
|
||||
looting = "rare",
|
||||
looting_factor = 0.0625},
|
||||
},
|
||||
animation = {
|
||||
stand_speed = 25, walk_speed = 25, run_speed = 50, punch_speed = 25,
|
||||
|
@ -75,6 +79,6 @@ mobs:register_arrow("mobs_mc:shulkerbullet", {
|
|||
})
|
||||
|
||||
|
||||
mobs:register_egg("mobs_mc:shulker", S("Schulker"), "mobs_mc_spawn_icon_shulker.png", 0)
|
||||
mobs:register_egg("mobs_mc:shulker", S("Shulker"), "mobs_mc_spawn_icon_shulker.png", 0)
|
||||
|
||||
mobs:spawn_specific("mobs_mc:shulker", mobs_mc.spawn.end_city, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 5000, 2, mobs_mc.spawn_height.end_min, mobs_mc.spawn_height.end_max)
|
||||
|
|
|
@ -12,6 +12,9 @@ mobs:register_mob("mobs_mc:silverfish", {
|
|||
reach = 1,
|
||||
hp_min = 8,
|
||||
hp_max = 8,
|
||||
xp_min = 5,
|
||||
xp_max = 5,
|
||||
armor = {fleshy = 100, arthropod = 100},
|
||||
collisionbox = {-0.4, -0.01, -0.4, 0.4, 0.44, 0.4},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_silverfish.b3d",
|
||||
|
|
|
@ -17,7 +17,10 @@ local skeleton = {
|
|||
spawn_class = "hostile",
|
||||
hp_min = 20,
|
||||
hp_max = 20,
|
||||
xp_min = 6,
|
||||
xp_max = 6,
|
||||
breath_max = -1,
|
||||
armor = {undead = 100, fleshy = 100},
|
||||
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.98, 0.3},
|
||||
pathfinding = 1,
|
||||
group_attack = true,
|
||||
|
@ -43,15 +46,18 @@ local skeleton = {
|
|||
{name = mobs_mc.items.arrow,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
{name = mobs_mc.items.bow,
|
||||
chance = 11,
|
||||
chance = 100 / 8.5,
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "rare",},
|
||||
{name = mobs_mc.items.bone,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
|
||||
-- Head
|
||||
-- TODO: Only drop if killed by charged creeper
|
||||
|
@ -75,7 +81,7 @@ local skeleton = {
|
|||
die_speed = 15,
|
||||
die_loop = false,
|
||||
},
|
||||
sunlight_damage = 1,
|
||||
ignited_by_sunlight = true,
|
||||
view_range = 16,
|
||||
fear_height = 4,
|
||||
attack_type = "dogshoot",
|
||||
|
@ -113,12 +119,21 @@ stray.textures = {
|
|||
-- TODO: different sound (w/ echo)
|
||||
-- TODO: stray's arrow inflicts slowness status
|
||||
table.insert(stray.drops, {
|
||||
-- Chance to drop additional arrow.
|
||||
-- TODO: Should be tipped arrow of slowness
|
||||
name = mobs_mc.items.arrow,
|
||||
name = "mcl_potions:slowness_arrow",
|
||||
chance = 2,
|
||||
min = 1,
|
||||
max = 1,
|
||||
looting = "rare",
|
||||
looting_chance_function = function(lvl)
|
||||
local chance = 0.5
|
||||
for i = 1, lvl do
|
||||
if chance > 1 then
|
||||
return 1
|
||||
end
|
||||
chance = chance + (1 - chance) / 2
|
||||
end
|
||||
return chance
|
||||
end,
|
||||
})
|
||||
|
||||
mobs:register_mob("mobs_mc:stray", stray)
|
||||
|
|
|
@ -14,7 +14,10 @@ mobs:register_mob("mobs_mc:witherskeleton", {
|
|||
spawn_class = "hostile",
|
||||
hp_min = 20,
|
||||
hp_max = 20,
|
||||
xp_min = 6,
|
||||
xp_max = 6,
|
||||
breath_max = -1,
|
||||
armor = {undead = 100, fleshy = 100},
|
||||
pathfinding = 1,
|
||||
group_attack = true,
|
||||
collisionbox = {-0.35, -0.01, -0.35, 0.35, 2.39, 0.35},
|
||||
|
@ -42,17 +45,20 @@ mobs:register_mob("mobs_mc:witherskeleton", {
|
|||
{name = mobs_mc.items.coal,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "common",},
|
||||
{name = mobs_mc.items.bone,
|
||||
chance = 1,
|
||||
min = 0,
|
||||
max = 2,},
|
||||
max = 2,
|
||||
looting = "common",},
|
||||
|
||||
-- Head
|
||||
{name = mobs_mc.items.head_wither_skeleton,
|
||||
chance = 40, -- 2.5% chance
|
||||
min = 1,
|
||||
max = 1,},
|
||||
max = 1,
|
||||
looting = "rare",},
|
||||
},
|
||||
animation = {
|
||||
stand_start = 0,
|
||||
|
@ -84,6 +90,7 @@ mobs:register_mob("mobs_mc:witherskeleton", {
|
|||
dogshoot_count_max =0.5,
|
||||
fear_height = 4,
|
||||
harmed_by_heal = true,
|
||||
fire_resistant = true,
|
||||
})
|
||||
|
||||
--spawn
|
||||
|
|
|
@ -51,6 +51,7 @@ local spawn_children_on_die = function(child_mob, children_count, spawn_distance
|
|||
end
|
||||
end, children, self.attack)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -62,6 +63,8 @@ local slime_big = {
|
|||
group_attack = { "mobs_mc:slime_big", "mobs_mc:slime_small", "mobs_mc:slime_tiny" },
|
||||
hp_min = 16,
|
||||
hp_max = 16,
|
||||
xp_min = 4,
|
||||
xp_max = 4,
|
||||
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"}},
|
||||
|
@ -105,7 +108,9 @@ local slime_big = {
|
|||
jump_height = 5.2,
|
||||
fear_height = 0,
|
||||
spawn_small_alternative = "mobs_mc:slime_small",
|
||||
on_die = spawn_children_on_die("mobs_mc:slime_small", 4, 1.0, 1.5)
|
||||
on_die = spawn_children_on_die("mobs_mc:slime_small", 4, 1.0, 1.5),
|
||||
fire_resistant = true,
|
||||
use_texture_alpha = true,
|
||||
}
|
||||
mobs:register_mob("mobs_mc:slime_big", slime_big)
|
||||
|
||||
|
@ -113,6 +118,8 @@ local slime_small = table.copy(slime_big)
|
|||
slime_small.sounds.base_pitch = 1.15
|
||||
slime_small.hp_min = 4
|
||||
slime_small.hp_max = 4
|
||||
slime_small.xp_min = 2
|
||||
slime_small.xp_max = 2
|
||||
slime_small.collisionbox = {-0.51, -0.01, -0.51, 0.51, 1.00, 0.51}
|
||||
slime_small.visual_size = {x=6.25, y=6.25}
|
||||
slime_small.damage = 3
|
||||
|
@ -128,6 +135,8 @@ local slime_tiny = table.copy(slime_big)
|
|||
slime_tiny.sounds.base_pitch = 1.3
|
||||
slime_tiny.hp_min = 1
|
||||
slime_tiny.hp_max = 1
|
||||
slime_tiny.xp_min = 1
|
||||
slime_tiny.xp_max = 1
|
||||
slime_tiny.collisionbox = {-0.2505, -0.01, -0.2505, 0.2505, 0.50, 0.2505}
|
||||
slime_tiny.visual_size = {x=3.125, y=3.125}
|
||||
slime_tiny.damage = 0
|
||||
|
@ -160,6 +169,8 @@ local magma_cube_big = {
|
|||
spawn_class = "hostile",
|
||||
hp_min = 16,
|
||||
hp_max = 16,
|
||||
xp_min = 4,
|
||||
xp_max = 4,
|
||||
collisionbox = {-1.02, -0.01, -1.02, 1.02, 2.03, 1.02},
|
||||
visual_size = {x=12.5, y=12.5},
|
||||
textures = {{ "mobs_mc_magmacube.png" }},
|
||||
|
@ -176,7 +187,7 @@ local magma_cube_big = {
|
|||
run_velocity = 4,
|
||||
damage = 6,
|
||||
reach = 3,
|
||||
armor = 40,
|
||||
armor = 53,
|
||||
drops = {
|
||||
{name = mobs_mc.items.magma_cream,
|
||||
chance = 4,
|
||||
|
@ -211,7 +222,8 @@ local magma_cube_big = {
|
|||
walk_chance = 0,
|
||||
fear_height = 0,
|
||||
spawn_small_alternative = "mobs_mc:magma_cube_small",
|
||||
on_die = spawn_children_on_die("mobs_mc:magma_cube_small", 3, 0.8, 1.5)
|
||||
on_die = spawn_children_on_die("mobs_mc:magma_cube_small", 3, 0.8, 1.5),
|
||||
fire_resistant = true,
|
||||
}
|
||||
mobs:register_mob("mobs_mc:magma_cube_big", magma_cube_big)
|
||||
|
||||
|
@ -220,6 +232,8 @@ magma_cube_small.sounds.jump = "mobs_mc_magma_cube_small"
|
|||
magma_cube_small.sounds.death = "mobs_mc_magma_cube_small"
|
||||
magma_cube_small.hp_min = 4
|
||||
magma_cube_small.hp_max = 4
|
||||
magma_cube_small.xp_min = 2
|
||||
magma_cube_small.xp_max = 2
|
||||
magma_cube_small.collisionbox = {-0.51, -0.01, -0.51, 0.51, 1.00, 0.51}
|
||||
magma_cube_small.visual_size = {x=6.25, y=6.25}
|
||||
magma_cube_small.damage = 3
|
||||
|
@ -229,7 +243,7 @@ magma_cube_small.run_velocity = 2.6
|
|||
magma_cube_small.jump_height = 6
|
||||
magma_cube_small.damage = 4
|
||||
magma_cube_small.reach = 2.75
|
||||
magma_cube_small.armor = 70
|
||||
magma_cube_small.armor = 66
|
||||
magma_cube_small.spawn_small_alternative = "mobs_mc:magma_cube_tiny"
|
||||
magma_cube_small.on_die = spawn_children_on_die("mobs_mc:magma_cube_tiny", 4, 0.6, 1.0)
|
||||
mobs:register_mob("mobs_mc:magma_cube_small", magma_cube_small)
|
||||
|
@ -240,6 +254,8 @@ magma_cube_tiny.sounds.death = "mobs_mc_magma_cube_small"
|
|||
magma_cube_tiny.sounds.base_pitch = 1.25
|
||||
magma_cube_tiny.hp_min = 1
|
||||
magma_cube_tiny.hp_max = 1
|
||||
magma_cube_tiny.xp_min = 1
|
||||
magma_cube_tiny.xp_max = 1
|
||||
magma_cube_tiny.collisionbox = {-0.2505, -0.01, -0.2505, 0.2505, 0.50, 0.2505}
|
||||
magma_cube_tiny.visual_size = {x=3.125, y=3.125}
|
||||
magma_cube_tiny.walk_velocity = 1.02
|
||||
|
@ -247,7 +263,7 @@ magma_cube_tiny.run_velocity = 1.02
|
|||
magma_cube_tiny.jump_height = 4
|
||||
magma_cube_tiny.damage = 3
|
||||
magma_cube_tiny.reach = 2.5
|
||||
magma_cube_tiny.armor = 85
|
||||
magma_cube_tiny.armor = 50
|
||||
magma_cube_tiny.drops = {}
|
||||
magma_cube_tiny.spawn_small_alternative = nil
|
||||
magma_cube_tiny.on_die = nil
|
||||
|
|
|
@ -31,11 +31,16 @@ mobs:register_mob("mobs_mc:snowman", {
|
|||
fall_damage = 0,
|
||||
water_damage = 4,
|
||||
rain_damage = 4,
|
||||
armor = { fleshy = 100, water_vulnerable = 100 },
|
||||
attacks_monsters = true,
|
||||
collisionbox = {-0.35, -0.01, -0.35, 0.35, 1.89, 0.35},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_snowman.b3d",
|
||||
-- TODO: sounds: damage, death
|
||||
sounds = {
|
||||
damage = { name = "mobs_mc_snowman_hurt", gain = 0.2 },
|
||||
death = { name = "mobs_mc_snowman_death", gain = 0.25 },
|
||||
distance = 16,
|
||||
},
|
||||
textures = {
|
||||
"mobs_mc_snowman.png", --snowman texture
|
||||
"farming_pumpkin_side.png", --top
|
||||
|
@ -73,7 +78,7 @@ mobs:register_mob("mobs_mc:snowman", {
|
|||
run_end = 20,
|
||||
die_start = 40,
|
||||
die_end = 50,
|
||||
die_speed = 25,
|
||||
die_speed = 15,
|
||||
die_loop = false,
|
||||
},
|
||||
do_custom = function(self, dtime)
|
||||
|
@ -116,7 +121,7 @@ mobs:register_mob("mobs_mc:snowman", {
|
|||
})
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
minetest.sound_play("shears", {pos = pos}, true)
|
||||
minetest.sound_play("mcl_tools_shears_cut", {pos = pos}, true)
|
||||
|
||||
-- Wear out
|
||||
if not minetest.is_creative_enabled(clicker:get_player_name()) then
|
||||
|
@ -127,6 +132,26 @@ mobs:register_mob("mobs_mc:snowman", {
|
|||
end,
|
||||
})
|
||||
|
||||
local summon_particles = function(obj)
|
||||
local lua = obj:get_luaentity()
|
||||
local min = {x=lua.collisionbox[1], y=lua.collisionbox[2], z=lua.collisionbox[3]}
|
||||
local max = {x=lua.collisionbox[4], y=lua.collisionbox[5], z=lua.collisionbox[6]}
|
||||
local pos = obj:get_pos()
|
||||
minetest.add_particlespawner({
|
||||
amount = 60,
|
||||
time = 0.1,
|
||||
minpos = vector.add(pos, min),
|
||||
maxpos = vector.add(pos, max),
|
||||
minvel = {x = -0.1, y = -0.1, z = -0.1},
|
||||
maxvel = {x = 0.1, y = 0.1, z = 0.1},
|
||||
minexptime = 1.0,
|
||||
maxexptime = 2.0,
|
||||
minsize = 2.0,
|
||||
maxsize = 3.0,
|
||||
texture = "mcl_particles_smoke.png",
|
||||
})
|
||||
end
|
||||
|
||||
-- This is to be called when a pumpkin or jack'o lantern has been placed. Recommended: In the on_construct function
|
||||
-- of the node.
|
||||
-- This summons a snow golen when pos is next to a row of two snow blocks.
|
||||
|
@ -156,7 +181,10 @@ mobs_mc.tools.check_snow_golem_summon = function(pos)
|
|||
core.check_for_falling(pos)
|
||||
core.check_for_falling(b1)
|
||||
core.check_for_falling(b2)
|
||||
minetest.add_entity(place, "mobs_mc:snowman")
|
||||
local obj = minetest.add_entity(place, "mobs_mc:snowman")
|
||||
if obj then
|
||||
summon_particles(obj)
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
|