System Camera System with Mouse Detection

saw792

Is known to say things. That is all.
Reaction score
280
Camera System
By saw792

Code:
First Person Camera System v1.00                                         by saw792
//    -First person camera including: 
//        -Mouse controlled camera angle (uses trackables)
//        -Arrow key movement
//        -Lock to unit of your choice, or dummy created by system
//        -Can be modified to Third Person by changing a config global

Requirements:
Code:
-Requirements:
//        -A vJASS preprocessor (eg: JassHelper, Jass Newgen Pack)
//        -Dummy unit with no mode;, no attacks and locust model
//        -Trackable model (see import manager of test map)
//        -Preplaced rects for walkable areas (see below: Instructions)

Instructions:
Code:
-Instructions for use:
//        1. Convert two empty triggers to custom text, delete all text
//        2. Paste TrackableAPI library into one empty trigger
//        3. Paste FirstPerson library into the other empty trigger
//        4. Identify all areas on map that should be walkable by first person unit
//        5. Create rects in Rect Palette on the inside border of all walkable areas
//           NB: Remember! Trackables will only work if there is a clear line of site!
//               Keep this in mind when placing rects. The rect borders must be visible
//               to the unit in the area. Also, try to place borders between rects on
//               top of eachother to prevent areas with no trackable coverage
//        6. Rename all placed rects to FP1, FP2, FP3, FP4 etc (case sensitive)
//        7. Modify Config Global RECT_COUNT below to the number of rects placed
//        8. Modify Config Function RectInit to include a textmacro line for every
//               preplaced region (eg: for three rects, copy and paste the runtextmacro
//               line twice replacing the second "1" with "2" and the third "1" with "3"
//        9. Use custom script: call EnableFirstPersonForPlayer(player, locked unit,
//               x coordinate of dummy, y coordinate of dummy, boolean arrowkey)
//           NB: Use null for locked unit to use a dummy created by the system.
//               x and y have no effect when locked unit is not null
//           Example: Custom Script: call EnableFirstPersonForPlayer(Player(0), null, 0, 0, true)
//    -Credits to AceHart for arrow key template
//    -Credits to TheHelper members, who generally help with anything you need
//    -By saw792 (TheHelper.net, wc3campaigns.net, USWest)

How it works:
The system works by surrounding a set of preplaced regions with trackables at different heights forming four walls around it (not along the ground or the ceiling).. The camera is then locked to a unit within a region. When the mouse moves on the horizon it then is forced to track over a trackable. These track events are all recorded and the camera is adjusted each time based on the distance between the locked unit and the trackable and the angle (both vertical and horizontal angle, adjusting rotation and angle of attack). To allow smooth passing between regions with the arrow key movement the camera is not adjusted when within a certain range of the trackable wall.

The trackable model used is in the shape of a cube, so that the track events are counted from any angle. The density of trackables can be easily modified in the config globals.

A possible extension of this system involves using the hit events of the trackables (ie., when a trackable is clicked) to trigger a gunshot or some other event.

