System Custom Cooldown System

Laiev

Hey Listen!!
Reaction score
188
Custom Cooldown System​

Requirement

JASS:
library Cooldown /* v7.0.0.0
*************************************************************************************
*
*   Description
*   ¯¯¯¯¯¯¯¯¯¯¯
*        -    Cooldown is a full controllable custom cooldown system
*
*************************************************************************************
*
*   */uses/*
*   
*       */  AIDS  /*       thehelper.net/forums/showthread.php/130752-Advanced-Indexing-Data-Storage
*       */  Event /*       thehelper.net/forums/showthread.php/126846-Event
*       */  T32   /*       thehelper.net/forums/showthread.php/132538-Timer32
*       */  Table /*       thehelper.net/forums/showthread.php/162582-Table
*
************************************************************************************
*
*   Importing
*   ¯¯¯¯¯¯¯¯¯
*      Create a new trigger named Cooldown. Go to 'Edit > Convert to Custom Text',
*      and replace everything that's there with this script
*      Copy every ability in this map and change the icon, name and description
*
*   How to use
*   ¯¯¯ ¯¯ ¯¯¯
*      Cooldown[someUnit].$methods$
*        -    This will interact with some $method$ (read the docs below)
*        -    In Cooldown, everything is based on an unit reference
*        -    The reference of unit is treated as 'this'
*        -    This is why all method is non-static
*
*      Cooldown.$member$
*        -    This will interact with some static $member$
*        -    The static $members$ are just part of the events
*
*******************************************************************
*
*   struct Cooldown extends array
*
*       readonly static Event START
*            -    Fire event when some cooldown start
*       readonly static Event FINISH
*            -    Fire event when some cooldown finish
*       readonly static unit    Unit
*       readonly static integer AbilityId
*       readonly static real    Duration
*       readonly static integer Hotkey
*            -    Corresponds to the above events
*       method start takes integer abilId, integer hotkey, real duration returns nothing
*            -    Start the cooldown for some abilId corresponding to the hoktye for duration
*                   _______________       _______________
*                  |___|___|___|___|     |___|___|___|___|
*                  |___|_S_|_D_|___|  >  |___|_4_|_5_|___|
*                  |_Q_|_W_|_E_|_R_|     |_0_|_1_|_2_|_3_|
*
*       method duration takes integer hotkey returns real
*            -    Get the value of cooldown corresponding to the hotkey
*       method setDuration takes integer hotkey, real duration returns nothing
*            -    Set the value of cooldown corresponding to the hotkey
*       method abilityId takes integer hotkey returns integer
*            -    Get the id of ability in cooldown corresponding to the hotkey
*       method setAbilityId takes integer hotkey, integer abilId returns nothing
*            -    Set the id of ability in cooldown corresponding to the hotkey
*
************************************************************************************
*
*   Setting
*   ¯¯¯¯¯¯¯
*/

globals
    //-----------------------------------------------------------
    // Configure the value of execution, in other words, every X
    // second(s), the system will reduce the value of each cooldown
    private constant real    COUNT_COOLDOWN     = 1.0
    
    //-----------------------------------------------------------
    // Configure if the system should refresh the cooldown when
    // finish the cooldown of the system
    private constant boolean REFRESH_COOLDOWN   = true
    
            constant integer COOLDOWN_HOTKEY_Q  = 0
            constant integer COOLDOWN_HOTKEY_W  = 1
            constant integer COOLDOWN_HOTKEY_E  = 2
            constant integer COOLDOWN_HOTKEY_R  = 3
            
            constant integer COOLDOWN_HOTKEY_S  = 4
            constant integer COOLDOWN_HOTKEY_D  = 5
    
    //------------------------------------------------------------
    // Change this for your map rawcodes
    private constant integer COOLDOWN_ABILITY_Q = 'AC@Q'
    private constant integer COOLDOWN_ABILITY_W = 'AC@W'
    private constant integer COOLDOWN_ABILITY_E = 'AC@E'
    private constant integer COOLDOWN_ABILITY_R = 'AC@R'
    
    private constant integer COOLDOWN_ABILITY_S = 'AC@S'
    private constant integer COOLDOWN_ABILITY_D = 'AC@D'
endglobals
    
// The filter, if you want to use the system with units, just change here
private function System_Filter takes unit u returns boolean
    return IsUnitType(u, UNIT_TYPE_HERO)
