You must be logged in to post messages.
Please login or register

Stronghold and Crusader: Scenario Design and Modding Forum
Moderated by ericgolf, Lady Arcola, peter2008, Lord Michael I, Lord_of_Hell

Hop to:    
loginhomeregisterhelprules
Bottom
Topic Subject: course about scripting (very long)
« Previous Page  1 2  Next Page »
posted 07-16-02 18:39 EST (US)   
Course on
Programming Scripts for Stronghold


By Franηois Delmotte (ultima_spock_3@yahoo.com)

This document has been written by a fan of the Stronghold game and is intended to serve as a reference for other players who will find here all informations to write good scripts. However, as it is written below, a script is only a part of a scenario, which requires also a map and other things. Here you will learn how to make good scripts, but making good scenarios requires much more hard work.

This document has three parts. The first one is based on the description of the general scheme of a scenario It gives examples about very simple events and other general informations. In this part you will learn how to make a simple scenario. The second part is for advanced programmers only. It presents some tricks to create much more complicated scenarios. The third part is a reference of all actions and events that can be used in a scenario.

************************************************************ ************
1 Basic Notions
************************************************************ ************

In this section is described the general scheme of any script. It will also tackle invasion, while these latter are not used in economical scenarios.

1.1 General Scheme of a script
A script uses invasions, messages, and events. It has also a starting date. Everything in the script must have a date from which they can be activated.
Invasions are armies attacking the player's lord. You must choose a starting date, but no condition as with Events. They can be repeated every n months with no end.
Messages appear at a given date and have no other implications.
Events are much more interesting to study and will take the rest of this section.

1.2 The Basic Element of a script : the Event
1.2.1 A single condition
The following notation will be used for any Event.
Event x : (date t ; Cond i) => Action a
It means that at the date t, Condition i is checked and will imply if true the action a. You choose a condition mentionned in the reference section. You choose an action from the reference section.

In this game there are conditions that can be tested at a given threshold. For example you can test if the population is equal to 300. In fact the game engine consider the test not as an equal test, but as an equal or higher test. It means that a condition of a population equal to 300 will become true if the population is 400.

1.2.2 Multiple conditions
You can also test a serie of conditions, this will be noted :
Event x : (date t ; Cond i,...,Cond j) => Action a
With this notation, all conditions must be matched in the same time so that the action is triggered. For example you can script the Event (date t ; Stone = 300, Ale = 200) => Win.
You will win if you have in the same time 300 stones and 200 ale.

In the Editor, when you have several conditions for the same Event, you can choose to use the 'or' operator, which will be noted :
Event x : (date t ; Cond i,...,Cond j ;+) => Action a
It means that action a is triggered as soon as one of the conditions becomes true, not necessarily all. For example (date t ; Stone = 300, Ale = 200 ;+) => Win means that you win if either you have 300 stones or 200 ale. Totally different from the first case.

1.2.3 Until activated, an Event can be triggered
An extremy important point to highlight is that once an event is scripted at date t, it will remain likely to trigger even after date t until it will become triggered.
For example consider (date 1500 ; Stone = 300, Ale = 200) => Win.
Departing from the date 1500, this Event will be tested. You can win in 1500 if you have 300 stones and 200 ale, or later when you will gather enough ressources.

This simple example may be obvious, but must be kept in memory. When scripting complex scripts, with a large set of Events that are linked and interlaced, there could be some big surprises with some forgotten Events that are triggered well long after they were defined.

1.2.4 Final comments
You can attach a single action to a serie of conditions. But you cannot attach a serie of action to a serie of conditions. If for example you want to create (date t ; Stone = 300, Ale = 200) => Fire (10) AND bandits (green) you must cut them in two and write (date t ; Stone = 300, Ale = 200) => Fire (10)
(date t ; Stone = 300, Ale = 200) => bandits (green)

You can indeed scripts several Events at the same date. The only problem is that if messages are attached to actions, some will be delayed.

Now you are ready to tackle the design of simple scenarios by adding several Events. They will be noted :
Name (starting date) {
Event x
Event y
Event z...}

1.3 First basic scripts
In this part is given some examples for simple scripts. From them you can create your own ones, add everything you want and are limited only by your imagination.

1.3.1 Example of an economical script
MonPremier (1000) {
(1010 ; AutoStop) => bandits (red, 10) for 3 times every 9 months
(1020 ; Stone = 300, Ale = 200) => Win }

It means that you begins in 1000. In 1010 you will be attacked automatically by bandits, and they will come back 2 times (one for the first time, plus two others equal 3).
At 1020 or later, you will win if you gather 300 stones and 200 ale.

This example is perfect for a tutorial in stronghold, but is incorrect for a true scenario. For a tutorial, a beginner would have all the time to learn the game and try various tactics. But you want a true scenario for players. So what is the problem ? The script lacks of a losing condition. Usually in economical scenarios, you have a deadline to do the required job.
To do this you simply change the script as follows :

MonPremier1 (1000) {
(1010 ; AutoStop) => bandits (red, 10) for 3 times every 9 months
(1020 ; Stone = 300, Ale = 200) => Win
(1025 ; AutoStop) => Lose }

In this case if you do not win before 1025, you lose. That is not more complex, but add a high pressure on the player who will see in the left top of the screen the countdown !
Depending on the map, the available resources, wolves and so on, the scenario could be anything between easy to impossible.

You could forget the wining condition and write
MonPremier2 (1000) {
(1010 ; AutoStop) => bandits (red, 10) for 3 times every 9 months
(1025 ; AutoStop) => Lose }

