ElCeejo / paleotest

Adds Prehistoric Fauna and Flora to Minetest Game
GNU General Public License v3.0
4 stars 7 forks source link

Spawn in Wild #5

Open HeyITGuyFixIt opened 3 years ago

HeyITGuyFixIt commented 3 years ago

Could there be a setting to allow dinosaurs to spawn in the wild? It would make trying to survive a lot harder.

ElCeejo commented 3 years ago

That'd be perfectly do-able. I can't promise it'll be added soon but certainly at some point.

HeyITGuyFixIt commented 3 years ago

The time_travel mod uses paleotest to spawn dinosaurs in various biomes. If I have time, I can use that mod as a base to work with. I'll look into it and create pr.

HeyITGuyFixIt commented 3 years ago

I started looking into it, and I realized time_travel relies on mobs redo for spawning, which appears to be much simpler than mobkit spawning. So it won't be as easy as I thought it was going to be. I'll still try to put together a pr though

JDSoar commented 3 years ago

Hey all, Just to put in my two cents worth, I really like HeyITGuyFixIt's suggestion as I generally like to play in survival mode! His suggestion would make for more challenging gameplay. I hope this feature can be added in the future. Unfortunately, I'm only somewhat familiar with Lua code so I wouldn't be very much help. I tried looking at it today, but I'm not getting very far. The mob_kit does not seem to have very much documentation; unlike mobs redo. So anyway, I just wanted to voice my support for this project! Have a great day!

HeyITGuyFixIt commented 3 years ago

@JDSoar I asked the creator of mobkit about spawning and they told me,

there's this function available mobkit.get_spawn_pos_abr() The examples don't use the function, because they predate it.

Still isn't going to be as simple as redo, because it just uses ABMs which are - pros: trivial to implement, cons: works horribly.

Hopefully that helps anyone who wants to give this a try as well. I just need to find time to actually do it.

HeyITGuyFixIt commented 3 years ago

Here's the documentation for that function mentioned above:

function mobkit.get_spawn_pos_abr(dtime,intrvl,radius,chance,reduction)
    -- returns a potential spawn position at random intervals
    -- intrvl: avg spawn attempt interval for every player
    -- radius: spawn distance in nodes, active_block_range*16 is recommended
    -- chance: (0,1) chance to spawn a mob if there are no other objects in area
    -- reduction: (0,1) spawn chance is reduced by this factor for every object in range.
    --usage:
    minetest.register_globalstep(function(dtime)
        local spawnpos = mobkit.get_spawn_pos_abr(...)
        if spawnpos then
            ...                             -- mod/game specific logic
        end
    end)

Can't say I know what comes next, but that is a start.

JDSoar commented 3 years ago

Hey Christian, Thanks for passing that critical information to me! I was able to get something to work.....well kinda.

Screenshot (75)

I implemented the code into the bottom of the Tyrannosaurus.lua file and I was able to get tyrannosauruses to spawn by themselves! Except, I started getting error messages and all the dinosaurs started all spawning in the same spot very rapidly. Hence the picture.

Here is the code that I used; I am going to try to work on it some more to get the number of dinosaurs a little more reasonable. Also, I need to mess with the values in the mobkit.get_spawn_pos_abr() function. Note: if you see anything that should be done a different way please bring it to light. This is just a rough, rough draft.

minetest.register_globalstep(function(dtime) local spawnpos = mobkit.get_spawn_pos_abr(1, 1, 32, 1, 0) if spawnpos then minetest.add_entity(spawnpos, "paleotest:tyrannosaurus") end end)

HeyITGuyFixIt commented 3 years ago

@JDSoar the first parameter needs to be dtime. That might help some things. So mobkit.get_spawn_pos_abr(dtime, 1, 32, 1, 0). They are spawning so rapidly probably because of that and because the chance of spawning is 100% with 0% reduction. Definitely experiment with fractions.

I don't understand the interval parameter, so I'm not sure what to expect by changing it.

With the radius, 32 might be okay.

I took a look at the source code for this function and I am having a hard time understanding it's logic. It would help to understand what it's doing so we can figure out easier what values we should be setting and why those values.

