Jump to content
    1. Welcome to GTAForums!

    1. GTANet.com

    1. GTA Online

      1. Los Santos Drug Wars
      2. Updates
      3. Find Lobbies & Players
      4. Guides & Strategies
      5. Vehicles
      6. Content Creator
      7. Help & Support
    2. Red Dead Online

      1. Blood Money
      2. Frontier Pursuits
      3. Find Lobbies & Outlaws
      4. Help & Support
    3. Crews

    1. Grand Theft Auto Series

      1. Bugs*
      2. St. Andrews Cathedral
    2. GTA VI

    3. GTA V

      1. Guides & Strategies
      2. Help & Support
    4. GTA IV

      1. The Lost and Damned
      2. The Ballad of Gay Tony
      3. Guides & Strategies
      4. Help & Support
    5. GTA San Andreas

      1. Classic GTA SA
      2. Guides & Strategies
      3. Help & Support
    6. GTA Vice City

      1. Classic GTA VC
      2. Guides & Strategies
      3. Help & Support
    7. GTA III

      1. Classic GTA III
      2. Guides & Strategies
      3. Help & Support
    8. Portable Games

      1. GTA Chinatown Wars
      2. GTA Vice City Stories
      3. GTA Liberty City Stories
    9. Top-Down Games

      1. GTA Advance
      2. GTA 2
      3. GTA
    1. Red Dead Redemption 2

      1. PC
      2. Help & Support
    2. Red Dead Redemption

    1. GTA Mods

      1. GTA V
      2. GTA IV
      3. GTA III, VC & SA
      4. Tutorials
    2. Red Dead Mods

      1. Documentation
    3. Mod Showroom

      1. Scripts & Plugins
      2. Maps
      3. Total Conversions
      4. Vehicles
      5. Textures
      6. Characters
      7. Tools
      8. Other
      9. Workshop
    4. Featured Mods

      1. Design Your Own Mission
      2. OpenIV
      3. GTA: Underground
      4. GTA: Liberty City
      5. GTA: State of Liberty
    1. Rockstar Games

    2. Rockstar Collectors

    1. Off-Topic

      1. General Chat
      2. Gaming
      3. Technology
      4. Movies & TV
      5. Music
      6. Sports
      7. Vehicles
    2. Expression

      1. Graphics / Visual Arts
      2. GFX Requests & Tutorials
      3. Writers' Discussion
      4. Debates & Discussion
    1. Announcements

    2. Forum Support

    3. Suggestions

First CLEO script is working but needs optimization


Dteyn_
 Share

Recommended Posts

I've put together my first CLEO script over the last few days, and while the code is functioning well, I feel like it could be optimized.  I'm also new to CLEO scripting and may have missed some obvious things, and wanted to make sure my script won't break anything.

 

For some background, during a GTA:VC playthrough I found about 85 packages through natural means, then found another 14 with the help of an online guide.  Despite checking the list twice, I somehow could not locate the last package.  This was so frustrating, and I'm sure some of you can relate to this experience. :)

 

Of course, I realize there exist scripts to spawn 100 packages and can easily collect those to get to 100 packages collected, but I am stubborn and wanted to find that last package that I missed in my playthrough.  So I set about to create a CLEO script to help me with that.

 

Before starting, I envisioned a script that would highlight packages on the map that I had missed.  But I quickly discovered the game doesn't keep track of exactly which packages have been picked up, only how many out of the total # of packages defined.  So I had to settle on another approach.

 

After finding all the hidden package coords in main.scm, the first version of my script simply displayed the coords on the map in groups of 10, but after playtesting I felt it would work better as a mission where it moves from one package to the next. This allows for a methodical search and also to display some text for each package about where it can be located and how to access it (ie: if helicopter is required, etc).

 

The script I ended up creating is a Hidden Package mission that guides the player to all hidden packages on the map from #1 - #100 in sequence.  Checkpoints are created at each coord, along with a description on screen of where to find each package.  Once the player reaches the checkpoint, the next package is automatically highlighted.  The point of this script is to help a player locate packages they have missed, as in my case.

 

After much code cobbling it is working to my satisfaction, however as it's my first CLEO script, I'm sure it could be optimized.  Right now the list of packages is hard-coded, but if possible it would probably be better to have a file with a list of co-ordinates, and have some re-usable code that can cycle through that list.

 

One thing I'd like to add is a way to stop the mission once it's started.  Currently there is a way to skip packages, but no way to stop the mission without cycling through all the packages. I tried adding a nested if..then with another is_key_pressed opcode to exit the loop if an exit key is pressed, but can't seem to get the second key detection working.  I can either get "skip package" or "end mission" functionality working, but not both at the same time.  I'll admit my coding skills are a bit rusty so I may have overlooked something obvious.

 

