30 Commits
mobs ... v1.0

Author SHA1 Message Date
Jordan Irwin
eaab253726 Add to changelog 2021-05-08 21:41:57 -07:00
Jordan Irwin
5be4c40e97 Link to doc reference, changelog, & todo list in README 2021-05-08 21:28:41 -07:00
Jordan Irwin
5c75481d8a Add changelog & set version to 1.0 2021-05-08 21:25:02 -07:00
Jordan Irwin
d992f38268 Generate HTML documentation with LDoc 2021-05-08 21:18:58 -07:00
Jordan Irwin
2210eff6bc Add LuaDoc 2021-05-08 21:18:33 -07:00
Jordan Irwin
62175d6a75 Add config & script for generating HTML documentation with LDoc 2021-05-08 21:17:55 -07:00
Jordan Irwin
6205ae4031 Update README 2021-05-08 18:26:39 -07:00
Jordan Irwin
cc73168dd4 Implement method to despawn sneekers that aren't near any players 2021-05-08 18:15:22 -07:00
Jordan Irwin
d741261156 Add lifetime limit 2021-05-08 18:12:19 -07:00
Jordan Irwin
969cac3860 Add setting to adjust loudness of explostion 2021-05-08 16:58:10 -07:00
Jordan Irwin
1aff8fee5b Add option to require nearby players for spawn 2021-05-08 16:01:21 -07:00
Jordan Irwin
b0f464e7ac Add TODO list 2021-05-08 15:26:18 -07:00
Jordan Irwin
e733689692 Add debug message when spawned 2021-05-08 15:19:44 -07:00
Jordan Irwin
0cb069edeb Add setting to chance spawn mapblock limit 2021-05-08 15:19:44 -07:00
Jordan Irwin
94c22a5406 Add some logging 2021-05-08 15:19:41 -07:00
Jordan Irwin
aa6c19dd82 Change spawn nodes...
- Remove: default:dirt_with_grass, default:stone
- Add: default:dirt_with_dry_grass, defaut:dry_dirt, default:dtry_dirt_with_dry_grass, default:desert_sand
2021-05-08 15:06:51 -07:00
Jordan Irwin
7edfb6cb9b Use settings to determine spawn chance, frequency, level, & light requirements 2021-05-08 15:06:48 -07:00
Jordan Irwin
7ca26b4105 Spawn on node nether:rack of nether mod available 2021-05-08 11:53:32 -07:00
Jordan Irwin
b64b6a67db Copy license text from tnt mod for tnt_function.lua module 2021-05-08 11:51:20 -07:00
Jordan Irwin
b9609a5b16 Replace deprecated setting_get methods 2021-05-08 11:44:42 -07:00
Jordan Irwin
be4c3617af Cleanup 2021-05-08 11:42:35 -07:00
Jordan Irwin
b082a746fa Relable to "sneeker" 2021-05-08 11:18:50 -07:00
Jordan Irwin
c29a930352 Change license to MIT 2021-05-08 11:10:20 -07:00
Jordan Irwin
84f6c2f3c9 Hack: check that coordinates are numbers before setting new velocity 2021-05-06 18:01:33 -07:00
Jordan Irwin
6c46f8bf7e Check that tnt is enabled 2021-05-06 18:00:40 -07:00
Jordan Irwin
45b0bf5f08 Update for Minetest 5.x API 2021-05-06 17:58:47 -07:00
Jordan Irwin
6efa22caf4 Fix line endings 2021-05-06 17:32:24 -07:00
Jordan Irwin
b88e4357f9 Add tnt as dependency 2021-05-06 17:14:03 -07:00
Jordan Irwin
cc9cb71090 Whitespace cleanup 2021-05-06 17:13:44 -07:00
Jordan Irwin
a89eb699c9 Move description & dependencies into mod.conf 2021-05-06 17:10:14 -07:00
23 changed files with 1771 additions and 414 deletions

12
CHANGES.txt Normal file
View File

@@ -0,0 +1,12 @@
1.0
- Forked & renamed from Rui's original "creeper" mod.
- Updated for Minetest 5.x API.
- Changed to MIT license.
- Changed spawn nodes:
- default:dirt_with_dry_grass
- default:dry_dirt
- default:dry_dirt_with_dry_grass
- default:desert_sand
- Spawns on "nether:rack" if nether mod available.
- Spawning attributes can now be set in configuration file.

View File

@@ -1,13 +0,0 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

