• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[JASS] Flame Shackles (Spell) - Getting stuck on some 'basic' things

Status
Not open for further replies.
Level 19
Joined
Oct 12, 2007
Messages
1,821
Hey there.

I'm making a Jass spell for the last Sage spell for Oakwood Forest.
Recently RaiN. left the team because of exams and Starcraft II (Boo!!!). For now I try to create this last spell that was needed on my own but I got a bit stuck.

Here's the spell description:

Flame Shackles
Summons fiery shackles at the targetted location. The shackles will grab any enemy target around them and slowly drag the targets towards the center for 6 seconds. After the 6 seconds the shackles will drag the targets to the center again; breaking the shackles and causing a fiery explosion dealing Intelligence * 1.4 fire damage to the targets.

[Effect looks like Aerial Shackles comming out of the center of the area]
[Spell area of effect is 200 but units will be able to move a littlebit out of the area. The further the unit is away from the center the stronger the chains drag him so after a certain range (based on his move speed) he won't be able to move any further]
[If the unit is within 150 of the center he wont get dragged to still be able to cast cast-time spells.]
[A unit that's 400 out of the center will get a 'drag power' of 600 speed. Meaning that if the unit has a movement speed of 600 and moves straight out of the area it will basically stand still]
[A unit that's 150 out of the center will get a 'drag power' of 0 speed.]
[A unit that's 275 out of the center will get a 'drag power' of 300 speed. Meaning that if the unit has a movement speed of 300 and moves straight out of the area it will basically stand still]


Here's the test map Im trying to make the spell in.
I wrote down the issues it has at the moment in the "Trigger Comment" menu.
Note: I already did all caltulation stuff. I think it's a pretty easy task to solve my problems for an average scripter.

Here are basically the things that are wrong with the trigger:

Things that are currently undone/wrong:

1) There is no special effect that creates an Aerial Shackles chain between the point and the units hit by the spell.
2) I don't know how to activate the loop. The spell get's cast now and all that happens is it groups unit in a unit group while that group is never getting used because I don't know how to connect those functions.
3) The loop at the moment takes FirstOfGroup as it's unit. But it is supposed to loop this multiple times until all units in the group have been under the loop's effect.
4) Didn't test stuff yet but I think the calculations are right. The 600 is representing the unit's maximum movement speed.
5) Didn't know all those stupid damage names so after the effect there is no damage dealt yet.
6) Probably some more stuff I'm not aware of.



Here's the code:
JASS:
scope Fiery Shackles initializer Initialization

globals
    private constant integer SPELL_ID = 'A000'
    private constant integer BUFF_ID = 'B000'
    
    private constant string FinalEffectArt = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
    
    private constant real AoE = 200.00
    private constant real Duration = 6.00
    private constant real MinDistance = 150
    private constant real MaxDistance = 400
    private constant real Interval = 0.03
    private constant real SpeedIncrement = 600 * Interval / (MaxDistance - MinDistance)
endglobals

globals
    private group UnitGroup = CreateGroup()
    private boolean bool = false
endglobals

private function Check takes nothing returns nothing
local unit u = GetTriggerUnit()
local real x = GetLocationX(GetSpellTargetLoc())
local real y = GetLocationY(GetSpellTargetLoc())


if GetSpellAbilityId() == SPELL_ID then

    call GroupEnumUnitsInRange(UnitGroup, x, y, AoE, bool)
    
endif
endfunction

