Spell Senbonzakura

Status
Not open for further replies.

NetherHawk

New Member
Reaction score
26
Kuchiki Byakuya

Model credits go to : da1nonlyed

Spell Details: MUI
Uses: Jass
Requires: Jass New Gen Pack or JassHelper
How to install: Copy the triggers; Senbonzakura, Extras and ABC into your map. Copy the dummy unit and the ability and you are done.

Still a beta project. As i get more models that resemble byakuya's abilities i will continue to create more.

JASS:
scope Senbonzakura initializer Init

// Configuration Data
globals
    private unit byakuya
    private constant integer SabilID = 'A000' // The ability id of the Senbonzakura  
    private constant integer SpetalID = 'h000' // The unit id of the Petals
    private constant real Sdist = 800. // Distance of the spell
    private constant real Sspeed = 12. // Speed of the petals
    private constant real Sdmg = 4. // Base Damage a petal does ( Total damage = Sdmg + Sdmgx )
    private constant real Sdmgx = 1. // Increment of damage per level
    private constant string Sfx = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl" // Blood effect
    private constant sound Ssd = gg_snd_Shikai // Shikai sound
endglobals

private struct petal
    unit u
    real a
    real ds
    unit array d[5]
    real array ufh[5]
    real array ax[5]
    boolean array b[5]
    boolean array bx[5]
    integer ix
    group g           
    
    method onDestroy takes nothing returns nothing
        local integer i = 1
        
        loop
            exitwhen i > .ix
            call KillUnit(.d<i>)
            set .d<i> = null
            set i = i + 1
        endloop
                
        call DestroyGroup(.g)
        set .u = null        
        set .g = null
    endmethod
endstruct

private function Senbonzakura_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == SabilID 
endfunction

