Replace mobs version of spider with cmer_spider...

https://github.com/AntumMT/mod-spider
master
Jordan Irwin 2021-05-19 23:19:42 -07:00
parent d71a37a023
commit 290ffb9c59
27 changed files with 1099 additions and 211 deletions

View File

@ -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

View File

@ -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/

View File

@ -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

View File

@ -1,3 +0,0 @@
default
mobs
intllib?

View File

@ -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"},
}
})

View File

@ -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.

View File

@ -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

View File

@ -1,6 +0,0 @@
# Template for translations of mob_spider mod
# last update: 2017-08-09
Spider =
Cobweb =

View File

@ -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.

Before

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -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>

View File

@ -0,0 +1,4 @@
minetest-spidermob-v1
=====================
Spider mob extracted from the subgame LOTT

View File

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

895
mods/mobiles/spider/api.lua Normal file
View File

@ -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

View File

@ -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"
]
}

View File

@ -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)
]]

View File

@ -0,0 +1,4 @@
name = cmer_spider
description = An itsy bitsy spider.
depends = cmer, default
optional_depends = farming

View File

@ -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}

View File

@ -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