modding-guide

Written by Serp

The Anno devs meanwhile finally published an xml file that contains all allowed properties and values with sometimes a short description (next to assets.xml of game files): properties-toolone.xml (I will call it p-t.xml below as abbreviation).
You can look up many things there to find out what is supported where and what they do.
In the following I copy pasted these property descriptions and added some notes to it to make some things a bit more clear.

Properties/Values of Quests explained:

See templates.xml searching for <Name>QuestTypes</Name> to see the properties a normal quest has. See p-t.xml and search for <Name>Quest</Name> (there are multiple results, in current version it is in line 46508) and the other relevant properties.
Properties/values I don’t mention here should be self explanatory or already explained enough by the description in p-t.xml.

“Defaults to” is based on the default values defined in properties.xml. There may be other values defined in the template you are using (if defined nowhere the values will be 0).

StarterMessage/SuccessMessage :

and all those “Message” values:
According to p-t.xml you can define a Notification here or set SuppressMessage: “Do not play any notification and do not fall back to PamSy configuration”.
If no message is defined here and SuppressMessage is not set to 1, the game automatically adds CharacterNotifications based on the “PaMSy” of the Questgiver. Eg. the pirate Anne Harlow (GUID 73) is using:

<ParticipantMessageObject>
  <ParticipantMessages>148</ParticipantMessages>
</ParticipantMessageObject>

while in the asset GUID 148 are notifications defined that should be played in specific situations, eg. on “QuestSuccessful” and so on.
So most of the time for generic quests it is enough to leave this “Message” values from the Quest empty or even better do completely skip them (not mention them at all in your code) since they are inherited from the templates/internally prefilled with PaMSy anyways unless you want to add your own text/audio for specific messages.
Note: This “internally prefilled” mechanic of PaMSy seems not to work like normal inheritance. Because otherwise a template Notification adding new Text should not overwrite a Subtitle. But it does for whatever reason. So if your Quest template adds not-empty Notifications (like A7_QuestSustain does for InvitationMessage), you most likely have to add at least the NotificationSubtitle from PaMSy again (eg. open assets.xml, go to GUID 148 for Harlow and search for QuestInvitation and copy paste the part with subtitle into your Quests InvitationMessage Notification)

OnQuestStart/OnQuestDeclined:

and all those “On…” values followed by ActionList:
Here you can add any Actions you want to be executed when the Quest reaches a specific status. Most names are self explanatory. Make sure to read the description in p-t.xml if you are not sure.
Eg. OnQuestStart already happens as soon as the player is able to accept the Quest (eg. the “quest star” to accept a quest becomes visible), while OnQuestActive starts as soon as the player accepted the Quest.

QuestGiver:

“This is the guys picture will be shown in the quest”. As mentioned above this is also where the default messages will be taken from. A quest can not start, if the QuestGiver does not exist in the game (eg. Jorgensen can not start a quest if she is not part of the game). Most neutral QuestGivers like the farmers (<GUID>86</GUID>) are using the Profile_Virtual_NeverOwnsObjects template which has <CreateModeMeta>AutoCreate_Always</CreateModeMeta> defined to make sure they always exist in every game.

StoryText/DescriptionText/AlternativeRewardTitle/QuestHints:

MaxCallOut/MaxSolveCount/MaxAbortCount:

“Maximum number that this quest can be triggered.” / “Maximum number that this quest can be solved.” / “Maximum number that this quest can be aborted.”
Defaults to -1. A value <= 0 means infinite calls are possible. Eg. use these to make sure eg. a QuestPool can only start your Quest once at all/until solved once.
The same Quest can only be active once at the same time IF started via a QuestPool (ActionStartQuest can start multiple times), regardless of any other settings.

CountForQuestLimit:

“True if this quest counts for the global and the pool quest limits.”. Defaults to 1. Set this to 0 if you don’t want a quest to prevent other quests of the same pool to be started. I don’t know if there really is a global limit and how much it is.

PreActivationTimer/QuestTimeLimit:

QuestCategory:

“The category of the quest defines the internal behaviour of the quest.”. Defaults to MainQuest. Since we can neither change nor look at the “interal behaviour”, we can only test a bit what this does exactly. See datasets.xml QuestCategory for all allowed values. But it might be best to always use “RandomQuest” here unless you want to add a new Quest to the vanilla Story Questline.

QuestActivation:

“Defines at which point this quest changes its status to “Activated”. Only activated quests are visible in the Quest Tracker.” Defaults to QuestStart. For allowed values see datasets.xml QuestActivationTime.

IsAbortable:

“If true, this quest can be aborted in the assignment center or the quest tracker”. Defaults to 1. Allow to abort accepted/active quests or not.