In this case the scenario is in a dead end, it is not possible to win it.

Let us come back to the working scenario and change something :
MonPremier3 (1000) {
(1000 ; Stone = 300, Ale = 200) => Win
(1010 ; AutoStop) => bandits (red, 10) for 3 times every 9 months
(1025 ; AutoStop) ( Lose }

We simply changed the starting date of the winning Event. Now it begins in 1000 so it means that you can win before 1020, even before 1010 and so a player could very well never see the bandits. In this script this does not change anything, because resources you gathered cannot be destroyed, and so if you could win before 1010, you will surely win after 1020. But this can be very different with the script
MonPremier4 (1000) {
(1010 ; AutoStop) => bandits (red, 10) for 3 times every 9 months
(1020 ; bread = 500) => Win
(1025 ; AutoStop) => Lose }
Indeed food can disappear if the granary is destroyed. You might very well win before 1010 and not be able to resist the bandits' attack.

1.3.2 Example of military script
MonSecond1 (1000) {
(1000 ; LordKilled) => Lose
(1010 Invasion : 100 bowmen)
(1020 ; AutoStop) => Win }
In this case you have 10 years to prepare yourself to an invasion. You win in 1020 if you just go to that date. You lose if your lord is killed. You could write the winning Event by two other means :
(1000 ; NoEnemy&InvasionLeft) => Win
and
(1010 ; NoEnemyOnMap) => Win

The first one can be placed in 1000. It checks if there are any enemies on the map, and a left invasion. So between 1000 and 1010 it will wait, and you will win if you kill all the enemies. The second must not be placed before 1010 because at this time there are no enemies and you would win without doing anything.

1.3.3 Breaking the Siege script
You want to improve your previous script and enhances it in some ways. You want to prepare a huge invasion, but if the player is doing well he will receive reinforcements.
Let us study :
MonSecond2 (1000) {
(1000 ; LordKilled) => Lose
(1000 ; NoEnemy&InvasionLeft) => Win
(1010 Invasion : 200 bowmen, 100 pikemen)
(1011, AutoStop) => Bandits (green, 50) 1 time}
The reinforcements could very well appear in the middle of the battle, or at least they could be surrounded by ennemies. This is not very good or realistic.
You may in this case write :
MonSecond3 (1000) {
(1000 ; LordKilled) => Lose
(1000 ; NoEnemy&InvasionLeft) => Win
(1010 Invasion : 100 bowmen, 50 pikemen)
(1010, NoEnemyOnMap) => Bandits (green, 50) 1 time
(1012 Invasion : 100 bowmen, 50 pikemen)}
In this case reinforcements appear only if there are no enemies on the map. The player has two years to kill the first wave, after that he will have to battle the second wave. If he is not enough fast, he will have to battle a huge invasion without any help.

Let us come back to section 1.2.3 concerning Event that can be triggered well after they were defined.
Concerning the script MonSecond2, you tried yourself the scenario, and know that in one year the first wave can be destroyed. It is hard, but possible if the player spends and uses all of its best troops. You do not want any reinforcement, but instead of you want to force the player to kill the first wave in one year and not more, due to the story you invented.
Let us consider the script
MonSecond4 (1000) {
(1000 ; LordKilled) => Lose
(1000 ; NoEnemy&InvasionLeft) => Win
(1010 Invasion : 100 bowmen, 50 pikemen)
(1011, AnyEnemyOnMap) => Lose
(1012 Invasion : 100 bowmen, 50 pikemen)}
This script will surely fail.
Indeed in 1012 there will be new enemies, and you lose.

So now keep in mind that you can trigger an action with the AutoStop Condition at the time t you want. You can trigger an action conditonned by a test from and after a time t. But you cannot decide to test something at a date t and not after.

As a last comment concerning Invasions, if you trigger several ones in the same time, they will all appear in the same place on the map, even if they are several signposts. This allows you to stack for exemple 300 crossbwomen in the same place. Waouuuu !

1.4 Concluding remarks

So in this part you have learnt how to script simple scripts. You can add plenty of Events, attacks from wolves, wheat diseases, theft in the granary, and so on and so on... But this would be not more complex -concerning the script- that what has been presented above. What would be more complex is the whole scenario, the links between timing, the map, the resources...
You do not need lengthy scripts to make interesting scenarios. I remember absolutely amazing games, including some economical ones at the hard level from the original game, that were based on a script of 4-5 Events.

In the next section you will learn some tricks that are quite complex to enhance the possibilites you have when writing Events. Read it only if you already wrote scenarios. All scenarios from the original game, and a crushing majority of scenarios from fans use only the principles presented here.

************************************************************ *****
2 Advanced programming : How to impress FireFly's Studio !
************************************************************ *****
In this section you will learn some more complex principles, that mainly turn around the principle of memory. When we will be able to use memory, we will see how to create the logical operator lower than. All the tools presented here are not elegant and have one or more drawbacks. But they multiply by so much the possibilites of your imagination that they reward well.

2.1 Memory
Events, and thus scripts, are memoryless in Stronghold. If you had 300 ale in 1010, but spend it with inns, you cannot remember in 1020 that you had 300 ale in 1010. You have no variable to store something. Except :

2.1.1 The eights kills'counters.
YourTroopsKilled from one side (Pig, Rat, Wolf and Snake) and EnemyTroopsKilled from the same sides store the amounts of casualties from each side, the one you did, and the one they did on you.
They were used in the original game to send messages. For example if you killed 10 Snakes men, he was angerous. If you killed 100 of his mens, he was asking mercy. A pure waste !
We will use these variables for much more interesting scripts.

They are also the possibility of testing YourTroopsKilled and EnemyTroopsKilled with the side 'any'. We could believe it adds kills from the four sides. This is the contrary ! It is a substracter !!! It removes kills from one of the four sides. Consider for example the following script :
Plusqu'etonnant1 (1000) {
(1000; Invasion Rat : 20)
(1000 ; EnemyTroopsKilled (Rat,19)) => Message X
(1000, EnemyTroopsKilled (Pig,19)) => Message Y
(1000, EnemyTroopsKilled (Any,15)) => Message Z
(1001 ; Invasion Rat : 20)
(1002 ; Invasion Pig : 20)}

