Won't run 2 timers at once

D.V.D

Make a wish
Reaction score
73
My code doesn't want to run 2 timers at once. The code is supposed to make a unit be knockbacked and during hes sliding, the caster charges a circle of energy and lets out a beam causing a explosion to happen. Whats not working is the charging. It seems to skip the charging part and skips the wait in the timer and fires the beam right after the unit is knockbacked. Here's the code:

JASS:
scope GentleFist initializer Init

    globals
        private constant attacktype atype1 = ATTACK_TYPE_NORMAL
        private constant attacktype atype2 = ATTACK_TYPE_MAGIC
        
        private constant damagetype dtype1 = DAMAGE_TYPE_NORMAL
        private constant damagetype dtype2 = DAMAGE_TYPE_MAGIC
        
        private constant integer AbilId = 'AHtb'
        private constant integer Castrange = 10
        private constant integer DummyId = 'h000'
        private constant integer DummyId2 = 'h001'
        private constant integer DummyId3 = 'h002'
        private constant integer Laserarray = 200
        
        private constant real dummydist = 50.00
        private constant real laserdamage = 500.00
        private constant real laserdmgradius = 200.00
        private constant real laserdistance = 9.00
        private constant real movedamage = 2.00
        private constant real movedistance = 9.00
        private constant real movedistancefull = 360.00
        private constant real movetime = 0.02
        
        private constant string EffectId = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"
        private constant string EffectId2 = "Abilities\\Spells\\Orc\\EarthQuake\\EarthQuakeTarget.mdl"
        private constant string EffectId3 = "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl"
        
        private constant weapontype wtype1 = WEAPON_TYPE_WHOKNOWS
        private constant weapontype wtype2 = WEAPON_TYPE_WHOKNOWS
    endglobals
    
    //-------------------\\
    //   CONFIGURABLES:  \\
    //-------------------\\
    
    private function GetDamage takes integer lvl returns real
        return lvl + 1.00
    endfunction
    
    private function GetLaserDamage takes integer lvl returns real
        return 300.00 * lvl
    endfunction
    
    private function GetLaserRadius takes integer lvl returns real
        return 200.00 * lvl
    endfunction
    
    private function GetMoveDistanceFull takes nothing returns real
        return movedistance * 40
    endfunction
    
    private function GetChargeTime takes nothing returns real
        return GetMoveDistanceFull() / movedistance
    endfunction
    
    //-------------------\\
    // DO NOT EDIT BELOW \\
    //-------------------\\
    
    globals
        private unit Explosion
    endglobals
    
    private struct data
        integer count
        integer count1
        real distance
        real sizex
        real sizey
        real sizez
        real x
        real y
        unit caster
        unit charge
        unit array laser [Laserarray]
        unit target
        
        method onDestroy takes nothing returns nothing
            set .caster = null
            set .charge = null
            set .target = null
        endmethod
        
    endstruct

    private function Conditions takes nothing returns boolean
        return ( GetSpellAbilityId() == AbilId )
    endfunction
    
    private function Laser takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local data d = GetTimerData(t)
        local integer lvl = GetUnitAbilityLevel( d.caster, AbilId )
        local real angle = GetUnitFacing(d.caster)
        local real x = GetUnitX(d.caster) + d.distance * Cos(angle * bj_DEGTORAD)
        local real y = GetUnitY(d.caster) + d.distance * Sin(angle * bj_DEGTORAD)
        
        set d.laser[d.count] = CreateUnit( GetOwningPlayer(d.caster), DummyId2, x, y, angle )
        call PauseUnit( d.laser[d.count], true )
        call SetUnitTimeScale( d.laser[d.count], 0.00 )
        
        set d.count = d.count + 1
        set d.distance = d.distance + laserdistance
        
        if ( d.count == GetMoveDistanceFull / movedistance + Castrange ) then
            set d.count = 0
            loop
                exitwhen d.count > movedistancefull / movedistance + 100.00
                call SetUnitTimeScale( d.laser[d.count], 100.00 )
                call SetUnitAnimation( d.laser[d.count], "death" )
                call KillUnit(d.laser[d.count])
                set d.count = d.count + 1
            endloop
            set Explosion = CreateUnit( GetOwningPlayer(d.caster), DummyId3, x, y, angle )
            call UnitApplyTimedLife( Explosion, 'BTLF', 1.00 )
            call UnitDamagePoint( d.caster, 0.00, GetLaserRadius(lvl), x, y, GetLaserDamage(lvl), true, false, atype2, dtype2, wtype2 )
            call ReleaseTimer(t)
            call d.destroy()
        endif
    endfunction
    
    private function Move takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local data d = GetTimerData(t)
        local integer lvl = GetUnitAbilityLevel( d.caster, AbilId )
        local real angle = GetUnitFacing(d.caster)
        local real x = GetUnitX(d.target) + movedistance * Cos(angle * bj_DEGTORAD)
        local real y = GetUnitY(d.target) + movedistance * Sin(angle * bj_DEGTORAD)
        
        call DestroyEffect( AddSpecialEffect( EffectId, x, y ) )
        call SetUnitPosition( d.target, x, y )
        call UnitDamageTarget( d.caster, d.target, GetDamage(lvl), true, false, atype1, dtype1, wtype1 )
        set d.count = d.count + 1
        
        if ( d.count == GetMoveDistanceFull() / movedistance ) then
            call SetUnitAnimation( d.target, "death" )
            call DestroyEffect( AddSpecialEffect( EffectId2, x, y ) )
            set d.count = 1
            set d.distance = 9.00
            set d.x = x
            set d.y = y
            call PauseTimer(t)
            call TimerStart( t, 0.02, true, function Laser )
            set t = null
        endif
        
    endfunction
    
    private function Charge takes nothing returns nothing
        local timer z = GetExpiredTimer()
        local data u = GetTimerData(z)
        
        set u.sizex = u.sizex + 10.00
        set u.sizey = u.sizey + 10.00
        set u.sizez = u.sizez + 10.00
        
        call DestroyEffect( AddSpecialEffectTarget( EffectId3, u.charge,"chest" ) )
        call SetUnitScale( u.charge, u.sizex, u.sizey, u.sizez )
        set u.count1 = u.count1 + 1
        
        if ( u.count1 == GetMoveDistanceFull() / movedistance ) then
            call KillUnit(u.charge)
            call ReleaseTimer(z)
            call u.destroy()
        endif
    endfunction

    private function Actions takes nothing returns nothing
        local data d = data.create()
        local data u = data.create()
        local real face = GetUnitFacing(d.caster) + 50.00
        local real x
        local real y
        local timer t = NewTimer()
        local timer z = NewTimer()
        local unit dummy
        
        set d.count = 0
        set u.count1 = 0
        set d.caster = GetTriggerUnit()
        set d.target = GetSpellTargetUnit()
        set u.sizex = 100.00
        set u.sizey = 100.00
        set u.sizez = 100.00
        set x = GetUnitX(d.caster) + dummydist * Cos(face * bj_DEGTORAD)
        set y = GetUnitY(d.caster) + dummydist * Sin(face * bj_DEGTORAD)
        set dummy = CreateUnit(GetOwningPlayer(d.caster),DummyId,x,y,face)
        
        call PauseUnit(dummy, true)
        call UnitApplyTimedLife( dummy, 'BTLF', 0.30 )
        
        set u.charge = CreateUnit(GetOwningPlayer(d.caster), DummyId3, x, y, face)
        
        call PauseUnit(d.charge, true)
        call SetTimerData( t, d )
        call SetTimerData( z, u )
        call TimerStart( t, movetime, true, function Move )
        call TimerStart( z, 0.07, true, function Charge )
    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
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
Ok, firstly, your timers are starting just fine. The reason you THINK your charge timer doesn't work is that you have no clue how the unit scale native works.
1-Only the x input works. y and z scale inputs do absolutely nothing. Just do:
JASS:
call SetUnitScale(u,scale,0,0)