Entire Code:
JASS:
library TrackableAPI
//***************************************************************************
// Trackable API v2.00                          by saw792
//   -Credits to KaTTana for the basic system
//   -Credits to Vexorian for CheckPathability
//   -Modified CreateTrackableZ to include terrain height
//   -Modified CreateTrackableZ to automatically store
//      owner, x, y, and z coordinates
//   -Modified CreateTrackableZ to add event to global 
//      trigger for external use
//   -By saw792 (TheHelper.net, wc3campaigns.net, USWest)
//
//***************************************************************************

  globals
    private gamecache trackstore = InitGameCache("trackcache.w3v")
    trigger TrackTrigger = CreateTrigger()
  endglobals

  private function H2I takes handle h returns integer
    return h
    return 0
  endfunction

  private function SetTrackOwner takes trackable t, integer i returns nothing
    call StoreInteger(trackstore, I2S(H2I(t)), "owner", i)
  endfunction
  
  private function SetTrackableX takes trackable t, real x returns nothing
    call StoreReal(trackstore, I2S(H2I(t)), "x", x)
  endfunction

  private function SetTrackableY takes trackable t, real y returns nothing
    call StoreReal(trackstore, I2S(H2I(t)), "y", y)
  endfunction

  private function SetTrackableZ takes trackable t, real z returns nothing
    call StoreReal(trackstore, I2S(H2I(t)), "z", z)
  endfunction

  function GetTrackOwner takes trackable t returns player
    return Player(GetStoredInteger(trackstore, I2S(H2I(t)), "owner"))
  endfunction
  
  function GetTrackableX takes trackable t returns real
    return GetStoredReal(trackstore, I2S(H2I(t)), "x")
  endfunction

  function GetTrackableY takes trackable t returns real
    return GetStoredReal(trackstore, I2S(H2I(t)), "y")
  endfunction

  function GetTrackableZ takes trackable t returns real
    return GetStoredReal(trackstore, I2S(H2I(t)), "z")
  endfunction
  
  function CreateTrackableZ takes string path, real x, real y, real z, real face, player p returns trackable
      local location l = Location(x, y)
      local destructable d = CreateDestructableZ( 'OTip', x, y, GetLocationZ(l) + z, 0.00, 1, 0 )
      local trackable tr = CreateTrackable( path, x, y, face )
      call RemoveDestructable( d )
      call SetTrackableX(tr, x)
      call SetTrackableY(tr, y)
      call SetTrackableZ(tr, z)
      call SetTrackOwner(tr, GetPlayerId(p))
      call TriggerRegisterTrackableTrackEvent(TrackTrigger, tr)
      set d = null
      call RemoveLocation(l)
      set l = null
      return tr
  endfunction
  
  private function CheckPathabilityTrickGet takes nothing returns nothing
      set bj_rescueChangeColorUnit = bj_rescueChangeColorUnit or (GetEnumItem()!=bj_itemRandomCurrentPick)
  endfunction

  private function CheckPathabilityTrick takes item p, real x, real y returns boolean
      local integer i=30
      local rect r
      call SetItemPosition(p,x,y)
      if ((Pow(GetItemX(p)-x,2)+Pow(GetItemY(p)-y,2))<=100) then
          return true
      endif
      set r=Rect(x-i,y-i,x+i,y+i)
      set bj_itemRandomCurrentPick=p
      set bj_rescueChangeColorUnit=false
      call EnumItemsInRect(r,null,function CheckPathabilityTrickGet)
      call RemoveRect(r)
      set r=null
      return bj_rescueChangeColorUnit
  endfunction

  function CheckPathability takes real x, real y returns boolean
      local item it = CreateItem('ciri',x,y)
      local boolean b = CheckPathabilityTrick(it,x,y)
      call SetItemVisible(it,false)
      call RemoveItem(it)
      set it=null
      return b
  endfunction

endlibrary
JASS:
library FirstPerson initializer Init requires TrackableAPI
//******************************************************************************************
//    Config Globals
  globals
    //Rect globals
    private constant integer RECT_COUNT = 1 //Number of preplaced rects
    private constant integer TRACK_DENSITY = 25 //Number of trackables along each
                                                //side of a rect
    //Camera globals
    private constant real CAM_ZOOM = 100 //Change this to change the 'zoom' of the camera
    private constant real CAM_DISTANCE = 100 //Increase this to make a third person camera
                                             //Do not decrease below 100
    private constant real CAM_HEIGHT = 180 //Change to alter height off the ground
    private constant real CAM_MAX_HEIGHT = 400 //Maximum height of camera target
    private constant real CAM_MIN_ADJUST_DISTANCE = 300 //Minimum distance locked unit must be for cam to turn
    //Arrowkey globals
    private constant real ARROW_TIMER_RATE = 0.05 //Timer countdown for arrow key movement
    private constant real ARROW_MOVE_SPEED = 600 //Distance moved per second with arrow key held
    //Dummy unit globals
    private constant integer LOCKED_UNIT_CODE = 'h000' //Raw code of dummy unit. Used when no unit
                                                       //is set in the Enable function
    private constant string TRACK_PATH = "Cube.mdx" //Custom path of trackable model
  endglobals                                           
//     End Config Globals
  
//     Config Functions
  private function RectInit takes nothing returns nothing
    private keyword FPRect
    //! textmacro RectInit takes INTEGER
    set FPRect[$INTEGER$] = gg_rct_FP$INTEGER$
    //! endtextmacro
    //Copy this line for every preplaced rect you have made, changing the 1 to the appropriate integer.
    //! runtextmacro RectInit("1")
  endfunction
//     End Config Functions

