Age of Wonders III

Age of Wonders III

The Fate of Emrilia
WoodChip  [developer] Apr 30, 2020 @ 4:31pm
Quick FoE Script Guide
General Information about scripts in Age of Wonders III
Scripts have to begin with *HexWorld:GetScriptingS():* After that, the specific script to execute can be added.
Note that you can use if/and/then/else commands to create more complex scripts than described here.

There are several ways which can be used a add scripts to your mod.

First of all, scripts can be attached to marker placed on the map. In this case, the following lines are needed to activate the script once a unit enters or leaves the marker:

function Class:Event_OnStackEnters(argTarget) [INSERT SCRIPT HERE] end
or:
function Class:Event_OnStackLeaves(argTarget) [INSERT SCRIPT HERE] end
or:
function Class:Event_OnStackArrives(argTarget) [INSERT SCRIPT HERE] end

It is possible to differentiate between different players who can or cannot activate the script, using the player alias filter-settings of the marker. After creating a script, you have to drag and drop the "declared script" to the "attached script"-section or nothing will happen.

Second, scripts can be acitvated using the map settings. Most of these options are pretty useless. For the FoE Mod, I used the Settings in the Script-Manager in the player sections. Helpful entries are "On Players Meet", "On Player Trespasses", "On Leader Unit Dies", "On Defeat", "On Victory". You can also use the map settings to add extra income for some players.

Third, scripts can be attached to buttons of story messages. This is very helpful to differentiate between scripts that should be activated only for AI players or only for Human players. AI players never activate scripts that are attached to story messages. This means, you could activate or deactivate different markers or timers for AI vs Human players as long as you force the player to receive at least one story message.

Fourth, you can add scripts if something happens to a unit (this means, if it dies) using the "scripting" button when selecting the unit and adding the following commands:
function Class:Event_OnDeath(argTarget) [INSERT SCRIPT HERE] end

Overview of useful scripts: Part 1: Scripts to check some condition
  • if HexWorld:GetScriptingS():PlayerHasMetPlayer("PLAYER1", "PLAYER2") == true then ...
  • if HexWorld:GetScriptingS():PlayerGetDiplomaticState("PLAYER1", "PLAYER2") == 1 then ...
  • if HexWorld:GetScriptingS():CityGetDiplomaticState("PLAYER1", "CITYALIAS") == 1 then ...
  • if HexWorld:GetScriptingS():CityGetRace("CITYALIAS") == "TIGRAN" then ...
  • if HexWorld:GetScriptingS():StructureGetState("STRUCTUREALIAS") == 10 then
    if HexWorld:GetScriptingS():StructureGetOwner("CITYNAME") == "PLAYER1"

A diplomatic state of 1 means neutral, 2 means war, 3 means peace, 4 means alliance.
A teleporter with state "9" is activated. A sctructure with state "10" is deactivated.
City states: 1 = razed, 2 = under control of a player, 3 = occupied.
Watch Tower, Forts, Spelljammer sates: 1 = razed
Treasure states: 5 = unexplored, 6 = explored
Visit structure states: 7 = charged, 8 = depleted

With the following script it is possible to check the alias of a specific unit entering a hexfield (in this case, the first unit of the stack and it should not be named "HERO"):
function Class:Event_OnStackEnters(argTarget) stackalias = HexWorld:GetScriptingS():GetAlias(argTarget) checkunit = HexWorld:GetScriptingS():StackGetUnit(stackalias, 0) checkunitalias = HexWorld:GetScriptingS():GetAlias(checkunit) if checkunitalias ~= "HERO" then ... end end

For example, in FoE Reforged, I did not want Gryx to sacrifice himself in his experiments, so the according scripts will only be executed if the unitalias is not named "GOBLIN".

Script Example: check if a unit with a specific alias (in this case "CANNON") is part of a stack entering a stack area trigger (use this if you don't know which order the units have)
function Class:Event_OnStackEnters(argTarget) stackalias = HexWorld:GetScriptingS():GetAlias(argTarget) blastunit = HexWorld:GetScriptingS():StackGetUnit(stackalias, 0) blastunitalias = HexWorld:GetScriptingS():GetAlias(blastunit) if HexWorld:GetScriptingS():StackGetNumUnits(argTarget) == 6 then blastunit1 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 1) blastunitalias1 = HexWorld:GetScriptingS():GetAlias(blastunit1) blastunit2 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 2) blastunitalias2 = HexWorld:GetScriptingS():GetAlias(blastunit2) blastunit3 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 3) blastunitalias3 = HexWorld:GetScriptingS():GetAlias(blastunit3) blastunit4 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 4) blastunitalias4 = HexWorld:GetScriptingS():GetAlias(blastunit4) blastunit5 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 5) blastunitalias5 = HexWorld:GetScriptingS():GetAlias(blastunit5) end if HexWorld:GetScriptingS():StackGetNumUnits(argTarget) == 5 then blastunit1 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 1) blastunitalias1 = HexWorld:GetScriptingS():GetAlias(blastunit1) blastunit2 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 2) blastunitalias2 = HexWorld:GetScriptingS():GetAlias(blastunit2) blastunit3 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 3) blastunitalias3 = HexWorld:GetScriptingS():GetAlias(blastunit3) blastunit4 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 4) blastunitalias4 = HexWorld:GetScriptingS():GetAlias(blastunit4) blastunitalias5 = "EMPTY5" end if HexWorld:GetScriptingS():StackGetNumUnits(argTarget) == 4 then blastunit1 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 1) blastunitalias1 = HexWorld:GetScriptingS():GetAlias(blastunit1) blastunit2 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 2) blastunitalias2 = HexWorld:GetScriptingS():GetAlias(blastunit2) blastunit3 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 3) blastunitalias3 = HexWorld:GetScriptingS():GetAlias(blastunit3) blastunitalias4 = "EMPTY4" blastunitalias5 = "EMPTY5" end if HexWorld:GetScriptingS():StackGetNumUnits(argTarget) == 3 then blastunit1 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 1) blastunitalias1 = HexWorld:GetScriptingS():GetAlias(blastunit1) blastunit2 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 2) blastunitalias2 = HexWorld:GetScriptingS():GetAlias(blastunit2) blastunitalias3 = "EMPTY3" blastunitalias4 = "EMPTY4" blastunitalias5 = "EMPTY5" end if HexWorld:GetScriptingS():StackGetNumUnits(argTarget) == 2 then blastunit1 = HexWorld:GetScriptingS():StackGetUnit(stackalias, 1) blastunitalias1 = HexWorld:GetScriptingS():GetAlias(blastunit1) blastunitalias2 = "EMPTY2" blastunitalias3 = "EMPTY3" blastunitalias4 = "EMPTY4" blastunitalias5 = "EMPTY5" end if HexWorld:GetScriptingS():StackGetNumUnits(argTarget) == 1 then blastunitalias1 = "EMPTY1" blastunitalias2 = "EMPTY2" blastunitalias3 = "EMPTY3" blastunitalias4 = "EMPTY4" blastunitalias5 = "EMPTY5" end if blastunitalias == "CANNON" or blastunitalias1 == "CANNON" or blastunitalias2 == "CANNON" or blastunitalias3 == "CANNON" or blastunitalias4 == "CANNON" or blastunitalias5 == "CANNON" then ... end end

