Results 1 to 9 of 9

Thread: 'this' not working when speeding animation

  1. #1

    Default 'this' not working when speeding animation

    I'm trying to set up a script that transfers a unique ancillary from a denouncement target to the inquisitor (same idea for assassination target and assassin). This is what I have:

    Code:
    monitor_event DenouncementMission MissionSucceeded     ;exports inquisitor ID
    and Trait CharacterID_0001 > 0     ;unique trait to identify the inquisitor that will get the ancillary, prevents effects from firing if a different inquisitor does the denouncement
    and I_EventCounter test_anc_on_map == 1     ;this is linked to other monitors which tells us the ancillary is being held by an agent/general and they haven't died by any other means
    
         campaign_wait 5.0     ;it takes around 5 in-game seconds for the target to die and hence for the game to return false for I_WorldwideAncillaryExists
    
         if not I_WorldwideAncillaryExists test_anc     ;unique ancillary, only one on the map at a time
              console_command give_ancillary this test_anc     ;'this' is exported by character_record from DenouncementMission
              historic_event test_event_message
         end_if
    end_monitor
    This script works almost as intended (I haven't tested for assassins, but presumably it would be the same with AssassinationMission MissionSucceeded), it allows me to transfer a unique ancillary from the target to the inquisitor when the inquisitor successfully denounces the target. The problem is that if I left-click the map quickly after the denouncement animation begins to play on the inquisitor strat model (to speed it up), then the give_ancillary command doesn't fire. The historic_event test_event_message still plays which means the 'if not I_WorldwideAncillaryExists' condition is passed, i.e. speeding the animation has no effect on the campaign_wait. If I speed up the animation by left-clicking the map, the log says:

    give_ancillary this test_anc
    err: character not found

    The problem seems to be 'this' not pointing to the correct character at that moment in time when I speed up the animation. If I let the animation play out, 'this' points at the correct character. Obviously, I don't want the script to break if the user speeds up the denouncement animation (it has been my experience that 100% of users speed up strat animations 100% of the time). So, any ideas to address this bug?

  2. #2
    Gigantus's Avatar I am not special - I am a limited edition.
    Patrician took an arrow to the knee spy of the council

    Join Date
    Aug 2006
    Location
    Goa - India
    Posts
    53,125
    Blog Entries
    35

    Default Re: 'this' not working when speeding animation

    Your assumption is correct that interaction will break the 'this' condition. You can speed up animations via script, see here but it will be a 50\50 chance whether it accelerates or slows down, depending on the previous state of acceleration. It might be a better idea to disable user input during the monitor processing, example:
    Code:
        monitor_event whatever
            any conditions
            disable_cursor
            disable_shortcuts true
               do your stuff
            enable_cursor
            disable_shortcuts false
        end_monitor
    Used that a lot during 'map tours' in RotK, to ensure uninterrupted, scripted map movement.
    Last edited by Gigantus; November 22, 2020 at 11:00 AM.










  3. #3

    Default Re: 'this' not working when speeding animation

    I'm getting the same result as before using disable_cursor and disable_shortcuts. If I left-click immediately after accepting the denouncement, it still breaks 'this'. What I suspect is happening is the event is exporting character ID so the correct inquisitor is loaded into the memory used for 'this', but then as soon as I click the map that memory is cleared and 'this' no longer points to any character. So, it's not a problem with the speed of the target's death animation (the inquisitor doesn't actually have a denounce animation from what I can tell, if he does then it's instantaneous, the rate limiting step is clearly the death of the target, until that death animation finishes, the target is still 'alive' for scripting purposes with all their ancillaries on the map) - it's probably a problem with clearing/reloading whatever 'this' takes as an argument. The disable_cursor command doesn't seem to be able to prevent this clearing/reloading.

    Since the rate limiting step is the death animation of the victim, and the death animation isn't skipped and plays at the same speed in fast mode, I don't need to worry about whether the user is in fast or slow mode. The campaign_wait 5 is more than enough to handle the death animation. I actually need to optimize it as the true minimum is probably closer to 3. Edit: actually 5 was the minimum corresponding to the length of the death animation of the merchant (my test target). I will have to test for all other viable target types.


    Edit: I was wrong - disable_cursor does do what it advertises and clicking the map while the cursor is disabled won't do anything, it will not clear the argument for 'this'. However, it's possible to click very fast after hitting Accept Mission, i.e. click after the mission has started but before the result of the mission has fired the DenouncementMission event and hence the disable_cursor command. Clicking this quickly will clear the argument for 'this' and break the script. But you almost have to know about this failure mode to exploit it, I don't think the average user will just start spamming clicks immediately after hitting Accept Mission, so I'm comfortable with considering this issue resolved. I also don't see anyway to address this exploit. We could set up a separate monitor to see if the inquisitor is selected and not any other agent, then set a counter to 1, then if the DenouncementMission fires with the counter == 1 then we know who to transfer the ancillary to. But this will fail if you select the agent from the list of agents and it won't work for the AI. I'm also guessing there is some ingenious way to hit Accept Mission while having a completely different character selected.
    Last edited by Callistonian; November 22, 2020 at 12:27 PM.

  4. #4
    Gigantus's Avatar I am not special - I am a limited edition.
    Patrician took an arrow to the knee spy of the council

    Join Date
    Aug 2006
    Location
    Goa - India
    Posts
    53,125
    Blog Entries
    35

    Default Re: 'this' not working when speeding animation

    In the code you are providing there is no indication that input by the user is required - what you mention is the input of a yes\no event that I don't see here. If so then it should be fairly easy to disable input using the 'while' method of checking for response. Underneath such a structure from EBII, heavily abbreviated by me:
    Code:
        ; --- Warleader election request ---
        monitor_event whatever
                historic_event HE_f_carthage_warleader_needed true                 ; yes\no message pop up
    
            while I_EventCounter HE_f_carthage_warleader_needed_accepted = 0     ; while-loop to pause the script until a decision is made
                and I_EventCounter HE_f_carthage_warleader_needed_declined = 0
            end_while
    
            if I_EventCounter HE_f_carthage_warleader_needed_accepted = 1
    insert disabling here
                do denouncement stuff and transfer
    enable
            end_if
            if I_EventCounter HE_f_carthage_warleader_needed_declined = 1
             do other stuff stuff
            end_if
        end_monitor
    In other words: as soon as the user has accepted his input will be disabled.

    On the other hand I am wondering why you can't use a simple counter system to get the deed done seeing that the character has a unique trait:

    denouncement event creates counter
    character check asks for trait and counter and gives ancillary, resets counter
    Last edited by Gigantus; November 22, 2020 at 12:51 PM.










  5. #5

    Default Re: 'this' not working when speeding animation

    In order to denounce (or assassinate) a target, you must push a button in the dialogue scroll next to the Success Rate number. The tooltip for this button says Accept Mission (at least in vanilla). This is the required user input. The problem is not disabling user input until they hit that button, it's disabling user input after they hit that button and until the effects fire (5 seconds later when the target's death animation finishes) because, at least in my working theory, clicking anywhere will clear the argument for 'this' and thus prevent the transfer of the ancillary.

    I'm now getting conflicting results using disable_cursor. Sometimes I can clear the argument for 'this' (breaking the script) by clicking while the cursor is disabled (not clicking immediately after Accept Mission, but waiting a couple seconds but before the effects fire), and sometimes I can't (script works even while spamming the left-click in that time window).


    Edit: I don't know why this didn't occur to me sooner, but since I'm uniquely identifying the inquisitor by a unique trait, I don't need to use 'this' at all so the whole question about clearing the argument for 'this' by clicking is academic.
    Last edited by Callistonian; November 22, 2020 at 01:09 PM.

  6. #6
    Gigantus's Avatar I am not special - I am a limited edition.
    Patrician took an arrow to the knee spy of the council

    Join Date
    Aug 2006
    Location
    Goa - India
    Posts
    53,125
    Blog Entries
    35

    Default Re: 'this' not working when speeding animation

    Yeah, that's why I ruminated about the trait. Thanks for clarifying that it is actually the confirmation of the denounce action itself that you meant when you mentioned the 'accept' option. In that case it should work if you disable the interface even before the campaign_wait command in your monitor but frmo your testing it would appear that it takes a while before the event actually finishes.

    Which means you would have to test for the clicking of that accept button to disable stuff. Here an example from 1648 on how we clicked the 'fight' button for the user on the prebattle scroll after disabling his input
    Code:
        ;--- Keine Feigheit vor dem Feind ---
        declare_counter hist_schlacht
        monitor_event ScrollOpened ScrollOpened prebattle_scroll
            if I_CompareCounter hist_schlacht = 1
                campaign_wait 1
                disable_cursor
                ui_flash_start prebattle_fight_button
                campaign_wait 3
                select_ui_element prebattle_fight_button
                simulate_mouse_click lclick_down
                simulate_mouse_click lclick_up
            end_if
            enable_cursor
            set_counter hist_schlacht 0
            
        end_monitor
    With some creative scripting it might be possible to do something similar, provided it's possible to identify that scroll and the button.

    In the meantime use the character's trait
    Last edited by Gigantus; November 22, 2020 at 07:35 PM.










  7. #7
    Withwnar's Avatar Script To The Waist
    Join Date
    Oct 2008
    Location
    Earth
    Posts
    6,329

    Default Re: 'this' not working when speeding animation

    "this" only means "the currently selected character", not necessarily "the character this monitor is firing on". When you click off him you're deselecting him so "this" no longer refers to anybody. Or worse, instead of clicking off him you could click on somebody else and so now "this" means them and they would have gotten the anc.

    For the record, e_select_character selects the character that the monitor is firing on. So you could have done this...
    Code:
    e_select_character
    console_command give_ancillary this test_anc
    ...but from memory e_select_character is not always reliable.

  8. #8

    Default Re: 'this' not working when speeding animation

    Quote Originally Posted by Withwnar View Post
    "this" only means "the currently selected character", not necessarily "the character this monitor is firing on".
    Well that explains it. Time to review every instances of 'this' in CS. I'm sure any bugs arising from improper use of 'this' would have been a nightmare to diagnose had I not known. Thank you so much for informing me.

    One of the obvious problems with the e_select_character workaround is that it rules out AI-compatibility. This thread may be what you're remembering about e_select- commands having issues.

  9. #9
    Withwnar's Avatar Script To The Waist
    Join Date
    Oct 2008
    Location
    Earth
    Posts
    6,329

    Default Re: 'this' not working when speeding animation

    This is what I was remembering.

    One of the obvious problems with the e_select_character workaround is that it rules out AI-compatibility.
    So does "this" because AI characters are never selected.

Posting Permissions

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