I also added a warning to not save the game while this script is active.  I realize the blip created could be permanent if game is saved while it's active, so I added a warning when the mission is started to that effect.

 

Here is the code, I've truncated it down to 5 packages for brevity.  The source with 100 packages is about 54kb or so.

 

Spoiler


// Hidden Package Mission VC v0.5
// Mission to track down packages in order from #1 to #100
// Game: GTA Vice City
// Author: Dteyn
// Date: 2021-01-06
{$CLEO .cs}
{$USE ini}
0000:
0AF0: $BlipColor = get_int_from_ini_file "cleo\PackageMissionVC.ini" section "config" key "BlipColor"       // $BlipColor = Color of blip on map
0AF0: $StartKey = get_int_from_ini_file "cleo\PackageMissionVC.ini" section "config" key "StartKey"         // $StartKey = key for starting the mission
0AF0: $SkipKey = get_int_from_ini_file "cleo\PackageMissionVC.ini" section "config" key "SkipKey"           // $SkipKey = key for skipping a package
:pkgbegin
while true
    wait 0 ms
    if
        0AB0: key_pressed $StartKey    // Press to begin mission
    then
        jump @pkg1
    end 
end
:pkg1
03E5: print_help 'PKGSTRT' // Hidden Package Mission started. DO NOT SAVE while on mission!
00BC: print_now 'PKG1' 10000 ms 1 // Hidden Package #1 - Ocean Beach - On a wooden structure in the water. Access by boat or helicopter.
0189: add_blip_for_contact_point [email protected] -368.4 -1733.2 11.6
0165: change_blip_colour [email protected] color_to $BlipColor
:pkg1wait
if or
    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 -368.4 -1733.2 radius 4.0 4.0
    0AB0: key_pressed $SkipKey    // Press to skip package
then
    0164: remove_blip [email protected]
    jump @pkg2
end
wait 0
jump @pkg1wait
:pkg2
wait 200
00BC: print_now 'PKG2' 10000 ms 1 // Hidden Package #2 - Ocean Beach - On a rocky outcrop. Access by boat or helicopter.
0189: add_blip_for_contact_point [email protected] -213.01 -1647.11 13.1
0165: change_blip_colour [email protected] color_to $BlipColor
:pkg2wait
if or
    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 -213.01 -1647.11 radius 4.0 4.0
    0AB0: key_pressed $SkipKey    // Press to skip package
then
    0164: remove_blip [email protected]
    jump @pkg3
end
wait 0
jump @pkg2wait
:pkg3
wait 200
00BC: print_now 'PKG3' 10000 ms 1 // Hidden Package #3 - Ocean Beach - At the south steps of Lance Vance's house.
0189: add_blip_for_contact_point [email protected] = -104.3 -1600.3 10.4
0165: change_blip_colour [email protected] color_to $BlipColor
:pkg3wait
if or
    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 -104.3 -1600.3 radius 4.0 4.0
    0AB0: key_pressed $SkipKey    // Press to skip package
then
    0164: remove_blip [email protected]
    jump @pkg4
end
wait 0
jump @pkg3wait
:pkg4
wait 200
00BC: print_now 'PKG4' 10000 ms 1 // Hidden Package #4 - Ocean Beach - On the steps of the lighthouse.        
0189: add_blip_for_contact_point [email protected] = 479.6 -1718.5 15.6
0165: change_blip_colour [email protected] color_to $BlipColor
:pkg4wait
if or
    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 479.6 -1718.5 radius 4.0 4.0
    0AB0: key_pressed $SkipKey    // Press to skip package
then
    0164: remove_blip [email protected]
    jump @pkg5
end
wait 0
jump @pkg4wait
:pkg5
wait 200
00BC: print_now 'PKG5' 10000 ms 1 // Hidden Package #5 - Ocean Beach - NW corner of underground car park near Ocean Bay Marina.        
0189: add_blip_for_contact_point [email protected] = -172.4 -1341.3 3.9
0165: change_blip_colour [email protected] color_to $BlipColor
:pkg5wait
if or
    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 -172.4 -1341.3 radius 4.0 4.0
    0AB0: key_pressed $SkipKey    // Press to skip package
then
    0164: remove_blip [email protected]
    jump @pkg6
end
wait 0
jump @pkg5wait
:pkgdone
wait 200
03E5: print_help 'PKGEND' 10000 ms 1 // Hidden package mission ended.
jump @pkgbegin     // Wait for mission to be started again

 

 

PackageMissionVC.ini contents:

 

[config]
StartKey=50
SkipKey=51
BlipColor=4

 

 

PackageMissionVC.fxt contents:

 

