Results 1 to 7 of 7

Thread: Is it still possible to "steal" ancillaries from fallen enemies?

  1. #1

    Default Is it still possible to "steal" ancillaries from fallen enemies?

    Considering that the GeneralWithAncKilled condition allegedly does not work at all, has anyone found another way to effectively make ancillaries be taken from one general by another during a battle?

    In RTW's Lord of the Rings mod, they used a simple "
    I_WorldwideAncillaryExists" to determine when a certain ancillary had ceased to exist, and then give it to the first general who won a battle after said ancillary no longer exists. In theory, this should work to effectively let you steal the ancillary from the enemy general whom you kill in battle, however there are several problems with that approach. For one, it only works if you fight the battle manually, otherwise you won't get the ancillary and the next general who wins a totally unrelated battle will. For two, it only works if you win the battle on top of killing the enemy general. And lastly, it requires that someone always have this ancillary, because the moment no one has it, the next general who wins a battle will get it. This is a problem because I might want to keep the ancillary out of the campaign for a time.

    Is there some standard method that seasoned modders tend to use instead? I would assume "
    I_WorldwideAncillaryExists" in combination with something else, perhaps.

  2. #2

    Default Re: Is it still possible to "steal" ancillaries from fallen enemies?

    GeneralWithAncKilled always returns true no matter what arguments you supply it. Simply using 'not I_WorldWideancillaryExists' to give the ancillary to whomever wins the next battle is the naïve approach that proliferated around 2010 when people realized that GeneralWithAncKilled is completely broken. Although it has a high failure rate (the anc going to the wrong character), that approach has the virtue of simplicity and it works for the AI. There have been improvements on the concept since then but it's still an advanced bit of scripting and there is no generally agreed upon optimal solution. How you implement ancillary stealing depends on the needs of your mod - if only a small selection of characters with known labels can hold the anc, the solution is almost trivial, if you want an entire class of characters (like all named characters or all assassins or etc.) to be able to hold the anc, it becomes more complicated but still possible.

    The approach I favor is to check that the ancillary still exists when PostBattle fires, then wait 4-5 seconds for characters to finish their strat death animations, and then check again if the ancillary exists. If it did exist at PostBattle, but not 4-5 seconds later, then whomever had the ancillary must have died as a result of the battle. Since PostBattle exports character_record, we can use e_select_character to select the winner of the battle (named character in command of the army) and then use 'this' to give the ancillary to the selected character. This won't work for the AI since AI characters can't be selected, but PostBattle also exports faction type so we can use the same monitor to give the ancillary to an AI faction leader (or etc.). Or, if you know who the character is, you can just send it to his label without using selection and 'this'. The principle of checking if the ancillary exists, waiting a few seconds, and then checking again can also be used for assassination missions and denouncement missions to transfer ancillaries between agents. You can also add conditions like WonBattle to the PostBattle monitor for general-to-general anc stealing so that it only transfers for victories and is lost otherwise. I suggest pairing these monitors with an event counter that continuously tracks the status of the ancillary - held by a faction, off map, destroyed, etc.

    Here's an example where we know the faction who won the battle but not the specific named character, so we use selection.

    Code:
        monitor_event PostBattle WonBattle                                            ;this also handles auto-resolved battles
        and FactionType turks
            if I_EventCounter one_ring_status == -1                                    ;terminate if Ring is destroyed
                terminate_monitor
            end_if
            if I_WorldwideAncillaryExists one_ring                                    ;this tells us the anc wasn't lost in any other way prior to the battle
                if not I_IsFactionAIControlled turks
                    e_select_character                                                ;e_select_character only works for human factions
                    campaign_wait 4.0                                                ;minimized for length of general death animation (in residence == 2.0, field battle = 4.0)
                    e_select_character
                    if not I_WorldwideAncillaryExists one_ring                        ;4 seconds later the anc no longer exists, this means the holder must have died as a result of the battle
                        console_command logon password                                ;in case the user password-locked the console for hotseat
                        console_command give_ancillary this one_ring                ;if faction is human, Ring goes to general who won the battle
                        if I_WorldwideAncillaryExists one_ring                        ;still not guaranteed that Ring was transferred, the general may already have max ancillaries
                            historic_event general_capture_ring factions { turks, }
                            inc_event_counter general_steals_ring 1                    ;CALL: general_steals_ring, send out news to other participating factions
                        end_if
                    end_if
                end_if
                if I_IsFactionAIControlled turks
                    campaign_wait 4.0
                    if not I_WorldwideAncillaryExists one_ring
                        set_event_counter edain_leader_to_get_one_ring 1            ;schedule AI-Edain leader to get the Ring in an EDA trigger
                    end_if
                end_if
            end_if
        end_monitor
    And here is an example where we know the label of an inquisitor who stole the ancillary.

    Code:
        monitor_event DenouncementMission MissionSucceeded                            ;inquisitor takes the Ring from a denounced target
        and Trait NazgulEpithet == 1                                                ;identify inquisitor who made the kill
        and I_EventCounter one_ring_status > 200                                    ;Ring is held by a foreign agent
        and I_WorldwideAncillaryExists one_ring                                   ;ancillary exists when denouncement mission ends
            campaign_wait 5                                                            ;target is only dead once their death animation finishes playing out, this takes 5 seconds
            if not I_WorldwideAncillaryExists one_ring
                console_command logon password
                console_command give_ancillary nazgul_1 one_ring     ;we know this character so just give it to them directly without using selection, this works for the AI
                if I_WorldwideAncillaryExists one_ring
                    if not I_IsFactionAIControlled england
                        historic_event nazgul_1_finds_ring factions { england, }
                    end_if
                    inc_event_counter nazgul_find_ring 1                            ;CALL: nazgul_find_ring
                end_if
            end_if
        end_monitor
    Last edited by Callistonian; June 24, 2021 at 09:31 AM.

  3. #3

    Default Re: Is it still possible to "steal" ancillaries from fallen enemies?

    Quote Originally Posted by Callistonian View Post
    GeneralWithAncKilled always returns true no matter what arguments you supply it. Simply using 'not I_WorldWideancillaryExists' to give the ancillary to whomever wins the next battle is the naïve approach that proliferated around 2010 when people realized that GeneralWithAncKilled is completely broken. Although it has a high failure rate (the anc going to the wrong character), that approach has the virtue of simplicity and it works for the AI. There have been improvements on the concept since then but it's still an advanced bit of scripting and there is no generally agreed upon optimal solution. How you implement ancillary stealing depends on the needs of your mod - if only a small selection of characters with known labels can hold the anc, the solution is almost trivial, if you want an entire class of characters (like all named characters or all assassins or etc.) to be able to hold the anc, it becomes more complicated but still possible.

    The approach I favor is to check that the ancillary still exists when PostBattle fires, then wait 4-5 seconds for characters to finish their strat death animations, and then check again if the ancillary exists. If it did exist at PostBattle, but not 4-5 seconds later, then whomever had the ancillary must have died as a result of the battle. Since PostBattle exports character_record, we can use e_select_character to select the winner of the battle (named character in command of the army) and then use 'this' to give the ancillary to the selected character. This won't work for the AI since AI characters can't be selected, but PostBattle also exports faction type so we can use the same monitor to give the ancillary to an AI faction leader (or etc.). Or, if you know who the character is, you can just send it to his label without using selection and 'this'. The principle of checking if the ancillary exists, waiting a few seconds, and then checking again can also be used for assassination missions and denouncement missions to transfer ancillaries between agents. You can also add conditions like WonBattle to the PostBattle monitor for general-to-general anc stealing so that it only transfers for victories and is lost otherwise. I suggest pairing these monitors with an event counter that continuously tracks the status of the ancillary - held by a faction, off map, destroyed, etc.

    Here's an example where we know the faction who won the battle but not the specific named character, so we use selection.

    Code:
        monitor_event PostBattle WonBattle                                            ;this also handles auto-resolved battles
        and FactionType turks
            if I_EventCounter one_ring_status == -1                                    ;terminate if Ring is destroyed
                terminate_monitor
            end_if
            if I_WorldwideAncillaryExists one_ring                                    ;this tells us the anc wasn't lost in any other way prior to the battle
                if not I_IsFactionAIControlled turks
                    e_select_character                                                ;e_select_character only works for human factions
                    campaign_wait 4.0                                                ;minimized for length of general death animation (in residence == 2.0, field battle = 4.0)
                    e_select_character
                    if not I_WorldwideAncillaryExists one_ring                        ;4 seconds later the anc no longer exists, this means the holder must have died as a result of the battle
                        console_command logon password                                ;in case the user password-locked the console for hotseat
                        console_command give_ancillary this one_ring                ;if faction is human, Ring goes to general who won the battle
                        if I_WorldwideAncillaryExists one_ring                        ;still not guaranteed that Ring was transferred, the general may already have max ancillaries
                            historic_event general_capture_ring factions { turks, }
                            inc_event_counter general_steals_ring 1                    ;CALL: general_steals_ring, send out news to other participating factions
                        end_if
                    end_if
                end_if
                if I_IsFactionAIControlled turks
                    campaign_wait 4.0
                    if not I_WorldwideAncillaryExists one_ring
                        set_event_counter edain_leader_to_get_one_ring 1            ;schedule AI-Edain leader to get the Ring in an EDA trigger
                    end_if
                end_if
            end_if
        end_monitor
    And here is an example where we know the label of an inquisitor who stole the ancillary.

    Code:
        monitor_event DenouncementMission MissionSucceeded                            ;inquisitor takes the Ring from a denounced target
        and Trait NazgulEpithet == 1                                                ;identify inquisitor who made the kill
        and I_EventCounter one_ring_status > 200                                    ;Ring is held by a foreign agent
        and I_WorldwideAncillaryExists one_ring                                   ;ancillary exists when denouncement mission ends
            campaign_wait 5                                                            ;target is only dead once their death animation finishes playing out, this takes 5 seconds
            if not I_WorldwideAncillaryExists one_ring
                console_command logon password
                console_command give_ancillary nazgul_1 one_ring     ;we know this character so just give it to them directly without using selection, this works for the AI
                if I_WorldwideAncillaryExists one_ring
                    if not I_IsFactionAIControlled england
                        historic_event nazgul_1_finds_ring factions { england, }
                    end_if
                    inc_event_counter nazgul_find_ring 1                            ;CALL: nazgul_find_ring
                end_if
            end_if
        end_monitor
    I need something that lets any general steal the ancillary without distinction, so I fear these label-specific methods will not do... Also I have no desire of making this type of acquisition a privilege of the player faction.

    I trust those are still the best methods around, is that it?

  4. #4

    Default Re: Is it still possible to "steal" ancillaries from fallen enemies?

    Getting general-to-general anc stealing to work for unlabeled AI characters is difficult because, to recap the thought process underlying my approach: the GeneralWithAncKilled condition doesn't work, therefor we need a way to test if the general holding the anc died as a result of the battle and by no other means, and the only way to test this (that I've seen so far) is by using sequential I_WorldWideAncillaryExists conditions that return different results and are only separated by a wait for the strat death animations, and this can obviously only be set up in CS and not in a trigger, and the only way to directly give an ancillary to an unlabeled character in CS is by using 'this', and the only way to use 'this' is by selecting the character, and only human-controlled characters can be selected. My script uses an event counter to schedule the anc transfer for an AI faction, but it's not instantaneous and it doesn't transfer to the character who won the battle.

    If you could hack the game, the easiest solution to all of this would be to just fix the GeneralWithAncKilled condition. Another solution would be to assign a label to the character exported by the PostBattle event and then use the label to give the ancillary in CS instead of having to select them and use 'this'. As long as we're in the magical world of altering the game engine, you could even create a new type of 'this' that works for all script commands instead of just give_trait/give_ancillary and refers to the character exported by the event instead of the currently selected character, and that would be extremely useful for manipulating unlabeled characters in CS.

  5. #5

    Default Re: Is it still possible to "steal" ancillaries from fallen enemies?

    Quote Originally Posted by Callistonian View Post
    Getting general-to-general anc stealing to work for unlabeled AI characters is difficult because, to recap the thought process underlying my approach: the GeneralWithAncKilled condition doesn't work, therefor we need a way to test if the general holding the anc died as a result of the battle and by no other means, and the only way to test this (that I've seen so far) is by using sequential I_WorldWideAncillaryExists conditions that return different results and are only separated by a wait for the strat death animations, and this can obviously only be set up in CS and not in a trigger, and the only way to directly give an ancillary to an unlabeled character in CS is by using 'this', and the only way to use 'this' is by selecting the character, and only human-controlled characters can be selected. My script uses an event counter to schedule the anc transfer for an AI faction, but it's not instantaneous and it doesn't transfer to the character who won the battle.

    If you could hack the game, the easiest solution to all of this would be to just fix the GeneralWithAncKilled condition. Another solution would be to assign a label to the character exported by the PostBattle event and then use the label to give the ancillary in CS instead of having to select them and use 'this'. As long as we're in the magical world of altering the game engine, you could even create a new type of 'this' that works for all script commands instead of just give_trait/give_ancillary and refers to the character exported by the event instead of the currently selected character, and that would be extremely useful for manipulating unlabeled characters in CS.
    I think I don't grasp precisely what you are saying.

    Is there any possible way for a general to die of causes not related to the battle in the timespan between the battle ends and the time the death animation ends? As far as I know, the game is frozen in the present turn and doesn't allow further action until the animation is finished.

    My script uses an event counter to schedule the anc transfer for an AI faction, but it's not instantaneous and it doesn't transfer to the character who won the battle.
    What do you mean here? Maybe I could use this.

  6. #6

    Default Re: Is it still possible to "steal" ancillaries from fallen enemies?

    Quote Originally Posted by es157
    Is there any possible way for a general to die of causes not related to the battle in the timespan between the battle ends and the time the death animation ends?
    No, there isn't. But you're missing the point. We want to check that the ancillary exists at the time the PostBattle event fires, and then that it doesn't exist several seconds later when the generals involved in the battle have finished dying. If it exists at PostBattle but then doesn't exist several seconds later, then the only possibility is that whoever had it died in the battle. This is precisely because the game essentially pauses and prevents user input during those seconds, so the only possible way that I_WorldWideAncillaryExists returns true at PostBattle and false a few seconds later is that the general died in the battle. If we know that the general holding the anc died in the battle, then we can confidently give the anc to the general who won the battle. Conversely, if we don't know that the general holding the anc died in the battle, then we don't know who should get the anc after a battle (or after any other event). If all we do is check PostBattle with I_WorldWideAncillaryExists returning false (anc doesn't exist), then we will end up giving the anc to some random guy who wins a battle - we have no idea if the general formerly holding the ancillary died as a result of the battle or as a result of any other random cause of death on the other side of the map.

    Here's what's happening sequentially:

    1. PostBattle event fires, we check if the ancillary exists on the map - it does exist
    2. we wait a few seconds for any generals killed in the battle to finish dying on the strat map, during this time nothing else happens on the map
    3. we check again if the ancillary exists, if it does still exist then whoever is holding it didn't die, but if it doesn't exist then whoever was holding it did die in the battle
    4. we give the ancillary to whoever won the battle

    Now for that final step #4, how we give the ancillary depends on whether the faction is human or AI controlled since we're not using labels. If we're using labels, it's easy for human and AI but we're limited to a small set of participating characters. But if we don't know who the character is, then we can select him and give the ancillary to 'this' (the selected character) if he's human-controlled. If he's AI controlled, I use an event counter as shown in my first monitor. There is a simple EDA trigger that checks when this counter is set to 1 and gives the AI faction leader the ancillary at the start of their next turn (or end of current turn). I then have another script portion that checks if the ancillary exists and the counter == 1 and then resets the counter to 0 so the process can loop.

  7. #7

    Default Re: Is it still possible to "steal" ancillaries from fallen enemies?

    Well, to be more clear, I'm not completely against characters "finding" the trait after winning a random battle as opposed to stealing it in the right battle. I was thinking of doing just that by using the 2010 method, in case I could not find a better solution. Admitted, it's a bit lame, but it worked fine in LoTR TW.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •