Fix typos documentation, add ignore_gravity and liquid_drag options, use vl_projectile.register() for enter pearl, move projectile physics to vl_projectile add hook for future vl_physics support

This commit is contained in:
teknomunk 2024-09-01 20:41:21 -05:00
parent 1b5baef889
commit 0f3af79de1
5 changed files with 72 additions and 41 deletions

@ -15,11 +15,6 @@ local STUCK_RECHECK_TIME = 5
local YAW_OFFSET = -math.pi/2 local YAW_OFFSET = -math.pi/2
local function dir_to_pitch(dir)
local xz = math.abs(dir.x) + math.abs(dir.z)
return -math.atan2(-dir.y, xz)
end
local function random_arrow_positions(positions, placement) local function random_arrow_positions(positions, placement)
if positions == "x" then if positions == "x" then
return math.random(-4, 4) return math.random(-4, 4)
@ -123,6 +118,7 @@ local arrow_entity = {
textures = {"mcl_bows_arrow.png"}, textures = {"mcl_bows_arrow.png"},
collisionbox = {-0.19, -0.125, -0.19, 0.19, 0.125, 0.19}, collisionbox = {-0.19, -0.125, -0.19, 0.19, 0.125, 0.19},
collide_with_objects = false, collide_with_objects = false,
liquid_drag = true,
_fire_damage_resistant = true, _fire_damage_resistant = true,
_save_fields = { _save_fields = {
@ -348,35 +344,11 @@ local arrow_entity = {
self._deflection_cooloff = self._deflection_cooloff - dtime self._deflection_cooloff = self._deflection_cooloff - dtime
end end
-- TODO: change to use vl_physics
-- TODO: move to vl_projectile
local def = minetest.registered_nodes[minetest.get_node(pos).name]
if def and def.liquidtype ~= "none" then
-- Slow down arrow in liquids
local v = def.liquid_viscosity or 0
self._viscosity = v
local vpenalty = math.max(0.1, 0.98 - 0.1 * v)
local vel = self.object:get_velocity()
if math.abs(vel.x) > 0.001 then
vel.x = vel.x * vpenalty
end
if math.abs(vel.z) > 0.001 then
vel.z = vel.z * vpenalty
end
self.object:set_velocity(vel)
end
-- Process as projectile -- Process as projectile
vl_projectile.update_projectile(self, dtime) vl_projectile.update_projectile(self, dtime)
-- Update yaw -- Update yaw
local vel = self.object:get_velocity() local vel = self.object:get_velocity()
if vel and not self._stuck then
local yaw = minetest.dir_to_yaw(vel)+YAW_OFFSET
local pitch = dir_to_pitch(vel)
self.object:set_rotation(vector.new(0,yaw,pitch))
end
end, end,
-- Force recheck of stuck arrows when punched. -- Force recheck of stuck arrows when punched.

@ -23,7 +23,7 @@ minetest.register_craftitem("mcl_throwing:ender_pearl", {
mcl_throwing.register_throwable_object("mcl_throwing:ender_pearl", "mcl_throwing:ender_pearl_entity", 22) mcl_throwing.register_throwable_object("mcl_throwing:ender_pearl", "mcl_throwing:ender_pearl_entity", 22)
-- Ender pearl entity -- Ender pearl entity
minetest.register_entity("mcl_throwing:ender_pearl_entity",{ vl_projectile.register("mcl_throwing:ender_pearl_entity",{
physical = false, physical = false,
timer=0, timer=0,
textures = {"mcl_throwing_ender_pearl.png"}, textures = {"mcl_throwing_ender_pearl.png"},

@ -10,19 +10,21 @@ Arguments:
* `def`: Projectile defintion. Supports all fields that standard minetest entities support. * `def`: Projectile defintion. Supports all fields that standard minetest entities support.
Must include the field `_vl_projectile` for projectile-specific behaviors. These are the supported Must include the field `_vl_projectile` for projectile-specific behaviors. These are the supported
fields: fields:
* `ignore_gravity`: if true, the projectile will not be affected by gravity
* `liquid_drag`: if true, apply drag from liquid nodes to the projectile
* `survive_collision`: if this field is `false` or `nil`, the projectile will be removed after a collision. * `survive_collision`: if this field is `false` or `nil`, the projectile will be removed after a collision.
* `sticks_in_players`: if true, the projectile will stick into players after colliding with them. * `sticks_in_players`: if true, the projectile will stick into players after colliding with them.
* `damage_groups`: damage group information to use for `punch()`. May be a function of type `function(projectile, entity_def, projectile_def, obj)` * `damage_groups`: damage group information to use for `punch()`. May be a function of type `function(projectile, entity_def, projectile_def, obj)`
that returns dynamic damange group information. that returns dynamic damange group information.
* `allow_punching`: will the projectile punch entities it collieds with. May be a function of type `function(projectile, entity_def, projectile_def, obj)`. * `allow_punching`: will the projectile punch entities it collides with. May be a function of type `function(projectile, entity_def, projectile_def, obj)`.
* `behaviors`: a list of behavior callbacks that define the projectile's behavior. This mod provides two * `behaviors`: a list of behavior callbacks that define the projectile's behavior. This mod provides the following
behaviors: `vl_projectiles.collides_with_solids`, `vl_projectiles.collides_with_entities` and `vl_projectiles_raycast_collieds_with_entities` behaviors: `vl_projectiles.collides_with_solids`, `vl_projectiles.collides_with_entities` and `vl_projectiles_raycast_collides_with_entities`
* `sounds`: sounds for this projectile. All fields take a table with three parameters corresponding to the * `sounds`: sounds for this projectile. All fields take a table with three parameters corresponding to the
three parameters for `minetest.play_sound()`. Supported sounds are: three parameters for `minetest.play_sound()`. Supported sounds are:
* `on_collision`: played when no other more specific sound is defined. May be a function of type `function(projectile, entity_def, projectile_def, type, ...)` * `on_collision`: played when no other more specific sound is defined. May be a function of type `function(projectile, entity_def, projectile_def, type, ...)`
* `on_solid_collision`: played when the projectile collides with a solid node. May be a function of type * `on_solid_collision`: played when the projectile collides with a solid node. May be a function of type
`funciton(projectile, entity_def, projectile_def, type, pos, node, node_def)` with `type = "node"` `funciton(projectile, entity_def, projectile_def, type, pos, node, node_def)` with `type = "node"`
* `on_entity_collision`: played when the projectile collieds with another entity. May be a function of type * `on_entity_collision`: played when the projectile collides with another entity. May be a function of type
`function(projectile, entity_def, projectile_def, type, entity)` with `type = "entity"` `function(projectile, entity_def, projectile_def, type, entity)` with `type = "entity"`
* `on_collide_with_solid`: callback of type `function(projectile, pos, node, node_def)` used when the projectile collides with a solid node. Requires * `on_collide_with_solid`: callback of type `function(projectile, pos, node, node_def)` used when the projectile collides with a solid node. Requires
`vl_projectile.collides_with_solids` in `behaviors` list. `vl_projectile.collides_with_solids` in `behaviors` list.

@ -1,9 +1,64 @@
local mod = {} local mod = {}
vl_projectile = mod vl_projectile = mod
local vl_physics_path = minetest.get_modpath("vl_physics")
local YAW_OFFSET = -math.pi/2
local GRAVITY = tonumber(minetest.settings:get("movement_gravity")) local GRAVITY = tonumber(minetest.settings:get("movement_gravity"))
local enable_pvp = minetest.settings:get_bool("enable_pvp") local enable_pvp = minetest.settings:get_bool("enable_pvp")
local function dir_to_pitch(dir)
local xz = math.abs(dir.x) + math.abs(dir.z)
return -math.atan2(-dir.y, xz)
end
function mod.projectile_physics(obj, entity_def, v, a)
local le = obj:get_luaentity()
local entity_def = minetest.registered_entities[le.name]
local pos = obj:get_pos()
if not pos then return end
if vl_physics_path then
v,a = vl_physics.apply_entity_environmental_physics(obj)
else
-- Simple physics
if not v then v = obj:get_velocity() end
if not a then a = vector.zero() end
if not entity_def.ignore_gravity then
a = a + vector.new(0,-GRAVITY,0)
end
if entity_def.liquid_drag then
local def = minetest.registered_nodes[minetest.get_node(pos).name]
if def and def.liquidtype ~= "none" then
-- Slow down arrow in liquids
local visc = def.liquid_viscosity or 0
le._viscosity = visc
local vpenalty = math.max(0.1, 0.98 - 0.1 * visc)
if math.abs(v.x) > 0.001 then
v.x = v.x * vpenalty
end
if math.abs(v.z) > 0.001 then
v.z = v.z * vpenalty
end
end
end
end
-- Pass to entity
if v then obj:set_velocity(v) end
if a then obj:set_acceleration(a) end
-- Update projectile yaw to match velocity direction
if v and le and not le._stuck then
local yaw = minetest.dir_to_yaw(v) + YAW_OFFSET
local pitch = dir_to_pitch(v)
obj:set_rotation(vector.new(0,yaw,pitch))
end
end
function mod.update_projectile(self, dtime) function mod.update_projectile(self, dtime)
if self._removed then return end if self._removed then return end
@ -22,6 +77,8 @@ function mod.update_projectile(self, dtime)
return return
end end
end end
mod.projectile_physics(self.object, entity_def)
end end
local function no_op() local function no_op()
@ -300,14 +357,13 @@ function mod.raycast_collides_with_entities(self, dtime, entity_def, projectile_
end end
function mod.create(entity_id, options) function mod.create(entity_id, options)
local obj = minetest.add_entity(options.pos, entity_id, options.staticdata) local pos = options.pos
local obj = minetest.add_entity(pos, entity_id, options.staticdata)
-- Set initial velocoty and acceleration -- Set initial velocity and acceleration
obj:set_velocity(vector.multiply(options.dir or vector.zero(), options.velocity or 0)) local v = vector.multiply(options.dir or vector.zero(), options.velocity or 0)
obj:set_acceleration(vector.add( local a = vector.multiply(v, -math.abs(options.drag))
vector.multiply(options.dir or vector.zero(), -math.abs(options.drag)), mod.projectile_physics(obj, entity_def, v, a)
vector.new(0,-GRAVITY,0)
))
-- Update projectile parameters -- Update projectile parameters
local luaentity = obj:get_luaentity() local luaentity = obj:get_luaentity()

@ -1,2 +1,3 @@
name = vl_projectile name = vl_projectile
depends = mcl_util depends = mcl_util
optional_depends = vl_physics