PKGSTRT Hidden Package Mission started. DO NOT SAVE while on mission!
PKGEND Hidden Package Mission ended.
PKG1 Hidden Package #1 - Ocean Beach - On a wooden structure in the water. Access by boat or helicopter.
PKG2 Hidden Package #2 - Ocean Beach - On a rocky outcrop in the water. Access by boat or helicopter.
PKG3 Hidden Package #3 - Ocean Beach - At the south (rear) steps of Lance Vance's house.
PKG4 Hidden Package #4 - Ocean Beach - On the steps of the lighthouse at the SE corner of the beach.
PKG5 Hidden Package #5 - Ocean Beach - NW corner of underground car park near Ocean Bay Marina.

 


 

Link to comment
Share on other sites

6 hours ago, Dteyn_ said:

wanted to make sure my script won't break anything

Using custom global variable names in a cleo script will corrupt something, maybe it won't matter, but it could break the save, and would be hard to tell the difference without play testing everything. However, if you decompile your compiled script without using Sanny's special SCM Info the raw script should show you which global variable numbers your script highjacked. Then you could check how those variables are used in the main.scm script. Figure that all global variables are owned my main.scm. If you are writing a cleo script then you can only use global variables in context with main.scm. Normally, you can safely use the $Player_Char and $Player_Actor handles as expect, and change the $OnMission flag on and off as required. If you are messing with anything else then you'd better know what you are doing or something will break.

 

Setting $OnMission = 1 will prevent missions from starting, and save pickups are disabled until it's turned off.

 

You can fix your global variable issue by changing the global variables to local variables. Search and replace can do this quickly. Local variables can't be named like global variable, but the can be assigned to constants. So instead of, for example, replacing $BlipColor with [email protected], replace it with BlipColor, and assign the constants by defining them in your header - in this case, just before 0000: should do nicely.

const
  StartKey = [email protected]
  SkipKey = [email protected]
  BlipColor = [email protected]
end

 

Try adding your exit check after the skip check in it's own if..then..end construct - don't nest it.

 

As far as reorganizing goes... Don't fix what's not broken. Once you sort out a few bugs this script should be a very good guide in the context of starting a new game and collecting all the packages. Consider applying what you've learned to a more optimized script that can;

  • search game memory and identify the next currently available package, even on custom mains with modified package locations
  • attach the blip directly to the pickup so if the player saves the blip using a mod the blip will still get removed when the package is collected

The game memory part probably sounds intimidating, but if you are comfortable with algebra and aren't afraid of hexadecimal it isn't that hard to code. I'm not familiar with the details for VC; I usually mod SA. Shouldn't be hard to look up though.

Link to comment
Share on other sites

Thank you so much for your reply, this is exactly what I was hoping for.

 

13 hours ago, OrionSR said:

Using custom global variable names in a cleo script will corrupt something, maybe it won't matter, but it could break the save, and would be hard to tell the difference without play testing everything. However, if you decompile your compiled script without using Sanny's special SCM Info the raw script should show you which global variable numbers your script highjacked.

 

This is great to know, as a newbie I wasn't aware that using global variables is a no-no with cleo scripts.  I checked by decompiling and my script had hijacked $6, $7, and $8 which appear to be part of the stadium mission scripting in main.scm.  Glad to avoid this issue, I will take your suggestion of using constants and local variables instead.

 

It's also good to know about $OnMission, I'll definitely use that as well.  I'll also try your suggestion of creating a separate if..then..end construct for the "end mission" key.

 

My algebra skills haven't been put to the test in years, but I am comfortable with hexadecimal.  I like the idea of making a more advanced script in the event of custom mains, that would be a neat ability as well.  May consider pursuing this for additional challenge once I've completed v1.0.

 

Thanks again for your help and suggestions!  I will be sure to reply back if I have more questions and will also post a link to the completed script in this thread once it's published.

Link to comment
Share on other sites

  • 3 weeks later...

I've completed most of the code changes I had planned for v1.0 and it's nearly ready to publish.  I have thoroughly playtested this, but there may still be things I have missed. 

 

I'm hoping that I haven't done anything that will break a save game.  I did read the CLEO scripting tutorial by ZAZ which was helpful in understanding a few things.

 

I have implemented many changes since my last post:

  • using only local variables instead of global variables
  • using $OnMission and also checking to ensure it's not set before starting my script
  • using opcode 048C to detect whether a package has been picked up and skip automatically
  • can now stop guide at any point using ToggleKey as defined in .ini file
  • cleaned up formatting and commented a lot of code

I'm currently quite happy with how everything is working and am hoping to release v1.0 soon, provided there aren't any glaring game breaking bugs left that I have missed.

 

Below is the current source with packages 6-100 removed for brevity.

 

Spoiler


// Hidden Package Guide VC v0.9
// Mission to track down packages in order from #1 to #100
// Game: GTA Vice City
// Author: Dteyn
// Date: 2021-01-22
{$CLEO .cs}
{$USE ini}