private function Senbonzakura_Filter takes nothing returns boolean    
    local unit f = GetFilterUnit()
    if IsUnitEnemy(f,GetOwningPlayer(byakuya)) == true and IsUnitType(f,UNIT_TYPE_MAGIC_IMMUNE) == false and IsUnitType(f,UNIT_TYPE_STRUCTURE) == false and GetUnitState(f,UNIT_STATE_LIFE) &gt; 0.5 then
        call UnitDamageTarget(byakuya,f,Sdmg+(I2R(GetUnitAbilityLevel(byakuya,SabilID))*Sdmgx),true,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
        call DestroyEffect(AddSpecialEffectTarget(Sfx,f,AttachBlood(GetRandomInt(0,11))))
    endif
    set f = null
    return false
endfunction   

private function Senbonzakura_Scatter takes nothing returns nothing    
    local timer t = GetExpiredTimer()
    local petal data = GetTimeStructA(t)    
    local real x 
    local real y     
    local integer i = 1
    
    if data.ds &gt; 0  then
    set data.ds = data.ds - Sspeed
    
    loop
        exitwhen i &gt; data.ix      
    
        set x = GetUnitX(data.d<i>) + Sspeed*Cos(data.a+data.ax<i>)
        set y = GetUnitY(data.d<i>) + Sspeed*Sin(data.a+data.ax<i>)
        call SetUnitPosition(data.d<i>,x,y)
        call SetUnitFlyHeight(data.d<i>,data.ufh<i>,0.)                   
        call GroupEnumUnitsInRange(data.g,GetUnitX(data.d<i>),GetUnitY(data.d<i>),120.,Condition(function Senbonzakura_Filter))    
        
        if data.b<i> == true then         
            set data.ax<i> = data.ax<i> - (6*bj_DEGTORAD)
        else
            set data.ax<i> = data.ax<i> + (6*bj_DEGTORAD)
        endif
    
        if data.bx<i> == true then         
            set data.ufh<i> = data.ufh<i> + 10
        else
            set data.ufh<i> = data.ufh<i> - 10
        endif
        
        if data.ax<i> == -60*bj_DEGTORAD then
            set data.b<i> = false
        elseif data.ax<i> == 60*bj_DEGTORAD then
            set data.b<i> = true
        endif
    
        if data.ufh<i> == 200 then
            set data.bx<i> = false
        elseif data.ufh<i> == 100 then
            set data.bx<i> = true
        endif    
    
    set i = i + 1
    
    endloop
    
    else
        call PauseTimer(t)
        call data.destroy()
        call ClearTimeStructA(t)
        call DestroyTimer(t)        
    endif
    
    call SetTimeStructA(t,data)    
    
    //call DestroyEffect(AddSpecialEffect(&quot;SenbonzakuraPart.mdx&quot;,GetUnitX(d),GetUnitY(d)))
        
    set t = null    
endfunction

private function Senbonzakura_Actions takes nothing returns nothing
    local petal data = petal.create()     
    local unit array dx
    local integer i    
    local real x = GetSpellTargetX()
    local real y = GetSpellTargetY()    
    local timer t = CreateTimer()
    local sound sd = Ssd
    
    set data.u = GetTriggerUnit()
    set data.ds = Sdist
    set data.g = CreateGroup()     
    set data.a = Atan2(y-GetUnitY(data.u),x-GetUnitX(data.u))  
    set data.ix = 4

    set byakuya = data.u  
    call StartSound(sd)
    
    set i = 1   
    loop 
        exitwhen i &gt; data.ix          
        set dx<i> = CreateUnit(GetOwningPlayer(data.u),SpetalID,GetUnitX(data.u),GetUnitY(data.u),data.a)
        call UnitAddAbility(dx<i>,&#039;Amrf&#039;)
        call UnitAddAbility(dx<i>,&#039;Aloc&#039;)
        call UnitRemoveAbility(dx<i>,&#039;Amrf&#039;)
        call SetUnitInvulnerable(dx<i>,true)
        set i = i + 1
    endloop
    
    set i = 1
    set x = GetUnitX(data.u) + 50*Cos(data.a)
    set y = GetUnitY(data.u) + 50*Sin(data.a)
    call SetUnitPosition(dx<i>,x,y)
    call SetUnitFlyHeight(dx<i>,150.,0.)    
    
    set i = 2
    
    set x = GetUnitX(data.u) + 50*Cos((data.a+(60*bj_DEGTORAD)))
    set y = GetUnitY(data.u) + 50*Sin((data.a+(60*bj_DEGTORAD)))
    call SetUnitPosition(dx<i>,x,y)
    call SetUnitFlyHeight(dx<i>,100.,0.)
    
    set i = 3
    
    set x = GetUnitX(data.u) + 50*Cos((data.a-(60*bj_DEGTORAD)))
    set y = GetUnitY(data.u) + 50*Sin((data.a-(60*bj_DEGTORAD)))
    call SetUnitPosition(dx<i>,x,y)
    call SetUnitFlyHeight(dx<i>,100.,0.)
    
    set i = 4
    
    set x = GetUnitX(data.u) + 50*Cos(data.a)
    set y = GetUnitY(data.u) + 50*Sin(data.a)
    call SetUnitPosition(dx<i>,x,y)
    call SetUnitFlyHeight(dx<i>,50.,0.)
    
    set i = 1
    
    loop
        exitwhen i &gt; data.ix
        set data.d<i> = dx<i>
        set data.b<i> = true
        set dx<i> = null
        set i = i + 1
    endloop
    
    set data.ufh[1] = 150.
    set data.ax[1] = 60.*bj_DEGTORAD     
    set data.bx[1] = true
    set data.ufh[2] = 100.
    set data.ax[2] = 0.*bj_DEGTORAD     
    set data.bx[2] = true
    set data.ufh[3] = 100.
    set data.ax[3] = 0.*bj_DEGTORAD     
    set data.bx[3] = false
    set data.ufh[4] = 50.
    set data.ax[4] = 60.*bj_DEGTORAD     
    set data.bx[4] = true
    
    call SetTimeStructA(t,data)
    call TimerStart(t,.03,true,function Senbonzakura_Scatter)    
   
    set t = null       
    set sd = null
endfunction

private function Init takes nothing returns nothing
    local trigger tr = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(tr,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(tr, Condition(function Senbonzakura_Conditions))
    call TriggerAddAction(tr,function Senbonzakura_Actions)
endfunction

endscope


</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>


Attachment System : ABCv6.1 by Cohadar

========
Changelog
========
-changed attachment system to ABC v6.1, added grouputils to recycle groups
-configuration is now available, kindly give ideas on what parts of the spell you would like to edit.
-added some implementation notes in the trigger editor, please let me know if im being clear enough and how best to make it more user-friendly
 

Attachments

  • Kuchiki ByakuyaX.w3x
    368.7 KB · Views: 474

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
+graveyard vote. It does not efficient.

JASS:
    call SetHandleUnit(t1,&quot;caster&quot;,u)
    call SetHandleUnit(t1,&quot;petal&quot;,d[1])
    call SetHandleReal(t1,&quot;angle&quot;,a)
    call SetHandleReal(t1,&quot;distance&quot;,ds)
    call SetHandleReal(t1,&quot;unitflyheight&quot;,150.)
    call SetHandleReal(t1,&quot;anglex&quot;,60)
    call SetHandleBoolean(t1,&quot;b&quot;,b)
    call SetHandleBoolean(t1,&quot;bx&quot;,bx)    
    call SetHandleGroup(t1,&quot;groupdamaged&quot;,g)
    
    call SetHandleUnit(t2,&quot;caster&quot;,u)
    call SetHandleUnit(t2,&quot;petal&quot;,d[2])
    call SetHandleReal(t2,&quot;angle&quot;,a)
    call SetHandleReal(t2,&quot;distance&quot;,ds)
    call SetHandleReal(t2,&quot;unitflyheight&quot;,100.)
    call SetHandleReal(t2,&quot;anglex&quot;,0.)
    call SetHandleBoolean(t2,&quot;b&quot;,b)
    call SetHandleBoolean(t2,&quot;bx&quot;,bx)    
    call SetHandleGroup(t2,&quot;groupdamaged&quot;,g)
    
    call SetHandleUnit(t3,&quot;caster&quot;,u)
    call SetHandleUnit(t3,&quot;petal&quot;,d[3])
    call SetHandleReal(t3,&quot;angle&quot;,a)
    call SetHandleReal(t3,&quot;distance&quot;,ds)
    call SetHandleReal(t3,&quot;unitflyheight&quot;,100.)
    call SetHandleReal(t3,&quot;anglex&quot;,0.)
    call SetHandleBoolean(t3,&quot;b&quot;,b)
    call SetHandleBoolean(t3,&quot;bx&quot;,false)    
    call SetHandleGroup(t3,&quot;groupdamaged&quot;,g)
    
    call SetHandleUnit(t4,&quot;caster&quot;,u)
    call SetHandleUnit(t4,&quot;petal&quot;,d[4])
    call SetHandleReal(t4,&quot;angle&quot;,a)
    call SetHandleReal(t4,&quot;distance&quot;,ds)
    call SetHandleReal(t4,&quot;unitflyheight&quot;,50.)
    call SetHandleReal(t4,&quot;anglex&quot;,60)
    call SetHandleBoolean(t4,&quot;b&quot;,b)
    call SetHandleBoolean(t4,&quot;bx&quot;,bx)    
    call SetHandleGroup(t4,&quot;groupdamaged&quot;,g)


vs

JASS:
call SetHandleInt(t1,&quot;data&quot;,struct1)
call SetHandleInt(t2,&quot;data&quot;,struct2)
call SetHandleInt(t3,&quot;data&quot;,struct3)
call SetHandleInt(t4,&quot;data&quot;,struct4)


which is more efficient?

I was lol'ed when I see this spell uses leakly handle vars.

Nice eye candy. :D
 

Viikuna

No Marlo no game.
Reaction score
265
And thats not all. Spell is pretty muchly a badly coded in many ways ( It has no configuration section, damit! ). It really needs some reworking.
 

Hatebreeder

So many apples
Reaction score
381
[ljass] local real a = AngleBetweenPoints(ul,l) [/ljass]

thats a BJ which i removable.

I also suggest that you don't use locations. They are messy and leaky :D
 

NetherHawk

New Member
Reaction score
26
And thats not all. Spell is pretty muchly a badly coded in many ways ( It has no configuration section, damit! ). It really needs some reworking.

could you elaborate where? can we ignore that im not using structs first.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
why cant i make a spell without using structs? @.@
Try to compare them. Spam them heavily. You will find the spell without using struct is more faster to lag up the computer.

can we ignore that im not using structs first.
Okay.
JASS:
        if i == 1 then
            call DestroyEffect(AddSpecialEffectTarget(&quot;Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl&quot;,GetFilterUnit(),&quot;chest&quot;))
        elseif i == 2 then
            call DestroyEffect(AddSpecialEffectTarget(&quot;Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl&quot;,GetFilterUnit(),&quot;left hand&quot;))
        elseif i == 3 then
            call DestroyEffect(AddSpecialEffectTarget(&quot;Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl&quot;,GetFilterUnit(),&quot;right hand&quot;))
        elseif i == 4 then
            call DestroyEffect(AddSpecialEffectTarget(&quot;Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl&quot;,GetFilterUnit(),&quot;left leg&quot;))
        elseif i == 5 then
            call DestroyEffect(AddSpecialEffectTarget(&quot;Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl&quot;,GetFilterUnit(),&quot;right leg&quot;))
        endif

Why can't you set up an init for a string array and store the value?
JASS:
call DestroyEffect(AddSpecialEffectTarget(&quot;Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl&quot;,GetFilterUnit(),AttachPoint[GetRandomInt(1,6)]))

Set the GetFilterUnit() to a variable to reduce the function calling.


Is this a joke?
We already have GetSpellTargetX() and GetSpellTargetY(), why are you still using it?

JASS:
        call GroupClear(g)
        call DestroyGroup(g)

Use a global groups, since you do not use it to store units.

JASS:
        call DestroyTimer(t)

Reuse the timer please.
 

Executor

I see you
Reaction score
57
ok thanks for the reply, i will adjust. What do you mean reuse the timer though?

You create and destroy timer. Why not create a timer only once, pause it after usage and then reuse it the next time the spell is casted.


BTW your spell isnt MUI ! You use a global var set it in the "Actions" functions but use it in the delayed "Scatter" function, so what happens if another hero casts this spell a few miliseconds after the first one ? ;)
 

NetherHawk

New Member
Reaction score
26
ok i changed the coding... would it work better this way? i dont understand the struct1 struct2 struct3 thing kingkingy said in the first post. Can someone show me an example. I have different angle values for the dummy units, so how do i set the data for them. Only 1 of my 4 petal units move.
 

Flare

Stops copies me!
Reaction score
662
As regards the spell itself...
  • As Viikuna said, lack of configuration - given the fact that you're using NewGen, it isn't too difficult to add, and it'll make life immensely easier for the person using the spell
  • Are 4 timers really necessary?
  • Going by code in your first post, you appear to be leaking timers - you create 4 timers in Senbonsakura_Actions (you could be grabbing a recycled timer here), yet you only pause those timers. Simple enough to fix. Either (1) make the timer(s) a dynamic struct member, and do something like
    JASS:
    if data.timer == null then
      set data.timer = CreateTimer ()
    endif

    or (2) get TimerUtils (or anything similar), replace [ljass]CreateTimer ()[/ljass] with [ljass]NewTimer ()[/ljass] and replace [ljass]DestroyTimer (timer) /*or*/PauseTimer (timer)[/ljass] with [ljass]ReleaseTimer (timer)[/ljass]
There may be more stuff I missed, I'm a tad sleepy right now so... :D


+graveyard vote. It does not efficient.
This whole graveyard vote thing is getting ridiculous (curse you J4L! :p). Voting to graveyard this within the first response to the submission is a bit rude (ye, let's not give people any time whatsoever to fix any flaws in the submission) and you want to graveyard something, yet you only point out one flaw?
 

Romek

Super Moderator
Reaction score
963
> You will find the spell without using struct is more faster to lag up the computer.
Really? o_O
News to me.

You don't need to prefix private functions and globals.

> [ljass]function InitTrig_Senbonzakura[/ljass]
[ljass]private function Init[/ljass]

> [ljass]scope Senbonzakura[/ljass]
[ljass]scope Senbonzakura initializer Init[/ljass]

> [ljass]unit byakuya[/ljass]
[ljass]private unit byakuya[/ljass]

You also need a configuration header which basically allows people to modify things such as damage, IDs, models, etc without having to dig through the code. Look through some approved JASS spells to see what I mean.
 

NetherHawk

New Member
Reaction score
26
@ flare: thanks for the comments. Er but i am using the hashtables. The SetHandleXXX is just made to look like the old handle vars but in fact it uses the hashtables. (Vexorian's faux handle vars)

@Romek: thanks too. will edit. I shall add the configuration section too.

Im still having problem with attaching the 4 different dummies to the struct. Cuz i set the angle and height values of each dummy differently. Could someone teach me how?
 

Flare

Stops copies me!
Reaction score
662
The SetHandleXXX is just made to look like the old handle vars but in fact it uses the hashtables. (Vexorian's faux handle vars)
Ah, never realised that Vex made a compatability version of LHV - I just assumed that it was the original by the trigger object's name. In that case, ignore the second half of what I said :p
 

NetherHawk

New Member
Reaction score
26
besides these few variables that i can adjust, are there any more improvements to the code i can make?
 

Romek

Super Moderator
Reaction score
963
Post a link to those Handle Vars in the first post.
Though I'd strongly recommend using a system other than handle vars...

I also tested the spell. I must say that it looks quite impressive!
Though I get three "Double Free of Type: Senbonzakura__Petal" messages per cast.
 

Viikuna

No Marlo no game.
Reaction score
265
For Gods sake, please remove this: [lJASS]call DestroyEffect(AddSpecialEffect("SenbonzakuraPart.mdx",GetUnitX(d),GetUnitY(d)))[/lJASS]

Spell looks much better without it.

If you really need more effect spam, either incerease the number of created projectiles, or that effects particle emmission rate.

( Its a pretty cool looking effect, btw. That curving projectile movement really makes this spell look quite cool )


Also, you should add some [lJASS]group hit[/lJASS] for each projectile, so each projectile can only hit one units once. ( For less blood effect spam )
 

NetherHawk

New Member
Reaction score
26
@ romek: ok i will post the code for the attachments. i think its because i got 4 basic petals moving and i free the Senbonzakura__Petal for each.
@ viikuna: i want to make more particles but i have to sort out my arrays first. i will update asap.

edit: can someone show me 1 example of how i use the array. i use the same senbonzakura_scatter function for all the callbacks, you when i retrieve an array, how do i retrieve the right 1.

@ viikuna: if i want to check if they are in group how do i get the group variable into the filter function, do i have to change my group to a global?
 

Weep

Godspeed to the sound of the pounding
Reaction score
400
Your demo map uses icons for the skill which inexplicably freeze Warcraft 3 on Macs. Perhaps you'd consider removing or re-BLPing the icons?
 
Status
Not open for further replies.
General chit-chat
Help Users
  • No one is chatting at the moment.

      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