Spell Static Shield

The_Kingpin

Member (Who are you and why should I care?)
Reaction score
41
Static Shield - Follows JESP Standard

scrn.jpg

Surrounds a targeted friendly unit with balls of static electricity. If the target it attacked, a ball will fly off and damage the attacker.

Info:
- My second spell.
- In vJass, requires Jass NewGen Pack v4b or newer.
- MUI (Now)
- Leakless
- BJ-Free

Code:
JASS:
library StaticShield
//Configuration Section
//Edit the following varibles as needed.
globals
        //Spell Data
        
        //This is the raw code of the ability.
        private integer Ability = 'A000'
        
        //This is the raw code of the dummy.
        private integer Dummy = 'u001'
        
        //This is how long the effect will last before it dispels.
        private real Duration = 58
        
        //This is the attack type when damaging the target.
        private attacktype AttackType = ATTACK_TYPE_MAGIC
        
        //This is the damage type when damaging the target.
        private damagetype DamageType = DAMAGE_TYPE_LIGHTNING        
        
        //Other Data
        
        //This is how often the movement triggers.
        private real Interval = 0.03
        
        //This is how many degrees the balls will move in one second.
        private real Degrees = 180
        
        //This is the distance the balls will be from the unit.
        private real Offset = 100
        
        //This is how close the balls need to be to an attacker before the attacker is damaged.
        private real Radius = 60
        
        //This is how fast the balls will travel when moving toward a target.
        private real Speed = 800
    endglobals
    
    //Level Settings
    //
    //To add more levels, add another line like this:
    //set Level[<LEVEL>] = <AMOUNT>
    
    private function Balls takes integer lvl returns integer 
        local integer array Level
        set Level[lvl]=1 
        //Balls per level.
        
        set Level[1] = 1
        set Level[2] = 2
        set Level[3] = 3
        
        return Level[lvl]
    endfunction

    private function Damage takes integer lvl returns real
        local real array Level
        set Level[lvl] = 50
        
        //Damage per level (per ball).
        set Level[1] = 75
        set Level[2] = 80
        set Level[3] = 90
        
        return Level[lvl]
    endfunction

    //End of configuration settings.
    //DO NOT edit anything below this unless
    //you are absolutely sure of what you are doing!
    //
    //
    //
    //
    //
    
    globals
        private integer array Database1
        private integer array Database2
        private integer array Database3
        private integer array Database4
    endglobals
    
    private function H2I takes handle h returns integer
        return h
        return 0
    endfunction
    
    private function Store takes handle h, integer s returns nothing
        local integer id = H2I(h)-0x100000
        if id <= 8190 then
            set Database1[id]=s
        elseif id <= 16380 then
            set Database2[id-8190]=s
        elseif id <= 24570 then
            set Database3[id-16380]=s
        elseif id <= 32760 then
            set Database4[id-24570]=s
        else
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,20,"|cffff0000Static Shield storage limit reached at "+I2S(id)+".|r")
        endif  
    endfunction
    
    private function Recall takes handle h returns integer
        local integer id = H2I(h)-0x100000
        if id <= 8190 then
            return Database1[id]
        elseif id <= 16380 then
            return Database2[id-8190]
        elseif id <= 24570 then
            return Database3[id-16380]
        elseif id <= 32760 then
            return Database4[id-24570]
        endif  
        return 0
    endfunction

    private keyword Projectile
    private keyword Orbit
    private keyword Unit
    
    private struct Projectile
        unit Unit 
        unit Target
        real Damage
        trigger Trigger = CreateTrigger()
        timer Timer = CreateTimer()
        
        static method Movement takes nothing returns boolean
            local Projectile this = Projectile(Recall(GetTriggeringTrigger()))
            local real cx = GetUnitX(this.Unit)
            local real cy = GetUnitY(this.Unit)
            local real tx = GetUnitX(this.Target)
            local real ty = GetUnitY(this.Target)
            local real a = Atan2(ty-cy,tx-cx)
            call SetUnitX(this.Unit,cx+(Speed*Interval)*Cos(a))
            call SetUnitY(this.Unit,cy+(Speed*Interval)*Sin(a))
            if SquareRoot((tx-cx)*(tx-cx)+(ty-cy)*(ty-cy)) <= Radius then
                call UnitDamageTarget(this.Unit,this.Target,this.Damage,true,true,AttackType,DamageType,WEAPON_TYPE_WHOKNOWS)
                call KillUnit(this.Unit)
                call this.destroy()
            endif
            return false
        endmethod
        
        method onDestroy takes nothing returns nothing
            call PauseTimer(this.Timer)
            call DestroyTimer(this.Timer)
            call DestroyTrigger(this.Trigger)
        endmethod
        
        static method create takes unit u, unit t, real damage returns Projectile
            local Projectile this = Projectile.allocate()
            set this.Unit = u
            set this.Target = t
            set this.Damage = damage
            call TriggerRegisterTimerExpireEvent(this.Trigger,this.Timer)
            call TriggerAddCondition(this.Trigger,Condition(function Projectile.Movement))
            call Store(this.Trigger,this)
            call TimerStart(this.Timer,Interval,true,null)
            return this
        endmethod
    endstruct
            
    private struct Orbit
        unit Unit
        Unit Center
        real Degrees
        trigger Trigger = CreateTrigger()
        
        static method Movement takes nothing returns boolean
            local Orbit this = Orbit(Recall(GetTriggeringTrigger()))
            set this.Degrees = this.Degrees+Degrees*Interval
            call SetUnitX(this.Unit,GetUnitX(this.Center.Unit)+Offset*Cos(this.Degrees*(3.14159/180)))
            call SetUnitY(this.Unit,GetUnitY(this.Center.Unit)+Offset*Sin(this.Degrees*(3.14159/180)))
            return false
        endmethod
        
        method onDestroy takes nothing returns nothing
            call DestroyTrigger(this.Trigger)
        endmethod
        
        static method create takes Unit s, real Angle returns Orbit
            local Orbit this = Orbit.allocate()
            set this.Center = s
            set this.Unit = CreateUnit(GetOwningPlayer(this.Center.Unit),Dummy,GetUnitX(this.Center.Unit),GetUnitY(this.Center.Unit),0)
            call GroupAddUnit(this.Center.Balls,this.Unit)
            call Store(this.Unit,this)
            set this.Degrees = Angle
            call TriggerRegisterTimerExpireEvent(this.Trigger,this.Center.Timer)
            call TriggerAddCondition(this.Trigger,Condition(function Orbit.Movement))
            call Store(this.Trigger,this)
            return this
        endmethod
    endstruct
            
    private struct Unit
        unit Unit
        group Balls = CreateGroup()
        integer BallCount
        integer Level
        timer Timer = CreateTimer()
        trigger Trigger = CreateTrigger()
        trigger Exit = CreateTrigger()
        
        static method OnAttack takes nothing returns boolean
            local Unit this = Unit(Recall(GetTriggeringTrigger()))
            local unit u = FirstOfGroup(this.Balls)
            if IsUnitEnemy(this.Unit,GetOwningPlayer(GetAttacker())) then
                call GroupRemoveUnit(this.Balls,u)
                call Orbit(Recall(u)).destroy()
                call Projectile.create(u,GetAttacker(),Damage(this.Level))
                set this.BallCount = this.BallCount - 1
                if this.BallCount <= 0 then
                    call this.destroy()
                endif
            endif
            set u=null
            return false
        endmethod
            
        static method ExitF takes nothing returns boolean
            local Unit this = Unit(Recall(GetTriggeringTrigger()))
            call this.destroy()
            return false
        endmethod
            
        method onDestroy takes nothing returns nothing
            local unit f
            call Store(this.Unit,0)
            loop
                set f = FirstOfGroup(this.Balls)
                exitwhen f == null
                call Orbit(Recall(f)).destroy()
                call KillUnit(f)
                call GroupRemoveUnit(this.Balls,f)
            endloop
            call DestroyGroup(this.Balls)
            call PauseTimer(this.Timer)
            call DestroyTimer(this.Timer)
            call DestroyTrigger(this.Trigger)
            call DestroyTrigger(this.Exit)
        endmethod
            
        static method create takes unit u, integer l returns Unit
            local Unit this = Unit.allocate()
            local Orbit o
            local integer i = 0
            local integer a = 0
            local integer balls = Balls(l)
            set this.Unit=u
            set this.Level=l
            set this.BallCount = balls
            loop
                exitwhen i >= balls
                set o = Orbit.create(this,a)
                set a = a+360/balls
                set i=i+1
            endloop
            call TimerStart(this.Timer,Interval,true,null)
            call TriggerRegisterUnitEvent(this.Trigger,this.Unit,EVENT_UNIT_ATTACKED)
            call TriggerAddCondition(this.Trigger,Condition(function Unit.OnAttack))
            call Store(this.Trigger,this)
            call TriggerRegisterTimerEvent(this.Exit,Duration,false)
            call TriggerRegisterUnitEvent(this.Exit,this.Unit,EVENT_UNIT_DEATH)
            call TriggerAddCondition(this.Exit,Condition(function Unit.ExitF))
            call Store(this.Exit,this)
            return this
        endmethod
    endstruct
    

    function Trig_Static_Shield_Conditions takes nothing returns boolean
        return GetSpellAbilityId() == Ability
    endfunction

    function Trig_Static_Shield_Actions takes nothing returns nothing
        local unit u = GetSpellTargetUnit()
        local Unit U = Recall(u)
        if U != 0 then
            call U.destroy()
        endif
        set U = Unit.create(u,GetUnitAbilityLevel(GetTriggerUnit(),Ability))
        call Store(u,U)
        set u = null
    endfunction

    //===========================================================================
    function InitTrig_Static_Shield takes nothing returns nothing
        set gg_trg_Static_Shield = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_Static_Shield, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( gg_trg_Static_Shield, Condition( function Trig_Static_Shield_Conditions ) )
        call TriggerAddAction( gg_trg_Static_Shield, function Trig_Static_Shield_Actions )
    endfunction