What is happening is :
You get message Z first in 1000. Message X does not appear at the end of the first invasion. Message X appears in 1001 when 15 more Rat's men are killed. Message Y appears in 1002. Weird isn't it ? Implications of such behaviours have to be drawn so far.

Anyway we will be able to do lots of things with these eights counters. The two weird ones are left there and need more studies.

A very important remark is that kills from bandits do not raise the four counters EnemyTroopsKilled(). We will use this later.

2.1.2 Use the wolves
Wolves are very interesting objects you can handle. You can create at any times wolves. But more interestingly, you can awake wolves on a map, that will next attack the player and finaly they will be killed. So there were wolves, and then you do not have wolves any longer. So you have a binary memory.
The script for the binary memory based on wolves is as follows :
WolvesKeepMemory (t) {
(t; AutoStop) => WolfSleeps
(t+x ; Condition i, ..., Condition j) => WolfAwakes()(A)
(t+x+y, Condition i', ..., Condition j', NoWolvesOnMap) => Action a}(B)

The event A triggers the memory. The event B uses the memory.

Let us consider the following simple example. You have a very limited space to put your farms. The king asks you to have 2000 bread in 1010 and 2000 ale before 1015. You know that when 1010 arrives, there will be wheat diseases and you will not be able to gather food.

LimitedPlace1 (1000) {
(1000; AutoStop) => WolfSleeps
(1000 ; ale = 2000, NoWolvesOnMap) => Win
(1010 ; Bread = 2000) => WolfAwakes()
(1010 ; AutoStop) => WheatDisease (9*7 months)
(1015 ;AutoStop) => Lose}


This example is clearly totally misleading, since you do not need a memory for that.
Simply write
LimitedPlace2 (1000) {
(1000 ; ale = 2000, bread = 2000) => Win
(1015 ;AutoStop) => Lose}

Indeed since you cannot harvest wheat as soon as 1010 is here, you are forced to have 2000 bread in 1010 to win anyway. So a memory is useless in this case.

However it is very usefull in the next scripts :
LimitedPlace3 (1000) {
(1000; AutoStop) => WolfSleeps
(1000 ; ale = 2000, NoWolvesOnMap) => Win
(1010 ; Bread = 2000) => WolfAwakes()
(1010 ; AutoStop) => TheftFromTheGranary (9*7 months)
(1015 ;AutoStop) => Lose}

We had to change a little bit the scenario : instead of wheat disease, some bandits steal food. So in this case a memory is required, because you cannot have before 1010 both 2000 bread and 2000 ale, and bread can only be produced before 1010 and disappear after that.

The approach of using wolves as a memory has two constraints :

The first is the main one. There must be wolves on the map, and they must be protected. Indeed bandits, bear, invaders, anything else, must not kill the wolves, otherwise your script will be defective. And you have to tell the player to not kill the wolves, who must not be in any interesting area of the map. You can protect the wolves by an enemy's castle, or the passage leading to them...Or you can decide on the contrary to test if the player has been in this area. Possibilites are numerous, depending on the scenario.
The second constraint is not that much of a problem : you have to fit the power of WolfAwakes to the number of wolves present on the map. Of course, again, you can decide to use weak WolfAwakes in order to take into account several different conditions at different times, so that when there are no longer any wolves you can trigger something big...It's up your imagination.

The next paragraph proposes a much more complex example than the one of the bread.

2.1.3 Countdown to take the castle
Let us consider the example of a scenario in which there is a strong enemy's castle (let set the Pig) as well as a small village for the player. The player will have some time to prepare its invasion of the Pig's castle. However will arrive more and more invasions. But to raise the stress of the player, you can decide that he will have only a limited amount of time to take the castle, from when he will begins to fight the Pig. You can imagine that as soon as the Pig is attacked, he will ask for some big reinforcements, and the player will lose.
So you decide that the player can freely decide of the moment at which he attacks the castle, but when he decides to do so, he only has, let us say, 1 year.

This is a complex example that requires the use of a memory, EnemyTroopsKilled, and also a WinTimer !!!! Marvelous, isn't it ?

Countdown1 (t) {
(t; AutoStop) => WolfSleeps
(t ; EnemyTroopsKilled (Pig,1),YourTroopsKilled(Pig,1) ;() => WolfAwakes()
(t, NoWolvesOnMap,population 10,WinTimer(6)) => Lose
(t ; EnemyLordKilled,population 100)) => Win}