21
LICENSE.txt Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright © 2021 Jordan Irwin (AntumDeluge)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,8 +1,82 @@
# creeper
Adds some explosive nuisance.
## Sneeker mod for Minetest
## Forum Topic
- https://forum.minetest.net/viewtopic.php?t=11891
---
### Description:
## License
- **Code:** WTFPL
An explosive nuisance for [Minetest](http://minetest.net/).
![screenshot](screenshot.png)
---
### Licensing:
- Code: [MIT](LICENSE.txt)
- Original by Rui: WTFPL
- tnt_function code: [MIT](tnt_function.lua)
---
### Usage:
Settings:
- ***sneeker.lifetime***
- How long (in seconds) sneeker remains in world after spawn.
- type: int
- default: 900 (15 minutes)
- ***sneeker.boom_gain***
- Loudness of explosion.
- type: float
- default: 1.5
- ***sneeker.spawn_require_player_nearby***
- Determines whether or not a player must be close for spawn to occur.
- type: bool
- default: true
- ***sneeker.spawn_player_radius***
- Distance a player must be within for spawn to occur.
- type: int
- default: 100
- ***sneeker.despawn_player_far***
- If enabled, mobs not near any players will despawn.
- type: bool
- default: true
- ***sneeker.despawn_player_radius***
- Distance determining if a player is near enough to prevent despawn.
- type: int
- default: 500
- ***sneeker.spawn_chance***
- Sets possibility for spawn.
- type: int
- default: 10000
- ***sneeker.spawn_interval***
- Sets frequency of spawn chance.
- type: int
- default: 240 (4 minutes)
- ***sneeker.spawn_minlight***
- Sets the minimum light that a node must have for spawn to occur.
- type: int
- default: 0
- ***sneeker.spawn_maxlight***
- Sets the maximum light that a node can have for spawn to occur.
- type: int
- default: 4
- ***sneeker.spawn_minheight***
- Sets the maximum light that a node can have for spawn to occur.
- type: int
- default: -31000
- ***sneeker.spawn_maxheight***
- Sets the lowest position at which sneeker can spawn.
- type: int
- default 31000
- ***sneeker.spawn_mapblock_limit***
- Limits the number of entities that can spawn per mapblock (16x16x16).
- type: int
- default: 1
---
### Links:
- [Forum thread](https://forum.minetest.net/viewtopic.php?t=26685)
- [Original forum thread](https://forum.minetest.net/viewtopic.php?t=11891)
- [Git repo](https://github.com/AntumMT/mod-sneeker)
- [Reference](https://antummt.github.io/mod-sneeker/docs/api.html)
- [Changelog](CHANGES.txt)
- [TODO](TODO.txt)

2
TODO.txt Normal file
View File

@@ -0,0 +1,2 @@
TODO:

View File

@@ -1 +0,0 @@
default

View File

@@ -1 +0,0 @@
Adds some explosive nuisance.

488
docs/api.html Normal file
View File

@@ -0,0 +1,488 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Sneeker mod for Minetest</title>
<link rel="stylesheet" href="ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>sneeker</h1>
<h2>Contents</h2>
<ul>
<li><a href="#Settings">Settings</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><strong>settings.lua</strong></li>
</ul>
</div>
<div id="content">
<h1>Module <code>settings.lua</code></h1>
<p>Settings for sneeker mod.</p>
<p>
</p>
<h2><a href="#Settings">Settings</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#sneeker.lifespan">sneeker.lifespan</a></td>
<td class="summary">How long (in seconds) sneeker remains in world after spawn.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.boom_gain">sneeker.boom_gain</a></td>
<td class="summary">Loudness of explosion.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.spawn_require_player_nearby">sneeker.spawn_require_player_nearby</a></td>
<td class="summary">Determines whether or not a player must be close for spawn to occur.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.spawn_player_radius">sneeker.spawn_player_radius</a></td>
<td class="summary">Distance in nodes a player must be for spawn to occur.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.despawn_player_far">sneeker.despawn_player_far</a></td>
<td class="summary">If enabled, mobs not near any players will despawn.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.despawn_player_radius">sneeker.despawn_player_radius</a></td>
<td class="summary">Distance determining if a player is near enough to prevent despawn.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.spawn_chance">sneeker.spawn_chance</a></td>
<td class="summary">Sets possibility for spawn.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.spawn_interval">sneeker.spawn_interval</a></td>
<td class="summary">Sets frequency of spawn chance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.spawn_minlight">sneeker.spawn_minlight</a></td>
<td class="summary">Sets the minimum light that a node must have for spawn to occur.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.spawn_maxlight">sneeker.spawn_maxlight</a></td>
<td class="summary">Sets the maximum light that a node can have for spawn to occur.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.spawn_minheight">sneeker.spawn_minheight</a></td>
<td class="summary">Sets the lowest position at which sneeker can spawn.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.spawn_maxheight">sneeker.spawn_maxheight</a></td>
<td class="summary">Sets the highest position at which sneeker can spawn.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sneeker.spawn_mapblock_limit">sneeker.spawn_mapblock_limit</a></td>
<td class="summary">Limits the number of entities that can spawn per mapblock (16x16x16).</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Settings"></a>Settings</h2>
<dl class="function">
<dt>
<a name = "sneeker.lifespan"></a>
<strong>sneeker.lifespan</strong>
</dt>
<dd>
How long (in seconds) sneeker remains in world after spawn.
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>int</i>
</ul>
<h3>Default:</h3>
<ul>
<i>900 (15 minutes)</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.boom_gain"></a>
<strong>sneeker.boom_gain</strong>
</dt>
<dd>
Loudness of explosion.
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>float</i>
</ul>
<h3>Default:</h3>
<ul>
<i>1.5</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.spawn_require_player_nearby"></a>
<strong>sneeker.spawn_require_player_nearby</strong>
</dt>
<dd>
Determines whether or not a player must be close for spawn to occur.
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>bool</i>
</ul>
<h3>Default:</h3>
<ul>
<i>true</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.spawn_player_radius"></a>
<strong>sneeker.spawn_player_radius</strong>
</dt>
<dd>
Distance in nodes a player must be for spawn to occur. </p>
<p> Only used if <a href="api.html#sneeker.spawn_require_player_nearby">sneeker.spawn_require_player_nearby</a> enabled.
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>int</i>
</ul>
<h3>Default:</h3>
<ul>
<i>100</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.despawn_player_far"></a>
<strong>sneeker.despawn_player_far</strong>
</dt>
<dd>
If enabled, mobs not near any players will despawn.
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>bool</i>
</ul>
<h3>Default:</h3>
<ul>
<i>true</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.despawn_player_radius"></a>
<strong>sneeker.despawn_player_radius</strong>
</dt>
<dd>
Distance determining if a player is near enough to prevent despawn. </p>
<p> Only used if <a href="api.html#sneeker.despawn_player_far">sneeker.despawn_player_far</a> enabled.
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>int</i>
</ul>
<h3>Default:</h3>
<ul>
<i>500</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.spawn_chance"></a>
<strong>sneeker.spawn_chance</strong>
</dt>
<dd>
Sets possibility for spawn. </p>
<p> Inverted value (e.g. 10000 = 1/10000).
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>int</i>
</ul>
<h3>Default:</h3>
<ul>
<i>10000</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.spawn_interval"></a>
<strong>sneeker.spawn_interval</strong>
</dt>
<dd>
Sets frequency of spawn chance.
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>int</i>
</ul>
<h3>Default:</h3>
<ul>
<i>240 (4 minutes)</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.spawn_minlight"></a>
<strong>sneeker.spawn_minlight</strong>
</dt>
<dd>
Sets the minimum light that a node must have for spawn to occur. </p>
<p> Value can be set between 0 (no light) &amp; 15 (max light).
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>int</i>
</ul>
<h3>Default:</h3>
<ul>
<i>0</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.spawn_maxlight"></a>
<strong>sneeker.spawn_maxlight</strong>
</dt>
<dd>
Sets the maximum light that a node can have for spawn to occur. </p>
<p> Value can be set between 0 (no light) &amp; 15 (max light).
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>int</i>
</ul>
<h3>Default:</h3>
<ul>
<i>4</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.spawn_minheight"></a>
<strong>sneeker.spawn_minheight</strong>
</dt>
<dd>
Sets the lowest position at which sneeker can spawn.
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>int</i>
</ul>
<h3>Default:</h3>
<ul>
<i>-31000</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.spawn_maxheight"></a>
<strong>sneeker.spawn_maxheight</strong>
</dt>
<dd>
Sets the highest position at which sneeker can spawn.
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>int</i>
</ul>
<h3>Default:</h3>
<ul>
<i>31000</i>
</ul>
</ul>
</dd>
<dt>
<a name = "sneeker.spawn_mapblock_limit"></a>
<strong>sneeker.spawn_mapblock_limit</strong>
</dt>
<dd>
Limits the number of entities that can spawn per mapblock (16x16x16).
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>int</i>
</ul>
<h3>Default:</h3>
<ul>
<i>1</i>
</ul>
</ul>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/AntumDeluge/LDoc">LDoc 1.4.6-antum-2</a></i>
<i style="float:right;">Last updated 2021-05-08 21:15:42 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

58
docs/config.ld Normal file
View File

@@ -0,0 +1,58 @@
title = "Sneeker mod for Minetest"
project = "sneeker"
format = "markdown"
not_luadoc = true
boilerplate = false
file = {"settings.lua",}
local function italic(value)
return "<i>" .. value .. "</i>"
end
new_type("setting", "Settings")
new_type("chatcmd", "Chat Commands", false, "chatparam")
custom_tags = {
{"type2",
title = "Type",
format = italic,
},
{"dfield",
title = "Definition Fields",
},
{"chatparam",
title = "Parameters",
},
{"option",
title = "Options",
},
{"settype",
title = "Type",
format = italic,
},
{"default",
title = "Default",
format = italic,
},
{"note",
title = "Notes",
format = italic,
},
}
local function chatcmd_handler(item)
local output = item.name
for i, p in ipairs(item.tags.chatparam) do
output = output .. " " .. p
end
return output
end
function custom_display_name_handler(item, default_handler)
if item.type == "chatcmd" then
return chatcmd_handler(item)
end
return default_handler(item)
end

13
docs/gendoc.sh Normal file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
DOCS="$(dirname $(readlink -f $0))"
ROOT="$(dirname ${DOCS})"
CONFIG="${DOCS}/config.ld"
cd "${ROOT}"
# Clean old files
rm -rf "${DOCS}/api.html" "${DOCS}/scripts" "${DOCS}/modules"
# Create new files
ldoc -c "${CONFIG}" -d "${DOCS}" -o "api" "${ROOT}"

303
docs/ldoc.css Normal file
View File

@@ -0,0 +1,303 @@
/* BEGIN RESET
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 2.8.2r1
*/
html {
color: #000;
background: #FFF;
}
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
fieldset,img {
border: 0;
}
address,caption,cite,code,dfn,em,strong,th,var,optgroup {
font-style: inherit;
font-weight: inherit;
}
del,ins {
text-decoration: none;
}
li {
margin-left: 20px;
}
caption,th {
text-align: left;
}
h1,h2,h3,h4,h5,h6 {
font-size: 100%;
font-weight: bold;
}
q:before,q:after {
content: '';
}
abbr,acronym {
border: 0;
font-variant: normal;
}
sup {
vertical-align: baseline;
}
sub {
vertical-align: baseline;
}
legend {
color: #000;
}
input,button,textarea,select,optgroup,option {
font-family: inherit;
font-size: inherit;
font-style: inherit;
font-weight: inherit;
}
input,button,textarea,select {*font-size:100%;
}
/* END RESET */
body {
margin-left: 1em;
margin-right: 1em;
font-family: arial, helvetica, geneva, sans-serif;
background-color: #ffffff; margin: 0px;
}
code, tt { font-family: monospace; font-size: 1.1em; }
span.parameter { font-family:monospace; }
span.parameter:after { content:":"; }
span.types:before { content:"("; }
span.types:after { content:")"; }
.type { font-weight: bold; font-style:italic }
body, p, td, th { font-size: .95em; line-height: 1.2em;}
p, ul { margin: 10px 0 0 0px;}
strong { font-weight: bold;}
em { font-style: italic;}
h1 {
font-size: 1.5em;
margin: 20px 0 20px 0;
}
h2, h3, h4 { margin: 15px 0 10px 0; }
h2 { font-size: 1.25em; }
h3 { font-size: 1.15em; }
h4 { font-size: 1.06em; }
a:link { font-weight: bold; color: #004080; text-decoration: none; }
a:visited { font-weight: bold; color: #006699; text-decoration: none; }
a:link:hover { text-decoration: underline; }
hr {
color:#cccccc;
background: #00007f;
height: 1px;
}
blockquote { margin-left: 3em; }
ul { list-style-type: disc; }
p.name {
font-family: "Andale Mono", monospace;
padding-top: 1em;
}
pre {
background-color: rgb(245, 245, 245);
border: 1px solid #C0C0C0; /* silver */
padding: 10px;
margin: 10px 0 10px 0;
overflow: auto;
font-family: "Andale Mono", monospace;
}
pre.example {
font-size: .85em;
}
table.index { border: 1px #00007f; }
table.index td { text-align: left; vertical-align: top; }
#container {
margin-left: 1em;
margin-right: 1em;
background-color: #f0f0f0;
}
#product {
text-align: center;
border-bottom: 1px solid #cccccc;
background-color: #ffffff;
}
#product big {
font-size: 2em;
}
#main {
background-color: #f0f0f0;
border-left: 2px solid #cccccc;
}
#navigation {
float: left;
width: 14em;
vertical-align: top;
background-color: #f0f0f0;
overflow: visible;
}
#navigation h2 {
background-color:#e7e7e7;
font-size:1.1em;
color:#000000;
text-align: left;
padding:0.2em;
border-top:1px solid #dddddd;
border-bottom:1px solid #dddddd;
}
#navigation ul
{
font-size:1em;
list-style-type: none;
margin: 1px 1px 10px 1px;
}
#navigation li {
text-indent: -1em;
display: block;
margin: 3px 0px 0px 22px;
}
#navigation li li a {
margin: 0px 3px 0px -1em;
}
#content {
margin-left: 14em;
padding: 1em;
width: 700px;
border-left: 2px solid #cccccc;
border-right: 2px solid #cccccc;
background-color: #ffffff;
}
#about {
clear: both;
padding: 5px;
border-top: 2px solid #cccccc;
background-color: #ffffff;
}
@media print {
body {
font: 12pt "Times New Roman", "TimeNR", Times, serif;
}
a { font-weight: bold; color: #004080; text-decoration: underline; }
#main {
background-color: #ffffff;
border-left: 0px;
}
#container {
margin-left: 2%;
margin-right: 2%;
background-color: #ffffff;
}
#content {
padding: 1em;
background-color: #ffffff;
}
#navigation {
display: none;
}
pre.example {
font-family: "Andale Mono", monospace;
font-size: 10pt;
page-break-inside: avoid;
}
}
table.module_list {
border-width: 1px;
border-style: solid;
border-color: #cccccc;
border-collapse: collapse;
}
table.module_list td {
border-width: 1px;
padding: 3px;
border-style: solid;
border-color: #cccccc;
}
table.module_list td.name { background-color: #f0f0f0; min-width: 200px; }
table.module_list td.summary { width: 100%; }
table.function_list {
border-width: 1px;
border-style: solid;
border-color: #cccccc;
border-collapse: collapse;
}
table.function_list td {
border-width: 1px;
padding: 3px;
border-style: solid;
border-color: #cccccc;
}
table.function_list td.name { background-color: #f0f0f0; min-width: 200px; }
table.function_list td.summary { width: 100%; }
ul.nowrap {
overflow:auto;
white-space:nowrap;
}
dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;}
dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;}
dl.table h3, dl.function h3 {font-size: .95em;}
/* stop sublists from having initial vertical space */
ul ul { margin-top: 0px; }
ol ul { margin-top: 0px; }
ol ol { margin-top: 0px; }
ul ol { margin-top: 0px; }
/* make the target distinct; helps when we're navigating to a function */
a:target + * {
background-color: #FF9;
}
/* styles for prettification of source */
pre .comment { color: #558817; }
pre .constant { color: #a8660d; }
pre .escape { color: #844631; }
pre .keyword { color: #aa5050; font-weight: bold; }
pre .library { color: #0e7c6b; }
pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
pre .string { color: #8080ff; }
pre .number { color: #f8660d; }
pre .operator { color: #2239a8; font-weight: bold; }
pre .preprocessor, pre .prepro { color: #a33243; }
pre .global { color: #800080; }
pre .user-keyword { color: #800080; }
pre .prompt { color: #558817; }
pre .url { color: #272fc2; text-decoration: underline; }

277
init.lua
View File

@@ -1,45 +1,73 @@
creeper = {}
--[[
-- DISABLED!!!
do return end
--]]
sneeker = {}
sneeker.modname = core.get_current_modname()
sneeker.modpath = core.get_modpath(sneeker.modname)
dofile(minetest.get_modpath("creeper").."/tnt_function.lua")
dofile(minetest.get_modpath("creeper").."/spawn.lua")
local debugging = core.settings:get_bool("enable_debug_mods", false)
sneeker.log = function(lvl, msg)
if lvl == "debug" and not debugging then return end
local function jump(self,pos,direction)
local velocity = self.object:getvelocity()
if minetest.registered_nodes[minetest.get_node(pos).name].climbable then
self.object:setvelocity({x=velocity.x,y=4,z=velocity.z})
if msg == nil then
msg = lvl
lvl = nil
end
msg = "[" .. sneeker.modname .. "] " .. msg
if lvl == "debug" then
msg = "[DEBUG]" .. msg
lvl = nil;
end
if not lvl then
core.log(msg)
else
core.log(lvl, msg)
end
end
local scripts = {
"settings",
"tnt_function",
"spawn",
}
for _, script in ipairs(scripts) do
dofile(sneeker.modpath .. "/" .. script .. ".lua")
end
local function jump(self, pos, direction)
local velocity = self.object:get_velocity()
if core.registered_nodes[core.get_node(pos).name].climbable then
self.object:set_velocity({x=velocity.x, y=4, z=velocity.z})
return
end
local spos = {x=pos.x+direction.x,y=pos.y,z=pos.z+direction.z}
local node = minetest.get_node_or_nil(spos)
local spos = {x=pos.x+direction.x, y=pos.y, z=pos.z+direction.z}
local node = core.get_node_or_nil(spos)
spos.y = spos.y+1
local node2 = minetest.get_node_or_nil(spos)
local def,def2 = {}
local node2 = core.get_node_or_nil(spos)
local def, def2 = {}
if node and node.name then
def = minetest.registered_items[node.name]
def = core.registered_items[node.name]
end
if node2 and node2.name then
def2 = minetest.registered_items[node2.name]
def2 = core.registered_items[node2.name]
end
if def and def.walkable
and def2 and not def2.walkable
and def.drawtype ~= "fencelike" then
self.object:setvelocity({
x=velocity.x*2.2,
y=self.jump_height,
z=velocity.z*2.2
self.object:set_velocity({
x = velocity.x*2.2,
y = self.jump_height,
z = velocity.z*2.2
})
end
end
local function random_turn(self)
if self.turn_timer > math.random(2,5) then
local select_turn = math.random(1,3)
if self.turn_timer > math.random(2, 5) then
local select_turn = math.random(1, 3)
if select_turn == 1 then
self.turn = "left"
elseif select_turn == 2 then
@@ -55,10 +83,10 @@ end
local def = {
hp_max = 20,
physical = true,
collisionbox = {-0.25,-0.7,-0.25, 0.25,0.8,0.25},
collisionbox = {-0.25, -0.7, -0.25, 0.25, 0.8, 0.25},
visual = "mesh",
mesh = "character.b3d",
textures = {"creeper.png"},
textures = {"sneeker.png"},
makes_footstep_sound = false,
-- Original
@@ -74,7 +102,7 @@ local def = {
knockback_level = 2
}
def.on_activate = function(self,staticdata)
def.on_activate = function(self, staticdata)
self.yaw = 0
self.anim = 1
self.timer = 0
@@ -84,45 +112,91 @@ def.on_activate = function(self,staticdata)
self.turn_speed = 0
self.powered = false
self.knockback = false
self.state = math.random(1,2)
self.old_y = self.object:getpos().y
self.state = math.random(1, 2)
self.old_y = self.object:get_pos().y
local data = minetest.deserialize(staticdata)
-- despawning
self.lifetime = sneeker.lifetime
self.lifetimer = 0
self.check_despawn_player_distance = true
local data = core.deserialize(staticdata)
if data and type(data) == "table" then
if data.powered == true then
self.powered = true
self.object:set_properties({textures = {"creeper_powered.png"}})
self.object:set_properties({textures = {"sneeker_powered.png"}})
end
else
if math.random(0,20) == 20 then
if math.random(0, 20) == 20 then
self.powered = true
self.object:set_properties({textures = {"creeper_powered.png"}})
self.object:set_properties({textures = {"sneeker_powered.png"}})
end
end
end
local function isnan(n)
return tostring(n) == tostring((-1)^.5)
end
def.on_step = function(self, dtime)
-- update lifetime timer
-- FIXME: this is longer than realtime
self.lifetimer = self.lifetimer + dtime
if self.lifetimer >= self.lifetime then
-- TODO: should have a death animation
self.object:remove()
return true
end
if self.knockback then
return
return false
end
local ANIM_STAND = 1
local ANIM_WALK = 2
local pos = self.object:getpos()
local yaw = self.object:getyaw()
local inside = minetest.get_objects_inside_radius(pos,10)
local pos = self.object:get_pos()
if sneeker.despawn_player_far then
-- run check about once per 60 seconds
local interval_reached = math.floor(self.lifetimer % 60) == 0
if not interval_reached and not self.check_despawn_player_distance then
self.check_despawn_player_distance = true
end
if interval_reached and self.check_despawn_player_distance then
local player_nearby = false
for _, entity in ipairs(core.get_objects_inside_radius(pos, sneeker.despawn_player_radius)) do
if entity:is_player() then
player_nearby = true
break
end
end
if not player_nearby then
self.object:remove()
return true
end
-- set flag to not check again until next interval
self.check_despawn_player_distance = false
end
end
local yaw = self.object:get_yaw()
local inside = core.get_objects_inside_radius(pos, 10)
local walk_speed = self.walk_speed
local animation = self.animation
local anim_speed = self.animation_speed
local velocity = self.object:getvelocity()
local velocity = self.object:get_velocity()
self.timer = self.timer+0.01
self.turn_timer = self.turn_timer+0.01
self.jump_timer = self.jump_timer+0.01
if not self.chase
and self.timer > math.random(2,5) then
and self.timer > math.random(2, 5) then
if math.random() > 0.8 then
self.state = "stand"
else
@@ -133,32 +207,32 @@ def.on_step = function(self, dtime)
if self.turn == "right" then
self.yaw = self.yaw+self.turn_speed
self.object:setyaw(self.yaw)
self.object:set_yaw(self.yaw)
elseif self.turn == "left" then
self.yaw = self.yaw-self.turn_speed
self.object:setyaw(self.yaw)
self.object:set_yaw(self.yaw)
end
if self.chase and self.visualx < 2 then
if self.hiss == false then
minetest.sound_play("creeper_hiss",{pos=pos,gain=1.5,max_hear_distance=2*64})
core.sound_play("sneeker_hiss", {pos=pos, gain=1.5, max_hear_distance=2*64})
end
self.visualx = self.visualx+0.05
self.object:set_properties({
visual_size = {x=self.visualx,y=1}
visual_size = {x=self.visualx, y=1}
})
self.hiss = true
elseif self.visualx > 1 then
self.visualx = self.visualx-0.05
self.object:set_properties({
visual_size = {x=self.visualx,y=1}
visual_size = {x=self.visualx, y=1}
})
self.hiss = false
end
self.chase = false
for _,object in ipairs(inside) do
for _, object in ipairs(inside) do
if object:is_player() then
self.state = "chase"
end
@@ -166,7 +240,7 @@ def.on_step = function(self, dtime)
if self.state == "stand" then
if self.anim ~= ANIM_STAND then
self.object:set_animation({x=animation.stand_START,y=animation.stand_END},anim_speed,0)
self.object:set_animation({x=animation.stand_START, y=animation.stand_END}, anim_speed, 0)
self.anim = ANIM_STAND
end
@@ -174,31 +248,31 @@ def.on_step = function(self, dtime)
if velocity.x ~= 0
or velocity.z ~= 0 then
self.object:setvelocity({x=0,y=velocity.y,z=0})
self.object:set_velocity({x=0, y=velocity.y, z=0})
end
end
if self.state == "walk" then
if self.anim ~= ANIM_WALK then
self.object:set_animation({x=animation.walk_START,y=animation.walk_END},anim_speed,0)
self.object:set_animation({x=animation.walk_START, y=animation.walk_END}, anim_speed, 0)
self.anim = ANIM_WALK
end
self.direction = {x=math.sin(yaw)*-1,y=-10,z=math.cos(yaw)}
self.direction = {x=math.sin(yaw)*-1, y=-10, z=math.cos(yaw)}
if self.direction then
self.object:setvelocity({x=self.direction.x*walk_speed,y=velocity.y,z=self.direction.z*walk_speed})
self.object:set_velocity({x=self.direction.x*walk_speed, y=velocity.y, z=self.direction.z*walk_speed})
end
random_turn(self)
local velocity = self.object:getvelocity()
local velocity = self.object:get_velocity()
if self.turn_timer > 1 then
local direction = self.direction
local npos = {x=pos.x+direction.x,y=pos.y+0.2,z=pos.z+direction.z}
local npos = {x=pos.x+direction.x, y=pos.y+0.2, z=pos.z+direction.z}
if velocity.x == 0 or velocity.z == 0
or minetest.registered_nodes[minetest.get_node(npos).name].walkable then
local select_turn = math.random(1,2)
or core.registered_nodes[core.get_node(npos).name].walkable then
local select_turn = math.random(1, 2)
if select_turn == 1 then
self.turn = "left"
elseif select_turn == 2 then
@@ -211,67 +285,80 @@ def.on_step = function(self, dtime)
-- Jump
if self.jump_timer > 0.2 then
jump(self,pos,self.direction)
jump(self, pos, self.direction)
end
end
if self.state == "chase" then
if self.anim ~= ANIM_WALK then
self.object:set_animation({x=animation.walk_START,y=animation.walk_END},anim_speed,0)
self.object:set_animation({x=animation.walk_START, y=animation.walk_END}, anim_speed, 0)
self.anim = ANIM_WALK
end
self.turn = "straight"
local inside_2 = minetest.get_objects_inside_radius(pos,2)
local inside_2 = core.get_objects_inside_radius(pos, 2)
-- Boom
if #inside_2 ~= 0 then
for _,object in ipairs(inside_2) do
for _, object in ipairs(inside_2) do
if object:is_player() and object:get_hp() ~= 0 then
self.chase = true
if self.visualx >= 2 then
self.object:remove()
creeper.boom(pos,self.powered)
minetest.sound_play("creeper_explode",{pos=pos,gain=1.5,max_hear_distance=2*64})
sneeker.boom(pos, self.powered)
core.sound_play("sneeker_explode", {pos=pos, gain=sneeker.boom_gain, max_hear_distance=2*64})
return true
end
end
end
end
if #inside ~= 0 then
for _,object in ipairs(inside) do
for _, object in ipairs(inside) do
if object:is_player() and object:get_hp() ~= 0 then
if #inside_2 ~= 0 then
for _,object in ipairs(inside_2) do
for _, object in ipairs(inside_2) do
-- Stop move
if object:is_player() then
if self.anim ~= ANIM_STAND then
self.object:set_animation({x=animation.stand_START,y=animation.stand_END},anim_speed,0)
self.object:set_animation({x=animation.stand_START, y=animation.stand_END}, anim_speed, 0)
self.anim = ANIM_STAND
end
self.object:setvelocity({x=0,y=velocity.y,z=0})
self.object:set_velocity({x=0, y=velocity.y, z=0})
return
end
end
end
local ppos = object:getpos()
self.vec = {x=ppos.x-pos.x,y=ppos.y-pos.y,z=ppos.z-pos.z}
local ppos = object:get_pos()
self.vec = {x=ppos.x-pos.x, y=ppos.y-pos.y, z=ppos.z-pos.z}
self.yaw = math.atan(self.vec.z/self.vec.x)+math.pi^2
if ppos.x > pos.x then
self.yaw = self.yaw+math.pi
end
self.yaw = self.yaw-2
self.object:setyaw(self.yaw)
self.direction = {x=math.sin(self.yaw)*-1,y=0,z=math.cos(self.yaw)}
self.object:set_yaw(self.yaw)
self.direction = {x=math.sin(self.yaw)*-1, y=0, z=math.cos(self.yaw)}
local direction = self.direction
self.object:setvelocity({x=direction.x*2.5,y=velocity.y,z=direction.z*2.5})
-- FIXME: hack
local can_set = true
for _, c in ipairs({direction.x*2.5, direction.z*2.5}) do
if isnan(c) then
can_set = false
break
end
end
if can_set then
self.object:set_velocity({x=direction.x*2.5, y=velocity.y, z=direction.z*2.5})
end
-- Jump
if self.jump_timer > 0.2 then
jump(self,pos,direction)
jump(self, pos, direction)
end
end
end
@@ -281,60 +368,62 @@ def.on_step = function(self, dtime)
end
-- Swim
local node = minetest.get_node(pos)
if minetest.get_item_group(node.name,"water") ~= 0 then
self.object:setacceleration({x=0,y=1,z=0})
local velocity = self.object:getvelocity()
if self.object:getvelocity().y > 5 then
self.object:setvelocity({x=0,y=velocity.y-velocity.y/2,z=0})
local node = core.get_node(pos)
if core.get_item_group(node.name, "water") ~= 0 then
self.object:set_acceleration({x=0, y=1, z=0})
local velocity = self.object:get_velocity()
if self.object:get_velocity().y > 5 then
self.object:set_velocity({x=0, y=velocity.y-velocity.y/2, z=0})
else
self.object:setvelocity({x=0,y=velocity.y+1,z=0})
self.object:set_velocity({x=0, y=velocity.y+1, z=0})
end
else
self.object:setacceleration({x=0,y=-10,z=0})
self.object:set_acceleration({x=0, y=-10, z=0})
end
return true
end
def.on_punch = function(self,puncher,time_from_last_punch,tool_capabilities,dir)
def.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if self.knockback == false then
local knockback_level = self.knockback_level
self.object:setvelocity({x=dir.x*knockback_level,y=3,z=dir.z*knockback_level})
self.object:set_velocity({x=dir.x*knockback_level, y=3, z=dir.z*knockback_level})
self.knockback = true
minetest.after(0.6,function()
core.after(0.6, function()
self.knockback = false
end)
end
if self.object:get_hp() < 1 then
local pos = self.object:getpos()
local x = 1/math.random(1,5)*dir.x
local z = 1/math.random(1,5)*dir.z
local p = {x=pos.x+x,y=pos.y,z=pos.z+z}
local node = minetest.get_node_or_nil(p)
local pos = self.object:get_pos()
local x = 1/math.random(1, 5)*dir.x
local z = 1/math.random(1, 5)*dir.z
local p = {x=pos.x+x, y=pos.y, z=pos.z+z}
local node = core.get_node_or_nil(p)
if node == nil or not node.name or node.name ~= "air" then
p = pos
end
local obj = minetest.add_item(p, {name="tnt:gunpowder",count=math.random(0,2)})
local obj = core.add_item(p, {name="tnt:gunpowder", count=math.random(0, 2)})
end
end
def.get_staticdata = function(self)
return minetest.serialize({
return core.serialize({
powered = self.powered
})
end
minetest.register_entity("creeper:creeper",def)
core.register_entity("sneeker:sneeker", def)
minetest.register_craftitem("creeper:spawnegg",{
description = "Creeper Spawn Egg",
inventory_image = "creeper_spawnegg.png",
core.register_craftitem("sneeker:spawnegg", {
description = "Sneeker Spawn Egg",
inventory_image = "sneeker_spawnegg.png",
stack_max = 64,
on_place = function(itemstack,placer,pointed_thing)
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local pos = pointed_thing.above
pos.y = pos.y+1
minetest.add_entity(pos,"creeper:creeper")
if not minetest.setting_getbool("creative_mode") then
core.add_entity(pos, "sneeker:sneeker")
if not core.settings:get_bool("creative_mode", false) then
itemstack:take_item()
end
return itemstack

7
mod.conf Normal file
View File

@@ -0,0 +1,7 @@
name = sneeker
title = Sneeker
description = An explosive nuisance.
version = 1.0
author = Rui
depends = default, tnt
optional_depends = nether

108
settings.lua Normal file
View File

@@ -0,0 +1,108 @@
--- Settings for sneeker mod.
--
-- @module settings.lua
local time_min = 60
--- How long (in seconds) sneeker remains in world after spawn.
--
-- @setting sneeker.lifespan
-- @settype int
-- @default 900 (15 minutes)
sneeker.lifetime = tonumber(core.settings:get("sneeker.lifetime") or time_min * 15)
--- Loudness of explosion.
--
-- @setting sneeker.boom_gain
-- @settype float
-- @default 1.5
sneeker.boom_gain = tonumber(core.settings:get("sneeker.boom_gain") or 1.5)
--- Determines whether or not a player must be close for spawn to occur.
--
-- @setting sneeker.spawn_require_player_nearby
-- @settype bool
-- @default true
sneeker.spawn_require_player_nearby = core.settings:get_bool("sneeker.spawn_require_player_nearby", true)
--- Distance in nodes a player must be for spawn to occur.
--
-- Only used if `sneeker.spawn_require_player_nearby` enabled.
--
-- @setting sneeker.spawn_player_radius
-- @settype int
-- @default 100
sneeker.spawn_player_radius = tonumber(core.settings:get("sneeker.spawn_player_radius") or 100)
--- If enabled, mobs not near any players will despawn.
--
-- @setting sneeker.despawn_player_far
-- @settype bool
-- @default true
sneeker.despawn_player_far = core.settings:get_bool("sneeker.despawn_player_far", true)
--- Distance determining if a player is near enough to prevent despawn.
--
-- Only used if `sneeker.despawn_player_far` enabled.
--
-- @setting sneeker.despawn_player_radius
-- @settype int
-- @default 500
sneeker.despawn_player_radius = tonumber(core.settings:get("sneeker.despawn_player_radius") or 500)
--- Sets possibility for spawn.
--
-- Inverted value (e.g. 10000 = 1/10000).
--
-- @setting sneeker.spawn_chance
-- @settype int
-- @default 10000
sneeker.spawn_chance = tonumber(core.settings:get("sneeker.spawn_chance") or 10000)
--- Sets frequency of spawn chance.
--
-- @setting sneeker.spawn_interval
-- @settype int
-- @default 240 (4 minutes)
sneeker.spawn_interval = tonumber(core.settings:get("sneeker.spawn_interval") or time_min * 4)
--- Sets the minimum light that a node must have for spawn to occur.
--
-- Value can be set between 0 (no light) & 15 (max light).
--
-- @setting sneeker.spawn_minlight
-- @settype int
-- @default 0
sneeker.spawn_minlight = tonumber(core.settings:get("sneeker.spawn_minlight") or 0)
--- Sets the maximum light that a node can have for spawn to occur.
--
-- Value can be set between 0 (no light) & 15 (max light).
--
-- @setting sneeker.spawn_maxlight
-- @settype int
-- @default 4
sneeker.spawn_maxlight = tonumber(core.settings:get("sneeker.spawn_maxlight") or 4)
--- Sets the lowest position at which sneeker can spawn.
--
-- @setting sneeker.spawn_minheight
-- @settype int
-- @default -31000
sneeker.spawn_minheight = tonumber(core.settings:get("sneeker.spawn_minheight") or -31000)
--- Sets the highest position at which sneeker can spawn.
--
-- @setting sneeker.spawn_maxheight
-- @settype int
-- @default 31000
sneeker.spawn_maxheight = tonumber(core.settings:get("sneeker.spawn_maxheight") or 31000)
--- Limits the number of entities that can spawn per mapblock (16x16x16).
--
-- @setting sneeker.spawn_mapblock_limit
-- @settype int
-- @default 1
sneeker.spawn_mapblock_limit = tonumber(core.settings:get("sneeker.spawn_mapblock_limit") or 1)

52
settingtypes.txt Normal file
View File

@@ -0,0 +1,52 @@
# Extra debugging messages.
enable_debug_mods (Mod debugging) bool false
# How long (in seconds) sneeker remains in world after spawn.
#
# Default: 900 (15 minutes)
sneeker.lifetime (Sneeker lifetime) int 900
# Loudness of explosion.
#
# Those with a weak heart might want to turn it down.
sneeker.boom_gain (Boom volume) float 1.5
# Determines whether or not a player must be close for spawn to occur.
sneeker.spawn_require_player_nearby (Require player nearby for spawn) bool true
# Distance in nodes a player must be for spawn to occur.
#
# Only used if `sneeker.spawn_require_player_nearby` enabled.
sneeker.spawn_player_radius (Player spawn detect radius) int 100
# If enabled, mobs not near any players will despawn.
sneeker.despawn_player_far (Despawn sneekers not near players) bool true
# Distance determining if a player is near enough to prevent despawn.
#
# Only used if `sneeker.despawn_player_far` enabled.
sneeker.despawn_player_radius (Player despawn detect radius) int 500
# Sets possibility for spawn.
#
# Rate is the inverted value (e.g. 1/value).
sneeker.spawn_chance (Sneeker spawn chance) int 10000
# Sets frequency of spawn chance. Default 240 is equivalent to 4 minutes (60 * 4).
sneeker.spawn_interval (Sneeker spawn interval) int 240
# Sets the minimum light that a node must have for spawn to occur.
sneeker.spawn_minlight (Sneeker min light for spawn) int 0 0 15
# Sets the maximum light that a node can have for spawn to occur.
sneeker.spawn_maxlight (Sneeker max light for spawn) int 4 0 15
# Sets the lowest position at which sneeker can spawn.
sneeker.spawn_minheight (Sneeker min spawn height) int -31000
# Sets the highest position at which sneeker can spawn.
sneeker.spawn_maxheight (Sneeker max spawn height) int 31000
# Limits the number of entities that can spawn per mapblock (16x16x16).
sneeker.spawn_mapblock_limit (Sneeker spawn limit) int 1

View File

@@ -1,32 +1,70 @@
minetest.register_abm({
nodenames = {"default:dirt_with_grass","default:stone"},
local spawn_nodes = {
"default:dirt_with_dry_grass",
"default:dry_dirt",
"default:dry_dirt_with_dry_grass",
"default:desert_sand",
}
if core.global_exists("nether") then
table.insert(spawn_nodes, "nether:rack")
end
for _, node_name in ipairs(spawn_nodes) do
if not core.registered_nodes[node_name] then
sneeker.log("warning", "Invalid node for spawn: " .. node_name)
end
end
core.register_abm({
nodenames = spawn_nodes,
neighbors = {"air"},
interval = 30,
chance = 9000,
action = function(pos, node, _, active_object_count_wider)
if active_object_count_wider > 5 then
return
end
interval = sneeker.spawn_interval,
chance = sneeker.spawn_chance,
action = function(pos, node, aoc, aocw)
if aoc >= sneeker.spawn_mapblock_limit then return end
-- check above target node
pos.y = pos.y+1
if not minetest.get_node_light(pos) then
local pos_string = tostring(math.floor(pos.x))
.. "," .. tostring(math.floor(pos.y))
.. "," .. tostring(math.floor(pos.z))
if sneeker.spawn_require_player_nearby then
local player_nearby = false
for _, entity in ipairs(core.get_objects_inside_radius(pos, sneeker.spawn_player_radius)) do
if entity:is_player() then
player_nearby = true
break
end
end
if not player_nearby then return end
end
if pos.y > sneeker.spawn_maxheight or pos.y < sneeker.spawn_minheight then
return
end
if minetest.get_node_light(pos) > 5 then
-- needs two vertical air nodes to spawn
for _, node_pos in ipairs({pos, {x=pos.x, y=pos.y+1, z=pos.z}}) do
if core.get_node(node_pos).name ~= "air" then
return
end
end
local llevel = core.get_node_light(pos)
if not llevel or llevel > sneeker.spawn_maxlight or llevel < sneeker.spawn_minlight then
return
end
if minetest.get_node_light(pos) < -1 then
return
local spawned = core.add_entity(pos, "sneeker:sneeker")
if not spawned then
sneeker.log("warning", "Failed to spawn at: " .. pos_string)
else
sneeker.log("debug", "Spawned at: " .. pos_string)
end
if pos.y > 31000 then
return
end
if minetest.get_node(pos).name ~= "air" then
return
end
pos.y = pos.y+1
if minetest.get_node(pos).name ~= "air" then
return
end
minetest.add_entity(pos,"creeper:creeper")
end
})

View File

Before

Width:  |  Height:  |  Size: 353 B

After

Width:  |  Height:  |  Size: 353 B

View File

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 355 B

View File

Before

Width:  |  Height:  |  Size: 139 B

After

Width:  |  Height:  |  Size: 139 B

View File

Before

Width:  |  Height:  |  Size: 249 B

After

Width:  |  Height:  |  Size: 249 B

View File

@@ -1,14 +1,117 @@
-- From TNT
--[[ From TNT
License of source code
----------------------
The MIT License (MIT)
Copyright (C) 2014-2016 PilzAdam
Copyright (C) 2014-2016 ShadowNinja
Copyright (C) 2016 sofar (sofar@foo-projects.org)
Copyright (C) 2014-2016 Various Minetest developers and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
For more details:
https://opensource.org/licenses/MIT
===================================
Licenses of media
-----------------
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
Copyright (C) 2014-2016 BlockMen
Copyright (C) 2014-2016 ShadowNinja
Copyright (C) 2015-2016 Wuzzy
Copyright (C) 2016 sofar (sofar@foo-projects.org)
Copyright (C) 2018 paramat
You are free to:
Share — copy and redistribute the material in any medium or format.
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
Under the following terms:
Attribution — You must give appropriate credit, provide a link to the license, and
indicate if changes were made. You may do so in any reasonable manner, but not in any way
that suggests the licensor endorses you or your use.
ShareAlike — If you remix, transform, or build upon the material, you must distribute
your contributions under the same license as the original.
No additional restrictions — You may not apply legal terms or technological measures that
legally restrict others from doing anything the license permits.
Notices:
You do not have to comply with the license for elements of the material in the public
domain or where your use is permitted by an applicable exception or limitation.
No warranties are given. The license may not give you all of the permissions necessary
for your intended use. For example, other rights such as publicity, privacy, or moral
rights may limit how you use the material.
For more details:
http://creativecommons.org/licenses/by-sa/3.0/
====================================================
CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
for audio files (found in sounds folder)
TumeniNodes
steveygos93
theneedle.tv
frankelmedico
No Copyright
The person who associated a work with this deed has dedicated the work to the public domain
by waiving all of his or her rights to the work worldwide under copyright law, including all
related and neighboring rights, to the extent allowed by law.
You can copy, modify, distribute and perform the work, even for commercial purposes, all
without asking permission. See Other Information below.
In no way are the patent or trademark rights of any person affected by CC0, nor are the
rights that other persons may have in the work or in how the work is used, such as publicity
or privacy rights.
Unless expressly stated otherwise, the person who associated a work with this deed makes no
warranties about the work, and disclaims liability for all uses of the work, to the fullest
extent permitted by applicable law.
When using or citing the work, you should not imply endorsement by the author or the affirmer.
This license is acceptable for Free Cultural Works.
For more Information:
https://creativecommons.org/publicdomain/zero/1.0/
]]
local cid_data = {}
local radius = tonumber(minetest.setting_get("tnt_radius") or 3)
local radius = tonumber(core.settings:get("tnt_radius") or 3)
local large_radius = 5
local loss_prob = {
["default:cobble"] = 3,
["default:dirt"] = 4,
}
minetest.after(0, function()
for name, def in pairs(minetest.registered_nodes) do
cid_data[minetest.get_content_id(name)] = {
core.after(0, function()
for name, def in pairs(core.registered_nodes) do
cid_data[core.get_content_id(name)] = {
name = name,
drops = def.drops,
flammable = def.groups.flammable,
@@ -34,11 +137,11 @@ local function eject_drops(drops, pos, radius)
item:set_count(count)
end
rand_pos(pos, drop_pos, radius)
local obj = minetest.add_item(drop_pos, item)
local obj = core.add_item(drop_pos, item)
if obj then
obj:get_luaentity().collect = true
obj:setacceleration({x=0, y=-10, z=0})
obj:setvelocity({x=math.random(-3, 3), y=10,
obj:set_acceleration({x=0, y=-10, z=0})
obj:set_velocity({x=math.random(-3, 3), y=10,
z=math.random(-3, 3)})
end
count = count - max
@@ -62,7 +165,7 @@ local function add_drop(drops, item)
end
local function destroy(drops, pos, cid)
if minetest.is_protected(pos, "") then
if core.is_protected(pos, "") then
return
end
local def = cid_data[cid]
@@ -70,9 +173,9 @@ local function destroy(drops, pos, cid)
def.on_blast(vector.new(pos), 1)
return
end
minetest.remove_node(pos)
core.remove_node(pos)
if def then
local node_drops = minetest.get_node_drops(def.name, "")
local node_drops = core.get_node_drops(def.name, "")
for _, item in ipairs(node_drops) do
add_drop(drops, item)
end
@@ -98,14 +201,14 @@ end
local function entity_physics(pos, radius)
-- Make the damage radius larger than the destruction radius
radius = radius * 2
local objs = minetest.get_objects_inside_radius(pos, radius)
local objs = core.get_objects_inside_radius(pos, radius)
for _, obj in pairs(objs) do
local obj_pos = obj:getpos()
local obj_vel = obj:getvelocity()
local obj_pos = obj:get_pos()
local obj_vel = obj:get_velocity()
local dist = math.max(1, vector.distance(pos, obj_pos))
if obj_vel ~= nil then
obj:setvelocity(calc_velocity(pos, obj_pos,
obj:set_velocity(calc_velocity(pos, obj_pos,
obj_vel, radius * 10))
end
@@ -115,7 +218,7 @@ local function entity_physics(pos, radius)
end
local function add_effects(pos, radius)
minetest.add_particlespawner({
core.add_particlespawner({
amount = 128,
time = 1,
minpos = vector.subtract(pos, radius / 2),
@@ -128,7 +231,7 @@ local function add_effects(pos, radius)
maxexptime = 3,
minsize = 8,
maxsize = 16,
texture = "creeper_smoke.png",
texture = "sneeker_smoke.png",
})
end
@@ -146,12 +249,16 @@ local function explode(pos, radius)
local drops = {}
local p = {}
local c_air = minetest.get_content_id("air")
local c_tnt = minetest.get_content_id("tnt:tnt")
local c_tnt_burning = minetest.get_content_id("tnt:tnt_burning")
local c_gunpowder = minetest.get_content_id("tnt:gunpowder")
local c_gunpowder_burning = minetest.get_content_id("tnt:gunpowder_burning")
local c_boom = minetest.get_content_id("tnt:boom")
local c_air = core.get_content_id("air")
local c_tnt = nil
if core.settings:get_bool("enable_tnt", false) then
c_tnt = core.get_content_id("tnt:tnt")
end
local c_tnt_burning = core.get_content_id("tnt:tnt_burning")
local c_gunpowder = core.get_content_id("tnt:gunpowder")
local c_gunpowder_burning = core.get_content_id("tnt:gunpowder_burning")
local c_boom = core.get_content_id("tnt:boom")
for z = -radius, radius do
for y = -radius, radius do
@@ -180,14 +287,14 @@ local function explode(pos, radius)
return drops
end
function creeper.boom(pos,large)
function sneeker.boom(pos, large)
local radius = radius
if large then
radius = large_radius
end
minetest.sound_play("creeper_explode", {pos=pos, gain=1.5, max_hear_distance=2*64})
minetest.set_node(pos, {name="tnt:boom"})
minetest.get_node_timer(pos):start(0.5)
core.sound_play("sneeker_explode", {pos=pos, gain=1.5, max_hear_distance=2*64})
core.set_node(pos, {name="tnt:boom"})
core.get_node_timer(pos):start(0.5)
local drops = explode(pos, radius)
entity_physics(pos, radius)
eject_drops(drops, pos, radius)