endlibrary

Download: View attachment Spell-StaticShield.w3x

Credits to Tinki3 for the test map template.

Constructive criticism and comments are welcome.
 

RedRage

New Member
Reaction score
7
^_^ GJ


                 ,r=''""゙゙゙li,
      _,、r=====、、,,_ ,r!'   ...::;il!
     ,r!'゙゙´       `'ヾ;、, ..::::;r!'゙
    ,i{゙‐'_,,_         :l}..::;r!゙
.  ,r!'゙´ ´-ー‐‐==、;;;:....   :;l!:;r゙
 ,rジ          `~''=;;:;il!::'li
. ill゙  ....         .:;ll:::: ゙li
..il'   ' ' '‐‐===、;;;;;;;:.... .;;il!::  ,il!
..ll          `"゙''l{::: ,,;r'゙
..'l!       . . . . . . ::l}::;rll(,
 'i,  ' ' -=====‐ー《:::il::゙ヾ;、 |
  ゙i、            ::li:il::|  
  ゙li、      ..........,,ノ;i!:   
   `'=、:::::;;、:、===''ジ゙'= 
     `~''''===''"゙´   
 

The_Kingpin

Member (Who are you and why should I care?)
Reaction score
41
I'm not sure if it truly is leakless, so if you find anything, please let me know.
 
Reaction score
456
I don't see why you're using keywords... *edit*, now I can see..

JASS:
Database[H2I(h)-0x100000]

Does this use some kind of system?
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
um...Lightening shield anyone?

Never mind. This is way better.

Question: why are you using Handle Vars INSIDE structs?
 

The_Kingpin

Member (Who are you and why should I care?)
Reaction score
41
@Uberplayer:

Yes, it is an integer attachment system. It's an array that uses handles converted to integers as it's index. (All handles' integer values start at around hex 0x100000 and go up.) Much faster than gamecache. (And ABC...)

@Chovynz:

They're not exactly handle vars. I'm attaching the struct's ID to an object so I can perform actions on it later, like in static methods I cannot used instanced variables. Structs still have to use handle vars sometimes.
 

The_Kingpin

Member (Who are you and why should I care?)
Reaction score
41
Does anyone know how often moderators look through spell submissions?
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
Your map and code is missing stuff. Your missing a section of the library at the top.
The map crashes to wc3 main menu.
 

Cohadar

master of fugue
Reaction score
209
Yes, it is an integer attachment system. It's an array that uses handles converted to integers as it's index. (All handles' integer values start at around hex 0x100000 and go up.) Much faster than gamecache. (And ABC...)
Also unsafe. (what happens when indexes break array limit of 8192?)
It is just a noob version of Vexorian's CSData. (witch is safe)
much faster than ABC? I lol'ed.
 

The_Kingpin

Member (Who are you and why should I care?)
Reaction score
41
@Chovynz
Look at the top of the trigger. Scroll to the right. It's there. It doesn't crash to the desktop. (Unless you did something.)

@Cohadar
If you have more than 8192 unnulled handles in your map, your map has some serious problems. And about speed, check out the benchmark test results http://wc3campaigns.net/showthread.php?t=96879
 

Cohadar

master of fugue
Reaction score
209
You know that bullshit about 8192 not-nulled handles is something I heard million times by now.

More than half maps are made mostly in GUI, and even if GUI mappers clean leaks, they usually don't null handles.
And even if you are a jass-only mapper you cannot null all handles because 20% of blizzards functions have handle leaks.
Not to mention return leaks.

So sooner or later a map that uses systems that are based on 0x100000 will either crash or get slow.

And benchmark results that PandaMine posted are a bit rigged:
Code:
Attaching and Retrieving Structs through a single handle (timer)
HSAS ~ 93 Executions Per Millisecond
ABC ~ 56 Executions Per Millisecond
Gamecache ~ 52 Executions Per Millisecond
Where did you ever see a map that has only one timer?

Code:
Attaching and Retrieving Structs through a multiple handles stored in an array (timer)
HSAS ~ 83 Executions Per Millisecond
ABC ~ 61 Executions Per Millisecond
Gamecache ~ 56 Executions Per Millisecond
This results are almost OK.
There is only a small problem that this test was made in NewGen debug mode.
ABC is slower in debug mode because it has error/warning reporting,
a feature that no other system of this type has.

So in release mode ABC will be maybe 10 Executions Per Millisecond slower than 0x100000 based systems.
But after half an hour of playing a map 0x100000 systems will start to show problems while ABC will continue to work normally.

Oh gee did I forget to null some variable?
Oh yes I don't give a shit because I use ABC.

But hay I always say, speed is not everything.
Lets talk about type-safety.
What happens when you use one of those 0x100000 systems and get a brilliant idea to attach things to units?

ERROR - your code is not MUI any more.
Witch is worse if spell that uses unit attaching is cast on the same unit twice game will probably crash.

I guess now your map has some bigger problems than 8192 not-nulled handles.
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
@Chovynz
Look at the top of the trigger. Scroll to the right. It's there. It doesn't crash to the desktop. (Unless you did something.)

Now you're just being insulting.

I just downloaded it again and it works. The Spells good. I mustve done something Retarded.

Constructive criticism:
Please fix the spaces of all those blank lines and library on the FAR right. Those shouldn't be there and its not hard to fix. Tighten up the spaces between the top parts, private functions and the level settings. The bottom is nice and readable.
 

The_Kingpin

Member (Who are you and why should I care?)
Reaction score
41
@ cohadar
Okay, now you're just being a douche. I've tested it and it works when cast on a unit multiple times. And it is small, so I can put it directly in the trigger. The spell is responsible for itself, not the map it is used in. If someone's map is really leaky, that's the author's fault. Besides, that is what I chose to use. It's not your concern. End of discussion.

@ Chovynz (Apologies for all that.)
I moved those there so that the configuration is easier to understand and less confusing with all these other things around it. But perhaps I will do away with that.
 

phyrex1an

Staff Member and irregular helper
Reaction score
447
If someone's map is really leaky, that's the author's fault.
Despite how rude you think he was the concern is real, it doesn't take leaks to reach H2I - 0x100000 > 8192.

For example, on the DOTA Template this test:
JASS:
function H2I takes handle h returns integer
    return h
    return 0
endfunction

function DoTest takes nothing returns nothing
    local location l = Location(0,0)
    call BJDebugMsg(I2S(H2I(l)-0x100000))
    call RemoveLocation(l)
    set l = null
endfunction

Gives 5121 after 30 seconds (this is before any spawns and before anything at all happens in the game), and gives 5450 after 2 minutes (this is after two waves and me selecting one hero).
Most of the handles are the destructables, other things that add up are multiboard cells, units, triggers, blizzard.j stuff, ect.
 

phyrex1an

Staff Member and irregular helper
Reaction score
447
Twice, once after 30 seconds and once after 120 seconds. The DoTest is just stuff I added myself to the map and not really important. The point is that it's possible, and not even unlikely, that a leak free map can reach 8192 handles. Afaik, the maximum destructable limit is 10000 so you can reach the handle limit(*) with pre-placed destructables alone. 10000 is not that much on an epic RPG map :p

(*) In lack of a better word.
 

Cohadar

master of fugue
Reaction score
209
Like I said attaching to units is not MUI.

Casting lightning shield on same unit from 2 heroes.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • 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
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/
  • The Helper The Helper:
    Here is another comfort food favorite - Million Dollar Casserole - https://www.thehelper.net/threads/recipe-million-dollar-casserole.193614/

      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