Note that forcing the game to define unitalias when there is no unit may lead to immedate crashes.

Overview of useful scripts: Part 2: Scripts to change/do something
  • HexWorld:GetScriptingS():PlayerSetDiplomaticState("PLAYER1", "PLAYER2", 2, true)
  • HexWorld:GetScriptingS():CitySetDiplomaticState("CITYALIAS", "PLAYER", 3)
  • HexWorld:GetScriptingS():PlayerSendMessage("MESSAGE", "PLAYER")
  • HexWorld:GetScriptingS():TimerStop("TIMERALIAS")
  • HexWorld:GetScriptingS():TimerStart("TIMERALIAS")
  • HexWorld:GetScriptingS():TimerReset("TIMERALIAS")
  • HexWorld:GetScriptingS():MarkerEnable("MARKERALIAS")
  • HexWorld:GetScriptingS():MarkerDisable("MARKERALIAS")
  • HexWorld:GetScriptingS():PlayerSetVictorious(PLAYER, Text)
  • HexWorld:GetScriptingS():PlayerSetDefeated(PLAYER, Text)
  • HexWorld:GetScriptingS():PlayerSetGold("PLAYER", gold-integer)
  • HexWorld:GetScriptingS():PlayerSetMana("PLAYER", mana-integer)
  • HexWorld:GetScriptingS():PlayerRemoveCP("PLAYER", casting-points-integer)
  • HexWorld:GetScriptingS():StructureSetState("STRUCTUREALIAS", 9) # this means active
  • HexWorld:GetScriptingS():StructureSetState("STRUCTUREALIAS", 10) # this means inactive
  • HexWorld:GetScriptingS():StructureSetOwner("CITYALIAS", "PLAYER1")
  • HexWorld:GetScriptingS():SpawnGroupSpawnAtPosition("SPAWNERGROUP", HexWorld:GetScriptingS():GetPosition("MARKERALIAS"), "SW")
  • HexWorld:GetScriptingS():CityRaze(CITYALIAS, PLAYER)
  • HexWorld:GetScriptingS():DestroyCityGuards("CITYALIAS")
  • local markerPosition = HexWorld:GetScriptingS():GetPosition("MARKERALIAS")
    HexWorld:GetScriptingS():PlayerCastSpell("INDEPENDENTS/PLAYER", markerPosition, "#0000011A00000B56")
  • HexWorld:GetScriptingS():PlayerApplyHappinessModifier("PLAYER", "#0000012000000076", "text ...")
  • HexWorld:GetScriptingS():PlayerApplyAlignmentModifier("PLAYER", "#0000014E00000107", "text ...")

Note that you need the ID of the spell you want to be casted for the last script example. You can find it at the according .rpk-file, which can be opened using the package manager / Mod Editor. For example, the spell-ID's of the sorcerer-class can be found in the "SkillSorcerer.rpk"-file.
The "SW" at the end of some scripts means "South-West"; you can change it to the direction you want the spawned or teleported unit to look at.

Overview of useful scripts: Part 3: Scripts to change AI behaviour
  • HexWorld:GetScriptingS():AISpellcastingLimit(PLAYER, limit-integer)
  • HexWorld:GetScriptingS():AISetPlayerTargetBounty(PLAYER, TARGETALIAS, bounty-integer)
  • HexWorld:GetScriptingS():SetOffensiveAIEnabled("PLAYER", bool)
  • HexWorld:GetScriptingS():DiplomacyAIEnabled("PLAYER")
  • HexWorld:GetScriptingS():DiplomacyAIDisabled("PLAYER")

The first script can be used to increase the number of spells the AI use, which is useful especially if you gave them access to more spellpoints than in the normal game. The second one could be used to influence the target priority of an AI player. ALIAS can be a structure, a unit, or a pickup.
If you want the AI to use tunneling, spawning a unit with this ability in a cave surrounded by earth walls is an effective method.