//*******************************************************************************
//     Do not edit below here
//*******************************************************************************
  globals
    private trigger ArrowKeyUp = CreateTrigger()
    private trigger ArrowKeyDown = CreateTrigger()
    private trigger ArrowKeyLeft = CreateTrigger()
    private trigger ArrowKeyRight = CreateTrigger()
    private boolean array UpOn
    private boolean array DownOn
    private boolean array LeftOn
    private boolean array RightOn
    private keyword Track
    private Track array data
    private unit array dummy
    private rect array FPRect
  endglobals
  
  private struct Track
     
    private real x
    private real y
    private real z
    
    static method create takes player p returns Track
      local Track t = Track.allocate()
      local real minx
      local real maxx
      local real miny
      local real maxy
      local real lx
      local real ly
      local integer index = 0
      loop
        set index = index + 1
        exitwhen index >= RECT_COUNT + 1
        set minx = GetRectMinX(FPRect[index])
        set maxx = GetRectMaxX(FPRect[index])
        set miny = GetRectMinY(FPRect[index])
        set maxy = GetRectMaxY(FPRect[index])
        set lx = (maxx - minx) / TRACK_DENSITY
        set ly = (maxy - miny) / TRACK_DENSITY
        set t.z = 0
        loop
          set t.x = minx + 1
          set t.y = miny + 1
          set t.z = t.z + 50
          exitwhen t.z >= CAM_MAX_HEIGHT + 50
          loop
            exitwhen t.y >= maxy - 1
            set t.x = minx + 1
            call CreateTrackableZ(TRACK_PATH, t.x, t.y, t.z, 0, p)
            set t.x = maxx - 1
            call CreateTrackableZ(TRACK_PATH, t.x, t.y, t.z, 0, p)
            set t.y = t.y + ly
          endloop
          set t.y = miny + 1
          set t.x = minx + 1
          loop
            exitwhen t.x >= maxx - 1
            set t.y = miny + 1
            call CreateTrackableZ(TRACK_PATH, t.x, t.y, t.z, 0, p)
            set t.y = maxy - 1
            call CreateTrackableZ(TRACK_PATH, t.x, t.y, t.z, 0, p)
            set t.x = t.x + lx
          endloop
        endloop
        call TriggerSleepAction(0.00) //Included to prevent reaching loop limit
      endloop
      return t
    endmethod
    
  endstruct
  
  function EnableFirstPersonForPlayer takes player p, unit locked, real x, real y, boolean arrowkey returns nothing
    if data[GetPlayerId(p)] != null then
      call BJDebugMsg("Already enabled")
      return
    endif
    if locked == null then
      set dummy[GetPlayerId(p)] = CreateUnit(p, 'h000', x, y, 90)
    else
      set dummy[GetPlayerId(p)] = locked
      call SetUnitFacing(dummy[GetPlayerId(p)], 90)
    endif
    set data[GetPlayerId(p)] = Track.create(p)
    if IsTriggerEnabled(TrackTrigger) == false then
      call EnableTrigger(TrackTrigger)
      call FogEnableOff()
      call FogMaskEnableOff()
    endif
    if GetLocalPlayer() == p then
      call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, CAM_DISTANCE, 0)
      call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, -2.00, 0)
      call SetCameraField(CAMERA_FIELD_ZOFFSET, CAM_HEIGHT, 0)
      call SetCameraField(CAMERA_FIELD_FIELD_OF_VIEW, CAM_ZOOM, 0)
      call SetCameraTargetController(dummy[GetPlayerId(p)], 0, 0, false)
    endif
    if arrowkey then
      call TriggerRegisterPlayerEvent(ArrowKeyUp, p, EVENT_PLAYER_ARROW_UP_DOWN)
      call TriggerRegisterPlayerEvent(ArrowKeyDown, p, EVENT_PLAYER_ARROW_DOWN_DOWN)
      call TriggerRegisterPlayerEvent(ArrowKeyLeft, p, EVENT_PLAYER_ARROW_LEFT_DOWN)
      call TriggerRegisterPlayerEvent(ArrowKeyRight, p, EVENT_PLAYER_ARROW_RIGHT_DOWN)
      call TriggerRegisterPlayerEvent(ArrowKeyUp, p, EVENT_PLAYER_ARROW_UP_UP)
      call TriggerRegisterPlayerEvent(ArrowKeyDown, p, EVENT_PLAYER_ARROW_DOWN_UP)
      call TriggerRegisterPlayerEvent(ArrowKeyLeft, p, EVENT_PLAYER_ARROW_LEFT_UP)
      call TriggerRegisterPlayerEvent(ArrowKeyRight, p, EVENT_PLAYER_ARROW_RIGHT_UP)
      set UpOn[GetPlayerId(p)] = false
      set DownOn[GetPlayerId(p)] = false
      set LeftOn[GetPlayerId(p)] = false
      set RightOn[GetPlayerId(p)] = false
      if IsTriggerEnabled(ArrowKeyUp) == false then
        call EnableTrigger(ArrowKeyUp)
        call EnableTrigger(ArrowKeyDown)
        call EnableTrigger(ArrowKeyLeft)
        call EnableTrigger(ArrowKeyRight)
      endif
    endif
  endfunction
  
  private function ArrowUp takes nothing returns nothing
    set UpOn[GetPlayerId(GetTriggerPlayer())] = not UpOn[GetPlayerId(GetTriggerPlayer())]
  endfunction
  
  private function ArrowDown takes nothing returns nothing
    set DownOn[GetPlayerId(GetTriggerPlayer())] = not DownOn[GetPlayerId(GetTriggerPlayer())]
  endfunction
  
  private function ArrowLeft takes nothing returns nothing
    set LeftOn[GetPlayerId(GetTriggerPlayer())] = not LeftOn[GetPlayerId(GetTriggerPlayer())]
  endfunction
  
  private function ArrowRight takes nothing returns nothing
    set RightOn[GetPlayerId(GetTriggerPlayer())] = not RightOn[GetPlayerId(GetTriggerPlayer())]
  endfunction
  
  private function KeyActions takes nothing returns nothing
    local integer i = 0
    local real x
    local real y
    local real a
    loop
      set x = GetUnitX(dummy<i>)
      set y = GetUnitY(dummy<i>)
      set a = GetUnitFacing(dummy<i>) * bj_DEGTORAD
      if UpOn<i> then
        set x = x + (ARROW_MOVE_SPEED * ARROW_TIMER_RATE) * Cos(a)
        set y = y + (ARROW_MOVE_SPEED * ARROW_TIMER_RATE) * Sin(a)
        if CheckPathability(x, y) then
          call SetUnitX(dummy<i>, x)
          call SetUnitY(dummy<i>, y)
        endif
      endif
      if DownOn<i> then
        set a = a - bj_PI
        set x = x + (ARROW_MOVE_SPEED * ARROW_TIMER_RATE) * Cos(a)
        set y = y + (ARROW_MOVE_SPEED * ARROW_TIMER_RATE) * Sin(a)
        if CheckPathability(x, y) then
          call SetUnitX(dummy<i>, x)
          call SetUnitY(dummy<i>, y)
        endif
        set a = a + bj_PI
      endif
      if LeftOn<i> then
        set a = a + (bj_PI / 2)
        set x = x + (ARROW_MOVE_SPEED * ARROW_TIMER_RATE) * Cos(a)
        set y = y + (ARROW_MOVE_SPEED * ARROW_TIMER_RATE) * Sin(a)
        if CheckPathability(x, y) then
          call SetUnitX(dummy<i>, x)
          call SetUnitY(dummy<i>, y)
        endif
      endif
      if RightOn<i> then
        set a = a - (bj_PI / 2)
        set x = x + (ARROW_MOVE_SPEED * ARROW_TIMER_RATE) * Cos(a)
        set y = y + (ARROW_MOVE_SPEED * ARROW_TIMER_RATE) * Sin(a)
        if CheckPathability(x, y) then
          call SetUnitX(dummy<i>, x)
          call SetUnitY(dummy<i>, y)
        endif
      endif
      if GetLocalPlayer() == Player(i) then
        call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, CAM_DISTANCE, 0)
        call SetCameraField(CAMERA_FIELD_ZOFFSET, CAM_HEIGHT, 0)
        call SetCameraField(CAMERA_FIELD_FIELD_OF_VIEW, CAM_ZOOM, 0)
      endif
      set i = i + 1
      exitwhen i == 11
    endloop
  endfunction
  
  private function Actions takes nothing returns nothing
    local player p = GetTrackOwner(GetTriggeringTrackable())
    local real x = GetTrackableX(GetTriggeringTrackable())
    local real y = GetTrackableY(GetTriggeringTrackable())
    local real z = GetTrackableZ(GetTriggeringTrackable())
    local real x2 = GetUnitX(dummy[GetPlayerId(p)])
    local real y2 = GetUnitY(dummy[GetPlayerId(p)])
    local real z2 = 180
    local real dx = x - x2
    local real dy = y - y2
    local real d = SquareRoot(dx * dx + dy * dy)
    local real dz = z - z2
    local real a = Atan2BJ(dz, d)
    local real a2 = Atan2BJ(dy, dx)
    if d &lt; CAM_MIN_ADJUST_DISTANCE then
      return
    endif
    call SetUnitFacing(dummy[GetPlayerId(p)], a2)
    if GetLocalPlayer() == p then
        call SetCameraField(CAMERA_FIELD_ROTATION, a2, 0.5)
    endif
    if a &lt; -1 then
      set a = -1
    endif
    if GetLocalPlayer() == p then
      call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, a, 1)
    endif
    set p = null
  endfunction
  
  private function Init takes nothing returns nothing
    local timer t = CreateTimer()
    call DisableTrigger(TrackTrigger)
    call TriggerAddAction(TrackTrigger, function Actions)
    call RectInit()
    call TriggerAddAction(ArrowKeyUp, function ArrowUp)
    call TriggerAddAction(ArrowKeyDown, function ArrowDown)
    call TriggerAddAction(ArrowKeyLeft, function ArrowLeft)
    call TriggerAddAction(ArrowKeyRight, function ArrowRight)
    call DisableTrigger(ArrowKeyUp)
    call DisableTrigger(ArrowKeyDown)
    call DisableTrigger(ArrowKeyLeft)
    call DisableTrigger(ArrowKeyRight)
    call TimerStart(t, ARROW_TIMER_RATE, true, function KeyActions)
  endfunction

