System Damage

Jesus4Lyf

Good Idea™
Damage​
Version 1.0.5​

Requirements:
- Jass NewGen
- AIDS
- Event

JASS:
//  
//      ___   _     __  __   _   ___  ____    _______________________________
//     |   \ /_\   /  |/  | /_\ /  _\|  __|   ||      D E A L   I T ,      ||
//     | |) / _ \ / / | / |/ _ \| |/||  __|   ||    D E T E C T   I T ,    ||
//     |___/_/ \_/_/|__/|_|_/ \_\___/|____|   ||     B L O C K   I T .     ||
//                            By Jesus4Lyf    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//                                                                    v 1.0.5
//      What is Damage?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Damage is a damage dealing, detection and blocking system. It implements
//          all such functionality. It also provides a means to detect what type
//          of damage was dealt, so long as all damage in your map is dealt using
//          this system's deal damage functions (except for basic attacks).
//
//          It is completely recursively defined, meaning if you deal damage on
//          taking damage, the type detection and other features like blocking
//          will not malfunction.
//          
//      How to implement?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Create a new trigger object called Damage, go to 'Edit -> Convert to
//          Custom Text', and replace everything that's there with this script.
//
//          At the top of the script, there is a '//! external ObjectMerger' line.
//          Save your map, close your map, reopen your map, and then comment out this
//          line. Damage is now implemented. This line creates a dummy ability used
//          in the system in some circumstances with damage blocking.
//
//      Functions:
//     ¯¯¯¯¯¯¯¯¯¯¯¯
//          function Damage_RegisterEvent takes trigger whichTrigger returns nothing
//              - This registers a special "any unit takes damage" event.
//              - This event supports dynamic trigger use.
//              - Only triggers registered on this event may block damage.
//              - Only fires when the damage dealt is not 0.
//
//          function Damage_RegisterZeroEvent takes trigger whichTrigger returns nothing
//              - The same as Damage_RegisterEvent, but for only zero damage events
//                (which are excluded from Damage_RegisterEvent).
//              - Note that getting the damage type may be unreliable, since spells
//                like faerie fire trigger 0 damage, but it will count as an attack.
//
//          function Damage_GetType takes nothing returns damagetype
//              - This will get the type of damage dealt, like an event response,
//                for when using a unit takes damage event (or the special event above).
//
//          function Damage_IsPhysical takes nothing returns boolean
//          function Damage_IsSpell takes nothing returns boolean
//          function Damage_IsPure takes nothing returns boolean
//              - Wrappers to simply check if Damage_GetType is certain types.
//
//          function Damage_IsAttack takes nothing returns boolean
//              - Checks if the damage is from a physical attack (so you can deal
//                physical damage without it being registered as an actual attack).
//
//          function Damage_Block takes real amount returns nothing
//          function Damage_BlockAll takes nothing returns nothing
//              - For use only with Damage_RegisterEvent.
//              - Blocks 'amount' of the damage dealt.
//              - Multiple blocks at once work correctly.
//              - Blocking more than 100% of the damage will block 100% instead.
//              - Damage_BlockAll blocks 100% of the damage being dealt.
//
//          function Damage_EnableEvent takes boolean enable returns nothing
//              - For disabling and re-enabling the special event.
//              - Use it to deal damage which you do not want to be detected by
//                the special event.
//
//          function UnitDamageTargetEx takes lots of things returns boolean
//              - Replaces UnitDamageTarget in your map, with the same arguments.
//
//          function Damage_Physical takes unit source, unit target, real amount,
//            attacktype whichType, boolean attack, boolean ranged returns boolean
//              - A clean wrapper for physical damage.
//              - 'attack' determines if this is to be treated as a real physical
//                attack or just physical type damage.
//              - 'ranged' determines if this is to be treated as a ranged or melee
//                attack.
//
//          function Damage_Spell takes unit source, unit target, real amount returns boolean
//              - A clean wrapper for spell damage.
//
//          function Damage_Pure takes unit source, unit target, real amount returns boolean
//              - A clean wrapper for pure type damage (universal type, 100% damage).
//          
//      Thanks:
//     ¯¯¯¯¯¯¯¯¯
//          - Romek, for helping me find a better way to think about damage blocking.
//
library Damage uses AIDS, Event
    //============================================================
    //! external ObjectMerger w3a AIlz dprv anam "Life Bonus" ansf "(Damage System)" Ilif 1 500000 aite 0
    globals
        private constant integer LIFE_BONUS_ABIL='dprv'
    endglobals
    
    //============================================================
    globals
        private Event OnDamageEvent
        private Event OnZeroDamageEvent
        private boolean EventEnabled=true
    endglobals
    
    public function RegisterEvent takes trigger whichTrigger returns nothing
        call OnDamageEvent.register(whichTrigger)
    endfunction
    
    public function RegisterZeroEvent takes trigger whichTrigger returns nothing
        call OnZeroDamageEvent.register(whichTrigger)
    endfunction
    
    public function EnableEvent takes boolean enable returns nothing
        set EventEnabled=enable
    endfunction
    
    //============================================================
    globals
        private integer TypeStackLevel=0
        private damagetype array TypeStackValue
        private boolean array TypeStackAttack
        private real array ToBlock
    endglobals
    
    public function GetType takes nothing returns damagetype
        return TypeStackValue[TypeStackLevel]
    endfunction
    
    public function IsAttack takes nothing returns boolean
        return TypeStackAttack[TypeStackLevel]
    endfunction
    
    public function Block takes real amount returns nothing
        set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel]+amount
    endfunction
    
    public function BlockAll takes nothing returns nothing
        set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel]+GetEventDamage()
    endfunction
    
    //============================================================
    globals
        private integer BlockNum=0
        private unit array BlockUnit
        private real array BlockUnitLife
        private real array BlockRedamage
        private unit array BlockDamageSource
        
        private timer BlockTimer=CreateTimer()
    endglobals
    
    //============================================================
    globals
        private unit array RemoveBoosted
        private integer RemoveBoostedMax=0
        
        private timer RemoveBoostedTimer=CreateTimer()
    endglobals
    
    globals//locals
        private real BoostedLifeTemp
        private unit BoostedLifeUnit
    endglobals
    private function RemoveBoostedTimerFunc takes nothing returns nothing
        loop
            exitwhen RemoveBoostedMax==0
            set BoostedLifeUnit=RemoveBoosted[RemoveBoostedMax]
            set BoostedLifeTemp=GetWidgetLife(BoostedLifeUnit)
            call UnitRemoveAbility(BoostedLifeUnit,LIFE_BONUS_ABIL)
            if BoostedLifeTemp>0.405 then
                call SetWidgetLife(BoostedLifeUnit,BoostedLifeTemp)
            endif
            set RemoveBoostedMax=RemoveBoostedMax-1
        endloop
    endfunction
    
    //============================================================
    private keyword Detector // Darn, I actually had to do this. XD
    globals//locals
        private unit ForUnit
        private real NextHealth
    endglobals
    private function OnDamageActions takes nothing returns boolean
        if EventEnabled then
            if GetEventDamage()==0. then
                call OnZeroDamageEvent.fire()
            else
                call OnDamageEvent.fire()
            endif
            
            if ToBlock[TypeStackLevel]!=0. then
                //====================================================
                // Blocking
                set ForUnit=GetTriggerUnit()
                
                set NextHealth=GetEventDamage()
                if ToBlock[TypeStackLevel]>=NextHealth then
                    set NextHealth=GetWidgetLife(ForUnit)+NextHealth
                else
                    set NextHealth=GetWidgetLife(ForUnit)+ToBlock[TypeStackLevel]
                endif
                
                call SetWidgetLife(ForUnit,NextHealth)
                if GetWidgetLife(ForUnit)<NextHealth then
                    // NextHealth is over max health.
                    call UnitAddAbility(ForUnit,LIFE_BONUS_ABIL)
                    call SetWidgetLife(ForUnit,NextHealth)
                    
                    set RemoveBoostedMax=RemoveBoostedMax+1
                    set RemoveBoosted[RemoveBoostedMax]=ForUnit
                    call ResumeTimer(RemoveBoostedTimer)
                endif
                //====================================================
                set ToBlock[TypeStackLevel]=0.
            endif
        endif
        return false
    endfunction
    
    //============================================================
    function UnitDamageTargetEx takes unit whichUnit, widget target, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, weapontype weaponType returns boolean
        local boolean result
        set TypeStackLevel=TypeStackLevel+1
        set TypeStackValue[TypeStackLevel]=damageType
        set TypeStackAttack[TypeStackLevel]=attack
        set result=UnitDamageTarget(whichUnit,target,amount,attack,ranged,attackType,damageType,weaponType)
        set TypeStackLevel=TypeStackLevel-1
        return result
    endfunction
    //! textmacro Damage__DealTypeFunc takes NAME, TYPE
        public function $NAME$ takes unit source, unit target, real amount returns boolean
            return UnitDamageTargetEx(source,target,amount,false,false,ATTACK_TYPE_NORMAL,$TYPE$,WEAPON_TYPE_WHOKNOWS)
        endfunction
        public function Is$NAME$ takes nothing returns boolean
            return GetType()==$TYPE$
        endfunction
    //! endtextmacro
    
    //! runtextmacro Damage__DealTypeFunc("Pure","DAMAGE_TYPE_UNIVERSAL")
    //! runtextmacro Damage__DealTypeFunc("Spell","DAMAGE_TYPE_MAGIC")
    
    // Uses different stuff, but works much the same way.
    public function Physical takes unit source, unit target, real amount, attacktype whichType, boolean attack, boolean ranged returns boolean
        return UnitDamageTargetEx(source,target,amount,attack,ranged,whichType,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
    endfunction
    public function IsPhysical takes nothing returns boolean
        return GetType()==DAMAGE_TYPE_NORMAL
    endfunction
    
    //============================================================
    private struct Detector extends array // Uses AIDS.
        //! runtextmacro AIDS()
        
        private static conditionfunc ACTIONS_COND
        
        private trigger t
        
        private method AIDS_onCreate takes nothing returns nothing
            set this.t=CreateTrigger()
            call TriggerAddCondition(this.t,thistype.ACTIONS_COND)
            call TriggerRegisterUnitEvent(this.t,this.unit,EVENT_UNIT_DAMAGED)
        endmethod
        
        private method AIDS_onDestroy takes nothing returns nothing
            call DestroyTrigger(this.t)
        endmethod
        
        private static method AIDS_onInit takes nothing returns nothing
            set thistype.ACTIONS_COND=Condition(function OnDamageActions)
        endmethod
    endstruct
    
    //============================================================
    private module InitModule
        private static method onInit takes nothing returns nothing
            local unit abilpreload=CreateUnit(Player(15),'uloc',0,0,0)
            call UnitAddAbility(abilpreload,LIFE_BONUS_ABIL)
            call RemoveUnit(abilpreload)
            set abilpreload=null
            
            set OnDamageEvent=Event.create()
            set OnZeroDamageEvent=Event.create()
            set TypeStackValue[TypeStackLevel]=DAMAGE_TYPE_NORMAL
            set TypeStackAttack[TypeStackLevel]=true
            call TimerStart(RemoveBoostedTimer,0.0,false,function RemoveBoostedTimerFunc)
        endmethod
    endmodule
    private struct InitStruct extends array
        implement InitModule
    endstruct
endlibrary

TESH Highlighting:
JASS:
//
//      _____ ___ ___ _   _ 
//     |_   _| __/ __| |_| |
//       | | | _|\__ \  _  |
//       |_| |___|___/_| |_| Highlighting:
//                            - Damage by Jesus4Lyf.
//
//      What is this?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Implementing this allows the TESH syntax highlighter in Jass NewGen
//          to highlight the syntax for this system (and autocomplete the functions).
//          
//      How to import?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Copy this into a blank text file, and save it at:
//          <Your Jass NewGen folder>\tesh\includes\Damage.j
//
function Damage_RegisterEvent takes trigger whichTrigger returns nothing
    // Registers an event: Any unit is damaged.
endfunction
function Damage_RegisterZeroEvent takes trigger whichTrigger returns nothing
    // Registers an event: Any unit is dealt zero damage.
endfunction
function Damage_GetType takes nothing returns damagetype
    // Requires all damage in the map (except basic attacks) to be dealt with one of:
    //  - UnitDamageTargetEx
    //  - Damage_Physical
    //  - Damage_Spell
    //  - Damage_Pure
endfunction
function Damage_IsPhysical takes nothing returns boolean
    // Requires all damage in the map (except basic attacks) to be dealt with one of:
    //  - UnitDamageTargetEx
    //  - Damage_Physical
    //  - Damage_Spell
    //  - Damage_Pure
endfunction
function Damage_IsSpell takes nothing returns boolean
    // Requires all damage in the map (except basic attacks) to be dealt with one of:
    //  - UnitDamageTargetEx
    //  - Damage_Physical
    //  - Damage_Spell
    //  - Damage_Pure
endfunction
function Damage_IsPure takes nothing returns boolean
    // Requires all damage in the map (except basic attacks) to be dealt with one of:
    //  - UnitDamageTargetEx
    //  - Damage_Physical
    //  - Damage_Spell
    //  - Damage_Pure
endfunction
function Damage_IsAttack takes nothing returns boolean
    // Requires all damage in the map (except basic attacks) to be dealt with one of:
    //  - UnitDamageTargetEx
    //  - Damage_Physical
    //  - Damage_Spell
    //  - Damage_Pure
endfunction
function Damage_Block takes real amount returns nothing
    // Must only be used from a trigger with the event from:
    //  - Damage_RegisterEvent
endfunction
function Damage_BlockAll takes nothing returns nothing
    // Must only be used from a trigger with the event from:
    //  - Damage_RegisterEvent
endfunction
function Damage_EnableEvent takes boolean enable returns nothing
endfunction
function UnitDamageTargetEx takes unit source, widget target, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, weapontype weaponType returns boolean
    // The same parameters as the native UnitDamageTarget, but allows type detection.
endfunction
function Damage_Physical takes unit source, unit target, real amount, attacktype whichType, boolean attack, boolean ranged returns boolean
    // "attack" is whether or not the damage is an attack.
    // "ranged" is whether or not the damage is a ranged attack (set "attack" to true also).
endfunction
function Damage_Spell takes unit source, unit target, real amount returns boolean
endfunction
function Damage_Pure takes unit source, unit target, real amount returns boolean
endfunction

"Damage" is a full damage system for any map. It doesn't leak events internally, supports damage-on-damage functions without bugging (so it supports recursion), etc.

The main features are:
  • An AnyUnitDamaged event (which supports dynamic triggers just fine)
  • Instant damage blocking (only for triggers registered on the above event)
  • Get dealt damage type (as long as all damage is dealt with the functions from this system - except for basic attacks - which means the map's spells must damage through this system and not use damage from things like frost nova... so this feature is only for maps where the map is built to run on this system).
Demo map is a simple demonstration of stopping everything from dealing damage on the map. :)

Updates:
- Version 1.0.5: Added Damage_RegisterZeroEvent(trig).
- Version 1.0.4: Changed initialiser to module/struct to make it fire first.
- Version 1.0.3: Stopped detection of 0.0 damage events.
- Version 1.0.2: Added Damage_IsPure(), Damage_IsSpell(), Damage_IsPhysical() and Damage_IsAttack() (so damage can be physical but not count as an attack).
- Version 1.0.1: Changed the syntax from EnableEvent and DisableEvent to EnableEvent(boolean).
- Version 1.0.0: Release.
 

Attachments

Renendaru

(Evol)ution is nothing without love.
Finally you submit this, once you told me about it on the chat I couldn't wait. :thup:
Looks good.
 

Viikuna

No Marlo no game.
It would be better to use use one trigger with multiple events to detect damage and recycle units to avoid event leaks, but I guess this is ok too...
 

Troll-Brain

You can change this now in User CP.
Recycle units is not easy, and i guess a good universal system can't be done without any Warcraft III 3rd party tools like GMSI .
If you want a good recycle system you should use many instant morph abilities and there are many side effect to play around them ...
 

Steel

Software Engineer
It would be a good idea to benchmark your system with a small, medium, large and very large number of units at once. I know from experience that having too many units in a system like this that has too many function calls or conditions can cause noticeable slowdowns. You may want to examine this because the slowdowns can get to the point where players can see what is happening and you always want to mask what your system is doing.
 

T.s.e

Wish I was old and a little sentimental
Who cares if this is one hundredth of a milisecond slower than another system, as long as it's easily used and actually works, that's enough for me.
 

Hatebreeder

So many apples
JASS:
    globals//locals
        private real BoostedLifeTemp
        private unit BoostedLifeUnit
    endglobals


What do you mean with Globals/Locals?
I don't see how they behave like locals, actually... Since they ARE globals, or?
I havn't used vJASS for a while now...
Many things changed :X
 

Romek

Super Moderator
Staff member
He just uses global variables instead of local variables in the instant functions.
They're about 0.000000000001 nanoseconds faster, and don't need nulling. :p
 

Jesus4Lyf

Good Idea™
Yay, replies.

>It would be better to use use one
I'm not going to release a system that assumes players took the ridiculous measure to recycle units, and if they did, I believe the triggers in this would never actually get destroyed, so this supports unit recycling just fine anyway. :thup:

>It would be a good idea to benchmark your system
Benchmark -what- part of my system? Every single part of this system is O(1) complexity (in relation to its interface) so nothing should slow down anything at all. I don't know what you're talking about with units slowing things down, can you give me an example of why it might slow?

Looking at that alternative (no offense to the author, but these are the things I noticed):
IDDS:
  • Doesn't work: If you have a damage on damage action, the damage type and stuff screws up completely. It isn't recursively defined, which is VITAL to a system like this actually being reliable. I would never use IDDS for that reason - it breaks.
  • Uses TriggerUnregisterDamageEvent which isn't a nice interface, so this isn't behaving like a real event anyway, because you can't just destroy triggers.
  • Damage type is an integer (how is that intuitive?) which is actually one of the reasons I wrote this.
  • Uses H2I (Table) which will break on 1.24, etc. I do not want any of my maps to break when new patches come out. Purely personal choice, but I wrote this system out of necessity.
  • Has an O(n) complexity trigger sorting mechanism for some reason.
That was just at a quick glance.

>Who cares if this is one hundredth of a milisecond slower than another system
No, this system should be faster than other systems which try to accomplish the same thing. AND actually work. :) :thup:
 