Workaround to create Random-Number-Generators (RNG)
There are no documanted scripts for creating RNG's in Age of Wonders III. As a workaround, you can create an inaccessible area somewhere in your map and place a neutral unit there. The way this unit will move to is randomized at the start of each game. You can use this and create as many markers as you need around this unit. Each of these markers should deactivate each other marker when it is triggered. For the FoE Mod, I used this method to randomize the starting position of the Bariclar Player (if controled by the AI) and the Strenght of Lotharsburg's Defenders (if Arshack is crontroled by the AI).

Changing Terrain
  • position = HexWorld:GetScriptingS():GetPosition("MARKERALIAS")
    HexWorld:GetScriptingS():StrategicWorldChangeOverlay(position, 0, "#0000010600000055")
  • local markerPostion = HexWorld:GetScriptingS():GetPosition("MARKERALIAS")
    HexWorld:GetScriptingS():StrategicWorldChangeTheme(markerPostion, 0, "#00000001058000DD")

The game differentiates terrain between WorldThemes and WorldOverlays. Themes are "temperate", "arctic", "tropical" and so on. Overlays are "fertile plains", "barrens", wetlands" etc. The IDs are listed in the last section of this guide.
Changing Terrain can be a bit complicated, because not all terrain types can directly be changed into another. For example, in the Reforged version of FoE, I wanted cavern walls to transform into lava during a volcano outbreak. However, using the scripts posted above, nothing will happen. Instead, the cavern walls have to be changed into another overlay (e.g. dense vegetation) first, which can be transformed into another theme (volcanic), which then can be transformed to the new overlay (lava).

position = HexWorld:GetScriptingS():GetPosition("OUTBREAK_LOCB1_1") HexWorld:GetScriptingS():StrategicWorldChangeOverlay(position, 0, "#000000010580006A") local markerPostion = HexWorld:GetScriptingS():GetPosition("OUTBREAK_LOCB1_1") HexWorld:GetScriptingS():StrategicWorldChangeTheme(markerPostion, 0, "#0000012F0000157C") position = HexWorld:GetScriptingS():GetPosition("OUTBREAK_LOCB1_1") HexWorld:GetScriptingS():StrategicWorldChangeOverlay(position, 0, "#0000010600000055")

Stacks and Units
The available scripts cause some difficulties when dealing with stacks and individual units of a stack. It is possible to assign a stack to a new player, but it is not possible to assign a single unit to a player. Conversely, a single unit can be teleported, but not an entire stack.
The orientation of a stack can also be changed, but not the orientation of an individual unit.
The aliases of stacks can also change quickly (e.g. when the AI redivides the stack).

Stack Scripts:
  • HexWorld:GetScriptingS():StackJoinPlayer("STACKALIAS", "PLAYERALIAS")
  • HexWorld:GetScriptingS():StackSetDirection("STACKALIAS", "SW")

Unit Scripts:
  • HexWorld:GetScriptingS():UnitKill("UNITALIAS", true, false, true)
  • HexWorld:GetScriptingS():UnitTeleport("UNITALIAS", HexWorld:GetScriptingS():GetPosition("MARKERALIAS"), "SW")

Script Example: Killing a the first unit of a stack entering a specific hexfield
function Class:Event_OnStackEnters(argTarget) stackalias = HexWorld:GetScriptingS():GetAlias(argTarget) sacrificeunit = HexWorld:GetScriptingS():StackGetUnit(stackalias, 0) sacrificeunitalias = HexWorld:GetScriptingS():GetAlias(sacrificeunit) HexWorld:GetScriptingS():SetAlias(sacrificeunitalias, "SACRIFICE") HexWorld:GetScriptingS():UnitKill("SACRIFICE", false, true, true) end

Script Example: a dragon Units join a player and are teleported
HexWorld:GetScriptingS():StackJoinPlayer("DRAGON_GROUP_1", "DRAKONIER") HexWorld:GetScriptingS():UnitTeleport("DRAGON_PRESENT_1", HexWorld:GetScriptingS():GetPosition("CINDER_MOUNTAIN_PEAK"), SW)

The main point about the last script is that the unit with the alias "DRAGON_PRESENT_1" will keep this alias and can be targeted in other scripts. In contrast, the stack Alias "DRAGON_GROUP_1" is instable and cannot be used in later scripts (e.g. timers).
The StackJoinPlayer function must be used before the UnitTeleport function, because the stackalias could change in the meantime.
This also means that the DRAGON_GROUP_1 Stack must not be allowed to move in any direction if it contains more than 1 unit before the script is executed.
In the "Fate of Emrilia" , I solved this problem by placing units in the Circus of Souls at the void level.

Staging scenes
Scripts that influence the camera are particularly relevant for staging.

Script example:
HexWorld:GetScriptingS():CenterCameraOnEntity("ORC", "ALIAS", true, 1, -1)

The last integers describe how many fields are releved and how long the camera will focus on the alias.
The story message settings also allows to focus the camera on an entity.

The "stacksetdirection" script (see above) can also be useful for setting up scenes (Imagine the arch enemy apperas from the north and your suprised heroes turn towards him). Note that individual units cannot be given a direction, this means if you cannot be sure about the stackalias you will have to teleport an individual unit and set it to a specific direction (the unitteleport-script can target the same hexfield where the unit is placed before).

