Added barbarian archer, added blacksmith npc, fixed dungeon master bugs

master
Brandon 2014-07-07 22:00:46 -05:00
parent 39c2cfcbb4
commit 0d173d8161
12 changed files with 392 additions and 56 deletions

View File

@ -18,7 +18,7 @@ function mobs:register_mob(name, def)
run_velocity = def.run_velocity,
damage = def.damage,
light_damage = def.light_damage,
water_damage = def.water_damage,
water_damage = def.water_damage or 1,
lava_damage = def.lava_damage,
disable_fall_damage = def.disable_fall_damage,
drops = def.drops,
@ -28,11 +28,12 @@ function mobs:register_mob(name, def)
type = def.type,
attack_type = def.attack_type,
arrow = def.arrow,
arrow_offset = def.arrow_offset or 1,
shoot_interval = def.shoot_interval,
sounds = def.sounds,
animation = def.animation,
follow = def.follow,
jump = def.jump or true,
jump = def.jump,
exp_min = def.exp_min or 0,
exp_max = def.exp_max or 0,
walk_chance = def.walk_chance or 50,
@ -47,6 +48,8 @@ function mobs:register_mob(name, def)
blood_amount = def.blood_amount or 15,
blood_texture = def.blood_texture or "mobs_blood.png",
rewards = def.rewards or nil,
stationary = def.stationary or false,
activity_level = def.activity_level or 10,
stimer = 0,
timer = 0,
@ -59,6 +62,60 @@ function mobs:register_mob(name, def)
tamed = false,
last_state = nil,
pause_timer = 0,
path = nil,
path_pos = nil,
last_dist = nil,
leg_timer = nil,
path_callback = nil,
start_path = function(self,callback)
-- start on the defined path
self.physical = false -- allow the mob to walk through other entities
self.path_pos = 1
self.state = "path"
self.set_animation(self,"walk")
mobs:face_pos(self,self.path[1])
self.set_velocity(self,self.walk_velocity/2)
self.last_dist = get_distance(self.object:getpos(),self.path[1])
self.leg_timer = 0
self.path_callback = callback
end,
check_path = function(self)
local p = self.object:getpos()
local pa = self.path[self.path_pos]
local this_dist = get_distance(p,pa)
if this_dist > self.last_dist or self.leg_timer > 1 then
-- overshot the point so redirect the mob
mobs:face_pos(self,self.path[self.path_pos])
self.leg_timer = 0
end
self.last_dist = this_dist
if math.abs(p.x - pa.x) < 1 and math.abs(p.z - pa.z) < 1 or ( self.path_pos == #self.path and this_dist < 1 ) then
-- goto next position
self.path_pos = self.path_pos + 1
if self.path_pos <= #self.path then
-- continue to next point
mobs:face_pos(self,self.path[self.path_pos])
self.set_velocity(self,self.walk_velocity)
self.set_animation(self,"walk")
self.leg_timer = 0
else
if self.path_callback ~= nil then
-- do the arrival callback
self.path_callback(self)
end
-- stop following path
self.set_velocity(self,0)
self.state = "stand"
self.set_animation(self,"stand")
self.path = nil
self.path_pos = nil
self.physical = true
self.leg_timer = nil
end
end
end,
do_attack = function(self, player, dist)
if self.state ~= "attack" then
@ -376,7 +433,7 @@ function mobs:register_mob(name, def)
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:getvelocity().y == 0 then
if self.jump == true and self.get_velocity(self) <= 1.5 and self.object:getvelocity().y == 0 then
local v = self.object:getvelocity()
v.y = 6
self.object:setvelocity(v)
@ -396,7 +453,7 @@ function mobs:register_mob(name, def)
if self.state == "stand" then
-- randomly turn
if math.random(1, 4) == 1 then
if math.random(1, 100) < self.activity_level then
-- if there is a player nearby look at them
local lp = nil
local s = self.object:getpos()
@ -412,42 +469,40 @@ function mobs:register_mob(name, def)
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
mobs:face_pos(self,lp)
else
yaw = self.object:getyaw()+((math.random(0,360)-180)/180*math.pi)
yaw = self.object:getyaw()+((math.random(0,360)-270)/180*math.pi)
self.object:setyaw(yaw)
end
self.object:setyaw(yaw)
end
self.set_velocity(self, 0)
self.set_animation(self, "stand")
if math.random(1, 100) <= self.walk_chance then
if math.random(1, 100) <= self.activity_level and self.stationary == false 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:setyaw(self.object:getyaw()+((math.random(0,360)-180)/180*math.pi))
elseif self.state == "walk" or self.state == "path" then
if ( math.random(1, 100) <= 30 or ( self.get_velocity(self) < self.walk_velocity ) ) and self.state ~= "path" then
self.object:setyaw(self.object:getyaw()+((math.random(0,360)-270)/180*math.pi))
end
if self.jump and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0 then
if self.jump == true and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0 then
local v = self.object:getvelocity()
v.y = 5
self.object:setvelocity(v)
end
self:set_animation("walk")
self.set_velocity(self, self.walk_velocity)
if math.random(1, 100) <= 30 then
if math.random(1, 100) <= 30 and self.state ~= "path" then
self.set_velocity(self, 0)
self.state = "stand"
self:set_animation("stand")
end
if self.state == "path" then
self.leg_timer = self.leg_timer + dtime
self.check_path(self)
end
elseif self.state == "attack" and self.attack_type == "dogfight" then
if not self.attack.player or not self.attack.player:getpos() then
print("stop attacking")
@ -483,7 +538,7 @@ function mobs:register_mob(name, def)
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:getvelocity().y == 0 then
if self.jump == true and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0 then
local v = self.object:getvelocity()
v.y = 5
self.object:setvelocity(v)
@ -561,15 +616,18 @@ function mobs:register_mob(name, def)
end
local p = self.object:getpos()
p.y = p.y + (self.collisionbox[2]+self.collisionbox[5])/2
p.y = p.y + self.arrow_offset
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.y = vec.y
vec.x = vec.x*v/amount
vec.y = vec.y*v/amount
vec.z = vec.z*v/amount
obj:setvelocity(vec)
if obj:get_luaentity().drop_rate ~= nil then
obj:setacceleration({x=vec.x, y=obj:get_luaentity().drop_rate, z=vec.z})
end
end
end
end,
@ -656,18 +714,10 @@ function mobs:register_mob(name, def)
local obj = oir:get_luaentity()
if obj then
if obj.type == "npc" and obj.rewards ~= nil then
local yaw = nil
local lp = hitter:getpos()
local s = obj.object:getpos()
local yaw = mobs:face_pos(self,lp)
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:setyaw(yaw)
local x = math.sin(yaw) * -2
local z = math.cos(yaw) * 2
acc = {x=x, y=-5, z=z}
@ -842,24 +892,53 @@ function mobs:register_arrow(name, def)
velocity = def.velocity,
hit_player = def.hit_player,
hit_node = def.hit_node,
timer = 0,
on_step = function(self, dtime)
local pos = self.object:getpos()
if minetest.get_node(self.object:getpos()).name ~= "air" then
self.hit_node(self, pos, node)
self.object:remove()
return
end
pos.y = pos.y-1
for _,player in pairs(minetest.get_objects_inside_radius(pos, 1)) do
self.hit_player(self, player)
self.object:remove()
return
self.timer=self.timer+dtime
if self.timer > 0.2 then
local pos = self.object:getpos()
if minetest.get_node(self.object:getpos()).name ~= "air" and minetest.get_node(self.object:getpos()).name ~= "fire:basic_flame"then
self.hit_node(self, pos, node)
self.object:remove()
return
end
--pos.y = pos.y-1
local objs = minetest.get_objects_inside_radius(pos, 2)
for _,player in pairs(objs) do
if player:get_luaentity() ~= nil then
local luae = player:get_luaentity()
if luae.name ~= self.object:get_luaentity().name and luae.name ~= "__builtin:item" then
self.hit_player(self, player)
self.object:remove()
return
end
else
self.hit_player(self, player)
self.object:remove()
return
end
end
end
end
})
end
function mobs:face_pos(self,pos)
local s = self.object:getpos()
local vec = {x=pos.x-s.x, y=pos.y-s.y, z=pos.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 pos.x > s.x then
yaw = yaw+math.pi
end
self.object:setyaw(yaw)
return yaw
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 )))