NeededProgressLevel:

“This quest can only be triggered if the player progress level matches these checked levels.” Defaults to EarlyGame;EarlyMidGame;MidGame;LateMidGame;LateGame;EndGame so all progresslevels are allowed by default.

LatencyTimer/DelayTimer:

QuestTrackerVisibility/QuestBookVisibility:

ConfirmOnReached/CustomizeConfirmOnReachedCondition/ConfirmOnReachedCondition:

HasExclusiveQuestGiver:

“Optional quests are only started if no other exclusive quest is already running with the same quest giver”. Defaults to 1. Most of the time you should set this to 0 if you don’t want to block other quests from the same QuestGiver.

QuestBlackList:

I don’t know what this does, it is neither used in vanilla nor explained in p-t.xml. I assume quests listed here can not be active at the same time? But one needs to test.

QuestSessionDependencies/QuestBlockedSessions:

QuestDifficulty:

“This is the balanced difficulty of this quest”. Defaults to Easy. Allowed values: Easy, Medium or Hard. These are mostly relevant for (money) reward balancing you can find in RewardBalancing GUID 140501, see also Reward.

KeepCheckingPreconditionsWhenRunning:

“If true, the quest keeps checking the preconditions and will abort automatically if they are not met any longer”. Defaults to 0. This is eg. especially helpful for Quests involving QuestGivers you can have different treaties with. Eg. you can add a PreCondition that the player must at least have TradeRights with the QuestGiver and set KeepCheckingPreconditionsWhenRunning=1 to automatically abort the active Quest if this is no longer the case.
Note: KeepCheckingPreconditionsWhenRunning does only check the PreConditions of the Quest itself, not the ones from the executing QuestPool.
The game does already cancels Quests to players you declare war to, but this is bugged since it only cancels one Quest. If there are multiple they are not all cancelled, so it is better to also include this as PreCondition if practicable.

ReputationQuestFail/ReputationQuestDeclined/Reward-RewardReputation:

Adding a list here with ReputationParticipant (“The participant that rewards reputation”) and ReputationAmount (“The amount of reputation that is rewarded. This number can be negative to create a reputation loss”). So you can make the player loose reputation when a quest fails, but also gain reputation with other AIs (not only QuestGiver).
Reward/RewardReputation is defined outside of the Quest property, but works the same and is awared on Success of the Quest, see also Reward.
Note: Many Quest templates prefill ReputationQuestFail and RewardReputation with a ReputationAmount (for no sane reason). So if you don’t want any reputation gain/malus it is not enough to simply not mention it in your Quest (because it defaults to Human0 as ReputationParticipant, which does nothing, but is still displayed). Instead you have to overwrite the inherited list in your asset by adding <ReputationFailList /> and <RewardReputation />.

Reward:

ResetPreconditionsAfterQuestWasTriggered:

“If true, the interal state of all preconditions will be reset. This is especially important for ConditionEvent which otherwise endlessly remembers any received event”. Defaults to 0. I think this is only relevant if your PreCondition contain ConditionEvent like SessionEnter an such events. If you use such an event and leave this value 0, only “Entering the Session” once is enough to have the PreCondition true always, also for the next time the same Quest might start. If you set it to 1 instead, you must enter the Session everytime again to again allow the Quest to be started.
So most of the time this is not relevant for you.
Note: For testing is also helpful to set this to 1! Because without it, changing the code of PreConditions has no effect on savegames! (Already started quests can not be changed much anyways, but even newly started Quests of that GUID won’t have your new code as PreCondition without this set to 1)

RespectRelatedQuestSession:

“If true, this quest tries to spawn in the same session as another quest that is configured in the preconditions. We try to determine the correct quest out of all conditions given. An assert will be thrown if we don’t manage to find a quest but this flag is set”. Better define the sessions in different way to be sure, eg. in QuestSessionDependencies if started via a Pool or with QuestSession if started via ActionStartQuest.

HasStarterSpeechBubble/StarterSpeechBubble/HasSuccessSpeechBubble/SuccessSpeechBubble:

Did not use this yet. Feel free to add how to use this if you know more about it.

CanBeActiveForMultipleParticipants:

“Only takes effect in quest pools. Checking this will stop preventing the quest from being called from the pool, while another player has this quest running”. Defaults to 0, but set it to 1 if you want it possible that the Quest can be active for more than one human player at the same time.

QuestOptional:

This contains on what object (where) you want your Quest to start. Mostly relevant if you set QuestActivation to ManualActivation, then this object will be the one with the star-icon over it the player has to click on to get the Quest offered.

WinConditions:

You can set up as many WinConditions to any quest as you like.