Another useful method is to use spell effects. For example, when Sol Galgaloth awakens in the reforged version of FoE, the spell "Animate Ruins" will be cast on her location. This spell has no effect (there is no ruin), but the animations will still look nice ;)

Script example:
local markerPosition = HexWorld:GetScriptingS():GetPosition("MG_GALGALOTHS_LAIR") HexWorld:GetScriptingS():PlayerCastSpell("INDEPENDENTS", markerPosition, "#0000032F000002EF")

Determining the leading faction
Sometimes, for balancing reasons, it can be useful to find out which leader is in the first place to win the game. In most cases, this will be the leader who controls the most cities. The following scripts checks if PLAYER1 is in this position.

Example:
if and HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER1") > HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER2") and HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER1") > HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER3") and HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER1") > HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER4") and HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER1") > HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER4") and HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER1") > HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER5") and HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER1") > HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER6") and HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER1") > HexWorld:GetScriptingS():PlayerGetNumCities("PLAYER7") then ... end

Building a command centre
For the reforged version, i wanted to use a lot of conditional scripts. For example, the Gold Wyvern Cult will regulary spawn a stack of Units fighting Zarzissh while she is alive, but spawn a stack of units hating everyone as soon as she has been defeated.
In order to be able to monitor the various states of the map ingame at a glance, one (crude) possibility is to use teleporters in an inaccessible part of the map, which can indicate certain states through their activity.

Script Example:
if HexWorld:GetScriptingS():StructureGetState("CHECK_ZARZISSH_IS_DEAD") == 9 then HexWorld:GetScriptingS():SpawnGroupSpawnAtPosition("GOLD_WYVERN_ATTACK_ALL_SPAWN", HexWorld:GetScriptingS():GetPosition("GOLD_WYVERN_ATTACK_SPAWNLOC"), "SW") end if HexWorld:GetScriptingS():StructureGetState("CHECK_ZARZISSH_IS_DEAD") == 10 then HexWorld:GetScriptingS():SpawnGroupSpawnAtPosition("GOLD_WYVERN_ATTACK_P5_SPAWN", HexWorld:GetScriptingS():GetPosition("GOLD_WYVERN_ATTACK_SPAWNLOC"), "SW") end

For complex scenarios, I strongly recommend from my own experience to resist the temptation and place stack area triggers in the map. If any errors occur later, it is difficult to find the corresponding scripts and triggers. Instead, I recommend placing all stack area triggers in one place (e.g. sorted by player) and then managing them centrally from there.

Using timer loops
If you want things to happen again and again and again, you can create timer loops. Timer loops can be created across different timers or with a single timer.

Script example for a Timer named "MAGGOT_SPAWNER"
HexWorld:GetScriptingS():SpawnGroupSpawnAtPosition("MAGGOTSPAWN", HexWorld:GetScriptingS():GetPosition("MUDPIT_1_LOC"), "SW") HexWorld:GetScriptingS():TimerReset("MAGGOT_SPAWNER_1") HexWorld:GetScriptingS():TimerStart("MAGGOT_SPAWNER_1")

This will restart the timer once if fired. In the reforged version, this script grants Gryx an unending stream of new servants.

The Postman trick
Maybe it would be nice for an item to show up at a certain point of the game at a certain place in the map. If this is something you want to create for your mod, you'll encounter the problem that there is no script to place items during a session (at least as far as I know).
However, heroes can carry items and heroes can be teleported. One workaround is to create a hero (nickname: "postman"), creating an item in his inventory and then use the teleport script.

HexWorld:GetScriptingS():UnitTeleport("THE_POSTMAN", HexWorld:GetScriptingS():GetPosition("DESTINY"), "SW") HexWorld:GetScriptingS():UnitKill("THE_POSTMAN", false, false, true)

Create an Item Fetch Quest
Note that I've not tried this for myself at the moment (I will look into this as soon as I reintegrate the Raven Quest into the reforged version). If you want to create a item based fetch quest, the following scripts might be useful:

Item UnitGetInventoryItem(unitAlias : string, inventorySlot : int)
<function>: Get an item from the unit’s inventory
<return value>: The item in the inventory slot. Returns NULL if there is no item.
<param unitAlias>: The alias of the unit whose inventory to get the item from.
<param inventorySlot>: The index of the inventory slot to get the item from.

Index reference:
0 = Weapon
1 = Shield
2 = Accessoire
3 = Accessoire
4 = Head
5 = Torso
6 = Legs
7 = Mount
8-17 = Use items, Bag
   
Example: Print the the id of the item in the unit's head slot (script from the developer's guide, I think there is a mistake in the index reference which should be "4")
local item = HexWorld:GetScriptingS():UnitGetInventoryItem("UNITALIAS", 3) HexWorld:GetScriptingS():ItemHasTag(item, "OVERPOWERED"))

Resource IDs
Fertile Plains: #0000000105800069
Barrens: #00000001058000DF
Wetlands: #00000001058000E0
Dense Vegetation: #000000010580006A
Mountains: #0000000105800092
Coastal Mountains: #00000001058000B1
Cavern Walls Impassable: #0000011000000153
Cavern Walls Passable: #0000011000000154
Water: #0000013D000006AA
Frozen Water: #0000013D000006BB
Blocked Water: #0000013D000006DB
Mountains Impassable: #0000012B0000058D
Lava: #0000010600000055
Temperate: #0000000105800062
Arctic: #0000000105800063
Tropical: #00000001058000DC
Blighted: #00000001058000DD
Subterranean: #00000001058000DE
Water: #0000010400000195
Water Subterranean: #0000010400000696
Volcanic: #0000012F0000157C