endlibrary</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>


Screenshots:
Coming Soon!

Pros:Mouse detection, awesome.
Cons:Lots of configuration

I would appreciate some feedback on how it runs in multiplayer, as I have been unable to test it with anybody else yet. All feedback is welcome.
 

Attachments

  • FirstPersonSystem.w3x
    30.4 KB · Views: 345

dannyboydude

Ultra Cool Member
Reaction score
33
I will be about 5 mins going to test in multiplayer but this is awesome


I remember one f your posts which said

It requires 3rd party software to do this and you said you would do it anyway

So congrats saw

You deserve a good pat on the back for the rest of your life
 

Vestras

Retired
Reaction score
248
I like it, but when getting close to the trees, the camera and arrow keys are totally fucked up.
 

saw792

Is known to say things. That is all.
Reaction score
280
Like... how. The idea is that the camera angles don't change when within 300 distance of the trackable (which currently is on the tree border.
 

dannyboydude

Ultra Cool Member
Reaction score
33
Dont know well 1 person joined and said get lost looser

And i was hosting it for like 10 mins and no one wanted to test it with me

Sory
 

saw792

Is known to say things. That is all.
Reaction score
280
lol thanks for trying. I'll test it at some stage. I fear it will lag like a b*tch though. Might find a replacement for gamecache when I get around to it.
 

