Example mobkit mob

Post Reply
User avatar
MisterE
Member
Posts: 693
Joined: Sun Feb 16, 2020 21:06
GitHub: MisterE123
IRC: MisterE
In-game: MisterE

Example mobkit mob

by MisterE » Post

Code: Select all






local dirt_man_brain = function(self)

        
        local pos = mobkit.get_stand_pos(self)
        local prty = mobkit.get_queue_priority(self)
        local player = mobkit.get_nearby_player(self)

        mob_core.random_sound(self, 16/self.dtime)
        --death handling
        if self.hp <= 0 then    
                local stored_drops = mobkit.recall(self,"stored_drops")
                if stored_drops then
                        for _,item in pairs(stored_drops) do
                                if item then
                                        minetest.add_item(pos,item)
                                end
                        end
                end
                mob_core.on_die(self)
                minetest.add_particlespawner({
                        amount = 100,
                        time = 2,
                        minpos = {x=pos.x-1, y=pos.y-1, z=pos.z-1},
                        maxpos = {x=pos.x+1, y=pos.y+1, z=pos.z+1},
                        minvel = {x=-0, y=-0, z=-0},
                        maxvel = {x=1, y=1, z=1},
                        minacc = {x=-0.5,y=5,z=-0.5},
                        maxacc = {x=0.5,y=5,z=0.5},
                        minexptime = 0.1,
                        maxexptime = 1,
                        minsize = 1,
                        maxsize = 3,
                        collisiondetection = false,
                        texture="default_dirt.png"
                })
                return
        end
        --light and water damages
        if mobkit.timer(self,2) then
                if minetest.get_node_light(pos) > 10 then
                        mobs_creatures.flash_red(self)
                        mobkit.hurt(self,1)
                        if math.random(1,3) == 1 then
                                mob_core.make_sound(self, "hurt")
                        end
                        minetest.add_particlespawner({
                                amount = 10,
                                time = .1,
                                minpos = {x=pos.x-1, y=pos.y-1, z=pos.z-1},
                                maxpos = {x=pos.x+1, y=pos.y+1, z=pos.z+1},
                                minvel = {x=-0, y=-0, z=-0},
                                maxvel = {x=1, y=1, z=1},
                                minacc = {x=-0.5,y=5,z=-0.5},
                                maxacc = {x=0.5,y=5,z=0.5},
                                minexptime = 0.1,
                                maxexptime = 1,
                                minsize = 1,
                                maxsize = 3,
                                collisiondetection = false,
                                texture="default_dirt.png"
                        })
                end
                -- extra water damage, dirt disintigrates in water
                if self.isinliquid then
                        mobs_creatures.flash_red(self)
                        mobkit.hurt(self,1)
                        if math.random(1,3) == 1 then
                                mob_core.make_sound(self, "hurt")
                        end
                        minetest.add_particlespawner({
                                amount = 10,
                                time = .1,
                                minpos = {x=pos.x-1, y=pos.y-1, z=pos.z-1},
                                maxpos = {x=pos.x+1, y=pos.y+1, z=pos.z+1},
                                minvel = {x=-0, y=-0, z=-0},
                                maxvel = {x=1, y=1, z=1},
                                minacc = {x=-0.5,y=5,z=-0.5},
                                maxacc = {x=0.5,y=5,z=0.5},
                                minexptime = 0.1,
                                maxexptime = 1,
                                minsize = 1,
                                maxsize = 3,
                                collisiondetection = false,
                                texture="default_dirt.png"
                        })
                end
        end

        --decision_making, every second
        if mobkit.timer(self,1) then

                mob_core.vitals(self)
                mob_core.growth(self)

                item = mobs_creatures.find_item_inside_radius(self, self.view_range, 'default:dirt')
                status = self.status
                if not status then
                        mobkit.remember(self, "status", "")
                        status = ''
                end

                if status == 'seeking_item' then
                        if prty < 40 and player then
                                if self.isinliquid then
                                        mob_core.hq_aqua_attack(self, math.random(41,69) , puncher, 3)
                                else
                                        mob_core.hq_hunt(self, math.random(41,69) , player)
                                end
                        end
                        if prty < 50 and self.isinliquid then
                                mobkit.hq_liquid_recovery(self, prty + 1)
                        end


                elseif status == 'hunting' then

                        if prty < 60 and item then
                                mobs_creatures.hq_seek_item(self, prty + 1, 'default:dirt')
                                
                        end
                        if prty < 50 and self.isinliquid then
                                mobkit.hq_liquid_recovery(self, prty+1)
                        end


                else --status == ''

                        if prty < 50 and item then
                                mobs_creatures.hq_seek_item(self, math.random(1,49), 'default:dirt')
                        end
                        if prty < 70 and player then
                                if self.isinliquid then
                                        mob_core.hq_aqua_attack(self, math.random(41,69) , puncher, 3)
                                else
                                        mob_core.hq_hunt(self, math.random(41,69) , player)
                                end
                        end
                        if prty < 40 and self.isinliquid then
                                mobkit.hq_liquid_recovery(self,math.random(41,55))
                        end
                        


                end

                if mobkit.is_queue_empty_high(self) then
                        mob_core.hq_roam(self, 0, 1)
                        self.status = mobkit.remember(self,'status','')
                end        
        
                -- if prty < math.random(0,50) and not mobkit.recall(self, 'status') == "seeking_item" and item then 
                --         mobs_creatures.hq_seek_item(self, 20, 'default:dirt')
                -- end


                -- if prty < 20 and player and not(player:get_player_name() == self.owner) then
                --         if self.isinliquid then
                --                 mob_core.hq_aqua_attack(self, 20, puncher, 3)
                --         else
                --                 mob_core.hq_hunt(self, 20, player)
                --         end
                -- end



                -- if self.isinliquid and prty < 20 then
                --         mobkit.hq_liquid_recovery(self,20)
                -- end

                -- if mobkit.is_queue_empty_high(self) then
                --         mob_core.hq_roam(self, 0, 1)
                -- end
        end