JDSoar commented 3 years ago

Hey @HeyITGuyFixIt ,

Thanks for the suggestion about using the dtime. That slowed the spawn rate way down!

Concerning the interval parameter, I noticed that when you increase the value fewer dinosaurs spawn. So, I bumped up the value to 50. This will work for now, but we need to consider increasing it in the future if we have multiple dinosaurs types spawning. The world might get I little overrun with dinosaurs.

And concerning the radius of 32, I just used that as a place holder. I had trouble implementing the recommended value of active_block_range*16.

One problem I have noticed is when the tyrannosauruses spawn, they just standstill. They are not moving around unless you hit them; then they will attack you. This needs to be fixed. Do you know what to do about it?

HeyITGuyFixIt commented 3 years ago

If you can figure out how to get the entity, use this to tell it to spawn, where self is the registered entity:

mobkit.clear_queue_high(self)
mobkit.clear_queue_low(self)
self.status = mobkit.remember(self, "status", "")
self.order = mobkit.remember(self, "order", "wander")

This needs to be done after it's spawned.

HeyITGuyFixIt commented 3 years ago

Once we figure this out, I think we should do something like this to help keep the code DRY and readable:

local mob_list = {
    -- create item for every mob with fine tuned settings here
    tyrannosaurus = {intrvl = 1, chance = 1, reduction = 0, near = {'default:dirt_with_grass'}},
}
-- after defining these mobs, we can add mod dependant materials to the near array like this:
if minetest.get_modpath('ethereal') then
    table.insert(mob_list.tyrannosaurus.near, 'ethereal:mushroom_dirt')
end

local radius = 32 -- I expect the radius to be the same for every mob, if not we can add it as an item in the mob definitions array above, which would be accessed below as def.radius
for mob, def in ipairs(mob_list) do
    minetest.register_globalstep(function(dtime)
        local spawnpos = mobkit.get_spawn_pos_abr(dtime, def.intrvl, radius, def.chance, def.reduction)
        if spawnpos then
            -- either search for a single matching node in radius or find all nodes that match in an area
            -- if minetest.find_nodes_in_area(pos1, pos2, def.near) then
            if minetest.find_node_near(spawnpos, radius, def.near, true) then
                minetest.add_entity(spawnpos, "paleotest:"..mob)
                -- add other spawning stuff here
            end
        end
    end)
end

Mobs that spawn in water may be trickier, since we don't want a giant sea monster spawning in a little pond. We can figure that out when we get there.

JDSoar commented 3 years ago

Hi @HeyITGuyFixIt ,

So I tried implemented what you sent me, but I keep getting an error before the game starts up. It says:

ModError: Failed to load and run script from C:\Program Files\minetest-5.3.0-win64\bin..\mods\paleotest\init.lua: ...5.3.0-win64\bin..\mods\paleotest/mobs/tyrannosaurus.lua:279: function arguments expected near '.' stack traceback: [C]: in function 'dofile' ...iles\minetest-5.3.0-win64\bin..\mods\paleotest\init.lua:129: in main chunk

The code I have used up to this point is:

minetest.register_globalstep(function(dtime)
        local spawnpos = mobkit.get_spawn_pos_abr(dtime, 50, 32, 1, 1)
        if spawnpos then
          minetest.add_entity(spawnpos, "paleotest:tyrannosaurus")

          mobkit.clear_queue_high("paleotest:tyrannosaurus")
          mobkit.clear_queue_low("paleotest:tyrannosaurus")
          paleotest:tyrannosaurus.status = mobkit.remember("paleotest:tyrannosaurus", "status", " ")
          paleotest:tyrannosaurus.order = mobkit.remember("paleotest:tyrannosaurus", "order", "wander")

        end
end)

Perhaps I have not implemented the code in the correct way? I don't understand exactly how this code works so I am having a hard time debugging it.

Furthermore, at the risk of sounding less than intelligent, what exactly is the purpose of the additional code you added? Is it to keep the dinosaurs only spawning on grass and not on the top of trees, houses, etc?

HeyITGuyFixIt commented 3 years ago

