Compare commits

..

7 Commits

Author SHA1 Message Date
Brandon 55551069b0 Remove some Crafter files 2020-07-18 15:57:08 -04:00
Brandon 3bbe7a6826 Update api_hook for mcl_mobs definition 2020-07-17 17:47:52 -04:00
Brandon 796c45d4b3 add head code and interaction code from crafter 2020-07-16 19:56:35 -04:00
Brandon 0e797e2c3f localize variables once - not in every loop 2020-07-16 19:48:30 -04:00
Brandon 53d52b3cac formatting 2020-07-16 19:26:56 -04:00
Brandon 0637adf7ef update local calls 2020-07-16 19:25:22 -04:00
Brandon 266fd6fc71 update for head tracking 2020-07-14 20:41:45 -04:00
724 changed files with 5735 additions and 20433 deletions

View File

@ -5,47 +5,47 @@ Wow, thank you! :-)
But first, some things to note:
MineClone 2's development target is to make a free software clone of Minecraft,
***version 1.12***, ***PC edition***, *** + Optifine features supported by the Minetest Engine ***.
***version 1.11***, ***PC edition***.
MineClone 2 is maintained by two persons. Namely, kay27 and EliasFleckenstein. You can find us
in the Minetest forums (forums.minetest.net), in IRC in the #minetest
MineClone 2 is maintained by one person. Namely, Wuzzy. You can find me,
Wuzzy, in the Minetest forums (forums.minetest.net), in IRC in the #minetest
channel on irc.freenode.net. And finally, you can send e-mails to
<eliasfleckenstein@web.de> or <kay27@bk.ru>.
<Wuzzy2@mail.ru>.
There is **no** guarantee we will accept anything from anybody.
There is **no** guarantee I will accept anything from anybody.
By sending us patches or asking us to include your changes in this game,
By sending me patches or asking me to include your changes in this game,
you agree that they fall under the terms of the LGPLv2.1, which basically
means they will become part of a free software.
## The suggested workflow
We don't **dictate** your workflow, but in order to work with us in an efficient
way, you can follow these suggestions:
I don't **dictate** your workflow, but in order to work with me in an efficient
way, you can follow my suggestions.
For small and medium changes:
* Fork the repository
* Do your change in a new branch
* Upload the repository somewhere where it can be accessed from the Internet and
notify us
notify me
For small changes, sending us a patch is also good.
For small changes, sending me a patch is also good.
For big changes: Same as above, but consider notifying us first to avoid
For big changes: Same as above, but consider notifying me first to avoid
duplicate work and possible tears of rejection. ;-)
For trusted people, we might give them direct commit access to this
For people that I trust, I might give them direct commit access to this
repository. In this case, you obviously don't need to fork, but you still
need to show your contributions align with the project goals. We still
reserve the right to revert everything that we don't like.
For bigger changes, we strongly recommend to use feature branches and
need to show your contributions align with the project goals. I still
reserve the right to revert everything that I don't like.
For bigger changes, I strongly recommend to use feature branches and
discuss with me first.
Contributors will be credited in `README.md`.
## Quality remarks
Again: There is ***no*** guarantee we will accept anything from anybody.
But we will gladly take in code from others when we feel it saves us work
Again: There is ***no*** guarantee I will accept anything from anybody.
But I will gladly take in code from others when I feel it saves me work
in the long run.
### Inclusion criteria
@ -79,18 +79,4 @@ Depending on what you add, the chances for inclusion vary:
## Reporting bugs
Report all bugs and missing Minecraft features here:
<https://git.minetest.land/MineClone2/MineClone2/issues>
## Direct discussion
We have an IRC channel! Join us on #mineclone2 in freenode.net.
<ircs://irc.freenode.net:6697/#mineclone2>
## Creating releases
* Launch MineClone2 to make sure it still runs
* Update the version number in README.md
* Use `git tag <version number>` to tag the latest commit with the version number
* Push to repo (don't forget `--tags`!)
* Update ContentDB (https://content.minetest.net/packages/Wuzzy/mineclone2/)
* Update first post in forum thread (https://forum.minetest.net/viewtopic.php?f=50&t=16407)
* Post release announcement and changelog in forums
<https://git.minetest.land/Wuzzy/MineClone2/issues>

View File

@ -70,7 +70,6 @@ Please read <http://minecraft.gamepedia.com/Breaking> to learn how digging times
* `coral_fan=X`: Coral fan (1 = alive, 2 = dead)
* `coral_block=X`: Coral block (1 = alive, 2 = dead)
* `coral_species=X`: Specifies the species of a coral; equal X means equal species
* `set_on_fire=X`: Sets any (not fire-resistant) mob or player on fire for X seconds when touching
#### Footnotes
@ -97,8 +96,6 @@ Please read <http://minecraft.gamepedia.com/Breaking> to learn how digging times
* `carpet=1:` (Wool) carpet
* `stick=1`: Stick
* `water_bucket=1`: Bucket containing a liquid of group “water”
* `enchantability=X`: How good the enchantments are the item gets (1 equals book)
* `enchanted=1`: The item is already enchanted, meaning that it can't be enchanted using an enchanting table
### Material groups
@ -200,7 +197,6 @@ These groups are used mostly for informational purposes
* `building_block=1`: Block is a building block
* `deco_block=1`: Block is a decorational block
## Fake item groups
These groups put similar items together which should all be treated by the gameplay or the GUI as a single item.
You should not add custom items to these groups for no good reason, this is likely to cause a ton of conflicts.

View File

@ -1,7 +1,7 @@
# Missing features in Minetest to recreate Minecraft features
A side goal of the MineClone 2 project is to find any shortcomings of Minetest which make it impossible to recreate a Minecraft feature exactly.
This file lists some of the missing features in Minetest which MineClone 2 would require.
This file lists some of the missing features in Minetest which MineClone 2 would require.MineClone 2 would require.MineClone 2 would require.MineClone 2 would require.
## No workaround possible
For these features, no easy Lua workaround could be found.
@ -20,6 +20,7 @@ For these features, no easy Lua workaround could be found.
## Interface
- Inventory: Hold down right mouse button while holding an item stack to drop items into the slots as you move the mouse. Makes crafting MUCH faster
- Sneak+Leftclick on crafting output crafts as many items as possible and immediately puts it into the player inventory ([issue 5211](https://github.com/minetest/minetest/issues/5211))
- Sneak+click on inventory slot should be able to put items into additional “fallback inventories” if the first inventory is full. Required for large chests
- Sneak+click puts items in different inventories depending on the item type (maybe group-based)? Required for sneak-clicking to armor slots
## Workaround theoretically possible
@ -34,7 +35,6 @@ For these features, a workaround (or hack ;-)) by using Lua is theoretically pos
- Set frequency in which players lose breath. 2 seconds are hardcoded in Minetest, in Minecraft it's 1 second
- Set damage frequency of `damage_per_second`. In Minecraft many things damage players every half-second rather than every second
- Possible to damage players directly when they are with the head inside. This allows to add Minecraft-like suffocation
- Sneak+click on inventory slot should be able to put items into additional “fallback inventories” if the first inventory is full. Useful for large chests
#### Nice-to-haye
- Utility function to rotate pillar-like nodes, requiring only 3 possible orientations (X, Y, Z). Basically this is `minetest.rotate_node` but with less orientations; the purpur pillar would mess up if a mirrored rotation would be possible. This is already implemented in MCL2, See `mcl_util` for more infos

View File

@ -1,8 +1,8 @@
# MineClone 2
An unofficial Minecraft-like game for Minetest. Forked from MineClone by davedevils.
Developed by many people. Not developed or endorsed by Mojang AB.
Developed by Wuzzy and contributors. Not developed or endorsed by Mojang AB.
Version: 0.70.0
Version: 0.66.2
### Gameplay
You start in a randomly-generated world made entirely of cubes. You can explore
@ -14,10 +14,9 @@ Or you can play in “creative mode” in which you can build almost anything in
#### Gameplay summary
* Sandbox-style gameplay, no goals
* Sandbox-style gameplay, no goals (for now)
* Survive: Fight against hostile monsters and hunger
* Mine for ores and other treasures
* Magic: Gain experience and enchant your tools
* Use the collected blocks to create great buildings, your imagination is the limit
* Collect flowers (and other dye sources) and colorize your world
* Find some seeds and start farming
@ -86,8 +85,7 @@ Minetest to learn more.
## Project description
The main goal of **MineClone 2** is to be a clone of Minecraft and to be released as free software.
* **Target of development: Minecraft, PC Edition, version 1.12** (later known as “Java Edition”)
* MineClone2 also includes Optifine features supported by the Minetest
* **Target of development: Minecraft, PC Edition, version 1.11** (later known as “Java Edition”)
* Features of later Minecraft versions might sneak in, but they have a low priority
* In general, Minecraft is aimed to be cloned as good as Minetest currently permits (no hacks)
* Cloning the gameplay has highest priority
@ -104,7 +102,7 @@ big bugs (such as “missing node” errors or even crashes).
The following main features are available:
* Tools, weapons
* Armor
* Armor (unbalanced)
* Crafting system: 2×2 grid, crafting table (3×3 grid), furnace, including a crafting guide
* Chests, large chests, ender chests, shulker boxes
* Furnaces, hoppers
@ -118,10 +116,6 @@ The following main features are available:
* The Nether, a fiery underworld in another dimension
* Redstone circuits (partially)
* Minecarts (partial)
* Status effects (partial)
* Experience
* Enchanting
* Brewing, potions, tipped arrow (partial)
* Boats
* Fire
* Buidling blocks: Stairs, slabs, doors, trapdoors, fences, fence gates, walls
@ -146,9 +140,14 @@ The following main features are available:
The following features are incomplete:
* Generated structures (especially villages)
* NPCs
* Some monsters and animals
* Redstone-related things
* The End
* Enchanting
* Experience
* Status effects
* Brewing, potions, tipped arrows
* Special minecarts
* A couple of non-trivial blocks and items
@ -183,7 +182,7 @@ Technical differences from Minecraft:
## Reporting bugs
Please report all bugs and missing Minecraft features here:
<https://git.minetest.land/MineClone2/MineClone2/issues>
<https://git.minetest.land/Wuzzy/MineClone2/issues>
## Other readme files
@ -196,7 +195,7 @@ Please report all bugs and missing Minecraft features here:
There are so many people to list (sorry). Check out the respective mod directories for details. This section is only a rough overview of the core authors of this game.
### Coding
* [Wuzzy](https://forum.minetest.net/memberlist.php?mode=viewprofile&u=3082): Main programmer of most mods (retired)
* [Wuzzy](https://forum.minetest.net/memberlist.php?mode=viewprofile&u=3082): Main programmer of most mods
* davedevils: Creator of MineClone on which MineClone 2 is based on
* [ex-bart](https://github.com/ex-bart): Redstone comparators
* [Rootyjr](https://github.com/Rootyjr): Fishing rod and bugfixes
@ -204,9 +203,6 @@ There are so many people to list (sorry). Check out the respective mod directori
* [ryvnf](https://github.com/ryvnf): Explosion mechanics
* MysticTempest: Bugfixes
* [bzoss](https://github.com/bzoss): Status effects, potions, brewing stand
* kay27 <kay27@bk.ru>: Experience system, bugfixes, optimizations (Current maintainer)
* [EliasFleckenstein03](https://github.com/EliasFleckenstein03): End crystals, enchanting, burning mobs / players, animated chests, bugfixes (Current maintainer)
* 2mac: Fix bug with powered rail
* Lots of other people: TO BE WRITTEN (see mod directories for details)
#### Mod credits (summary)
@ -252,7 +248,6 @@ Various sources. See the respective mod directories for details.
### Special thanks
* davedevils for starting MineClone, the original version of this game
* Wuzzy for starting and maintaining MineClone2 for several years
* celeron55 for creating Minetest
* Minetest's modding community for providing a huge selection of mods, some of which ended up in MineClone 2
* Jordach for the jukebox music compilation from Big Freaking Dig
@ -264,6 +259,7 @@ Various sources. See the respective mod directories for details.
## Info for programmers
You find interesting and useful infos in `API.md`.
This project is currently mostly a one-person project.
## Legal information
This is a fan game, not developed or endorsed by Mojang AB.
@ -272,7 +268,7 @@ Copying is an act of love. Please copy and share! <3
Here's the detailed legalese for those who need it:
### License of source code
MineClone 2 (by kay27, EliasFleckenstein, Wuzzy, davedevils and countless others)
MineClone 2 (by Wuzzy, davedevils and countless others)
is an imitation of Minecraft.
MineClone 2 is free software: you can redistribute it and/or modify

View File

@ -31,5 +31,3 @@ mgvalleys_spflags = noaltitude_chill,noaltitude_dry,nohumid_rivers,vary_river_de
# MCL2-specific stuff
keepInventory = false
dedicated_server_step = 0.001

View File

@ -18,7 +18,7 @@ digging times in seconds. These digging times can be then added verbatim into th
Example:
mcl_autogroup.digtimes.pickaxey_dig_diamond[1] = 0.2
This means that when a node has been assigned the group pickaxey_dig_diamond=1, it can be dug by the
This menas that when a node has been assigned the group pickaxey_dig_diamond=1, it can be dug by the
diamond pickaxe in 0.2 seconds.
@ -44,7 +44,6 @@ local divisors = {
["shearsy_wool"] = 5,
["swordy_cobweb"] = 15,
}
local max_efficiency_level = 5
mcl_autogroup = {}
mcl_autogroup.digtimes = {}
@ -54,18 +53,11 @@ for m=1, #materials do
for g=1, #basegroups do
mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m]] = {}
mcl_autogroup.creativetimes[basegroups[g].."_dig_"..materials[m]] = {}
for e=1, max_efficiency_level do
mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m].."_efficiency_"..e] = {}
end
end
end
for g=1, #minigroups do
mcl_autogroup.digtimes[minigroups[g].."_dig"] = {}
mcl_autogroup.creativetimes[minigroups[g].."_dig"] = {}
for e=1, max_efficiency_level do
mcl_autogroup.digtimes[minigroups[g].."_dig_efficiency_"..e] = {}
mcl_autogroup.creativetimes[minigroups[g].."_dig_efficiency_"..e] = {}
end
end
local overwrite = function()
@ -88,7 +80,7 @@ local overwrite = function()
groups_changed = true
end
local function calculate_group(hardness, material, diggroup, newgroups, actual_rating, expected_rating, efficiency)
local function calculate_group(hardness, material, diggroup, newgroups, actual_rating, expected_rating)
local time, validity_factor
if actual_rating >= expected_rating then
-- Valid tool
@ -97,20 +89,14 @@ local overwrite = function()
-- Wrong tool (higher digging time)
validity_factor = 5
end
local speed_multiplier = divisors[material]
if efficiency then
speed_multiplier = speed_multiplier + efficiency * efficiency + 1
end
time = (hardness * validity_factor) / speed_multiplier
time = (hardness * validity_factor) / divisors[material]
if time <= 0.05 then
time = 0
else
time = math.ceil(time * 20) / 20
end
table.insert(mcl_autogroup.digtimes[diggroup], time)
if not efficiency then
table.insert(mcl_autogroup.creativetimes[diggroup], 0)
end
table.insert(mcl_autogroup.creativetimes[diggroup], 0)
newgroups[diggroup] = #mcl_autogroup.digtimes[diggroup]
return newgroups
end
@ -127,9 +113,6 @@ local overwrite = function()
for g=1,#materials do
local diggroup = basegroup.."_dig_"..materials[g]
newgroups = calculate_group(hardness, materials[g], diggroup, newgroups, g, ndef.groups[basegroup])
for e=1,max_efficiency_level do
newgroups = calculate_group(hardness, materials[g], diggroup .. "_efficiency_" .. e, newgroups, g, ndef.groups[basegroup], e)
end
groups_changed = true
end
end
@ -151,9 +134,6 @@ local overwrite = function()
or
(ndef.groups[minigroup] and minigroup ~= "swordy_cobweb" and minigroup ~= "shearsy_wool") then
newgroups = calculate_group(hardness, minigroup, diggroup, newgroups, ar, 1)
for e=1,max_efficiency_level do
newgroups = calculate_group(hardness, minigroup, diggroup .. "_efficiency_" .. e, newgroups, ar, 1, e)
end
groups_changed = true
end
end

View File

@ -32,10 +32,6 @@ local STEP_LENGTH = 0.3
-- How many rays to compute entity exposure to explosion
local N_EXPOSURE_RAYS = 16
-- Nodes having a blast resistance of this value or higher are treated as
-- indestructible
local INDESTRUCT_BLASTRES = 1000000
minetest.register_on_mods_loaded(function()
-- Store blast resistance values by content ids to improve performance.
for name, def in pairs(minetest.registered_nodes) do
@ -128,7 +124,7 @@ local function add_particles(pos, radius)
maxexptime = 1.0,
minsize = radius * 0.5,
maxsize = radius * 1.0,
texture = "mcl_particles_smoke.png",
texture = "tnt_smoke.png",
})
end
@ -139,21 +135,14 @@ end
-- strength - The strength of each ray
-- raydirs - The directions for each ray
-- radius - The maximum distance each ray will go
-- info - Table containing information about explosion
-- puncher - object that punches other objects (optional)
--
-- Values in info:
-- drop_chance - The chance that destroyed nodes will drop their items
-- fire - If true, 1/3 nodes become fire
-- griefing - If true, the explosion will destroy nodes (default: true)
-- max_blast_resistance - The explosion will treat all non-indestructible nodes
-- as having a blast resistance of no more than this
-- value
-- fire - If true, 1/3 of destroyed nodes become fire
-- puncher - object that punches other objects (optional)
--
-- Note that this function has been optimized, it contains code which has been
-- inlined to avoid function calls and unnecessary table creation. This was
-- measured to give a significant performance increase.
local function trace_explode(pos, strength, raydirs, radius, info, puncher)
local function trace_explode(pos, strength, raydirs, radius, drop_chance, fire, puncher, creative_enabled)
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(vector.subtract(pos, radius),
@ -175,49 +164,39 @@ local function trace_explode(pos, strength, raydirs, radius, info, puncher)
local data = vm:get_data()
local destroy = {}
local drop_chance = info.drop_chance
local fire = info.fire
local max_blast_resistance = info.max_blast_resistance
-- Trace rays for environment destruction
if info.griefing then
for i = 1, #raydirs do
local rpos_x = pos.x
local rpos_y = pos.y
local rpos_z = pos.z
local rdir_x = raydirs[i].x
local rdir_y = raydirs[i].y
local rdir_z = raydirs[i].z
local rstr = (0.7 + math.random() * 0.6) * strength
for i = 1, #raydirs do
local rpos_x = pos.x
local rpos_y = pos.y
local rpos_z = pos.z
local rdir_x = raydirs[i].x
local rdir_y = raydirs[i].y
local rdir_z = raydirs[i].z
local rstr = (0.7 + math.random() * 0.6) * strength
for r = 0, math.ceil(radius * (1.0 / STEP_LENGTH)) do
local npos_x = math.floor(rpos_x + 0.5)
local npos_y = math.floor(rpos_y + 0.5)
local npos_z = math.floor(rpos_z + 0.5)
local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride +
npos_x - emin_x + 1
for r = 0, math.ceil(radius * (1.0 / STEP_LENGTH)) do
local npos_x = math.floor(rpos_x + 0.5)
local npos_y = math.floor(rpos_y + 0.5)
local npos_z = math.floor(rpos_z + 0.5)
local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride +
npos_x - emin_x + 1
local cid = data[idx]
local br = node_blastres[cid]
if br < INDESTRUCT_BLASTRES and br > max_blast_resistance then
br = max_blast_resistance
end
local cid = data[idx]
local br = node_blastres[cid]
local hash = minetest.hash_node_position({x=npos_x, y=npos_y, z=npos_z})
local hash = minetest.hash_node_position({x=npos_x, y=npos_y, z=npos_z})
rpos_x = rpos_x + STEP_LENGTH * rdir_x
rpos_y = rpos_y + STEP_LENGTH * rdir_y
rpos_z = rpos_z + STEP_LENGTH * rdir_z
rpos_x = rpos_x + STEP_LENGTH * rdir_x
rpos_y = rpos_y + STEP_LENGTH * rdir_y
rpos_z = rpos_z + STEP_LENGTH * rdir_z
rstr = rstr - 0.75 * STEP_LENGTH - (br + 0.3) * STEP_LENGTH
rstr = rstr - 0.75 * STEP_LENGTH - (br + 0.3) * STEP_LENGTH
if rstr <= 0 then
break
end
if rstr <= 0 then
break
end
if cid ~= minetest.CONTENT_AIR and not minetest.is_protected({x = npos_x, y = npos_y, z = npos_z}, "") then
destroy[hash] = idx
end
if cid ~= minetest.CONTENT_AIR then
destroy[hash] = idx
end
end
end
@ -255,9 +234,9 @@ local function trace_explode(pos, strength, raydirs, radius, info, puncher)
local z_len = math.abs(z2 - z1)
-- Move object position to the center of its bounding box
opos.x = opos.x + 0.5 * (x1 + x2)
opos.y = opos.y + 0.5 * (y1 + y2)
opos.z = opos.z + 0.5 * (z1 + z2)
opos.x = opos.x + x1 + x2
opos.y = opos.y + y1 + y2
opos.z = opos.z + z1 + z2
-- Count number of rays from collision box which are unobstructed
local count = N_EXPOSURE_RAYS
@ -305,40 +284,20 @@ local function trace_explode(pos, strength, raydirs, radius, info, puncher)
impact = 0
end
local damage = math.floor((impact * impact + impact) * 7 * strength + 1)
local source = puncher or obj
local sleep_formspec_doesnt_close_mt53 = false
if obj:is_player() then
local name = obj:get_player_name()
if mcl_beds then
local meta = obj:get_meta()
if meta:get_string("mcl_beds:sleeping") == "true" then
minetest.close_formspec(name, "") -- ABSOLUTELY NECESSARY FOR MT5.3 -- TODO: REMOVE THIS IN THE FUTURE
sleep_formspec_doesnt_close_mt53 = true
end
end
if mod_death_messages then
mcl_death_messages.player_damage(obj, S("@1 was caught in an explosion.", name))
end
if rawget(_G, "armor") and armor.last_damage_types then
armor.last_damage_types[name] = "explosion"
end
if mod_death_messages and obj:is_player() then
mcl_death_messages.player_damage(obj, S("@1 was caught in an explosion.", obj:get_player_name()))
end
local source = puncher
if not source then
source = obj
end
obj:punch(source, 10, { damage_groups = { full_punch_interval = 1,
fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
if sleep_formspec_doesnt_close_mt53 then
minetest.after(0.3, function(obj, damage, impact, punch_dir) -- 0.2 is minimum delay for closing old formspec and open died formspec -- TODO: REMOVE THIS IN THE FUTURE
if not obj then return end
obj:punch(obj, 10, { damage_groups = { full_punch_interval = 1, fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
obj:add_player_velocity(vector.multiply(punch_dir, impact * 20))
end, obj, damage, impact, vector.new(punch_dir))
else
obj:punch(source, 10, { damage_groups = { full_punch_interval = 1, fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
if obj:is_player() then
obj:add_player_velocity(vector.multiply(punch_dir, impact * 20))
elseif ent.tnt_knockback then
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
end
if obj:is_player() then
obj:add_player_velocity(vector.multiply(punch_dir, impact * 20))
elseif ent.tnt_knockback then
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
end
end
end
@ -348,14 +307,14 @@ local function trace_explode(pos, strength, raydirs, radius, info, puncher)
-- Remove destroyed blocks and drop items
for hash, idx in pairs(destroy) do
local do_drop = math.random() <= drop_chance
local do_drop = not creative_enabled and math.random() <= drop_chance
local on_blast = node_on_blast[data[idx]]
local remove = true
if do_drop or on_blast ~= nil then
local npos = minetest.get_position_from_hash(hash)
if on_blast ~= nil then
on_blast(npos, 1.0, do_drop)
on_blast(npos, 1.0)
remove = false
else
local name = minetest.get_name_from_content_id(data[idx])
@ -398,6 +357,7 @@ local function trace_explode(pos, strength, raydirs, radius, info, puncher)
-- Log explosion
minetest.log('action', 'Explosion at ' .. minetest.pos_to_string(pos) ..
' with strength ' .. strength .. ' and radius ' .. radius)
end
-- Create an explosion with strength at pos.
@ -405,24 +365,16 @@ end
-- Parameters:
-- pos - The position where the explosion originates from
-- strength - The blast strength of the explosion (a TNT explosion uses 4)
-- info - Table containing information about explosion
-- info - Table containing information about explosion.
-- puncher - object that is reported as source of punches/damage (optional)
--
-- Values in info:
-- drop_chance - If specified becomes the drop chance of all nodes in the
-- explosion (default: 1.0 / strength)
-- max_blast_resistance - If specified the explosion will treat all
-- non-indestructible nodes as having a blast resistance
-- of no more than this value
-- sound - If true, the explosion will play a sound (default: true)
-- particles - If true, the explosion will create particles (default: true)
-- explosion (defaults to 1.0 / strength)
-- no_sound - If true then the explosion will not play a sound
-- no_particle - If true then the explosion will not create particles
-- fire - If true, 1/3 nodes become fire (default: false)
-- griefing - If true, the explosion will destroy nodes (default: true)
function mcl_explosions.explode(pos, strength, info, puncher)
if info == nil then
info = {}
end
-- The maximum blast radius (in the air)
local radius = math.ceil(1.3 * strength / (0.3 * 0.75) * 0.3)
@ -431,27 +383,13 @@ function mcl_explosions.explode(pos, strength, info, puncher)
end
local shape = sphere_shapes[radius]
-- Default values
if info.drop_chance == nil then info.drop_chance = 1 / strength end
if info.particles == nil then info.particles = true end
if info.sound == nil then info.sound = true end
if info.fire == nil then info.fire = false end
if info.griefing == nil then info.griefing = true end
if info.max_blast_resistance == nil then
info.max_blast_resistance = INDESTRUCT_BLASTRES
end
local creative_enabled = minetest.is_creative_enabled("")
trace_explode(pos, strength, shape, radius, (info and info.drop_chance) or 1 / strength, info.fire == true, puncher, creative_enabled)
-- Dont do drops in creative mode
if minetest.is_creative_enabled("") then
info.drop_chance = 0
end
trace_explode(pos, strength, shape, radius, info, puncher)
if info.particles then
if not (info and info.no_sound) then
add_particles(pos, radius)
end
if info.sound then
if not (info and info.no_particle) then
minetest.sound_play("tnt_explode", {
pos = pos, gain = 1.0,
max_hear_distance = strength * 16

View File

@ -1,2 +0,0 @@
# textdomain:mcl_explosions
@1 was caught in an explosion.=@1 a été pris dans une explosion.

View File

@ -1,2 +0,0 @@
# textdomain:mcl_explosions
@1 was caught in an explosion.=@1 не удалось пережить взрыва.

View File

@ -1,4 +1,3 @@
name = mcl_explosions
description = A common API to create explosions.
depends = mcl_particles
optional_depends = mcl_fire

View File

@ -1,8 +1,6 @@
-- Some global variables (don't overwrite them!)
mcl_vars = {}
mcl_vars.redstone_tick = 0.1
--- GUI / inventory menu settings
mcl_vars.gui_slots = "listcolors[#9990;#FFF7;#FFF0;#000;#FFF]"
-- nonbg is added as formspec prepend in mcl_formspec_prepend
@ -25,64 +23,8 @@ mcl_vars.inventory_header = ""
local mg_name = minetest.get_mapgen_setting("mg_name")
local minecraft_height_limit = 256
local superflat = mg_name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true"
local singlenode = mg_name == "singlenode"
-- Calculate mapgen_edge_min/mapgen_edge_max
mcl_vars.chunksize = math.max(1, tonumber(minetest.get_mapgen_setting("chunksize")) or 5)
mcl_vars.MAP_BLOCKSIZE = math.max(1, core.MAP_BLOCKSIZE or 16)
mcl_vars.mapgen_limit = math.max(1, tonumber(minetest.get_mapgen_setting("mapgen_limit")) or 31000)
mcl_vars.MAX_MAP_GENERATION_LIMIT = math.max(1, core.MAX_MAP_GENERATION_LIMIT or 31000)
local central_chunk_offset = -math.floor(mcl_vars.chunksize / 2)
local chunk_size_in_nodes = mcl_vars.chunksize * mcl_vars.MAP_BLOCKSIZE
local central_chunk_min_pos = central_chunk_offset * mcl_vars.MAP_BLOCKSIZE
local central_chunk_max_pos = central_chunk_min_pos + chunk_size_in_nodes - 1
local ccfmin = central_chunk_min_pos - mcl_vars.MAP_BLOCKSIZE -- Fullminp/fullmaxp of central chunk, in nodes
local ccfmax = central_chunk_max_pos + mcl_vars.MAP_BLOCKSIZE
local mapgen_limit_b = math.floor(math.min(mcl_vars.mapgen_limit, mcl_vars.MAX_MAP_GENERATION_LIMIT) / mcl_vars.MAP_BLOCKSIZE)
local mapgen_limit_min = -mapgen_limit_b * mcl_vars.MAP_BLOCKSIZE
local mapgen_limit_max = (mapgen_limit_b + 1) * mcl_vars.MAP_BLOCKSIZE - 1
local numcmin = math.max(math.floor((ccfmin - mapgen_limit_min) / chunk_size_in_nodes), 0) -- Number of complete chunks from central chunk
local numcmax = math.max(math.floor((mapgen_limit_max - ccfmax) / chunk_size_in_nodes), 0) -- fullminp/fullmaxp to effective mapgen limits.
mcl_vars.mapgen_edge_min = central_chunk_min_pos - numcmin * chunk_size_in_nodes
mcl_vars.mapgen_edge_max = central_chunk_max_pos + numcmax * chunk_size_in_nodes
local function coordinate_to_block(x)
return math.floor(x / mcl_vars.MAP_BLOCKSIZE)
end
local function coordinate_to_chunk(x)
return math.floor((coordinate_to_block(x) + central_chunk_offset) / mcl_vars.chunksize)
end
function mcl_vars.pos_to_block(pos)
return {
x = coordinate_to_block(pos.x),
y = coordinate_to_block(pos.y),
z = coordinate_to_block(pos.z)
}
end
function mcl_vars.pos_to_chunk(pos)
return {
x = coordinate_to_chunk(pos.x),
y = coordinate_to_chunk(pos.y),
z = coordinate_to_chunk(pos.z)
}
end
local k_positive = math.ceil(mcl_vars.MAX_MAP_GENERATION_LIMIT / chunk_size_in_nodes)
local k_positive_z = k_positive * 2
local k_positive_y = k_positive_z * k_positive_z
function mcl_vars.get_chunk_number(pos) -- unsigned int
local c = mcl_vars.pos_to_chunk(pos)
return
(c.y + k_positive) * k_positive_y +
(c.z + k_positive) * k_positive_z +
c.x + k_positive
end
if not superflat and not singlenode then
if not superflat then
-- Normal mode
--[[ Realm stacking (h is for height)
- Overworld (h>=256)
@ -103,14 +45,6 @@ if not superflat and not singlenode then
mcl_vars.mg_lava = true
mcl_vars.mg_bedrock_is_rough = true
elseif singlenode then
mcl_vars.mg_overworld_min = -66
mcl_vars.mg_overworld_max_official = mcl_vars.mg_overworld_min + minecraft_height_limit
mcl_vars.mg_bedrock_overworld_min = mcl_vars.mg_overworld_min
mcl_vars.mg_bedrock_overworld_max = mcl_vars.mg_bedrock_overworld_min
mcl_vars.mg_lava = false
mcl_vars.mg_lava_overworld_max = mcl_vars.mg_overworld_min
mcl_vars.mg_bedrock_is_rough = false
else
-- Classic superflat
local ground = minetest.get_mapgen_setting("mgflat_ground_level")
@ -127,7 +61,7 @@ else
mcl_vars.mg_bedrock_is_rough = false
end
mcl_vars.mg_overworld_max = mcl_vars.mapgen_edge_max
mcl_vars.mg_overworld_max = 31000
-- The Nether (around Y = -29000)
mcl_vars.mg_nether_min = -29067 -- Carefully chosen to be at a mapchunk border
@ -174,3 +108,4 @@ minetest.craftitemdef_default.stack_max = 64
-- Set random seed for all other mods (Remember to make sure no other mod calls this function)
math.randomseed(os.time())

View File

@ -11,15 +11,12 @@ Parameters:
stacks_max = 3, -- Maximum number of item stacks to get. Default: 1
items = { -- Table of possible loot items. This function selects between stacks_min and stacks_max of these.
{
weight = 5, -- Likelihood of this item being selected (see below). Optional (default: 1)
itemstack = ItemStack("example:item1"), -- Itemstack to select
-- OR
itemstring = "example:item1", -- Which item to select
amount_min = 1, -- Minimum size of itemstack. Must not be larger than 6553. Optional (default: 1)
amount_max = 10, -- Maximum size of item stack. Must not be larger than item definition's stack_max or 6553. Optional (default: 1)
wear_min = 1, -- Minimum wear value. Must be at least 1. Optional (default: no wear)
wear_max = 1, -- Maxiumum wear value. Must be at least 1. Optional (default: no wear)
weight = 5, -- Likelihood of this item being selected (see below). Optional (default: 1)
},
{ -- more tables like above, one table per item stack }
}
@ -59,29 +56,24 @@ function mcl_loot.get_loot(loot_definitions, pr)
end
if item then
local itemstring = item.itemstring
local itemstack = item.itemstack
if itemstring then
if item.amount_min and item.amount_max then
itemstring = itemstring .. " " .. pr:next(item.amount_min, item.amount_max)
end
if item.wear_min and item.wear_max then
-- Sadly, PseudoRandom only allows very narrow ranges, so we set wear in steps of 10
local wear_min = math.floor(item.wear_min / 10)
local wear_max = math.floor(item.wear_max / 10)
local wear = pr:next(wear_min, wear_max) * 10
if not item.amount_min and not item.amount_max then
itemstring = itemstring .. " 1"
end
itemstring = itemstring .. " " .. tostring(wear)
end
table.insert(items, itemstring)
elseif itemstack then
table.insert(items, itemstack)
else
minetest.log("error", "[mcl_loot] INTERNAL ERROR! Failed to select random loot item!")
if item.amount_min and item.amount_max then
itemstring = itemstring .. " " .. pr:next(item.amount_min, item.amount_max)
end
if item.wear_min and item.wear_max then
-- Sadly, PseudoRandom only allows very narrow ranges, so we set wear in steps of 10
local wear_min = math.floor(item.wear_min / 10)
local wear_max = math.floor(item.wear_max / 10)
local wear = pr:next(wear_min, wear_max) * 10
if not item.amount_min and not item.amount_max then
itemstring = itemstring .. " 1"
end
itemstring = itemstring .. " " .. tostring(wear)
end
table.insert(items, itemstring)
else
minetest.log("error", "[mcl_loot] INTERNAL ERROR! Failed to select random loot item!")
end
end
@ -111,14 +103,14 @@ end
Returns a table of length `max_slot` and all natural numbers between 1 and `max_slot`
in a random order.
]]
local function get_random_slots(max_slot, pr)
local function get_random_slots(max_slot)
local slots = {}
for s=1, max_slot do
slots[s] = s
end
local slots_out = {}
while #slots > 0 do
local r = pr and pr:next(1, #slots) or math.random(1, #slots)
local r = math.random(1, #slots)
table.insert(slots_out, slots[r])
table.remove(slots, r)
end
@ -135,9 +127,9 @@ Items will be added from start of the table to end.
If the inventory already has occupied slots, or is
too small, placement of some items might fail.
]]
function mcl_loot.fill_inventory(inv, listname, items, pr)
function mcl_loot.fill_inventory(inv, listname, items)
local size = inv:get_size(listname)
local slots = get_random_slots(size, pr)
local slots = get_random_slots(size)
local leftovers = {}
-- 1st pass: Add items into random slots
for i=1, math.min(#items, size) do

View File

@ -1,68 +0,0 @@
mcl_particles = {}
-- Table of particlespawner IDs on a per-node hash basis
-- Keys: node position hashes
-- Values: Tables of particlespawner IDs (each node pos can have an arbitrary number of particlespawners)
local particle_nodes = {}
-- Node particles can be disabled via setting
local node_particles_allowed = minetest.settings:get("mcl_node_particles") or "none"
local levels = {
high = 3,
medium = 2,
low = 1,
none = 0,
}
allowed_level = levels[node_particles_allowed]
if not allowed_level then
allowed_level = levels["none"]
end
-- Add a particlespawner that is assigned to a given node position.
-- * pos: Node positon. MUST use integer values!
-- * particlespawner_definition: definition for minetest.add_particlespawner
-- * level: detail level of particles. "high", "medium", "low" or "none". High detail levels are for
-- CPU-demanding particles, like smoke of fire (which occurs frequently)
-- NOTE: All particlespawners are automatically removed on shutdown.
-- Returns particlespawner ID on succcess and nil on failure
function mcl_particles.add_node_particlespawner(pos, particlespawner_definition, level)
if allowed_level == 0 or levels[level] > allowed_level then
return
end
local poshash = minetest.hash_node_position(pos)
if not poshash then
return
end
local id = minetest.add_particlespawner(particlespawner_definition)
if id == -1 then
return
end
if not particle_nodes[poshash] then
particle_nodes[poshash] = {}
end
table.insert(particle_nodes[poshash], id)
return id
end
-- Deletes all particlespawners that are assigned to a node position.
-- If no particlespawners exist for this position, nothing happens.
-- pos: Node positon. MUST use integer values!
-- Returns true if particlespawner could be removed and false if not
function mcl_particles.delete_node_particlespawners(pos)
if allowed_level == 0 then
return false
end
local poshash = minetest.hash_node_position(pos)
local ids = particle_nodes[poshash]
if ids then
for i=1, #ids do
minetest.delete_particlespawner(ids[i])
end
particle_nodes[poshash] = nil
return true
end
return false
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B

After

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 B

View File

@ -114,9 +114,9 @@ end
function mcl_sounds.node_sound_leaves_defaults(table)
table = table or {}
table.footstep = table.footstep or
{name="default_grass_footstep", gain=0.1325}
{name="default_grass_footstep", gain=0.35}
table.dug = table.dug or
{name="default_grass_footstep", gain=0.425}
{name="default_grass_footstep", gain=0.85}
table.dig = table.dig or
{name="default_dig_snappy", gain=0.4}
table.place = table.place or

View File

@ -395,13 +395,4 @@ function mcl_util.generate_on_place_plant_function(condition)
end
end
-- adjust the y level of an object to the center of its collisionbox
-- used to get the origin position of entity explosions
function mcl_util.get_object_center(obj)
local collisionbox = obj:get_properties().collisionbox
local pos = obj:get_pos()
local ymin = collisionbox[2]
local ymax = collisionbox[5]
pos.y = pos.y + (ymax - ymin) / 2.0
return pos
end

View File

@ -70,12 +70,6 @@ function mcl_worlds.has_weather(pos)
return pos.y <= mcl_vars.mg_overworld_max and pos.y >= mcl_vars.mg_overworld_min - 64
end
-- Takes a position and returns true if this position can have Nether dust
function mcl_worlds.has_dust(pos)
-- Weather in the Overworld and the high part of the void below
return pos.y <= mcl_vars.mg_nether_max + 64 and pos.y >= mcl_vars.mg_nether_min - 64
end
-- Takes a position (pos) and returns true if compasses are working here
function mcl_worlds.compass_works(pos)
-- It doesn't work in Nether and the End, but it works in the Overworld and in the high part of the void below

View File

@ -1,11 +1,4 @@
-- register extra flavours of a base nodedef
walkover = {}
walkover.registered_globals = {}
function walkover.register_global(func)
table.insert(walkover.registered_globals, func)
end
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime;
@ -17,15 +10,11 @@ minetest.register_globalstep(function(dtime)
if loc ~= nil then
local nodeiamon = minetest.get_node(loc)
if nodeiamon ~= nil then
local def = minetest.registered_nodes[nodeiamon.name]
if def ~= nil and def.on_walk_over ~= nil then
def.on_walk_over(loc, nodeiamon, player)
end
for _, func in ipairs(walkover.registered_globals) do
func(loc, nodeiamon, player)
end
end
end
end

View File

@ -1,24 +1,13 @@
local S = minetest.get_translator("mcl_boats")
local boat_visual_size = {x = 3, y = 3, z = 3}
local paddling_speed = 22
local boat_y_offset = 0.35
local boat_y_offset_ground = boat_y_offset + 0.6
local boat_side_offset = 1.001
local boat_max_hp = 4
local function is_group(pos, group)
local nn = minetest.get_node(pos).name
return minetest.get_item_group(nn, group) ~= 0
end
--
-- Helper functions
--
local function is_water(pos)
return is_group(pos, "water")
local nn = minetest.get_node(pos).name
return minetest.get_item_group(nn, "water") ~= 0
end
local function is_ice(pos)
return is_group(pos, "ice")
end
local function get_sign(i)
if i == 0 then
@ -28,83 +17,25 @@ local function get_sign(i)
end
end
local function get_velocity(v, yaw, y)
local x = -math.sin(yaw) * v
local z = math.cos(yaw) * v
return {x = x, y = y, z = z}
end
local function get_v(v)
return math.sqrt(v.x ^ 2 + v.z ^ 2)
end
local function check_object(obj)
return obj and (obj:is_player() or obj:get_luaentity()) and obj
end
local function get_visual_size(obj)
return obj:is_player() and {x = 1, y = 1, z = 1} or obj:get_luaentity()._old_visual_size or obj:get_properties().visual_size
end
local function set_attach(boat)
boat._driver:set_attach(boat.object, "",
{x = 0, y = 0.42, z = -1}, {x = 0, y = 0, z = 0})
end
local function set_double_attach(boat)
boat._driver:set_attach(boat.object, "",
{x = 0, y = 0.42, z = 0.8}, {x = 0, y = 0, z = 0})
boat._passenger:set_attach(boat.object, "",
{x = 0, y = 0.42, z = -2.2}, {x = 0, y = 0, z = 0})
end
local function attach_object(self, obj)
if self._driver then
if self._driver:is_player() then
self._passenger = obj
else
self._passenger = self._driver
self._driver = obj
end
set_double_attach(self)
else
self._driver = obj
set_attach(self)
end
local visual_size = get_visual_size(obj)
local yaw = self.object:get_yaw()
obj:set_properties({visual_size = vector.divide(visual_size, boat_visual_size)})
if obj:is_player() then
local name = obj:get_player_name()
mcl_player.player_attached[name] = true
minetest.after(0.2, function(name)
local player = minetest.get_player_by_name(name)
if player then
mcl_player.player_set_animation(player, "sit" , 30)
end
end, name)
obj:set_look_horizontal(yaw)
mcl_tmp_message.message(obj, S("Sneak to dismount"))
else
obj:get_luaentity()._old_visual_size = visual_size
end
end
local function detach_object(obj, change_pos)
obj:set_detach()
obj:set_properties({visual_size = get_visual_size(obj)})
if obj:is_player() then
mcl_player.player_attached[obj:get_player_name()] = false
mcl_player.player_set_animation(obj, "stand" , 30)
else
obj:get_luaentity()._old_visual_size = nil
end
if change_pos then
obj:set_pos(vector.add(obj:get_pos(), vector.new(0, 0.2, 0)))
end
end
local boat_visual_size = {x = 3, y = 3}
-- Note: This mod assumes the default player visual_size is {x=1, y=1}
local driver_visual_size = { x = 1/boat_visual_size.x, y = 1/boat_visual_size.y }
local paddling_speed = 22
local boat_y_offset = 0.35
local boat_y_offset_ground = boat_y_offset + 0.6
local boat_side_offset = 1.001
--
-- Boat entity
@ -119,41 +50,67 @@ local boat = {
mesh = "mcl_boats_boat.b3d",
textures = {"mcl_boats_texture_oak_boat.png"},
visual_size = boat_visual_size,
hp_max = boat_max_hp,
damage_texture_modifier = "^[colorize:white:0",
_driver = nil, -- Attached driver (player) or nil if none
_passenger = nil,
_v = 0, -- Speed
_last_v = 0, -- Temporary speed variable
_removed = false, -- If true, boat entity is considered removed (e.g. after punch) and should be ignored
_itemstring = "mcl_boats:boat", -- Itemstring of the boat item (implies boat type)
_animation = 0, -- 0: not animated; 1: paddling forwards; -1: paddling forwards
_regen_timer = 0,
_damage_anim = 0,
}
minetest.register_on_respawnplayer(detach_object)
function boat.on_rightclick(self, clicker)
if self._passenger or not clicker or clicker:get_attach() then
if not clicker or not clicker:is_player() then
return
end
attach_object(self, clicker)
local name = clicker:get_player_name()
if self._driver and clicker == self._driver then
self._driver = nil
clicker:set_detach()
clicker:set_properties({visual_size = {x=1, y=1}})
mcl_player.player_attached[name] = false
mcl_player.player_set_animation(clicker, "stand" , 30)
local pos = clicker:get_pos()
pos = {x = pos.x, y = pos.y + 0.2, z = pos.z}
clicker:set_pos(pos)
elseif not self._driver then
local attach = clicker:get_attach()
if attach and attach:get_luaentity() then
local luaentity = attach:get_luaentity()
if luaentity._driver then
luaentity._driver = nil
end
clicker:set_detach()
clicker:set_properties({visual_size = {x=1, y=1}})
end
self._driver = clicker
clicker:set_attach(self.object, "",
{x = 0, y = 0.42, z = -1}, {x = 0, y = 0, z = 0})
clicker:set_properties({ visual_size = driver_visual_size })
mcl_player.player_attached[name] = true
minetest.after(0.2, function(name)
local player = minetest.get_player_by_name(name)
if player then
mcl_player.player_set_animation(player, "sit" , 30)
end
end, name)
clicker:set_look_horizontal(self.object:get_yaw())
end
end
function boat.on_activate(self, staticdata, dtime_s)
self.object:set_armor_groups({fleshy = 100})
self.object:set_armor_groups({immortal = 1})
local data = minetest.deserialize(staticdata)
if type(data) == "table" then
self._v = data.v
self._last_v = self._v
self._itemstring = data.itemstring
self.object:set_properties({textures = data.textures})
self.object:set_properties({textures=data.textures})
end
end
function boat.get_staticdata(self)
return minetest.serialize({
v = self._v,
@ -162,104 +119,52 @@ function boat.get_staticdata(self)
})
end
function boat.on_death(self, killer)
if killer and killer:is_player() and minetest.is_creative_enabled(killer:get_player_name()) then
local inv = killer:get_inventory()
if not inv:contains_item("main", self._itemstring) then
inv:add_item("main", self._itemstring)
function boat.on_punch(self, puncher)
if not puncher or not puncher:is_player() or self._removed then
return
end
if self._driver and puncher == self._driver then
self._driver = nil
puncher:set_detach()
puncher:set_properties({visual_size = {x=1, y=1}})
mcl_player.player_attached[puncher:get_player_name()] = false
end
if not self._driver then
self._removed = true
-- Drop boat as item on the ground after punching
if not minetest.is_creative_enabled(puncher:get_player_name()) then
minetest.add_item(self.object:get_pos(), self._itemstring)
else
local inv = puncher:get_inventory()
if not inv:contains_item("main", self._itemstring) then
inv:add_item("main", self._itemstring)
end
end
else
minetest.add_item(self.object:get_pos(), self._itemstring)
end
if self._driver then
detach_object(self._driver)
end
if self._passenger then
detach_object(self._passenger)
end
self._driver = nil
self._passenger = nil
end
function boat.on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
if damage > 0 then
self._regen_timer = 0
self.object:remove()
end
end
function boat.on_step(self, dtime, moveresult)
function boat.on_step(self, dtime)
self._v = get_v(self.object:get_velocity()) * get_sign(self._v)
local on_water = true
local in_water = false
local v_factor = 1
local v_slowdown = 0.02
local p = self.object:get_pos()
local on_water = true
local on_ice = false
local in_water = is_water({x=p.x, y=p.y-boat_y_offset+1, z=p.z})
local waterp = {x=p.x, y=p.y-boat_y_offset - 0.1, z=p.z}
if not is_water(waterp) then
if (not is_water({x=p.x, y=p.y-boat_y_offset, z=p.z})) then
on_water = false
if not in_water and is_ice(waterp) then
on_ice = true
else
v_slowdown = 0.04
end
v_factor = 0.5
elseif in_water then
v_slowdown = 0.04
elseif (is_water({x=p.x, y=p.y-boat_y_offset+1, z=p.z})) then
on_water = false
in_water = true
v_factor = 0.75
v_slowdown = 0.05
end
local hp = self.object:get_hp()
local regen_timer = self._regen_timer + dtime
if hp >= boat_max_hp then
regen_timer = 0
elseif regen_timer >= 0.5 then
hp = hp + 1
self.object:set_hp(hp)
regen_timer = 0
end
self._regen_timer = regen_timer
if moveresult and moveresult.collides then
for _, collision in ipairs(moveresult.collisions) do
local pos = collision.node_pos
if collision.type == "node" and minetest.get_item_group(minetest.get_node(pos).name, "dig_by_boat") > 0 then
minetest.dig_node(pos)
end
end
end
local had_passenger = self._passenger
self._driver = check_object(self._driver)
self._passenger = check_object(self._passenger)
if self._passenger then
if not self._driver then
self._driver = self._passenger
self._passenger = nil
else
local ctrl = self._passenger:get_player_control()
if ctrl and ctrl.sneak then
detach_player(self._passenger, true)
self._passenger = nil
end
end
end
if self._driver then
if had_passenger and not self._passenger then
set_attach(self)
end
local ctrl = self._driver:get_player_control()
if ctrl and ctrl.sneak then
detach_object(self._driver, true)
self._driver = nil
return
end
local yaw = self.object:get_yaw()
if ctrl.up then
-- Forwards
@ -286,13 +191,13 @@ function boat.on_step(self, dtime, moveresult)
self._animation = 0
end
end
if ctrl and ctrl.left then
if ctrl.left then
if self._v < 0 then
self.object:set_yaw(yaw - (1 + dtime) * 0.03 * v_factor)
else
self.object:set_yaw(yaw + (1 + dtime) * 0.03 * v_factor)
end
elseif ctrl and ctrl.right then
elseif ctrl.right then
if self._v < 0 then
self.object:set_yaw(yaw + (1 + dtime) * 0.03 * v_factor)
else
@ -305,19 +210,11 @@ function boat.on_step(self, dtime, moveresult)
self.object:set_animation({x=0, y=40}, 0, 0, true)
self._animation = 0
end
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1.3)) do
local entity = obj:get_luaentity()
if entity and entity._cmi_is_mob then
attach_object(self, obj)
break
end
end
end
local s = get_sign(self._v)
if not on_ice and not on_water and not in_water and math.abs(self._v) > 2.0 then
v_slowdown = math.min(math.abs(self._v) - 2.0, v_slowdown * 5)
elseif not on_ice and in_water and math.abs(self._v) > 1.5 then
if not on_water and not in_water and math.abs(self._v) > 1.0 then
v_slowdown = math.min(math.abs(self._v) - 1.0, v_slowdown * 5)
elseif in_water and math.abs(self._v) > 1.5 then
v_slowdown = math.min(math.abs(self._v) - 1.5, v_slowdown * 5)
end
self._v = self._v - v_slowdown * s
@ -328,7 +225,7 @@ function boat.on_step(self, dtime, moveresult)
p.y = p.y - boat_y_offset
local new_velo
local new_acce = {x = 0, y = 0, z = 0}
if not is_water(p) and not on_ice then
if not is_water(p) then
-- Not on water or inside water: Free fall
local nodedef = minetest.registered_nodes[minetest.get_node(p).name]
new_acce = {x = 0, y = -9.8, z = 0}
@ -358,17 +255,12 @@ function boat.on_step(self, dtime, moveresult)
end
-- Terminal velocity: 8 m/s per axis of travel
local terminal_velocity = on_ice and 57.1 or 8.0
for _,axis in pairs({"z","y","x"}) do
if math.abs(new_velo[axis]) > terminal_velocity then
new_velo[axis] = terminal_velocity * get_sign(new_velo[axis])
if math.abs(new_velo[axis]) > 8 then
new_velo[axis] = 8 * get_sign(new_velo[axis])
end
end
local yaw = self.object:get_yaw()
local anim = (boat_max_hp - hp - regen_timer * 2) / boat_max_hp * math.pi / 4
self.object:set_rotation(vector.new(anim, yaw, anim))
self.object:set_velocity(new_velo)
self.object:set_acceleration(new_acce)
end

View File

@ -1,11 +0,0 @@
# textdomain: mcl_boats
Acacia Boat=Лодка из акации
Birch Boat=Берёзовая лодка
Boat=Лодка
Boats are used to travel on the surface of water.=С помощью лодки можно путешествовать по водной поверхности.
Dark Oak Boat=Лодка из тёмного дуба
Jungle Boat=Лодка из дерева джунглей
Oak Boat=Дубовая лодка
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Rightclick the boat again to leave it, punch the boat to make it drop as an item.=Правый клик по воде спустит лодку на воду. Правый клик по лодке разместит вас в ней. [Влево] и [Вправо] - рулить, [Вперед] - разгоняться, [Назад] - тормозить или плыть назад. Правый клик по лодке, когда вы в ней, позволит выйти из неё. Удар по лодке превратит её обратно в предмет.
Spruce Boat=Еловая лодка
Water vehicle=Водный транспорт

View File

@ -1,298 +0,0 @@
local S = minetest.get_translator("mcl_burning")
function mcl_burning.get_default(datatype)
local default_table = {string = "", float = 0.0, int = 0, bool = false}
return default_table[datatype]
end
function mcl_burning.get(obj, datatype, name)
local key
if obj:is_player() then
local meta = obj:get_meta()
return meta["get_" .. datatype](meta, "mcl_burning:" .. name)
else
local luaentity = obj:get_luaentity()
return luaentity and luaentity["mcl_burning_" .. name] or mcl_burning.get_default(datatype)
end
end
function mcl_burning.set(obj, datatype, name, value)
if obj:is_player() then
local meta = obj:get_meta()
meta["set_" .. datatype](meta, "mcl_burning:" .. name, value or mcl_burning.get_default(datatype))
else
local luaentity = obj:get_luaentity()
if mcl_burning.get_default(datatype) == value then
value = nil
end
luaentity["mcl_burning_" .. name] = value
end
end
function mcl_burning.is_burning(obj)
return mcl_burning.get(obj, "float", "burn_time") > 0
end
function mcl_burning.is_affected_by_rain(obj)
return mcl_weather.get_weather() == "rain" and mcl_weather.is_outdoor(obj:get_pos())
end
function mcl_burning.get_collisionbox(obj, smaller)
local box = obj:get_properties().collisionbox
local minp, maxp = vector.new(box[1], box[2], box[3]), vector.new(box[4], box[5], box[6])
if smaller then
local s_vec = vector.new(0.1, 0.1, 0.1)
minp = vector.add(minp, s_vec)
maxp = vector.subtract(maxp, s_vec)
end
return minp, maxp
end
function mcl_burning.get_touching_nodes(obj, nodenames)
local pos = obj:get_pos()
local box = obj:get_properties().collisionbox
local minp, maxp = mcl_burning.get_collisionbox(obj, true)
local nodes = minetest.find_nodes_in_area(vector.add(pos, minp), vector.add(pos, maxp), nodenames)
return nodes
end
function mcl_burning.get_highest_group_value(obj, groupname)
local nodes = mcl_burning.get_touching_nodes(obj, "group:" .. groupname, true)
local highest_group_value = 0
for _, pos in pairs(nodes) do
local node = minetest.get_node(pos)
local group_value = minetest.get_item_group(node.name, groupname)
if group_value > highest_group_value then
highest_group_value = group_value
end
end
return highest_group_value
end
function mcl_burning.damage(obj)
local luaentity = obj:get_luaentity()
local health
if luaentity then
health = luaentity.health
end
local hp = health or obj:get_hp()
if hp <= 0 then
return
end
local do_damage = true
if obj:is_player() then
if mcl_potions.player_has_effect(obj, "fire_proof") then
do_damage = false
else
local name = obj:get_player_name()
armor.last_damage_types[name] = "fire"
local deathmsg = S("@1 burned to death.", name)
local reason = mcl_burning.get(obj, "string", "reason")
if reason ~= "" then
deathmsg = S("@1 was burned by @2.", name, reason)
end
mcl_death_messages.player_damage(obj, deathmsg)
end
else
if luaentity.fire_damage_resistant then
do_damage = false
end
end
if do_damage then
local new_hp = hp - 1
if health then
luaentity.health = new_hp
else
obj:set_hp(new_hp)
end
end
end
function mcl_burning.set_on_fire(obj, burn_time, reason)
local luaentity = obj:get_luaentity()
if luaentity and luaentity.fire_resistant then
return
end
local old_burn_time = mcl_burning.get(obj, "float", "burn_time")
local max_fire_prot_lvl = 0
if obj:is_player() then
if minetest.is_creative_enabled(obj:get_player_name()) then
burn_time = burn_time / 100
end
local inv = obj:get_inventory()
for i = 2, 5 do
local stack = inv:get_stack("armor", i)
local fire_prot_lvl = mcl_enchanting.get_enchantment(stack, "fire_protection")
max_fire_prot_lvl = math.max(max_fire_prot_lvl, fire_prot_lvl)
end
end
if max_fire_prot_lvl > 0 then
burn_time = burn_time - math.floor(burn_time * max_fire_prot_lvl * 0.15)
end
if old_burn_time <= burn_time then
local sound_id = mcl_burning.get(obj, "int", "sound_id")
if sound_id == 0 then
sound_id = minetest.sound_play("fire_fire", {
object = obj,
gain = 0.18,
max_hear_distance = 16,
loop = true,
}) + 1
end
local hud_id
if obj:is_player() then
hud_id = mcl_burning.get(obj, "int", "hud_id")
if hud_id == 0 then
hud_id = obj:hud_add({
hud_elem_type = "image",
position = {x = 0.5, y = 0.5},
scale = {x = -100, y = -100},
text = "fire_basic_flame.png",
z_index = 1000,
}) + 1
end
end
mcl_burning.set(obj, "float", "burn_time", burn_time)
mcl_burning.set(obj, "string", "reason", reason)
mcl_burning.set(obj, "int", "hud_id", hud_id)
mcl_burning.set(obj, "int", "sound_id", sound_id)
local fire_entity = minetest.add_entity(obj:get_pos(), "mcl_burning:fire")
local minp, maxp = mcl_burning.get_collisionbox(obj)
local obj_size = obj:get_properties().visual_size
local vertical_grow_factor = 1.2
local horizontal_grow_factor = 1.1
local grow_vector = vector.new(horizontal_grow_factor, vertical_grow_factor, horizontal_grow_factor)
local size = vector.subtract(maxp, minp)
size = vector.multiply(size, grow_vector)
size = vector.divide(size, obj_size)
local offset = vector.new(0, size.y * 10 / 2, 0)
fire_entity:set_properties({visual_size = size})
fire_entity:set_attach(obj, "", offset, {x = 0, y = 0, z = 0})
mcl_burning.update_animation_frame(obj, fire_entity, 0)
end
end
function mcl_burning.extinguish(obj)
if mcl_burning.is_burning(obj) then
local sound_id = mcl_burning.get(obj, "int", "sound_id") - 1
minetest.sound_stop(sound_id)
if obj:is_player() then
local hud_id = mcl_burning.get(obj, "int", "hud_id") - 1
obj:hud_remove(hud_id)
end
mcl_burning.set(obj, "string", "reason")
mcl_burning.set(obj, "float", "burn_time")
mcl_burning.set(obj, "float", "damage_timer")
mcl_burning.set(obj, "int", "hud_id")
mcl_burning.set(obj, "int", "sound_id")
end
end
function mcl_burning.catch_fire_tick(obj, dtime)
if mcl_burning.is_affected_by_rain(obj) or #mcl_burning.get_touching_nodes(obj, "group:puts_out_fire") > 0 then
mcl_burning.extinguish(obj)
else
local set_on_fire_value = mcl_burning.get_highest_group_value(obj, "set_on_fire")
if set_on_fire_value > 0 then
mcl_burning.set_on_fire(obj, set_on_fire_value)
end
end
end
function mcl_burning.tick(obj, dtime)
local burn_time = mcl_burning.get(obj, "float", "burn_time") - dtime
if burn_time <= 0 then
mcl_burning.extinguish(obj)
else
mcl_burning.set(obj, "float", "burn_time", burn_time)
local damage_timer = mcl_burning.get(obj, "float", "damage_timer") + dtime
if damage_timer >= 1 then
damage_timer = 0
mcl_burning.damage(obj)
end
mcl_burning.set(obj, "float", "damage_timer", damage_timer)
end
mcl_burning.catch_fire_tick(obj, dtime)
end
function mcl_burning.update_animation_frame(obj, fire_entity, animation_frame)
local fire_texture = "mcl_burning_entity_flame_animated.png^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. animation_frame
local fire_HUD_texture = "mcl_burning_hud_flame_animated.png^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. animation_frame
fire_entity:set_properties({textures = {"blank.png", "blank.png", fire_texture, fire_texture, fire_texture, fire_texture}})
if obj:is_player() then
local hud_id = mcl_burning.get(obj, "int", "hud_id") - 1
obj:hud_change(hud_id, "text", fire_HUD_texture)
end
end
function mcl_burning.fire_entity_step(self, dtime)
if self.removed then
return
end
local obj = self.object
local parent = obj:get_attach()
local do_remove
self.doing_step = true
if not parent or not mcl_burning.is_burning(parent) then
do_remove = true
else
for _, other in ipairs(minetest.get_objects_inside_radius(obj:get_pos(), 0)) do
local luaentity = obj:get_luaentity()
if luaentity and luaentity.name == "mcl_burning:fire" and not luaentity.doing_step and not luaentity.removed then
do_remove = true
break
end
end
end
self.doing_step = false
if do_remove then
self.removed = true
obj:remove()
return
end
local animation_timer = self.animation_timer + dtime
if animation_timer >= 0.015 then
animation_timer = 0
local animation_frame = self.animation_frame + 1
if animation_frame > mcl_burning.animation_frames - 1 then
animation_frame = 0
end
mcl_burning.update_animation_frame(parent, obj, animation_frame)
self.animation_frame = animation_frame
end
self.animation_timer = animation_timer
end

View File

@ -1,36 +0,0 @@
local S = minetest.get_translator("mcl_burning")
local modpath = minetest.get_modpath("mcl_burning")
mcl_burning = {
animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8
}
dofile(modpath .. "/api.lua")
minetest.register_entity("mcl_burning:fire", {
initial_properties = {
physical = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "cube",
pointable = false,
glow = -1,
},
animation_frame = 0,
animation_timer = 0,
on_step = mcl_burning.fire_entity_step,
})
minetest.register_globalstep(function(dtime)
for _, player in ipairs(minetest.get_connected_players()) do
mcl_burning.tick(player, dtime)
end
end)
minetest.register_on_respawnplayer(function(player)
mcl_burning.extinguish(player)
end)
minetest.register_on_leaveplayer(function(player)
mcl_burning.set(player, "int", "hud_id")
end)

View File

@ -1,3 +0,0 @@
name = mcl_burning
description = Burning Objects for MineClone2
author = Fleckenstein

View File

@ -1,3 +0,0 @@
# textdomain: mcl_falling_nodes
@1 was smashed by a falling anvil.=@1 придавило падающей наковальней.
@1 was smashed by a falling block.=@1 раздавило падающим блоком.

View File

@ -1,2 +1 @@
flowlib
mcl_enchanting

View File

@ -2,7 +2,6 @@
local item_drop_settings = {} --settings table
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
item_drop_settings.radius_magnet = 2.0 --radius of item magnet. MUST BE LARGER THAN radius_collect!
item_drop_settings.xp_radius_magnet = 7.25 --radius of xp magnet. MUST BE LARGER THAN radius_collect!
item_drop_settings.radius_collect = 0.2 --radius of collection
item_drop_settings.player_collect_height = 1.0 --added to their pos y value
item_drop_settings.collection_safety = false --do this to prevent items from flying away on laggy servers
@ -61,8 +60,8 @@ minetest.register_globalstep(function(dtime)
local checkpos = {x=pos.x,y=pos.y + item_drop_settings.player_collect_height,z=pos.z}
--magnet and collection
for _,object in ipairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.xp_radius_magnet)) do
if not object:is_player() and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then
for _,object in ipairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.radius_magnet)) do
if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then
object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime
local collected = false
if object:get_luaentity()._magnet_timer >= 0 and object:get_luaentity()._magnet_timer < item_drop_settings.magnet_time and inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
@ -153,11 +152,6 @@ minetest.register_globalstep(function(dtime)
end
end
elseif not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "mcl_experience:orb" then
local entity = object:get_luaentity()
entity.collector = player:get_player_name()
entity.collected = true
end
end
@ -194,12 +188,6 @@ local check_can_drop = function(node_name, tool_capabilities)
if toolgroupcaps[plus] then
return true
end
for e=1,5 do
local effplus = plus .. "_efficiency_" .. e
if toolgroupcaps[effplus] then
return true
end
end
end
end
for b=1, #basegroups do
@ -211,12 +199,6 @@ local check_can_drop = function(node_name, tool_capabilities)
if toolgroupcaps[plus] then
return true
end
for e=1,5 do
local effplus = plus .. "_efficiency_" .. e
if toolgroupcaps[effplus] then
return true
end
end
end
end
end
@ -225,66 +207,21 @@ local check_can_drop = function(node_name, tool_capabilities)
end
end
-- Stupid workaround to get drops from a drop table:
-- Create a temporary table in minetest.registered_nodes that contains the proper drops,
-- because unfortunately minetest.get_node_drops needs the drop table to be inside a registered node definition
-- (very ugly)
local tmp_id = 0
local function get_drops(drop, toolname, param2, paramtype2)
tmp_id = tmp_id + 1
local tmp_node_name = "mcl_item_entity:" .. tmp_id
minetest.registered_nodes[tmp_node_name] = {
name = tmp_node_name,
drop = drop,
paramtype2 = paramtype2
}
local drops = minetest.get_node_drops({name = tmp_node_name, param2 = param2}, toolname)
minetest.registered_nodes[tmp_node_name] = nil
return drops
end
local function discrete_uniform_distribution(drops, min_count, max_count, cap)
local new_drops = table.copy(drops)
for i, item in ipairs(drops) do
local new_item = ItemStack(item)
local multiplier = math.random(min_count, max_count)
if cap then
multiplier = math.min(cap, multiplier)
end
new_item:set_count(multiplier * new_item:get_count())
new_drops[i] = new_item
end
return new_drops
end
local function get_fortune_drops(fortune_drops, fortune_level)
local drop
local i = fortune_level
repeat
drop = fortune_drops[i]
i = i - 1
until drop or i < 1
return drop or {}
end
function minetest.handle_node_drops(pos, drops, digger)
-- NOTE: This function override allows digger to be nil.
-- This means there is no digger. This is a special case which allows this function to be called
-- by hand. Creative Mode is intentionally ignored in this case.
local doTileDrops = minetest.settings:get_bool("mcl_doTileDrops", true)
if (digger and digger:is_player() and minetest.is_creative_enabled(digger:get_player_name())) or doTileDrops == false then
if (digger ~= nil and minetest.is_creative_enabled(digger:get_player_name())) or doTileDrops == false then
return
end
-- Check if node will yield its useful drop by the digger's tool
local dug_node = minetest.get_node(pos)
local toolcaps
local tool
if digger ~= nil then
tool = digger:get_wielded_item()
local tool = digger:get_wielded_item()
toolcaps = tool:get_tool_capabilities()
if not check_can_drop(dug_node.name, toolcaps) then
@ -292,16 +229,12 @@ function minetest.handle_node_drops(pos, drops, digger)
end
end
--[[ Special node drops when dug by shears by reading _mcl_shears_drop or with a silk touch tool reading _mcl_silk_touch_drop
--[[ Special node drops when dug by shears by reading _mcl_shears_drop
from the node definition.
Definition of _mcl_shears_drop / _mcl_silk_touch_drop:
* true: Drop itself when dug by shears / silk touch tool
* table: Drop every itemstring in this table when dug by shears _mcl_silk_touch_drop
Definition of _mcl_shears_drop:
* true: Drop itself when dug by shears
* table: Drop every itemstring in this table when dub by shears
]]
local enchantments = tool and mcl_enchanting.get_enchantments(tool, "silk_touch")
local silk_touch_drop = false
local nodedef = minetest.registered_nodes[dug_node.name]
if toolcaps ~= nil and toolcaps.groupcaps and toolcaps.groupcaps.shearsy_dig and nodedef._mcl_shears_drop then
if nodedef._mcl_shears_drop == true then
@ -309,39 +242,6 @@ function minetest.handle_node_drops(pos, drops, digger)
else
drops = nodedef._mcl_shears_drop
end
elseif tool and enchantments.silk_touch and nodedef._mcl_silk_touch_drop then
silk_touch_drop = true
if nodedef._mcl_silk_touch_drop == true then
drops = { dug_node.name }
else
drops = nodedef._mcl_silk_touch_drop
end
end
if tool and nodedef._mcl_fortune_drop and enchantments.fortune then
local fortune_level = enchantments.fortune
local fortune_drop = nodedef._mcl_fortune_drop
if fortune_drop.discrete_uniform_distribution then
local min_count = fortune_drop.min_count
local max_count = fortune_drop.max_count + fortune_level * (fortune_drop.factor or 1)
local chance = fortune_drop.chance or fortune_drop.get_chance and fortune_drop.get_chance(fortune_level)
if not chance or math.random() < chance then
drops = discrete_uniform_distribution(fortune_drop.multiply and drops or fortune_drop.items, min_count, max_count, fortune_drop.cap)
elseif fortune_drop.override then
drops = {}
end
else
-- Fixed Behavior
local drop = get_fortune_drops(fortune_drop, fortune_level)
drops = get_drops(drop, tool:get_name(), dug_node.param2, nodedef.paramtype2)
end
end
if digger and mcl_experience.throw_experience and not silk_touch_drop then
local experience_amount = minetest.get_item_group(dug_node.name,"xp")
if experience_amount > 0 then
mcl_experience.throw_experience(pos, experience_amount)
end
end
for _,item in ipairs(drops) do
@ -619,7 +519,6 @@ minetest.register_entity(":__builtin:item", {
minetest.log("warning", "Item entity with empty itemstring found at "..minetest.pos_to_string(self.object:get_pos()).. "! Deleting it now.")
self._removed = true
self.object:remove()
return
end
local p = self.object:get_pos()
@ -645,15 +544,12 @@ minetest.register_entity(":__builtin:item", {
local fg = minetest.get_item_group(nn, "fire")
local dg = minetest.get_item_group(nn, "destroys_items")
if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then
--Wait 2 seconds to allow mob drops to be cooked, & picked up instead of instantly destroyed.
if self.age > 2 then
if dg ~= 2 then
minetest.sound_play("builtin_item_lava", {pos = self.object:get_pos(), gain = 0.5})
end
self._removed = true
self.object:remove()
return
if dg ~= 2 then
minetest.sound_play("builtin_item_lava", {pos = self.object:get_pos(), gain = 0.5}, true)
end
self._removed = true
self.object:remove()
return
end
-- Push item out when stuck inside solid opaque node

View File

@ -175,19 +175,6 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
cart.on_activate_by_rail = on_activate_by_rail
function cart:on_step(dtime)
local ctrl, player = nil, nil
if self._driver then
player = minetest.get_player_by_name(self._driver)
if player then
ctrl = player:get_player_control()
-- player detach
if ctrl.sneak then
detach_driver(self)
return
end
end
end
local vel = self.object:get_velocity()
local update = {}
if self._last_float_check == nil then
@ -203,14 +190,18 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
node = minetest.get_node(rou_pos)
local g = minetest.get_item_group(node.name, "connect_to_raillike")
if g ~= self._railtype and self._railtype ~= nil then
local player
-- Detach driver
if player then
if self._driver then
if self._old_pos then
self.object:set_pos(self._old_pos)
end
mcl_player.player_attached[self._driver] = nil
player:set_detach()
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
player = minetest.get_player_by_name(self._driver)
if player then
player:set_detach()
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
end
end
-- Explode if already ignited
@ -346,6 +337,14 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
end
end
local ctrl, player = nil, nil
if self._driver then
player = minetest.get_player_by_name(self._driver)
if player then
ctrl = player:get_player_control()
end
end
-- Stop cart if velocity vector flips
if self._old_vel and self._old_vel.y == 0 and
(self._old_vel.x * vel.x < 0 or self._old_vel.z * vel.z < 0) then
@ -415,17 +414,14 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
-- Slow down or speed up
local acc = dir.y * -1.8
local friction = 0.4
local speed_mod = minetest.registered_nodes[minetest.get_node(pos).name]._rail_acceleration
acc = acc - friction
if has_fuel then
acc = acc + 0.6
end
if speed_mod and speed_mod ~= 0 then
acc = acc + speed_mod + friction
acc = acc + 0.2
elseif speed_mod and speed_mod ~= 0 then
acc = acc + speed_mod
else
acc = acc - 0.4
end
new_acc = vector.multiply(dir, acc)
@ -644,7 +640,6 @@ register_minecart(
if player then
mcl_player.player_set_animation(player, "sit" , 30)
player:set_eye_offset({x=0, y=-5.5, z=0},{x=0, y=-4, z=0})
mcl_tmp_message.message(clicker, S("Sneak to dismount"))
end
end, name)
end

View File

@ -1,36 +0,0 @@
# textdomain: mcl_minecarts
Minecart=Вагонетка
Minecarts can be used for a quick transportion on rails.=Вагонетки нужны, чтобы быстро перемещаться по рельсам.
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Вагонетки едут строго по проложенному железнодорожному пути. На Т-образной развилке они поворачивают налево. Скорость зависит от типа рельсов.
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Вы ставите вагонетку на рельсы. Правым кликом садитесь в неё. Стукаете, чтобы начать движение.
To obtain the minecart, punch it while holding down the sneak key.=Чтобы взять вагонетку, стукните её, удерживая клавишу [Красться].
A minecart with TNT is an explosive vehicle that travels on rail.=Вагон тротила это подрывной железнодорожный транспорт.
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Поместите его на рельсы. Стукните, чтобы он поехал. Тротил воспламеняется, если его поджечь огнивом, либо при попадании на подключенный рельсовый активатор.
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Чтобы взять вагон тротила, стукните его, удерживая клавишу [Красться]. Если тротил воспламенён, сделать это нельзя.
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Вагон с печью - это железнодорожный транспорт. Он может двигаться за счёт топлива.
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Поставьте его на рельсы. Если добавить немного угля, то печь зажжётся на продолжительное время и вагон сможет ехать. Стукните вагон для начала движения.
To obtain the minecart and furnace, punch them while holding down the sneak key.=Чтобы взять вагон с печью, стукните его, удерживая клавишу [Красться].
Minecart with Chest=Вагон с сундуком
Minecart with Furnace=Вагон с печью
Minecart with Command Block=Вагон с командным блоком
Minecart with Hopper=Вагон с бункером
Minecart with TNT=Вагон тротила
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Поместите на землю, чтобы сделать железную дорогу, рельсы автоматически соединятся между собой и будут превращаться в плавный повороты, T-образные развилки, перекрёстки и уклоны там, где это потребуется.
Rail=Рельсы
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Рельсы используются для строительства железной дороги. Обычные рельсы немного замедляют движение вагонеток из-за трения.
Powered Rail=Подключаемые рельсы
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Рельсы используются для строительства железной дороги. Подключённые рельсы могут разгонять и тормозить вагонетки.
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Без энергии редстоуна рельсы будут тормозить вагонетки.
Activator Rail=Рельсовый активатор
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Рельсы используются для строительства железной дороги. Рельсовый активатор активирует особые вагонетки.
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Чтобы этот блок рельсов активировал вагонетку, подключите его к энергии редстоуна и направьте вагонетку через него.
Detector Rail=Рельсовый детектор
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Рельсы используются для строительства железной дороги. Рельсовый детектор может обнаруживать вагонетку у себя наверху и подключать механизмы редстоуна.
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Чтобы обнаруживать вагонетку и подавать энергию редстоуна, подключите его к дорожке редстоуна или механизму редстоуна, после чего направьте любую вагонетку через него.
Track for minecarts=Железная дорога
Speed up when powered, slow down when not powered=Разгоняет, если подключён, тормозит, если не подключён
Activates minecarts when powered=Активирует особые вагонетки, если подключён
Emits redstone power when a minecart is detected=Испускает энергию редстоуна при обнаружении вагонетки
Vehicle for fast travel on rails=Быстрый железнодорожный транспорт
Can be ignited by tools or powered activator rail=Можно воспламенить с помощью инструмента или подключенного рельсового активатора
Sneak to dismount=Нажмите [Красться] для высадки

View File

@ -33,4 +33,3 @@ Activates minecarts when powered=
Emits redstone power when a minecart is detected=
Vehicle for fast travel on rails=
Can be ignited by tools or powered activator rail=
Sneak to dismount=

File diff suppressed because it is too large Load Diff

View File

@ -108,7 +108,6 @@ functions needed for the mob to work properly which contains the following:
'explosion_timer' number of seconds before mob explodes while its target
is still inside reach or explosion_damage_radius,
defaults to 3.
'explosiontimer_reset_radius' The distance you must travel before the timer will be reset.
'allow_fuse_reset' Allow 'explode' attack_type to reset fuse and resume
chasing if target leaves the blast radius or line of
sight. Defaults to true.
@ -146,14 +145,12 @@ functions needed for the mob to work properly which contains the following:
'base_pitch' base pitch to use adult mobs, default is 1.0 (MCL2 extension)
'random' played randomly from time to time.
also played for overfeeding animal.
'eat' played when mob eats something
'war_cry' what you hear when mob starts to attack player. (currently disabled)
'attack' what you hear when being attacked.
'shoot_attack' sound played when mob shoots.
'damage' sound heard when mob is hurt.
'death' played when mob is killed.
'jump' played when mob jumps. There's a built-in cooloff timer to avoid sound spam
'flop' played when mob flops (like a stranded fish)
'fuse' sound played when mob explode timer starts.
'explode' sound played when mob explodes.
@ -225,8 +222,6 @@ functions needed for the mob to work properly which contains the following:
'speed_normal' is used for animation speed for compatibility with some
older mobs.
'pushable' Allows players, & other mobs to push the mob.
MineClone 2 extensions:
@ -246,14 +241,6 @@ functions needed for the mob to work properly which contains the following:
dir is mob's aiming direction
'sounds_child' same as sounds, but for childs. If not defined, childs will use same
sound as adults but with higher pitch
'follow_velocity' The speed at which a mob moves toward the player when they're holding the appropriate follow item.
'instant_death' If true, mob dies instantly (no death animation or delay) (default: false)
'xp_min' the minimum XP it drops on death (default: 0)
'xp_max' the maximum XP it drops on death (default: 0)
'fire_resistant' If true, the mob can't burn
'fire_damage_resistant' If true the mob will not take damage when burning
'ignited_by_sunlight' If true the mod will burn at daytime. (Takes sunlight_damage per second)
Node Replacement
@ -294,9 +281,8 @@ Custom Definition Functions
Along with the above mob registry settings we can also use custom functions to
enhance mob functionality and have them do many interesting things:
'on_die' a function that is called when the mob is killed; the
parameters are (self, pos). Return true to skip the builtin
death animation and death effects
'on_die' a function that is called when the mob is killed the
parameters are (self, pos)
'on_rightclick' its same as in minetest.register_entity()
'on_blast' is called when an explosion happens near mob when using TNT
functions, parameters are (object, damage) and returns
@ -353,14 +339,6 @@ for each mob.
dogs
'self.order' set to "follow" or "stand" so that npc will follow owner
or stand it's ground
'self.state' Current mob state.
"stand": no movement (except turning around)
"walk": walk or move around aimlessly
"attack": chase and attack enemy
"runaway": flee from target
"flop": bounce around aimlessly
(for swimming mobs that have stranded)
"die": during death
'self.nametag' contains the name of the mob which it can show above
@ -431,10 +409,6 @@ This function spawns a mob as a child. The parameter mob_type is the
entitystring of the new mob.
This function returns the mob on success and nil otherwise.
mobs:death_effect(pos, collisionbox)
Create death particles at pos with the given collisionbox.
Making Arrows
-------------

View File

@ -1,11 +0,0 @@
# textdomain: mcl_mobs
Peaceful mode active! No monsters will spawn.=Мирный режим включён! Монстры не будут появляться.
This allows you to place a single mob.=Позволяет вам разместить одного моба.
Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns.=Просто поместите это туда, где хотите, чтобы появился моб. Животные будут появляться уже прирученные, если это не нужно, удерживайте клавишу [Красться] при размещении. Если поместить это на спаунер, появляющийся из него моб будет изменён.
You need the “maphack” privilege to change the mob spawner.=Вам нужно обладать привилегией “maphack”, чтобы изменить спаунер моба.
Name Tag=Именная бирка
A name tag is an item to name a mob.=Именная бирка это предмет, чтобы дать мобу имя.
Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag.=Прежде чем использовать именную бирку, нужно задать имя на наковальне. Тогда вы сможете использовать бирку, чтобы дать имя мобу.
Only peaceful mobs allowed!=Разрешены только мирные мобы!
Give names to mobs=Даёт имена мобам
Set name at anvil=Задайте имя при помощи наковальни

View File

@ -1,3 +1,2 @@
name = mcl_mobs
depends = mcl_particles
optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, invisibility, lucky_block, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience
optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, invisibility, lucky_block, cmi, doc_identifier, mcl_armor

View File

@ -10,14 +10,13 @@ This mod contains the API only for adding your own mobs into the world, so pleas
https://forum.minetest.net/viewtopic.php?f=11&t=9917
------------
Credits:
mcl_mobs_mob_poof.ogg:
- by Planman (license: Creative Commons Zero)
- Source: <https://freesound.org/people/Planman/sounds/208111/>
Items:
- Nametag (paper, black dye, string) can be used right-click on a tamed mob to give them a name.
Lucky Block items: 1
------------
Changelog from original Mobs Redo mod:
- 1.41- Mob pathfinding has been updated thanks to Elkien3

View File

@ -143,7 +143,6 @@ minetest.register_entity("mcl_paintings:painting", {
_xsize = 1,
_ysize = 1,
on_activate = function(self, staticdata)
self.object:set_armor_groups({immortal = 1})
if staticdata and staticdata ~= "" then
local data = minetest.deserialize(staticdata)
if data then
@ -166,20 +165,18 @@ minetest.register_entity("mcl_paintings:painting", {
}
return minetest.serialize(data)
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
-- Drop as item on punch
if puncher and puncher:is_player() then
kname = puncher:get_player_name()
on_death = function(self, killer)
-- Drop as item on death
local kname = ""
if killer and killer:is_player() then
kname = killer:get_player_name()
end
if not minetest.is_creative_enabled(kname) then
local pos = self._pos
if not pos then
pos = self.object:get_pos()
end
if not minetest.is_protected(pos, kname) then
self.object:remove()
if not minetest.is_creative_enabled(kname) then
minetest.add_item(pos, "mcl_paintings:painting")
end
end
minetest.add_item(pos, "mcl_paintings:painting")
end
end,
})

View File

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

View File

@ -1,2 +0,0 @@
# textdomain:mcl_paintings
Painting=Рисование

View File

@ -39,7 +39,6 @@ minetest.register_node("mobs_mc:arrow_box", {
}
},
tiles = {"mcl_bows_arrow.png^[transformFX", "mcl_bows_arrow.png^[transformFX", "mcl_bows_arrow_back.png", "mcl_bows_arrow_front.png", "mcl_bows_arrow.png", "mcl_bows_arrow.png^[transformFX"},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype = "light",
paramtype2 = "facedir",
sunlight_propagates = true,

View File

@ -1,20 +1,11 @@
local function is_forbidden_node(pos, node)
node = node or minetest.get_node(pos)
return minetest.get_item_group(node.name, "stair") > 0 or minetest.get_item_group(node.name, "slab") > 0 or minetest.get_item_group(node.name, "carpet") > 0
end
function mobs:spawn_abm_check(pos, node, name)
-- Don't spawn monsters on mycelium
if (node.name == "mcl_core:mycelium" or node.name == "mcl_core:mycelium_snow") and minetest.registered_entities[name].type == "monster" then
return true
--Don't Spawn mobs on stairs, slabs, or carpets
elseif is_forbidden_node(pos, node) or is_forbidden_node(vector.add(pos, vector.new(0, 1, 0))) then
return true
-- Spawn on opaque or liquid nodes
elseif minetest.get_item_group(node.name, "opaque") ~= 0 or minetest.registered_nodes[node.name].liquidtype ~= "none" or node.name == "mcl_core:grass_path" then
elseif minetest.get_item_group(node.name, "opaque") ~= 0 or minetest.registered_nodes[node.name].liquidtype ~= "none" then
return false
end
-- Reject everything else
return true
end

View File

@ -84,12 +84,6 @@ Origin of those models:
* [AGFX](http://www.freesound.org/people/DrMinky/sounds/) (CC0)
* `mobs_mc_chicken_child.ogg`
* Source: <https://freesound.org/people/AGFX/sounds/43380/>
* [evsecrets](https://freesound.org/people/evsecrets/sounds/) (CC0)
* `mobs_mc_chicken_*.ogg`
* Source: <https://freesound.org/people/evsecrets/sounds/346961/>
* [contramundum](https://freesound.org/people/contramundum/sounds/)
* `mobs_mc_parrot_*.ogg`
* Source: <https://freesound.org/people/contramundum/sounds/388417/>
* Randomation (CC0)
* `green_slime_damage.ogg`
* `green_slime_attack.ogg`
@ -105,78 +99,27 @@ Origin of those models:
* `mobs_mc_cow_hurt.ogg` (CC0)
* Heavily modified
* Source: <https://freesound.org/people/Bird_man/packs/16972/>
* [Klaraschick](https://freesound.org/people/Klaraschick/)
* `mobs_mc_cow_milk.ogg` (CC0)
* shortened
* Source: <https://freesound.org/people/Klaraschick/sounds/415312/>
* [Hitrison](https://freesound.org/people/Hitrison/)
* `mobs_mc_cow_mushroom_stew.ogg` (CC BY 3.0)
* sound was modified
* Source: <https://freesound.org/people/Hitrison/sounds/251411/>
* [NPXcoot](https://github.com/NPXcoot1) (CC BY-SA 4.0)
* `mobs_mc_ender_dragon_*`
* [bevibeldesign](https://freesound.org/people/bevibeldesign/)
* `mobs_mc_wither_spawn.ogg` (CC0)
* Source: <https://freesound.org/people/bevibeldesign/sounds/366095/>
* [rubberduck](https://opengameart.org/users/rubberduck)
* `mobs_mc_endermite_*.ogg` (CC0)
* `mobs_mc_zombiepig_*.ogg` (CC0)
* `mobs_mc_enderman_teleport_*.ogg` (CC0)
* Source 1: <https://opengameart.org/content/80-cc0-creature-sfx>
* Source 2: <https://opengameart.org/content/80-cc0-creture-sfx-2>
* [Soundscapes55](https://freesound.org/people/Soundscapes55/)
* `mobs_mc_enderman_random.1.ogg` (CC0)
* Source: <https://freesound.org/people/Soundscapes55/sounds/434973/>
* [griffinjennings](https://freesound.org/people/griffinjennings/)
* `mobs_mc_enderman_death.*.ogg` (CC BY 3.0)
* `mobs_mc_enderman_hurt.*.ogg` (CC BY 3.0)
* Sounds were heavily modified
* Source: <https://freesound.org/people/griffinjennings/sounds/463972/>
* [pointparkcinema](https://freesound.org/people/pointparkcinema/)
* `mobs_mc_guardian_random.1.ogg` (CC0)
* Source: <https://freesound.org/people/pointparkcinema/sounds/407252/>
* [nornalbion](https://freesound.org/people/nornalbion/)
* `mobs_mc_guardian_random.2.ogg` (CC BY 3.0)
* `mobs_mc_guardian_random.3.ogg` (CC BY 3.0)
* `mobs_mc_guardian_hurt.*.ogg` (CC BY 3.0)
* Sounds were modified
* Source: <https://freesound.org/people/nornalbion/sounds/195733/>
* [TheBuilder15](https://freesound.org/people/TheBuilder15/)
* `mobs_mc_guardian_death.ogg` (CC0)
* Source: <https://freesound.org/people/pointparkcinema/sounds/407252/>
* Blender Foundation (CC BY 3.0)
* `mobs_sheep.ogg`,
* daufinsyd (MIT License)
* `mobs_mc_blaze_breath.ogg`
* `mobs_mc_blaze_died.ogg`
* [qubodup](https://opengameart.org/content/slime-monster)
* `mobs_mc_squid_hurt.*.ogg` (CC BY 3.0)
* `mobs_mc_squid_death.*.ogg` (CC BY 3.0)
* Changes were made
* Source: <https://opengameart.org/content/slime-monster>
* [kyles](https://freesound.org/people/kyles/)
* `mobs_mc_squid_flop.*.ogg` (CC0)
* Source: <https://freesound.org/people/kyles/sounds/450830/>
* `mobs_mc_snowman_hurt.1.ogg` (CC0)
* Source: <https://freesound.org/people/kyles/sounds/450848/>
* `mobs_mc_squid_hurt.ogg`
* [thefilmbakery](https://freesound.org/people/thefilmbakery/) (CC0)
* `mobs_mc_blaze_hurt.ogg`
* Source: <https://freesound.org/people/thefilmbakery/sounds/137836/>
* TenPlus1, from `mobs_monster` or `mobs_animal` mod (MIT License)
* `mobs_chicken.ogg`
* `mobs_fireball.ogg`
* `mobs_mc_cat_idle.1.ogg`
* `mobs_mc_llama.ogg`
* `mobs_pig.ogg`
* `mobs_pig_angry.ogg`
* `mobs_rat.ogg`
* `mobs_sandmonster.ogg`
* [Daysycho](https://freesound.org/people/Darsycho/)
* `mobs_mc_spider_hurt.*.ogg` (CC0)
* Source: <https://freesound.org/people/Darsycho/sounds/505185/>
* [columbia23](https://freesound.org/people/columbia23/)
* `mobs_mc_spider_death.ogg` (CC BY 3.0)
* `mobs_mc_spider_random.*.ogg` (CC BY 3.0)
* `mobs_mc_spider_attack.*.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/columbia23/sounds/395395/>
* `mobs_spider.ogg`
* BrandonReese (LGPL v2.1)
* `mobs_eerie.ogg`
* [Under7dude](https://freesound.org/people/Under7dude/) (CC0)
@ -204,13 +147,6 @@ Origin of those models:
* Source: <https://freesound.org/people/GoodListener/sounds/322454/>
* `mobs_mc_horse_death.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/GoodListener/sounds/322445/>
* [Garuda1982](https://freesound.org/people/Garuda1982/)
* `mobs_mc_donkey_random.1.ogg` (CC BY 3.0)
* `mobs_mc_donkey_hurt.ogg` (CC BY 3.0)
* `mobs_mc_donkey_death.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/Garuda1982/sounds/539505/>
* [JarredGibb](https://freesound.org/people/JarredGibb/sounds/233131/)
* `mobs_mc_donkey_random.2.ogg` (CC0)
* [ERH](https://freesound.org/people/ERH/)
* `mobs_mc_horse_random.2.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/ERH/sounds/32043/>
@ -228,10 +164,6 @@ Origin of those models:
* [suonho](https://freesound.org/people/suonho/)
* `mobs_mc_bat_idle.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/suonho/sounds/59344/>
* [toefur](https://freesound.org/people/toefur/)
* `mobs_mc_bat_hurt.*.ogg` (CC0)
* `mobs_mc_bat_death.ogg` (CC0)
* Source: <https://freesound.org/people/toefur/sounds/288941/>
* [cmusounddesign](https://freesound.org/people/cmusounddesign/)
* `mobs_mc_cat_hiss.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/cmusounddesign/sounds/71899/>
@ -241,16 +173,6 @@ Origin of those models:
* [ebcrosby](https://freesound.org/people/ebcrosby/)
* `mobs_mc_ocelot_hurt.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/ebcrosby/sounds/332979/>
* Hybrid Dog (forum.minetest.net)
* `mobs_mc_wolf_hurt.*.ogg` (CC0)
* `mobs_mc_wolf_bark.*.ogg` (CC0)
* `mobs_mc_wolf_death.*.ogg` (CC0)
* `mobs_mc_wolf_growl.*.ogg` (CC0)
* Sounds modified and simplified
* Source: "dogblocks" mod by Hybrid Dog <https://github.com/HybridDog/dogblocks/>
* [cliftoncarlson](https://freesound.org/people/cliftonmcarlson/)
* `mobs_mc_wolf_take_bone.ogg` (CC0)
* Source: <https://freesound.org/people/cliftonmcarlson/sounds/392883/>
* [Inocodum](https://forum.minetest.net/memberlist.php?mode=viewprofile&u=3115)
* `mobs_mc_silverfish_hurt.ogg` (CC BY-SA 4.0)
* `mobs_mc_silverfish_death.ogg` (CC BY-SA 4.0)
@ -264,45 +186,6 @@ Origin of those models:
* [kbnevel](https://freesound.org/people/kbnevel/)
* `mobs_mc_magma_cube_attack.ogg` (CC0)
* Derived from: <https://freesound.org/people/kbnevel/sounds/119863/>
* [InspectorJ](https://freesound.org/people/InspectorJ/sounds/429591/)
* `mobs_mc_animal_eat_generic.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/InspectorJ/>
* [tbsounddesigns](https://freesound.org/people/tbsounddesigns/)
* `mobs_mc_bear_random.*.ogg` (CC BY 3.0)
* Source 1: <https://freesound.org/people/tbsounddesigns/sounds/416853/>
* Source 2: <https://freesound.org/people/tbsounddesigns/sounds/416857/>
* Source 3: <https://freesound.org/people/tbsounddesigns/sounds/416855/>
* `mobs_mc_bear_growl.*.ogg` (CC BY 3.0)
* Source 1: <https://freesound.org/people/tbsounddesigns/sounds/416861/>
* Source 2: <https://freesound.org/people/tbsounddesigns/sounds/416859/>
* Source 3: <https://freesound.org/people/tbsounddesigns/sounds/416862/>
* [YleArkisto](https://freesound.org/people/YleArkisto/)
* `mobs_mc_bear_attack.*.ogg` (CC BY 3.0)
* `mobs_mc_bear_death.*.ogg` (CC BY 3.0)
* `mobs_mc_bear_hurt.1.ogg` (CC BY 3.0)
* Changes were made
* Source: <https://freesound.org/people/YleArkisto/sounds/249441/>
* [alexo400](https://freesound.org/people/alexo400/)
* `mobs_mc_snowman_death.*.ogg` (CC0)
* Source: <https://freesound.org/people/alexo400/sounds/543385/>
* [cabled\_mess](https://freesound.org/people/cabled_mess/)
* `mobs_mc_snowman_hurt.2.ogg` (CC0)
* Source: <https://freesound.org/people/cabled_mess/sounds/384424/>
* `mobs_mc_snowman_hurt.3.ogg` (CC0)
* Source: <https://freesound.org/people/cabled_mess/sounds/384421/>
* [kessir](https://freesound.org/people/kessir/sounds/)
* `mobs_mc_rabbit_hurt.*.ogg` (CC0)
* `mobs_mc_rabbit_death.2.ogg` (CC0)
* `mobs_mc_rabbit_death.3.ogg` (CC0)
* Source: <https://freesound.org/people/kessir/sounds/372075/>
* `mobs_mc_rabbit_attack.*.ogg` (CC0)
* Source: <https://freesound.org/people/kessir/sounds/372076/>
* `mobs_mc_rabbit_death.1.ogg` (CC0)
* Source: <https://freesound.org/people/kessir/sounds/385850/>
* [Alshred](https://freesound.org/people/Alshred/sounds/403773/)
* `mobs_mc_rabbit_random.*.ogg` (CC0)
* Changes were made.
* Source: <https://freesound.org/people/Alshred/>
Note: Many of these sounds have been more or less modified to fit the game.

View File

@ -18,8 +18,6 @@ mobs:register_mob("mobs_mc:bat", {
visual_size = {x=1, y=1},
sounds = {
random = "mobs_mc_bat_idle",
damage = "mobs_mc_bat_hurt",
death = "mobs_mc_bat_death",
distance = 16,
},
walk_velocity = 4.5,
@ -35,19 +33,18 @@ mobs:register_mob("mobs_mc:bat", {
run_speed = 80,
run_start = 0,
run_end = 40,
die_speed = 60,
-- TODO: Less ugly death animation
--[[ die_speed = 60,
die_start = 40,
die_end = 80,
die_loop = false,
]]
},
walk_chance = 100,
fall_damage = 0,
view_range = 16,
fear_height = 0,
jump = false,
fly = true,
makes_footstep_sound = false,
})

View File

@ -15,8 +15,6 @@ mobs:register_mob("mobs_mc:blaze", {
spawn_class = "hostile",
hp_min = 20,
hp_max = 20,
xp_min = 10,
xp_max = 10,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.79, 0.3},
rotate = -180,
visual = "mesh",
@ -24,7 +22,7 @@ mobs:register_mob("mobs_mc:blaze", {
textures = {
{"mobs_mc_blaze.png"},
},
armor = { fleshy = 100, snowball_vulnerable = 100, water_vulnerable = 100 },
armor = { fleshy = 100, snowball_vulnerable = 100 },
visual_size = {x=3, y=3},
sounds = {
random = "mobs_mc_blaze_breath",
@ -41,8 +39,7 @@ mobs:register_mob("mobs_mc:blaze", {
{name = mobs_mc.items.blaze_rod,
chance = 1,
min = 0,
max = 1,
looting = "common",},
max = 1,},
},
animation = {
stand_speed = 25,
@ -71,10 +68,8 @@ mobs:register_mob("mobs_mc:blaze", {
jump = true,
jump_height = 4,
fly = true,
makes_footstep_sound = false,
fear_height = 0,
glow = 14,
fire_resistant = true,
})
mobs:spawn_specific("mobs_mc:blaze", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 5000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
@ -88,10 +83,6 @@ mobs:register_arrow("mobs_mc:blaze_fireball", {
-- Direct hit, no fire... just plenty of pain
hit_player = function(self, player)
if rawget(_G, "armor") and armor.last_damage_types then
armor.last_damage_types[player:get_player_name()] = "fireball"
end
mcl_burning.set_on_fire(player, 5, "blaze")
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 5},
@ -99,7 +90,6 @@ mobs:register_arrow("mobs_mc:blaze_fireball", {
end,
hit_mob = function(self, mob)
mcl_burning.set_on_fire(mob, 5)
mob:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 5},

View File

@ -14,8 +14,6 @@ mobs:register_mob("mobs_mc:chicken", {
hp_min = 4,
hp_max = 4,
xp_min = 1,
xp_max = 3,
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.69, 0.2},
runaway = true,
floats = 1,
@ -32,28 +30,23 @@ mobs:register_mob("mobs_mc:chicken", {
{name = mobs_mc.items.chicken_raw,
chance = 1,
min = 1,
max = 1,
looting = "common",},
max = 1,},
{name = mobs_mc.items.feather,
chance = 1,
min = 0,
max = 2,
looting = "common",},
max = 2,},
},
fall_damage = 0,
fall_speed = -2.25,
sounds = {
random = "mobs_mc_chicken_buck",
damage = "mobs_mc_chicken_hurt",
death = "mobs_mc_chicken_hurt",
eat = "mobs_mc_animal_eat_generic",
random = "mobs_chicken",
-- TODO: death, damage
distance = 16,
},
sounds_child = {
random = "mobs_mc_chicken_child",
damage = "mobs_mc_chicken_child",
death = "mobs_mc_chicken_child",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
},
animation = {

View File

@ -7,8 +7,6 @@ local cow_def = {
spawn_class = "passive",
hp_min = 10,
hp_max = 10,
xp_min = 1,
xp_max = 3,
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.39, 0.45},
visual = "mesh",
mesh = "mobs_mc_cow.b3d",
@ -23,28 +21,24 @@ local cow_def = {
{name = mobs_mc.items.beef_raw,
chance = 1,
min = 1,
max = 3,
looting = "common",},
max = 3,},
{name = mobs_mc.items.leather,
chance = 1,
min = 0,
max = 2,
looting = "common",},
max = 2,},
},
runaway = true,
sounds = {
random = "mobs_mc_cow",
damage = "mobs_mc_cow_hurt",
death = "mobs_mc_cow_hurt",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
},
animation = {
stand_speed = 25, walk_speed = 40,
run_speed = 60, stand_start = 0,
stand_end = 0, walk_start = 0,
walk_end = 40, run_start = 0,
run_end = 40,
stand_speed = 25, walk_speed = 25, run_speed = 50,
stand_start = 0, stand_end = 0,
walk_start = 0, walk_end = 40,
run_start = 0, run_end = 40,
},
follow = mobs_mc.follow.cow,
on_rightclick = function(self, clicker)
@ -59,7 +53,6 @@ local cow_def = {
if item:get_name() == mobs_mc.items.bucket and clicker:get_inventory() then
local inv = clicker:get_inventory()
inv:remove_item("main", mobs_mc.items.bucket)
minetest.sound_play("mobs_mc_cow_milk", {pos=self.object:get_pos(), gain=0.6})
-- if room add bucket of milk to inventory, otherwise drop as item
if inv:room_for_item("main", {name=mobs_mc.items.milk}) then
clicker:get_inventory():add_item("main", mobs_mc.items.milk)
@ -95,7 +88,7 @@ mooshroom_def.on_rightclick = function(self, clicker)
-- Use shears to get mushrooms and turn mooshroom into cow
if item:get_name() == mobs_mc.items.shears then
local pos = self.object:get_pos()
minetest.sound_play("mcl_tools_shears_cut", {pos = pos}, true)
minetest.sound_play("shears", {pos = pos}, true)
if self.base_texture[1] == "mobs_mc_mooshroom_brown.png" then
minetest.add_item({x=pos.x, y=pos.y+1.4, z=pos.z}, mobs_mc.items.mushroom_brown .. " 5")
@ -116,7 +109,6 @@ mooshroom_def.on_rightclick = function(self, clicker)
elseif item:get_name() == mobs_mc.items.bucket and clicker:get_inventory() then
local inv = clicker:get_inventory()
inv:remove_item("main", mobs_mc.items.bucket)
minetest.sound_play("mobs_mc_cow_milk", {pos=self.object:get_pos(), gain=0.6})
-- If room, add milk to inventory, otherwise drop as item
if inv:room_for_item("main", {name=mobs_mc.items.milk}) then
clicker:get_inventory():add_item("main", mobs_mc.items.milk)
@ -129,7 +121,6 @@ mooshroom_def.on_rightclick = function(self, clicker)
elseif item:get_name() == mobs_mc.items.bowl and clicker:get_inventory() then
local inv = clicker:get_inventory()
inv:remove_item("main", mobs_mc.items.bowl)
minetest.sound_play("mobs_mc_cow_mushroom_stew", {pos=self.object:get_pos(), gain=0.6})
-- If room, add mushroom stew to inventory, otherwise drop as item
if inv:room_for_item("main", {name=mobs_mc.items.mushroom_stew}) then
clicker:get_inventory():add_item("main", mobs_mc.items.mushroom_stew)

View File

@ -14,15 +14,12 @@ mobs:register_mob("mobs_mc:creeper", {
spawn_class = "hostile",
hp_min = 20,
hp_max = 20,
xp_min = 5,
xp_max = 5,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.69, 0.3},
pathfinding = 1,
visual = "mesh",
mesh = "mobs_mc_creeper.b3d",
textures = {
{"mobs_mc_creeper.png",
"mobs_mc_empty.png"},
{"mobs_mc_creeper.png"},
},
visual_size = {x=3, y=3},
sounds = {
@ -38,12 +35,9 @@ mobs:register_mob("mobs_mc:creeper", {
run_velocity = 2.1,
runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" },
attack_type = "explode",
explosion_strength = 3,
explosion_radius = 3.5,
explosion_damage_radius = 3.5,
explosiontimer_reset_radius = 6,
reach = 3,
reach = 4,
explosion_timer = 1.5,
allow_fuse_reset = true,
stop_to_explode = true,
@ -75,21 +69,17 @@ mobs:register_mob("mobs_mc:creeper", {
if self._forced_explosion_countdown_timer ~= nil then
self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime
if self._forced_explosion_countdown_timer <= 0 then
mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
mobs:boom(self, self.object:get_pos(), self.explosion_strength)
self.object:remove()
end
end
end,
on_die = function(self, pos, cmi_cause)
-- Drop a random music disc when killed by skeleton or stray
if cmi_cause and cmi_cause.type == "punch" then
local luaentity = cmi_cause.puncher and cmi_cause.puncher:get_luaentity()
if luaentity and luaentity.name:find("arrow") then
local shooter_luaentity = luaentity._shooter and luaentity._shooter:get_luaentity()
if shooter_luaentity and (shooter_luaentity.name == "mobs_mc:skeleton" or shooter_luaentity.name == "mobs_mc:stray") then
minetest.add_item({x=pos.x, y=pos.y+1, z=pos.z}, mobs_mc.items.music_discs[math.random(1, #mobs_mc.items.music_discs)])
end
end
on_die = function(self, pos)
-- Drop a random music disc
-- TODO: Only do this if killed by skeleton
if math.random(1, 200) == 1 then
local r = math.random(1, #mobs_mc.items.music_discs)
minetest.add_item({x=pos.x, y=pos.y+1, z=pos.z}, mobs_mc.items.music_discs[r])
end
end,
maxdrops = 2,
@ -97,8 +87,7 @@ mobs:register_mob("mobs_mc:creeper", {
{name = mobs_mc.items.gunpowder,
chance = 1,
min = 0,
max = 2,
looting = "common",},
max = 2,},
-- Head
-- TODO: Only drop if killed by charged creeper
@ -128,127 +117,6 @@ mobs:register_mob("mobs_mc:creeper", {
view_range = 16,
})
mobs:register_mob("mobs_mc:creeper_charged", {
type = "monster",
spawn_class = "hostile",
hp_min = 20,
hp_max = 20,
xp_min = 5,
xp_max = 5,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.69, 0.3},
pathfinding = 1,
visual = "mesh",
mesh = "mobs_mc_creeper.b3d",
textures = {
{"mobs_mc_creeper.png",
"mobs_mc_creeper_charge.png"},
},
visual_size = {x=3, y=3},
sounds = {
attack = "tnt_ignite",
death = "mobs_mc_creeper_death",
damage = "mobs_mc_creeper_hurt",
fuse = "tnt_ignite",
explode = "tnt_explode",
distance = 16,
},
makes_footstep_sound = true,
walk_velocity = 1.05,
run_velocity = 2.1,
runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" },
attack_type = "explode",
explosion_strength = 6,
explosion_radius = 8,
explosion_damage_radius = 8,
explosiontimer_reset_radius = 6,
reach = 3,
explosion_timer = 1.5,
allow_fuse_reset = true,
stop_to_explode = true,
-- Force-ignite creeper with flint and steel and explode after 1.5 seconds.
-- TODO: Make creeper flash after doing this as well.
-- TODO: Test and debug this code.
on_rightclick = function(self, clicker)
if self._forced_explosion_countdown_timer ~= nil then
return
end
local item = clicker:get_wielded_item()
if item:get_name() == mobs_mc.items.flint_and_steel then
if not minetest.is_creative_enabled(clicker:get_player_name()) then
-- Wear tool
local wdef = item:get_definition()
item:add_wear(1000)
-- Tool break sound
if item:get_count() == 0 and wdef.sound and wdef.sound.breaks then
minetest.sound_play(wdef.sound.breaks, {pos = clicker:get_pos(), gain = 0.5}, true)
end
clicker:set_wielded_item(item)
end
self._forced_explosion_countdown_timer = self.explosion_timer
minetest.sound_play(self.sounds.attack, {pos = self.object:get_pos(), gain = 1, max_hear_distance = 16}, true)
end
end,
do_custom = function(self, dtime)
if self._forced_explosion_countdown_timer ~= nil then
self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime
if self._forced_explosion_countdown_timer <= 0 then
mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
self.object:remove()
end
end
end,
on_die = function(self, pos, cmi_cause)
-- Drop a random music disc when killed by skeleton or stray
if cmi_cause and cmi_cause.type == "punch" then
local luaentity = cmi_cause.puncher and cmi_cause.puncher:get_luaentity()
if luaentity and luaentity.name:find("arrow") then
local shooter_luaentity = luaentity._shooter and luaentity._shooter:get_luaentity()
if shooter_luaentity and (shooter_luaentity.name == "mobs_mc:skeleton" or shooter_luaentity.name == "mobs_mc:stray") then
minetest.add_item({x=pos.x, y=pos.y+1, z=pos.z}, mobs_mc.items.music_discs[math.random(1, #mobs_mc.items.music_discs)])
end
end
end
end,
maxdrops = 2,
drops = {
{name = mobs_mc.items.gunpowder,
chance = 1,
min = 0,
max = 2,
looting = "common",},
-- Head
-- TODO: Only drop if killed by charged creeper
{name = mobs_mc.items.head_creeper,
chance = 200, -- 0.5%
min = 1,
max = 1,},
},
animation = {
speed_normal = 24,
speed_run = 48,
stand_start = 0,
stand_end = 23,
walk_start = 24,
walk_end = 49,
run_start = 24,
run_end = 49,
hurt_start = 110,
hurt_end = 139,
death_start = 140,
death_end = 189,
look_start = 50,
look_end = 108,
},
floats = 1,
fear_height = 4,
view_range = 16,
--Having trouble when fire is placed with lightning
fire_resistant = true,
glow = 3,
})
mobs:spawn_specific("mobs_mc:creeper", mobs_mc.spawn.solid, {"air"}, 0, 7, 20, 16500, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)

View File

@ -1,5 +1,4 @@
mcl_init
mcl_particles
default?
mcl_mobs
mcl_tnt?

View File

@ -12,8 +12,6 @@ mobs:register_mob("mobs_mc:enderdragon", {
walk_chance = 100,
hp_max = 200,
hp_min = 200,
xp_min = 500,
xp_max = 500,
collisionbox = {-2, 3, -2, 2, 5, 2},
physical = false,
visual = "mesh",
@ -25,7 +23,6 @@ mobs:register_mob("mobs_mc:enderdragon", {
view_range = 35,
walk_velocity = 6,
run_velocity = 6,
can_despawn = false,
sounds = {
-- TODO: more sounds
shoot_attack = "mobs_mc_ender_dragon_shoot",
@ -37,12 +34,17 @@ mobs:register_mob("mobs_mc:enderdragon", {
jump = true,
jump_height = 14,
fly = true,
makes_footstep_sound = false,
dogshoot_switch = 1,
dogshoot_count_max =5,
dogshoot_count2_max = 5,
passive = false,
attack_animals = true,
drops = {
{name = mobs_mc.items.dragon_egg,
chance = 1,
min = 1,
max = 1},
},
lava_damage = 0,
fire_damage = 0,
on_rightclick = nil,
@ -50,26 +52,14 @@ mobs:register_mob("mobs_mc:enderdragon", {
arrow = "mobs_mc:dragon_fireball",
shoot_interval = 0.5,
shoot_offset = -1.0,
xp_min = 12000,
xp_max = 12000,
animation = {
fly_speed = 8, stand_speed = 8,
stand_start = 0, stand_end = 20,
walk_start = 0, walk_end = 20,
run_start = 0, run_end = 20,
},
ignores_nametag = true,
on_die = function(self, own_pos)
if self._egg_spawn_pos then
local pos = minetest.string_to_pos(self._egg_spawn_pos)
--if minetest.get_node(pos).buildable_to then
minetest.set_node(pos, {name = mobs_mc.items.dragon_egg})
return
--end
end
minetest.add_item(own_pos, mobs_mc.items.dragon_egg)
end,
fire_resistant = true,
})

View File

@ -8,6 +8,7 @@
-- However, they have a reduced viewing range to make them less dangerous.
-- This differs from MC, in which endermen only become hostile when provoked,
-- and they are provoked by looking directly at them.
-- TODO: Implement MC behaviour.
-- Rootyjr
-----------------------------
@ -26,16 +27,6 @@
local S = minetest.get_translator("mobs_mc")
local telesound = function(pos, is_source)
local snd
if is_source then
snd = "mobs_mc_enderman_teleport_src"
else
snd = "mobs_mc_enderman_teleport_dst"
end
minetest.sound_play(snd, {pos=pos, max_hear_distance=16}, true)
end
--###################
--################### ENDERMAN
--###################
@ -43,10 +34,10 @@ end
local pr = PseudoRandom(os.time()*(-334))
-- How freqeuntly to take and place blocks, in seconds
local take_frequency_min = 235
local take_frequency_max = 245
local place_frequency_min = 235
local place_frequency_max = 245
local take_frequency_min = 25
local take_frequency_max = 90
local place_frequency_min = 10
local place_frequency_max = 30
-- Create the textures table for the enderman, depending on which kind of block
-- the enderman holds (if any).
@ -187,17 +178,16 @@ local select_enderman_animation = function(animation_type)
end
end
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
mobs:register_mob("mobs_mc:enderman", {
-- TODO: Endermen should be classified as passive
type = "monster",
spawn_class = "passive",
passive = true,
pathfinding = 1,
hp_min = 40,
hp_max = 40,
xp_min = 5,
xp_max = 5,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 2.89, 0.3},
visual = "mesh",
mesh = "mobs_mc_enderman.b3d",
@ -205,11 +195,9 @@ mobs:register_mob("mobs_mc:enderman", {
visual_size = {x=3, y=3},
makes_footstep_sound = true,
sounds = {
-- TODO: Custom war cry sound
war_cry = "mobs_sandmonster",
death = {name="mobs_mc_enderman_death", gain=0.7},
damage = {name="mobs_mc_enderman_hurt", gain=0.5},
random = {name="mobs_mc_enderman_random", gain=0.5},
death = "green_slime_death",
-- TODO: damage, random
distance = 16,
},
walk_velocity = 0.2,
@ -220,11 +208,11 @@ mobs:register_mob("mobs_mc:enderman", {
{name = mobs_mc.items.ender_pearl,
chance = 1,
min = 0,
max = 1,
looting = "common"},
max = 1,},
},
animation = select_enderman_animation("normal"),
_taken_node = "",
-- TODO: Teleport enderman on damage, etc.
do_custom = function(self, dtime)
-- PARTICLE BEHAVIOUR HERE.
local enderpos = self.object:get_pos()
@ -242,55 +230,52 @@ mobs:register_mob("mobs_mc:enderman", {
})
end
-- RAIN DAMAGE / EVASIVE WARP BEHAVIOUR HERE.
local dim = mcl_worlds.pos_to_dimension(enderpos)
if dim == "overworld" then
if mcl_weather.state == "rain" or mcl_weather.state == "lightning" then
local damage = true
local enderpos = self.object:get_pos()
enderpos.y = enderpos.y+2.89
local height = {x=enderpos.x, y=enderpos.y+512,z=enderpos.z}
local ray = minetest.raycast(enderpos, height, true)
-- Check for blocks above enderman.
for pointed_thing in ray do
if pointed_thing.type == "node" then
local nn = minetest.get_node(minetest.get_pointed_thing_position(pointed_thing)).name
local def = minetest.registered_nodes[nn]
if (not def) or def.walkable then
-- There's a node in the way. Delete arrow without damage
damage = false
break
end
if mcl_weather.state == "rain" or mcl_weather.state == "lightning" then
local damage = true
local enderpos = self.object:get_pos()
enderpos.y = enderpos.y+2.89
local height = {x=enderpos.x, y=enderpos.y+512,z=enderpos.z}
local ray = minetest.raycast(enderpos, height, true)
-- Check for blocks above enderman.
for pointed_thing in ray do
if pointed_thing.type == "node" then
local nn = minetest.get_node(minetest.get_pointed_thing_position(pointed_thing)).name
local def = minetest.registered_nodes[nn]
if (not def) or def.walkable then
-- There's a node in the way. Delete arrow without damage
damage = false
break
end
end
if damage == true then
self.state = ""
--rain hurts enderman
self.object:punch(self.object, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=self._damage},
}, nil)
--randomly teleport hopefully under something.
self:teleport(nil)
end
end
else return end
if damage == true then
self.state = ""
--rain hurts enderman
self.object:punch(self.object, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=self._damage},
}, nil)
--randomly teleport hopefully under something.
self:teleport(nil)
end
end
-- AGRESSIVELY WARP/CHASE PLAYER BEHAVIOUR HERE.
if self.state == "attack" then
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
--self:teleport(nil)
--self.state = ""
--else
if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
self:teleport(nil)
self.state = ""
else
if self.attack then
local target = self.attack
local pos = target:get_pos()
target = self.attack
pos = target:get_pos()
if pos ~= nil then
if vector.distance(self.object:get_pos(), target:get_pos()) > 10 then
self:teleport(target)
end
end
end
--end
end
end
-- ARROW / DAYTIME PEOPLE AVOIDANCE BEHAVIOUR HERE.
-- Check for arrows and people nearby.
@ -301,9 +286,9 @@ mobs:register_mob("mobs_mc:enderman", {
if obj then
if minetest.is_player(obj) then
-- Warp from players during day.
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
-- self:teleport(nil)
--end
if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
self:teleport(nil)
end
else
local lua = obj:get_luaentity()
if lua then
@ -318,18 +303,17 @@ mobs:register_mob("mobs_mc:enderman", {
local enderpos = self.object:get_pos()
if self.provoked == "broke_contact" then
self.provoked = "false"
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
-- self:teleport(nil)
-- self.state = ""
--else
if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
self:teleport(nil)
self.state = ""
else
if self.attack ~= nil then
self.state = 'attack'
end
--end
end
end
-- Check to see if people are near by enough to look at us.
local objs = minetest.get_objects_inside_radius(enderpos, 64)
local obj
for n = 1, #objs do
obj = objs[n]
if obj then
@ -342,7 +326,7 @@ mobs:register_mob("mobs_mc:enderman", {
-- Cast up to 64 to see if player is looking at enderman.
for n = 1,64,.25 do
local node = minetest.get_node(look_pos)
if node.name ~= "air" then
if node.name ~= "air" then
break
end
if look_pos.x-1<enderpos.x and look_pos.x+1>enderpos.x and look_pos.y-2.89<enderpos.y and look_pos.y-2>enderpos.y and look_pos.z-1<enderpos.z and look_pos.z+1>enderpos.z then
@ -360,7 +344,7 @@ mobs:register_mob("mobs_mc:enderman", {
end
end
end
end
end
-- TAKE AND PLACE STUFF BEHAVIOUR BELOW.
if not mobs_griefing then
return
@ -377,7 +361,7 @@ mobs:register_mob("mobs_mc:enderman", {
self._take_place_timer = 0
self._next_take_place_time = math.random(place_frequency_min, place_frequency_max)
local pos = self.object:get_pos()
local takable_nodes = minetest.find_nodes_in_area_under_air({x=pos.x-2, y=pos.y-1, z=pos.z-2}, {x=pos.x+2, y=pos.y+1, z=pos.z+2}, mobs_mc.enderman_takable)
local takable_nodes = minetest.find_nodes_in_area({x=pos.x-2, y=pos.y-1, z=pos.z-2}, {x=pos.x+2, y=pos.y+1, z=pos.z+2}, mobs_mc.enderman_takable)
if #takable_nodes >= 1 then
local r = pr:next(1, #takable_nodes)
local take_pos = takable_nodes[r]
@ -477,9 +461,7 @@ mobs:register_mob("mobs_mc:enderman", {
end
end
if telepos then
telesound(self.object:get_pos(), false)
self.object:set_pos(telepos)
telesound(telepos, true)
end
end
end
@ -507,10 +489,7 @@ mobs:register_mob("mobs_mc:enderman", {
end
end
if node_ok then
telesound(self.object:get_pos(), false)
local telepos = {x=nodepos.x, y=nodepos.y+1, z=nodepos.z}
self.object:set_pos(telepos)
telesound(telepos, true)
self.object:set_pos({x=nodepos.x, y=nodepos.y+1, z=nodepos.z})
break
end
end
@ -531,16 +510,15 @@ mobs:register_mob("mobs_mc:enderman", {
do_punch = function(self, hitter, tflp, tool_caps, dir)
-- damage from rain caused by itself so we don't want it to attack itself.
if hitter ~= self.object and hitter ~= nil then
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
-- self:teleport(nil)
--else
if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
self:teleport(nil)
else
self:teleport(hitter)
self.attack=hitter
self.state="attack"
--end
end
end
end,
armor = { fleshy = 100, water_vulnerable = 100 },
water_damage = 8,
view_range = 64,
fear_height = 4,

View File

@ -10,9 +10,7 @@ mobs:register_mob("mobs_mc:endermite", {
passive = false,
hp_min = 8,
hp_max = 8,
xp_min = 3,
xp_max = 3,
armor = {fleshy = 100, arthropod = 100},
armor = 100,
group_attack = true,
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.29, 0.2},
visual = "mesh",
@ -23,10 +21,9 @@ mobs:register_mob("mobs_mc:endermite", {
visual_size = {x=3, y=3},
makes_footstep_sound = false,
sounds = {
random = "mobs_mc_endermite_random",
damage = "mobs_mc_endermite_hurt",
death = "mobs_mc_endermite_death",
random = "mobs_rat",
distance = 16,
-- TODO: more sounds
},
walk_velocity = 1,
run_velocity = 2,

View File

@ -17,8 +17,6 @@ mobs:register_mob("mobs_mc:ghast", {
group_attack = true,
hp_min = 10,
hp_max = 10,
xp_min = 5,
xp_max = 5,
collisionbox = {-2, 5, -2, 2, 9, 2},
visual = "mesh",
mesh = "mobs_mc_ghast.b3d",
@ -38,8 +36,8 @@ mobs:register_mob("mobs_mc:ghast", {
walk_velocity = 1.6,
run_velocity = 3.2,
drops = {
{name = mobs_mc.items.gunpowder, chance = 1, min = 0, max = 2, looting = "common"},
{name = mobs_mc.items.ghast_tear, chance = 10/6, min = 0, max = 1, looting = "common", looting_ignore_chance = true},
{name = mobs_mc.items.gunpowder, chance = 1, min = 0, max = 2,},
{name = mobs_mc.items.ghast_tear, chance = 3,min = 0,max = 1,},
},
animation = {
stand_speed = 50, walk_speed = 50, run_speed = 50,
@ -60,9 +58,6 @@ mobs:register_mob("mobs_mc:ghast", {
jump_height = 4,
floats=1,
fly = true,
makes_footstep_sound = false,
instant_death = true,
fire_resistant = true,
})
@ -76,9 +71,6 @@ mobs:register_arrow("mobs_mc:fireball", {
velocity = 15,
hit_player = function(self, player)
if rawget(_G, "armor") and armor.last_damage_types then
armor.last_damage_types[player:get_player_name()] = "fireball"
end
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 6},

View File

@ -1,3 +1,5 @@
-- v1.4
--###################
--################### GUARDIAN
--###################
@ -9,8 +11,6 @@ mobs:register_mob("mobs_mc:guardian", {
spawn_class = "hostile",
hp_min = 30,
hp_max = 30,
xp_min = 10,
xp_max = 10,
breath_max = -1,
passive = false,
attack_type = "dogfight",
@ -28,11 +28,8 @@ mobs:register_mob("mobs_mc:guardian", {
},
visual_size = {x=3, y=3},
sounds = {
random = "mobs_mc_guardian_random",
war_cry = "mobs_mc_guardian_random",
damage = {name="mobs_mc_guardian_hurt", gain=0.3},
death = "mobs_mc_guardian_death",
flop = "mobs_mc_squid_flop",
damage = "mobs_mc_squid_hurt",
-- TODO: more and better sounds
distance = 16,
},
animation = {
@ -46,8 +43,7 @@ mobs:register_mob("mobs_mc:guardian", {
{name = mobs_mc.items.prismarine_shard,
chance = 1,
min = 0,
max = 32,
looting = "common",},
max = 32,},
-- TODO: Reduce of drops when ocean monument is ready.
-- The following drops are approximations
@ -55,42 +51,31 @@ mobs:register_mob("mobs_mc:guardian", {
{name = mobs_mc.items.fish_raw,
chance = 4,
min = 1,
max = 1,
looting = "common",},
max = 1,},
{name = mobs_mc.items.prismarine_crystals,
chance = 4,
min = 1,
max = 2,
looting = "common",},
max = 2,},
-- Rare drop: fish
{name = mobs_mc.items.fish_raw,
chance = 160, -- 2.5% / 4
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.0025,},
max = 1,},
{name = mobs_mc.items.salmon_raw,
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.0025,},
max = 1,},
{name = mobs_mc.items.clownfish_raw,
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.0025,},
max = 1,},
{name = mobs_mc.items.pufferfish_raw,
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.0025,},
max = 1,},
},
fly = true,
makes_footstep_sound = false,
fly_in = { mobs_mc.items.water_source, mobs_mc.items.river_water_source },
jump = false,
view_range = 16,

View File

@ -11,8 +11,6 @@ mobs:register_mob("mobs_mc:guardian_elder", {
spawn_class = "hostile",
hp_min = 80,
hp_max = 80,
xp_min = 10,
xp_max = 10,
breath_max = -1,
passive = false,
attack_type = "dogfight",
@ -30,12 +28,8 @@ mobs:register_mob("mobs_mc:guardian_elder", {
},
visual_size = {x=7, y=7},
sounds = {
random = "mobs_mc_guardian_random",
war_cry = "mobs_mc_guardian_random",
damage = {name="mobs_mc_guardian_hurt", gain=0.3},
death = "mobs_mc_guardian_death",
flop = "mobs_mc_squid_flop",
base_pitch = 0.6,
damage = "mobs_mc_squid_hurt",
-- TODO: more and better sounds
distance = 16,
},
animation = {
@ -51,8 +45,7 @@ mobs:register_mob("mobs_mc:guardian_elder", {
{name = mobs_mc.items.prismarine_shard,
chance = 1,
min = 1,
max = 64,
looting = "common",},
max = 64,},
-- TODO: Only drop if killed by player
{name = mobs_mc.items.wet_sponge,
@ -65,42 +58,31 @@ mobs:register_mob("mobs_mc:guardian_elder", {
{name = mobs_mc.items.fish_raw,
chance = 4,
min = 1,
max = 1,
looting = "common",},
max = 1,},
{name = mobs_mc.items.prismarine_crystals,
chance = 1,
min = 1,
max = 10,
looting = "common",},
max = 10,},
-- Rare drop: fish
{name = mobs_mc.items.fish_raw,
chance = 160, -- 2.5% / 4
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.01 / 4,},
max = 1,},
{name = mobs_mc.items.salmon_raw,
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.01 / 4,},
max = 1,},
{name = mobs_mc.items.clownfish_raw,
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.01 / 4,},
max = 1,},
{name = mobs_mc.items.pufferfish_raw,
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.01 / 4,},
max = 1,},
},
fly = true,
makes_footstep_sound = false,
fly_in = { mobs_mc.items.water_source, mobs_mc.items.river_water_source },
jump = false,
view_range = 16,

View File

@ -96,7 +96,7 @@ local horse = {
walk_speed = 25,
walk_start = 0,
walk_end = 40,
run_speed = 60,
run_speed = 50,
run_start = 0,
run_end = 40,
},
@ -106,7 +106,6 @@ local horse = {
-- TODO: Separate damage sound
damage = "mobs_mc_horse_death",
death = "mobs_mc_horse_death",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
},
fear_height = 4,
@ -117,8 +116,6 @@ local horse = {
passive = true,
hp_min = 15,
hp_max = 30,
xp_min = 1,
xp_max = 3,
floats = 1,
makes_footstep_sound = true,
jump = true,
@ -127,8 +124,7 @@ local horse = {
{name = mobs_mc.items.leather,
chance = 1,
min = 0,
max = 2,
looting = "common",},
max = 2,},
},
do_custom = function(self, dtime)
@ -354,7 +350,6 @@ mobs:register_mob("mobs_mc:horse", horse)
-- Skeleton horse
local skeleton_horse = table.copy(horse)
skeleton_horse.breath_max = -1
skeleton_horse.armor = {undead = 100, fleshy = 100}
skeleton_horse.textures = {{"blank.png", "mobs_mc_horse_skeleton.png", "blank.png"}}
skeleton_horse.drops = {
{name = mobs_mc.items.bone,
@ -366,8 +361,6 @@ skeleton_horse.sounds = {
random = "mobs_mc_skeleton_random",
death = "mobs_mc_skeleton_death",
damage = "mobs_mc_skeleton_hurt",
eat = "mobs_mc_animal_eat_generic",
base_pitch = 0.95,
distance = 16,
}
skeleton_horse.harmed_by_heal = true
@ -376,7 +369,6 @@ mobs:register_mob("mobs_mc:skeleton_horse", skeleton_horse)
-- Zombie horse
local zombie_horse = table.copy(horse)
zombie_horse.breath_max = -1
zombie_horse.armor = {undead = 100, fleshy = 100}
zombie_horse.textures = {{"blank.png", "mobs_mc_horse_zombie.png", "blank.png"}}
zombie_horse.drops = {
{name = mobs_mc.items.rotten_flesh,
@ -385,12 +377,9 @@ zombie_horse.drops = {
max = 2,},
}
zombie_horse.sounds = {
random = "mobs_mc_horse_random",
-- TODO: Separate damage sound
damage = "mobs_mc_horse_death",
death = "mobs_mc_horse_death",
eat = "mobs_mc_animal_eat_generic",
base_pitch = 0.5,
random = "mobs_mc_zombie_growl",
death = "mobs_mc_zombie_death",
damage = "mobs_mc_zombie_hurt",
distance = 16,
}
zombie_horse.harmed_by_heal = true
@ -405,13 +394,8 @@ donkey.animation = {
stand_start = 0, stand_end = 0,
walk_start = 0, walk_end = 40,
}
donkey.sounds = {
random = "mobs_mc_donkey_random",
damage = "mobs_mc_donkey_hurt",
death = "mobs_mc_donkey_death",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
}
-- TODO: donkey sounds
donkey.sounds = nil
donkey.visual_size = { x=horse.visual_size.x*d, y=horse.visual_size.y*d }
donkey.collisionbox = {
horse.collisionbox[1] * d,
@ -431,8 +415,7 @@ local m = 0.94
local mule = table.copy(donkey)
mule.textures = {{"blank.png", "mobs_mc_mule.png", "blank.png"}}
mule.visual_size = { x=horse.visual_size.x*m, y=horse.visual_size.y*m }
mule.sounds = table.copy(donkey.sounds)
mule.sounds.base_pitch = 1.15
mule.sounds = horse.sounds
mule.collisionbox = {
horse.collisionbox[1] * m,
horse.collisionbox[2] * m,

View File

@ -29,8 +29,6 @@ mobs:register_mob("mobs_mc:llama", {
spawn_class = "passive",
hp_min = 15,
hp_max = 30,
xp_min = 1,
xp_max = 3,
passive = false,
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.86, 0.45},
visual = "mesh",
@ -48,27 +46,21 @@ mobs:register_mob("mobs_mc:llama", {
runaway = true,
walk_velocity = 1,
run_velocity = 4.4,
follow_velocity = 4.4,
floats = 1,
drops = {
{name = mobs_mc.items.leather,
chance = 1,
min = 0,
max = 2,
looting = "common",},
max = 2,},
},
fear_height = 4,
sounds = {
random = "mobs_mc_llama",
eat = "mobs_mc_animal_eat_generic",
-- TODO: Death and damage sounds
distance = 16,
},
animation = {
speed_normal = 24,
run_speed = 60,
run_start = 0,
run_end = 40,
stand_start = 0,
stand_end = 0,
walk_start = 0,

View File

@ -1,75 +0,0 @@
# textdomain: mobs_mc
Totem of Undying=Тотем бессмертия
A totem of undying is a rare artifact which may safe you from certain death.=Тотем бессмертия это редкий артефакт, способный спасти вас от смерти.
The totem only works while you hold it in your hand. If you receive fatal damage, you are saved from death and you get a second chance with 1 HP. The totem is destroyed in the process, however.=Тотем работает только когда вы держите его в руке. Если вы получаете смертельный урон, вы спасаетесь от смерти и получаете второй шанс с 1 HP. Однако тотем при этом уничтожается.
Agent=Агент
Bat=Летучая мышь
Blaze=Ифрит
Chicken=Курица
Cow=Корова
Mooshroom=Гриб
Creeper=Крипер
Ender Dragon=Дракон Предела
Enderman=Эндермен
Endermite=Эндермит
Ghast=Гаст
Elder Guardian=Древний страж
Guardian=Страж
Horse=Лошадь
Skeleton Horse=Скелет лошади
Zombie Horse=Зомби-лошадь
Donkey=Ослик
Mule=Мул
Iron Golem=Железный голем
Llama=Лама
Ocelot=Оцелот
Parrot=Попугай
Pig=Свинья
Polar Bear=Полярный медведь
Rabbit=Кролик
Killer Bunny=Кролик-убийца
Sheep=Овца
Shulker=Шалкер
Silverfish=Чешуйница
Skeleton=Скелет
Stray=Странник
Wither Skeleton=Скелет-иссушитель
Magma Cube=Лавовый куб
Slime=Слизняк
Snow Golem=Снежный голем
Spider=Паук
Cave Spider=Пещерный паук
Squid=Кальмар
Vex=Досаждатель
Evoker=Маг
Illusioner=Иллюзор
Villager=Житель
Vindicator=Поборник
Zombie Villager=Зомби-житель
Witch=Ведьма
Wither=Иссушитель
Wolf=Волк
Husk=Кадавр
Zombie=Зомби
Zombie Pigman=Зомби-свиночеловек
Iron Horse Armor=Железные доспехи лошади
Iron horse armor can be worn by horses to increase their protection from harm a bit.=Железные доспехи лошади, надетые на лошадь, немного защищают её от вреда.
Golden Horse Armor=Золотые доспехи лошади
Golden horse armor can be worn by horses to increase their protection from harm.=Золотые доспехи лошади, надетые на лошадь, защищают её от вреда.
Diamond Horse Armor=Алмазные доспехи лошади
Diamond horse armor can be worn by horses to greatly increase their protection from harm.=Алмазные доспехи лошади, надетые на лошадь, отлично защищают её от вреда.
Place it on a horse to put on the horse armor. Donkeys and mules can't wear horse armor.=Поместите это на лошадь, чтобы одеть лошадь в доспехи. Ослики и мулы не могут носить лошадиные доспехи.
Farmer=Фермер
Fisherman=Рыбак
Fletcher=Лучник
Shepherd=Пастух
Librarian=Библиотекарь
Cartographer=Картограф
Armorer=Бронник
Leatherworker=Кожевник
Butcher=Мясник
Weapon Smith=Оружейник
Tool Smith=Инструментальщик
Cleric=Церковник
Nitwit=Нищий
Protects you from death while wielding it=Защищает вас от смерти, пока вы владеете им

View File

@ -32,8 +32,6 @@ local ocelot = {
can_despawn = true,
hp_min = 10,
hp_max = 10,
xp_min = 1,
xp_max = 3,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 0.69, 0.3},
visual = "mesh",
mesh = "mobs_mc_cat.b3d",
@ -43,7 +41,6 @@ local ocelot = {
walk_chance = default_walk_chance,
walk_velocity = 1,
run_velocity = 3,
follow_velocity = 1,
floats = 1,
runaway = true,
fall_damage = 0,
@ -51,12 +48,11 @@ local ocelot = {
sounds = {
damage = "mobs_mc_ocelot_hurt",
death = "mobs_mc_ocelot_hurt",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
},
animation = {
speed_normal = 25,
run_speed = 50,
speed_run = 50,
stand_start = 0,
stand_end = 0,
walk_start = 0,
@ -109,14 +105,12 @@ cat.order = "roam" -- "sit" or "roam"
cat.owner_loyal = true
cat.tamed = true
cat.runaway = false
cat.follow_velocity = 2.4
-- Automatically teleport cat to owner
cat.do_custom = mobs_mc.make_owner_teleport_function(12)
cat.sounds = {
random = "mobs_mc_cat_idle",
damage = "mobs_mc_cat_hiss",
death = "mobs_mc_ocelot_hurt",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
}
cat.on_rightclick = function(self, clicker)

View File

@ -17,53 +17,43 @@ mobs:register_mob("mobs_mc:parrot", {
pathfinding = 1,
hp_min = 6,
hp_max = 6,
xp_min = 1,
xp_max = 3,
collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.89, 0.25},
visual = "mesh",
mesh = "mobs_mc_parrot.b3d",
textures = {{"mobs_mc_parrot_blue.png"},{"mobs_mc_parrot_green.png"},{"mobs_mc_parrot_grey.png"},{"mobs_mc_parrot_red_blue.png"},{"mobs_mc_parrot_yellow_blue.png"}},
visual_size = {x=3, y=3},
makes_footstep_sound = true,
walk_velocity = 3,
run_velocity = 5,
sounds = {
random = "mobs_mc_parrot_random",
damage = {name="mobs_mc_parrot_hurt", gain=0.3},
death = {name="mobs_mc_parrot_death", gain=0.6},
eat = "mobs_mc_animal_eat_generic",
distance = 16,
},
-- TODO: sounds
drops = {
{name = mobs_mc.items.feather,
chance = 1,
min = 1,
max = 2,
looting = "common",},
max = 2,},
},
animation = {
stand_speed = 50,
walk_speed = 50,
fly_speed = 50,
stand_start = 30,
stand_end = 45,
fly_start = 30,
fly_end = 45,
walk_start = 30,
walk_end = 45,
-- TODO: actual walk animation
--walk_start = 0,
--walk_end = 20,
-- TODO: more unused animations between 45 and 130
stand_start = 0,
stand_end = 0,
walk_start = 0,
walk_end = 130,
--run_start = 0,
--run_end = 20,
--fly_start = 30,
--fly_end = 45,
},
walk_chance = 100,
fall_damage = 0,
fall_speed = -2.25,
attack_type = "dogfight",
jump = true,
jump_height = 4,
floats = 1,
physical = true,
fly = true,
makes_footstep_sound = false,
fear_height = 0,
fear_height = 4,
view_range = 16,
follow = mobs_mc.follow.parrot,
on_rightclick = function(self, clicker)
@ -71,7 +61,6 @@ mobs:register_mob("mobs_mc:parrot", {
local item = clicker:get_wielded_item()
-- Kill parrot if fed with cookie
if item:get_name() == mobs_mc.items.cookie then
minetest.sound_play("mobs_mc_animal_eat_generic", {object = self.object, max_hear_distance=16}, true)
self.health = 0
-- Doomed to die
self._doomed = true
@ -90,8 +79,10 @@ mobs:register_mob("mobs_mc:parrot", {
})
-- Parrots spawn rarely in jungles. TODO: Also check for jungle *biome*
mobs:spawn_specific("mobs_mc:parrot", {"mcl_core:jungletree", "mcl_core:jungleleaves"}, {"air"}, 0, minetest.LIGHT_MAX+1, 7, 30000, 1, mobs_mc.spawn_height.water+7, mobs_mc.spawn_height.overworld_max)
-- Spawn disabled because parrots are not very smart.
-- TODO: Re-enable when parrots are finished
--mobs:spawn_specific("mobs_mc:parrot", mobs_mc.spawn.jungle, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 30000, 1, mobs_mc.spawn_height.water+1, mobs_mc.spawn_height.overworld_max)
-- spawn eggs
mobs:register_egg("mobs_mc:parrot", S("Parrot"), "mobs_mc_spawn_icon_parrot.png", 0)
mobs:register_egg("mobs_mc:parrot", S("Parrot"), "mobs_mc_spawn_icon_parrot.png", 0, true)

View File

@ -8,8 +8,6 @@ mobs:register_mob("mobs_mc:pig", {
runaway = true,
hp_min = 10,
hp_max = 10,
xp_min = 1,
xp_max = 3,
collisionbox = {-0.45, -0.01, -0.45, 0.45, 0.865, 0.45},
visual = "mesh",
mesh = "mobs_mc_pig.b3d",
@ -22,26 +20,23 @@ mobs:register_mob("mobs_mc:pig", {
makes_footstep_sound = true,
walk_velocity = 1,
run_velocity = 3,
follow_velocity = 3.4,
drops = {
{name = mobs_mc.items.porkchop_raw,
chance = 1,
min = 1,
max = 3,
looting = "common",},
max = 3,},
},
fear_height = 4,
sounds = {
random = "mobs_pig",
death = "mobs_pig_angry",
damage = "mobs_pig",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
},
animation = {
stand_speed = 40,
walk_speed = 40,
run_speed = 90,
run_speed = 50,
stand_start = 0,
stand_end = 0,
walk_start = 0,
@ -50,7 +45,7 @@ mobs:register_mob("mobs_mc:pig", {
run_end = 40,
},
follow = mobs_mc.follow.pig,
view_range = 8,
view_range = 5,
do_custom = function(self, dtime)
-- set needed values if not already present
@ -83,6 +78,7 @@ mobs:register_mob("mobs_mc:pig", {
if self.driver then
mobs.detach(self.driver, {x = 1, y = 0, z = 1})
end
end,
on_rightclick = function(self, clicker)

View File

@ -14,8 +14,6 @@ mobs:register_mob("mobs_mc:polar_bear", {
passive = false,
hp_min = 30,
hp_max = 30,
xp_min = 1,
xp_max = 3,
breath_max = -1,
collisionbox = {-0.7, -0.01, -0.7, 0.7, 1.39, 0.7},
visual = "mesh",
@ -36,26 +34,17 @@ mobs:register_mob("mobs_mc:polar_bear", {
{name = mobs_mc.items.fish_raw,
chance = 2,
min = 0,
max = 2,
looting = "common",},
max = 2,},
-- 1/4 to drop raw salmon
{name = mobs_mc.items.salmon_raw,
chance = 4,
min = 0,
max = 2,
looting = "common",},
max = 2,},
},
floats = 1,
fear_height = 4,
sounds = {
random = "mobs_mc_bear_random",
attack = "mobs_mc_bear_attack",
damage = "mobs_mc_bear_hurt",
death = "mobs_mc_bear_death",
war_cry = "mobs_mc_bear_growl",
distance = 16,
},
-- TODO: sounds
animation = {
speed_normal = 25, speed_run = 50,
stand_start = 0, stand_end = 0,

View File

@ -10,8 +10,6 @@ local rabbit = {
hp_min = 3,
hp_max = 3,
xp_min = 1,
xp_max = 3,
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.49, 0.2},
visual = "mesh",
@ -25,25 +23,19 @@ local rabbit = {
{"mobs_mc_rabbit_black.png"},
},
visual_size = {x=1.5, y=1.5},
sounds = {
random = "mobs_mc_rabbit_random",
damage = "mobs_mc_rabbit_hurt",
death = "mobs_mc_rabbit_death",
attack = "mobs_mc_rabbit_attack",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
},
-- TODO: sounds: random, damage, death
makes_footstep_sound = false,
walk_velocity = 1,
run_velocity = 3.7,
follow_velocity = 1.1,
floats = 1,
runaway = true,
jump = true,
drops = {
{name = mobs_mc.items.rabbit_raw, chance = 1, min = 0, max = 1, looting = "common",},
{name = mobs_mc.items.rabbit_hide, chance = 1, min = 0, max = 1, looting = "common",},
{name = mobs_mc.items.rabbit_foot, chance = 10, min = 0, max = 1, looting = "rare", looting_factor = 0.03,},
{name = mobs_mc.items.rabbit_raw, chance = 1, min = 0, max = 1},
{name = mobs_mc.items.rabbit_hide, chance = 1, min = 0, max = 1},
{name = mobs_mc.items.rabbit_foot, chance = 10, min = 0, max = 1},
-- TODO: Drop rabbit's foot when it's useful
--{name = mobs_mc.items.rabbit_foot, chance = 10, min = 1, max = 1},
},
fear_height = 4,
animation = {

View File

@ -47,8 +47,7 @@ mobs:register_mob("mobs_mc:sheep", {
spawn_class = "passive",
hp_min = 8,
hp_max = 8,
xp_min = 1,
xp_max = 3,
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.29, 0.45},
visual = "mesh",
@ -63,25 +62,22 @@ mobs:register_mob("mobs_mc:sheep", {
{name = mobs_mc.items.mutton_raw,
chance = 1,
min = 1,
max = 2,
looting = "common",},
max = 2,},
{name = colors["unicolor_white"][1],
chance = 1,
min = 1,
max = 1,
looting = "common",},
max = 1,},
},
fear_height = 4,
sounds = {
random = "mobs_sheep",
death = "mobs_sheep",
damage = "mobs_sheep",
sounds = "mobs_mc_animal_eat_generic",
distance = 16,
},
animation = {
speed_normal = 25, run_speed = 65,
stand_start = 40, stand_end = 80,
speed_normal = 25, speed_run = 50,
stand_start = 40, stand_end = 80,
walk_start = 0, walk_end = 40,
run_start = 0, run_end = 40,
},
@ -160,7 +156,7 @@ mobs:register_mob("mobs_mc:sheep", {
if item:get_name() == mobs_mc.items.shears and not self.gotten and not self.child then
self.gotten = true
local pos = self.object:get_pos()
minetest.sound_play("mcl_tools_shears_cut", {pos = pos}, true)
minetest.sound_play("shears", {pos = pos}, true)
pos.y = pos.y + 0.5
if not self.color then
self.color = "unicolor_white"

View File

@ -21,8 +21,6 @@ mobs:register_mob("mobs_mc:shulker", {
passive = false,
hp_min = 30,
hp_max = 30,
xp_min = 5,
xp_max = 5,
armor = 150,
collisionbox = {-0.5, -0.01, -0.5, 0.5, 0.99, 0.5},
visual = "mesh",
@ -35,11 +33,9 @@ mobs:register_mob("mobs_mc:shulker", {
jump = false,
drops = {
{name = mobs_mc.items.shulker_shell,
chance = 2,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.0625},
chance = 1,
min = 0,
max = 1,},
},
animation = {
stand_speed = 25, walk_speed = 25, run_speed = 50, punch_speed = 25,
@ -79,6 +75,6 @@ mobs:register_arrow("mobs_mc:shulkerbullet", {
})
mobs:register_egg("mobs_mc:shulker", S("Shulker"), "mobs_mc_spawn_icon_shulker.png", 0)
mobs:register_egg("mobs_mc:shulker", S("Schulker"), "mobs_mc_spawn_icon_shulker.png", 0)
mobs:spawn_specific("mobs_mc:shulker", mobs_mc.spawn.end_city, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 5000, 2, mobs_mc.spawn_height.end_min, mobs_mc.spawn_height.end_max)

View File

@ -12,9 +12,6 @@ mobs:register_mob("mobs_mc:silverfish", {
reach = 1,
hp_min = 8,
hp_max = 8,
xp_min = 5,
xp_max = 5,
armor = {fleshy = 100, arthropod = 100},
collisionbox = {-0.4, -0.01, -0.4, 0.4, 0.44, 0.4},
visual = "mesh",
mesh = "mobs_mc_silverfish.b3d",

View File

@ -17,10 +17,7 @@ local skeleton = {
spawn_class = "hostile",
hp_min = 20,
hp_max = 20,
xp_min = 6,
xp_max = 6,
breath_max = -1,
armor = {undead = 100, fleshy = 100},
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.98, 0.3},
pathfinding = 1,
group_attack = true,
@ -46,18 +43,15 @@ local skeleton = {
{name = mobs_mc.items.arrow,
chance = 1,
min = 0,
max = 2,
looting = "common",},
max = 2,},
{name = mobs_mc.items.bow,
chance = 100 / 8.5,
chance = 11,
min = 1,
max = 1,
looting = "rare",},
max = 1,},
{name = mobs_mc.items.bone,
chance = 1,
min = 0,
max = 2,
looting = "common",},
max = 2,},
-- Head
-- TODO: Only drop if killed by charged creeper
@ -81,7 +75,7 @@ local skeleton = {
die_speed = 15,
die_loop = false,
},
ignited_by_sunlight = true,
sunlight_damage = 1,
view_range = 16,
fear_height = 4,
attack_type = "dogshoot",
@ -119,21 +113,12 @@ stray.textures = {
-- TODO: different sound (w/ echo)
-- TODO: stray's arrow inflicts slowness status
table.insert(stray.drops, {
name = "mcl_potions:slowness_arrow",
-- Chance to drop additional arrow.
-- TODO: Should be tipped arrow of slowness
name = mobs_mc.items.arrow,
chance = 2,
min = 1,
max = 1,
looting = "rare",
looting_chance_function = function(lvl)
local chance = 0.5
for i = 1, lvl do
if chance > 1 then
return 1
end
chance = chance + (1 - chance) / 2
end
return chance
end,
})
mobs:register_mob("mobs_mc:stray", stray)

View File

@ -14,10 +14,7 @@ mobs:register_mob("mobs_mc:witherskeleton", {
spawn_class = "hostile",
hp_min = 20,
hp_max = 20,
xp_min = 6,
xp_max = 6,
breath_max = -1,
armor = {undead = 100, fleshy = 100},
pathfinding = 1,
group_attack = true,
collisionbox = {-0.35, -0.01, -0.35, 0.35, 2.39, 0.35},
@ -45,20 +42,17 @@ mobs:register_mob("mobs_mc:witherskeleton", {
{name = mobs_mc.items.coal,
chance = 1,
min = 0,
max = 1,
looting = "common",},
max = 1,},
{name = mobs_mc.items.bone,
chance = 1,
min = 0,
max = 2,
looting = "common",},
max = 2,},
-- Head
{name = mobs_mc.items.head_wither_skeleton,
chance = 40, -- 2.5% chance
min = 1,
max = 1,
looting = "rare",},
max = 1,},
},
animation = {
stand_start = 0,
@ -90,7 +84,6 @@ mobs:register_mob("mobs_mc:witherskeleton", {
dogshoot_count_max =0.5,
fear_height = 4,
harmed_by_heal = true,
fire_resistant = true,
})
--spawn

View File

@ -51,7 +51,6 @@ local spawn_children_on_die = function(child_mob, children_count, spawn_distance
end
end, children, self.attack)
end
return true
end
end
@ -63,8 +62,6 @@ local slime_big = {
group_attack = { "mobs_mc:slime_big", "mobs_mc:slime_small", "mobs_mc:slime_tiny" },
hp_min = 16,
hp_max = 16,
xp_min = 4,
xp_max = 4,
collisionbox = {-1.02, -0.01, -1.02, 1.02, 2.03, 1.02},
visual_size = {x=12.5, y=12.5},
textures = {{"mobs_mc_slime.png"}},
@ -108,9 +105,7 @@ local slime_big = {
jump_height = 5.2,
fear_height = 0,
spawn_small_alternative = "mobs_mc:slime_small",
on_die = spawn_children_on_die("mobs_mc:slime_small", 4, 1.0, 1.5),
fire_resistant = true,
use_texture_alpha = true,
on_die = spawn_children_on_die("mobs_mc:slime_small", 4, 1.0, 1.5)
}
mobs:register_mob("mobs_mc:slime_big", slime_big)
@ -118,8 +113,6 @@ local slime_small = table.copy(slime_big)
slime_small.sounds.base_pitch = 1.15
slime_small.hp_min = 4
slime_small.hp_max = 4
slime_small.xp_min = 2
slime_small.xp_max = 2
slime_small.collisionbox = {-0.51, -0.01, -0.51, 0.51, 1.00, 0.51}
slime_small.visual_size = {x=6.25, y=6.25}
slime_small.damage = 3
@ -135,8 +128,6 @@ local slime_tiny = table.copy(slime_big)
slime_tiny.sounds.base_pitch = 1.3
slime_tiny.hp_min = 1
slime_tiny.hp_max = 1
slime_tiny.xp_min = 1
slime_tiny.xp_max = 1
slime_tiny.collisionbox = {-0.2505, -0.01, -0.2505, 0.2505, 0.50, 0.2505}
slime_tiny.visual_size = {x=3.125, y=3.125}
slime_tiny.damage = 0
@ -169,8 +160,6 @@ local magma_cube_big = {
spawn_class = "hostile",
hp_min = 16,
hp_max = 16,
xp_min = 4,
xp_max = 4,
collisionbox = {-1.02, -0.01, -1.02, 1.02, 2.03, 1.02},
visual_size = {x=12.5, y=12.5},
textures = {{ "mobs_mc_magmacube.png" }},
@ -187,7 +176,7 @@ local magma_cube_big = {
run_velocity = 4,
damage = 6,
reach = 3,
armor = 53,
armor = 40,
drops = {
{name = mobs_mc.items.magma_cream,
chance = 4,
@ -222,8 +211,7 @@ local magma_cube_big = {
walk_chance = 0,
fear_height = 0,
spawn_small_alternative = "mobs_mc:magma_cube_small",
on_die = spawn_children_on_die("mobs_mc:magma_cube_small", 3, 0.8, 1.5),
fire_resistant = true,
on_die = spawn_children_on_die("mobs_mc:magma_cube_small", 3, 0.8, 1.5)
}
mobs:register_mob("mobs_mc:magma_cube_big", magma_cube_big)
@ -232,8 +220,6 @@ magma_cube_small.sounds.jump = "mobs_mc_magma_cube_small"
magma_cube_small.sounds.death = "mobs_mc_magma_cube_small"
magma_cube_small.hp_min = 4
magma_cube_small.hp_max = 4
magma_cube_small.xp_min = 2
magma_cube_small.xp_max = 2
magma_cube_small.collisionbox = {-0.51, -0.01, -0.51, 0.51, 1.00, 0.51}
magma_cube_small.visual_size = {x=6.25, y=6.25}
magma_cube_small.damage = 3
@ -243,7 +229,7 @@ magma_cube_small.run_velocity = 2.6
magma_cube_small.jump_height = 6
magma_cube_small.damage = 4
magma_cube_small.reach = 2.75
magma_cube_small.armor = 66
magma_cube_small.armor = 70
magma_cube_small.spawn_small_alternative = "mobs_mc:magma_cube_tiny"
magma_cube_small.on_die = spawn_children_on_die("mobs_mc:magma_cube_tiny", 4, 0.6, 1.0)
mobs:register_mob("mobs_mc:magma_cube_small", magma_cube_small)
@ -254,8 +240,6 @@ magma_cube_tiny.sounds.death = "mobs_mc_magma_cube_small"
magma_cube_tiny.sounds.base_pitch = 1.25
magma_cube_tiny.hp_min = 1
magma_cube_tiny.hp_max = 1
magma_cube_tiny.xp_min = 1
magma_cube_tiny.xp_max = 1
magma_cube_tiny.collisionbox = {-0.2505, -0.01, -0.2505, 0.2505, 0.50, 0.2505}
magma_cube_tiny.visual_size = {x=3.125, y=3.125}
magma_cube_tiny.walk_velocity = 1.02
@ -263,7 +247,7 @@ magma_cube_tiny.run_velocity = 1.02
magma_cube_tiny.jump_height = 4
magma_cube_tiny.damage = 3
magma_cube_tiny.reach = 2.5
magma_cube_tiny.armor = 50
magma_cube_tiny.armor = 85
magma_cube_tiny.drops = {}
magma_cube_tiny.spawn_small_alternative = nil
magma_cube_tiny.on_die = nil

View File

@ -31,16 +31,11 @@ mobs:register_mob("mobs_mc:snowman", {
fall_damage = 0,
water_damage = 4,
rain_damage = 4,
armor = { fleshy = 100, water_vulnerable = 100 },
attacks_monsters = true,
collisionbox = {-0.35, -0.01, -0.35, 0.35, 1.89, 0.35},
visual = "mesh",
mesh = "mobs_mc_snowman.b3d",
sounds = {
damage = { name = "mobs_mc_snowman_hurt", gain = 0.2 },
death = { name = "mobs_mc_snowman_death", gain = 0.25 },
distance = 16,
},
-- TODO: sounds: damage, death
textures = {
"mobs_mc_snowman.png", --snowman texture
"farming_pumpkin_side.png", --top
@ -78,7 +73,7 @@ mobs:register_mob("mobs_mc:snowman", {
run_end = 20,
die_start = 40,
die_end = 50,
die_speed = 15,
die_speed = 25,
die_loop = false,
},
do_custom = function(self, dtime)
@ -121,7 +116,7 @@ mobs:register_mob("mobs_mc:snowman", {
})
local pos = self.object:get_pos()
minetest.sound_play("mcl_tools_shears_cut", {pos = pos}, true)
minetest.sound_play("shears", {pos = pos}, true)
-- Wear out
if not minetest.is_creative_enabled(clicker:get_player_name()) then
@ -132,26 +127,6 @@ mobs:register_mob("mobs_mc:snowman", {
end,
})
local summon_particles = function(obj)
local lua = obj:get_luaentity()
local min = {x=lua.collisionbox[1], y=lua.collisionbox[2], z=lua.collisionbox[3]}
local max = {x=lua.collisionbox[4], y=lua.collisionbox[5], z=lua.collisionbox[6]}
local pos = obj:get_pos()
minetest.add_particlespawner({
amount = 60,
time = 0.1,
minpos = vector.add(pos, min),
maxpos = vector.add(pos, max),
minvel = {x = -0.1, y = -0.1, z = -0.1},
maxvel = {x = 0.1, y = 0.1, z = 0.1},
minexptime = 1.0,
maxexptime = 2.0,
minsize = 2.0,
maxsize = 3.0,
texture = "mcl_particles_smoke.png",
})
end
-- This is to be called when a pumpkin or jack'o lantern has been placed. Recommended: In the on_construct function
-- of the node.
-- This summons a snow golen when pos is next to a row of two snow blocks.
@ -181,10 +156,7 @@ mobs_mc.tools.check_snow_golem_summon = function(pos)
core.check_for_falling(pos)
core.check_for_falling(b1)
core.check_for_falling(b2)
local obj = minetest.add_entity(place, "mobs_mc:snowman")
if obj then
summon_particles(obj)
end
minetest.add_entity(place, "mobs_mc:snowman")
break
end
end

Binary file not shown.

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