Random Recruits

The place to post your WML questions and answers.

Moderator: Forum Moderators

Forum rules
  • Please use [code] BBCode tags in your posts for embedding WML snippets.
  • To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
Post Reply
User avatar
db0
Posts: 400
Joined: January 3rd, 2006, 8:39 pm
Location: Somewhere Far Beyond...
Contact:

Random Recruits

Post by db0 »

Here's a little code I cooked for Gotrek's campaign

What this does is change your recruit option after each time you recruit. The recruit option are separated in categories (altough you can change/expand that) Archers, Melee, Util etc.

Every time you recruit a unit, the recruit option for that category is randomized within a predefined pool of recruits.

This might be useful for a urban or mercenary themed campaign I think.

EDIT: I removed the obsolete code since there is a better version available. Get that ;)

I've also uploaded it into a file format if you want to use it as a module

Currently you can see it in action if you download the attachments I put up for gotrek and replace the appropriate files in his campaign

What do you think?
Attachments
randomizer_util.cfg
Add this to your utils folder and allow your _main.cfg to see it

{@campaigns/YourCampaignName/utils/randomizer_util.cfg}

Alternatively, cut and paste the contents into your utils.cfg file (if you have one)
(4.71 KiB) Downloaded 241 times
randomizer_sample_prestart_event.cfg
Modify and add the contents into your prestart event
(2.01 KiB) Downloaded 216 times
Last edited by db0 on February 12th, 2008, 5:51 pm, edited 2 times in total.
User avatar
governor
Posts: 267
Joined: December 8th, 2006, 12:32 am

Post by governor »

To avoid potential problems you should change the way you store/access array variables.

Code: Select all

array[0].xxxx = y
Is better than:

Code: Select all

array[0] = y
This is a WML quirk that was brought up by meriton and should still be stickified. It has to do with disabling binary saves.

So changing:

Code: Select all

{VARIABLE archer_recruits[0] "Orcish Archer"}
to:

Code: Select all

{VARIABLE archer_recruits[0].type "Orcish Archer"}
Will save people grief in the long run.
User avatar
db0
Posts: 400
Joined: January 3rd, 2006, 8:39 pm
Location: Somewhere Far Beyond...
Contact:

Post by db0 »

a-HA! So that is why this was in the httt Crossroads scenario. And I was wondering about it...
User avatar
db0
Posts: 400
Joined: January 3rd, 2006, 8:39 pm
Location: Somewhere Far Beyond...
Contact:

Post by db0 »

OK, I may need some help now. I modified the code to make it more portable but it doesn't seem to work. Any ideas if it doesn't work because of coding error or because WML capabilities?

EDIT: Since this is now fixed, I'm removing the obsolete code

Using the debug feature, it seems that the recruit_types[#].current is not set during the recruit event or is set during the start init option but it is not handled correctly to set recruits.

Any ideas?
Last edited by db0 on February 12th, 2008, 5:28 pm, edited 1 time in total.
User avatar
db0
Posts: 400
Joined: January 3rd, 2006, 8:39 pm
Location: Somewhere Far Beyond...
Contact:

Post by db0 »

Yay! I fixed it. My masterpiece is complete!

What this means is that you can now increase or reduce your the recruit type options as much as you want and you don't have to expand your if statements to compensate. It is all done automatically for you. You can also add extra generic types of recruits instead of sticking to just three as it was initially. So you can now have an option, say, for an elf, an orc, a goblin and a dwarf and these choices will cycle through each possible type of recruit for that race (depending on the choices you've set) but only for that race you recruited from.

So, here it is. I hope you find it useful,

MACROS

Code: Select all

#Recruits randomizer script by Db0. If you use this and you like it, send me a cheers! :)

#define SET_RECRUITS
    #You can use this to set the recruits at any point to the last options. This Macro works by using a variable called "recruits" which is populated with the random recruits in the loop below. This is so that you can have any number of recruit type (archer, util, melee, mounted, etc) instead of just 3

    # Here we initialize our recruits variable to the first table type so that we avoid the extra comma.
    {VARIABLE recruits $recruit_types[0].array[$recruit_types[0].current].type}
    # This is the loop
    {VARIABLE recruit_types_i 1}
    [while]
        [variable]
            name=recruit_types_i
            less_than=$recruit_types.length
        [/variable]
        [do]
            # Now we append the current selection (done with the iteration variable) to the "recruits" variable.
            {VARIABLE recruits $recruits|,$recruit_types[$recruit_types_i].array[$recruit_types[$recruit_types_i].current].type}
            [set_variable]
                name=recruit_types_i
                add=1
            [/set_variable]
        [/do]
    [/while]
    {CLEAR_VARIABLE recruit_types_i}
    # And finally we set the side's recruit options.
    [modify_side]
        side=1
        recruit=$recruits
    [/modify_side]
#enddef