private function Loop takes nothing returns nothing
local real i = 0.
local integer i2 = 0
local unit t = null
local real dx = 0.
local real dy = 0.
local real px = 0.
local real py = 0.
local real Distance = 0.

    loop
    /// Duration is in this case 6.00 seconds ///
    exitwhen i >= Duration
        
        set t = FirstOfGroup(UnitGroup)
        if GetUnitAbilityLevel(FirstOfGroup(UnitGroup), BUFF_ID) > 0 then
            if IsUnitInRangeLoc(t, GetSpellTargetLoc()), MinDistance) == false then
            
            /// Calculating the Distance from Picked Unit to Spell Location ///
            set dx = GetLocationX(GetSpellTargetLoc()) - GetUnitX(t)
            set dy = GetLocationY(GetSpellTargetLoc()) - GetUnitY(t)
            set Distance = SquareRoot(dx * dx + dy * dy)
            
            /// Calculating the unit's new X and Y ///
            set px = GetUnitX(t) + SpeedIncrement * (Distance - MinDistance) * Cos(bj_RADTODEG * Atan2(GetUnitY(t) - GetLocationY(GetSpellTargetLoc()), GetUnitX(t) - GetLocationX(GetSpellTargetLoc())) * bj_DEGTORAD)
            set py = GetUnitY(t) + SpeedIncrement * (Distance - MinDistance) * Sin(bj_RADTODEG * Atan2(GetUnitY(t) - GetLocationY(GetSpellTargetLoc()), GetUnitX(t) - GetLocationX(GetSpellTargetLoc())) * bj_DEGTORAD)
            
            call SetUnitPositionLoc(t, Location(px, py))
            set i = i+Interval
            call TriggerSleepAction(Interval)
            else
            call GroupRemoveUnit(UintGroup, t)
        endif
    endloop
    
    /// This occurs after the duration of the loop ///
    /// The units will lose the "Grip debuff" but will get pulled towards the center over 0.30 sec first ///
    loop
    /// Duration is 0.30 second to match with 10 intervals of 0.03 ///
    exitwhen i2 >= 10
        
        set t = FirstOfGroup(UnitGroup)
            
        /// Calculating the unit's new X and Y ///
        set px = GetUnitX(t) + SpeedIncrement * (MaxDistance / 0.3 - (0.3 * 600)) * Cos(bj_RADTODEG * Atan2(GetUnitY(t) - GetLocationY(GetSpellTargetLoc()), GetUnitX(t) - GetLocationX(GetSpellTargetLoc())) * bj_DEGTORAD)
        set py = GetUnitY(t) + SpeedIncrement * (MaxDistance / 0.3 - (0.3 * 600)) * Sin(bj_RADTODEG * Atan2(GetUnitY(t) - GetLocationY(GetSpellTargetLoc()), GetUnitX(t) - GetLocationX(GetSpellTargetLoc())) * bj_DEGTORAD)
            
        call SetUnitPositionLoc(t, Location(px, py))
        set i2 = i2+0.03
        call TriggerSleepAction(0.03)
    endloop
    
    ///Now the big fire splash happens and the units will get 'released' from the chains ///
    
    /// call caster deals Int*1.4 damage to all enemy units within the assigned AoE (200 in this case) at SpellTargetLocation ///
    call DestroyEffect(AddSpecialEffectLoc(FinalEffectArt, GetSpellTargetLoc()))
        

endfunction

//===========================================================================
function Initialization takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Fiery_Shackles, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Fiery_Shackles, function Check )
    set t = null
endfunction
endscope

I hope there's anyone out there that wants to solve these issues for me because this is the last spell one of the last classes from Oakwood needs so I can make a little preview movie and get closer to a demo version.
 

Attachments

  • FlameShackles.w3x
    15.9 KB · Views: 58
Level 11
Joined
Sep 30, 2009
Messages
698
Ok some basics:
local real x = GetLocationX(GetSpellTargetLoc())
local real y = GetLocationY(GetSpellTargetLoc())

should be:
local real x = GetSpellTargetX()
local real y = GetSpellTargetY()

same for othe things with locations just use coordinates they are faster

dont use waits in loops


for the connection you should learn structs it makes it way easier :)

~ Axarion
 
Level 19
Joined
Oct 12, 2007
Messages
1,821
Ok some basics:
local real x = GetLocationX(GetSpellTargetLoc())
local real y = GetLocationY(GetSpellTargetLoc())

should be:
local real x = GetSpellTargetX()
local real y = GetSpellTargetY()

Ahh oke.
I already changed GetLocationX(GetUnitLoc(t)) into GetUnitX
Didn't know it was possible to do this with SpellTarget aswell.

Thanks:)

As for the structs. Yeah I have no clue what a struct is about but I heard many people about it before so that's probably something I got to spend some time on.
I also knew that I should've tried to avoid waits but I didn't know how to avoid them. Apperantly that will get solved with structs aswell.
Would be great if someone knew a good tutorial that explains what structs do and how to make structs. Didn't find one on the hive workshop atleast.
 
Level 14
Joined
Nov 18, 2007
Messages
816
Imagine structs as real objects. Take a human: Each human has certain properties like eye color, height, hair color and so on. In vJass, you model your data as objects:

JASS:
struct Human
    string EyeColor
    string HairColor
    real Height
endstruct


Hmmm, you could just open JassHelpers manual and read it instead.
 
Level 19
Joined
Oct 12, 2007
Messages
1,821
Imagine structs as real objects. Take a human: Each human has certain properties like eye color, height, hair color and so on. In vJass, you model your data as objects:

JASS:
struct Human
    string EyeColor
    string HairColor
    real Height
endstruct


Hmmm, you could just open JassHelpers manual and read it instead.

I see, thanks.
 
Level 14
Joined
Jul 26, 2008
Messages
1,009
There's OOP tutorials here on hive for great justice! Just head to the tutorial header and do a CTRL+F for OOP. That'll get you started.

As for your issue with avoiding waits in loops, try out some TimerUtils. I think I directed you to a thread once before that I had started concerning periodics and how to make them work. Unfortunately I've forgotten it. :\
 
Status
Not open for further replies.
Top