Author Topic: health and everyone on the battlefield  (Read 13457 times)

grailknighthero

  • Guest
health and everyone on the battlefield
« on: October 24, 2007, 07:57:06 AM »
For my mod I am making a function in mission templates that needs to access everyone on the battlefield.  Once the game has "gotten a hold of" a troop\agent, it would check their health.  If their health is less than normal, it would check to make sure they don't have a ranged weapon and if they have favor with the Lady (my mod is a Warhammer Bretonnian mod, if you want more info on what I mean go to games-workshop.com and look up Bretonnians under the game warhammer).  Then there will be a few calculations and an amount is added to the agent's health.  This is very complicated for me and I need help.  This is what I have so far.

   (60, 0, 0, [],
        [
            (try_for_range, ":agent", < >, < >), #I need to get everyone on the battlefield but don't know quite what to do
            (store_agent_hit_points,":hp",":agent",1),
            (try_begin),
                (check to make sure agent has less health than *started the battle with*), #maybe this is too complicated and I will change to is wounded at all if it is.
                (check to make sure they have favor with the lady), #i know how to do
                (check to make sure no ranged weapon equipped), not sure how to specify all ranged weapons in 1 line
                (value modifications),  #i know how to do
                (add value modifications to health),  # i know how to do
         ]
       ),
Any help is appreciated.  This is only the first step, the rest of what I want to do gets even more complicated, at least for me.
« Last Edit: November 14, 2007, 08:43:53 AM by grailknighthero »

Offline Hellequin

  • Journeyman
  • ***
  • Posts: 254
    • View Profile
Re: health and everyone on the battlefield
« Reply #1 on: October 24, 2007, 09:54:13 AM »
Sounds familiar - very similar to lots of stuff I do in Schattenlander.  A couple of tips:

1) The loop you're looking for is (try_for_agents, ":agent"), no other args necessary.  Note that I recommend using ":this_agent" or something (and associated things like ":this_agent_hp") just to avoid potential confusion once your scripts get more complicated and involve multiple loops.

2) It's quite easily possible to run a separate trigger at the start of the battle to store their initial HP, if you like - probably in an agent slot, there's plenty of those unused.  However, for the first run-through you might want to consider using the "relative" version of store_agent_hit_points (last arg zero or omitted), in which case you'll just get a percentage value.  If this isn't 100 you know they're wounded.  Likewise on the healing stage, a percentage of their max might be a more appropriate benefit.

3) To check for ranged weapons you've got three choices.
3a) You could try using the new operation agent_get_class.  This will tell you not "do they have a ranged weapon" but "are they considered an archer (grc_archer) by the core engine" with all the vagaries that brings.  You'd need a separate check for heroes, for example, and I'm not sure what you'll get on a mounted archer.
3b) For this or the next one, you need to make sure that the items are properly ordered in module_items.py.  In Native this is (now) the case.  Warhammer mod has a different item list so you'll have to check.  Once it's ordered so that the ranged weapons are all grouped together, and the constants ranged_weapons_begin and _end are correct in module_constants, then you just loop through them, using a (try_for_range, ":this_item", ranged_weapons_begin, ranged_weapons_end), and use (agent_has_item_equipped) to check for it.
3c) Use (agent_get_wielded_item), presumably only right hand is necessary.  Then use (is_between, ":this_item", ranged_weapons_begin, ranged_weapons_end), and you're done.  This version will only trigger, then when they not only possess but are actively wielding a ranged weapon - this may be a bonus or a flaw depending on what you were looking for.

The rest you should be okay on.

Cheers!

grailknighthero

  • Guest
Re: health and everyone on the battlefield
« Reply #2 on: October 24, 2007, 10:49:54 AM »
Thanks!  I will try this out when I get done with classes today.  Once I get this sorted out I will move to the more complicated stuff.  For the complicated stuff, its going to be something like:
The player holds down a key for x amount of time and doesn't move to count as praying to the Lady to be able to get the health regen every 60 seconds (which I am thinking will be a random percentage between 1 and 10).  I say it is more complicated because I haven't worked with positions at all.  This won't apply to the ai because Ill add in different stuff for the player and the ai in the health regen code.  And after that I am going to work out the knightly virtues and possibly some magic items.  There are magic items that affect the Lady's blessing(the health regen code I am working on) and if the player or npc has it equipped, then Ill have it modify the health regen (the same goes for one of the virtues).  It looks like I am starting to get into the stuff that makes my mod more unique than just changing scenes, items, troops, towns, factions, simple scripts, and the map.

