"Script can fail" error?

Users who are viewing this thread

jik

Knight
Ok when I compile my scripts, I get this error:

WARNING: Script can fail at operation #61.  Use cf_ at the beginning of it's name: joust_unhorsing

Here is the script, but I don't understand the error...
###script_joust_unhorsing
###Checks the horsing chance when hit while jousting.  $joust_mark is set here for the first strike
###Of course, if you are unhorsed (here) you don't get to strike back
###Animations and messages done here too
###Inputs : param 1 = agent getting hit
###        param 2 = range the strike happened at
###Outputs: $joust_mark is set if it is currently 0 (showing this is the first strike)

("joust_unhorsing",
[(store_script_param,":victim",1),
(store_script_param,":striker",2),
(store_script_param,":hit_range",3),
(assign,":joust_bonus",0),
###Setting up regs for display messages########################################
(assign,reg40,":hit_range"),                                                  #
(agent_get_troop_id,":temp_id", ":striker"),                                  #
        (str_clear, s30),                                                            #
(str_store_troop_name,s30,":temp_id"),      ##S30 has the Striker Troop name #
(agent_get_troop_id,":temp_id", ":victim"),                                  #
        (str_clear, s31),                                                            #
(str_store_troop_name,s31,":temp_id"),      ##S31 has the Victim Troop name  #
###End of regs setup for display messages######################################
###to remove redundancy, animation stuff should go here:
(assign,":jossled",0),
(try_begin),
(gt,"$joust_mark",550),            ##If a mark has been set, victim gets pentalty if above 550
(try_begin),###penalties for the victim's early swing
(is_between,"$joust_mark",591,600),
(assign,":joust_bonus",20),
(else_try),
(is_between,"$joust_mark",581,590),
(assign,":joust_bonus",15),
(else_try),
(is_between,"$joust_mark",571,580),
(assign,":joust_bonus",12),
(else_try),
(is_between,"$joust_mark",561,570),
(assign,":joust_bonus",:cool:,
(else_try),
(is_between,"$joust_mark",551,560),
(assign,":joust_bonus",4),
(try_end),###End of penalties for the victim's early swing
(else_try),
(neq,"$joust_mark",0),            ##can't be zero for this test
(le,":hit_range",450),            ##If a mark has been set, striker gets pentalty if below 450
(try_begin),###penalties for the striker's late swing
(is_between,":hit_range",400,410),
(is_between,"$joust_mark",450,550),
(assign,":jossled",1),
(else_try),
(is_between,":hit_range",411,420),
(is_between,"$joust_mark",455,545),
(assign,":jossled",1),
(else_try),
(is_between,":hit_range",421,430),
(is_between,"$joust_mark",460,540),
(assign,":jossled",1),
(else_try),
(is_between,":hit_range",431,440),
(is_between,"$joust_mark",470,530),
(assign,":jossled",1),
(else_try),
(is_between,":hit_range",441,450),
(is_between,"$joust_mark",480,520),
(assign,":jossled",1),
(try_end),###End of penalties for the striker's late swing
(try_end),
(try_begin),
(eq,":jossled",1),              ##you struck to late and are not able to hit back...
(agent_set_animation, ":striker", "anim_strike2_abdomen_front"),
(display_message,"@{s30} was jossled, and unable to return a thrust..."),
(agent_set_slot,":striker",slot_agent_jousting,-1), ##they have thrusted, no more chances
(try_end),
(eq,":jossled",0),
(agent_set_animation, ":striker", "anim_release_joust"),
(display_message,"@{s30} strikes {s31} at range {reg56}notches!",0x991111),
###End of animations stuff
(play_sound,"snd_crowd_shouts"),
(play_sound,"snd_hit_wood_metal"),                  ##sound of the lance breaking
(play_sound,"snd_blunt_hit"),
(try_begin),
(eq,"$joust_mark",0),                            #if 0, this is first strike, set the mark
(assign,"$joust_mark",":hit_range"),
(try_end),
(try_begin),#+/- 90-100 on range from 500
(this_or_next|is_between,":hit_range",400,411),
(is_between,":hit_range",591,601),
(assign,":unhorse_chance",5),
(else_try),#+/- 80-90
(this_or_next|is_between,":hit_range",411,421),
(is_between,":hit_range",581,591),
(assign,":unhorse_chance",10),
(else_try),#+/- 70-80
(this_or_next|is_between,":hit_range",421,431),
(is_between,":hit_range",571,581),
(assign,":unhorse_chance",15),
(else_try),#+/- 60-70
(this_or_next|is_between,":hit_range",431,441),
(is_between,":hit_range",561,571),
(assign,":unhorse_chance",20),
(else_try),#+/- 50-60
(this_or_next|is_between,":hit_range",441,451),
(is_between,":hit_range",551,561),
(assign,":unhorse_chance",30),
(else_try),#+/- 40-50
(this_or_next|is_between,":hit_range",451,461),
(is_between,":hit_range",541,551),
(assign,":unhorse_chance",40),
(else_try),#+/- 30-40
(this_or_next|is_between,":hit_range",461,471),
(is_between,":hit_range",531,541),
(assign,":unhorse_chance",50),
(else_try),#+/- 20-30
(this_or_next|is_between,":hit_range",471,481),
(is_between,":hit_range",521,531),
(assign,":unhorse_chance",60),
(else_try),#+/- 10-20
(this_or_next|is_between,":hit_range",481,491),
(is_between,":hit_range",511,521),
(assign,":unhorse_chance",70),
(else_try),#+/- 5-10
(this_or_next|is_between,":hit_range",491,496),
(is_between,":hit_range",506,511),
(assign,":unhorse_chance",80),
(else_try),#+/- 0-5
(is_between,":hit_range",496,506),
(assign,":unhorse_chance",90),
(try_end),
(val_add,":unhorse_chance",":joust_bonus"),                  ##Can be more than 100% if victim is off balance
(assign,reg41,":unhorse_chance"),
(display_message,"@there was a {reg41}% chance to unhorse",0x1111aa), 
(store_random_in_range,":percent",1,101),                    ##Roll percentage against the chance to unhorse
(try_begin),
(le,":percent",":unhorse_chance"),                        ##is he unhorsed?
(agent_set_slot,":victim",slot_agent_jousting,-1),        ##YES, make sure he doesn't get a swing.
(agent_set_hit_points,":victim",0,0),                      ##they are off thier horse, KO them.
(agent_deliver_damage_to_agent,":striker",":victim"),
(play_sound,"snd_body_fall_big"),                          ##sound of falling
(try_end),
(agent_set_slot,":striker",slot_agent_jousting,-1), ##they have thrusted, no more chances
]
),
 
Umm, I don't know, but it says Use cf_ at the beginning of it's name: joust_unhorsing, so how about :

("cf_joust_unhorsing",

Just an idea...

And did you try the script in game? If it can fail, it doesn't mean it will...
 
MrRoy said:
Umm, I don't know, but it says Use cf_ at the beginning of it's name: joust_unhorsing, so how about :

("cf_joust_unhorsing",

Just an idea...

And did you try the script in game? If it can fail, it doesn't mean it will...

I thought about that, but I first would like to know what the error means.  I jousted a few times and got no hang ups or errors (well I have a few that happen because sometimesthe agents are not yet present when I run my first check...)

I just don't like having errors...
 
jik said:
MrRoy said:
Umm, I don't know, but it says Use cf_ at the beginning of it's name: joust_unhorsing, so how about :

("cf_joust_unhorsing",

Just an idea...

And did you try the script in game? If it can fail, it doesn't mean it will...

I thought about that, but I first would like to know what the error means.  I jousted a few times and got no hang ups or errors (well I have a few that happen because sometimesthe agents are not yet present when I run my first check...)

I just don't like having errors...

If you try changing it with the cf_ does it gives an error?

And no, does it work in-game?

If yes, then this error doesn't mean anything, just put the cf_ so you don't get the error...
 
jik said:
Ok when I compile my scripts, I get this error:

WARNING: Script can fail at operation #61.  Use cf_ at the beginning of it's name: joust_unhorsing
...
(try_begin),
(eq,":jossled",1),              ##you struck to late and are not able to hit back...
(agent_set_animation, ":striker", "anim_strike2_abdomen_front"),
(display_message,"@{s30} was jossled, and unable to return a thrust..."),
(agent_set_slot,":striker",slot_agent_jousting,-1), ##they have thrusted, no more chances
(try_end),
(eq,":jossled",0),
(agent_set_animation, ":striker", "anim_release_joust"),
(display_message,"@{s30} strikes {s31} at range {reg56}notches!",0x991111),
###End of animations stuff
...
It looks like it's unhappy that you have a check-return in the middle of a zero nested block (I've highlighted it in red).  That's grounds for a "can fail" function.  All other scripts will generally go through their code and execute every block with early outs for nested blocks using the check-return behavior we all know and love.  The line in red is at zero nesting and the return scope if the check fails is the entire script. 

The compilation code which generates the warning confirms my suspicion:
    elif (can_fail_statement == 0 and current_depth == 0
          and (is_can_fail_operation(opcode)
              or ((opcode == call_script) and (statement[1].startswith("cf_", 7))))
          and (not statement_name.startswith("cf_"))):
      print "WARNING: Script can fail at operation #" + str(i) + ". Use cf_ at the beginning of its name: " + statement_name
    save_statement(ofile,opcode,no_variables,statement,variable_list,variable_uses,local_vars, local_var_uses,tag_uses,quick_strings)

This technically isn't an error (just a warning) because this behavior is supported by the engine; it's just letting you know that you're doing this thing and haven't given anyone the hint that you're doing it (by prepending cf_ to the script name).  This is a good warning since the usual way that computation type functions work is to do some maths/decisions/random rolls/whatever then at the bottom of the function write something that has a side effect, either setting a slot or setting a value in a return register.  If you early out of the entire script without intending it, the script probably won't function correctly and callers may be very confused, hence the warning.

edit)  clarifications
 
Thanks Kt0,

"check-return" behavior?  I am a bit confused with what you mean... 

I kind of skipped putting half the code I already wrote on the other side of a else_try.  I can go and fix that, but I do want the code to stop there if that result is reached.
 
yeah kt0 already explained it.

Basically envision this.

You're writing a script that has to return something to reg0

but in the root of that script (so not in a try_begin/try_end) you have a condition, like let's say (eq, ":my_var", 1),

If :my_var isn't 1, then the whole script fails and won;t return any information.

Just in case you didn't realize this could happen, the compiler throws this warning and prompts you to use cf_ in front of the script name so you as a programmer are aware that it won't always return a value.

Usually when I get this, it means that I messed up my if statements, unless it's a script that's specifically meant to check for a condition
 
jik said:
"check-return" behavior?  I am a bit confused with what you mean... 
Most of the checks in the module system do a check and might jump to the end of a block.  In X86 we do stuff like:
  cmp ax, bx
  jne somewhere_else

This compares the registers ax and bx and if they're not the same, we jump to the code labelled "somewhere_else".  This is terribly similar to:
  (neg|eq, reg0, reg1),

which does almost the exact same thing except that the jump location is the end of the current block, either a (try_end), or a (else_try) or the end of the script. 

I've always referred to the X86 version of this kind of thing as a check-jump though I have no idea where I picked that up (I don't do all that much assembly but it's a lot catchier than "jump on condition").  So for M&B I called the similar structure a "check-return" because it's returning from the current block.  Sorry for the confusion  :mrgreen:
 
MartinF said:
If :my_var isn't 1, then the whole script fails and won;t return any information.
I think it returns false. So, if script_cf_script_name fails in this code:
Code:
(try_begin),
 (call_script, "script_cf_script_name"),
 (assign, ":var", 1),
(else_try),
 (assign, ":var", 0),
(try_end),
":var" will be set to 0.
 
ok...  Thanks.  I was being a bit lazy, since I had added a new condition that would cause the final outcome of the script (namely the actual thrust) not to happen.  I forgot that if I select the whole area and hit tab, it would tab everything equally. 

Fixed it.  Didn't know that scripts had to return a value...  Will keep this in mind.
 
Back
Top Bottom