Hands-on: Checkpoint Hunt
Let’s put arrays to work in a playable mini-game. The script will place 3 checkpoints around the player. The player can collect them in any order. Once all three are collected, the script rewards the player with a cash bonus.
Here’s the final script:
{$CLEO .cs}nop
const REWARD = 5000const NUM = 3int last_index = NUM - 1
// read the player's current position as a base pointfloat base[3]...base = get_char_coordinates $scplayer
// generate checkpoint positions around the playerfloat cx[NUM]float cy[NUM]float cz[NUM]
int ifor i = 0 to last_index float xoffset = generate_random_float_in_range {min} -25.0 {max} 25.0 float yoffset = generate_random_float_in_range {min} -25.0 {max} 25.0 cx[i] = base[0] cx[i] += xoffset cy[i] = base[1] cy[i] += yoffset cz[i] = base[2]end
// track which checkpoints have been collectedint collected[NUM]for i = 0 to last_index collected[i] = falseend
int remaining = NUMprint_formatted_now "Checkpoint Hunt! Find all %d markers." 3000 NUM
// main loopwhile remaining > 0 wait 0
float pos[3] ...pos = get_char_coordinates $scplayer
for i = 0 to last_index // skip already collected checkpoints if collected[i] == true then continue end
if locate_char_on_foot_3d $scplayer cx[i] cy[i] cz[i] {xRadius} 3.0 {yRadius} 3.0 {zRadius} 3.0 {drawSphere} true then collected[i] = true remaining -= 1 print_formatted_now "Got one! %d remaining." 2000 remaining end endend
add_score {player} 0 REWARDprint_formatted_now "All checkpoints collected! +$%d" 3000 REWARD
terminate_this_scriptLet’s walk through it section by section.
Constants and Setup
const REWARD = 5000const NUM = 3int last_index = NUM - 1Two constants control the script’s behavior. NUM is the number of checkpoints and REWARD is the cash prize. Changing these values at the top instantly adjusts the game. The variable last_index stores the last valid index for the array to be used with FOR loops.
Generating Checkpoints
First, we read the player’s current position into a base point using the spread operator:
float base[3]...base = get_char_coordinates $scplayerThen three parallel arrays store the X, Y, and Z of each checkpoint. A for loop copies the player’s base position into each one and adds a random offset:
float cx[NUM]float cy[NUM]float cz[NUM]
int ifor i = 0 to last_index float xoffset = generate_random_float_in_range {min} -25.0 {max} 25.0 float yoffset = generate_random_float_in_range {min} -25.0 {max} 25.0 cx[i] = base[0] cx[i] += xoffset cy[i] = base[1] cy[i] += yoffset cz[i] = base[2]endEach checkpoint gets a random X and Y offset between -25 and +25 units from the player. The Z coordinate stays the same so they’re on the same ground level.
Tracking Collection
An integer array marks which checkpoints have been collected. 0 means not yet, 1 means collected:
int collected[NUM]for i = 0 to last_index collected[i] = falseend
int remaining = NUMThe variable remaining counts down as the player picks them up.
The Main Loop
The while loop runs until all checkpoints are collected:
while remaining > 0 wait 0 ...endInside, the script gets the player’s current position every frame and loops through each checkpoint:
for i = 0 to last_index if collected[i] == true then continue end ...endAlready-collected checkpoints are skipped with continue — exactly as we learned in Chapter V.
For each uncollected checkpoint, the script uses locate_char_on_foot_3d to check if the player is within 3 units. The drawSphere parameter set to true makes the game draw a visible marker at the checkpoint position:
if locate_char_on_foot_3d $scplayer cx[i] cy[i] cz[i] {xRadius} 3.0 {yRadius} 3.0 {zRadius} 3.0 {drawSphere} truethen collected[i] = true remaining -= 1 print_formatted_now "Got one! %d remaining." 2000 remainingendThe Reward
Once the loop exits (all collected), the player gets the prize:
add_score {player} 0 REWARDprint_formatted_now "All checkpoints collected! +$%d" 3000 REWARDSave the file as checkpoint_hunt.txt, press F7 to compile, and head into the game. Walk around and find all three markers!
What’s next?
Try these modifications and recompile:
- Change the reward
- Change
NUMto5for a longer hunt. - Widen the random offset range from
25.0to100.0to spread the checkpoints farther apart. - Replace
truewithfalseinlocate_char_on_foot_3dto hide the markers and make it a blind hunt.