-1

我尝试为 Gmod amd 修复一些旧的 Basewars 脚本,我尝试修复一些东西,但我不知道我在那里缺少什么。基本上它是关于银行脚本的。这家银行最初可以存储 20 亿美元。我想将该存储量扩展到 1 万亿。

所以基本上 Basewars 游戏模式允许玩家拥有高达 10^18 $ = 1 Quintillion 的大量资金。我查看了https://wiki.garrysmod.com/page/Category:number

所以基本上lua使用双精度浮点格式。所以 lua 使用 32 位来存储数字,这意味着数字可以在 -2,147,483,647 到 2,147,483,647 的范围内。

Basewars 游戏模式使用函数来计算 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

游戏模式正在使用该派系来转换金额。这是 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,
}

所以我知道这个函数确实有效,但我不明白,变量 num 怎么可能那么高!为什么我知道它的作用?

这是我尝试过的,它操纵了高达 1 万亿的容量,但此时我操纵了另一个问题,我不知道我做错了什么!

这是原始的:

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

这是我所做的更改:

删除行:local cap = tonumber(Cp) or 0

添加本地上限 = 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

所以现在如果你看一下游戏,它看起来像这样:现在我有一个问题,当它收钱时,它会达到 20 亿,如果我尝试改变

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

local money =self:GetMoney()

我直接 -21 亿

或者我尝试更改最小最大值:

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

基本上这些行:

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

如果我运行游戏,银行将只收取最多 2 比尔的钱,然后它会变成 -21 亿美元。那时我不知道为什么以及什么时候某个值会出现问题,就像它自己设置为 -21 亿一样。math.Round 会创建此错误还是 funktion return 仅返回完整整数?

谢谢任何帮助

4

1 回答 1

0

因为银行使用的网络变量是一个整数,所以它只能存储 $(2^31-1) 到 $-(2^31-1)。尝试将其更改为网络浮动:

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

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

但是,请注意,随着玩家积累的资金越多,这些数字的精确度就越低。

于 2019-07-13T01:18:07.503 回答