• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

[JASS] How does this script look?

Status
Not open for further replies.
Level 9
Joined
Jul 30, 2018
Messages
445
Hey!

I'm making a Camera system with sliders and it's working now and I don't have any problems, but because I am quite a noob what comes to JASS coding, I thought you guys should take a look. Just let me know if there are some oddities or if something could simply be done more cleverly or easier.

For example, is this a good way to use the GetLocalPlayer? Or would that cause desyncs?

Another question: what's the difference of scopes and libraries? When should one be used and why? I read libraries can't be nested, like making a child library, but scopes can. Is that the only difference? :p

JASS:
library CombinedCameraSliderSystem
    globals
        private framehandle sliderDistance
        private framehandle sliderDistanceLabel
        private framehandle sliderAngleOfAttack
        private framehandle sliderAngleOfAttackLabel
        private framehandle sliderRotation
        private framehandle sliderRotationLabel
        private framehandle sliderHeight
        private framehandle sliderHeightLabel
        private framehandle resetButton
     
        private framepointtype FRAMEPOINT_VERTICAL_MAIN
        private framepointtype FRAMEPOINT_VERTICAL_SECONDARY
        private framepointtype FRAMEPOINT_CORNER_MAIN
     
        private framepointtype FRAMEPOINT_CHECKBOX_MAIN
        private framepointtype FRAMEPOINT_CHECKBOX_SECONDARY
    endglobals
 
    function LoadToc takes string s returns nothing
        if not BlzLoadTOCFile(s) then
            call BJDebugMsg("|cffff0000Failed to Load: " + s + "|r \nYou need to import the |cffffcc00templates.toc|r file.")
        endif 
    endfunction

    function UpdateCam takes nothing returns nothing
        local unit u = udg_CCSS_TargetUnit[GetConvertedPlayerId(GetLocalPlayer())]
        call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, BlzFrameGetValue(sliderDistance), 0)
        call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, BlzFrameGetValue(sliderAngleOfAttack), 0)
        call SetCameraField(CAMERA_FIELD_ZOFFSET, BlzFrameGetValue(sliderHeight), 0)
     
        if (u != null) and (udg_CCSS_3rdPersonCamMode) then //Check if local player has a Target Unit and if 3rd Person Cam is allowed
            call SetCameraField(CAMERA_FIELD_ROTATION, GetUnitFacing(u), 0)
        else
            call SetCameraField(CAMERA_FIELD_ROTATION, BlzFrameGetValue(sliderRotation) + 90, 0) //+90 Because I want the default rotation angle (90) to be zero for simplicity's sake
        endif
     
        if (udg_CCSS_ShowValues) then
            call BlzFrameSetText(sliderDistanceLabel, "Distance: " + R2SW(BlzFrameGetValue(sliderDistance), 1, 1))
            call BlzFrameSetText(sliderAngleOfAttackLabel, "Angle: " + R2SW(BlzFrameGetValue(sliderAngleOfAttack), 1, 1))
            call BlzFrameSetText(sliderRotationLabel, "Rotation: " + R2SW(BlzFrameGetValue(sliderRotation), 1, 1))
            call BlzFrameSetText(sliderHeightLabel, "Height: " + R2SW(BlzFrameGetValue(sliderHeight), 1, 1))
        else
            call BlzFrameSetText(sliderDistanceLabel, "Distance")
            call BlzFrameSetText(sliderAngleOfAttackLabel, "Angle")
            call BlzFrameSetText(sliderRotationLabel, "Rotation")
            call BlzFrameSetText(sliderHeightLabel, "Height")
        endif
    endfunction

    function CreateSliders takes nothing returns nothing
        local real labelGap
        set sliderDistance = BlzCreateFrame("EscMenuSliderTemplate",  BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0, 0)
        set sliderDistanceLabel = BlzCreateFrame("EscMenuLabelTextTemplate",  sliderDistance, 0, 0)
        set sliderAngleOfAttack = BlzCreateFrame("EscMenuSliderTemplate",  BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0, 1)
        set sliderAngleOfAttackLabel = BlzCreateFrame("EscMenuLabelTextTemplate",  sliderAngleOfAttack, 0, 0)
        set sliderRotation = BlzCreateFrame("EscMenuSliderTemplate",  BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0, 2)
        set sliderRotationLabel = BlzCreateFrame("EscMenuLabelTextTemplate",  sliderRotation, 0, 0)
        set sliderHeight = BlzCreateFrame("EscMenuSliderTemplate",  BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0, 3)
        set sliderHeightLabel = BlzCreateFrame("EscMenuLabelTextTemplate",  sliderHeight, 0, 0)
     
        if (udg_CCSS_PositionSlidersX >= 8) then
            set udg_CCSS_PositionSlidersX = 0.8
        else
            if (udg_CCSS_PositionSlidersX < 0) then
                set udg_CCSS_PositionSlidersX = 0
            else
                set udg_CCSS_PositionSlidersX = udg_CCSS_PositionSlidersX / 10
            endif
        endif
        if (udg_CCSS_PositionSlidersY >= 6) then
            set udg_CCSS_PositionSlidersY = 0.6
        else
            if (udg_CCSS_PositionSlidersY < 0) then
                set udg_CCSS_PositionSlidersY = 0
            else
                set udg_CCSS_PositionSlidersY = udg_CCSS_PositionSlidersY / 10
            endif
        endif
     
        set udg_CCSS_SliderGap = udg_CCSS_SliderGap / 10
     
        if (udg_CCSS_AlignmentLeft) then
            set FRAMEPOINT_VERTICAL_MAIN = FRAMEPOINT_LEFT
            set FRAMEPOINT_VERTICAL_SECONDARY = FRAMEPOINT_RIGHT
            set FRAMEPOINT_CORNER_MAIN = FRAMEPOINT_TOPLEFT
            set labelGap = 0.005
        else
            set FRAMEPOINT_VERTICAL_MAIN = FRAMEPOINT_RIGHT
            set FRAMEPOINT_VERTICAL_SECONDARY = FRAMEPOINT_LEFT
            set FRAMEPOINT_CORNER_MAIN = FRAMEPOINT_TOPRIGHT
            set labelGap = -0.005
        endif

        //Distance Slider options
        call BlzFrameSetAbsPoint(sliderDistance, FRAMEPOINT_VERTICAL_MAIN, udg_CCSS_PositionSlidersX, udg_CCSS_PositionSlidersY)
        call BlzFrameSetPoint(sliderDistanceLabel, FRAMEPOINT_VERTICAL_MAIN, sliderDistance, FRAMEPOINT_VERTICAL_SECONDARY, labelGap, 0)
        call BlzFrameSetMinMaxValue(sliderDistance, udg_CCSS_DistanceMin, udg_CCSS_DistanceMax)
        call BlzFrameSetValue(sliderDistance, udg_CCSS_DistanceDefault)
        call BlzFrameSetStepSize(sliderDistance, udg_CCSS_DistanceStep)
        call BlzFrameSetEnable(sliderDistance, udg_CCSS_DistanceEnabled)
        call BlzFrameSetVisible(sliderDistance, false)

        //Angle of Attack Slider options
        call BlzFrameSetPoint(sliderAngleOfAttack, FRAMEPOINT_TOPLEFT, sliderDistance, FRAMEPOINT_BOTTOMLEFT, 0, -udg_CCSS_SliderGap)
        call BlzFrameSetPoint(sliderAngleOfAttackLabel, FRAMEPOINT_VERTICAL_MAIN, sliderAngleOfAttack, FRAMEPOINT_VERTICAL_SECONDARY, labelGap, 0)
        call BlzFrameSetMinMaxValue(sliderAngleOfAttack, udg_CCSS_AngleOfAttackMin, udg_CCSS_AngleOfAttackMax)
        call BlzFrameSetValue(sliderAngleOfAttack, udg_CCSS_AngleOfAttackDefault)
        call BlzFrameSetStepSize(sliderAngleOfAttack, udg_CCSS_AngleOfAttackStep)
        call BlzFrameSetEnable(sliderAngleOfAttack, udg_CCSS_AngleOfAttackEnabled)
        call BlzFrameSetVisible(sliderAngleOfAttack, false)
     
        //Rotation Slider options
        call BlzFrameSetPoint(sliderRotation, FRAMEPOINT_TOPLEFT, sliderAngleOfAttack, FRAMEPOINT_BOTTOMLEFT, 0, -udg_CCSS_SliderGap)
        call BlzFrameSetPoint(sliderRotationLabel, FRAMEPOINT_VERTICAL_MAIN, sliderRotation, FRAMEPOINT_VERTICAL_SECONDARY, labelGap, 0)
        call BlzFrameSetMinMaxValue(sliderRotation, udg_CCSS_RotationMin, udg_CCSS_RotationMax)
        call BlzFrameSetValue(sliderRotation, udg_CCSS_RotationDefault)
        call BlzFrameSetStepSize(sliderRotation, udg_CCSS_RotationStep)
        call BlzFrameSetEnable(sliderRotation, udg_CCSS_RotationEnabled)
        call BlzFrameSetVisible(sliderRotation, false)
     
        //Height Slider options
        call BlzFrameSetPoint(sliderHeight, FRAMEPOINT_TOPLEFT, sliderRotation, FRAMEPOINT_BOTTOMLEFT, 0, -udg_CCSS_SliderGap)
        call BlzFrameSetPoint(sliderHeightLabel, FRAMEPOINT_VERTICAL_MAIN, sliderHeight, FRAMEPOINT_VERTICAL_SECONDARY, labelGap, 0)
        call BlzFrameSetMinMaxValue(sliderHeight, udg_CCSS_HeightMin, udg_CCSS_HeightMax)
        call BlzFrameSetValue(sliderHeight, udg_CCSS_HeightDefault)
        call BlzFrameSetStepSize(sliderHeight, udg_CCSS_HeightStep)
        call BlzFrameSetEnable(sliderHeight, udg_CCSS_HeightEnabled)
        call BlzFrameSetVisible(sliderHeight, false)
    endfunction

    function ResetSliders takes nothing returns nothing
        if GetLocalPlayer() == GetTriggerPlayer() then
            call BlzFrameSetValue(sliderDistance, udg_CCSS_DistanceDefault)
            call BlzFrameSetValue(sliderAngleOfAttack, udg_CCSS_AngleOfAttackDefault)
            call BlzFrameSetValue(sliderRotation, udg_CCSS_RotationDefault)
            call BlzFrameSetValue(sliderHeight, udg_CCSS_HeightDefault)
        endif
     
        call BlzFrameSetEnable(BlzGetTriggerFrame(), false)
        call BlzFrameSetEnable(BlzGetTriggerFrame(), true)
    endfunction

    function CreateResetButton takes nothing returns nothing
        local trigger trig = CreateTrigger()
        set resetButton = BlzCreateFrame("ScriptDialogButton",  BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0, 0)
        set udg_CCSS_ResetButtonSizeX = udg_CCSS_ResetButtonSizeX / 10
        set udg_CCSS_ResetButtonSizeY = udg_CCSS_ResetButtonSizeY / 10
     
        call BlzFrameSetPoint(resetButton, FRAMEPOINT_CORNER_MAIN, sliderHeight, FRAMEPOINT_VERTICAL_MAIN, 0, -(udg_CCSS_SliderGap * 2))
        call BlzFrameSetSize(resetButton, udg_CCSS_ResetButtonSizeX, udg_CCSS_ResetButtonSizeY) 
        call BlzFrameSetText(resetButton, udg_CCSS_ResetButtonText)
        call BlzFrameSetVisible(resetButton, false)
     
        call TriggerAddAction(trig, function ResetSliders)
        call BlzTriggerRegisterFrameEvent(trig, resetButton, FRAMEEVENT_CONTROL_CLICK) 
    endfunction

    function CheckBoxLockSliders takes nothing returns nothing
        local boolean b = (BlzGetTriggerFrameEvent() == FRAMEEVENT_CHECKBOX_CHECKED)
        if GetLocalPlayer() == GetTriggerPlayer() then
            call BlzFrameSetVisible(sliderDistance, b)
            call BlzFrameSetVisible(sliderAngleOfAttack, b)
            call BlzFrameSetVisible(sliderRotation, b)
            call BlzFrameSetVisible(sliderHeight, b)
            call BlzFrameSetVisible(resetButton, b)
        endif 
    endfunction

    function CreateCheckbox takes nothing returns nothing
        local trigger trig = CreateTrigger()
        local framehandle fh = BlzCreateFrame("QuestCheckBox",  BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0, 3)
        local framehandle label = BlzCreateFrame("EscMenuLabelTextTemplate",  fh, 0, 3)
        local real labelGap
     
        if (udg_CCSS_PositionCheckBoxX >= 8) then
            set udg_CCSS_PositionCheckBoxX = 0.8
        else
            if (udg_CCSS_PositionCheckBoxX < 0) then
                set udg_CCSS_PositionCheckBoxX = 0
            else
                set udg_CCSS_PositionCheckBoxX = udg_CCSS_PositionCheckBoxX / 10
            endif
        endif
        if (udg_CCSS_PositionCheckBoxY >= 6) then
            set udg_CCSS_PositionCheckBoxY = 0.6
        else
            if (udg_CCSS_PositionCheckBoxY < 0) then
                set udg_CCSS_PositionCheckBoxY = 0
            else
                set udg_CCSS_PositionCheckBoxY = udg_CCSS_PositionCheckBoxY / 10
            endif
        endif
     
        if (udg_CCSS_CheckBoxTextOnLeft) then
            set FRAMEPOINT_CHECKBOX_MAIN = FRAMEPOINT_RIGHT
            set FRAMEPOINT_CHECKBOX_SECONDARY = FRAMEPOINT_LEFT
            set labelGap = -0.005
        else
            set FRAMEPOINT_CHECKBOX_MAIN = FRAMEPOINT_LEFT
            set FRAMEPOINT_CHECKBOX_SECONDARY = FRAMEPOINT_RIGHT
            set labelGap = 0.005
        endif
     
        call BlzFrameSetPoint(label, FRAMEPOINT_CHECKBOX_MAIN, fh, FRAMEPOINT_CHECKBOX_SECONDARY, labelGap, 0)
        call BlzFrameSetAbsPoint(fh, FRAMEPOINT_CHECKBOX_MAIN, udg_CCSS_PositionCheckBoxX, udg_CCSS_PositionCheckBoxY) 
        call BlzFrameSetText(label, udg_CCSS_CheckBoxText)
     
        call TriggerAddAction(trig, function CheckBoxLockSliders)
        call BlzTriggerRegisterFrameEvent(trig, fh, FRAMEEVENT_CHECKBOX_CHECKED)
        call BlzTriggerRegisterFrameEvent(trig, fh, FRAMEEVENT_CHECKBOX_UNCHECKED)
    endfunction
 
    function CreateCamControl takes nothing returns nothing
        call LoadToc("war3mapimported\\templates.toc")
        call CreateSliders()
        call CreateCheckbox()
        call CreateResetButton()
        call TimerStart(CreateTimer(), 0.05, true, function UpdateCam)
    endfunction