The first event is required by WolfAwakes. The second awakes the wolves if there is a single casualty from one side or the other. This will trigger the memory.
The third event is the loose event. The WinTimer requires to test an economical variable - it does not work with EnemyTroopsKilled-. The simplest is the population. The WinTimer must take into account the time required by the wolves to be killed. Here are 6 months for the timer, and you guess wolves need 6 months to be killed. The sum makes one year.
The last event is the winning event. You win if the lord is killed. Of course devious players who studied the script could say, Oh ! lets us have a big population before the fight, so that I can be ready. And then act so that my population goes below 10, so that the timer is no longer activated, and so that i have all the time needed. So you add the population 100 condition. A population requires more time to go from 9 to 100 than the 6 months of the timer. Of course when disbanding soldiers, population can skyrocket in a second. So the designer of the scenario should check that the remnant of the player's army should be well below 100 mens.

Ahahaha ! We begin some Real scripting !

As a side note, remark that the WolfSleeps does not require an AutoStop condition, but could be conditionned by something else too. In this case the WolfAwakes is not activated. Let us improve the script. Let say that if your small village remains a small village, the Pig will not pay a real attention to you, and will not have big reinforcements close to his castle. However if your population overshoot, let say 200, the Pig will have a big army close to him.
This gives :
Countdown2 (t) {
(t; population = 200) => WolfSleeps
(t ; EnemyTroopsKilled (Pig,1),YourTroopsKilled(Pig,1) ;() => WolfAwakes()
(t, NoWolvesOnMap,population 10,WinTimer(6)) => Lose
(t ; EnemyLordKilled,population 100)) => Win
(t + 20; AutoStop) => Lose}

In this case, the scenario becomes to be really really interesting. The player has the choice to work with a small village, but perhaps he will not have lots of weapons or gold, or anyhing else, and he will have to resist invasions as well, BUT he will have 20 years to take the castle to take the castle. Or he can decide to go right away for a huge town and try to crush the Pig's castle in one swift attack.

The Countdown1 example has been used in the Mad King map2.

2.2 Logical operator Lower than
If you read all previous pages, you should have noticed that we can test variables with the logical operator: equal or higher than.
For example you can test if a population is equal or higher than 200. But the logical operator less than does not exist. Perhaps the game engine can handle it, but at least the editor does not allow you to do that.
This has a very important consequence: games are one-way games. You set an objective, and the whole game is aimed at achieving it. You can only improve variables to reach your goals. You cannot say for example that, if the population is lower than 200 in 1050, you lose.
This is what is presented now. They are two ways to do that. Both have advantages and drawbacks.

2.2.2 Multiple Signposts on the map
This trick can be used only one time.
You trigger a repeated invasion of size n just before testing the variable. If the variable is higher than the threshold you want to use, you turn off repeated invasion. A few months after that you test the number of kills.
If the number of kills is higher than n, then it means than the turn off repeated invasions was not triggered.
So it finally means than the variable you tested was LOWER than the desired threshold!
Of course, number of kills can mix up with others invasions, past and future.
So you have to use a peculiar chief for that invasion. It must not be used elsewhere in the whole game.
That's it! Let use consider the following example, with the Pig's army as a reference (not used elsewhere). You have 10 years to gather 2000 food that the King will take. The scenario, of course, continues after these first 10 years, otherwise a script like MonPremier1 should work.

TaxIncome1 (1000) {
(1000, EnemyTroopsKilled(101,Pig)) => Lose
(1010; Invasion 100 Pig every 9 months)
(1010; bread = 2000) => TurnOffRepeatingInvasion()
(1010, AutoStop) => TheftInTheGranary(100)
.....}
The Pig could have attacked you before, in this case you must take into account it in the losing condition :
TaxIncome2 (1000) {
(1000, EnemyTroopsKilled(151,Pig)) => Lose
(1005; Invasion 50 Pig 1 time)
(1010; Invasion 100 Pig every 9 months)
(1010; bread = 2000) => TurnOffRepeatingInvasion()
(1010, AutoStop) => TheftInTheGranary(100)
.....}
This trick can only be used one time because a TurnOffRepeatingInvasion() action stops every repeated invasions. It has been used in the Kiev 1240 : The Mongol Invasion map.

2.2.3 One SignPost on the map
However this trick can be used several times. It is a variation of the first one. It uses the fact that bandits'kills do not count towards your own number of kills. It can be used several times, since it does not require a turn off repeated invasion.

The principle is as follows : you trigger an invasion of a particular army the month you want to test the variable. In the same time if your variable is higher than the desired treshold, you trigger some bandits. If the bandits outnumber the invasion, they will kill all the invasion, and you will not have to kill enemies, and you can again test the number of kills of that particular army. Of course bandits must appear in the same place than the invasion, that's why there can be only one signpost.
TaxIncome3 (1000) {
(1000, EnemyTroopsKilled(1,Pig)) => Lose
(Jan. of 1010; Invasion 15 Pig 1 time)
(Jan. of 1010; bread = 2000) => bandits (red, 25) one time
(1010, AutoStop) => TheftInTheGranary(100)}

Numbers given in this example are not random : you must have enough bandits to kill the whole invasion. Moreover in this example we give the month of the event. Indeed you have to carefully that bandits and invaders will fight each other. In this example we consider that the signpost is very close to the border of the map, so bandits and invadrrs appears in the same place.

If the signpost is a little bit more inside the map, you have to take into account the time for invaders to go to the signpost. Bandits always appear right on the signpost. Depending on the map you could write
TaxIncome4 (1000) {
(1000, EnemyTroopsKilled(1,Pig)) => Lose
(Jan. of 1010; Invasion 15 Pig 1 time)
(Feb. of 1010; bread = 2000) => bandits (red, 25) one time
(1010, AutoStop) => TheftInTheGranary(100)}

