Results 1 to 6 of 6

Thread: Common Causes of Script CTDs

  1. #1

    Icon4 Common Causes of Script CTDs

    SCRIPTING CTD CAUSES

    People think that scripts causes a lot of ctds and they are sometimes afraid to use them, but in fact there are very few scripting commands that can cause ctds, and most of them are related to mistakes in other files related to advices, buildings, units, traits...
    These are the only ctd causes that I have ever found in my scripts:

    1) advance_advice_thread Advice_Thread
    if there is something wrong with the advice thread
    2) spawn_army or spawn_character
    with a wrong character name or wrong unit name
    3) console_command create_unit Settlement "unit name" 1
    if there is something wrong with the unit
    4) console_command create_building Settlement building_name
    if there is something wrong with the building
    5) console_command give_ancillary Character ancillary_name
    if there is something wrong with the ancillary
    6) console_command give_trait Character trait_name 1
    if there is something wrong with the trait

    7) move or reposition_character cause ctds if the character does not exist (or it is died). Better use console_command move_character that can not cause ctds.
    8) to spawn admirals (with ships) could cause ctds when other ships try to attack them, because they are created as if they where land units, in stead of naval units.

    That I know, it does not matter if you use a name that does not exist with other commands like kill_character or move_character, or if the name of the faction is wrong using diplomatic_stance, control, or add_money, or if the settlement name is wrong when you use add_population, capture_settlement... Only the commands listed above seems to cause ctds when they are wrong.
    However, there are many commands I have never used, so other known ctd causes will be welcome.


    Just checking those 8 script commands, I think you could avoid most of the random CTDs with no error message caused by scripts.
    Last edited by Bardo; November 07, 2012 at 07:50 PM.

  2. #2

    Default Re: Common Causes of Scirpt CTDs

    Adendum

    METHOD TO LAUNCH SCRIPTS ALMOST AUTOMATICALLY

    Using this method:
    -If you start the campaign (not from a saved game), then scripts are automatically loaded up.
    -If you load a savegame: the advisor appears automatically when you select any unit or settlement or when you press any button (even end turn button).
    You just need to click on the advisor to activate the background scripts. (No need to press show_me_how)
    -If you Reload a savegame without exiting the game, then the scripts are automatically relaunched.

    All this method is based on the use of 'on_display' to trigger the script without pressing show_me_how button (thanks to HouseOfHam for the awesome discovery). And also based on the use of 'declare_show_me' inside the script so the advice is opened automatically without clicking the advisor portrait.


    Export_descr_advice.txt
    Spoiler Alert, click show to read: 
    ;===============================================================
    ;== ADVICE THREAD DATA STARTS HERE ==
    ;===============================================================

    ;------------------------------------------ LOTR-TW
    AdviceThread Lotr_Script_Thread
    GameArea Campaign

    Item Lotr_Script_Text_01
    Uninhibitable
    Verbosity 0
    Threshold 2
    Attitude Excited
    Presentation Default
    Title Lotr_Script_Text_01_Title
    On_display scripts\show_me\background_script.txt
    Text Lotr_Script_Text_01_Text1

    ;===============================================================
    ;== TRIGGER DATA STARTS HERE ==
    ;===============================================================

    ;------------------------------------------ LOTR-TW trigger
    Trigger Reload_Script_Trigger1
    WhenToTest SettlementSelected

    AdviceThread Lotr_Script_Thread 1

    ;------------------------------------------ LOTR-TW trigger
    Trigger Reload_Script_Trigger2
    WhenToTest CharacterSelected

    AdviceThread Lotr_Script_Thread 1

    ;------------------------------------------ LOTR-TW trigger

    Trigger Reload_Script_Trigger3
    WhenToTest ButtonPressed

    AdviceThread Lotr_Script_Thread 1

    ;------------------------------------------ LOTR-TW trigger
    Trigger Reload_Script_Trigger
    WhenToTest GameReloaded

    AdviceThread Lotr_Script_Thread 0



    Campaign Script (placed in the campaign folder)
    Spoiler Alert, click show to read: 
    script

    declare_show_me

    ;...

    wait 1
    console_command trigger_advice Lotr_Script_Thread
    advance_advice_thread Lotr_Script_Thread no_dismiss


    end_script



    Background Script (placed into \scripts\show_me)
    Spoiler Alert, click show to read: 
    script

    wait 1
    select_ui_element advisor_dismiss_button
    simulate_mouse_click lclick_up

    ; This is the important one, needed so the text of the advice can be opened automatically;
    declare_show_me

    ;This is needed when you reload games without exiting the game, it disables the script of the previous game, and it allows the new script to be launched inmediately. Without this monitor, the script is not activated until end of turn;
    monitor_event GameReloaded TrueCondition
    terminate_script
    end_monitor



    while I_TurnNumber < 1000
    ;... We use a turn per year script inside this loop, but I think it is not relevant.
    end_while

    end_script


    This method is currently used in LOTR-TW. Tested and working. Scripts not completely automatic, but really close.


    More info about scripts

    IMPLEMENTING SCRIPTS

    -The most important when you implement a "monitor_event" is to check the "Trigger requirements:" of the condition you want to use (looking at docudemon_conditions.txt),
    and verify that this requeriment s included in the "Exports:" of the event used to trigger the monitor (looking at docudemon_events.txt).
    Conditions starting by "I_" do not need requeriments from the event, and so they can be used with "if" and "while" statements.
    -The condition RandomPercent can be used without any requeriments, like all conditions starting by I_
    -WorldwideAncillaryExists does not need any Trigger requirements (even when the docudemon_conditions.txt says character_record). I use the next syntaxis and it works as expected (I'm sure):
    Code:
    monitor_event PreBattlePanelOpen WorldwideAncillaryExists one_ring true
       and not WorldwideAncillaryExists lost_ring true
       ;code here
    end_monitor
    -The condition that triggers a "monitor_conditions" can not be changed inside the monitor, so it needs the command "terminate_monitor" to avoid being executed for ever.
    If you want the monitor to be triggered more than once you need to use a "monitor_event".
    Code:
    monitor_conditions I_CompareCounter no = 1
       ;code here executed up to one time until you reload the script
       terminate_monitor
    end_monitor
    -The condition SettlementName uses the Name showed in the strat map (look at ...\text\region and settlement names.txt), not the internal name of the settlement like other commands related to settlements.
    Note it does work with CharacterTurnEnd but does not with CharacterTurnStart (the later does not export the settlement)
    -The event GeneralCaptureSettlement is triggered no matter the type of character: general, named character or family.

    -Moving characters:
    1) move: it uses the standard movement points of the character to try to reach the destiny. So it has to be used during the turn of the character you want to move, and it will not work if the character is far from the target possition (it is equal to select the character and click the right button over the target coordinates). If the character is the commander of his army, all the army will be moved, if not, only the character will move.
    This is the only command that allows you to move a character in and out of a settlement or an army.
    2) console_command move_character: In this case the character is teleported to the target possition, no matter the movement points or the availability of a path, but it does nothing if the character is not the commander of his army, or if the character is inside a settlement.
    If the character is moved over an occupied tile (or over a city), the armies do not merge (nor enter into the city). In stead the moved army stand over them, and then you have to select them using the character browser, because sometimes it is not possible to click them directly.
    This command sometimes makes the moved character invisible. It seems random, but related to characters teleported when they are sieging or hidden in forests, or in a occupied tile. However, this effect dissapears after reload and it do not cause ctds (that I know).
    3) reposition_character: the same than move_character, but it could cause ctds if the character does not exist, and probably in some other cases too, I do not use it.


    SUGGESTIONS

    -When you are at the console command interface, if you press up-arrow you can see all the commands that have been executed previously, in the order they have been launched.
    By using this with a script, you can check if monitors containing a console_command are working, and when they are triggered.
    -use console_command toggle_fow and toggle_perfect_spy to view all the info about armies and settlements in the strat map.


    DESIGNING SCRIPTS

    Since counters are not stored when you save and reload the game, we need some workarround to save script's state upon reloads. There are several options, both with pros and cons:

    1)Buildings/plugins: condition checked from an event that exports the settlement. They can be created but not destroyed by script. They can be permanent if hinterland_buildings.
    (console_command set_building_health Settlement building -1 does not destroy it)
    2)Traits: condition checked from an event that exports the character_record. They can be created and removed by script, but they are not permanent since the characters can die.
    3)Ancillaries: can be checked from ANY event using WorldwideAncillaryExists (except from trait triggers). They can be created by script, but the only way to destroy them is to kill the character. As traits, non permanent.

    In our mod, we use a hidden city in the top-right corner with a special character who we can use to save a lot of info about the scripts: using buildings with the city, traits and ancillaries with the character (since we know his name we can kill and respawn him), and even changing and checking his possition in the map.
    Very useful, but only recomended for heavy scripted mods

    -To detect the owner for a certain retinue: the retinue should affect one Attribute of the character not affected by any other aspect of the game,
    usually "SenateStanding", "PopularStanding", "Electability" (without senate) or "NavalCommand".
    -The console_command "diplomatic_stance faction1 faction2 allied" does not change the attitude of one faction against the other, just the alliance agreement, so it is a bit useless to avoid attacks from the ai factions.
    -To check that a certain character is placed near a certain position, without using settlements: you can try to move the target character to the target possition in the map, then wait for the movement, and then to check if the character has arrived to the destination, by using "not I_CharacterTypeNearTile" before the movement, and "I_CharacterTypeNearTile" after the movement. If the character has not arrive in this time is because he was not near that tile.
    -The commands "wait" or "campaign_wait" do not stop the campaign, just the scripts, and they should not be used inside a monitor, nor during AI turn.
    Also, it seems that script's variables are not updated correctly while the "wait" is called from the inside of an "if" sentence.


    EXAMPLES
    Some examples from our scripts, that could be useful for someone else

    FORCE OCCUPY
    Spoiler Alert, click show to read: 
    Code:
    ;**********************************************
    ; FORCE OCCUPY
    ; Avoid the human player to exterminate/enslave while playing certain factions: seleucid, macedon and thrace in this case
    ;**********************************************
    
    script
    
    declare_counter player
    set_counter player 1
    declare_counter scroll
    set_counter scroll 0
    
    monitor_event FactionTurnStart FactionIsLocal
       set_counter player 1
    end_monitor
    monitor_event FactionTurnEnd FactionIsLocal
       set_counter player 0
    end_monitor
    
    monitor_event ScrollOpened ScrollOpened loot_settlement_scroll
       if I_LocalFaction seleucid
          set_counter scroll 1
       end_if
       if I_LocalFaction macedon
          set_counter scroll 1
       end_if
       if I_LocalFaction thrace
          set_counter scroll 1
       end_if
    end_monitor
    
    monitor_conditions I_CompareCounter player = 1
       and I_CompareCounter scroll = 1
       set_counter scroll 0
       select_ui_element loot_settlement_occupy_button
       simulate_mouse_click lclick_down
       simulate_mouse_click lclick_up
    end_monitor
    
    while TrueCondition
    end_while
    
    script

    GARRISON SCRIPT
    Spoiler Alert, click show to read: 
    Code:
    ;**********************************************
    ; GARRISON SCRIPT
    ;**********************************************
    
    script
    
    declare_counter City1Besiged
    set_counter City1Besiged 0
    declare_counter City2Besiged
    set_counter City2Besiged 0
    ;...per settlement
    
    monitor_event FactionTurnEnd FactionType [faction1]
    and I_LocalFaction [faction1]
    
       if I_CompareCounter City1Besiged = 0
          and not I_SettlementOwner [city1] = [faction1]
          if I_CharacterTypeNearTile [faction1] general,  2 x1,y1
             set_counter City1Besiged 1
          end_if
          if I_CharacterTypeNearTile [faction1] family,  2 x1,y1
             set_counter City1Besiged 1
          end_if
       end_if
       if I_CompareCounter City1Besiged = 2
          and not I_CharacterTypeNearTile [faction1] family, 2 x1,y1
          and not I_CharacterTypeNearTile [faction1] general, 2 x1,y1
          set_counter City1Besiged 0
       end_if
    
       if I_CompareCounter City2Besiged = 0
          and not I_SettlementOwner [city2] = [faction1]
          if I_CharacterTypeNearTile [faction1] general,  2 x2,y2
             set_counter City2Besiged 1
          end_if
          if I_CharacterTypeNearTile [faction1] family,  2 x2,y2
             set_counter City2Besiged 1
          end_if
       end_if
       if I_CompareCounter City2Besiged = 2
          and not I_CharacterTypeNearTile [faction1] family, 2 x2,y2
          and not I_CharacterTypeNearTile [faction1] general, 2 x2,y2
          set_counter City2Besiged 0
       end_if
       ;...per settlement
    
    end_monitor
    ;...a monitor per possible local faction
    
    monitor_event SettlementTurnEnd SettlementName [city1-mapname]
       and I_CompareCounter City1Besiged = 1
       and GarrisonSettlementRatio < 0.5
          if I_SettlementOwner [city1] = [faction1]
             console_command create_unit [city1] "unit name" 4
             console_command add_money -2000       
             console_command add_population City -1500
          end_if
          if I_SettlementOwner [city1] = [faction2]
             console_command create_unit [city1] "unit name" 4
             console_command add_money -2000       
             console_command add_population City -1500
          end_if
          set_counter City1Besiged 2
          ;...an if per faction
    end_monitor
    
    monitor_event SettlementTurnEnd SettlementName [city2-mapname]
       and I_CompareCounter City2Besiged = 1
       and GarrisonSettlementRatio < 0.5
          if I_SettlementOwner [city2] = [faction1]
             console_command create_unit [city1] "unit name" 4
             console_command add_money -2000       
             console_command add_population City -1500
          end_if
          if I_SettlementOwner [city2] = [faction2]
             console_command create_unit [city1] "unit name" 4
             console_command add_money -2000       
             console_command add_population City -1500
          end_if
          ;...an if per faction
          set_counter City2Besiged 2
    end_monitor
    ;...a monitor per settlement
    
    
    while TrueCondition
    end_while
    
    end_script

    CHECK CHARACTER POSSITION
    Spoiler Alert, click show to read: 
    Code:
    ;**********************************************
    ; CHECK CHARACTER POSSITION
    ; show_me script
    ;**********************************************
    
    ;(This script does work:)
    script 
    
    declare_counter Character_moved
    set_counter Character_moved 0
    
       if not I_CharacterTypeNearTile faction named_character, 0 116,154
          set_counter Character_moved 1
          move Character, 116,154
       end_if
    
       campaign_wait 5
    
       if I_CharacterTypeNearTile germans named_character, 0 116,154
          and I_CompareCounter Character_moved = 1
          console_command give_ancillary Character ancillary
       end_if
    
    end_script
    
    
    ;(This script do the same, but does not work when the wait is placed inside the if... weird)
    script
    
       if not I_CharacterTypeNearTile faction named_character, 0 116,154
          set_counter Character_moved 1
          move Character, 116,154
    
          campaign_wait 5
    
          if I_CharacterTypeNearTile germans named_character, 0 116,154
             console_command give_ancillary Character ancillary
          end_if
       end_if
    
    end_script


    You can find all my scripts into this patch, so people do not need the whole mod if just interested in the scripts: http://www.mediafire.com/?uzzwg0nemmz
    (I'm tired of downloading hundreds of Megas from other mods just to look at the scripts...)
    Last edited by Bardo; November 26, 2009 at 04:11 AM.

  3. #3

    Default Re: Common Causes of Scirpt CTDs

    great job bardo ! Will come in very handy !

    +rep if i can

  4. #4

    Default Re: Common Causes of Scirpt CTDs

    Really useful information. Thanks a lot. + Rep too!

  5. #5

    Default Re: Common Causes of Scirpt CTDs

    Ironic enough, you`ve written script wrong in the title.
    Good initiative btw!

  6. #6
    Squid's Avatar Opifex
    Patrician Artifex Technical Staff

    Join Date
    Feb 2007
    Location
    Frozen waste lands of the north
    Posts
    17,760
    Blog Entries
    3

    Default Re: Common Causes of Script CTDs

    That was me not Bardo and I've fixed my typo.
    Under the patronage of Roman_Man#3, Patron of Ishan
    Click for my tools and tutorials
    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe." -----Albert Einstein

Posting Permissions

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