Darthfett

Aerospace/Cybersecurity Software Engineer
Reaction score
615
It crashed when I tried to make the peasant build a town hall. I was also unable to see where the town hall was going to be built. : / The second is probably a problem that is with the wc3 engine, not your system though.

In the demo map, is it possible to lock the camera to a unit (so that I could test the system with it)?

If the camera is locked to a unit, how do the arrow keys work? The same? If it is the same, shouldn't it change something like the zoom, angle of attack, rotation, or something like that?

private constant real CAM_MAX_HEIGHT = 400 //Maximum height of camera target

Does this change how many trackables are created on the Z plane (so that the camera can actually go higher)?

Does your system create trackables along the ground, so that If I wanted to look down from a much higher camera, it would be possible? Is it possible to create a Z "ceiling", so that I could look up at flying units if I have a really low camera?

Overall, I thought it worked pretty well. :) The only other thing I can think of is to post information about what your system actually does for the trackables, rather than telling what it is supposed to do, so that people who want to modify it, understand what changing a few things here will do to the system without having to read every line and understand it.
 

saw792

Is known to say things. That is all.
Reaction score
280
Ah okay thanks for the comments Darthfett.

The camera is actually locked to a unit the whole time. You can specify what unit the camera should be locked to when calling the Enable function. If no unit is passed to the enable function an invisible dummy unit is created at the x and y that are passed to the enable function (x and y have no effect otherwise). The three other units outside the tree line aren't actually within the trackable field. I should move those inside so you can test locking units to them. The camera and arrow keys behave the same way when locked to a visible unit. The arrow keys are based on the facing angle of the locked unit, so the unit rotates as the camera rotates with mouse movement. When locked to a visible unit you may have to fiddle around with some of the config constants to get a camera angle that suits you.

