123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- local abs = math.abs
- local function node_dps_dmg(self)
- local pos = self.object:get_pos()
- local box = self.object:get_properties().collisionbox
- local pos1 = {x = pos.x + box[1], y = pos.y + box[2], z = pos.z + box[3]}
- local pos2 = {x = pos.x + box[4], y = pos.y + box[5], z = pos.z + box[6]}
- local nodes_overlap = mobkit.get_nodes_in_area(pos1, pos2)
- local total_damage = 0
- for node_def, _ in pairs(nodes_overlap) do
- local dps = node_def.damage_per_second
- if dps then
- total_damage = math.max(total_damage, dps)
- end
- end
- if total_damage ~= 0 then
- mobkit.hurt(self, total_damage)
- end
- end
- function unicorn.node_name_in(self, where)
- local pos = self.object:get_pos()
- local yaw = self.object:get_yaw()
- if yaw then
- local dir_x = -math.sin(yaw)
- local dir_z = math.cos(yaw)
- local pos2
- if where == 'front' then
- pos2 = {
- x = pos.x + dir_x,
- y = pos.y,
- z = pos.z + dir_z,
- }
- elseif where == 'top' then
- pos2= {
- x = pos.x,
- y = pos.y + 0.5,
- z = pos.z,
- }
- elseif where == 'below' then
- pos2 = mobkit.get_stand_pos(self)
- pos2.y = pos2.y - 0.1
- elseif where == 'back' then
- pos2 = {
- x = pos.x - dir_x,
- y = pos.y,
- z = pos.z - dir_z,
- }
- elseif where == 'self' then
- pos2= {
- x = pos.x,
- y = pos.y - 0.75,
- z = pos.z,
- }
- elseif where == 'front_top' then
- pos2= {
- x = pos.x + dir_x,
- y = pos.y + 1,
- z = pos.z + dir_z,
- }
- end
- local node = minetest.get_node_or_nil(pos2)
- if node and minetest.registered_nodes[node.name] then
- return node.name, pos2
- else
- return nil
- end
- else
- return nil
- end
- end
- function unicorn.check_height(self)
- local yaw = self.object:get_yaw()
- local dir_x = -math.sin(yaw) * (self.collisionbox[4] + 0.5)
- local dir_z = math.cos(yaw) * (self.collisionbox[4] + 0.5)
- local pos = self.object:get_pos()
- local ypos = pos.y - self.collisionbox[2] -- just floor level
- local pos1 = {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}
- local pos2 = {x = pos.x + dir_x, y = ypos - self.max_height, z = pos.z + dir_z}
- local blocking_node, blocking_node_pos = minetest.line_of_sight(pos1, pos2, 1)
- if not(blocking_node) then
- local height = ypos - blocking_node_pos.y
- return height
- end
- return false
- end
- function unicorn.check_front_obstacle(self)
- local yaw = self.object:get_yaw()
- local dir_x = -math.sin(yaw) * (self.collisionbox[4] + 0.5)
- local dir_z = math.cos(yaw) * (self.collisionbox[4] + 0.5)
- local pos = self.object:get_pos()
- local nodes_front = 5
- if minetest.line_of_sight(
- {x = pos.x + dir_x, y = pos.y, z = pos.z + dir_z}, {x = pos.x + dir_x + nodes_front, y = pos.y, z = pos.z + dir_z + nodes_front}, 1) then
- return false
- end
- return true
- end
- function unicorn.lq_turn2yaw(self, yaw)
- local func = function(self)
- if mobkit.turn2yaw(self, yaw) then
- return true
- end
- end
- mobkit.queue_low(self,func)
- end
- function unicorn.set_velocity(self, velocity)
- local yaw = self.object:get_yaw() or 0
- self.object:set_velocity({
- x = (math.sin(yaw) * -velocity.x),
- y = velocity.y or 0,
- z = (math.cos(yaw) * velocity.z),
- })
- end
- function unicorn.goto_next_waypoint(self,tpos,speed_fac,anim)
- speed_fac = speed_fac or 1
- anim = anim or 'walk'
- local height, pos2 = mobkit.get_next_waypoint(self,tpos)
- if not height then return false end
- if height <= 0.51 then
- local yaw = self.object:get_yaw()
- local tyaw = minetest.dir_to_yaw(vector.direction(self.object:get_pos(),pos2))
- if abs(tyaw-yaw) > 1 then
- mobkit.lq_turn2pos(self,pos2)
- end
- unicorn.lq_dumbwalk(self,pos2,speed_fac,anim)
- else
- mobkit.clear_queue_high(self)
- mobkit.lq_turn2pos(self,pos2)
- unicorn.hq_fly(self,0)
- end
- return true
- end
- function unicorn.lq_dumbwalk(self,dest,speed_factor, anim)
- local timer = 3 -- failsafe
- speed_factor = speed_factor or 1
- local func=function(self)
- mobkit.animate(self,anim)
- timer = timer - self.dtime
- if timer < 0 then return true end
- local pos = mobkit.get_stand_pos(self)
- local y = self.object:get_velocity().y
- if mobkit.is_there_yet2d(pos,minetest.yaw_to_dir(self.object:get_yaw()),dest) then
- if not self.isonground or abs(dest.y-pos.y) > 0.1 then
- self.object:set_velocity({x=0,y=y,z=0})
- end
- return true
- end
- if self.isonground then
- local dir = vector.normalize(vector.direction({x=pos.x,y=0,z=pos.z},{x=dest.x,y=0,z=dest.z}))
- dir = vector.multiply(dir,self.max_speed*speed_factor)
- mobkit.turn2yaw(self,minetest.dir_to_yaw(dir))
- dir.y = y
- self.object:set_velocity(dir)
- end
- end
- mobkit.queue_low(self,func)
- end
- function unicorn.hq_fly(self, prty)
- local func = function(self)
- if mobkit.is_queue_empty_low(self) then
- unicorn.lq_fly(self, 1.1)
- end
- end
- mobkit.queue_high(self, func, prty)
- end
- function unicorn.lq_fly(self)
- local func = function(self)
- mobkit.animate(self, 'fly')
- unicorn.lq_dumbfly(self, 1.1)
- self.object:set_acceleration({x = 0, y = 4, z = 0})
- end
- mobkit.queue_low(self, func)
- end
- function unicorn.lq_dumbfly(self, speed_factor)
- local timer = 60
- local fly_status = 'ascend'
- speed_factor = speed_factor or 1
- local func = function(self)
- timer = timer - self.dtime
- if timer < 0 then
- local velocity
- mobkit.animate(self, 'fly')
- local random_number = math.random(1,6)
- local yaw = self.object:get_yaw()
- local rotation = self.object:get_rotation()
- if random_number <= 1 or unicorn.node_name_in(self, 'front') ~= 'air' then
- if yaw then
- local rotation_integer = math.random(0, 4)
- local rotation_decimals = math.random()
- local new_yaw = yaw + rotation_integer + rotation_decimals
- unicorn.lq_turn2yaw(self, new_yaw)
- return true
- end
- end
- local y_impulse = 1
- if unicorn.check_front_obstacle(self) and unicorn.node_name_in(self, 'top') == 'air' then
- fly_status = 'ascend'
- y_impulse = 3
- end
- local altitude = unicorn.check_height(self)
- if not(altitude) or unicorn.node_name_in(self, 'top') == 'air' then
- random_number = math.random(1,10)
- if random_number < 7 then
- fly_status = 'descend'
- else
- fly_status = 'hover'
- end
- else
- local node_name = unicorn.node_name_in(self, 'below')
- if minetest.get_item_group(node_name, 'water') >= 1 then
- fly_status = 'ascend'
- end
- if altitude and (altitude < 1) then
- fly_status = 'ascend'
- end
- end
- if fly_status == 'hover' then
- velocity = {x = self.max_speed * speed_factor,
- y = 0,
- z = self.max_speed * speed_factor}
- self.object:set_rotation({x = 0, y = rotation.y, z = rotation.z})
- random_number = math.random(1,10)
- if random_number < 2 and not (altitude) then
- fly_status = 'descend'
- elseif random_number < 4 then
- fly_status = 'ascend'
- end
- elseif fly_status == 'descend' then
- velocity = {x = self.max_speed * speed_factor,
- y = -speed_factor,
- z = self.max_speed * speed_factor}
- self.object:set_rotation({x = .16, y = rotation.y, z = rotation.z})
- random_number = math.random(1,10)
- if random_number < 2 then
- fly_status = 'hover'
- elseif random_number < 4 then
- fly_status = 'ascend'
- end
- else
- fly_status = 'ascend'
- velocity = {x = self.max_speed * speed_factor,
- y = speed_factor * (y_impulse or 1),
- z = self.max_speed * speed_factor}
- self.object:set_rotation({x = -0.16, y = rotation.y, z = rotation.z})
- end
- timer = 60
- unicorn.set_velocity(self, velocity)
- self.fly_velocity = velocity
- return true
- else
- if self.fly_velocity then
- unicorn.set_velocity(self, self.fly_velocity)
- else
- unicorn.set_velocity(self, {x = 0.0, y = 0.0, z = 0.0})
- end
- end
- end
- mobkit.queue_low(self, func)
- end
- function unicorn.hq_runfrom(self,prty,tgtobj)
- local init=true
- local timer=6
- local func = function(self)
- if not mobkit.is_alive(tgtobj) then return true end
- if init then
- timer = timer-self.dtime
- if timer <=0 or vector.distance(self.object:get_pos(),tgtobj:get_pos()) < 8 then
- mobkit.make_sound(self,'scared')
- init=false
- end
- return
- end
- if mobkit.is_queue_empty_low(self) and self.isonground then
- local pos = mobkit.get_stand_pos(self)
- local opos = tgtobj:get_pos()
- if vector.distance(pos,opos) < self.view_range*1.1 then
- local tpos = {x=2*pos.x - opos.x, y=opos.y, z=2*pos.z - opos.z}
- unicorn.goto_next_waypoint(self,tpos,1.1,'gallop')
- else
- self.object:set_velocity({x=0,y=0,z=0})
- return true
- end
- end
- end
- mobkit.queue_high(self,func,prty)
- end
- function unicorn.brain(self)
- local pos = self.object:get_pos()
- local die = false
- mobkit.vitals(self)
- if self.hp <= 0 then
- die = true
- mobkit.clear_queue_high(self)
- mobkit.hq_die(self)
- mokapi.drop_items(self)
- return
- end
- if die then
- petz.on_die(self)
- return
- end
- if mobkit.timer(self,1) then
- local prty = mobkit.get_queue_priority(self)
- local pos = self.object:get_pos()
- if prty < 25 then
- if self.driver then
- petz.hq_mountdriver(self, 25)
- return
- end
- end
- if prty < 20 and self.isinliquid then
- mobkit.hq_liquid_recovery(self,20)
- return
- end
- if prty < 16 then
- local player = mobkit.get_nearby_player(self)
- if petz.bh_start_follow(self, pos, player, 16) then
- return
- end
- end
- if prty == 16 then
- local player = mobkit.get_nearby_player(self)
- if petz.bh_stop_follow(self, player) then
- return
- end
- end
- if prty < 10 then
- if not(self.tamed) then
- local player = mobkit.get_nearby_player(self)
- if player then
- local player_pos = player:get_pos()
- local player_wield = player:get_wielded_item():get_name()
- if vector.distance(pos, player_pos) < 8 and player_wield ~= 'unicorn:apple' then
- unicorn.hq_runfrom(self,10,player)
- return
- end
- end
- end
- end
- if mobkit.is_queue_empty_high(self) and not(self.status) and not(self.wagon) then
- mobkit.hq_roam(self,0)
- end
- end
- end
|