2-Like just about everything in jass, it takes factors, not percents. The reason you can't see anything going on? It's all WAAAY OFF SCREEEN. Because your unit has a scale of 100 TIMES ITS NORMAL SIZE right off the bat.


Now that that's covered, let's get to the reason why, according to the code you posted, your laser is probably creating laser units indefinitely.
See this in your Laser function:
JASS:
if ( d.count == GetMoveDistanceFull / movedistance + Castrange ) then

Two major problems here. First and formost, comparing anything to a real with == is extremely dangerous in wc3. If the real happens to not be an integer, it fails miserably. Put an R2I wrapper around the right side of the comparison. Second problem is, you use GetMoveDistanceFull instead of GetMoveDistanceFull(). This causes vJass to think you want a function integer key instead of an actual useful value from said function. In other words, GetMoveDistanceFull will return a value of like 1 or 36 or something.
I recommend wrapping the R2I around equivalent checks in other functions. Note that you do the same silly GetMoveDistanceFull thing again like 3 lines later. And that ALSO needs the R2I call.

Then there's this in the move function:
JASS:
set t = null

You only change the pointer when you need the ref count to be decremented. This has no purpose for objects that won't be destroyed.

Then there's the inherent aesthetic problem. You move the unit and THEN create a laser going in the same distance and direction but at the same speed and from a DIFFERENT starting point.
Imagine kicking someone backwards, and then having a car park in the same direction of your kick in some nearby parking lot, and then blaiming the cars movement on kicking the guy. It makes no sense.
I dunno, maybe you intended that, which would mean I don't get in any way shape or form WTF you're trying to accomplish.
 

T.s.e

Wish I was old and a little sentimental
Reaction score
133
If I'm not horribly mistaken, you do not need to use R2I here, but instead change this..
JASS:
if ( d.count == GetMoveDistanceFull / movedistance + Castrange ) then

To this:
JASS:
if ( d.count >= GetMoveDistanceFull / movedistance + Castrange ) then
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top