const
    BlipColor = [email protected]
    ToggleKey = [email protected]
    SkipKey = [email protected]
    PkgCheck = [email protected]
    BlipScale = 2.0
    WaitPkgPU = 500
    PkgMsgDelay = 10000
end

0000: nop       
03A4: name_thread 'HPACK'                   // Name thread

// Get settings from ini file
0AF0: BlipColor = get_int_from_ini_file "cleo\PackageGuideVC.ini" section "config" key "BlipColor"       // BlipColor = Color of blip on map
0AF0: ToggleKey = get_int_from_ini_file "cleo\PackageGuideVC.ini" section "config" key "ToggleKey"       // ToggleKey = key for toggling the mission on or off
0AF0: SkipKey = get_int_from_ini_file "cleo\PackageGuideVC.ini" section "config" key "SkipKey"           // SkipKey = key for skipping a package
0AF0: PkgCheck = get_int_from_ini_file "cleo\PackageGuideVC.ini" section "config" key "PkgCheck"         // PkgCheck = whether to check if packages picked up


:pkgbegin
while true
    wait 0 ms
    if
        0AB0: key_pressed ToggleKey        // Activate when ToggleKey is pressed
    then    
        if
            $OnMission == 0                // OnMission check
        then           
            $OnMission = 1                 // Set OnMission flag
            03E5: print_help 'PKGSTRT'     // Hidden Package Guide started.
            jump @pkg1pre
        end
    end 
end

// ==============================     PACKAGE #1     ==============================
:pkg1pre
if
    PkgCheck == true                                    // If PkgCheck is enabled, perform a check
then
    jump @pkg1ck                                        
else
    jump @pkg1                                          
end    
:pkg1ck
if
    048C: is_any_pickup_at_coords -368.4 -1733.2 11.6   // Check coords to see if package is present
then
    jump @pkg1                                          // If so, display location
else
    00BC: print_now 'PKG1P' WaitPkgPU ms 1              // If not, print 'Hidden Package already picked up'
    wait WaitPkgPU 
    jump @pkg2pre                                       // and go to next package
end
:pkg1 
00BC: print_now 'PKG1' PkgMsgDelay ms 1                 // Display priority text with package location details
018A: add_blip_for_coord [email protected] -368.4 -1733.2 11.6         // Add blip
0165: change_blip_colour [email protected] color_to BlipColor          // Change blip color
03BC: add_shere [email protected] -368.4 -1733.2 11.6 scale BlipScale  // Add sphere
wait 500  // Wait 500 ms to prevent toggle end mission keypress from activating
:pkg1wait
if
    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 -368.4 -1733.2 radius BlipScale BlipScale  // When near package
then
    0164: remove_blip [email protected]                                // Remove blip
    03BD: remove_sphere [email protected]                              // Remove sphere
    jump @pkg2pre                                       // And move to next package
end
if
    0AB0: key_pressed SkipKey                           // If SkipKey is pressed
then
    03E5: print_help 'PKGSKIP'                          // Hidden package skipped
    0164: remove_blip [email protected]                                // Remove blip
    03BD: remove_sphere [email protected]                              // Remove sphere
    jump @pkg2pre                                       // And move to next package
end
if
    0AB0: key_pressed ToggleKey                         // End mission if ToggleKey is pressed
then
    jump @pkgdone
end
wait 0                                                  // Loop
jump @pkg1wait


// ==============================     PACKAGE #2     ==============================
:pkg2pre
wait 200
if
    PkgCheck == true                                    // If PkgCheck is enabled, perform a check
then
    jump @pkg2ck
else
    jump @pkg2
end    
:pkg2ck
if
    048C: is_any_pickup_at_coords -213.0 -1647.1 13.1   // Check coords to see if package is present
then
    jump @pkg2                                          // If so, display location
else
    00BC: print_now 'PKG2P' WaitPkgPU ms 1              // If not, print 'Hidden Package already picked up'
    wait WaitPkgPU 
    jump @pkg3pre                                       // and go to next package
end
:pkg2 
00BC: print_now 'PKG2' PkgMsgDelay ms 1                 // Display priority text with package location details
018A: add_blip_for_coord [email protected] -213.0 -1647.1 13.1         // Add blip
0165: change_blip_color [email protected] color_to BlipColor           // Change blip color
03BC: add_shere [email protected] -213.0 -1647.1 13.1 scale BlipScale  // Add sphere
:pkg2wait
if
    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 -213.0 -1647.1 radius BlipScale BlipScale  // When near package
then
    0164: remove_blip [email protected]                                // Remove blip
    03BD: remove_sphere [email protected]                              // Remove sphere
    jump @pkg3pre                                       // And move to next package
end
if
    0AB0: key_pressed SkipKey                           // If SkipKey is pressed