endlibrary

Edit:
I was now thinking that I could also pick all players in the update cam function and set the camera values for each player individually. This would solve the problem of using LocalPlayer like that, but how taxing would it be to pick and loop through all players every .05 seconds? I guess technically that shouldn’t be much different, since the code has to be run for each player anyway?
 
Last edited:
Level 20
Joined
May 16, 2012
Messages
635
- GetLocalPlayer() is the most commom cause for desyncs. Running code for just one player that takes effect to other units or parts of the map will cause the desync. I'm not sure for frames though, since they are only a visual action, but you can try it out by opening multiple instances of warcraft and hoping in a LAN created map with each one and see if desyncs happens.

- Libraries are usualy used when creating systems, since the functions you declare and code inside them can be called out of their scopes. Scopes are used to incapsulate stuff. This is not a JASS/vJASS only concept, actually its a
abstraction that you can google pretty easily.

- Your code looks alright, but i would change a few things, for example, you are still using global variables that were created using the GUI. Thats not necessary anymore since you can declare global blocks. You could also create a function to call the BlzSetFrame... set of functions, instead of repeating the all over again, reducing the amount of total code.
 
Level 9
Joined
Jul 30, 2018
Messages
445
Thanks for the reply!

- Yes, that's why I was wondering if that was a good way to use the GetLocalPlayer() so that the desyncs was most unlikely. However, I've now replaced it with a Player group pick loop, because it solved other problems as well, so I might as well get rid of LocalPlayer. (Although, it should work fine with frames, or at least has worked so far)

- Thanks, I'll dig into that a bit deeper. But looks like library was then a right choice for me.

- Yeah, that is because I want to have a GUI-friendly way to control the settings. If it wasn't clear already, it is indeed a system I planned for others to use, and I always liked systems can be used in GUI easily, so that's the reason why I use so much global variables declared in GUI.

(I ended up uploading the system already, so you can check the updated code, if you want. There's a link in my signature.)
 
Status
Not open for further replies.
Top