Ill mess around with the player classes and if I can't get them to work exactly Ill group all of the ranged weapons together.  I don't normally like to group native and my items together but if I have to, Ill have to.


I figured you did something like this in Schattenlander but I didn't know where to look exactly.

Thanks again.

Offline Hellequin

  • Journeyman
  • ***
  • Posts: 254
    • View Profile
Re: health and everyone on the battlefield
« Reply #3 on: October 24, 2007, 12:32:11 PM »
If you crack open Schattenlander's "classify_items" script (located in module_scripts), you'll see where I take the "ordering your items" to the next, more complex, level.  The nice thing about isolating everything into that classification script was that it functions much like defining the constants - if I alter something in module_items, I know exactly where to go to accomodate those changes.  One script.

You could do the same thing here, if you prefer.  Then you replace the is_between call with a call to the script, and an (eq, "$is_this_a_ranged_weapon", const_yes) or whatever.  The nice thing about that is that having called the script, you can also get out of it something like "$magnitude_of_prayer_bonus" from the one script call.  Even more elegantly, write a specific "wrapper" script, "script_is_ranged", which calls the classification script internally, and returns a boolean.  (Huh, you say?  If a script's main ops block aborts due to a false statement, such as (eq, 1, 0), instead of completing normally, the script itself is "false" and will register as such to the block that called it, serving much like an (eq) or (gt) operation.)

As for your invocation mode, it's a good idea.  It has a lot of room for chrome, too.  For example, after implementing the main part and getting it working, you could work on a presentation which slowly buids a heavenly glory effect onto the screen, as they hold the key down, culminating in a flash of white perhaps.  I would suggest one thing, though... rather than requiring that they stand perfectly still, give a little leeway (50cm?).  I don't know that the various "impatience" animations don't displace the player's position slightly.  Also if they're mounted you might consider checking it vs. the horse instead, though that gives mounted a substantial advantage; you might instead want to require that they dismount.

As an alternative, use a set of triggers which checks if any of the other game keys (such as move forward) have been clicked, and if so sets a "cancel prayer" flag.  Note that in this version you can just have the prayer key be clicked, not held, which frees you from writing code to detect states such as (key held -> prayer starts -> other key clicked -> prayer cancelled -> prayer key is still being held -> prayer starts again).

The other nice thing I'd suggest for special effects would be to make the camera dramatically circle the PC during the prayer sequence.  An animation would be nice but, alas, I don't know how that would interact with other animations such as being knocked down.  Any of these things can be implemented after the functional part is working, though.

grailknighthero

  • Guest
Re: health and everyone on the battlefield
« Reply #4 on: October 24, 2007, 03:53:39 PM »
Here is what I have so far:
Code: [Select]
(60, 0, 10, [],
        [   (display_message, "@Blessing is checking."),
            #(get_player_agent_no,":player_agent_number"),
            #(display_message, "@Troop checked."),
            (assign, ":count", 0),
            (try_for_agents, ":this_agent"),
                (val_add, ":count", 1),
                (assign, reg50, ":count"),
                (agent_is_alive, ":this_agent"),
                (store_agent_hit_points,":this_agent_hp",":this_agent",0),
                #(display_message, "@Agent HP checked."),
                (lt, ":this_agent_hp", 100),
                #(display_message, "@Troop has less than 100% hp."),
                (agent_get_troop_id,":this_agent_trp_id", ":this_agent"),
                (try_begin),
                    #(eq, ":this_agent", ":player_agent_number"),
                    (eq, ":this_agent_trp_id", "trp_player"),
                    (display_message, "@The player has been selected."),
                    (this_or_next|ge, "$knight_class", 1),
                    (ge, "$grail_pilgrim", 1),
                    (display_message, "@The player is a knight or grail pilgrim."),
                    (store_random_in_range, ":agent_added_hp",1,11),
                    (assign, ":agent_total_hp", ":this_agent_hp"),
                    (val_add, ":agent_total_hp", ":agent_added_hp"),
                    (val_clamp,":agent_total_hp",0, 100),
                    (agent_set_hit_points,":this_agent",":agent_total_hp",0),
                    (display_message, "@The Lady has blessed you and healed some of your wounds."),
                (else_try),
                    (is_between, ":this_agent_trp_id", troop_lady_favor_begin, troop_lady_favor_end),
                    (store_troop_faction,":this_agent_faction",":this_agent_trp_id"),
                    (this_or_next|eq, ":this_agent_faction", "fac_kingdom_1"),
                    (this_or_next|eq, ":this_agent_faction", "fac_kingdom_3"),
                    (eq, ":this_agent_faction", "fac_kingdom_5"),
                    (store_random_in_range, ":agent_added_hp",1,11),
                    (assign, ":agent_total_hp", ":this_agent_hp"),
                    (val_add, ":agent_total_hp", ":agent_added_hp"),
                    (val_clamp,":agent_total_hp",0, 100),
                    (agent_set_hit_points,":this_agent",":agent_total_hp",0),
                    (display_message, "@A troop has been healed."),
                (else_try),
                    (is_between, ":this_agent_trp_id", companion_knights_begin, companion_knights_end),
                    (store_troop_faction,":this_agent_faction",":this_agent_trp_id"),
                    (store_random_in_range, ":agent_added_hp",1,11),
                    (assign, ":agent_total_hp", ":this_agent_hp"),
                    (val_add, ":agent_total_hp", ":agent_added_hp"),
                    (val_clamp,":agent_total_hp",0, 100),
                    (agent_set_hit_points,":this_agent",":agent_total_hp",0),
                    (display_message, "@A companion has been healed."),
                (else_try),
                    (is_between, ":this_agent_trp_id", kingdom_heroes_begin, kingdom_heroes_end),
                    (store_troop_faction,":this_agent_faction",":this_agent_trp_id"),
                    (this_or_next|eq, ":this_agent_faction", "fac_kingdom_1"),
                    (this_or_next|eq, ":this_agent_faction", "fac_kingdom_3"),
                    (eq, ":this_agent_faction", "fac_kingdom_5"),
                    (store_random_in_range, ":agent_added_hp",1,11),
                    (assign, ":agent_total_hp", ":this_agent_hp"),
                    (val_add, ":agent_total_hp", ":agent_added_hp"),
                    (val_clamp,":agent_total_hp",0, 100),
                    (agent_set_hit_points,":this_agent",":agent_total_hp",0),
                    (display_message, "@A kingdom hero has been healed."),
                (try_end),
            (try_end),
            (display_message, "@Count is {reg50}."),
            ]
       ),


Edit once again:  I just changed the code above.  I added a count and now I need to test it out.  My problem right now is that it does the player, companions, and kingdom heroes twice while not doing troops at all.  Is the reason why it doesn't do troops because they dont have a percentage health?  It says if they are hurt, but it doesn't say they are healed.  The first time the count is 17 and there was 16 people on the field, 17 if you count my horse (horses count as agent's right)?
Ok it seems to be random when the player is healed twice.  I had it heal me right for the first 2 times, and then the third time it healed me twice.  The count was 17 each time.
« Last Edit: October 25, 2007, 11:57:31 AM by grailknighthero »

Offline Hellequin

  • Journeyman
  • ***
  • Posts: 254
    • View Profile
Re: health and everyone on the battlefield
« Reply #5 on: October 25, 2007, 11:57:10 AM »
(Amusingly, the only programming class I've ever taken was a rock-simple first-year university course in, of all things, Fortran.  I'm a physicist, working as a technical officer in nanotechnology.)

My recollection had been that unconscious troops failed the "agent_is_alive" check, but an easy alternate approach since you're checking their health anyway would just be to drop the is_alive check and instead of (lt, ":this_agent_hp", 100) do (is_between, ":this_agent_hp", 1, 100).  This should tell you if the KO'd companions are the ones being healed.  My guess is that they are, because there's really nothing here which could cause it to multiply evaluate on a single agent.

As for your (is_between, ":this_agent_trp_id", troop_lady_favor_begin, etc_end) portion not working, maybe you should try commenting out this check and replacing it with an explicit (eq, ":this_agent_trp_id", <the troop I'm checking>) instead, to isolate the problem.  Also double-check your constants and their spelling, etc.  Basic troubleshooting; it's probably something very simple, once you find it.

As for elegance, one thing you might consider is running the checks backward - have the first branch be satisfied if it should do nothing.  This may make the logic simpler in practice.  For example:
Code: [Select]
(store_troop_faction, ":this_agent_faction", ":this_agent_trp_id"),
(try_begin),
  (this_or_next|neq, ":this_agent_trp_id", "trp_player"),
  (this_or_next|lt, "$knight_class", 1),
  (lt, "$grail_pilgrim", 1),
  (neg|is_between, ":this_agent_trp_id", companion_knights_begin, companion_knights_end),
  (neg|is_between, ":this_agent_trp_id", troop_lady_favor_begin, troop_lady_favor_end),
  (neg|is_between, ":this_agent_trp_id", kingdom_knights_begin, kingdom_knights_end),
  (faction_slot_eq, ":this_agent_faction", slot_ladys_favor, 0), # Set this to 1 on the player faction as well as kingdoms 1, 3, and 5, during game init.  Remember to define the slot constant in module_constants.
  (assign, ":do_nothing", 0),
(else_try),
  # All your healing code goes here, since it's all identical.  While debugging you need to know which kinds have been healed, but you can now use simpler try checks for that - no checking faction and so forth.
(try_end),

grailknighthero

  • Guest
Re: health and everyone on the battlefield
« Reply #6 on: October 25, 2007, 12:18:14 PM »
(Amusingly, the only programming class I've ever taken was a rock-simple first-year university course in, of all things, Fortran.  I'm a physicist, working as a technical officer in nanotechnology.)

My recollection had been that unconscious troops failed the "agent_is_alive" check, but an easy alternate approach since you're checking their health anyway would just be to drop the is_alive check and instead of (lt, ":this_agent_hp", 100) do (is_between, ":this_agent_hp", 1, 100).  This should tell you if the KO'd companions are the ones being healed.  My guess is that they are, because there's really nothing here which could cause it to multiply evaluate on a single agent.

As for your (is_between, ":this_agent_trp_id", troop_lady_favor_begin, etc_end) portion not working, maybe you should try commenting out this check and replacing it with an explicit (eq, ":this_agent_trp_id", <the troop I'm checking>) instead, to isolate the problem.  Also double-check your constants and their spelling, etc.  Basic troubleshooting; it's probably something very simple, once you find it.

As for elegance, one thing you might consider is running the checks backward - have the first branch be satisfied if it should do nothing.  This may make the logic simpler in practice.  For example:
Code: [Select]
(store_troop_faction, ":this_agent_faction", ":this_agent_trp_id"),
(try_begin),
  (this_or_next|neq, ":this_agent_trp_id", "trp_player"),
  (this_or_next|lt, "$knight_class", 1),
  (lt, "$grail_pilgrim", 1),
  (neg|is_between, ":this_agent_trp_id", companion_knights_begin, companion_knights_end),
  (neg|is_between, ":this_agent_trp_id", troop_lady_favor_begin, troop_lady_favor_end),
  (neg|is_between, ":this_agent_trp_id", kingdom_knights_begin, kingdom_knights_end),
  (faction_slot_eq, ":this_agent_faction", slot_ladys_favor, 0), # Set this to 1 on the player faction as well as kingdoms 1, 3, and 5, during game init.  Remember to define the slot constant in module_constants.
  (assign, ":do_nothing", 0),
(else_try),
  # All your healing code goes here, since it's all identical.  While debugging you need to know which kinds have been healed, but you can now use simpler try checks for that - no checking faction and so forth.
(try_end),

Ok.  One thing I have noticed is that horses are counted in the agents, and they might be healed as well but I am not sure yet, I need more testing.  It very well could be healing the knocked out companions, but it always heals double the amount of my total companions in the battle and the same goes for kingdom heroes.  Except once it healed double of my companions -1.  I am suspecting it heals the horses as well and that companion's horse wasn't hurt.

Ok.  I ran around for like 10 minutes hurt, and it was only healing me once.  Then I got my horse hurt, and it started healing me twice.  I am not even sure that it healed me twice, but it said that I was selected twice and then healed twice so I dont know if it healed me and the horse or if it healed me twice.  I am going to check it out with companions now.

Ok.  If I take the horses away from my companions it only heals them once and the agent alive check works and doesnt heal companions who are knocked out.

For the troop part, I dont have anything misspelled in module constants or module troops.  Ill try what you said later today.

This time I had my horse get hurt and I did not and it healed me.  Again, I am not sure if it healed me or my horse.  It says I was selected and I was healed, but my health was full.  Only my horse was hurt.
« Last Edit: October 25, 2007, 12:45:17 PM by grailknighthero »

Offline Hellequin

  • Journeyman
  • ***
  • Posts: 254
    • View Profile
Re: health and everyone on the battlefield
« Reply #7 on: October 25, 2007, 12:55:49 PM »
I suggest an explicit check.  Set up a trigger to call up your horse's agentID, get its troopID, assign that to a register, and display it in a debug script.

If the answer is that (agent_get_troop_ID) is returning the troop_ID of its rider, then that may be your double-tap, yeah.  Sounds consistent with what you're seeing.

I don't know if you've noticed this op or not, but you can explicitly exclude horses easily with (agent_is_human).  Sounds like once you're done debugging (or stuck) you should definitely be using that as a filter on the whole shebang.

grailknighthero

  • Guest
Re: health and everyone on the battlefield
« Reply #8 on: October 25, 2007, 01:23:53 PM »
You beat me to editing my post saying I put the human check in and it fixes the problem.

I also just did what you suggested for eloquence, and it is a lot easier to read now and better, because it does the same thing in 2 condition statements.  And what is even better, troops are healed now as well.  I don't know why, because I didnt mess with troop_lady_favor_begin and troop_lady_favor_end.  Tonight I am going to work on what you posted above with making sure the player does not have a ranged weapon equipped, and then I am going to work on the praying.  Your idea for having the kingdom slot ladys_favor is a very good idea, because I plan to add in some more factions and I will only have to make their ladys_favor slot equal 1.

Here is what my code looks like right now:
Code: [Select]
(try_for_agents, ":this_agent"),
                (agent_is_alive, ":this_agent"),
                (agent_is_human,":this_agent"),
                (store_agent_hit_points,":this_agent_hp",":this_agent",0),
                #(display_message, "@Agent HP checked."),
                (lt, ":this_agent_hp", 100),
                #(display_message, "@Troop has less than 100% hp."),
                (agent_get_troop_id,":this_agent_trp_id", ":this_agent"),
                (store_troop_faction, ":this_agent_faction", ":this_agent_trp_id"),
                (try_begin),
                    (this_or_next|neq, ":this_agent_trp_id", "trp_player"),
                    (this_or_next|lt, "$knight_class", 1),
                    (lt, "$grail_pilgrim", 1),
                    (neg|is_between, ":this_agent_trp_id", companion_knights_begin, companion_knights_end),
                    (neg|is_between, ":this_agent_trp_id", troop_lady_favor_begin, troop_lady_favor_end),
                    (neg|is_between, ":this_agent_trp_id", kingdom_heroes_begin, kingdom_heroes_end),
                    (faction_slot_eq, ":this_agent_faction", slot_ladys_favor, 0),
                    (assign, ":do_nothing", 0),
                (else_try),
                    (neq, ":do_nothing", 0),
                    (store_random_in_range, ":agent_added_hp",1,11),
                    (assign, ":agent_total_hp", ":this_agent_hp"),
                    (val_add, ":agent_total_hp", ":agent_added_hp"),
                    (val_clamp,":agent_total_hp",0, 100),
                    (agent_set_hit_points,":this_agent",":agent_total_hp",0),
                    (str_store_troop_name,s50,":this_agent_trp_id"),
                    (display_message, "@The Lady has blessed and healed some of {s50}'s wounds."),
                (try_end),
            (try_end),
            ]
       ),
« Last Edit: October 25, 2007, 02:56:52 PM by grailknighthero »

Offline Hellequin

  • Journeyman
  • ***
  • Posts: 254
    • View Profile
Re: health and everyone on the battlefield
« Reply #9 on: October 25, 2007, 03:07:29 PM »
Erm... your code right now will (each time it evaluates) only heal until it comes to an agent on the list who can't be healed, and then stop.

The statement (assign, ":do_nothing", 0) is basically a comment.  It's not required and could be omitted without changing anything; I assumed you were more comfortable having it there than having the block actually have nothing in it other than tests.  But you shouldn't be checking it!  There's no need; just drop the (neq, ":do_nothing", 0) entirely.

Oh, and BTW - "eloquence" is fancy speech, wise or witty or persuasive use of language.  "Elegance" is a quality of conciseness and efficiency which can be possessed by, among other things, code.  I think you mean the latter.

grailknighthero

  • Guest
Re: health and everyone on the battlefield
« Reply #10 on: October 25, 2007, 04:56:52 PM »
Erm... your code right now will (each time it evaluates) only heal until it comes to an agent on the list who can't be healed, and then stop.

The statement (assign, ":do_nothing", 0) is basically a comment.  It's not required and could be omitted without changing anything; I assumed you were more comfortable having it there than having the block actually have nothing in it other than tests.  But you shouldn't be checking it!  There's no need; just drop the (neq, ":do_nothing", 0) entirely.

Oh, and BTW - "eloquence" is fancy speech, wise or witty or persuasive use of language.  "Elegance" is a quality of conciseness and efficiency which can be possessed by, among other things, code.  I think you mean the latter.

Ya, I have made some stupid mistakes.  First with the eloquence thing which I can't believe I messed it up because I should know better.  And then with he do nothing thing, I obviously wasn't thinking it straight.  I did have class in ten minutes and obviously I was in a hurry to get the thing done.  I am glad you picked up on it, because it would have caused problems later on.  It isn't even needed, because that condition will only evaluate if the first one fails.  One reason I  did put it in there though is because if the local variable isn't used, it gives a warning, and I try to satisfy the engine because I dont like seeing the warnings unless there is an actual error.

Here is what I have now:  the message for the player below will be kept once I am done debugging and the message for everyone else and the "Blessing is checking" message will be removed.

(60, 0, 0, [],
        [   (display_message, "@Blessing is checking."),

            (try_for_agents, ":this_agent"),
                (agent_is_alive, ":this_agent"),
                (agent_is_human,":this_agent"),
                (store_agent_hit_points,":this_agent_hp",":this_agent",0),
                #(display_message, "@Agent HP checked."),
                (lt, ":this_agent_hp", 100),
                #(display_message, "@Troop has less than 100% hp."),
                (agent_get_troop_id,":this_agent_trp_id", ":this_agent"),
                (store_troop_faction, ":this_agent_faction", ":this_agent_trp_id"),
                (try_begin),
                    (this_or_next|neq, ":this_agent_trp_id", "trp_player"),
                    (this_or_next|lt, "$knight_class", 1),
                    (lt, "$grail_pilgrim", 1),
                    (neg|is_between, ":this_agent_trp_id", companion_knights_begin, companion_knights_end),
                    (neg|is_between, ":this_agent_trp_id", troop_lady_favor_begin, troop_lady_favor_end),
                    (neg|is_between, ":this_agent_trp_id", kingdom_heroes_begin, kingdom_heroes_end),
                    (faction_slot_eq, ":this_agent_faction", slot_ladys_favor, 0),
                    (assign, ":do_nothing", 0),
                (else_try),
                    (store_random_in_range, ":agent_added_hp",1,11),
                    (assign, ":agent_total_hp", ":this_agent_hp"),
                    (val_add, ":agent_total_hp", ":agent_added_hp"),
                    (val_clamp,":agent_total_hp",0, 100),
                    (agent_set_hit_points,":this_agent",":agent_total_hp",0),
                    (str_store_troop_name,s50,":this_agent_trp_id"),
                    (try_begin),
                        (eq, ":this_agent_trp_id", "trp_player"),
                        (display_message, "@The Lady has blessed you and healed some of your wounds."),
                    (else_try),
                        (display_message, "@The Lady has blessed and healed some of {s50}'s wounds."),
                    (try_end),
                (try_end),
            (try_end),
            ]
       ),
« Last Edit: October 25, 2007, 05:19:20 PM by grailknighthero »

grailknighthero

  • Guest
Re: health and everyone on the battlefield
« Reply #11 on: October 28, 2007, 12:34:23 PM »
Sorry for the double post.  I took a couple days off from working on this and I am working on it some more.  I am trying to get a check for a ranged weapon working.  This is what I have:

Code: [Select]
("is_ranged",
    [
      (store_script_param_1, ":agent_no"),

      (try_for_range, ":ranged", ranged_begin, ranged_end),
          (agent_has_item_equipped,":agent_no",":ranged"),
          (assign, ":has_ranged", 1),
      (try_end),
  ]),

# this is what I have until I can figure out a return statement
("is_ranged",
    [
      (store_script_param_1, ":agent_no"),

      (try_for_range, ":ranged", ranged_begin, ranged_end),
          (agent_has_item_equipped,":agent_no",":ranged"),
          (assign, reg51, 1),
      (try_end),

     
  ]),

This is what I want to do after the try_end (in a normal programing language it would be like this):
return ":has_ranged"

So, How do I do a return statement in M&B scripting?

I am going to call this script in the section below.  I am only going to have it check for companions and the player.  Will this work?

Also, this is is what I have so far for the thing in mission templates:
Code: [Select]
(60, 0, 0, [],
        [   (display_message, "@Blessing is checking."),
            (try_for_agents, ":this_agent"),
                (agent_is_alive, ":this_agent"),
                (agent_is_human,":this_agent"),
                (store_agent_hit_points,":this_agent_hp",":this_agent",0),
                (lt, ":this_agent_hp", 100),
                (agent_get_troop_id,":this_agent_trp_id", ":this_agent"),
                (store_troop_faction, ":this_agent_faction", ":this_agent_trp_id"),
                (try_begin),

                    # player and ranged weapon check
                    (try_begin),
                        (eq, ":this_agent_trp_id", "trp_player"),
                        (neq, "$prayed", 1),
                        (call_script, "script_is_ranged", ":this_agent_trp_id"),
                        #(this_or_next|neq, ":has_ranged", 0),
                        (this_or_next|neq, reg51, 0),
                        (this_or_next|lt, "$knight_class", 1),
                        (lt, "$grail_pilgrim_class", 1), 
                    (try_end),

                    # companion and ranged weapon check
                    (try_begin),
                        (is_between, ":this_agent_trp_id", companion_knights_begin, companion_knights_end),
                        (call_script, "script_is_ranged", ":this_agent_trp_id"),
                        #(neq, ":has_ranged", 0),
                        (neq, reg51, 0),
                    (try_end),

                    (faction_get_slot,":ladys_favor",":this_agent_faction",slot_ladys_favor),
                    (eq, ":ladys_favor", 0),
                    (neg|is_between, ":this_agent_trp_id", troop_lady_favor_begin, troop_lady_favor_end),
                    (neg|is_between, ":this_agent_trp_id", kingdom_heroes_begin, kingdom_heroes_end),
                    (assign, ":do_nothing", 0),

                (else_try),
                    (store_random_in_range, ":agent_added_hp",1,11),
                    (assign, ":agent_total_hp", ":this_agent_hp"),
                    (val_add, ":agent_total_hp", ":agent_added_hp"),
                    (val_clamp,":agent_total_hp",0, 100),
                    (agent_set_hit_points,":this_agent",":agent_total_hp",0),
                    (str_store_troop_name,s50,":this_agent_trp_id"),

                    (try_begin),
                        (eq, ":this_agent_trp_id", "trp_player"),
                        (display_message, "@The Lady has blessed you and healed some of your wounds."),
                    (else_try),
                        (display_message, "@The Lady has blessed and healed some of {s50}'s wounds."),
                    (try_end),

                (try_end),
            (try_end),
            ]
       ),

The above code is largely untested because I have been working on this:
Code: [Select]
# edited
      (ti_inventory_key_pressed, 0, 0, [
          (display_message,"str_use_baggage_for_inventory"),
          # added
          (try_begin),
              (eq, "$prayed", 1),
              (display_message,"@You already have the blesssing."),
          (try_end),
          (neq, "$prayed", 1),
          (this_or_next|ge, "$knight_class", 1),
          (ge, "$grail_pilgrim_class", 1),
          (try_begin),
              (call_script, "script_is_ranged", "trp_player"),
              #(eq, ":has_ranged", 1),
              (eq, reg51, 1),
              (display_message,"@The Lady does not favor you because you have a ranged weapon."),
          (else_try),
              (display_message,"@You begin to pray."),
              (get_player_agent_no,":player_agent_no"),
              (try_begin),
                  (agent_get_horse,":player_horse",":player_agent_no"),
                  (neq, ":player_horse", 0),
                  (agent_set_animation, ":player_horse", anim_rear),
              (else_try),
                  (agent_set_animation, ":player_agent_no", anim_defend_right_twohanded_parry),
              (try_end),
              (assign, "$prayed", 1),
          (try_end),
          # end added
          ], []),
      # end edited

I don't know how to animate so for the time being those are the animations I am using as fillers.  I have a problem though.  Whenever you put a ranged weapon in your equipment slot, it breaks  ti_inventory_key_pressed entirely and  (display_message,"str_use_baggage_for_inventory"), isnt even displayed.

Edit:  Something is wrong because now it is that way even if I dont have a ranged weapon.  I have only got it to work for 1 battle...

Ok. now it is working...Except for when the player does not have a horse.  The next battle it was broken though...
Wait...It might not be broken, I do not know for sure, but my message displays are broken.  If I get hit, kill someone, etc, nothing is displayed.  No animations are shown though so it is still broken.

Ok the text comes back after a little while, this time there was a ton of red errors but they went so fast that I couldnt read them.  Also, for some reason my script to check ranged weapons isnt working anymore and I havent changed it.
 
« Last Edit: October 28, 2007, 04:04:37 PM by grailknighthero »

Offline Hellequin

  • Journeyman
  • ***
  • Posts: 254
    • View Profile
Re: health and everyone on the battlefield
« Reply #12 on: October 29, 2007, 10:06:58 AM »
I'm not sure where to pull the questions out of there, but...

There is no formal equivalent to the "return" statement.  These aren't functions in the sense that they have a return value; they really are scripts, which execute without being assigned a value.  Some people like to assign a return value to reg(0), in mimicry of the way Native operations handle this; others (including me) prefer a single global variable "$return" for the same use.

However, there is one exception.  These scripts can return a boolean - more specifically, they can succeed/fail in the same way that (eq) or (troop_slot_gt) can do so.  They return "true" if the uppermost layer completed all its operations successfully - the normal case, you do everything in the body of the script, hit the closing bracket, and stop.  They return "false" if their uppermost layer - that is, outside of any try statements - hits a statement which fails (aka returns false).  (Also note that if it does so, just like a try block, the script itself will abort immediately and will not execute any code which follows the failed statement.)  So, for example, in your code, tidying and adding one crucial line:
Code: [Select]
("has_ranged",
  [
  (store_script_param_1, ":agent_no"),
  (try_for_range, ":ranged_wpn", ranged_weapons_begin, ranged_weapons_end), # Clarity is good.
     (agent_has_item_equipped, ":agent_no", ":ranged_wpn"),
     (assign, ":has_ranged_wpn", 1),
  (else_try),
     (assign, ":has_ranged_wpn", 0),
  (try_end),
  (eq, ":has_ranged_wpn", 1),  # The important bit - a boolean op not enclosed by any tries.
  ]),
... means that you can just call (has_ranged, ":this_agent"), and if they have a ranged weapon you'll carry on, if they don't then this will stop the current try block just as if the script call itself had been an (eq, 0, 1), statement.

Obviously in this case you'd want the inverse of this.  I'm not sure, but I suspect that you could use (neg|call_script, "script_has_ranged", ":this_agent"), to get the correct result.  Test it with something simple - (neg|call_script, "script_does_one_equal_zero") or something.

grailknighthero

  • Guest
Re: health and everyone on the battlefield
« Reply #13 on: October 29, 2007, 03:33:03 PM »
Ya I know my ramblings are hard to understand.  I was getting weird and unexpected results of what should be happening.  If I do what you say to the script, does this look right to you?  Do you see any errors?  Why would the messages completely go away for a few seconds?  Why would this function(I dont know what else to call it) affect damage and kill messages?

Code: [Select]
(ti_inventory_key_pressed, 0, 0, [
          (display_message,"str_use_baggage_for_inventory"),

          (try_begin),
              (eq, "$prayed", 1),
              (display_message,"@You already have the blesssing."),
          (try_end),
          (neq, "$prayed", 1),
          (this_or_next|ge, "$knight_class", 1),
          (ge, "$grail_pilgrim_class", 1),
          (try_begin),
              (call_script, "script_is_ranged", "trp_player"),

              (display_message,"@The Lady does not favor you because you have a ranged weapon."),
          (else_try),
              (display_message,"@You begin to pray."),
              (get_player_agent_no,":player_agent_no"),
              (try_begin),
                  (agent_get_horse,":player_horse",":player_agent_no"),
                  (neq, ":player_horse", 0),
                  (agent_set_animation, ":player_horse", anim_rear),
              (else_try),
                  (agent_set_animation, ":player_agent_no", anim_defend_right_twohanded_parry),
              (try_end),
              (assign, "$prayed", 1),
          (try_end),
          ], []),

Edit:  I didnt think I would have time to test it out right now but I decided to anyway.  I did what you said and as always, it worked for the first time (that I know of), but the second and third time the messages disappeared.  That is all I have time right now to test it.  The first time the script evaluated to false and worked exactly how it needed to work.  Thanks for explaining that to me (and obviously all this which I have needed help on every part).
« Last Edit: October 29, 2007, 03:57:16 PM by grailknighthero »

Offline Hellequin

  • Journeyman
  • ***
  • Posts: 254
    • View Profile
Re: health and everyone on the battlefield
« Reply #14 on: October 29, 2007, 04:42:35 PM »
Generally speaking if your messages are disappearing this means you're overloading the message queue.  Turning edit mode off may help (gets rid of the red "opcode error" and similar).  Otherwise you basically need to be using fewer debug strings, or isolating debugging from normal play more.