CAM_MAX_HEIGHT does exactly what you have described. The trackables are created at z 50, then 100, then 150, etc up until the level reaches the value of that constant. The camera will be able to go higher if you set this to a higher value.

No trackables are currently created along the ground or as a ceiling, though this could be implemented quite easily. The code that creates the trackables is actually the create method of the struct in the FirstPerson library. You could easily modify this code to create these features, and I may add them in as config options in the future.

Any more bug reports are welcome. The building one intrigues me.

EDIT: It seems that if the entire screen is facing a wall of trackables the building target cannot be seen. This is something to do with the way the trackables function, in that if you hover your mouse over a trackable all targeting disappears. Then if you try and build while hovering over a trackable it tries to build on the trackable, or doesn't know where to build or something. I'll look into some solutions.
 

saw792

Is known to say things. That is all.
Reaction score
280
Any other comments / suggestions before I release the next version today sometime?
 

CaptDeath

New Member
Reaction score
103
can the camera be attached to a unit and not just flying around?
with the mouse pan its seems really nice
 

saw792

Is known to say things. That is all.
Reaction score
280
If you read the details you would see that it is always attached to a unit. Whether that unit is one that you specify or an invisible dummy unit is determined in the Enable function.
 

saw792

Is known to say things. That is all.
Reaction score
280
Hehe I forgot about this thread, sorry guys...

I'm afraid I won't be developing this any further as there are problems that make it unsuitable for a fair few situations. The problem is that you cannot target through a trackable, and issuing a build order while the mouse is hovering over a trackable causes a fatal error. Ah well, it seemed like a good idea at the time.
 

Ryuu

I am back with Chocolate (:
Reaction score
64
If you are still giving support, please help me with this.
I implemented this system into my map awhile ago, and did it successfully. However when I tested my map, the camera position was at another side of the map instead of my unit. When I shifted the camera back to my unit, none of your functions work. I can't move using arrow keys and and I can't move the camera using the mouse at all.
 

saw792

Is known to say things. That is all.
Reaction score
280
The system is enabled on a player by player basis, so you have to manually call the Enable function for each player you want to use it. If you have done this, please post your code and your config globals from my code and I'll have a look.
 

Ryuu

I am back with Chocolate (:
Reaction score
64
Sure. Here are the the globals:

JASS:
  globals
    //Rect globals
    private constant integer RECT_COUNT = 9 //Number of preplaced rects
    private constant integer TRACK_DENSITY = 25 //Number of trackables along each
                                                //side of a rect
    //Camera globals
    private constant real CAM_ZOOM = 100 //Change this to change the &#039;zoom&#039; of the camera
    private constant real CAM_DISTANCE = 400.09 //Increase this to make a third person camera
                                             //Do not decrease below 100
    private constant real CAM_HEIGHT = 180 //Change to alter height off the ground
    private constant real CAM_MAX_HEIGHT = 512 //Maximum height of camera target
    private constant real CAM_MIN_ADJUST_DISTANCE = 300 //Minimum distance locked unit must be for cam to turn
    //Arrowkey globals
    private constant real ARROW_TIMER_RATE = 0.03 //Timer countdown for arrow key movement
    private constant real ARROW_MOVE_SPEED = 600 //Distance moved per second with arrow key held
    //Dummy unit globals
    private integer LOCKED_UNIT_CODE          //Raw code of dummy unit. Used when no unit
                                                       //is set in the Enable function
    private constant string TRACK_PATH = &quot;Cube.mdx&quot; //Custom path of trackable model
  endglobals
 

Ryuu

I am back with Chocolate (:
Reaction score
64
Trigger:
  • Trigger
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set Unit = Footman 0001 &lt;gen&gt;
      • Custom script: call EnableFirstPersonForPlayer(Player(0), udg_Unit, 0, 0, true)
 
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