• 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.

[vJASS] Problems with angles on sliding system

Status
Not open for further replies.
I have problems with my sliding system.

In this map I got boats. These boats are moving via Triggers. When the owner of the boat click somewhere on the map the boat turn to reach the location.

The problem is when I test the map sometiles they're doeing some beautifus angles sometimes they turn to the finalOrientation directly and sometimes they just don't.

Here is the code
JASS:
scope Move initializer init_Move
    globals
        private constant integer BUFF_ID = 'B000'
     
        private constant real INTERVAL = 0.04
     
        private constant boolean DISPLAY_EFFECT = true
        private constant string EFFECT = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl"
        private constant real EFFECT_DISTANCE = 50
    endglobals
 
private struct Move
    static Move array M
    static integer MT             = 0
    static group G                  = null
    static timer Timer            = null
  
    Boat data      // this is an other struct that record the datas of boats Acceleration, Deceleration, Max movespeed
    unit boat
    real boatDirection  // the current direction of the boat
    real finalAngle  // the direction asked by player
    real effectDistance
    real speed
    boolean turning  // a boolean to know if the boat is turning or not
    boolean turnPlus  // a boolean to know iw wich sens the boat is turning (true is anti-hour sens)
 
    private method onDestroy takes nothing returns nothing
        local real X = GetUnitX(.boat)
        local real Y = GetUnitY(.boat)
        local real A = Deg2Rad(GetUnitFacing(.boat))
        local real pas = 1000
     
        call IssuePointOrder(.boat, "move", X + (Cos(A) * pas), Y + (Sin(A) * pas))
     
        set .boat = null
    endmethod
 
    private method accelerate takes nothing returns nothing
        set .speed = .speed + (.data.acceleration * INTERVAL)
     
        if .speed >= .data.maxSpeed then
            set .speed = .data.maxSpeed
        endif
    endmethod

    private method decelerate takes nothing returns nothing
        set .speed = .speed - (.data.deceleration * INTERVAL)
     
        if .speed <= GetUnitDefaultMoveSpeed(.boat) then
            set .speed = GetUnitDefaultMoveSpeed(.boat)
        endif
    endmethod
 
// HERE IS THE FUNCTION THAT DOES NOT WORKS PROPERLY (This method send a boolean that says when the boat have the correct direction angle or if it has to continue turning)

    private method finishRotation takes nothing returns boolean
        local boolean finish = false
        local real angle = .boatDirection
     
        if angle >= pi(1.5) and .finalAngle <= pi(0.5) then  // method pi return a coeff * pi here 0.5 * 3.1415
            set angle = angle - pi(2)
        endif
     
        if angle <= pi(0.5) and .finalAngle >= pi(1.5) then
            set angle = angle + pi(2)
        endif
     
        if .turnPlus then
            if angle >= .finalAngle then
                set finish = true
            endif
        else
            if angle <= .finalAngle then
                set finish = true
            endif
        endif
     
        return finish
     
    endmethod
 
