Spell Ice Wall

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
JASS - Yes - vJASS Required
MUI - Yes
Works - Yes
Leaks - I find your lack of leaklessness disturbing.

Ice Wall

This spell summons a wall of ice behind the caster, blocking advancing enemy units.

IceWallScreenshot.jpg


Code:

JASS:
//**************************ICE WALL by GHAN_04***********************
//******************************DESCRIPTION*****************************
//**Creates a wall of ice behind the caster that blocks enemy advance.**
//**********************************************************************
//**********************************************************************


scope IceWall initializer Init
    
    globals
        private trigger t = CreateTrigger()
        private integer ICE_WALL_CODE = 'A000'               //The raw code of the Ice Wall ability.
        private integer ICE_WALL_SECTION_CODE = 'h000'       //The raw code of the Ice Wall unit.
        private integer ICE_WALL_DURATION = 15               //The duration of the ice wall.
        private integer ICE_WALL_DURATION_FACTOR = 5         //The amount that the duration increases each level.
        private real ICE_WALL_DISTANCE = 500                 //The initial distance back from the caster that the wall appears.
        private real ICE_WALL_DISTANCE_FACTOR = 25           //The amount that the distance decreases with each level.
        private real ICE_WALL_WIDTH = 600                    //The distance sideways that the wall will expand.
        private real ICE_WALL_WIDTH_FACTOR = 25              //The amount that the width increases with each level.
        private real ICE_WALL_SIZE = 80                      //This is the distance between each wall section. CHANGE WITH CAUTION
        private real PLAYABLE_MAX_X
        private real PLAYABLE_MIN_X
        private real PLAYABLE_MAX_Y
        private real PLAYABLE_MIN_Y
    endglobals

    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == ICE_WALL_CODE
    endfunction
    
    private function checkPoint takes real X1, real Y1, real X2, real Y2 returns boolean
        local real height1 = GetLocationZ(Location(X1, Y1))
        local real height2 = GetLocationZ(Location(X2, Y2))
        local real offset = height1 - height2
        if (offset < 0) then
            set offset = -offset
        endif
        return (PLAYABLE_MIN_X <= X2) and (X2 <= PLAYABLE_MAX_X) and (PLAYABLE_MIN_Y <= Y2) and (Y2 <= PLAYABLE_MAX_Y) and offset < 10
    endfunction
    
    private function Actions takes nothing returns nothing
        local unit caster = GetTriggerUnit()
        local real abilitylevel = GetUnitAbilityLevel(caster, ICE_WALL_CODE)
        local real X = GetUnitX(caster)
        local real Y = GetUnitY(caster)
        local real facing = GetUnitFacing(caster)
        local real left = facing - 90
        local real right = facing + 90
        local real wallstartX = X + (ICE_WALL_DISTANCE - ICE_WALL_DISTANCE_FACTOR * GetUnitAbilityLevel(caster, ICE_WALL_CODE)) * Cos((facing + 180) * bj_DEGTORAD)
        local real wallstartY = Y + (ICE_WALL_DISTANCE - ICE_WALL_DISTANCE_FACTOR * abilitylevel) * Sin((facing + 180) * bj_DEGTORAD)
        local unit start = CreateUnit(Player(15), ICE_WALL_SECTION_CODE, wallstartX, wallstartY, 0.00)
        local real count = 0
        local real currentwallX
        local real currentwallY
        local real oldX = wallstartX
        local real oldY = wallstartY
        call UnitApplyTimedLife(start, 'BTLF', ICE_WALL_DURATION + ICE_WALL_DURATION_FACTOR * abilitylevel)
        loop
            exitwhen count >= (ICE_WALL_WIDTH + ICE_WALL_WIDTH_FACTOR * abilitylevel)/2
            set count = count + ICE_WALL_SIZE
            if(not checkPoint(oldX, oldY, wallstartX + count * Cos((left) * bj_DEGTORAD), wallstartY + count * Sin((left) * bj_DEGTORAD))) then
                exitwhen true
            endif
            set currentwallX = wallstartX + count * Cos(left * bj_DEGTORAD)
            set currentwallY = wallstartY + count * Sin(left * bj_DEGTORAD)
            set oldX = currentwallX
            set oldY = currentwallY
            call UnitApplyTimedLife(CreateUnit(Player(15), ICE_WALL_SECTION_CODE, currentwallX, currentwallY, 0.00), 'BTLF', ICE_WALL_DURATION + ICE_WALL_DURATION_FACTOR * abilitylevel)
        endloop
        set count = 0
        loop
            exitwhen count >= (ICE_WALL_WIDTH + ICE_WALL_WIDTH_FACTOR * abilitylevel)/2
            set count = count + ICE_WALL_SIZE
            if(not checkPoint(oldX, oldY, wallstartX + count * Cos(right * bj_DEGTORAD), wallstartY + count * Sin((right) * bj_DEGTORAD))) then
                exitwhen true
            endif
            set currentwallX = wallstartX + count * Cos(right * bj_DEGTORAD)
            set currentwallY = wallstartY + count * Sin(right * bj_DEGTORAD)
            set oldX = currentwallX
            set oldY = currentwallY
            call UnitApplyTimedLife(CreateUnit(Player(15), ICE_WALL_SECTION_CODE, currentwallX, currentwallY, 0.00), 'BTLF', ICE_WALL_DURATION + ICE_WALL_DURATION_FACTOR * abilitylevel)
        endloop
        set caster = null
        set start = null
    endfunction
    
    private function Init takes nothing returns nothing
        local integer index = 0
        set PLAYABLE_MAX_X = GetRectMaxX(bj_mapInitialPlayableArea)
        set PLAYABLE_MIN_X = GetRectMinX(bj_mapInitialPlayableArea)
        set PLAYABLE_MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea)
        set PLAYABLE_MIN_Y = GetRectMinY(bj_mapInitialPlayableArea)
        loop
            call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)

            set index = index + 1
            exitwhen index == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddCondition(t, Condition(function Conditions))
        call TriggerAddAction(t, function Actions)
    endfunction