endfunction

/************************************************************************************/

struct Cooldown extends array
    private real            count
    
    private static integer array Cooldown_Ability[5]
    private static Table array T
    
    readonly static Event   START
    readonly static Event   FINISH
    readonly static unit    Unit
    readonly static integer AbilityId
    readonly static real    Duration
    readonly static integer Hotkey
    
    method start takes integer abilId, integer hotkey, real duration returns nothing
        set thistype.T[this].real[hotkey] = duration
        set thistype.T[this][hotkey] = abilId
        
        set thistype.Unit         = this.unit
        set thistype.AbilityId    = abilId
        set thistype.Duration     = duration
        set thistype.Hotkey       = hotkey
        call thistype.START.fire()
        
        call SetPlayerAbilityAvailable(GetOwningPlayer(this.unit), abilId, false)
        call UnitAddAbility(this.unit, Cooldown_Ability[hotkey])
        call UnitMakeAbilityPermanent(this.unit, true, Cooldown_Ability[hotkey])
    endmethod
    
    method duration takes integer hotkey returns real
        return thistype.T[this].real[hotkey]
    endmethod
    
    method setDuration takes integer hotkey, real duration returns nothing
        set thistype.T[this].real[hotkey] = duration
    endmethod
    
    method abilityId takes integer hotkey returns integer
        return thistype.T[this][hotkey]
    endmethod
    
    method setAbilityId takes integer hotkey, integer abilId returns nothing
        set thistype.T[this][hotkey] = abilId
    endmethod
    
    private method periodic takes nothing returns nothing
        local integer i = 0
        local integer lvl = 0
        
        if COUNT_COOLDOWN <= this.count then
            loop
                exitwhen 6 == i
                if 0 &lt; GetUnitAbilityLevel(this.unit, Cooldown_Ability<i>) then
                    if 0 &gt;= this.duration(i) then
                        call UnitMakeAbilityPermanent(this.unit, false, Cooldown_Ability<i>)
                        call UnitRemoveAbility(this.unit, Cooldown_Ability<i>)
                        
                        static if REFRESH_COOLDOWN then
                            set lvl = GetUnitAbilityLevel(this.unit, this.abilityId(i))
                            call UnitRemoveAbility(this.unit, this.abilityId(i))
                            call UnitAddAbility(this.unit, this.abilityId(i))
                            call SetUnitAbilityLevel(this.unit, this.abilityId(i), lvl)
                        endif
                        
                        call SetPlayerAbilityAvailable(GetOwningPlayer(this.unit), this.abilityId(i), true)
                        
                        set thistype.Unit         = this.unit
                        set thistype.AbilityId    = this.abilityId(i)
                        set thistype.Duration     = this.duration(i)
                        set thistype.Hotkey       = i
                        call thistype.FINISH.fire()
                        
                        call this.setDuration(i, 0.0)
                        call this.setAbilityId(i, 0)
                    else
                        call this.setDuration(i, this.duration(i) - this.count)
                    endif
                endif
                set i = i + 1
            endloop
            set this.count = this.count - COUNT_COOLDOWN
        endif
        set this.count = this.count + T32_PERIOD
    endmethod
    
    private method AIDS_onDestroy takes nothing returns nothing
        call this.stopPeriodic()
        call thistype.T[this].flush()
    endmethod
    
    implement T32x
    
    private method AIDS_onCreate takes nothing returns nothing
        set this.count = 0.
        call this.startPeriodic()
        set thistype.T[this] = Table.create()
    endmethod
    
    private static method AIDS_onInit takes nothing returns nothing
        set thistype.Cooldown_Ability[0] = COOLDOWN_ABILITY_Q
        set thistype.Cooldown_Ability[1] = COOLDOWN_ABILITY_W
        set thistype.Cooldown_Ability[2] = COOLDOWN_ABILITY_E
        set thistype.Cooldown_Ability[3] = COOLDOWN_ABILITY_R
        
        set thistype.Cooldown_Ability[4] = COOLDOWN_ABILITY_S
        set thistype.Cooldown_Ability[5] = COOLDOWN_ABILITY_D
        
        set thistype.START = Event.create()
        set thistype.FINISH = Event.create()
    endmethod
    
    private static method AIDS_filter takes unit u returns boolean
        return System_Filter(u)
    endmethod
    
    //! runtextmacro AIDS()
