• 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] Missile movement question (With xe)

Status
Not open for further replies.
Level 14
Joined
Jul 26, 2008
Messages
1,009
Alright I'm using xe to move a missile towards a location. It's got the whole grenade effect, as the spell is called molotov and simulates a molotov cocktail bomb when thrown. However I'm having troubles. Mainly with transfering the fx I created in one trigger and moving it into the timer properly.

Since fx runs on a system, I wasn't sure how to do it properly. Any help on getting the fx's information from the trigger it's created in into the timer?

JASS:
 scope AlcheBomb initializer Init

globals
    private constant integer    SpellID = 'bomb'
    private constant damagetype dmg     = DAMAGE_TYPE_FIRE
    private constant weapontype wpn     = WEAPON_TYPE_WHOKNOWS
    private constant attacktype atk     = ATTACK_TYPE_MAGIC
    private constant string  MODEL_PATH_MISSILE       = "Abilities\\Weapons\\BatTrollMissile\\BatTrollMissile.mdl"
    private constant string  MODEL_PATH_FLASH         = null
    private unit caster
    private real damage
endglobals

private function JumpParabola takes real dist, real maxdist,real maxheight returns real
    local real t = (dist*2)/maxdist-1    
    return (-t*t+1)*maxheight
endfunction
   
private struct Data
    unit c
    real X2
    real Y2
    real til
    real dur
    group g
    real X3
    real Y3
    real maxDist
    
    static method create takes unit caster, real targX, real targY, group gro, real xefxX3, real xefxY3 returns Data
     local Data D = Data.allocate()
        set D.c = caster
        set D.X2 = targX
        set D.Y2 = targY
        set D.dur = 0.
        set D.g = gro
        set D.X3 = xefxX3
        set D.Y3 = xefxY3
        set D.maxDist = SquareRoot((D.X2 - D.X3)*(D.X2 - D.X3)+(D.Y2 - D.Y3)*(D.Y2 - D.Y3))
     return D
    endmethod
    
endstruct

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

private function MissileMove takes nothing returns nothing
 local timer tim = GetExpiredTimer()
 local Data D = Data(GetTimerData(tim))
 local real maxHeight = 500.
 local real cur_dist = SquareRoot((fx.x - D.X2)*(fx.x - D.X2)+(fx.y - D.Y2)*(fx.y-D.Y2))
 local real fly = JumpParabola(cur_dist, maxDist, maxHeight)//Shadow1500 jump parabola 
 local real angle = Atan2(D.X2 - GetUnitY(D.c), D.Y2 - GetUnitX(D.c))
 local real moveX              = fx.x + 15. * Cos(angle)
 local real moveY              = fx.y + 15. * Sin(angle)
 
    if cur_dist <= 15.0 then
        call fx.destroy
        call ReleaseTimer(tim)
        Do Damage Stuff Here
        
    else
        set fx.x = GetUnitX( moveX )
        set fx.y = GetUnitY( moveY )
        set fx.z = fly  
    endif
    
endfunction

private function GroupEnum takes nothing returns boolean
    if IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(caster)) then
        call UnitDamageTarget(caster, GetFilterUnit(), damage, true, false, atk, dmg, wpn)
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl", GetFilterUnit(), "origin"))
    endif
 return false
endfunction

private function Timer takes nothing returns nothing
    local timer tim = GetExpiredTimer()
    local Data D = Data(GetTimerData(tim))
    if D.dur >= 5. then
        call ReleaseTimer(tim)
        call D.destroy()
    else
    set damage = 5 * GetUnitAbilityLevel(D.c, SpellID)
    call GroupEnumUnitsInRange(D.g, D.X2, D.Y2, 150 + 45. * GetUnitAbilityLevel(D.c, SpellID), function GroupEnum)
    set D.dur = D.dur + 1.
    endif
endfunction

private function Actions takes nothing returns nothing
 local timer tim = NewTimer()
 local timer tim2 = NewTimer()
 local real X1 = GetUnitX(GetTriggerUnit())
 local real Y1 = GetUnitY(GetTriggerUnit())
 local real a = Atan2(GetSpellTargetX() - GetUnitY(GetTriggerUnit()), GetSpellTargetY() - GetUnitX(GetTriggerUnit()))
 local xefx fx = xefx.create(GetUnitX(GetTriggerUnit())+20.0*Cos(a), GetUnitY(GetTriggerUnit())+20.0*Sin(a), a)
 local Data D = Data.create(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY(), CreateGroup(), fx.x, fx.y)
 
 local real til = SquareRoot(Pow(X1 - D.X2, 2) + Pow(Y1 - D.Y2, 2)) / 700.
    
    set caster = D.c
    set fx.fxpath = "Abilities\\Weapons\\BatTrollMissile\\BatTrollMissile.mdl"
    
    call SetTimerData(tim, D)
    call TimerStart(tim, 0.03, true, function MissileMove)
    
    call TriggerSleepAction(til)
    call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\DemolisherFireMissile\\DemolisherFireMissile.mdl", D.X2, D.Y2))
    set damage = 125 + 50 * GetUnitAbilityLevel(caster, SpellID)
    call GroupEnumUnitsInRange(D.g, D.X2, D.Y2, 150 + 45. * (GetUnitAbilityLevel(D.c, SpellID) - 1), function GroupEnum)
    call SetTimerData(tim2, D)
    call TimerStart(tim2, til, true, function Timer)
    
        call fx.destroy()
 set tim = null
endfunction

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

endscope

Mind you these are not my equations. I can't do this level of math. :\ Also I still have a lot of the basic non-missile effect set up, which I'll likely change when I have figured this out. Still optomization suggestions are always +repable :)
 