View File

@ -3,6 +3,7 @@ dofile(minetest.get_modpath("mobs").."/spawner.lua")
dofile(minetest.get_modpath("mobs").."/npcs/explorer.lua")
dofile(minetest.get_modpath("mobs").."/npcs/men.lua")
dofile(minetest.get_modpath("mobs").."/npcs/women.lua")
dofile(minetest.get_modpath("mobs").."/npcs/blacksmith.lua")
dofile(minetest.get_modpath("mobs").."/monsters/barbarians.lua")
dofile(minetest.get_modpath("mobs").."/monsters/dirtmonster.lua")

View File

@ -46,6 +46,7 @@ mobs:register_mob("mobs:barbarian1", {
step=0.5,
blood_amount = 35,
blood_offset = 0.25,
activity_level=2,
})
mobs:register_mob("mobs:barbarian2", {
@ -96,4 +97,58 @@ mobs:register_mob("mobs:barbarian2", {
step=0.5,
blood_amount = 35,
blood_offset = 0.25,
activity_level=2,
})
mobs:register_mob("mobs:barbarian_archer", {
type = "barbarian",
hp_min = 10,
hp_max = 45,
exp_min = 10,
exp_max = 65,
collisionbox = {-0.35,-1.0,-0.35, 0.35,0.8,0.35},
visual = "mesh",
mesh = "3d_armor_character.x",
textures = {"mobs_barbarian_archer.png",
"3d_armor_trans.png",
minetest.registered_items["throwing:bow_steel"].inventory_image,
},
visual_size = {x=1, y=1},
makes_footstep_sound = true,
view_range = 25,
walk_velocity = 2,
run_velocity = 4,
damage = 4,
drops = { },
armor = 150,
drawtype = "front",
water_damage = 1,
lava_damage = 5,
light_damage = 0,
on_rightclick = nil,
attack_type = "shoot",
arrow_offset = 1.2,
arrow = "throwing:arrow_entity",
shoot_interval = 2.2,
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 189,
punch_end = 198,
},
jump = true,
sounds = {
death = "mobs_barbarian_death",
},
step=0.5,
blood_amount = 35,
blood_offset = 0.25,
activity_level=2,
})

View File

@ -28,6 +28,7 @@ mobs:register_mob("mobs:dungeon_master", {
on_rightclick = nil,
attack_type = "shoot",
arrow = "mobs:fireball",
arrow_offset = 2,
shoot_interval = 2.5,
sounds = {
attack = "mobs_fireball",
@ -54,6 +55,7 @@ mobs:register_arrow("mobs:fireball", {
textures = {"mobs_fireball.png"},
velocity = 5,
hit_player = function(self, player)
print("hit player")
local s = self.object:getpos()
local p = player:getpos()
local vec = {x=s.x-p.x, y=s.y-p.y, z=s.z-p.z}
@ -78,6 +80,7 @@ mobs:register_arrow("mobs:fireball", {
end
end,
hit_node = function(self, pos, node)
print("hit node")
for dx=-1,1 do
for dy=-2,1 do
for dz=-1,1 do

View File

@ -0,0 +1,195 @@
mobs:register_mob("mobs:blacksmith",{
type = "npc",
hp_min = 30,
hp_max = 75,
exp_min = 0,
exp_max = 0,
collisionbox = {-0.35,-1.0,-0.35, 0.35,0.8,0.35},
visual = "mesh",
mesh = "3d_armor_character.x",
textures = {"mobs_blacksmith.png",
"3d_armor_trans.png",
minetest.registered_items["cottages:hammer"].inventory_image,
},
visual_size = {x=1, y=1},
makes_footstep_sound = true,
view_range = 12,
walk_velocity = 1,
run_velocity = 4.5,
damage = 6,
drops = { },
armor = 150,
drawtype = "front",
water_damage = 1,
lava_damage = 5,
light_damage = 0,
on_rightclick = function (self, clicker)
-- show formspec
if self.state ~= "path" and self.state ~= "working" then
blacksmith_formspec(self,clicker)
else
chat.local_chat(clicker:getpos(),"Blacksmith: Sorry, I'm busy. Come back later",3)
end
end,
walk_chance = 1,
stationary = true,
attack_type = "dogfight",
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 189,
punch_end = 198,
},
jump = false,
sounds = {
war_cry = "mobs_die_yell",
death = "default_death",
attack = "default_punch2",
},
attacks_monsters=false,
peaceful = true,
group_attack = false,
blood_amount = 35,
blood_offset = 0.25,
activity_level = 15,
})
-- list of active blacksmiths... I'm not sure how this is going to work when an entity is unloaded
local active_blacksmiths = {}
function blacksmith_formspec(self,player)
local name = player:get_player_name()
if active_blacksmiths[name] == nil then
mobs:face_pos(self,player:getpos())
chat.local_chat(player:getpos(),"Blacksmith: Give me your metal lumps and I will smelt them for you",3)
active_blacksmiths[name] = {entity=self,inventory=nil,player=player,furnace=nil,active=false}
local formspec = "size[8,6.25]"..
"list[current_player;main;0,2.5;8,4;]"..
"label[3,0.25;Lump]"..
"list[detached:"..name.."_blacksmith;src;3,0.75;1,1;]"..
"button_exit[5,0.25;2,1;smelt;Smelt]"..
"button_exit[5,1;2,1;cancel;Cancel]"
minetest.show_formspec(name,"blacksmith",formspec)
else
chat.local_chat(player:getpos(),"Blacksmith: Sorry, I'm not able to work for you at this time",3)
end
end
function blacksmith_use_furnace(self,player)
local name = player:get_player_name()
local pos = active_blacksmiths[name].furnace
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_stack("src",1,active_blacksmiths[name].inventory)
inv:set_stack("fuel",1,"default:coal_lump 99")
self.state = "working"
self.set_animation(self,"punch")
active_blacksmiths[name].active = true
end
minetest.register_on_player_receive_fields(function(player,formname,fields)
if formname == "blacksmith" then
local name = player:get_player_name()
local blacksmith = active_blacksmiths[name].entity
if blacksmith == nil then
minetest.chat_send_player(name,"An error occured... blacksmith lost")
minetest.log("error","Blacksmith lost")
return
end
if fields.smelt then
-- find a furnace
local inv = minetest.get_inventory({type="detached", name=name.."_blacksmith"})
local stack = inv:get_stack("src",1)
if stack:get_count() == 0 then
chat.local_chat(player:getpos(),"Blacksmith: Please give me something to smelt",3)
return
else
-- see if it's a smeltable item
end
local furnace = minetest.find_node_near(player:getpos(),55,{"default:furnace"})
if furnace ~= nil then
--furnace.y = furnace.y + 1
local node = minetest.get_node(furnace) -- On top of the furnace
local fdir = minetest.facedir_to_dir(node.param2)
local dest = {x=furnace.x,y=furnace.y,z=furnace.z}
dest.x = dest.x + ( fdir.x * -1 )
dest.y = dest.y + ( fdir.y * -1 )
dest.z = dest.z + ( fdir.z * -1 )
local start = blacksmith.object:getpos()
start.y = start.y - 1
-- find a path to the furnace
local path = minetest.find_path(start,dest,5,1,1,"Dijkstra")
if path ~= nil then
-- move the inventory from the detached inventory to the inventory variable
active_blacksmiths[name].inventory = stack
active_blacksmiths[name].furnace = furnace
inv:remove_item("src",stack)
blacksmith.path = path
blacksmith.start_path(blacksmith, function (self)
blacksmith_use_furnace(self,player)
end)
else
chat.local_chat(player:getpos(),"Blacksmith: Sorry, I can't get to the furance.",3)
active_blacksmiths[name] = nil
return
end
else
chat.local_chat(player:getpos(),"Blacksmith: Sorry, I don't see a furance in this area.",3)
active_blacksmiths[name] = nil
-- TODO Get invnetory and throw item toward player
end
else
active_blacksmiths[name] = nil
end
end
end)
-- create detached inventory for blacksmith
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
local binv = minetest.create_detached_inventory(name.."_blacksmith",{})
binv:set_size("src",1)
end)
local bs_timer = 5
minetest.register_globalstep(function(dtime)
bs_timer = bs_timer - dtime
if bs_timer <= 0 then
print("bs timer")
bs_timer = 5
-- loop through the active blacksmiths and check their furnaces
for name,bs in pairs(active_blacksmiths) do
print("Processing "..name.." blacksmith")
if bs.active == true then
bs.entity.set_animation(bs.entity,"punch")
bs.entity.state = "working"
print("furnace not nil")
local meta = minetest.get_meta(bs.furnace)
local inv = meta:get_inventory()
if inv:is_empty("src") then
-- empty the fuel
inv:set_stack("fuel",1,nil)
print("smelting done")
-- they are done smelting
local dlist = inv:get_list("dst")
-- TODO return smelted items to the player
-- blacksmith is done working
bs.entity.state = "standing"
bs.entity.set_animation(bs.entity,"stand")
chat.local_chat(bs.entity.object:getpos(),"Blacksmith: "..name.." your ingots are ready!",25)
active_blacksmiths[name] = nil -- I think it's all byref so bs = nil should also work
end
print("processing done")
end
end
end
end)

View File

@ -24,6 +24,7 @@ mobs:register_mob("mobs:explorer",{
lava_damage = 5,
light_damage = 0,
on_rightclick = function (self, clicker)
mobs:face_pos(self,clicker:getpos())
quests.treasure.tell_story(self.object:getpos())
end,
walk_chance = 1,

View File

@ -24,7 +24,7 @@ mobs:register_mob("mobs:male1_npc",{
lava_damage = 5,
light_damage = 0,
on_rightclick = nil,
walk_chance = 1,
activity_level = 10,
attack_type = "dogfight",
animation = {
speed_normal = 30,
@ -38,7 +38,7 @@ mobs:register_mob("mobs:male1_npc",{
punch_start = 200,
punch_end = 219,
},
jump = false,
jump = true,
sounds = {
war_cry = "mobs_die_yell",
death = "default_death",
@ -83,7 +83,7 @@ mobs:register_mob("mobs:male2_npc",{
lava_damage = 5,
light_damage = 0,
on_rightclick = nil,
walk_chance = 1,
activity_level=10,
attack_type = "dogfight",
animation = {
speed_normal = 30,
@ -97,7 +97,7 @@ mobs:register_mob("mobs:male2_npc",{
punch_start = 200,
punch_end = 219,
},
jump = false,
jump = true,
sounds = {
war_cry = "mobs_die_yell",
death = "default_death",
@ -142,7 +142,7 @@ mobs:register_mob("mobs:male3_npc",{
lava_damage = 5,
light_damage = 0,
on_rightclick = nil,
walk_chance = 1,
activity_level = 10,
attack_type = "dogfight",
animation = {
speed_normal = 30,
@ -156,7 +156,7 @@ mobs:register_mob("mobs:male3_npc",{
punch_start = 200,
punch_end = 219,
},
jump = false,
jump = true,
sounds = {
war_cry = "mobs_die_yell",
death = "default_death",

View File

@ -20,7 +20,7 @@ type = "npc",
drops = { },
armor = 150,
drawtype = "front",
water_damage = 1,
activity_level = 5,
lava_damage = 5,
light_damage = 0,
on_rightclick = nil,
@ -38,7 +38,7 @@ type = "npc",
punch_start = 200,
punch_end = 219,
},
jump = false,
jump = true,
sounds = {
attack = "default_punch",
},
@ -80,7 +80,7 @@ type = "npc",
lava_damage = 5,
light_damage = 0,
on_rightclick = nil,
walk_chance = 1,
activity_level = 5,
attack_type = "dogfight",
animation = {
speed_normal = 30,
@ -94,7 +94,7 @@ type = "npc",
punch_start = 200,
punch_end = 219,
},
jump = false,
jump = true,
sounds = {
attack = "default_punch",
},
@ -136,7 +136,7 @@ type = "npc",
lava_damage = 5,
light_damage = 0,
on_rightclick = nil,
walk_chance = 1,
activity_level = 5,
attack_type = "dogfight",
animation = {
speed_normal = 30,
@ -150,7 +150,7 @@ type = "npc",
punch_start = 200,
punch_end = 219,
},
jump = false,
jump = true,
sounds = {
attack = "default_punch",
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -69,7 +69,7 @@ end
function skills.get_probability(name, skill1, skill2)
--print("get_probablilty("..name..","..tostring(skill1)..","..tostring(skill2)..")")
if ( name == nil ) then
if ( name == nil or name == "" ) then
return 99
end
local s1 = skills.get_skill(name, skill1)

View File

@ -39,6 +39,8 @@ local THROWING_ARROW_ENTITY={
collisionbox = {0,0,0,0,0,0},
player = nil,
max_damage=25,
velocity = 12, --for mobs using this arrow
drop_rate = -2, --for mobs using this arrow - for players this is defined in the bow
}
THROWING_ARROW_ENTITY.on_step = function(self, dtime)