#define FIX_ARRAY_VARIABLE_LENGTH
    # This is needed because the length of the table is always one more than what possible values the array can take. I thus need to reduce the length in a variable so that it does not stop recruiting. This is done through a loop as well so that any number of arrays can be used.
    {FOREACH recruit_types recruit_types_i}
    {VARIABLE recruit_types[$recruit_types_i].size $recruit_types[$recruit_types_i].array.length}
    {VARIABLE_OP recruit_types[$recruit_types_i].size add -1}
    {NEXT recruit_types_i}
#enddef

#define INITIALIZE_RANDOM_RECRUITS
    # This macro sets the first recruits randomly. This way every game starts with different options. Loop again
    {FOREACH recruit_types recruit_types_i}
    [set_variable]
        name=recruit_types[recruit_types_i].current
        rand=0..$recruit_types[recruit_types_i].size
    [/set_variable]
    {NEXT recruit_types_i}
    {SET_RECRUITS}
#enddef

#define CHANGE_RECRUITED_TYPE_EVENT SIDE
    #This is the meat of the trick. This macro changes only the current type of recruits that you recruited. Thus if you recruited an archer, only the archer types will be randomized.
    [event]
        name=recruit
        first_time_only=no
        [filter]
            side={SIDE}
        [/filter]
        {VARIABLE recruit_found no}
        #This variable stores the current recruited unit type which we will use to compare with our possible choices.
        {VARIABLE current_recruit $unit.type}
        {FOREACH recruit_types recruit_types_i}
        # We are now iterating through each general type of recruit (archer, melee etc). Once a match is made (below), the variable "recruit_found" is set and the event aborts so as to not waste much time.
        [if]
            [variable]
                name=recruit_found
                equals=no
            [/variable]
            [then]
                {FOREACH recruit_types[$recruit_types_i].array if_i}
                # Now we are iterating through each specific types of recruit and checking each result to see if it matches.
                [if]
                    [variable]
                        name=current_recruit
                        equals=$recruit_types[$recruit_types_i].array[$if_i].type
                    [/variable]
                    [then]
                        # Now that a match is made, we have found which general type of recruit we will randomize. This is done by setting the next variable, which I've set up as a key in the array. This variable will then in turn be used to modify the side's recruit key.
                        [set_variable]
                            name=recruit_types[$recruit_types_i].current
                            rand=0..$recruit_types[$recruit_types_i].size
                        [/set_variable]
                        {VARIABLE recruit_found yes}
                    [/then]
                [/if]
                {NEXT if_i}
            [/then]
        [/if]
        {NEXT recruit_types_i}
        {CLEAR_VARIABLE recruit_found}
        {CLEAR_VARIABLE current_recruit}
        # And finally, lets put our changes into action.
        {SET_RECRUITS}
    [/event]
#enddef

#define CLEAR_RANDOMIZER_VARIABLES
    # We need to clear our tables at the end of the scenario or we'll end up with leftover recruit types in the next scenario we may not want. This is quite simple since everything is in one table.
    {CLEAR_VARIABLE recruit_types}
#enddef

EVENTS (only one event is needed now but you will have to enter the {CHANGE_RECRUITED_TYPE_EVENT #} under your scenario tag and replace # with the side you want to have their recruits randomized. Beware that if you run this for two or more sides, then all of them will have the same possible recruit choices. Don't forget to put the {CLEAR_RANDOMIZER_VARIABLES} macro in your victory event

Code: Select all

    [event]
        name=prestart

        #The possible list of recruits. We use three types of recruits so that when one is used, not all are modified. Instead of archers, melee and util (Scouts, Mages etc) you could use Orcs, Goblin, Humans for example. Feel free to replace the sample choices for anything else that fits in your own campaign. You can add extra rows and extra generic types as well. Just increase the number of the table or the type.
        # You see the same unit more than once because this way I give this unit type a bigger probability to be selected. This is because a goblin spearman is more common than a thug for example.

#IMPORTANT: Do not put the same type of unit in two different tables. As the checking goes through each table to see what you recruited, it will reset the wrong table.

        {VARIABLE recruit_types[0].array[0].type "Orcish Archer"}
        {VARIABLE recruit_types[0].array[1].type "Woodsman"}
        {VARIABLE recruit_types[0].array[2].type "Poacher"}
        {VARIABLE recruit_types[0].array[3].type "Orcish Archer"}
        {VARIABLE recruit_types[0].array[4].type "Poacher"}

        {VARIABLE recruit_types[1].array[0].type "Goblin Spearman"}
        {VARIABLE recruit_types[1].array[1].type "Goblin Spearman"}
        {VARIABLE recruit_types[1].array[2].type "Thug"}
        {VARIABLE recruit_types[1].array[3].type "Ruffian"}
        {VARIABLE recruit_types[1].array[4].type "Ruffian"}

        {VARIABLE recruit_types[2].array[0].type "Thief"}
        {VARIABLE recruit_types[2].array[1].type "Thief"}
        {VARIABLE recruit_types[2].array[2].type "Footpad"}
        {VARIABLE recruit_types[2].array[3].type "Brigand"}

        {FIX_ARRAY_VARIABLE_LENGTH}

# Comment out the following line if you don't want your initial choices randomized as well
        {INITIALIZE_RANDOM_RECRUITS}
    [/event]
Post Reply