-
An Intermediate Guide to Scripting
AN INTERMEDIATE GUIDE TO SCRIPTING
BACKGROUND SCRIPTS
By Epistolary Richard & Myrddraal
___________________________
In A Beginner Guide to Scripting we identified two different types of scripts: campaign scripts and show_me scripts, and went further to divide show_me scripts into event scripts and background scripts.
The Beginner Guide taught us the basics of using the event script – which is a script that runs only for a moment, making a change to the game world. These must be manually activated when their trigger event occurs.
This guide takes us a little deeper into the world of the background script – this is a script that is running constantly in the background of the game. It must be activated at the start of the game, and then manually reactivated each time the game is reloaded.
The Benefits of a Background script
There are two major limitations to the use of event scripts. The first is that it requires the player to click on the show_me button each and every time you want to make a change to the game environment.
The second, more importantly, is that the event script trigger can only ever be something that will happen in the player’s own turn. If it occurs outside of the player’s turn then the player will never get the chance to click on the show_me button as the advisor will appear and disappear during the AI turn.
This is why modders use background scripts as the main driver for their scripting features as they require the player only to make a single click each time the game is reloaded to run all their features and it gives them complete flexibility as to when and how their features are implemented.
In fact, the very first scripts that Myrddraal released – the Multiple Turns per Year script and the Hot Seat Beta script – were both background scripts.
In truth, every mod with significant scripting features will end up making use of all of the different types of script – background, event and campaign – as they all compliment each other.
What is a Background script?
As all show_me scripts, the background script is activated through the advisor. It must have all the components of a show_me script as listed in the Beginner Guide, namely trigger, advice thread and script.
The fundamental difference between an event script and a background script is that a background script is supposed to keep running and not terminate until the game is quit.
This is accomplished with the addition of a simple piece of code to the script – a While loop:
Code:
script
declare_counter loop
set_counter loop 0
; Insert your background script here
while I_CompareCounter loop = 0
end_while
end_script
Once activated, this script will never terminate as when it reaches the end_while it will loop back to the I_CompareCounter.
Now we have the script working all the time, however, we have to incorporate the triggers we want to use into the script itself, instead of the export_descr_advice file. To do that, we need to use new syntax:
Monitors, If statements and While loops
The monitor event/monitor conditions/if/while commands are very much like the triggers for advice threads.
Basically they are for checking conditions.
If statements
Like for example if you have a counter called no
Code:
script
declare_counter no
set_counter no 1
If I_CompareCounter no 1
Insert code here
end_if
end_script
What this will do is at the stage at which it reaches the If line, it will check counter no, if counter no is 1 then it will run the code, if not it will skip to the end_if.
While loops
A while loop will repeat itself whilst its conditions are true.
Code:
script
declare_counter no
set_counter no 0
While I_CompareCounter no = 0
Insert code here
end_while
end_script
When the script runs through, everytime it reaches and end_while, it will check the conditions, and if they are still true, it will jump back to the while statement. Basically looping that bit of code. In this example, the script will keep running forever, because the condition is that no is zero, and there is no code to stop this.
While monitors can be extreemly usefull for pausing the script until something happens.
Code:
While I_TurnNumber = 0
end_while
This will pause the script until the player ends the first turn (turn 0)
It can also be very helpfull if you do not want a script to end before a monitor is triggered. (see below)
Monitors
Condition monitors
Code:
script
declare_counter loop
set_counter loop 1
declare_counter no
set_counter no 0
monitor_conditions I_CompareCounter no = 1
Insert code here
terminate_monitor
end_monitor
campaign_wait 10
set_counter no 1
while I_CompareCounter loop = 1
end_while
end_script
The difference between a Monitor and an If statement is that the conditions for an if statement are checked when the if statement is reached, and not again. A monitor can be declared at the beginning of the script and will then be checked continuously.
In the example above, the monitor is declared, but the counter no is not 1. As soon as no changes to 1 (after waiting 10) the monitor is triggered and the code inside it is run.
Event monitors
Code:
script
declare_counter loop
set_counter loop 1
monitor_event buttonpressed buttonpressed end_turn TrueCondition
Insert code here
terminate_monitor
end_monitor
while I_CompareCounter loop = 1
end_while
end_script
An event monitor is basically a trigger using certain conditions. For example the pressing of a button. In this case, on the pressing of the end turn button, the code inside the monitor will be run.
The difference between terminate_monitor and end_monitor
With some monitors, you will see both terminate_monitor and end_monitor at the end. This basically determines whether the monitor can be triggered more than once. If you include both, the monitor can only be triggered once, then it cannot be used again. If you only include the end_monitor, then the monitor can be enabled several times.
And statements
And statments can be used with monitors, if statements and while loops. This is for multiple conditions. For example:
Code:
script
declare_counter noone
declare_counter notwo
declare_counter nothree
set_counter noone 1
set_counter notwo 1
set_counter nothree 1
monitor_conditions I_CompareCounter noone = 1
and I_CompareCounter notwo = 1
and I_CompareCounter nothree = 1
Insert code here
terminate_monitor
end_monitor
if I_CompareCounter noone = 1
and I_CompareCounter notwo = 1
and I_CompareCounter nothree = 1
Insert code here
end_if
end_script
A full list of events, conditions & commands can be found here:
https://forums.totalwar.org/vb/showthread.php?t=54299
Now, that’s all a lot to take in. So let’s try some examples:
More More Money
Here we give the player a little monetary boost each turn. It’ll happen automatically, no need for him to manually activate it.
For the event to trigger it, I’m going to choose FactionTurnStart and I want it only at the start of the player’s turn so I’m going to use the FactionIsLocal conditional.
Code:
script
declare_counter loop
set_counter loop 0
monitor_event FactionTurnStart FactionIsLocal
console_command add_money 100
end_monitor
while I_CompareCounter loop = 0
end_while
end_script
Now, at the beginning of each turn, the player’s treasury will increase by 100.
Simple enough. Let’s make it more complicated.
Here is a script that will make it considerably harder for a player to amass a huge treasury:
Code:
script
declare_counter loop
set_counter loop 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;; Creosote remover
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
monitor_event FactionTurnStart FactionIsLocal
and not LosingMoney
and Treasury > 10000
console_command add_money -1000
end_monitor
monitor_event FactionTurnStart FactionIsLocal
and not LosingMoney
and Treasury > 20000
console_command add_money -3000
end_monitor
monitor_event FactionTurnStart FactionIsLocal
and not LosingMoney
and Treasury > 30000
console_command add_money -6000
end_monitor
while I_CompareCounter loop = 0
end_while
end_script
At the beginning of each turn, the script will check the player’s treasury and then, if it above a certain amount and the player is not losing money, it will reduce it by the specified amount eg, 1,000 if it is above 10,000.
Note that all of these monitors will be triggered at the start of the player’s turn. Therefore if his treasury has gone higher than 30,000 he will not be docked 6,000 but 10,000 (1,000 + 3,000 + 6,000).
Here’s a very different script (from the late, unlamented Client Kingdoms 2 which will never be), one designed to give a non-player controlled faction a helping hand if things start going bad for them.
Code:
script
declare_counter loop
set_counter loop 0
monitor_event FactionTurnStart FactionType britons
and I_NumberOfSettlements britons < 4
and RandomPercent < 15
console_command create_unit Londinium "warband sword briton" 1
console_command create_unit Londinium "warband hurler briton" 1
console_command create_unit Eburacum "warband sword briton" 1
console_command create_unit Eburacum "warband hurler briton" 1
console_command create_unit Deva "warband sword briton" 1
console_command create_unit Deva "warband hurler briton" 1
end_monitor
while I_CompareCounter loop = 0
end_while
end_script
Let’s take it step by step, first of all, the initial event:
Code:
monitor_event FactionTurnStart FactionType Britons
and not FactionIsLocal
and I_NumberOfSettlements britons < 4
and RandomPercent < 26
Means that it will be triggered when:
1) At the start of the Britons turn
2) When the player is _not_ playing the Britons
3) When the number of settlements the Britons own is less than 4
4) And if the computer picks a random number between 1 and 25 – this means that even when all the other conditions are satisfied it will only happen on average 1 time in 4.
If all those conditions are satisfied, then the game will run the script within the monitor, creating the units within those settlements. The problem with it at present is that script will create the unit its told to, irrespective of whether it is the Britons or another faction who control that settlement, and assign it to that faction which controls the settlement. We therefore need to check to make sure we only create the unit in a settlement if the Britons control that settlement, for example:
Code:
if I_SettlementOwner Londinium = britons
console_command create_unit Londinium "warband sword briton" 1
console_command create_unit Londinium "warband hurler briton" 1
end_if
So our full script would look like the following:
Code:
script
declare_counter loop
set_counter loop 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;; britons in danger - Dads Army
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
monitor_event FactionTurnStart FactionType britons
and I_NumberOfSettlements britons < 4
and RandomPercent < 15
if I_SettlementOwner Londinium = britons
console_command create_unit Londinium "warband sword briton" 1
console_command create_unit Londinium "warband hurler briton" 1
end_if
if I_SettlementOwner Eburacum = britons
console_command create_unit Eburacum "warband sword briton" 1
console_command create_unit Eburacum "warband hurler briton" 1
end_if
if I_SettlementOwner Deva = britons
console_command create_unit Deva "warband sword briton" 1
console_command create_unit Deva "warband hurler briton" 1
end_if
end_monitor
while I_CompareCounter loop = 0
end_while
end_script
Triggers
We’re now beginning to understand what a background script is, however the script is only one of the three elements listed in the Beginner Guide – we also need an advice thread and, more importantly, a trigger. These are done in the same way as in the Beginner Guide, so rather than go through them again, I’ll just show you an example.
The F1 trigger
This is the trigger used by Myrddraal in the first scripts that he released. It’s great benefit is that the trigger is not activated by normal play, it is therefore ideal for testing purposes and mods where the player can be relied upon to follow the process each time.
It is, in fact the exact same trigger that was used in the Beginner Guide. But here it is again
This is the advice thread (NB, all this already exists, only the Script line has been added)
Code:
;------------------------------------------
AdviceThread Help_Campaign_Keyboard_Shortcuts_Scroll_Thread
GameArea Campaign
Item Help_Campaign_Keyboard_Shortcuts_Scroll_Text_01
Uninhibitable
Verbosity 0
Threshold 1
Attitude Normal
Presentation Default
Title Help_Campaign_Keyboard_Shortcuts_Scroll_Text_01_Title
Script scripts\show_me\background_script.txt ; This is the added line
Text Help_Campaign_Keyboard_Shortcuts_Scroll_Text_01_Text1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;------------------------------------------
Trigger 2137_Help_Campaign_Keyboard_Shortcuts_Scroll_Trigger
WhenToTest ScrollAdviceRequested
Condition ScrollAdviceRequested help_scroll
AdviceThread Help_Campaign_Keyboard_Shortcuts_Scroll_Thread 0
To activate your background script (placed in the data\scripts\show_me folder, of course), you must press F1 – then click on the ? – then the advisor should pop up and you can click on the Show Me How button at the beginning of the campaign and after each reload.
Now more and more mods are developing background scripts, scripters have been looking into ways to make activation and reactivated more user friendly. Eventually, once a certain number of mods have been released, I imagine that a community standard will develop as mod-users become accustomed with a specific method. More sophisticated triggers (and their consequences) will be the topic of the further portion of this guide which will be a series of modules focusing on various advanced scripting techniques to which all are invited to contribute.
Scripting links
CA's list of commands, events and conditions
Scripting research thread
Hot Seat Mod - Beta Release
More than two turns a year - release
-
Re: An Intermediate Guide to Scripting
You're a scripting god. Thanks very much!!!
-
Re: An Intermediate Guide to Scripting
Quick question Richard
With use of script would that be possible to spawn mercenary unit for hire only for non-Roman factions (playable and non playable one) for example "Roman deserters".Obviously such a unit would not be available for Romans.Is that at all possible ?
-
Re: An Intermediate Guide to Scripting
Yes, perfectly possible - but obviously not through the existing mercenary mechanism. Look at the Client Kingdoms mod for one way of doing it for the player. For non-player factions you would have to do it in a background script using a monitor_event with whatever conditionals you want and a create_unit console command inside.
-
Re: An Intermediate Guide to Scripting
a wonderful Thread...
I'm posting for very first time in this forum but i'm not reading in this section for first time...my english is not very good..please forgive me some grammar faults!
~:rolleyes:
A quick question:
has anybody checked the disable_ai console command if it works?
I would like to make a script that disable all the ai_actions and combine this with the faction switcher script! I have some problems with this matter because in the faction switcher script the ai make some stuff at the end of every turn...
i would like to execute this...
could it be that the command terminate_script? :stupido2:
here is the script:
HTML Code:
script
declare_counter player_faction
if I_LocalFaction romans_julii
set_counter player_faction 1
end_if
if I_LocalFaction macedon
set_counter player_faction 2
end_if
if I_LocalFaction egypt
set_counter player_faction 3
end_if
if I_LocalFaction seleucid
set_counter player_faction 4
end_if
if I_LocalFaction carthage
set_counter player_faction 5
end_if
if I_LocalFaction parthia
set_counter player_faction 6
end_if
if I_LocalFaction pontus
set_counter player_faction 7
end_if
if I_LocalFaction gauls
set_counter player_faction 8
end_if
if I_LocalFaction germans
set_counter player_faction 9
end_if
if I_LocalFaction britons
set_counter player_faction 10
end_if
if I_LocalFaction armenia
set_counter player_faction 11
end_if
if I_LocalFaction dacia
set_counter player_faction 12
end_if
if I_LocalFaction greek_cities
set_counter player_faction 13
end_if
if I_LocalFaction numidia
set_counter player_faction 14
end_if
if I_LocalFaction scythia
set_counter player_faction 15
end_if
if I_LocalFaction spain
set_counter player_faction 16
end_if
if I_LocalFaction thrace
set_counter player_faction 17
end_if
;---------------------------------------------
if I_CompareCounter player_faction = 1
console_command disable_ai thrace
end_if
if I_CompareCounter player_faction = 2
console_command disable_ai romans_julii
end_if
if I_CompareCounter player_faction = 3
console_command disable_ai egypt
end_if
if I_CompareCounter player_faction = 4
console_command disable_ai seleucid
end_if
if I_CompareCounter player_faction = 5
console_command disable_ai carthage
end_if
if I_CompareCounter player_faction = 6
console_command disable_ai parthia
end_if
if I_CompareCounter player_faction = 7
console_command disable_ai pontus
end_if
if I_CompareCounter player_faction = 8
console_command disable_ai gauls
end_if
if I_CompareCounter player_faction = 9
console_command disable_ai germans
end_if
if I_CompareCounter player_faction = 10
console_command disable_ai britons
end_if
if I_CompareCounter player_faction = 11
console_command disable_ai armenia
end_if
if I_CompareCounter player_faction = 12
console_command disable_ai dacia
end_if
if I_CompareCounter player_faction = 13
console_command disable_ai greek_cities
end_if
if I_CompareCounter player_faction = 14
console_command disable_ai numidia
end_if
if I_CompareCounter player_faction = 15
console_command disable_ai scythia
end_if
if I_CompareCounter player_faction = 16
console_command disable_ai spain
end_if
if I_CompareCounter player_faction = 17
console_command disable_ai thrace
end_if
;----------------------------------------------
console_command control slave
if I_LocalFaction romans_julii
console_command control macedon
terminate_script
end_if
if I_LocalFaction macedon
console_command control egypt
terminate_script
end_if
if I_LocalFaction egypt
console_command control seleucid
terminate_script
end_if
if I_LocalFaction seleucid
console_command control carthage
terminate_script
end_if
if I_LocalFaction carthage
console_command control parthia
terminate_script
end_if
if I_LocalFaction parthia
console_command control pontus
terminate_script
end_if
if I_LocalFaction pontus
console_command control gauls
terminate_script
end_if
if I_LocalFaction gauls
console_command control germans
terminate_script
end_if
if I_LocalFaction germans
console_command control britons
terminate_script
end_if
if I_LocalFaction britons
console_command control armenia
terminate_script
end_if
if I_LocalFaction armenia
console_command control dacia
terminate_script
end_if
if I_LocalFaction dacia
console_command control greek_cities
terminate_script
end_if
if I_LocalFaction greek_cities
console_command control numidia
terminate_script
end_if
if I_LocalFaction numidia
console_command control scythia
terminate_script
end_if
if I_LocalFaction scythia
console_command control spain
terminate_script
end_if
if I_LocalFaction spain
console_command control thrace
terminate_script
end_if
if I_LocalFaction thrace
console_command control romans_julii
terminate_script
end_if
end_script
-
Re: An Intermediate Guide to Scripting
Quote:
Originally Posted by Epistolary Richard
Yes, perfectly possible - but obviously not through the existing mercenary mechanism. Look at the
Client Kingdoms mod for one way of doing it for the player. For non-player factions you would have to do it in a background script using a monitor_event with whatever conditionals you want and a create_unit console command inside.
Thx for your reply Richard
Would something like this make any sens ?
HTML Code:
script
if I_SettlementOwner Tarsus =(probably list of all non roman factions or is that another way ?)
console_command create_unit Tarsus "merc roman deserters" 1
end_if
end_script
-
Re: An Intermediate Guide to Scripting
pilatus I remember Myrddraal saying something about the disable_ai command when putting together the Hot Seat Mod. He certainly used halt_ai for that.
Maly Jacek If that's an event script then you're better off putting the conditionals in the trigger. If that's a background script you need a loop to keep it running and a monitor event in there to tell the game when to check the conditionals.
-
Re: An Intermediate Guide to Scripting
thx richard
but i've already checked the halt_ai command in myrdaals script and there is the problem that you can't make all factions playable at yourself..only two of them...if you make more the script says good bye!
I've also already checked the set_ai off command but i think this is only for the battle_ai...
has nobody checked the disable_ai command ?
-
Re: An Intermediate Guide to Scripting
I put command line to export_descr_advise.txt, but when I press F1 and activate advisor, the <show me> button did not highlighted so I cannot click it to start scripts. What is wrong?
-
Re: An Intermediate Guide to Scripting
Did the correct advisor speech bubble appear? The Show Me How button doesn't become available until the speech bubble appears.
Post the advice thread that you added the script line to in export_descr_advice.
-
Re: An Intermediate Guide to Scripting
Richard
As I have got not experience whatsover in scripting I have copy edited your your script:
HTML Code:
script
declare_counter loop
set_counter loop 0
monitor_event FactionTurnStart FactionType sassanids
if I_SettlementOwner Dumatha = sassanids
console_command create_unit Dumatha "merc cata" 1
console_command create_unit Dumatha "merc veteranii" 1
end_if
if I_SettlementOwner Erewan = sassanids
console_command create_unit Erewan "elite cata" 1
end_if
terminate_monitor
end_monitor
while I_CompareCounter loop = 0
end_while
end_script
That works but despite press F1 button it only works once.When I remove terminate_monitor I get new units created on every turn.Could you kindly tell me what line needs to be change for the unit to be created only upon pressing F1.I guess that could be also way of having message appearing advising player he can get new units.Also is there a line that could replace "Sassanids" with something like "all except Romans"
-
Re: An Intermediate Guide to Scripting
Quote:
Originally Posted by dzsagon
I put command line to export_descr_advise.txt, but when I press F1 and activate advisor, the <show me> button did not highlighted so I cannot click it to start scripts. What is wrong?
I solved the problem. If a script has any syntax error, the <show me how> button did not highlighted, not allows to run a script. Now my scripts run, but not wery well:(
script
declare_counter state
set_counter state 0
declare_counter loop
set_counter loop 0
console_command add_money -100; just for test to scripts really runs
monitor_event FactionTurnStart FactionType Egypt
and FactionIsLocal
and FactionHasAllies
if DiplomaticStanceFromFaction pontus >= Hostile
set_counter state 1
console_command add_money 2000; just for test to scripts really runs
end_if
if DiplomaticStanceFromFaction pontus < Hostile
set_counter state 0
console_command add_money -2000; just for test to scripts really runs
end_if
end_monitor
monitor_event FactionTurnStart EgyptFactionType Numidia
and not FactionIsLocal
and DiplomaticStanceFromFaction pontus <= Hostile
and I_CompareCounter state = 1
console_command diplomatic_stance numidia pontus war
end_monitor
while I_CompareCounter loop = 0
end_while
end_script
My allies is Nubidia. If I declare war with pontus I want to Nubidia declares war to. But the script not doing this.
-
Re: An Intermediate Guide to Scripting
If that is a direct copy&paste from your script then this line is part of the problem:
Code:
monitor_event FactionTurnStart EgyptFactionType Numidia
Then, there are the if lines in the first monitor.
Code:
monitor_event FactionTurnStart FactionType Egypt
and FactionIsLocal
and FactionHasAllies
if DiplomaticStanceFromFaction pontus >= Hostile
DiplomaticStanceFromFaction requires exported parametres from a monitor, so it will no work if it is not tied to the monitor with ands. You'll have to split the monitor in two. This is how the other monitor should begin:
Code:
monitor_event FactionTurnStart FactionType Egypt
and FactionIsLocal
and FactionHasAllies
and DiplomaticStanceFromFaction pontus >= Hostile
As a rule of thumb, if a condition doesn't start with I_ it requires to be used as an event monitor condition.
-
Re: An Intermediate Guide to Scripting
Thanks a lot! It works now!
Another question. What is the proper command to give money to other fraction?
add_money <amount> <fraction name> not works.
-
Re: An Intermediate Guide to Scripting
From what other people have posted, you need a comma in there:
console_command add_money faction, how_much
-
Re: An Intermediate Guide to Scripting
Quote:
Originally Posted by Epistolary Richard
From what other people have posted, you need a comma in there:
console_command add_money faction, how_much
Thanks, it seems to be working.
-
Re: An Intermediate Guide to Scripting
HI!
I want to use move_character command , but I don't know how to calculate x,y koordinates of a position on campaign map. Is there a tool or method to do this?
-
Re: An Intermediate Guide to Scripting
Bring up the console on campaign map, place cursor over desired tile and type show_cursorstat, then press enter :)
-
Re: An Intermediate Guide to Scripting
If I use spawn and move command to not local faction with monitor_event, hothing happaned:
script
monitor_event FactionTurnStart FactionType romans_julii
and not FactionIsLocal
spawn_army
faction romans_julii
character Flavius Julius, general, command 0, influence 0, management 0, subterfuge 0, age 20, x 180, y 5
unit roman generals guard cavalry, soldiers 20 exp 9 armour 1 weapon_lvl 0
unit roman legionary first cohort ii, soldiers 40 exp 0 armour 0 weapon_lvl 0
unit roman legionary cohort ii, soldiers 60 exp 0 armour 0 weapon_lvl 0
unit roman praetorian cohort i, soldiers 60 exp 0 armour 0 weapon_lvl 0
end
console_command move_character Flavius Julius 170, 5
campaign_wait 1
console_command move_character Flavius Julius 160, 15
end_monitor
end_script
If I use it to not local faction without monitor_event spawn work, but no moves
If I use it to local faction spawn works, move works too.
-
Re: An Intermediate Guide to Scripting
Weird. Beats me why it doesn't work.
The only thing I can think of is that you were playing with the Julii when testing with not FactionIsLocal, but that wouldn't still explain why the moves didn't work..
-
Re: An Intermediate Guide to Scripting
Is there easiest way to check - me and my ally's- diplomatic stance for all other fractions? I am chartage, my ally is spain.
Quote:
script
declare_counter war0
set_counter war0 0
declare_counter war1
set_counter war1 0
declare_counter war2
set_counter war2 0
declare_counter war3
set_counter war3 0
declare_counter war4
set_counter war4 0
declare_counter war5
set_counter war5 0
declare_counter loop
set_counter loop 0
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction romans_brutii = AtWar
set_counter war0 1
end_monitor
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction romans_brutii <= Neutral
set_counter war0 0
end_monitor
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction romans_julii = AtWar
set_counter war1 1
end_monitor
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction romans_julii <= Neutral
set_counter war1 0
end_monitor
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction romans_scipii = AtWar
set_counter war2 1
end_monitor
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction romans_scipii <= Neutral
set_counter war2 0
end_monitor
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction gauls = AtWar
set_counter war3 1
end_monitor
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction gauls <= Neutral
set_counter war3 0
end_monitor
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction numidia = AtWar
set_counter war4 1
end_monitor
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction numidia <= Neutral
set_counter war4 0
end_monitor
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction greek_cities = AtWar
set_counter war5 1
end_monitor
monitor_event FactionTurnStart FactionType carthage
and FactionIsLocal
and DiplomaticStanceFromFaction greek_cities <= Neutral
set_counter war5 0
end_monitor
monitor_event FactionTurnStart FactionType spain
and not FactionIsLocal
and DiplomaticStanceFromFaction romans_brutii < AtWar
and DiplomaticStanceFromFaction carthage = Allied
and I_CompareCounter war0 = 1
console_command diplomatic_stance spain romans_brutii war
end_monitor
monitor_event FactionTurnStart FactionType spain
and not FactionIsLocal
and DiplomaticStanceFromFaction romans_julii < AtWar
and DiplomaticStanceFromFaction carthage = Allied
and I_CompareCounter war1 = 1
console_command diplomatic_stance spain romans_julii war
end_monitor
monitor_event FactionTurnStart FactionType spain
and not FactionIsLocal
and DiplomaticStanceFromFaction romans_scipii < AtWar
and DiplomaticStanceFromFaction carthage = Allied
and I_CompareCounter war2 = 1
console_command diplomatic_stance spain romans_scipii war
end_monitor
monitor_event FactionTurnStart FactionType spain
and not FactionIsLocal
and DiplomaticStanceFromFaction gauls < AtWar
and DiplomaticStanceFromFaction carthage = Allied
and I_CompareCounter war3 = 1
console_command diplomatic_stance spain gauls war
end_monitor
monitor_event FactionTurnStart FactionType spain
and not FactionIsLocal
and DiplomaticStanceFromFaction numidia < AtWar
and DiplomaticStanceFromFaction carthage = Allied
and I_CompareCounter war4 = 1
console_command diplomatic_stance spain numidia war
end_monitor
monitor_event FactionTurnStart FactionType spain
and not FactionIsLocal
and DiplomaticStanceFromFaction greek_cities < AtWar
and DiplomaticStanceFromFaction carthage = Allied
and I_CompareCounter war5 = 1
console_command diplomatic_stance spain greek_cities war
end_monitor
while I_CompareCounter loop = 0
end_while
end_script
-
Re: An Intermediate Guide to Scripting
You probably have the easiest way right there in your hands. If you don't need to check for specific factions there are a couple of conditions (OnWarFooting or similar), but for specific factions there's really no way around it. If you start doing these kind of repetitive scripts you should learn how to do script generators, with php, C++, excel or similar.
-
Re: An Intermediate Guide to Scripting
-
Re: An Intermediate Guide to Scripting
is it possible to have nested loops, if-statements and so on? could be a time saver in-game
pseudo-code:
Code:
if 1
if 2
[do something]
end if ; 2
if 3
[do something]
end if ; 3
while [something]
[do something]
end while
end if ; 1
edit: I just realized it is ~D
another thing, for it to be a background script you have to add
Code:
while I_CompareCounter loop = 0
end_while
won't it go faster if you have
Code:
while I_CompareCounter loop = 0
campaign_wait 1
end_while
?
-
Re: An Intermediate Guide to Scripting
Quote:
won't it go faster if you have
while I_CompareCounter loop = 0
campaign_wait 1
end_while?
Well I don't think it would be noticable to be honest, but in theory yes :smile:
-
Re: An Intermediate Guide to Scripting
Is there a way to script senate-like missions?
-
Re: An Intermediate Guide to Scripting
Quote:
Originally Posted by Spitful
Is there a way to script senate-like missions?
I tried something like that some time ago.
https://forums.totalwar.org/vb/showt...without+senate
One of the possible problems is to link the end of one mission with the beginning of the following one, and the method to test if that mission is feasible or not (for example if the corresponding region is still rebel, or it is owned by your own faction).
Any advance will be welcome.
-
Re: An Intermediate Guide to Scripting
Im just going to spawn a building in different provinces on the far reaches of the map to show which mission they are on, then use a monitor that will produce the appropriate mission when the building is spawned on completion of the previous mission, preventing old missions from running again.
Is there a way of counting how many turns have passed since a randomly generated event took place?
What about
and I_SettlementOwner <> Romans_Julii
?
-
Re: An Intermediate Guide to Scripting
Quote:
What about
and I_SettlementOwner <> Romans_Julii
and not I_SettlementOwner = Romans_Julii
or possibly and I_SettlementOwner != Romans_Julii
Nice thread ER. I just noticed it. :laugh4:
I guess i have to come out of EB hole more often.
-
Re: An Intermediate Guide to Scripting
Myrddraal worked out all the technical stuff, I just do the talking sloooowly with hand gestures bit. :bow:
But yes! Let us have some advanced scripting tutorials about the scripting in EB!
-
Re: An Intermediate Guide to Scripting
I'm going to need some, to keep up with you, LorDBulA, and The_Mark!
-
Re: An Intermediate Guide to Scripting
Question guys, which I feel is a little silly but here it is nonetheless: how do you test if a character has a certain trait, and what level of the trait? I tried the following and it doesn't work:
Code:
monitor_event CharacterTurnStart TrueCondition
if FactionType empire_west
if Trait AgeTraitLevel1 = 1
; do some stuff
end_if
end_if
end_monitor
-
Re: An Intermediate Guide to Scripting
Code:
monitor_event CharacterTurnStart FactionType empire_west
and Trait AgeTraitLevel1 = 1
; do some stuff
end_monitor
-
Re: An Intermediate Guide to Scripting
Hmm, that's weird, I thought both "FactionType" and "Trait" were conditions, and thus not usable in monitor_event, but only in monitor_conditions, or "if" clauses?
-
Re: An Intermediate Guide to Scripting
Hmm, we have syntax like that in our EBBS background script, and it seems to work.
-
Re: An Intermediate Guide to Scripting
That is because monitor_event in fact requires an event AND a condition.
If you don't want one, you have to use monitor_event EVENT TrueCondition or else the game will crash.
-
Re: An Intermediate Guide to Scripting
Right, but then what could be the reason why isolating the conditions into their own "if" statements, e.g in my code above, doesn't work?
-
Re: An Intermediate Guide to Scripting
Because most conditionals require exports from an event (eg, settlement, character) - and therefore need to be included in a monitor_event. It's only conditionals that start with I_ that do not require an event which can be used in if and monitor_conditions.
-
Re: An Intermediate Guide to Scripting
While experimenting with scripts I noticed that some AdviceThreads in export_descr_advice.txt have a parameter. I found SettlementName and CharacterName. Not useful for me, but I guess some can use it to make their Advisor texts a little bit more detailed, showing the settlement's or character's name.
-
Re: An Intermediate Guide to Scripting
Is there a way to make the background script detect whether an AI faction has done something, and then have that trigger an event script at the start of the player's turn?
-
Re: An Intermediate Guide to Scripting
Depends on what the AI faction has done. What AI event do you want to trigger it?
-
Re: An Intermediate Guide to Scripting
Which of the following events would be detectable for an AI nation?
Takes a (particular) city.
Declares war/peace with another nation.
Accumulates X amount of money.
Family member (specifically faction leader) dies.
Family member accumulates X command stars.
-
Re: An Intermediate Guide to Scripting
These should be possible.
Just open beginer screepting guide and dive in into RTW script documentation.
-
Re: An Intermediate Guide to Scripting
Quote:
Originally Posted by Epistolary Richard
Depends on what the AI faction has done. What AI event do you want to trigger it?
Beseiging a city would probably be best.
-
Re: An Intermediate Guide to Scripting
Besieging a city's tricky, you can put a conditional in for a monitor to fire if an enemy family member is within one tile of a certain location and if the two factions are at war.
Gets a bit cumbersome with large numbers of factions and cities, but it's possible.
LorDBulA does something similar with his Roma siege script, have a look at his code:
http://www.twcenter.net/forums/showthread.php?t=24968
You can use something like that to increment a counter and then have a separate monitor_event FactionTurnStart FactionIsLocal with an I_CompareCounter condition. Be sure to set the counter back to 0 though, otherwise it will keep triggering.
-
Re: An Intermediate Guide to Scripting
This is a quite similar question, but I hope it can be done:
Is it possible to make an army (or naval army) besiege a city/port at game start through a script? I'm not very familiar with scrpits, so I hope someone could help me with this one.
- Tittils -
-
Re: An Intermediate Guide to Scripting
ER,
Sorry I was unclear. I meant to say "besieging a neutral city." Unless I'm missing something (certainly a possibility), I don't think those conditions would work with a city you do not own. Is there anything else I could try?
Thanks much.
-
Re: An Intermediate Guide to Scripting
As it was said there is no easy way to check for siege.
The only way is to detect enemy army near a settlement.
You can do this for any faction holding city and any faction standing next to the city.
Proximity alert should be set to 2 titles. If you set it to 1 it wont be triggered if enemy attacks from any of city corners.
-
Re: An Intermediate Guide to Scripting
Oh ok, I guess I misunderstood. Thanks.
-
Re: An Intermediate Guide to Scripting
I don't understand, I'm using Malrubius' code:
Code:
monitor_event CharacterTurnStart FactionType empire_west
and Trait AgeTraitLevel1 = 1
; do some stuff
end_monitor
To do something to the character when a turn starts, but nothing happens. Here's the full code:
Code:
console_command give_trait "Gaius Fabricius" GoodCommander 2
campaign_wait 2
console_command add_money 1000
campaign_wait 2
monitor_event CharacterTurnStart FactionType empire_west
and Trait GoodCommander = 2
; do stuff
end_monitor
I start the campaign, press F1 and run the script, the Trait is added, I press Next Turn expecting some stuff to happen to the char based on that trait, but nothing happens... Help?
PS: ER, would you like me to use the other thread referencing this one from now on?
-
Re: An Intermediate Guide to Scripting
Is that the full script? Do you have 'script' at the beginning? end_script at the end? Do you have a loop so that the script is still running the next turn?
If you have all that try getting rid of the campaign_wait commands.
-
Re: An Intermediate Guide to Scripting
Quote:
Do you have a loop so that the script is still running the next turn?
Maybe that's my problem. I was under the assumption that if a script was launched, that it will persist throughout the entire game session, including all the monitors. Is that right, or do I have to have some sort of loop to keep the script persisting through the turns?
All of the action that I want to happen above is inside the monitor, which I thought will persist though turn 2, even though loaded at turn 1 (assuming the game wasn't reloaded).
-
Re: An Intermediate Guide to Scripting
Have a look at the first script in the first post, there's your basic background script with a while loop. You need a while loop at the bottom otherwise the script will terminate immediately.
-
Re: An Intermediate Guide to Scripting
When script execution reaches end_script command you can guess what happens next :)
-
Re: An Intermediate Guide to Scripting
I think I figured out what was going wrong:
inside that event monitor I have two commands:
Code:
console_command add_money 10000
campaign_wait 2
console_command kill_character "Gaius Fabricius"
campaign_wait 2
(the campaign waits are apparently necessary for all console_commands).
Ok so here's what happens: apparently, under some conditions, the kill_character command does-not-work, and the script processing engine seems to stop processing. What's been happening in my script, and why I was prompted to post in this thread, was that I've been developing a background script for the Paeninsula Italica mod; I tried inserting just one command that had to be in my script -- kill_character -- and it would not work (hence my posts). I started this script every time I started a new campaign in our beta campaign map, so obviously we have a lot of things unbalanced yet, and a lot of provinces (over 50) rebel on the next turn. Also, the Adoption thing springs into action, since there are like 3 generals for the entire faction.
SO -- to make a long story short -- when I start the campaign and run my script, after pressing next turn, all this massive avalanche of events starts to happen on the next turn, and the kill_character event does not work. It is in the monitor correctly, and the monitor is triggered correctly, but the command simply doesn't work! How do I know the monitor is triggered correctly? Because I placed the give money command before it, which never fails to work. And what's even more, I placed a second give money command after it, e.g.
Code:
console_command add_money 10000
campaign_wait 2
console_command kill_character "Gaius Fabricius"
campaign_wait 2
console_command add_money 10000
campaign_wait 2
And the execution never reaches the second money command, and no money is added after the first. This is a very weird problem. Here's what's even weirder: sometimes, if I keep pressing Next Turn, the event_monitor is still apparently running in the background, sometimes will make the kill_character command work. So sometimes, a few turns in, the character does get killed (although the money command works always, at least the first one).
It seems that the script engine somehow gets "stuck" on the kill_character command, and simply does not proceed executing any further. I thought that maybe it's from all the events happening so fast, and tried to somehow pause the game, or at least pause all the events and UI things happening, until my script monitor runs and finishes its stuff. Thus, I tried everything imaginable, e.g.:
Code:
monitor_event FactionTurnStart FactionIsLocal
declare_show_me
hide_ui
suspend_unscripted_advice true
disable_entire_ui
console_command add_money 10000
campaign_wait 5
console_command kill_character "Gaius Fabricius"
campaign_wait 5
console_command add_money 10000
campaign_wait 5
enable_entire_ui
suspend_unscripted_advice false
show_ui
end_monitor
all the things that I guessed could suspend the proper flow of the game until my poor script has finished. None of these things work. One of the funny things is, I just added the "hide_ui" thing, to try and hide the events until my script finishes, and -- the UI gets hidden, the "adoption" event pops up anyway (due to the conditions in my campaign), and when I dismiss it, the UI continues to remain hidden. The script simply does not proceed further, beyond the kill_character command, the UI remains hidden even though the script says to unhide it. It just gets stuck. And I know that the kill_character command works always when in direct script mode (i.e. without the monitors), and it sometimes works even in the monitors, seemingly when there aren't that many events popping up. So that's what's been going on with my script :-) Anyone else have something similar?
-
Re: An Intermediate Guide to Scripting
Okay guys, in order to narrow down the source of the problem, I have considerably cleaned up the campaign situation, gave the faction enough generals so that adoptions would not pop up, removed almost all the provinces owned so that there are would be no rebellions, etc. Now, practically no events happen on each turn, and yet the problem with kill_character still persists!
I don't want to clutter up ER's thread with this one problem, so I've started a new thread, where I explain the situation in less clumsy terms, the above complications have been removed as I just said, and I also posted screenshots of what goes on.
The thread is here: https://forums.totalwar.org/vb/showthread.php?t=62364
-
Re: An Intermediate Guide to Scripting
A few more questions: the only way to browse if a character has one of a list of traits is by having a monitor event for each trait, right? i.e. there's no way to do something like right:
if Trait X = 1
do A
if Trait Y = 1
do B
Also, is there a limit for how many "and" conditions can exist for event_monitors? This sort of information seems not to be included in the Hardcoded Limits thread.
-
Re: An Intermediate Guide to Scripting
I think that's because no one has ever hit it. From my understanding of CA it seems unlikely that they would have imposed a limit because they never expected people to be using big scripts. But equally there may be an extent by which a big monitor may not work right.
There's no easy way to do the trait thing - however if you want to use that in many different monitors then you may want to have a separate monitor to use the existence to set a counter. You can then use an if I_CompareCounter line within your monitors.
-
Re: An Intermediate Guide to Scripting
I've found problems in making the command test_message working:
https://forums.totalwar.org/vb/showp...65&postcount=8
Any of the experts in scripting could give me the tip?:help:
-
Re: An Intermediate Guide to Scripting
Can someone supply me with a code for changing diplomacy between factions? Thanks.
-
Re: An Intermediate Guide to Scripting
Quote:
diplomatic_stance
Availability: campaign
Usage: diplomatic_stance <faction_a> <faction_b> <allied/neutral/war>:
Set the diplomatic stance between the two factions
So the usage in a script would look like this:
Code:
console_command diplomatic_stance romans_brutii parthia neutral
console_command diplomatic_stance romans_julii parthia neutral
console_command diplomatic_stance romans_scipii parthia neutral
console_command diplomatic_stance romans_senate parthia neutral
That makes all the roman factions "Neutral" toward Parthia, whether they were are war or allied. Note that only allied, neutral and war are available - there does not appear to be a way to force protectorates (I only mention this since that's what people usually seem to be looking for).
-
Re: An Intermediate Guide to Scripting
Thanks, that was easier than I thought it was.
(BTW I'm Piko on the RTR forums, that was the only thing I wasn't able to locate in your TFT files, thanks again!)
Yet another question, can you force ownership?
-
Re: An Intermediate Guide to Scripting
Can you count how many battles the player has fought in the campaign so far?
-
Re: An Intermediate Guide to Scripting
Is this what you're looking for? It doesn't actually return a number unfortunately.
Code:
---------------------------------------------------
Identifier: BattlesFought
Trigger requirements: faction
Parameters: logic token, quantity
Sample use: BattlesFought = 6
Description: How many battles has the player fought so far during this campaign?
Battle or Strat: Either
Class: BATTLES_FOUGHT
Implemented: Yes
Author: Guy
---------------------------------------------------
-
Re: An Intermediate Guide to Scripting
What do you mean?
Does it work for IF and WHILE statements?
-
Re: An Intermediate Guide to Scripting
Nope, it has an import - the only conditions that work with if and while statements are prefixed with I_
-
Re: An Intermediate Guide to Scripting
Can you force ownership of a city? If so can I have the code please?
-
Re: An Intermediate Guide to Scripting
console_command take_settlement i think, take a look at the docudemon
-
Re: An Intermediate Guide to Scripting
Quote:
Originally Posted by shadowstar
Can you force ownership of a city? If so can I have the code please?
Hey Piko-
As an example, on turn #100 at the start of the Julii turn, this will give the Senate control of Antioch and then create two units of Hastati in Antioch.
Code:
monitor_event FactionTurnStart FactionType romans_julii
and I_TurnNumber = 100
console_command control romans_senate
console_command capture_settlement Antioch
console_command create_unit Antioch "roman hastati" 2
console_command control romans_julii
terminate_monitor
end_monitor
This assumes the player is playing romans_julii. If not, the code gets more complicated because you'll need some sort of variable to return control of the correct faction to the player.
-
Re: An Intermediate Guide to Scripting
Hi all!
I have a question about assassination and whether it's possible to script it?
My idea involes the assassination a faction leader that i don't know the name of i.e a spawned character, has anyone tried this?
Cheers!
-
Re: An Intermediate Guide to Scripting
To my knowledge, no one's had any luck in scripting agent missions. The kill_character command, which could be used instead, as you say needs to know the character's name.
-
Re: An Intermediate Guide to Scripting
Quote:
Originally Posted by Stuie
Hey Piko-
As an example, on turn #100 at the start of the Julii turn, this will give the Senate control of Antioch and then create two units of Hastati in Antioch.
Code:
monitor_event FactionTurnStart FactionType romans_julii
and I_TurnNumber = 100
console_command control romans_senate
console_command capture_settlement Antioch
console_command create_unit Antioch "roman hastati" 2
console_command control romans_julii
terminate_monitor
end_monitor
This assumes the player is playing romans_julii. If not, the code gets more complicated because you'll need some sort of variable to return control of the correct faction to the player.
Thanks, I needed this for RTR: under the eagle, hereby promoting it, please visit us at: http://forums.rometotalrealism.org/i...?showforum=157 . We're only just starting out but I'm sure this information's all going to help.
-
Re: An Intermediate Guide to Scripting
Quote:
Originally Posted by Epistolary Richard
To my knowledge, no one's had any luck in scripting agent missions. The kill_character command, which could be used instead, as you say needs to know the character's name.
Ah, oh well - back to the drawing board. Thank you anyway.
-
Re: An Intermediate Guide to Scripting
Quote:
Originally Posted by Stuie
So the usage in a script would look like this:
Code:
console_command diplomatic_stance romans_brutii parthia neutral
console_command diplomatic_stance romans_julii parthia neutral
console_command diplomatic_stance romans_scipii parthia neutral
console_command diplomatic_stance romans_senate parthia neutral
That makes all the roman factions "Neutral" toward Parthia, whether they were are war or allied. Note that only allied, neutral and war are available - there does not appear to be a way to force protectorates (I only mention this since that's what people usually seem to be looking for).
I wonder, is there a way to detect the event of one faction becoming a protectorate?
If so, there might be a way to work around the annoying alliance issue with protectorates (You can´t attack allies of your protectorate without losing the protectorate), simply by setting the relations of the protectorate to all other factions to neutral.
-
Re: An Intermediate Guide to Scripting
No, there's no way that I'm aware of to detect the existence or creation of a protectorate. :sad:
-
Re: An Intermediate Guide to Scripting
Here I have learned how to script changing a city's ownership, but now I wish to change a family_members ownership, ex. G M from romans_julii to romans_brutii. I know his name.
-
Re: An Intermediate Guide to Scripting
Quote:
Originally Posted by shadowstar
Here I have learned how to script changing a city's ownership, but now I wish to change a family_members ownership, ex. G M from romans_julii to romans_brutii. I know his name.
As far as I know, you will need to kill_character him from the original faction and then spawn him in the new faction. No other way to force a change of allegiance that I know of.
-
Re: An Intermediate Guide to Scripting
Well maybe trigger rebelling in BI? Is that possible? Where are these docudemon files BTW?
-
Re: An Intermediate Guide to Scripting
No, as far I know there's no change allegiance command.
The docudemon files are linked in the first post of this topic. They can be found here:
https://forums.totalwar.org/vb/showthread.php?t=54299
-
Re: An Intermediate Guide to Scripting
Quote:
Originally Posted by shadowstar
Well maybe trigger rebelling in BI? Is that possible? Where are these docudemon files BTW?
If you're using loyalty in BI, you could always give the character a huge negative to loyalty using a trait. I haven't messed around much with loyalty though, so I'm not so sure how predictable it is.