-1

I try to fix some old Basewars script for Gmod amd there is something i tried to fix but i dont know what i am missing there. Basicly its about a Bank script. This Bank could original store a amount of 2 Billion $. I would like to expand that storage amount to 1 Quadtrillion.

So Basicly the Basewars Gamemode allows players to have an high amount of money up to 10^18 $ = 1 Quintillion. I looked up into https://wiki.garrysmod.com/page/Category:number

so basicly lua uses double-precision floating-point format. So lua uses 32 bits for storing numbers and that means the number can be from a range of -2,147,483,647 to 2,147,483,647.

The Basewars Gamemode uses a Function to make out of 10^18 = 1 Quintillion

function BaseWars.NumberFormat(num)

    local t = BaseWars.LANG.Numbers
    for i = 1, #t do

        local Div = t[i][1]
        local Str = t[i][2]

        if num >= Div or num <= -Div then

         return string.Comma(math.Round(num / Div, 1)) .. " " .. Str

        end

    end

    return string.Comma(math.Round(num, 1))

end

The Gamemode is using that faction to convert the amount of money. and here is the BaseWars.LANG.Numbers:

BaseWars.LANG = {}
BaseWars.LANG.__LANGUAGELOOK = {}

BaseWars.LANG.__LANGUAGELOOK.ENGLISH = {
    Numbers = {
        [5] = {10^6, "Million"},
        [4] = {10^9, "Billion"},
        [3] = {10^12, "Trillion"},
        [2] = {10^15, "Quadtillion"},
        [1] = {10^18, "Quintillion"},
    },

    CURFORMER       = CURRENCY .. "%s",
    CURRENCY        = CURRENCY,
}

So i know that this function does work but i dont get it, how the variable num can be that high! Why do i know what it does work ?

Here is what i tried and it manipulated the Capacity up to 1 Quadtrillion but at the point i manipluated a other Problem came up and i do not know what i do wrong!

Here how it was Original:

ENT.Capacity        = 2000000000 --Max money in the bank. Can be bugs if it is more than 2000000000 (2 bil)
ENT.Money           = 0
ENT.MaxPaper        = 0

local Clamp = math.Clamp
function ENT:GSAT(slot, name,  min, max)

    self:NetworkVar("Int", slot, name)

    local getVar = function(minMax)

        if self[minMax] and isfunction(self[minMax]) then return self[minMax](self) end
        if self[minMax] and isnumber(self[minMax]) then return self[minMax] end

        return minMax or 0

    end

    self["Add" .. name] = function(_, var)

            local Val = self["Get" .. name](self) + var

            if min and max then

                Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))

            end

            self["Set" .. name](self, Val)

    end

    self["Take" .. name] = function(_, var)

        local Val = self["Get" .. name](self) - var

        if min and max then

            Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))

        end

        self["Set" .. name](self, Val)

    end

end


function ENT:StableNetwork()

    self:GSAT(2, "Capacity")

    self:GSAT(3, "Money", 0, "GetCapacity")
    self:GSAT(4, "Paper", 0, "MaxPaper")
    self:GSAT(5, "Level", 0, "MaxLevel")

end

function ENT:ThinkFunc() --This Funtion is to auto collect all the Money of Printers 


for k, v in pairs( ents.FindByClass( "bw_printer_*" ) ) do 
            if v:CPPIGetOwner() == self:CPPIGetOwner() then
                if self:GetMoney() < self.Capacity then
                    local allmoney = v:GetMoney()
                    v:TakeMoney(allmoney)
                    self:AddMoney(allmoney)
                end
            end
        end     

        for k, v in pairs( ents.FindByClass( "bw_base_moneyprinter" ) ) do
            if v:CPPIGetOwner() == self:CPPIGetOwner() then
                if self:GetMoney() < self.Capacity then
                    local allmoney = v:GetMoney()
                    v:TakeMoney(allmoney)
                    self:AddMoney(allmoney)
                end
            end
        end 

end

if CLIENT then
local Cp = self:GetCapacity()
local money = tonumber(self:GetMoney()) or 0
        local cap = tonumber(Cp) or 0

        local moneyPercentage = math.Round( money / cap * 100 ,1)

        draw.DrawText( moneyPercentage .."%" , fontName .. ".Huge", w - 4-430, 71+610, self.FontColor, TEXT_ALIGN_CENTER)

local currentMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(money)
            local maxMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap)
            local font = fontName .. ".Big"
            if #currentMoney > 16 then

                font = fontName .. ".MedBig"

            end
            if #currentMoney > 20 then

                font = fontName .. ".Med"

            end
            local fh = draw.GetFontHeight(font)

            local StrW,StrH = surface.GetTextSize("")
            local moneyW,moneyH = surface.GetTextSize(currentMoney)
            draw.DrawText(currentMoney.. " / " .. BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap) , font,
                w/2 - StrW/2-225 , (font == fontName .. ".Big" and 106 or 105 + fh / 4)+675, self.FontColor, TEXT_ALIGN_CENTER)


end

Here the changes i did:

removed line: local cap = tonumber(Cp) or 0

added local cap = 10^15 if self:GetMoney() < cap then

