Spell Nature Wall

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
Nature Wall
nwkw9.jpg


A spell from my map - Mini Ashenvale Arena.

GUI/JASS/vJASS? vJASS.
MUI? Yes.
Leakless? Yes.
Lagless? Yes.
Follows JESP? No.
Requires?
- JASS NewGen Editor v1.5a
- ABCT v2.0
- PUI v5.1

Description:
Creates a wall of vines, branches and leaves across the landcape, creating a strong barrier. Units that pass through the wall will be caught in roots for one second. Released units have 1.5 seconds to get away from the wall or they are caught again. Lasts 15 seconds.
Level 1 - Deals 35 DPS.
Level 2 - Deals 55 DPS.
Level 3 - Deals 80 DPS.

Code:
JASS:
scope NatureWall
// Do not touch this textmacro line! It's PUI attaching!
//! runtextmacro PUI_PROPERTY("private", "boolean", "AGAIN", "false") 

//===========================================================================
//  CONFIGURATION MENU
//===========================================================================
globals
// Raw code of the Nature Wall ability.
    private constant integer AID_NATURE_WALL = 'A000'
// Raw code of the buff that comes with the aura.
    private constant integer BID_NATURE_WALL_AURA = 'B000'
// Raw code of the wall units.
    private constant integer UID_NATURE_WALL_UNIT = 'u000'
// Raw code of the dummy unit.
    private constant integer UID_DUMMY = 'u001'
// Raw code of the ability that is casted when a unit comes near the wall.
    private constant integer AID_NATURE_WALL_ENTANGLE = 'A002'
// String for casting the AID_NATURE_WALL_ENTANGLE ability.
    private constant string SID_ENTANGLE = "entanglingroots"
// Raw code of the destructibles created on the two sides of the wall (in this case - Ashenvale tree).
    private constant integer DID_NATURE_WALL_WOOD = 'ATtr'
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// Period that is given for the unit to get away from the wall, or it will be entangled again.
    private constant real ENTANGLE_PERIOD = 1.5 
// Period between group picks and special effect creation.
    private constant real PICK_PERIOD = 1.
// Special effect created at each wall unit.
    private constant string SFX_EFFECT = "Objects\\Spawnmodels\\NightElf\\EntBirthTarget\\EntBirthTarget.mdl"
// Scale of the two destructibles created at the wall's sides.
    private constant real TREE_SCALE  = 1.
// Range between wall units (used for creation). 
    private constant integer RANGE = 75
endglobals
// Duration of the wall
    private function DURATION takes unit cast, integer lvl returns real
        // Included the caster because someone might want to base
        // duration on his attributes
        return lvl * 10.
    endfunction
// Number of wall units.
// More units means increased wall length.
    private function N_UNITS takes unit cast, integer lvl returns integer
        // Included the caster because someone might want to base
        // number of units on his attributes.
        return 4 + (lvl * 2)
    endfunction
//===========================================================================
//  END OF CONFIGURATION MENU
//=========================================================================== 

private struct Data
    unit caster
    integer level
    unit array wall[100]
    destructable array wood[3]
    integer ticks
    
    method onDestroy takes nothing returns nothing
        call KillDestructable(.wood[1])
        call KillDestructable(.wood[2])
    endmethod
endstruct

private struct Info
    unit picked
endstruct

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == AID_NATURE_WALL
endfunction

private function Filterz takes nothing returns boolean
    return GetUnitAbilityLevel(GetFilterUnit(), BID_NATURE_WALL_AURA) > 0
endfunction

private function Wait takes nothing returns boolean
    local Info data = ABCT_GetData()
    set AGAIN[data.picked] = false
    call data.destroy()
    return true
endfunction

private function Root takes unit whichUnit, unit whichTarg returns nothing
    local unit dum = CreateUnit(GetOwningPlayer(whichUnit), UID_DUMMY, 0., 0., 0.)
    local Info data = Info.create()
    call UnitApplyTimedLife(dum, 'BTLF', 2.)
    call UnitAddAbility(dum, AID_NATURE_WALL_ENTANGLE)
    call SetUnitAbilityLevel(dum, AID_NATURE_WALL_ENTANGLE, GetUnitAbilityLevel(whichUnit, AID_NATURE_WALL))
    call IssueTargetOrder(dum, SID_ENTANGLE, whichTarg)
    call UnitRemoveAbility(whichTarg, BID_NATURE_WALL_AURA) // prevent aura bugs
    set AGAIN[whichTarg] = true
    set data.picked = whichTarg
    call ABCT_Start(function Wait, data, ENTANGLE_PERIOD)
    set dum = null
endfunction

