Jump to content

Making a chesterlike creature go to the caves and back


Recommended Posts

Hey, 

so I'm currently doing a mod where I add a chesterlike creature, also with a container. I wanted to make it able to go to the caves with a working container. I took a look at the personal chester mod and freki mod to see what had to be done, so this is already working as I wanted it to.
The problem is now that the creature doesn't despawn when the server is closed, as it should and also does with the personal chester mod, which results in more and more creatures at the each restart of the server. I used the same code as there, I just cut some out that I didn't need. I have "fixed" it by removing the creature and the eyebone when the player enters with the onload function, but this is not how I want it to stay. I added print statements for the remove function, but they are not printed, perhaps as the server is already down because of the DoTaskInTime, but they are working for personal chesters, that's why I'm very confused.

If you could help me, I would be very grateful!

Spoiler


local function deletehunter(inst)
    print("deletehunter")
    local hunter = TheSim:FindFirstEntityWithTag("hunter")
    local salat = TheSim:FindFirstEntityWithTag("salat")
    if hunter and hunter:IsValid() then 
        print("hunterremoved2")
        hunter:Remove() end
    if salat and salat:IsValid() then 
        print("salatremoved2")
        salat:Remove() end
end

local function WorldPrefabPostInit(inst)
    if not GLOBAL.TheWorld.ismastersim then
        return
    end

    inst:ListenForEvent("ms_playerdespawnanddelete",
                        function (inst, player)
                            OnDespawnAndDelete(player)
                        end)
    --inst:ListenForEvent("ms_playerleft", deletehunter)

end

AddPrefabPostInit("world", WorldPrefabPostInit)

local SPAWN_DIST = 30

local function GetSpawnPoint(pt)
    local theta = math.random() * 2 * GLOBAL.PI
    local radius = SPAWN_DIST
    local offset = GLOBAL.FindWalkableOffset(pt, theta, radius, 12, true)
    return offset ~= nil and (pt + offset) or nil
end