end



minetest.register_entity("mobs_creatures:dirt_man",{
        max_hp = 45,
        view_range = 15,
        reach = 2,
        armor = 100,
        damage = 4,
        passive = false,
        armor_groups = {fleshy=75},
        physical = true,
        collide_with_objects = true,
        collisionbox = {-0.4, -1, -0.4, 0.4, 0.8, 0.4},
        visual_size = {x=1,y=1},
        scale_stage1 = 0.5,
        scale_stage2 = 0.65,
        scale_stage3 = 0.80,
        visual = "mesh",

        mesh = "mobs_character.b3d",
        textures = {"mobs_creatures_dirt_man.png"},
        animation = {
                stand = {range={x=0,y=79},speed=30,loop=true},
                walk={range={x=168,y=187},speed=30,loop=true},		-- single
                run={range={x=168,y=187},speed=40,loop=true},		-- single
                attack={range={x=200,y=219},speed=30,loop=true},		-- single
        },
        obstacle_avoidance_range = 5,
        surface_avoidance_range = 0,
	floor_avoidance_range = 0,
        sounds = {
                random = "mobs_creatures_dirt_man_random",
                hurt = "default_dirt_footstep",
                attack = "default_dirt_footstep",
                jump = "default_dirt_footstep",
                death = "default_dirt_footstep",
        
        },
        max_speed = 3,					-- m/s
        stepheight = 1.1,				
        jump_height = 1.1,
        buoyancy = .7,
        lung_capacity = 10, 		-- seconds
        ignore_liquidflag = true,			
        timeout = 500,	
        semiaquatic = false,
        core_growth = false,	
        push_on_collide = true,
        catch_with_net = false,
        follow = {},                
        drops = {{name = "default:dirt", chance = 1, min = 1, max = 1},},
        on_step = better_fauna.on_step,
        on_activate = better_fauna.on_activate,		
        get_staticdata = mobkit.statfunc,
        logic = dirt_man_brain,		        
        attack={range=2,damage_groups={fleshy=4}},	
        damage_groups={{fleshy=4}},
        knockback = .05,
        defend_owner = true,
        on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
                if time_from_last_punch < .5 then return end --dont hurt more than every .5 sec, cant make this tooo easy


                mob_core.on_punch_basic(self, puncher, tool_capabilities, dir)
                local prty = mobkit.get_queue_priority(self)
                if prty < 60 then
                        mobkit.clear_queue_high(self)
                end
                local new_prty = prty + 5
                if self.status ~= 'hunting' then
                        new_prty = math.random(60,100)
                end
                if new_prty > 95 then
                        new_prty = 100
                end
                if self.hp > 5 then
                        if mobkit.is_alive(self) then
                                local pos = self.object:get_pos()
                                if not(self.isinliquid) then
                                        mob_core.hq_hunt(self, new_prty, puncher)
                                else
                                        mob_core.hq_aqua_attack(self, new_prty, puncher, 1) 
                                end
                        end
                else
                        if mobkit.is_alive(self) then
                                local pos = self.object:get_pos()
                                if not(self.isinliquid) then
                                        mobkit.hq_runfrom(self, new_prty, puncher)
                                else
                                        mob_core.hq_swimfrom(self, new_prty, puncher, 1)
                                end
                        end 
                end
                
                
                
        end,
})