This trick has been used several times in the Mad King map. For example the Ling asks you one year to be very pleasant (factor 5), and very cruel another one (factor 5). Impossible to do without using advanced tools.

So far all examples of this section used EnemyTroopsKilled for a binary purpose : a failure or not. You could imagine a scenario in which the player has several tasks to do, the more he fails, the more the counter rises. And a loss occurs only if the counter reaches high values. For medium values, the game could be harder, with lots of plague, bandits, anything bad...

2.3 Concluding words
This section presented to you complex tools. They are not required to design very good scenarios, since scenarios are maps plus scripts plus story, plus plus...The whole original game was provided with very simple scritps. However the principles presented here greatly enhance your possibilites. If you use them, please add a reference to me, since I had to deeply deeply deeeeeeply think.

************************************************************ **
3 Reference
In this section are described every actions and conditions that can be used in a scenario.
************************************************************ **

3.1 Actions :
Actions are grouped in several classes : terminal actions, economical actions, troops actions, and special.
If an action can be repeated, it will be noted by *. If you set the counter to i (with i from 0 to 9 and -) the action will be repeated i times every n months. You choose the period n of the repeating action. 'n' can range from 0 to 60 months. If you set the counter i to - with a non zero period n, the action will be repeated with no end every n months.

3.1.1 Terminal Actions
They are clear : when they are triggered, you lose, or you win. They must always appear in any scenario, or it will not be playable (because either you cannot lose or you cannot win).
Win
Lose

3.1.2 Economical actions, Repeating ones :
In this group You can choose the power of some actions if they have an x in parenthesis. For example a plague of power 1 will create one cloud of poison, a plague of power 10 will create 10 clouds.

Plague (x)*
-6 to popularity, and kills peasants around the stockpile and the campfire.
HopsWeevil*
The Production from farms of Hops is reinitialized.
MadCows*
The Production from farms of cows is reinitialized.
WheatDisease*
The Production from farms of wheat is reinitialized.
AppleBlight*
The Production from farms of apple is reinitialized.
TreeFungus*
Kills many tree on the map
RabbitExplosion*
Create rabbit on the map which threatens wheat farms
TheftFromGranary (x)*
Some food disappear from the granary
TravelingFair*
+16 to pop for 3 months
Fire (x)*
Create fires on the map, where there are buildings

3.1.3 Troops Actions
These actions can create bandits of one side or the other, and wolves. An invasion CANNOT be put in this section, invasions can never triggered by conditions but only by time. Some actions have an x, you can choose their power.

WolfAttacks (x) XXX *
Create right away wolves on the map that will attack you. They appear on the map in the place where you put wolves for the first time.
WolfsSleeps
Weird action only to be used with WolfAwakes.
WolfAwakes (x)*
If a WolfSleep has been used, awakes already existing wolves on the map. They will next attack you. Does not create any wolves.
Bandits (x, red)*
Create a group of attacking bandits (macemen). They appear on a random signpost.
Bandits(x, green)*
Create a group of allied bandits (bowmen). They appear on a random signpost.
TurnOffRepeatingInvasion
Once used this action kills any present or future invasion appearing in the scenario. Only non repeating invasion can then appear on the map.

3.1.4 Others and Special
Message
Send a message to the player. You choose the message from all messages of the campaign
Jester
+2 to popularity for 6 months
Marriage
+8 to popularity for 3 months

3.2 Conditions
3.2.1 Economical Conditions
GoldAcquired
Test the gold of the treasury. From 0 to 25000
Goods
Test all the possible goods of the game. From 0 to 10000. This condition appears 4 times, so you can test 4 different goods.
%Blessed
Test the percent of blessed people from priests.
MaximumCruelity
Test the bad things factor. Opposite to good things.
Population
Test you population from 10 to 500
%DrinkingAle
Test the drinking percent of your population
MaximumPleasantness
Test the good things factor. Opposite to bad things.
NoPeopleLeft
Test if you have any peasant.

3.2.2 Military Conditions
In the following the side y means armies controlled by the pig, the rat, the snake or the wolf.
LordKilled (y)
Test if your lord has been killed by the side y.
EnemyTroopsKilled (x,y)
You have killed x men of the y side
EnemyLordKilled
You have killed a lord killed. It seems not possible to test one side or the other.
YourTroopKilled (x,y)
The y side has killed x of your men.
NoEnemy&InvasionLeft
They are no enemy on the map (including bandits) and no invasion are planned in the future.
NoEnemyOnMap
Test if they are no enemies on the map (including bandits)
AnyEnemyOnMap
Test if they are bandits or enemies on the map.
NoWolvesOnMap
They are no longer any wolves on the map.

3.2.3 Other and Special
KeepEnclosed
Test if your keep is surrounded by a continuous line of walls and gatehouses.
AutoStop
Set automatically by the editor if there are no other conditions. Means always true, so an event planned at time t conditionned by autostop will always be triggered at time t.
WinTimer (x)
More complex condition. A timer is triggered when all others conditions of the same event are true. The WinTimer becomes true at the end of the timer, which can be set from 0 to 60 months. If one of the conditions appearing in the same event becomes false during the timer, the timer restarts. For example consider an event such as (At T= t ; %DrinkingAle = 60%, %Blessed = 75%,WinTimer = 12) ( Win. You can only win if for a full duration of 12 months you have in the same time a percent of blessed people equal or higher than 75 % and a drinking percent equal or higher than 60 %.
A countdown will appear in the top left corner of the screen when the WinTimer is triggered. The WinTimer is defective with the conditions EnemyLordKilled, YourTroopsKilled and EnemyTroopsKilled.

1 Months will be mostly omitted in this article, since we do not need to be so accute in simple examples
2 available at the site www.stronghold.heavengames.com

Replies:
posted 07-16-02 21:03 EST (US)     1 / 52  
A truly excellent article. I highly recommend this for the Mapmaking 101 database. Finally an article about scenario making, not just map design.
posted 07-16-02 22:24 EST (US)     2 / 52  
This is great,,well done spock,

Damn i want IMG to be enabled......
posted 07-17-02 01:05 EST (US)     3 / 52  
not only have this bookmarked I printed off a PDF of this text. well done.. damn early to understand right now but I'll have a better read when I get back from helping a friend move...yes move at 7:30 guh...
posted 07-17-02 03:00 EST (US)     4 / 52  
thank you very much guys!
any comments to improve this article are welcome. But moreover, now, I am waiting amazing scenarios :-))))
posted 07-17-02 03:04 EST (US)     5 / 52  
Looks good, ultima.
I may put it up on the main site.

Angel Jayhawk
Eyrie • Caesar 4 Heaven • Children of the Nile Heaven • Stronghold Heaven • Caesar 3 Heaven • Emperor Heaven • Pharaoh Heaven • Zeus Heaven • My Deviations
Support your local Heaven • My Recommendations • EXCO • HALO
I believe violence will only increase the cycle of violence. — The Dalai Lama
posted 07-17-02 07:02 EST (US)     6 / 52  
thank you Jayhawk.

a note concerning the countdown 2 script i wrote this night (read the article to understand)

Countdown2 (t) {
(t; population = 200) => WolfSleeps
(t ; EnemyTroopsKilled (Pig,1),YourTroopsKilled(Pig,1),+) => WolfAwakes()
(t, NoWolvesOnMap,population 10,WinTimer(6)) => Lose
(t ; EnemyLordKilled,population 100)) => Win
(t + 20; AutoStop) => Lose}


it may not work properly in every cases. Indeed
if you begin to attack the castle with a low population, the timer will not be triggered. That's normal, but what is not is that if you raise your population over 200 after the beginning it should. Yet with this script it will not, because the WolfAwakes occurs before the WolfSleeps.
The WolfSleeps will be wasted. I am still searching a simple solution to that problem.

A first fix would be to write several WolfAwakes, starting at different time:
(t+1 ; EnemyTroopsKilled (Pig,1),YourTroopsKilled(Pig,1),+) => WolfAwakes()
(t+2 ; EnemyTroopsKilled (Pig,1),YourTroopsKilled(Pig,1),+) => WolfAwakes()
(t+3 ; EnemyTroopsKilled (Pig,1),YourTroopsKilled(Pig,1),+) => WolfAwakes()
...
Quite cumbersome, but this approach ensures that a wolfawakes could appear each year after the wolfsleep.


posted 07-17-02 07:48 EST (US)     7 / 52  
I have just found one application of EnemyTroopsKilled(Any) instead of EnemyTroopsKilled(one of the four camp)

very subtle, but gives you even more possibilites in designing scripts.
Let us imagine a scenario where they are two enemies castles, and you. For example the pig, and the wolf.
The player can decide which castle he attacks first, but he knows that if he did not kill firstly the wolf, something really really bad will happen to him.
Of course, for the fun, the wolf castle will be harder to take down, and will ensure heavy losses for the player.


Interesting isn'it?

Let see the script. Quite simple but very very subtle. We assume that the two castles are defended by the same number of men, let say 20.

Plusqu'etonnant2 (1000) {
(1000 ; EnemyTroopsKilled (Wolf,12)) => TheftFromTheGranary(100% every month with no end)
(1000, EnemyTroopsKilled (Pig,12)) => Something not so bad
(1000, EnemyTroopsKilled (Any,9)) => Something not so bad
}

What is happening is that: if you first destroy at half the pig, with 9 kills, its own counter will never reach again 12 since 9+12 equals 21 and the 9 are taken by the 'any' counter.
Only the counter of the wolf can reach 12 to 20. So the TheftFromTheGranary will occur at half the kills.
If the player does the opposite, first he destroys at half the wolf, the wolf's counter will never be able to reach 12.

posted 07-17-02 08:33 EST (US)     8 / 52  
An improvement on the previous Countdown script is to put several WolfAwakes, but this time they depend on the number of kills.
You do not need to write 200 Events if they are 200 years...

the script:

(t ; EnemyTroopsKilled (Pig,10)) => WolfAwakes()
(t ; EnemyTroopsKilled (Pig,20)) => WolfAwakes()
(t ; EnemyTroopsKilled (Pig,30)) => WolfAwakes()
...

This time you test the amount of damage done to the pig. You can work by percent on the total amount of troops of pig, for example yu can add a line for every 10%
This way if the player kills 20% of the pig with a low population, but rises to 201 after that, the wolf awakes will trigger at 30% of damages.

Of course a player could stop to attack at 25% of damage and wait until he has an extraordinary army.
No solution to this, but this could be considered as cheating, since the unfair player would have to study your script to find the thresholds and next to check the number of kills he did!

posted 07-17-02 12:01 EST (US)     9 / 52  
:: saves page ::