endstruct
endlibrary
</i></i></i>



Easy API (Plugin)
JASS:
library CooldownAPI /* v1.0.0.0
*************************************************************************************
*
*   Description
*   ¯¯¯¯¯¯¯¯¯¯¯
*        -    Easy API
*
*************************************************************************************
*
*   */uses/*
*   
*       */  Cooldown  /*   thehelper.net/forums/showthread.php/166181-Custom-Cooldown-System
*
************************************************************************************
*
*    Functions
*    ¯¯¯¯¯¯¯¯¯
*       - Basic
*         ¯¯¯¯¯
*           function StartCooldown takes unit whichUnit, integer abilId, integer hotkey, real duration returns nothing
*           function SetCooldownDuration takes unit whichUnit, integer hotkey, real duration returns nothing
*           function GetCooldownDuration takes unit whichUnit, integer hotkey returns real
*           function SetCooldownAbilityId takes unit whichUnit, integer hotkey, integer abilId returns nothing
*           function GetCooldownAbilityId takes unit whichUnit, integer hotkey returns integer
*
*       - Event
*         ¯¯¯¯¯
*           function CooldownRegisterEvent takes trigger whichTrigger returns nothing
*               -   Fire when some cooldown starts
*           function CooldownRegisterFinishEvent takes trigger whichTrigger returns nothing
*               -   Fire when some cooldown ends
*           function GetEventCooldownUnit takes nothing returns unit
*               -   Matching unit of Events above
*           function GetEventCooldownAbilityId takes nothing returns integer
*               -   Matching ability id of Events above
*           function GetEventCooldownDuration takes nothing returns real
*               -   Remainer duration of Events above
*           function GetEventCooldownHotkey takes nothing returns integer
*               -   Matching hotkey of Events above
*
*       - Advanced Single
*         ¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯
*           function AddCooldownDuration takes unit whichUnit, integer hotkey, real duration returns nothing
*           function ReduceCooldownDuration takes unit whichUnit, integer hotkey, real duration returns nothing
*           function MultiplyCooldownDuration takes unit whichUnit, integer hotkey, real multiplier returns nothing
*           function DivideCooldownDuration takes unit whichUnit, integer hotkey, real diviser returns nothing
*           function StopCooldown takes unit whichUnit, integer hotkey returns nothing
*
*       - Advanced All
*         ¯¯¯¯¯¯¯¯ ¯¯¯
*           function SetAllCooldownDuration takes unit whichUnit, real duration returns nothing
*           function AddAllCooldownDuration takes unit whichUnit, real duration returns nothing
*           function ReduceAllCooldownDuration takes unit whichUnit, real duration returns nothing
*           function MultiplyAllCooldownDuration takes unit whichUnit, real multiplier returns nothing
*           function DivideAllCooldownDuration takes unit whichUnit, real diviser returns nothing
*           function StopAllCooldown takes unit whichUnit returns nothing
*
************************************************************************************/
function StartCooldown takes unit whichUnit, integer abilId, integer hotkey, real duration returns nothing
    call Cooldown[whichUnit].start(abilId, hotkey, duration)
endfunction

function SetCooldownDuration takes unit whichUnit, integer hotkey, real duration returns nothing
    call Cooldown[whichUnit].setDuration(hotkey, duration)
endfunction

function GetCooldownDuration takes unit whichUnit, integer hotkey returns real
    return Cooldown[whichUnit].duration(hotkey)
endfunction

function SetCooldownAbilityId takes unit whichUnit, integer hotkey, integer abilId returns nothing
    call Cooldown[whichUnit].setAbilityId(hotkey, abilId)
endfunction

function GetCooldownAbilityId takes unit whichUnit, integer hotkey returns integer
    return Cooldown[whichUnit].abilityId(hotkey)
endfunction

/************************************************************************************/

function StopCooldown takes unit whichUnit, integer hotkey returns nothing
    call SetCooldownDuration(whichUnit, hotkey, 0.)
endfunction

function AddCooldownDuration takes unit whichUnit, integer hotkey, real duration returns nothing
    call SetCooldownDuration(whichUnit, hotkey, GetCooldownDuration(whichUnit, hotkey) + duration)
endfunction

