parent
d71a37a023
commit
290ffb9c59
|
@ -95,11 +95,11 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
|||
* [horse][] ([MIT][lic.horse]) -- version: [3240dde Git][ver.horse] *2021-05-19*
|
||||
* [kitten][mobs_kitten] ([MIT][lic.mobs_kitten]) -- version: [4efdd4b Git][ver.mobs_kitten] *2021-05-19*
|
||||
* [monsters_aggressive][] (see individual mods for licensing) -- version: [89a8187 Git][ver.monsters_aggressive] *2017-08-30*
|
||||
* [monsters_passive][] (see individual mods for licensing) -- version: [b07fe19 Git][ver.monsters_passive] *2017-08-09*
|
||||
* [oerkki][creatures] ([Zlib][lic.creatures] / [CC BY-SA][lic.ccbysa3.0]) -- version: [70410fe Git][ver.oerkki] *2021-05-05*
|
||||
* [shark][] ([CC0 / CC BY-SA][lic.shark]) -- version: [9e0e048 Git][ver.shark] *2021-05-19*
|
||||
* [sheep][creatures] ([Zlib][lic.creatures] / [CC BY-SA][lic.ccbysa3.0]) -- version: [ff39b4a Git][ver.sheep] *2021-05-13*
|
||||
* [sneeker][] ([MIT][lic.sneeker]) -- version: [1.0][ver.sneeker] *2021-05-08*
|
||||
* [spider][cmer_spider] ([unilicense][lic.cmer_spider]) -- version: [d1a9a82 Git][ver.cmer_spider] *2021-05-19*
|
||||
* velociraptor ([LGPL][lic.lgpl2.1] / [CC BY-SA][lic.ccbysa3.0]) -- forked from *mobs_farlands* (part of [farlands][] sub-game)
|
||||
* [zombie][creatures] ([Zlib][lic.creatures] / [CC BY-SA][lic.ccbysa3.0]) -- version: [4edb18e Git][ver.zombie] *2021-05-05*
|
||||
* player/action/
|
||||
|
@ -270,6 +270,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
|||
[chatlog]: https://forum.minetest.net/viewtopic.php?t=18287
|
||||
[christmas]: https://forum.minetest.net/viewtopic.php?t=3950
|
||||
[cleaner]: https://github.com/AntumMT/mod-cleaner/tree/2404594
|
||||
[cmer_spider]: https://github.com/AntumMT/mod-spider
|
||||
[coloredwood]: https://forum.minetest.net/viewtopic.php?t=2411
|
||||
[compass]: https://forum.minetest.net/viewtopic.php?t=3785
|
||||
[compassgps]: https://forum.minetest.net/viewtopic.php?t=9373
|
||||
|
@ -394,6 +395,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
|||
[lic.castle]: mods/modpacks/castle/LICENSE
|
||||
[lic.christmas]: mods/buildings/christmas/LICENSE.txt
|
||||
[lic.cleaner]: mods/admin/cleaner/LICENSE.txt
|
||||
[lic.cmer_spider]: mods/mobiles/spider/LICENSE
|
||||
[lic.craftguide]: mods/crafting/craftguide/license.txt
|
||||
[lic.creatures]: mods/mobiles/engine/creatures/LICENSE.txt
|
||||
[lic.crops]: mods/farming/crops/LICENSE
|
||||
|
@ -503,6 +505,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
|||
[ver.chicken]: http://github.com/AntumMT/mod-cmer/tree/b126cdb
|
||||
[ver.christmas]: https://github.com/TheZenKitteh/minetest-christmas/tree/d3bd872
|
||||
[ver.cleaner]: https://github.com/AntumMT/mod-cleaner/tree/e8359d8
|
||||
[ver.cmer_spider]: https://github.com/AntumMT/mod-spider/tree/d1a9a82
|
||||
[ver.coloredwood]: https://gitlab.com/VanessaE/coloredwood/tags/2021-01-30
|
||||
[ver.compassgps]: https://github.com/Kilarin/compassgps/tree/567b95f
|
||||
[ver.crafting_bench]: https://github.com/minetest-mods/crafting_bench/tree/69083ed
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
# Passive Monsters Modpack for [Minetest][]
|
||||
|
||||
|
||||
---
|
||||
### **Description:**
|
||||
|
||||
A compilation of passive (retaliate only) monster mods for Minetest.
|
||||
|
||||
|
||||
---
|
||||
### **Mods:**
|
||||
|
||||
- ***[spider](spider/README.md):*** ([MIT](spider/license.txt))
|
||||
|
||||
|
||||
---
|
||||
### **Dependencies:**
|
||||
|
||||
See individual mods for requirements.
|
||||
|
||||
|
||||
[Minetest]: http://www.minetest.net/
|
|
@ -1,32 +0,0 @@
|
|||
## Spider mod for [Minetest][]
|
||||
|
||||
|
||||
---
|
||||
### **Description:**
|
||||
|
||||
Spider mod extracted from *[mobs_monster][]* @ [Git commit 1561ec1][ver.mobs_monster].
|
||||
|
||||
[b]Mob description:[/b]
|
||||
- Found in dark holes inside desertstone (crystal biomes in ethereal), spiders wait for prey to amble past and strike. They are mostly docile during the day though unless hit. Will drop string when killed.
|
||||
|
||||
---
|
||||
### **Dependencies:**
|
||||
|
||||
- **Required:**
|
||||
- ***[mobs (mobs_redo)][mobs_redo]***
|
||||
|
||||
|
||||
---
|
||||
### **Licensing:**
|
||||
|
||||
- [MIT](license.txt)
|
||||
- Textures:
|
||||
- CC BY-SA 3.0
|
||||
|
||||
|
||||
[Minetest]: http://www.minetest.net/
|
||||
|
||||
[mobs_monster]: https://github.com/tenplus1/mobs_monster
|
||||
[mobs_redo]: https://forum.minetest.net/viewtopic.php?t=9917
|
||||
|
||||
[ver.mobs_monster]: https://github.com/tenplus1/mobs_monster/tree/1561ec1
|
|
@ -1,3 +0,0 @@
|
|||
default
|
||||
mobs
|
||||
intllib?
|
|
@ -1,108 +0,0 @@
|
|||
|
||||
local S = mobs.intllib
|
||||
|
||||
|
||||
-- Spider by AspireMint (fishyWET (CC-BY-SA 3.0 license for texture)
|
||||
|
||||
mobs:register_mob("mobs:spider", {
|
||||
docile_by_day = true,
|
||||
group_attack = true,
|
||||
type = "monster",
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
reach = 2,
|
||||
damage = 3,
|
||||
hp_min = 20,
|
||||
hp_max = 40,
|
||||
armor = 200,
|
||||
collisionbox = {-0.9, -0.01, -0.7, 0.7, 0.6, 0.7},
|
||||
visual = "mesh",
|
||||
mesh = "mobs_spider.x",
|
||||
textures = {
|
||||
{"mobs_spider.png"},
|
||||
},
|
||||
visual_size = {x = 7, y = 7},
|
||||
makes_footstep_sound = false,
|
||||
sounds = {
|
||||
random = "mobs_spider",
|
||||
attack = "mobs_spider",
|
||||
},
|
||||
walk_velocity = 1,
|
||||
run_velocity = 3,
|
||||
jump = true,
|
||||
view_range = 15,
|
||||
floats = 0,
|
||||
drops = {
|
||||
{name = "farming:string", chance = 1, min = 1, max = 2},
|
||||
{name = "ethereal:crystal_spike", chance = 15, min = 1, max = 2},
|
||||
},
|
||||
water_damage = 5,
|
||||
lava_damage = 5,
|
||||
light_damage = 0,
|
||||
animation = {
|
||||
speed_normal = 15,
|
||||
speed_run = 15,
|
||||
stand_start = 1,
|
||||
stand_end = 1,
|
||||
walk_start = 20,
|
||||
walk_end = 40,
|
||||
run_start = 20,
|
||||
run_end = 40,
|
||||
punch_start = 50,
|
||||
punch_end = 90,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
local spawn_on = "default:desert_stone"
|
||||
|
||||
if minetest.get_modpath("ethereal") then
|
||||
spawn_on = "ethereal:crystal_dirt"
|
||||
else
|
||||
minetest.register_alias("ethereal:crystal_spike", "default:sandstone")
|
||||
end
|
||||
|
||||
mobs:spawn({
|
||||
name = "mobs:spider",
|
||||
nodes = {spawn_on},
|
||||
min_light = 0,
|
||||
max_light = 12,
|
||||
chance = 7000,
|
||||
active_object_count = 1,
|
||||
min_height = -50,
|
||||
max_height = 31000,
|
||||
})
|
||||
|
||||
|
||||
mobs:register_egg("mobs:spider", S("Spider"), "mobs_cobweb.png", 1)
|
||||
|
||||
|
||||
-- cobweb
|
||||
minetest.register_node(":mobs:cobweb", {
|
||||
description = S("Cobweb"),
|
||||
drawtype = "plantlike",
|
||||
visual_scale = 1.2,
|
||||
tiles = {"mobs_cobweb.png"},
|
||||
inventory_image = "mobs_cobweb.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
liquid_viscosity = 11,
|
||||
liquidtype = "source",
|
||||
liquid_alternative_flowing = "mobs:cobweb",
|
||||
liquid_alternative_source = "mobs:cobweb",
|
||||
liquid_renewable = false,
|
||||
liquid_range = 0,
|
||||
walkable = false,
|
||||
groups = {snappy = 1, disable_jump = 1},
|
||||
drop = "farming:cotton",
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mobs:cobweb",
|
||||
recipe = {
|
||||
{"farming:string", "", "farming:string"},
|
||||
{"", "farming:string", ""},
|
||||
{"farming:string", "", "farming:string"},
|
||||
}
|
||||
})
|
|
@ -1,21 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 TenPlus1
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -1,8 +0,0 @@
|
|||
# German Translation for mobs_monster mod
|
||||
# Deutsche Übersetzung der mobs_monster Mod
|
||||
# last update: 2016/June/10
|
||||
# Author: Xanthin
|
||||
|
||||
|
||||
Spider = Spinne
|
||||
Cobweb = Spinnennetz
|
|
@ -1,6 +0,0 @@
|
|||
# Template for translations of mob_spider mod
|
||||
# last update: 2017-08-09
|
||||
|
||||
|
||||
Spider =
|
||||
Cobweb =
|
|
@ -1,9 +0,0 @@
|
|||
# Türkçe çeviri by Admicos
|
||||
# Turkish translation by Admicos
|
||||
|
||||
# Son düzenleme: 26 Nisan 2017
|
||||
# Last edit: 26 April 2017
|
||||
|
||||
|
||||
Spider = Örümcek
|
||||
Cobweb = Örümcek ağı
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 144 B |
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB |
|
@ -0,0 +1,25 @@
|
|||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
minetest-spidermob-v1
|
||||
=====================
|
||||
|
||||
Spider mob extracted from the subgame LOTT
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
TODO:
|
|
@ -0,0 +1,895 @@
|
|||
|
||||
spidermob.disable_blood = core.settings:get_bool("mobs_disable_blood", false)
|
||||
|
||||
function spidermob:register_mob(name, def)
|
||||
minetest.register_entity(name, {
|
||||
name = name,
|
||||
hp_min = def.hp_min or 5, --
|
||||
hp_max = def.hp_max,
|
||||
physical = true,
|
||||
collisionbox = def.collisionbox,
|
||||
visual = def.visual,
|
||||
visual_size = def.visual_size,
|
||||
mesh = def.mesh,
|
||||
textures = def.textures,
|
||||
makes_footstep_sound = def.makes_footstep_sound,
|
||||
view_range = def.view_range,
|
||||
walk_velocity = def.walk_velocity,
|
||||
run_velocity = def.run_velocity,
|
||||
damage = def.damage,
|
||||
light_damage = def.light_damage,
|
||||
water_damage = def.water_damage,
|
||||
lava_damage = def.lava_damage,
|
||||
disable_fall_damage = def.disable_fall_damage,
|
||||
drops = def.drops,
|
||||
armor = def.armor,
|
||||
drawtype = def.drawtype,
|
||||
on_rightclick = def.on_rightclick,
|
||||
type = def.type,
|
||||
attack_type = def.attack_type,
|
||||
arrow = def.arrow,
|
||||
shoot_interval = def.shoot_interval,
|
||||
sounds = def.sounds,
|
||||
animation = def.animation,
|
||||
follow = def.follow,
|
||||
jump = def.jump or true,
|
||||
exp_min = def.exp_min or 0,
|
||||
exp_max = def.exp_max or 0,
|
||||
walk_chance = def.walk_chance or 50,
|
||||
attacks_monsters = def.attacks_monsters or false,
|
||||
group_attack = def.group_attack or false,
|
||||
step = def.step or 0,
|
||||
fov = def.fov or 120,
|
||||
passive = def.passive or false,
|
||||
recovery_time = def.recovery_time or 0.5,
|
||||
knock_back = def.knock_back or 3,
|
||||
blood_offset = def.blood_offset or 0,
|
||||
blood_amount = def.blood_amount or 5, -- 15
|
||||
blood_texture = def.blood_texture or "spidermob_blood.png",
|
||||
rewards = def.rewards or nil,
|
||||
animaltype = def.animaltype,
|
||||
|
||||
stimer = 0,
|
||||
timer = 0,
|
||||
env_damage_timer = 0, -- only if state = "attack"
|
||||
attack = {player=nil, dist=nil},
|
||||
state = "stand",
|
||||
v_start = false,
|
||||
old_y = nil,
|
||||
lifetimer = 600,
|
||||
tamed = false,
|
||||
last_state = nil,
|
||||
pause_timer = 0,
|
||||
|
||||
do_attack = function(self, player, dist)
|
||||
if self.state ~= "attack" then
|
||||
if self.sounds.war_cry then
|
||||
if math.random(0,100) < 90 then
|
||||
minetest.sound_play(self.sounds.war_cry,{ object = self.object })
|
||||
end
|
||||
end
|
||||
self.state = "attack"
|
||||
self.attack.player = player
|
||||
self.attack.dist = dist
|
||||
end
|
||||
end,
|
||||
|
||||
set_velocity = function(self, v)
|
||||
local yaw = self.object:get_yaw()
|
||||
if self.drawtype == "side" then
|
||||
yaw = yaw+(math.pi/2)
|
||||
end
|
||||
local x = math.sin(yaw) * -v
|
||||
local z = math.cos(yaw) * v
|
||||
self.object:set_velocity({x=x, y=self.object:get_velocity().y, z=z})
|
||||
end,
|
||||
|
||||
get_velocity = function(self)
|
||||
local v = self.object:get_velocity()
|
||||
return (v.x^2 + v.z^2)^(0.5)
|
||||
end,
|
||||
|
||||
in_fov = function(self,pos)
|
||||
-- checks if POS is in self's FOV
|
||||
local yaw = self.object:get_yaw()
|
||||
if self.drawtype == "side" then
|
||||
yaw = yaw+(math.pi/2)
|
||||
end
|
||||
local vx = math.sin(yaw)
|
||||
local vz = math.cos(yaw)
|
||||
local ds = math.sqrt(vx^2 + vz^2)
|
||||
local ps = math.sqrt(pos.x^2 + pos.z^2)
|
||||
local d = { x = vx / ds, z = vz / ds }
|
||||
local p = { x = pos.x / ps, z = pos.z / ps }
|
||||
|
||||
local an = ( d.x * p.x ) + ( d.z * p.z )
|
||||
|
||||
local a = math.deg( math.acos( an ) )
|
||||
|
||||
if a > ( self.fov / 2 ) then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end,
|
||||
|
||||
set_animation = function(self, type)
|
||||
if not self.animation then
|
||||
return
|
||||
end
|
||||
if not self.animation.current then
|
||||
self.animation.current = ""
|
||||
end
|
||||
if type == "stand" and self.animation.current ~= "stand" then
|
||||
if
|
||||
self.animation.stand_start
|
||||
and self.animation.stand_end
|
||||
and self.animation.speed_normal
|
||||
then
|
||||
self.object:set_animation(
|
||||
{x=self.animation.stand_start,y=self.animation.stand_end},
|
||||
self.animation.speed_normal, 0
|
||||
)
|
||||
self.animation.current = "stand"
|
||||
end
|
||||
elseif type == "walk" and self.animation.current ~= "walk" then
|
||||
if
|
||||
self.animation.walk_start
|
||||
and self.animation.walk_end
|
||||
and self.animation.speed_normal
|
||||
then
|
||||
self.object:set_animation(
|
||||
{x=self.animation.walk_start,y=self.animation.walk_end},
|
||||
self.animation.speed_normal, 0
|
||||
)
|
||||
self.animation.current = "walk"
|
||||
end
|
||||
elseif type == "run" and self.animation.current ~= "run" then
|
||||
if
|
||||
self.animation.run_start
|
||||
and self.animation.run_end
|
||||
and self.animation.speed_run
|
||||
then
|
||||
self.object:set_animation(
|
||||
{x=self.animation.run_start,y=self.animation.run_end},
|
||||
self.animation.speed_run, 0
|
||||
)
|
||||
self.animation.current = "run"
|
||||
end
|
||||
elseif type == "punch" and self.animation.current ~= "punch" then
|
||||
if
|
||||
self.animation.punch_start
|
||||
and self.animation.punch_end
|
||||
and self.animation.speed_normal
|
||||
then
|
||||
self.object:set_animation(
|
||||
{x=self.animation.punch_start,y=self.animation.punch_end},
|
||||
self.animation.speed_normal, 0
|
||||
)
|
||||
self.animation.current = "punch"
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
on_step = function(self, dtime)
|
||||
|
||||
if self.type == "monster" and minetest.settings:get_bool("only_peaceful_mobs") then
|
||||
self.object:remove()
|
||||
end
|
||||
|
||||
self.lifetimer = self.lifetimer - dtime
|
||||
if self.lifetimer <= 0 and not self.tamed and self.type ~= "npc" then
|
||||
local player_count = 0
|
||||
for _,obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 10)) do
|
||||
if obj:is_player() then
|
||||
player_count = player_count+1
|
||||
end
|
||||
end
|
||||
if player_count == 0 and self.state ~= "attack" then
|
||||
minetest.log("action","lifetimer expired, removed mob "..self.name)
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- drop egg
|
||||
-- if self.animaltype == "clucky" then
|
||||
-- if math.random(1, 1000) <= 1
|
||||
-- and minetest.get_node(self.object:get_pos()).name == "air"
|
||||
-- and self.state == "stand" then
|
||||
-- minetest.set_node(self.object:get_pos(), {name="mobs:egg"})
|
||||
-- end
|
||||
-- end
|
||||
|
||||
if self.object:get_velocity().y > 0.1 then
|
||||
local yaw = self.object:get_yaw()
|
||||
if self.drawtype == "side" then
|
||||
yaw = yaw+(math.pi/2)
|
||||
end
|
||||
local x = math.sin(yaw) * -2
|
||||
local z = math.cos(yaw) * 2
|
||||
self.object:set_acceleration({x=x, y=-10, z=z})
|
||||
else
|
||||
self.object:set_acceleration({x=0, y=-10, z=0})
|
||||
end
|
||||
|
||||
if self.disable_fall_damage and self.object:get_velocity().y == 0 then
|
||||
if not self.old_y then
|
||||
self.old_y = self.object:get_pos().y
|
||||
else
|
||||
local d = self.old_y - self.object:get_pos().y
|
||||
if d > 5 then
|
||||
local damage = d-5
|
||||
self.object:set_hp(self.object:get_hp()-damage)
|
||||
if self.object:get_hp() == 0 then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
self.old_y = self.object:get_pos().y
|
||||
end
|
||||
end
|
||||
|
||||
-- if pause state then this is where the loop ends
|
||||
-- pause is only set after a monster is hit
|
||||
if self.pause_timer > 0 then
|
||||
self.pause_timer = self.pause_timer - dtime
|
||||
if self.pause_timer <= 0 then
|
||||
self.pause_timer = 0
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
self.timer = self.timer+dtime
|
||||
if self.state ~= "attack" then
|
||||
if self.timer < 1 then
|
||||
return
|
||||
end
|
||||
self.timer = 0
|
||||
end
|
||||
|
||||
if self.sounds and self.sounds.random and math.random(1, 100) <= 1 then
|
||||
minetest.sound_play(self.sounds.random, {object = self.object})
|
||||
end
|
||||
|
||||
local do_env_damage = function(self)
|
||||
local pos = self.object:get_pos()
|
||||
local n = minetest.get_node(pos)
|
||||
|
||||
if self.light_damage and self.light_damage ~= 0
|
||||
and pos.y>0
|
||||
and minetest.get_node_light(pos)
|
||||
and minetest.get_node_light(pos) > 4
|
||||
and minetest.get_timeofday() > 0.2
|
||||
and minetest.get_timeofday() < 0.8
|
||||
then
|
||||
self.object:set_hp(self.object:get_hp()-self.light_damage)
|
||||
if self.object:get_hp() == 0 then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
|
||||
if self.water_damage and self.water_damage ~= 0 and
|
||||
minetest.get_item_group(n.name, "water") ~= 0
|
||||
then
|
||||
self.object:set_hp(self.object:get_hp()-self.water_damage)
|
||||
if self.object:get_hp() == 0 then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
|
||||
if self.lava_damage and self.lava_damage ~= 0 and
|
||||
minetest.get_item_group(n.name, "lava") ~= 0
|
||||
then
|
||||
self.object:set_hp(self.object:get_hp()-self.lava_damage)
|
||||
if self.object:get_hp() == 0 then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.env_damage_timer = self.env_damage_timer + dtime
|
||||
if self.state == "attack" and self.env_damage_timer > 1 then
|
||||
self.env_damage_timer = 0
|
||||
do_env_damage(self)
|
||||
elseif self.state ~= "attack" then
|
||||
do_env_damage(self)
|
||||
end
|
||||
|
||||
-- FIND SOMEONE TO ATTACK
|
||||
if ( self.type == "monster" or self.type == "barbarian" ) and minetest.settings:get_bool("enable_damage") and self.state ~= "attack" then
|
||||
local s = self.object:get_pos()
|
||||
local inradius = minetest.get_objects_inside_radius(s,self.view_range)
|
||||
local player = nil
|
||||
local type = nil
|
||||
for _,oir in ipairs(inradius) do
|
||||
if oir:is_player() then
|
||||
player = oir
|
||||
type = "player"
|
||||
else
|
||||
local obj = oir:get_luaentity()
|
||||
if obj then
|
||||
player = obj.object
|
||||
type = obj.type
|
||||
end
|
||||
end
|
||||
|
||||
if type == "player" or type == "npc" then
|
||||
local s = self.object:get_pos()
|
||||
local p = player:get_pos()
|
||||
local sp = s
|
||||
p.y = p.y + 1
|
||||
sp.y = sp.y + 1 -- aim higher to make looking up hills more realistic
|
||||
local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5
|
||||
if dist < self.view_range and self.in_fov(self,p) then
|
||||
if minetest.line_of_sight(sp,p,2) == true then
|
||||
self.do_attack(self,player,dist)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- NPC FIND A MONSTER TO ATTACK
|
||||
-- if self.type == "npc" and self.attacks_monsters and self.state ~= "attack" then
|
||||
-- local s = self.object:get_pos()
|
||||
-- local inradius = minetest.get_objects_inside_radius(s,self.view_range)
|
||||
-- for _, oir in pairs(inradius) do
|
||||
-- local obj = oir:get_luaentity()
|
||||
-- if obj then
|
||||
-- if obj.type == "monster" or obj.type == "barbarian" then
|
||||
-- -- attack monster
|
||||
-- local p = obj.object:get_pos()
|
||||
-- local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5
|
||||
-- self.do_attack(self,obj.object,dist)
|
||||
-- break
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
if self.follow ~= "" and not self.following then
|
||||
for _,player in pairs(minetest.get_connected_players()) do
|
||||
local s = self.object:get_pos()
|
||||
local p = player:get_pos()
|
||||
local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5
|
||||
if self.view_range and dist < self.view_range then
|
||||
self.following = player
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.following and self.following:is_player() then
|
||||
if self.following:get_wielded_item():get_name() ~= self.follow then
|
||||
self.following = nil
|
||||
else
|
||||
local s = self.object:get_pos()
|
||||
local p = self.following:get_pos()
|
||||
local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5
|
||||
if dist > self.view_range then
|
||||
self.following = nil
|
||||
self.v_start = false
|
||||
else
|
||||
local vec = {x=p.x-s.x, y=p.y-s.y, z=p.z-s.z}
|
||||
local yaw = math.atan(vec.z/vec.x)+math.pi/2
|
||||
if self.drawtype == "side" then
|
||||
yaw = yaw+(math.pi/2)
|
||||
end
|
||||
if p.x > s.x then
|
||||
yaw = yaw+math.pi
|
||||
end
|
||||
self.object:set_yaw(yaw)
|
||||
if dist > 2 then
|
||||
if not self.v_start then
|
||||
self.v_start = true
|
||||
self.set_velocity(self, self.walk_velocity)
|
||||
else
|
||||
if self.jump and self.get_velocity(self) <= 1.5 and self.object:get_velocity().y == 0 then
|
||||
local v = self.object:get_velocity()
|
||||
v.y = 6
|
||||
self.object:set_velocity(v)
|
||||
end
|
||||
self.set_velocity(self, self.walk_velocity)
|
||||
end
|
||||
self:set_animation("walk")
|
||||
else
|
||||
self.v_start = false
|
||||
self.set_velocity(self, 0)
|
||||
self:set_animation("stand")
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.state == "stand" then
|
||||
-- randomly turn
|
||||
if math.random(1, 4) == 1 then
|
||||
-- if there is a player nearby look at them
|
||||
local lp = nil
|
||||
local s = self.object:get_pos()
|
||||
local yaw = 0
|
||||
if self.type == "npc" then
|
||||
local o = minetest.get_objects_inside_radius(self.object:get_pos(), 3)
|
||||
|
||||
for _,o in ipairs(o) do
|
||||
if o:is_player() then
|
||||
lp = o:get_pos()
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if lp ~= nil then
|
||||
local vec = {x=lp.x-s.x, y=lp.y-s.y, z=lp.z-s.z}
|
||||
yaw = math.atan(vec.z/vec.x)+math.pi/2
|
||||
if self.drawtype == "side" then
|
||||
yaw = yaw+(math.pi/2)
|
||||
end
|
||||
if lp.x > s.x then
|
||||
yaw = yaw+math.pi
|
||||
end
|
||||
else
|
||||
yaw = self.object:get_yaw()+((math.random(0,360)-180)/180*math.pi)
|
||||
end
|
||||
self.object:set_yaw(yaw)
|
||||
end
|
||||
self.set_velocity(self, 0)
|
||||
self.set_animation(self, "stand")
|
||||
if math.random(1, 100) <= self.walk_chance then
|
||||
self.set_velocity(self, self.walk_velocity)
|
||||
self.state = "walk"
|
||||
self.set_animation(self, "walk")
|
||||
end
|
||||
elseif self.state == "walk" then
|
||||
if math.random(1, 100) <= 30 then
|
||||
self.object:set_yaw(self.object:get_yaw()+((math.random(0,360)-180)/180*math.pi))
|
||||
end
|
||||
if self.jump and self.get_velocity(self) <= 0.5 and self.object:get_velocity().y == 0 then
|
||||
local v = self.object:get_velocity()
|
||||
v.y = 5
|
||||
self.object:set_velocity(v)
|
||||
end
|
||||
self:set_animation("walk")
|
||||
self.set_velocity(self, self.walk_velocity)
|
||||
if math.random(1, 100) <= 30 then
|
||||
self.set_velocity(self, 0)
|
||||
self.state = "stand"
|
||||
self:set_animation("stand")
|
||||
end
|
||||
elseif self.state == "attack" and self.attack_type == "dogfight" then
|
||||
if not self.attack.player or not self.attack.player:get_pos() then
|
||||
print("stop attacking")
|
||||
self.state = "stand"
|
||||
self:set_animation("stand")
|
||||
return
|
||||
end
|
||||
local s = self.object:get_pos()
|
||||
local p = self.attack.player:get_pos()
|
||||
local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5
|
||||
if dist > self.view_range or self.attack.player:get_hp() <= 0 then
|
||||
self.state = "stand"
|
||||
self.v_start = false
|
||||
self.set_velocity(self, 0)
|
||||
self.attack = {player=nil, dist=nil}
|
||||
self:set_animation("stand")
|
||||
return
|
||||
else
|
||||
self.attack.dist = dist
|
||||
end
|
||||
|
||||
local vec = {x=p.x-s.x, y=p.y-s.y, z=p.z-s.z}
|
||||
local yaw = math.atan(vec.z/vec.x)+math.pi/2
|
||||
if self.drawtype == "side" then
|
||||
yaw = yaw+(math.pi/2)
|
||||
end
|
||||
if p.x > s.x then
|
||||
yaw = yaw+math.pi
|
||||
end
|
||||
self.object:set_yaw(yaw)
|
||||
if self.attack.dist > 2 then
|
||||
if not self.v_start then
|
||||
self.v_start = true
|
||||
self.set_velocity(self, self.run_velocity)
|
||||
else
|
||||
if self.jump and self.get_velocity(self) <= 0.5 and self.object:get_velocity().y == 0 then
|
||||
local v = self.object:get_velocity()
|
||||
v.y = 5
|
||||
self.object:set_velocity(v)
|
||||
end
|
||||
self.set_velocity(self, self.run_velocity)
|
||||
end
|
||||
self:set_animation("run")
|
||||
else
|
||||
self.set_velocity(self, 0)
|
||||
self:set_animation("punch")
|
||||
self.v_start = false
|
||||
if self.timer > 1 then
|
||||
self.timer = 0
|
||||
local p2 = p
|
||||
local s2 = s
|
||||
p2.y = p2.y + 1.5
|
||||
s2.y = s2.y + 1.5
|
||||
if minetest.line_of_sight(p2,s2) == true then
|
||||
if self.sounds and self.sounds.attack then
|
||||
minetest.sound_play(self.sounds.attack, {object = self.object})
|
||||
end
|
||||
self.attack.player:punch(self.object, 1.0, {
|
||||
full_punch_interval=1.0,
|
||||
damage_groups = {fleshy=self.damage}
|
||||
}, vec)
|
||||
if self.attack.player:get_hp() <= 0 then
|
||||
self.state = "stand"
|
||||
self:set_animation("stand")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif self.state == "attack" and self.attack_type == "shoot" then
|
||||
if not self.attack.player or not self.attack.player:is_player() then
|
||||
self.state = "stand"
|
||||
self:set_animation("stand")
|
||||
return
|
||||
end
|
||||
local s = self.object:get_pos()
|
||||
local p = self.attack.player:get_pos()
|
||||
p.y = p.y - .5
|
||||
s.y = s.y + .5
|
||||
local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5
|
||||
if dist > self.view_range or self.attack.player:get_hp() <= 0 then
|
||||
self.state = "stand"
|
||||
self.v_start = false
|
||||
self.set_velocity(self, 0)
|
||||
if self.type ~= "npc" then
|
||||
self.attack = {player=nil, dist=nil}
|
||||
end
|
||||
self:set_animation("stand")
|
||||
return
|
||||
else
|
||||
self.attack.dist = dist
|
||||
end
|
||||
|
||||
local vec = {x=p.x-s.x, y=p.y-s.y, z=p.z-s.z}
|
||||
local yaw = math.atan(vec.z/vec.x)+math.pi/2
|
||||
if self.drawtype == "side" then
|
||||
yaw = yaw+(math.pi/2)
|
||||
end
|
||||
if p.x > s.x then
|
||||
yaw = yaw+math.pi
|
||||
end
|
||||
self.object:set_yaw(yaw)
|
||||
self.set_velocity(self, 0)
|
||||
|
||||
if self.timer > self.shoot_interval and math.random(1, 100) <= 60 then
|
||||
self.timer = 0
|
||||
|
||||
self:set_animation("punch")
|
||||
|
||||
if self.sounds and self.sounds.attack then
|
||||
minetest.sound_play(self.sounds.attack, {object = self.object})
|
||||
end
|
||||
|
||||
local p = self.object:get_pos()
|
||||
p.y = p.y + (self.collisionbox[2]+self.collisionbox[5])/2
|
||||
local obj = minetest.add_entity(p, self.arrow)
|
||||
local amount = (vec.x^2+vec.y^2+vec.z^2)^0.5
|
||||
local v = obj:get_luaentity().velocity
|
||||
vec.y = vec.y+1
|
||||
vec.x = vec.x*v/amount
|
||||
vec.y = vec.y*v/amount
|
||||
vec.z = vec.z*v/amount
|
||||
obj:set_velocity(vec)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
on_activate = function(self, staticdata, dtime_s)
|
||||
-- reset HP
|
||||
local pos = self.object:get_pos()
|
||||
local distance_rating = ( ( get_distance({x=0,y=0,z=0},pos) ) / 20000 )
|
||||
local newHP = self.hp_min + math.floor( self.hp_max * distance_rating )
|
||||
self.object:set_hp( newHP )
|
||||
|
||||
self.object:set_armor_groups({fleshy=self.armor})
|
||||
self.object:set_acceleration({x=0, y=-10, z=0})
|
||||
self.state = "stand"
|
||||
self.object:set_velocity({x=0, y=self.object:get_velocity().y, z=0})
|
||||
self.object:set_yaw(math.random(1, 360)/180*math.pi)
|
||||
if self.type == "monster" and minetest.settings:get_bool("only_peaceful_mobs") then
|
||||
self.object:remove()
|
||||
end
|
||||
if self.type ~= "npc" then
|
||||
self.lifetimer = 600 - dtime_s
|
||||
end
|
||||
if staticdata then
|
||||
local tmp = minetest.deserialize(staticdata)
|
||||
if tmp and tmp.lifetimer then
|
||||
self.lifetimer = tmp.lifetimer - dtime_s
|
||||
end
|
||||
if tmp and tmp.tamed then
|
||||
self.tamed = tmp.tamed
|
||||
end
|
||||
--[[if tmp and tmp.textures then
|
||||
self.object:set_properties(tmp.textures)
|
||||
end]]
|
||||
end
|
||||
if self.lifetimer <= 0 and not self.tamed and self.type ~= "npc" then
|
||||
self.object:remove()
|
||||
end
|
||||
end,
|
||||
|
||||
get_staticdata = function(self)
|
||||
local tmp = {
|
||||
lifetimer = self.lifetimer,
|
||||
tamed = self.tamed,
|
||||
textures = { textures = self.textures },
|
||||
}
|
||||
return minetest.serialize(tmp)
|
||||
end,
|
||||
|
||||
on_punch = function(self, hitter, tflp, tool_capabilities, dir)
|
||||
|
||||
process_weapon(hitter,tflp,tool_capabilities)
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
if self.object:get_hp() <= 0 then
|
||||
if hitter and hitter:is_player() and hitter:get_inventory() then
|
||||
for _,drop in ipairs(self.drops) do
|
||||
if math.random(1, drop.chance) == 1 then
|
||||
local d = ItemStack(drop.name.." "..math.random(drop.min, drop.max))
|
||||
--default.drop_item(pos,d)
|
||||
local pos2 = pos
|
||||
pos2.y = pos2.y + 0.5 -- drop items half block higher
|
||||
minetest.add_item(pos2,d)
|
||||
end
|
||||
end
|
||||
|
||||
if self.sounds.death ~= nil then
|
||||
minetest.sound_play(self.sounds.death,{
|
||||
object = self.object,
|
||||
})
|
||||
end
|
||||
if minetest.get_modpath("skills") and minetest.get_modpath("experience") then
|
||||
-- DROP experience
|
||||
local distance_rating = ( ( get_distance({x=0,y=0,z=0},pos) ) / ( skills.get_player_level(hitter:get_player_name()).level * 1000 ) )
|
||||
local emax = math.floor( self.exp_min + ( distance_rating * self.exp_max ) )
|
||||
local expGained = math.random(self.exp_min, emax)
|
||||
skills.add_exp(hitter:get_player_name(),expGained)
|
||||
local expStack = experience.exp_to_items(expGained)
|
||||
for _,stack in ipairs(expStack) do
|
||||
default.drop_item(pos,stack)
|
||||
end
|
||||
end
|
||||
|
||||
-- see if there are any NPCs to shower you with rewards
|
||||
if self.type ~= "npc" then
|
||||
local inradius = minetest.get_objects_inside_radius(hitter:get_pos(),10)
|
||||
for _, oir in pairs(inradius) do
|
||||
local obj = oir:get_luaentity()
|
||||
if obj then
|
||||
if obj.type == "npc" and obj.rewards ~= nil then
|
||||
local yaw = nil
|
||||
local lp = hitter:get_pos()
|
||||
local s = obj.object:get_pos()
|
||||
local vec = {x=lp.x-s.x, y=1, z=lp.z-s.z}
|
||||
yaw = math.atan(vec.z/vec.x)+math.pi/2
|
||||
if self.drawtype == "side" then
|
||||
yaw = yaw+(math.pi/2)
|
||||
end
|
||||
if lp.x > s.x then
|
||||
yaw = yaw+math.pi
|
||||
end
|
||||
obj.object:set_yaw(yaw)
|
||||
local x = math.sin(yaw) * -2
|
||||
local z = math.cos(yaw) * 2
|
||||
acc = {x=x, y=-5, z=z}
|
||||
for _, r in pairs(obj.rewards) do
|
||||
if math.random(0,100) < r.chance then
|
||||
default.drop_item(obj.object:get_pos(),r.item, vec, acc)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--blood_particles
|
||||
|
||||
if not spidermob.disable_blood and self.blood_amount > 0 and pos then
|
||||
local p = pos
|
||||
p.y = p.y + self.blood_offset
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount = self.blood_amount,
|
||||
time = 0.25,
|
||||
minpos = {x=p.x-0.2, y=p.y-0.2, z=p.z-0.2},
|
||||
maxpos = {x=p.x+0.2, y=p.y+0.2, z=p.z+0.2},
|
||||
minvel = {x=0, y=-2, z=0},
|
||||
maxvel = {x=2, y=2, z=2},
|
||||
minacc = {x=-4,y=-4,z=-4},
|
||||
maxacc = {x=4,y=-4,z=4},
|
||||
minexptime = 0.1,
|
||||
maxexptime = 1,
|
||||
minsize = 0.5,
|
||||
maxsize = 1,
|
||||
texture = self.blood_texture,
|
||||
})
|
||||
end
|
||||
|
||||
-- knock back effect, adapted from blockmen's pyramids mod
|
||||
-- https://github.com/BlockMen/pyramids
|
||||
local kb = self.knock_back
|
||||
local r = self.recovery_time
|
||||
|
||||
if tflp < tool_capabilities.full_punch_interval then
|
||||
kb = kb * ( tflp / tool_capabilities.full_punch_interval )
|
||||
r = r * ( tflp / tool_capabilities.full_punch_interval )
|
||||
end
|
||||
|
||||
local ykb=2
|
||||
local v = self.object:get_velocity()
|
||||
if v.y ~= 0 then
|
||||
ykb = 0
|
||||
end
|
||||
|
||||
self.object:set_velocity({x=dir.x*kb,y=ykb,z=dir.z*kb})
|
||||
self.pause_timer = r
|
||||
|
||||
-- attack puncher and call other mobs for help
|
||||
if self.passive == false then
|
||||
if self.state ~= "attack" then
|
||||
self.do_attack(self,hitter,1)
|
||||
end
|
||||
-- alert other NPCs to the attack
|
||||
local inradius = minetest.get_objects_inside_radius(hitter:get_pos(),5)
|
||||
for _, oir in pairs(inradius) do
|
||||
local obj = oir:get_luaentity()
|
||||
if obj then
|
||||
if obj.group_attack == true and obj.state ~= "attack" then
|
||||
obj.do_attack(obj,hitter,1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end,
|
||||
|
||||
})
|
||||
end
|
||||
|
||||
spidermob.spawning_spidermob = {}
|
||||
function spidermob:register_spawn(name, nodes, max_light, min_light, chance, active_object_count, max_height, spawn_func)
|
||||
spidermob.spawning_spidermob[name] = true
|
||||
minetest.register_abm({
|
||||
nodenames = nodes,
|
||||
neighbors = {"air"},
|
||||
interval = 30,
|
||||
chance = chance,
|
||||
action = function(pos, node, _, active_object_count_wider)
|
||||
if active_object_count_wider > active_object_count then
|
||||
return
|
||||
end
|
||||
if not spidermob.spawning_spidermob[name] then
|
||||
return
|
||||
end
|
||||
|
||||
pos.y = pos.y+1
|
||||
if not minetest.get_node_light(pos) then
|
||||
return
|
||||
end
|
||||
if minetest.get_node_light(pos) > max_light then
|
||||
return
|
||||
end
|
||||
if minetest.get_node_light(pos) < min_light then
|
||||
return
|
||||
end
|
||||
if pos.y > max_height then
|
||||
return
|
||||
end
|
||||
|
||||
if minetest.registered_nodes[minetest.get_node(pos).name].walkable then
|
||||
return
|
||||
end
|
||||
|
||||
pos.y = pos.y+1
|
||||
pos.y = pos.y+1
|
||||
|
||||
if minetest.registered_nodes[minetest.get_node(pos).name].walkable then
|
||||
return
|
||||
end
|
||||
|
||||
if min_dist == nil then
|
||||
min_dist = {x=-1,z=-1}
|
||||
end
|
||||
if max_dist == nil then
|
||||
max_dist = {x=33000,z=33000}
|
||||
end
|
||||
|
||||
if math.abs(pos.x) < min_dist.x or math.abs(pos.z) < min_dist.z then
|
||||
return
|
||||
end
|
||||
|
||||
if math.abs(pos.x) > max_dist.x or math.abs(pos.z) > max_dist.z then
|
||||
return
|
||||
end
|
||||
|
||||
if spawn_func and not spawn_func(pos, node) then
|
||||
return
|
||||
end
|
||||
|
||||
if minetest.settings:get_bool("display_mob_spawn") then
|
||||
minetest.chat_send_all("[spidermob] Add "..name.." at "..minetest.pos_to_string(pos))
|
||||
end
|
||||
local mob = minetest.add_entity(pos, name)
|
||||
|
||||
-- setup the hp, armor, drops, etc... for this specific mob
|
||||
local distance_rating = ( ( get_distance({x=0,y=0,z=0},pos) ) / 15000 )
|
||||
if mob then
|
||||
mob = mob:get_luaentity()
|
||||
local newHP = mob.hp_min + math.floor( mob.hp_max * distance_rating )
|
||||
mob.object:set_hp( newHP )
|
||||
end
|
||||
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
function spidermob:register_arrow(name, def)
|
||||
minetest.register_entity(name, {
|
||||
physical = false,
|
||||
visual = def.visual,
|
||||
visual_size = def.visual_size,
|
||||
textures = def.textures,
|
||||
velocity = def.velocity,
|
||||
hit_player = def.hit_player,
|
||||
hit_node = def.hit_node,
|
||||
collisionbox = {0,0,0,0,0,0}, -- remove box around arrows
|
||||
on_step = function(self, dtime)
|
||||
local pos = self.object:get_pos()
|
||||
if minetest.get_node(self.object:get_pos()).name ~= "air" then
|
||||
self.hit_node(self, pos, node)
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
-- pos.y = pos.y-1.0
|
||||
for _,player in pairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
if player:is_player() then
|
||||
self.hit_player(self, player)
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
function get_distance(pos1,pos2)
|
||||
if ( pos1 ~= nil and pos2 ~= nil ) then
|
||||
return math.abs(math.floor(math.sqrt( (pos1.x - pos2.x)^2 + (pos1.z - pos2.z)^2 )))
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
function process_weapon(player, time_from_last_punch, tool_capabilities)
|
||||
local weapon = player:get_wielded_item()
|
||||
if tool_capabilities ~= nil then
|
||||
local wear = ( tool_capabilities.full_punch_interval / 75 ) * 65535
|
||||
weapon:add_wear(wear)
|
||||
player:set_wielded_item(weapon)
|
||||
end
|
||||
|
||||
if weapon:get_definition().sounds ~= nil then
|
||||
local s = math.random(0,#weapon:get_definition().sounds)
|
||||
minetest.sound_play(weapon:get_definition().sounds[s], {
|
||||
object=player,
|
||||
})
|
||||
else
|
||||
minetest.sound_play("default_sword_wood", {
|
||||
object = player,
|
||||
})
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "spidermob",
|
||||
"description": "Spider mob extracted from the subgame LOTT",
|
||||
"keywords": [
|
||||
"spidermob"
|
||||
],
|
||||
"homepage": "https://github.com/Ombridride/minetest-spidermob-v1",
|
||||
"forum": "http://forum.minetest.net/viewtopic.php?f=11&t=10045",
|
||||
"screenshots": [
|
||||
"https://cloud.githubusercontent.com/assets/51875/9277499/91c4d0c0-42e9-11e5-939c-972d8e8dcbee.png"
|
||||
],
|
||||
"authors": [
|
||||
"Ombridride"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
|
||||
spidermob = {}
|
||||
spidermob.modname = core.get_current_modname()
|
||||
spidermob.modpath = core.get_modpath(spidermob.modname)
|
||||
|
||||
--dofile(spidermob.modpath .. "/api.lua")
|
||||
|
||||
|
||||
local spider_drops = {}
|
||||
if core.registered_items["farming:string"] then
|
||||
table.insert(spider_drops, {"farming:string", {min=1, max=3}, chance=0.5})
|
||||
end
|
||||
|
||||
local spawn_nodes = {
|
||||
"default:junglegrass",
|
||||
"default:jungleleaves",
|
||||
"default:jungletree",
|
||||
}
|
||||
|
||||
|
||||
cmer.register_mob({
|
||||
name = "creatures:spider",
|
||||
stats = {
|
||||
hp = 30,
|
||||
hostile = true,
|
||||
lifetime = 600, -- 10 minutes
|
||||
can_jump = 1,
|
||||
},
|
||||
modes = {
|
||||
idle = {chance=0.7, duration=3.0,},
|
||||
walk = {chance=0.3, duration=5.5, moving_speed=1,},
|
||||
--follow = {chance=0, moving_speed=3, radius=15,},
|
||||
attack = {chance=0, moving_speed=3},
|
||||
},
|
||||
model = {
|
||||
mesh = "spider_model.x",
|
||||
textures = {"spidermob_spider.png"},
|
||||
collisionbox = {-0.9, -0.01, -0.7, 0.7, 0.6, 0.7},
|
||||
scale = {x=7, y=7},
|
||||
rotation = -90.0,
|
||||
animations = {
|
||||
idle = {start=1, stop=1, speed=15,},
|
||||
walk = {start=20, stop=40, speed=15,},
|
||||
--follow = {start=20, stop=40, speed=15,},
|
||||
attack = {start=50, stop=90, speed=15,},
|
||||
},
|
||||
},
|
||||
sounds = {
|
||||
on_death = {name="mobs_howl", gain=1.0,},
|
||||
},
|
||||
drops = spider_drops,
|
||||
combat = {
|
||||
attack_damage = 3,
|
||||
attack_radius = 1.3,
|
||||
search_enemy = true,
|
||||
search_radius = 15,
|
||||
search_type = "player",
|
||||
},
|
||||
spawning = {
|
||||
abm_nodes = {spawn_on=spawn_nodes,},
|
||||
abm_interval = 60,
|
||||
abm_chance = 7500,
|
||||
max_number = 3,
|
||||
number = 1,
|
||||
time_range = {min=0, max=23999},
|
||||
light = {min=-10, max=20},
|
||||
height_limit = {min=-500, max=31000},
|
||||
},
|
||||
})
|
||||
|
||||
--[[
|
||||
local spider_drops = {}
|
||||
if core.registered_items["farming:string"] then
|
||||
table.insert(spider_drops, {
|
||||
name = "farming:string",
|
||||
chance = 2,
|
||||
min = 1,
|
||||
max = 3,
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
spidermob:register_mob("spidermob:spider", {
|
||||
type = "monster",
|
||||
hp_min = 15,
|
||||
hp_max = 30,
|
||||
collisionbox = {-0.9, -0.01, -0.7, 0.7, 0.6, 0.7},
|
||||
textures = {"spidermob_spider.png"},
|
||||
visual_size = {x=7,y=7},
|
||||
visual = "mesh",
|
||||
mesh = "spider_model.x",
|
||||
makes_footstep_sound = true,
|
||||
view_range = 15,
|
||||
walk_velocity = 1,
|
||||
run_velocity = 3,
|
||||
armor = 200,
|
||||
damage = 3,
|
||||
drops = spider_drops,
|
||||
light_resistant = true,
|
||||
drawtype = "front",
|
||||
water_damage = 5,
|
||||
lava_damage = 5,
|
||||
light_damage = 0,
|
||||
on_rightclick = nil,
|
||||
attack_type = "dogfight",
|
||||
animation = {
|
||||
speed_normal = 15,
|
||||
speed_run = 15,
|
||||
stand_start = 1,
|
||||
stand_end = 1,
|
||||
walk_start = 20,
|
||||
walk_end = 40,
|
||||
run_start = 20,
|
||||
run_end = 40,
|
||||
punch_start = 50,
|
||||
punch_end = 90,
|
||||
},
|
||||
jump = true,
|
||||
step = 1,
|
||||
blood_texture = "spidermob_blood.png",
|
||||
sounds = {
|
||||
war_cry = "mobs_eerie",
|
||||
death = "mobs_howl",
|
||||
attack = "mobs_oerkki_attack",
|
||||
},
|
||||
})
|
||||
|
||||
spidermob:register_spawn(
|
||||
"spidermob:spider",
|
||||
{
|
||||
"default:junglegrass",
|
||||
"default:jungleleaves",
|
||||
"default:jungletree",
|
||||
},
|
||||
20, -10, 7500, 3, 31000)
|
||||
]]
|
|
@ -0,0 +1,4 @@
|
|||
name = cmer_spider
|
||||
description = An itsy bitsy spider.
|
||||
depends = cmer, default
|
||||
optional_depends = farming
|
|
@ -1,5 +1,10 @@
|
|||
xof 0303txt 0032
|
||||
|
||||
template AnimTicksPerSecond {
|
||||
<9E415A43-7BA6-4a73-8743-B73D47E88476>
|
||||
DWORD AnimTicksPerSecond;
|
||||
}
|
||||
|
||||
template XSkinMeshHeader {
|
||||
<3cf169ce-ff7c-44ab-93c0-f78f62d172e2>
|
||||
WORD nMaxSkinWeightsPerVertex;
|
||||
|
@ -2354,7 +2359,9 @@ Frame Root {
|
|||
} // End of Group8
|
||||
} // End of Armature
|
||||
} // End of Root
|
||||
|
||||
AnimTicksPerSecond {
|
||||
24;
|
||||
}
|
||||
AnimationSet Global {
|
||||
Animation {
|
||||
{Armature}
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
# Disable blood splatter when attacking mobs.
|
||||
mobs_disable_blood (Disable Mob blood) bool false
|
||||
|
||||
# Only spawn mobs that don't attack players.
|
||||
only_peaceful_mobs (Peaceful only) bool false
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 267 B |
Binary file not shown.
After Width: | Height: | Size: 6.2 KiB |
Loading…
Reference in New Issue