Flight Sim Help

Jonnycakes

New Member
Reaction score
6
Hi, I started messing around with a flight system today that utilizes the arrow keys. The system works by creating one flying unit for each player (more specifically a ground unit that has had crow form added/removed from it) that is then controlled with the arrow keys (the unit moves forward at a fixed rate. Left/Right turn the unit and Up/Down change its height). The camera locks behind that unit for the player. The problem is this:

When I added some noise to the terrain to test the system's height adjustment, the flying unit started going batsh**. When a unit flies over varied terrain, the camera level stays normal, but the unit's fly height starts changing inversely with the height of the terrain (i.e. if the terrain lowers, the unit starts flying higher. If the terrain raises, the unit starts flying lower). I have no idea why this is-the "base height" (height of the unit disregarding terrain height) stays the same, and if the unit flies back to a level surface, all is well. It is quite strange...

Anyway, here is my trigger. Each unit's data is stored as an instance of a struct in an array. This function loops through said struct array and does periodic actions for each unit.
JASS:
scope moveloop initializer init

private function actions takes nothing returns nothing
    local integer i=0
    local unitdata temp
    local location loc
    local real z
    
    loop
        exitwhen i==playerstotal
        set temp=ud<i>
        set temp.velocity=temp.velocity+temp.accelleration
        if temp.velocity&lt;0 then
            set temp.velocity=0
            set temp.accelleration=0
        endif
        if temp.left and not temp.right then
            set temp.facing=temp.facing+.1
        elseif temp.right and not temp.left then
            set temp.facing=temp.facing-.1
        endif
        call SetUnitFacing(temp.u, Rad2Deg(temp.facing))
        set temp.x=GetUnitX(temp.u)
        set temp.y=GetUnitY(temp.u)
        if temp.up and not temp.down then
            set temp.height=temp.height+10
        elseif temp.down and not temp.up then
            set temp.height=temp.height-10
        endif
        set temp.x=temp.x+temp.velocity*Cos(temp.facing)
        set temp.y=temp.y+temp.velocity*Sin(temp.facing)
        call SetUnitPosition(temp.u, temp.x, temp.y)
        set loc=Location(temp.x, temp.y)
        set z=GetLocationZ(loc)
        if temp.height-z&lt;HEIGHTMIN then
            set temp.height=z+HEIGHTMIN
        endif
        if temp.height&gt;HEIGHTMAX then
            set temp.height=HEIGHTMAX
        endif
        call SetUnitFlyHeight(temp.u, temp.height-z, 0)
        if GetLocalPlayer()==temp.p then
            call PanCameraToTimed(temp.x-10*Cos(temp.facing), temp.y-10*Sin(temp.facing), 0)
            call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, 330, 0)
            call SetCameraField(CAMERA_FIELD_ROTATION, Rad2Deg(temp.facing), 0)
            call SetCameraField(CAMERA_FIELD_ZOFFSET, temp.height, 0)
        endif
        //call BJDebugMsg(R2S(GetUnitFlyHeight(temp.u)))
        //call BJDebugMsg(R2S(z))
        call RemoveLocation(loc)
        set i=i+1
    endloop
    set loc=null    
endfunction

//===========================================================================
private function init takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerAddAction(t, function actions)
    call TriggerRegisterTimerEvent(t, .04, true)
endfunction

endscope</i>
 

Tyman2007

Ya Rly >.
Reaction score
74
Meh.. Seeing as how WC3 sucks with dealing with Z values over terraindeformations the game can de-sync T.T

It's probably just better to avoid terrain deformations if you're planning on messing with z values.

or.. I could be horribly wrong and someone can correct me :p

EDIT: Just looked at your trigger.

JASS:
        set temp.x=temp.x+temp.velocity*Cos(temp.facing)
        set temp.y=temp.y+temp.velocity*Sin(temp.facing)

        set loc=Location(temp.x, temp.y)
        set z=GetLocationZ(loc)


The bottom part there is useless. If you're only dealing with X and Ys, Z is going to return 0 anyway, so why have it?

here is the original location of temp.x and temp.y
JASS:
        set temp.x=GetUnitX(temp.u)
        set temp.y=GetUnitY(temp.u)

It's smart to get the unit Z there.

[ljass]set z = GetUnitZ(temp.u)[/ljass]

instead of trying to get a Z value that doesn't exist.

but.. the problem is, I don't think there's a GetUnitZ, so that's a problem.
 

Jonnycakes

New Member
Reaction score
6
The idea of that is to get the TERRAIN z, not the UNIT z. The unit z is stored in it's fly height, or in the struct (.height). The purpose of getting the terrain z is to know what value to set the unit's fly height to. If the terrain is higher, the unit's fly height needs to be set lower and vice versa. So the unit's overall height (.height) minus the terrain height (z, or GetLocationZ(loc)) is what the unit's fly height needs to be. The reason I use the new X and Y is because the unit is being moved there, and its height needs to reflect the terrain height at where it will actually be, not where it was 1 frame ago. So, z shouldn't be 0.

Also, why/how does the game desync when this happens?
 

Sevion