function ReduceCooldownDuration takes unit whichUnit, integer hotkey, real duration returns nothing
    call SetCooldownDuration(whichUnit, hotkey, GetCooldownDuration(whichUnit, hotkey) - duration)  
endfunction

function MultiplyCooldownDuration takes unit whichUnit, integer hotkey, real multiplier returns nothing
    call SetCooldownDuration(whichUnit, hotkey, GetCooldownDuration(whichUnit, hotkey) * multiplier)
endfunction

function DivideCooldownDuration takes unit whichUnit, integer hotkey, real diviser returns nothing
    call SetCooldownDuration(whichUnit, hotkey, GetCooldownDuration(whichUnit, hotkey) / diviser)
endfunction

/************************************************************************************/

function SetAllCooldownDuration takes unit whichUnit, real duration returns nothing
    local integer i = 0
    
    loop
        exitwhen i == 6
        call SetCooldownDuration(whichUnit, i, duration)
        set i = i + 1
    endloop
endfunction

function StopAllCooldown takes unit whichUnit returns nothing
    call SetAllCooldownDuration(whichUnit, 0)
endfunction

function AddAllCooldownDuration takes unit whichUnit, real duration returns nothing
    local integer i = 0
    
    loop
        exitwhen i == 6
        call SetCooldownDuration(whichUnit, i, GetCooldownDuration(whichUnit, i) + duration)
        set i = i + 1
    endloop
endfunction

function ReduceAllCooldownDuration takes unit whichUnit, real duration returns nothing
    local integer i = 0
    
    loop
        exitwhen i == 6
        call SetCooldownDuration(whichUnit, i, GetCooldownDuration(whichUnit, i) - duration)
        set i = i + 1
    endloop    
endfunction

function MultiplyAllCooldownDuration takes unit whichUnit, real multiplier returns nothing
    local integer i = 0
    
    loop
        exitwhen i == 6
        call SetCooldownDuration(whichUnit, i, GetCooldownDuration(whichUnit, i) * multiplier)
        set i = i + 1
    endloop    
endfunction

function DivideAllCooldownDuration takes unit whichUnit, real diviser returns nothing
    local integer i = 0
    
    loop
        exitwhen i == 6
        call SetCooldownDuration(whichUnit, i, GetCooldownDuration(whichUnit, i) / diviser)
        set i = i + 1
    endloop    
endfunction

/************************************************************************************/

function CooldownRegisterEvent takes trigger whichTrigger returns nothing
    call Cooldown.START.register(whichTrigger)
endfunction

function CooldownRegisterFinishEvent takes trigger whichTrigger returns nothing
    call Cooldown.FINISH.register(whichTrigger)
endfunction

function GetEventCooldownUnit takes nothing returns unit
    return Cooldown.Unit
endfunction

function GetEventCooldownAbilityId takes nothing returns integer
    return Cooldown.AbilityId
endfunction

function GetEventCooldownDuration takes nothing returns real
    return Cooldown.Duration
endfunction

function GetEventCooldownHotkey takes nothing returns integer
    return Cooldown.Hotkey
endfunction
endlibrary

Changelog
7.0.0.0
  • Rewrited code
  • Improved performance
  • Added Table as requirement
  • No bad code generated by normal struct anymore
  • Main struct now just have basic and important things
  • Created other library just for easy API

API 1.0.0.0
  • Release

6.2
  • Now uses GetVarObject to generate the abilities

6.1
  • Added globals for easy use
  • Added condition to check if want to refresh the cooldown

6.0
  • Added two events (onFinish and onStart)
  • Added API (and Tesh)
  • Public released since the contest
  • Fixed wrong position of the icon R
  • Fixed a bug with Object Editor abilities
  • Fixed a bug with crash using morph abilities
 

Attachments

  • Cooldown System 6.1.w3x
    99.7 KB · Views: 753
It should be using Nestharus' safe generation scripts.

It'd be nice if the demomap was attached directly to the post, not hotlinked.

Why would I use this instead of WC3 native cooldowns?
 
>>It should be using Nestharus' safe generation scripts
I don't know how to use that hack :(

>>It'd be nice if the demomap was attached directly to the post, not hotlinked.
Fixed.

>>Why would I use this instead of WC3 native cooldowns?
What Natives?
 
He meant normal object editor cooldown.

Oh... Well

Is impossible to Add/Remove/Manipulate Cooldown on Warcraft

