Improve bow/arrow physics
This commit is contained in:
commit
be4639044e
257
api.lua
257
api.lua
|
@ -236,6 +236,7 @@ function XBows.register_bow(self, name, def, override)
|
||||||
wield_image = def.custom.wield_image_charged or def.custom.inventory_image_charged,
|
wield_image = def.custom.wield_image_charged or def.custom.inventory_image_charged,
|
||||||
groups = def.custom.groups_charged,
|
groups = def.custom.groups_charged,
|
||||||
wield_scale = {x = 2, y = 2, z = 1.5},
|
wield_scale = {x = 2, y = 2, z = 1.5},
|
||||||
|
range = 0,
|
||||||
---@param itemstack ItemStack
|
---@param itemstack ItemStack
|
||||||
---@param user ObjectRef|nil
|
---@param user ObjectRef|nil
|
||||||
---@param pointed_thing PointedThingDef
|
---@param pointed_thing PointedThingDef
|
||||||
|
@ -605,6 +606,7 @@ function XBows.shoot(self, itemstack, user, pointed_thing)
|
||||||
user:get_player_name()
|
user:get_player_name()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
---Handle HUD and 3d Quiver
|
||||||
if is_arrow_from_quiver == 1 then
|
if is_arrow_from_quiver == 1 then
|
||||||
XBowsQuiver:udate_or_create_hud(user, detached_inv:get_list('main'), found_arrow_stack_idx)
|
XBowsQuiver:udate_or_create_hud(user, detached_inv:get_list('main'), found_arrow_stack_idx)
|
||||||
|
|
||||||
|
@ -618,7 +620,7 @@ function XBows.shoot(self, itemstack, user, pointed_thing)
|
||||||
if not inv:is_empty('x_bows:arrow_inv') then
|
if not inv:is_empty('x_bows:arrow_inv') then
|
||||||
XBowsQuiver:udate_or_create_hud(user, inv:get_list('x_bows:arrow_inv'))
|
XBowsQuiver:udate_or_create_hud(user, inv:get_list('x_bows:arrow_inv'))
|
||||||
else
|
else
|
||||||
---no ammo (fake stack)
|
---no ammo (fake stack just for the HUD)
|
||||||
XBowsQuiver:udate_or_create_hud(user, {ItemStack({
|
XBowsQuiver:udate_or_create_hud(user, {ItemStack({
|
||||||
name = 'x_bows:no_ammo'
|
name = 'x_bows:no_ammo'
|
||||||
})})
|
})})
|
||||||
|
@ -637,16 +639,6 @@ function XBows.shoot(self, itemstack, user, pointed_thing)
|
||||||
local bow_name = x_bows_registered_bow_charged_def.custom.name
|
local bow_name = x_bows_registered_bow_charged_def.custom.name
|
||||||
local uses = x_bows_registered_bow_charged_def.custom.uses
|
local uses = x_bows_registered_bow_charged_def.custom.uses
|
||||||
local crit_chance = x_bows_registered_bow_charged_def.custom.crit_chance
|
local crit_chance = x_bows_registered_bow_charged_def.custom.crit_chance
|
||||||
local bow_strength = x_bows_registered_bow_charged_def.custom.strength
|
|
||||||
local bow_strength_min = x_bows_registered_bow_charged_def.custom.strength_min
|
|
||||||
local bow_strength_max = x_bows_registered_bow_charged_def.custom.strength_max
|
|
||||||
local acc_x_min = x_bows_registered_bow_charged_def.custom.acc_x_min
|
|
||||||
local acc_y_min = x_bows_registered_bow_charged_def.custom.acc_y_min
|
|
||||||
local acc_z_min = x_bows_registered_bow_charged_def.custom.acc_z_min
|
|
||||||
local acc_x_max = x_bows_registered_bow_charged_def.custom.acc_x_max
|
|
||||||
local acc_y_max = x_bows_registered_bow_charged_def.custom.acc_y_max
|
|
||||||
local acc_z_max = x_bows_registered_bow_charged_def.custom.acc_z_max
|
|
||||||
local gravity = x_bows_registered_bow_charged_def.custom.gravity
|
|
||||||
---Arrow
|
---Arrow
|
||||||
local projectile_entity = x_bows_registered_arrow_def.custom.projectile_entity
|
local projectile_entity = x_bows_registered_arrow_def.custom.projectile_entity
|
||||||
---Quiver
|
---Quiver
|
||||||
|
@ -655,11 +647,12 @@ function XBows.shoot(self, itemstack, user, pointed_thing)
|
||||||
local _tool_capabilities = x_bows_registered_arrow_def.custom.tool_capabilities
|
local _tool_capabilities = x_bows_registered_arrow_def.custom.tool_capabilities
|
||||||
local quiver_xbows_def = x_bows_registered_quiver_def
|
local quiver_xbows_def = x_bows_registered_quiver_def
|
||||||
|
|
||||||
|
---@type EnityStaticDataAttrDef
|
||||||
local staticdata = {
|
local staticdata = {
|
||||||
_arrow_name = arrow_name,
|
_arrow_name = arrow_name,
|
||||||
_bow_name = bow_name,
|
_bow_name = bow_name,
|
||||||
user_name = user:get_player_name(),
|
_user_name = user:get_player_name(),
|
||||||
is_critical_hit = false,
|
_is_critical_hit = false,
|
||||||
_tool_capabilities = _tool_capabilities,
|
_tool_capabilities = _tool_capabilities,
|
||||||
_tflp = tflp,
|
_tflp = tflp,
|
||||||
_add_damage = 0
|
_add_damage = 0
|
||||||
|
@ -668,13 +661,13 @@ function XBows.shoot(self, itemstack, user, pointed_thing)
|
||||||
---crits, only on full punch interval
|
---crits, only on full punch interval
|
||||||
if crit_chance and crit_chance > 1 and tflp >= _tool_capabilities.full_punch_interval then
|
if crit_chance and crit_chance > 1 and tflp >= _tool_capabilities.full_punch_interval then
|
||||||
if math.random(1, crit_chance) == 1 then
|
if math.random(1, crit_chance) == 1 then
|
||||||
staticdata.is_critical_hit = true
|
staticdata._is_critical_hit = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---speed multiply
|
---speed multiply
|
||||||
if quiver_xbows_def and quiver_xbows_def.custom.faster_arrows and quiver_xbows_def.custom.faster_arrows > 1 then
|
if quiver_xbows_def and quiver_xbows_def.custom.faster_arrows and quiver_xbows_def.custom.faster_arrows > 1 then
|
||||||
staticdata.faster_arrows_multiplier = quiver_xbows_def.custom.faster_arrows
|
staticdata._faster_arrows_multiplier = quiver_xbows_def.custom.faster_arrows
|
||||||
end
|
end
|
||||||
|
|
||||||
---add quiver damage
|
---add quiver damage
|
||||||
|
@ -684,20 +677,23 @@ function XBows.shoot(self, itemstack, user, pointed_thing)
|
||||||
|
|
||||||
---sound
|
---sound
|
||||||
local sound_name = x_bows_registered_bow_charged_def.custom.sound_shoot
|
local sound_name = x_bows_registered_bow_charged_def.custom.sound_shoot
|
||||||
if staticdata.is_critical_hit then
|
if staticdata._is_critical_hit then
|
||||||
sound_name = x_bows_registered_bow_charged_def.custom.sound_shoot_crit
|
sound_name = x_bows_registered_bow_charged_def.custom.sound_shoot_crit
|
||||||
end
|
end
|
||||||
|
|
||||||
meta:set_string('arrow_itemstack_string', '')
|
---stop punching close objects/nodes when shooting
|
||||||
itemstack:set_name(bow_name)
|
minetest.after(0.2, function()
|
||||||
|
if user:get_wielded_item():get_name() == itemstack:get_name() then
|
||||||
|
user:set_wielded_item(ItemStack({name = bow_name, wear = itemstack:get_wear()}))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
local pos = user:get_pos()
|
local player_pos = user:get_pos()
|
||||||
local dir = user:get_look_dir()
|
|
||||||
local obj = minetest.add_entity(
|
local obj = minetest.add_entity(
|
||||||
{
|
{
|
||||||
x = pos.x,
|
x = player_pos.x,
|
||||||
y = pos.y + 1.5,
|
y = player_pos.y + 1.5,
|
||||||
z = pos.z
|
z = player_pos.z
|
||||||
},
|
},
|
||||||
projectile_entity,
|
projectile_entity,
|
||||||
minetest.serialize(staticdata)
|
minetest.serialize(staticdata)
|
||||||
|
@ -707,44 +703,6 @@ function XBows.shoot(self, itemstack, user, pointed_thing)
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
local strength_multiplier = tflp
|
|
||||||
|
|
||||||
if strength_multiplier > _tool_capabilities.full_punch_interval then
|
|
||||||
strength_multiplier = 1
|
|
||||||
|
|
||||||
---faster arrow, only on full punch interval
|
|
||||||
if staticdata.faster_arrows_multiplier then
|
|
||||||
strength_multiplier = strength_multiplier + (strength_multiplier / staticdata.faster_arrows_multiplier)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if bow_strength_max and bow_strength_min then
|
|
||||||
bow_strength = math.random(bow_strength_min, bow_strength_max)
|
|
||||||
end
|
|
||||||
|
|
||||||
---acceleration
|
|
||||||
local acc_x = dir.x
|
|
||||||
local acc_y = gravity
|
|
||||||
local acc_z = dir.z
|
|
||||||
|
|
||||||
if acc_x_min and acc_x_max then
|
|
||||||
acc_x = math.random(acc_x_min, acc_x_max)
|
|
||||||
end
|
|
||||||
|
|
||||||
if acc_y_min and acc_y_max then
|
|
||||||
acc_y = math.random(acc_y_min, acc_y_max)
|
|
||||||
end
|
|
||||||
|
|
||||||
if acc_z_min and acc_z_max then
|
|
||||||
acc_z = math.random(acc_z_min, acc_z_max)
|
|
||||||
end
|
|
||||||
|
|
||||||
local strength = bow_strength * strength_multiplier
|
|
||||||
|
|
||||||
obj:set_velocity(vector.multiply(dir, strength))
|
|
||||||
obj:set_acceleration({x = acc_x, y = acc_y, z = acc_z})
|
|
||||||
obj:set_yaw(minetest.dir_to_yaw(dir))
|
|
||||||
|
|
||||||
if not self:is_creative(user:get_player_name()) then
|
if not self:is_creative(user:get_player_name()) then
|
||||||
itemstack:add_wear(65535 / uses)
|
itemstack:add_wear(65535 / uses)
|
||||||
end
|
end
|
||||||
|
@ -843,24 +801,9 @@ local function limit(x, min, max)
|
||||||
return math.min(math.max(x, min), max)
|
return math.min(math.max(x, min), max)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Gets collision box
|
|
||||||
---@param obj ObjectRef
|
|
||||||
---@return number[]
|
|
||||||
local function get_obj_box(obj)
|
|
||||||
local box
|
|
||||||
|
|
||||||
if obj:is_player() then
|
|
||||||
box = obj:get_properties().collisionbox or {-0.5, 0.0, -0.5, 0.5, 1.0, 0.5}
|
|
||||||
else
|
|
||||||
box = obj:get_luaentity().collisionbox or {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
|
|
||||||
end
|
|
||||||
|
|
||||||
return box
|
|
||||||
end
|
|
||||||
|
|
||||||
---Function receive a "luaentity" table as `self`. Called when the object is instantiated.
|
---Function receive a "luaentity" table as `self`. Called when the object is instantiated.
|
||||||
---@param self EntityDef|EntityDefCustom|XBows
|
---@param self EntityDef|EntityDefCustom|XBows
|
||||||
---@param selfObj table
|
---@param selfObj EnityCustomAttrDef
|
||||||
---@param staticdata string
|
---@param staticdata string
|
||||||
---@param dtime_s? integer|number
|
---@param dtime_s? integer|number
|
||||||
---@return nil
|
---@return nil
|
||||||
|
@ -870,7 +813,7 @@ function XBowsEntityDef.on_activate(self, selfObj, staticdata, dtime_s)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local _staticdata = minetest.deserialize(staticdata)
|
local _staticdata = minetest.deserialize(staticdata)--[[@as EnityStaticDataAttrDef]]
|
||||||
|
|
||||||
-- set/reset - do not inherit from previous entity table
|
-- set/reset - do not inherit from previous entity table
|
||||||
selfObj._velocity = {x = 0, y = 0, z = 0}
|
selfObj._velocity = {x = 0, y = 0, z = 0}
|
||||||
|
@ -888,12 +831,12 @@ function XBowsEntityDef.on_activate(self, selfObj, staticdata, dtime_s)
|
||||||
selfObj._shot_from_pos = selfObj.object:get_pos()
|
selfObj._shot_from_pos = selfObj.object:get_pos()
|
||||||
selfObj._arrow_name = _staticdata._arrow_name
|
selfObj._arrow_name = _staticdata._arrow_name
|
||||||
selfObj._bow_name = _staticdata._bow_name
|
selfObj._bow_name = _staticdata._bow_name
|
||||||
selfObj._user_name = _staticdata.user_name
|
selfObj._user_name = _staticdata._user_name
|
||||||
selfObj.user = minetest.get_player_by_name(_staticdata.user_name)
|
selfObj._user = minetest.get_player_by_name(_staticdata._user_name)
|
||||||
selfObj._tflp = _staticdata._tflp
|
selfObj._tflp = _staticdata._tflp
|
||||||
selfObj._tool_capabilities = _staticdata._tool_capabilities
|
selfObj._tool_capabilities = _staticdata._tool_capabilities
|
||||||
selfObj._is_critical_hit = _staticdata.is_critical_hit
|
selfObj._is_critical_hit = _staticdata._is_critical_hit
|
||||||
selfObj._faster_arrows_multiplier = _staticdata.faster_arrows_multiplier
|
selfObj._faster_arrows_multiplier = _staticdata._faster_arrows_multiplier
|
||||||
selfObj._add_damage = _staticdata._add_damage
|
selfObj._add_damage = _staticdata._add_damage
|
||||||
selfObj._caused_damage = 0
|
selfObj._caused_damage = 0
|
||||||
selfObj._caused_knockback = 0
|
selfObj._caused_knockback = 0
|
||||||
|
@ -903,9 +846,58 @@ function XBowsEntityDef.on_activate(self, selfObj, staticdata, dtime_s)
|
||||||
selfObj._arrow_particle_effect_crit = x_bows_registered_arrow_def.custom.particle_effect_crit
|
selfObj._arrow_particle_effect_crit = x_bows_registered_arrow_def.custom.particle_effect_crit
|
||||||
selfObj._arrow_particle_effect_fast = x_bows_registered_arrow_def.custom.particle_effect_fast
|
selfObj._arrow_particle_effect_fast = x_bows_registered_arrow_def.custom.particle_effect_fast
|
||||||
|
|
||||||
|
---Bow Def
|
||||||
local x_bows_registered_bow_def = self.registered_bows[selfObj._bow_name]
|
local x_bows_registered_bow_def = self.registered_bows[selfObj._bow_name]
|
||||||
selfObj._sound_hit = x_bows_registered_bow_def.custom.sound_hit
|
selfObj._sound_hit = x_bows_registered_bow_def.custom.sound_hit
|
||||||
|
local bow_strength = x_bows_registered_bow_def.custom.strength
|
||||||
|
local acc_x_min = x_bows_registered_bow_def.custom.acc_x_min
|
||||||
|
local acc_y_min = x_bows_registered_bow_def.custom.acc_y_min
|
||||||
|
local acc_z_min = x_bows_registered_bow_def.custom.acc_z_min
|
||||||
|
local acc_x_max = x_bows_registered_bow_def.custom.acc_x_max
|
||||||
|
local acc_y_max = x_bows_registered_bow_def.custom.acc_y_max
|
||||||
|
local acc_z_max = x_bows_registered_bow_def.custom.acc_z_max
|
||||||
|
local gravity = x_bows_registered_bow_def.custom.gravity
|
||||||
|
local bow_strength_min = x_bows_registered_bow_def.custom.strength_min
|
||||||
|
local bow_strength_max = x_bows_registered_bow_def.custom.strength_max
|
||||||
|
|
||||||
|
---acceleration
|
||||||
|
selfObj._player_look_dir = selfObj._user:get_look_dir()
|
||||||
|
|
||||||
|
selfObj._acc_x = selfObj._player_look_dir.x
|
||||||
|
selfObj._acc_y = gravity
|
||||||
|
selfObj._acc_z = selfObj._player_look_dir.z
|
||||||
|
|
||||||
|
if acc_x_min and acc_x_max then
|
||||||
|
selfObj._acc_x = math.random(acc_x_min, acc_x_max)
|
||||||
|
end
|
||||||
|
|
||||||
|
if acc_y_min and acc_y_max then
|
||||||
|
selfObj._acc_y = math.random(acc_y_min, acc_y_max)
|
||||||
|
end
|
||||||
|
|
||||||
|
if acc_z_min and acc_z_max then
|
||||||
|
selfObj._acc_z = math.random(acc_z_min, acc_z_max)
|
||||||
|
end
|
||||||
|
|
||||||
|
---strength
|
||||||
|
local strength_multiplier = selfObj._tflp
|
||||||
|
|
||||||
|
if strength_multiplier > selfObj._tool_capabilities.full_punch_interval then
|
||||||
|
strength_multiplier = 1
|
||||||
|
|
||||||
|
---faster arrow, only on full punch interval
|
||||||
|
if selfObj._faster_arrows_multiplier then
|
||||||
|
strength_multiplier = strength_multiplier + (strength_multiplier / selfObj._faster_arrows_multiplier)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if bow_strength_max and bow_strength_min then
|
||||||
|
bow_strength = math.random(bow_strength_min, bow_strength_max)
|
||||||
|
end
|
||||||
|
|
||||||
|
selfObj._strength = bow_strength * strength_multiplier
|
||||||
|
|
||||||
|
---rotation factor
|
||||||
local x_bows_registered_entity_def = self.registered_entities[selfObj.name]
|
local x_bows_registered_entity_def = self.registered_entities[selfObj.name]
|
||||||
selfObj._rotation_factor = x_bows_registered_entity_def._custom.rotation_factor
|
selfObj._rotation_factor = x_bows_registered_entity_def._custom.rotation_factor
|
||||||
|
|
||||||
|
@ -913,15 +905,19 @@ function XBowsEntityDef.on_activate(self, selfObj, staticdata, dtime_s)
|
||||||
selfObj._rotation_factor = selfObj._rotation_factor()
|
selfObj._rotation_factor = selfObj._rotation_factor()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---add infotext
|
||||||
selfObj.object:set_properties({
|
selfObj.object:set_properties({
|
||||||
infotext = selfObj._arrow_name,
|
infotext = selfObj._arrow_name,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
---idle animation
|
||||||
if x_bows_registered_entity_def and x_bows_registered_entity_def._custom.animations.idle then
|
if x_bows_registered_entity_def and x_bows_registered_entity_def._custom.animations.idle then
|
||||||
selfObj.object:set_animation(unpack(x_bows_registered_entity_def._custom.animations.idle))
|
selfObj.object:set_animation(unpack(x_bows_registered_entity_def._custom.animations.idle))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---counter, e.g. for initial values set `on_step`
|
||||||
|
selfObj._step_count = 0
|
||||||
|
|
||||||
---Callbacks
|
---Callbacks
|
||||||
local on_after_activate_callback = x_bows_registered_arrow_def.custom.on_after_activate
|
local on_after_activate_callback = x_bows_registered_arrow_def.custom.on_after_activate
|
||||||
|
|
||||||
|
@ -932,7 +928,7 @@ end
|
||||||
|
|
||||||
---Function receive a "luaentity" table as `self`. Called when the object dies.
|
---Function receive a "luaentity" table as `self`. Called when the object dies.
|
||||||
---@param self XBows
|
---@param self XBows
|
||||||
---@param selfObj table
|
---@param selfObj EnityCustomAttrDef
|
||||||
---@param killer ObjectRef|nil
|
---@param killer ObjectRef|nil
|
||||||
---@return nil
|
---@return nil
|
||||||
function XBowsEntityDef.on_death(self, selfObj, killer)
|
function XBowsEntityDef.on_death(self, selfObj, killer)
|
||||||
|
@ -946,10 +942,20 @@ end
|
||||||
|
|
||||||
--- Function receive a "luaentity" table as `self`. Called on every server tick, after movement and collision processing. `dtime`: elapsed time since last call. `moveresult`: table with collision info (only available if physical=true).
|
--- Function receive a "luaentity" table as `self`. Called on every server tick, after movement and collision processing. `dtime`: elapsed time since last call. `moveresult`: table with collision info (only available if physical=true).
|
||||||
---@param self XBows
|
---@param self XBows
|
||||||
---@param selfObj table
|
---@param selfObj EnityCustomAttrDef
|
||||||
---@param dtime number
|
---@param dtime number
|
||||||
---@return nil
|
---@return nil
|
||||||
function XBowsEntityDef.on_step(self, selfObj, dtime)
|
function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
|
selfObj._step_count = selfObj._step_count + 1
|
||||||
|
|
||||||
|
if selfObj._step_count == 1 then
|
||||||
|
---initialize
|
||||||
|
---this has to be done here for raycast to kick-in asap
|
||||||
|
selfObj.object:set_velocity(vector.multiply(selfObj._player_look_dir, selfObj._strength))
|
||||||
|
selfObj.object:set_acceleration({x = selfObj._acc_x, y = selfObj._acc_y, z = selfObj._acc_z})
|
||||||
|
selfObj.object:set_yaw(minetest.dir_to_yaw(selfObj._player_look_dir))
|
||||||
|
end
|
||||||
|
|
||||||
local pos = selfObj.object:get_pos()
|
local pos = selfObj.object:get_pos()
|
||||||
selfObj._old_pos = selfObj._old_pos or pos
|
selfObj._old_pos = selfObj._old_pos or pos
|
||||||
local ray = minetest.raycast(selfObj._old_pos, pos, true, true)
|
local ray = minetest.raycast(selfObj._old_pos, pos, true, true)
|
||||||
|
@ -1029,7 +1035,7 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
and pointed_thing.ref ~= selfObj.object
|
and pointed_thing.ref ~= selfObj.object
|
||||||
and pointed_thing.ref:get_hp() > 0
|
and pointed_thing.ref:get_hp() > 0
|
||||||
and (
|
and (
|
||||||
(pointed_thing.ref:is_player() and pointed_thing.ref:get_player_name() ~= selfObj.user:get_player_name())
|
(pointed_thing.ref:is_player() and pointed_thing.ref:get_player_name() ~= selfObj._user:get_player_name())
|
||||||
or (
|
or (
|
||||||
pointed_thing.ref:get_luaentity()
|
pointed_thing.ref:get_luaentity()
|
||||||
and pointed_thing.ref:get_luaentity().physical
|
and pointed_thing.ref:get_luaentity().physical
|
||||||
|
@ -1041,25 +1047,16 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
then
|
then
|
||||||
if pointed_thing.ref:is_player() then
|
if pointed_thing.ref:is_player() then
|
||||||
minetest.sound_play('x_bows_arrow_successful_hit', {
|
minetest.sound_play('x_bows_arrow_successful_hit', {
|
||||||
to_player = selfObj.user:get_player_name(),
|
to_player = selfObj._user:get_player_name(),
|
||||||
gain = 0.3
|
gain = 0.3
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
minetest.sound_play(selfObj._sound_hit, {
|
minetest.sound_play(selfObj._sound_hit, {
|
||||||
to_player = selfObj.user:get_player_name(),
|
to_player = selfObj._user:get_player_name(),
|
||||||
gain = 0.6
|
gain = 0.6
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- store these here before punching in case pointed_thing.ref dies
|
|
||||||
local collisionbox = get_obj_box(pointed_thing.ref)
|
|
||||||
local xmin = collisionbox[1] * 100
|
|
||||||
local ymin = collisionbox[2] * 100
|
|
||||||
local zmin = collisionbox[3] * 100
|
|
||||||
local xmax = collisionbox[4] * 100
|
|
||||||
local ymax = collisionbox[5] * 100
|
|
||||||
local zmax = collisionbox[6] * 100
|
|
||||||
|
|
||||||
selfObj.object:set_velocity({x = 0, y = 0, z = 0})
|
selfObj.object:set_velocity({x = 0, y = 0, z = 0})
|
||||||
selfObj.object:set_acceleration({x = 0, y = 0, z = 0})
|
selfObj.object:set_acceleration({x = 0, y = 0, z = 0})
|
||||||
|
|
||||||
|
@ -1136,7 +1133,6 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
|
|
||||||
-- attach arrow prepare
|
-- attach arrow prepare
|
||||||
local rotation = {x = 0, y = 0, z = 0}
|
local rotation = {x = 0, y = 0, z = 0}
|
||||||
local position = {x = 0, y = 0, z = 0}
|
|
||||||
|
|
||||||
if in_pos.x == 1 then
|
if in_pos.x == 1 then
|
||||||
-- x = 0
|
-- x = 0
|
||||||
|
@ -1145,10 +1141,6 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
rotation.x = math.random(-10, 10)
|
rotation.x = math.random(-10, 10)
|
||||||
rotation.y = math.random(-100, -80)
|
rotation.y = math.random(-100, -80)
|
||||||
rotation.z = math.random(-10, 10)
|
rotation.z = math.random(-10, 10)
|
||||||
|
|
||||||
position.x = xmax / 10
|
|
||||||
position.y = math.random(ymin, ymax) / 10
|
|
||||||
position.z = math.random(zmin, zmax) / 10
|
|
||||||
elseif in_pos.x == -1 then
|
elseif in_pos.x == -1 then
|
||||||
-- x = 0
|
-- x = 0
|
||||||
-- y = 90
|
-- y = 90
|
||||||
|
@ -1156,10 +1148,6 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
rotation.x = math.random(-10, 10)
|
rotation.x = math.random(-10, 10)
|
||||||
rotation.y = math.random(80, 100)
|
rotation.y = math.random(80, 100)
|
||||||
rotation.z = math.random(-10, 10)
|
rotation.z = math.random(-10, 10)
|
||||||
|
|
||||||
position.x = xmin / 10
|
|
||||||
position.y = math.random(ymin, ymax) / 10
|
|
||||||
position.z = math.random(zmin, zmax) / 10
|
|
||||||
elseif in_pos.y == 1 then
|
elseif in_pos.y == 1 then
|
||||||
-- x = -90
|
-- x = -90
|
||||||
-- y = 0
|
-- y = 0
|
||||||
|
@ -1167,10 +1155,6 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
rotation.x = math.random(-100, -80)
|
rotation.x = math.random(-100, -80)
|
||||||
rotation.y = math.random(-10, 10)
|
rotation.y = math.random(-10, 10)
|
||||||
rotation.z = math.random(-190, -170)
|
rotation.z = math.random(-190, -170)
|
||||||
|
|
||||||
position.x = math.random(xmin, xmax) / 10
|
|
||||||
position.y = ymax / 10
|
|
||||||
position.z = math.random(zmin, zmax) / 10
|
|
||||||
elseif in_pos.y == -1 then
|
elseif in_pos.y == -1 then
|
||||||
-- x = 90
|
-- x = 90
|
||||||
-- y = 0
|
-- y = 0
|
||||||
|
@ -1178,10 +1162,6 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
rotation.x = math.random(80, 100)
|
rotation.x = math.random(80, 100)
|
||||||
rotation.y = math.random(-10, 10)
|
rotation.y = math.random(-10, 10)
|
||||||
rotation.z = math.random(170, 190)
|
rotation.z = math.random(170, 190)
|
||||||
|
|
||||||
position.x = math.random(xmin, xmax) / 10
|
|
||||||
position.y = ymin / 10
|
|
||||||
position.z = math.random(zmin, zmax) / 10
|
|
||||||
elseif in_pos.z == 1 then
|
elseif in_pos.z == 1 then
|
||||||
-- x = 180
|
-- x = 180
|
||||||
-- y = 0
|
-- y = 0
|
||||||
|
@ -1189,10 +1169,6 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
rotation.x = math.random(170, 190)
|
rotation.x = math.random(170, 190)
|
||||||
rotation.y = math.random(-10, 10)
|
rotation.y = math.random(-10, 10)
|
||||||
rotation.z = math.random(170, 190)
|
rotation.z = math.random(170, 190)
|
||||||
|
|
||||||
position.x = math.random(xmin, xmax) / 10
|
|
||||||
position.y = math.random(ymin, ymax) / 10
|
|
||||||
position.z = zmax / 10
|
|
||||||
elseif in_pos.z == -1 then
|
elseif in_pos.z == -1 then
|
||||||
-- x = -180
|
-- x = -180
|
||||||
-- y = 180
|
-- y = 180
|
||||||
|
@ -1200,10 +1176,6 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
rotation.x = math.random(-190, -170)
|
rotation.x = math.random(-190, -170)
|
||||||
rotation.y = math.random(170, 190)
|
rotation.y = math.random(170, 190)
|
||||||
rotation.z = math.random(-190, -170)
|
rotation.z = math.random(-190, -170)
|
||||||
|
|
||||||
position.x = math.random(xmin, xmax) / 10
|
|
||||||
position.y = math.random(ymin, ymax) / 10
|
|
||||||
position.z = zmin / 10
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if not XBows.settings.x_bows_attach_arrows_to_entities and not pointed_thing.ref:is_player() then
|
if not XBows.settings.x_bows_attach_arrows_to_entities and not pointed_thing.ref:is_player() then
|
||||||
|
@ -1211,7 +1183,26 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---normalize arrow scale when attached to scaled entity (prevents huge arrows when attached to scaled up entity models)
|
||||||
|
local obj_props = selfObj.object:get_properties()
|
||||||
|
local obj_to_props = pointed_thing.ref:get_properties()
|
||||||
|
local vs = vector.divide(obj_props.visual_size, obj_to_props.visual_size)
|
||||||
|
|
||||||
|
selfObj.object:set_properties({visual_size = vs})
|
||||||
|
|
||||||
-- attach arrow
|
-- attach arrow
|
||||||
|
local position = vector.subtract(
|
||||||
|
ip_pos,
|
||||||
|
pointed_thing.ref:get_pos()
|
||||||
|
)
|
||||||
|
|
||||||
|
if pointed_thing.ref:is_player() then
|
||||||
|
position = vector.multiply(position, 10)
|
||||||
|
end
|
||||||
|
|
||||||
|
---`after` here prevents visual glitch when the arrow still shows as huge for a split second
|
||||||
|
---before the new calculated scale is applied
|
||||||
|
minetest.after(0, function()
|
||||||
selfObj.object:set_attach(
|
selfObj.object:set_attach(
|
||||||
pointed_thing.ref,
|
pointed_thing.ref,
|
||||||
'',
|
'',
|
||||||
|
@ -1219,6 +1210,8 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
rotation,
|
rotation,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
end)
|
||||||
|
|
||||||
selfObj._attached = true
|
selfObj._attached = true
|
||||||
selfObj._attached_to.type = pointed_thing.type
|
selfObj._attached_to.type = pointed_thing.type
|
||||||
selfObj._attached_to.pos = position
|
selfObj._attached_to.pos = position
|
||||||
|
@ -1329,6 +1322,24 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
|
||||||
on_hit_node_callback(selfObj, pointed_thing)
|
on_hit_node_callback(selfObj, pointed_thing)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local new_pos = selfObj.object:get_pos()
|
||||||
|
|
||||||
|
minetest.add_particlespawner({
|
||||||
|
amount = 5,
|
||||||
|
time = 0.25,
|
||||||
|
minpos = {x = new_pos.x - 0.4, y = new_pos.y + 0.2, z = new_pos.z - 0.4},
|
||||||
|
maxpos = {x = new_pos.x + 0.4, y = new_pos.y + 0.3, z = new_pos.z + 0.4},
|
||||||
|
minvel = {x = 0, y = 3, z = 0},
|
||||||
|
maxvel = {x = 0, y = 4, z = 0},
|
||||||
|
minacc = {x = 0, y = -28, z = 0},
|
||||||
|
maxacc = {x = 0, y = -32, z = 0},
|
||||||
|
minexptime = 1,
|
||||||
|
maxexptime = 1.5,
|
||||||
|
node = {name = node_def.name},
|
||||||
|
collisiondetection = true,
|
||||||
|
object_collision = true,
|
||||||
|
})
|
||||||
|
|
||||||
minetest.sound_play(selfObj._sound_hit, {
|
minetest.sound_play(selfObj._sound_hit, {
|
||||||
pos = pointed_thing.under,
|
pos = pointed_thing.under,
|
||||||
gain = 0.6,
|
gain = 0.6,
|
||||||
|
@ -1346,7 +1357,7 @@ end
|
||||||
|
|
||||||
---Function receive a "luaentity" table as `self`. Called when somebody punches the object. Note that you probably want to handle most punches using the automatic armor group system. Can return `true` to prevent the default damage mechanism.
|
---Function receive a "luaentity" table as `self`. Called when somebody punches the object. Note that you probably want to handle most punches using the automatic armor group system. Can return `true` to prevent the default damage mechanism.
|
||||||
---@param self XBows
|
---@param self XBows
|
||||||
---@param selfObj table
|
---@param selfObj EnityCustomAttrDef
|
||||||
---@param puncher ObjectRef|nil
|
---@param puncher ObjectRef|nil
|
||||||
---@param time_from_last_punch number|integer|nil
|
---@param time_from_last_punch number|integer|nil
|
||||||
---@param tool_capabilities ToolCapabilitiesDef
|
---@param tool_capabilities ToolCapabilitiesDef
|
||||||
|
|
|
@ -31,12 +31,19 @@
|
||||||
---@field move_to fun(self: ObjectRef, pos: Vector, continuous?: boolean): nil Does an interpolated move for Lua entities for visually smooth transitions. If `continuous` is true, the Lua entity will not be moved to the current position before starting the interpolated move. For players this does the same as `set_pos`,`continuous` is ignored.
|
---@field move_to fun(self: ObjectRef, pos: Vector, continuous?: boolean): nil Does an interpolated move for Lua entities for visually smooth transitions. If `continuous` is true, the Lua entity will not be moved to the current position before starting the interpolated move. For players this does the same as `set_pos`,`continuous` is ignored.
|
||||||
---@field set_hp fun(self: ObjectRef, hp: number, reason: table): nil set number of health points See reason in register_on_player_hpchange Is limited to the range of 0 ... 65535 (2^16 - 1) For players: HP are also limited by `hp_max` specified in object properties
|
---@field set_hp fun(self: ObjectRef, hp: number, reason: table): nil set number of health points See reason in register_on_player_hpchange Is limited to the range of 0 ... 65535 (2^16 - 1) For players: HP are also limited by `hp_max` specified in object properties
|
||||||
---@field set_animation fun(self: ObjectRef, frame_range?: {["x"]: number, ["y"]: number}, frame_speed?: number, frame_blend?: number, frame_loop?: boolean): nil `frame_range`: table {x=num, y=num}, default: `{x=1, y=1}`, `frame_speed`: number, default: `15.0`, `frame_blend`: number, default: `0.0`, `frame_loop`: boolean, default: `true`
|
---@field set_animation fun(self: ObjectRef, frame_range?: {["x"]: number, ["y"]: number}, frame_speed?: number, frame_blend?: number, frame_loop?: boolean): nil `frame_range`: table {x=num, y=num}, default: `{x=1, y=1}`, `frame_speed`: number, default: `15.0`, `frame_blend`: number, default: `0.0`, `frame_loop`: boolean, default: `true`
|
||||||
|
---@field get_velocity fun(self: ObjectRef): Vector returns the velocity, a vector.
|
||||||
|
---@field set_rotation fun(self: ObjectRef, rot: Vector): nil `rot` is a vector (radians). X is pitch (elevation), Y is yaw (heading) and Z is roll (bank).
|
||||||
|
---@field set_pos fun(self: ObjectRef, pos: Vector): nil
|
||||||
|
|
||||||
|
|
||||||
---Moving things in the game are generally these.
|
---Moving things in the game are generally these.
|
||||||
---This is basically a reference to a C++ `ServerActiveObject`.
|
---This is basically a reference to a C++ `ServerActiveObject`.
|
||||||
---@class ObjectRefLuaEntityRef
|
---@class ObjectRefLuaEntityRef
|
||||||
---@field set_velocity fun(self: ObjectRef, vel: Vector): nil `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}`
|
---@field set_velocity fun(self: ObjectRef, vel: Vector): nil `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}`
|
||||||
---@field remove fun(): nil remove object, The object is removed after returning from Lua. However the `ObjectRef` itself instantly becomes unusable with all further method calls having no effect and returning `nil`.
|
---@field remove fun(): nil remove object, The object is removed after returning from Lua. However the `ObjectRef` itself instantly becomes unusable with all further method calls having no effect and returning `nil`.
|
||||||
|
---@field get_rotation fun(self: ObjectRef): Vector returns the rotation, a vector (radians)
|
||||||
|
---@field get_attach fun(self: ObjectRef): any Returns parent, bone, position, rotation, forced_visible, or nil if it isn't attached.
|
||||||
|
---@field set_attach fun(self: ObjectRef, parent: ObjectRef, bone?: string, position?: Vector, rotation?: Vector, forced_visible?: boolean): any Returns parent, bone, position, rotation, forced_visible, or nil if it isn't attached.
|
||||||
|
|
||||||
---`ObjectRef` armor groups
|
---`ObjectRef` armor groups
|
||||||
---@class ObjectRefArmorGroups
|
---@class ObjectRefArmorGroups
|
||||||
|
|
|
@ -13,3 +13,4 @@
|
||||||
---@field round fun(v: Vector): Vector Returns a vector, each dimension rounded to nearest integer. At a multiple of 0.5, rounds away from zero.
|
---@field round fun(v: Vector): Vector Returns a vector, each dimension rounded to nearest integer. At a multiple of 0.5, rounds away from zero.
|
||||||
---@field new fun(a, b?, c?): Vector Returns a new vector `(a, b, c)`.
|
---@field new fun(a, b?, c?): Vector Returns a new vector `(a, b, c)`.
|
||||||
---@field direction fun(p1: Vector, p2: Vector): Vector Returns a vector of length 1 with direction `p1` to `p2`. If `p1` and `p2` are identical, returns `(0, 0, 0)`.
|
---@field direction fun(p1: Vector, p2: Vector): Vector Returns a vector of length 1 with direction `p1` to `p2`. If `p1` and `p2` are identical, returns `(0, 0, 0)`.
|
||||||
|
---@field divide fun(v: Vector, s: Vector | number): Vector Returns a scaled vector. Deprecated: If `s` is a vector: Returns the Schur quotient.
|
||||||
|
|
|
@ -154,3 +154,51 @@
|
||||||
---@class EntityAnimationDef
|
---@class EntityAnimationDef
|
||||||
---@field idle {frame_range?: {["x"]: number, ["y"]: number}, frame_speed?: number, frame_blend?: number, frame_loop?: boolean}
|
---@field idle {frame_range?: {["x"]: number, ["y"]: number}, frame_speed?: number, frame_blend?: number, frame_loop?: boolean}
|
||||||
---@field on_hit_node {frame_range?: {["x"]: number, ["y"]: number}, frame_speed?: number, frame_blend?: number, frame_loop?: boolean}
|
---@field on_hit_node {frame_range?: {["x"]: number, ["y"]: number}, frame_speed?: number, frame_blend?: number, frame_loop?: boolean}
|
||||||
|
|
||||||
|
---Arrow object and custom attributes
|
||||||
|
---@class EnityCustomAttrDef
|
||||||
|
---@field object ObjectRef
|
||||||
|
---@field _velocity Vector
|
||||||
|
---@field _old_pos Vector
|
||||||
|
---@field _attached boolean
|
||||||
|
---@field _attached_to {["type"]: string, ["pos"]: Vector | nil}
|
||||||
|
---@field _has_particles boolean
|
||||||
|
---@field _lifetimer number
|
||||||
|
---@field _nodechecktimer number
|
||||||
|
---@field _is_drowning boolean
|
||||||
|
---@field _in_liquid boolean
|
||||||
|
---@field _shot_from_pos Vector
|
||||||
|
---@field _arrow_name string
|
||||||
|
---@field _bow_name string
|
||||||
|
---@field _user_name string
|
||||||
|
---@field _user ObjectRef
|
||||||
|
---@field _tflp number
|
||||||
|
---@field _tool_capabilities ToolCapabilitiesDef
|
||||||
|
---@field _is_critical_hit boolean
|
||||||
|
---@field _faster_arrows_multiplier number
|
||||||
|
---@field _add_damage number
|
||||||
|
---@field _caused_damage number
|
||||||
|
---@field _caused_knockback number
|
||||||
|
---@field _arrow_particle_effect string
|
||||||
|
---@field _arrow_particle_effect_crit string
|
||||||
|
---@field _arrow_particle_effect_fast string
|
||||||
|
---@field _sound_hit string
|
||||||
|
---@field _player_look_dir Vector
|
||||||
|
---@field _acc_x number
|
||||||
|
---@field _acc_y number
|
||||||
|
---@field _acc_z number
|
||||||
|
---@field _strength number
|
||||||
|
---@field name string
|
||||||
|
---@field _rotation_factor number | fun(): number
|
||||||
|
---@field _step_count number
|
||||||
|
|
||||||
|
---Staticdata attributes
|
||||||
|
---@class EnityStaticDataAttrDef
|
||||||
|
---@field _arrow_name string
|
||||||
|
---@field _bow_name string
|
||||||
|
---@field _user_name string
|
||||||
|
---@field _is_critical_hit boolean
|
||||||
|
---@field _tool_capabilities ToolCapabilitiesDef
|
||||||
|
---@field _tflp number
|
||||||
|
---@field _add_damage number
|
||||||
|
---@field _faster_arrows_multiplier number | nil
|
||||||
|
|
Ŝarĝante…
Reference in New Issue