323 lines
8.9 KiB
Lua
323 lines
8.9 KiB
Lua
|
-------------------------------------------------------------------------------
|
||
|
-- Mob Framework Mod by Sapier
|
||
|
--
|
||
|
-- You may copy, use, modify or do nearly anything except removing this
|
||
|
-- copyright notice.
|
||
|
-- And of course you are NOT allow to pretend you have written it.
|
||
|
--
|
||
|
--! @file weapons.lua
|
||
|
--! @brief weapon related functions
|
||
|
--! @copyright Sapier
|
||
|
--! @author Sapier
|
||
|
--! @date 2012-08-09
|
||
|
--
|
||
|
--! @defgroup weapons Weapons
|
||
|
--! @brief weapon entitys predefined by mob framework (can be extended by mod)
|
||
|
--
|
||
|
-- Contact sapier a t gmx net
|
||
|
-------------------------------------------------------------------------------
|
||
|
|
||
|
local weapons_spacer = {} --unused to fix lua doxygen bug only
|
||
|
|
||
|
-------------------------------------------------------------------------------
|
||
|
-- name: mobf_init_weapons = function(self, dtime)
|
||
|
--
|
||
|
--! @brief initialize weapons handled by mobf mod
|
||
|
--
|
||
|
-------------------------------------------------------------------------------
|
||
|
function mobf_init_weapons()
|
||
|
minetest.register_entity(":mobf:fireball_entity", MOBF_FIREBALL_ENTITY)
|
||
|
minetest.register_entity(":mobf:plasmaball_entity", MOBF_PLASMABALL_ENTITY)
|
||
|
end
|
||
|
|
||
|
-------------------------------------------------------------------------------
|
||
|
-- name: mobf_do_area_damage(pos,immune,damage,range)
|
||
|
--
|
||
|
--! @brief damage all objects within a certain range
|
||
|
--
|
||
|
--! @param pos cennter of damage area
|
||
|
--! @param immune object immune to damage
|
||
|
--! @param damage damage to be done
|
||
|
--! @param range range around pos
|
||
|
-------------------------------------------------------------------------------
|
||
|
function mobf_do_area_damage(pos,immune,damage,range)
|
||
|
--damage objects within inner blast radius
|
||
|
objs = minetest.env:get_objects_inside_radius(pos, range)
|
||
|
for k, obj in pairs(objs) do
|
||
|
|
||
|
--don't do damage to issuer
|
||
|
if obj ~= immune then
|
||
|
obj:set_hp(obj:get_hp()-damage)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
-------------------------------------------------------------------------------
|
||
|
-- name: mobf_do_node_damage(pos,immune_list,range,chance)
|
||
|
--
|
||
|
--! @brief damage all nodes within a certain range
|
||
|
--
|
||
|
--! @param pos center of area
|
||
|
--! @param immune_list list of nodes immune to damage
|
||
|
--! @param range range to do damage
|
||
|
--! @param chance chance damage is done to a node
|
||
|
-------------------------------------------------------------------------------
|
||
|
function mobf_do_node_damage(pos,immune_list,range,chance)
|
||
|
--do node damage
|
||
|
for i=pos.x-range, pos.x+range, 1 do
|
||
|
for j=pos.y-range, pos.y+range, 1 do
|
||
|
for k=pos.z-range,pos.z+range,1 do
|
||
|
--TODO create a little bit more sophisticated blast resistance
|
||
|
if math.random() < chance then
|
||
|
local toremove = minetest.env:get_node({x=i,y=j,z=k})
|
||
|
|
||
|
if toremove ~= nil then
|
||
|
local immune = false
|
||
|
|
||
|
if immune_list ~= nil then
|
||
|
for i,v in ipairs(immune_list) do
|
||
|
if (torremove.name == v) then
|
||
|
immune = true
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
if immune ~= true then
|
||
|
minetest.env:remove_node({x=i,y=j,z=k})
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--! @class MOBF_FIREBALL_ENTITY
|
||
|
--! @ingroup weapons
|
||
|
--! @brief a fireball weapon entity
|
||
|
MOBF_FIREBALL_ENTITY = {
|
||
|
physical = false,
|
||
|
textures = {"animals_fireball.png"},
|
||
|
collisionbox = {0,0,0,0,0,0},
|
||
|
|
||
|
damage_range = 4,
|
||
|
velocity = 3,
|
||
|
gravity = -0.01,
|
||
|
|
||
|
damage = 15,
|
||
|
|
||
|
owner = 0,
|
||
|
lifetime = 30,
|
||
|
created = -1,
|
||
|
}
|
||
|
|
||
|
|
||
|
-------------------------------------------------------------------------------
|
||
|
-- name: MOBF_FIREBALL_ENTITY.on_activate = function(self, staticdata)
|
||
|
--
|
||
|
--! @brief onactivate callback for fireball
|
||
|
--! @memberof MOBF_FIREBALL_ENTITY
|
||
|
--! @private
|
||
|
--
|
||
|
--! @param self fireball itself
|
||
|
--! @param staticdata
|
||
|
-------------------------------------------------------------------------------
|
||
|
function MOBF_FIREBALL_ENTITY.on_activate(self,staticdata)
|
||
|
self.created = mobf_get_current_time()
|
||
|
end
|
||
|
|
||
|
-------------------------------------------------------------------------------
|
||
|
-- name: MOBF_FIREBALL_ENTITY.surfacefire = function(self, staticdata)
|
||
|
--
|
||
|
--! @brief place fire on surfaces around pos
|
||
|
--! @memberof MOBF_FIREBALL_ENTITY
|
||
|
--! @private
|
||
|
--
|
||
|
--! @param pos position to place fire around
|
||
|
--! @param range square around pos to set on fire
|
||
|
-------------------------------------------------------------------------------
|
||
|
function MOBF_FIREBALL_ENTITY.surfacefire(pos,range)
|
||
|
--start fire on any surface within inner damage range
|
||
|
for i=pos.x-range/2, pos.x+range/2, 1 do
|
||
|
for j=pos.y-range/2, pos.y+range/2, 1 do
|
||
|
for k=pos.z-range/2, pos.z+range/2, 1 do
|
||
|
|
||
|
local current = minetest.env:get_node({x=i,y=j,z=k})
|
||
|
local ontop = minetest.env:get_node({x=i,y=j+1,z=k})
|
||
|
|
||
|
--print("put fire? " .. printpos({x=i,y=j,z=k}) .. " " .. current.name .. " " ..ontop.name)
|
||
|
|
||
|
if (current.name ~= "air") and
|
||
|
(current.name ~= "fire:basic_flame") and
|
||
|
(ontop.name == "air") then
|
||
|
minetest.env:set_node({x=i,y=j+1,z=k}, {name="fire:basic_flame"})
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-------------------------------------------------------------------------------
|
||
|
-- name: MOBF_FIREBALL_ENTITY.on_step = function(self, dtime)
|
||
|
--
|
||
|
--! @brief onstep callback for fireball
|
||
|
--! @memberof MOBF_FIREBALL_ENTITY
|
||
|
--! @private
|
||
|
--
|
||
|
--! @param self fireball itself
|
||
|
--! @param dtime time since last callback
|
||
|
-------------------------------------------------------------------------------
|
||
|
function MOBF_FIREBALL_ENTITY.on_step(self, dtime)
|
||
|
local pos = self.object:getpos()
|
||
|
local node = minetest.env:get_node(pos)
|
||
|
|
||
|
|
||
|
--detect hit
|
||
|
local objs=minetest.env:get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 1)
|
||
|
|
||
|
local hit = false
|
||
|
|
||
|
for k, obj in pairs(objs) do
|
||
|
if obj:get_entity_name() ~= "mobf:fireball_entity" and
|
||
|
obj ~= self.owner then
|
||
|
hit=true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
if hit then
|
||
|
--damage objects within inner blast radius
|
||
|
mobf_do_area_damage(pos,self.owner,self.damage_range/4,self.damage/4)
|
||
|
|
||
|
--damage all objects within blast radius
|
||
|
mobf_do_area_damage(pos,self.owner,self.damage_range/2,self.damage/2)
|
||
|
|
||
|
MOBF_FIREBALL_ENTITY.surfacefire(pos,self.damage_range)
|
||
|
|
||
|
self.object:remove()
|
||
|
end
|
||
|
|
||
|
-- vanish when hitting a node
|
||
|
if node.name ~= "air" then
|
||
|
MOBF_FIREBALL_ENTITY.surfacefire(pos,self.damage_range)
|
||
|
self.object:remove()
|
||
|
end
|
||
|
|
||
|
--remove after lifetime has passed
|
||
|
if self.created > 0 and
|
||
|
self.created + self.lifetime < mobf_get_current_time() then
|
||
|
self.object:remove()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
--! @class MOBF_PLASMABALL_ENTITY
|
||
|
--! @ingroup weapons
|
||
|
--! @brief a plasmaball weapon entity
|
||
|
MOBF_PLASMABALL_ENTITY = {
|
||
|
physical = false,
|
||
|
textures = {"animals_plasmaball.png"},
|
||
|
lastpos={},
|
||
|
collisionbox = {0,0,0,0,0,0},
|
||
|
|
||
|
damage_range = 2,
|
||
|
velocity = 4,
|
||
|
gravity = -0.001,
|
||
|
|
||
|
damage = 8,
|
||
|
|
||
|
owner = 0,
|
||
|
lifetime = 30,
|
||
|
created = -1,
|
||
|
}
|
||
|
|
||
|
-------------------------------------------------------------------------------
|
||
|
-- name: MOBF_PLASMABALL_ENTITY.on_activate = function(self, staticdata)
|
||
|
--
|
||
|
--! @brief onactivate callback for plasmaball
|
||
|
--! @memberof MOBF_PLASMABALL_ENTITY
|
||
|
--! @private
|
||
|
--
|
||
|
--! @param self fireball itself
|
||
|
--! @param staticdata
|
||
|
-------------------------------------------------------------------------------
|
||
|
function MOBF_PLASMABALL_ENTITY.on_activate(self,staticdata)
|
||
|
self.created = mobf_get_current_time()
|
||
|
end
|
||
|
|
||
|
|
||
|
-------------------------------------------------------------------------------
|
||
|
-- name: MOBF_PLASMABALL_ENTITY.on_step = function(self, dtime)
|
||
|
--
|
||
|
--! @brief onstep callback for plasmaball
|
||
|
--! @memberof MOBF_PLASMABALL_ENTITY
|
||
|
--! @private
|
||
|
--
|
||
|
--! @param self plasmaball itself
|
||
|
--! @param dtime time since last callback
|
||
|
-------------------------------------------------------------------------------
|
||
|
function MOBF_PLASMABALL_ENTITY.on_step(self, dtime)
|
||
|
local pos = self.object:getpos()
|
||
|
local node = minetest.env:get_node(pos)
|
||
|
|
||
|
|
||
|
--detect hit
|
||
|
local objs=minetest.env:get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 1)
|
||
|
|
||
|
local hit = false
|
||
|
|
||
|
for k, obj in pairs(objs) do
|
||
|
if obj:get_entity_name() ~= "mobf:plasmaball_entity" and
|
||
|
obj ~= self.owner then
|
||
|
hit=true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--damage all objects not hit but at least passed
|
||
|
mobf_do_area_damage(pos,self.owner,2,1)
|
||
|
|
||
|
if hit then
|
||
|
--damage objects within inner blast radius
|
||
|
mobf_do_area_damage(pos,self.owner,self.damage_range/4,self.damage/2)
|
||
|
|
||
|
--damage all objects within blast radius
|
||
|
mobf_do_area_damage(pos,self.owner,self.damage_range/2,self.damage/2)
|
||
|
end
|
||
|
|
||
|
-- vanish when hitting a node
|
||
|
if node.name ~= "air" or
|
||
|
hit then
|
||
|
|
||
|
--replace this loop by minetest.env:find_node_near?
|
||
|
--do node damage
|
||
|
for i=pos.x-1, pos.x+1, 1 do
|
||
|
for j=pos.y-1, pos.y+1, 1 do
|
||
|
for k=pos.z-1,pos.z+1,1 do
|
||
|
--TODO create a little bit more sophisticated blast resistance
|
||
|
if math.random() < 0.5 then
|
||
|
local toremove = minetest.env:get_node({x=i,y=j,z=k})
|
||
|
|
||
|
if toremove ~= nil and
|
||
|
toremove.name ~= "default:stone" and
|
||
|
toremove.name ~= "default:cobble" then
|
||
|
|
||
|
minetest.env:remove_node({x=i,y=j,z=k})
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
self.object:remove()
|
||
|
end
|
||
|
|
||
|
--remove after lifetime has passed
|
||
|
if self.created > 0 and
|
||
|
self.created + self.lifetime < mobf_get_current_time() then
|
||
|
self.object:remove()
|
||
|
end
|
||
|
end
|