Compare commits

..

70 Commits

Author SHA1 Message Date
Jordan Irwin
b4b71f5dc8 Cleanup 2021-05-06 21:45:12 -07:00
Jordan Irwin
edb0a24809 Update README 2021-05-06 21:40:38 -07:00
Jordan Irwin
3e007b1ea6 Change to MIT license 2021-05-06 21:40:38 -07:00
Jordan Irwin
02c8bea45e Update changelog 2021-05-06 21:40:38 -07:00
Jordan Irwin
d74dfde51a Add changelog & todo list 2021-05-06 21:40:38 -07:00
Jordan Irwin
e2fe01a10b Add screenshot to README 2021-05-06 21:40:37 -07:00
Jordan Irwin
1fc949bf99 Add mode "inflate" 2021-05-06 21:40:37 -07:00
Jordan Irwin
47185f48c8 Make sneeker follow player 2021-05-06 21:40:37 -07:00
Jordan Irwin
ea4e576ee6 Re-enable "boom" (WIP) 2021-05-06 21:40:37 -07:00
Jordan Irwin
43855a6e6b Fix spawning 2021-05-06 21:40:37 -07:00
Jordan Irwin
9f061a533c Remove combat settings 2021-05-06 21:40:37 -07:00
Jordan Irwin
523492b1a4 Fix rotation 2021-05-06 21:40:37 -07:00
Jordan Irwin
692b36ba59 Cleanup 2021-05-06 21:40:37 -07:00
Jordan Irwin
0e173ccefb Only add gunpower drop if tnt mod available 2021-05-06 21:40:37 -07:00
Jordan Irwin
ae9c9c32dc Add more nodes to spawn on 2021-05-06 21:40:37 -07:00
Jordan Irwin
9046b0fad7 Begin porting to creatures (cmer) mob engine 2021-05-06 21:40:05 -07:00
Jordan Irwin
ff01e876f5 Change default settings 2021-05-06 21:35:00 -07:00
Jordan Irwin
da35fb58ac Cleanup 2021-05-06 21:34:38 -07:00
Jordan Irwin
4db155bd9b Move all settings values into settings.lua 2021-05-06 21:30:26 -07:00
Jordan Irwin
428b88bdda Cleanup logging 2021-05-06 21:28:05 -07:00
Jordan Irwin
2603c721d2 Use asm_spawneggs to create egg 2021-05-06 21:16:44 -07:00
Jordan Irwin
592e247c1c Spawn on nether:rack if nether mod available 2021-05-06 21:11:18 -07:00
Jordan Irwin
a4d47e7e6b Remove WTFPL license 2021-05-06 21:03:18 -07:00
AntumDeluge
9739add50c Set default max light for spawn to 4 2021-05-06 21:03:01 -07:00
AntumDeluge
5eb1de1627 Add settings & set max/min height for spawning:
- sneeker.spawn_minlight
  - Sets the minimum light required for spawn to occur.
- sneeker.spawn_minheight
  - Sets the lowest position at which sneeker can spawn.
- sneeker.spawn_maxheight
  - Sets the highest position at which sneeker can spawn.