then
    03E5: print_help 'PKGSKIP'                          // Hidden package skipped
    0164: remove_blip [email protected]                                // Remove blip
    03BD: remove_sphere [email protected]                              // Remove sphere
    jump @pkg3pre                                       // And move to next package
end
if
    0AB0: key_pressed ToggleKey                         // End mission if ToggleKey is pressed
then
    jump @pkgdone
end
wait 0
jump @pkg2wait                                          // Loop


// ==============================     PACKAGE #3     ==============================
:pkg3pre
wait 200
if
    PkgCheck == true                                    // If PkgCheck is enabled, perform a check
then
    jump @pkg3ck
else
    jump @pkg3
end    
:pkg3ck
if
    048C: is_any_pickup_at_coords -104.3 -1600.3 10.4   // Check coords to see if package is present
then
    jump @pkg3                                          // If so, display location
else
    00BC: print_now 'PKG3P' WaitPkgPU ms 1              // If not, print 'Hidden Package already picked up'
    wait WaitPkgPU 
    jump @pkg4ck                                        // and go to next package
end
:pkg3 
00BC: print_now 'PKG3' PkgMsgDelay ms 1                 // Display priority text with package location details
018A: add_blip_for_coord [email protected] -104.3 -1600.3 10.4         // Add blip
0165: change_blip_color [email protected] color_to BlipColor           // Change blip color
03BC: add_shere [email protected] -104.3 -1600.3 10.4 scale BlipScale  // Add sphere
:pkg3wait
if
    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 -104.3 -1600.3 radius BlipScale BlipScale  // When near package
then
    0164: remove_blip [email protected]                                // Remove blip
    03BD: remove_sphere [email protected]                              // Remove sphere
    jump @pkg4pre                                       // And move to next package
end
if
    0AB0: key_pressed SkipKey                           // If SkipKey is pressed
then
    03E5: print_help 'PKGSKIP'                          // Hidden package skipped
    0164: remove_blip [email protected]                                // Remove blip
    03BD: remove_sphere [email protected]                              // Remove sphere
    jump @pkg4pre                                       // And move to next package
end
if
    0AB0: key_pressed ToggleKey                         // End mission if ToggleKey is pressed
then
    jump @pkgdone
end
wait 0
jump @pkg3wait                                          // Loop


// ==============================     PACKAGE #4     ==============================
:pkg4pre
wait 200
if
    PkgCheck == true                                    // If PkgCheck is enabled, perform a check
then
    jump @pkg4ck
else
    jump @pkg4
end    
:pkg4ck
if
    048C: is_any_pickup_at_coords 479.6 -1718.5 15.6    // Check coords to see if package is present
then
    jump @pkg4                                          // If so, display location
else
    00BC: print_now 'PKG4P' WaitPkgPU ms 1              // If not, print 'Hidden Package already picked up'
    wait WaitPkgPU 
    jump @pkg5pre                                       // and go to next package
end
:pkg4 
00BC: print_now 'PKG4' PkgMsgDelay ms 1                 // Display priority text with package location details
018A: add_blip_for_coord [email protected] 479.6 -1718.5 15.6          // Add blip
0165: change_blip_color [email protected] color_to BlipColor           // Change blip color
03BC: add_shere [email protected] 479.6 -1718.5 15.6 scale BlipScale   // Add sphere
:pkg4wait
if
    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 479.6 -1718.5 radius BlipScale BlipScale  // When near package
then
    0164: remove_blip [email protected]                                // Remove blip
    03BD: remove_sphere [email protected]                              // Remove sphere
    jump @pkg5pre                                       // And move to next package
end
if
    0AB0: key_pressed SkipKey                           // If SkipKey is pressed
then
    03E5: print_help 'PKGSKIP'                          // Hidden package skipped
    0164: remove_blip [email protected]                                // Remove blip
    03BD: remove_sphere [email protected]                              // Remove sphere
    jump @pkg5pre                                       // And move to next package
end
if
    0AB0: key_pressed ToggleKey                         // End mission if ToggleKey is pressed
then
    jump @pkgdone
end
wait 0
jump @pkg4wait                                          // Loop


// ==============================     PACKAGE #5     ==============================
:pkg5pre
wait 200
if
    PkgCheck == true                                    // If PkgCheck is enabled, perform a check
then
    jump @pkg5ck
else
    jump @pkg5
end    
:pkg5ck
if
    048C: is_any_pickup_at_coords -172.4 -1341.3 3.9   // Check coords to see if package is present
then
    jump @pkg5                                         // If so, display location
else
    00BC: print_now 'PKG5P' WaitPkgPU ms 1             // If not, print 'Hidden Package already picked up'
    wait WaitPkgPU 
    jump @pkg6pre                                      // and go to next package