@JDSoar I don't think replacing self with paleotest:tyrannosaurus or "paleotest:tyrannosaurus" is the correct way to do this. There is very likely a much better way to do this, maybe @ElCeejo can inform us on the best way to get a mob moving after spawning.

Otherwise, we can use minetest.registered_entities["paleotest:tyrannosaurus"] instead. So maybe create a variable after minetest.add_entity that stores this as its value. Then use that variable in place of self.

HeyITGuyFixIt commented 3 years ago

@JDSoar the code I added is to make adding more mobs to spawn easier, while also specifying where to spawn them. The example I gave only checks if a given node is in the area, and then spawns if it is. That way, we can control what biomes mobs are spawned in. It doesn't prevent the possiblity of a dinosaur spawning on top of a house however.

HeyITGuyFixIt commented 3 years ago

My idea with adding spawning is to put the code for spawning in a separate file that is the last file included in init, but only included if a spawning setting is set to true. That part is easy.

HeyITGuyFixIt commented 3 years ago

Looking into the code a bit more, adding

mobkit.clear_queue_high(self)
mobkit.clear_queue_low(self)
self.status = mobkit.remember(self, "status", "")
self.order = mobkit.remember(self, "order", "wander")

shouldn't be necessary. I would think that on_activate would be called whenever the mob is spawned, and the default behavior is to wander if there is no order to recall. @ElCeejo can you confirm that this is the case and maybe help figure out why the mobs weren't wandering initially?

JDSoar commented 3 years ago

@HeyITGuyFixIt

Yeah, I still can't get it to work. To reaffirm, @ElCeejo can you help us figure out why the mobs are not moving when they are first spawned?

HeyITGuyFixIt commented 3 years ago

@JDSoar I haven't had a chance to reproduce the issue of the dinos standing still. I might have time tonight. Can you make sure mobkit and mob_core are up-to-date for you and see if that still happens? I want to make sure that isn't the issue. If you just installed them when we started to figure this out, then this probably isn't the issue.

JDSoar commented 3 years ago

Hey @HeyITGuyFixIt Sorry, it's been a couple of days. I did verify that the mobkit and the mob_core are up to date. So I am running the current version. Let me know if you need anything else. I will have some time this week, but next week I will be more limited as the spring term for my college IT classes start.

HeyITGuyFixIt commented 3 years ago

@JDSoar I'm working on this, had a chance to test things out. I noticed the same issue you did with the mobs standing still. They also look like they are a bit inside the ground too. I found some helper functions in mob_core for spawning. So I'm looking into making use of those to get the results I want.

If we can establish which nodes we want dinosaurs to spawn on, we can easily implement those functions to get the mobs to spawn. However, I think it would be better to define what biomes we want dinosaurs to spawn in instead, but the spawning functions don't make that easy to do. So I'm playing with their code to see if I can get what I want here. Maybe using their code to spawn, we can fix the issue of the mobs standing still.

I should be able to take it from here, thank you for your help with establishing a foundation to work with and testing it.

Once I figure out the issue I mentioned above, I'll go ahead and create a pull request where we can discuss the details further.

ElCeejo commented 3 years ago

Seems like a lot of work when mob core itself already has a spawn function that works with mobkit mobs and is just as easy to use as mobs_redo.

HeyITGuyFixIt commented 3 years ago

@ElCeejo yeah, didn't realize that until I was going crazy trying to figure that out. I'm tinkering with those functions now

JDSoar commented 3 years ago

@HeyITGuyFixIt I just looked at the mobkit mobs and it seems like that in fact would be the easier path to go down. I just hope that the mobs will automatically start moving around when they spawn. We will need to test that. Please keep me posted on your progress! And again, if you need anything just let me know!

HeyITGuyFixIt commented 3 years ago

@JDSoar created PR. See #6

HeyITGuyFixIt commented 3 years ago

@JDSoar it is in a much better place. For the most part, the mobs are moving around on their own, unless they are stuck in the ground. Not sure what to do about that. That might be a mob_core bug, not sure.

It definitely needs some testing and refinement of values. I haven't tested the water mobs to see how frequently they spawn. I have velociraptors and dire wolves spawning in forests in packs, but they may need to spawn more, not sure.