mob_core.register_spawn({
	name = 'mobs_creatures:dirt_man',
	nodes = {"default:dirt_with_grass", "ethereal:gray_dirt"},
	min_light = 0,
	max_light = 7,
	min_height = -500,
	max_height = 100,
	group = 3,
	optional = {
                reliability = 3
	}
}, 10, 60)


mob_core.register_spawn_egg("mobs_creatures:dirt_man", "45160a" ,"24db0f")
-- mob_core.register_set("mobs_walrus:walrus", "mobs_walrus_walrus1.png", true)


the above needs the dirt man from various mobs_redo packs, it needs mobkit, mob_core, and better_fauna (you probably could replace refs to better_fauna with mob_core and be fine.

The special behavior of picking up dirt and keeping it needs the following functions (properly named for the mod):

Code: Select all



function mobs_creatures.pick_up_drops(self, radius, item)
    local pos = mobkit.get_stand_pos(self)
    local objects = minetest.get_objects_inside_radius(pos, radius)
    --minetest.chat_send_all('92')
    if #objects < 1 then return end
    for _, object in ipairs(objects) do
        local ent = object:get_luaentity()
        if ent and ent.name == "__builtin:item" then
            local itemstring = ent.itemstring
            local stack = ItemStack(itemstring)
            local count = stack:get_count()
            --minetest.chat_send_all(dump(ent))
            if item == nil or item == 'any' or ItemStack(itemstring):get_name() == ItemStack(item):get_name() then
                local stored_drops = {} --stored_drops is a table of itemstrings
                local prev_drops = mobkit.recall(self,"stored_drops")
                if prev_drops then
                    stored_drops = prev_drops
                end
                table.insert(stored_drops,itemstring)

                mobkit.remember(self, "stored_drops", stored_drops)

                object:remove()
            end
        end
    end
end




function mobs_creatures.find_item_inside_radius(self, radius, item)
    local pos = mobkit.get_stand_pos(self)
    local objects = minetest.get_objects_inside_radius(pos, radius)
    if #objects < 1 then return end
    for _, object in ipairs(objects) do
        local ent = object:get_luaentity()
        if ent and ent.name == "__builtin:item" then
            local itemstring = ent.itemstring
            if item == nil or item == 'any' or ItemStack(itemstring):get_name() == ItemStack(item):get_name() then
                return object
            end
        end
    end
end


function mobs_creatures.hq_seek_item(self, prty, itemstring)
    local init = false
    local timer = 2
    local func = function(self)
        local item = mobs_creatures.find_item_inside_radius(self, self.view_range, itemstring)
        if not item then return true end
        if not init then
            timer = timer - self.dtime
            
            if timer <= 0 or vector.distance(self.object:get_pos(), item:get_pos()) < 8 then
                init = true
                mobkit.animate(self, "run")
            end
        end
        self.status = mobkit.remember(self, "status", "seeking_item")
        if mobkit.is_queue_empty_low(self) and self.isonground then
            local pos = mobkit.get_stand_pos(self)
            local opos = item:get_pos()
            if vector.distance(pos, opos) < self.view_range * 1.1 then

                mob_core.goto_next_waypoint(self, opos)
                mobs_creatures.pick_up_drops(self,0.8,itemstring)

            else
                
                mobkit.lq_idle(self, 1, "stand")
                self.status = mobkit.remember(self, "status", "seeking_item")
                
                -- self.object:set_velocity({x = 0, y = 0, z = 0})
                
                return true
            end
        end
    end
    mobkit.queue_high(self, func, prty)
end



the purpose for posting this is to give an example of using mob_kit and mob_core to make better mobs. License is GPL, and I recieved a lot of help from ElCeejo to understand and debug code

User avatar
MisterE
Member
Posts: 693
Joined: Sun Feb 16, 2020 21:06
GitHub: MisterE123
IRC: MisterE
In-game: MisterE

Re: Example mobkit mob

by MisterE » Post

you can download the WIP conversion mob pack here:

https://github.com/MisterE123/mobs_creatures-mobkit

Adnunano
Member
Posts: 43
Joined: Thu Feb 13, 2020 09:28

Re: Example mobkit mob

by Adnunano » Post

I have been trying to convert but no luck.It crashes.
Spoiler




-- local badger_brain = function(self)

-- if self.hp <= 0 then
-- mob_core.on_die(self)
-- return
-- end

-- local pos = mobkit.get_stand_pos(self)
-- local prty = mobkit.get_queue_priority(self)
-- local player = mobkit.get_nearby_player(self)



-- if mobkit.is_queue_empty_high(self) then
-- mob_core.hq_roam(self, 0)
-- end
-- end
-- end

local badger_brain = function(self)

if self.hp <= 0 then
mob_core.on_die(self)
return
end

local pos = mobkit.get_stand_pos(self)
local prty = mobkit.get_queue_priority(self)
local player = mobkit.get_nearby_player(self)

mob_core.random_sound(self, 16/self.dtime)

if mobkit.timer(self,1) then

mob_core.vitals(self)
mob_core.growth(self)

if self.status ~= "following" then
if self.attention_span > 1 then
self.attention_span = self.attention_span - 1
mobkit.remember(self, "attention_span", self.attention_span)
end
else
self.attention_span = self.attention_span + 1
mobkit.remember(self, "attention_span", self.attention_span)
end

-- if prty < 3
-- and self.breeding
-- and self.isonground then
-- better_fauna.hq_breed(self, 3)
-- end

if prty < 2
and player then
if self.attention_span < 5 then
if mob_core.follow_holding(self, player) then
if self.isinliquid then
mob_core.hq_follow_holding(self, 2, player)
else
mob_core.hq_aqua_follow_holding(self, 2, player)
end
self.attention_span = self.attention_span + 1
end
end
end

if mobkit.is_queue_empty_high(self) then
if self.isinliquid then
mob_core.hq_aqua_roam(self, 0, 3)
else
mob_core.hq_roam(self, 0)
end
end
end
end




minetest.register_entity("mobs_doomed:badger",{

-- required minetest api props
max_hp = 22,
view_range = 14,
reach = 1,
armor = 130,
damage = 2,
passive = false,
armor_groups = {fleshy=75},
physical = true,
collide_with_objects = true,
collisionbox = {-0.3, -0.15, -0.3, 0.3, 0.4, 0.3},
visual_size = {x=2,y=2},
scale_stage1 = 0.5,
scale_stage2 = 0.65,
scale_stage3 = 0.80,
visual = "mesh",
mesh = "badger.b3d",
textures = {"mobs_doomed_badger.png",},
animation = {
walk={range={x=34,y=58},speed=12,loop=true},
run={range={x=34,y=58},speed=18,loop=true},
stand={range={x=1,y=30},speed=15,loop=true},
punch={range={x=60,y=80},speed=15,loop=true}, -- single
},


obstacle_avoidance_range = 4,
surface_avoidance_range = 0,
floor_avoidance_range = 0,



max_speed = 1,
stepheight = 1.1,
jump_height = 1.1, -- no
buoyancy = 0.5, -- (0
lung_capacity = 10, -- seconds
timeout = 1200,
ignore_liquidflag = false, -- range is distance between
semiaquatic = false,
core_growth = false,
push_on_collide = true,
catch_with_net = false,

follow = {
"water_life:riverfish",
"water_life:piranha",
"water_life:coralfish",
"water_life:clownfish",
"water_life:urchin_item",
},
drops = {
{name = "water_life:meat_raw", chance = 1, min = 2, max = 5},
},

mob_core.register_spawn({
name = "mobs_doomed:badger",
nodes = {"default:dirt_with_grass", "default:dirt_with_coniferous_litter", "default:dirt"},
min_light = 0,
max_light = 20,
min_height = -31000,
max_height = 31000,
group = 1,
end
mob_core.register_spawn_egg("mobs_doomed:badger", "f5cc5b" ,"b57b24")
mobs:register_mob("mobs_doomed:badger", {
type = "animal",
passive = false,
reach = 1,
damage = 2,
attack_type = "dogfight",
specific_attack = {
"mobs_doomed:hedgehog",
"mobs_bugslive:bug",
"mobs_better_rat:rat",
"mobs_animal:rat",
},

hp_min = 12,
hp_max = 22,
armor = 130,
collisionbox = {-0.3, -0.15, -0.3, 0.3, 0.4, 0.3},
visual = "mesh",
mesh = "badger.b3d",
textures = {
{"mobs_doomed_badger.png"},
},
blood_texture = "mobs_blood.png",
visual_size = {x=2, y=2},
makes_footstep_sound = true,
walk_velocity = 0.7,
run_velocity = 1,
jump = true,
drops = {
{name = "mobs:meat_raw", chance = 1, min = 1, max = 3},
},
water_damage = 0,
lava_damage = 2,
light_damage = 0,
fall_damage = 1,
fall_speed = -8,
fear_height = 4,
view_range = 14,
animation = {
speed_normal = 12,
speed_run = 18,
walk_start = 34,
walk_end = 58,
stand_start = 1,
stand_end = 30,
run_start = 34,
run_end = 58,
punch_start = 60,
punch_end = 80,
},
follow = {
"mobs_doomed:hedgehog",
"mobs_bugslive:bug",
"mobs_better_rat:rat",
"mobs_animal:rat",
"mobs:egg",
},
on_rightclick = function(self, clicker)
if mobs:feed_tame(self, clicker, 8, true, true) then return end
if mobs:protect(self, clicker) then return end
if mobs:capture_mob(self, clicker, 0, 5, 50, false, nil) then return end
end,
})

mobs:register_egg("mobs_doomed:badger", "Badger", "default_obsidian.png", 1)

mobs:spawn_specific("mobs_doomed:badger",
{
"default:dirt_with_grass",
"default:dirt",
"default:dirt_with_coniferous_litter"
},
{"air"},
0, 14, 30, 300000, 2, 0, 5000)
NfAPhpmGaVphBjK8NIr9Mit5xNW2emD2

User avatar
MisterE
Member
Posts: 693
Joined: Sun Feb 16, 2020 21:06
GitHub: MisterE123
IRC: MisterE
In-game: MisterE

Re: Example mobkit mob

by MisterE » Post

where is your brainfunc aka logic?

Edit: ah, in the spoiler

When I convert mobs, it crashes too. Im not good at writing code. you have to look in the debug and figure out WHAT is causing the crash. If you post a github (or similar) link, I will took at it myself.

Alternatively, you could post the error, and that would give a clue as to the problem.

User avatar
MisterE
Member
Posts: 693
Joined: Sun Feb 16, 2020 21:06
GitHub: MisterE123
IRC: MisterE
In-game: MisterE

Re: Example mobkit mob

by MisterE » Post

OK,so there are LOTs of problems with your code.

First, you keep referencing "mobs" functions. As of the moment you decide to convert the mob, "mobs" is dead. From now on, you must reference mobkit functions only. If you depend on a helpful api, you an also call water_life or mob_core functions. You can also write your own functions. But any reference to mobs_redo, aka mobs: is not available.

Second, mobs_redo and mobkit have different ways of defining properties. It seems that you simply copied the mobs_redo definition:

Code: Select all

mobs:register_mob("mobs_doomed:badger", {
mobkit just uses:

Code: Select all

minetest.register_entity("mobs_doomed:badger",{
Mobs_redo properties and mobkit properties are different too. You have to use the resources and apis and examples in/with mobkit and mob_core to figure out the proper properties of your mob. You definitely cant just copy/paste. You actually have to "translate" the mobs_redo properties and behaviors into *similar* mobkit properties and behaviors.

Once you know what you are doing, it is kind of easy, though it is always easy to make mistakes. Debug is your friend. It will tell you, usually, what kind of error occured and which line it occured on. I bet that the error you were getting was that you are trying to call undefined global variable "mobs". This is because you are trying to call the mobs_redo entity registration function, which no longer exists.

ShadMOrdre
Member
Posts: 1118
Joined: Mon Dec 29, 2014 08:07
Location: USA

Re: Example mobkit mob

by ShadMOrdre » Post

So is there good documentation / code organization to assist with identifying which functions would be used setting up the various mods.

I've got around 65 animals, and at least 20 monster mobs, all mobs_redo. If general performance is improved, I'd like to consider moving the mobs from mobs_redo. How much of this is complete / standalone, or will mob_core and water_life be necessary? It would be best to have all the functionality seperate from the content, so if other mods are needed to add functionality, it seems that things are becoming fragmented in not so good ways. I'd like to see all relevant logic for mobs/NPC behavior, well documented, and easy to assemble "behaviors", packaged together. Otherwise the incentive to move away from mobs_redo becomes less motivating.

Thanks for this example, nonetheless, as it provides a starting point. Since mob behavior differs according to the type of mob in question, can you at least provide an example of a flying mob, swimming mob, predator and prey type mobs, and domesticated type mob. Say, an example bird, fish, wolf-zebra / shark-fish, and sheep / cow / pig. I know this sounds like a lot, but I do believe it will encourage developers such as myself, to adopt this mob framework, and to start developing for it.

Shad

Termos
Member
Posts: 417
Joined: Sun Dec 16, 2018 12:50

Re: Example mobkit mob

by Termos » Post

ShadMOrdre wrote:
Mon Jan 18, 2021 08:46
I've got around 65 animals, and at least 20 monster mobs, all mobs_redo. If general performance is improved, I'd like to consider moving the mobs from mobs_redo.
redo and mobkit are quite different barrels of fish, redo is a ready to go customizable mob, mobkit is a library for coding any entities possible.
If you're satisfied with how your mobs behave I'd say stick with redo. If performance is a concern, consider getting rid of redo's spawn ABMs and using mobkit.get_spawn_pos_abr() which is orders of magnitude less resource hungry.

mobkit documentation is inside the package (I'd appreciate any comments as to its usefulness)
If you're interested, my example mods are Wildlife, Zombies: The Real Deal - Now with Sharks and Sailing Kit
Mobkit behaviors are each a separate function, mostly to be user provided but there are some example behaviors included, and as I understand mob_core is an user behavior pack made by El_Ceejo.

User avatar
MisterE
Member
Posts: 693
Joined: Sun Feb 16, 2020 21:06
GitHub: MisterE123
IRC: MisterE
In-game: MisterE

Re: Example mobkit mob

by MisterE » Post

let me be clear, I am not a very good programmer, and I am only just starting to learn to use mobkit. I am relying heavily on mob_core functions to get the job done. The above example could be simplified and could be better organized. However, it works. I, a mobkit noob, with a lot of help, managed to get it to work. One of the main purposes of this post is that you can get it to work too.

As Termos said, mobkit provides a framework for making any mob imaginable.
Meanwhile mobs_redo provides certain built-in behaviors and ready-to-go mobs that can use them.
Mobkit and mob_core's spawning functions are much better than mobs_redo.

The main advantage of using mobkit is that you can program unique behaviors, with many different subtle interactions with the world, other mobs, and players. For example, instead of a skeleton archer simply shooting, you could have him shoot, then if the player got close enough, make him run away to avoid being killed. Then, if the player was very close, turn and fight meele style. ( I am currently working on this functionality)

so far, there are 4 sources of ready-to-go behavior functions. Mobkit example behaviors, mob_core, better_fauna (which builds on mob_core) and water_life. Each has its own api (basically, you can call its functions because they are in a global table named after the mod.) If you want to keep everything simple and consolidated, you should make your own mod, with its own api. Then you should copy functions from other mods that provide them, rename them, add to them, and change them however you see fit. What I am doing, personally, Is making an api in my mobs mod that contains any functions that I find necessary to have. Typically this involves copying functions from mob_core and editing them to do something slightly different. Sometimes I have to write almost from scratch. Sometimes I copy functionality from mobs_redo. If you don't like the fragmentation of mob_core, better_fauna, mob_kit, etc, then simply adapt them all into your own api. Then build on that api as you need.

I have only just started learning to convert and improve mobs_redo mobs. Personally, I have decided to use mobkit example behaviors, mob_core, and better_fauna functions. I have also written behavior functions, which often involve copying an existing behavior function and modifying it to my needs. ElCeejo on discord has been very helpful in getting me to understand stuff so far.
ShadMOrdre wrote:
Mon Jan 18, 2021 08:46
So is there good documentation / code organization to assist with identifying which functions would be used setting up the various mods.

Shad
good documentation - NO. there is sufficient documentation for a determined individual to figure it out.
however, I think that that situation is being improved.
code organization - YES
mobkit is VERY WELL ORGANIZED. Mob_core is pretty well organized. They are all much better organized than redo, in that they are intended to be expanded and improved upon, whereas redo is difficult to expand upon. (though possible). The catch is that mobkit ONLY gives a framework to write a brain. YOU then actually have to write that brain, unless you use brain functions that others have written. Mob_core gives many useful brain functions. You can easily-ish modify those brainfunctions if you need to.

ShadMOrdre wrote:
Mon Jan 18, 2021 08:46

I've got around 65 animals, and at least 20 monster mobs, all mobs_redo. If general performance is improved, I'd like to consider moving the mobs from mobs_redo. How much of this is complete / standalone, or will mob_core and water_life be necessary? It would be best to have all the functionality seperate from the content, so if other mods are needed to add functionality, it seems that things are becoming fragmented in not so good ways. I'd like to see all relevant logic for mobs/NPC behavior, well documented, and easy to assemble "behaviors", packaged together. Otherwise the incentive to move away from mobs_redo becomes less motivating.


Shad
the two reasons to switch are better spawning and more complex behaviors/interactions. However someone has to program these behaviors/interactions. mob_core provides some very good functionality, but it is not yet sufficient to replicate all mobs_redo functionality. I also have many animals and monsters to port over. I am having to develop my own api that provides functionality that I have to define myself. Right now, I am working on shooting arrows. It is perfectly possible to have all the functionality separate from the content. mob_core is JUST functionality. you could easily organize a modpack that keeps all the functionality mods together. You would have to document stuff yourself or wait until better docs are available.

ShadMOrdre wrote:
Mon Jan 18, 2021 08:46

Thanks for this example, nonetheless, as it provides a starting point. Since mob behavior differs according to the type of mob in question, can you at least provide an example of a flying mob, swimming mob, predator and prey type mobs, and domesticated type mob. Say, an example bird, fish, wolf-zebra / shark-fish, and sheep / cow / pig. I know this sounds like a lot, but I do believe it will encourage developers such as myself, to adopt this mob framework, and to start developing for it.

Shad
I will not *agree* to do that (perhaps ElCeejo will), but I may get around to it. I already have a flying mob (bat), that mostly works the way I want. Better docs really are needed. I posted this post as a documentary of my foray into mobkit so far. I may help contribute to the actual docs, especially as that will help myself better understand what I am working with :)

User avatar
MisterE
Member
Posts: 693
Joined: Sun Feb 16, 2020 21:06
GitHub: MisterE123
IRC: MisterE
In-game: MisterE

Re: Example mobkit mob

by MisterE » Post

Ok, I have started a thread that will be a better explanation of mobkit and mob_core.
check it out:

viewtopic.php?f=9&t=26046&p=388461#p388461

ShadMOrdre
Member
Posts: 1118
Joined: Mon Dec 29, 2014 08:07
Location: USA

Re: Example mobkit mob

by ShadMOrdre » Post

@Termos, @MisterE,

Thank you both for such detailed info.

After accumulating a number of mobs_redo mobs, reworking the spawn ABM, and still feeling like they are nothing more than randomly moving entities, I am still left wanting. Even with Advanced_NPC, smart_mobs, and nssm, I feel like life in MT worlds is less than believable, much less, not fun to play with.

In Opensim, I created an NPC brain, composed of multiple scripts, each controlling an aspect of the NPC, (ie, movement, sensors, communication, pathfinding, and object interaction. Due to the obvious differences in environments, those scripts work asynchronously to create very believable NPCs.

Mobs_redo does not give me the set of tools I need, but I have a strong feeling that mobkit might have even replicated some of the ideas I had for the Opensim NPCs.

Once I've completed the final mass update to my geology and ecology mods, the GAL project, I want to turn my attention to mobs. My recent experiments with a basic mob NPC were less than stellar, by got me familiar enough with mobs_redo mob definitions.

I recently downloaded mobkit, water_life, and zombies, aerotest, cows, and sailing. I liked what I saw inworld. Not just the updated models, but also a more familiar behavior. Antelopes running away, and sharks that would attempt a bite during a charge attack, but swimming on through the charge, turning, and taking another charge, instead of melee until death.

MisterE, I'll add what knowledge I can extract to your new mobkit primer post.


Shad

User avatar
MisterE
Member
Posts: 693
Joined: Sun Feb 16, 2020 21:06
GitHub: MisterE123
IRC: MisterE
In-game: MisterE

Re: Example mobkit mob

by MisterE » Post

Yes, all that functionality and lots of other rich interaction is possible with mobkit.

If you are willing to spend the time, you can program practically any behavior you like. As an example, gundul recently updated water_life with gulls that swoop down and try to steal bread out of your hand.

I am working on converting this mod of mobs over to mobkit. I would be very interested in seeing what you accomplish when you start programming for it. Feel free to use what I make there according to it permissive license.

when you say that it would be best to have functionality separate from content, the best I can suggest is that you start your own api. Waterlife has a setting for api only, but I dont have experience using water_life's api.
I would suggest that, whenever you need to use an api's function, you put in a line in your api that reads something like:

Code: Select all

myapi.hq_hunt = mob_core.hq_hunt(self)
rename all the functions you use to use your api's namespace. Then, whenever you want to get rid of the dependency on mob_core, all you have to do is to copy all the functions in mob_core over to your api, rename them, and viola! you have a custom api. You probably want to wait on copying and just reference the functions by name as suggested above, though, for a while, because mob_core and water_life are under active development, and the functions will get better with time. Meanwhile, whenever you need to edit a mob_core function because it doesnt do exactly what you want, or because you need new functionality (You will!), all you have to do is use you api's namespace, and put it in your api's files. When you change anything, you won't have to worry about editing all those mob files to change the function namespace calls.

P.S, I just finished the third post in the mobkit primer. It took a while, but gives a pretty complete intro to making your first mobkit mob, using mob_core as a library (which is all I can do right now)

Post Reply

Who is online

Users browsing this forum: No registered users and 14 guests