private function Callback takes nothing returns boolean
    local Data d = ABCT_GetData()
    local group gru = CreateGroup()
    local unit pick
    local integer int
    local real x
    local real y
    call GroupEnumUnitsInRange(gru, 0., 0., 999999., Condition(function Filterz))
    loop    
        set pick = FirstOfGroup(gru)
        exitwhen pick == null
        if AGAIN[pick] == false then
            call Root.execute(d.caster, pick)
        endif
        call GroupRemoveUnit(gru, pick)
    endloop
    call DestroyGroup(gru)
    set int = 1
    loop    
        exitwhen int > N_UNITS(d.caster, d.level)
        set x = GetUnitX(d.wall[int])
        set y = GetUnitY(d.wall[int])
        call DestroyEffect(AddSpecialEffect(SFX_EFFECT, x, y))
        set int = int + 1
    endloop
    set d.ticks = d.ticks - 1
    set gru = null
    set pick = null
    if d.ticks <= 0 then
        call d.destroy()
        return true
    endif
    return false
endfunction
        
private function Actions takes nothing returns nothing
    local unit cast = GetTriggerUnit() 
    local location spell = GetSpellTargetLoc()
    local integer lvl = GetUnitAbilityLevel(cast, AID_NATURE_WALL)
    local Data d = Data.create()
    local integer int = 1
    local real x = GetUnitX(cast)
    local real y = GetUnitY(cast)
    local real tx = GetLocationX(spell)
    local real ty = GetLocationY(spell)
    local real angle = Atan2(ty - y, tx - x)
    local real dd = (N_UNITS(cast, lvl) +1) * RANGE
    set x = Cos(angle + bj_PI / 2) * dd
    set y = Sin(angle + bj_PI / 2) * dd
    set tx = tx + x / 2
    set ty = ty + y / 2
    set x = x / (N_UNITS(cast, lvl) + 1)
    set y = y / (N_UNITS(cast, lvl) + 1)
    set d.caster = cast
    set d.ticks = R2I(DURATION(cast, lvl) / PICK_PERIOD)
    set d.wood[1] = CreateDestructable(DID_NATURE_WALL_WOOD, tx, ty, 270., TREE_SCALE, GetRandomInt(0, 2))
    loop
        exitwhen int > N_UNITS(cast, lvl)
        set tx = tx - x
        set ty = ty - y
        set d.wall[int] = CreateUnit(GetOwningPlayer(d.caster), UID_NATURE_WALL_UNIT, tx, ty, 270.)
        call UnitApplyTimedLife(d.wall[int], 'BTLF', DURATION(cast, lvl))
        set int = int + 1
    endloop
    set tx = tx - x
    set ty = ty - y
    set d.wood[2] = CreateDestructable(DID_NATURE_WALL_WOOD, tx, ty, 270., TREE_SCALE, GetRandomInt(0, 2))
    set d.level = lvl
    call ABCT_Start(function Callback, d, PICK_PERIOD)
    call RemoveLocation(spell)
    set cast = null
    set spell = null
endfunction

//===========================================================================
function InitTrig_NatureWall takes nothing returns nothing
    local trigger trig = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(trig, Condition(function Conditions))
    call TriggerAddAction(trig, function Actions)
endfunction

endscope

Screenshots:
naturewalldb2.jpg


Also credits to Tinki3 for the map template.

Changelog:
JASS:
// - - - - - - - - - - - - - - - - - - - - - v1.0 - - - - - - - - - - - - - - - - - - - - - - -
- Release
// - - - - - - - - - - - - - - - - - - - - - v2.0 - - - - - - - - - - - - - - - - - - - - - - -
- Fixed a little location leak
- Fixed a bug that made the unit created on the target point of ability being cast
   to be always counted as array 7 ( d.wall[7] ), thus bugging the loop in Callback() action.
- Added a better implementation instruction.
// - - - - - - - - - - - - - - - - - - - - - v3.0 - - - - - - - - - - - - - - - - - - - - - - -
- Removed a few unnecessary lines
- Variables are now properly nulled
// - - - - - - - - - - - - - - - - - - - - - v4.0 - - - - - - - - - - - - - - - - - - - - - - -
- Removed a location or two and moved some stuff to reals
- Period between entangles no longer uses TriggerSleepAction() so you can be
  sure that it will wait an exact amount of time. 
- Ticks are now properly calculated (had a bug with more frequent group checks)
// - - - - - - - - - - - - - - - - - - - - - v4.1 - - - - - - - - - - - - - - - - - - - - - - -
- Edited a little the math on creating the wall.
- Now uses latest PUI - v5.1.
- Edited a little the Configuration Menu. Now it's more understandable (I think).
 

Attachments

  • [Spell]Nature Wall v4[1].1.w3x
    56.3 KB · Views: 565

Joker(Div)

Always Here..
Reaction score
86
I'll take a look, gonna edit with comments.

Edit: It seems like a pretty stable spell. Kinda heavy on animations don't ya think? I think the treant birth is fine itself, but thats my opinion. I don't have the time to go through your trigger, but after briefing scanning it, it seems fine.

Awesome job!
 

Tinki3

Special Member
Reaction score
418
I like this spell, good job.

Though, you should increase the level of the spell tester hero.
I had to spam "Esc" to heal myself continuously.

There was no "Read Me" included in the test map.
You'll need one for approval (a decent one :p).

The "loc" variable in the function "Actions" is not removed in the 2nd loop.

Apart from those few things, all else seems to be fine at this stage;
you seem to have used ABCT correctly, and PUI as well.