Alignment modifiers:
AbsorbCity+100: #0000014E00000103
OpenedBorders+50: #0000014E00000104
MadePeaceFromNeutral+100: #0000014E00000105
MadePeaceFromWar+200: #0000014E00000106
ForgedAlliance+100: #0000014E00000107
ForgedAllianceWithFormerEnemy+100: #0000014E00000108
EliminatedEvilPlayer+400: #0000014E00000109
LetGuardsGo+50: #0000014E00000129
RebuildCity+150: #0000014E0000012D
KillDedicatedToEvilUnit+(5*tier): #0000014E0000012E
CampaignSpecificEvilAlignment(-800): #0000030D0000000E
CampaignSpecificGoodAlignment(+800): #0000030D0000000F
CivilUnrest-50: #0000014E00000125
MigrateCity-100: #0000014E0000010B
RazedStructure-100: #0000014E00000118
RazedOccupiedCity-150: #0000014E00000121
RazedOwnCity-200: #0000014E00000122
CancelledOpenBorders-100: #0000014E0000011D
DeclaredWarFromNeutral-100: #0000014E0000011E
DeclaredWarFromPeace-200: #0000014E0000011F
BrokeAlliance-100: #0000014E00000120
StartedwarAgainstFormerAlly-100: #0000014E00000123
EliminatedGoodPlayer-400: #0000014E00000124
SlayedGuards-50: #0000014E0000012A
KillDedicatedToEvilUnit-(5*tier): #0000014E0000012F
WarProvocation-100: #0000014E00000130

Happiness modifiers:
Happiness-25: #0000012000000095
Happiness-50: #0000012000000087
Happiness-75: #0000012000000096
Happiness-100: #0000012000000097
Happiness-150: #0000012000000088
Happiness-200: #0000012000000098
RecruitedHero+25 / 5 turns: #0000014E0000001C
FoundCity+50 / 10 turns: #0000014E0000001E
IsThroneCity+50: #0000014E00000026
WonABattle+100 / 5 turns: #0000014E00000019
RichEmpire+100: #0000014E0000001B
VanquishedEnemyLeader+100 / 10 turns: #0000014E0000001F
AddedCityToEmpire+150 / 10 turns: #0000014E0000001A
HeroDied-25 / 5 turns: #0000014E0000003B
LostABattle-100 / 10 turns: #0000014E00000020
LostCity-100 / 10 turns: #0000014E00000021
RazedOwnCity-100 / 10 turns: #0000014E00000037
LeaderDead-100 / 10 turns: #0000014E00000038
LostACityToRebellion-100 / 10 turns: #0000014E00000039
TreasureEmpties-100: #0000014E0000003A
HurryProduction-100 / 5 turns: #0000014E0000003E
MigratedCity-100 / 5 turns: #0000014E00000131
Happiness+20: #0000012000000076
Happiness+30: #0000012000000078
Happiness+40: #000001200000007F
Happiness+50: #0000012000000079
Happiness+60: #0000012000000080
Happiness+70: #0000012000000081
Happiness+75: #0000012000000082
Happiness+80: #00000120000000E3
Happiness+100: #0000012000000083
Happiness+120: #0000012000000084
Happiness+125: #000001200000008E
Happiness+140: #0000012000000085
Happiness+150: #000001200000008F
Happiness+160: #0000012000000086
Happiness+175: #000001200000008D
Happiness+200: #0000012000000089
Happiness+225: #000001200000008A
Happiness+250: #000001200000008B
Happiness+275: #000001200000008C
Happiness+300: #0000012000000091
Happiness+375: #0000012000000092
Happiness+400: #00000120000000A4
Happiness+450: #0000012000000093
Happiness+525: #0000012000000094
LeaderDead-400 Unique: #0000014E00000011
CityPreferredClime+100 Unique: #0000014E000000A5
CityHasHero+100 Unique: #000001200000009E
CityHasLeader+50 Unique: #00000120000000A1
CityPlundering-800 Unique: #0000014E00000017
CityRecoveredRebellion+400: #000001730000000C