end                                                    
:pkg5 
00BC: print_now 'PKG5' PkgMsgDelay ms 1                // Display priority text with package location details
018A: add_blip_for_coord [email protected] -172.4 -1341.3 3.9         // Add blip
0165: change_blip_color [email protected] color_to BlipColor          // Change blip color
03BC: add_shere [email protected] -172.4 -1341.3 3.9 scale BlipScale  // Add sphere
:pkg5wait
if
    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 -172.4 -1341.3 radius BlipScale BlipScale  // When near package
then
    0164: remove_blip [email protected]                                // Remove blip
    03BD: remove_sphere [email protected]                              // Remove sphere
    jump @pkg6pre                                       // And move to next package
end
if
    0AB0: key_pressed SkipKey                           // If SkipKey is pressed
then
    03E5: print_help 'PKGSKIP'                          // Hidden package skipped
    0164: remove_blip [email protected]                                // Remove blip
    03BD: remove_sphere [email protected]                              // Remove sphere
    jump @pkg6pre                                       // And move to next package
end
if
    0AB0: key_pressed ToggleKey                         // End mission if ToggleKey is pressed
then
    jump @pkgdone
end
wait 0
jump @pkg5wait                                          // Loop

:pkg6pre    // snipped 6-100

:pkgdone
0164: remove_blip [email protected]                                    // Remove blip
03BD: remove_sphere [email protected]                                  // Remove sphere
00BE: clear_prints                                      // Clear any on-screen text
$OnMission = 0                                          // Clear OnMission flag
wait 200
03E5: print_help 'PKGEND'                               // Hidden Package Guide ended.
jump @pkgbegin                                          // Wait for mission to be started again

 

 

Here is the new .fxt file:

 

PKGSTRT Hidden Package Guide started.
PKGEND Hidden Package Guide stopped.
PKGSKIP Hidden Package skipped.
PKG1 Hidden Package #1 - Ocean Beach - On a wooden structure in the water. Access by boat or helicopter.
PKG2 Hidden Package #2 - Ocean Beach - On a rocky outcrop in the water. Access by boat or helicopter.
PKG3 Hidden Package #3 - Ocean Beach - At the south (rear) steps of Lance Vance's house.
PKG4 Hidden Package #4 - Ocean Beach - On the steps of the lighthouse at the SE corner of the beach.
PKG5 Hidden Package #5 - Ocean Beach - NW corner of underground car park near Ocean Bay Marina.
PKG1P Hidden Package #1 already picked up.
PKG2P Hidden Package #2 already picked up.
PKG3P Hidden Package #3 already picked up.
PKG4P Hidden package #4 already picked up.
PKG5P Hidden package #5 already picked up.

 

 

And the latest PackageGuideVC.ini file:

 

// Config file for Hidden Package Guide

// NOTE: To redefine keys, use decimal keycode values from this link:
// https://www.indigorose.com/webhelp/ams/Program_Reference/Misc/Virtual_Key_Codes.htm

// ToggleKey = key for toggling the mission on/off
// SkipKey = key for skipping a package
// PkgCheck = whether to check for packages being picked up. set to 0 to guide to all locations
// BlipColor = set the color of the radar blips, values 0-6 as below
//   0 = red
//   1 = green
//   2 = blue
//   3 = white
//   4 = yellow
//   5 = purple
//   6 = cyan

[config]
ToggleKey=50
SkipKey=51
BlipColor=4
PkgCheck=1


 

Link to comment
Share on other sites

2 hours ago, Dteyn_ said:

I'm currently quite happy with how everything is working and am hoping to release v1.0 soon, provided there aren't any glaring game breaking bugs left that I have missed.

This version looks a lot better. Nice work. I don't see any game breaking issues, but I do have a few comments, and ideas you can use in future projects. I'll work though a few suggestions as I look for more serious issues.

 

0000: nop       
03A4: name_thread 'HPACK'                   // Name thread

The hard rule is that cleo scripts can't jump to a 0 offset - you can't start the script with a label. The general rule is to start with a NOP in a cleo script that will execute and terminate, and name the thread if it'll continue to run in a loop. Naming the thead/script allows the script to be terminated by other scripts, or the script offset to be identified by cleo opcodes, using the name as a handle.

 

const
  [email protected] = hBlip // BlipHandle
  [email protected] = hSphere // SphereHandle
end

I really like how you used constants in this script to make it easy to read. Many of your comments are hardly needed. But you may as well go all in and define them all.

 

What happens if your script can't find it's INI file? This is an issue in my current project as well; I'm not sure what happens. Either way, I have been considering a strategy to create a default INI if none is found. Not sure what it'll look like just yet.

 

            03E5: print_help 'PKGSTRT'     // Hidden Package Guide started.

Be aware that Cleo offers opcodes to add "dynamic" gxt strings, and to print "formatted" custom text, as an alternative to using FXT files. However, considering the length and number of strings required for a hidden package guide, offloading the strings to an FXT file will shorten the total size of the script considerably. I wouldn't suggest any changes to the current strategy.

 

    048C: is_any_pickup_at_coords -368.4 -1733.2 11.6   // Check coords to see if package is present

