Jump to content

heat factor issues in temperature component


hoxi
  • Fixed

This is gonna look big, but the following chunk of code has a few issues:

        if not inside_pocket_container then
            for i, v in ipairs(ents) do
                if v ~= self.inst and
                    not v:IsInLimbo() and
                    v.components.heater ~= nil and
                    (v.components.heater:IsExothermic() or v.components.heater:IsEndothermic()) then

                    local heat = v.components.heater:GetHeat(self.inst)
                    if heat ~= nil then
                        local dsqtoinst = self.inst:GetDistanceSqToInst(v)
                        local heatfactor
                        if v.components.heater:ShouldFalloff() then
                            -- This produces a gentle falloff from 1 to zero.
                            heatfactor = 1 - dsqtoinst / ZERO_DISTSQ
                        else
                            heatfactor = 1
                        end
                        local radius_cutoff = v.components.heater:GetHeatRadiusCutoff()
                        if radius_cutoff and dsqtoinst > radius_cutoff * radius_cutoff then
                            heatfactor = 0
                        end
                        if self.inst:GetIsWet() then
                            heatfactor = heatfactor * TUNING.WET_HEAT_FACTOR_PENALTY
                        end

                        if v.components.heater:IsExothermic() then
                            -- heating heatfactor is relative to 0 (freezing)
                            local warmingtemp = heat * heatfactor
                            if warmingtemp > self.current then
                                self.delta = self.delta + warmingtemp - self.current
                            end
                            self.externalheaterpower = self.externalheaterpower + warmingtemp
                        else--if v.components.heater:IsEndothermic() then
                            -- cooling heatfactor is relative to overheattemp
                            local coolingtemp = (heat - self.overheattemp) * heatfactor + self.overheattemp
                            if coolingtemp < self.current then
                                self.delta = self.delta + coolingtemp - self.current
                            end
                        end
                    end
                end
            end
        end

This is a version of that bit I made for a mod I use, updated for the beta:

                if not inside_pocket_container then
                    local apply_wet_penalty = self.inst:GetIsWet()
                    local wet_factor_penalty = TUNING.WET_HEAT_FACTOR_PENALTY

                    for i, v in ipairs(ents) do
                        if v ~= self.inst and
                            not v:IsInLimbo() and
                            v.components.heater ~= nil and
                            (v.components.heater:IsExothermic() or v.components.heater:IsEndothermic()) then

                            local heat = v.components.heater:GetHeat(self.inst)

                            if heat ~= nil then
                                local heatfactor, dsqtoinst = nil

                                if v.components.heater:ShouldFalloff() then
                                    dsqtoinst = self.inst:GetDistanceSqToInst(v)

                                    -- This produces a gentle falloff from 1 to zero.
                                    heatfactor = 1 - dsqtoinst / ZERO_DISTSQ
                                else
                                    heatfactor = 1
                                end

                                do
                                    local radius_cutoff = v.components.heater:GetHeatRadiusCutoff()

                                    if radius_cutoff then
                                        dsqtoinst = dsqtoinst or self.inst:GetDistanceSqToInst(v)

                                        if dsqtoinst > radius_cutoff * radius_cutoff then
                                            heatfactor = 0
                                        end
                                    end
                                end

                                -- check that we're not at the edge or somehow past the range, that would produce unexpected results
                                if heatfactor > 0 then
                                    if apply_wet_penalty then
                                        -- normally, wetness penalty works as a bonus for endothermics, unless the heat value they provide is below 0
                                        -- in which case it turns into a penalty, so address that and reverse it in those cases, further lowering temperature
                                        -- if we're exothermic and we're somehow below 0, it's fine if we further lowers the value anyway, that's still doing the intended effect
                                        if heat > 0 then
                                            heatfactor = heatfactor / wet_factor_penalty
                                        else
                                            heatfactor = heatfactor * wet_factor_penalty
                                        end
                                    end

                                    if v.components.heater:IsExothermic() then
                                        -- heating heatfactor is relative to 0 (freezing)
                                        local warmingtemp = heat * heatfactor
                                        if warmingtemp > self.current then
                                            self.delta = self.delta + warmingtemp - self.current
                                        end
                                        self.externalheaterpower = self.externalheaterpower + heatfactor
                                    else--if v.components.heater:IsEndothermic() then
                                        -- cooling heatfactor is relative to overheattemp
                                        local coolingtemp = (heat - self.overheattemp) * heatfactor + self.overheattemp
                                        if coolingtemp < self.current then
                                            self.delta = self.delta + coolingtemp - self.current
                                        end
                                    end
                                end
                            end
                        end
                    end
                end

The changes I made there would address the following issues:

  • If standard temperature falloff returns 0 by being exactly at the edge of the temperature range, heat will be 0, regardless if the source is exothermic or endothermic (it can make the latter be colder in some cases). This also applies with the new heat cutoff feature added in the beta. Ideally, nothing should be processed after that point when heat factor is 0.
  • Heat factor penalty works fine in most cases, but not for endothermic sources with heat values below 0. In those cases, they make the cold sources warmer. Either it needs to multiply with values below 0 (as shown above), or not apply at all for endothermic sources.
  • Small optimization, but checking for GetIsWet once before the iteration would be faster than doing so for every heat source.

Steps to Reproduce

For the falloff issue:

  • Be exactly at the edge of the range for standard heat sources, or outside the cutoff range for ones that use that feature, and observe the weird behavior.

For the heat factor wet penalty issue:

  1. While at high moisture, stand near a standard campfire or firepit (max out their fire to make it more obvious) and check how the heat values are affected. Rain can help preventing moisture from drying.
  2. Now do the same with a cold fire or cold fire pit and check as well.
  3. Notice how with heat values below 0, being wet means you receive less coldness instead of more.



User Feedback


A developer has marked this issue as fixed. This means that the issue has been addressed in the current development build and will likely be in the next update.


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

×
  • Create New...