2021-05-06 21:01:40 -07:00
AntumDeluge
3497f917f9 Call 'core.*' instead of 'minetest.*' 2021-05-06 20:54:51 -07:00
AntumDeluge
88794f7a8f settings: Use 'enable_debug_mods' instead of 'sneeker.debug' 2021-05-06 20:51:49 -07:00
AntumDeluge
6b94bef75e User alternate message if spawn chance is less than 1% 2021-05-06 20:49:38 -07:00
AntumDeluge
394465e515 Fix 'spawn_cap' 2021-05-06 20:45:58 -07:00
AntumDeluge
a003553309 Set default maximum spawn to 10 2021-05-06 20:42:51 -07:00
AntumDeluge
3f12094bdf Lower spawn rate & chance 2021-05-06 20:41:42 -07:00
AntumDeluge
f26ca5c2b9 Make 'spawn_cap' local to 'spawn.lua' 2021-05-06 20:39:02 -07:00
AntumDeluge
87dec04c58 Make 'spawn_maxlight' local to 'spawn.lua' 2021-05-06 20:34:18 -07:00
AntumDeluge
41bf1ae241 Set 'spawn_maxlight' to 5 for lower spawn rate 2021-05-06 20:29:43 -07:00
AntumDeluge
b271747df7 Change 'spawn_maxlight' default value to '7' 2021-05-06 20:26:20 -07:00
AntumDeluge
d12f80d1f3 Change 'spawn_interval' default to 2 minutes (120) 2021-05-06 20:25:17 -07:00
AntumDeluge
1d9c2ed3c5 Change 'spawn_chance' default to '2' (1/2 or 50%) 2021-05-06 20:23:44 -07:00
AntumDeluge
e96d9da420 Add more debugging output 2021-05-06 20:21:40 -07:00
AntumDeluge
6b8a1b7f82 Fix finding number of active entities in world 2021-05-06 20:19:08 -07:00
AntumDeluge
da60a0f9ab Don't set local 'spawnit' 2021-05-06 20:18:43 -07:00
AntumDeluge
fe42ca01db Add method 'sneeker.get_pos_string':
Returns x, y, z coordinates in a string.
2021-05-06 20:14:21 -07:00
AntumDeluge
21d78e0b65 Add debugging output in case of denied spawn 2021-05-06 20:03:37 -07:00
AntumDeluge
3a3de549bf Fix global name:
- 'sneeker' not 'sneaker'
2021-05-06 19:59:49 -07:00
AntumDeluge
58b239b4ae Minor edit to log message 2021-05-06 19:57:26 -07:00
AntumDeluge
c905656ec8 Changes to 'sneeker.log' method:
Only log message if minetest setting 'log_mods' is 'true'.
2021-05-06 19:56:00 -07:00
AntumDeluge
ea3ab21024 Change debug message in 'sneeker.log_debug' 2021-05-06 19:48:48 -07:00
AntumDeluge
23477fb85f Add debug message to display in log when turned on 2021-05-06 19:48:29 -07:00
AntumDeluge
a73dc9aa39 Put node light in local variable & add debugging output 2021-05-06 19:46:51 -07:00
AntumDeluge
a5025cdfb8 Use setting 'sneeker.spawn_maxlight' to determine node light for spawn 2021-05-06 19:44:49 -07:00
AntumDeluge
439646417a Add method 'sneaker.spawn' to spawn entity 2021-05-06 19:42:16 -07:00
AntumDeluge
1f04669a68 Do not spawn if spawn cap is reached 2021-05-06 19:42:16 -07:00
AntumDeluge
05670a46c7 Put mob & spawnegg names in 'sneeker' attributes 2021-05-06 19:41:57 -07:00
AntumDeluge
af4f5219f1 Set spawn cap at 25 2021-05-06 19:35:02 -07:00
AntumDeluge
43bfded8b2 Change settings naming convention from 'sneeker_*' to 'sneeker.*' 2021-05-06 19:33:34 -07:00
AntumDeluge
517c7afd06 Re-label to 'sneeker' 2021-05-06 19:31:05 -07:00
AntumDeluge
40f0c24552 Move settings variables & functions:
- Settings to 'settings.lua'
- Functions to 'functions.lua'
2021-05-06 19:24:36 -07:00
AntumDeluge
e2badd6a6f Add debugging setting & log method 2021-05-06 19:18:37 -07:00
AntumDeluge
58d9d44c35 Add logging messages 2021-05-06 19:13:35 -07:00
AntumDeluge
3d06833867 settingtypes.txt: Add 'sneaker_spawn_cap' 2021-05-06 19:08:46 -07:00
AntumDeluge
0b7e8b89c6 Change spawn rate:
- Use settings file to set 'chance' & 'interval'
- Set spawn chance to 1/18000 (18000)
- Set spawn interval to 40 minutes (2400)
2021-05-06 19:08:27 -07:00
AntumDeluge
beaff3d886 Add variable 'sneaker.spawn_cap':
Will set maximun number of sneakers that can be spawned in world at one
time.
2021-05-06 19:03:24 -07:00
AntumDeluge
a52acac435 Remove unnecessary variable 'time_sec' 2021-05-06 19:00:40 -07:00
AntumDeluge
c0a53e2340 Add 'sneaker.log' method 2021-05-06 19:00:17 -07:00
AntumDeluge
f838db1cef Set license for new code as CC0 2021-05-06 18:57:53 -07:00
AntumDeluge
c789f39247 Rename 'LICENSE.md' to 'LICENSE-wtfpl.txt' 2021-05-06 18:55:30 -07:00
AntumDeluge
d9602eef55 Set variables 'sneaker.modname' & 'sneaker.modpath' 2021-05-06 18:54:39 -07:00
AntumDeluge
58ac8ed83c Relabel to 'sneaker' 2021-05-06 18:35:19 -07:00
AntumDeluge
b1c3a5a590 Replace deprecated methods:
- 'setting_get' with 'settings:get'
- 'setting_getbool' with 'settings:get_bool'
2021-05-06 18:26:41 -07:00
AntumDeluge
de7cd62f17 Run spawn function every 20 minutes 2021-05-06 18:23:40 -07:00
AntumDeluge
9d4581ec5b Use 'spawneggs' & 'tnt' to craft 'creeper:spawnegg' 2021-05-06 18:21:48 -07:00
18 changed files with 705 additions and 1848 deletions

8
CHANGES.txt Normal file

@ -0,0 +1,8 @@
1.0
- Forked & renamed from Rui's original "creeper" mod.
- Updated for Minetest 5.x API.
- Changed to MIT license.
- Ported to Creatures Revived (cmer) engine.
- Spawn on more types of nodes.
- Spawn on "nether:rack" if nether mod available.