Awesome find and use of this opcode. Have you considered using it in place of:

    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 479.6 -1718.5 radius BlipScale BlipScale  // When near package

 

As I mentioned before, I would not recommend making large scale changes to a working script. But this script does present an excellent example for suggestions on how to optimize future projects. 

 

gosub..return is a powerful tool for organizing scripts. When gosub @label is called, execution will jump to a subroutine at that label, and when a Return is encountered execution resumes at the command follow the gosub. An easy example for you script would look something like this:

const
  [email protected] = X_Coord
  [email protected] = Y_Coord
  [email protected] = Z_Coord
  [email protected] = PKGHINT 
  [email protected] = PKGPICD 
end
{...}

:pkg1pre
gosub @Package_Data_1
{...}

:Package_Data_1
//048C: is_any_pickup_at_coords -368.4 -1733.2 11.6   // Check coords to see if package is present
X_Coord = -368.4
Y_Coord = -1733.2
Z_Coord = 11.6
PKGHINT = 'PKG1'
PKGPICD = 'PKG1P'
return

:Package_Data_2
{...}

Then many codes would be more generic, easier to edit.

048C: is_any_pickup_at_coords X_Coord Y_Coord Z_Coord
00BC: print_now PKGPICD WaitPkgPU ms 1              // If not, print 'Hidden Package already picked up'
00BC: print_now PKGHINT PkgMsgDelay ms 1            // Display priority text with package location details
018A: add_blip_for_coord hBlip X_Coord Y_Coord Z_Coord
0165: change_blip_colour hBlip color_to BlipColor
03BC: add_shere hSphere X_Coord Y_Coord Z_Coord scale BlipScale
00E3: locate_player_any_means_2d $PLAYER_CHAR 0 X_Coord Y_Coord radius BlipScale BlipScale

 

From there... There would definitely be some problems with the logic flow of the script, particularly the exit strategy, but you would be really close changing your Package 1 segment into a generic :Do_Package_Stuff subroutine, and dumping segments for 2 through 100. The main body of the script would look something like:

gosub @Package_Data_1
gosub @Do_Package_Stuff

gosub @Package_Data_2
gosub @Do_Package_Stuff

gosub @Package_Data_3
gosub @Do_Package_Stuff

 

Hopefully these examples illustrate how subroutines can help optimize a script so it's easier to write and edit. But for this script, you have finished writing and editing, so the changes are not necessary.

Link to comment
Share on other sites

Thanks for the kind words, and for the informative reply.  It's hugely appreciated. 🙂

 

12 hours ago, OrionSR said:

The hard rule is that cleo scripts can't jump to a 0 offset - you can't start the script with a label. The general rule is to start with a NOP in a cleo script that will execute and terminate, and name the thread if it'll continue to run in a loop. Naming the thead/script allows the script to be terminated by other scripts, or the script offset to be identified by cleo opcodes, using the name as a handle.

 

My main purpose for this was that I want to leave the thread running in case the user wants to restart the guide to check for any packages they may have skipped over.  At the end I just have it jump back to the while..end loop and wait for another keypress to restart the guide.  If I read your comment correctly, it sounds like this is functioning as intended.

 

I took your advice and went all-in on the constants for the other local variables.  It sure does make it lot easier to read.  I also like that using the constants allows for easier tweaking of the hardcoded values such as the BlipScale or Wait delays, it's nice to have those all in one spot for quick editing.

 

12 hours ago, OrionSR said:
    048C: is_any_pickup_at_coords -368.4 -1733.2 11.6   // Check coords to see if package is present

Awesome find and use of this opcode. Have you considered using it in place of:

    00E3: locate_player_any_means_2d $PLAYER_CHAR 0 479.6 -1718.5 radius BlipScale BlipScale  // When near package

 

 

I was super excited when I stumbled across opcode 048C, it happened to catch my eye as I was scrolling through the Sanny Builder library and am sure glad I spotted it.  Prior to using this opcode, the script would direct the player to each location to check if the package had been picked up which was very time-consuming.  With this opcode it's greatly simplified the process, it just scans and tells you which packages still need picking up instead of blindly guiding the player to all locations.

 

The 00E3 opcode was originally chosen so that the next package could be triggered with a helicopter flyover, as before I found 048C that was my primary way of going around and checking each package location.  Using 00E3 to locate the player by 2d made it so I could just fly over any checkpoints to trigger the next one.

 

During playtesting though I realized 00E3 wasn't ideal for some packages where the player is able to walk above/below the package while attempting to retrieve it.  For those packages, I changed to opcode 00F5 locate_player_by_any_means_3d so that the trigger sphere must be walked into, to prevent accidental early triggering by walking above or below.

 