Renendaru

(Evol)ution is nothing without love.
I've updated most triggers to use Damage and most things are running faster/better than they did. For example my trigger used to be delayed since I had to use a wait in a trigger for my old system. But now, it works perfectly without delays.
 

lep

Active Member
>Uses H2I (Table) which will break on 1.24, etc. I do not want any of my maps to break >when new patches come out. Purely personal choice, but I wrote this system out of >necessity.

Hell, no. Since he uses Table as a abstraction everyone using IDDS just have to update
Table.

>Has an O(n) complexity trigger sorting mechanism for some reason.

An O(n) sorting algorithm wouls be awesome....


>>Who cares if this is one hundredth of a milisecond slower than another system
>No, this system should be faster than other systems which try to accomplish the >same thing. AND actually work. :) :thup:

Ahh, that kind of mapper...
And don't use Dusks System but i would prefer his to this, because those priorities are actualy quite nice.
 

Jesus4Lyf

Good Idea™
>Hell, no. Since he uses Table as a abstraction everyone using IDDS just have to update Table.
Actually, he incorporated his own H2I and didn't use HandleTables. Besides (and this is irrelevant), even using HandleTables in your map will make it break for 1.24. I want my 1.23 RELEASE to work on 1.24.

>An O(n) sorting algorithm wouls be awesome....
Actually, his is O(n^2).