Spell ID
Glyphs of warding: #0000012C000000EB
Enchanted walls: #0000013D000004AE
Hallowed domain: #0000011A0000001D
Thorhedge walls: #0000013D00000473
Poison domain: #0000011A0000112D
Poison domain spell: #0000011A00001131
Night Wish: #0000011A0000083F
Corrupt the Source: #0000033A000007F3
Animate Ruins: #0000032F000002EF
Dark Ritual: #0000032F000003EF
Insect Plague: #0000012C000001A5
City Quake: #0000014D00000396
Dread Omen: #0000014D00000261
Wrath of God: #0000011B000005CB
Glyphs of warding: #0000014D00000252
Enchanted walls: #0000013D000004B0
Age of Magic: #0000014D00000112
Hallowed domain: #0000014D0000015A
Armageddon: #0000014D0000016C
The Great Purge: #0000014D0000015C
Global Assault: #0000014D000000DF
Thorhedge walls: #0000013D00000475
Poison domain: #0000011A00001131
The Wild Hunt: #0000011A00001148
The Great Mobilization: #0000014D000001E2
Dragon Oil: #0000013D0000048A
Age of Death: #0000032F0000035F
Damnation: #0000032F00000358
Power Ritual: #0000032F00000343
Age of Deception: #0000014D00000206
Anti Magic Field Skill: #0000014D00000294
Anti Magic Field Spell: #0000014D00000296
Rotten Wall Skill: #0000032F0000032D
Rotten Wall Spell: #0000032F0000032F
Forge Blast spell: #0000012C00000248
Incite Revolt skill: #0000011A0000060C
Incite Revolt spell: #0000011A00000606
Warp Domain skill: #0000032B00000021
Warp Domain spell: #0000032B00000024
Produce Juggernaut Skill ID: #0000011A0000069D
Summon Horned God Skill ID: #0000012C00000055
Summon Horned God Spell ID: #0000012C00000057
Produce Shadow Stalker Skill ID: #0000011A00000588
Scorched Earth Skill ID: #0000013D00000400
Scorched Earth Spell ID: #0000013D00000410
Martial Arts: #0000014D0000020F
Last edited by WoodChip; Mar 7 @ 3:33pm
< >
Showing 1-15 of 15 comments
Semper Feb 7, 2023 @ 12:34pm 
Thanks for listing a way to look up some ResourceIDs through the modding tools. Still don't know were those IDs are listed in the Wiki. You're talking about this one "https://age-of-wonders-3.fandom.com/wiki/Age_Of_Wonders_3_Wiki", right? Didn't find any IDs there.
Where did you find the alignment IDs? Are they also stored in a .rpk file?
WoodChip  [developer] Feb 8, 2023 @ 2:16pm 
@Semper: I've added a list of all Resource IDs I know. Hope this helps :)
Semper Feb 9, 2023 @ 11:32am 
That's great! Really helpful. Thank you.
Erke Aug 2, 2023 @ 1:42pm 
How would I go about applying some resource ID's to a city?

Let's say I like to do Happiness-200: #0000012000000098 for a city if a certain quest failed.

Or let's say I like to change the terrain of a hex from
Mountains Impassable: #0000012B0000058D
to
Barrens: #00000001058000DF

Would really appreciate any response.
WoodChip  [developer] Aug 3, 2023 @ 4:47am 
@Erke:
For changing the terrain, you can use:
position = HexWorld:GetScriptingS():GetPosition("MARKERALIAS")
HexWorld:GetScriptingS():StrategicWorldChangeOverlay(position, 0, "#00000001058000DF")

the index "0" means 0 hex fields from the target. If you set this to 1, a radius of 1 hexes will be changed (and so on). I don't know if Mountains to barrens work, some combinations won't work (e.g. water to barrens doesn't as far as I remember).
Instead of "MARKERALIAS", use the name of a marker or structure (mabye even units or stacks?).

For applying the Happiness Malus to players, you can use:
HexWorld:GetScriptingS():PlayerApplyHappinessModifier("PLAYER1", "#0000012000000098", "[Explanation Text]")
I don't know if there is a way to add this to certain cities.

Hope this helps :)
Last edited by WoodChip; Aug 3, 2023 @ 5:29am
Erke Aug 3, 2023 @ 5:41am 
Originally posted by WoodChip:
@Erke:
For changing the terrain, you can use:
position = HexWorld:GetScriptingS():GetPosition("MARKERALIAS")
HexWorld:GetScriptingS():StrategicWorldChangeOverlay(position, 0, "#00000001058000DF")

the index "0" means 0 hex fields from the target. If you set this to 1, a radius of 1 hexes will be changed (and so on). I don't know if Mountains to barrens work, some combinations won't work (e.g. water to barrens doesn't as far as I remember).
Instead of "MARKERALIAS", use the name of a marker or structure (mabye even units or stacks?).

For applying the Happiness Malus to players, you can use:
HexWorld:GetScriptingS():PlayerApplyHappinessModifier("PLAYER1", "#0000012000000098", "[Explanation Text]")
I don't know if there is a way to add this to certain cities.

Hope this helps :)
Thank you so much for your response and detailed answer. I know this is an old game, but it is great to still receive support about it, especially regarding custom user content... So that it may continue to extend player base and replayability.

Somebody else wrote elsewhere to perhaps use PlayerCastSpell would that work on happiness modifiers as well or is it just for Spell IDs

I can't try out right now, instead of asking because the editor won't open "any" my project files. Even though they were saved properly and tested in game to be working.... Hopefully I'll be able to fix it.
Last edited by Erke; Aug 3, 2023 @ 5:42am
WoodChip  [developer] Aug 13, 2023 @ 9:15am 
@Erke: Sorry for the late response. I tried out the playercastspell script for happiness modifiers on cities, but it did not seem to work. Good luck with restoring your save files!
Erke Aug 13, 2023 @ 2:46pm 
Originally posted by WoodChip:
@Erke: Sorry for the late response. I tried out the playercastspell script for happiness modifiers on cities, but it did not seem to work. Good luck with restoring your save files!
Thank you so much for your time.
WoodChip  [developer] Feb 6, 2024 @ 3:36pm 
@Erke: I don't know if it is still of any relevance, but I've found out how to transform terrain even if scripts don't seem to work at the first sight due to incompatible overlays. I've added an example above.
JointBlack Feb 10, 2024 @ 3:38am 
Good afternoon. A question. I want to try to create a map with my own quests. I know that once upon a time there was a guide from developers on Scripts. I try everything from scratch, I understand the principle. But I would like to know how to do typical quests by type. Bring an artifact, Kill a squad, Capture the capital, and so on. I opened maps from the developers in the editor. I looked at their examples, but without a manual it’s difficult to understand what and how. Don't know where to find a guide from the developers?