The DIY Ninja
Reaction score
413
JASS:
scope moveloop initializer init

private function actions takes nothing returns nothing
    local integer i=0
    local unitdata temp
    local location loc
    local real z
    
    loop
        exitwhen i==playerstotal
        set temp=ud<i>
        set temp.velocity=temp.velocity+temp.accelleration
        if temp.velocity&lt;0 then
            set temp.velocity=0
            set temp.accelleration=0
        endif
        if temp.left and not temp.right then
            set temp.facing=temp.facing+.1
        elseif temp.right and not temp.left then
            set temp.facing=temp.facing-.1
        endif
        call SetUnitFacing(temp.u, temp.facing * bj_RADTODEG)
        set temp.x=GetUnitX(temp.u)
        set temp.y=GetUnitY(temp.u)
        if temp.up and not temp.down then
            set temp.height=temp.height+10
        elseif temp.down and not temp.up then
            set temp.height=temp.height-10
        endif
        set temp.x=temp.x+temp.velocity*Cos(temp.facing)
        set temp.y=temp.y+temp.velocity*Sin(temp.facing)
        call SetUnitX(temp.u, temp.x)
        call SetUnitY(temp.u, temp.y)
        set loc=Location(temp.x, temp.y)
        set z=GetLocationZ(loc)
        set temp.height = temp.height - z
        call SetUnitFlyHeight(temp.u, temp.height-z, 0)
        if GetLocalPlayer()==temp.p then
            call PanCameraToTimed(temp.x-10*Cos(temp.facing), temp.y-10*Sin(temp.facing), 0)
            call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, 330, 0)
            call SetCameraField(CAMERA_FIELD_ROTATION, temp.facing * bj_RADTODEG, 0)
            call SetCameraField(CAMERA_FIELD_ZOFFSET, temp.height, 0)
        endif
        //call BJDebugMsg(R2S(GetUnitFlyHeight(temp.u)))
        //call BJDebugMsg(R2S(z))
        call RemoveLocation(loc)
        set i=i+1
    endloop
    set loc=null    
endfunction

//===========================================================================
private function init takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerAddAction(t, function actions)
    call TriggerRegisterTimerEvent(t, .04, true)
endfunction

endscope</i>


Try that.
 

Jonnycakes

New Member
Reaction score
6
Tried. Removing Deg2Rad for constants is a good suggestion, thanks. Setting temp.height==temp.height-z is a bad idea. Since the terrain (-z) is already accounted for while setting the unit's fly height and temp.height stores the unit's height disregarding terrain, introducing terrain height into that variable causes all sorts of awful things to happen (if the unit is flying on positive-height terrain, it flies lower incredibly fast, and vice versa).
 

Sevion

The DIY Ninja
Reaction score
413
In that case, this should work:

JASS:
scope moveloop initializer init

private function actions takes nothing returns nothing
    local integer i=0
    local unitdata temp
    local location loc
    local real z
    
    loop
        exitwhen i==playerstotal
        set temp=ud<i>
        set temp.velocity=temp.velocity+temp.accelleration
        if temp.velocity&lt;0 then
            set temp.velocity=0
            set temp.accelleration=0
        endif
        if temp.left and not temp.right then
            set temp.facing=temp.facing+.1
        elseif temp.right and not temp.left then
            set temp.facing=temp.facing-.1
        endif
        call SetUnitFacing(temp.u, temp.facing * bj_RADTODEG)
        set temp.x=GetUnitX(temp.u)
        set temp.y=GetUnitY(temp.u)
        if temp.up and not temp.down then
            set temp.height=temp.height+10
        elseif temp.down and not temp.up then
            set temp.height=temp.height-10
        endif
        set temp.x=temp.x+temp.velocity*Cos(temp.facing)
        set temp.y=temp.y+temp.velocity*Sin(temp.facing)
        call SetUnitX(temp.u, temp.x)
        call SetUnitY(temp.u, temp.y)
        set loc=Location(temp.x, temp.y)
        call SetUnitFlyHeight(temp.u, temp.height-GetLocationZ(loc), 0)
        if GetLocalPlayer()==temp.p then
            call PanCameraToTimed(temp.x-10*Cos(temp.facing), temp.y-10*Sin(temp.facing), 0)
            call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, 330, 0)
            call SetCameraField(CAMERA_FIELD_ROTATION, temp.facing * bj_RADTODEG, 0)
            call SetCameraField(CAMERA_FIELD_ZOFFSET, temp.height, 0)
        endif
        //call BJDebugMsg(R2S(GetUnitFlyHeight(temp.u)))
        //call BJDebugMsg(R2S(z))
        call RemoveLocation(loc)
        set i=i+1
    endloop
    set loc=null    
endfunction

//===========================================================================
private function init takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerAddAction(t, function actions)
    call TriggerRegisterTimerEvent(t, .04, true)
endfunction

endscope</i>
 

Jonnycakes

New Member
Reaction score
6
So...your solution is to remove the bit of code that enforces height restrictions? The only thing that your code did was to enable the unit to fly as high and low as the user wants (including below the ground). That is not where the problem is.
 
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