Last edited:
Level 14
Joined
Jul 26, 2008
Messages
1,009
Alright, this is what I did. But I get this error "Unexpected ".x"" I don't think I'm grasping exactly what it is you're telling me to do.

JASS:
scope AlcheBomb initializer Init

globals
    private constant integer    SpellID = 'bomb'
    private constant damagetype dmg     = DAMAGE_TYPE_FIRE
    private constant weapontype wpn     = WEAPON_TYPE_WHOKNOWS
    private constant attacktype atk     = ATTACK_TYPE_MAGIC
    private constant string  MODEL_PATH_MISSILE       = "Abilities\\Weapons\\BatTrollMissile\\BatTrollMissile.mdl"
    private constant string  MODEL_PATH_FLASH         = null
    private unit caster
    private real damage
endglobals

private function GroupEnum takes nothing returns boolean
    if IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(caster)) then
        call UnitDamageTarget(caster, GetFilterUnit(), damage, true, false, atk, dmg, wpn)
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl", GetFilterUnit(), "origin"))
    endif
 return false
endfunction

private function JumpParabola takes real dist, real maxdist,real maxheight returns real
    local real t = (dist*2)/maxdist-1    
    return (-t*t+1)*maxheight
endfunction
   
private struct Data
    unit c
    real X2
    real Y2
    real til
    real dur
    group g
    real maxDist
    real fx.x
    real fx.y
    real fx.z
    
    static method create takes unit caster, real targX, real targY, group gro, real fxx, real fxy returns Data
     local Data D = Data.allocate()
        set D.c = caster
        set D.X2 = targX
        set D.Y2 = targY
        set D.dur = 0.
        set D.g = gro
        set D.fx.x = fxx
        set D.fx.y = fxy
        set D.fx.z = 60
        set D.maxDist = SquareRoot((D.X2 - D.fx.x)*(D.X2 - D.fx.x)+(D.Y2 - D.fx.y)*(D.Y2 - D.fx.y))
     return D
    endmethod
    
endstruct

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

private function MissileMove takes nothing returns nothing
 local timer tim = GetExpiredTimer()
 local Data D = Data(GetTimerData(tim))
 local real maxHeight = 500.
 local real cur_dist = SquareRoot((D.fx.x - D.X2)*(D.fx.x - D.X2)+(D.fx.y - D.Y2)*(D.fx.y-D.Y2))
 local real fly = JumpParabola(cur_dist, maxDist, maxHeight)//Shadow1500 jump parabola 
 local real angle = Atan2(D.X2 - GetUnitY(D.c), D.Y2 - GetUnitX(D.c))
 local real moveX              = D.fx.x + 15. * Cos(angle)
 local real moveY              = D.fx.y + 15. * Sin(angle)
 
    if cur_dist <= 15.0 then
        call D.fx.destroy
        call ReleaseTimer(tim)
        Do Damage Stuff Here
        
    else
        set D.fx.x = GetUnitX( moveX )
        set D.fx.y = GetUnitY( moveY )
        set D.fx.z = fly  
    endif
    
endfunction

private function Timer takes nothing returns nothing
    local timer tim = GetExpiredTimer()
    local Data D = Data(GetTimerData(tim))
    if D.dur >= 5. then
        call ReleaseTimer(tim)
        call D.destroy()
    else
    set damage = 5 * GetUnitAbilityLevel(D.c, SpellID)
    call GroupEnumUnitsInRange(D.g, D.X2, D.Y2, 150 + 45. * GetUnitAbilityLevel(D.c, SpellID), function GroupEnum)
    set D.dur = D.dur + 1.
    endif
endfunction

private function Actions takes nothing returns nothing
 local timer tim = NewTimer()
 local timer tim2 = NewTimer()
 local real X1 = GetUnitX(GetTriggerUnit())
 local real Y1 = GetUnitY(GetTriggerUnit())
 local real a = Atan2(GetSpellTargetX() - GetUnitY(GetTriggerUnit()), GetSpellTargetY() - GetUnitX(GetTriggerUnit()))
 local xefx fx = xefx.create(GetUnitX(GetTriggerUnit())+20.0*Cos(a), GetUnitY(GetTriggerUnit())+20.0*Sin(a), a)
 local Data D = Data.create(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY(), CreateGroup(), fx.x, fx.y)
 
 local real til = SquareRoot(Pow(X1 - D.X2, 2) + Pow(Y1 - D.Y2, 2)) / 700.
    
    set caster = D.c
    set fx.fxpath = "Abilities\\Weapons\\BatTrollMissile\\BatTrollMissile.mdl"
    
    call SetTimerData(tim, D)
    call TimerStart(tim, 0.03, true, function MissileMove)
    
    call TriggerSleepAction(til)
    call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\DemolisherFireMissile\\DemolisherFireMissile.mdl", D.X2, D.Y2))
    set damage = 125 + 50 * GetUnitAbilityLevel(caster, SpellID)
    call GroupEnumUnitsInRange(D.g, D.X2, D.Y2, 150 + 45. * (GetUnitAbilityLevel(D.c, SpellID) - 1), function GroupEnum)
    call SetTimerData(tim2, D)
    call TimerStart(tim2, til, true, function Timer)
    
        call fx.destroy()
 set tim = null
endfunction

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

endscope

if you're suggesting the "this." keyword doesn't that just point to the current instance of the struct?
 
Level 14
Joined
Jul 26, 2008
Messages
1,009
Ahh okay. So I'm adding the entire struct to the struct, not just elements.

What about extending the struct? Would that be easier? Or wait, nvm, that just adds data to it or something. I haven't gotten that far into vJASS.

:D Thanks, it works now btw. Only, not quiet. The formula must be off or missing something, since it seems to sit for a second then accelerate really fast and explode.
 
Last edited:
Status
Not open for further replies.
Top