Nice overall.
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
> There was no "Read Me" included in the test map.
Well, there's one at the end of the trigger. But if it's not extended enough then I'll add a new one ^^

> The "loc" variable in the function "Actions" is not removed in the 2nd loop.

Will fix.

> Kinda heavy on animations don't ya think?
No. :)

> you should increase the level of the spell tester hero.

Will fix that one too.

> Nice overall.
> Awesome job!

Thanks :)

EDIT:
New version. Fixed the location leak and also saw a minor bug with the array stored wall units
( the unit created on the target spell of ability being cast was always counted as array 7 d.wall[7] and that
could bug the loop in Callback() function).
 

Cohadar

master of fugue
Reaction score
209
LoL the code looks like I wrote it :eek:

Very good. Very good indeed.

This spell would be great in some altered melee.
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
> LoL the code looks like I wrote it :eek:

Omg, thanks. :D


Just a few questions, quys:

Is this needed?
JASS:

   if whichTarg == null then
        return
    endif


And should the nulling part be replaced?
JASS:

    if d.ticks <= 0 then
        call d.destroy()
        return true
    endif
    set gru = null
    set pick = null
    return false
endfunction

//===========
Becomes:

    set gru = null
    set pick = null
    if d.ticks <= 0 then
        call d.destroy()
        return true
    endif
    return false

So this can null all the variables... Or does it already null them?
 

Cohadar

master of fugue
Reaction score
209
JASS:
    
if whichTarg == null then
    return
endif

This is not needed since you call it on units from group.


This is correct.
JASS:

    set gru = null
    set pick = null
    if d.ticks <= 0 then
        call d.destroy()
        return true
    endif
    return false


You should null variables before any and all return statements or it will leak.
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
> You should null variables before any and all return statements or it will leak.
Thanks. I made that. Removed that if statement too.
This should be the last update.
 

Joker(Div)

Always Here..
Reaction score
86
JASS:

This is correct.
<div class="bbCodeBlock bbCodeBlock--screenLimited bbCodeBlock--code"><div class="bbCodeBlock-title">JASS:</div><div class="bbCodeBlock-content"><pre class="bbCodeCode"><code class="jass">
    <span class="keyword">set</span> <span>gru</span> <span class="symbol">=</span> <span class="value">null</span>
    <span class="keyword">set</span> <span>pick</span> <span class="symbol">=</span> <span class="value">null</span>
    <span class="keyword">if</span> <span>d</span>.<span>ticks</span> &<span>lt</span>;<span class="symbol">=</span> <span class="number">0</span> <span class="keyword">then</span>
        <span class="keyword">call</span> <span>d</span>.<span>destroy</span><span class="symbol">(</span><span class="symbol">)</span>
        <span class="keyword">return</span> <span class="value">true</span>
    <span class="keyword">endif</span>
    <span class="keyword">return</span> <span class="value">false</span></code></pre></div></div>

You should null variables before any and all return statements or it will leak.
JASS:

Woah, you have to destroy the struct in ABCT? I thought it did it itself when returned true. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite3" alt=":(" title="Frown    :(" loading="lazy" data-shortname=":(" />
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
> Woah, you have to destroy the struct in ABCT? I thought it did it itself when returned true.
Structs must be destroyed every time or you can quickly reach the 8191 limit.
When you return true the timer just stops ticking. It does nothing to the attached struct.
So you have to destroy it manually or it will leak :)

> Approved.
Thanks ^^
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
Just saw a small issue in the code while I was checking all my triggers in my map.

JASS:
    set d.ticks = R2I(DURATION)

This is supposed to be
JASS:
    set d.ticks = R2I(DURATION / PERIOD)


I don't have time now to fix it but it'll be done tomorrow.
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
Well, probably this wasn't tomorrow ... xD

Anyway, another update. Fixed the ticks that would screw the whole group pick. Wait between entangles no longer uses TriggerSleepAction() and now it works properly for period < 0.3 seconds. Also removed a few locations and moved to reals. Well, that's it. I hope this is the last update... :)
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
Short update.

JASS:

// - - - - - - - - - - - - - - - - - - - - - v4.1 - - - - - - - - - - - - - - - - - - - - - - -
- Edited a little the math on creating the wall.
- Now uses latest PUI - v5.1.
- Edited a little the Configuration Menu. Now it&#039;s more understandable (I think).


Have fun mapping guys.
 

hoihoi8

New Member
Reaction score
0
Great spell, but the comments for the unit/spell abilities are horrid. Why don't you just put the exact name of the unit/spell there instead of a vague description? Made importing it a guessing game.

Edit: finally got it working. Works perfectly. Look for it in hoihoi8's Amazing Race :)
 
General chit-chat
Help Users
  • The Helper The Helper:
    Actually I was just playing with having some kind of mention of the food forum and recipes on the main page to test and see if it would engage some of those people to post something. It is just weird to get so much traffic and no engagement
  • The Helper The Helper:
    So what it really is me trying to implement some kind of better site navigation not change the whole theme of the site
  • Varine Varine:
    How can you tell the difference between real traffic and indexing or AI generation bots?
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top