endscope


I created this spell on a request, so now I'm submitting it for review.
Enjoy!
 

Attachments

  • Ice Wall.w3x
    20.2 KB · Views: 263

Romek

Super Moderator
Reaction score
964
Why does this require UMSWE?

> set offset = -1 * offset
set offset = -offset

The map Max/Min[X/Y] could be stored into globals

There's no point in inlining TriggerRegisterAnyUnitEventBJ, especially if you're not going to change it in any way.

I'll look through it in more detail later. The spell seems useful though. I had someone asking me about a spell like this just a few minutes ago. So I'm sure a lot of people will be happy to see this. :)
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
Thanks for the suggestions. I updated those things.
 

Kenny

Back for now.
Reaction score
202
JASS:
private real ICE_WALL_WIDTH_FACTOR = 25              //The amount that the width decreases with each level.


Why does the wall width decrease per level, or am I not understanding correctly.

JASS:
private real PLAYABLE_MAX_X = GetRectMaxX(bj_mapInitialPlayableArea)
private real PLAYABLE_MIN_X = GetRectMinX(bj_mapInitialPlayableArea)
private real PLAYABLE_MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea)
private real PLAYABLE_MIN_Y = GetRectMinY(bj_mapInitialPlayableArea)


I'm not sure if GetRectMaxX and all that can be initialized in the globals block. At least last time I checked it didn't work. You should initialize them in the Init function.

It is also more accurate to +/- 64 to the max and min values, so:

JASS:
// Done in the Init function.
set PLAYABLE_MAX_X = GetRectMaxX(bj_mapInitialPlayableArea) - 64.00
set PLAYABLE_MIN_X = GetRectMinX(bj_mapInitialPlayableArea) + 64.00
set PLAYABLE_MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea) - 64.00
set PLAYABLE_MIN_Y = GetRectMinY(bj_mapInitialPlayableArea) + 64.00


You should probably add GetTriggerUnit() to a local variable, as you are using it like 10 times in the function, so that can be cleaned up. You will need to null it too.

You also don't null start (the unit variable).

You could also probably set GetUnitAbilityLevel(GetTriggerUnit(),ICE_WALL_CODE) to a variable, as you use it a fair bit.

And although it doesn't matter, you dont need the parenthesis around (left) and (right).

You could also make this use GTrigger by Jesus4Lyf. It would shorten the script quite a bit.

And maybe add some function for distance, width and duration to make it a bit easier to read and understand.

JASS:
private function Duration takes integer level returns real
    return 15.00 + (5.00 * level) // something like that.
