add World Conquest II to mainline

For mainline we will just call it "World Conquest"

World Conquest II is a coop multiplayer campaign
of 5 scenarios for 1,2 or 3 players.
It features highly randomized maps for
replayability. Also custom item and training
systems. The majority of the campaign is
implemented in lua for better preformance.

It also contains a custom era to be used together
woth the campaign, since the default era is
quite unbalanced for this coop gamemode against
the ai. It for example makes sure that every
faction has a leader.

This is one of the most popular MP addons on
wesnoth 1.14, 1.12 and older.
This commit is contained in:
gfgtdf 2020-06-04 00:21:14 +02:00
parent 4a7d008be5
commit cef77a51df
171 changed files with 23370 additions and 0 deletions

View file

@ -0,0 +1,58 @@
This file describes how to make your addon work well together with
world conquest 2. In particular how to write an era that can be used together with world conquest ii.
Making an era that works well together with world conquest ii, is quite
easy: just add the [world_conquest_data] tag to your [multiplayer_side] tag just as
the standard word conquest2 era does, important: your era may not have
require_download=no for this to work. Furthermore if your era contains
new unit types that are not mainline wesnoth, don't forget to put an additional
[world_conquest_data] in [era] to describe which trails these unit types should get
when they are selected as heroes (use this to compensate weaker unit types).
To make an era/modification that also changes the enemy army unit types,
make sure to define the wc2_init_enemy event and use it to set the enemy_army
variable that should contains the pool of 'armies' that the enemies are chosen from:
```
[event]
name = "wc2_init_enemy"
[filter_conditional]
[variable]
name="wc2_enemy_army.length"
equals=0
[/variable]
[/filter_conditional]
[set_variables]
name = "wc2_enemy_army"
[literal]
[group]
id = "enemyfaction_id"
recruit= "Orcish Grunt,Orcish Archer,Wolf Rider,Orcish Assassin,Troll Whelp"
[recall]
level2 = "Orcish Ruler, Orcish Slayer,..."
level2 = "Orcish Warlord, Troll Warrior,..."
[/recall]
[commander]
level1 = "Orcish Leader, Orcish Grunt,..."
level2 = "Orcish Ruler, Orcish Slayer,..."
level2 = "Orcish Warlord, Troll Warrior,..."
[/commander]
[leader]
level2 = "Troll"
level3 = "Troll Warrior"
recruit = "Orcish Grunt,Orcish Archer,Troll Whelp"
[/leader]
[leader]
level2 = "Orcish Warrior"
level3 = "Orcish Warlord"
recruit = "Orcish Grunt,Orcish Archer,Wolf Rider,Orcish Assassin"
[/leader]
....
[/group]
[/literal]
[/set_variables]
[/event]
```
TODO: how to overwrite training and artifacts.

View file

@ -0,0 +1,48 @@
A description of this addon's code:
This addon makes a lot use of lua wherever possible, even [side] definitions
were moved to lua by using scenario_generation=lua, that is why the [multiplayer]
tags are nearly empty. One of the main advantage of this is that this addon
doesn't increase the wesnoth parsing time, also i just found lua easier to
read and much easier to debug since it gives better error messages, and doesnt
require reloading the cache after changes were made.
The directory is organized as follows:
./lua/map :
the files in ./lua/map contain the code that generate the content of the
[multiplayer] tag, in particular [side] definitions, [event]s, map_data and
[load_resource]. The biggest part of the scenario is the map generation,
World conquest map generation works as follows: First we run the wesnoth
default map generator (here: the files in lua/map/generator), then we run
a custom lua scrips to fix it up (lua/map/postgeneration). For each
scenario there ia a fixed set of generator+postgenerator pairs defined in
lua/map/scenarios for each scenario.
./lua/shared_utils :
libraries and helper functions that are used by both the map editor and
during the actual game.
./lua/optional_mechanics :
A few lua mechanics that works independent on the rest of the world conquest
II code.
./lua/era :
the code for the World Conquest era, this is in particular the recruitment in pair
function. And delivering wc data that depends on the current era (for
example which heroes should be available for which faction)
./lua/game_mechanics :
The lua code that implements the custom game mechanics of World Conquest, that is:
The dropping system, the invest system, the training system, World Conquest
specific abilities, the bonus points system
./lua/campaign :
The code specific to the wc2 campaign: the difficulties, victory conditions,
enemy spawns etc.
./utils/gameplay :
The training and artifact definitions
./utils/era :
The factions of the World Conquest era.

View file

@ -0,0 +1,14 @@
* Balance, readd dunefolk.
* translatable strings are still a mess, some are defined at top of the file while other are defined in the middle.
* the artifacts file should be change in the same way as the training file wrt translatable strings.
* We should consider moving the pickup event implementation to core (and rename it)
* Maybe change the recruit costs for certain types of units. e.g. Fencers are too expensive, Dwarvish fighters are too cheap etc.
* Maybe readd the ruined Fence terrain but in better quality.
* The mapgeneratot used a deprecated mushroom terrain.

View file

@ -0,0 +1,25 @@
## MP Campaign (Scenarios in Multiplayer >> Random Maps)
#textdomain wesnoth-World_Conquest
{./config.cfg}
[textdomain]
name="wesnoth-World_Conquest"
[/textdomain]
#ifdef LOAD_WC2
[binary_path]
path=data/campaigns/World_Conquest
[/binary_path]
{./era}
{./resources}
{./scenarios}
{WORLD_CONQUEST_II_ERA}
{WORLD_CONQUEST_II_ERA_RESOURCE}
{WORLD_CONQUEST_II_CAMPAIGN_RESOURCE}
#endif

View file

@ -0,0 +1,488 @@
# Modification from World Conquest 1.10.10 (created by TL, maintained by Natasiel).
# Code, idea and design: tekelili
Minor code contributors: ezysquire (forcefield), tsr (preset advancement)
# Playtesting: Bear, Honor, jb, paso, tekelili
# Text: TL, Natasiel, Rigor, tekelili
# Images: All custom images based in other authors files, but it is hard find out their names, sorry :(
Several images created by doofus-01
All editing work to adapt custom images and create new from mainline (poorly executed): tekelili
# PBL file
title="World Conquest II"
type="campaign_mp"
icon= "misc/blank-hex.png~BG(140,85,75)~O(1%)~BLIT(units/elves-wood/sorceress.png~RC(magenta>green)~CROP(14,1,58,71))~BLIT(units/undead-necromancers/dark-sorcerer+female.png~RC(magenta>blue)~CROP(0,0,60,67),12,5)"
author="tekelili, TL"
description="Highly randomized and replayable, combat focused campaign for 1-3 players. Players and enemies can improve their armies with magic items, heroes and trainings. Includes an era with 10 factions.
Campaign complete (Beta version).
Scenarios can be found in Multiplayer >> Random Maps. More detailed info at website.
(Expert level, 5 scenarios.)"
[feedback]
topic_id=39651
[/feedback]
passphrase=#####
version=#####
email=#####
# Changelog:
0.8.2:
- misc bugfixes, mostly related to the new lua map generator
- Disable dune piercer and The empire faction, since units were
removed from mainline
0.8:
- A lot of code refactors.
- port the whole postgenerator mapgen code to a scenario_generation=lua .
- huge performance boost in the mapgen code.
- the mapgenerators can now be used in the editor.
- the start-of-scenario savefiles no don't determine anymore which
typegenerator is chosen.
- remove a lot of other code to lua. The only [event] remaining is from
the custom_terrain_mod.
- Pickuppable items no always show on top of decorative items.
- Add a libary wc2_convert which is a schema bases wml <-> lua converter.
- fix wc2_optional_attack effect in case that no attack machted the filter.
- Adapt to mainline dunefolk name changes.
0.7.10.3
- Fix village colors.
- Fix error in mapgen code.
0.7.10
- Improve mapgeneration speed.
- Fix error when using alienera.
0.7.9.1
- Fix enemy training.
0.7.9
- The pickup promt can now be disabled in the wocopedia->settings page.
- Fix unit not advancing after picking up an item that decrease max xp.
- Improved gold carryover code to be compatiable with more mod addons.
- Fixed unit images in messages not scaled in plot sequences.
- Clear shroud after finding a hero in a bonus point.
0.7.8.2
- Improve compatabiltiy with other add-ons and code cleanups.
0.7.8
- Added confirmation promt when picking up items.
- Fix ai side color when player changes colors.
- Fix item drop message.
- Fix bug in preset advancement
0.7.7
- Fixed invest itemlist not increasing.
0.7.6
- Fixed rare lua error when picking up training from bonus point if the
player cannot pick up more training.
0.7.5
- Fixed Gold pick in invest giving no gold.
0.7.4
- Fixed 'Terror disguise' and 'Herald armor' not settings alignment.
0.7.3
- Fixed wrong experience of recruited units and of units with epic trait.
0.7.2
- Fixed show item info.
- Added 'settings' section to wocopedia
0.7.1
- Fixed shuffle starting locations
0.7
- Alienera modification is no longer needed to play with other eras than wc2.
- Most code moved to lua
- New WoCopedia ui
- New Invest ui
- Observer can no no longer see the enemies side
- unit can no longer pickup items that won't give them anything
- fixed wesnoth 1.14 depercation wanrings
- fixed wrong xp for units with epic trait
- Improved advancement pick code so that it no longer needs to intercept recruit etc events.
- reduced savefile size
- use new scaling algorithm for missing portaits
- compatabiltiy issue: when loading saves from older wc2 versions the invest artifact list will be regenerated.
0.6.13
- Fixed crash when loading games caused by 'adamant armour '
- Fixed Winter's bloom not giving cold resistance
0.6.12
- added lua implementation of the default mapgens
- fixed skeleton archer image not showing
- Alien eras can now be enaled without changing core files.
- Simpler implementation custom recall cost
- Simpler implementation of additional advancement
- Fixed upkeep of units with items
- Fixed 'Adamot aromor' effect
0.6.11
- synced=no for menu items
- unitmarker and pya are now optional
- misc refactors
0.6.10
- bugfix
0.6.9
- Adapt to wesnoth 1.14
- Correct recruits show in faction select dialog
0.6.8
- Redefined Trust pairs (intended as little nerf)
- Added Chocobone to enemy recalls
- Removed Young Ogre from pickable from lists without orcs
- Removed as pickables leaders mages not available as random for Militia and Gang
- Tweaked Dark, Melee, Ranger and Experience trainings
- Now enemy undead units get benefict from item Melange (they consumed it while alive)
- Tweaked how scale enemy recalls at scenarios 4,5 with enemy_power (now is more difficult for players at easier levels)
- Scaled enemy commander xp bonus with unit level
- Redefined roads and rivers near castles in Maritime generator
- Fixed calling Alien Eras modification with wrong id
- Fixed not fog update for hero found
- Added explanation of carryover to WoCopedia. Improved bonus points names generation
- Fixed custom feeding description not matching mainline one. Fixed drains special could be displayed twice on a unit.
- "Terrific disguise" becomes "Terror disguise", "Winged Staff" becomes "Winged scepter"
- Fixed version warnings not aimed to host.
0.6.7
- Removed Mages as random leaders for Militia
- Small buffs to enemy at scenario4: 1 commander upgraded to level2 and +1 supply village
- Small buffs to enemy at last scenario: 2 commander upgraded to level3 and +2 supply villages
- Supply village for enemy gives leader trait "expert" (it doesnt give +70 gold, just normal income and upkeep)
- Small nerf to enemy recalls at 1p-2p modes to absorb buffs on comanders aimed for 3p
- Added xp scenario based bonus to hero found
- Scaled early finish gold bonus (before percentage) with number of players
- Removed resistence bonus from item Ring of Power and added disengage weapon special
- Removed secondary effect for flying units from item Winged Staff
- Tweaked all trainings
- Scaled army discipline bonus chance with scenario
- Thug hero gets "resilent" as extra trait instead "fearless" and Young Ogre "epic" instead "expert"
- Scaled enemy items at last map with difficulty
- Simplified/tweaked several junky map generation rutines
- Tweaked faction images
- Fixed bug: heals +8 training not working over heals +4 units
- Fixed some translation notes shown and lacking commander overlay for observers
- Disabled ruiened wood birdge destruction for lacking good image and transition
- Shorted scenario name to ease savefiles management
0.6.6
- Redefined the Guild: Now can spam Dark Adept and Ghoul becomes paired with Elvish Shaman
- Added as leaders: Troll Hero and Lieutenant for The Hand, Troll Hero for The Gang and The Horde
- Tweaked Ranger, Movement and Experience Trainings
- Added Troll Hero and Great Troll to enemy orc recalls. Added Troll Hero to comanders
- Changed The Horde faction image
- Fixed bug: full movement on recruit was giving 1 MP less when assigned on recruit before +22% moves
0.6.5.1
- Added as leaders: Orcish Ruler for The Gang and The Horde, Elvish Lord for The Guild
- Rescaled bonus gold and enemies trained with difficulty level
- Fixed bug: possible OOS in carryover using non-integer values inside [gold]
- Fixed bug: possible castle expanding recruit in map3 Savannah
- Fixed bug: 2 filters chosing some wrong bonus-point-images on a few maps
- Fixed bug: yard generated at 0,0 sometimes at map2 Paradise
0.6.5
(Not compatible with previous versions)
- Developed new alternative map4 (Wild)
- Swaped Arif and khaiyal as desesters for Guild and Hand. Swaped Hakim and Jundi as desesters for Gang and Militia. Added Dwarvish Scout to Knalgans pickables heroes
- Tewaked trainings beneficts. Changes training order to extend +10% health profit to all redudancy consolation +1HP bonus
- Enemy pets get trait "expert". Some tweaks/fixes to enemy recall lists
- Legendary Goblin Pillager gets leadership (to be consistent with Rouser path)
- Harcoded suffle players starting position, to fix [generator] pattern
- Fixed bug: impassible terrain could become invest item impossible to pick
- Fixed bug: enemy castle expansion on map1 called after map repaint could expand recruit. Several minor changes to some generations
- Fixed glitch: optional charge duplicating attacks after unit AMLA
- Fixed typo: gold amount not displayed in expensive recall warning message
- Changed item "Winter Bloom" resistance bonus to "up to 20" (it was "+50"), removed movement and defense bonus.
- The Key now gives teleport animation
- Improved decorative destruction (fences, rotten bridges)
- Several code fixes to alievate save files size (still a lot to do in BfW 1.14)
- Used image for invest training from mainline and removed custom one, as is the same from BfW 1.12.4
- Disabled [allow_undo] in 2p/3p modes due to OOS in bfW 1.12
- fixed [insert_tag] creating empty [if] to avoid bug in BfW 1.13
0.6.4.4
- Fixed bug in generating starting positions for alien eras in 2p-1p modes due to key terrain_liked=
0.6.4.3
- Developed new alternative final map (Feudal)
- Increased forest amount on map3 Delta wich becomed too low after generation redesign
0.6.4.2
- "legendary" is renamed as "epic". Walking Corpse and Goblin Spearman heroes get new "legendary" trait (enables special advances to Chocobone and Goblin Pillager)
- Enemy leaders get trait "heroic"
- Fixed glitch: unit taking only 1 item when 2 items placed on same map spot
- Fixed typo in BfW version warning
- WC II version becomes a variable to be consistent with code stored in savegame
0.6.4.1
- Fixed bug:Northerens bonus heroes was added twice and loyalist none to point list (responsable of 2 goblins heroes on bonus list)
- Redefined data structure relationship between campaign and era (ease adapt other eras)
- Removed unneccesary hack for recall store due to behavior changed in BfW 1.12
- Rewritten/redefined junky generator-postgeneration for map3 Delta
- Tweaked map3 Wetland postgeneration with extra obstacles in zones lacking them
- Eliminated all players amount reference in postgenerations and made them consistent with any map size. Eliminated chance of generation expanding recruit for all maps.
- Fixed bug: enemy with feeding item not getting scenario-based hp buff (made it also scale with enemy power)
- Improved chances of melee recalls for enemy Elf
- Added version warning urging to upgrade to 1.12.2 or later
0.6.4
- Redefined The Scourge: Ghost paired with Skirmisher and Guilder-Bat (trades better scouting for less use of specialists)
- Redefined The Guild: Can spam Elf Fighter and Ghoul. Reduced random leaders to shamans, mages, dark adepts, and necrophages
- Removed White Mage as random leader for The Gang (intended as neutral/flavor change; too many chances of white mages and few of orc leaders among other factions)
- Army discipline bonus nerfed to 3%
- small tweak to Ranger Tactics training
- Fixed bug: recruit list not consistent for different eras after scenario transition
- Small tweaks to generators Wicked adn Provinces
- Fixed custom forest terrain code (small "bugs" with no gameplay effect)
- Improved themed enemy: added outlaw to maps Wetland and Wicked
- Added saurians and outlaws to enemy commander types
- Each enemy faction will not get commanders of repeated faction along campaign
- Added 2 new alternative supply village images, added 3 bonus point images
- Improved pickup bonus point image syncro. Revised and added bonus names.
- Fixed Classic WC junky code of store empty points as (1,1). Rewroten some code for ease reading
- Added debug config option to end scenario
0.6.3.3
- Developed new alternative map4 (Wicked)
- Enemy xp bonus (to commanders and units with item) now scales with enemy_power
- Fixed wrong number of iterations (swaped numbers) in scenario4 for 1p and 2p modes.
0.6.3.2
- Fixed bug introduced in 0.6.3.1 giving error to players joining a new game (wrong key use inside [scenario] was cause)
- Added old tropical forests to custom terrain (to enhance some maps decoration)
- Changed bonus labels font to Lucida Sans Unicode for ease reading (I couldnt read well "l","i","n","r" with default font. I accept better ideas...)
- Some postgeneration code optimized (roads iteration)
0.6.3.1
- Developed new alternative map3 (Wetland)
0.6.3
- Developed new alternative map3 (Coral)
- Small adjust to experiency penalty scaling with difficulty
- Forbidden enemy castle expansion on water and villages
- Simplified plot at fork 3 and now correctly shows all enemy leaders in scenario 4 (plot text is provisional anyway)
- Redefined some postgeneration rutines as events
- Reduced resources consumed loading scenario events from variables
- [modification] loads now events in every scenario, removed reload them
0.6.2.2
- Fixed bug in Training buff "full movement on turn recruited or recalled".
0.6.2.1
- The Horde can now spam Skirmisher and Naga
0.6.2
- Buffed The Gang (now can spam Grunt, Assasin, Elvish Archer and Wose)
- Small Buff to The Hand (now can spam Young Ogre and Heavy Infantryman)
- Small Buff to Dark Training
- Developed new alternative map2 (Clayey)
- Chose Difficulty menu is fired now at start (instead at first recruit). This set experency penalty correctly for all units.
- Changed Young Ogre for Khalifate hero as Deserter for 6 factions
0.6.1.7
- Enemy nerfed at last map (-2 level3 recalls)
- Decoration fix to map6 Industrial (roads)
- Fixed training names in WoCopedia showed all as Melee
0.6.1.6
- Developed new alternative final map (Industrial)
- Fixed support for change side color not working well for less than 3 players
- Map4 Podzol tweaked with some extra rough terrain
0.6.1.5
- Fixed bug making players leaders not affected by experience penalty (introduced in 0.6.1)
0.6.1.4
- Nerfed enemy at last map (-2 commanders)
0.6.1.3
- Nerfed enemy at last map (-1 training and -2 level3 recalls)
0.6.1.2
- Nerfed enemy at last map (-1 magic item and -1 training)
- Fixed wrong "Dwarvish Ulfserker" as enemy recall instead "Dwarvish Berserker"
- Code reorganization for enemy configuration.
- Redefined as events some macros to alleviate disguised code bloat
0.6.1.1
- Fixed typo making scenario 4 one enemy side become broken in some difficulties for 2 players
- Enemy recalls at map 3 now scales with enemy power
- The Cult can now spam Vampire Bat and Cavalryman
- Duplicated orcs random leaders and removed Elder Wose for The Gang
0.6.1
- Redefined The Guild: Ghoul is now paired with Elvish Fighter and Skeleton with Wose.
- Duplicated Dark Sorcerer and Necrophage as random leaders for Guild and Cult. Removed Elder Wose for Guild.
- Disabled The Empire as random faction (added config option to enable it)
- Experiency penalty now scales with difficulty
- Improved movement training lvl2. Move on recruit buff now allows also attack.
0.6.0.2
- Changed Classic WC heores recall limit (was 6 maximun) to player castle size.
- Ruffian hero gets legendary (was expert). Naffat hero gets resilient and Rami hero gets strong.
- Fixed defense boost working bad for negative values due to different WML behavior in BfW 1.12
- Fixed typo making castles 1 hex smaller in map3 Sulfurous
- Small improves to melee and movement traings advanced levels
0.6.0.1
- Developed new alternative final map (Maritime)
0.6
- Buffed The Gang (now can spam Shaman and Orcish Archer)
- Buffed trait "legendary"
- Redefined WC II era events to make it copatible with other scenarios (integrated info recruit option)
- Minor tweaks to map generation, menu appearence, and code organization
- Fixed creation of useless variables in 2p and 1p modes
0.5.9.3.2
- Improved Dark Training
- Increased minimun keep separation in map2 Provinces and map4 Mines
0.5.9.3.1
- Some map generation/decoration tweaks. Improved decorative destruction
- Small improve to melee training
0.5.9.3
- More changes to Empire. Test in progress
0.5.9.2
- Buffed Cult (really hoping this is last one): Hakim paired with Walking corpose
- Fixed alias for custom villages using add on terrain modification to new 1.11 code (they were giving only flat defense)
0.5.9.1
- Developed new alternative map3 (Sulfurous)
- Converted to road swamp castle conected to keep in map3 Jungle
0.5.9
- Buffed The Cult (yea... again), now can spam more units
- Some modifications/fixes in enemy comanders extra recruits lists
0.5.8.7.2
- Removed Footpad from Empire recruit, now can spam Jundi
0.5.8.7.1
- Guardsman changed for dwarvish fighter in empire recruit
0.5.8.7
- redefined The Empire recruit. (First try to create faction was a mess)
0.5.8.6
- fixed rerandomize recruit after map1 due to new [event] inside [era] behavior in BfW 1.11
0.5.8.5
- empire buffed with 2 new pairs
- Hakim heroe gets expert trait, jundi heroe gets strong trait
0.5.8.4
- Replaced commander overlay for BfW 1.10 one
- Buffed Empire
0.5.8.3
- Developed new alternative map2 (Paradise)
0.5.8.2
- Scaled unit images for missing portraits
0.5.8.1
- Hakim hero gets "strong" trait
- Replaced thief for thug in Empire deserters
- Tweaked themed enemies adjacent villages
- Some tweaks to map3 Delta and map4 Podzol generation
0.5.8
- Added new faction with Khalifate units: The Empire
- Added Khalifate heroes to bonus points
- Fixed thread name in objectives
0.5.7.3
- Developed new alternative map4 (Podzol)
- Small fix to halo behavior
- Small fixes to map decoration
0.5.7.2
- Fixed buggy behavior in train benefict "optional charge"
- Fixed wrong commanders and pickable heroes lists for The Guild
0.5.7.1
- Redefined custom terrain config option as modification
- Added allow_undo to all menu items but preset advacement
- Fixed Classic WC bug: adamant armor not working as intended on some units after level
- Small improve to Movement training maximun level
- Reduced Discipline bonus for advanced trainers to 4%
- Some code simplification and/or clarification
0.5.7
- Redefined The Cult recruit to give a great buff to faction
- Change in The Guild recruit intended as very small buff (also for flavor reasons).
0.5.6.0.1
- Fixed bug in recall (making players need exced in 11 gold unit recall cost)
0.5.6
- Developed new alternative map2 (Glaciers)
- Developed new alternative map2 (Provinces)
- Developed new alternative map4 (Mines)
- Fixed minor bug in Classic WC jungle generator (mushroom max temperature)
- Enemy allies recruits are now randomized instead pick first value of list
- Forced lock scenario settings (but sides color for map1)
0.5.5.6.1
- Fixed bug in random hero list creation for other eras (possible empty value)
0.5.5.6
- Added config option to allow other eras (create random heroes lists)
0.5.5.5
- Redifined The Cult pairs (intended as a very small buff)
- Fixed bug causing not giving trainings in bonus points (introduced in 0.5.4)
- Fixed undesired scroll to random unit in invest training
- Fixed typo in trait "trained" description for ranger terrains specials
- Added custom bonus images
- Undead bosses get name
- Removed clear map lables (generator bug solved in 1.11.1)
0.5.5
- Added a new alternative map3: Delta
- Fixed minor bug replacing a custom image in bonus
- More acurated use of new 1.12 terrain forest. Minor decoration tweaks.
- Redefined The Militia to slighty buff it. Target is (taking fighter/scout pair apart), give the best possible pairs. New image.
- Removed Young Ogre from Heroes and Deserters of The Hand and added to its commanders.
- Fixed low unintended finish gold bonus for 2p and 1p. (carry_over formula was not working well for less players)
- Harcoded "village map amount" for finish gold bonus calculation. Fixes map generation as undesired source of stupid umbalance in players gold.
- Split WoCopedia and recruit info (new images)
0.5.4.1
- Fixed traings not giving correctly specials
- Fixed typo in random leaders info
0.5.4 (developed for BfW v1.11 series)
- Changed add on name to World Conquest II
- Chanaged abilities descriptions to 1.12 format
- Changed image file name to 1.12 path for thunderer,scout,skeleton,horseman,cavalryman(croped)
- Added support for change side colors
- Improved decoration using new 1.12 terrains
- Removed unit name mark for special_overlay in recall list (1.12 includes overlays)
- Redefined era code to make more easy additions and maintenance
- Disabled era outside WC II and seted era as only one allowed for campaign (prevents crash)
- Improved decorative destruction with custom terrain (snowed forests)
- Improved Recruit info option (added units images)
- Added deserters to WoCopedia factions. Improved WoCopedia design and readbility.
- Developed a new help option to see again items info (rightclick on image)
- Redefined The Hand pairs and random leaders to buff faction
- Integrated translated version as config option
- Increased trun limit in 2p and 1p versions. +25 gold each map for 1p.
- Reduced enemy lvl2 recalls in map4 for lower difficulties.
(deleted changelog only valid for previous BfW versions)

View file

@ -0,0 +1,34 @@
#ifdef EDITOR
#ifndef LOAD_WC2
#define LOAD_WC2
#enddef
#endif
#endif
#ifdef MULTIPLAYER
#ifndef LOAD_WC2
#define LOAD_WC2
#enddef
#endif
#endif
#ifdef LOAD_WC2
#ifdef IS_ADD_ON
#define ID_SUFFIX
_umc#enddef
#define WC2_DIR
~add-ons/World_Conquest_II/#enddef
#else
#define ID_SUFFIX
#enddef
#define WC2_DIR
campaigns/World_Conquest/#enddef
#endif
#endif

View file

@ -0,0 +1,316 @@
##############################################################
#define WORLD_CONQUEST_II_ERA_HEROES_TRAITS
[trait_extra]
types=Walking Corpse
{WORLD_CONQUEST_II_TRAIT_LEGENDARY_ZOMBIE}
[/trait_extra]
[trait_extra]
types=Goblin Spearman
{WORLD_CONQUEST_II_TRAIT_LEGENDARY_GOBLIN}
[/trait_extra]
[trait_extra]
types=Orcish Assassin,Young Ogre,Ruffian,Woodsman
{WORLD_CONQUEST_II_TRAIT_EPIC}
[/trait_extra]
[trait_extra]
types=Ghoul,Poacher,Thief,Footpad,Saurian Skirmisher,Vampire Bat,Peasant,Dune Herbalist
{WORLD_CONQUEST_II_TRAIT_EXPERT}
[/trait_extra]
[trait_extra]
types=Elvish Archer,Elvish Shaman,Elvish Scout,Elvish Fighter
{TRAIT_DEXTROUS}
[/trait_extra]
[trait_extra]
types=Dwarvish Guardsman,Dwarvish Ulfserker,Dwarvish Thunderer,Dwarvish Scout
{TRAIT_HEALTHY}
[/trait_extra]
[trait_extra]
types=Naga Fighter,Wolf Rider,Orcish Grunt,Drake Glider,Dune Rover,Dune Rider
{TRAIT_STRONG}
[/trait_extra]
[trait_extra]
types=Spearman,Fencer,Cavalryman,Merman Fighter,Merman Hunter,Mermaid Initiate,Dune Burner,Thug
{TRAIT_RESILIENT}
[/trait_extra]
[trait_extra]
types=Heavy Infantryman,Bowman,Skeleton,Skeleton Archer,Saurian Augur,Troll Whelp,Orcish Archer
{TRAIT_FEARLESS}
[/trait_extra]
[hero_spawn_filter]
types=Naga Fighter,Merman Fighter,Merman Hunter,Mermaid Initiate,
[filter_location]
[filter_radius]
[not]
terrain="M*,X*"
[/not]
[/filter_radius]
terrain="W*,S*"
radius=2
[/filter_location]
[/hero_spawn_filter]
#enddef
#define WORLD_CONQUEST_II_TRAIT_HEROIC
[trait]
id=heroic
male_name= {STR_HEROIC}
female_name= {STR_HEROIC_FEMALE}
[effect]
apply_to=loyal
[/effect]
[effect]
apply_to=attack
range=melee
increase_damage=1
[/effect]
[effect]
apply_to=attack
range=ranged
increase_damage=1
[/effect]
[effect]
apply_to=hitpoints
increase_total=5
[/effect]
[effect]
apply_to=hitpoints
times=per level
increase_total=1
[/effect]
[effect]
apply_to=movement
increase=1
[/effect]
[effect]
apply_to=max_experience
increase=-20%
[/effect]
[/trait]
#enddef
#define WORLD_CONQUEST_II_TRAIT_EXPERT
[trait]
id=expert
male_name= {STR_EXPERT}
female_name= {STR_EXPERT_FEMALE}
[effect]
apply_to=attack
range=melee
increase_attacks=1
[/effect]
[effect]
apply_to=hitpoints
increase_total=3
[/effect]
[/trait]
#enddef
#define WORLD_CONQUEST_II_TRAIT_EPIC
[trait]
id=epic
male_name= {STR_EPIC}
female_name= {STR_EPIC_FEMALE}
description= {STR_EPIC_DESCRIPTION}
[effect]
apply_to=hitpoints
increase_total=6
[/effect]
[effect]
apply_to=attack
increase_attacks=1
[/effect]
[effect]
apply_to=remove_advancement
amlas=amla_default
[/effect]
[effect]
apply_to=max_experience
lua_filter="wc2_utils.has_no_advances"
set=60
[/effect]
[effect]
apply_to=new_advancement
lua_filter="wc2_utils.has_no_advances"
amlas=amla_default
[advancement]
strict_amla=yes
max_times=100
id=amla_default
description= _ "Max HP bonus +6%"
image="icons/amla-default.png"
[effect]
apply_to=hitpoints
increase_total=6
heal_full=yes
[/effect]
[effect]
apply_to=status
remove=poisoned
[/effect]
[effect]
apply_to=status
remove=slowed
[/effect]
[/advancement]
[/effect]
[/trait]
#enddef
#define WORLD_CONQUEST_II_TRAIT_LEGENDARY_ZOMBIE
[trait]
id=legendary_zombie
male_name= {STR_LEGENDARY}
female_name= {STR_LEGENDARY_FEMALE}
description= {STR_LEGENDARY_ZOMBIE_DESCRIPTION}
[effect]
apply_to=hitpoints
increase_total=5
[/effect]
[effect]
apply_to=hitpoints
times=per level
increase_total=1
[/effect]
[effect]
apply_to=attack
increase_attacks=1
[/effect]
[effect]
apply_to=attack
type=pierce
[set_specials]
mode=append
{WEAPON_SPECIAL_PLAGUE}
[/set_specials]
[/effect]
[effect]
[filter]
type="Soulless"
[/filter]
apply_to=remove_advancement
amlas=amla_default
[/effect]
[effect]
[filter]
type="Soulless"
[/filter]
apply_to=new_advancement
types=Chocobone
[/effect]
[/trait]
#enddef
#define WORLD_CONQUEST_II_TRAIT_LEGENDARY_GOBLIN
[trait]
id=legendary_goblin
male_name= {STR_LEGENDARY}
female_name= {STR_LEGENDARY_FEMALE}
description= {STR_LEGENDARY_GOBLIN_DESCRIPTION}
[effect]
apply_to=hitpoints
increase_total=5
[/effect]
[effect]
apply_to=hitpoints
times=per level
increase_total=1
[/effect]
[effect]
apply_to=attack
increase_attacks=1
[/effect]
[effect]
apply_to=attack
type=blade
[set_specials]
mode=append
{WEAPON_SPECIAL_POISON}
[/set_specials]
[/effect]
[effect]
apply_to=attack
type=fire,blade
increase_damage=1
[/effect]
{WCT_LEADERSHIP}
[effect]
[filter]
level=1
[/filter]
apply_to=remove_advancement
amlas=amla_default
[/effect]
[effect]
[filter]
level=1
[/filter]
apply_to=new_advancement
types=Goblin Pillager
[/effect]
[/trait]
#enddef
#textdomain wesnoth-multiplayer
#define WORLD_CONQUEST_II_ERA_HEROES_TYPES
[Northerners]
name=_"Northerners"
types="Orcish Grunt,Troll Whelp,Orcish Archer,Orcish Assassin,Orcish Leader"
[/Northerners]
[Northerners_All]
types="Northerners,Naga Fighter"
[/Northerners_All]
[Rebels]
name=_"Rebels"
types="Mage,Elvish Fighter,Elvish Archer,Elvish Shaman,Elvish Scout,Wose"
[/Rebels]
[Rebels_All]
types="Rebels,Merman Hunter,Mermaid Initiate"
[/Rebels_All]
[Loyalists]
name=_"Loyalists"
types="Cavalryman,Horseman,Spearman,Fencer,Heavy Infantryman,Bowman,Sergeant,Mage"
[/Loyalists]
[Loyalists_All]
types="Loyalists,Merman Fighter"
[/Loyalists_All]
[Knalgans]
name=_"Knalgan Alliance"
types="Dwarvish Fighter,Thief,Dwarvish Thunderer,Poacher,Dwarvish Guardsman,Footpad,Dwarvish Ulfserker,Gryphon Rider"
[/Knalgans]
[Knalgans_All]
types="Knalgans,Dwarvish Scout"
[/Knalgans_All]
[Drakes]
name=_"Drakes"
types="Drake Fighter,Drake Clasher,Drake Burner,Saurian Augur,Drake Glider,Saurian Skirmisher"
[/Drakes]
[Undead]
name=_"Undead"
types="Skeleton,Skeleton Archer,Ghoul,Dark Adept,Ghost"
[/Undead]
[Undead_All]
types="Undead,Vampire Bat"
[/Undead_All]
[Bonus]
types="Goblin Spearman,Walking Corpse,Ruffian,Peasant,Woodsman"
[/Bonus]
[Khalifate]
#TODO: this contained 'Dune Piercer' in 1.14
types="Dune Rover,Dune Rider,Dune Burner,Dune Herbalist,Dune Soldier"
[/Khalifate]
[Empire_commanders]
types="Elvish Fighter,Dwarvish Fighter,Orcish Archer,Spearman,Drake Burner"
[/Empire_commanders]
[Empire_heroes]
types="Mage,Bowman,Saurian Skirmisher,Drake Clasher,Elvish Archer,Wose,Gryphon Rider,Poacher,Orcish Leader,Wolf Rider,Ghost,Dark Adept"
[/Empire_heroes]
[Empire_deserters]
types="Heavy Infantryman,Sergeant,Drake Glider,Saurian Augur,Elvish Shaman,Elvish Scout,Thug,Dwarvish Scout,Troll Whelp,Orcish Assassin,Ghoul,Skeleton Archer"
[/Empire_deserters]
[Bonus_All]
types="Northerners_All,Rebels_All,Loyalists_All,Knalgans_All,Drakes,Undead_All,Young Ogre,Thug,Bonus,Khalifate"
[/Bonus_All]
#enddef

View file

@ -0,0 +1,34 @@
#textdomain wesnoth-World_Conquest
#define STR_HEROIC
_ "heroic" #enddef
#define STR_HEROIC_FEMALE
_ "female^heroic" #enddef
#define STR_EXPERT
_ "expert" #enddef
#define STR_EXPERT_FEMALE
_ "female^expert" #enddef
#define STR_EPIC
_ "epic" #enddef
#define STR_EPIC_FEMALE
_ "female^epic" #enddef
#define STR_EPIC_DESCRIPTION
_ "Always AMLA with 60 XP and raises maximum health by 6 HP." #enddef
#define STR_LEGENDARY
_ "legendary" #enddef
#define STR_LEGENDARY_FEMALE
_ "female^legendary" #enddef
#define STR_LEGENDARY_ZOMBIE_DESCRIPTION
_ "Special advancement to Chocobone enabled." #enddef
#define STR_LEGENDARY_GOBLIN_DESCRIPTION
_ "Special advancement to Goblin Pillager enabled." #enddef

View file

@ -0,0 +1,60 @@
## add subfolders
{./factions}
{./campaign}
#define WORLD_CONQUEST_II_ERA
[era]
id= "{STR_ERA_ID_WC_II}{ID_SUFFIX}"
name= {STR_ERA_NAME_WC_II}{ID_SUFFIX}
description= {STR_ERA_DESCRIPTION_WC_II}
require_era=yes
# addon_min_version="8.2"
{MULTIPLAYER_SIDE_RANDOM_WC_II}
{MULTIPLAYER_SIDE_THE_TRUST}
{MULTIPLAYER_SIDE_THE_GUILD}
{MULTIPLAYER_SIDE_THE_HAND}
{MULTIPLAYER_SIDE_THE_MILITIA}
{MULTIPLAYER_SIDE_THE_HORDE}
{MULTIPLAYER_SIDE_THE_CULT}
{MULTIPLAYER_SIDE_THE_GANG}
{MULTIPLAYER_SIDE_THE_SCOURGE}
{MULTIPLAYER_SIDE_THE_ALLIANCE}
#TODO: disabled since it contains 'Dune Piercer'
# {MULTIPLAYER_SIDE_THE_EMPIRE}
[load_resource]
id = "wc2_era_res{ID_SUFFIX}"
[/load_resource]
[/era]
#enddef
#define WORLD_CONQUEST_II_ERA_RESOURCE
## this is needed in both the era and the campaign, in particular in the campaign this data is used to generate the deserters and the ai sides.
[resource]
id = "wc2_era_res{ID_SUFFIX}"
[lua]
code = " wesnoth.dofile('{WC2_DIR}/lua/era_main.lua') "
[/lua]
[load_resource]
id = "wc2_mainline_heroes{ID_SUFFIX}"
[/load_resource]
[/resource]
[resource]
id = "wc2_mainline_heroes{ID_SUFFIX}"
[world_conquest_data]
[hero_types]
{WORLD_CONQUEST_II_ERA_HEROES_TYPES}
[/hero_types]
## array of [trait_extra]
{WORLD_CONQUEST_II_ERA_HEROES_TRAITS}
[/world_conquest_data]
[/resource]
#enddef
#define WC_II_PAIR UNIT1 UNIT2
[pair]
types = {UNIT1} + "," + {UNIT2}
[/pair]
#enddef

View file

@ -0,0 +1,12 @@
#textdomain wesnoth-multiplayer
#define MULTIPLAYER_SIDE_RANDOM_WC_II
[multiplayer_side]
id=Random
name= _ "Random"
image= units/random-dice.png
random_faction=yes
## The empire is not complteley blaanced to exclude it for now from random.
except=The Empire
[/multiplayer_side]
#enddef

View file

@ -0,0 +1,33 @@
#textdomain wesnoth-units
#define MULTIPLAYER_SIDE_THE_ALLIANCE
[multiplayer_side]
id=The Alliance
name={STR_ALLIANCE}
recruit=Spearman, Dwarvish Fighter,Bowman,Poacher,Horseman, Dwarvish Thunderer,Fencer,Thief,Mage,Dwarvish Ulfserker,Heavy Infantryman,Dwarvish Guardsman,Cavalryman,Footpad,Merman Fighter,Gryphon Rider
image={IMG_ALLIANCE}
type=random
leader= Dwarvish Steelclad,Dwarvish Thunderguard,Dwarvish Stalwart,Rogue,Trapper,Lieutenant,Swordsman,Pikeman,Javelineer,Shock Trooper,Longbowman,White Mage,Red Mage
random_leader= {RANDOM_LEADERS_ALLIANCE}
[world_conquest_data]
commanders=Loyalists,Knalgans
heroes=Rebels_All,Drakes
deserters=Undead,Northerners,Young Ogre
deserters_names={STR_YOUNG_OGRE}+", "+{STR_THE_UNDEAD}+{STR_AND}+{STR_NORTHERENS}
{WC_II_PAIR "Spearman" "Dwarvish Fighter"}
{WC_II_PAIR "Bowman" "Poacher"}
{WC_II_PAIR "Horseman" "Dwarvish Thunderer"}
{WC_II_PAIR "Fencer" "Thief"}
{WC_II_PAIR "Mage" "Dwarvish Ulfserker"}
{WC_II_PAIR "Heavy Infantryman" "Dwarvish Guardsman"}
{WC_II_PAIR "Cavalryman" "Footpad"}
{WC_II_PAIR "Merman Fighter" "Gryphon Rider"}
[/world_conquest_data]
[/multiplayer_side]
#enddef
#define RANDOM_LEADERS_ALLIANCE
Dwarvish Steelclad,Dwarvish Thunderguard,Dwarvish Stalwart,Rogue,Trapper,Lieutenant,Swordsman,Pikeman,Longbowman,White Mage,Red Mage #enddef
#define IMG_ALLIANCE
"misc/blank-hex.png~BLIT(units/dwarves/steelclad.png~RC(magenta>purple)~CROP(0,0,59,72),13,0)~BLIT(units/human-loyalists/lieutenant.png~RC(magenta>white)~CROP(16,0,56,72))" #enddef

View file

@ -0,0 +1,39 @@
#textdomain wesnoth-units
#define MULTIPLAYER_SIDE_THE_CULT
[multiplayer_side]
id=The Cult
name={STR_CULT}
recruit=Spearman,Spearman,Skeleton,Skeleton,Bowman,Bowman,Skeleton Archer,Skeleton Archer,Mage,Mage,Dark Adept,Dark Adept,Horseman,Horseman,Ghoul,Ghoul,Fencer,Fencer,Dune Herbalist,Walking Corpse,Heavy Infantryman,Ghost,Cavalryman,Cavalryman,Vampire Bat,Vampire Bat,Merman Fighter,Merman Fighter
image={IMG_CULT}
type=random
leader= Lieutenant,Swordsman,Pikeman,Javelineer,Shock Trooper,Longbowman,White Mage,Red Mage,Dark Sorcerer,Revenant,Deathblade,Bone Shooter,Necrophage
random_leader= {RANDOM_LEADERS_CULT}
[world_conquest_data]
commanders=Loyalists,Undead,Dune Herbalist
heroes=Rebels_All,Knalgans_All
deserters=Drakes,Northerners,Young Ogre
deserters_names={STR_YOUNG_OGRE}+", "+{STR_DRAKES}+{STR_AND}+{STR_NORTHERENS}
{WC_II_PAIR "Spearman" "Spearman"}
{WC_II_PAIR "Skeleton" "Skeleton"}
{WC_II_PAIR "Bowman" "Bowman"}
{WC_II_PAIR "Skeleton Archer" "Skeleton Archer"}
{WC_II_PAIR "Mage" "Mage"}
{WC_II_PAIR "Dark Adept" "Dark Adept"}
{WC_II_PAIR "Horseman" "Horseman"}
{WC_II_PAIR "Ghoul" "Ghoul"}
{WC_II_PAIR "Fencer" "Fencer"}
{WC_II_PAIR "Dune Herbalist" "Walking Corpse"}
{WC_II_PAIR "Heavy Infantryman" "Ghost"}
{WC_II_PAIR "Cavalryman" "Cavalryman"}
{WC_II_PAIR "Vampire Bat" "Vampire Bat"}
{WC_II_PAIR "Merman Fighter" "Merman Fighter"}
[/world_conquest_data]
[/multiplayer_side]
#enddef
#define RANDOM_LEADERS_CULT
Lieutenant,Swordsman,Pikeman,Longbowman,White Mage,Red Mage,Dark Sorcerer,Dark Sorcerer,Revenant,Bone Shooter,Necrophage,Necrophage #enddef
#define IMG_CULT
"misc/blank-hex.png~BLIT(units/human-loyalists/pikeman.png~RC(magenta>white)~CROP(0,3,58,69),14,0)~BLIT(units/undead-skeletal/revenant/revenant.png~RC(magenta>blue)~CROP(9,0,63,71),0,1)" #enddef

View file

@ -0,0 +1,31 @@
#textdomain wesnoth-units
#define MULTIPLAYER_SIDE_THE_EMPIRE
[multiplayer_side]
id=The Empire
name={STR_EMPIRE}
recruit=Dune Rover,Elvish Fighter,Dune Burner,Drake Burner,Dune Soldier,Spearman,Dune Piercer,Dwarvish Fighter,Dune Herbalist,Dune Herbalist,Dune Rider,Orcish Archer,Falcon,Vampire Bat
image={IMG_EMPIRE}
type=random
leader= Dune Explorer,Dune Swordsman,Dune Spearguard,Dune Skirmisher,Dune Apothecary,Dune Scorcher
random_leader= {RANDOM_LEADERS_EMPIRE}
[world_conquest_data]
commanders=Khalifate,Empire_commanders
heroes=Empire_heroes
deserters=Empire_deserters,Young Ogre
{WC_II_PAIR "Dune Rover" "Elvish Fighter"}
{WC_II_PAIR "Dune Burner" "Drake Burner"}
{WC_II_PAIR "Dune Soldier" "Spearman"}
{WC_II_PAIR "Dune Piercer" "Dwarvish Fighter"}
{WC_II_PAIR "Dune Herbalist" "Dune Herbalist"}
{WC_II_PAIR "Dune Rider" "Orcish Archer"}
{WC_II_PAIR "Falcon" "Vampire Bat"}
[/world_conquest_data]
[/multiplayer_side]
#enddef
#define RANDOM_LEADERS_EMPIRE
Dune Explorer,Dune Swordsman,Dune Spearguard,Dune Skirmisher,Dune Scorcher #enddef
#define IMG_EMPIRE
"misc/blank-hex.png~BLIT(units/dunefolk/scorcher.png~RC(magenta>teal)~CROP(0,13,57,59),15,0)~BLIT(units/dunefolk/explorer.png~RC(magenta>teal)~FL()~CROP(11,0,61,67),0,5)" #enddef

View file

@ -0,0 +1,35 @@
#textdomain wesnoth-units
#define MULTIPLAYER_SIDE_THE_GANG
[multiplayer_side]
id=The Gang
name={STR_GANG}
recruit=Troll Whelp,Elvish Fighter,Orcish Grunt,Orcish Grunt,Elvish Archer,Elvish Archer,Orcish Archer,Orcish Archer,Elvish Shaman,Elvish Shaman,Orcish Assassin,Orcish Assassin,Wose,Wose,Goblin Spearman,Mage,Wolf Rider,Elvish Scout,Naga Fighter,Merman Hunter
image={IMG_GANG}
type=random
leader= Elvish Captain,Elvish Hero,Elvish Ranger,Elvish Marksman,Elvish Druid,Elvish Sorceress,Red Mage,Elder Wose,Orcish Ruler,Orcish Warrior,Troll Hero,Troll,Troll Rocklobber,Orcish Crossbowman,Orcish Slayer
random_leader= {RANDOM_LEADERS_GANG}
[world_conquest_data]
commanders=Rebels,Northerners
heroes=Drakes,Undead_All
deserters=Loyalists,Knalgans,Dune Herbalist
deserters_names={STR_HAKIM}+", "+{STR_LOYALISTS}+{STR_AND}+{STR_KNALGAN}
{WC_II_PAIR "Troll Whelp" "Elvish Fighter"}
{WC_II_PAIR "Orcish Grunt" "Orcish Grunt"}
{WC_II_PAIR "Elvish Archer" "Elvish Archer"}
{WC_II_PAIR "Orcish Archer" "Orcish Archer"}
{WC_II_PAIR "Elvish Shaman" "Elvish Shaman"}
{WC_II_PAIR "Orcish Assassin" "Orcish Assassin"}
{WC_II_PAIR "Wose" "Wose"}
{WC_II_PAIR "Goblin Spearman" "Mage"}
{WC_II_PAIR "Wolf Rider" "Elvish Scout"}
{WC_II_PAIR "Naga Fighter" "Merman Hunter"}
[/world_conquest_data]
[/multiplayer_side]
#enddef
#define RANDOM_LEADERS_GANG
Elvish Captain,Elvish Hero,Elvish Ranger,Elvish Marksman,Elvish Druid,Elvish Sorceress,Red Mage,Orcish Ruler,Troll Hero,Troll,Troll,Orcish Warrior,Orcish Warrior,Orcish Crossbowman,Orcish Crossbowman #enddef
#define IMG_GANG
"misc/blank-hex.png~BLIT(units/orcs/xbowman.png~RC(magenta>red)~CROP(0,8,54,64),18,0)~BLIT(units/elves-wood/ranger.png~RC(magenta>green)~CROP(15,0,57,72),0,0)" #enddef

View file

@ -0,0 +1,35 @@
#textdomain wesnoth-units
#define MULTIPLAYER_SIDE_THE_GUILD
[multiplayer_side]
id=The Guild
name={STR_GUILD}
recruit=Elvish Fighter,Elvish Fighter,Dark Adept,Dark Adept,Elvish Archer,Skeleton Archer,Mage,Walking Corpse,Elvish Shaman,Ghoul,Wose,Skeleton,Elvish Scout,Vampire Bat,Ghost,Ghost,Merman Hunter,Merman Hunter,Mermaid Initiate,Mermaid Initiate
image={IMG_GUILD}
type=random
leader=Elvish Lord,Elvish Captain,Elvish Hero,Elvish Ranger,Elvish Marksman,Elvish Druid,Elvish Sorceress,White Mage,Red Mage,Elder Wose,Dark Sorcerer,Revenant,Deathblade,Bone Shooter,Necrophage
random_leader= {RANDOM_LEADERS_GUILD}
[world_conquest_data]
commanders=Rebels,Undead
heroes=Knalgans_All,Northerners_All,Young Ogre
deserters=Loyalists,Drakes,Dune Soldier
deserters_names={STR_ARIF}+", "+{STR_LOYALISTS}+{STR_AND}+{STR_DRAKES}
{WC_II_PAIR "Elvish Fighter" "Elvish Fighter"}
{WC_II_PAIR "Dark Adept" "Dark Adept"}
{WC_II_PAIR "Elvish Archer" "Skeleton Archer"}
{WC_II_PAIR "Mage" "Walking Corpse"}
{WC_II_PAIR "Elvish Shaman" "Ghoul"}
{WC_II_PAIR "Wose" "Skeleton"}
{WC_II_PAIR "Elvish Scout" "Vampire Bat"}
{WC_II_PAIR "Ghost" "Ghost"}
{WC_II_PAIR "Merman Hunter" "Merman Hunter"}
{WC_II_PAIR "Mermaid Initiate" "Mermaid Initiate"}
[/world_conquest_data]
[/multiplayer_side]
#enddef
#define RANDOM_LEADERS_GUILD
Elvish Lord,Elvish Druid,Elvish Sorceress,White Mage,Red Mage,Dark Sorcerer,Dark Sorcerer,Necrophage,Necrophage #enddef
#define IMG_GUILD
"misc/blank-hex.png~BLIT(units/elves-wood/sorceress.png~RC(magenta>green)~CROP(14,1,58,71))~BLIT(units/undead-necromancers/dark-sorcerer+female.png~RC(magenta>blue)~CROP(0,0,60,67),12,5)" #enddef

View file

@ -0,0 +1,36 @@
#textdomain wesnoth-units
#define MULTIPLAYER_SIDE_THE_HAND
[multiplayer_side]
id=The Hand
name={STR_HAND}
recruit=Spearman,Orcish Grunt,Bowman,Orcish Assassin,Mage,Orcish Archer,Troll Whelp,Troll Whelp,Heavy Infantryman,Heavy Infantryman,Young Ogre,Young Ogre,Cavalryman,Wolf Rider,Horseman,Orcish Leader,Fencer,Goblin Spearman,Merman Fighter,Naga Fighter
image={IMG_HAND}
type=random
leader=Lieutenant,Swordsman,Pikeman,Javelineer,Shock Trooper,Longbowman,White Mage,Red Mage,Orcish Warrior,Troll,Troll Rocklobber,Orcish Crossbowman,Orcish Slayer,Orcish Ruler,Troll Hero
random_leader= {RANDOM_LEADERS_HAND}
[world_conquest_data]
commanders=Loyalists,Northerners,Young Ogre
heroes=Undead_All,Rebels_All
# TODO: this contained 'Dune Piercer' in 1.14
deserters=Knalgans,Drakes
deserters_names={STR_KHAIYAL}+", "+{STR_KNALGAN}+{STR_AND}+{STR_DRAKES}
{WC_II_PAIR "Spearman" "Orcish Grunt"}
{WC_II_PAIR "Bowman" "Orcish Assassin"}
{WC_II_PAIR "Mage" "Orcish Archer"}
{WC_II_PAIR "Troll Whelp" "Troll Whelp"}
{WC_II_PAIR "Heavy Infantryman" "Heavy Infantryman"}
{WC_II_PAIR "Young Ogre" "Young Ogre"}
{WC_II_PAIR "Cavalryman" "Wolf Rider"}
{WC_II_PAIR "Horseman" "Orcish Leader"}
{WC_II_PAIR "Fencer" "Goblin Spearman"}
{WC_II_PAIR "Merman Fighter" "Naga Fighter"}
[/world_conquest_data]
[/multiplayer_side]
#enddef
#define RANDOM_LEADERS_HAND
White Mage,White Mage,Orcish Ruler,Orcish Ruler,Lieutenant,Troll Hero #enddef
#define IMG_HAND
"misc/blank-hex.png~BLIT(units/human-magi/white-mage.png~RC(magenta>white)~CROP(18,0,54,72))~BLIT(units/orcs/ruler.png~RC(magenta>red)~CROP(0,0,58,72),14,0)" #enddef

View file

@ -0,0 +1,33 @@
#textdomain wesnoth-units
#define MULTIPLAYER_SIDE_THE_HORDE
[multiplayer_side]
id=The Horde
name={STR_HORDE}
recruit=Orcish Grunt,Drake Fighter,Orcish Archer,Drake Burner,Orcish Assassin,Saurian Augur,Troll Whelp,Drake Clasher,Wolf Rider,Drake Glider,Goblin Spearman,Goblin Spearman,Saurian Skirmisher,Saurian Skirmisher,Naga Fighter,Naga Fighter
image={IMG_HORDE}
type=random
leader= Orcish Ruler,Orcish Warrior,Troll Hero,Troll,Troll Rocklobber,Orcish Crossbowman,Orcish Slayer,Drake Flare,Fire Drake,Drake Arbiter,Drake Thrasher,Drake Warrior,Saurian Oracle,Saurian Soothsayer
random_leader= {RANDOM_LEADERS_HORDE}
[world_conquest_data]
commanders=Drakes,Northerners
heroes=Undead_All,Loyalists_All
deserters=Knalgans,Rebels,Dune Rider
deserters_names={STR_RAMI}+", "+{STR_KNALGAN}+{STR_AND}+{STR_REBELS}
{WC_II_PAIR "Orcish Grunt" "Drake Fighter"}
{WC_II_PAIR "Orcish Archer" "Drake Burner"}
{WC_II_PAIR "Orcish Assassin" "Saurian Augur"}
{WC_II_PAIR "Troll Whelp" "Drake Clasher"}
{WC_II_PAIR "Wolf Rider" "Drake Glider"}
{WC_II_PAIR "Goblin Spearman" "Goblin Spearman"}
{WC_II_PAIR "Saurian Skirmisher" "Saurian Skirmisher"}
{WC_II_PAIR "Naga Fighter" "Naga Fighter"}
[/world_conquest_data]
[/multiplayer_side]
#enddef
#define RANDOM_LEADERS_HORDE
Orcish Ruler,Troll Hero,Orcish Warrior,Orcish Warrior,Troll,Troll,Orcish Crossbowman,Orcish Crossbowman,Drake Flare,Fire Drake,Fire Drake,Drake Arbiter,Drake Arbiter,Drake Thrasher,Drake Thrasher,Drake Warrior,Drake Warrior #enddef
#define IMG_HORDE
"misc/blank-hex.png~BLIT(units/drakes/warrior.png~RC(magenta>orange)~CROP(0,7,66,65),6,0)~BLIT(units/orcs/warrior.png~RC(magenta>red)~CROP(17,0,55,65),0,7)" #enddef

View file

@ -0,0 +1,33 @@
#textdomain wesnoth-units
#define MULTIPLAYER_SIDE_THE_MILITIA
[multiplayer_side]
id=The Militia
name={STR_MILITIA}
recruit=Dwarvish Fighter,Elvish Scout,Thug,Elvish Fighter,Dwarvish Thunderer,Elvish Archer,Poacher,Elvish Shaman,Dwarvish Guardsman,Wose,Footpad,Mage,Dwarvish Ulfserker,Thief,Gryphon Rider,Merman Hunter
image={IMG_MILITIA}
type=random
leader= Elvish Captain,Elvish Hero,Elvish Ranger,Elvish Marksman,Elvish Druid,Elvish Sorceress,Elder Wose,Dwarvish Steelclad,Dwarvish Thunderguard,Dwarvish Stalwart,Rogue,Trapper,Bandit
random_leader= {RANDOM_LEADERS_MILITIA}
[world_conquest_data]
commanders=Rebels,Knalgans,Thug
heroes=Northerners_All,Young Ogre,Drakes
deserters=Undead,Loyalists,Dune Rover
deserters_names={STR_JUNDI}+", "+{STR_THE_UNDEAD}+{STR_AND}+{STR_LOYALISTS}
{WC_II_PAIR "Dwarvish Fighter" "Elvish Scout"}
{WC_II_PAIR "Thug" "Elvish Fighter"}
{WC_II_PAIR "Dwarvish Thunderer" "Elvish Archer"}
{WC_II_PAIR "Poacher" "Elvish Shaman"}
{WC_II_PAIR "Dwarvish Guardsman" "Wose"}
{WC_II_PAIR "Footpad" "Mage"}
{WC_II_PAIR "Dwarvish Ulfserker" "Thief"}
{WC_II_PAIR "Gryphon Rider" "Merman Hunter"}
[/world_conquest_data]
[/multiplayer_side]
#enddef
#define RANDOM_LEADERS_MILITIA
Elvish Captain,Elvish Hero,Elvish Ranger,Elvish Marksman,Elvish Druid,Elvish Sorceress,Elder Wose,Dwarvish Steelclad,Dwarvish Thunderguard,Dwarvish Stalwart,Rogue,Trapper,Bandit #enddef
#define IMG_MILITIA
"misc/blank-hex.png~BLIT(units/human-outlaws/bandit.png~RC(magenta>purple)~FL()~CROP(12,4,60,68))~BLIT(units/elves-wood/captain.png~RC(magenta>green)~CROP(0,0,57,72),15,0)" #enddef

View file

@ -0,0 +1,32 @@
#textdomain wesnoth-units
#define MULTIPLAYER_SIDE_THE_SCOURGE
[multiplayer_side]
id=The Scourge
name={STR_SCOURGE}
recruit=Skeleton,Drake Fighter,Skeleton Archer,Drake Burner,Dark Adept,Saurian Augur,Ghoul,Drake Clasher,Ghost,Saurian Skirmisher,Vampire Bat,Drake Glider,Walking Corpse,Walking Corpse
image={IMG_SCOURGE}
type=random
leader=Dark Sorcerer,Revenant,Deathblade,Bone Shooter,Necrophage,Drake Flare,Fire Drake,Drake Arbiter,Drake Thrasher,Drake Warrior,Saurian Oracle,Saurian Soothsayer
random_leader= {RANDOM_LEADERS_SCOURGE}
[world_conquest_data]
commanders=Drakes,Undead
heroes=Loyalists_All,Knalgans_All
deserters=Rebels,Northerners,Young Ogre
deserters_names={STR_YOUNG_OGRE}+", "+{STR_REBELS}+{STR_AND}+{STR_NORTHERENS}
{WC_II_PAIR "Skeleton" "Drake Fighter"}
{WC_II_PAIR "Skeleton Archer" "Drake Burner"}
{WC_II_PAIR "Dark Adept" "Saurian Augur"}
{WC_II_PAIR "Ghoul" "Drake Clasher"}
{WC_II_PAIR "Ghost" "Saurian Skirmisher"}
{WC_II_PAIR "Vampire Bat" "Drake Glider"}
{WC_II_PAIR "Walking Corpse" "Walking Corpse"}
[/world_conquest_data]
[/multiplayer_side]
#enddef
#define RANDOM_LEADERS_SCOURGE
Dark Sorcerer,Revenant,Bone Shooter,Necrophage,Drake Flare,Fire Drake,Drake Arbiter,Drake Thrasher,Drake Warrior #enddef
#define IMG_SCOURGE
"misc/blank-hex.png~BLIT(units/undead/necrophage.png~RC(magenta>blue)~CROP(0,13,55,59),17,0)~BLIT(units/drakes/flare.png~RC(magenta>orange)~CROP(10,0,62,67),0,5)" #enddef

View file

@ -0,0 +1,32 @@
#textdomain wesnoth-units
#define MULTIPLAYER_SIDE_THE_TRUST
[multiplayer_side]
id=The Trust
name={STR_TRUST}
recruit=Drake Fighter,Dwarvish Fighter,Drake Burner,Dwarvish Thunderer,Saurian Augur,Dwarvish Ulfserker,Drake Clasher,Dwarvish Guardsman,Saurian Skirmisher,Poacher,Drake Glider,Footpad,Thief,Thief
image={IMG_TRUST}
type=random
leader= Dwarvish Steelclad,Dwarvish Thunderguard,Dwarvish Stalwart,Rogue,Trapper,Drake Flare,Fire Drake,Drake Arbiter,Drake Thrasher,Drake Warrior,Saurian Oracle,Saurian Soothsayer
random_leader= {RANDOM_LEADERS_TRUST}
[world_conquest_data]
commanders=Drakes,Knalgans
heroes=Loyalists_All,Northerners_All,Young Ogre
deserters=Rebels,Undead,Dune Burner
deserters_names={STR_NAFFAT}+", "+{STR_REBELS}+{STR_AND}+{STR_THE_UNDEAD}
{WC_II_PAIR "Drake Fighter" "Dwarvish Fighter"}
{WC_II_PAIR "Drake Burner" "Dwarvish Thunderer"}
{WC_II_PAIR "Saurian Augur" "Dwarvish Ulfserker"}
{WC_II_PAIR "Drake Clasher" "Dwarvish Guardsman"}
{WC_II_PAIR "Saurian Skirmisher" "Poacher"}
{WC_II_PAIR "Drake Glider" "Footpad"}
{WC_II_PAIR "Thief" "Thief"}
[/world_conquest_data]
[/multiplayer_side]
#enddef
#define RANDOM_LEADERS_TRUST
Dwarvish Steelclad,Dwarvish Thunderguard,Dwarvish Stalwart,Rogue,Trapper,Drake Flare,Fire Drake,Drake Arbiter,Drake Thrasher,Drake Warrior #enddef
#define IMG_TRUST
"misc/blank-hex.png~BLIT(units/dwarves/stalwart.png~RC(magenta>purple)~CROP(0,20,55,52),17,0)~BLIT(units/drakes/arbiter.png~RC(magenta>orange)~CROP(8,0,64,67),0,5)" #enddef

View file

@ -0,0 +1,89 @@
#textdomain wesnoth-World_Conquest
#define STR_ERA_ID_WC_II
world_conquest_era#enddef
#define STR_ERA_NAME_WC_II
_"World Conquest" #enddef
#define STR_ERA_DESCRIPTION_WC_II
_"Units are defined as pairs in recruit list: Every time a unit is recruited, it is remplaced by its pair. This era is designed to be balanced playing World Conquest II.
Includes an in-game help to know pairs status, with a right-click on an emty hex." #enddef
#define STR_HORDE
_"The Horde" #enddef
#define STR_ALLIANCE
_"The Alliance" #enddef
#define STR_GUILD
_"The Guild" #enddef
#define STR_TRUST
_"The Trust" #enddef
#define STR_GANG
_"The Gang" #enddef
#define STR_CULT
_"The Cult" #enddef
#define STR_MILITIA
_"The Militia" #enddef
#define STR_SCOURGE
_"The Scourge" #enddef
#define STR_HAND
_"The Hand" #enddef
#define STR_EMPIRE
_"The Empire" #enddef
######################################
#################################
#textdomain wesnoth-units
#################################
#define STR_ARIF
_ "Dune Soldier" #enddef
#define STR_HAKIM
_ "Dune Herbalist" #enddef
#define STR_JUNDI
_ "Dune Rover" #enddef
#define STR_KHAIYAL
_ "Dune Piercer" #enddef
#define STR_NAFFAT
_ "Dune Burner" #enddef
#define STR_RAMI
_ "Dune Rider" #enddef
#define STR_YOUNG_OGRE
_ "Young Ogre" #enddef
#################################
#textdomain wesnoth-multiplayer
#################################
#define STR_DRAKES
_ "Drakes" #enddef
#define STR_KNALGAN
_ "Knalgan Alliance" #enddef
#define STR_LOYALISTS
_ "Loyalists" #enddef
#define STR_NORTHERENS
_ "Northerners" #enddef
#define STR_REBELS
_ "Rebels" #enddef
#define STR_THE_UNDEAD
_ "Undead" #enddef

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 731 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -0,0 +1,41 @@
local on_event = wesnoth.require("on_event")
-- players get recalled by free all heroes up to castle size
local function wc2_autorecall()
for side_num = 1, wml.variables.wc2_player_count do
local castle_tiles = wesnoth.get_locations {
terrain = "C*",
wml.tag["and"] {
radius = 3,
wml.tag.filter_radius {
terrain = "C*,K*"
},
wml.tag.filter {
side = side_num,
canrecruit = true,
}
}
}
for i, loc in ipairs(castle_tiles) do
wesnoth.wml_actions.recall {
x = loc[1],
y = loc[2],
show = false,
side = side_num,
wml.tag.filter_wml {
wml.tag.modifications {
wml.tag.trait {
id = "heroic"
}
}
}
}
end
end
end
on_event("start", function(cx)
local scenario_num = wc2_scenario.scenario_num()
if (scenario_num or 1) > 1 then
wc2_autorecall()
end
end)

View file

@ -0,0 +1,120 @@
-- The difficulty dialog. unlike other files this does not 'export' functions,
-- just run this file to show the diffculty dialog.
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local strings = {
chose_difficulty = "<span size='large'>" .. _"Choose difficulty level:" .. "</span>",
}
local _ = wesnoth.textdomain 'wesnoth-units'
local strings_mainline = {
Sergeant = _"Sergeant",
Peasant = _"Peasant",
Lieutenant = _"Lieutenant",
General = _"General",
Grand_Marshal = _"Grand Marshal"
}
local function icon_human_difficult(unit_image, color)
return "misc/blank-hex.png~SCALE(140,100)" ..
"~BLIT(units/" .. unit_image .. ".png~RC(magenta>" .. color .. "),34,7)"
end
local function str_dif_lvl(name)
return "<span size='large'>" .. name .. "</span>"
end
local icon_nightmare_difficulty = "units/monsters/fire-dragon.png~CROP(0,0,160,160)~RC(magenta>red)"
local t_option = wml.tag.option
local function wct_difficulty(name, power, enemy_t, heroes, gold, train, exp)
local nplayers = wml.variables.wc2_player_count
if nplayers == 1 then
heroes = heroes + 1
end
-- adjust bonus gold for number of players
gold = gold * math.pow(2, 3 - nplayers)
return wml.tag.command {
wml.tag.set_variables {
name = "wc2_difficulty",
wml.tag.literal {
name = name,
enemy_power = power,
enemy_trained = enemy_t,
heroes = heroes,
extra_gold = gold,
extra_trainig = train,
experience_penalty = exp,
}
}
}
end
function wct_scenario_chose_difficulty()
-- fixme: should the first part argument of wct_difficulty be translatable
wesnoth.wml_actions.message {
speaker = "narrator",
caption = strings.chose_difficulty,
t_option {
image = icon_human_difficult("human-peasants/peasant", "purple"),
label = str_dif_lvl(strings_mainline.Peasant),
description="(" .. _"Easy" .. ")",
wct_difficulty("Peasant", 6, 2, 2, 10, true, 0),
},
t_option {
image=icon_human_difficult("human-loyalists/sergeant", "black"),
label=str_dif_lvl(strings_mainline.Sergeant),
wct_difficulty("Sergeant", 7, 3, 2, 7, true, 5),
},
t_option {
image=icon_human_difficult("human-loyalists/lieutenant", "brown"),
label=str_dif_lvl(strings_mainline.Lieutenant),
wct_difficulty("Lieutenant", 8, 4, 2, 5, true, 10),
},
t_option {
image=icon_human_difficult("human-loyalists/general", "orange"),
label=str_dif_lvl(strings_mainline.General),
wct_difficulty("General", 8, 5, 2, 2, false, 13),
},
t_option {
image=icon_human_difficult("human-loyalists/marshal", "white"),
label=str_dif_lvl(strings_mainline.Grand_Marshal),
wct_difficulty("Grand_marshal", 9, 6, 2, 1, false, 17),
},
t_option {
image=icon_nightmare_difficulty,
label=str_dif_lvl("Nightmare"),
description="(" .. _"Expert" .. ")",
wct_difficulty("Nightmare", 9, 7, 1, 0, false, 20),
},
}
end
function wct_scenario_start_bonus()
for side_num = 1, wml.variables.wc2_player_count do
wesnoth.wml_actions.wc2_start_units {
side = side_num
}
end
if wml.variables.wc2_difficulty.extra_trainig then
for side_num = 1, wml.variables.wc2_player_count do
wesnoth.wml_actions.wc2_give_random_training {
among="2,3,4,5,6",
side = side_num,
}
end
end
end
function wesnoth.wml_actions.wc2_choose_difficulty(cfg)
if wml.variables["wc2_difficulty"] then
return
end
wct_scenario_chose_difficulty()
wct_scenario_start_bonus()
wesnoth.fire_event("wc2_start")
end

View file

@ -0,0 +1,299 @@
local on_event = wesnoth.require("on_event")
local helper = wesnoth.require("helper")
local enemy = {}
local function get_advanced_units(level, list, res)
res = res or {}
-- guards against units that can advance in circles or to themselves
res_set = {}
local add_units = function(units)
for unused, typename in ipairs(units) do
local unittype = wesnoth.unit_types[typename]
if unittype.level == level then
table.insert(res, typename)
elseif not res_set[typename] then
res_set[typename] = true;
add_units(unittype.advances_to)
end
end
end
add_units(list)
return res
end
function enemy.pick_suitable_enemy_item(unit)
local enemy_items = wc2_utils.split_to_array(wml.variables["wc2_enemy_army.artifacts"])
if #enemy_items == 0 then
enemy_items = wc2_artifacts.fresh_artifacts_list("enemy")
end
-- list of indexes to enemy_items
local possible_artifacts = {}
for i, v in ipairs(enemy_items) do
local filter = wml.get_child(wc2_artifacts.get_artifact(tonumber(v)), "filter")
if not filter or unit:matches(filter) then
table.insert(possible_artifacts, i)
end
end
if #possible_artifacts == 0 then
return
end
local i = possible_artifacts[wesnoth.random(#possible_artifacts)]
local artifact_id = tonumber(enemy_items[i])
table.remove(enemy_items, i)
wml.variables["wc2_enemy_army.artifacts"] = table.concat(enemy_items, ",")
return artifact_id
end
-- todo the old code used prerecruit to allow artifact events written into unit become active in recruit, why?
on_event("recruit", function(ec)
if wesnoth.current.turn < 2 then
--the old code also didn't gave items on first turn.
return
end
local side_variables = wesnoth.sides[wesnoth.current.side].variables
local needs_item = side_variables["wc2.random_items"] or 0
local scenario_num = wc2_scenario.scenario_num()
if needs_item == 0 then
return
end
side_variables["wc2.random_items"] = needs_item - 1
local unit = wesnoth.get_unit(ec.x1, ec.y1)
local item_id = enemy.pick_suitable_enemy_item(unit)
wc2_artifacts.give_item(unit, item_id, false)
if true then
unit.experience = unit.experience + scenario_num * (16 + wml.variables["wc2_difficulty.enemy_power"])
unit:advance(true, true)
end
wesnoth.allow_undo(false)
end)
--Gives the enemy side @cfg.side a commander (a hero unit)
function enemy.do_commander(cfg, group_id, loc)
if not cfg.commander or cfg.commander <= 0 then
return
end
local scenario = wc2_scenario.scenario_num()
--wesnoth.message("do_commander", wml.variables[("wc2_enemy_army.group[%d].allies_available"):format(group_id)])
local ally_i = wc2_utils.pick_random(("wc2_enemy_army.group[%d].allies_available"):format(group_id)) - 1
local leader_index = wesnoth.random(wml.variables[("wc2_enemy_army.group[%d].leader.length"):format(ally_i)]) - 1
local new_recruits = wml.variables[("wc2_enemy_army.group[%d].leader[%d].recruit"):format(ally_i, leader_index)]
wesnoth.wml_actions.allow_recruit {
side = cfg.side,
type = new_recruits
}
local commander_options = wml.variables[("wc2_enemy_army.group[%d].commander.level%d"):format(ally_i, cfg.commander)]
wesnoth.wml_actions.unit {
x = loc[1],
y = loc[2],
type = helper.rand(commander_options),
side = cfg.side,
generate_name = true,
role = "commander",
experience = scenario * ((wml.variables["wc2_difficulty.enemy_power"] or 6) - 7 + cfg.commander),
wml.tag.modifications {
wc2_heroes.commander_overlay_object(),
wml.tag.trait(wc2_heroes.trait_heroic),
},
}
end
-- WORLD_CONQUEST_TEK_ENEMY_SUPPLY
function enemy.do_supply(cfg, group_id, loc)
if not (cfg.supply == 1) then
return
end
local u = wesnoth.get_unit(loc[1], loc[2])
u:add_modification("trait", wc2_heroes.trait_expert)
wesnoth.wml_actions.event {
name = "side " .. cfg.side .. " turn 2",
wml.tag.wc2_map_supply_village {
x = u.x,
y = u.y,
}
}
end
-- WORLD_CONQUEST_TEK_ENEMY_RECALLS
on_event("recruit", function(ec)
local side_num = wesnoth.current.side
local side_variables = wesnoth.sides[side_num].variables
local to_recall = wc2_utils.split_to_array(side_variables["wc2.to_recall"] or "")
if #to_recall == 0 then
return
end
local candidates = wesnoth.get_locations {
terrain = "K*,C*,*^C*,*^K*",
wml.tag["and"] {
wml.tag.filter {
canrecruit = true,
side = side_num,
wml.tag.filter_location {
terrain = "K*^*,*^K*",
},
},
radius = 999,
wml.tag.filter_radius {
terrain = "K*^*,C*^*,*^K*,*^C*",
},
},
wml.tag["not"] {
wml.tag.filter {}
}
}
helper.shuffle(candidates)
while #candidates > 0 and #to_recall > 0 do
enemy.fake_recall(side_num, to_recall[1], candidates[1])
table.remove(to_recall, 1)
table.remove(candidates, 1)
end
side_variables["wc2.to_recall"] = table.concat(to_recall, ",")
end)
--Gives the enemy side @cfg.side units that it can recall.
--It does not really addthem to the recall list but
--emulates that by placing higher level units on the map in that sides
function enemy.do_recall(cfg, group_id, loc)
local side_num = cfg.side
local side_variables = wesnoth.sides[side_num].variables
local group = wml.variables[("wc2_enemy_army.group[%d]"):format(group_id)]
local to_recall = wc2_utils.split_to_array(side_variables["wc2.to_recall"])
local function recall_level(level)
local amount = wml.get_child(cfg, "recall")["level" .. level] or 0
local types = wc2_utils.split_to_array(wml.get_child(group, "recall")["level" .. level] or "")
if #types == 0 then
get_advanced_units(level, wc2_utils.split_to_array(group.recruit), types)
end
for i = 1, amount do
table.insert(to_recall, types[wesnoth.random(#types)])
end
end
recall_level(2)
recall_level(3)
side_variables["wc2.to_recall"] = table.concat(to_recall, ",")
end
-- WCT_ENEMY_FAKE_RECALL
function enemy.fake_recall(side_num, t, loc)
local side = wesnoth.sides[side_num]
local u = wesnoth.create_unit {
side = side_num,
type = t,
generate_name = true,
moves = 0,
}
wc2_training.apply(u)
u:to_map(loc)
side.gold = side.gold - 20
end
-- WORLD_CONQUEST_TEK_ENEMY_TRAINING
function enemy.do_training(cfg, group_id, loc)
local tr = cfg.trained or 0
local dif = wml.variables["wc2_difficulty.enemy_trained"] or 0
if tr ~= 0 and dif >= tr then
--enemy can only get Melee, Ranger, Health or Movement
wesnoth.wml_actions.wc2_give_random_training {
side = cfg.side,
among="2,3,4,6"
}
end
end
function enemy.do_gold(cfg, side)
--difficulty_enemy_power is in [6,9]
local enemy_power = (wml.variables["wc2_difficulty.enemy_power"] or 6)
local factor = (cfg.nplayers + 1 ) * enemy_power/6 - 2
side.gold = side.gold + cfg.bonus_gold * factor
end
function enemy.init_data()
if wml.variables.wc2_enemy_army == nil then
-- give eras an option to overwrite the enemy data.
wesnoth.fire_event("wc2_init_enemy")
end
if wml.variables.wc2_enemy_army == nil then
-- give eras an option to overwrite the enemy data.
local enemy_army = wesnoth.dofile("./enemy_data.lua")
wml.variables.wc2_enemy_army = wc2_convert.lon_to_wml(enemy_army, "wct_enemy")
end
end
--[[
called like
[wc2_enemy]
side={SIDE}
##the level of the commander.
commander={COM}
have_item={ITEM}
trained={TRAIN}
supply={SUP}
[recall]
level2={L2}
level3={L3}
[/recall]
[/wc2_enemy]
--]]
function wesnoth.wml_actions.wc2_enemy(cfg)
enemy.init_data()
local side_num = cfg.side
local side = wesnoth.sides[side_num]
local scenario = wc2_scenario.scenario_num()
enemy.do_gold(cfg, side)
local dummy_unit = wesnoth.get_units({side = side_num, canrecruit = true})[1]
local loc = {dummy_unit.x,dummy_unit.y}
dummy_unit:erase()
local enemy_type_id = wc2_utils.pick_random("wc2_enemy_army.factions_available") - 1
if enemy_type_id == nil then
--should't happen, added for robustness.
local n_groups = wml.variables["wc2_enemy_army.group.length"]
if n_groups > 0 then
enemy_type_id = wesnoth.random(n_groups) - 1
else
error("no enemy groups defined")
end
end
local leader_cfg = wc2_utils.pick_random_t(("wc2_enemy_army.group[%d].leader"):format(enemy_type_id))
local unit = wesnoth.create_unit {
x = loc[1],
y = loc[2],
type = scenario == 1 and leader_cfg.level2 or leader_cfg.level3,
side = side_num,
canrecruit = true,
generate_name = true,
max_moves = 0,
wml.tag.modifications { wml.tag.trait(wc2_heroes.trait_heroic) },
}
if unit.name == "" then
-- give names to undead
unit.name = wc2_random_names.generate()
end
unit:to_map()
wesnoth.wml_actions.set_recruit {
side = side_num,
recruit = wml.variables[("wc2_enemy_army.group[%d].recruit"):format(enemy_type_id)]
}
wesnoth.wml_actions.allow_recruit {
side = side_num,
type = leader_cfg.recruit
}
enemy.do_training(cfg, enemy_type_id, loc)
enemy.do_commander(cfg, enemy_type_id, loc)
enemy.do_supply(cfg, enemy_type_id, loc)
enemy.do_recall(cfg, enemy_type_id, loc)
-- todo: remove or uncomment (i think this was moved to scenario generation)
-- side.gold = side.gold + wml.variables["enemy_army.bonus_gold"]
if cfg.have_item > 0 and cfg.have_item <= (wml.variables["wc2_difficulty.enemy_power"] or 6) then
side.variables["wc2.random_items"] = 1
end
end
return enemy

View file

@ -0,0 +1,322 @@
-- The rules for enemy recruitlist are as follows:
-- each side Has a 'faction' (here: group) a leader from that faction and maybe a leader from another faction.
-- the enemy side can then recruit all units from its faction and from all it's leaders, that why having
-- unit {recruit= that are already contained in {recruit= is not redundant.
local enemy_army = {}
enemy_army.group = {
{
id = "northerners",
recruit = {"Orcish Grunt","Orcish Archer","Wolf Rider","Orcish Assassin","Troll Whelp"},
recall = {
level2 = {"Orcish Ruler","Orcish Slayer","Orcish Crossbowman","Troll Rocklobber","Troll","Orcish Warrior","Goblin Pillager","Goblin Knight","Orcish Crossbowman","Troll","Orcish Warrior","Troll Hero"},
level3 = {"Orcish Warlord","Troll Warrior","Orcish Slurbow","Orcish Sovereign","Direwolf Rider","Orcish Warlord","Troll Warrior","Orcish Slurbow","Great Troll","Direwolf Rider"},
},
commander = {
level1 = {"Orcish Leader","Orcish Grunt","Orcish Archer","Orcish Assassin"},
level2 = {"Orcish Ruler","Troll Hero","Orcish Slayer","Orcish Crossbowman","Troll Rocklobber","Troll","Orcish Warrior"},
level3 = {"Orcish Warlord","Troll Warrior","Orcish Slurbow","Orcish Sovereign","Great Troll"},
},
leader = {
{
level2 = "Orcish Warrior",
level3 = "Orcish Warlord",
recruit = {"Orcish Grunt","Orcish Archer","Wolf Rider","Orcish Assassin"},
},
{
level2 = "Troll",
level3 = "Troll Warrior",
recruit = {"Orcish Grunt","Orcish Archer","Orcish Assassin","Troll Whelp"},
},
{
level2 = "Troll Rocklobber",
level3 = "Great Troll",
recruit = {"Orcish Grunt","Orcish Assassin","Wolf Rider","Troll Whelp"},
},
{
level2 = "Orcish Crossbowman",
level3 = "Orcish Slurbow",
recruit = {"Orcish Grunt","Orcish Archer","Wolf Rider","Orcish Assassin"},
},
{
level2 = "Orcish Slayer",
level3 = "Naga Myrmidon",
recruit = {"Orcish Grunt","Orcish Archer","Wolf Rider","Orcish Assassin","Naga Fighter"},
},
{
level2 = "Goblin Knight",
level3 = "Direwolf Rider",
recruit = {"Goblin Spearman","Orcish Leader","Wolf Rider","Orcish Archer","Troll Whelp"},
},
{
level2 = "Orcish Ruler",
level3 = "Orcish Sovereign",
recruit = {"Orcish Grunt","Orcish Leader","Wolf Rider","Orcish Archer"},
},
}
},
{
id = "loyalists",
recruit = {"Spearman","Bowman","Cavalryman","Fencer","Mage"},
recall = {
level2 = {"White Mage","Red Mage","Duelist","Longbowman","Shock Trooper","Pikeman","Swordsman","Lieutenant","Dragoon","Knight","Javelineer","Pikeman","Swordsman","Longbowman"},
level3 = {"General","Halberdier","Royal Guard","Silver Mage","Iron Mauler","Master Bowman","Master at Arms","Arch Mage","Mage of Light","Paladin","Grand Knight","Cavalier","General","Halberdier","Royal Guard","Iron Mauler","Master Bowman","Master at Arms"},
},
commander = {
level1 = {"Sergeant","Spearman","Bowman","Mage","Fencer","Heavy Infantryman"},
level2 = {"White Mage","Red Mage","Duelist","Longbowman","Shock Trooper","Pikeman","Swordsman","Lieutenant","Javelineer"},
level3 = {"General","Halberdier","Royal Guard","Silver Mage","Iron Mauler","Master Bowman","Master at Arms","Arch Mage","Mage of Light"},
},
leader = {
{
level2 = "Lieutenant",
level3 = "General",
recruit = {"Spearman","Bowman","Cavalryman","Fencer","Mage"},
},
{
level2 = "Swordsman",
level3 = "Royal Guard",
recruit = {"Spearman","Bowman","Cavalryman","Heavy Infantryman","Mage"},
},
{
level2 = "Pikeman",
level3 = "Halberdier",
recruit = {"Spearman","Bowman","Cavalryman","Horseman","Mage"},
},
{
level2 = "Javelineer",
level3 = "Silver Mage",
recruit = {"Spearman","Bowman","Horseman","Fencer","Mage"},
},
{
level2 = "Shock Trooper",
level3 = "Iron Mauler",
recruit = {"Spearman","Mage","Cavalryman","Heavy Infantryman"},
},
{
level2 = "Longbowman",
level3 = "Master Bowman",
recruit = {"Spearman","Bowman","Cavalryman","Horseman","Heavy Infantryman"},
},
{
level2 = "Duelist",
level3 = "Master at Arms",
recruit = {"Spearman","Bowman","Cavalryman","Fencer","Mage"},
},
{
level2 = "Red Mage",
level3 = "Arch Mage",
recruit = {"Spearman","Bowman","Mage","Cavalryman","Heavy Infantryman"},
},
{
level2 = "White Mage",
level3 = "Mage of Light",
recruit = {"Spearman","Heavy Infantryman","Cavalryman","Mage","Bowman"},
},
}
},
{
id = "elves",
recruit = {"Elvish Fighter","Elvish Archer","Elvish Shaman","Elvish Scout","Wose"},
recall = {
level2 = {"Elder Wose","Elvish Sorceress","Elvish Druid","Elvish Marksman","Elvish Ranger","Elvish Hero","Elvish Captain","Elvish Rider","Elder Wose","Elvish Hero","Elder Wose","Elvish Sorceress","Red Mage","Elvish Marksman","Elvish Ranger","Elvish Hero","Elvish Captain","Elvish Rider","Elvish Ranger","Elvish Hero"},
level3 = {"Elvish Marshal","Elvish Champion","Elvish Avenger","Elvish Sharpshooter","Elvish Shyde","Elvish Enchantress","Ancient Wose","Elvish Outrider","Ancient Wose","Elvish Champion","Elvish Marshal","Elvish Champion","Elvish Avenger","Elvish Sharpshooter","Arch Mage","Elvish Enchantress","Ancient Wose","Elvish Outrider","Elvish Avenger","Elvish Champion"},
},
commander = {
level1 = {"Elvish Shaman","Elvish Fighter","Elvish Archer","Wose"},
level2 = {"Elder Wose","Elvish Sorceress","Elvish Druid","Elvish Marksman","Elvish Ranger","Elvish Hero","Elvish Captain","Elvish Lord"},
level3 = {"Elvish Marshal","Elvish Champion","Elvish Avenger","Elvish Sharpshooter","Elvish Shyde","Elvish Enchantress","Ancient Wose","Arch Mage","Elvish High Lord"},
},
leader = {
{
level2 = "Elvish Captain",
level3 = "Elvish Marshal",
recruit = {"Elvish Fighter","Elvish Archer","Elvish Shaman","Elvish Scout"},
},
{
level2 = "Elvish Hero",
level3 = "Elvish Champion",
recruit = {"Elvish Fighter","Elvish Archer","Elvish Shaman","Elvish Scout"},
},
{
level2 = "Elvish Ranger",
level3 = "Elvish Avenger",
recruit = {"Elvish Fighter","Elvish Archer","Wose","Elvish Scout"},
},
{
level2 = "Elvish Marksman",
level3 = "Elvish Sharpshooter",
recruit = {"Elvish Fighter","Elvish Archer","Mage","Elvish Scout"},
},
{
level2 = "Elvish Druid",
level3 = "Elvish Shyde",
recruit = {"Elvish Fighter","Elvish Archer","Elvish Shaman","Wose"},
},
{
level2 = "Elvish Sorceress",
level3 = "Elvish Enchantress",
recruit = {"Elvish Fighter","Elvish Archer","Elvish Shaman","Elvish Scout","Mage"},
},
{
level2 = "Elder Wose",
level3 = "Ancient Wose",
recruit = {"Elvish Shaman","Elvish Fighter","Mage"," Wose"},
},
}
},
{
id = "knalgans",
recruit = {"Dwarvish Fighter","Dwarvish Thunderer","Thief","Footpad","Poacher"},
recall = {
level2 = {"Dwarvish Stalwart","Dwarvish Thunderguard","Dwarvish Steelclad","Rogue","Trapper","Gryphon Master","Bandit","Outlaw","Dwarvish Stalwart","Dwarvish Thunderguard","Dwarvish Steelclad","Dwarvish Berserker"},
level3 = {"Dwarvish Lord","Dwarvish Dragonguard","Dwarvish Sentinel","Assassin","Huntsman","Fugitive","Highwayman","Dwarvish Lord","Dwarvish Dragonguard","Dwarvish Sentinel"},
},
commander = {
level1 = {"Dwarvish Thunderer","Dwarvish Fighter","Dwarvish Guardsman","Dwarvish Scout","Thief","Poacher"},
level2 = {"Dwarvish Stalwart","Dwarvish Thunderguard","Dwarvish Steelclad","Dwarvish Pathfinder","Rogue","Trapper"},
level3 = {"Dwarvish Lord","Dwarvish Dragonguard","Dwarvish Sentinel","Assassin","Huntsman","Highwayman","Dwarvish Explorer"},
},
leader = {
{
level2 = "Dwarvish Steelclad",
level3 = "Dwarvish Lord",
recruit = {"Dwarvish Fighter","Dwarvish Thunderer","Dwarvish Ulfserker","Dwarvish Guardsman"},
},
{
level2 = "Dwarvish Thunderguard",
level3 = "Dwarvish Dragonguard",
recruit = {"Dwarvish Fighter","Dwarvish Thunderer","Gryphon Rider","Poacher"},
},
{
level2 = "Dwarvish Stalwart",
level3 = "Dwarvish Sentinel",
recruit = {"Footpad","Dwarvish Thunderer","Gryphon Rider","Dwarvish Guardsman"},
},
{
level2 = "Rogue",
level3 = "Assassin",
recruit = {"Thug","Thief","Footpad","Dwarvish Ulfserker","Gryphon Rider"},
},
{
level2 = "Trapper",
level3 = "Huntsman",
recruit = {"Thug","Thief","Poacher","Dwarvish Fighter","Dwarvish Thunderer"},
},
{
level2 = "Bandit",
level3 = "Highwayman",
recruit = {"Thug","Thief","Dwarvish Thunderer","Dwarvish Ulfserker","Dwarvish Fighter"},
},
}
},
{
id = "drakes",
recruit = {"Drake Fighter","Drake Clasher","Drake Glider","Drake Burner","Saurian Augur"},
recall = {
level2 = {"Drake Arbiter","Drake Thrasher","Drake Warrior","Fire Drake","Drake Flare","Saurian Oracle","Saurian Soothsayer","Saurian Ambusher","Drake Warrior","Drake Thrasher","Sky Drake"},
level3 = {"Drake Flameheart","Inferno Drake","Drake Blademaster","Drake Blademaster","Drake Enforcer","Drake Warden","Saurian Flanker","Saurian Flanker","Hurricane Drake"},
},
commander = {
level1 = {"Drake Burner","Drake Fighter","Drake Clasher","Saurian Augur","Saurian Skirmisher"},
level2 = {"Drake Arbiter","Drake Thrasher","Drake Warrior","Fire Drake","Drake Flare","Saurian Ambusher","Saurian Oracle"},
level3 = {"Drake Flameheart","Inferno Drake","Drake Blademaster","Drake Enforcer","Drake Warden","Saurian Flanker"},
},
leader = {
{
level2 = "Drake Flare",
level3 = "Drake Flameheart",
recruit = {"Drake Fighter","Drake Clasher","Drake Glider","Drake Burner"},
},
{
level2 = "Fire Drake",
level3 = "Inferno Drake",
recruit = {"Drake Fighter","Saurian Augur","Drake Glider","Drake Burner"},
},
{
level2 = "Drake Warrior",
level3 = "Drake Blademaster",
recruit = {"Drake Fighter","Saurian Skirmisher","Drake Glider","Drake Burner"},
},
{
level2 = "Drake Thrasher",
level3 = "Drake Enforcer",
recruit = {"Drake Fighter","Drake Clasher","Saurian Skirmisher","Drake Burner"},
},
{
level2 = "Drake Arbiter",
level3 = "Drake Warden",
recruit = {"Saurian Skirmisher","Drake Clasher","Drake Glider","Drake Burner"},
},
{
level2 = "Saurian Oracle",
level3 = "Saurian Flanker",
recruit = {"Saurian Skirmisher","Saurian Augur","Drake Clasher","Drake Burner"},
},
{
level2 = "Saurian Soothsayer",
level3 = "Hurricane Drake",
recruit = {"Saurian Skirmisher","Saurian Augur","Drake Glider","Drake Fighter"},
},
}
},
{
id = "undead",
recruit = {"Skeleton","Skeleton Archer","Ghost","Ghoul","Dark Adept"},
recall = {
level2 = {"Revenant","Deathblade","Bone Shooter","Dark Sorcerer","Necrophage","Wraith","Shadow","Revenant","Bone Shooter","Dark Sorcerer","Necrophage","Chocobone"},
level3 = {"Draug","Death Knight","Necromancer","Lich","Ghast","Banebow","Spectre","Nightgaunt","Draug","Ghast","Banebow"},
},
commander = {
level1 = {"Dark Adept","Skeleton Archer","Skeleton","Ghoul"},
level2 = {"Revenant","Deathblade","Bone Shooter","Dark Sorcerer","Necrophage"},
level3 = {"Draug","Death Knight","Necromancer","Lich","Ghast","Banebow"},
},
leader = {
{
level2 = "Revenant",
level3 = "Draug",
recruit = {"Skeleton","Skeleton Archer","Ghost","Ghoul"},
},
{
level2 = "Deathblade",
level3 = "Death Knight",
recruit = {"Skeleton","Skeleton Archer","Dark Adept","Ghoul"},
},
{
level2 = "Bone Shooter",
level3 = "Banebow",
recruit = {"Skeleton","Skeleton Archer","Ghost","Ghoul"},
},
{
level2 = "Dark Sorcerer",
level3 = "Lich",
recruit = {"Skeleton Archer","Dark Adept","Ghoul","Vampire Bat"},
},
{
level2 = "Necrophage",
level3 = "Ghast",
recruit = {"Skeleton","Dark Adept","Ghoul","Ghost"},
},
}
},
}
enemy_army.factions_available = {}
-- each faction can be picked up to 4 times along campaign
for i = 1, #enemy_army.group do
for j = 1, 4 do
table.insert(enemy_army.factions_available, i)
end
end
-- each faction pick any faction as ally just 1 time
for i = 1, #enemy_army.group do
local ally = {}
enemy_army.group[i].allies_available = ally
for j = 1, #enemy_army.group do
if j ~= i then
table.insert(ally, j)
end
end
end
return enemy_army

View file

@ -0,0 +1,98 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local on_event = wesnoth.require("on_event")
local strings = {
enemy_pet = _ "$name|'s pet"
}
-- in the later scenarios there is a small chance that a scenario will be themed for an enemy
-- which means in paticular changing the castle of the enemy accorign to the unit type of that
-- enemy, and giving him an extra unit.
local function wct_map_enemy_themed(race, pet, castle, village, chance)
if wesnoth.random(100) > chance then
return
end
local boss = wesnoth.get_units {
side="4,5,6,7,8,9",
canrecruit=true,
race=race,
-- human means only outlaw
wml.tag["not"] {
race="human",
wml.tag["not"] {
wml.tag.filter_wml {
alignment="chaotic",
}
}
}
}
boss = boss[1]
if boss == nil then
return
end
--give themed castle
wesnoth.set_terrain(boss.loc, "K" .. castle, "base")
wesnoth.wml_actions.terrain {
terrain="C" .. castle,
wml.tag["and"] {
terrain = "C*,*^C*",
wml.tag["and"] {
wml.tag.filter {
x=boss.x,
y=boss.y,
},
radius=999,
wml.tag.filter_radius {
terrain="K*^*,C*^*,*^K*,*^C*"
},
},
},
}
local elvish_castle = wesnoth.get_locations {
terrain="Cv",
wml.tag.filter_adjacent_location {
terrain="Kv^*"
}
}
-- extra tweak with trees to elvish castle
for i, tile in ipairs(elvish_castle) do
if wesnoth.random(10) <= 4 then
wesnoth.set_terrain(tile, "Cv^Fet")
end
end
-- adjacent themed villages
wesnoth.wml_actions.terrain {
terrain=village,
wml.tag["and"] {
terrain="*^V*",
wml.tag.filter_adjacent_location {
terrain="C" .. castle .. ",K" .. castle .. "^*",
},
},
}
-- give pet
wesnoth.wml_actions.unit {
x = boss.x,
y = boss.y,
type=pet,
side = boss.side,
name= wesnoth.format(enemy_pet, { name = boss.name }),
role = "hero",
overlays = "misc/hero-icon.png",
wml.tag.modifications {
wc2_heroes.trait_heroic,
wc2_heroes.trait_expert,
wml.tag.object {
id = "wc2_hero_overlay",
wml.tag.effect {
apply_to="overlay",
add = "misc/hero-icon.png",
}
}
}
}
end
function wesnoth.wml_actions.wc2_enemy_themed(cfg)
wct_map_enemy_themed(cfg.race, cfg.pet, cfg.castle, cfg.village, cfg.chance)
end

View file

@ -0,0 +1,35 @@
--creates the objectives of the wc2 scenarios.
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local strings = {
wct_victory_condition = _"Defeat all enemy leaders and commanders",
turns = _"Turns run out",
wct_defeat_condition = _ "Lose your leader and all your commanders",
difficulty = "Difficulty: ",
version = "Version",
help_available = _ "An in-game help is available: rightclick on any empty hex.",
}
function wesnoth.wml_actions.wc2_objectives(cfg)
wesnoth.wml_actions.objectives {
wml.tag.objective {
description = strings.wct_victory_condition,
condition = "win",
},
wml.tag.objective {
description = strings.turns,
condition = "lose",
},
wml.tag.objective {
description = strings.wct_defeat_condition,
condition = "lose",
},
wml.tag.note {
description = strings.difficulty .. wml.variables["wc2_difficulty.name"],
},
wml.tag.note {
description = strings.version .. wml.variables["wc2_host_version"],
},
note = wc2_color.help_text(strings.help_available)
}
end

View file

@ -0,0 +1,103 @@
--<<
local wc2_scenario = {}
local on_event = wesnoth.require("on_event")
function wc2_scenario.is_human_side(side_num)
return side_num == 1 or side_num == 2 or side_num == 3
end
function wc2_scenario.scenario_num()
return wml.variables["wc2_scenario"] or 1
end
function wc2_scenario.experience_penalty()
return wml.tag.effect {
apply_to = "max_experience",
increase = wml.variables["wc2_difficulty.experience_penalty"] .. "%",
}
end
-- happens before training events.
on_event("recruit", 1, function(ec)
local u = wesnoth.get_unit(ec.x1, ec.y1)
if (not u) or (not wc2_scenario.is_human_side(u.side)) then
return
end
u:add_modification("advancement", { wc2_scenario.experience_penalty() })
end)
function wesnoth.wml_actions.wc2_start_units(cfg)
local u = wesnoth.get_units({ side = cfg.side, canrecruit = true })[1]
if not u then error("[wc2_start_units] no leader found") end
u:add_modification("advancement", { wc2_scenario.experience_penalty() })
u:add_modification("trait", wc2_heroes.trait_heroic )
u.hitpoints = u.max_hitpoints
u.moves = u.max_moves
for i = 1, wml.variables["wc2_difficulty.heroes"] do
wesnoth.wml_actions.wc2_random_hero {
x = u.x,
y = u.y,
side = u.side,
}
end
end
function wesnoth.wml_actions.wc2_store_carryover(cfg)
local human_sides = wesnoth.get_sides(wml.get_child(cfg, "sides"))
--use an the average amount of villages for this scenario to stay independent of map generator results.
local nvillages = cfg.nvillages
local turns_left = math.max(wesnoth.game_config.last_turn - wesnoth.current.turn, 0)
local player_gold = 0
for side_num, side in ipairs(human_sides) do
player_gold = player_gold + side.gold
end
local player_gold = math.max(player_gold / #human_sides, 0)
wml.variables.wc2_carryover = math.ceil( (nvillages*turns_left + player_gold) * 0.15)
end
-- carryover handling: we use a custom carryover machnics that
-- splits the carryover gold evenly to all players
on_event("prestart", function(cx)
wesnoth.fire_event("wc2_start")
end)
-- we need to do this also after difficulöty selection.
-- NOTE: this is a bit fragile, in particualr it breaks if difficulty_selection happens before the prestart event above.
on_event("wc2_start", function(cx)
local gold = (wml.variables.wc2_carryover or 0) + (wml.variables["wc2_difficulty.extra_gold"] or 0)
for i = 1, wml.variables.wc2_player_count do
wesnoth.sides[i].gold = wesnoth.sides[i].gold + gold
end
wml.variables.wc2_carryover = nil
end)
-- our victory condition
on_event("enemies defeated", function(cx)
if wml.variables.wc2_scenario > 5 then
return
end
wesnoth.play_sound("ambient/ship.ogg")
wesnoth.wml_actions.endlevel {
result = "victory",
carryover_percentage = 0,
carryover_add = false,
carryover_report = false,
}
end)
on_event("victory", function(cx)
if wml.variables.wc2_scenario > 5 then
return
end
wesnoth.wml_actions.wc2_set_recall_cost { }
--{CLEAR_VARIABLE bonus.theme,bonus.point,items}
wml.variables.wc2_scenario = (wml.variables.wc2_scenario or 1) + 1
end)
on_event("start", function(cx)
wesnoth.wml_actions.wc2_objectives({})
end)
return wc2_scenario
-->>

View file

@ -0,0 +1,29 @@
-- the main file for the WC2 mp campaign
T = wml.tag
on_event = wesnoth.require("on_event")
wesnoth.dofile("./game_mechanics/_load.lua")
wc2_era = wesnoth.require("./era/era.lua")
wc2_enemy = wesnoth.dofile("./campaign/enemy.lua")
wc2_scenario = wesnoth.dofile("./campaign/scenario.lua")
wesnoth.dofile("./campaign/autorecall.lua")
wesnoth.dofile("./campaign/objectives.lua")
wesnoth.dofile("./campaign/enemy_themed.lua")
wc2_difficulty = wesnoth.require("./campaign/difficulty.lua")
on_event("prestart", function(cx)
wesnoth.wml_actions.wc2_fix_colors {
wml.tag.player_sides {
side="1,2,3",
wml.tag.has_unit {
canrecruit = true,
}
}
}
end)

View file

@ -0,0 +1,371 @@
local helper = wesnoth.require("helper")
local on_event = wesnoth.require("on_event")
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local wc2_era = {}
wc2_era.factions_wml = {}
wc2_era.standard_factions = {}
wc2_era.hero_types = {}
wc2_era.hero_traits = {}
wc2_era.spawn_filters = {}
local strings = {
info_menu = _"Tell me how my recruit works",
info_recruit = _"Every time you recruit a unit, it is replaced in your recruit list by its pair. The following pairs can also be found here:",
}
local images = {
menu_recruit_info = "icons/action/editor-tool-unit_25.png~CROP(3,4,18,18)~GS()"
}
-- the wc2 recruit pair logic.
on_event("recruit", function(ctx)
local unit = wesnoth.get_unit(ctx.x1, ctx.y1)
local side_num = unit.side
local side = wesnoth.sides[side_num]
local unittype = unit.type
for i,v in ipairs(wml.array_access.get("wc2.pair", side)) do
local p = wc2_utils.split_to_array(v.types)
if p[1] == unittype and p[2] ~= nil then
wesnoth.wml_actions.disallow_recruit {
side = side_num,
type = p[1],
}
wesnoth.wml_actions.allow_recruit {
side = side_num,
type = p[2],
}
p[1],p[2] = p[2],p[1]
side.variables["wc2.pair[" .. (i - 1) .. "].types"] = table.concat(p, ",")
wesnoth.allow_undo(false)
return
end
end
end)
function wc2_era.get_faction(id)
if type(id) == "number" then
local side = wesnoth.sides[id]
id = side.variables["wc2.faction_id"] or side.faction
end
for i, faction in ipairs(wc2_era.factions_wml) do
if faction.id == id then
return faction
end
end
end
local function init_side(side_num)
if wesnoth.get_side_variable(side_num, "wc2.faction_id") ~= nil then
-- don't do this twice.
return
end
local side = wesnoth.sides[side_num]
local faction = wc2_era.get_faction(side_num)
if faction and side.variables["wc2.pair.length"] == 0 and wml.get_child(faction, "pair") then
side.variables["wc2.faction_id"] = faction.id
wesnoth.wml_actions.disallow_recruit { side = side_num, recruit="" }
local i = 0
for v in wml.child_range(faction, "pair") do
i = i + 1
local p = wc2_utils.split_to_array(v.types)
if wesnoth.random(1,2) == 2 then
p[1],p[2] = p[2],p[1]
end
wesnoth.wml_actions.allow_recruit {
side = side_num,
type = p[1],
}
side.variables["wc2.pair[" .. (i - 1) .. "].types"] = table.concat(p, ",")
end
end
if not faction and #wc2_era.factions_wml > 0 then
faction = wc2_era.factions_wml[wesnoth.random(#wc2_era.factions_wml)]
end
if not faction then
faction = wc2_era.create_random_faction()
end
local heroes = wc2_era.expand_hero_types(faction.heroes)
local deserters = wc2_era.expand_hero_types(faction.deserters)
local commanders = wc2_era.expand_hero_types(faction.commanders)
helper.shuffle(heroes)
helper.shuffle(deserters)
helper.shuffle(commanders)
side.variables["wc2.heroes"] = table.concat(heroes, ",")
side.variables["wc2.deserters"] = table.concat(deserters, ",")
side.variables["wc2.commanders"] = table.concat(commanders, ",")
end
local function add_known_faction(cfg)
table.insert(wc2_era.factions_wml, cfg)
end
local function add_known_hero_group(id, cfg)
wc2_era.hero_types[id] = cfg
end
local function add_known_spawn_filter(spawn_filter)
local types = wc2_utils.split_to_set(spawn_filter.types)
local filter_location = wml.get_child(spawn_filter, "filter_location") or helper.wml_error("missing [filter_location] in [hero_spawn_filter]")
table.insert(wc2_era.spawn_filters, { types = types, filter_location = filter_location} )
end
local function add_known_trait_extra(trait_extra)
local types = wc2_utils.split_to_set(trait_extra.types)
local trait = wml.get_child(trait_extra, "trait") or helper.wml_error("missing [trait] in [trait_extra]")
table.insert(wc2_era.hero_traits, { types = types, trait = trait} )
end
-- in case that a [multiplayer_side] has not [world_conquest_data] we generate it randomly.
function wc2_era.create_random_faction(id)
local deserters_set = {}
local heros_set = {}
local commanders_set = {}
local i_deserters1 = wesnoth.random(#wc2_era.standard_factions)
local i_deserters2 = wesnoth.random(#wc2_era.standard_factions)
local i_heroes1 = wesnoth.random(#wc2_era.standard_factions)
local i_heroes2 = wesnoth.random(#wc2_era.standard_factions)
local i_commanders = wesnoth.random(#wc2_era.standard_factions)
wc2_utils.split_to_set(wc2_era.standard_factions[i_deserters1].recruits, deserters_set)
wc2_utils.split_to_set(wc2_era.standard_factions[i_deserters2].recruits, deserters_set)
wc2_utils.split_to_set(wc2_era.standard_factions[i_heroes1].recruits, heros_set)
wc2_utils.split_to_set(wc2_era.standard_factions[i_heroes2].recruits, heros_set)
wc2_utils.split_to_set(wc2_era.standard_factions[i_commanders].recruits, commanders_set)
local faction = {
id = "custom_random",
deserters = table.concat( wc2_utils.set_to_array(deserters_set), ","),
heroes = table.concat( wc2_utils.set_to_array(heros_set), ","),
commanders = table.concat( wc2_utils.set_to_array(commanders_set), ","),
}
return faction
end
function wc2_era.read_era_tag(era_wml)
era_wml = wml.literal(era_wml)
for multiplayer_side in wml.child_range(era_wml, "multiplayer_side") do
if not multiplayer_side.random_faction then
--used for random faction generation.
table.insert(wc2_era.standard_factions, {
id = multiplayer_side.id,
recruits = multiplayer_side.recruit
})
end
local faction = wml.get_child(multiplayer_side, "world_conquest_data")
if faction then
faction.id = multiplayer_side.id
faction.name = multiplayer_side.name
faction.image = multiplayer_side.image
add_known_faction(faction)
end
end
-- No need to read [hero_types] since wc2_utils.get_wc2_data also reads from [era]
end
function wc2_era.init_era_default()
wc2_era.read_era_tag(wesnoth.game_config.era)
wc2_era.init_data()
end
function wc2_era.init_data()
for i,v in ipairs(wml.get_child(wc2_utils.get_wc2_data("hero_types"), "hero_types")) do
add_known_hero_group(v[1], v[2])
end
for trait_extra in wml.child_range(wc2_utils.get_wc2_data("trait_extra"), "trait_extra") do
add_known_trait_extra(trait_extra)
end
for spawn_filter in wml.child_range(wc2_utils.get_wc2_data("hero_spawn_filter"), "hero_spawn_filter") do
add_known_spawn_filter(spawn_filter)
end
end
function wesnoth.wml_actions.wc2_init_era(cfg)
cfg = wml.literal(cfg)
if cfg.clear then
wc2_era.factions_wml = {}
wc2_era.hero_types = {}
wc2_era.hero_traits = {}
wc2_era.spawn_filters = {}
end
wc2_era.wc2_era_id = cfg.wc2_era_id -- TODO removed for testing or error("missing wc2_era_id")
for faction in wml.child_range(cfg, "faction") do
add_known_faction(faction)
end
for i,v in ipairs(wml.get_child(cfg, "hero_types")) do
add_known_hero_group(v[1], v[2])
end
for trait_extra in wml.child_range(cfg, "trait_extra") do
add_known_trait_extra(trait_extra)
end
for spawn_filter in wml.child_range(cfg, "hero_spawn_filter") do
add_known_spawn_filter(spawn_filter)
end
end
-- picks a deserter for the side @a side_num using the list of posibel deserters for that sides faction.
function wc2_era.pick_deserter(side_num)
local side_variables = wesnoth.sides[side_num].variables
local deserters = wc2_utils.split_to_array(side_variables["wc2.deserters"])
if #deserters == 0 then
return nil
end
-- fixme: shouldn't we randomoize this?
local index = #deserters
local res = deserters[index]
table.remove(deserters, index)
side_variables["wc2.deserters"] = table.concat(deserters, ",")
return res
end
-- replaces group ids with the corresponding unit lists.
-- @a types_str a comma seperated list of unti types and group ids.
-- @returns an array of unit types.
function wc2_era.expand_hero_types(types_str)
local types = wc2_utils.split_to_array(types_str)
local types_new = {}
local types_res = {}
while #types > 0 do
for i,v in ipairs(types) do
if wesnoth.unit_types[v] then
table.insert(types_res, v)
elseif wc2_era.hero_types[v] then
local group = wc2_era.hero_types[v]
wc2_utils.split_to_array(group.types, types_new)
else
wesnoth.message("WCII ERROR", "unknown deserter group: '" .. v .. "'")
end
end
types = types_new
types_new = {}
end
wc2_utils.remove_dublicates(types_res)
return types_res
end
-- replaces group ids with the corresponding unit lists.and replaces unit type ids with their names. (used by wocopedia)
-- @a types_str a comma seperated list of unti types and group ids.
-- @returns an array of unit type names.
function wc2_era.expand_hero_names(types_str, only_unitnames)
local types = wc2_utils.split_to_array(types_str)
local types_new = {}
local names_res = {}
while #types > 0 do
for i,v in ipairs(types) do
local ut = wesnoth.unit_types[v]
if ut then
table.insert(names_res, ut.name)
else
local group = wc2_era.hero_types[v]
if group.name and not only_unitnames then
table.insert(names_res, group.name)
else
wc2_utils.split_to_array(group.types, types_new)
end
end
end
types = types_new
types_new = {}
end
return names_res
end
on_event("prestart", function()
for i, s in ipairs(wesnoth.sides) do
init_side(i)
end
end)
-- Generates the list of possible unit types that can be found in bonus points.
function wc2_era.generate_bonus_heroes()
return wc2_era.expand_hero_types("Bonus_All")
end
-- shows the recruit info dialog for the faction of the currently viewing side.
function wesnoth.wml_actions.wc2_recruit_info(cfg)
local side_num = wesnoth.get_viewing_side()
local faction = wc2_era.get_faction(side_num)
if not faction then
wesnoth.wml_actions.message {
scroll = false,
canrecruit = true,
side = side_num,
message = _ "You are not using a WC2 faction.",
}
return
end
local message = {
scroll = false,
canrecruit = true,
side = side_num,
caption = faction.name,
message = cfg.message,
}
for i,v in ipairs(wml.array_access.get("wc2.pair", side_num)) do
local p = wc2_utils.split_to_array(v.types)
local ut1 = wesnoth.unit_types[p[1]]
local ut2 = wesnoth.unit_types[p[2]]
local img = "misc/blank.png~SCALE(144,72)" ..
"~BLIT(" .. wc2_color.tc_image(side_num, ut1.image) .. ")" ..
"~BLIT(" .. wc2_color.tc_image(side_num, ut2.image) .. ",72,0)"
table.insert(message, {"option", {
image = img,
label= ut1.name,
description = ut2.name,
}})
end
wesnoth.wml_actions.message(message)
end
wc2_utils.menu_item {
id="1_WC_II_Era_Info_Recruit_Option",
description=strings.info_menu,
image=images.menu_recruit_info,
synced=false,
filter = function (x, y)
local u wesnoth.get_unit(x, y)
if u and u.side == wesnoth.current.side then
return false
end
if not wc2_era.get_faction(wesnoth.get_viewing_side()) then
return false
end
if wc2_artifacts.is_item_at(x, y) then
return false
end
return true
end,
handler = function(cx)
wesnoth.wml_actions.wc2_recruit_info {
message = strings.info_recruit
}
end
}
wc2_era.init_era_default()
return wc2_era

View file

@ -0,0 +1,4 @@
-- the main file for the WC2 mp era
wc2_utils = wesnoth.require('./game_mechanics/utils.lua')
wc2_era = wesnoth.require('./era/era.lua')

View file

@ -0,0 +1,29 @@
-- Loads the WC2 'engine' that is making bonus points, items, training etc work.
wc2_convert = wesnoth.require("./../shared_utils/wml_converter.lua")
wc2_ability_events = wesnoth.require("./ability_events.lua")
wc2_artifacts = wesnoth.require("./artifacts.lua")
wc2_bonus = wesnoth.require("./bonus.lua")
wc2_color = wesnoth.require("./color.lua")
wc2_dropping = wesnoth.require("./dropping.lua")
wc2_effects = wesnoth.require("./effects.lua")
wc2_heroes = wesnoth.require("./heroes.lua")
wc2_pickup_confirmation_dialog = wesnoth.require("./pickup_confirmation_dialog.lua")
wc2_random_names = wesnoth.require("./random_names.lua")
wc2_recall = wesnoth.require("./recall.lua")
wc2_supply = wesnoth.require("./supply.lua")
wc2_training = wesnoth.require("./training.lua")
wc2_unittypedata = wesnoth.require("./unittypedata.lua")
wc2_utils = wesnoth.require("./utils.lua")
wc2_wiki_dialog = wesnoth.require("./wocopedia/help_dialog.lua")
wc2_wiki = wesnoth.require("./wocopedia/help.lua")
wc2_invest = wesnoth.require("./invest/invest.lua")
wc2_invest_dialog = wesnoth.require("./invest/invest_dialog.lua")
wc2_invest_show_dialog = wesnoth.require("./invest/invest_show_dialog.lua")
wc2_invest_tellunit = wesnoth.require("./invest/invest_tellunit.lua")
wesnoth.require("./promote_commander.lua")

View file

@ -0,0 +1,52 @@
local on_event = wesnoth.require("on_event")
----- the 'full movement on turn recuited' ability implementation -----
-- priority -1 because this event must be happen after the training event.
on_event("recruit,recall", -1, function(ec)
local unit = wesnoth.get_unit(ec.x1, ec.y1)
if not unit then
return
end
local matches = unit.variables["mods.wc2_move_on_recruit"]
if matches then
unit.attacks_left = 1
unit.moves = unit.max_moves
end
end)
----- the 'corruption' ability implementation -----
on_event("turn_refresh", function(event_context)
wesnoth.wml_actions.harm_unit {
wml.tag.filter {
wml.tag.filter_side {
wml.tag.enemy_of {
side = wesnoth.current.side,
},
},
wml.tag.filter_adjacent {
side = wesnoth.current.side,
ability = "wc2_corruption",
},
},
amount = 6,
kill = false,
animate = true,
}
end)
----- the 'disengage' ability implementation -----
on_event("attack_end", function(cx)
local u = wesnoth.get_unit(cx.x1, cx.y1)
if not u then
return
end
if not u:matches { wml.tag.has_attack { special_active = "wc2_disengage"} } then
--IMPORTANT: using 'special_active' like this is only guaranteed to work if
-- the attack has a [filter_self] or a simlar filter tag, otherwise it might
-- also fire when another attack that is not the currently used attack has
-- that special
return
end
u.moves = 1
end)

View file

@ -0,0 +1,247 @@
local on_event = wesnoth.require("on_event")
local helper = wesnoth.require("helper")
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local artifacts = {}
artifacts.list = {}
function artifacts.add_artifact_data(a)
table.insert(artifacts.list, a)
end
function artifacts.read_wml_data(cfg)
for i, artifact in ipairs(wc2_convert.wml_to_lon(wml.literal(cfg), "wct_artifact_list").artifact or {}) do
artifacts.add_artifact_data(artifact)
end
end
function artifacts.init_data()
local cfg = wc2_utils.get_wc2_data("artifact")
for i, a in ipairs(wc2_convert.wml_to_lon(cfg, "wct_artifact_list").artifact or {}) do
artifacts.add_artifact_data(a)
end
end
function artifacts.get_artifact(id)
return artifacts.list[id]
end
function artifacts.get_artifact_list()
return artifacts.list
end
function artifacts.drop_message(index)
local aftifact_data = artifacts.get_artifact(index)
wesnoth.wml_actions.message {
speaker = "narrator",
caption = aftifact_data.name,
message = aftifact_data.info .. "\n" .. wc2_color.bonus_text(aftifact_data.description),
image = aftifact_data.icon,
}
end
function wc2_artifact_needs_compensation(side)
return not wc2_scenario.is_human_side(side.side)
end
-- place an artifact with id @a index on the map at position @a x, y.
-- can be used from the bug console as `lua wc2_artifacts.place_item(30,20,1)`
function artifacts.place_item(x, y, index)
wc2_dropping.add_item(x, y, {
wc2_atrifact_id = index,
image = artifacts.get_artifact(index).icon,
z_order = 20,
})
end
-- give te item with id @a index to unit @a unit, set @a visualize=true, to show the item pickup animation.
function artifacts.give_item(unit, index, visualize)
local aftifact_data = artifacts.get_artifact(index)
if visualize then
-- play visual/sound effects if item have any
wesnoth.wml_actions.sound {
name = aftifact_data.sound or ""
}
if unit.gender == "male" then
wesnoth.wml_actions.sound {
name = aftifact_data.sound_male or ""
}
else
wesnoth.wml_actions.sound {
name = aftifact_data.sound_female or ""
}
end
for i, animate_unit in ipairs(aftifact_data.animate_unit) do
wesnoth.wml_actions.animate_unit(animate_unit)
end
end
local make_holder_loyal = wml.variables["wc2_config_items_make_loyal"] ~= false
-- is_commander or is_hero imples unit.upkeep == "loyal"
-- note that the following `unit.upkeep` does not match normal
-- level 0 (which have still 'full' upkeep) only units with upkeep=0 explicitly set
if make_holder_loyal and (not unit.canrecruit) and (unit.upkeep ~= 0) and (unit.upkeep ~= "loyal") then
unit:add_modification("object", { wml.tag.effect { apply_to = "wc2_overlay", add = "misc/loyal-icon.png" }})
end
local object = {
wc2_atrifact_id = index,
-- cannot filter on wc2_atrifact_id beeing empty so we also need wc2_is_artifact
wc2_is_artifact = true,
}
if make_holder_loyal then
table.insert(object, wml.tag.effect { apply_to= "loyal" })
end
-- IDEA: i _could_ replace the follwing with a 'apply_to=wc2_artifact' effect that
-- basicially applies all effects in the [artifact]s definition. The obvious
-- advantage would be a smaller savefile size. Also this woudl change how savefiles
-- would behve if an artifacts effect has changed, i am currently not sure
-- whether that'd be good or bad
--
-- One of the reasons why i currently won't do this is to make the artifacts list
-- more flixible: the suggested approach requires that artifacts are loaded before
-- units are created which means artifacts must be loaded at toplevel [lua] tags
for i, effect in ipairs(aftifact_data.effect) do
table.insert(object, wml.tag.effect (effect) )
end
unit:add_modification("object", object)
--rebuild unit, to reduce savefile size.
unit:transform(unit.type)
-- the artifact might reduce the max xp.
unit:advance(true, true)
end
-- unit picking up artifacts
on_event("wc2_drop_pickup", function(ec)
local item = wc2_dropping.current_item
local unit = wesnoth.get_unit(ec.x1, ec.y1)
if not item.wc2_atrifact_id then
return
end
if not unit then
return
end
local side_num = unit.side
local is_human = wc2_scenario.is_human_side(side_num)
if not wml.variables["wc2_config_experimental_pickup"] and not is_human then
return
end
local index = item.wc2_atrifact_id
local filter = artifacts.get_artifact(index).filter
if filter and not unit:matches(filter) then
if is_human then
wesnoth.wml_actions.message {
id = unit.id,
message = _"I cannot pick up that item.",
}
end
return
end
if is_human and not wml.variables["wc2_config_disable_pickup_confirm"] then
if not wc2_pickup_confirmation_dialog.promt_synced(unit, artifacts.get_artifact(index).icon) then
return
end
end
wc2_dropping.item_taken = true
artifacts.give_item(unit, index, true)
wesnoth.allow_undo(false)
end)
-- returns a list of artifact ids, suitable for the give type ('enemy' for example).
function artifacts.fresh_artifacts_list(for_type)
local res = {}
for i,v in ipairs(artifacts.get_artifact_list()) do
if not for_type or not wc2_utils.split_to_set(v.not_available or "")[for_type] then
table.insert(res, i)
end
end
return res
end
-- drop all items a dying unit carries.
on_event("die", function(event_context)
local unit = wesnoth.get_unit(event_context.x1, event_context.y1)
if not unit then
return
end
if not wml.variables["wc2_config_experimental_pickup"] and wc2_scenario.is_human_side(unit.side) then
return
end
for object in helper.child_range(wml.get_child(unit.__cfg, "modifications") or {}, "object") do
if object.wc2_atrifact_id then
artifacts.place_item(unit.x, unit.y, object.wc2_atrifact_id)
artifacts.drop_message(object.wc2_atrifact_id)
wesnoth.allow_undo(false)
end
end
-- remove the item from the unit, just in case the unit is somehow brought back to life by another addons code. (for example 'besieged druid' can do such a thing)
unit:remove_modifications { wc2_is_artifact = true }
end)
-- returns true if there is an item in the map at the given position,
-- used to determine whether to show the artifact info menu at that position.
function artifacts.is_item_at(x,y)
for i,item in ipairs(wc2_dropping.get_entries_at_readonly(x,y)) do
if item.wc2_atrifact_id then
return true
end
end
return false
end
-- shows an information [message] about the item laying at position
-- @a cfg.x, cfg.y
function wesnoth.wml_actions.wc2_show_item_info(cfg)
local x = cfg.x
local y = cfg.y
for i,item in ipairs(wc2_dropping.get_entries_at_readonly(x,y)) do
if item.wc2_atrifact_id then
local artifact_info = artifacts.get_artifact(item.wc2_atrifact_id)
wesnoth.wml_actions.message {
scroll = false,
image = artifact_info.icon,
caption = artifact_info.name,
message= artifact_info.info .. "\n" .. wc2_color.help_text(artifact_info.description),
}
end
end
end
wc2_utils.menu_item {
id="4_WCT_Item_Info_Option",
description = _ "Remind me what this item does",
image = "icons/terrain/terrain_type_info.png",
synced = false,
filter = artifacts.is_item_at,
handler = function(cx)
wesnoth.wml_actions.wc2_show_item_info {
x = cx.x1,
y = cx.y1,
}
end
}
function wesnoth.wml_actions.wc2_place_item(cfg)
artifacts.place_item(cfg.x, cfg.y, cfg.item_index)
if cfg.message then
artifacts.drop_message(cfg.item_index)
end
end
artifacts.init_data()
return artifacts

View file

@ -0,0 +1,231 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local on_event = wesnoth.require("on_event")
local helper = wesnoth.require("helper")
local bonus = {}
bonus.sceneries = {}
-- places a bonus point on the map.
function wesnoth.wml_actions.wc2_place_bonus(cfg)
local x = cfg.x or helper.wml_error("[wc2_place_bonus] missing required 'x' attribute")
local y = cfg.y or helper.wml_error("[wc2_place_bonus] missing required 'y' attribute")
local scenery = cfg.scenery or helper.wml_error("[wc2_place_bonus] missing required 'scenery' attribute")
local c_scenery = bonus.sceneries[scenery]
if not c_scenery then
helper.wml_error("[wc2_place_bonus] invalid 'scenery' attribute: ".. tostring(scenery))
end
local image = c_scenery.image or scenery
bonus.place_item(x, y, image)
-- Note: although the numbrs of options passed to helper.rand might depend on the langauge
-- the number of thimes random is called does not (random is called even if there is
-- only one option), so this doesn't cause OOS.
local name1 = wc2_random_names.generate()
local name_options = c_scenery.names or { _"place" }
local name2 = tostring(name_options[wesnoth.random(#name_options)])
local function span_font_family(str, fam)
return string.format("<span font-family='%s'>%s</span>", fam, str)
end
print("placed label", x, y)
wesnoth.wml_actions.label {
x = x,
y = y,
text = span_font_family(wesnoth.format(_ "$name's $type", {name = name1, type = name2}), "Lucida Sans Unicode")
}
end
function bonus.place_item(x, y, image)
if image == "campfire" then
wesnoth.set_terrain(x, y, "*^Ecf", "overlay")
image = nil
else
image = image or "scenery/lighthouse.png"
end
wc2_dropping.add_item(x, y, {
wc2_is_bonus = true,
image = image,
z_order = 10,
})
end
function bonus.remove_current_item(ec)
wc2_dropping.remove_current_item()
--TODO: i don't think its worth to keep this code, to alos allow bonus points to use terrains instead of overlays.
wesnoth.wml_actions.terrain {
x = ec.x1,
y = ec.y1,
wml.tag["and"] {
terrain = "*^Ecf",
},
terrain = "Gs",
layer = "overlay",
}
wesnoth.wml_actions.item {
x = ec.x1,
y = ec.y1,
image = "scenery/rubble.png",
z_order = -10,
}
end
-- check to be overwritten by other mods.
function bonus.can_pickup_bonus(side_num, x, y)
return wc2_scenario.is_human_side(side_num)
end
-- callback to be overwritten by other mods.
function bonus.post_pickup(side_num, x, y)
end
-- event fired by dropping.lua
on_event("wc2_drop_pickup", function(ec)
local item = wc2_dropping.current_item
local side_num = wesnoth.current.side
if not item.wc2_is_bonus then
return
end
if not bonus.can_pickup_bonus(side_num, ec.x1, ec.y1) then
return
end
local bonus_type = item.wc2_type
if bonus_type == nil then
local training_chance = wml.variables.wc2_config_training_chance or 1
local hero_chance = wml.variables.wc2_config_hero_chance or 1
local item_chance = wml.variables.wc2_config_item_chance or 1
local r = wesnoth.random(training_chance + hero_chance + item_chance)
if r <= training_chance then
bonus_type = 1
elseif r <= training_chance + item_chance then
bonus_type = 2
else
bonus_type = 3
end
end
local bonus_subtype = item.wc2_subtype
if bonus_type == 1 then
if not bonus.found_training(wesnoth.current.side, bonus_subtype, ec) then
bonus_type = wesnoth.random(2,3)
bonus_subtype = nil
end
end
if bonus_type == 2 then
bonus_subtype = bonus_subtype or bonus.get_random_item()
bonus.found_artifact(ec, tonumber(bonus_subtype))
elseif bonus_type == 3 then
bonus_subtype = bonus_subtype or bonus.get_random_hero(ec.x1, ec.y1)
bonus.found_hero(ec, bonus_subtype)
end
bonus.post_pickup(side_num, ec.x1, ec.y1)
assert(wc2_dropping.item_taken, "item still there")
end)
function bonus.get_random_item()
return tonumber(wc2_utils.pick_random("wc2.random_items", wc2_artifacts.fresh_artifacts_list))
end
function bonus.get_random_hero(x, y)
return wc2_utils.pick_random_filtered("wc2.random_heroes", wc2_era.generate_bonus_heroes, function(unittypeid)
for _, sf in ipairs(wc2_era.spawn_filters) do
if sf.types[unittypeid] and not wesnoth.match_location(x, y, sf.filter_location) then
return false
end
end
return true
end)
end
function bonus.found_artifact(ec, index)
wesnoth.wml_actions.message {
x = ec.x1,
y = ec.y1,
message = _ "Hey, I found some treasure!",
}
bonus.remove_current_item(ec)
wc2_artifacts.drop_message(index)
--local x2, y2 = wesnoth.find_vacant_tile(ec.x1, ec.y1)
local x2, y2 = ec.x1, ec.y1 + 1
wc2_artifacts.place_item(x2, y2, index)
return true
end
function bonus.found_hero(ec, herotype)
local finder = wesnoth.get_unit(ec.x1, ec.y1)
wesnoth.wml_actions.message {
x = ec.x1,
y = ec.y1,
message = _"Someone is here!",
}
bonus.remove_current_item(ec)
local newunit = wc2_heroes.place(herotype, finder.side, ec.x1, ec.y1)
-- hero found and unit in bonus point face each other
wc2_utils.facing_each_other(finder, newunit)
wc2_heroes.founddialouge(finder, newunit)
wesnoth.wml_actions.redraw {
clear_shroud = true,
side = newunit.side,
}
return true
end
function bonus.found_training(side_num, suggested_subtype, ec)
local traintype, amount
if suggested_subtype then
amount = 1
traintype = wc2_training.trainings_left(side_num, suggested_subtype) >= amount and suggested_subtype or nil
else
traintype, amount = wc2_training.pick_bonus(side_num)
end
if traintype == nil then
return false
end
wesnoth.wml_actions.message {
x = ec.x1,
y = ec.y1,
message = _"Someone is here!",
}
bonus.remove_current_item(ec)
wc2_training.give_bonus(side_num, ec, amount, traintype)
return true
end
function bonus.init_data(cfg)
local sceneries = bonus.sceneries
local lit = wml.literal(cfg)
for k,v in pairs(wml.get_child(lit, "str") or {}) do
local scenery = sceneries[k] or {}
scenery.names = v
sceneries[k] = scenery
end
for k,v in pairs(wml.get_child(lit, "img") or {}) do
local scenery = sceneries[k] or {}
sceneries[k].image = v
sceneries[k] = scenery
end
end
if true then
local sceneries = bonus.sceneries
local strings, images = wesnoth.dofile("./bonus_point_definitions.lua")
for k,v in pairs(strings) do
local scenery = sceneries[k] or {}
scenery.names = v
sceneries[k] = scenery
end
for k,v in pairs(images) do
local scenery = sceneries[k] or {}
scenery.image = v
sceneries[k] = scenery
end
end
return bonus

View file

@ -0,0 +1,325 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local STR_BONUS_SHIP_NAMES = { _"Point", _"Rest", _"Ruin", _"Rocks", _"Bane", _"Waters", _"Route", _"Vestige", _"Disaster", _"Massacre", _"Expedition", _"Cargo" }
local STR_BONUS_BONES_NAMES = { _"Point", _"Rest", _"Lair", _"Exile", _"Bane", _"Passage", _"Curse" }
local STR_BONUS_BONES_SWAMP_NAMES = { _"Point", _"Rest", _"Lair", _"Exile", _"Bane", _"Death", _"Passage", _"Curse", _"Quagmire" }
local STR_BONUS_DEAD_OAK_NAMES = { _"Rest", _"Point", _"Lair", _"Exile", _"Bane", _"Death", _"Curse", _"Wasteland", _"Desolation", _"Despair", _"Desert", _"Route", _"Passage", _"Cementery" }
local STR_BONUS_VILLAGE_RUINED_NAMES = { _"Rest", _"Ruin", _"Lair", _"Exile", _"Bane", _"Curse", _"Destruction", _"Desolation", _"Vestige", _"Disaster" }
local STR_BONUS_BURIAL_NAMES = { _"Point", _"Rest", _"Lair", _"Passage", _"Bane", _"Massacre", _"Curse", _"Disaster", _"Cementery" }
local STR_BONUS_BURIAL_SAND_NAMES = { _"Point", _"Rest", _"Lair", _"Exile", _"Passage", _"Bane", _"Massacre", _"Curse", _"Disaster" }
local STR_BONUS_BURIAL_CAVE_NAMES = { _"Rest", _"Lair", _"Passage", _"Bane", _"Grotto", _"Curse", _"Cave", _"Cementery", _"Graveyard" }
local STR_BONUS_DETRITUS_NAMES = { _"Point", _"Rest", _"Ruin", _"Lair", _"Exile", _"Passage", _"Bane", _"Massacre", _"Curse", _"Quagmire", _"Bog", _"Hideout", _"Desolation" }
local STR_BONUS_TRAPDOOR_NAMES = { _"Rest", _"Ruin", _"Lair", _"Passage", _"Bane", _"Despair", _"Curse", _"Cave", _"Dungeon", _"Secret", _"Hideout", _"Mine", _"Grotto", _"Den" }
local STR_BONUS_COFFIN_NAMES = { _"Rest", _"Ruin", _"Lair", _"Exile", _"Passage", _"Bane", _"Dream", _"Crypt", _"Grotto", _"Graveyard", _"Secret", _"Curse", _"Mausoleum", _"Ossuary" }
local STR_BONUS_MINE_NAMES = { _"Lair", _"Passage", _"Bane", _"Peak", _"Mine", _"Curse", _"Den", _"Site", _"Quarry", _"Dungeon" }
local STR_BONUS_DOORS_NAMES = { _"Rest", _"Lair", _"Passage", _"Bane", _"Peak", _"Mine", _"Destiny", _"Door", _"Gate", _"Curse", _"Domain", _"Secret", _"Dungeon" }
local STR_BONUS_SHOP_NAMES = { _"Path", _"Road", _"Route", _"Market", _"Fair", _"Festival", _"Tournament", _"Enclave", _"Armory" }
local STR_BONUS_SHOP_GRASS_NAMES = { _"Route", _"Market", _"Enclave", _"Fair", _"Festival", _"Tournament", _"Armory", _"Refuge" }
local STR_BONUS_SIGNPOST_NAMES = { _"Rest", _"Path", _"Point", _"Passage", _"Road", _"Route", _"Domain" }
local STR_BONUS_ROCK_CAIRN_NAMES = { _"Rest", _"Memory", _"Triumph", _"Vestige", _"Point", _"Passage", _"Domain", _"Route", _"Rock" }
local STR_BONUS_ROCK_CAIRN_CAVE_NAMES = { _"Rest", _"Memory", _"Vestige", _"Grotto", _"Passage", _"Domain", _"Secret", _"Curse", _"Rock" }
local STR_BONUS_DOLMEN_NAMES = { _"Rest", _"Memory", _"Triumph", _"Vestige", _"Point", _"Passage", _"Domain", _"Route", _"Ruin", _"Road", _"Path" }
local STR_BONUS_MONOLITH_NAMES = { _"Rest", _"Memory", _"Triumph", _"Vestige", _"Point", _"Path", _"Domain", _"Route", _"Monolith", _"Road" }
local STR_BONUS_OBELISK_NAMES = { _"Rest", _"Memory", _"Triumph", _"Vestige", _"Point", _"Path", _"Domain", _"Route", _"Obelisk", _"Road" }
local STR_BONUS_WELL_GRASS_NAMES = { _"Rest", _"Lair", _"Exile", _"Point", _"Passage", _"Ruin", _"Route", _"Refuge", _"Enclave", _"Domain" }
local STR_BONUS_WELL_ROAD_NAMES = { _"Rest", _"Point", _"Desire", _"Route", _"Passage", _"Refuge", _"Enclave", _"Path", _"Road", _"Market" }
local STR_BONUS_WELL_CAVE_NAMES = { _"Rest", _"Lair", _"Exile", _"Passage", _"Ruin", _"Well", _"Mine", _"Grotto", _"Den", _"Secret" }
local STR_BONUS_WELL_CRYSTAL_NAMES = { _"Bane", _"Lair", _"Curse", _"Passage", _"Grotto", _"Cave", _"Mine", _"Site", _"Quarry", _"Secret" }
local STR_BONUS_MONOLITH_HILLS_NAMES = { _"Rest", _"Point", _"Passage", _"Ruin", _"Lair", _"Exile", _"Plateau", _"Cliff", _"Domain", _"Route", _"Vestige" }
local STR_BONUS_LIGHTHOUSE_NAMES = { _"Port", _"Seaport", _"Harbor", _"Enclave", _"Bay", _"Coast", _"Shore", _"Lighthouse", _"Domain" }
local STR_BONUS_CAMPFIRE_NAMES = { _"Port", _"Seaport", _"Harbor", _"Bay", _"Coast", _"Shore", _"Cliff", _"Domain", _"Signal", _"Beacon", _"Enclave" }
local STR_BONUS_LILIES_NAMES = { _"Point", _"Passage", _"Lair", _"Rest", _"Waters", _"Domain", _"Curse", _"Secret", _"Hideout", _"Bane" }
local STR_BONUS_LILIES_SWAMP_NAMES = { _"Point", _"Passage", _"Rest", _"Lair", _"Exile", _"Domain", _"Curse", _"Secret", _"Hideout", _"Bane", _"Marsh" }
local STR_BONUS_ROCK_SAND_NAMES = { _"Rest", _"Point", _"Passage", _"Ruin", _"Lair", _"Exile", _"Delirium", _"Graveyard", _"Cementery", _"Ossuary", _"Domain", _"Route", _"Vestige" }
local STR_BONUS_ROCK_NAMES = { _"Rest", _"Point", _"Passage", _"Ruin", _"Lair", _"Exile", _"Domain", _"Route", _"Vestige" }
local STR_BONUS_DOLMEN_GRASS_NAMES = { _"Rest", _"Point", _"Passage", _"Ruin", _"Lair", _"Domain", _"Route", _"Vestige", _"Conclave", _"Graveyard" }
local STR_BONUS_WINDMILL_NAMES = { _"Meadow", _"Prairie", _"Grassland", _"Refuge", _"Windmill", _"Enclave", _"Domain", _"Farm", _"Granary", _"Field", _"Shire" }
local STR_BONUS_TENT_NAMES = { _"Exile", _"Route", _"Enclave", _"Domain", _"Outpost", _"Refuge" }
local STR_BONUS_TENT_FANCY_GRASS_NAMES = { _"Exile", _"Route", _"Enclave", _"Domain", _"Outpost", _"Refuge", _"Festival", _"Fair", _"Tournament" }
local STR_BONUS_TENT_FANCY_ROAD_NAMES = { _"Route", _"Road", _"Path", _"Enclave", _"Domain", _"Outpost", _"Refuge", _"Festival", _"Fair", _"Tournament", _"Market", _"Armory" }
local STR_BONUS_SHELTER_NAMES = { _"Passage", _"Exile", _"Route", _"Refuge", _"Domain", _"Shelter", _"Shelter", _"Quarry", _"Plateau", _"Site", _"Outpost", _"Enclave", _"Passage" }
local STR_BONUS_TENT_OUTPOST_NAMES = { _"Exile", _"Route", _"Refuge", _"Domain", _"Outpost", _"Site", _"Expedition", _"Enclave" }
local STR_BONUS_ALTAR_NAMES = { _"Rest", _"Passage", _"Ruin", _"Lair", _"Oracle", _"Altar", _"Secret", _"Ossuary", _"Conclave", _"Curse", _"Grotto" }
local STR_BONUS_ALTAR_CRYSTAL_NAMES = { _"Passage", _"Lair", _"Curse", _"Domain", _"Bane", _"Cave", _"Secret" }
local STR_BONUS_TEMPLE_NAMES = { _"Rest", _"Ruin", _"Lair", _"Oracle", _"Temple", _"Sanctuary", _"Shrine", _"Conclave", _"Refuge", _"Library", _"Academy", _"School", _"Mausoleum", _"Crypt", _"Memory" }
local STR_BONUS_TEMPLE_ROAD_NAMES = { _"Rest", _"Route", _"Oracle", _"Temple", _"Sanctuary", _"Shrine", _"Refuge", _"Road", _"Library", _"Path", _"Market", _"Academy", _"School", _"Conclave", _"Mausoleum", _"Crypt" }
local STR_BONUS_TEMPLE_GRASS_NAMES = { _"Rest", _"Ruin", _"Oracle", _"Temple", _"Sanctuary", _"Shrine", _"Refuge", _"Library", _"Academy", _"School", _"Conclave", _"Mausoleum", _"Crypt", _"Market" }
local STR_BONUS_TEMPLE_MOUNTAIN_NAMES = { _"Rest", _"Passage", _"Ruin", _"Lair", _"Exile", _"Oracle", _"Temple", _"Sanctuary", _"Shrine", _"Refuge", _"Peak", _"Domain", _"Conclave", _"Mausoleum", _"Crypt", _"Memory" }
local STR_BONUS_TEMPLE_HILLS_NAMES = { _"Rest", _"Passage", _"Ruin", _"Lair", _"Refuge", _"Cliff", _"Domain", _"Route", _"Sanctuary", _"Conclave", _"Temple", _"Shrine", _"Oracle", _"Crypt", _"Mausoleum", _"Route" }
local STR_BONUS_TEMPLE_GREEN_NAMES = { _"Rest", _"Passage", _"Ruin", _"Lair", _"Exile", _"Oracle", _"Domain", _"Curse", _"Bane", _"Vestige", _"Perversion", _"Decay", _"Moor", _"Crypt", _"Mausoleum", _"Ossuary" }
local STR_BONUS_TREE_NAMES = { _"Conclave", _"Enclave", _"Meadow", _"Prairie", _"Field", _"Route", _"Refuge", _"Tree", _"Glade", _"Domain", _"Shire" }
local STR_BONUS_ROCK_TOWER_NAMES = { _"Rest", _"Vestige", _"Lair", _"Domain", _"Tower", _"Ruin", _"Refuge", _"Sanctuary", _"Observatory", _"Observatory", _"Enclave", _"Conclave", _"Crypt" }
local STR_BONUS_ROCK_SWAMP_NAMES = { _"Rest", _"Point", _"Decay", _"Passage", _"Ruin", _"Lair", _"Exile", _"Bog", _"Domain", _"Bane", _"Curse", _"Vestige", _"Secret" }
local STR_BONUS_GENERIC_NAMES = { _"Rest", _"Point", _"Passage", _"Ruin", _"Lair", _"Exile", _"Vestige" }
local strings = {
detritus = STR_BONUS_DETRITUS_NAMES,
detritus2 = STR_BONUS_DETRITUS_NAMES,
lilies = STR_BONUS_LILIES_NAMES,
lilies_s = STR_BONUS_LILIES_SWAMP_NAMES,
oak1 = STR_BONUS_TREE_NAMES,
oak2 = STR_BONUS_TREE_NAMES,
oak3 = STR_BONUS_TREE_NAMES,
oak4 = STR_BONUS_TREE_NAMES,
oak5 = STR_BONUS_TREE_NAMES,
oak6 = STR_BONUS_TREE_NAMES,
oak7 = STR_BONUS_TREE_NAMES,
oak_dead = STR_BONUS_DEAD_OAK_NAMES,
oak_dead2 = STR_BONUS_DEAD_OAK_NAMES,
obelisk = STR_BONUS_OBELISK_NAMES,
rock1 = STR_BONUS_ROCK_SAND_NAMES,
rock3 = STR_BONUS_ROCK_SWAMP_NAMES,
rock4 = STR_BONUS_ROCK_NAMES,
tower_r1 = STR_BONUS_ROCK_TOWER_NAMES,
tower_r4 = STR_BONUS_GENERIC_NAMES,
crystal = STR_BONUS_WELL_CRYSTAL_NAMES,
crystal3 = STR_BONUS_ALTAR_CRYSTAL_NAMES,
ship1 = STR_BONUS_SHIP_NAMES,
ship2 = STR_BONUS_SHIP_NAMES,
bones = STR_BONUS_BONES_NAMES,
bones_s = STR_BONUS_BONES_SWAMP_NAMES,
village = STR_BONUS_VILLAGE_RUINED_NAMES,
burial = STR_BONUS_BURIAL_NAMES,
burial_s = STR_BONUS_BURIAL_SAND_NAMES,
burial_c = STR_BONUS_BURIAL_CAVE_NAMES,
trapdoor = STR_BONUS_TRAPDOOR_NAMES,
coffin = STR_BONUS_COFFIN_NAMES,
mine = STR_BONUS_MINE_NAMES,
doors = STR_BONUS_DOORS_NAMES,
tent1 = STR_BONUS_TENT_NAMES,
shelter = STR_BONUS_SHELTER_NAMES,
tent2 = STR_BONUS_TENT_NAMES,
tent2_g = STR_BONUS_TENT_FANCY_GRASS_NAMES,
tent2_r = STR_BONUS_TENT_FANCY_ROAD_NAMES,
shop = STR_BONUS_SHOP_NAMES,
shop_g = STR_BONUS_SHOP_GRASS_NAMES,
outpost = STR_BONUS_TENT_OUTPOST_NAMES,
signpost = STR_BONUS_SIGNPOST_NAMES,
rock_cairn = STR_BONUS_ROCK_CAIRN_NAMES,
rock_cairn_c = STR_BONUS_ROCK_CAIRN_CAVE_NAMES,
dolmen = STR_BONUS_DOLMEN_NAMES,
monolith1 = STR_BONUS_MONOLITH_HILLS_NAMES,
monolith1_r = STR_BONUS_GENERIC_NAMES,
monolith2 = STR_BONUS_MONOLITH_NAMES,
monolith3 = STR_BONUS_ROCK_NAMES,
dolmen_g = STR_BONUS_DOLMEN_GRASS_NAMES,
monolith4 = STR_BONUS_MONOLITH_HILLS_NAMES,
monolith4_r = STR_BONUS_GENERIC_NAMES,
well_g = STR_BONUS_WELL_GRASS_NAMES,
well_r = STR_BONUS_WELL_ROAD_NAMES,
well = STR_BONUS_WELL_CAVE_NAMES,
lighthouse = STR_BONUS_LIGHTHOUSE_NAMES,
campfire = STR_BONUS_CAMPFIRE_NAMES,
temple = STR_BONUS_TEMPLE_NAMES,
temple2 = STR_BONUS_TEMPLE_ROAD_NAMES,
temple2_g = STR_BONUS_TEMPLE_GRASS_NAMES,
temple3 = STR_BONUS_TEMPLE_MOUNTAIN_NAMES,
temple4 = STR_BONUS_TEMPLE_HILLS_NAMES,
temple_green_h = STR_BONUS_TEMPLE_GREEN_NAMES,
temple_green_h2 = STR_BONUS_TEMPLE_GREEN_NAMES,
temple_green_g = STR_BONUS_TEMPLE_GREEN_NAMES,
temple_green_g2 = STR_BONUS_TEMPLE_GREEN_NAMES,
altar = STR_BONUS_ALTAR_NAMES,
windmill = STR_BONUS_WINDMILL_NAMES
}
local IMG_DETRITUS = "misc/blank-hex.png~BLIT(terrain/misc/detritus/detritusC-3.png~CROP(0,18,66,54),6,13)~BLIT(terrain/misc/detritus/detritusC-2.png~CROP(8,0,35,70),0,2)~BLIT(terrain/misc/detritus/detritusC-2.png~CROP(43,44,29,26),36,46)"
local IMG_DETRITUS_2 = "misc/blank-hex.png~BLIT(terrain/misc/detritus/detritusC-2.png~CROP(0,4,59,68),13,0)~BLIT(terrain/misc/detritus/detritusC-5.png~CROP(17,0,55,63),0,9)"
local IMG_LILIES = "terrain/embellishments/water-lilies-flower-small4.png~BLIT(terrain/embellishments/water-lilies-flower-small5.png~CROP(40,28,17,17),40,28)"
local IMG_LILIES_2 = "misc/blank-hex.png~BLIT(terrain/embellishments/water-lilies-flower5.png~CROP(21,12,72,72)~BLIT(terrain/embellishments/water-lilies-flower-small2.png~CROP(0,8,55,64),17,0)"
local IMG_OAK_1 = "terrain/embellishments/flowers-mixed4.png~MASK(scenery/whirlpool.png)~BLIT(scenery/oak-leaning.png)"
local IMG_OAK_2 = "terrain/embellishments/flowers-mixed3.png~MASK(scenery/whirlpool.png)~BLIT(scenery/oak-leaning.png)"
-- custom image
local IMG_OAK_3 = "scenery/treehouse.png"
-- custom image
local IMG_OAK_4 = "scenery/treehouse.png"
local IMG_OAK_5 = "terrain/embellishments/flower-purple.png~MASK(scenery/whirlpool.png)~BLIT(scenery/oak-leaning.png)"
-- custom image
local IMG_OAK_6 = "scenery/treehouse.png"
-- custom image
local IMG_OAK_7 = "scenery/treehouse.png"
local IMG_ROCK_1 = "misc/blank-hex.png~BLIT(scenery/rock1.png~CROP(1,11,71,61),0,0)"
local IMG_ROCK_3 = "misc/blank-hex.png~BLIT(scenery/rock3.png~CROP(0,11,66,61),6,0)"
local IMG_ROCK_4 = "misc/blank-hex.png~BLIT(scenery/rock4.png~CROP(0,8,66,64),6,0)"
-- custom image
local IMG_ROCK_1_TOWER = "misc/blank-hex.png~BLIT(scenery/wct-tower.png)"
-- custom image
local IMG_ROCK_4_TOWER = "misc/blank-hex.png~BLIT(scenery/wct-tower.png)"
-- custom image
local IMG_OBELISK_POST = "misc/blank-hex.png~BLIT(scenery/wct-obelisk.png)"
-- custom image
local IMG_ROCK_CAIRN_DOLMEN = "misc/blank-hex.png~BLIT(scenery/wct-dolmen.png~SCALE(75,75)~CROP(0,0,72,62),0,10)"
-- custom image
local IMG_MONOLITH_DOLMEN = "misc/blank-hex.png~BLIT(scenery/wct-dolmen2.png~SCALE(75,75)~CROP(0,0,72,62),0,10)"
-- custom image
local IMG_TEMPLE_2 = "misc/blank-hex.png~BLIT(scenery/wct-temple.png~SCALE(60,60),6,3)"
-- custom image
local IMG_TEMPLE_3 = "scenery/wct-temple2.png"
-- custom image
local IMG_TEMPLE_GREEN_HILLS = "misc/blank-hex.png~BLIT(scenery/wct-temple4.png~SCALE(65,65),4,4)"
-- custom image
local IMG_TEMPLE_GREEN_HILLS_2 = "misc/blank-hex.png~BLIT(scenery/wct-temple5.png~SCALE(63,63),6,2)"
-- custom image
local IMG_TEMPLE_GREEN_GRASS = "misc/blank-hex.png~BLIT(scenery/wct-temple3.png)"
-- custom image
local IMG_TEMPLE_GREEN_GRASS_2 = "misc/blank-hex.png~BLIT(scenery/wct-temple5.png~SCALE(63,63),6,2)"
-- custom image
local IMG_DETRITUS_OAK_1 = "scenery/wct-oak-dead.png"
-- custom image
local IMG_DETRITUS_OAK_2 = "scenery/wct-oak-dead2.png"
-- custom image
local IMG_CRYSTAL_WELL = "scenery/wct-crystal.png"
-- custom image
local IMG_CRYSTALS_ALTAR = "misc/blank-hex.png~BLIT(scenery/wct-crystal3.png~SCALE(59,59),6,4)"
-- custom image
local IMG_TENT_OUTPOST = "scenery/wct-outpost.png"
local images = {
rock1 = IMG_ROCK_1,
rock3 = IMG_ROCK_3,
rock4 = IMG_ROCK_4,
tower_r1 = IMG_ROCK_1_TOWER,
tower_r4 = IMG_ROCK_4_TOWER,
lilies = IMG_LILIES,
lilies_s = IMG_LILIES_2,
detritus = IMG_DETRITUS,
detritus2 = IMG_DETRITUS_2,
oak1 = IMG_OAK_1,
oak2 = IMG_OAK_2,
oak3 = IMG_OAK_3,
oak4 = IMG_OAK_4,
oak5 = IMG_OAK_5,
oak6 = IMG_OAK_6,
oak7 = IMG_OAK_7,
obelisk = IMG_OBELISK_POST,
dolmen = IMG_ROCK_CAIRN_DOLMEN,
dolmen_g = IMG_MONOLITH_DOLMEN,
oak_dead = IMG_DETRITUS_OAK_1,
oak_dead2 = IMG_DETRITUS_OAK_2,
crystal = IMG_CRYSTAL_WELL,
crystal3 = IMG_CRYSTALS_ALTAR,
outpost = IMG_TENT_OUTPOST,
ship1 = "scenery/shipwreck-1.png",
ship2 = "scenery/wreck.png",
bones = "items/bones.png",
bones_s = "items/bones.png",
village = "scenery/village-human-burned2.png",
burial = "items/burial.png",
burial_s = "items/burial.png",
burial_c = "items/burial.png",
trapdoor = "scenery/trapdoor-open.png",
coffin = "items/coffin-closed.png",
mine = "scenery/mine-abandoned.png",
doors = "scenery/dwarven-doors-closed.png",
tent1 = "scenery/tent-ruin-1.png",
shelter = "scenery/tent-ruin-1.png",
tent2 = "scenery/tent-fancy-red.png",
tent2_g = "scenery/tent-fancy-red.png",
tent2_r = "scenery/tent-fancy-red.png",
shop = "scenery/tent-shop-weapons.png",
shop_g = "scenery/tent-shop-weapons.png",
signpost = "scenery/signpost.png",
rock_cairn = "scenery/rock-cairn.png",
rock_cairn_c = "scenery/rock-cairn.png",
monolith1 = "scenery/monolith1.png",
monolith1_r = "scenery/monolith1.png",
monolith2 = "scenery/monolith2.png",
monolith3 = "scenery/monolith3.png",
monolith4 = "scenery/monolith4.png",
monolith4_r = "scenery/monolith4.png",
well_g = "scenery/well.png",
well_r = "scenery/well.png",
well = "scenery/well.png",
lighthouse = "scenery/lighthouse.png",
temple = "scenery/temple1.png",
temple2 = IMG_TEMPLE_2,
temple2_g = IMG_TEMPLE_2,
temple3 = IMG_TEMPLE_2,
temple4 = IMG_TEMPLE_3,
temple_green_h = IMG_TEMPLE_GREEN_HILLS,
temple_green_h2 = IMG_TEMPLE_GREEN_HILLS_2,
temple_green_g = IMG_TEMPLE_GREEN_GRASS,
temple_green_g2 = IMG_TEMPLE_GREEN_GRASS_2,
altar = "items/altar.png",
}
return strings, images

View file

@ -0,0 +1,69 @@
local color = {}
function color.to_pango_string(c)
return ("#%02x%02x%02x"):format(c.r, c.g, c.b)
end
function color.color_text(color_str, text)
return "<span color='" .. color_str .. "'>" .. text .. "</span>"
end
function color.bonus_text(str)
return color.color_text("#ff75ff", str)
end
function color.help_text(str)
return color.color_text("#ff95ff", str)
end
-- note: the default argument for the first parameter is the
-- currently active side, not the currently viewing side
function color.tc_text(team_num, text)
if text == nil then
text = team_num
team_num = wesnoth.current.side
end
local c = wesnoth.colors[wesnoth.sides[team_num].color].mid
local color_str = color.to_pango_string(c)
return color.color_text(color_str, text)
end
function color.tc_image(team_num, img)
if img == nil then
img = team_num
team_num = wesnoth.current.side
end
return img .. "~TC(" .. team_num .. ",magenta)"
end
-- Fixes the colors in mp campaigns: in case that the players changed the
-- colors in the mp setup screen, we have to remember those settings and
-- set the teams color in later scenarios acccordingly.
function wesnoth.wml_actions.wc2_fix_colors(cfg)
local player_sides = wesnoth.get_sides(wml.get_child(cfg, "player_sides"))
local other_sides = wesnoth.get_sides { { "not", wml.get_child(cfg, "player_sides") } }
local available_colors = { "red", "blue", "green", "purple", "black", "brown", "orange", "white", "teal" }
local taken_colors = {}
for i, side in ipairs(player_sides) do
if side.variables.wc2_color then
side.color = side.variables.wc2_color
else
side.variables.wc2_color = side.color
end
taken_colors[side.color] = true
end
local color_num = 1
for i, side in ipairs(other_sides) do
while taken_colors[available_colors[color_num]] == true do
color_num = color_num + 1
end
side.color = available_colors[color_num]
taken_colors[side.color] = true
end
end
return color

View file

@ -0,0 +1,156 @@
-- general code related to dropping items, code taken from 'scenario with robots' add-on.
-- todo: maybe we coudl mainline this and merge it with the iterms.lua code ( this means
-- adding a mainline "pickup item" event that fires when a unit steops on an [item] and
-- would have the same features as this here)
local on_event = wesnoth.require("on_event")
local dropping = {}
dropping.field_data = {}
dropping.loc_to_index = function(x,y)
return (y - 1) * 1000 + x
end
dropping.index_to_loc = function(index)
local y_m1 = math.floor(index / 1000)
return index - y_m1 * 1000, y_m1 + 1
end
dropping.decorate_imagename = function(id)
return "wc2_item_" .. id
end
dropping.place_image = function(x, y, cfg)
wesnoth.add_tile_overlay(x, y, {
image = cfg.image,
team_name = cfg.team_name,
visible_in_fog = cfg.visible_in_fog,
redraw = cfg.redraw,
name = dropping.decorate_imagename(cfg.id),
z_order = cfg.z_order
})
end
-- this can be used to remove item but not to add items.
dropping.get_entries_at_readonly = function(x,y)
return dropping.field_data[dropping.loc_to_index(x,y)] or {}
end
dropping.get_entries_at_readwrite = function(x,y)
local index = dropping.loc_to_index(x,y)
dropping.field_data[index] = dropping.field_data[index] or {}
return dropping.field_data[index]
end
dropping.remove_empty_lists = function()
local to_delete = {}
for k,v in pairs(dropping.field_data) do
if #v == 0 then
to_delete[k] = true
end
end
for k,v in pairs(to_delete) do
dropping.field_data[k] = nil
end
end
dropping.add_item = function(x, y, cfg)
table.insert(dropping.get_entries_at_readwrite(x,y), cfg)
cfg.id = dropping.next_id
dropping.next_id = dropping.next_id + 1
dropping.place_image(x, y, cfg)
end
dropping.remove_item = function(x, y, id)
local entries = dropping.get_entries_at_readwrite(x,y)
for i,v in ipairs(entries) do
if v.id == id then
wesnoth.remove_tile_overlay(x, y, dropping.decorate_imagename(id))
table.remove(entries, i)
break
end
end
end
dropping.remove_all_items = function(filter)
for k,v in pairs(dropping.field_data) do
local start = #v
local x, y = dropping.index_to_loc(k)
for i = start, 1, -1 do
if filter(v[i], x, y) then
wesnoth.remove_tile_overlay(x, y, dropping.decorate_imagename(v[i].id))
table.remove(v, i)
end
end
end
end
dropping.remove_current_item = function()
local v = dropping.current_item
local ec = wesnoth.current.event_context
wesnoth.remove_tile_overlay(ec.x1, ec.y1, dropping.decorate_imagename(v.id))
dropping.item_taken = true
end
wesnoth.persistent_tags.wc2_dropping.write = function(add)
local res = {
next_id = dropping.next_id,
}
for i,v in pairs(dropping.field_data) do
local x,y = dropping.index_to_loc(i)
for i2,v2 in ipairs(v) do
table.insert(res, wml.tag.item {
x = x,
y = y,
wml.tag.data (v2)
})
end
end
add(res)
end
-- read might not be called if there is no [dropped_items] tag found
wesnoth.persistent_tags.wc2_dropping.read = function(cfg)
for item in wml.child_range(cfg, "item") do
local hex_list = dropping.get_entries_at_readwrite(item.x, item.y)
table.insert(hex_list, (wml.get_child(item, "data")))
end
dropping.next_id = cfg.next_id or 0
dropping.remove_empty_lists()
end
on_event("moveto", function(event_context)
local x = event_context.x1
local y = event_context.y1
local entries = dropping.get_entries_at_readonly(x,y)
local i = 1
while i <= #entries do
local v = entries[i]
dropping.current_item = v
dropping.item_taken = nil
wesnoth.fire_event("wc2_drop_pickup", x, y)
if dropping.item_taken then
table.remove(entries, i)
wesnoth.remove_tile_overlay(x, y, dropping.decorate_imagename(v.id))
wesnoth.allow_undo(false)
else
i = i + 1
end
dropping.current_item = nil
dropping.item_taken = nil
end
end)
on_event("preload", function()
dropping.next_id = dropping.next_id or 0
for k,v in pairs(dropping.field_data) do
local x,y = dropping.index_to_loc(k)
for i, cfg in ipairs(v) do
dropping.place_image(x, y, cfg)
end
end
end)
return dropping

View file

@ -0,0 +1,171 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local helper = wesnoth.require("helper")
local T = wml.tag
local terrain_map = { fungus = "Uft", cave = "Ut", sand = "Dt",
reef = "Wrt", hills = "Ht", swamp_water = "St", shallow_water = "Wst", castle = "Ct",
mountains = "Mt", deep_water = "Wdt", flat = "Gt", forest = "Ft", frozen = "At",
village = "Vt", impassable = "Xt", unwalkable = "Qt", rails = "Rt"
}
-- for all attacks that match [filter_attack], it add a dublicate fo that attack and modifres is as describes in the [attack] subtag which uses the apply_to=attack syntax
function wesnoth.effects.wc2_optional_attack(u, cfg)
local name_suffix = cfg.name_suffix or helper.wml_error("apply_to=wc2_optional_attack missing required name_suffix= attribute.")
local attack_mod = wml.get_child(cfg, "attack") or helper.wml_error("apply_to=wc2_optional_attack missing required [attack] subtag")
local attacks_to_add = {}
local names = {}
for i = 1, #u.attacks do
local attack = u.attacks[i]
if attack:matches(wml.get_child(cfg, "filter_attack")) then
local new_name = attack.name .. name_suffix
local new_attack = attack.__cfg
new_attack.name = new_name
new_attack.apply_to = "new_attack"
table.insert(names, new_name)
table.insert(attacks_to_add, new_attack)
end
end
for k,v in ipairs(attacks_to_add) do
wesnoth.add_modification(u, "object", { T.effect ( v)}, false)
end
if #names > 0 then
-- if names is empty then it would give 'name=""' which would match all attacks.
attack_mod.apply_to = "attack"
attack_mod.name = table.concat(names, ",")
wesnoth.add_modification(u, "object", { T.effect (attack_mod) }, false)
end
end
-- The implementation of the moves defense bonus in movement training.
function wesnoth.effects.wc2_moves_defense(u, cfg)
wesnoth.add_modification(u, "object", { T.effect {
apply_to = "defense",
replace = false,
T.defense {
fungus = -u.max_moves,
cave = -u.max_moves,
deep_water = -u.max_moves,
shallow_water = -u.max_moves,
swamp_water = -u.max_moves,
flat = -u.max_moves,
sand = -u.max_moves,
forest = -u.max_moves,
hills = -u.max_moves,
mountains = -u.max_moves,
village = -u.max_moves,
castle = -u.max_moves,
frozen = -u.max_moves,
unwalkable = -u.max_moves,
reef = -u.max_moves,
},
}}, false)
end
-- Like apply_to=resistance with replace=true, but never decreases resistances.
function wesnoth.effects.wc2_min_resistance(u, cfg)
local resistance_new = {}
local resistance_old = wml.parsed(wml.get_child(cfg, "resistance"))
local unit_resistance_cfg = nil
for k,v in pairs(resistance_old) do
if type(k) == "string" and type(v) == "number" then
if not unit_resistance_cfg then
unit_resistance_cfg = wml.parsed(wml.get_child(u.__cfg, "resistance"))
end
if unit_resistance_cfg[k] >= v then
resistance_new[k] = v
end
end
end
wesnoth.add_modification(u, "object", {
T.effect {
apply_to = "resistance",
replace = true,
T.resistance (resistance_new),
},
}, false)
end
-- Like apply_to=defense with replace=true, but never decreases defense.
function wesnoth.effects.wc2_min_defense(u, cfg)
local defense_new = {}
local defense_old = wml.parsed(wml.get_child(cfg, "defense"))
for k,v in pairs(defense_old) do
if type(k) == "string" and type(v) == "number" and wesnoth.unit_defense(u, terrain_map[k] or "") >= v then
defense_new[k] = v
end
end
wesnoth.add_modification(u, "object", {
T.effect {
apply_to = "defense",
replace = true,
T.defense (defense_new),
},
}, false)
end
-- Sets the auro accordingly if unit might have multiple of illumination, darkness or forcefield abilities.
function wesnoth.effects.wc2_update_aura(u, cfg)
local illuminates = wesnoth.match_unit(u, { ability = "illumination" } )
local darkens = wesnoth.match_unit(u, { ability = "darkness" } )
local forcefield = wesnoth.match_unit(u, { ability = "forcefield" } )
local halo = ""
if illuminates and darkens then
wesnoth.message("WC2", "Warning illuminates and darkens discovered on a unit")
end
if forcefield and illuminates then
halo = "halo/illuminates-aura.png~R(50)"
elseif forcefield and darkens then
halo = "halo/darkens-aura.png~R(40)"
elseif forcefield then
halo = "halo/darkens-aura.png~O(65%)~R(150)"
elseif darkens then
halo = "halo/darkens-aura.png"
elseif illuminates then
halo = "halo/illuminates-aura.png"
end
wesnoth.add_modification(u, "object", {
T.effect {
apply_to = "halo",
halo = halo,
},
}, false)
end
-- Similar to the usual apply_to=overlay effect but does not add overlays the the unit already has.
function wesnoth.effects.wc2_overlay(u, cfg)
if cfg.add then
local to_add_old = wc2_utils.split_to_array(cfg.add)
local to_add_new = {}
local current = u.overlays
for i1,v1 in ipairs(to_add_old) do
local has_already = false
for i2,v2 in ipairs(current) do
if v2 == v1 then
has_already = true
break
end
end
if not has_already then
table.insert(to_add_new, v1)
end
end
cfg.add = table.concat(to_add_new,",")
end
cfg.apply_to = "overlay"
wesnoth.add_modification(u, "object", { T.effect(cfg)} , false)
end
-- Can move in same turn as when recruited/recalled
function wesnoth.effects.wc2_move_on_recruit(u, cfg)
u.variables["mods.wc2_move_on_recruit"] = true
end
-- The implementation of this mods reduced recall costs, all units get an object with this effect.
function wesnoth.effects.wc2_recall_cost(u, cfg)
local t = wesnoth.unit_types[u.type]
u.recall_cost = math.min(20, t.cost + 3)
end

View file

@ -0,0 +1,130 @@
local helper = wesnoth.require("helper")
local T = wml.tag
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local wc2_heroes = {}
-- an array of wml tables, usually containing type,
wc2_heroes.commander_overlay = "misc/wct-commander.png"
wc2_heroes.hero_overlay = "misc/hero-icon.png"
wc2_heroes.dialogues = {}
wc2_heroes.trait_heroic = nil
wc2_heroes.trait_expert = nil
if wesnoth.have_file("./unittypedata.lua") then
local data = wesnoth.require("./unittypedata.lua")
for v,k in pairs(data) do
wc2_heroes.dialogues[v] = k
end
end
function wc2_heroes.find_dialogue(t)
return wc2_heroes.dialogues[t] or wc2_heroes.dialogues.default
end
function wc2_heroes.init_data()
local cfg_heroic = wc2_utils.get_wc2_data("trait_heroic")
local cfg_expert = wc2_utils.get_wc2_data("trait_expert")
wc2_heroes.trait_heroic = wml.get_child(wml.get_child(cfg_heroic, "trait_heroic"), "trait")
wc2_heroes.trait_expert = wml.get_child(wml.get_child(cfg_expert, "trait_expert"), "trait")
end
function wc2_heroes.commander_overlay_object()
return wml.tag.object {
id = "wc2_commander_overlay",
wml.tag.effect {
apply_to="overlay",
add = wc2_heroes.commander_overlay
}
}
end
function wc2_heroes.hero_overlay_object()
return wml.tag.object {
id = "wc2_hero_overlay",
wml.tag.effect {
apply_to="overlay",
add = wc2_heroes.hero_overlay
}
}
end
-- @a t the unit type id
-- @returns the content of [modifications] for a unit.
function wc2_heroes.generate_traits(t)
local res = {}
if wc2_heroes.trait_heroic then
table.insert(res, wml.tag.trait (wc2_heroes.trait_heroic))
end
for k,v in ipairs(wc2_era.hero_traits) do
if v.types[t] then
table.insert(res, wml.tag.trait (v.trait))
end
end
return res
end
-- @a t the unit type
function wc2_heroes.place(t, side, x, y, is_commander)
--print("wc2_heroes.place type=" .. t .. " side=" .. side)
local modifications = wc2_heroes.generate_traits(t)
table.insert(modifications, 1, wml.tag.advancement { wc2_scenario.experience_penalty() })
table.insert(
modifications,
is_commander and wc2_heroes.commander_overlay_object() or wc2_heroes.hero_overlay_object()
)
local u = wesnoth.create_unit {
type = t,
side = side,
random_traits = false,
role = is_commander and "commander" or nil,
wml.tag.modifications (modifications),
}
if is_commander then
u.variables["wc2.is_commander"] = true
end
local x2,y2 = wesnoth.find_vacant_tile(x, y, u)
u:to_map(x2,y2)
return u
end
function wesnoth.wml_actions.wc2_random_hero(cfg)
local side_num = cfg.side or helper.wml_error("missing side= attribute in [wc2_initial_hero]")
local x = cfg.x or helper.wml_error("missing x= attribute in [wc2_initial_hero]")
local y = cfg.y or helper.wml_error("missing y= attribute in [wc2_initial_hero]")
local t = wc2_era.pick_deserter(side_num)
if t == nil then
print("No serserter available for side", side_num)
return
end
wc2_heroes.place(t, side_num, x, y)
end
-- prints the dialoge when @finder finds @found from a unit type, both parameters are lua unit objects.
function wc2_heroes.founddialouge(finder, found)
local type_dialogue = wc2_heroes.find_dialogue(found.type)
wesnoth.wml_actions.message {
id = found.id,
message = type_dialogue.founddialogue,
}
local reply = type_dialogue.reply or wc2_heroes.dialogues.default.reply
for i, alt_replay in ipairs(type_dialogue.alt_reply or {}) do
local function matches(attr)
return string.match(alt_replay[attr] or "", finder[attr])
end
if matches("race") or matches("gender") or matches("type") then
reply = alt_replay.reply
end
end
wesnoth.wml_actions.message {
id = finder.id,
message = reply,
}
end
wc2_heroes.init_data()
return wc2_heroes

View file

@ -0,0 +1,178 @@
local on_event = wesnoth.require("on_event")
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local wc2_invest = {}
function wc2_invest.add_items(side_num, num_items)
local side = wesnoth.sides[side_num]
local items_left = wc2_utils.split_to_array(side.variables["wc2.items_left"])
local items_available = wc2_utils.split_to_array(side.variables["wc2.items"])
for j = 1, num_items do
local i = wesnoth.random(#items_left)
table.insert(items_available, items_left[i])
table.remove(items_left, i)
end
side.variables["wc2.items_left"] = table.concat(items_left, ",")
side.variables["wc2.items"] = table.concat(items_available, ",")
end
function wc2_invest.has_items(side_num)
local side = wesnoth.sides[side_num]
return side.variables["wc2.items"] ~= nil
end
function wc2_invest.initialize()
local all_items = {}
for i,v in ipairs(wc2_artifacts.get_artifact_list()) do
local not_available = wc2_utils.split_to_set(v.not_available or "")
if not not_available["player"] then
table.insert(all_items, i)
end
end
for side_num, side in ipairs(wesnoth.sides) do
if wc2_scenario.is_human_side(side_num) then
if not wc2_invest.has_items(side_num) then
side.variables["wc2.items_left"] = table.concat(all_items, ",")
wc2_invest.add_items(side_num, 9)
else
wc2_invest.add_items(side_num, 1)
end
end
end
end
on_event("prestart", function()
wc2_invest.initialize()
end)
local function find_index(t, v)
for i,v2 in ipairs(t) do
if v2 == v then return i end
end
end
function wc2_invest.do_gold()
local side_num = wesnoth.current.side
local side = wesnoth.sides[side_num]
local leaders = wesnoth.get_units { side = side_num, canrecruit = true }
side.gold = side.gold + 70
wesnoth.wml_actions.wc2_map_supply_village {
x = leaders[1].x,
y = leaders[1].y
}
end
function wc2_invest.do_hero(t, is_local)
local side_num = wesnoth.current.side
local side = wesnoth.sides[side_num]
local leaders = wesnoth.get_units { side = side_num, canrecruit = true }
local x,y = leaders[1].x, leaders[1].y
if t == "wc2_commander" then
local commanders = wc2_utils.split_to_array(side.variables["wc2.commanders"])
local i = wesnoth.random(#commanders)
t = commanders[i]
table.remove(commanders, i)
side.variables["wc2.commanders"] = table.concat(commanders, ",")
if is_local then
wc2_invest_tellunit.execute(t)
end
wc2_heroes.place(t, side_num, x, y, true)
elseif t == "wc2_deserter" then
wesnoth.sides[side_num].gold = wesnoth.sides[side_num].gold + 15
local deserters = wc2_utils.split_to_array(side.variables["wc2.deserters"])
local i = wesnoth.random(#deserters)
t = deserters[i]
table.remove(deserters, i)
side.variables["wc2.deserters"] = table.concat(deserters, ",")
if is_local then
wc2_invest_tellunit.execute(t)
end
wc2_heroes.place(t, side_num, x, y, false)
else
local heroes_available = wc2_utils.split_to_array(side.variables["wc2.heroes"])
local i = find_index(heroes_available, t)
if i == nil then
error("wc2 invest: invalid pick")
end
table.remove(heroes_available, i)
side.variables["wc2.heroes"] = table.concat(heroes_available, ",")
wc2_heroes.place(t, side_num, x, y, false)
end
end
function wc2_invest.do_training(t)
local side_num = wesnoth.current.side
wc2_training.inc_level(side_num, t)
end
function wc2_invest.do_item(t)
local side_num = wesnoth.current.side
local side = wesnoth.sides[side_num]
local leaders = wesnoth.get_units { side = side_num, canrecruit = true }
local x,y = leaders[1].x, leaders[1].y
local items_available = wc2_utils.split_to_array(side.variables["wc2.items"], {}, tonumber)
local i = find_index(items_available, tostring(t))
if i == nil then
error("wc2 invest: invalid item pick '" .. t .. "' (" .. type(t) ..")")
end
table.remove(items_available, i)
side.variables["wc2.items"] = table.concat(items_available, ",")
wc2_artifacts.place_item(x, y + 1, t)
end
function wc2_invest.invest()
local side_num = wesnoth.current.side
local side = wesnoth.sides[side_num]
local items_available = wc2_utils.split_to_array(side.variables["wc2.items"])
local heroes_available = wc2_utils.split_to_array(side.variables["wc2.heroes"])
local commanders_available = wc2_utils.split_to_array(side.variables["wc2.commanders"])
local deserters_available = wc2_utils.split_to_array(side.variables["wc2.deserters"])
local trainings_available = wc2_training.list_available(side_num, {2,3,4,5,6})
local gold_available = true
for i =1,2 do
local is_local = false
local res = wesnoth.synchronize_choice(_"WC2 Invest", function()
is_local = true
return wc2_show_invest_dialog {
items_available = items_available,
heroes_available = heroes_available,
trainings_available = trainings_available,
gold_available = gold_available,
deserters_available = deserters_available,
commanders_available = commanders_available,
}
end)
if res.pick == "gold" then
wc2_invest.do_gold()
gold_available = nil
elseif res.pick == "hero" then
wc2_invest.do_hero(res.type, is_local)
heroes_available = nil
elseif res.pick == "training" then
wc2_invest.do_training(res.type)
trainings_available = nil
elseif res.pick == "item" then
wc2_invest.do_item(res.type)
items_available = nil
else
error("wc2 invest: invalid pick , pick='" .. tostring(res.pick) .. "'.")
end
end
end
function wesnoth.wml_actions.wc2_invest(cfg)
--disallow undoing.
wesnoth.random(100)
wc2_invest.invest()
end
return wc2_invest

View file

@ -0,0 +1,331 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local T = wml.tag
local function GUI_FORCE_WIDGET_MINIMUM_SIZE(w,h, content)
return T.stacked_widget {
definition = "default",
T.stack {
T.layer {
T.row {
T.column {
T.spacer {
definition = "default",
width = w,
height = h
}
}
}
},
T.layer {
T.row {
grow_factor = 1,
T.column {
grow_factor = 1,
horizontal_grow = "true",
vertical_grow = "true",
content
}
}
}
}
}
end
local dialog_wml = {
maximum_width = 1200,
maximum_height = 700,
T.helptip { id = "tooltip_large" }, -- mandatory field
T.tooltip { id = "tooltip_large" }, -- mandatory field
T.linked_group { id = "list_image", fixed_width = true },
T.linked_group { id = "unit_panel", fixed_width = true },
T.grid {
T.row {
grow_factor = 1,
T.column {
border = "all",
border_size = 5,
horizontal_alignment = "left",
T.label {
definition = "title",
label = _"Invest",
id = "title"
}
}
},
T.row {
grow_factor = 1,
T.column {
horizontal_grow = true,
vertical_grow = true,
T.grid {
T.row {
T.column {
border = "all",
border_size = 5,
horizontal_grow = true,
vertical_grow = true,
T.tree_view {
id = "left_tree",
definition = "default",
horizontal_scrollbar_mode = "never",
vertical_scrollbar_mode = "initial_auto",
indentation_step_size = 30,
T.node {
id = "category",
T.node_definition {
T.row {
T.column {
grow_factor = 0,
horizontal_grow = true,
T.toggle_button {
id = "tree_view_node_toggle",
definition = "tree_view_node",
},
},
T.column {
grow_factor = 1,
horizontal_grow = true,
T.grid {
T.row {
T.column {
horizontal_alignment = "left",
T.label {
id = "category_name",
},
},
},
},
},
},
},
},
T.node {
id = "item_desc",
T.node_definition {
T.row {
T.column {
grow_factor = 1,
horizontal_grow = true,
T.toggle_panel {
id = "tree_view_node_label",
T.grid {
T.row {
T.column {
grow_factor = 0,
horizontal_alignment = "left",
T.image {
id = "image",
linked_group = "list_image",
},
},
T.column {
horizontal_grow = true,
grow_factor = 1,
T.grid {
T.row {
T.column {
grow_factor = 1,
horizontal_alignment = "left",
T.label {
id = "name",
},
},
},
T.row {
T.column {
grow_factor = 1,
horizontal_alignment = "left",
T.label {
use_markup = true,
id = "desc",
},
},
},
},
},
},
},
},
},
},
},
},
T.node {
id = "item",
T.node_definition {
T.row {
T.column {
grow_factor = 1,
horizontal_grow = true,
T.toggle_panel {
id = "tree_view_node_label",
T.grid {
T.row {
T.column {
grow_factor = 0,
T.image {
id = "image",
linked_group = "list_image",
},
},
T.column {
horizontal_alignment = "left",
grow_factor = 1,
T.grid {
T.row {
T.column {
horizontal_alignment = "left",
T.label {
id = "name",
use_markup = true,
},
},
},
},
},
},
},
},
},
},
},
},
},
},
T.column { vertical_grow = true, T.grid { T.row {
T.column {
vertical_grow = true,
T.multi_page {
id = "details",
definition = "default",
horizontal_scrollbar_mode = "never",
vertical_grow = true,
T.page_definition {
T.row {
T.column {
horizontal_grow = true,
vertical_grow = true,
T.scroll_label {
id = "label",
label = "Text",
use_markup = true,
},
},
},
},
T.page_definition {
id = "hero",
T.row {
T.column {
vertical_grow = true,
T.unit_preview_pane {
definition = "default",
id = "unit",
linked_group = "unit_panel",
} ,
},
},
},
T.page_definition {
id = "trailing",
--T.row { T.column { T.size_lock { width = 600, height = 900, T.widget { T.grid {
--[[
T.row {
T.column {
horizontal_grow = true,
vertical_grow = true,
T.label {
label = "Before:",
},
},
},
T.row {
T.column {
horizontal_grow = true,
vertical_grow = true,
T.scroll_label {
id = "training_before",
use_markup = true,
},
},
},
T.row {
T.column {
horizontal_grow = true,
vertical_grow = true,
T.label {
label = "After:",
},
},
},
T.row {
T.column {
horizontal_grow = true,
vertical_grow = true,
T.scroll_label {
id = "training_after",
use_markup = true,
},
},
},
--]]
T.row {
T.column {
horizontal_grow = true,
vertical_grow = true,
T.scroll_label {
id = "details",
use_markup = true,
},
},
},
--},},},},},
},
},
},
},
T.row {
T.column {
horizontal_alignment = "center",
T.button {
definition = "really_large",
label = "Get This Item",
id = "ok",
}
}
}
},},
},
},
},
},
--[[
T.row {
T.column {
horizontal_grow = true,
T.grid {
T.row {
T.column {
grow_factor = 1,
T.spacer {
}
},
T.column {
horizontal_alignment = "right",
T.button {
label = "Ok",
id = "ok",
}
}
}
}
}
}
--]]
}
}
return dialog_wml

View file

@ -0,0 +1,178 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local dialog_wml = wc2_invest_dialog
function wc2_show_invest_dialog_impl(args)
local side_num = wesnoth.current.side
local available_artifacts = args.items_available
local available_heroes = args.heroes_available
local available_deserters = args.deserters_available
local available_commanders = args.commanders_available
local available_training = args.trainings_available
local show_artifacts = args.items_available ~= nil
local show_heroes = args.heroes_available ~= nil
local show_training = args.trainings_available ~= nil
local show_other = args.gold_available
local cati_items, cati_heroes, cati_training, cati_other
local res = nil
local index_map = {}
local details_index_counter = 1
local function add_index(page, r)
index_map[page] = {page_num = details_index_counter, res = r}
details_index_counter = details_index_counter + 1
if res == nil then
res = r
end
end
local function preshow()
local cati_current = 0
if show_artifacts then
cati_current = cati_current + 1
wesnoth.add_dialog_tree_node("category", cati_current, "left_tree")
wesnoth.set_dialog_value(true, "left_tree", cati_current)
wesnoth.set_dialog_value(_ "Artifacts", "left_tree", cati_current, "category_name")
for i,v in ipairs(available_artifacts) do
local artifact_info = wc2_artifacts.get_artifact(tonumber(v))
if not artifact_info then
error("invalid item id'" .. v .. "'")
end
wesnoth.add_dialog_tree_node("item_desc", i, "left_tree", cati_current)
wesnoth.set_dialog_value(artifact_info.icon, "left_tree", cati_current, i, "image")
wesnoth.set_dialog_value(artifact_info.name, "left_tree", cati_current, i, "name")
wesnoth.set_dialog_value(wc2_color.tc_text(artifact_info.description), "left_tree", cati_current, i, "desc")
wesnoth.add_dialog_tree_node("", -1, "details")
wesnoth.set_dialog_value(artifact_info.info, "details", details_index_counter, "label")
add_index(cati_current .. "_" .. i, { pick = "item", type=v })
end
end
if show_heroes then
cati_current = cati_current + 1
wesnoth.add_dialog_tree_node("category", cati_current, "left_tree")
wesnoth.set_dialog_value(true, "left_tree", cati_current)
wesnoth.set_dialog_value(_ "Heroes", "left_tree", cati_current, "category_name")
local i = 1
if available_commanders then
local desc = _ "Commanders will take your leaders place when the leader dies, possible commanders:"
for j,v in ipairs(available_commanders) do
desc = desc .. "\n" .. wesnoth.unit_types[v].name
end
wesnoth.add_dialog_tree_node("item", i, "left_tree", cati_current)
wesnoth.set_dialog_value(wc2_color.tc_image("units/unknown-unit.png"), "left_tree", cati_current, i, "image")
wesnoth.set_dialog_value(_ "Commander" .. "\n" .. wc2_color.tc_text(_ "promote to leader"), "left_tree", cati_current, i, "name")
wesnoth.add_dialog_tree_node("", -1, "details")
wesnoth.set_dialog_value(desc, "details", details_index_counter, "label")
add_index(cati_current .. "_" .. i, { pick = "hero", type="wc2_commander" })
i = i + 1
end
for j,v in ipairs(available_heroes) do
unit_type = wesnoth.unit_types[v]
wesnoth.add_dialog_tree_node("item", i, "left_tree", cati_current)
wesnoth.set_dialog_value(wc2_color.tc_image(unit_type.image), "left_tree", cati_current, i, "image")
wesnoth.set_dialog_value(unit_type.name, "left_tree", cati_current, i, "name")
wesnoth.add_dialog_tree_node("hero", -1, "details")
wesnoth.set_dialog_value(unit_type, "details", details_index_counter, "unit")
add_index(cati_current .. "_" .. i, { pick = "hero", type=v })
i = i + 1
end
if available_deserters then
local desc = "<b>" .. _ "possible units:" .. "</b>"
for j,v in ipairs(available_deserters) do
desc = desc .. "\n" .. wesnoth.unit_types[v].name
end
wesnoth.add_dialog_tree_node("item", i, "left_tree", cati_current)
wesnoth.set_dialog_value(wc2_color.tc_image("units/unknown-unit.png"), "left_tree", cati_current, i, "image")
wesnoth.set_dialog_value(_ "Deserter" .. "\n" .. wc2_color.tc_text("+15 gold"), "left_tree", cati_current, i, "name")
wesnoth.add_dialog_tree_node("", -1, "details")
wesnoth.set_dialog_value(desc, "details", details_index_counter, "label")
add_index(cati_current .. "_" .. i, { pick = "hero", type="wc2_deserter" })
end
end
if show_training then
cati_current = cati_current + 1
wesnoth.add_dialog_tree_node("category", cati_current, "left_tree")
wesnoth.set_dialog_value(true, "left_tree", cati_current)
wesnoth.set_dialog_value(_ "Training", "left_tree", cati_current, "category_name")
for i,v in ipairs(available_training) do
local current_grade = wc2_training.get_level(side_num, v)
local training_info = wc2_training.get_trainer(v)
local train_message = wc2_training.generate_message(v, current_grade + 1)
local train_message_before = wc2_training.generate_message(v, current_grade)
local title = wesnoth.format(_ "$name Training", { name = training_info.name })
local desc = wc2_training.describe_training_level2(current_grade, #training_info.grade) .. wc2_color.tc_text("") .. wc2_training.describe_training_level2(current_grade + 1, #training_info.grade)
wesnoth.add_dialog_tree_node("item_desc", i, "left_tree", cati_current)
wesnoth.set_dialog_value(training_info.image, "left_tree", cati_current, i, "image")
wesnoth.set_dialog_value(title, "left_tree", cati_current, i, "name")
wesnoth.set_dialog_value(desc, "left_tree", cati_current, i, "desc")
wesnoth.add_dialog_tree_node("", -1, "details")
local label = wc2_color.tc_text("<big>" .. _ "Before:" .. "</big>\n") .. train_message_before.message .. wc2_color.tc_text("\n<big>" .. _ "After:" .. "</big>\n") .. train_message.message
wesnoth.set_dialog_value(label , "details", details_index_counter, "label")
--wesnoth.set_dialog_value(train_message.message, "details", details_index_counter, "training_after")
add_index(cati_current .. "_" .. i, { pick = "training", type=v })
end
end
if show_other then
cati_current = cati_current + 1
wesnoth.add_dialog_tree_node("category", cati_current, "left_tree")
wesnoth.set_dialog_value(true, "left_tree", cati_current)
wesnoth.set_dialog_value(_ "Other", "left_tree", cati_current, "category_name")
local colored_galleon = wc2_color.tc_image("units/transport/transport-galleon.png")
local supplies_image = "misc/blank-hex.png~SCALE(90,80)~BLIT(" .. colored_galleon .. ",9,4)"
local supplies_text = wc2_color.tc_text(_ "+70 gold and +1 village")
--"+{STR_COLOR_PLAYER ("+70 "+{STR_GOLD}+{STR_AND}+"+1 "+{STR_VILLAGE})}
wesnoth.add_dialog_tree_node("item_desc", 1, "left_tree", cati_current)
wesnoth.set_dialog_value(supplies_image, "left_tree", cati_current, 1, "image")
wesnoth.set_dialog_value(_"Stock up supplies", "left_tree", cati_current, 1, "name")
wesnoth.set_dialog_value(supplies_text, "left_tree", cati_current, 1, "desc")
wesnoth.add_dialog_tree_node("", -1, "details")
wesnoth.set_dialog_value(_"Gives 70 gold and places a village on your keep.", "details", details_index_counter, "label")
add_index(cati_current .. "_" .. 1, { pick = "gold" })
end
wesnoth.set_dialog_callback(function()
local selected = wesnoth.get_dialog_value("left_tree")
local selected_data = index_map[table.concat(selected, '_')]
if selected_data ~= nil then
wesnoth.set_dialog_value(selected_data.page_num, "details")
end
res = selected_data.res
end, "left_tree")
end
local d_res = wesnoth.show_dialog(dialog_wml, preshow)
return d_res, res
end
function wc2_show_invest_dialog(args)
--do it in a loop to disable esc.
while true do
local d_res, res = wc2_show_invest_dialog_impl(args)
if d_res ~= -2 then
return res
end
end
end
return wc2_show_invest_dialog

View file

@ -0,0 +1,72 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local T = wml.tag
local invest_tellunit = {}
invest_tellunit.dialog_wml = {
maximum_width = 1200,
maximum_height = 700,
T.helptip { id = "tooltip_large" }, -- mandatory field
T.tooltip { id = "tooltip_large" }, -- mandatory field
T.grid {
T.row {
T.column {
border = "all",
border_size = 5,
horizontal_alignment = "left",
T.label {
definition = "title",
label = _"You got",
id = "title"
}
}
},
T.row {
T.column {
T.grid {
T.row {
T.column {
T.image {
id="icon"
}
},
},
T.row {
T.column {
T.label {
id="name"
}
},
},
},
},
},
T.row {
T.column {
T.button {
label = _"Ok",
id = "ok",
},
},
},
},
}
-- todo:maybe use a dialog ith the unit specific welcome mesage?
function invest_tellunit.execute(unit_type)
if type(unit_type) == "string" then
unit_type = wesnoth.unit_types[unit_type]
end
if not wesnoth.sides[wesnoth.current.side].is_local then
return
end
local function preshow()
wesnoth.set_dialog_value(wc2_color.tc_image(unit_type.image), "icon")
wesnoth.set_dialog_value(unit_type.name, "name")
end
wesnoth.show_dialog(invest_tellunit.dialog_wml, preshow)
end
return invest_tellunit

View file

@ -0,0 +1,98 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local T = wml.tag
local pickup_confirmation_dialog = {}
-- returns true when the item should be picked up.
local function show_dialog(unit, item_image)
if wc2_utils.global_vars.skip_pickup_dialog then
return 1
end
local dialog_wml = {
maximum_width = 1200,
maximum_height = 700,
T.helptip { id = "tooltip_large" }, -- mandatory field
T.tooltip { id = "tooltip_large" }, -- mandatory field
T.grid {
T.row {
T.column {
border = "all",
border_size = 5,
horizontal_alignment = "left",
T.label {
definition = "title",
label = _"Pick up item?",
id = "title",
},
},
},
T.row {
T.column {
T.grid {
T.row {
T.column {
T.image {
id="item_icon",
},
},
T.column {
T.label {
id="arrow",
use_markup=true
},
},
T.column {
T.image {
id="unit_icon",
},
},
},
},
},
},
T.row {
T.column {
T.grid {
T.row {
T.column {
T.button {
label = _"Yes (enter)",
id="res_yes",
return_value = 1,
},
},
T.column {
T.button {
label = _"No (esc)",
id="res_no",
return_value = 2
},
},
},
},
},
},
},
}
local function preshow()
wesnoth.set_dialog_value(wc2_color.tc_image(wesnoth.unit_types[unit.type].image), "unit_icon")
wesnoth.set_dialog_value(wc2_color.tc_text(""), "arrow")
wesnoth.set_dialog_value(item_image, "item_icon")
wesnoth.set_dialog_focus("res_yes")
end
local res = wesnoth.show_dialog(dialog_wml, preshow)
return res == 1 or res == -1
end
-- returns true when the item should be picked up.
function pickup_confirmation_dialog.promt_synced(unit, item_image)
local res = wesnoth.synchronize_choice("Item Pickup Choice", function()
return { take_item = show_dialog(unit, item_image) }
end)
return res.take_item
end
return pickup_confirmation_dialog

View file

@ -0,0 +1,39 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local on_event = wesnoth.require("on_event")
local strings = {
defeat = _ "No! This is the end!",
promotion = _ "Don't lose heart comrades, we can still win this battle."
}
-- when a leader dies, take a commonder and make him the leader.
on_event("die", function(cx)
local u = wesnoth.get_unit(cx.x1, cx.y1)
if (not u) or (not u:matches({ canrecruit = true })) then
return
end
local commander = wesnoth.get_units {
side = u.side,
role = "commander",
canrecruit = false
}
commander = commander[1]
if commander then
commander.canrecruit = true
commander:remove_modifications({ id = "wc2_commander_overlay" })
wesnoth.wml_actions.message {
id = commander.id,
message = strings.promotion
}
else
if u.side < 4 then
wesnoth.wml_actions.message {
side = "1,2,3",
message = strings.defeat
}
wesnoth.wml_actions.endlevel {
result = "defeat"
}
end
end
end)

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,17 @@
local function add_rc_object(u)
if not u.variables.wc2_has_recall_object then
u.variables.wc2_has_recall_object = true
u:add_modification("object", {
{"effect", {
apply_to = "wc2_recall_cost"
}},
})
end
end
-- the implementation of the addons reduces recall cost mechanic.
function wesnoth.wml_actions.wc2_set_recall_cost(cfg)
for i,u in ipairs(wesnoth.get_units { side = "1,2,3" }) do
add_rc_object(u)
end
end

View file

@ -0,0 +1,32 @@
local supply_images =
{
"misc/blank-hex.png~BLIT(items/straw-bale2.png~CROP(24,15,48,57))~BLIT(items/straw-bale1.png~CROP(0,9,72,63))",
"misc/blank-hex.png~BLIT(items/straw-bale1.png~CROP(8,15,64,57))~BLIT(items/leather-pack.png~CROP(0,10,62,62),10,0)~BLIT(items/leather-pack.png~CROP(0,0,69,72),3,0)",
"misc/blank-hex.png~BLIT(items/straw-bale2.png~CROP(19,18,53,54))~BLIT(items/straw-bale2.png~CROP(7,6,65,66))~BLIT(items/leather-pack.png~CROP(4,23,68,49))~BLIT(items/straw-bale2.png~CROP(7,15,65,57))",
-- custom image
"terrain/wct-supply2.png",
-- custom image
"terrain/wct-supply1.png",
"misc/blank-hex.png~BLIT(items/box.png~SCALE(54,54)~CROP(0,11,54,43),4,0)~BLIT(items/straw-bale2.png~CROP(5,24,67,48),0,24)~BLIT(items/leather-pack.png~CROP(0,9,63,63),9,0)",
"misc/blank-hex.png~BLIT(items/box.png~SCALE(54,54)~CROP(0,11,54,43),4,0)~BLIT(items/box.png~SCALE(54,54)~CROP(0,1,54,53),17,0)",
-- custom image
"terrain/wct-supply3.png~BLIT(items/box.png~SCALE(54,54)~CROP(0,1,54,53),17,0)",
}
function wesnoth.wml_actions.wc2_map_supply_village(t)
local unit = wesnoth.get_unit(t.x, t.y)
local loc = unit.loc
wesnoth.set_terrain(loc, "Kh^Vov", "overlay")
wesnoth.set_village_owner(loc, unit.side, false)
local supply_image = ((wml.variables.wc2_supply_image_counter or 0) % #supply_images ) + 1
wml.variables.wc2_supply_image_counter = supply_image
wesnoth.wml_actions.item {
x = loc[1],
y = loc[2],
image = supply_images[supply_image],
z_order = -10,
}
end

View file

@ -0,0 +1,284 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local on_event = wesnoth.require("on_event")
local helper = wesnoth.require("helper")
local training = {}
function training.add_training_data(a)
training.trainers = training.trainers or {}
table.insert(training.trainers, a)
end
function training.read_wml_data(cfg)
for i, t in ipairs(wc2_convert.wml_to_lon(cfg, "wct_trainer_list").trainer or {}) do
training.add_training_data(t)
end
end
function training.get_list()
if not training.trainers then
training.init_data()
end
return training.trainers
end
function training.init_data()
local cfg = wc2_utils.get_wc2_data("trainer")
for i, t in ipairs(wc2_convert.wml_to_lon(cfg, "wct_trainer_list").trainer or {}) do
training.add_training_data(t)
end
end
function training.get_trainer(trainer)
return training.get_list()[trainer]
end
function training.get_chances(trainer, grade)
return training.get_trainer(trainer).grade[grade + 1].chance
end
function training.apply_trait(unit, trait, check)
if u:matches(check) and u:matches( wml.tag.filter_wml { wml.tag.modifications { wml.tag.trait { id = trait.id } } } ) then
u:add_modification("trait", trait)
else
u:add_modification("object", { wml.tag.effect { apply_to = "hitpoints", increase_total = 1, heal_full = true}})
end
end
--the current level of a certain traing, a value of 0 means this skill wasn't trained yet.
function training.get_level(side_num, trainer)
return wesnoth.sides[side_num].variables["wc2.training[" .. trainer - 1 .. "].level"] or 0
end
function training.set_level(side_num, trainer, level)
wesnoth.sides[side_num].variables["wc2.training[" .. trainer - 1 .. "].level"] = level
end
function training.inc_level(side, trainer, level)
local new_level = training.get_level(side, trainer) + (level or 1)
if new_level < 0 or new_level >= #training.get_trainer(trainer).grade then
error("training level out of range")
end
training.set_level(side, trainer, new_level)
end
-- to be used by bonus points chance to extra taining.
function training.get_level_sum(side)
local res = 0
for i = 1, #training.get_list() do
res = res + training.get_level(side, i)
end
return res
end
function training.trainings_left(side_num, trainer)
return (#training.get_trainer(trainer).grade - 1) - training.get_level(side_num, trainer)
end
function training.available(side_num, trainer, amount)
return training.trainings_left(side_num, trainer) >= (amount or 1)
end
function training.has_max_training(side_num, trainer, amount)
return training.available(side_num, trainer) == 0
end
function training.list_available(side_num, among, amount)
local av = among or wc2_utils.range(#training.get_list())
local res = {}
for i,v in ipairs(av) do
local j = tonumber(v)
if training.available(side_num, j, amount) then
table.insert(res, j)
end
end
return res
end
function training.find_available(side_num, among, amount)
local possible_traintypes = training.list_available(side_num, among, amount)
if #possible_traintypes == 0 then
return
else
return possible_traintypes[wesnoth.random(#possible_traintypes)]
end
end
function training.describe_training_level(name, level, max_level)
if level == max_level then
return tostring(wesnoth.format(_ "$name Training Maximum Level", {
name = name
}))
else
return tostring(wesnoth.format(_ "$name Training level $level", {
name = name,
level = level
}))
end
end
function training.describe_training_level2(level, max_level)
if level == max_level then
return _ "Maximum Level"
else
return tostring(wesnoth.format(_ "level $level", {
level = level
}))
end
end
function training.generate_message(n_trainer, n_grade)
local c_trainer = training.get_trainer(n_trainer)
local c_grade = c_trainer.grade[n_grade + 1]
if c_grade == nil then
return { message = "" }
end
local caption = training.describe_training_level(c_trainer.name, n_grade, #c_trainer.grade - 1)
local messages = {}
for unused, chance in ipairs(c_grade.chance) do
local vchance = chance.variable_substitution ~= false and wesnoth.tovconfig(chance) or chance
if (chance.value or 0) < 100 then
local str = wesnoth.format(_ "$chance| chance to $arrow $desc", {
chance = ("%d%%"):format(vchance.value),
desc = wc2_utils.get_fstring(chance, "info"),
arrow = wc2_color.tc_text("")
})
table.insert(messages, tostring(str))
else
table.insert(messages, tostring(wc2_utils.get_fstring(chance, "info")))
end
end
return {
caption = caption,
message = table.concat(messages, "\n"),
speaker = "narrator",
image = c_trainer.image,
}
end
function training.give_bonus(side_num, cx, amount, traintype_index)
local traintype = training.get_trainer(traintype_index)
local cur_level = training.get_level(side_num, traintype_index)
local new_level = cur_level + amount
local teacher = wc2_heroes.place(amount > 1 and traintype.advanced_type or traintype.type, side_num, cx.x1,cx.y1)
local u = wesnoth.get_unit(cx.x1, cx.y1)
wc2_utils.facing_each_other(u, teacher)
wesnoth.wml_actions.sound {
name = "flail-miss.ogg"
}
wesnoth.wml_actions.message {
speaker = teacher.id,
message = traintype.dialogue,
}
wesnoth.extract_unit(teacher)
local message = training.generate_message(traintype_index, new_level)
wesnoth.wml_actions.message(message)
training.inc_level(side_num, traintype_index, amount)
return true
end
function training.bonus_calculate_amount(side_num)
local amount = 1
local advanced_chance = 4 * training.get_level_sum(side_num)
if wc2_scenario.scenario_num() > 3 or wesnoth.random(100) <= advanced_chance then
amount = 2
end
return amount
end
function training.pick_bonus(side_num)
local amount = training.bonus_calculate_amount(side_num)
-- dark training reduced chances
local traintype_index = training.find_available(side_num, {1,2,3,4,5,6,2,3,4,5,6,2,3,4,5,6}, amount)
if traintype_index == nil then
return nil
end
--dark training increased level.
if traintype_index == 1 then
amount = math.min(training.trainings_left(side_num, traintype_index), math.max(amount, wc2_scenario.scenario_num() - 1))
end
return traintype_index, amount
end
on_event("recruit", function(event_context)
training.apply(wesnoth.get_unit(event_context.x1, event_context.y1))
end)
function training.apply(u)
if not u then
return
end
local side = u.side
local trait = {}
local descriptions = {}
trait.male_name = _ "trained"
trait.female_name = _ "female^trained"
trait.generate_description = false
for i, trainer in ipairs(training.get_list()) do
local level = training.get_level(side, i) or 0
for unused, chance in ipairs(training.get_chances(i, level)) do
--some effects use expressions like $(5+{GRADE}) so we want variable_substitution there
local vchance = wesnoth.tovconfig(chance)
local filter = wml.get_child(vchance, "filter")
local matches_filter = (not filter) or u:matches(filter)
if wesnoth.random(100) <= vchance.value and matches_filter then
--wesnoth.wml_actions.message { message = "Got it" }
table.insert(descriptions, wc2_utils.get_fstring(chance, "info"))
for effect in helper.child_range(vchance, "effect") do
table.insert(trait, {"effect", effect })
end
end
end
end
trait.description = wc2_utils.concat(descriptions, "\n")
if #trait > 0 then
u:add_modification("trait", trait)
--rebuild unit, to reduce savefile size.
u:transform(u.type)
end
u.variables.wc2_trained = true
u.hitpoints = u.max_hitpoints
end
function wesnoth.wml_actions.wc2_apply_training(cfg)
for i,u in ipairs(wesnoth.get_units(cfg)) do
training.apply(u)
end
end
function wesnoth.wml_actions.wc2_give_random_training(cfg)
local side_num = cfg.side
local amount = cfg.amount or 1
local among = cfg.among and wc2_utils.split_to_array(cfg.among)
for i = 1, amount do
local traintype = training.find_available(side_num, among)
if traintype == nil then error("wc2_give_random_training: everything alerady maxed") end
training.inc_level(side_num, traintype, 1)
end
end
function training.describe_bonus(side, traintype)
local traintype_data = training.get_trainer(traintype)
local cur_level = training.get_level(side, traintype)
local max_level = #traintype_data.grade - 1
local image = wesnoth.unit_types[traintype_data.type].__cfg.image
local message = nil
if cur_level == max_level then
message = _"Nothing to learn here"
else
message = wesnoth.format(_"From $level_before to $level_after", {
level_before = training.describe_training_level(traintype_data.name, cur_level, max_level),
level_after = training.describe_training_level(traintype_data.name, cur_level + 1, max_level)
})
end
return message, image
end
return training

View file

@ -0,0 +1,404 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
type_infos = {
["default"] = {
founddialogue = _"You guys look like you could use some help. Mind if I join in? It's been a while since I had a good fight!",
reply = _ "Excellent. We could always use more help.",
},
["Orcish Grunt"] = {
founddialogue=_"'bout time. Been forever since I had a good fight, eh?",
image="units/orcs/grunt.png",
name="Orcish Grunt",
},
["Troll Whelp"] = {
founddialogue=_"Who you? I help you smash!",
image="units/trolls/whelp.png",
name="Troll Whelp",
},
["Orcish Archer"] = {
founddialogue=_"My clan was destroyed long ago, leaving me to fend for myself. Let me join your army and I will fight as though your clan was my own!",
image="units/orcs/archer.png",
name="Orcish Archer",
},
["Orcish Assassin"] = {
founddialogue=_"Heya, boss. Looks like you've got some guys need killing.",
image="units/orcs/assassin.png",
name="Orcish Assassin",
},
["Wolf Rider"] = {
founddialogue=_"I hunts. I join you, I hunts good for you!",
image="units/goblins/wolf-rider.png",
name="Wolf Rider",
alt_reply = { {
race="wose",
reply=_"Ok. But take care where your dog does its stuff.",
} }
},
["Orcish Leader"] = {
founddialogue=_"Heh, looks like you whelps might be getting in over your heads. Good thing I'm here now to win this fight for ya, huh?",
image="units/orcs/leader.png",
name="Orcish Leader",
},
["Naga Fighter"] = {
founddialogue=_"I too have come a long way to this strange land. Perhaps we were destined to join blades here.",
image="units/nagas/fighter.png",
name="Naga Fighter",
alt_reply = { {
race="gryphon",
reply=_"Looks like we fished some tasty help.",
} }
},
["Mage"] = {
image="units/human-magi/mage.png",
name="Mage",
},
["Elvish Fighter"] = {
founddialogue=_"Need a friendly blade?",
image="units/elves-wood/fighter.png",
name="Elvish Fighter",
},
["Elvish Archer"] = {
founddialogue=_"You guys look like you could use some help. Mind if I join in? It's been a while since I had a good fight!",
image="units/elves-wood/archer.png",
name="Elvish Archer",
},
["Elvish Shaman"] = {
founddialogue=_"The mother forest sends you her blessings. Let us join together against her foes.",
image="units/elves-wood/shaman.png",
name="Elvish Shaman",
alt_reply = { {
race="elf,wose",
reply=_"Yea, flower power!",
} }
},
["Elvish Scout"] = {
founddialogue=_"I offer you the service of my arrows and my steed. You will find none that fly faster than either.",
image="units/elves-wood/scout/scout.png",
name="Elvish Scout",
},
["Wose"] = {
founddialogue=_"Hmm! Welcome, tree-friends. We will pound our enemies into dust!",
image="units/woses/wose.png",
name="Wose",
},
["Merman Hunter"] = {
founddialogue=_"Greetings, friends. I am a lone hunter and have no legions of warriors to offer you, but I will gladly lend my arms to your cause.",
image="units/merfolk/hunter.png",
name="Merman Hunter",
alt_reply = { {
race="gryphon",
reply=_"Looks like we fished some tasty help.",
} }
},
["Mermaid Initiate"] = {
founddialogue=_"You have come a long way over the ocean, yet I see that you know little of her ways. Let me show you.",
image="units/merfolk/initiate.png",
name="Mermaid Initiate",
alt_reply = { {
race="gryphon",
reply=_"Looks like we fished some tasty help.",
} }
},
["Cavalryman"] = {
founddialogue=_"You're not from around here, but I seem to find myself between employers at the moment and I'm not picky. I'll fight for you, if you'll have me.",
image="units/human-loyalists/cavalryman/cavalryman.png~CROP(14,14,72,72)",
name="Cavalryman",
alt_reply = { {
gender="female",
reply=_"Of course. How could a girl say no to a man riding a horse?",
} }
},
["Horseman"] = {
founddialogue=_"Hurrah! Now THIS is a battle too grand to be missed. Save some for me, eh?",
image="units/human-loyalists/horseman/horseman.png",
name="Horseman",
alt_reply = { {
gender="female",
reply=_"Of course. How could a girl say no to a man riding a horse?",
} }
},
["Spearman"] = {
founddialogue=_"Ho there, friends! I am but a soldier of humble circumstances, yet long have I dreamed of joining great wars beyond our shores. Let me join your mission!",
image="units/human-loyalists/spearman.png",
name="Spearman",
},
["Fencer"] = {
founddialogue=_"Looks like you're a bit down on your luck, my friends. But now that I am here, there's nothing to worry about!",
image="units/human-loyalists/fencer.png",
name="Fencer",
},
["Heavy Infantryman"] = {
founddialogue=_"Finally reinforcements are here! I've been pinned down for days. Help me fight my way out of here and I'll gladly follow you!",
image="units/human-loyalists/heavyinfantry.png",
name="Heavy Infantryman",
},
["Bowman"] = {
founddialogue=_"Greetings, my lords. I have watched your battle from afar and yearn to join such a glorious campaign. I pledge myself to your service!",
image="units/human-loyalists/bowman.png",
name="Bowman",
},
["Sergeant"] = {
founddialogue=_"You're not from around here, but I seem to find myself between employers at the moment and I'm not picky. I'll fight for you, if you'll have me.",
image="units/human-loyalists/sergeant.png",
name="Sergeant",
},
["Mage"] = {
founddialogue=_"Long have I studied the ways of lore, and I have much wisdom to offer. Allow me to guide you on your quest and together we will accomplish great things!",
image="units/human-magi/mage.png",
name="Mage",
},
["Merman Fighter"] = {
founddialogue=_"I bring greetings from the merfolk. We have heard your plight, and though we have few warriors to spare among us, I would gladly lend my trident to your cause.",
image="units/merfolk/fighter.png",
name="Merman Fighter",
alt_reply = { {
race="gryphon",
reply=_"Looks like we fished some tasty help.",
} }
},
["Dwarvish Fighter"] = {
founddialogue=_"Having trouble, eh? Never worry, lads, we'll sort 'em out soon enough!",
image="units/dwarves/fighter.png",
name="Dwarvish Fighter",
},
["Thief"] = {
founddialogue=_"You've got me, guv, it's a fair cop! Just lemme work for you instead. You won't regret it, guv, I promise!",
image="units/human-outlaws/thief.png",
name="Thief",
},
["Dwarvish Thunderer"] = {
founddialogue=_"Listen up, ye primitive screwheads! This... is me BOOM STICK. Lemme show you what this baby can do!",
image="units/dwarves/thunderer/thunderer.png",
name="Dwarvish Thunderer",
},
["Poacher"] = {
founddialogue=_"What, you want my help? A guy like me? Huh, that's rich. Oh well... let's give it a shot, eh?",
image="units/human-outlaws/poacher.png",
name="Poacher",
},
["Dwarvish Guardsman"] = {
founddialogue=_"A soldier is no good without something to fight for. Let me fight for you!",
image="units/dwarves/guard.png",
name="Dwarvish Guardsman",
},
["Footpad"] = {
founddialogue=_"Hey, hey, easy there! I done nothin' to hurt you. We're all friends here, right? Looks like you might be in a tight spot, but don't worry. No one's better at getting out of tight spots than me, boss!",
image="units/human-outlaws/footpad.png",
name="Footpad",
},
["Dwarvish Ulfserker"] = {
founddialogue=_"Chin up, lads. Today is a good day to die!",
image="units/dwarves/ulfserker.png",
name="Dwarvish Ulfserker",
alt_reply = { {
race="dwarf",
reply=_"Brave words. Welcome to The Fight Club...",
}, {
race="human",
reply=_"Brave words. Welcome little big man.",
} }
},
["Gryphon Rider"] = {
founddialogue=_"Need a hand? Me an' me bird can get just about anywheres you need.",
image="units/dwarves/gryphon-rider.png",
name="Gryphon Rider",
alt_reply = { {
race="merman,naga",
reply=_"Sounds good. You scared me for a moment.",
}, {
race="gryphon,bats",
reply=_"Cool. We could always need more air power.",
} }
},
["Dwarvish Scout"] = {
founddialogue=_"Having trouble, eh? Never worry, lads, we'll sort 'em out soon enough!",
image="units/dwarves/scout.png",
name="Dwarvish Scout",
},
["Drake Fighter"] = {
founddialogue=_"The ancient spirits tell me my destiny lies with yours. My sword is at your command.",
image="units/drakes/fighter.png",
name="Drake Fighter",
},
["Drake Clasher"] = {
founddialogue=_"Stand fast, for I bring you the strength of dragons to assist you in your battle!",
image="units/drakes/clasher.png",
name="Drake Clasher",
},
["Drake Burner"] = {
founddialogue=_"Today is a most auspicious day for you, for I deem you worthy of the power of dragonfire. Show me your foes and I will incinerate them!",
image="units/drakes/burner.png",
name="Drake Burner",
alt_reply = { {
race="drake",
reply=_"Perfect. We can always use more fire power.",
} }
},
["Saurian Augur"] = {
founddialogue=_"You no fight good enough, no have saurian way. I show you way of saurian!",
image="units/saurians/augur/augur.png",
name="Saurian Augur",
alt_reply = { {
race="lizard",
reply=_"Sure, bro...",
} }
},
["Drake Glider"] = {
founddialogue=_"You may be out to take over the land and the seas, but you'll never get anywhere without control of the skies. Fortunately I'm here to help you!",
image="units/drakes/glider.png",
name="Drake Glider",
alt_reply = { {
race="gryphon,bats",
reply=_"Cool. We could always need more air power.",
} }
},
["Saurian Skirmisher"] = {
founddialogue=_"Tribe fall long time ago, now tribe lost. This last fight of tribe. I fight with you, make last very great!",
image="units/saurians/skirmisher/skirmisher.png",
name="Saurian Skirmisher",
},
["Skeleton"] = {
founddialogue=_"Don't hit me! I'm just your average regular friendly talking skeleton, see? Looks like you fellows could use some help!",
image="units/undead-skeletal/skeleton/skeleton.png",
name="Skeleton",
},
["Skeleton Archer"] = {
founddialogue=_"I am called forth from eternal rest, bound to follow he who called me. Show me the enemy, master!",
image="units/undead-skeletal/archer.png",
name="Skeleton Archer",
},
["Ghoul"] = {
founddialogue=_"I say, old sport! It looks like you've got a spot of bother. Well, chin up, I say! I'm sure we'll make a simply smashing team-up. We can sort this lot out and be done by tea, what?",
image="units/undead/ghoul.png",
name="Ghoul",
reply=_"Have at thee, unholy abomin... wait, huh?",
alt_reply = { {
race="undead,bats",
reply=_"Excellent. We could always use more help.",
} }
},
["Dark Adept"] = {
founddialogue=_"You may not trust me or my reasons, but it seems you are not in a position to be choosy about your allies. Let me assist you and you just may survive.",
image="units/undead-necromancers/adept.png",
name="Dark Adept",
},
["Ghost"] = {
founddialogue=_"Who calls me from my slumber? I sense a great battle being joined. Point me towards the enemy and I will feast upon their very souls!",
image="units/undead/ghost-s-2.png",
name="Ghost",
},
["Vampire Bat"] = {
founddialogue=_"Skreeeeeeee!",
image="units/undead/bat-se-3.png",
name="Vampire Bat",
reply=_"This creature seems unusually intelligent for its kind. Perhaps it will help us!",
alt_reply = { {
race="undead,bats",
reply=_"Excellent. We could always use more help.",
} }
},
["Young Ogre"] = {
founddialogue=_"You friend are? I friend help!",
image="units/ogres/young-ogre.png",
name="Young Ogre",
alt_reply = { {
race="ogre,troll",
reply=_"Me friend. We can play together.",
} }
},
["Thug"] = {
founddialogue=_"What, you want my help? A guy like me? Huh, that's rich. Oh well... let's give it a shot, eh?",
image="units/human-outlaws/thug.png",
name="Thug",
},
["Goblin Spearman"] = {
founddialogue=_"Ah, please no hurtings me! I helps you, see?",
image="units/goblins/spearman.png",
name="Goblin Spearman",
reply=_"Fine. We could need a small help.",
alt_reply = { {
race="orc,troll,dwarf,ogre,gryphon,wolf",
reply=_"Excellent. We could always need cannon fodder.",
}, {
race="goblin",
reply=_"Excellent. We could always use more help.",
} }
},
["Walking Corpse"] = {
founddialogue=_"...",
image="units/undead/zombie.png",
name="Walking Corpse",
reply=_"Odd, it doesn't seem to attack. I wonder if we can use it?",
alt_reply = { {
race="undead,bats",
reply=_"Excellent. We could always use more help.",
type="Dark Adept,Dark Sorcerer,Necromancer,Lich",
} }
},
["Ruffian"] = {
founddialogue=_"Oooh oooh oooh! I want to help! Pick me, pick me!",
name="Ruffian",
reply=_"...fine. I guess.",
alt_reply = { {
race="human",
reply=_"Excellent. We could always use more help.",
} }
},
["Peasant"] = {
founddialogue=_"Oooh oooh oooh! I want to help! Pick me, pick me!",
name="Peasant",
reply=_"...fine. I guess.",
alt_reply = { {
race="human",
reply=_"Excellent. We could always use more help.",
} }
},
["Woodsman"] = {
founddialogue=_"Ho there, friends! I am but a soldier of humble circumstances, yet long have I dreamed of joining great wars beyond our shores. Let me join your mission!",
name="Woodsman",
},
["Dune Herbalist"] = {
founddialogue=_"Long have I studied the ways of lore, and I have much wisdom to offer. Allow me to guide you on your quest and together we will accomplish great things!",
image="units/dunefolk/herbalist.png",
name="Dune Herbalist",
},
["Dune Soldier"] = {
founddialogue=_"I too have come a long way to this strange land. Perhaps we were destined to join blades here.",
image="units/dunefolk/soldier.png",
name="Dune Soldier",
},
["Dune Rover"] = {
founddialogue=_"Ho there, friends! I am but a soldier of humble circumstances, yet long have I dreamed of joining great wars beyond our shores. Let me join your mission!",
image="units/dunefolk/rover.png",
name="Dune Rover",
},
["Dune Piercer"] = {
founddialogue=_"Heh, looks like you whelps might be getting in over your heads. Good thing I'm here now to win this fight for ya, huh?",
image="units/dunefolk/piercer.png",
name="Dune Piercer",
},
["Dune Burner"] = {
founddialogue=_"You may not trust me or my reasons, but it seems you are not in a position to be choosy about your allies. Let me assist you and you just may survive.",
image="units/dunefolk/burner.png",
name="Dune Burner",
},
["Dune Rider"] = {
founddialogue=_"A soldier is no good without something to fight for. Let me fight for you!",
image="units/dunefolk/rider.png",
name="Dune Rider",
},
}
return type_infos
-- generated vai regex from original data:
-- regex1:
-- \[[A-Z][a-zA-Z_]+\](.*?)type="([A-Za-z_ ]+)"\r\n(.*?)\[/[A-Z][a-zA-Z_]+\]
-- to
-- ["\2"] = { \1 \3}
--
-- regex2:
-- \[alt_reply\](.*?)\[/alt_reply\]
-- to
-- alt_reply = { { \1 } }
-- + handfix to fix trypes with nultiple alt replies.

View file

@ -0,0 +1,266 @@
local on_event = wesnoth.require("on_event")
local wc2_utils = {}
function wc2_utils.split_to_array(s, res)
res = res or {}
for part in tostring(s or ""):gmatch("[^%s,][^,]*") do
table.insert(res, part)
end
return res
end
function wc2_utils.split_to_set(s, res)
res = res or {}
for part in tostring(s or ""):gmatch("[^%s,][^,]*") do
res[part] = true
end
return res
end
function wc2_utils.set_to_array(s, res)
res = res or {}
for k,v in pairs(s) do
table.insert(res, k)
end
table.sort( res )
return res
end
function wc2_utils.remove_dublicates(t)
local found = {}
for i = #t, 1, -1 do
local v = t[i]
if found[v] then
table.remove(t, i)
else
found[v] = true
end
end
end
--comma seperated list
function wc2_utils.pick_random(str, generator)
local s2 = wml.variables[str]
if s2 ~= nil or generator then
local array = s2 and wc2_utils.split_to_array(s2) or {}
if #array == 0 and generator then
array = generator()
end
local index = wesnoth.random(#array)
local res = array[index]
table.remove(array, index)
wml.variables[str] = table.concat(array, ",")
return res
end
end
local function filtered_from_array(array, filter)
local possible_indicies = {}
for i, v in ipairs(array) do
if filter(v) then
table.insert(possible_indicies, i)
end
end
if #possible_indicies == 0 then
return nil
end
local index = possible_indicies[wesnoth.random(#possible_indicies)]
return index
end
function wc2_utils.pick_random_filtered(str, generator, filter)
local s2 = wml.variables[str]
if s2 == nil and generator == nil then
return
end
local array = s2 and wc2_utils.split_to_array(s2) or {}
if #array == 0 and generator then
array = generator()
end
local index = filtered_from_array(array, filter)
if index == nil then
array = generator()
index = filtered_from_array(array, filter)
end
local res = array[index]
table.remove(array, index)
wml.variables[str] = table.concat(array, ",")
return res
end
--wml array
function wc2_utils.pick_random_t(str)
local size = wml.variables[str .. ".length"]
if size ~= 0 then
local index = wesnoth.random(size) - 1
local res = wml.variables[str .. "[" .. index .. "]"]
wml.variables[str .. "[" .. index .. "]"] = nil
return res
end
end
--like table concat but for tstrings.
function wc2_utils.concat(t, sep)
local res = t[1]
if not res then
return ""
end
for i = 2, #t do
-- uses .. so we dont hae to call tostring. so this function can still return a tstring.
res = res .. sep .. t[i]
end
return res
end
function wc2_utils.range(a1,a2)
if a2 == nil then
a2 = a1
a1 = 1
end
local res = {}
for i = a1, a2 do
res[i] = i
end
return res
end
function wc2_utils.facing_each_other(u1,u2)
u1.facing = wesnoth.map.get_relative_dir(u1.x, u1.y, u2.x, u2.y)
u2.facing = wesnoth.map.get_relative_dir(u2.x, u2.y, u1.x, u1.y)
wesnoth.wml_actions.redraw {}
end
function wc2_utils.has_no_advances(u)
return #u.advances_to == 0
end
local global_vars = setmetatable({}, {
__index = function(self, namespace)
return setmetatable({}, {
__index = function(self, name)
wml.variables.lua_global_variable = nil
wesnoth.unsynced(function()
wesnoth.wml_actions.get_global_variable {
namespace = namespace,
to_local = "lua_global_variable",
from_global = name,
immediate = true,
}
end)
local res = wml.variables.lua_global_variable
wml.variables.lua_global_variable = nil
if res == "" then
return nil
end
return res
end,
__newindex = function(self, name, val)
wml.variables.lua_global_variable = val
wesnoth.unsynced(function()
wesnoth.wml_actions.set_global_variable {
namespace = namespace,
from_local = "lua_global_variable",
to_global = name,
immediate = true,
}
end)
wml.variables.lua_global_variable = nil
end,
})
end
})
wc2_utils.global_vars = global_vars.wc2
if rawget(_G, "wc2_menu_filters") == nil then
wc2_menu_filters = {}
end
function wc2_utils.menu_item(t)
local id_nospace = string.gsub(t.id, " ", "_")
local cfg = {}
on_event("start", function()
wesnoth.wml_actions.set_menu_item {
id = t.id,
description = t.description,
image = t.image,
synced = t.synced,
wml.tag.filter_location {
lua_function="wc2_menu_filters." .. id_nospace,
},
}
end)
if t.handler then
on_event("menu_item_" .. t.id, t.handler)
end
wc2_menu_filters[id_nospace] = t.filter
end
function wc2_utils.get_fstring(t, key)
local args = wml.get_child(t, key .. "_data")
if args then
args = wc2_utils.get_fstring_all(args)
else
args = {}
end
return wesnoth.format(t[key], args)
end
function wc2_utils.get_fstring_all(t)
local res = {}
for k,v in pairs(t) do
res[k] = wc2_utils.get_fstring(t, k)
end
return res
end
-- populates wc2_utils.world_conquest_data, reads [world_conquest_data] from all [resource]s and [era]
function wc2_utils.load_wc2_data()
if wc2_utils.world_conquest_data == nil then
local data_dict = {}
local ignore_list = {}
for i,res_id in ipairs(wesnoth.game_config.active_resources) do
local ressource = wesnoth.get_resource(res_id)
local world_conquest_data = wml.get_child(ressource, "world_conquest_data")
if world_conquest_data then
for ignore in wml.child_range(world_conquest_data, "ignore") do
ignore_list[ignore.id] = true
end
table.insert(data_dict, {id=res_id, data = world_conquest_data})
end
end
table.insert(data_dict, {id="era", data = wesnoth.game_config.era})
-- make sure the result does not depend on the order in which these addons are loaded.
table.sort(data_dict, function(a,b) return a.id<b.id end)
wc2_utils.world_conquest_data = {}
for i, v in ipairs(data_dict) do
if not ignore_list[v.id] then
for i2, tag in ipairs(v.data) do
local tagname = tag[1]
wc2_utils.world_conquest_data[tagname] = wc2_utils.world_conquest_data[tagname] or {}
table.insert( wc2_utils.world_conquest_data[tagname], tag )
end
end
end
end
end
-- reads the tag @a tagnaem from [world_conquest_data] provided by any of the ressoucrs or eras used in the game.
-- returns a wml table that contains only tagname subtags.
function wc2_utils.get_wc2_data(tagname)
wc2_utils.load_wc2_data()
--todo: maybe we shoudl clear wc2_utils.world_conquest_data[tagname] afterwards ?
return wc2_utils.world_conquest_data[tagname]
end
return wc2_utils

View file

@ -0,0 +1,277 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local dialog = wc2_wiki_dialog
function wesnoth.set_dialog_text(text, ...)
wesnoth.set_dialog_markup(true, ...)
wesnoth.set_dialog_value(text, ...)
end
function wesnoth.wml_actions.wc2_show_wocopedia(cfg)
local show_help_mechanics = cfg.show_mechanics ~= false
local show_help_training = cfg.show_training ~= false
local show_help_factions = cfg.show_factions ~= false
local show_help_artifacts = cfg.show_artifacts ~= false
local show_help_settings = cfg.show_settings ~= false
local show_help_feedback = cfg.show_feedback ~= false
-- maps the treeview rows to pagenumber in the help page.
local index_map = {}
local desc_index = 1
local ti = {1}
local function add_index()
index_map[table.concat(ti, "_")] = desc_index
desc_index = desc_index + 1
ti[#ti] = ti[#ti] + 1
end
local function tree_enter_mode()
ti[#ti] = ti[#ti] - 1
table.insert(ti, 1)
end
local function leave_enter_mode()
table.remove(ti)
ti[#ti] = ti[#ti] + 1
end
local current_side = wesnoth.get_viewing_side()
local preshow = function()
local str_cat_mechnics = _ "Game Mechanics"
local str_des_mechnics = cfg.mechanics_text or
_ "<b>Gold</b>:\n" ..
_ "Carryover is 15%, comunitary and avoid negative amounts. Early finish bonus is superior to village control, but it is not directly related to their amount.\n\n" ..
_ "<b>Autorecall</b>:\n" ..
_ "Units with trait HEROIC are recalled at start of each scenario with no cost (up to castle size).\n\n" ..
_ "<b>Recall Cost</b>:\n" ..
_ "Units costing less than 17 gold are cheaper to recall.\n\n" ..
_ "<b>Trainings</b>:\n" ..
_ "Every time you recruit a new unit, your trainings levels will be applied. Every chance will do different dice rolls, if a unit gains training beneficts, you can see them in a trait \"trained\".\n\n" ..
_ "<b>Upkeep</b>:\n" ..
_ "Units with trait HEROIC or holding any magic ITEM have FREE upkeep.\n\n" ..
_ "<b>Bonus Points</b>:\n" ..
_ "In every scenario the game generates as many bonus points on the map as there are players in the game, the bonus points can be picked up by player units and either contain artifacts, loyal units or training.\n\n" ..
_ "<b>Army discipline</b>:\n" ..
_ "At scenarios 1 to 3, for each training level player already own, trainers found have 2% to 4% chance to become advanced trainers (provide 2 levels). Becomes irrelevant from scenario 4 because all trainers always will be advanced.\n\n" ..
""
local str_cat_feedback = _ "Feedback"
local str_des_feedback =
_ "<b>Feedback</b>:\n" ..
_ "For feedback plase either post in the Word conquest II thread in the official wesnoth forum https://r.wesnoth.org/t39651 or file an issue at github https://github.com/gfgtdf/World_Conquest_II/issues .\n\n" ..
""
local str_cat_abilities = _ "Abilities"
local str_des_abilities =
_ "Ability <b>Autorecall</b>:\n" ..
_ "Units with trait HEROIC are recalled at start of each scenario with no cost (up to castle size).\n\n" ..
""
local str_cat_training = _ "Training"
local str_des_training = _ "<b>Training</b>\nTraining improves newly recruited units, it has no effect on already recruited units. The follwing list shows all available trainings, the training you currently have is marked in green."
local str_cat_items = _ "Artifacts"
local str_des_items = _ "<b>Items</b>\nItems can be given to units to make them stronger. You can get artifcats in three ways: 1) By choosing an item as your starting bonus, 2) By finding it on a map in a bonus point, 3) By dropping from enemies in later scenarios. Note however that not all units can pickup all items."
local str_cat_era = _ "Factions"
local str_des_era = _ "<b>Factions</b>\n The Word Conquest 2 era consists of faction that are build of pairs of mainline faction of which at one has a healer available (Drakes, Rebels and Loyalists), and one does not (Orcs, Dwarves and Undead) the recruilist is also organized in pairs so that you sometimes have to recruit a different units before you can recruit the units that you want. The available heroes, desertes and random leaders also depend on your factions, the items you can get do not depend on the faction you choose."
local str_cat_settings = _ "Settings"
---- add general topic ----
if show_help_mechanics then
wesnoth.add_dialog_tree_node("category", ti[1], "left_tree")
wesnoth.set_dialog_value(str_cat_mechnics, "left_tree", ti[1], "training_name")
wesnoth.set_dialog_value(true, "left_tree", ti[1])
wesnoth.add_dialog_tree_node("simpletext", -1, "details")
wesnoth.set_dialog_text(str_des_mechnics, "details", desc_index, "label")
add_index()
end
if show_help_training then
---- add general training topic ----
wesnoth.add_dialog_tree_node("category", ti[1], "left_tree")
wesnoth.set_dialog_value(str_cat_training, "left_tree", ti[1], "training_name")
wesnoth.set_dialog_value(true, "left_tree", ti[1])
wesnoth.add_dialog_tree_node("simpletext", -1, "details")
wesnoth.set_dialog_text(str_des_training, "details", desc_index, "label")
add_index()
tree_enter_mode()
-- add specific training pages
for i = 1, #wc2_training.get_list() do
local current_level = wc2_training.get_level(current_side, i)
local function set_description(train_num, j)
local desc = wc2_training.generate_message(i, train_num)
if train_num == current_level then
desc.caption = "<span color='#00FF00'>" .. desc.caption .. "</span>"
desc.message = "<span color='#00FF00'>" .. desc.message .. "</span>"
end
wesnoth.add_dialog_tree_node("training_details", j, "details", desc_index, "tree_details")
wesnoth.set_dialog_text(desc.caption, "details", desc_index, "tree_details", j, "training_caption")
wesnoth.set_dialog_text(desc.message, "details", desc_index, "tree_details", j, "training_description")
end
local trainer = wc2_training.get_trainer(i)
wesnoth.add_dialog_tree_node("training_category", i, "left_tree", ti[1])
wesnoth.set_dialog_value(trainer.name, "left_tree", ti[1], ti[2], "training_name")
set_description(1, 1)
for j = 2, #trainer.grade - 1, 1 do
wesnoth.add_dialog_tree_node("seperator", 2*j - 2, "details", desc_index, "tree_details")
set_description(j, 2*j - 1)
end
add_index()
end
leave_enter_mode()
end
if show_help_factions then
local function type_icon(ut)
local icon = ut.icon
if icon and icon ~= "" then
return icon
else
return ut.image
end
end
---- add general factions topic ----
local era_wml = wesnoth.game_config.era
wesnoth.add_dialog_tree_node("category", ti[1], "left_tree")
wesnoth.set_dialog_value(str_cat_era, "left_tree", ti[1], "training_name")
wesnoth.set_dialog_value(true, "left_tree", ti[1])
wesnoth.add_dialog_tree_node("simpletext", -1, "details")
wesnoth.set_dialog_text(str_des_era, "details", desc_index, "label")
add_index()
tree_enter_mode()
for i, faction_info in ipairs(wc2_era.factions_wml) do
local faction_wml = wml.get_child(era_wml, "multiplayer_side", faction_info.id)
wesnoth.add_dialog_tree_node("training_category", ti[2], "left_tree", ti[1])
wesnoth.set_dialog_value(faction_info.name, "left_tree", ti[1], ti[2], "training_name")
wesnoth.add_dialog_tree_node("faction_info", -1, "details")
j = 0
for p_wml in wml.child_range(faction_info, "pair") do
j = j + 1
local p = wc2_utils.split_to_array(p_wml.types)
local ut1 = wesnoth.unit_types[p[1]] or error("invald unit type" .. tostring(p[1]))
local ut2 = wesnoth.unit_types[p[2]] or error("invald unit type" .. tostring(p[2]))
wesnoth.add_dialog_tree_node("recruit_pair", j, "details", desc_index, "recruit_pairs")
wesnoth.set_dialog_text(ut1.name, "details", desc_index, "recruit_pairs", j, "label1")
print(tostring(ut1.icon or ut1.image))
wesnoth.set_dialog_value(type_icon(ut1), "details", desc_index, "recruit_pairs", j, "image1")
wesnoth.set_dialog_text(ut2.name, "details", desc_index, "recruit_pairs", j, "label2")
wesnoth.set_dialog_value(type_icon(ut2), "details", desc_index, "recruit_pairs", j, "image2")
end
local deserters_names = wesnoth.format_conjunct_list("", wc2_era.expand_hero_names(faction_info.deserters))
wesnoth.set_dialog_text(deserters_names, "details", desc_index, "deserters")
local deserters_names = wesnoth.format_conjunct_list("", wc2_era.expand_hero_names(faction_info.commanders))
wesnoth.set_dialog_text(deserters_names, "details", desc_index, "commanders")
local deserters_names = wesnoth.format_conjunct_list("", wc2_era.expand_hero_names(faction_info.heroes, true))
wesnoth.set_dialog_text(deserters_names, "details", desc_index, "heroes")
if faction_wml then
local random_leaders = {}
for i,v in ipairs(wc2_utils.split_to_array(faction_wml.random_leader)) do
table.insert(random_leaders, wesnoth.unit_types[v].name)
end
random_leaders = wesnoth.format_conjunct_list("", random_leaders)
wesnoth.set_dialog_text(random_leaders, "details", desc_index, "random_leaders")
else
wesnoth.set_dialog_visible(false, "details", desc_index, "tit_random_leaders")
end
add_index()
end
leave_enter_mode()
end
---- add general bonus point topic ----
--wesnoth.add_dialog_tree_node("category", ti[1], "left_tree")
--wesnoth.set_dialog_value(str_cat_bonus, "left_tree", ti[1], "training_name")
--wesnoth.add_dialog_tree_node("simpletext", -1, "details")
--wesnoth.set_dialog_text(str_des_bonus, "details", desc_index, "label")
--add_index()
if show_help_artifacts then
local str_not_for_enemies = _ " (not available for enemies)"
local str_not_for_players = _ " (not available for players)"
wesnoth.add_dialog_tree_node("category", ti[1], "left_tree")
wesnoth.set_dialog_value(str_cat_items, "left_tree", ti[1], "training_name")
wesnoth.add_dialog_tree_node("artifact_list", -1, "details")
wesnoth.set_dialog_text(str_des_items, "details", desc_index, "desc")
for i, artifact in ipairs(wc2_artifacts.get_artifact_list()) do
local artifact_icon = artifact.icon or ""
local artifact_name = artifact.name or ""
local artifact_desc = artifact.description or ""
local not_available = wc2_utils.split_to_set(artifact.not_available or "")
if not_available.player then
artifact_name = artifact_name .. str_not_for_players
end
if not_available.enemy then
artifact_name = artifact_name .. str_not_for_enemies
end
wesnoth.add_dialog_tree_node("artifact", i, "details", desc_index, "artifact_list_tv")
wesnoth.set_dialog_value(artifact_icon, "details", desc_index, "artifact_list_tv", i, "image")
wesnoth.set_dialog_value(artifact_name .. "\n" .. artifact_desc, "details", desc_index, "artifact_list_tv", i, "label")
end
add_index()
end
if show_help_settings then
wesnoth.add_dialog_tree_node("category", ti[1], "left_tree")
wesnoth.set_dialog_value(str_cat_settings, "left_tree", ti[1], "training_name")
wesnoth.set_dialog_value(true, "left_tree", ti[1])
wesnoth.add_dialog_tree_node("settings", -1, "details")
wesnoth.set_dialog_value(not not wml.variables["wc2_config_enable_pya"], "details", desc_index, "checkbox_use_pya")
wesnoth.set_dialog_active(false, "details", desc_index, "checkbox_use_pya")
wesnoth.set_dialog_value(not not wml.variables["wc2_config_enable_unitmarker"], "details", desc_index, "checkbox_use_markers")
wesnoth.set_dialog_active(false, "details", desc_index, "checkbox_use_markers")
wesnoth.set_dialog_value(not not wml.variables["wc2_config_experimental_pickup"], "details", desc_index, "checkbox_use_pickup")
wesnoth.set_dialog_active(false, "details", desc_index, "checkbox_use_pickup")
wesnoth.set_dialog_text(wml.variables["wc2_host_version"] or "unknown", "details", desc_index, "label_version")
wesnoth.set_dialog_text(wml.variables["wc2_difficulty.name"] or "unknown", "details", desc_index, "label_difficulty")
wesnoth.set_dialog_value(not wc2_utils.global_vars.skip_pickup_dialog, "details", desc_index, "checkbox_show_pickup_confirmation")
wesnoth.set_dialog_active(true, "details", desc_index, "checkbox_show_pickup_confirmation")
local desc_index_copy = desc_index
wesnoth.set_dialog_callback(function()
wc2_utils.global_vars.skip_pickup_dialog = not wesnoth.get_dialog_value("details", desc_index_copy, "checkbox_show_pickup_confirmation")
end, "details", desc_index_copy, "checkbox_show_pickup_confirmation")
local mp_settings = wesnoth.game_config.mp_settings
if mp_settings and mp_settings.active_mods then
--FIXME: mp_settings.active_mods was removed during an internal refactor of the c++ mp_settings object.
-- but maybe we shouldn't need this in the mainline version anyways.
wesnoth.set_dialog_text(mp_settings.active_mods, "details", desc_index, "label_activemods")
end
add_index()
end
if show_help_feedback then
wesnoth.add_dialog_tree_node("category", ti[1], "left_tree")
wesnoth.set_dialog_value(str_cat_feedback, "left_tree", ti[1], "training_name")
wesnoth.set_dialog_value(true, "left_tree", ti[1])
wesnoth.add_dialog_tree_node("simpletext", -1, "details")
wesnoth.set_dialog_text(str_des_feedback, "details", desc_index, "label")
add_index()
end
wesnoth.set_dialog_focus("left_tree")
wesnoth.set_dialog_callback(function()
local selected = wesnoth.get_dialog_value("left_tree")
local selected_page_index = index_map[table.concat(selected, '_')]
if selected_page_index ~= nil then
wesnoth.set_dialog_value(selected_page_index, "details")
end
end, "left_tree")
end
wesnoth.show_dialog(dialog, preshow)
end
wc2_utils.menu_item {
id = "5_WCT_Wocopedia_Option",
description = _ "WoCopedia",
image= "help/closed_section.png~SCALE(18,17)",
synced = false,
filter = function(x, y)
local u = wesnoth.get_unit(x, y)
if wc2_artifacts.is_item_at(x, y) then
return false
end
return not (u and u.side == wesnoth.current.side)
end,
handler = function(cx)
wesnoth.wml_actions.wc2_show_wocopedia {
x = cx.x1,
y = cx.y1,
}
end
}

View file

@ -0,0 +1,711 @@
local _ = wesnoth.textdomain 'wesnoth-World_Conquest'
local T = wml.tag
local function GUI_FORCE_WIDGET_MINIMUM_SIZE(w,h, content)
return T.stacked_widget {
definition = "default",
T.stack {
T.layer {
T.row {
T.column {
T.spacer {
definition = "default",
width = w,
height = h
}
}
}
},
T.layer {
T.row {
grow_factor = 1,
T.column {
grow_factor = 1,
horizontal_grow = "true",
vertical_grow = "true",
content
}
}
}
}
}
end
local GUI_HORIZONTAL_SPACER_LINE = T.row {
grow_factor = 0,
T.column {
grow_factor = 1,
border = "all",
border_size = 10,
horizontal_grow = true,
T.drawing {
definition = "default",
width = "(width)",
height = 1,
T.draw {
T.line {
x1 = 0,
y1 = 0,
x2 = "(width - 1)",
y2 = 0,
color = "114, 79, 46, 255",
thickness = 1,
}
}
}
}
}
return {
maximum_width = 900,
T.helptip { id = "tooltip_large" }, -- mandatory field
T.tooltip { id = "tooltip_large" }, -- mandatory field
T.linked_group { id = "artifact_icon", fixed_width = true },
T.linked_group { id = "artifact_name", fixed_width = true },
T.linked_group { id = "recruit_icon", fixed_width = true },
T.linked_group { id = "recruit_name", fixed_width = true },
T.grid {
T.row {
grow_factor = 1,
T.column {
border = "all",
border_size = 5,
horizontal_alignment = "left",
T.label {
definition = "title",
label = _"WoCopedia",
id = "title"
}
}
},
T.row {
grow_factor = 1,
T.column {
horizontal_grow = true,
vertical_grow = true,
T.grid {
T.row {
T.column {
border = "all",
border_size = 5,
horizontal_grow = true,
vertical_grow = true,
T.tree_view {
id = "left_tree",
definition = "default",
horizontal_scrollbar_mode = "never",
vertical_scrollbar_mode = "never",
indentation_step_size = 35,
T.node {
id = "training_category",
T.node_definition {
T.row {
T.column {
grow_factor = 1,
horizontal_grow = true,
T.toggle_panel {
id = "tree_view_node_label",
T.grid {
T.row {
T.column {
horizontal_alignment = "left",
T.label {
id = "training_name",
},
},
},
},
},
},
},
},
},
T.node {
id = "category",
T.node_definition {
T.row {
T.column {
grow_factor = 0,
horizontal_grow = true,
T.toggle_button {
id = "tree_view_node_toggle",
definition = "tree_view_node",
},
},
T.column {
grow_factor = 1,
horizontal_grow = true,
T.toggle_panel {
id = "tree_view_node_label",
T.grid {
T.row {
T.column {
horizontal_alignment = "left",
T.label {
id = "training_name",
},
},
},
},
},
},
},
},
},
},
},
T.column {
T.multi_page {
id = "details",
definition = "default",
horizontal_scrollbar_mode = "never",
T.page_definition {
T.row {
T.column {
horizontal_grow = true,
vertical_grow = true,
T.scrollbar_panel {
T.definition {
T.row {
T.column {
horizontal_grow = true,
vertical_grow = true,
T.tree_view {
id = "tree_details",
definition = "default",
horizontal_scrollbar_mode = "never",
vertical_scrollbar_mode = "never",
indention_step_size = 20,
T.node {
id = "training_details",
T.node_definition {
T.row {
T.column {
grow_factor = 1,
horizontal_alignment = "left",
T.label {
definition = "default_large",
id = "training_caption",
label = "default description",
},
},
},
T.row {
T.column {
grow_factor = 1,
horizontal_alignment = "left",
T.label {
id = "training_description",
label = "default description",
},
},
},
},
},
T.node {
id = "scroll_details",
T.node_definition {
T.row {
T.column {
grow_factor = 1,
horizontal_alignment = "left",
T.label {
definition = "default_large",
id = "training_caption",
label = "default description",
},
},
},
T.row {
T.column {
grow_factor = 1,
horizontal_alignment = "left",
T.scroll_label {
id = "training_description",
label = "default description",
},
},
},
},
},
T.node {
id = "seperator",
T.node_definition {
T.row {
T.column {
grow_factor = 1,
horizontal_grow = true,
T.spacer {
height = 20,
width = 20,
},
},
},
},
},
}
}
}
}
}
}
}
},
T.page_definition {
id="simpletext",
T.row {
T.column {
horizontal_grow = true,
vertical_grow = true,
T.scroll_label {
id = "label",
label = "Text",
}
}
}
},
T.page_definition {
id="artifact_list",
vertical_grow = true,
T.row {
T.column {
vertical_grow = true,
T.grid {
--T.row {
-- T.column {
-- grow_factor = 1,
-- vertical_grow = true,
-- T.label {
-- id = "title",
-- label = "Artifacts",
-- }
-- }
--},
T.row {
T.column {
T.scroll_label {
vertical_scrollbar_mode = "never",
id = "desc",
}
}
},
T.row {
T.column {
horizontal_grow = true,
T.tree_view {
vertical_grow = true,
id = "artifact_list_tv",
definition = "default",
horizontal_scrollbar_mode = "never",
vertical_scrollbar_mode = "always",
indentation_step_size = 35,
T.node {
id = "artifact",
horizontal_grow = true,
T.node_definition {
vertical_grow = true,
T.row {
horizontal_grow = true,
T.column {
horizontal_grow = true,
T.grid {
T.row {
T.column {
T.image {
id="image",
linked_group = "artifact_icon",
}
},
T.column {
T.label {
id="label",
linked_group = "artifact_name",
}
},
}
}
}
}
}
}
}
}
},
T.row {
grow_factor = 1,
T.column {
grow_factor = 0,
vertical_grow = true,
T.spacer {
id = "aa",
}
}
},
}
}
}
},
T.page_definition {
id="faction_info",
vertical_grow = true,
T.row {
T.column {
vertical_grow = true,
horizontal_grow = true,
T.grid {
--T.row {
-- T.column {
-- grow_factor = 1,
-- vertical_grow = true,
-- T.label {
-- id = "title",
-- label = "Artifacts",
-- }
-- }
--},
T.row {
T.column {
T.scroll_label {
vertical_scrollbar_mode = "never",
id = "desc",
}
}
},
T.row {
T.column {
T.label {
vertical_scrollbar_mode = "never",
label = "<b>Recruits:</b>",
use_markup = true,
}
}
},
T.row {
T.column {
horizontal_grow = true,
T.tree_view {
id = "recruit_pairs",
definition = "default",
horizontal_scrollbar_mode = "never",
vertical_scrollbar_mode = "always",
indentation_step_size = 35,
T.node {
id = "recruit_pair",
horizontal_grow = true,
T.node_definition {
T.row {
T.column {
horizontal_grow = true,
T.grid {
T.row {
T.column {
T.image {
id="image1",
linked_group = "recruit_icon",
}
},
T.column {
T.label {
id="label1",
linked_group = "recruit_name",
}
},
T.column {
T.label {
label="",
}
},
T.column {
T.image {
id="image2",
linked_group = "recruit_icon",
}
},
T.column {
T.label {
id="label2",
linked_group = "recruit_name",
}
},
}
}
}
}
}
}
}
}
},
T.row {
T.column {
T.label {
vertical_scrollbar_mode = "never",
label = "<b>Deserters:</b>",
use_markup = true,
}
}
},
T.row {
T.column {
horizontal_grow=true,
T.scroll_label {
vertical_scrollbar_mode = "never",
id = "deserters",
use_markup = true,
}
}
},
T.row {
T.column {
T.label {
vertical_scrollbar_mode = "never",
label = "<b>Commanders:</b>",
use_markup = true,
}
}
},
T.row {
T.column {
horizontal_grow=true,
T.scroll_label {
vertical_scrollbar_mode = "never",
id = "commanders",
use_markup = true,
}
}
},
T.row {
T.column {
T.label {
vertical_scrollbar_mode = "never",
label = "<b>Heroes:</b>",
use_markup = true,
}
}
},
T.row {
T.column {
horizontal_grow=true,
T.scroll_label {
vertical_scrollbar_mode = "never",
id = "heroes",
use_markup = true,
}
}
},
T.row {
T.column {
T.label {
vertical_scrollbar_mode = "never",
label = "<b>Random Leaders:</b>",
id = "tit_random_leaders",
use_markup = true,
}
}
},
T.row {
T.column {
horizontal_grow=true,
T.scroll_label {
vertical_scrollbar_mode = "never",
id = "random_leaders",
use_markup = true,
}
}
},
T.row {
grow_factor = 1,
T.column {
grow_factor = 0,
vertical_grow = true,
T.spacer {
id = "aa",
}
}
},
}
}
}
},
T.page_definition {
id="settings",
vertical_grow = true,
horizontal_grow = true,
T.row {
T.column {
vertical_grow = true,
horizontal_grow = true,
T.grid {
T.row {
grow_factor = 0,
T.column {
grow_factor = 0,
vertical_grow = false,
horizontal_alignment = "left",
T.label {
id = "title",
label = "<b>Settings</b>\n ",
use_markup=true,
},
},
},
T.row {
grow_factor = 0,
T.column {
horizontal_grow=true,
vertical_alignment="top",
grow_factor = 1,
T.grid {
T.row {
T.column {
horizontal_alignment="left",
T.label {
label = "Use WC2 PYA mod",
}
},
T.column {
horizontal_alignment="right",
T.toggle_button {
label = "",
id="checkbox_use_pya",
},
},
},
T.row {
T.column {
horizontal_alignment="left",
T.label {
label = "Use WC2 Unitmarkers",
}
},
T.column {
horizontal_alignment="right",
T.toggle_button {
label = "",
id="checkbox_use_markers",
},
},
},
T.row {
T.column {
horizontal_alignment="left",
T.label {
label = "Use WC2 experimental pickup",
}
},
T.column {
horizontal_alignment="right",
T.toggle_button {
label = "",
id="checkbox_use_pickup",
},
},
},
T.row {
T.column {
horizontal_alignment="left",
T.label {
label = "Show pickup confirmation",
}
},
T.column {
horizontal_alignment="right",
T.toggle_button {
label = "",
id="checkbox_show_pickup_confirmation",
},
},
},
T.row {
T.column {
horizontal_alignment="left",
T.label {
label = "difficulty",
}
},
T.column {
horizontal_alignment="right",
T.label {
label = "",
id="label_difficulty",
},
},
},
T.row {
T.column {
horizontal_alignment="left",
T.label {
label = "WC2 version",
}
},
T.column {
horizontal_alignment="right",
T.label {
label = "",
id="label_version",
},
},
},
}
}
},
GUI_HORIZONTAL_SPACER_LINE,
T.row {
grow_factor = 0,
T.column {
grow_factor = 0,
vertical_grow = false,
horizontal_alignment = "left",
T.label {
id = "title_2",
label = "<b>Active mods</b>\n ",
use_markup=true,
},
},
},
T.row {
grow_factor = 1,
T.column {
grow_factor = 0,
horizontal_grow=true,
vertical_alignment="top",
T.scroll_label {
id = "label_activemods",
},
},
},
}
}
}
},
},
}
}
}
}
},
T.row {
T.column {
horizontal_grow = true,
T.grid {
T.row {
T.column {
grow_factor = 1,
T.spacer {
}
},
T.column {
horizontal_alignment = "right",
T.button {
label = "Ok",
id = "ok",
}
}
}
}
}
}
}
}

View file

@ -0,0 +1,4 @@
-- the main file for other addons that want to use the WC2 mechanics.
wc2_convert = wesnoth.require("./wml_converter.lua")
wesnoth.dofile("./game_mechanics/_load.lua")

View file

@ -0,0 +1,88 @@
----------------------------------------------------------
---- A utility class, to calculate distances of each ----
---- tile to one given tile ----
----------------------------------------------------------
local Distmap = {}
function Distmap:create(w, h)
local o = {}
setmetatable(o, self)
self.__index = self
o.w = w
o.h = h
o.data = {}
for i = 1,w *h do
o.data[#o.data + 1] = false
end
return o
end
function Distmap:loc_to_index(loc)
return loc[1] + 1 + loc[2] * self.w
end
function Distmap:is_on_map(loc)
local x, y= loc[1], loc[2]
return x >= 0 and y >= 0 and y < self.h and x < self.w
end
function Distmap:get(loc)
return self.data[self:loc_to_index(loc)]
end
local adjacent_offset = {
--odd x
{ {0,-1}, {1,-1}, {1,0}, {0,1}, {-1,0}, {-1,-1} },
--even x
{ {0,-1}, {1,0}, {1,1}, {0,1}, {-1,1}, {-1,0} }
}
function Distmap:adjacent_tiles(loc, filter)
local x, y = loc[1], loc[2]
local offsets = adjacent_offset[2 - (x % 2)]
local res = {}
for i, offset in ipairs(offsets) do
local x2, y2 = x + offset[1], y + offset[2]
if self:is_on_map({x2, y2}) and ((filter == nil) or filter(x2, y2)) then
res[#res + 1] = { x2, y2}
end
end
return res
end
function Distmap:calculate_distances(locs, upto, filter)
wesnoth.log("info", "calculate_distances " .. upto .. " " .. #locs)
local todo = locs
local data = self.data
for i,loc in ipairs(todo) do
data[self:loc_to_index(loc)] = 0
end
while #todo ~= 0 do
local loc = todo[1]
local loc_i = self:loc_to_index(loc)
local dist = self.data[loc_i] + 1
for i2, loc2 in ipairs(self:adjacent_tiles(loc, filter)) do
local loc2_i = self:loc_to_index(loc2)
if (data[loc2_i] or 999) > dist then
data[loc2_i] = dist
todo[#todo + 1] = loc2
end
end
table.remove(todo, 1)
end
end
function Distmap:std_print(loc)
local data = functional.map(self.data, function(v)
return tostring(v or "nil")
end)
for i =1, self.h do
std_print(table.concat(data, "\t,\t", 1 + (i-1)* self.w, i * self.w ))
end
end
return Distmap

View file

@ -0,0 +1,70 @@
local function generate(length, villages, castle, iterations, size, players, island)
local res = wct_generator_settings_arguments( length, villages, castle, iterations, size, players, island)
res.max_lakes=10
res.min_lake_height=150
res.lake_size=125
res.river_frequency=100
res.temperature_size=size
res.roads=20
res.road_windiness=3
res.height = {
-- list of common terrain types which come in at different heights, from highest to lowest
dr_height(900, "Uh"),
dr_height(800, "Uu"),
dr_height(750, "Xu"),
dr_height(725, "Mm^Xm"),
dr_height(675, "Mm"),
dr_height(550, "Hh"),
dr_height(100, "Gg"),
dr_height(30, "Ds"),
dr_height(1, "Ww"),
dr_height(0, "Wo"),
}
res.convert = {
-- DR_CONVERT MIN_HT MAX_HT MIN_TMP MAX_TMP FROM TO
-- water at cold becomes ice
dr_convert(50, 999, 0, 50, "Ww, Wo", "Ai"),
-- at low temperatures, snow appears
dr_convert(50, 999, 0, 75, "Gg, Ds", "Aa"),
-- hills at cold get snow on them
dr_convert(0, 999, 0, 100, "Hh", "Ha"),
-- savannah appears on mod temp and high
dr_convert(250, 400, 500, 800, "Gg", "Gs"),
-- swamp appears on low land, at mod temp
dr_convert(0, 200, 400, 700, "Gg", "Ss"),
-- forest appears at moderate temperatures
dr_convert(0, 999, 320, 420, "Gg", "Gs^Fp"),
dr_convert(0, 999, 320, 420, "Hh", "Hh^Fp"),
-- jungle appears at mod high temperatures
dr_convert(0, 999, 450, 520, "Gg,Gs", "Gs^Ft"),
dr_convert(0, 999, 450, 520, "Hh", "Hh^Ft"),
-- fungus appears at med temp and high
dr_convert(825, 950, 500, 525, "Uu, Uh", "Uu^Uf"),
dr_convert(825, 950, 550, 575, "Uu, Uh", "Uu^Uf"),
dr_convert(825, 950, 600, 625, "Uu, Uh", "Uu^Uf"),
-- lava appears at extreme temp and height
dr_convert(800, 999, 850, 999, "Uu, Uh, Uu^Uf", "Ql"),
-- desert appears at extreme temperatures
dr_convert(0, 999, 800, 999, "Gg", "Dd"),
-- dunes at extreme temp and mod elevation
dr_convert(475, 550, 800, 999, "Ds, Hh", "Hd"),
}
res.road_cost = {
wct_generator_road_cost_classic(),
dr_road("Gs^Ft", "Re", 30),
dr_road("Ds", "Re", 25),
dr_bridge("Ww", "Ww^Bw", "Ce", 50),
}
res.village = {
wct_generator_village(8, 5, 2, 4, 3, 4, 4, 3, 3, 3, 2, 1)
}
res.castle = {
valid_terrain="Gs, Gg, Gs^Fp, Hh",
min_distance=12,
}
return default_generate_map(res)
end
return generate

View file

@ -0,0 +1,142 @@
local function generate(length, villages, castle, iterations, size, players, island)
local res = wct_generator_settings_arguments( length, villages, castle, iterations, size, players, island)
res.max_lakes=35
res.min_lake_height=250
res.lake_size=100
res.river_frequency=100
res.temperature_size=size
res.roads=0
res.road_windiness=1
res.height = {
-- list of common terrain types which come in at different heights, from highest to lowest
dr_height(955, "Uh"),
dr_height(945, "Uu^Uf"),
dr_height(900, "Uu"),
dr_height(855, "Uh"),
dr_height(845, "Uu^Uf"),
dr_height(825, "Uu"),
dr_height(775, "Xu"),
dr_height(750, "Mm^Xm"),
dr_height(700, "Mm"),
dr_height(690, "Hh^Uf"),
dr_height(660, "Hh^Fp"),
dr_height(625, "Hh"),
-- most rough terrain is added post generation
dr_height(115, "Gg"),
dr_height(30, "Ds"),
dr_height(1, "Wwg"),
dr_height(0, "Wog"),
}
res.convert = {
wct_fix_river_into_ocean("g", 29),
-- DR_CONVERT MIN_HT MAX_HT MIN_TMP MAX_TMP FROM TO
-- lava appears at extreme temp and height
dr_convert(800, 999, 850, 999, "Uu, Uh, Uu^Uf", "Ql"),
-- DR_TEMPERATURE FROM MIN MAX TO),
-- less wet flat as higher temperature
dr_temperature("Gg", 720, 999, "Dd"),
dr_temperature("Gg", 655, 720, "Rd"),
dr_temperature("Gg", 570, 655, "Re"),
dr_temperature("Gg", 435, 570, "Rb"),
dr_temperature("Gg", 340, 435, "Gs"),
}
res.village = {
-- flat villages
dr_village {
terrain = "Gg",
convert_to="Gg^Vht",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Re, Rd, Rb, Gg, Gs, Re, Rd, Rb, Gg, Gs",
rating=8
},
dr_village {
terrain = "Gs",
convert_to="Gs^Vc",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Re, Rd, Rb, Gg, Gs, Re, Rd, Rb, Gg, Gs",
rating=7
},
dr_village {
terrain = "Rb",
convert_to="Rb^Vda",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Re, Rd, Rb, Gg, Gs, Re, Rd, Rb, Gg, Gs, Dd",
rating=6
},
dr_village {
terrain = "Re",
convert_to="Re^Vda",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Re, Rd, Rb, Gg, Gs, Re, Rd, Rb, Gg, Gs, Dd",
rating=6
},
dr_village {
terrain = "Rd",
convert_to="Rd^Vda",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Re, Rd, Rb, Gg, Gs, Re, Rd, Rb, Gg, Gs, Dd, Dd",
rating=5
},
dr_village {
terrain = "Dd",
convert_to="Dd^Vda",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Re, Rd, Rb, Gg, Gs, Re, Rd, Rb, Gg, Gs, Dd, Dd",
rating=4
},
dr_village {
terrain = "Ds",
convert_to="Ds^Vda",
adjacent_liked="Gg, Gs, Wwg, Wwg, Ds, Ds, Re, Rd, Rb, Gg, Gs, Re, Rd, Rb, Gg, Gs",
rating=1
},
-- rough villages
dr_village {
terrain="Hh",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Re, Rd, Rb, Gg, Gs, Re, Rd, Rb, Gg, Gs, Hh, Hh^Fp, Hh^Uf, Mm",
rating=5
},
dr_village {
terrain="Hh^Fp",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Re, Rd, Rb, Gg, Gs, Re, Rd, Rb, Gg, Gs, Hh, Hh^Fp, Hh^Uf, Mm",
rating=4
},
dr_village {
terrain="Hh^Uf",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Re, Rd, Rb, Gg, Gs, Re, Rd, Rb, Gg, Gs, Hh, Hh^Fp, Hh^Uf, Mm",
rating=3
},
dr_village {
terrain="Mm",
convert_to="Mm^Vhh",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Re, Rd, Rb, Gg, Gs, Re, Rd, Rb, Gg, Gs, Hh, Hh^Fp, Hh^Uf, Mm",
rating=3
},
-- cave villages
dr_village {
terrain="Uu",
convert_to="Uu^Vu",
adjacent_liked="Hh,Hh^Fp,Mm,Uu,Uh,Hh^Uf,Xu,Uu^Uf,Mm^Xm,Ww",
rating=4
},
dr_village {
terrain="Uh",
convert_to="Uu^Vu",
adjacent_liked="Hh,Hh^Fp,Mm,Uu,Uh,Hh^Uf,Xu,Uu^Uf,Mm^Xm,Ww",
rating=4
},
-- water villages
dr_village {
terrain="Wwg",
convert_to="Wwg^Vm",
adjacent_liked="Wwg, Wwg, Ds",
rating=1
},
}
res.castle = {
valid_terrain="Gs, Gg, Re, Rb, Rd",
min_distance=14,
}
return default_generate_map(res)
end
return generate

View file

@ -0,0 +1,155 @@
local function generate(length, villages, castle, iterations, size, players, island)
local width = length
if width % 2 == 1 then
width = width + 1
end
local res = {}
res.border_size=0
res.map_width=width
res.map_height=length
res.iterations=iterations
res.hill_size=size
res.villages=villages
res.nplayers=players
res.island_size=island
res.castle_size=castle
res.temperature_iterations=0
--!? for some reason still can generate rivers with value 0
res.max_lakes=1
res.river_frequency=1
res.roads=18
res.road_windiness=4
res.link_castles=true
res.height = {
dr_height(955, "Uh"),
dr_height(945, "Uu^Uf"),
dr_height(900, "Uu"),
dr_height(855, "Uh"),
dr_height(845, "Uu^Uf"),
dr_height(825, "Uu"),
dr_height(775, "Xu"),
dr_height(750, "Mm^Xm"),
dr_height(700, "Mm"),
dr_height(690, "Hh^Uf"),
dr_height(660, "Hh^Fp"),
dr_height(625, "Hh"),
dr_height(540, "Gg"),
dr_height(380, "Gs"),
dr_height(310, "Wog"),-- just to avoid castle generation
dr_height(280, "Ds"),
dr_height(270, "Wwt"),
dr_height(260, "Ds"),
dr_height(250, "Wwrt"),
dr_height(240, "Ds"),
dr_height(230, "Wwt"),
dr_height(220, "Ds"),
dr_height(210, "Wwrt"),
dr_height(200, "Ds"),
dr_height(190, "Wwt"),
dr_height(180, "Ds"),
dr_height(170, "Wwt"),
dr_height(160, "Ds"),
dr_height(150, "Wwrt"),
dr_height(140, "Ds"),
dr_height(130, "Wwrt"),
dr_height(120, "Ds"),
dr_height(110, "Wwrt"),
dr_height(100, "Ds"),
dr_height(90, "Wwrt"),
dr_height(80, "Dd"),-- just to avoid village generation
dr_height(70, "Wwrt"),
dr_height(60, "Dd"),
dr_height(50, "Wwrt"),
dr_height(40, "Dd"),
dr_height(20, "Wwrt"),
dr_height(1, "Wwt"),
dr_height(0, "Wot"),
}
res.road_cost = {
dr_road("Gs", "Re", 10),
dr_road("Gg", "Re", 9),
dr_road("Re", "Re", 4),
}
res.village = {
dr_village {
terrain = "Gg",
convert_to="Gg^Vd",
adjacent_liked="Gg, Gs, Wwt, Wwrt, Re, Gg, Gs, Re, Gg, Gs, Hh, Mm, Hh^Fp",
rating=8
},
dr_village {
terrain = "Gs",
convert_to="Gs^Vc",
adjacent_liked="Gg, Gs, Wwt, Wwrt, Re, Gg, Gs, Re, Gg, Gs, Hh",
rating=8
},
dr_village {
terrain = "Wog",
convert_to="Gs^Vc",
adjacent_liked="Gg, Gs, Wwt, Wwrt, Re, Gg, Gs, Re, Gg, Gs, Hh",
rating=6
},
dr_village {
terrain = "Ds",
convert_to="Ds^Vc",
adjacent_liked="Gg, Gs, Wwt, Wwrt, Ds, Ds, Gs, Gs, Gs, Gs",
rating=1
},
-- rough villages
dr_village {
terrain="Hh",
convert_to="Hh^Vd",
adjacent_liked="Gg, Gs, Wwt, Wwrt, Re, Gg, Gs, Re, Gg, Gs, Hh, Hh^Fp, Hh^Uf, Mm",
rating=5
},
dr_village {
terrain="Hh^Fp",
convert_to="Hh^Vd",
adjacent_liked="Gg, Gs, Wwt, Wwrt, Re, Gg, Gs, Re, Gg, Gs, Hh, Hh^Fp, Hh^Uf, Mm",
rating=4
},
dr_village {
terrain="Hh^Uf",
convert_to="Hh^Vd",
adjacent_liked="Gg, Gs, Wwt, Wwrt, Re, Gg, Gs, Re, Rd, Rb, Gg, Gs, Hh, Hh^Fp, Hh^Uf, Mm",
rating=3
},
dr_village {
terrain="Mm",
convert_to="Mm^Vd",
adjacent_liked="Gg, Gs, Wwt, Wwrt, Re, Gg, Gs, Re, Rd, Rb, Gg, Gs, Hh, Hh^Fp, Hh^Uf, Mm",
rating=3
},
-- cave villages
dr_village {
terrain="Uu",
convert_to="Uu^Vu",
adjacent_liked="Hh,Hh^Fp,Mm,Uu,Uh,Hh^Uf,Xu,Uu^Uf,Mm^Xm",
rating=4
},
dr_village {
terrain="Uh",
convert_to="Uu^Vu",
adjacent_liked="Hh,Hh^Fp,Mm,Uu,Uh,Hh^Uf,Xu,Uu^Uf,Mm^Xm",
rating=4
},
-- water villages
dr_village {
terrain="Wwt",
convert_to="Wwt^Vm",
adjacent_liked="Wwt, Wwt, Wwrt",
rating=1
},
}
res.castle = {
valid_terrain="Gs,Gg",
min_distance=14,
}
return default_generate_map(res)
end
return generate

View file

@ -0,0 +1,140 @@
local function generate(length, villages, castle, iterations, size, players, island)
local res = wct_generator_settings_arguments( length, villages, castle, iterations, size, players, island)
res.max_lakes=10
res.min_lake_height=150
res.lake_size=125
res.river_frequency=100
res.temperature_size=4
res.roads=10
res.road_windiness=7
res.height = {
dr_height(960, "Uue^Dr"),
dr_height(910, "Uue"),
dr_height(870, "Uue^Dr"),
dr_height(800, "Uue"),
dr_height(700, "Xuce"),
dr_height(625, "Mm"),
dr_height(475, "Hh"),
dr_height(310, "Gg"),
dr_height(300, "Ds"),
dr_height(200, "Ww"),
dr_height(0, "Wo"),
}
res.convert = {
-- sand
dr_convert(75, nil, nil, 200, "Ww,Wo", "Dd^Do"),
dr_convert(180, nil, nil, 300, "Gg,Ds", "Dd"),
dr_convert(500, nil, nil, 425, "Hh", "Hd"),
dr_convert(nil, nil, 900, nil, "Gg", "Ds"),
-- swamp
dr_convert(nil, 200, 600, 900, "Gg", "Ss"),
-- forest
dr_convert(nil, nil, 240, 320, "Dd, Gs", "Ds^Ftd"),
dr_convert(nil, nil, 350, 420, "Gg", "Gs^Fp"),
-- fungus
-- DR_CONVERT MIN_HT MAX_HT MIN_TMP MAX_TMP FROM TO
dr_convert(825, 950, 500, 525, "Uue, Uue^Dr", "Uue^Uf"),
dr_convert(825, 950, 550, 575, "Uue, Uue^Dr", "Uue^Uf"),
dr_convert(825, 950, 600, 625, "Uue, Uue^Dr", "Uue^Uf"),
-- lava
dr_convert(800, nil, 850, nil, "Uue, Uue^Dr, Uue^Uf", "Ql"),
}
res.road_cost = {
dr_road("Gg", "Re", 10),
dr_road("Gs^Fp", "Re", 20),
dr_road("Hh", "Re", 30),
dr_road("Mm", "Re", 40),
dr_road("Xuce", "Re", 80),
dr_road("Uue", "Re", 10),
dr_road("Uue^Dr", "Re", 40),
dr_road("Ds", "Re", 25),
dr_bridge("Ww", "Ww^Bw", "Ce", 50),
dr_road("Re", "Re", 2),
dr_road("Ce", "Ce", 2),
dr_road_over_bridges("Ww^Bw", 2),
}
res.village = {
dr_village {
terrain = "Gg",
convert_to="Gg^Vh",
adjacent_liked="Gg, Ds^Ftd, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Hh, Gs^Fp",
rating=5
},
dr_village {
terrain="Ds",
convert_to="Ds^Vda",
adjacent_liked="Gg, Ds^Ftd, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Hh, Gs^Fp",
rating=4
},
dr_village {
terrain="Dd",
convert_to="Dd^Vda",
adjacent_liked="Gg, Ds^Ftd, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Hh, Gs^Fp, Dd, Dd, Dd^Do",
rating=4
},
dr_village {
terrain="Ds^Ftd",
convert_to="Ds^Vda",
adjacent_liked="Gg, Ds^Ftd, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Hh, Gs^Fp, Dd, Dd, Dd^Do",
rating=3
},
dr_village {
terrain="Dd^Do",
convert_to="Ds^Vdt",
adjacent_liked="Gg, Ds^Ftd, Ds^Ftd, Re, Re, Hh, Gs^Fp, Dd, Dd, Dd^Do, Dd^Do, Ds",
rating=1
},
dr_village {
terrain="Uue",
convert_to="Uue^Vu",
adjacent_liked="Re,Hh,Mm,Uue,Uue^Dr,Xuce",
rating=4
},
dr_village {
terrain="Uue^Dr",
convert_to="Uue^Vu",
adjacent_liked="Re,Hh,Mm,Uue,Uue^Dr,Xuce",
rating=3
},
dr_village {
terrain="Gs^Fp",
convert_to="Gg^Ve",
adjacent_liked="Gg, Ds^Ftd, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Hh, Gs^Fp, Gs^Fp",
rating=4
},
dr_village {
terrain="Hh",
convert_to="Hh^Vh",
adjacent_liked="Gg, Ds^Ftd, Hh, Hh, Mm, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Hh, Gs^Fp, Hh",
rating=8
},
dr_village {
terrain="Mm",
convert_to="Mm^Vd",
adjacent_liked="Gg, Ds^Ftd, Hh, Hh, Mm, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Hh, Gs^Fp, Hh",
rating=3
},
dr_village {
terrain="Ss",
convert_to="Ss^Vhs",
adjacent_liked="Gg, Ds^Ftd, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Hh, Gs^Fp",
rating=2
},
dr_village {
terrain="Ww",
convert_to="Ww^Vm",
adjacent_liked="Ww, Ww",
rating=1
},
}
res.castle = {
valid_terrain="Gg, Gs^Fp, Hh, Dd, Hd, Mm, Mm^Xm, Ds, Ss",
min_distance=13,
}
return default_generate_map(res)
end
return generate

View file

@ -0,0 +1,147 @@
local function generate(length, villages, castle, iterations, size, players, island)
local res = wct_generator_settings_arguments( length, villages, castle, iterations, size, players, island)
res.max_lakes=40
res.min_lake_height=450
res.lake_size=35
res.river_frequency=80
res.temperature_size=size
res.roads=20
res.road_windiness=4
res.height = {
dr_height(800, "Uu"),
dr_height(750, "Xu"),
dr_height(725, "Mm^Xm"),
dr_height(690, "Mm"),
dr_height(580, "Hh"),
dr_height(200, "Gg"),
dr_height(100, "Wot"), -- mark anti castle generation
dr_height(35, "Ds"),
dr_height(1, "Wwg"),
dr_height(0, "Wog"),
}
res.convert = {
wct_fix_river_into_ocean("g", 33),
-- DR_CONVERT MIN_HT MAX_HT MIN_TMP MAX_TMP FROM TO
-- low temperatures
dr_convert(100, 999, 0, 400, "Ww", "Ai"),
dr_convert(500, 999, 0, 420, "Ww", "Ai"),
dr_convert(300, 999, 0, 410, "Gg", "Aa"),
dr_convert(420, 999, 0, 425, "Gg", "Aa"),
dr_convert(580, 999, 0, 430, "Hh", "Ha"),
dr_convert(580, 999, 0, 435, "Mm", "Ms"),
dr_convert(580, 999, 0, 440, "Mm^Xm", "Ms^Xm"),
-- desert appears at extreme temperatures and medium altitude
dr_convert(250, 530, 800, 999, "Gg", "Dd"),
-- swamps
dr_convert(450, 500, 500, 575, "Gg", "Ss"),
dr_convert(300, 350, 475, 525, "Gg", "Ss"),
dr_convert(100, 200, 450, 500, "Gg,Wot", "Ss"),
dr_temperature("Gg", 0, 460, "Gs"),
dr_temperature("Hh", 470, 999, "Hhd"), -- mark for forst type
}
res.road_cost = {
dr_road("Gg", "Re", 8),
dr_road("Gs", "Re", 9),
dr_road("Ss", "Ce", 20),
dr_road("Hh", "Re", 20),
dr_road("Hhd", "Re", 20),
dr_road("Mm", "Re", 35),
dr_road("Mm^Xm", "Re", 50),
dr_road("Uu", "Re", 10),
dr_road("Xu", "Re", 50),
dr_road("Aa", "Coa", 20),
dr_road("Ha", "Re", 20),
dr_road("Dd", "Cd", 20),
dr_road("Hd", "Re", 20),
dr_bridge("Ww", "Ww^Bw", "Ce", 45),
dr_road("Re", "Re", 2),
dr_road_over_bridges("Ww^Bw", 2),
dr_road("Ch", "Ch", 2),
dr_road("Ce", "Ce", 2),
dr_road("Cd", "Cd", 2),
dr_road("Coa", "Coa", 2),
}
res.village = {
dr_village {
terrain = "Gg",
convert_to="Gg^Vc",
adjacent_liked="Gg, Gg, Gg, Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Hh, Hhd",
rating=8
},
dr_village {
terrain = "Gs",
convert_to="Gg^Vc",
adjacent_liked="Gg, Gg, Gs, Gs, Gs, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Hh, Hhd",
rating=8
},
dr_village {
terrain="Ds",
convert_to="Ds^Vda",
adjacent_liked="Gg, Ds, Ds, Wwg, Wwg, Wwg, Ww, Hhd",
rating=2
},
dr_village {
terrain="Uu",
convert_to="Uu^Vud",
adjacent_liked="Re,Hh,Hhd,Mm,Uu,Uu,Uu,Xu",
rating=4
},
dr_village {
terrain="Hh",
convert_to="Hh^Vhh",
adjacent_liked="Gs, Gs, Gs, Gs, Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Hh, Hh, Hhd",
rating=4
},
dr_village {
terrain="Hhd",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Gg, Gg, Gg, Gs, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Hhd, Hhd, Hhd",
rating=5
},
dr_village {
terrain="Mm",
convert_to="Mm^Vhh",
adjacent_liked="Gg, Gg, Gg, Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Hh, Hh, Hhd, Hhd",
rating=3
},
-- villages in snow
dr_village {
terrain="Aa",
convert_to="Aa^Voa",
adjacent_liked="Gs, Gs, Aa, Aa, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Hh, Ha, Ha",
rating=3
},
-- villages in dessert
dr_village {
terrain="Dd",
convert_to="Dd^Vda",
adjacent_liked="Gg, Gg, Dd, Dd, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Hhd, Hhd",
rating=3
},
-- swamp villages
dr_village {
terrain="Ss",
convert_to="Ss^Vhs",
adjacent_liked="Gg, Gg, Gs, Gs, Ss, Ss, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Hh, Hh, Hhd, Hhd",
rating=2
},
-- mermen villages - give them low chance of appearing
dr_village {
terrain="Wwg",
convert_to="Wwg^Vm",
adjacent_liked="Wwg, Wwg",
rating=1
},
}
res.castle = {
valid_terrain="Gs, Gg, Hh, Hhd, Mm, Aa, Ha",
min_distance=13,
}
return default_generate_map(res)
end
return generate

View file

@ -0,0 +1,226 @@
local function generate(length, villages, castle, iterations, size, players, island)
local res = wct_generator_settings_arguments( length, villages, castle, iterations, size, players, island)
res.max_lakes=115
res.min_lake_height=320
res.lake_size=60
res.river_frequency=95
res.temperature_size=7
res.roads=11
res.road_windiness=8
res.height = {
-- list of common terrain types which come in at different heights, from highest to lowest
dr_height(950, "Uh"),
dr_height(910, "Uu"),
dr_height(870, "Uh"),
dr_height(820, "Uu"),
dr_height(780, "Xu"),
dr_height(765, "Mm^Xm"),
dr_height(725, "Mm"),
dr_height(715, "Hh"),
dr_height(710, "Hh^Fp"),
dr_height(685, "Hh"),
dr_height(675, "Hh^Uf"),
dr_height(650, "Hh"),
dr_height(645, "Hh^Fp"),
dr_height(610, "Hh"),
dr_height(600, "Gg"),
dr_height(590, "Hh^Fp"),
dr_height(580, "Gg"),
dr_height(570, "Gs^Fp"),
dr_height(425, "Gg"),
dr_height(420, "Hh^Fp"),
dr_height(410, "Gg"),
dr_height(400, "Mm"),
dr_height(395, "Gs^Uf"),
dr_height(380, "Ss"),
dr_height(375, "Gs^Uf"),
dr_height(360, "Gg"),
dr_height(340, "Hh^Fp"),
dr_height(320, "Gg"),
dr_height(300, "Gs^Fp"),
dr_height(260, "Gg"),
dr_height(240, "Ss"),
dr_height(220, "Gs^Fp"),
dr_height(200, "Hh^Fp"),
dr_height(125, "Gg"),
dr_height(50, "Ds"),
dr_height(1, "Wwt"),
dr_height(0, "Wot"),
}
res.convert = {
wct_fix_river_into_ocean("t", 46),
-- DR_CONVERT MIN_HT MAX_HT MIN_TMP MAX_TMP FROM TO
-- low temperatures
dr_convert(80, 999, 0, 375, "Gg, Gs^Uf", "Aa"),
dr_convert(250, 999, 0, 375, "Ss", "Ai"),
dr_convert(80, 999, 370, 425, "Gg", "Gs"),
dr_convert(80, 999, 0, 375, "Gs^Fp", "Aa^Fpa"),
dr_convert(80, 999, 375, 425, "Gs^Fp", "Gs^Fmw"),
dr_convert(0, 999, 0, 400, "Hh^Fp, Hh^Uf", "Ha^Fpa"),
dr_convert(80, 999, 400, 450, "Hh^Fp", "Hh^Fmw"),
dr_convert(0, 999, 0, 425, "Hh", "Ha"),
dr_convert(0, 999, 0, 450, "Mm", "Ms"),
dr_convert(750, 999, 0, 460, "Mm^Xm", "Ms^Xm"),
-- fungus
dr_convert(850, 950, 500, 525, "Uu, Uh", "Uu^Uf"),
dr_convert(850, 950, 550, 575, "Uu, Uh", "Uu^Uf"),
dr_convert(850, 950, 600, 625, "Uu, Uh", "Uu^Uf"),
-- high temperatures
dr_convert(825, 999, 850, 999, "Uu, Uh, Uu^Uf", "Ql"),
dr_convert(0, 999, 800, 999, "Gg", "Dd"),
dr_convert(250, 999, 800, 999, "Ss", "Dd^Do"),
dr_convert(80, 999, 750, 800, "Gg", "Gs"),
dr_convert(80, 999, 730, 760, "Gs^Fp", "Gs^Fet"),
-- moderate temperatures
dr_convert(0, 999, 450, 575, "Hh^Fp", "Hh^Fmf"),
dr_convert(0, 999, 430, 575, "Gs^Fp", "Gg^Fmf"),
dr_convert(0, 999, 575, 725, "Hh^Fp", "Hh^Fms"),
dr_convert(0, 999, 575, 725, "Gs^Fp", "Gg^Fms"),
}
res.road_cost = {
dr_road("Gg", "Urb", 10),
dr_road("Gs^Fp", "Urb", 20),
dr_road("Gs^Fmw", "Urb", 20),
dr_road("Gs^Fet", "Urb", 20),
dr_road("Gg^Fmf", "Urb", 20),
dr_road("Gg^Fms", "Urb", 20),
dr_road("Hh", "Urb", 25),
dr_road("Hh^Fp", "Urb", 30),
dr_road("Hh^Fmf", "Urb", 30),
dr_road("Hh^Fmw", "Urb", 30),
dr_road("Hh^Fms", "Urb", 30),
dr_road("Hh^Uf", "Urb", 25),
dr_road("Mm", "Urb", 40),
dr_road("Mm^Xm", "Urb", 75),
dr_bridge("Ql", "Ql^Bs", "Urb", 100),
dr_bridge("Qxu", "Qxu^Bs", "Urb", 100),
dr_road("Uu", "Urb", 10),
dr_road("Uh", "Urb", 35),
dr_road("Xu", "Urb", 80),
dr_road("Aa", "Urb", 15),
dr_road("Ha", "Urb", 20),
dr_road("Ha^Fpa", "Urb", 25),
dr_road("Aa^Fpa", "Urb", 20),
dr_bridge("Ww", "Ww^Bcx", "Ce", 50),
dr_road("Urb", "Urb", 2),
dr_road_over_bridges("Ww^Bcx", 2),
dr_road("Ch", "Ch", 2),
dr_road("Ce", "Ce", 2),
dr_road("Dd", "Urb", 25),
dr_road("Ds", "Urb", 35),
}
res.village = {
dr_village {
terrain = "Gg",
convert_to="Gg^Vh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Urb, Urb, Urb, Urb, Hh, Gs^Fp, Gg^Fms",
rating=8
},
dr_village {
terrain = "Gs",
convert_to="Gs^Vh",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Urb, Urb, Urb, Urb, Hh, Ha, Gs^Fp, Gg^Fms",
rating=5
},
dr_village {
terrain="Ds",
convert_to="Ds^Vda",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Urb, Urb, Urb, Urb, Hh, Gs^Fp",
rating=2
},
dr_village {
terrain="Dd",
convert_to="Dd^Vda",
adjacent_liked="Gg, Gs, Dd, Dd, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Ww, Ww, Urb, Urb, Hh, Gs^Fp, Mm",
rating=4
},
-- villages in cave are orcish
dr_village {
terrain="Uu",
convert_to="Uu^Vo",
adjacent_liked="Urb,Hh,Mm,Uu,Uh,Xu,Mm^Xm,Uu^Uf,Uu,Uh,Ww,Ww",
rating=5
},
dr_village {
terrain="Uu^Uf",
convert_to="Uh^Vo",
adjacent_liked="Urb,Hh,Mm,Uu,Uh,Xu,Mm^Xm,Uu^Uf,Uu,Uh,Ww,Ww",
rating=5
},
dr_village {
terrain="Uh",
convert_to="Uu^Vo",
adjacent_liked="Urb,Hh,Mm,Uu,Uh,Xu,Mm^Xm,Uu^Uf,Uu,Uh,Ww,Ww",
rating=5
},
-- villages in forest
dr_village {
terrain="Gs^Fp",
convert_to="Gs^Vh",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Urb, Urb, Urb, Urb, Hh, Gs^Fp, Gs^Fp, Gg^Fms",
rating=4
},
dr_village {
terrain="Gg^Fms",
convert_to="Gg^Vh",
adjacent_liked="Gg, Gs, Gg, Ww, Ww, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Urb, Urb, Urb, Urb, Hh, Gs^Fp, Gg^Fms, Gg^Fms",
rating=4
},
dr_village {
terrain="Hh",
convert_to="Hh^Vh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Urb, Urb, Urb, Urb, Gg^Ve, Gg^Vh, Hh, Gs^Fp",
rating=4
},
dr_village {
terrain="Mm",
convert_to="Mm^Vd",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Urb, Urb, Urb, Urb, Gg^Ve, Gg^Vh, Hh, Gs^Fp",
rating=3
},
-- villages in snow
dr_village {
terrain="Aa",
convert_to="Aa^Vha",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Urb, Urb, Urb, Urb, Gg^Ve, Gg^Vh, Hh, Gs^Fp",
rating=3
},
dr_village {
terrain="Aa^Fpa",
convert_to="Aa^Vha",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Urb, Urb, Urb, Urb, Gg^Ve, Gg^Vh, Hh, Gs^Fp",
rating=3
},
dr_village {
terrain="Ha",
convert_to="Ha^Vha",
adjacent_liked="Gg, Gs, Gs, Ww, Ww, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Urb, Urb, Urb, Urb, Hh, Ha, Mm, Gs^Fp",
rating=3
},
-- swamp villages
dr_village {
terrain="Ss",
convert_to="Ss^Vhs",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bcx|, Ww^Bcx/, Ww^Bcx\\, Urb, Urb, Urb, Urb, Gg^Ve, Gg^Vh, Hh, Gs^Fp",
rating=2
},
-- mermen villages
dr_village {
terrain="Wwt",
convert_to="Wwt^Vm",
adjacent_liked="Wwt, Wwt",
rating=1
},
}
res.castle = {
valid_terrain="Gs, Gg, Hh, Ha, Hh^Uf, Gs^Uf, Ss, Dd, Aa",
min_distance=16,
}
return default_generate_map(res)
end
return generate

View file

@ -0,0 +1,202 @@
local function generate(length, villages, castle, iterations, size, players, island)
local res = wct_generator_settings_arguments( length, villages, castle, iterations, size, players, island)
res.max_lakes=90
res.min_lake_height=250
res.lake_size=60
res.river_frequency=100
res.temperature_size=7
res.roads=25
res.road_windiness=2
res.height = {
-- list of common terrain types which come in at different heights, from highest to lowest
dr_height(910, "Uh"),
dr_height(820, "Uu"),
dr_height(780, "Xu"),
dr_height(765, "Mm^Xm"),
dr_height(725, "Mm"),
dr_height(610, "Hh"),
dr_height(600, "Gg"),
dr_height(590, "Hh^Fp"),
dr_height(580, "Gg"),
dr_height(570, "Gs^Fp"),
dr_height(410, "Gg"),
dr_height(400, "Mm"),
dr_height(360, "Gg"),
dr_height(340, "Hh^Fp"),
dr_height(320, "Gg"),
dr_height(300, "Gs^Fp"),
dr_height(240, "Gg"),
dr_height(220, "Gs^Fp"),
dr_height(200, "Hh^Fp"),
dr_height(180, "Hh"),
dr_height(100, "Gg"),
dr_height(30, "Ds"),
dr_height(1, "Wwg"),
dr_height(0, "Wog"),
}
res.convert = {
wct_fix_river_into_ocean("g", 29),
-- DR_CONVERT MIN_HT MAX_HT MIN_TMP MAX_TMP FROM TO
-- low temperatures
dr_convert(50, 999, 0, 270, "Ww, Wo", "Ai"),
dr_convert(350, 999, 0, 320, "Gg", "Aa"),
dr_convert(330, 999, 320, 370, "Gg", "Gd"),
dr_convert(100, 999, 370, 475, "Gg", "Gs"),
dr_convert(350, 999, 0, 310, "Gs^Fp", "Aa^Fpa"),
dr_convert(350, 999, 0, 345, "Hh", "Ha"),
dr_convert(350, 999, 0, 335, "Hh^Fp", "Ha^Fpa"),
dr_convert(350, 999, 0, 370, "Mm", "Ms"),
dr_convert(350, 999, 0, 390, "Mm^Xm", "Ms^Xm"),
-- swamp appears on low land, at mod temp
dr_convert(0, 200, 400, 700, "Gg", "Ss"),
-- pine appears at low temperatures
dr_convert(150, 999, 320, 420, "Gg", "Gs^Fp"),
dr_convert(150, 999, 320, 420, "Hh", "Hh^Fp"),
-- decidius appears at mod temperatures with some heigh
dr_convert(300, 999, 510, 540, "Gg,Gs", "Gg^Fds"),
dr_convert(300, 999, 510, 540, "Hh", "Hh^Fds"),
-- fungus appears at med temp and high
dr_convert(825, 950, 500, 525, "Uu, Uh", "Uu^Uf"),
dr_convert(825, 950, 550, 575, "Uu, Uh", "Uu^Uf"),
dr_convert(825, 950, 600, 625, "Uu, Uh", "Uu^Uf"),
-- high temperatures
dr_convert(800, 999, 850, 999, "Uu, Uh, Uu^Uf", "Ql"),
dr_convert(260, 999, 800, 999, "Gg", "Dd"),
dr_convert(230, 999, 750, 999, "Gg", "Gd"),
dr_convert(100, 999, 650, 999, "Gg", "Gs"),
dr_convert(460, 630, 800, 999, "Ds, Hh", "Hd"),
-- DR_TEMPERATURE FROM MIN MAX TO),
-- convert forest at different temperatures
dr_temperature("Gs^Fp", 420, 475, "Gs^Fdf"),
dr_temperature("Hh^Fp", 420, 510, "Hh^Fmf"),
dr_temperature("Gs^Fp", 475, 510, "Gg^Fdf"),
dr_temperature("Gs^Fp", 510, 540, "Gg^Fds"),
dr_temperature("Hh^Fp", 510, 540, "Hh^Fds"),
dr_temperature("Gs^Fp", 540, 650, "Gg^Ftr"),
dr_temperature("Hh^Fp", 540, 650, "Hh^Fms"),
}
res.road_cost = {
wct_generator_road_cost_classic(),
dr_road("Gs", "Re", 10),
dr_road("Gd", "Re", 10),
dr_road("Gg^Fds", "Re", 20),
dr_road("Gg^Ftr", "Re", 20),
dr_road("Gg^Fdf", "Re", 20),
dr_road("Hh^Fmf", "Re", 20),
dr_road("Hh^Ft", "Re", 30),
dr_road("Hh^Fp", "Re", 30),
dr_road("Hh^Fds", "Re", 20),
dr_road("Hh^Fms", "Re", 20),
dr_road("Gs^Ft", "Re", 30),
dr_road("Ds", "Re", 20),
dr_bridge("Ww", "Ww^Bsb", "Chw", 35),
dr_road("Chw", "Chw", 2),
dr_road_over_bridges("Ww^Bsb", 2),
}
res.village = {
dr_village {
terrain = "Gg",
convert_to="Gg^Vh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Re, Re, Re, Re, Hh, Gs, Gg",
rating=8
},
dr_village {
terrain = "Gs",
convert_to="Gs^Vh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Re, Re, Re, Re, Hh, Gs, Gg, Gd, Gd, Gs, Gs",
rating=5
},
dr_village {
terrain = "Gd",
convert_to="Gd^Vc",
adjacent_liked="Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Re, Re, Re, Re, Hh, Gs, Gd, Gd, Gs, Gs, Gd",
rating=5
},
dr_village {
terrain="Ds",
convert_to="Dd^Vda",
adjacent_liked="Gg, Gs, Gd, Wwg, Wwg, Wwg, Re, Re, Hh, Ch, Wog,",
rating=2
},
dr_village {
terrain="Uu",
convert_to="Uu^Vud",
adjacent_liked="Re,Hh,Mm,Uu,Uh,Xu",
rating=4
},
dr_village {
terrain="Uh",
convert_to="Uu^Vu",
adjacent_liked="Re,Hh,Mm,Uu,Uh,Xu",
rating=3
},
dr_village {
terrain = "Gg^Fds",
convert_to="Gg^Vh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Re, Re, Re, Re, Hh, Gs, Gg, Gg^Fds",
rating=4
},
dr_village {
terrain="Gs^Fp",
convert_to="Gs^Vh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Re, Re, Re, Re, Hh, Gs, Gg, Gd, Gd, Gs, Gs, Gs^Fp",
rating=4
},
dr_village {
terrain="Hh",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Re, Re, Re, Re, Hh, Gs, Gg, Gd, Gd, Gs, Gs, Gs^Fp",
rating=4
},
dr_village {
terrain="Hh^Fp",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Re, Re, Re, Re, Hh, Gs, Gg, Gd, Gd, Gs, Gs, Gs^Fp",
rating=4
},
dr_village {
terrain="Mm",
convert_to="Mm^Vhh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bsb|, Ww^Bsb/, Ww^Bsb\\, Rr, Rr, Re, Re, Gg^Ve, Gg^Vh, Hh, Gs^Fp",
rating=4
},
-- villages in snow
dr_village {
terrain="Aa",
convert_to="Aa^Vha",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bsb|, Ww^Bsb/, Ww^Bsb\\, Rr, Rr, Re, Re, Gg^Ve, Gg^Vh, Hh, Gs^Fp",
rating=3
},
dr_village {
terrain="Aa^Fpa",
convert_to="Aa^Vea",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bsb|, Ww^Bsb/, Ww^Bsb\\, Rr, Rr, Re, Re, Gg^Ve, Gg^Vh, Hh, Gs^Fp",
rating=3
},
-- swamp villages
dr_village {
terrain="Ss",
convert_to="Ss^Vhs",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bsb|, Ww^Bsb/, Ww^Bsb\\, Rr, Rr, Re, Re, Gg^Ve, Gg^Vh, Hh, Gs^Fp",
rating=2
},
-- mermen villages - give them low chance of appearing
dr_village {
terrain="Wwg",
convert_to="Wwg^Vm",
adjacent_liked="Wwg, Wwg, Ch, Ss, Ds, Ds",
rating=1
},
}
res.castle = {
valid_terrain="Gs, Gg, Gd, Gs^Fp, Gg^Ft, Gg^Fds, Gg^Ftr, Hh, Hh^Fp, Hh^Ft, Hh^Fds, Hh^Fms, Ha^Fpa, Ha, Hh^Fmf, Gg^Fdf",
min_distance=15,
}
return default_generate_map(res)
end
return generate

View file

@ -0,0 +1,211 @@
local function generate(length, villages, castle, iterations, size, players, island)
local res = wct_generator_settings_arguments( length, villages, castle, iterations, size, players, island)
res.max_lakes=5
res.min_lake_height=900
res.lake_size=1
res.river_frequency=1
res.temperature_size=size
res.roads=25
res.road_windiness=4
res.height = {
-- list of common terrain types which come in at different heights, from highest to lowest
dr_height(990, "Rr"),
dr_height(980, "Ww"),
dr_height(960, "Rr"),
dr_height(950, "Xos"),
dr_height(940, "Rr^Fet"),
dr_height(910, "Xos"),
dr_height(870, "Rr"),
dr_height(855, "Rr^Fet"),
dr_height(850, "Ww"),
dr_height(840, "Hh^Fp"),
dr_height(830, "Hh"),
dr_height(820, "Mm"),
dr_height(810, "Gg"),
dr_height(785, "Gg^Fp"),
dr_height(775, "Gg"),
dr_height(760, "Hh^Fp"),
dr_height(750, "Gg"),
dr_height(730, "Hh"),
dr_height(720, "Mm"),
dr_height(685, "Gg"),
dr_height(670, "Gg^Fp"),
dr_height(620, "Gg"),
dr_height(610, "Hh^Fp"),
dr_height(560, "Gg"),
dr_height(550, "Hh"),
dr_height(500, "Gg"),
dr_height(485, "Mm"),
dr_height(450, "Hh"),
dr_height(400, "Hh^Fp"),
dr_height(350, "Gg^Fp"),
dr_height(230, "Gg"),
dr_height(220, "Gg^Fp"),
dr_height(85, "Gg"),
dr_height(30, "Ds"),
dr_height(20, "Ww"),
dr_height(17, "Wwr"),
dr_height(1, "Ww"),
dr_height(0, "Wo"),
}
res.convert = {
-- DR_CONVERT MIN_HT MAX_HT MIN_TMP MAX_TMP FROM TO
dr_convert(70, 150, 10, 300, "Gg", "Ss"),
dr_convert(550, 680, 350, 370, "Gg", "Hh^Uf"),
dr_convert(550, 680, 620, 640, "Gg", "Hh^Uf"),
-- DR_TEMPERATURE FROM MIN MAX TO),
-- convert forest at different temperatures
dr_temperature("Gs^Fp", 700, 990, "Gg^Ft"),
dr_temperature("Hh^Fp", 700, 990, "Hh^Ft"),
dr_temperature("Gg^Fp", 400, 700, "Gg^Ftp"),
dr_temperature("Hh^Fp", 400, 700, "Hh^Ftp"),
dr_temperature("Gg^Fp", 250, 400, "Gg^Ftr"),
dr_temperature("Hh^Fp", 250, 400, "Hh^Ftd"),
dr_temperature("Gg^Fp", 125, 250, "Gg^Fds"),
dr_temperature("Hh^Fp", 125, 250, "Hh^Fds"),
dr_temperature("Gg^Fp", 10, 125, "Gg^Fms"),
dr_temperature("Hh^Fp", 10, 125, "Hh^Fms"),
}
res.road_cost = {
-- try to conect citadels
dr_bridge("Rr", "Ww^Bsb", "Rr", 1),
dr_road("Ww^Bsb", "Ww^Bsb", 3),
dr_road("Rr^Fet", "Rr^Fet", 1),
dr_road("Xos", "Xos", 1),
-- flat
dr_road("Ch", "Ch", 2),
dr_road("Re", "Re", 2),
dr_road("Gg", "Re", 10),
-- forest
dr_road("Gg^Ftp", "Re", 20),
dr_road("Gg^Fms", "Re", 20),
dr_road("Gg^Fds", "Re", 20),
dr_road("Gg^Ft", "Re", 20),
dr_road("Gg^Ftr", "Re", 20),
dr_road("Hh^Ftp", "Re", 20),
dr_road("Hh^Fms", "Re", 20),
dr_road("Hh^Fds", "Re", 20),
dr_road("Hh^Ft", "Re", 20),
dr_road("Hh^Ftd", "Re", 20),
-- rough
dr_road("Hh", "Re", 20),
dr_road("Mm", "Re", 40),
dr_road("Ds", "Re", 25),
dr_bridge("Ww", "Ww^Bw", "Ch", 50),
}
res.village = {
dr_village {
terrain = "Rr",
convert_to="Rr^Vhc",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Rr, Rr, Re, Re, Rr^Fet, Gg^Vh, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=10
},
dr_village {
terrain = "Gg",
convert_to="Gg^Vh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Rr, Rr, Re, Re, Rr^Fet, Gg^Vh, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=5
},
dr_village {
terrain = "Hh^Fms",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Rr, Rr, Re, Re, Rr^Fet, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=2
},
dr_village {
terrain = "Hh^Fds",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Rr, Rr, Re, Re, Rr^Fet, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=2
},
dr_village {
terrain = "Hh^Ftp",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Rr, Rr, Re, Re, Rr^Fet, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=2
},
dr_village {
terrain = "Hh^Ft",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Rr, Rr, Re, Re, Rr^Fet, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=2
},
dr_village {
terrain = "Hh^Ftd",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Rr, Rr, Re, Re, Rr^Fet, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=3
},
dr_village {
terrain="Ds",
convert_to="Ds^Vc",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Rr, Rr, Re, Re, Hh, Rr^Fet, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=2
},
dr_village {
terrain="Gg^Fms",
convert_to="Gg^Vh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Rr, Rr, Re, Re, Rr^Fet, Gg^Vh, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=3
},
dr_village {
terrain="Gg^Fds",
convert_to="Gg^Vh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Rr, Rr, Re, Re, Rr^Fet, Gg^Vh, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=3
},
dr_village {
terrain="Gg^Ft",
convert_to="Gg^Vh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Rr, Rr, Re, Re, Rr^Fet, Gg^Vh, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=3
},
dr_village {
terrain="Gg^Ftp",
convert_to="Gg^Vh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Rr, Rr, Re, Re, Rr^Fet, Gg^Vh, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=3
},
dr_village {
terrain="Gg^Ftr",
convert_to="Gg^Vh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Rr, Rr, Re, Re, Rr^Fet, Gg^Vh, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=3
},
dr_village {
terrain="Hh",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Rr, Rr, Re, Re, Rr^Fet, Gg^Vh, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=4
},
dr_village {
terrain="Mm",
convert_to="Mm^Vhh",
adjacent_liked="Gg, Gg^Ftr, Gg^Ftp, Gg^Fds, Gg^Fms, Gg^Ftd, Gg^Ft, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Rr, Rr, Re, Re, Rr^Fet, Gg^Vh, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Xos",
rating=3
},
dr_village {
terrain="Ss",
convert_to="Ss^Vhs",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Rr, Rr, Re, Re, Gg^Ve, Gg^Vh, Hh, Gs^Fp",
rating=1
},
dr_village {
terrain="Ww",
convert_to="Ww^Vm",
adjacent_liked="Ww, Ww",
rating=1
},
}
res.castle = {
valid_terrain="Gg, Gg^Fp, Gg^Ft, Gg^Ftr, Gg^Ftp, Gg^Ftd, Gg^Fds, Gg^Fms, Hh, Hh^Ft, Hh^Ftr, Hh^Ftp, Hh^Ftd, Hh^Fds, Hh^Fms, Mm, Hh^Fp",
min_distance=14,
}
return default_generate_map(res)
end
return generate

View file

@ -0,0 +1,210 @@
local function generate(length, villages, castle, iterations, size, players, island)
local res = wct_generator_settings_arguments( length, villages, castle, iterations, size, players, island)
res.max_lakes=30
res.min_lake_height=170
res.lake_size=75
res.river_frequency=80
res.temperature_size=9
res.roads=11
res.road_windiness=8
res.height = {
dr_height(990, "Qxu"),
dr_height(960, "Uu"),
dr_height(900, "Uh"),
dr_height(825, "Uu"),
dr_height(775, "Xu"),
dr_height(750, "Mm^Xm"),
dr_height(720, "Mm"),
dr_height(670, "Hhd"),
dr_height(650, "Hh^Fp"),
dr_height(630, "Hhd^Uf"),
dr_height(610, "Gll^Fp"),
dr_height(590, "Gll^Uf"),
dr_height(580, "Hhd"),
dr_height(400, "Gll"),
dr_height(395, "Hh"),
dr_height(360, "Ss"),
dr_height(340, "Gll^Ftr"),
dr_height(330, "Hh"),
dr_height(320, "Hh^Uf"),
dr_height(300, "Hh^Fp"),
dr_height(280, "Ss"),
dr_height(270, "Hh"),
dr_height(250, "Gll^Fp"),
dr_height(225, "Gll^Uf"),
dr_height(175, "Gll"),
dr_height(70, "Ds"),
dr_height(65, "Wwrt"),
dr_height(35, "Wwt"),
dr_height(30, "Wwrt"),
dr_height(1, "Wwt"),
dr_height(0, "Wot"),
}
res.convert = {
wct_fix_river_into_ocean("t", 65),
-- DR_CONVERT MIN_HT MAX_HT MIN_TMP MAX_TMP FROM TO
dr_convert(360, 999, 10, 400, "Ww", "Ai"),
dr_convert(475, 750, 10, 415, "Gll^Fp", "Aa^Fpa"),
dr_convert(450, 750, 10, 425, "Gll", "Aa"),
dr_convert(410, 750, 10, 465, "Gll,Gll^Uf", "Gd"),
dr_convert(650, 750, 10, 540, "Hh,Hhd", "Ha"),
dr_convert(650, 750, 10, 510, "Hh^Fp", "Ha^Fpa"),
dr_convert(650, 750, 10, 415, "Hh^Uf,Hhd^Uf", "Ha^Uf"),
dr_convert(375, 750, 10, 390, "Ss", "Ai"),
dr_convert(450, 750, 650, 675, "Gll", "Gll^Fet"),
dr_convert(100, 300, 800, 850, "Gll", "Gll^Em"),
dr_convert(400, 750, 680, 700, "Gll", "Gll^Efm"),
dr_convert(475, 505, 725, 750, "Gll", "Ce"),
dr_convert(585, 595, 10, 440, "Aa,Gll^Uf", "Ms"),
dr_convert(575, 585, 10, 440, "Aa", "Ha"),
dr_convert(475, 600, 870, 900, "Gll,Gll^Uf", "Ql"),
-- DR_TEMPERATURE FROM MIN MAX TO),
dr_temperature("Mm", 10, 570, "Ms"),
dr_temperature("Mm^Xm", 10, 585, "Ms^Xm"),
dr_temperature("Ds", 870, 900, "Ds^Edpp"),
dr_temperature("Uu", 100, 300, "Ai"),
dr_temperature("Uu", 650, 700, "Uu^Uf"),
dr_temperature("Uh", 675, 725, "Uh^Uf"),
dr_temperature("(Uu,Uh,Uu^Uf)", 850, 999, "Ql"),
dr_temperature("Qxu", 800, 999, "Ql"),
}
res.road_cost = {
dr_road("Gll", "Rb", 10),
dr_road("Ce", "Rb", 20),
dr_road("Gll^Fp", "Rb", 20),
dr_road("Gll^Ftr", "Rb", 25),
dr_road("Gll^Fet", "Rb", 15),
dr_road("Ds", "Rb", 40),
dr_road("Ww", "Wwf", 50),
dr_road("Gll^Uf", "Rb", 15),
dr_road("Hh^Uf", "Rb", 15),
dr_road("Hhd^Uf", "Rb", 15),
dr_road("Ss", "Rb", 15),
dr_road("Aa", "Rb", 10),
dr_road("Hh", "Rb", 20),
dr_road("Hhd", "Rb", 20),
dr_road("Hh^Fp", "Rb", 25),
dr_road("Ha", "Rb", 25),
dr_road("Ha^Fpa", "Rb", 30),
dr_road("Mm", "Rb", 50),
dr_road("Ms", "Rb", 55),
dr_bridge("Ql", "Ql^Bsb", "Cud", 45),
dr_road("Uu", "Rb", 35),
dr_road("Uu^Uf", "Rb", 40),
dr_road("Uh", "Rb", 45),
dr_road("Xu", "Rb", 60),
dr_road("Rb", "Rb", 2),
dr_road_over_bridges("Ql^Bsb", 2),
}
res.village = {
dr_village {
terrain = "Gll",
convert_to="Gll^Vh",
adjacent_liked="Gll, Ce, Ww, Ww, Ww, Ww, Ww, Wwt, Wwf, Wwf, Rb, Rb, Rb, Rb, Gll, Gll, Hh, Gll^Fp",
rating=5
},
dr_village {
terrain = "Gd",
convert_to="Gd^Vc",
adjacent_liked="Gll, Gll^Fet, Ww, Ww, Ww, Ww, Wwt, Wwf, Wwf, Rb, Rb, Ce, Gd, Gd, Gll, Hh, Hh^Fp, Gll^Fp",
rating=5
},
dr_village {
terrain="Gll^Fp",
convert_to="Gll^Ve",
adjacent_liked="Gll, Gll^Fet, Ww, Ww, Ww, Ww, Ww, Wwt, Wwf, Wwf, Rb, Rb, Rb, Ce, Gd, Gll, Hh, Hh^Fp, Gll^Fp",
rating=5
},
dr_village {
terrain="Gll^Fet",
convert_to="Gll^Ve",
adjacent_liked="Gll, Gll^Fet, Ww, Ww, Ww, Ww, Ww, Wwt, Wwf, Wwf, Rb, Rb, Rb, Ce, Gd, Gll, Hh, Hh^Fp, Gll^Fp, Gll^Fp, Gll^Fet, Gll^Fet",
rating=7
},
dr_village {
terrain="Ds",
convert_to="Ds^Vda",
adjacent_liked="Gll, Gll, Wwt, Wwt, Wwt, Wwt, Wwt, Rb, Rb, Rb, Rb, Gll, Gll, Hh, Hh^Fp, Gll^Fp, Gll^Fet, Ds",
rating=4
},
dr_village {
terrain="Uu",
convert_to="Uu^Vo",
adjacent_liked="Ai,Hh,Mm,Uu,Uh,Uu^Uf,Xu,Rb",
rating=4
},
dr_village {
terrain="Uh",
convert_to="Uh^Vud",
adjacent_liked="Ai,Hh,Mm,Uu,Uh,Uu^Uf,Xu,Rb",
rating=3
},
dr_village {
terrain="Hh",
convert_to="Hh^Vhh",
adjacent_liked="Gll, Gll^Fet, Ww, Ww, Ww, Ww, Ww, Wwt, Wwf, Wwf, Rb, Rb, Rb, Ce, Gd, Gll, Hh, Hh^Fp, Gll^Fp, Gll^Fp, Gll^Fet, Gll^Fet",
rating=4
},
dr_village {
terrain="Hhd",
convert_to="Hh^Vhh",
adjacent_liked="Gll, Gll^Fet, Ww, Ww, Ww, Ww, Ww, Ww, Wwf, Wwf, Rb, Rb, Rb, Ce, Gd, Gll, Hhd, Hh^Fp, Gll^Fp, Gll^Fp, Gll^Fet, Gll^Fet",
rating=4
},
dr_village {
terrain="Mm",
convert_to="Mm^Vhh",
adjacent_liked="Gll, Gll^Fet, Mm, Mm^Xm, Ms, Ha, Ha^Fpa, Ww, Wwf, Wwf, Rb, Rb, Ce, Gd, Gd, Gll, Hh, Hh^Fp, Gll^Fp, Gll^Fp, Gll^Fet, Gll^Fet",
rating=3
},
-- villages in snow
dr_village {
terrain="Aa",
convert_to="Aa^Vha",
adjacent_liked="Gll, Gll^Fet, Aa, Ai, Ha, Mm, Ms, Ww, Wwf, Wwf, Rb, Rb, Ce, Gd, Gd, Gll, Hh, Hh^Fp, Gll^Fp",
rating=3
},
dr_village {
terrain="Aa^Fpa",
convert_to="Aa^Vea",
adjacent_liked="Gll, Gll^Fet, Aa, Ai, Ha, Mm, Ms, Ww, Wwf, Wwf, Rb, Rb, Ce, Gd, Gd, Gll, Hh, Hh^Fp, Gll^Fp",
rating=3
},
dr_village {
terrain="Ha",
convert_to="Ha^Vhha",
adjacent_liked="Gll, Gll^Fet, Aa, Ai, Ha, Mm, Ms, Ww, Wwf, Wwf, Rb, Rb, Ce, Gd, Gd, Gll, Hh, Hh^Fp, Gll^Fp",
rating=2
},
dr_village {
terrain="Ms",
convert_to="Ms^Vhha",
adjacent_liked="Gll, Gll^Fet, Aa, Ai, Ha, Mm, Ms, Ww, Wwf, Wwf, Rb, Rb, Ce, Gd, Gd, Gll, Hh, Hh^Fp, Gll^Fp",
rating=1
},
dr_village {
terrain="Ss",
convert_to="Ss^Vhs",
adjacent_liked="Gll, Ss, Ce, Ww, Ww, Ww, Ww, Wwt, Wwf, Wwf, Rb, Rb, Rb, Rb, Gll, Gll, Hh, Gll^Fp",
rating=3
},
dr_village {
terrain="Ww",
convert_to="Ww^Vm",
adjacent_liked="Ww, Ww",
rating=1
},
}
res.castle = {
valid_terrain="Gll, Gd, Hh, Gll^Ft, Gll^Efm, Gll^Fet, Gll^Ftr, Ss, Ai, Gll^Uf, Hh^Uf, Hh^Fp, Aa, Ha, Ha^Fpa, Mm, Ms",
min_distance=13,
}
return default_generate_map(res)
end
return generate

View file

@ -0,0 +1,183 @@
local function generate(length, villages, castle, iterations, size, players, island)
local res = wct_generator_settings_arguments( length, villages, castle, iterations, size, players, island)
res.max_lakes=5
res.min_lake_height=225
res.lake_size=90
res.river_frequency=80
res.temperature_size=size
res.roads=90
res.road_windiness=6
res.height = {
-- list of common terrain types which come in at different heights, from highest to lowest
dr_height(990, "Uh^Uf"),
dr_height(980, "Qxu"),
dr_height(970, "Uh"),
dr_height(950, "Uu^Uf"),
dr_height(920, "Uu"),
dr_height(915, "Qxu"),
dr_height(895, "Uh"),
dr_height(885, "Uu^Uf"),
dr_height(860, "Uu"),
dr_height(840, "Uh"),
dr_height(830, "Uu^Uf"),
dr_height(800, "Uu"),
dr_height(750, "Xu"),
dr_height(725, "Mm^Xm"),
dr_height(675, "Mm"),
dr_height(560, "Hh"),
dr_height(100, "Gg"),
dr_height(35, "Ds"),
dr_height(1, "Ww"),
dr_height(0, "Wo"),
}
res.convert = {
-- DR_CONVERT MIN_HT MAX_HT MIN_TMP MAX_TMP FROM TO
-- at low temperatures, from medium altitude, snow appears
dr_convert(300, 560, 0, 100, "Gg", "Aa"),
dr_convert(560, 999, 0, 150, "Hh", "Ha"),
-- swamps
dr_convert(100, 200, 410, 690, "Gg", "Ss"),
dr_convert(370, 400, 410, 430, "Gg", "Ss"),
dr_convert(370, 400, 525, 550, "Gg", "Ss"),
-- desert appears at extreme temperatures and medium altitude
dr_convert(250, 999, 780, 999, "Gg", "Dd"),
dr_convert(560, 590, 800, 999, "Hh", "Hd"),
-- savannah appears on mod temp and high
dr_convert(250, 400, 500, 780, "Gg", "Gs"),
-- forest appears at moderate temperatures
dr_convert(0, 999, 320, 420, "Gg", "Gs^Fp"),
dr_convert(0, 999, 320, 420, "Hh", "Hh^Fp"),
-- jungle appears at mod high temperatures
dr_convert(0, 999, 450, 520, "Gg,Gs", "Gs^Ft"),
dr_convert(0, 999, 450, 520, "Hh", "Hh^Ft"),
-- lava appears at extreme temperature
dr_temperature("Qxu", 850, 999, "Ql"),
}
res.road_cost = {
dr_road("Gg", "Re", 5),
dr_road("Gs", "Re", 5),
dr_road("Gs^Ft", "Re", 15),
dr_road("Gs^Fp", "Re", 15),
dr_road("Ss", "Re", 20),
dr_road("Ds", "Re", 25),
dr_road("Hh", "Re", 15),
dr_road("Hh^Fp", "Re", 20),
dr_road("Hh^Ft", "Re", 20),
dr_road("Mm", "Re", 35),
dr_road("Mm^Xm", "Re", 50),
dr_bridge("Ql", "Ql^Bs", "Re", 80),
dr_bridge("Qxu", "Qxu^Bs", "Re", 80),
dr_road("Uu", "Re", 10),
dr_road("Uh", "Re", 35),
dr_road("Xu", "Re", 50),
dr_road("Aa", "Re", 20),
dr_road("Ha", "Re", 20),
dr_road("Dd", "Re", 15),
dr_road("Hd", "Re", 20),
dr_road("Re", "Re", 2),
dr_road_over_bridges("Ww^Bw", 2),
dr_road("Ch", "Ch", 2),
dr_bridge("Ww", "Ww^Bw", "Rb", 50),
}
res.village = {
dr_village {
terrain = "Gg",
convert_to="Gg^Vh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Re, Re, Hh, Gs^Fp",
rating=8
},
dr_village {
terrain = "Gs",
convert_to="Gs^Vht",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Ww, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Re, Re, Hh, Gs^Fp",
rating=5
},
dr_village {
terrain="Ds",
convert_to="Dd^Vda",
adjacent_liked="Gg, Gs, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Re, Re, Hh, Gs^Fp",
rating=2
},
dr_village {
terrain="Uu",
convert_to="Uu^Vud",
adjacent_liked="Re,Hh,Mm,Uu,Uh,Xu",
rating=4
},
dr_village {
terrain="Uh",
convert_to="Uu^Vu",
adjacent_liked="Re,Hh,Mm,Uu,Uh,Xu",
rating=3
},
-- villages in forest are Elvish
dr_village {
terrain="Gs^Fp",
convert_to="Gg^Ve",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Re, Re, Hh, Gs^Fp, Gs^Fp, Gs^Fp",
rating=4
},
dr_village {
terrain="Hh",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Re, Re, Hh, Gs^Fp",
rating=4
},
dr_village {
terrain="Mm",
convert_to="Mm^Vhh",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Re, Re, Hh, Gs^Fp",
rating=3
},
-- villages in snow
dr_village {
terrain="Aa",
convert_to="Aa^Vha",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Re, Re, Hh, Gs^Fp",
rating=3
},
dr_village {
terrain="Aa^Fpa",
convert_to="Aa^Vea",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Re, Re, Hh, Gs^Fp",
rating=3
},
-- swamp villages
dr_village {
terrain="Ss",
convert_to="Ss^Vhs",
adjacent_liked="Gg, Ww, Ww, Ww, Ww^Bw|, Ww^Bw/, Ww^Bw\\, Re, Re, Re, Re, Hh, Gs^Fp",
rating=2
},
-- mermen villages - give them low chance of appearing
dr_village {
terrain="Ww",
convert_to="Ww^Vm",
adjacent_liked="Ww, Ww",
rating=1
},
dr_village {
terrain="Uu^Uf",
convert_to="Uu^Vud",
adjacent_liked="Hh^Uf,Hh,Mm,Uu,Uh,Xu,Qxu,Uu,Uu^Uf,Uu^Uf,Uh^Uf",
rating=3
},
dr_village {
terrain="Uh^Uf",
convert_to="Uh^Vud",
adjacent_liked="Hh^Uf,Hh,Mm,Uu,Uh,Xu,Qxu,Uu,Uu^Uf,Uh^Uf,Uh^Uf",
rating=2
},
}
res.castle = {
valid_terrain="Gs, Gg, Gs^Fp, Gs^Ft, Hh, Hh^Fp, Hh^Ft, Ss, Mm, Dd, Aa, Ai, Ha",
min_distance=14,
}
return default_generate_map(res)
end
return generate

View file

@ -0,0 +1,65 @@
local function generate(length, villages, castle, iterations, size, players, island)
local res = wct_generator_settings_arguments( length, villages, castle, iterations, size, players, island)
res.max_lakes=10
res.min_lake_height=150
res.lake_size=125
res.river_frequency=100
res.temperature_size=8
res.roads=12
res.road_windiness=10
res.height = {
dr_height(900, "Uh"),
dr_height(800, "Uu"),
dr_height(750, "Xu"),
dr_height(725, "Mm^Xm"),
dr_height(675, "Mm"),
dr_height(550, "Hh"),
dr_height(175, "Gs"),
dr_height(30, "Ds"),
dr_height(1, "Ww"),
dr_height(0, "Wo"),
}
res.convert = {
-- swamp appears on low land, at moderate temperatures
dr_convert(nil, 300, 300, 700, "Gg,Gs", "Ss"),
-- jungle appears at moderately high temperatures
dr_temperature("Gg,Gs", 380, 430, "Gs^Ft"),
dr_temperature("Gg,Gs", 460, 520, "Gs^Ft"),
-- fungus appears at medium temperatures and extremely high elevation
-- DR_CONVERT MIN_HT MAX_HT MIN_TMP MAX_TMP FROM TO
dr_convert(825, 950, 500, 525, "Uu, Uh", "Uu^Uf"),
dr_convert(825, 950, 550, 575, "Uu, Uh", "Uu^Uf"),
dr_convert(825, 950, 600, 625, "Uu, Uh", "Uu^Uf"),
-- lava appears at extreme temperatures and elevation
dr_convert(800, nil, 900, nil, "Uu, Uh, Uu^Uf", "Ql"),
-- desert appears at high temperatures
dr_temperature("Gs", 475, 500, "Dd"),
dr_temperature("Gs", 600, 650, "Dd"),
dr_temperature("Gs", 725, 775, "Dd"),
dr_temperature("Gs", 800, 999, "Dd"),
-- dunes appear at extreme temperatures
dr_temperature("Hh", 625, 650, "Hd"),
dr_temperature("Hh", 750, 775, "Hd"),
dr_temperature("Hh", 825, 999, "Hd"),
}
res.road_cost = {
wct_generator_road_cost_classic(),
dr_road("Ds", "Re", 15),
dr_road("Dd", "Re", 15),
dr_road("Gs^Ft", "Re", 20),
dr_bridge("Ww", "Ww^Bw", "Ce", 50),
}
res.village = {
wct_generator_village(2, 8, 8, 4, 3, 2, 6, 3, 3, 3, 5, 1)
}
res.castle = {
valid_terrain="Gs, Gg, Gs^Fp, Hh, Ds, Dd",
min_distance=12,
}
return default_generate_map(res)
end
return generate

View file

@ -0,0 +1,250 @@
local function generate(length, villages, castle, iterations, size, players, island)
local res = wct_generator_settings_arguments( length, villages, castle, iterations, size, players, island)
res.max_lakes=1
res.min_lake_height=150
res.lake_size=5
res.river_frequency=10
res.temperature_size=8
res.roads=15
res.road_windiness=4
res.height = {
dr_height(925, "Uh"),
dr_height(820, "Uu"),
dr_height(765, "Xu"),
dr_height(750, "Mm^Xm"),
dr_height(700, "Mm"),
dr_height(680, "Hh^Uf"),
dr_height(650, "Gs^Fp"),
dr_height(625, "Hh^Fp"),
dr_height(575, "Hh"),
dr_height(400, "Gs"),
dr_height(375, "Gs^Fp"),
dr_height(325, "Gs"),
dr_height(300, "Hh^Fp"),
dr_height(275, "Hh"),
dr_height(175, "Gs"),
dr_height(30, "Ds"),
dr_height(1, "Wwt"),
dr_height(0, "Wot"),
}
res.convert = {
-- DR_CONVERT MIN_HT MAX_HT MIN_TMP MAX_TMP FROM TO
dr_convert(450, 525, 925, 999, "Gs", "Md^Xm"),
dr_convert(450, 525, 875, 925, "Gs", "Md"),
dr_convert(450, 525, 775, 875, "Gs", "Qlf"),
dr_convert(450, 525, 770, 780, "Gs", "Hhd"),
dr_convert(450, 525, 525, 770, "Gs", "Dd"),
dr_convert(450, 525, 425, 525, "Gs", "Sm"),
dr_convert(450, 490, 375, 425, "Gs", "Wwg"),
dr_convert(490, 525, 375, 425, "Gs", "Wwrg"),
dr_convert(450, 525, 225, 375, "Gs", "Gs^Uf"),
dr_convert(450, 525, 10, 225, "Gs", "Gg^Fet"),
dr_convert(100, 999, 560, 999, "Gs", "Gd"),
dr_convert(100, 999, 10, 385, "Gs", "Gg"),
dr_convert(75, 999, 600, 999, "Ds", "Dd"),
dr_convert(200, 999, 600, 999, "Hh", "Hhd"),
dr_convert(200, 999, 650, 999, "Hh^Uf", "Hhd^Uf"),
dr_convert(200, 999, 600, 999, "Mm", "Md"),
-- DR_TEMPERATURE FROM MIN MAX TO),
-- convert forest at different temperatures
dr_temperature("Gs^Fp", 900, 999, "Gd^Fdw"),
dr_temperature("Hh^Fp", 900, 999, "Hhd^Fdw"),
dr_temperature("Gs^Fp", 775, 900, "Gd^Fetd"),
dr_temperature("Hh^Fp", 800, 900, "Hhd^Fdf"),
dr_temperature("Gs^Fp", 600, 775, "Gd^Fdf"),
dr_temperature("Hh^Fp", 700, 800, "Hhd^Fmf"),
dr_temperature("Gs^Fp", 560, 600, "Gs^Fet"),
dr_temperature("Gs^Fp", 500, 560, "Gs^Ftp"),
dr_temperature("Gs^Fp", 450, 500, "Gs^Ftr"),
dr_temperature("Hh^Fp", 450, 700, "Hh^Ftp"),
dr_temperature("Gs^Fp", 1, 450, "Gg^Ft"),
dr_temperature("Hh^Fp", 1, 450, "Hh^Ft"),
-- convert cave at different temperatures
dr_temperature("Uu,Uh", 850, 999, "Ql"),
dr_temperature("Uu", 725, 850, "Uue"),
dr_temperature("Uh", 725, 850, "Uue^Dr"),
dr_temperature("Uu", 700, 725, "Uue^Uf"),
dr_temperature("Uu", 575, 600, "Uu^Uf"),
}
res.road_cost = {
dr_road("Gg", "Re", 10),
dr_road("Gg^Ft", "Re", 20),
dr_road("Hh", "Re", 30),
dr_road("Hhd", "Re", 30),
dr_road("Hh^Ftp", "Re", 30),
dr_road("Hhd^Fmf", "Re", 30),
dr_road("Mm", "Re", 40),
dr_road("Md", "Re", 40),
dr_road("Mm^Xm", "Re", 75),
dr_bridge("Qlf", "Qlf^Bsb", "Cud", 55),
dr_bridge("Sm", "Sm^Bw", "Co", 45),
dr_road("Uu", "Re", 10),
dr_road("Uue", "Re", 10),
dr_road("Uh", "Re", 40),
dr_road("Xu", "Re", 90),
dr_road("Re", "Re", 2),
dr_road("Ch", "Ch", 2),
dr_road("Dd", "Re", 15),
dr_road("Gs", "Re", 9),
dr_road("Gd", "Re", 10),
dr_road("Gs^Uf", "Re", 12),
dr_road("Gs^Ftr", "Re", 20),
dr_road("Gs^Ftp", "Re", 20),
dr_road("Gs^Fet", "Re", 20),
dr_road("Gd^Fdf", "Re", 20),
dr_road("Gd^Fetd", "Re", 20),
}
res.village = {
dr_village {
terrain = "Gg",
convert_to="Gg^Vht",
adjacent_liked="Gg, Gs, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Hh, Mm, Hh^Ft, Hh^Ftp",
rating=5
},
dr_village {
terrain = "Gs",
convert_to="Gs^Vht",
adjacent_liked="Gg, Gs, Gd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd",
rating=4
},
dr_village {
terrain = "Gs^Uf",
convert_to="Gs^Vh",
adjacent_liked="Gg, Gs, Gs^Uf, Gs^Uf, Gs^Uf, Gd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd",
rating=8
},
dr_village {
terrain = "Gd",
convert_to="Gd^Vo",
adjacent_liked="Gg, Gs, Gd, Dd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Md, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd, Qlf, Cud, Qlf, Qlf^Bsb|, Qlf^Bsb/, Qlf^Bsb\\",
rating=4
},
dr_village {
terrain="Ds",
convert_to="Ds^Vda",
adjacent_liked="Gg, Gs, Wwt, Wwt, Wwt, Re, Re, Hh, Gg^Ft, Gs^Ftp",
rating=2
},
dr_village {
terrain="Dd",
convert_to="Dd^Vd",
adjacent_liked="Gg, Gs, Wwt, Wwt, Wwt, Re, Re, Hh, Gg^Ft, Gs^Ftp",
rating=4
},
dr_village {
terrain="Uu",
convert_to="Uu^Vud",
adjacent_liked=" Re,Hh,Hhd,Mm,Uu,Uh,Xu,Uue,Uue^Dr,Md,Mm^Xm,Md^Xm",
rating=5
},
dr_village {
terrain="Uh",
convert_to="Uu^Vud",
adjacent_liked=" Re,Hh,Hhd,Mm,Uu,Uh,Xu,Uue,Uue^Dr,Md,Mm^Xm,Md^Xm",
rating=5
},
dr_village {
terrain="Uue",
convert_to="Uue^Vo",
adjacent_liked=" Re,Hh,Hhd,Mm,Uu,Uh,Xu,Uue,Uue^Dr,Md,Mm^Xm,Md^Xm",
rating=5
},
dr_village {
terrain="Uue^Dr",
convert_to="Uh^Vo",
adjacent_liked=" Re,Hh,Hhd,Mm,Uu,Uh,Xu,Uue,Uue^Dr,Md,Mm^Xm,Md^Xm",
rating=5
},
-- villages in forest are Orcish
dr_village {
terrain="Gs^Ftp",
convert_to="Gs^Vo",
adjacent_liked="Gg, Gs, Gd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd",
rating=2
},
dr_village {
terrain="Gg^Ft",
convert_to="Gg^Vo",
adjacent_liked="Gg, Gs, Gd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd",
rating=2
},
dr_village {
terrain="Gs^Ftr",
convert_to="Gs^Vo",
adjacent_liked="Gg, Gs, Gd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd",
rating=2
},
dr_village {
terrain="Gd^Fdf",
convert_to="Gd^Vo",
adjacent_liked="Gg, Gs, Gd, Dd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Md, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd, Qlf, Cud, Qlf, Qlf^Bsb|, Qlf^Bsb/, Qlf^Bsb\\",
rating=2
},
dr_village {
terrain="Gd^Fetd",
convert_to="Gd^Vo",
adjacent_liked="Gg, Gs, Gd, Dd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Md, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd, Qlf, Cud, Qlf, Qlf^Bsb|, Qlf^Bsb/, Qlf^Bsb\\",
rating=2
},
dr_village {
terrain="Hh",
convert_to="Hh^Vhh",
adjacent_liked="Gg, Gs, Gd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd",
rating=4
},
dr_village {
terrain="Hh^Ftp",
convert_to="Hh^Vo",
adjacent_liked="Gg, Gs, Gd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd",
rating=2
},
dr_village {
terrain="Hh^Ft",
convert_to="Hh^Vo",
adjacent_liked="Gg, Gs, Gd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd",
rating=2
},
dr_village {
terrain="Hhd^Fmf",
convert_to="Hhd^Vo",
adjacent_liked="Gg, Gs, Gd, Dd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Md, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd, Qlf, Cud, Qlf, Qlf^Bsb|, Qlf^Bsb/, Qlf^Bsb\\",
rating=2
},
dr_village {
terrain="Hhd",
convert_to="Hhd^Vd",
adjacent_liked="Gg, Gs, Gd, Dd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Md, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd, Qlf, Cud, Qlf, Qlf^Bsb|, Qlf^Bsb/, Qlf^Bsb\\",
rating=5
},
dr_village {
terrain="Mm",
convert_to="Mm^Vhh",
adjacent_liked="Gg, Gs, Gd, Dd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Md, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd, Qlf, Cud, Qlf, Qlf^Bsb|, Qlf^Bsb/, Qlf^Bsb\\",
rating=3
},
dr_village {
terrain="Md",
convert_to="Md^Vd",
adjacent_liked="Gg, Gs, Gd, Dd, Re, Re, Gs^Ftr, Gs^Ftp, Gs^Fet, Gg^Ft, Gd^Fdf, Gd^Fetd, Hh, Mm, Md, Hh^Ft, Hh^Ftp, Hhd^Fmf, Hhd, Qlf, Cud, Qlf, Qlf^Bsb|, Qlf^Bsb/, Qlf^Bsb\\",
rating=4
},
-- mermen villages - give them low chance of appearing
dr_village {
terrain="Wwt",
convert_to="Wwt^Vm",
adjacent_liked="Wwt, Wwt, Wot, Ds",
rating=1
},
}
res.castle = {
valid_terrain="Gs, Gg, Gd, Gs^Fp, Gg^Ft, Gs^Ftr, Gs^Fet, Gd^Fetd, Gd^Fdf, Hh, Hhd, Dd, Mm, Md, Sm, Hh^Fp, Hh^Ftp, Hh^Fmf, Hh^Ft",
min_distance=13,
}
return default_generate_map(res)
end
return generate

Some files were not shown because too many files have changed in this diff Show more