Jump to content

Help optimising my 'Magic Bottle Lanterns' mod to reduce lag


Recommended Posts

My Magic Bottle Lanterns mod has proved really popular, but more than one person has said that having lots of them on a server creates big lag problems. The nature of the item lends itself to having lots of them, so I'd like that to be the case, without stripping them of their special features.

I'm pretty sure this is to do with how I coded the bottle effects - since I'm new to coding, and its been a very hashed together job, I'm sure there's more efficient ways to get the effects I'm after. For example, there's lots of use of inst:DoPeriodicTask, which I get the sense might be contributing to lag?

I'd appreciate any help or advice doing this! The mod is attached for you to look at. Here are the effects for reference, which are all meant to happen within a small range of the item, and only when they're lit at dusk and night:

  • white (just a light)
  • red (negative sanity)
  • blue (cools)
  • pink (makes hostile mobs passive)
  • purple (heals)
  • orange (heats)
  • yellow (positive sanity)
  • green (damage)
  •  

Magic Bottle Lanterns DST.rar

Link to comment
Share on other sites

Is it necessary, that updatelight function is called every 2 seconds? Or would it also be enough, if this function is only called when it changes to day/night?
For the other DoPeriodicTasks in your bottles, which mainly check if a combat entity is near, you could deatvivate the PeriodicTask while it is day.
I assueme the bottles should always light, if in caves?


New code for purple bottle:

Spoiler

local function AreaHeal(inst) 
    local pt = inst:GetPosition()
    --healing
    local ents = TheSim:FindEntities(pt.x,pt.y,pt.z, 6, {"_combat"}, {"ghost", "shadow"}, nil)
    for i,v in ipairs(ents) do
        if v.components.health then
            v.components.health:DoDelta(1)
        end
    end
end


local taskHeal = nil
local function updatelight(inst,isday)
    if isday then
        inst.Light:Enable(false)
        inst.AnimState:PlayAnimation("8_idle_off")
        inst.lighton = false -- storing values this way won't be saved when game is loaded 
        flicker_stop(inst)
        if taskHeal~=nil then
            taskHeal:Cancel() -- stop periodictask to heal
            taskHeal = nil
        end
    else
        inst.Light:Enable(true)
        flicker_update(inst)
        inst.Light:SetRadius(1.5)
        inst.Light:SetFalloff(.5)
        inst.Light:SetIntensity(.8)
        inst.Light:SetColour(174/174,0,255/255)
        inst.AnimState:PushAnimation("8_loop_on_purple",true)
        inst.lighton = true
        if taskHeal==nil then
            taskHeal = inst:DoPeriodicTask(2, function() AreaHeal(inst) end) -- start healing task again
        end
    end
end


local function OnInit(inst)
    if TheWorld:HasTag("cave") then
        updatelight(inst, false) -- always light in caves
    else -- overworld
        inst:WatchWorldState("isday", function(inst,isday) updatelight(inst, isday) end)
        inst:WatchWorldState("isnight", function(inst,isnight) updatelight(inst, not isnight) end) -- using "not isnight", so we have the isday value ... isnight is called when it gets evening
        updatelight(inst, TheWorld.state.isday)
    end
end


local function fn()
	local inst = CreateEntity()

	-- .. your other stuff
	
	inst:DoTaskInTime(0, OnInit)
	taskHeal = inst:DoPeriodicTask(2, function(inst) AreaHeal(inst) end)

    return inst
end

 

I already tested it and it works :)
You can make it the same way for your other bottles.
For red and yellow bottle you don't need any DoPeriodicTask, cause you can simple set the aura value in the updatelight function now (you should set it to 0 if it is day and to your chosen value if it is night)

If it still lags after these improvements change the intervall.
So instead of healing 1 point every 2 seconds, you could heal 5 points every 10 seconds ;)

Done with editing :):D

Edited by Serpens
Link to comment
Share on other sites

29 minutes ago, Serpens said:

To sum it up, you should merge mine and Aquaterion improvements, to get the best result.

I tried mine in caves, for some reason they stayed on, even in day. so idk

but personally i would modify the line to something like this:

if phase == "day" and not TheWorld:HasTag("cave") then

 

Edited by Aquaterion
Link to comment
Share on other sites

I forgot in my code obviously to improve the flickr thing, so Aquaterions code will reduce lag more I think.
But I think it is still a good idea to add the WorldState Watcher, that's why I wrote merge both codes :)

I was not sure how it should work in cave. I assuemed since it is always dark there, the bottles should be always on.
For cave you might use some of these:
TheWorld.state.iscaveday
inst:WatchWorldState("iscaveday", oniscaveday)
TheWorld.state.iscavenight
inst:WatchWorldState("iscavenight", oniscavenight)

Link to comment
Share on other sites

25 minutes ago, Serpens said:

I forgot in my code obviously to improve the flickr thing, so Aquaterions code will reduce lag more I think.
But I think it is still a good idea to add the WorldState Watcher, that's why I wrote merge both codes :)

I was not sure how it should work in cave. I assuemed since it is always dark there, the bottles should be always on.
For cave you might use some of these:
TheWorld.state.iscaveday
inst:WatchWorldState("iscaveday", oniscaveday)
TheWorld.state.iscavenight
inst:WatchWorldState("iscavenight", oniscavenight)

no point in watching for cave day and night, if they're always gonna be on, you only need to do it when you place them

 

I prefer using WatchWorldState("phase") rather than checking if its day or not. Less code and checks for dusk too

Edited by Aquaterion
Link to comment
Share on other sites

51 minutes ago, Aquaterion said:

no point in watching for cave day and night, if they're always gonna be on, you only need to do it when you place them

 

I prefer using WatchWorldState("phase") rather than checking if its day or not. Less code and checks for dusk too

didn't you asked how to know if it is cave day/night?
Ah yes, phase is also interesting, thank you :)

Link to comment
Share on other sites

On 06/12/2016 at 5:35 PM, Aquaterion said:

I made a version where instead of 8 prefab files, 1 for each lantern, there's just 1 that does it all, using 200lines of code in total, rather than 100 for each lantern, totaling to 800.

 

5844166c2db13_MagicBottleLanternsDST.rar

Wow, that's neat! I'm going to upload it on Steam and then take some time to study what you did to combine them. All interesting stuff to learn for future modding attempts!

Link to comment
Share on other sites

16 minutes ago, justjasper said:

Wow, that's neat! I'm going to upload it on Steam and then take some time to study what you did to combine them. All interesting stuff to learn for future modding attempts!

If you have any questions feel free to ask. There were also some fixes in there, such as the heat/cold lanterns giving their benefits even when they were off.

 

Edit: Also don't forget to apply some of the changes you did recently, like the no damage to walls and more damage from green lantern, as I was using the version given here.

Edited by Aquaterion
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...