An example of what my System do is, for example:

Ability A - Reduce the cooldown of all abilities in 10 seconds.
Ability B - Has 15 second of cooldown.


Cast B, cast A, now second ability will just need 5 more seconds to refresh the cooldown.
 
This system looks really cool! I don't suppose there is an easy way to add additional hotkeys (like for units that do not have the hero level up icon, move icon, etc. and have abilities in place of them)

It should be using Nestharus' safe generation scripts.

Those are obnoxious for the user as it requires them to go through a complex installation process to use this system.
 

Well..

I read everything and it don't work for me... I tried with 2 different newgens and the same error occur...

I really don't how what is and how to fix, searched about it and nothing....

The log is this: unfinished string near '"'

Also before save the log, editor show the error occur in FileExternal $FILENAME$
 
It'll tell you which line is bugging in the log... look in the Lua script (in temp folder) and find the line. It also tells you which Lua script it was (V#### or w/e).
 
Updated |:

Not sure if all right, but it generate the abilities right.
 
Don't import the constants ; P. You're using an array for this already, so the constants seem relatively pointless ; P.


Check out the writejass function in LUA_FILE_HEADER


I used writejass in my Bonus script ^)^.

JASS:

    /**********************************************************************
    *                                                                     *
    *                          GENERATE SCRIPT                            *
    *                                                                     *
    **********************************************************************/
    //generate globals
        //pw            powers
        //bd            bonus ability id
        //bp            bonus power
        //pm            power max
    //! i local script =
        //! i [[//! textmacro BONUS_DATA
        //! i globals
        //! i private integer array bd
        //! i private integer array bp
        //! i private integer array pw
        //! i private integer array pm
        //! i ]]
    //! i script = script .. const              --ability constant sets
    
    //generate script onInit
    //! i script = script ..
        //! i [[endglobals
        //! i private module I
        //! i private static method onInit takes nothing returns nothing
        //! i ]]
        
    //generate script PRELOAD
    //! i script = script ..
        //! i [[static if PRELOAD then
        //! i local unit u = CreateUnit(Player(14),&#039;hpea&#039;,0,0,0)
        //! i ]]
    //! i script = script .. preload
    
    //generate rest of onInit
    //! i script = script ..
    //! i [[call RemoveUnit(u)
    //! i set u = null
    //! i endif
    //! i ]]
    //! i script = script .. abil2              --ability data
    //! i script = script .. powmax             --max power (n)
    //! i script = script .. pows               --max power range (2^n)
    //! i script = script .. powerarray         --power on ability
    
    //write functions?
    //! i script = script..
    //! i [[endmethod
    //! i endmodule
    //! i private struct O extends array
    //! i implement I
    //! i endstruct
    //! i ]]
    
    //finish script
    //! i script = script .. [[//! endtextmacro]]
    
    //write script
    //! i writejass(&quot;BONUS&quot;,script)
    
    //create objects
    //! i updateobjects()
 
Nest

I'm not sure if you're talking about this

JASS:
            constant integer COOLDOWN_HOTKEY_Q  = 0
            constant integer COOLDOWN_HOTKEY_W  = 1
            constant integer COOLDOWN_HOTKEY_E  = 2
            constant integer COOLDOWN_HOTKEY_R  = 3
            
            constant integer COOLDOWN_HOTKEY_S  = 4
            constant integer COOLDOWN_HOTKEY_D  = 5


or this

JASS:
        set Cooldown_Ability[0] = COOLDOWN_ABILITY_Q
        set Cooldown_Ability[1] = COOLDOWN_ABILITY_W
        set Cooldown_Ability[2] = COOLDOWN_ABILITY_E
        set Cooldown_Ability[3] = COOLDOWN_ABILITY_R
        
        set Cooldown_Ability[4] = COOLDOWN_ABILITY_S
        set Cooldown_Ability[5] = COOLDOWN_ABILITY_D


But there's no reason to use a textmacro just to prevent some constants...

You said to me change the 'true' to 'false' but if you check, most of your system use the same way with 'true' and no textmacro as you said.

Anyway... If an moderator say to me do, I'll try.


I did all what tooltiperror said to do, and why I should prevent use of constants?

Me and most of all system here will need to use textmacro just to don't use constant?

I'm sorry Nest, but I disagree that.
 
Just saying that the constants aren't needed.


