mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-22 10:31:06 +01:00
Implement mod for general purpose environmental physics effects
This commit is contained in:
parent
d264ba70d8
commit
6076e35e98
8 changed files with 103 additions and 97 deletions
|
@ -657,62 +657,6 @@ local function push_out_item_stuck_in_solid(self, dtime, p, def, is_in_water)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function move_items_in_water (self, p, def, node, is_floating, is_in_water)
|
|
||||||
-- Move item around on flowing liquids; add 'source' check to allow items to continue flowing a bit in the source block of flowing water.
|
|
||||||
if def and not is_floating and (def.liquidtype == "flowing" or def.liquidtype == "source") then
|
|
||||||
self._flowing = true
|
|
||||||
|
|
||||||
--[[ Get flowing direction (function call from flowlib), if there's a liquid.
|
|
||||||
NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7.
|
|
||||||
Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]]
|
|
||||||
local vec = flowlib.quick_flow(p, node)
|
|
||||||
-- Just to make sure we don't manipulate the speed for no reason
|
|
||||||
if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then
|
|
||||||
-- Minecraft Wiki: Flowing speed is "about 1.39 meters per second"
|
|
||||||
local f = 1.2
|
|
||||||
-- Set new item moving speed into the direciton of the liquid
|
|
||||||
local newv = vector.multiply(vec, f)
|
|
||||||
-- Swap to acceleration instead of a static speed to better mimic MC mechanics.
|
|
||||||
self.object:set_acceleration(vector.new(newv.x, -0.22, newv.z))
|
|
||||||
|
|
||||||
self.physical_state = true
|
|
||||||
self._flowing = true
|
|
||||||
self.object:set_properties({
|
|
||||||
physical = true
|
|
||||||
})
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
if is_in_water and def.liquidtype == "source" then
|
|
||||||
local cur_vec = self.object:get_velocity()
|
|
||||||
-- apply some acceleration in the opposite direction so it doesn't slide forever
|
|
||||||
local vec = {
|
|
||||||
x = 0 - cur_vec.x * 0.9,
|
|
||||||
y = 3 - cur_vec.y * 0.9,
|
|
||||||
z = 0 - cur_vec.z * 0.9
|
|
||||||
}
|
|
||||||
self.object:set_acceleration(vec)
|
|
||||||
-- slow down the item in water
|
|
||||||
local vel = self.object:get_velocity()
|
|
||||||
if vel.y < 0 then
|
|
||||||
vel.y = vel.y * 0.9
|
|
||||||
end
|
|
||||||
self.object:set_velocity(vel)
|
|
||||||
if self.physical_state ~= false or self._flowing ~= true then
|
|
||||||
self.physical_state = true
|
|
||||||
self._flowing = true
|
|
||||||
self.object:set_properties({
|
|
||||||
physical = true
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif self._flowing == true and not is_in_water and not is_floating then
|
|
||||||
-- Disable flowing physics if not on/in flowing liquid
|
|
||||||
self._flowing = false
|
|
||||||
enable_physics(self.object, self, true)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_entity(":__builtin:item", {
|
minetest.register_entity(":__builtin:item", {
|
||||||
initial_properties = {
|
initial_properties = {
|
||||||
hp_max = 1,
|
hp_max = 1,
|
||||||
|
@ -1053,7 +997,7 @@ minetest.register_entity(":__builtin:item", {
|
||||||
|
|
||||||
if push_out_item_stuck_in_solid(self, dtime, p, def, is_in_water) then return end
|
if push_out_item_stuck_in_solid(self, dtime, p, def, is_in_water) then return end
|
||||||
|
|
||||||
if move_items_in_water (self, p, def, node, is_floating, is_in_water) then return end
|
mcl_physics.apply_entity_environmental_physics(self)
|
||||||
|
|
||||||
-- If node is not registered or node is walkably solid and resting on nodebox
|
-- If node is not registered or node is walkably solid and resting on nodebox
|
||||||
local nn = minetest.get_node(vector.offset(p, 0, -0.5, 0)).name
|
local nn = minetest.get_node(vector.offset(p, 0, -0.5, 0)).name
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
name = mcl_item_entity
|
name = mcl_item_entity
|
||||||
author = PilzAdam
|
author = PilzAdam
|
||||||
description = Dropped items will be attracted to the player like a magnet.
|
description = Dropped items will be attracted to the player like a magnet.
|
||||||
depends = flowlib, mcl_enchanting
|
depends = mcl_physics, mcl_enchanting
|
||||||
|
|
|
@ -411,7 +411,8 @@ local function on_step_work (self, dtime)
|
||||||
local player_in_active_range = self:player_in_active_range()
|
local player_in_active_range = self:player_in_active_range()
|
||||||
self:check_suspend(player_in_active_range)
|
self:check_suspend(player_in_active_range)
|
||||||
|
|
||||||
self:check_water_flow()
|
-- Handle environmental physics
|
||||||
|
mcl_physics.apply_entity_environmental_physics(self)
|
||||||
|
|
||||||
if not self._jumping_cliff then
|
if not self._jumping_cliff then
|
||||||
self._can_jump_cliff = self:can_jump_cliff()
|
self._can_jump_cliff = self:can_jump_cliff()
|
||||||
|
|
|
@ -2,4 +2,4 @@ name = mcl_mobs
|
||||||
author = PilzAdam
|
author = PilzAdam
|
||||||
description = Adds a mob API for mods to add animals or monsters, etc.
|
description = Adds a mob API for mods to add animals or monsters, etc.
|
||||||
depends = mcl_particles, mcl_luck
|
depends = mcl_particles, mcl_luck
|
||||||
optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, invisibility, lucky_block, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience, mcl_sculk
|
optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, invisibility, lucky_block, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience, mcl_sculk, mcl_physics
|
||||||
|
|
|
@ -996,43 +996,7 @@ function mob_class:falling(pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mob_class:check_water_flow()
|
function mob_class:check_water_flow()
|
||||||
-- Add water flowing for mobs from mcl_item_entity
|
-- Deprecated. Do nothing
|
||||||
local p, node, nn, def
|
|
||||||
p = self.object:get_pos()
|
|
||||||
node = minetest.get_node_or_nil(p)
|
|
||||||
if node then
|
|
||||||
nn = node.name
|
|
||||||
def = minetest.registered_nodes[nn]
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Move item around on flowing liquids
|
|
||||||
if def and def.liquidtype == "flowing" then
|
|
||||||
|
|
||||||
--[[ Get flowing direction (function call from flowlib), if there's a liquid.
|
|
||||||
NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7.
|
|
||||||
Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]]
|
|
||||||
local vec = flowlib.quick_flow(p, node)
|
|
||||||
-- Just to make sure we don't manipulate the speed for no reason
|
|
||||||
if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then
|
|
||||||
-- Minecraft Wiki: Flowing speed is "about 1.39 meters per second"
|
|
||||||
local f = 1.39
|
|
||||||
-- Set new item moving speed into the direciton of the liquid
|
|
||||||
local newv = vector.multiply(vec, f)
|
|
||||||
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
|
||||||
self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z})
|
|
||||||
|
|
||||||
self.physical_state = true
|
|
||||||
self._flowing = true
|
|
||||||
self.object:set_properties({
|
|
||||||
physical = true
|
|
||||||
})
|
|
||||||
return
|
|
||||||
end
|
|
||||||
elseif self._flowing == true then
|
|
||||||
-- Disable flowing physics if not on/in flowing liquid
|
|
||||||
self._flowing = false
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function mob_class:check_dying()
|
function mob_class:check_dying()
|
||||||
|
|
53
mods/ENVIRONMENT/mcl_physics/api.lua
Normal file
53
mods/ENVIRONMENT/mcl_physics/api.lua
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
local mod = mcl_physics
|
||||||
|
|
||||||
|
local registered_environment_effects = {}
|
||||||
|
|
||||||
|
function mod.register_enviornment_effect(effect)
|
||||||
|
local list = registered_effects
|
||||||
|
list[#list + 1] = effect
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.get_environment_effect(pos, vel, staticdata, mass)
|
||||||
|
local v = vector.new(0,0,0)
|
||||||
|
local a = vector.new(0,0,0)
|
||||||
|
|
||||||
|
-- Accumulate all enviornmental effects
|
||||||
|
for _,effect in ipairs(registered_environment_effects) do
|
||||||
|
local dv,da = effect(pos, vel, staticdata)
|
||||||
|
if dv then
|
||||||
|
v = v + dv
|
||||||
|
end
|
||||||
|
if da then
|
||||||
|
a = a + da
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if vector.length(v) > 0.01 or vector.length(a) > vector.length(a) > 0.01 then
|
||||||
|
return v,a
|
||||||
|
else
|
||||||
|
return -- nil,nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.apply_entity_environmental_physics(self, data)
|
||||||
|
data = data or {}
|
||||||
|
|
||||||
|
local pos = self.object:get_pos()
|
||||||
|
local vel = self.object:get_velocity()
|
||||||
|
local new_velocity,new_acceleration = mcl_physics.get_environment_effect(pos, vel, data, 1)
|
||||||
|
|
||||||
|
-- Update entity states
|
||||||
|
self._flowing = data.flowing
|
||||||
|
|
||||||
|
-- Apply environmental effects if there are any
|
||||||
|
if new_velocity or new_acceleration then
|
||||||
|
if new_acceleration then self.object:set_acceleration(new_acceleration) end
|
||||||
|
if new_velocity then self.object:set_velocity(new_velocity) end
|
||||||
|
|
||||||
|
self.physical_state = true
|
||||||
|
self._flowing = true
|
||||||
|
self.object:set_properties({
|
||||||
|
physical = true
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
40
mods/ENVIRONMENT/mcl_physics/init.lua
Normal file
40
mods/ENVIRONMENT/mcl_physics/init.lua
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
local modname = minetest.get_current_modname()
|
||||||
|
local modpath = minetest.get_modpath(modname)
|
||||||
|
local mod = {}
|
||||||
|
mcl_physics = mod
|
||||||
|
|
||||||
|
dofile(modpath.."/api.lua")
|
||||||
|
|
||||||
|
-- TODO: move to Flowlib
|
||||||
|
local FLOW_SPEED = 1.39
|
||||||
|
mod.register_effect(function(pos, vel, staticdata)
|
||||||
|
-- Get the node and node definition
|
||||||
|
local node = minetest.get_node_or_nil(pos)
|
||||||
|
if not node then return end
|
||||||
|
local nodedef = minetest.registered_nodes[node.name]
|
||||||
|
if not nodedef then return end
|
||||||
|
|
||||||
|
-- Make sure we are in a liquid before continuing
|
||||||
|
local is_flowing = (nodedef.liquidtype == "flowing")
|
||||||
|
staticdata.flowing = is_flowing
|
||||||
|
if not is_flowing then
|
||||||
|
-- Apply decelleration if the entity moved from flowing water to
|
||||||
|
-- stationary water
|
||||||
|
if nodedef.liquidtype == "source" then
|
||||||
|
return nil,vector.new(
|
||||||
|
0 - vel.x * 0.9,
|
||||||
|
3 - vel.y * 0.9,
|
||||||
|
0 - vel.z * 0.9
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get liquid flow direction
|
||||||
|
local vec = vector.multiply(flowlib.quick_flow(pos, node), FLOW_SPEED)
|
||||||
|
return vector.new(vec.x, -0.22, vec.z),nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Node effects
|
||||||
|
mod.register_effect
|
||||||
|
|
4
mods/ENVIRONMENT/mcl_physics/mod.conf
Normal file
4
mods/ENVIRONMENT/mcl_physics/mod.conf
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
name = mcl_physics
|
||||||
|
author = teknomunk
|
||||||
|
description = Environmental physics
|
||||||
|
depends = flowlib
|
Loading…
Reference in a new issue