endfunction


This is a pretty mad spell, and it will definately come in handy for a lot of people. Well done.
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
> Why does the wall width decrease per level, or am I not understanding correctly.

That should be increases. Fixed.

> You should initialize them in the Init function.

Done.

> It is also more accurate to +/- 64 to the max and min values

Why? Are there known errors that can occur to make stuff happen outside the playable map area with that restriction?

> GetTriggerUnit() to a local variable

Done.

> You also don't null start (the unit variable).

Thanks for that catch. Fixed.

> You could also probably set GetUnitAbilityLevel(GetTriggerUnit(),ICE_WALL_CODE) to a variable

Done.

> you dont need the parenthesis around (left) and (right).

In development, I had some extra stuff there; I just didn't take them out. Thanks.

> You could also make this use GTrigger by Jesus4Lyf. It would shorten the script quite a bit.

I'm not really even sure what that system does - it seems like an incredible amount of code to add here. o_O

> And maybe add some function for distance, width and duration to make it a bit easier to read and understand.

Considering that most of the customizable stuff is done in the globals, wouldn't that just add unneeded function calls?
 

Kenny

Back for now.
Reaction score
202
> Why? Are there known errors that can occur to make stuff happen outside the playable map area with that restriction?

I've just heard that it can be inaccurate, and that adding the +/- 64.00 ensures that no errors may occur, so I've just used it since then.

> I'm not really even sure what that system does - it seems like an incredible amount of code to add here. o_O

It makes it much easier to register events for single event spells, and all spells in general. It turns:

JASS:
private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == ICE_WALL_CODE
endfunction

private function Init takes nothing returns nothing
    local integer index
    set PLAYABLE_MAX_X = GetRectMaxX(bj_mapInitialPlayableArea)
    set PLAYABLE_MIN_X = GetRectMinX(bj_mapInitialPlayableArea)
    set PLAYABLE_MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea)
    set PLAYABLE_MIN_Y = GetRectMinY(bj_mapInitialPlayableArea)
    set index = 0
    loop
        call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)

        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddCondition(t, Condition(function Conditions))
    call TriggerAddAction(t, function Actions)
endfunction


Into:

JASS:
private function Init takes nothing returns nothing
    set PLAYABLE_MAX_X = GetRectMaxX(bj_mapInitialPlayableArea)
    set PLAYABLE_MIN_X = GetRectMinX(bj_mapInitialPlayableArea)
    set PLAYABLE_MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea)
    set PLAYABLE_MIN_Y = GetRectMinY(bj_mapInitialPlayableArea)

    call GT_AddStartsEffectEvent(function Actions,ICE_WALL_CODE)
endfunction

//  However, your actions function will need to return boolean,
//  so just add return false to the end, and make sure it returns boolean.


However it is not needed, I just think the system makes things much easier to read, and makes coding easier as well.

> Considering that most of the customizable stuff is done in the globals, wouldn't that just add unneeded function calls?

There is no reason at all to change it. I guess its just personal preference, I'd rather look at the function and be able to do whatever i want with it rather than changing the two globals and stuff getting done for me.

Keep it as is if you want, its perfectly fine.

Also if you arent going to use GTrigger, you should just initialize index (in the Init function) in the local block up the top. Theres no reason to initialize it afterwards. Oh and if you use GTrigger you can get rid of the private trigger t in the globals block.

And again, this isn't needed, but you should make the globals that are actually constant have the constant keyword prefix. Its currently a little deceiving :p.

EDIT:

You should make the local variable for the ability level an integer instead of a real.
 

Romek

Super Moderator
Reaction score
964
> Oh and if you use GTrigger you can get rid of the private trigger t in the globals block.
You can get rid of it anyway, without GTrigger.
Just make it a local. :)

GTrigger only shortens code by about 2 lines anyway. It seems more here because Ghan inlined TriggerRegisterAnyUnitEventBJ.
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
Updated.
I don't really want to introduce a bunch more code here where it really isn't needed. :/ I have a feeling it would confuse me and the user downloading the spell.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Monovertex Monovertex:
    How are you all? :D
    +1
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.

      The Helper Discord

      Staff online

      • tom_mai78101
        The Helper Connoisseur / Ex-MineCraft Host
      • Ghan
        Administrator - Servers are fun

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top