Invalid return; gosub has not yet been called

I don’t know what this error means. How am I doing gosub wrong? I’m trying to create a combat system, so when gosub is called it calculates randomly the damage that is done.

*fake_choice
    *selectable_if (psionics > 0) #Use psionics.  
        *if (psionics >=90) 
            A powerful hit!
            *set atked true
            *gosub atk_enemy_powerful
        *if (psionics >=70) 
            A strong hit!
            *set atked true
            *gosub atk_enemy_strong
        *if (psionics >=50) 
            A decent hit!
            *set atked true
            *gosub atk_enemy_medium
        *if (psionics >=30)
            A weak hit!
            *set atked true
            *gosub atk_enemy_weak
        *if (psionics <30)
            A very weak hit!
            *set atked true
            *gosub atk_enemy_veryweak
            
    *selectable_if (explosives > 0) #Use explosives. 

    #Retreat
        You attempt to run away!


*label atk_enemy_powerful
*if (atked = true)
    *rand hit 30 60
    *set enemy_dam hit 
*return

*label atk_enemy_strong
*if (atked = true)
    *rand hit 20 50
    *set enemy_dam hit
*return

*label atk_enemy_medium
*if (atked = true)
    *rand hit 10 30
    *set enemy_damn hit
*return

*label atk_enemy_weak
*if (atked = true)
    *rand hit 0 20
    *set enemy_dam hit
*return

*label atk_enemy_veryweak
*if (atked = true)
    *rand hit 0 10
    *set enemy_dam hit
*return

In your example CS will automatically jump into *label atk_enemy_powerful after the first return from subroutine and will bug out on the *return because gosub wasn’t called. Move the subroutine (all atk labels) somewhere out of game scope, e.g. after chapter *finish or before chapter start.

Having standard *choices with *goto’s should also prove useful in this case. Keep in mind that upon *return game parser will start at the line directly after *gosub, so having a goto will help avoid bugs similar to yours.

*gosub test
*goto there << the line where game resumes after *return

The above *goto makes sure CS heads in the right direction instead of wandering off.

I’m not sure I understand what you mean. What do you mean move the subroutine? When I move it to the top of the page it says gosub has not yet been called.

I think I fixed it. I added a finish to one of the lines in the code and it stopped giving me the error.

I would still advise to simplify and bring more structure to your code in order to avoid future headaches, something like:

*label battle
*if enemy_dam > 100
	*goto victory

*choice
	*selectable_if (psionics > 0) #Use psionics
		*gosub psi_calc
		*goto battle
	*selectable_if (explosives > 0) #Use explosives
		*gosub exp_calc
		*goto battle
	#Flee
		*goto flee


*label psi_calc
*if (psionics >=90)
	*rand hit 30 60
	*set enemy_dam + hit
	A powerful hit!
	*return
*elseif (psionics >=70)
	*rand hit 20 50
	*set enemy_dam + hit
	A not-so-powerful hit!
	*return
*elseif (psionics >=50)
	*rand hit 10 40
	*set enemy_dam + hit
	A not-so-powerful hit!
	*return
*else
	*rand hit 10 20
	*set enemy_dam + hit
	A not-so-powerful hit!
	*return

Also, *returns should be indented on the same level as the rest of the currently executable code.

2 Likes

It is the case where you can reach the subroutine’s *label without actually coming from *gosub. As a result, the code would eventually meet *return without knowing which *gosub it is anchored with and should return to.

What you did by adding *finish is sealing-off your subroutines from being reached by default, which is one way to solve this issue.

1 Like