ultima_spock, you've made Stronghold Scenario Design almost a science rather than an art

Truly outstanding.


"That buzzing-noise means something. You don't get a buzzing-noise like that, just buzzing and buzzing, without its meaning something. If there's a buzzing-noise, somebody's making a buzzing-noise, and the only reason for making a buzzing-noise that I know of is because you're a bee." — Winnie-the-Pooh, the World's greatest philosopher

Tower of Stronghold & Crusader Scenario Design

posted 07-17-02 12:35 EST (US)     10 / 52  
Wow, that...wow. Nice job. I'll second (or is it third) the idea of formatting this for Mapmaking 101.

- .... ..- .-. -.. .-.. ----- .----
.... --. / -.-. .... . .-. ..- -...
.. ..-. / - .... . / --. . .-. -... .. .-.. / . ... -.-. .- .--. . ... --..-- / .-- . / .- .-. . / .- .-.. .-.. / -.. --- --- -- . -..
posted 07-17-02 13:00 EST (US)     11 / 52  
Can I fourth that?!

Ultima_Spock, this looks incredible on paper. It'll take me a while to digest (i'm slow at absorbing stuff ) but I intend to design some test scenarios based on your work, and I really can't wait to see how this affects the maps.

I take my hat off to thee... great work!

With respect,

Sulis


The Bretwalda Chronicles: Northumbria|Anglia|Mercia
"There is material enough in a single flower for the ornament of a score of cathedrals" - John Ruskin
posted 07-17-02 15:03 EST (US)     12 / 52  
I'll be looking into this more when I get home from work, but....

This looks like some really good stuff! Question for you:
Is the script a file that can be opened and modified, or is this script created while running Stronghold in the Map Editor somewhere? Kind of a dumb question that I can probably figure out once I get home, but I just can't wait that long to find out (assuming this will be read and answered before I get home tonight, of course).

At any rate, I'm really looking forward to being able to do some scripting and make some really great scenarios!!! I've been busy DLing and playing for the last week, and I even found time to review one. I'll have to make it a point to review a scenario after playing it. I'm looking forward to creating a great map or 10 myself however, and would love to get my hands into this whole scripting thing. This is exciting, and I'm so glad you posted this, ultima_spock!

[This message has been edited by Seer (edited 07-17-2002 @ 03:05 PM).]

posted 07-18-02 02:52 EST (US)     13 / 52  
Seer, we're always happy with more reviews

The scripts need to be put in the scenario through the Event editor.


Angel Jayhawk
Eyrie • Caesar 4 Heaven • Children of the Nile Heaven • Stronghold Heaven • Caesar 3 Heaven • Emperor Heaven • Pharaoh Heaven • Zeus Heaven • My Deviations
Support your local Heaven • My Recommendations • EXCO • HALO
I believe violence will only increase the cycle of violence. — The Dalai Lama
posted 07-18-02 06:16 EST (US)     14 / 52  
thank you again guys. this warms my heart, and i feel well to know that i did not work for nothing.

again any comments welcome. Tommorow evening i will leave for vacations and come back only in septembre. Since i have access to internet only at my job, from this saturday to septembre i will not be there any more. If you have any questions, hurry!

posted 07-18-02 08:14 EST (US)     15 / 52  

Quote:

For example if you killed 10 Snakes men, he was angerous. If you killed 100 of his mens, he was asking mercy. A pure waste !

You can also do it in this way:

After-battle messages

Event 1

Condition a: Date t (whatever)
Effect a: Invasion (whatever)

Event 2

Condition a: Date t+ 1 month(one month after the invasion)
Condition b: No enemy on map
Effect a: Message from the enemy

This way, the enemy will send a message when it has lost all units on the map. Even if there are multiple enemies and invasions, it will still work. However, it the invasions overlap, then there will be a delay.

I have another "script" to add to ultima_spock's collections:

Wrench thrown in the works

Event 1 (victory conditions)

Condition a: 100 Bread
Effect a: Win

Event 2

Condition a: 20 Bread
Effect a: Theft from the Granary (10%)

Event 3

Condition a: 40 Bread
Effect a: Theft from the Granary (20%)

Event 4

Condition a: 60 Bread
Effect a: Theft from the Granary (30%)

Event 5

Condition a: 80 Bread
Effect a: Theft from the Granary (40%)

You can set the percentages to whatever you want. This script will trigger a theft at the specific bread amounts, so the player cannot survive the mission without suffering from each of the thefts. This also makes the scenario more realistic as there are no cyclic events. You can use drought event for wood conditions, hops worms for hops conditions and so on.

edit: fixed the after-battle message script


"That buzzing-noise means something. You don't get a buzzing-noise like that, just buzzing and buzzing, without its meaning something. If there's a buzzing-noise, somebody's making a buzzing-noise, and the only reason for making a buzzing-noise that I know of is because you're a bee." — Winnie-the-Pooh, the World's greatest philosopher

Tower of Stronghold & Crusader Scenario Design

[This message has been edited by lord_yoshi (edited 07-29-2002 @ 03:16 AM).]