// END OF THE FUNCTION THAT BUGS

    private method turn takes nothing returns nothing
        local real rotation = Deg2Rad(.data.turnSpeed) * INTERVAL
        local boolean arreteRotation = false
     
        if .turnPlus then
            set .boatDirection = removeModulo(.boatDirection + rotation)    // method that add 2pi if < 0 and remove 2pi if superior to 6.2831
        else
            set .boatDirection = removeModulo(.boatDirection - rotation)
        endif
     
        if .finishRotation() then
            set .boatDirection = .finalAngle
            set .turning = false
        endif
     
        call SetUnitFacing(.boat, Rad2Deg(.boatDirection))
 
    endmethod
 
    private method wichTurn takes nothing returns nothing
        local real borneMoins = .boatDirection
        local real bornePlus = borneMoins + pi(1)
     
        if borneMoins <= pi(2) and borneMoins > pi(1.5) then
            set borneMoins = borneMoins - pi(2)
        endif

        if .finalAngle >= borneMoins and .finalAngle <= bornePlus then
            set .turnPlus = true
        else
            set .turnPlus = false
        endif
     
    endmethod
 
    private method move takes nothing returns nothing
        local real X = GetUnitX(.boat)
        local real Y = GetUnitY(.boat)
        local real pas = .speed * INTERVAL
     
        set X = X + (Cos(.boatDirection) * pas)
        set Y = Y + (Sin(.boatDirection) * pas)
     
        if DISPLAY_EFFECT then
            set .effectDistance = .effectDistance + pas
         
            if .effectDistance >= EFFECT_DISTANCE then
                set .effectDistance = 0
                call DestroyEffect(AddSpecialEffect( EFFECT, X, Y))
            endif
        endif
     
        call SetUnitPosition(.boat, X, Y)
     
    endmethod
 
    static method update takes nothing returns nothing
        local Move m = 0
        local integer I = 0
     
        loop
            set I = I + 1
            set m = .M[I]
         
            if m.turning then
                call m.decelerate()
                call m.turn()
            else
                call m.accelerate()
            endif
         
            call m.move()
         
            if GetUnitAbilityLevel(m.boat, BUFF_ID) == 0 or not(isUnitAlive(m.boat)) or udg_EVENT then
                call UnitRemoveAbility(m.boat, BUFF_ID)
             
                call m.destroy()
             
                set .M[I] = .M[.MT]
                set .MT = .MT - 1
                set I = I - 1
            endif
         
            exitwhen I >= .MT
        endloop
     
        if .MT <= 0 then
            call PauseTimer(.Timer)
            set .MT = 0
        endif
     
    endmethod
 
    static method addMove takes unit U, real X1, real Y1 returns nothing
        local integer I = 0
        local Move m = 0
        local boolean notFound = true
     
        if .MT != 0 then
            loop
                set I = I + 1
                set m = .M[I]
             
                if m.boat == U then
                    set notFound = false
                    set I = .MT
                endif
             
                exitwhen I >= .MT
            endloop
        endif
 
        if notFound then
            set m = Move.allocate()
            set m.boat = U
            set m.speed = GetUnitDefaultMoveSpeed(U)
            set m.data = Boat.findBoat(GetUnitTypeId(U))
            set m.effectDistance = EFFECT_DISTANCE
         
            set .MT = .MT + 1
            set .M[.MT] = m
         
            if .MT == 1 then
                call TimerStart(.Timer, INTERVAL, true, function Move.update)
            endif
        endif
     
        set m.finalAngle = clearAngles(Atan2(Y1-GetUnitY(U), X1-GetUnitX(U)))
        set m.turning = true
        set m.boatDirection = Deg2Rad(GetUnitFacing(m.boat))
     
        call m.wichTurn()
     
//call BJDebugMsg("TARGET ANGLE" + " => " + R2S(m.finalAngle) + " | " + "BOAT ANGLE" + " => " + R2S(m.boatDirection))
     
        set U = null
     
    endmethod
endstruct

function Trig_Move_Conditions takes nothing returns boolean
    return GetUnitAbilityLevel(GetTriggerUnit(), BUFF_ID) != 0
endfunction

function Trig_Move_Actions takes nothing returns nothing
    local unit U = GetTriggerUnit()
 
    call IssueImmediateOrder(U, "stop")
 
    call Move.addMove(U, GetOrderPointX(), GetOrderPointY())
 
    set U = null
 
endfunction

//===========================================================================
function init_Move takes nothing returns nothing
    local trigger T = CreateTrigger(  )
 
    call addEvent(T, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddCondition( T, Condition( function Trig_Move_Conditions ) )
    call TriggerAddAction( T, function Trig_Move_Actions )
 
    set Move.G = CreateGroup()
    set Move.Timer = CreateTimer()
 
    call Preload( EFFECT )
 
    set T = null
endfunction

endscope

I've worked on that for a week I've tested a lot of stuffs so if anyone exterior can have a look it cound be nice

Thank you

Edit (IcemanBo): changed tags to JASS format

//// NEW ELEMENTS

I just add the pauseUnit before the order "stop" and it was worse
 
Last edited:
Hm ok, good luck. Just note if there's any problem.

By the way,
I don't due to double posting
if a post is in between, like DSG, or me already posted, then you for sure may post within 48 again, too - then it's not a double post. But also, in cases it makes good sense to make a new seperate post, like you find out a bug, and wanna let everyone know before we look at outdated code or so, then you may even double post. Site Rules
 
Status
Not open for further replies.
Top