local function PersonalHunter(inst)
    if inst.prefab ~= "melanie" then return end
    if not GLOBAL.TheWorld.ismastersim then
        return
    end

    local OnDespawn_prev = inst.OnDespawn
    local OnDespawn_new = function(inst)
        -- Remove hunter
        if inst.hunter then
            -- Don't allow hunter to despawn with irreplaceable items
            inst.hunter.components.container:DropEverythingWithTag("irreplaceable")
            print("despawn inst.hunter"..tostring(inst.hunter))
            
            -- We need time to save before despawning.
            inst.hunter:DoTaskInTime(0, function(inst)
                if inst and inst:IsValid() then
                    inst:Remove()
                    print("hunterremoved")
                end
            end)
            
        end
        
        if inst.salat then
            print("despawn inst.salat"..tostring(inst.hunter))
            -- salat drops from whatever its in
            local owner = inst.salat.components.inventoryitem.owner
            if owner then
                -- Remember if salat is held
                if owner == inst or (owner.components.inventoryitem and owner.components.inventoryitem.owner == inst) then
                    inst.salat.isheld = true
                else
                    inst.salat.isheld = false
                end
                if owner.components.container then
                    owner.components.container:DropItem(inst.salat)
                elseif owner.components.inventory then
                    owner.components.inventory:DropItem(inst.salat)
                end
            end
            -- Remove salat
            inst.salat:DoTaskInTime(0.1, function(inst)
                if inst and inst:IsValid() then
                    print("salatremoved")
                    inst:Remove()
                end
            end)
        else
            print("Error: Player has no linked salat!")
        end
        if OnDespawn_prev then
            return OnDespawn_prev(inst)
        end
    end
    inst.OnDespawn = OnDespawn_new
    
    local OnSave_prev = inst.OnSave
    local OnSave_new = function(inst, data)
        local references = OnSave_prev(inst, data)
        if inst.hunter then
            print("inst.hunter"..tostring(inst.hunter))
            -- Save hunter
            local refs = {}
            print(tostring(references))
            if not references then
                references = {}
            end
            data.hunter, refs = inst.hunter:GetSaveRecord()
            if refs then
                for k,v in pairs(refs) do
                    table.insert(references, v)
                end 
            end                
        end
        if inst.salat then
            print("inst.salat"..tostring(inst.salat))
            -- Save salat
            local refs = {}
            if not references then
                references = {}
            end
            data.salat, refs = inst.salat:GetSaveRecord()
            if refs then
                for k,v in pairs(refs) do
                    table.insert(references, v)
                end 
            end
            -- Remember if was holding salat
            if inst.salat.isheld then
                data.holdingsalat = true
            else
                data.holdingsalat = false
            end
        end
        return references
    end
    inst.OnSave = OnSave_new
    
    local OnLoad_prev = inst.OnLoad
    local OnLoad_new = function(inst, data, newents)

        local old_hunter = TheSim:FindFirstEntityWithTag("hunter")
        local old_salat = TheSim:FindFirstEntityWithTag("salat")
        print(tostring(old_hunter))
        if old_hunter and old_hunter:IsValid() then 
            print("hunterremoved2")
            old_hunter:Remove() end
        if old_salat and old_salat:IsValid() then 
            print("salatremoved2")
            old_salat:Remove() end

        if data.hunter ~= nil then
            -- Load hunter
            inst.hunter = GLOBAL.SpawnSaveRecord(data.hunter, newents)
            inst.hunter:AddTag("hunter"..inst.userid)
        else
            print("Warning: No hunter was loaded from save file!")
        end
        
        if data.salat ~= nil then
            -- Load salat
            inst.salat = GLOBAL.SpawnSaveRecord(data.salat, newents)
            inst.salat.owner = inst
            
            -- Look for salat at spawn point and re-equip
            inst:DoTaskInTime(0, function(inst)
                
                --[[if data.holdingsalat or (inst.salat and inst:IsNear(inst.salat,4)) then
                    inst:ReturnSalat()
                end]]
                
                --TEMPORARY FIX until I find a solution
                inst:ReturnSalat()
            end)
        else
            print("Warning: No salat was loaded from save file!")
        end
        
        
        if OnLoad_prev then
            return OnLoad_prev(inst, data, newents)
        end
    end
    inst.OnLoad = OnLoad_new

    
    inst:ListenForEvent("ms_playerreroll", function(inst)
        if inst.hunter and inst.hunter.components.container then
            inst.hunter.components.container:DropEverything()
        end
    end)
    
    -- Debug function to return salat
    inst.ReturnSalat = function()
        if inst.salat and inst.salat:IsValid() then
            if inst.salat.components.inventoryitem.owner ~= inst then
                inst.components.inventory:GiveItem(inst.salat)
            end
        end
        if inst.hunter and not inst:IsNear(inst.hunter, 20) then
            local pt = inst:GetPosition()
            local spawn_pt = GetSpawnPoint(pt)
            if spawn_pt ~= nil then
                inst.hunter.Physics:Teleport(spawn_pt:Get())
                inst.hunter:FacePoint(pt:Get())
            end
        end
    end
end
local doReturnSalat = function(target)
    if not target or not target.ReturnSalat then 
        print("Error: Cannot return salat")
        return 
    end
    target:ReturnSalat()
end
GLOBAL.c_returnsalat = function(inst)
    if type(inst) == "string" then
        local foundplayer = false
        for _, v in ipairs(GLOBAL.AllPlayers) do
            if v.name == inst or v.userid == inst then
                foundplayer = true;
                doReturnSalat(v)
                break;
            end
        end
        if not foundplayer then
            print("Error: No match")
        end
        return
    end
    if not inst then
        inst = GLOBAL.ConsoleCommandPlayer()
    end
    if not inst or not inst.ReturnSalat then 
        print("Error: Cannot return salat")
        return 
    end
    doReturnSalat(inst)
end

AddPlayerPostInit(PersonalHunter)

 

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...