• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Super Frost Joke 1.0

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
  • Like
Reactions: deepstrasz
My entry to the Spells And Systems Mini Contest 19...
JASS:
/*

    Super Frost Joke by Adiktuz
    
    Description:
        The caster cracks a joke which can freeze enemy units around him
    
    Configurables:
        -The jokes
        -The chances of freezing for each joke
        -The duration of the freeze
        -The targets of the freeze
        -The damage of the freeze
        -The AoE of the freeze
    
    How to import:
        -Copy and paste this code into your trigger editor
        -Copy the two abilities and the buff
        -Create a dummy caster if you don't have one or copy the one on this map
        -Change the rawcodes to fit the new rawcodes on your map
        -Edit the configurables to your liking
        -Add your jokes using [function RegisterJokes takes string joke, real chance]
            *examples given on InitJokes trigger
        
        IMPORTANT: On the gameplay constants, set the UNIT MIN MOVESPEED to 0.00
    
    Credits:
        Jesus4Lyf for Timer32
    
*/

library SuperFrostJoke initializer Init requires T32

    globals
    
        //The rawcode of the Frost joke spell
        private constant integer FJ_SPELL_ID = 'A000'
        
        //The rawcode of the frost joke buff placer (the soulburn-based ability)
        private constant integer FJ_BUFFPLACER_ID = 'A001'
        
        //The rawcode of the frost joke buff which the buffplacer uses
        private constant integer FJ_BUFF_ID = 'B000'
        
        //The rawcode of the dummy unit
        private constant integer DUMMY_ID = 'h000'
        
        //Checks if the FJ deals damage, if yes be sure to set the damage amount at the function below the globals
        private constant boolean DEALS_DAMAGE = false
        
        //Checks if the FJ deals damage after the duration, if yes be sure to set the damage amount at the function below the globals
        private constant boolean DEALS_END_DAMAGE = true
        
        /*
            Checks if the duration of the buff will stack if a unit gets hit by SFJ while still
            being affected by a previous one, if false, the new cast will overwrite the older one
        */
        private constant boolean STACK_TIME = false
        
        //The attack type of the primary damage
        private constant attacktype ATPD = ATTACK_TYPE_NORMAL
        
        //The damage type of the primary damage
        private constant damagetype DTPD = DAMAGE_TYPE_NORMAL
        
        //The attack type of the secondary damage
        private constant attacktype ATSD = ATTACK_TYPE_NORMAL
        
        //The damage type of the secondary damage
        private constant damagetype DTSD = DAMAGE_TYPE_NORMAL
        
        //DO NOT EDIT BELOW THIS LINE UP TO THE NEXT COMMENT
        private string array FrostJokes //[8190]
        
        private real array FrostChances //[8190]
        
        private integer JokesTotal = 0
        
        private group FJ_Group = CreateGroup()
        
        private boolean array IsJokeShown
        
        private hashtable SFJ_Hash = InitHashtable()
        
        //END of DO NOT EDIT
    endglobals
    
    //Set the damage formula using this function
    private function GetDamage takes integer level returns real
        return 0.00
    endfunction
    
    //Set the end damage formula using this function
    private function GetEndDamage takes integer level returns real
        return 75.00*level
    endfunction
    
    //Set the buff duration using this function
    private function GetDuration takes integer level returns real
        return 5.00
    endfunction
    
    //Set the chance formula using this function
    private function GetChance takes integer level, integer index returns real
        return FrostChances[index]
    endfunction
    
    //Set The AoE formula using this function
    private function GetAoE takes integer level returns real
        return 250.00*level
    endfunction
    
    //The frost joke struct which handles most of the system's work
    private struct FrostJokeStruct
    
        unit target //the units hit by SFJ
        
        unit caster //the caster of SFJ
        
        integer abillevel //the ability level of SFJ for the caster
        
        real timeleft //the timeleft for the duration of the buff
        
        static thistype data
        
        static unit TempUnit = null
        
        static unit FiltUnit = null
        
        static unit TempCaster = null
        
        static real chance = 0.00
        
        static integer joke
        
        static integer level
        
        static integer playern
        
        static player controller
        
        static integer id
        
        /*
            the periodic method for the buff duration, executed by T32
        */
        private method periodic takes nothing returns nothing
            set this.timeleft = this.timeleft - T32_PERIOD
            if this.timeleft <= 0.00 then
                call this.stopPeriodic()
                call UnitRemoveAbility(this.target, FJ_BUFFPLACER_ID)
                call UnitRemoveAbility(this.target, FJ_BUFF_ID)
                call FlushChildHashtable(SFJ_Hash, GetHandleId(this.target))
                if DEALS_END_DAMAGE then
                    call UnitDamageTarget(this.caster, this.target, GetEndDamage(this.abillevel), false, false, ATPD, DTPD, null)
                endif
                call this.destroy()
            endif
        endmethod
        
        //implements the T32x module
        implement T32x
        
        /*
            the method run when a unit gets hit by the SFJ
        */
        static method create takes unit target, unit caster, integer level returns thistype
            set thistype.id = GetHandleId(target)
            set data = LoadInteger(SFJ_Hash, thistype.id, 0)
            /*
                if the unit is currently unaffected by a SFJ, a new instance is created
                else we override the current one or increase the time depending 
                on the global STACK_TIME
            */
            if data == 0 then 
                set data = thistype.allocate()
                set data.target = target
                set data.caster = caster
                set data.abillevel = level
                set data.timeleft = GetDuration(level)
                set thistype.TempCaster = CreateUnit(GetOwningPlayer(caster), DUMMY_ID,GetUnitX(caster), GetUnitY(caster), 0.00)
                call UnitApplyTimedLife(thistype.TempCaster, 'BTLF', .5)
                call SetUnitExploded(thistype.TempCaster, true)
                call UnitAddAbility(thistype.TempCaster, FJ_BUFFPLACER_ID)
                call IssueTargetOrder(thistype.TempCaster, "soulburn", target)
                call data.startPeriodic()
                call SaveInteger(SFJ_Hash, thistype.id, 0, data)
            else
                set data.target = target
                set data.caster = caster
                set data.abillevel = level
                if STACK_TIME then
                    set data.timeleft = data.timeleft + GetDuration(level)
                else
                    set data.timeleft = GetDuration(level)
                endif
            endif
            if DEALS_DAMAGE then
                call UnitDamageTarget(caster, target, GetDamage(level), false, false, ATPD, DTPD, null) 
            endif
            return data
        endmethod
        
        /*
            this method checks if a unit will get affected by the SFJ or not
        */
        static method FrostJokeGroupLoop takes nothing returns boolean
            set thistype.FiltUnit = GetFilterUnit()
            set thistype.controller = GetOwningPlayer(FiltUnit)
            set thistype.playern = GetPlayerId(thistype.controller)
            if not IsJokeShown[thistype.playern] then
                set IsJokeShown[thistype.playern] = true
                call DisplayTextToPlayer(thistype.controller, 0, 0, FrostJokes[thistype.joke])
            endif
        
            //checks if the unit is alive
            if GetWidgetLife(FiltUnit) > .405 and /*
                checks if the unit is an enemy
            */ IsPlayerEnemy(thistype.controller, GetOwningPlayer(thistype.TempUnit)) and /*
                checks if the unit will be frozen
            */ GetRandomReal(0.00, 100.00) <= thistype.chance then
                call FrostJokeStruct.create(FiltUnit, thistype.TempUnit ,thistype.level)
            endif
            return false
        endmethod
        
        /*
          this method picks every unit around the caster of SFJ and passes them to the method above  
        */
        static method FrostJoke takes nothing returns boolean
            local integer i = 0
            set thistype.TempUnit = GetTriggerUnit()
            set thistype.level = GetUnitAbilityLevel(thistype.TempUnit, FJ_SPELL_ID)
            set thistype.joke = GetRandomInt(0, JokesTotal)
            set thistype.chance = GetChance(thistype.level, thistype.joke)
            if GetSpellAbilityId() == FJ_SPELL_ID then
                call GroupEnumUnitsInRange(FJ_Group, GetUnitX(thistype.TempUnit), GetUnitY(thistype.TempUnit), GetAoE(thistype.level), Condition(function thistype.FrostJokeGroupLoop))
            endif
            loop
                exitwhen i > 15
                set IsJokeShown[i] = false
                set i = i + 1
            endloop
            return false
        endmethod
    
    endstruct
    
    //The init method of this library
    private function Init takes nothing returns nothing
        local integer i = 0
        local trigger t = CreateTrigger()
        loop
            exitwhen i > 15
            call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            set i = i + 1
        endloop
        call TriggerAddCondition(t, Condition(function FrostJokeStruct.FrostJoke))
        set t = null
    endfunction
    
    //The function used to register jokes
    function RegisterJokes takes string joke, real chance returns nothing
        set FrostJokes[JokesTotal] = joke
        set FrostChances[JokesTotal] = chance
        set JokesTotal = JokesTotal + 1
    endfunction
    
endlibrary

Keywords:
joke, contest, spells, frost, ragnarok, bard, lame, freezing, slow, soulburn, vjass, jass, adiktuz
Contents

SFJ 1.0 (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. 19th Oct 2011 Bribe: Could use some static if's instead of dynamic ones in areas where you reference constant booleans. FirstOfGroup loop are way superior to group filters. Inlining...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.

19th Oct 2011
Bribe: Could use some static if's instead of dynamic ones in areas where you reference constant booleans.

FirstOfGroup loop are way superior to group filters.

Inlining the any unit event bj is a waste of time and space. This could use SpellEffectEvent if you care about speed.

"RegisterJokes" should be singular, not plural, because you can only register one at a time.
 
Top