>Ahh, that kind of mapper...
Yes, that kind of mapper. One who makes things which work. The fact that most of my stuff is highly efficient is a side bonus.

By the way, you can do sequencing just fine. Just register multiple conditions or actions on one trigger in the order you want them run...? <_<

By all means, use whatever you like. I wrote this because I needed it, so I figured it would be useful for others. :)
 

Kenny

Back for now.
Awesome, finally a good all-purpose full damage system for maps. Looks very cool, and interface is simple as, love it.

Once again, if I actually needed damage detection, I think I found the system to use.

Nice work. :D
 

D.V.D

Make a wish
JASS:
function UnitDamageTargetEx takes lots of things returns boolean


What if a GUI user wanted to use this? He would have to search your code to find out what function calls he needs to do and even if he found it, he still might not know how to call the function.
 

Romek

Super Moderator
Staff member
This system wasn't designed for GUI users.
 

D.V.D

Make a wish
But what if a GUI user want to use it? You could atleast just wright what the function takes.
 

uberfoop

~=Admiral Stukov=~
'But what if a foreign medical aid service wanted to use the Topol-M missile launch vehicle? You should at least include instructions on how to load medical supplies into the missile tube.'


Using AIDS within GUI would be horrifying to consider even if you were a master of both Jass and GUI. There's really no point facilitating it. I mean, if you're so beastly that you can actually use AIDS within GUI's structure, you'll have no trouble figuring out what that function takes.
 

