Merge pull request #8 from TheTermos/dev

Dev
master
TheTermos 2019-10-27 19:47:10 +01:00 committed by GitHub
commit 1eb151dc14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 114 additions and 112 deletions

226
init.lua
View File

@ -12,6 +12,7 @@ mobkit.friction = 0.4 -- less is more
local abs = math.abs
local pi = math.pi
local floor = math.floor
local ceil = math.ceil
local random = math.random
local sqrt = math.sqrt
local max = math.max
@ -45,6 +46,11 @@ function mobkit.dot(v1,v2)
return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z
end
function mobkit.minmax(v,m)
return min(abs(v),m)*sign(v)
end
function mobkit.dir2neighbor(dir)
dir.y=0
dir=vector.round(vector.normalize(dir))
@ -103,6 +109,16 @@ function mobkit.get_stand_pos(thing) -- thing can be luaentity or objectref.
return mobkit.pos_shift(pos,{y=colbox[2]+0.01}), pos
end
function mobkit.set_acceleration(thing,vec,limit)
limit = limit or 100
if type(thing) == 'table' then thing=thing.object end
vec.x=mobkit.minmax(vec.x,limit)
vec.y=mobkit.minmax(vec.y,limit)
vec.z=mobkit.minmax(vec.z,limit)
thing:set_acceleration(vec)
end
function mobkit.nodeatpos(pos)
local node = minetest.get_node_or_nil(pos)
if node then return minetest.registered_nodes[node.name] end
@ -379,17 +395,6 @@ function mobkit.heal(luaent,dmg)
end
end
-- function mobkit.animate(self,anim)
-- if self.animation and self.animation[anim] then
-- local crange = self.object:get_animation().range
-- if not crange
-- or crange.x ~= self.animation[anim].range.x
-- or crange.y ~= self.animation[anim].range.y then
-- self.object:set_animation(self.animation[anim].range,self.animation[anim].speed,0,self.animation[anim].loop)
-- end
-- end
-- end
function mobkit.animate(self,anim)
if self.animation and self.animation[anim] then
if self._anim == anim then return end
@ -746,6 +751,88 @@ function mobkit.default_brain(self)
if mobkit.is_queue_empty_high(self) then mobkit.hq_roam(self,0) end
end
function mobkit.physics(self)
local vel=self.object:get_velocity()
-- dumb friction
if self.isonground and not self.isinliquid then
self.object:set_velocity({x= vel.x> 0.2 and vel.x*mobkit.friction or 0,
y=vel.y,
z=vel.z > 0.2 and vel.z*mobkit.friction or 0})
end
-- bounciness
if self.springiness and self.springiness > 0 then
local vnew = vector.new(vel)
if not self.collided then -- ugly workaround for inconsistent collisions
for _,k in ipairs({'y','z','x'}) do
if vel[k]==0 and abs(self.lastvelocity[k])> 0.1 then
vnew[k]=-self.lastvelocity[k]*self.springiness
end
end
end
if not vector.equals(vel,vnew) then
self.collided = true
else
if self.collided then
vnew = vector.new(self.lastvelocity)
end
self.collided = false
end
self.object:set_velocity(vnew)
end
-- buoyancy
local spos = mobkit.get_stand_pos(self)
spos.y = spos.y+0.01
-- get surface height
local surface = nil
local snodepos = mobkit.get_node_pos(spos)
local surfnode = mobkit.nodeatpos(spos)
while surfnode and surfnode.drawtype == 'liquid' do
surface = snodepos.y+0.5
if surface > spos.y+self.height then break end
snodepos.y = snodepos.y+1
surfnode = mobkit.nodeatpos(snodepos)
end
if surface then -- standing in liquid
self.isinliquid = true
local submergence = min(surface-spos.y,self.height)
local balance = self.buoyancy*self.height
local buoyacc = mobkit.gravity*((balance - submergence)^2/balance^2*sign(balance - submergence))
mobkit.set_acceleration(self.object,
{x=-vel.x*self.water_drag,y=buoyacc-vel.y*abs(vel.y)*0.7,z=-vel.z*self.water_drag})
else
self.isinliquid = false
self.object:set_acceleration({x=0,y=mobkit.gravity,z=0})
end
end
function mobkit.vitals(self)
-- vitals: fall damage
vel = self.object:get_velocity()
local velocity_delta = abs(self.lastvelocity.y - vel.y)
if velocity_delta > mobkit.safe_velocity then
self.hp = self.hp - floor(self.max_hp * min(1, velocity_delta/mobkit.terminal_velocity))
end
-- vitals: oxygen
if self.lung_capacity then
local colbox = self.object:get_properties().collisionbox
local headnode = mobkit.nodeatpos(mobkit.pos_shift(self.object:get_pos(),{y=colbox[5]})) -- node at hitbox top
if headnode and headnode.drawtype == 'liquid' then
self.oxygen = self.oxygen - self.dtime
else
self.oxygen = self.lung_capacity
end
if self.oxygen <= 0 then self.hp=0 end -- drown
end
end
function mobkit.statfunc(self)
local tmptab={}
tmptab.memory = self.memory
@ -755,6 +842,10 @@ function mobkit.statfunc(self)
end
function mobkit.actfunc(self, staticdata, dtime_s)
self.logic = self.logic or self.brainfunc
self.physics = self.physics or mobkit.physics
self.lqueue = {}
self.hqueue = {}
self.nearby_objects = {}
@ -805,7 +896,7 @@ function mobkit.actfunc(self, staticdata, dtime_s)
end
function mobkit.stepfunc(self,dtime) -- not intended to be modified
self.dtime = dtime
self.dtime = max(dtime,0.05)
self.height = mobkit.get_box_height(self)
-- physics comes first
-- self.object:set_acceleration({x=0,y=mobkit.gravity,z=0})
@ -818,108 +909,16 @@ function mobkit.stepfunc(self,dtime) -- not intended to be modified
self.isonground = false
end
-- dumb friction
if self.isonground and not self.isinliquid then
self.object:set_velocity({x= vel.x> 0.2 and vel.x*mobkit.friction or 0,
y=vel.y,
z=vel.z > 0.2 and vel.z*mobkit.friction or 0})
end
-- bounciness
if self.springiness and self.springiness > 0 then
local vnew = vector.new(vel)
if not self.collided then -- ugly workaround for inconsistent collisions
for _,k in ipairs({'y','z','x'}) do
if vel[k]==0 and abs(self.lastvelocity[k])> 0.1 then
vnew[k]=-self.lastvelocity[k]*self.springiness
end
end
end
if not vector.equals(vel,vnew) then
self.collided = true
else
if self.collided then
vnew = vector.new(self.lastvelocity)
end
self.collided = false
end
self.object:set_velocity(vnew)
end
-- buoyancy
local spos = mobkit.get_stand_pos(self)
spos.y = spos.y+0.01
-- get surface height
-- local surface = mobkit.get_node_pos(spos).y+0.5
local surface = nil
local snodepos = mobkit.get_node_pos(spos)
local surfnode = mobkit.nodeatpos(spos)
while surfnode and surfnode.drawtype == 'liquid' do
surface = snodepos.y+0.5
if surface > spos.y+self.height then break end
snodepos.y = snodepos.y+1
surfnode = mobkit.nodeatpos(snodepos)
end
if surface then -- standing in liquid
self.isinliquid = true
local submergence = min(surface-spos.y,self.height)
local balance = self.buoyancy*self.height
local buoyacc = mobkit.gravity*((balance - submergence)^2/balance^2*sign(balance - submergence))
self.object:set_acceleration({x=-vel.x*self.water_drag,y=buoyacc-vel.y*abs(vel.y)*0.7,z=-vel.z*self.water_drag})
else
self.isinliquid = false
self.object:set_acceleration({x=0,y=mobkit.gravity,z=0})
end
-- local footnode = mobkit.nodeatpos(spos)
-- local headnode
-- if footnode and footnode.drawtype == 'liquid' then
-- vel = self.object:get_velocity()
-- headnode = mobkit.nodeatpos(mobkit.pos_shift(spos,{y=self.height or 0})) -- TODO: height may be nil
-- local submergence = headnode.drawtype=='liquid'
-- and self.buoyancy-1
-- or (self.buoyancy*self.height-(1-(spos.y+0.5)%1))^2/(self.buoyancy*self.height)^2*sign(self.buoyancy*self.height-(1-(spos.y+0.5)%1))
self:physics()
-- local buoyacc = submergence * mobkit.gravity
-- self.object:set_acceleration({x=-vel.x,y=buoyacc-vel.y*abs(vel.y)*0.5,z=-vel.z})
-- end
if self.brainfunc then
-- vitals: fall damage
vel = self.object:get_velocity()
local velocity_delta = abs(self.lastvelocity.y - vel.y)
if velocity_delta > mobkit.safe_velocity then
self.hp = self.hp - floor((self.max_hp-100) * min(1, velocity_delta/mobkit.terminal_velocity))
end
-- vitals: oxygen
if self.lung_capacity then
local colbox = self.object:get_properties().collisionbox
local headnode = mobkit.nodeatpos(mobkit.pos_shift(self.object:get_pos(),{y=colbox[5]})) -- node at hitbox top
if headnode and headnode.drawtype == 'liquid' then
self.oxygen = self.oxygen - self.dtime
else
self.oxygen = self.lung_capacity
end
if self.oxygen <= 0 then self.hp=0 end -- drown
end
if self.logic then
if self.view_range then self:sensefunc() end
self:brainfunc()
self:logic()
execute_queues(self)
end
self.lastvelocity = self.object:get_velocity()
self.time_total=self.time_total+self.dtime
self.time_total=self.time_total+dtime
end
----------------------------
@ -1007,7 +1006,7 @@ function mobkit.lq_dumbjump(self,height,anim)
dir = vector.multiply(dir,3)
end
dir.y = vel.y
self.object:set_velocity(dir,yaw)
self.object:set_velocity(dir)
end
end
mobkit.queue_low(self,func)
@ -1051,6 +1050,7 @@ end
function mobkit.lq_jumpattack(self,height,target)
local phase=1
local timer=0.5
local tgtbox = target:get_properties().collisionbox
local func=function(self)
if not mobkit.is_alive(target) then return true end
@ -1062,6 +1062,7 @@ function mobkit.lq_jumpattack(self,height,target)
mobkit.make_sound(self,'charge')
phase=2
else
mobkit.lq_idle(self,0.3)
return true
end
elseif phase==2 then
@ -1114,7 +1115,7 @@ end
-- HIGH LEVEL QUEUE FUNCTIONS
-----------------------------
function mobkit.dumbstep(self,height,tpos,speed_factor)
function mobkit.dumbstep(self,height,tpos,speed_factor,idle_duration)
if height <= 0.001 then
mobkit.lq_turn2pos(self,tpos)
mobkit.lq_dumbwalk(self,tpos,speed_factor)
@ -1122,7 +1123,8 @@ function mobkit.dumbstep(self,height,tpos,speed_factor)
mobkit.lq_turn2pos(self,tpos)
mobkit.lq_dumbjump(self,height)
end
mobkit.lq_idle(self,random(1,6))
idle_duration = idle_duration or 6
mobkit.lq_idle(self,random(ceil(idle_duration*0.5),idle_duration))
end
function mobkit.hq_roam(self,prty)
@ -1289,7 +1291,7 @@ function mobkit.hq_die(self)
local func = function(self)
if start then
mobkit.lq_fallover(self)
self.brainfunc = function(self) end -- brain dead as well
self.logic = function(self) end -- brain dead as well
start=false
end
timer = timer-self.dtime