With all that said, your idea of re-using 048C as the check seems like the best option, as opposed to using the locate_player opcodes.  I hadn't considered this until you mentioned it, if I do any more re-writes on this script I'll be sure to keep that in mind.

 

12 hours ago, OrionSR said:

this script does present an excellent example for suggestions on how to optimize future projects

 

I really appreciate your suggestions on how to further optimize the code. The gosub...return construct is something that definitely intrigues me, I would have loved to implement it that way as it would have greatly simplified the editing of the script and made for a cleaner approach.  I will keep this in mind for future projects, the example framework you've provided is extremely helpful in this regard. Thank you for that.

 

With a bit more playtesting I should be ready to publish this.  I will post a link here once it's been uploaded.  Thanks once again for your help, this is a great community and I'm glad I came here to have this discussion. 🙂

Link to comment
Share on other sites

13 hours ago, OrionSR said:

What happens if your script can't find it's INI file?

 

Also - good point about this.

 

To solve this I have implemented a check through a setting in the INI file itself (INISettings=1).  If the INI file is present, the setting will be read and the value will be true, and the INI settings are then read in and used.  If the INI file is not present, that setting doesn't simply get read in and the script knows to use some default failsafe values instead of reading the INI file.

 

 

// Check if INI file is present
0AF0: INISettings = get_int_from_ini_file "cleo\PackageGuideVC.ini" section "config" key "INISettings"       // INISettings = set to 1 to use settings from INI

if
    INISettings == true
then
    // Get settings from ini file
    0AF0: BlipColor = get_int_from_ini_file "cleo\PackageGuideVC.ini" section "config" key "BlipColor"       // BlipColor = Color of blip on map
    0AF0: ToggleKey = get_int_from_ini_file "cleo\PackageGuideVC.ini" section "config" key "ToggleKey"       // ToggleKey = key for toggling the mission on or off
    0AF0: SkipKey = get_int_from_ini_file "cleo\PackageGuideVC.ini" section "config" key "SkipKey"           // SkipKey = key for skipping a package
    0AF0: PkgCheck = get_int_from_ini_file "cleo\PackageGuideVC.ini" section "config" key "PkgCheck"         // PkgCheck = whether to check if packages picked up
else
    // Use default values below if INI is not present, or if INISettings is set to 0
    BlipColor = 5   // BlipColor = purple by default
    ToggleKey = 50  // ToggleKey = '2' by default
    SkipKey = 51    // SkipKey = '3' by default
    PkgCheck = 1    // Enable PkgCheck by default to skip packages already picked up
end 

 

I have tested this and it seems to be working as intended.

 

 

 

Link to comment
Share on other sites

To clarify, including the NOP isn't necessary. The thread name serves the same purpose. Personally, I usually start with wait 3000. It helps isolate crashes caused by the script from other issues.

 

31 minutes ago, Dteyn_ said:

With all that said, your idea of re-using 048C as the check seems like the best option

BTW, this isn't always clarified in the documentation but, if it works out better for the logic you require, you can change any conditional command to a not statement by changing the 0 at the start of the opcode to 8. A not should be added to the statement for clarification.

848C:  not is_any_pickup_at_coords -368.4 -1733.2 11.6   // Check coords to see if package is not present

 

48 minutes ago, Dteyn_ said:

The gosub...return construct is something that definitely intrigues me, I would have loved to implement it that way as it would have greatly simplified the editing of the script and made for a cleaner approach.

Yeah, but... Would you have appreciated the value of subroutines if you hadn't worked through a long version of the script?  Figure that any time you find yourself coding pretty much the same thing over and over then there is probably a better way. And that strategy could still be applied to the main-body and Package_Data subroutines I suggested. Those sections repeat mostly the same codes; isn't there a better way?

 

The answer is, Yes, but... Yes, all of the x,y,z coords and gxt keys could be loaded into arrays. A for..end loop can be used to cycle the index of the arrays. But... The problem with this strategy is that it would require 700 variables to hold all the data. Without access to large blocks of free global variables, or custom missions, there simply aren't enough variables to go around. So in this example, the repeated codes are simply a way to get around the limit of having only 16 local variables available in VC scripts.

 

 I like your solution to the missing INI issue. I may borrow that strategy if I can't figure out how to create a new default INI. I've only recently started messing with cleo's file commands; your examples made INIs look so easy I decided to give it a try. Creating a new INI with cleo is mostly a chance to try out some more new commands.

 

Again, nice work on the script. I'm a little disappointed that I don't have a way to try it out.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • 1 User Currently Viewing
    0 members, 0 Anonymous, 1 Guest

×
×
  • Create New...

Important Information

By using GTAForums.com, you agree to our Terms of Use and Privacy Policy.