Darthfett

Super Mod
But what if a GUI user want to use it?
Then he can spend the day or two learning JASS, instead of the week or two trying to figure out how to use a custom event system within GUI.

There are very few systems that should actually be used within GUI, and those are the one-function-call do-it-all-for-you systems, such as a knockback system.

Since there is no native way to add GUI function calls, every part of a system like this would need to deal with custom script. There are even conditional functions in here. There isn't any *native* custom script for conditions.

I would recommend adding in documentation about what the returned booleans mean for the functions, but other than that, good job. :)
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    It is online though at night
  • The Helper The Helper:
    You would probably have to take a loan to get the Rice cert it is like 14l
  • The Helper The Helper:
    I was hoping you were going to say you wanted to be a cook and wished to open up a Food Truck there are so many opportunities for that here
  • The Helper The Helper:
    you can only open the bar if you sell food and a food truck in the parking lot counts
  • The Helper The Helper:
    here in houston
  • The Helper The Helper:
    most bars are struggling to build food prep and even some I know are doing there own food trucks
  • The Helper The Helper:
    but yeah man you should come to Houston there is so much more opportunity here than San Antonio. Just look at all the homeless people on the Riverwalk and downtown there you cannot even walk down the street without getting mobbed them
  • The Helper The Helper:
    check out this place apparently it is the best roommate site out there roommates.com lol
  • Varine Varine:
    The homeless people reminded me of New York
  • Varine Varine:
    I'll check it out, my lease expires in like a few months so I need to figure something out.
  • Varine Varine:
    I tried to open a food truck in Sandpoint a few years ago but the city said no, then like two years later they passed new laws to encourage it and gave them all fucking tax breaks and shit. And at that point I didn't have enough money to go buy one so I was way too late to the game once other cities realized they could just bring their existing truck there, or sell their brick and mortar.
  • Varine Varine:
    I do like food trucks though, they're way more fun than restaurants and usually I also get some of that tip money there.
  • Varine Varine:
    Restaurants are really hard if you don't have a back up source of income to fund them sometimes, in my experience most owners either got really really lucky, had existing money that allowed them to buy an already successful one, or they have family money to fall back on for loans. It's few and far between to see very inspiring success stories where the person actually got it through hard work and perseverance. I thought about opening one lots and I always just end up not thinking it'll work. I would much rather just find someone that has that money and go work for them
  • The Helper The Helper:
    i am not talking about opening a brick and mortar I am talking about food trucks though I have seen some brick and mortar mexican places open up during covid that are doing good because there food is awesome!
  • The Helper The Helper:
    Food trucks are killing out here because Bars cannot open unless they sell food and the governor ok'd the use of a food truck in front as serving food
  • The Helper The Helper:
    Just not enough food trucks
  • The Helper The Helper:
    a buddy of mine just opened up a food truck and he is killing it but he is a great cook and has awesome food right in the middle of the pandemic too food trucks are immune to pandemic because they are take out in Texas you will always be able to get take out or delivery
  • The Helper The Helper:
    He is in the different food facebook groups in houston and posts videos of him making his food
  • The Helper The Helper:
    he is killing it
  • jonas jonas:
    @Varine with the restaurants, there surely is a lot of luck and hard work but most restaurants fail because they suck. Flair isn't right, economics not well thought through, food is mediocre or sucks, location is bad, etc. If you're thinking about opening one, make sure you're looking at the stories of those that would be playing at your level, don't let your hopes be dragged down by all the subpar restaurants out there.
  • jonas jonas:
    I'm a bit worried about the future of data science, there's an influx of incompetent people hired by incompetent managers, that can't last. But I'm sure smart data scientists will always be useful and hireable. Same as smart security people.
  • jonas jonas:
    My sister in law worked in a vegan food truck, the owners were also making a killing, added several trucks and opened two restaurants over 5 years
  • Ghan Ghan:
    The CompTIA stuff is pretty much crap unfortunately. The places that ask for those low-level certs aren't likely places you want to work. For IT you really want a degree, but in the meantime you need to figure out some way to learn the skills. Cybersecurity is really hot right now so competition is fierce.
  • tom_mai78101 tom_mai78101:
    I realized I don't have anything much to say, other than "Good luck!". Compared to other places, I'm just very lucky we didn't have a lot of surges of cases coming in.

    Staff online

    • Ghan
      Administrator - Servers are fun

    Members online

    Affiliates

    Hive Workshop
    Top