@ -1,40 +1,51 @@
## Sneeker mod for Minetest
---
### Description:
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)
- **Code:** [MIT](LICENSE.txt)
- Original by Rui: WTFPL
---
### Usage:
Settings documented in [reference][].
### Requirements:
- Depends: cmer, default, tnt
- Optional depends: nether, sounds, simple_protection
Settings:
- ***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: 9
- ***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
---
### Links:
- [![ContentDB](https://img.shields.io/static/v1?label=ContentDB&message=sneeker&color=%23375a7f&logo=minetest)](https://content.minetest.net/packages/AntumDeluge/sneeker/)
- [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][reference]
- [Changelog](changelog.txt)
- [Changelog](CHANGES.txt)
- [TODO](TODO.txt)
Rui's original mod:
- Forum thread (deleted: `t=11891`)
- [Final version](https://github.com/AntumMT/mod-sneeker/releases/tag/Rui)
- [Updated for Minetest 5.x](https://github.com/AntumMT/mod-sneeker/releases/tag/5.x)
[reference]: https://antummt.github.io/mod-sneeker/docs/reference/

@ -1,15 +1,5 @@
TODO:
- add version using mobs_redo API
- add version using cmer API
- add griefing option
- add wear to armor when exploding
- disable attacking if damage disabled
- make powered versions run faster when chasing
- fix knockback when chasing
- fix hit sound when chasing
- make sneeker stop when within 2 of player
- use asm_spawneggs for egg
- add localization support
- add Spanish translation
- fix removing single node if protected
- fix walk logic to stop before exploding
- fix sound playthrough
- remove unused setting "sneeker.spawn_cap"

@ -1,27 +0,0 @@
next
----
- uses "sounds" mod
v1.1
----
- added sound when hit
- fixed entity vertical positioning
- fixed tnt:boom node left after explosion
- added setting to customize spawn nodes
- added simple_protection support
v1.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

@ -1,58 +0,0 @@
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

@ -1,13 +0,0 @@
#!/bin/bash
docs="$(dirname $(readlink -f $0))"
root="$(dirname ${docs})"
config="${docs}/config.ld"
cd "${root}"
# Clean old files
rm -rf "${docs}/reference"
# Create new files
ldoc -c "${config}" -d "${docs}/reference" "${root}"

@ -1,519 +0,0 @@
<!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>
<tr>
<td class="name" nowrap><a href="#sneeker.spawn_nodes">sneeker.spawn_nodes</a></td>
<td class="summary">Comma-separated list of nodes on which sneeker can spawn.</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="index.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="index.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>
<dt>
<a name = "sneeker.spawn_nodes"></a>
<strong>sneeker.spawn_nodes</strong>
</dt>
<dd>
Comma-separated list of nodes on which sneeker can spawn.
</ul>
</ul>
</ul>
</ul>
<h3>Type:</h3>
<ul>
<i>string</i>
</ul>
<h3>Default:</h3>
<ul>
<i>default:dirt_with_dry_grass,default:dry_dirt,default:dry_dirt_with_dry_grass,default:desert_sand,nether:rack</i>
</ul>
</ul>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2021-07-20 11:23:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

@ -1,303 +0,0 @@
/* 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; }

@ -1,635 +0,0 @@
local hit_sound
if core.get_modpath("default") then
hit_sound = "player_damage"
elseif core.get_modpath("sounds") then
hit_sound = "sounds_entity_hit"
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 = core.get_node_or_nil(spos)
spos.y = spos.y+1
local node2 = core.get_node_or_nil(spos)
local def, def2 = {}
if node and node.name then
def = core.registered_items[node.name]
end
if node2 and node2.name then
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: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 select_turn == 1 then
self.turn = "left"
elseif select_turn == 2 then
self.turn = "right"
elseif select_turn == 3 then
self.turn = "straight"
end
self.turn_timer = 0
self.turn_speed = 0.05*math.random()
end
end
local walk_speed = 1.5
local def = {
hp_max = 20,
physical = true,
collisionbox = {-0.25, 0.3, -0.25, 0.25, 1.8, 0.25},
visual = "mesh",
mesh = "character.b3d",
textures = {"sneeker.png"},
makes_footstep_sound = false,
-- Original
animation = {
stand_START = 0,
stand_END = 79,
walk_START = 168,
walk_END = 187
},
walk_speed = walk_speed,
jump_height = 5,
animation_speed = 30,
knockback_level = 2
}
]]
local spawn_nodes = {}
if sneeker.spawn_nodes ~= "" then
if not sneeker.spawn_nodes:find(",") then
table.insert(spawn_nodes, sneeker.spawn_nodes)
else
for _, node in ipairs(sneeker.spawn_nodes:split(",")) do
local node = node:trim()
if node ~= "" then
table.insert(spawn_nodes, node)
end
end
end
end
if #spawn_nodes == 0 then
sneeker.log("warning", "no spawning nodes set, cannot spawn")
end
local item_drops = {}
if core.registered_items["tnt:gunpowder"] then
table.insert(item_drops, {"tnt:gunpowder", {min=1, max=2}, chance=0.66})
end
local def = {
name = "sneeker:sneeker",
nametag = "Sneeker",
stats = {
hp = 20,
hostile_2 = true,
lifetime = sneeker.lifetime,
can_jump = 5,
can_swim = true,
has_knockback = true,
sneaky = true,
},
modes = {
idle = {chance=0.3},
walk = {chance=0.7, moving_speed=1.5},
--chase = {moving_speed=1.5},
--death = {},
},
model = {
mesh = "character.b3d",
textures = {"sneeker.png"},
collisionbox = {-0.25, 0.3, -0.25, 0.25, 1.8, 0.25},
rotation = -90,
animations = {
idle = {start=0, stop=79, speed=30},
walk = {start=168, stop=187, speed=30},
--chase = {start=168, stop=187, speed=30},
--death = {},
},
},
--sounds = {},
drops = item_drops,
--[[
combat = {
search_enemy = true,
},
]]
spawning = {
abm_nodes = {
spawn_on = spawn_nodes,
},
abm_interval = sneeker.spawn_interval,
abm_chance = sneeker.spawn_chance,
number = 1,
light = {min=sneeker.spawn_minlight, max=sneeker.spawn_maxlight},
height_limit = {min=sneeker.spawn_minheight, max=sneeker.spawn_maxheight},
},
}
def.on_activate = function(self, staticdata, dtime_s)
--[[
self.yaw = 0
self.anim = 1
self.timer = 0
]]
self.visualx = 1
--[[
self.jump_timer = 0
self.turn_timer = 0
self.turn_speed = 0
]]
self.powered = false
--[[
self.knockback = false
self.state = math.random(1, 2)
self.old_y = self.object:get_pos().y
]]
--[[
-- 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 = {"sneeker_powered.png"}})
end
else
if math.random(0, 20) == 20 then
self.powered = true
self.object:set_properties({textures = {"sneeker_powered.png"}})
end
end
end
local function isnan(n)
return tostring(n) == tostring((-1)^.5)
end
local function expand(self)
if self.expanding and self.visualx < 2 then
if self.hiss == false and sounds then
sounds.fuse(1, {object=self.object, 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}
})
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}
})
self.hiss = false
end
end
local function explode(self, pos)
self.object:remove()
sneeker.boom(pos, self.powered)
end
--[[
local function h_collides(pos, collision_info, touching_ground)
if not touching_ground or type(collision_info) ~= "table" or #collision_info == 0 then
return false
end
local pos_y = math.floor(pos.y)
local h_col
for _, col in ipairs(collision_info) do
local npos = col.node_pos
if npos and col.type == "node" then
-- exclude ground collisions
if math.floor(npos.y) > pos_y then
h_col = col
break
end
end
end
if not h_col then return false end
local h_vel = {
x = math.floor(h_col.new_velocity.x * 10) / 10,
z = math.floor(h_col.new_velocity.z * 10) / 10,
}
return h_vel.x < walk_speed and h_vel.z < walk_speed, h_col.node_pos
end
]]
local function chase(self, target)
-- FIXME: why does setting mode = "chase" not work?
if not self.chase_anim then
self.object:set_animation({x=168, y=187}, 30, 0)
self.chase_anim = true
end
local pos = self.object:get_pos()
local tpos = target:get_pos()
local vec = {x=tpos.x-pos.x, y=tpos.y-pos.y, z=tpos.z-pos.z}
local yaw = math.atan(vec.z/vec.x)+math.pi^2
if tpos.x > pos.x then
yaw = yaw+math.pi
end
yaw = yaw-2
self.object:set_yaw(yaw)
local direction = {x=math.sin(yaw)*-1, y=0, z=math.cos(yaw)}
-- 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=self.object:get_velocity().y, z=direction.z*2.5})
end
end
local function end_chase(self)
self.chasing = nil
self.chase_anim = false
self.mode = "idle"
self.expanding = false
end
def.on_step = function(self, dtime, moveresult)
--[[
-- update lifetime timer
-- FIXME: this is longer than realtime
self.lifetimer = self.lifetimer + dtime_s
if self.lifetimer >= self.lifetime then
-- TODO: should have a death animation
self.object:remove()
return true
end
if self.knockback then
return false
end
local ANIM_STAND = 1
local ANIM_WALK = 2
]]
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
if self.chase or self.state == "chase" or self.state == "walk" then
local collided, npos = h_collides(pos, moveresult.collisions, moveresult.touching_ground)
if collided then
jump(self, npos, self.direction)
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: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
if math.random() > 0.8 then
self.state = "stand"
else
self.state = "walk"
end
self.timer = 0
end
if self.turn == "right" then
self.yaw = self.yaw+self.turn_speed
self.object:set_yaw(self.yaw)
elseif self.turn == "left" then
self.yaw = self.yaw-self.turn_speed
self.object:set_yaw(self.yaw)
end
]]
expand(self)
local players_within_10 = {}
for _, object in ipairs(core.get_objects_inside_radius(pos, 10)) do
if object:is_player() then
table.insert(players_within_10, object)
end
end
if not self.chasing then
self.chasing = players_within_10[1]
end
--[[
self.chase = false
for _, object in ipairs(inside) do
if object:is_player() then
self.state = "chase"
end
end
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.anim = ANIM_STAND
end
random_turn(self)
if velocity.x ~= 0
or velocity.z ~= 0 then
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.anim = ANIM_WALK
end
self.direction = {x=math.sin(yaw)*-1, y=-10, z=math.cos(yaw)}
if self.direction then
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: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}
if velocity.x == 0 or velocity.z == 0
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
self.turn = "right"
end
self.turn_timer = 0
self.turn_speed = 0.05*math.random()
end
end
end
]]
if self.chasing then
if self.chasing:get_hp() > 0 then
self.mode = "chase"
local within_2 = false
for _, object in ipairs(core.get_objects_inside_radius(pos, 2)) do
if object == self.chasing then
within_2 = true
break
end
end
if within_2 then
if self.visualx >= 2 then
explode(self, pos)
self.chasing = nil
return true
end
self.expanding = true
else
self.expanding = false
end
local within_10 = false
for _, object in ipairs(players_within_10) do
if object == self.chasing then
within_10 = true
break
end
end
if within_10 then
-- follow player
chase(self, self.chasing)
return true
end
end
end_chase(self)
--[[
if self.anim ~= ANIM_WALK then
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 = core.get_objects_inside_radius(pos, 2)
-- Boom
if #inside_2 ~= 0 then
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
explode(self, pos)
return true
end
end
end
end
]]
--[[
if #inside ~= 0 then
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
-- 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.anim = ANIM_STAND
end
self.object:set_velocity({x=0, y=velocity.y, z=0})
return
end
end
end
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:set_yaw(self.yaw)
self.direction = {x=math.sin(self.yaw)*-1, y=0, z=math.cos(self.yaw)}
local direction = self.direction
-- 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
end
end
else
self.state = "stand"
end
]]
elseif self.mode == "chase" then
self.mode = "idle"
end
--[[
-- Swim
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:set_velocity({x=0, y=velocity.y+1, z=0})
end
else
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)
if hit_sound then
core.sound_play(hit_sound, {object=self.object}, parameters, true)
end
if self.knockback == false then
local knockback_level = self.knockback_level
self.object:set_velocity({x=dir.x*knockback_level, y=3, z=dir.z*knockback_level})
self.knockback = true
core.after(0.6, function()
self.knockback = false
end)
end
if self.object:get_hp() < 1 then
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 = core.add_item(p, {name="tnt:gunpowder", count=math.random(0, 2)})
end
end
]]
def.get_staticdata = function(self)
return core.serialize({
powered = self.powered
})
end
--[[
core.register_entity("sneeker:sneeker", def)
]]
cmer.register_mob(def)
core.register_craftitem("sneeker:spawnegg", {
description = "Sneeker Spawn Egg",
inventory_image = "sneeker_spawnegg.png",
stack_max = 64,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local pos = pointed_thing.above
pos.y = pos.y+1
core.add_entity(pos, "sneeker:sneeker")
if not core.settings:get_bool("creative_mode", false) then
itemstack:take_item()
end
return itemstack
end
end
})

13
functions.lua Normal file

@ -0,0 +1,13 @@
-- Functions for sneeker mod
-- Spawns a sneeker entity
function sneeker.spawn(pos)
core.add_entity(pos, sneeker.mob_name)
sneeker.log("debug", "Spawned entity \"" .. sneeker.mob_name .. "\" at " .. tostring(pos.x) .. "," .. tostring(pos.y))
end
-- Retrieves pos coordinates in string value
function sneeker.get_pos_string(pos)
return "x=" .. tostring(pos.x) .. ", y=" .. tostring(pos.y) .. ", z=" .. tostring(pos.z)
end

542
init.lua

@ -3,19 +3,19 @@ sneeker = {}
sneeker.modname = core.get_current_modname()
sneeker.modpath = core.get_modpath(sneeker.modname)
local debugging = core.settings:get_bool("enable_debug_mods", false)
sneeker.log = function(lvl, msg)
if lvl == "debug" and not debugging then return end
dofile(sneeker.modpath .. "/settings.lua")
if msg == nil then
sneeker.log = function(lvl, msg)
if lvl == "debug" and not sneeker.debug then return end
if not msg then
msg = lvl
lvl = nil
end
msg = "[" .. sneeker.modname .. "] " .. msg
if lvl == "debug" then
msg = "[DEBUG]" .. msg
lvl = nil;
msg = "[DEBUG] " .. msg
end
if not lvl then
@ -25,12 +25,536 @@ sneeker.log = function(lvl, msg)
end
end
sneeker.log("debug", "Debugging is on")
if core.settings:get_bool("log_mods") then
core.log("action", "Loading mod \"" .. sneeker.modname .. "\" ...")
end
sneeker.mob_name = "sneeker:sneeker"
local old_spawnegg_name = "sneeker:spawnegg"
local scripts = {
"settings",
"functions",
"tnt_function",
"entity",
}
--"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 = core.get_node_or_nil(spos)
spos.y = spos.y+1
local node2 = core.get_node_or_nil(spos)
local def, def2 = {}
if node and node.name then
def = core.registered_items[node.name]
end
if node2 and node2.name then
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: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 select_turn == 1 then
self.turn = "left"
elseif select_turn == 2 then
self.turn = "right"
elseif select_turn == 3 then
self.turn = "straight"
end
self.turn_timer = 0
self.turn_speed = 0.05*math.random()
end
end
local def = {
hp_max = 20,
physical = true,
collisionbox = {-0.25, -0.7, -0.25, 0.25, 0.8, 0.25},
visual = "mesh",
mesh = "character.b3d",
textures = {"sneeker.png"},
makes_footstep_sound = false,
-- Original
animation = {
stand_START = 0,
stand_END = 79,
walk_START = 168,
walk_END = 187
},
walk_speed = 1.5,
jump_height = 5,
animation_speed = 30,
knockback_level = 2
}
]]
local sneeker_on_activate = function(self, staticdata)
--[[
self.yaw = 0
self.anim = 1
]]
self.timer = 0
self.visualx = 1
--[[
self.jump_timer = 0
self.turn_timer = 0
self.turn_speed = 0
]]
self.powered = false
--[[
self.knockback = false
self.state = math.random(1, 2)
self.old_y = self.object:get_pos().y
]]
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 = {"sneeker_powered.png"}})
end
else
if math.random(0, 20) == 20 then
self.powered = true
self.object:set_properties({textures = {"sneeker_powered.png"}})
end
end
end
local function isnan(n)
return tostring(n) == tostring((-1)^.5)
end
local sneeker_on_step = function(self, dtime)
if self.stunned then return false end
local pos = self.object:get_pos()
local inside = core.get_objects_inside_radius(pos, 10)
local velocity = self.object:get_velocity()
self.timer = self.timer+0.01
if self.mode == "follow" and self.visualx < 2 then
if not self.hiss then
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}
})
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}
})
self.hiss = false
end
for _, object in ipairs(inside) do
if object:is_player() then
self.mode = "follow"
end
end
if self.mode == "follow" then
local inside_2 = core.get_objects_inside_radius(pos, 2)
-- boom
if #inside_2 ~= 0 then
for _, object in ipairs(inside_2) do
if object:is_player() and object:get_hp() ~= 0 then
if self.visualx >= 2 then
self.object:remove()
sneeker.boom(pos, self.powered)
core.sound_play("sneeker_explode", {pos=pos, gain=1.5, max_hear_distance=2*64})
return true
end
end
end
end
if #inside > 0 then
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
-- 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.anim = ANIM_STAND
end
]]
--self.object:set_velocity({x=0, y=velocity.y, z=0})
return false
end
end
end
-- follow player
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:set_yaw(self.yaw)
self.direction = {x=math.sin(self.yaw)*-1, y=0, z=math.cos(self.yaw)}
local direction = self.direction
local dir_x = direction.x*2.5
local dir_y = velocity.y
local dir_z = direction.z*2.5
if not isnan(dir_x) and not isnan(dir_y) and not isnan(dir_z) then
self.object:set_velocity({x=direction.x*2.5, y=velocity.y, z=direction.z*2.5})
else
sneeker.log("warning", "Found NaN")
for k, v in ipairs({x=dir_x, y=dir_y, z=dir_z}) do
if isnan(v) then
sneeker.log("warning", "\"" .. k .. "\" is not a number: " .. tostring(v))
end
end
end
end
end
end
end
--[[
if self.knockback then
return
end
local ANIM_STAND = 1
local ANIM_WALK = 2
local pos = self.object:get_pos()
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: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
if math.random() > 0.8 then
self.state = "stand"
else
self.state = "walk"
end
self.timer = 0
end
if self.turn == "right" then
self.yaw = self.yaw+self.turn_speed
self.object:set_yaw(self.yaw)
elseif self.turn == "left" then
self.yaw = self.yaw-self.turn_speed
self.object:set_yaw(self.yaw)
end
if self.chase and self.visualx < 2 then
if self.hiss == false then
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}
})
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}
})
self.hiss = false
end
self.chase = false
for _, object in ipairs(inside) do
if object:is_player() then
self.state = "chase"
end
end
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.anim = ANIM_STAND
end
random_turn(self)
if velocity.x ~= 0
or velocity.z ~= 0 then
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.anim = ANIM_WALK
end
self.direction = {x=math.sin(yaw)*-1, y=-10, z=math.cos(yaw)}
if self.direction then
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: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}
if velocity.x == 0 or velocity.z == 0
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
self.turn = "right"
end
self.turn_timer = 0
self.turn_speed = 0.05*math.random()
end
end
-- Jump
if self.jump_timer > 0.2 then
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.anim = ANIM_WALK
end
self.turn = "straight"
local inside_2 = core.get_objects_inside_radius(pos, 2)
-- Boom
if #inside_2 ~= 0 then
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()
sneeker.boom(pos, self.powered)
core.sound_play("sneeker_explode", {pos=pos, gain=1.5, max_hear_distance=2*64})
end
end
end
end
if #inside ~= 0 then
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
-- 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.anim = ANIM_STAND
end
self.object:set_velocity({x=0, y=velocity.y, z=0})
return
end
end
end
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: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:set_velocity({x=direction.x*2.5, y=velocity.y, z=direction.z*2.5})
-- Jump
if self.jump_timer > 0.2 then
jump(self, pos, direction)
end
end
end
else
self.state = "stand"
end
end
-- Swim
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:set_velocity({x=0, y=velocity.y+1, z=0})
end
else
self.object:set_acceleration({x=0, y=-10, z=0})
end
]]
end
--[[
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:set_velocity({x=dir.x*knockback_level, y=3, z=dir.z*knockback_level})
self.knockback = true
core.after(0.6, function()
self.knockback = false
end)
end
if self.object:get_hp() < 1 then
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 = core.add_item(p, {name="tnt:gunpowder", count=math.random(0, 2)})
end
end
]]
local sneeker_get_staticdata = function(self)
return core.serialize({
powered = self.powered
})
end
--core.register_entity(sneeker.mob_name, def)
local spawn_nodes = {
"default:dirt",
"default:dirt_with_grass",
"default:dry_dirt_with_dry_grass",
"default:desert_sand",
"default:sand",
"default:stone",
"default:desert_stone",
}
if core.global_exists("nether") then
table.insert(spawn_nodes, "nether:rack")
end
local drops = nil
if core.global_exists("tnt") then
drops = {
{"tnt:gunpowder", {min=1, max=2}, chance=0.66},
}
end
cmer.register_mob({
name = sneeker.mob_name,
stats = {
hp = 20,
lifetime = 15 * 60, -- 15 minutes
can_jump = 5,
has_kockback = true,
sneaky = true,
},
modes = {
idle = {chance=0.3, moving_speed=0,},
walk = {chance=0.7, moving_speed=1.5,},
follow = {chance=0.0, moving_speed=1.5,},
inflate = {chance=0.0, moving_speed=0,},
},
model = {
mesh = "character.b3d",
textures = {"sneeker.png"},
collisionbox = {-0.25, -0.7, -0.25, 0.25, 0.8, 0.25},
rotation = 270.0,
animations = {
idle = {start=0, stop=79, speed=30,},
walk = {start=168, stop=187, speed=30,},
follow = {start=168, stop=187, speed=30,},
inflate = {start=0, stop=79, speed=30,},
},
},
sounds = {},
drops = drops,
spawning = {
abm_nodes = {
spawn_on = spawn_nodes,
},
abm_interval = sneeker.spawn_interval,
abm_chance = sneeker.spawn_chance,
max_number = 1,
number = 1,
time_range = {min=0, max=23999},
light = {min=sneeker.spawn_minlight, max=sneeker.spawn_maxlight},
height_limit = {min=sneeker.spawn_minheight, max=sneeker.spawn_maxheight},
},
on_step = sneeker_on_step,
on_activate = sneeker_on_activate,
get_staticdata = sneeker_get_staticdata,
})
if core.global_exists("asm") then
asm.addEgg({
name = "sneeker",
inventory_image = "sneeker_spawnegg.png",
spawn = "sneeker:sneeker",
})
core.register_alias(old_spawnegg_name, "spawneggs:sneeker")
if core.registered_items["tnt:tnt"] then
asm.addEggRecipe("sneeker", "tnt:tnt")
end
end

@ -1,9 +1,6 @@
name = sneeker
title = Sneeker
description = An explosive nuisance.
license = MIT
version = 1.1
author = Rui, Jordan Irwin (AntumDeluge)
min_minetest_version = 5.0
author = Rui
depends = cmer, default, tnt
optional_depends = nether, sounds, simple_protection
optional_depends = asm_spawneggs, nether

@ -1,116 +1,53 @@
--- Settings for sneeker mod.
--
-- @module settings.lua
-- Settings for sneeker mod
local time_min = 60
sneeker.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)
sneeker.debug = core.settings:get_bool("enable_debug_mods", false)
--- Loudness of explosion.
--- Sets maximum number of spawns that can exist in world at one time.
--
-- @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)
-- @setting sneeker.spawn_cap
sneeker.spawn_cap = tonumber(core.settings:get("sneeker.spawn_cap")) or 10
--- 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)
sneeker.spawn_chance = tonumber(core.settings:get("sneeker.spawn_chance")) or 10000
--- Sets frequency of spawn chance.
--
-- Default 240 is equivalent to 4 minutes (60 * 4).
--
-- @setting sneeker.spawn_interval
-- @settype int
-- @default 240 (4 minutes)
sneeker.spawn_interval = tonumber(core.settings:get("sneeker.spawn_interval") or time_min * 4)
sneeker.spawn_interval = tonumber(core.settings:get("sneeker.spawn_interval")) or sneeker.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).
-- Default: 0
--
-- @setting sneeker.spawn_minlight
-- @settype int
-- @default 0
sneeker.spawn_minlight = tonumber(core.settings:get("sneeker.spawn_minlight") or 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).
-- Default: 9
--
-- @setting sneeker.spawn_maxlight
-- @settype int
-- @default 4
sneeker.spawn_maxlight = tonumber(core.settings:get("sneeker.spawn_maxlight") or 4)
sneeker.spawn_maxlight = tonumber(core.settings:get("sneeker.spawn_maxlight")) or 9
--- Sets the lowest position at which sneeker can spawn.
--
-- Default: -31000
--
-- @setting sneeker.spawn_minheight
-- @settype int
-- @default -31000
sneeker.spawn_minheight = tonumber(core.settings:get("sneeker.spawn_minheight") or -31000)
sneeker.spawn_minheight = tonumber(core.settings:get("sneeker.spawn_minheight")) or -31000
--- Sets the highest position at which sneeker can spawn.
--
-- Default: 31000
--
-- @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)
--- Comma-separated list of nodes on which sneeker can spawn.
--
-- @setting sneeker.spawn_nodes
-- @settype string
-- @default default:dirt_with_dry_grass,default:dry_dirt,default:dry_dirt_with_dry_grass,default:desert_sand,nether:rack
sneeker.spawn_nodes = core.settings:get("sneeker.spawn_nodes") or "default:dirt_with_dry_grass,default:dry_dirt,default:dry_dirt_with_dry_grass,default:desert_sand,nether:rack"
sneeker.spawn_nodes = sneeker.spawn_nodes:trim()
sneeker.spawn_maxheight = tonumber(core.settings:get("sneeker.spawn_maxheight")) or 31000

@ -1,46 +1,17 @@
# 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 maximum number of spawns that can exist in world.
sneeker.spawn_cap (Sneeker maximum spawns) int 10
# 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
sneeker.spawn_minlight (Sneeker min light for spawn) int 0
# 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
sneeker.spawn_maxlight (Sneeker max light for spawn) int 9
# Sets the lowest position at which sneeker can spawn.
sneeker.spawn_minheight (Sneeker min spawn height) int -31000
@ -48,8 +19,5 @@ 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
# Comma-separated list of nodes on which sneeker can spawn.
sneeker.spawn_nodes (Sneeker spawn nodes) string default:dirt_with_dry_grass,default:dry_dirt,default:dry_dirt_with_dry_grass,default:desert_sand,nether:rack
# Logs extra debug messages.
enable_debug_mods (Enable debugging messages) bool false

BIN
sounds/sneeker_explode.ogg Normal file

Binary file not shown.

BIN
sounds/sneeker_hiss.ogg Normal file

Binary file not shown.

84
spawn.lua Normal file

@ -0,0 +1,84 @@
local time_hr = sneeker.time_min * 60
local time_day = time_hr * 24
-- Display spawn chance as percentage in log
local spawn_chance_percent = math.floor(1 / sneeker.spawn_chance * 100)
if spawn_chance_percent < 1 then
spawn_chance_percent = "Less than 1%"
else
spawn_chance_percent = tostring(spawn_chance_percent) .. "%"
end
sneeker.log("Spawn cap: " .. tostring(sneeker.spawn_cap))
sneeker.log("Spawn chance: " .. spawn_chance_percent)
sneeker.log("Spawn interval: " .. tostring(sneeker.spawn_interval) .. " (" .. tostring(sneeker.spawn_interval/60) .. " minute(s))")
sneeker.log("Maximum light value for spawn: " .. tostring(sneeker.spawn_maxlight))
local spawn_nodes = {"default:dirt_with_grass", "default:stone"}
if core.global_exists("nether") then
table.insert(spawn_nodes, "nether:rack")
end
core.register_abm({
nodenames = spawn_nodes,
neighbors = {"air"},
interval = spawn_interval,
chance = spawn_chance,
action = function(pos, node, _, active_object_count_wider)
if active_object_count_wider > 5 then
return
end
-- Check light value of node
pos.y = pos.y+1
local node_light = core.get_node_light(pos)
-- Debugging spawning
sneeker.log("debug", "Node light level at " .. sneeker.get_pos_string(pos) .. ": " .. tostring(node_light))
-- Node light level
if not node_light or node_light > spawn_maxlight then
sneeker.log("debug", "Node not dark enough for spawn")
return
elseif node_light < spawn_minlight then
sneeker.log("debug", "Node too dark for spawn")
return
end
-- Spawn range
if spawn_minheight ~= nil and pos.y < spawn_minheight then
sneeker.log("debug", "Position is too low for spawn")
return
elseif pos.y > spawn_maxheight then
sneeker.log("debug", "Position is too high for spawn")
return
end
-- Node must be touching air
if core.get_node(pos).name ~= "air" then
return
end
pos.y = pos.y+1
if core.get_node(pos).name ~= "air" then
return
end
-- Get total count of sneekers in world
local count = 0
for I in pairs(core.luaentities) do
if core.luaentities[I].name == sneeker.mob_name then
count = count + 1
end
end
sneeker.log("debug", "Current active spawns: " .. tostring(count) .. "/" .. tostring(spawn_cap))
if count >= spawn_cap then
sneeker.log("debug", "Max spawns reached")
return
end
sneeker.spawn(pos)
end
})

@ -1,107 +1,5 @@
--[[ 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/
]]
-- From TNT
local cid_data = {}
local radius = tonumber(core.settings:get("tnt_radius") or 3)
local large_radius = 5
@ -164,21 +62,8 @@ local function add_drop(drops, item)
end
end
local function is_protected(pos, name) return core.is_protected(pos, name) end
if core.global_exists("simple_protection") and simple_protection.can_access then
is_protected = function(pos, name)
local s_protect_name = name
-- simple_protection ignores names with empty strings
if s_protect_name == "" then
s_protect_name = " "
end
return core.is_protected(pos, name) or not simple_protection.can_access(pos, s_protect_name)
end
end
local function destroy(drops, pos, cid)
if is_protected(pos, "") then
if core.is_protected(pos, "") then
return
end
local def = cid_data[cid]
@ -301,20 +186,15 @@ local function explode(pos, radius)
end
function sneeker.boom(pos, large)
if not pos then return end
local radius = radius
if large then
radius = large_radius
end
if sounds then
sounds.explosion(1, {pos=pos, gain=sneeker.boom_gain, max_hear_distance=2*64})
end
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)
add_effects(pos, radius)
core.remove_node(pos)
end