The script can obviously be improved. You're just being lazy about it =p.
 
I'm not being lazy >.> I just want to understand why I need to avoid constants when people don't avoid them >.<
 
(Fun when people still using something and tell you to don't use it, make really non-sense to me)...

I'll wait a Mod.
 
He's right, you should remove those public constants. You should also probably remove public functions that you don't use as well, like that StartCooldown function, I don't see it called anywhere in your script.

:trollface:
 
I'm saying that the only reason you are creating those constants is to store them into an array, which seems pointless. It makes more sense to just store the ids directly into the array and avoid the constants altogether considering that those constants are being generated to access the ids.

If you were actually using them, then np, but you aren't.

Why not eliminate the useless middle man?
 
General chit-chat
Help Users
  • Varine Varine:
    We have some elderly guests that regularly come hang out at the bar at the end of the night, and every once in a while we don't see someone for a few weeks and then someone shows up with their obituary.
  • Varine Varine:
    We usually let them do their memorials there in the morning if they want to and I'll make them some snacks and drinks. There was one guy named Tom that came in like every night and would sit by himself and get a bunch of soup and a glass of wine. idk why but he LOVED our fucking soup, like he would order a fucking quart of it at a time and would always get so sad when we stop doing it for the summer.
    +1
  • Varine Varine:
    But he also loved our calamari, which is another thing I hate but it sells super well so I can't change it. There was one day he came in and was asking me how to make it, because he tried to at home once in the off season when we stop running it and he really wanted it lol
  • Varine Varine:
    I think he's one of the only people I've made recipes for for free because he really wanted a broccoli cheddar, and it was like dude I don't have a recipe, it's just whatever I have, but here, this is how you do it
  • Varine Varine:
    I don't think he ever figured out how to do the calamari in a pan though, like idk how to do that either. He was afraid of the at home deep fryers though and it's like yeah, that's fair, I am too
  • Varine Varine:
    He was just such a sweet old man, we had two servers pregnant and they held a baby shower together, he was soooooo fucking excited to get to see a baby. Unfortunately he died a month or so before they were born
  • The Helper The Helper:
    So I decided to Google some people that I had not seen or heard from in a while and sure enough one of my old best friends, we had a falling out years ago but whatever, find out he died of Pancreatic Cancer in January. I have also lost a few of my closer acquaintances from growing up the last year. Getting old - people die - I kinda thought it was going to be this way a few years ago....
    +2
  • The Helper The Helper:
    Forum running super slow again
  • Ghan Ghan:
    Not really clear from the stats as to what is causing the slowness.
  • Ghan Ghan:
    We get a lot of guest traffic so it may just be the load is getting too high and not from any particular source.
  • Ghan Ghan:
    Looks like the server is maxed out on CPU.
  • Ghan Ghan:
    Oh it looks like a lot of the traffic is Silkroad Forums. That domain isn't protected by Cloudflare.
  • Ghan Ghan:
    But the old Silkroad site is still on its own server. I just had a test site set up on this server for it.
  • Ghan Ghan:
    I just disabled that test site. Let's see if that helps the load.
  • Ghan Ghan:
    Looks much better already.
  • The Helper The Helper:
    I had actually forgot about the Silkroad site. I had asked
  • The Helper The Helper:
    SD Ryoko about it and he said the couple of people left on there really like it, that was a few years ago, maybe I should check back
  • jonas jonas:
    I guess when you're getting old, and the last day of soup season draws near, you start wondering
  • jonas jonas:
    will I make it to the start of the next season? or was this the last time I'll ever have my favorite dish?
  • The Helper The Helper:
    I am doing my first Vibe Coding project. In installed the environment and tools according to instructions but it is all chat doing this for me at my direction. It is fun really and holy shit I might finish in 2 hours what it would have taken a day to in my Access and this would be an electron app complete new
  • Ghan Ghan:
    Good stuff.
  • Ghan Ghan:
    Just make sure it is secure. :)
    +1
  • The Helper The Helper:
    It will only be on internal network
  • jonas jonas:
    Man the AI is good about gaslighting about security though. I've had several times where I pointed out security problems and it tried to convince me that with a tiny tweak it suddenly becomes secure
  • jonas jonas:
    Like using a distrobox as a "secure" container, and when I point out that's not secure at all, it claimed that specifying home will make it secure

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials
      Top