posted 07-18-02 08:57 EST (US)     16 / 52  
Indeed Lord yoshi, what you wrote is better than cyclic events. For the after-battle messages, I was talking about a scenario of the original game where there was a Snake's castle and pig invasions. So you cannot use your approach in this case. Indeed you do not know when the snake's troops will be killed by the player, and you must rely only on EnemyTroopsKilled.
posted 07-18-02 16:01 EST (US)     17 / 52  
I echo thurd01's sentiment, WOW! Excellent work ultima_spock. From what I've read so far, this looks very good and has a lot of potential. Like Sulis, I also need to digest this info until I feel comfortable with it. You've given us some great scripting tools, many more than I thought were possible with the editor. I should have seen some of these myself with my background in programming. I guess I never really looked into the possibilities and I haven't had much experience with scripting.(excuses,excuses)

Anyway, I think I can safely say for all of us here, a big thankyou and job well done!


What's with the old saying, "Like having your cake and eating it too"? That's easy.
Now, eating your cake and still having it, that's a wee bit harder to do.
posted 07-18-02 16:10 EST (US)     18 / 52  
Yoshi, you've made me realise that I need to spend more time playing with scenarios! Taking nothing away from Ultima_Spock here, you've posted something simple that I just never contemplated, or thought would work! This really interests me because it feels like a shot in the arm, so to speak, something new to delve into. I feel like I should have being doing this months ago!!

Thanks

posted 07-18-02 22:34 EST (US)     19 / 52  
My brain aches and I feel an evil smile creeping onto my face, as I imagine all the tortuous possibilities. Super travail, Ultima. Well done.
posted 07-19-02 04:47 EST (US)     20 / 52  
Maybe we should make a collection of all the possible "scripts" you can do in the Events Editor? Kind of a trigger collection for Frequently Used Scripts (FUS)?

Btw, if you think these Stronghold "scripts" are cool, you should see what people have done with the AoK triggers!


"That buzzing-noise means something. You don't get a buzzing-noise like that, just buzzing and buzzing, without its meaning something. If there's a buzzing-noise, somebody's making a buzzing-noise, and the only reason for making a buzzing-noise that I know of is because you're a bee." — Winnie-the-Pooh, the World's greatest philosopher

Tower of Stronghold & Crusader Scenario Design

posted 07-19-02 07:12 EST (US)     21 / 52  
I can do the thread myself, but if someone else wants to do it, I have a suggestion of the thread structure here:

INTRODUCTION

QUICK TUTORIAL(S) FOR BEGINNERS

BASIC SCRIPTS

ADVANCED SCRIPTS

EVENTS REFERENCE

SCRIPTING Q&A

Suggested layout used in the scripting studio thread:

Condition - "#66CC33"
Effect - "red"
Event - "orange"
Script - "#0099ff"

Event 1 - italics

Condition a: - whisper or font size="1"
Effect a: - same as for condition

Name suggestions for the thread:

The Scripting Studio, The Scripting Library, The Scripting Workshop, the place where the monks write books in a monastery, but I can't remember what it is called in English ...

ultima_spocks's article would be a major contributor to the thread, but naturally other designers would hopefully post new scripts, too. The Q&A section would consist of all questions related to events (whoever wants to make the thread will have to search for these questions, which can be hard work).

So, anyone wants to volunteer?

If the council of the SD Magi would still exist, anyone making this thread would have automatically been promoted into a High Mage


"That buzzing-noise means something. You don't get a buzzing-noise like that, just buzzing and buzzing, without its meaning something. If there's a buzzing-noise, somebody's making a buzzing-noise, and the only reason for making a buzzing-noise that I know of is because you're a bee." — Winnie-the-Pooh, the World's greatest philosopher

Tower of Stronghold & Crusader Scenario Design

posted 07-19-02 09:10 EST (US)     22 / 52  
i am leaving. I will come back in septembre with other scenarios i think. Please review Kiev 1240 and The mad King maps. These two scenarios are not for everyone. I am wondering if i have to make very difficult scenarios or simpler ones.
I submit the doc file of my article in the tools section, i have added one or two paragraphs.

I think it would be a good idea to put an article on this topic in the mapmaking section. Feel free to use my own one, but at least refere to my work. I think that my notation could be better than the one of yoshi. The latter, with all the color, could be more confusing. I don't know.

I wish all of you to have a great august month

posted 07-19-02 10:30 EST (US)     23 / 52  
Well, I finally realized that this 'scripting' is really just creating events rather than 'writing some code' type of thing. I had the wrong impression all along and was thinking that I would be able to actually write some code for events. I was truly drooling over the ability to do that.

Thus my confusion on where to create these scripts in my previous post.

This is still good stuff though and should be helpful for a lot of map designers to help achieve balance and make scenarios more interesting.

posted 07-20-02 00:03 EST (US)     24 / 52  
Awesome, Spock. Thanks alot for taking the time, very much appreciated, seeing as the manual has very limited info.

You provide food,water,and shelter for a dog,
he thinks "wow, this guy must be a god!".
You provide food,water,and shelter for a cat, he thinks "wow, I must be a god!".
posted 07-26-02 23:57 EST (US)     25 / 52  
Ok, this is gonna sound dumb, and Im not sure if I passed this one by in the manual, but HOW do you input this into a map? I think Seer asked, but got no response. From my limited knowledge of scripting UnrealED and Quake3, I KNOW that you can go fruther than mear triggers, but much much more. Please please someone tell me how to implement this into a map. *become an instant regular at SHHSD *

Guard your walls, I am coming.
My Recommendations
« Previous Page  1 2  Next Page »
Stronghold 2 » Forums » Stronghold and Crusader: Scenario Design and Modding Forum » course about scripting (very long)
Top
You must be logged in to post messages.
Please login or register
Hop to:    
Stronghold 2 | HeavenGames