Originally posted by WoodChip:
@Erke: I don't know if it is still of any relevance, but I've found out how to transform terrain even if scripts don't seem to work at the first sight due to incompatible overlays. I've added an example above.
WoodChip  [developer] Feb 10, 2024 @ 3:59am 
I might be wrong, but I think the guide got lost during the fusion of Triumph with paradox and moving the forum. I have never worked with the inbuild quest system myself, but I downloaded the guide once, so here is what was written by the developers:
I hope this helps, if not, feel free to ask more.


3.7 Quest
A Quest is a task you can give to the player, completing a quest gives the player a reward.

3.7.1 PlayerOfferQuest
void PlayerOfferQuest(playerAlias : string, questAlias : string, popupQuest: bool)
Offers a quest to the player which he can accept or decline.
<param playerAlias>:
    The alias of the player to offer the quest.
<param questAlias>:
    The alias of the quest to offer.
<param popupQuest>:
    Determines if it is a popup quest (= true) or a to-do quest (=false).

Example:
HexWorld:GetScriptingS():PlayerOfferQuest("PLAYER1", "QUEST1", false)

3.7.2 PlayerOfferCityQuest
void PlayerOfferCityQuest(playerAlias : string, cityAlias : string, questAlias : string)
Offers a quest from a city to the player which he can accept or decline. Completing this quest will absorb the city into the player's domain.
<param playerAlias>:
    The alias of the player to offer the quest to.
<param cityAlias>:
    The alias of the city offering the city quest.
<param questAlias>:
    The alias of the quest to offer.

Example:
HexWorld:GetScriptingS():PlayerOfferCityQuest("PLAYER1", "CITY1", "QUEST1")

3.7.3 PlayerForceQuest
void PlayerForceQuest(playerAlias : string, questAlias : string)
Force a quest to the player which is automatically accepted (cannot be declined).
<param playerAlias>:
    The alias of the player to force the quest.
<param questAlias>:
    The alias of the quest to force.

Example:
HexWorld:GetScriptingS():PlayerForceQuest("PLAYER1", "QUEST1")

3.7.4 PlayerOfferSubQuest
void PlayerOfferSubQuest(playerAlias : string, questHeaderAlias : string, questAlias : string, popupQuest: bool)
Offers a subquest to the player which he can accept or decline, this quest will get added to the specified quest header.
<param playerAlias>:
    The alias of the player to offer the quest.
<param questHeaderAlias >:
    The alias of the questheader to which the subquest will be attached (required to add subquest)
<param questAlias>:
    The alias of the quest to offer.
<param popupQuest>:
    Determines if it is a popup quest (= true) or a to-do quest (=false).

Example:
HexWorld:GetScriptingS():PlayerOfferSubQuest("PLAYER1", "QUEST_HEADER_1", "QUEST1", false)

3.7.5 PlayerForceSubQuest
void PlayerForceSubQuest(playerAlias : string, questHeaderAlias : string, questAlias : string)
Force a subquest to the player which is automatically accepted (cannot be declined), this quest will be added to the specified quest header.
<param playerAlias>:
    The alias of the player to force the quest.
<param questHeaderAlias>:
    The alias of the questheader the subquest will be attached to.
<param questAlias>:
    The alias of the quest to force.

Example:
HexWorld:GetScriptingS():PlayerForceSubQuest("PLAYER1", "QUEST_HEADER1", "QUEST1")

3.7.6 PlayerCompleteQuest
void PlayerCompleteQuest(playerAlias : string, questAlias : string)
Completes a quest of the player.
<param playerAlias>:
    The alias of the player to complete the quest.
<param questAlias>:
    The alias of the quest to complete.

Example:
HexWorld:GetScriptingS():PlayerCompleteQuest("PLAYER1", "QUEST1")

3.7.7 PlayerFailQuest
void PlayerFailQuest(playerAlias : string, questAlias : string)
Fails a quest of the player.
<param playerAlias>:
    The alias of the player to fail the quest.
<param questAlias>:
    The alias of the quest to fail.

Example:
HexWorld:GetScriptingS():PlayerFailQuest("PLAYER1", "QUEST1")

3.7.8 PlayerIncreaseQuestCompletionCount
void PlayerIncreaseQuestCompletionCount(playerAlias : string, questAlias : string)
Increases the completion count of a player's quest by 1.
<param playerAlias>:
    The alias of the player to increase the quest completion type of.
<param questAlias>:
    The alias of the quest  to increase the quest completion type of.

Example:
HexWorld:GetScriptingS():PlayerIncreaseQuestCompletionCount("PLAYER1", "QUEST1")

3.7.9 PlayerDecreaseQuestCompletionCount
void PlayerDecreaseQuestCompletionCount(playerAlias : string, questAlias : string)
Decreases the completion count of a player's quest by 1.
<param playerAlias>:
    The alias of the player to decrease the quest completion type of.
<param questAlias>:
    The alias of the quest  to decrease the quest completion type of.

Example:
HexWorld:GetScriptingS():PlayerDecreaseQuestCompletionCount("PLAYER1", "QUEST1")
Last edited by WoodChip; Feb 10, 2024 @ 8:06am
WoodChip  [developer] Feb 10, 2024 @ 8:11am 
I‘ve just found the guide if you want read there instead, it was posted in the paradox forums by some users.

E.g.:
https://forum.paradoxplaza.com/forum/threads/developer-guide.1589879/
JointBlack Feb 12, 2024 @ 4:30pm 
Originally posted by WoodChip:
I might be wrong, but I think the guide got lost during the fusion of Triumph with paradox and moving the forum. I have never worked with the inbuild quest system myself, but I downloaded the guide once, so here is what was written by the developers:
I hope this helps, if not, feel free to ask more.