ENT.Capacity        = 2000000000 --Max money in the bank. Can be bugs if it is more than 2000000000 (2 bil)
local cap = 10^15
ENT.Money           = 0
ENT.MaxPaper        = 0

local Clamp = math.Clamp
function ENT:GSAT(slot, name,  min, max)

    self:NetworkVar("Int", slot, name)

    local getVar = function(minMax)

        if self[minMax] and isfunction(self[minMax]) then return self[minMax](self) end
        if self[minMax] and isnumber(self[minMax]) then return self[minMax] end

        return minMax or 0

    end

    self["Add" .. name] = function(_, var)

            local Val = self["Get" .. name](self) + var

            if min and max then

                Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))

            end

            self["Set" .. name](self, Val)

    end

    self["Take" .. name] = function(_, var)

        local Val = self["Get" .. name](self) - var

        if min and max then

            Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))

        end

        self["Set" .. name](self, Val)

    end

end


function ENT:StableNetwork()

    self:GSAT(2, "Capacity")

    self:GSAT(3, "Money", 0, "GetCapacity")
    self:GSAT(4, "Paper", 0, "MaxPaper")
    self:GSAT(5, "Level", 0, "MaxLevel")

end

function ENT:ThinkFunc() --This Funtion is to auto collect all the Money of Printers 


for k, v in pairs( ents.FindByClass( "bw_printer_*" ) ) do 
            if v:CPPIGetOwner() == self:CPPIGetOwner() then
                if self:GetMoney() < cap then
                    local allmoney = v:GetMoney()
                    v:TakeMoney(allmoney)
                    self:AddMoney(allmoney)
                end
            end
        end     

        for k, v in pairs( ents.FindByClass( "bw_base_moneyprinter" ) ) do
            if v:CPPIGetOwner() == self:CPPIGetOwner() then
                if self:GetMoney() < cap then
                    local allmoney = v:GetMoney()
                    v:TakeMoney(allmoney)
                    self:AddMoney(allmoney)
                end
            end
        end 

end

if CLIENT then
local Cp = self:GetCapacity()
local money = tonumber(self:GetMoney()) or 0


        local moneyPercentage = math.Round( money / cap * 100 ,1)

        draw.DrawText( moneyPercentage .."%" , fontName .. ".Huge", w - 4-430, 71+610, self.FontColor, TEXT_ALIGN_CENTER)

local currentMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(money)
            local maxMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap)
            local font = fontName .. ".Big"
            if #currentMoney > 16 then

                font = fontName .. ".MedBig"

            end
            if #currentMoney > 20 then

                font = fontName .. ".Med"

            end
            local fh = draw.GetFontHeight(font)

            local StrW,StrH = surface.GetTextSize("")
            local moneyW,moneyH = surface.GetTextSize(currentMoney)
            draw.DrawText(currentMoney.. " / " .. BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap) , font,
                w/2 - StrW/2-225 , (font == fontName .. ".Big" and 106 or 105 + fh / 4)+675, self.FontColor, TEXT_ALIGN_CENTER)


end

So now if you i look into the game it looks like this: and now i have the problem that when it collects money it does it up to 2 billion and if i try to change

local money = tonumber(self:GetMoney()) or 0

to

local money =self:GetMoney()

i get straight -2.1 Bil

or i tried to change the min max values:

function ENT:GSAT(slot, name,  min, max)

    self:NetworkVar("Int", slot, name)

    local getVar = function(minMax)

        if self[minMax] and isfunction(self[minMax]) then return self[minMax](self) end
        if self[minMax] and isnumber(self[minMax]) then return self[minMax] end

        return minMax or 0

    end

    self["Add" .. name] = function(_, var)

            local Val = self["Get" .. name](self) + var

            if min and max then

                Val = Clamp(tonumber(Val) or 0, getVar(min), 10^15)

            end

            self["Set" .. name](self, Val)

    end

    self["Take" .. name] = function(_, var)

        local Val = self["Get" .. name](self) - var

        if min and max then

            Val = Clamp(tonumber(Val) or 0, getVar(min), 10^15)

        end

        self["Set" .. name](self, Val)

    end

end

Basicly these lines:

Val = Clamp(tonumber(Val) or 0, getVar(min), 10^15)

if i run the game the Bank will just collect the money up to 2 Bill and then it goes to -2.1Bil. And at that point i dont know why and when a value does go buggy like it self sets to -2.1 Bil. does math.Round create this bug or do funktion return only return full integer ?

thx for any help

Akina
  • 1
  • 2
    Double-precision floating-point can represent integers up to 2^52 exactly. – lhf Jul 04 '19 at 11:49
  • so basicly the number they can represent would be 4.5035996e+15 but why do i get sometimes as a result of a fuction the value - 2,147,483,647 ? specialy when i remove the tonumber when i try to get the entenies money value ? – Akina Jul 04 '19 at 13:39

1 Answers1

0

Because the network variable that the bank uses is an integer, it will only be able to store $(2^31-1) through $-(2^31-1). Try changing it to a networked float:

-- ...
function ENT:GSAT(slot, name,  min, max)

    -- self:NetworkVar("Int", slot, name), changes into:
    self:NetworkVar("Float", slot, name)
-- ...

But, beware as the more money players accumulate the less precision will be put into those numbers.

twentysix
  • 141
  • 4