There are several WinCondition Objectives to choose from, see templates.xml and search for <Name>QuestObjectives</Name> to see them all. I will not go into detail with all of them, study the templates, vanilla assets.xml and properties-toolone.xml to find out how they work and what they do. Also see my Tutorial Creating a Quest for a few examples.

ConditionQuestObjective:

Regardless what objective you choose, all templates have this ConditionQuestObjective property.


Properties/Values of Questpools:

(Again take a look at p-t.xml and search for <Name>QuestPool</Name> (the one that has “DisabledByDefault” directly below it) to see all allowed values and some description)

QuestPools are a helper construct to automatically start quests on regular basis if PreConditions are fullfilled. Eg. if you made like 10 Quests that simply should be chosen randomly if preconditions are fullfilled (just like the games Random Quests) you can put your Quests in a pool and define how often the pool should start up to how many quests at once and so on. It also supports adding QuestLines into the pool instead of Quests directly to make sure they are started one after the other.

A Pool will automatically start the Quests as soon as the PreConditions of the Pool and of the first Quest of the Questlines are met. There is no need to add this pool somewhere else or to activate it. If you set DisabledByDefault=1 in a pool it will be disabled (not starting any quests) and need to be enabled first with ActionSetQuestPoolEnablement and IsQuestPoolEnabled=1. But enabling/disabling pools with ActionSetQuestPoolEnablement is only needed if you are not able to include it as PreCondition (this vanilla pool is eg. disabled when the player looses the continental island).
Some QuestPools are also added to AI player assets, like <QuestPool>150082</QuestPool> is added to Jorgensen. This is not mandatory, as far as I know this only means that Quests are offered at the lighthouse of the AI and you don’t have to define the starting point of a Quest in the Quest itself.

DisabledByDefault:

Disabled Pools do not start Quests. Defaults to 0. For basic usage, just leave this at 0 and don’t mess with Enabling/Disabling QuestPools. Most of the time the PreConditions you can define for Pools/Quests are more then enough. Eg. the vanilla game disables the QuestPool for Cape-Quests if the player looses the continental island. An alternative would be to add “owning the continental island” into the PreConditions of the Pool. There may be cases where disabling/enabling Pools is better, but they are rare (use ActionSetQuestPoolEnablement and IsQuestPoolEnabled=1 to enable a disabled pool).

Quests/Groups/SubPools:

Lists inlucding Quests/Groups/SubPools, you can define a Weight for each of them to have some more likely to be chosen.

Note: I think one can not combine SubPools and Quests within the same QuestPool, at least in my test the Quest never triggered.
I found no integrated way to make the pool randomly start no Quest after the Cooldown (similar to random rewardpools using EmptyRewardPool to have the chance for no reward). But adding an AutoSolved-Quest kinds of act like this, you find one in my shared mod shared_ObjectDummies (v1.04 and higher).

IsMainStoryPool:

Defaults to 0. Not really sure what this does, but I assume it should only be used for vanilla story Quests, so better don’t touch this.

IsTopLevel:

“If true, this pool will be used directly to select quests and does not depent on a parent pool to be chosen.” Defaults to 0. Relevant because Pools can even include other pools. Only the TopLevel pool (the one that is not included within other pools) should have this set to 1 and it means that this pool is the one responsible to start the quests (while lower-level pools wait for “instructions” from their higher pool).

QuestLimit:

“The max number of quests that this pool can call simultaneously”. Defaults to 1. So the amount of quests that can be active at the same time started from this pool (if PreConditions are met).

PoolCooldown/CooldownOnQuestStart/CooldownOnQuestEnd/QuestCooldown/AffectedByCooldownFactor:

QuestSessionDependencies:

“If any sessions will be linked here, than this pool does only select new quests if one of the given sessions is currently running”. Also supports Region.

QuestPoolCooldownMultiplierList:

No description and never used from the game, but looking at p-t.xml <Name>QuestPoolCoodownMultiplier</Name> looks like one can make a Pool to multiply his Cooldown based on the Happiness of a specific population to make Quests appear more often.

QuestPoolActionCallbacks:

Here you can define Actions eg. on success or on discard and so on of Quests started via this Pool. You can also define these actions within the Quests itself, but if you want them to be the same for all quests of this pool, define it here. In vanilla there is eg. often code to remove the Quest-Offer-Ship (the one with a star above) if the Quest is discarded (rejected from the user before it really starts).

PreConditionList:

Here you can define Conditions that must be true for the Pool to start Quests. As long as they are not true, the pool does not start Quests. You can also define PreConditions for individual Quests in the Quests themself. Take a look at vanilla PreConditionList, eg. also with <SubConditions> to see how to use it.