3.7 Quest
A Quest is a task you can give to the player, completing a quest gives the player a reward.

3.7.1 PlayerOfferQuest
void PlayerOfferQuest(playerAlias : string, questAlias : string, popupQuest: bool)
Offers a quest to the player which he can accept or decline.
<param playerAlias>:
    The alias of the player to offer the quest.
<param questAlias>:
    The alias of the quest to offer.
<param popupQuest>:
    Determines if it is a popup quest (= true) or a to-do quest (=false).

Example:
HexWorld:GetScriptingS():PlayerOfferQuest("PLAYER1", "QUEST1", false)

3.7.2 PlayerOfferCityQuest
void PlayerOfferCityQuest(playerAlias : string, cityAlias : string, questAlias : string)
Offers a quest from a city to the player which he can accept or decline. Completing this quest will absorb the city into the player's domain.
<param playerAlias>:
    The alias of the player to offer the quest to.
<param cityAlias>:
    The alias of the city offering the city quest.
<param questAlias>:
    The alias of the quest to offer.

Example:
HexWorld:GetScriptingS():PlayerOfferCityQuest("PLAYER1", "CITY1", "QUEST1")

3.7.3 PlayerForceQuest
void PlayerForceQuest(playerAlias : string, questAlias : string)
Force a quest to the player which is automatically accepted (cannot be declined).
<param playerAlias>:
    The alias of the player to force the quest.
<param questAlias>:
    The alias of the quest to force.

Example:
HexWorld:GetScriptingS():PlayerForceQuest("PLAYER1", "QUEST1")

3.7.4 PlayerOfferSubQuest
void PlayerOfferSubQuest(playerAlias : string, questHeaderAlias : string, questAlias : string, popupQuest: bool)
Offers a subquest to the player which he can accept or decline, this quest will get added to the specified quest header.
<param playerAlias>:
    The alias of the player to offer the quest.
<param questHeaderAlias >:
    The alias of the questheader to which the subquest will be attached (required to add subquest)
<param questAlias>:
    The alias of the quest to offer.
<param popupQuest>:
    Determines if it is a popup quest (= true) or a to-do quest (=false).

Example:
HexWorld:GetScriptingS():PlayerOfferSubQuest("PLAYER1", "QUEST_HEADER_1", "QUEST1", false)

3.7.5 PlayerForceSubQuest
void PlayerForceSubQuest(playerAlias : string, questHeaderAlias : string, questAlias : string)
Force a subquest to the player which is automatically accepted (cannot be declined), this quest will be added to the specified quest header.
<param playerAlias>:
    The alias of the player to force the quest.
<param questHeaderAlias>:
    The alias of the questheader the subquest will be attached to.
<param questAlias>:
    The alias of the quest to force.

Example:
HexWorld:GetScriptingS():PlayerForceSubQuest("PLAYER1", "QUEST_HEADER1", "QUEST1")

3.7.6 PlayerCompleteQuest
void PlayerCompleteQuest(playerAlias : string, questAlias : string)
Completes a quest of the player.
<param playerAlias>:
    The alias of the player to complete the quest.
<param questAlias>:
    The alias of the quest to complete.

Example:
HexWorld:GetScriptingS():PlayerCompleteQuest("PLAYER1", "QUEST1")

3.7.7 PlayerFailQuest
void PlayerFailQuest(playerAlias : string, questAlias : string)
Fails a quest of the player.
<param playerAlias>:
    The alias of the player to fail the quest.
<param questAlias>:
    The alias of the quest to fail.

Example:
HexWorld:GetScriptingS():PlayerFailQuest("PLAYER1", "QUEST1")

3.7.8 PlayerIncreaseQuestCompletionCount
void PlayerIncreaseQuestCompletionCount(playerAlias : string, questAlias : string)
Increases the completion count of a player's quest by 1.
<param playerAlias>:
    The alias of the player to increase the quest completion type of.
<param questAlias>:
    The alias of the quest  to increase the quest completion type of.

Example:
HexWorld:GetScriptingS():PlayerIncreaseQuestCompletionCount("PLAYER1", "QUEST1")

3.7.9 PlayerDecreaseQuestCompletionCount
void PlayerDecreaseQuestCompletionCount(playerAlias : string, questAlias : string)
Decreases the completion count of a player's quest by 1.
<param playerAlias>:
    The alias of the player to decrease the quest completion type of.
<param questAlias>:
    The alias of the quest  to decrease the quest completion type of.

Example:
HexWorld:GetScriptingS():PlayerDecreaseQuestCompletionCount("PLAYER1", "QUEST1")

Thank you very much for your help. I have been looking for some information about creating quests for a long time. One of these days I’ll try to create my own test quest. If I have any questions, I will contact you. I am glad that people like you share their knowledge with simple, beginners.
JointBlack Feb 12, 2024 @ 10:58pm 
Originally posted by WoodChip:
I‘ve just found the guide if you want read there instead, it was posted in the paradox forums by some users.

E.g.:
https://forum.paradoxplaza.com/forum/threads/developer-guide.1589879/
I have this manual, but it doesn’t mention anything about Creating quests.
WoodChip  [developer] Feb 26, 2024 @ 1:07am 
@JointBlack: I've just updated the guide. If you want to create a "bring this artifact" quest, the additional scripts mentioned could be useful. It seems item tags can be defined in the ResourceManager of the Map editor (not sure if it is also possible for vanilla items via the package manager).
Last edited by WoodChip; Feb 26, 2024 @ 1:07am
< >
Showing 1-15 of 15 comments
Per page: 1530 50