diff --git a/changelog.md b/changelog.md index 9e2548e69b17..826e28cf29fb 100644 --- a/changelog.md +++ b/changelog.md @@ -1,11 +1,17 @@ ## Version 1.15.9+dev ### Add-ons client ### Add-ons server + * Fixed undefined behavior when servicing requests to downgrade add-ons. ### Campaigns + * The Rise of Wesnoth + * Adjust campaign difficulty ### Editor ### Multiplayer + * The Delay Advancements modification has been removed in favor of adding the Plan Unit Advance modification to mainline. Enabling this modification allows each player to choose what their units will level up into in case the advancement happens on an enemy player's turn in an online multiplayer game. + * Unit advancement that happens on an enemy's turn in online multiplayer games are no longer randomized. Instead, the first advancement listed for the unit is always used. ### Lua API * Upgrade to Lua 5.4.2. + * Added the wesnoth.as_text(...) function as a way to more easily view the contents of a lua table. This is intended as a debugging aid and nothing more. ### Packaging ### Terrain ### Translations @@ -15,8 +21,10 @@ * north-facing frames for dunefolk skirmisher, loyalist bowman, and troll whelp ### User interface * Added a "disengaged" orb, shown instead of the partially-moved orb for units that can move but can't attack. + * Added information about the build's (not runtime) target CPU architecture to the game version info dialog and --report. ### WML Engine ### Miscellaneous and Bug Fixes + * Fixed display zoom not being taken into account when using the `x`, `y`, `directional_x` and `directional_y` attributes in unit animations. ## Version 1.15.9 ### Add-ons server diff --git a/data/campaigns/Descent_Into_Darkness/_main.cfg b/data/campaigns/Descent_Into_Darkness/_main.cfg index 42d47745d7ef..789438499fe2 100644 --- a/data/campaigns/Descent_Into_Darkness/_main.cfg +++ b/data/campaigns/Descent_Into_Darkness/_main.cfg @@ -9,7 +9,7 @@ rank=100 year="389 YW" icon="data/campaigns/Descent_Into_Darkness/images/units/dark-mage.png~RC(magenta>red)" - image="data/campaigns/Descent_Into_Darkness/images/campaign_image.png" + background="data/campaigns/The_Rise_Of_Wesnoth/images/story/trow_intro_03.jpg" name= _ "Descent into Darkness" abbrev= _ "DiD" define=CAMPAIGN_DESCENT diff --git a/data/campaigns/Liberty/_main.cfg b/data/campaigns/Liberty/_main.cfg index 3c1bbade601f..d5bd45301d86 100644 --- a/data/campaigns/Liberty/_main.cfg +++ b/data/campaigns/Liberty/_main.cfg @@ -14,7 +14,7 @@ first_scenario=01_The_Raid define=CAMPAIGN_LIBERTY icon="units/human-outlaws/fugitive.png~RC(magenta>red)" - image="data/campaigns/Liberty/images/campaign_image.png" + background="data/campaigns/The_Rise_Of_Wesnoth/images/story/trow_intro_02.jpg" {CAMPAIGN_DIFFICULTY EASY "units/human-peasants/peasant.png~RC(magenta>red)" ( _ "Peasant") ( _ "Easy")} {DEFAULT_DIFFICULTY} {CAMPAIGN_DIFFICULTY NORMAL "units/human-outlaws/outlaw.png~RC(magenta>red)" ( _ "Outlaw") ( _ "Normal")} diff --git a/data/campaigns/Northern_Rebirth/_main.cfg b/data/campaigns/Northern_Rebirth/_main.cfg index 7e19116580a7..1318e258286b 100644 --- a/data/campaigns/Northern_Rebirth/_main.cfg +++ b/data/campaigns/Northern_Rebirth/_main.cfg @@ -22,7 +22,7 @@ " + _"(Expert level, 13 scenarios.)" icon="scenery/dwarven-doors-closed.png" - image="data/campaigns/Northern_Rebirth/images/campaign_image.png" + background="data/campaigns/The_Rise_Of_Wesnoth/images/story/trow_story_02-The_Fall.jpg" [about] title = _ "Campaign Design" diff --git a/data/campaigns/The_Rise_Of_Wesnoth/_main.cfg b/data/campaigns/The_Rise_Of_Wesnoth/_main.cfg index a0f40e5624e6..db5f89a35449 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/_main.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/_main.cfg @@ -11,7 +11,7 @@ end_year="1 YW" name= _ "The Rise of Wesnoth" icon="data/campaigns/The_Rise_Of_Wesnoth/images/units/noble-lord.png" - image="data/campaigns/The_Rise_Of_Wesnoth/images/campaign_image.png" + background="data/campaigns/The_Rise_Of_Wesnoth/images/story/trow_story_04b-The_Midlands.jpg" abbrev= _ "TRoW" define=CAMPAIGN_THE_RISE_OF_WESNOTH first_scenario=01_A_Summer_of_Storms diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/01_A_Summer_of_Storms.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/01_A_Summer_of_Storms.cfg index 985c794c70c1..e5525e9b2c32 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/01_A_Summer_of_Storms.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/01_A_Summer_of_Storms.cfg @@ -4,7 +4,7 @@ name= _ "A Summer of Storms" next_scenario=02_The_Fall map_file=01_A_Summer_of_Storms.map - {TURNS 31 28 25} + {TURNS 29 27 25} {DEFAULT_SCHEDULE} # Music for this scenario is handled in the intro and an event below @@ -76,7 +76,7 @@ id=Prince Haldric name= _ "Prince Haldric" profile=portraits/haldric.png - {GOLD 125 100 100} + {GOLD 140 120 100} unrenamable=yes side=1 canrecruit=yes @@ -97,7 +97,7 @@ profile="portraits/lady_outlaw.png" side=2 canrecruit=yes - {GOLD 70 120 170} + {GOLD 140 160 180} recruit=Footpad, Poacher, Thief, Thug team_name=wesfolk user_team_name=_"Wesfolk" diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/02_The_Fall.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/02_The_Fall.cfg index 6eb306c3ed41..0c530596d55f 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/02_The_Fall.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/02_The_Fall.cfg @@ -28,7 +28,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=100 + {GOLD 140 120 100} controller=human team_name=Haldric user_team_name=_"Stormvale" @@ -54,7 +54,7 @@ passive_leader=yes grouping=defensive [/ai] - {GOLD 90 130 170} + {GOLD 90 120 150} team_name=wesfolk user_team_name=_"Wesfolk" {FLAG_VARIANT6 ragged} @@ -70,7 +70,8 @@ side=3 canrecruit=yes recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Goblin Spearman - {GOLD 180 260 350} + {GOLD 120 160 200} + {INCOME 6 9 12} team_name=orcs user_team_name=_"Orcs" [ai] @@ -93,7 +94,8 @@ side=4 canrecruit=yes recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Goblin Spearman - {GOLD 160 220 310} + {GOLD 160 200 240} + {INCOME 4 6 8} team_name=orcs user_team_name=_"Orcs" [ai] diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/03_A_Harrowing_Escape.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/03_A_Harrowing_Escape.cfg index f0dcd1976b37..392fcc139792 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/03_A_Harrowing_Escape.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/03_A_Harrowing_Escape.cfg @@ -4,7 +4,7 @@ name= _ "A Harrowing Escape" map_file=03_A_Harrowing_Escape.map next_scenario=04a_The_Swamp_of_Esten - {TURNS 48 45 42} + {TURNS 42 39 36} {DEFAULT_SCHEDULE} {SCENARIO_MUSIC the_king_is_dead.ogg} @@ -22,7 +22,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=100 + {GOLD 140 120 100} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -36,7 +36,8 @@ profile=portraits/orcs/grunt.png side=2 canrecruit=yes - {GOLD 80 140 200} + {GOLD 100 150 200} + {INCOME 1 2 3} team_name=orcs user_team_name=_"Orcs" recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Goblin Spearman @@ -60,7 +61,8 @@ profile=portraits/orcs/grunt-2.png side=3 canrecruit=yes - {GOLD 80 140 200} + {GOLD 100 150 200} + {INCOME 1 2 3} team_name=orcs user_team_name=_"Orcs" recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Goblin Spearman @@ -332,7 +334,7 @@ SW — The Midlands." [then] [gold] side=3 - amount={ON_DIFFICULTY 60 80 90} + amount={ON_DIFFICULTY 70 80 90} [/gold] [message] diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/04a_The_Swamp_of_Esten.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/04a_The_Swamp_of_Esten.cfg index f504348c0822..5c67ae76bbe6 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/04a_The_Swamp_of_Esten.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/04a_The_Swamp_of_Esten.cfg @@ -35,7 +35,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=100 + {GOLD 160 140 120} controller=human team_name=Haldric user_team_name=_"Refugees" diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/04b_The_Midlands.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/04b_The_Midlands.cfg index 601bde7ec471..8604046b7133 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/04b_The_Midlands.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/04b_The_Midlands.cfg @@ -4,7 +4,7 @@ name= _ "The Midlands" next_scenario=05_The_Oldwood map_file=04b_The_Midlands.map - {TURNS 45 42 39} + {TURNS 36 33 30} {DEFAULT_SCHEDULE} {SCENARIO_MUSIC wanderer.ogg} @@ -35,7 +35,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=100 + {GOLD 160 140 120} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -43,7 +43,7 @@ [/side] [side] - type=Orcish Warlord + type=Orcish Warrior id=Tan-Vrodis name= _ "Tan-Vrodis" #This is the nearest enemy, make him softer. @@ -54,7 +54,7 @@ {NO_SCOUTS} recruitment_pattern=scout,fighter,fighter,mixed fighter,archer [/ai] - {GOLD 70 110 160} + {GOLD 80 100 120} user_team_name=_"Orcs" team_name=orcs [/side] @@ -66,7 +66,8 @@ profile="portraits/orcs/grunt-3.png" side=3 canrecruit=yes - {GOLD 110 150 190} + {GOLD 100 140 180} + {INCOME 1 2 3} [ai] {NO_SCOUTS} recruitment_pattern=scout,fighter,fighter,mixed fighter,archer @@ -99,7 +100,8 @@ profile="portraits/orcs/grunt-2.png" side=4 canrecruit=yes - {GOLD 110 150 190} + {GOLD 100 140 180} + {INCOME 1 2 3} [ai] {NO_SCOUTS} recruitment_pattern=scout,fighter,fighter,mixed fighter,archer @@ -321,7 +323,7 @@ [gold] side=4 - amount=80 + amount={ON_DIFFICULTY 60 70 80} [/gold] [/event] @@ -338,7 +340,7 @@ [gold] side=3 - amount=80 + amount={ON_DIFFICULTY 60 70 80} [/gold] [/event] diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/05_The_Oldwood.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/05_The_Oldwood.cfg index 9832caac81bd..9d7da647c0d6 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/05_The_Oldwood.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/05_The_Oldwood.cfg @@ -22,7 +22,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=100 + {GOLD 160 140 120} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -100,8 +100,8 @@ profile="portraits/rithrandil.png" canrecruit=yes recruit=Wose Sapling - {GOLD 160 100 60} - {INCOME 10 5 3} + {GOLD 160 130 100} + {INCOME 7 5 3} team_name=Haldric user_team_name=_"Refugees" [/side] diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/06_Temple_in_the_Deep.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/06_Temple_in_the_Deep.cfg index 95539df6cfe7..7bbbc1876b1a 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/06_Temple_in_the_Deep.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/06_Temple_in_the_Deep.cfg @@ -29,7 +29,7 @@ name= _ "Prince Haldric" unrenamable=yes canrecruit=yes - gold=100 + {GOLD 160 140 120} controller=human shroud=yes team_name=Haldric @@ -44,7 +44,7 @@ name= _ "Lich-Lord Lenvan" canrecruit=yes recruit=Revenant,Deathblade,Bone Shooter,Skeleton,Skeleton Archer - {GOLD 160 280 400} + {GOLD 240 300 360} {INCOME 6 10 14} team_name=undead user_team_name=_"Undead" diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/08_Clearwater_Port.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/08_Clearwater_Port.cfg index 6c2dbe289b92..184216a3359f 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/08_Clearwater_Port.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/08_Clearwater_Port.cfg @@ -25,7 +25,7 @@ name= _ "Prince Haldric" unrenamable=yes canrecruit=yes - gold=200 + {GOLD 220 200 180} controller=human team_name=Haldric user_team_name=_"Humans" @@ -40,7 +40,7 @@ profile="portraits/aethyr-first.png" canrecruit=yes recruit=Peasant, Bowman, Horseman, Mage, Spearman - {GOLD 220 160 120} + {GOLD 220 180 140} [ai] aggression=-0.5 {NO_SCOUTS} @@ -78,7 +78,7 @@ recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Orcish Crossbowman, Orcish Warrior, Goblin Knight, Goblin Pillager, Orcish Slayer, Goblin Spearman, Goblin Impaler #endif - {GOLD 190 230 290} + {GOLD 190 230 270} team_name=orcs user_team_name=_"Orcs" [ai] @@ -91,7 +91,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 4 8 12} + {INCOME 5 7 9} [/side] [side] @@ -112,7 +112,7 @@ recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Orcish Crossbowman, Orcish Warrior, Goblin Knight, Goblin Pillager, Orcish Slayer, Goblin Spearman, Goblin Impaler #endif - {GOLD 190 230 290} + {GOLD 190 230 270} team_name=orcs user_team_name=_"Orcs" [ai] @@ -125,7 +125,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 4 8 12} + {INCOME 5 7 9} [/side] [side] @@ -148,7 +148,7 @@ recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Orcish Crossbowman, Orcish Warrior, Goblin Knight, Goblin Pillager, Orcish Slayer, Goblin Spearman, Goblin Impaler #endif - {GOLD 260 300 360} + {GOLD 240 300 360} team_name=orcs user_team_name=_"Orcs" [ai] @@ -161,7 +161,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 5 10 15} + {INCOME 8 12 16} [/side] [event] diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/09_Fallen_Lich_Point.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/09_Fallen_Lich_Point.cfg index dc8fdc1ba310..6fd882e1dbf5 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/09_Fallen_Lich_Point.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/09_Fallen_Lich_Point.cfg @@ -5,7 +5,7 @@ next_scenario=10_Sewer_of_Southbay victory_when_enemies_defeated=no map_file=09_Fallen_Lich_Point.map - {TURNS 39 36 33} + {TURNS 36 33 30} {DEFAULT_SCHEDULE} {SCENARIO_MUSIC breaking_the_chains.ogg} @@ -23,7 +23,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=200 + {GOLD 220 200 180} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -114,7 +114,7 @@ name= _ "Lich-Lord Caror" canrecruit=yes recruit=Skeleton, Skeleton Archer, Ghost, Ghoul, Walking Corpse - {GOLD 0 150 190} + {GOLD 100 130 160} team_name=undead user_team_name=_"Undead" scroll_to_leader=no diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/10_Sewer_of_Southbay.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/10_Sewer_of_Southbay.cfg index 207b37c230e1..d9145914d121 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/10_Sewer_of_Southbay.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/10_Sewer_of_Southbay.cfg @@ -25,7 +25,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=200 + {GOLD 220 200 180} controller=human shroud=yes team_name=Haldric @@ -41,8 +41,8 @@ side=2 canrecruit=yes recruit=Red Mage,Giant Scorpion,Vampire Bat,Blood Bat - {GOLD 160 220 280} - {INCOME 4 8 12} + {GOLD 160 210 260} + {INCOME 5 7 9} team_name=wizards user_team_name=_"Red Wizards" [ai] @@ -60,8 +60,8 @@ side=3 canrecruit=yes recruit=Red Mage,Giant Scorpion,Vampire Bat,Blood Bat - {GOLD 160 220 280} - {INCOME 4 8 12} + {GOLD 160 210 260} + {INCOME 5 7 9} team_name=wizards user_team_name=_"Red Wizards" [ai] diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/12_A_Final_Spring.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/12_A_Final_Spring.cfg index 858c20f5e0be..c0b13718194c 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/12_A_Final_Spring.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/12_A_Final_Spring.cfg @@ -24,7 +24,7 @@ type=Noble Commander unrenamable=yes canrecruit=yes - gold=200 + {GOLD 220 200 180} controller=human team_name=Haldric user_team_name=_"Humans" @@ -40,7 +40,7 @@ name= _ "King Addroran IX" profile="portraits/addroran.png" canrecruit=yes - {GOLD 220 160 120} + {GOLD 200 160 120} team_name=Haldric user_team_name=_"Humans" recruit=Bowman, Horseman, Mage, Spearman, Knight, Swordsman, Peasant @@ -85,7 +85,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 2 4 8} + {INCOME 4 6 8} [/side] [side] @@ -118,7 +118,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 2 4 8} + {INCOME 4 6 8} [/side] [side] @@ -128,7 +128,7 @@ side=5 canrecruit=yes recruit=Naga Fighter,Vampire Bat - {GOLD 180 220 260} + {GOLD 120 180 200} team_name=orcs user_team_name=_"Orcs" [ai] @@ -141,7 +141,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 2 4 8} + {INCOME 2 3 4} [/side] [side] diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/13_Peoples_in_Decline.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/13_Peoples_in_Decline.cfg index 0d0b7ad145cc..47fdd737db4b 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/13_Peoples_in_Decline.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/13_Peoples_in_Decline.cfg @@ -4,7 +4,7 @@ name= _ "Peoples in Decline" next_scenario=14_Rough_Landing map_file=13_Peoples_in_Decline.map - {TURNS 39 36 33} + {TURNS 33 30 27} {DEFAULT_SCHEDULE} {SCENARIO_MUSIC knalgan_theme.ogg} @@ -33,7 +33,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=200 + {GOLD 210 180 150} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -46,8 +46,8 @@ name= _ "Kegrid" side=2 canrecruit=yes - {GOLD 110 150 190} - {INCOME 2 4 8} + {GOLD 80 110 140} + {INCOME 2 4 6} team_name=Drake user_team_name=_"Drakes" #ifdef EASY @@ -68,8 +68,8 @@ name= _ "Gerrick" side=3 canrecruit=yes - {GOLD 110 150 190} - {INCOME 2 4 8} + {GOLD 80 110 140} + {INCOME 2 4 6} team_name=Drake user_team_name=_"Drakes" @@ -96,8 +96,8 @@ name= _ "Merkush" side=4 canrecruit=yes - {GOLD 110 150 190} - {INCOME 2 4 8} + {GOLD 80 110 140} + {INCOME 2 4 6} team_name=Drake user_team_name=_"Drakes" diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/14_Rough_Landing.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/14_Rough_Landing.cfg index 90db2caba5c9..83eb8d5967a6 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/14_Rough_Landing.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/14_Rough_Landing.cfg @@ -5,7 +5,7 @@ next_scenario=15_A_New_Land map_file=14_Rough_Landing.map - {TURNS 35 32 29} + {TURNS 27 25 23} {DEFAULT_SCHEDULE} {SCENARIO_MUSIC knolls.ogg} @@ -28,7 +28,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=200 + {GOLD 210 180 150} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -41,8 +41,8 @@ name= _ "Abraxas" side=2 canrecruit=yes - {GOLD 90 145 230} - {INCOME 2 4 8} + {GOLD 90 120 150} + {INCOME 2 3 4} team_name=Naga user_team_name=_"Naga" #ifdef EASY @@ -67,8 +67,8 @@ name= _ "Xamalia" side=3 canrecruit=yes - {GOLD 90 145 230} - {INCOME 2 4 8} + {GOLD 90 120 150} + {INCOME 2 3 4} team_name=Naga user_team_name=_"Naga" #ifdef EASY @@ -93,8 +93,8 @@ name= _ "Gaxmail" side=4 canrecruit=yes - {GOLD 90 145 230} - {INCOME 2 4 8} + {GOLD 90 120 150} + {INCOME 2 3 4} team_name=Naga user_team_name=_"Naga" #ifdef EASY diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17a_The_Dragon.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17a_The_Dragon.cfg index a03738791a6b..0bedc7ba6650 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17a_The_Dragon.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17a_The_Dragon.cfg @@ -6,7 +6,7 @@ victory_when_enemies_defeated=no map_file=17a_The_Dragon.map - {TURNS 39 36 33} + {TURNS 33 30 27} {DEFAULT_SCHEDULE} {SCENARIO_MUSIC wanderer.ogg} @@ -25,7 +25,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=200 + {GOLD 230 200 170} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -38,8 +38,8 @@ name= _ "Irix" side=2 canrecruit=yes - {GOLD 110 140 160} - {INCOME 2 4 8} + {GOLD 80 100 120} + {INCOME 3 6 9} team_name=Liz user_team_name=_"Saurians" #ifdef EASY @@ -71,8 +71,8 @@ name= _ "Vriss" side=3 canrecruit=yes - {GOLD 110 140 160} - {INCOME 2 4 8} + {GOLD 80 100 120} + {INCOME 3 6 9} team_name=Liz user_team_name=_"Saurians" #ifdef EASY @@ -104,8 +104,8 @@ name= _ "Axiz" side=4 canrecruit=yes - {GOLD 110 140 160} - {INCOME 2 4 8} + {GOLD 80 100 120} + {INCOME 3 6 9} team_name=Liz user_team_name=_"Saurians" #ifdef EASY @@ -138,8 +138,8 @@ name= _ "Satras" side=5 canrecruit=yes - {GOLD 110 140 160} - {INCOME 2 4 8} + {GOLD 80 100 120} + {INCOME 3 6 9} team_name=Liz user_team_name=_"Saurians" diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17b_Lizard_Beach.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17b_Lizard_Beach.cfg index b31ffe7c446c..3b42618ee10c 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17b_Lizard_Beach.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17b_Lizard_Beach.cfg @@ -5,7 +5,7 @@ next_scenario=16_The_Kalian map_file=17b_Lizard_Beach.map - {TURNS 35 32 29} + {TURNS 30 27 24} {DEFAULT_SCHEDULE} {SCENARIO_MUSIC battle.ogg} @@ -23,7 +23,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=200 + {GOLD 200 175 150} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -36,8 +36,8 @@ name= _ "Tirasch" side=2 canrecruit=yes - {GOLD 130 190 250} - {INCOME 2 4 8} + {GOLD 100 125 150} + {INCOME 3 5 7} team_name=Liz user_team_name=_"Monsters" #ifdef EASY @@ -60,8 +60,8 @@ name= _ "Ssirk" side=3 canrecruit=yes - {GOLD 130 190 250} - {INCOME 2 4 8} + {GOLD 100 125 150} + {INCOME 3 5 7} team_name=Liz user_team_name=_"Monsters" #ifdef EASY diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17c_Troll_Hole.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17c_Troll_Hole.cfg index a713cb090d44..ef77914974ad 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17c_Troll_Hole.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17c_Troll_Hole.cfg @@ -5,7 +5,7 @@ next_scenario=16_The_Kalian map_file=17c_Troll_Hole.map - {TURNS 39 36 33} + {TURNS 32 30 28} {UNDERGROUND} {SCENARIO_MUSIC underground.ogg} @@ -22,12 +22,12 @@ unrenamable=yes side=1 canrecruit=yes - gold=200 + {GOLD 200 175 150} controller=human shroud=yes team_name=Haldric user_team_name=_"Refugees" - {INCOME 8 4 2} + {INCOME 5 4 3} {FLAG_VARIANT loyalist} [/side] @@ -37,8 +37,8 @@ name= _ "Erart" side=2 canrecruit=yes - {GOLD 80 140 200} - {INCOME 2 4 8} + {GOLD 90 120 150} + {INCOME 0 2 4} team_name=Troll user_team_name=_"Trolls" recruit=Troll Whelp,Troll,Troll Rocklobber @@ -57,8 +57,8 @@ name= _ "Raol" side=3 canrecruit=yes - {GOLD 80 140 200} - {INCOME 2 4 8} + {GOLD 90 120 150} + {INCOME 0 2 4} team_name=Troll user_team_name=_"Trolls" recruit=Troll Whelp,Troll,Troll Rocklobber diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17d_Cursed_Isle.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17d_Cursed_Isle.cfg index dde12e78661a..66a02a9b3b42 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17d_Cursed_Isle.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/17d_Cursed_Isle.cfg @@ -6,7 +6,7 @@ victory_when_enemies_defeated=no map_file=17d_Cursed_Isle.map - {TURNS 37 34 31} + {TURNS 30 27 24} {DEFAULT_SCHEDULE} {SCENARIO_MUSIC loyalists.ogg} @@ -24,7 +24,7 @@ unrenamable=yes side=1 canrecruit=yes - gold=200 + {GOLD 200 175 150} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -38,8 +38,8 @@ name= _ "Isorfilad" side=2 canrecruit=yes - {GOLD 130 190 250} - {INCOME 2 4 8} + {GOLD 100 125 150} + {INCOME 2 4 6} team_name=Undead user_team_name=_"Undead" #ifdef EASY @@ -77,8 +77,8 @@ name= _ "Tinoldor" side=3 canrecruit=yes - {GOLD 130 190 250} - {INCOME 2 4 8} + {GOLD 100 125 150} + {INCOME 2 4 6} team_name=Undead user_team_name=_"Undead" #ifdef EASY diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/19_The_Vanguard.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/19_The_Vanguard.cfg index fe676f5c8a0f..25b8f07800da 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/19_The_Vanguard.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/19_The_Vanguard.cfg @@ -5,7 +5,7 @@ next_scenario=20_Return_of_the_Fleet map_file=19_The_Vanguard.map - {TURNS 41 38 35} + {TURNS 39 37 35} {DEFAULT_SCHEDULE} {SCENARIO_MUSIC loyalists.ogg} @@ -25,7 +25,7 @@ type=Noble Commander unrenamable=yes canrecruit=yes - gold=200 + {GOLD 250 225 200} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -50,7 +50,7 @@ #ifdef HARD recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Orcish Crossbowman, Orcish Warrior, Goblin Knight, Goblin Pillager, Orcish Slayer, Goblin Spearman, Goblin Impaler #endif - {GOLD 150 190 230} + {GOLD 120 150 180} team_name=orcs user_team_name=_"Orcs" [ai] @@ -63,7 +63,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 2 4 8} + {INCOME 6 10 14} [/side] {STARTING_VILLAGES 2 8} @@ -86,7 +86,7 @@ #ifdef HARD recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Orcish Crossbowman, Orcish Warrior, Goblin Knight, Goblin Pillager, Orcish Slayer, Goblin Spearman, Goblin Impaler #endif - {GOLD 150 190 230} + {GOLD 120 150 180} team_name=orcs user_team_name=_"Orcs" [ai] @@ -99,7 +99,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 2 4 8} + {INCOME 6 10 14} [/side] {STARTING_VILLAGES 3 8} @@ -122,7 +122,7 @@ recruit=Troll Whelp,Troll,Troll Warrior,Troll Rocklobber #endif - {GOLD 110 150 190} + {GOLD 100 150 200} team_name=orcs user_team_name=_"Orcs" [ai] @@ -134,8 +134,7 @@ #endif grouping=no [/ai] - - {INCOME 2 4 8} + {INCOME 6 10 14} [/side] [side] diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/20_Return_of_the_Fleet.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/20_Return_of_the_Fleet.cfg index d635e7e90faf..f72bc016d5f7 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/20_Return_of_the_Fleet.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/20_Return_of_the_Fleet.cfg @@ -5,7 +5,7 @@ next_scenario=21_The_Plan map_file=20_Return_of_the_Fleet.map - {TURNS 45 42 39} + {TURNS 45 43 41} {DEFAULT_SCHEDULE} {SCENARIO_MUSIC vengeful.ogg} @@ -25,7 +25,7 @@ type=Noble Commander unrenamable=yes canrecruit=yes - gold=200 + {GOLD 275 250 225} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -42,7 +42,7 @@ profile="portraits/undead/death-knight.png" side=2 canrecruit=yes - {GOLD 130 170 210} + {GOLD 120 160 200} team_name=orcs user_team_name=_"Orcs" #ifdef EASY @@ -67,7 +67,7 @@ time_of_day=dusk,first_watch,second_watch aggression=0.7 [/ai] - {INCOME 2 4 8} + {INCOME 6 9 12} [/side] {STARTING_VILLAGES 2 10} @@ -89,7 +89,7 @@ #ifdef HARD recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Orcish Crossbowman, Orcish Warrior, Goblin Knight, Goblin Pillager, Orcish Slayer, Troll Whelp, Troll, Troll Warrior, Troll Rocklobber, Goblin Spearman, Goblin Impaler #endif - {GOLD 170 210 250} + {GOLD 200 250 300} team_name=orcs user_team_name=_"Orcs" [ai] @@ -102,7 +102,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 2 4 8} + {INCOME 6 10 14} [/side] {STARTING_VILLAGES 3 10} @@ -125,7 +125,7 @@ #ifdef HARD recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Orcish Crossbowman, Orcish Warrior, Goblin Knight, Goblin Pillager, Orcish Slayer, Troll Whelp, Troll, Troll Warrior, Troll Rocklobber, Goblin Spearman, Goblin Impaler #endif - {GOLD 170 210 250} + {GOLD 200 250 300} team_name=orcs user_team_name=_"Orcs" [ai] @@ -138,7 +138,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 2 4 8} + {INCOME 6 10 14} [/side] {STARTING_VILLAGES 4 10} diff --git a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/22_The_Rise_of_Wesnoth.cfg b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/22_The_Rise_of_Wesnoth.cfg index e7d020368fd9..bc886b9d7239 100644 --- a/data/campaigns/The_Rise_Of_Wesnoth/scenarios/22_The_Rise_of_Wesnoth.cfg +++ b/data/campaigns/The_Rise_Of_Wesnoth/scenarios/22_The_Rise_of_Wesnoth.cfg @@ -6,7 +6,7 @@ victory_when_enemies_defeated=no map_file=22_The_Rise_of_Wesnoth.map - {TURNS 45 42 39} + turns=unlimited {DEFAULT_SCHEDULE} {SCENARIO_MUSIC knalgan_theme.ogg} @@ -26,7 +26,7 @@ type=Noble Commander unrenamable=yes canrecruit=yes - gold=200 + {GOLD 300 275 250} controller=human team_name=Haldric user_team_name=_"Refugees" @@ -47,7 +47,7 @@ side=2 canrecruit=yes recruit=Revenant,Deathblade,Bone Shooter,Skeleton,Skeleton Archer,Vampire Bat,Walking Corpse,Soulless,Blood Bat,Ghoul,Necrophage - {GOLD 160 180 210} + {GOLD 160 200 240} user_team_name=_"Evil" team_name=orcs [ai] @@ -69,7 +69,7 @@ value=10 [/goal] [/ai] - {INCOME 4 6 8} + {INCOME 8 12 16} {FLAG_VARIANT undead} [/side] @@ -82,7 +82,7 @@ side=3 canrecruit=yes recruit=Naga Fighter,Vampire Bat - {GOLD 130 150 180} + {GOLD 100 125 150} team_name=orcs user_team_name=_"Evil" [ai] @@ -95,7 +95,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 1 2 4} + {INCOME 3 5 7} [/side] {STARTING_VILLAGES 3 10} @@ -118,7 +118,7 @@ #ifdef HARD recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Orcish Crossbowman, Orcish Warrior, Goblin Knight, Goblin Pillager, Orcish Slayer, Troll Whelp, Troll, Troll Warrior, Troll Rocklobber, Goblin Spearman, Goblin Impaler #endif - {GOLD 170 190 220} + {GOLD 150 180 210} team_name=orcs user_team_name=_"Evil" [ai] @@ -131,7 +131,7 @@ aggression=0.65 grouping=offensive [/ai] - {INCOME 2 4 8} + {INCOME 6 9 12} [/side] {STARTING_VILLAGES 4 10} @@ -154,7 +154,7 @@ #ifdef HARD recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Orcish Crossbowman, Orcish Warrior, Goblin Knight, Goblin Pillager, Orcish Slayer, Troll Whelp, Troll, Troll Warrior, Troll Rocklobber, Goblin Spearman, Goblin Impaler #endif - {GOLD 150 170 200} + {GOLD 150 180 210} team_name=orcs user_team_name=_"Evil" [ai] @@ -168,7 +168,7 @@ grouping=offensive [/ai] - {INCOME 1 2 4} + {INCOME 3 6 9} [/side] {STARTING_VILLAGES 5 10} @@ -191,7 +191,7 @@ #ifdef HARD recruit=Orcish Archer, Orcish Assassin, Orcish Grunt, Wolf Rider, Orcish Crossbowman, Orcish Warrior, Goblin Knight, Goblin Pillager, Orcish Slayer, Troll Whelp, Troll, Troll Warrior, Troll Rocklobber, Goblin Spearman, Goblin Impaler #endif - {GOLD 150 170 200} + {GOLD 150 180 210} team_name=orcs user_team_name=_"Evil" [ai] @@ -204,7 +204,7 @@ caution=0.0 grouping=no [/ai] - {INCOME 1 2 4} + {INCOME 3 6 9} [/side] {STARTING_VILLAGES 6 10} @@ -1619,15 +1619,6 @@ message= _ "Jevyan is destroyed, but at a terrible price. Let’s put Commander Aethyr to rest and discuss what is to come in the following days." [/message] [/event] - - [event] - name=time over - [message] - speaker=Prince Haldric - message= _ "Our strength is waning, and our foes grow stronger by the hour. The battle is lost!" - image=portraits/haldric-surprised.png - [/message] - [/event] [/scenario] #undef JEVGOLD diff --git a/data/campaigns/Two_Brothers/_main.cfg b/data/campaigns/Two_Brothers/_main.cfg index 4ed0c0a99662..2716c353c56e 100644 --- a/data/campaigns/Two_Brothers/_main.cfg +++ b/data/campaigns/Two_Brothers/_main.cfg @@ -9,7 +9,7 @@ rank=5 year="363 YW" icon="units/human-loyalists/knight/knight.png~RC(magenta>red)~CROP(6,4,72,72)" - image="data/campaigns/Two_Brothers/images/campaign_image.png" + background="data/campaigns/Two_Brothers/images/story/Two_Brothers_M2P1.png" name= _ "A Tale of Two Brothers" abbrev= _ "AToTB" define="CAMPAIGN_TWO_BROTHERS" diff --git a/data/campaigns/Under_the_Burning_Suns/scenarios/08_Out_of_the_Frying_Pan.cfg b/data/campaigns/Under_the_Burning_Suns/scenarios/08_Out_of_the_Frying_Pan.cfg index f0eb0c6f227a..b4f20f1446be 100644 --- a/data/campaigns/Under_the_Burning_Suns/scenarios/08_Out_of_the_Frying_Pan.cfg +++ b/data/campaigns/Under_the_Burning_Suns/scenarios/08_Out_of_the_Frying_Pan.cfg @@ -4181,7 +4181,7 @@ [/store_locations] [terrain] - terrain=Wwg + terrain=Wwgz [filter_adjacent_location] find_in=shallow_to_deep_locs diff --git a/data/campaigns/Under_the_Burning_Suns/scenarios/09_Blood_is_Thicker_Than_Water.cfg b/data/campaigns/Under_the_Burning_Suns/scenarios/09_Blood_is_Thicker_Than_Water.cfg index c6ccc58b0f43..4ba4c714f1e6 100644 --- a/data/campaigns/Under_the_Burning_Suns/scenarios/09_Blood_is_Thicker_Than_Water.cfg +++ b/data/campaigns/Under_the_Burning_Suns/scenarios/09_Blood_is_Thicker_Than_Water.cfg @@ -1335,7 +1335,6 @@ {NAMED_NOTRAIT_UNIT 4 (Necromancer) 15 28 (Hekuba) ( _ "Hekuba")} [+unit] random_gender=no - gender=female # seems strange for a man to be named Hekuba [/unit] [message] speaker=Hekuba diff --git a/data/campaigns/Under_the_Burning_Suns/utils/terrain.cfg b/data/campaigns/Under_the_Burning_Suns/utils/terrain.cfg index d7d534384505..e713f59882b1 100644 --- a/data/campaigns/Under_the_Burning_Suns/utils/terrain.cfg +++ b/data/campaigns/Under_the_Burning_Suns/utils/terrain.cfg @@ -15,6 +15,20 @@ hide_help=yes [/terrain_type] +# custom water for flood terrain-graphics transitions + +[terrain_type] + symbol_image=water/coast-grey-tile + id=gray_utbs_water + name= _ "Shallow Water" + editor_name= _ "Flood Water" + string=Wwgz + aliasof=Wst + submerge=0.4 + editor_group=utbs + hide_help=yes +[/terrain_type] + # human ship terrain (alias of village so it can be captured); note that the # ship images are placed as an [item] diff --git a/data/campaigns/Under_the_Burning_Suns/utils/terrain_graphics.cfg b/data/campaigns/Under_the_Burning_Suns/utils/terrain_graphics.cfg index 9dd871696d97..27857e3080fd 100644 --- a/data/campaigns/Under_the_Burning_Suns/utils/terrain_graphics.cfg +++ b/data/campaigns/Under_the_Burning_Suns/utils/terrain_graphics.cfg @@ -17,15 +17,26 @@ {DISABLE_WALL_TRANSITIONS Kyd} -#ifndef EDITOR -# This makes gray shallow water transition on top of the wooden floor, which +############################################################################ +# This makes gray shallow water transition on top of the floor terrains, which # otherwise would have a hard edge. -# -# This is #ifdef'd away for the editor because otherwise the transition would -# always work in the editor and give the false impression of working outside -# UtBS. +# It uses custom terrain Wwgz code in place of standard gray Wwg +############################################################################ + +# these are the terrains that look more 'flooded' without their usual banked transitions +#define UTBS_WOOD_FLOOR +Iwr,Ior,Icn,R*,Ias*,Uu* #enddef + +{NEW:WATER_342_180 Wwgz water/water 17 DURATION=125 RANDOM_START=125} +{NEW:DISABLE_GENERIC_CORNER_TRANSITION ({UTBS_WOOD_FLOOR},Xo*) Wwgz} +{NEW:DISABLE_TRANSITION Wwgz {UTBS_WOOD_FLOOR} FLAG=non_submerged} +{NEW:WATER_342_180_OVERLAY Wwgz water/overlay-gray -280} +{NEW:WATER_342_180_OVERLAY_TRANSITION Wwgz (!,Wog,Wwg,Wwrg,Wwgz,!,W*,Sm) -281 water/overlay-gray 0.20} -{NEW:WATER_342_180_TRANSITION Wwg Iwr -553 "~CS(10,-5,-10)" water/water 17} +# the wood-water transitions still have a faint hex-tooth edge, but this isn't enough to fix that without modifying the other side +# {NEW:TRANSITION Iwr,Ior,Icn Wwgz -501 interior/wood-regular FLAG=transition2 IPF="~O(0.1)"} + +{NEW:WATER_342_180_TRANSITION Wwgz ({UTBS_WOOD_FLOOR}) -282 "~CS(10,-5,-10)" water/water 17} # Disables the generic land-water transition from floor to water [terrain_graphics] @@ -35,12 +46,12 @@ 1" [tile] pos=1 - type=Wwg + type=Wwgz set_no_flag=beach-@R0-@R5,beach-@R0-@R1 [/tile] [tile] pos=2 - type=Iwr + type={UTBS_WOOD_FLOOR} set_no_flag=beach-@R2-@R3,beach-@R3-@R2 [/tile] @@ -55,17 +66,22 @@ 1" [tile] pos=1 - type=Iwr + type={UTBS_WOOD_FLOOR} set_flag=transition-@R0 [/tile] [tile] pos=2 - type=Wwg + type=Wwgz [/tile] rotations=n,ne,se,s,sw,nw [/terrain_graphics] +############################################################################ +############################################################################ + +#undef UTBS_WOOD_FLOOR +#ifndef EDITOR # The ruined desert castles in this campaign were ravaged by meteors {OVERLAY_RANDOM Cdr embellishments/stones-small} #endif diff --git a/data/core/_main.cfg b/data/core/_main.cfg index 6cda54639145..d1715ae598ae 100644 --- a/data/core/_main.cfg +++ b/data/core/_main.cfg @@ -8,6 +8,7 @@ wesnoth.dofile 'lua/wml-tags.lua' wesnoth.dofile 'lua/feeding.lua' wesnoth.dofile 'lua/diversion.lua' +wesnoth.dofile 'lua/as_text.lua' >> [/lua] diff --git a/data/core/macros/animation-utils.cfg b/data/core/macros/animation-utils.cfg index d97c45ff369f..717dde7a232f 100644 --- a/data/core/macros/animation-utils.cfg +++ b/data/core/macros/animation-utils.cfg @@ -1066,40 +1066,51 @@ #enddef #define STANDING_ANIM_BIG_TORCH IMG X X2 Y + +#arg IMG_NE + {IMG} +#endarg + +#arg X_NE + {X} +#endarg + +#arg Y_NE + {Y} +#endarg + [standing_anim] start_time=0 torch_start_time=0 [if] - direction=n,ne,se + direction=n,ne,nw [frame] - image={IMG} - auto_hflip=no + image={IMG_NE} auto_vflip=no primary=yes [/frame] [torch_frame] image="halo/torch/torch-big/flame-[1~17].png:120" layer=45 - x={X} - y={Y} - auto_hflip=no + directional_x={X_NE} + y={Y_NE} + auto_hflip=yes auto_vflip=no primary=no [/torch_frame] [/if] [else] - direction=s,sw,nw + direction=s,sw,se [frame] - image={IMG}~FL(horiz) - auto_hflip=no + image={IMG} auto_vflip=no primary=yes [/frame] [torch_frame] image="halo/torch/torch-big/flame-[1~17].png:120" layer=45 - x={X2} + directional_x={X} y={Y} auto_hflip=yes auto_vflip=no @@ -1110,40 +1121,51 @@ #enddef #define STANDING_ANIM_SMALL_TORCH IMG X X2 Y + +#arg IMG_NE + {IMG} +#endarg + +#arg X_NE + {X} +#endarg + +#arg Y_NE + {Y} +#endarg + [standing_anim] start_time=0 torch_start_time=0 [if] - direction=n,ne,se + direction=n,ne,nw [frame] - image={IMG} - auto_hflip=no + image={IMG_NE} auto_vflip=no primary=yes [/frame] [torch_frame] image="halo/torch/torch-small/flame-[1~17].png:120" layer=45 - x={X} - y={Y} - auto_hflip=no + directional_x={X_NE} + y={Y_NE} + auto_hflip=yes auto_vflip=no primary=no [/torch_frame] [/if] [else] - direction=s,sw,nw + direction=s,sw,se [frame] - image={IMG}~FL(horiz) - auto_hflip=no + image={IMG} auto_vflip=no primary=yes [/frame] [torch_frame] image="halo/torch/torch-small/flame-[1~17].png:120" layer=45 - x={X2} + directional_x={X} y={Y} auto_hflip=yes auto_vflip=no diff --git a/data/core/terrain-graphics.cfg b/data/core/terrain-graphics.cfg index a6bf9998fbc3..97f542ab71e6 100644 --- a/data/core/terrain-graphics.cfg +++ b/data/core/terrain-graphics.cfg @@ -1024,8 +1024,8 @@ C*,K*,X*,Q*,W*,Ai,M*,*^V*,*^B*,_off^_usr#enddef {NEW:WATER_342_180_TRANSITION Wo* (!,Wo*,!,W*,Sm) -550 "~O(50%)" water/ocean 21 DURATION=125 RANDOM_START=no} {NEW:WATER_342_180_TRANSITION Ww* (!,Ww*,!,W*,Sm) -551 "~O(50%)" water/water 17 DURATION=125 RANDOM_START=no} -{NEW:WATER_342_180_OVERLAY_TRANSITION Wog,Wwg,Wwrg (!,Wog,Wwg,Wwrg,!,W*,Sm) -503 water/overlay-gray 0.20} -{NEW:WATER_342_180_OVERLAY_TRANSITION Wot,Wwt,Wwrt (!,Wot,Wwt,Wwrt,!,W*,Sm) -505 water/overlay-tropical 0.16} +{NEW:WATER_342_180_OVERLAY_TRANSITION Wog,Wwg,Wwrg (!,Wog*,Wwg*,Wwrg,!,W*,Sm) -503 water/overlay-gray 0.20} +{NEW:WATER_342_180_OVERLAY_TRANSITION Wot,Wwt,Wwrt (!,Wot*,Wwt*,Wwrt,!,W*,Sm) -505 water/overlay-tropical 0.16} # We currently can't afford these extra rules to make the water transition nicely onto void and off-map, so # instead we make void and off-map transition over water. diff --git a/data/core/terrain-graphics/new-macros.cfg b/data/core/terrain-graphics/new-macros.cfg index 6f88344a4fb8..2e78614e5148 100644 --- a/data/core/terrain-graphics/new-macros.cfg +++ b/data/core/terrain-graphics/new-macros.cfg @@ -842,6 +842,9 @@ transition_inverted#endarg #arg FLAG transition#endarg +#arg IPF +~NOP()#endarg + [terrain_graphics] map=" , 2 @@ -854,7 +857,7 @@ transition#endarg type={ADJACENT} set_no_flag={FLAG}-@R0,{FLAG}-@R1,{FLAG}-@R2,{FLAG}-@R3,{FLAG}-@R4,{FLAG}-@R5 [image] - name={IMAGESTEM}-@R0-@R1-@R2-@R3-@R4-@R5.png + name={IMAGESTEM}-@R0-@R1-@R2-@R3-@R4-@R5.png{IPF} layer={LAYER} [/image] [/tile] @@ -903,7 +906,7 @@ transition#endarg type={ADJACENT} set_no_flag={FLAG}-@R0,{FLAG}-@R1,{FLAG}-@R2,{FLAG}-@R3,{FLAG}-@R4 [image] - name={IMAGESTEM}-@R0-@R1-@R2-@R3-@R4.png + name={IMAGESTEM}-@R0-@R1-@R2-@R3-@R4.png{IPF} layer={LAYER} [/image] [/tile] @@ -947,7 +950,7 @@ transition#endarg type={ADJACENT} set_no_flag={FLAG}-@R0,{FLAG}-@R1,{FLAG}-@R2,{FLAG}-@R3 [image] - name={IMAGESTEM}-@R0-@R1-@R2-@R3.png + name={IMAGESTEM}-@R0-@R1-@R2-@R3.png{IPF} layer={LAYER} [/image] [/tile] @@ -986,7 +989,7 @@ transition#endarg type={ADJACENT} set_no_flag={FLAG}-@R0,{FLAG}-@R1,{FLAG}-@R2 [image] - name={IMAGESTEM}-@R0-@R1-@R2.png + name={IMAGESTEM}-@R0-@R1-@R2.png{IPF} layer={LAYER} [/image] [/tile] @@ -1020,7 +1023,7 @@ transition#endarg type={ADJACENT} set_no_flag={FLAG}-@R0,{FLAG}-@R1 [image] - name={IMAGESTEM}-@R0-@R1.png + name={IMAGESTEM}-@R0-@R1.png{IPF} layer={LAYER} [/image] [/tile] @@ -1049,7 +1052,7 @@ transition#endarg type={ADJACENT} set_no_flag={FLAG}-@R0 [image] - name={IMAGESTEM}-@R0.png + name={IMAGESTEM}-@R0.png{IPF} layer={LAYER} [/image] [/tile] @@ -1520,6 +1523,177 @@ corner#endarg [/terrain_graphics] #enddef +#define NEW:DISABLE_GENERIC_CORNER_TRANSITION TERRAINLIST ADJACENT + +#arg FLAG +corner#endarg + + [terrain_graphics] + map=" +, 2 +2, 2 +, 1 +2, 2 +, 2" + [tile] + pos=1 + type={ADJACENT} + set_no_flag={FLAG}-concave-@R0,{FLAG}-concave-@R1,{FLAG}-concave-@R2,{FLAG}-concave-@R3,{FLAG}-concave-@R4,{FLAG}-concave-@R5 + [/tile] + [tile] + pos=2 + type={TERRAINLIST} + [/tile] + + rotations=tr,r,br,bl,l,tl + [/terrain_graphics] + [terrain_graphics] + map=" +, 2 +., 2 +, 1 +2, 2 +, 2" + [tile] + pos=1 + type={ADJACENT} + set_no_flag={FLAG}-concave-@R0,{FLAG}-concave-@R1,{FLAG}-concave-@R2,{FLAG}-concave-@R3 + [/tile] + [tile] + pos=2 + type={TERRAINLIST} + [/tile] + + rotations=tr,r,br,bl,l,tl + [/terrain_graphics] + [terrain_graphics] + map=" +, 2 +., 2 +, 1 +., 2 +, 2" + [tile] + pos=1 + type={ADJACENT} + set_no_flag={FLAG}-concave-@R0,{FLAG}-concave-@R1,{FLAG}-concave-@R2 + [/tile] + [tile] + pos=2 + type={TERRAINLIST} + [/tile] + + rotations=tr,r,br,bl,l,tl + [/terrain_graphics] + [terrain_graphics] + map=" +, 2 +., 2 +, 1 +., 2 +, ." + [tile] + pos=1 + type={ADJACENT} + set_no_flag={FLAG}-concave-@R0,{FLAG}-concave-@R1 + [/tile] + [tile] + pos=2 + type={TERRAINLIST} + [/tile] + + rotations=tr,r,br,bl,l,tl + [/terrain_graphics] + [terrain_graphics] + map=" +, 2 +., 2 +, 1 +., . +, ." + [tile] + pos=1 + type={ADJACENT} + set_no_flag={FLAG}-concave-@R0 + [/tile] + [tile] + pos=2 + type={TERRAINLIST} + [/tile] + + rotations=tr,r,br,bl,l,tl + [/terrain_graphics] + [terrain_graphics] + map=" +, 2 +3, 3 +, 1 +., . +, ." + [tile] + pos=1 + type={TERRAINLIST} + [/tile] + [tile] + pos=2 + type={ADJACENT} + set_no_flag={FLAG}-convex-@R0-@R5,{FLAG}-convex-@R5-@R0 + [/tile] + [tile] + pos=3 + type=!,{TERRAINLIST} + [/tile] + + rotations=tr,r,br,bl,l,tl + [/terrain_graphics] + [terrain_graphics] + map=" +, 2 +., 3 +, 1 +., . +, ." + [tile] + pos=1 + type={TERRAINLIST} + [/tile] + [tile] + pos=2 + type={ADJACENT} + set_no_flag={FLAG}-convex-@R0-@R5 + [/tile] + [tile] + pos=3 + type=!,{TERRAINLIST} + [/tile] + + rotations=tr,r,br,bl,l,tl + [/terrain_graphics] + [terrain_graphics] + map=" +, 2 +., 3 +, 1 +., . +, ." + [tile] + pos=1 + type={TERRAINLIST} + [/tile] + [tile] + pos=2 + type=!,{TERRAINLIST} + [/tile] + [tile] + pos=3 + type={ADJACENT} + set_no_flag={FLAG}-convex-@R0-@R1 + [/tile] + + rotations=tr,r,br,bl,l,tl + [/terrain_graphics] +#enddef + #define NEW:FOREST TERRAINLIST ADJACENT IMAGESTEM # This assumes centered images. Places the images named # {IMAGESTEM}-small[1-11].png on all {TERRAIN} adjacent to {ADJACENT}, and @@ -4194,6 +4368,9 @@ no#endarg #define NEW:WATER_342_180 TERRAINLIST IMAGESTEM FRAMES +#arg LAYER +-999#endarg + #arg DURATION 100#endarg @@ -4206,7 +4383,7 @@ no#endarg type={TERRAINLIST} set_no_flag=base - {WATER_342_180_TILE_VARIANTS "" -1000 "" {IMAGESTEM} {FRAMES} DURATION={DURATION} RANDOM_START={RANDOM_START}} + {WATER_342_180_TILE_VARIANTS "" {LAYER} "" {IMAGESTEM} {FRAMES} DURATION={DURATION} RANDOM_START={RANDOM_START}} [/tile] [/terrain_graphics] #enddef diff --git a/data/core/units/dunefolk/Cataphract.cfg b/data/core/units/dunefolk/Cataphract.cfg index 7df42ebebe07..1fe38ff70f24 100644 --- a/data/core/units/dunefolk/Cataphract.cfg +++ b/data/core/units/dunefolk/Cataphract.cfg @@ -19,6 +19,7 @@ units/dunefolk/rider/#enddef {AMLA_DEFAULT} cost=61 usage=fighter + undead_variation=mounted description= _ "Cataphracts are eminent horsemen, riders of mounts that are possessed less of speed or endurance but tremendous power instead. Bearing a lance along with their signature maces, these warriors are most often the secondary strike force after a primary assault. After enemy forces are already occupied and weakened by a flank of swordsmen, a terrifying sight is a group of cataphracts lining up, lances pitched at the ready. A gap is made amongst the Dunefolk ranks, and in a single charge, these mighty horsemen pierce straight through enemy formations, dealing a lethal blow in a single stroke. Those who try to flee swiftly discover that neither sand nor hills deter these riders in the slightest, and the displaced air of a descending mace is the last sound they hear." {NOTE_CHARGE} die_sound=horse-die.ogg diff --git a/data/core/units/dunefolk/Horse_Archer.cfg b/data/core/units/dunefolk/Horse_Archer.cfg index 1922879c7e9e..51cd7b214e4b 100644 --- a/data/core/units/dunefolk/Horse_Archer.cfg +++ b/data/core/units/dunefolk/Horse_Archer.cfg @@ -17,6 +17,7 @@ units/dunefolk/rider/#enddef advances_to=Dune Windbolt cost=38 usage=archer + undead_variation=mounted description= _ "Though relatively few in number, some riders favor archery as their technique of choice for battle. Fleet and elusive, these horsemen are experts at harassing less mobile foes with hails of arrows and hunting down fleeing enemies from a distance. Though not usually trained for infiltration or spying, these equestrians’ ability to pass messages from afar with their long-ranged arrows is of great use to maintain communication among the Dunefolk armies." die_sound=horse-die.ogg {DEFENSE_ANIM "{PATH_TEMP}horse-archer.png" "{PATH_TEMP}horse-archer.png" {SOUND_LIST:HORSE_HIT} } diff --git a/data/core/units/dunefolk/Marauder.cfg b/data/core/units/dunefolk/Marauder.cfg index 8fee2be14e78..dd77f30e1827 100644 --- a/data/core/units/dunefolk/Marauder.cfg +++ b/data/core/units/dunefolk/Marauder.cfg @@ -26,6 +26,7 @@ units/dunefolk/rider/#enddef advances_to=null {AMLA_DEFAULT} cost=52 + undead_variation=mounted usage=scout description= _ "Some find themselves well suited to the life of a raider and may even form their own clans with like-minded individuals. Ever roaming the deserts for unwary travelers or vulnerable caravans, these horsemen make their livelihood off scavenging and pilfering. Having no particular specialty, marauders are neither the strongest warriors, nor the most dextrous archers, but are nevertheless among the most dangerous enemies out in the desert due to their sheer maneuverability. A coordinated marauder attack can wipe out medium-sized camps before any response is possible, and guerrilla tactics may allow them to prevail against stronger foes where brute force does not. For this reason, they are sometimes hired by small armies or wealthier caravans as a deterrent to unwanted raids." die_sound=horse-die.ogg diff --git a/data/core/units/dunefolk/Raider.cfg b/data/core/units/dunefolk/Raider.cfg index b6b5c0cc7ceb..56732e4f38a9 100644 --- a/data/core/units/dunefolk/Raider.cfg +++ b/data/core/units/dunefolk/Raider.cfg @@ -26,6 +26,7 @@ units/dunefolk/rider/#enddef advances_to=Dune Marauder cost=34 usage=scout + undead_variation=mounted description= _ "Though rarely found in organized armies, raiders are a staple among the nomadic Dunefolk, who regularly ambush rival caravans and camps at night. In these scenarios, raw power is of little concern. The greatest importance is placed on speed — striking quickly and spreading as much chaos as possible in the shortest time possible allows these riders to get in and out of the blitz without fear of counterattack. Raiders are the fastest of the Dunefolk, capable of outpacing nearly anything they might encounter in the sandy deserts." die_sound={SOUND_LIST:HUMAN_DIE} {DEFENSE_ANIM_FILTERED "{PATH_TEMP}raider.png" "{PATH_TEMP}raider.png" {SOUND_LIST:HUMAN_HIT} ( diff --git a/data/core/units/dunefolk/Rider.cfg b/data/core/units/dunefolk/Rider.cfg index fd120f5342b0..6474c2c9dcbd 100644 --- a/data/core/units/dunefolk/Rider.cfg +++ b/data/core/units/dunefolk/Rider.cfg @@ -17,6 +17,7 @@ units/dunefolk/rider/#enddef advances_to=Dune Raider,Dune Horse Archer,Dune Sunderer cost=18 usage=scout + undead_variation=mounted description= _ "The Dunefolk are prominent horse breeders who raise many different varieties of mounts to fulfill various purposes. Those who are used for hard labor are bred for power, while those for journeys or caravans are bred for endurance. For warfare, a mix of traits is usually best, though the ability to easily and rapidly traverse sand is of utmost importance. The riders of these horses primarily function as scouts and messengers, or occasionally as supporting forces for weakened lines. The crucial trait of maneuverability is what allows these horsemen to be so effective and versatile out on the rolling dunes." die_sound=horse-die.ogg {DEFENSE_ANIM "{PATH_TEMP}rider.png" "{PATH_TEMP}rider.png" {SOUND_LIST:HORSE_HIT} } diff --git a/data/core/units/dunefolk/Sunderer.cfg b/data/core/units/dunefolk/Sunderer.cfg index 529676450af1..8071a634758a 100644 --- a/data/core/units/dunefolk/Sunderer.cfg +++ b/data/core/units/dunefolk/Sunderer.cfg @@ -17,6 +17,7 @@ units/dunefolk/rider/#enddef advances_to=Dune Cataphract cost=38 usage=fighter + undead_variation=mounted description= _ "Among the many different type of Dune horsemen, there are those who most enjoy the frantic melee at the heart of battle. Bearing short-ranged maces, these sunderers are sturdy, robust warriors who have both the disposition and skill to survive multiple skirmishes. Though not particularly creative or special warriors, such a rider is not impotent in any way — even a small group of sunderers is powerful enough to breach most enemy lines through sheer force. In a situation that requires it, these horsemen also possess enough skill at archery to weaken enemy forces or pick off fleeing stragglers." die_sound=horse-die.ogg {DEFENSE_ANIM "{PATH_TEMP}sunderer-defend2.png" "{PATH_TEMP}sunderer-defend1.png" {SOUND_LIST:HORSE_HIT} } diff --git a/data/core/units/dunefolk/Windbolt.cfg b/data/core/units/dunefolk/Windbolt.cfg index 4f47f528da07..dd36cdcd4f02 100644 --- a/data/core/units/dunefolk/Windbolt.cfg +++ b/data/core/units/dunefolk/Windbolt.cfg @@ -18,6 +18,7 @@ units/dunefolk/rider/#enddef {AMLA_DEFAULT} cost=50 usage=archer + undead_variation=mounted description= _ "Archery on horseback presents a number of additional challenges that very few are able to overcome. What separates the renowned windbolts from other bowmen is their ability to not only master these difficulties, but turn them into advantages instead. Making use of their steeds’ great speed, a windbolt is actually a better archer when mounted as compared to on land. The extra momentum from riding on horseback provides additional force to their already potent shots, and by riding in meandering patterns, these bowmen are able to curve the trajectories of their arrows, reaching targets they might not be able to otherwise. Having honed their craft to its apex, windbolts are the undisputed masters of ranged combat among the Dunefolk." die_sound=horse-die.ogg {DEFENSE_ANIM "{PATH_TEMP}windbolt.png" "{PATH_TEMP}windbolt.png" {SOUND_LIST:HORSE_HIT} } diff --git a/data/lua/as_text.lua b/data/lua/as_text.lua new file mode 100644 index 000000000000..5fe7fdaa2825 --- /dev/null +++ b/data/lua/as_text.lua @@ -0,0 +1,62 @@ +-- NOTE: the string output from here is intended solely as an aid in debugging; it should never be taken and used as an input to anything else. + +-- escaping takes 3/4 of the time, but we can't avoid it... +local function escape(str) + str = string.gsub(str, "%c", "") + str = string.gsub(str, "[\\\"]", "\\%0") + return str +end + +local function add_table_key(obj, buffer) + local _type = type(obj) + if _type == "string" then + buffer[#buffer + 1] = escape(obj) + elseif _type == "number" then + buffer[#buffer + 1] = obj + elseif _type == "boolean" then + buffer[#buffer + 1] = tostring(obj) + else + buffer[#buffer + 1] = '???' .. _type .. '???' + end +end + +local function format_any_value(obj, buffer) + local _type = type(obj) + if _type == "table" then + buffer[#buffer + 1] = '{' + buffer[#buffer + 1] = '"' -- needs to be separate for empty tables {} + for key, value in pairs(obj) do + add_table_key(key, buffer) + buffer[#buffer + 1] = '":' + format_any_value(value, buffer) + buffer[#buffer + 1] = ',"' + end + buffer[#buffer] = '}' -- note the overwrite + elseif _type == "string" then + buffer[#buffer + 1] = '"' .. escape(obj) .. '"' + elseif _type == "boolean" or _type == "number" then + buffer[#buffer + 1] = tostring(obj) + elseif _type == "userdata" then + buffer[#buffer + 1] = '"' .. escape(tostring(obj)) .. '"' + else + buffer[#buffer + 1] = '"???' .. _type .. '???"' + end +end + +local function value_to_text(obj) + if obj == nil then return "null" else + local buffer = {} + format_any_value(obj, buffer) + return table.concat(buffer) + end +end + +function wesnoth.as_text(...) + local result = {} + local n = 1 + for _, v in ipairs({ ... }) do + result[n] = value_to_text(v) + n = n + 1 + end + return table.concat(result, "\t") +end diff --git a/data/lua/cave_map_generator.lua b/data/lua/cave_map_generator.lua index 279622f3aa1e..962d1df4feff 100644 --- a/data/lua/cave_map_generator.lua +++ b/data/lua/cave_map_generator.lua @@ -122,6 +122,10 @@ function callbacks.generate_map(params) local width = math.max(v.data.width or 1, 1) local jagged = v.data.jagged or 0 local calc = function(x, y) + if x == 0 or x == params.map_width or y == 0 or y == params.map_height then + -- Map borders are impassable + return math.huge + end local res = 1.0 if map:get_tile(x, y) == params.terrain_wall then res = laziness diff --git a/data/lua/core.lua b/data/lua/core.lua index a232563d8667..8414e0b20f7b 100644 --- a/data/lua/core.lua +++ b/data/lua/core.lua @@ -282,7 +282,7 @@ function wesnoth.deprecate_api(elem_name, replacement, level, version, elem, det end local mt = {} for k,v in pairs(old_mt) do - mt[k] = old_mt[v] + mt[k] = old_mt[k] end mt.__index = function(self, key) if not msg_shown then @@ -699,7 +699,7 @@ local function reorder_dialog_args(t, n) table.insert( res, t[1]) table.remove( t, 1 ) end - local w = open_dialogs[1]:find(unpack(t)) + local w = open_dialogs[1]:find(table.unpack(t)) return w, res end @@ -720,7 +720,7 @@ end local function set_dialog_canvas(...) local w, args = reorder_dialog_args({...}, 2) - w:set_canvas(unpack(args)) + w:set_canvas(table.unpack(args)) end local function set_dialog_focus(...) @@ -750,12 +750,12 @@ end local function add_dialog_tree_node(...) local w, args = reorder_dialog_args({...}, 2) - w:add_item_of_type(unpack(args)) + w:add_item_of_type(table.unpack(args)) end local function remove_dialog_item(...) local w, args = reorder_dialog_args({...}, 2) - w:remove_items_at(unpack(args)) + w:remove_items_at(table.unpack(args)) end local old_show_dialog = gui.show_dialog @@ -881,3 +881,5 @@ wesnoth.show_dialog = wesnoth.deprecate_api('wesnoth.show_dialog', 'gui.show_dia wesnoth.format = wesnoth.deprecate_api('wesnoth.format', 'stringx.vformat', 1, nil, stringx.vformat) wesnoth.format_conjunct_list = wesnoth.deprecate_api('wesnoth.format_conjunct_list', 'stringx.format_conjunct_list', 1, nil, stringx.format_conjunct_list) wesnoth.format_disjunct_list = wesnoth.deprecate_api('wesnoth.format_disjunct_list', 'stringx.format_disjunct_list', 1, nil, stringx.format_disjunct_list) +-- Other +unpack = wesnoth.deprecate_api('unpack', 'table.unpack', 3, '1.17', table.unpack) diff --git a/data/modifications.cfg b/data/modifications.cfg index 24984fb1bb04..ad54bc4ce3d4 100644 --- a/data/modifications.cfg +++ b/data/modifications.cfg @@ -1,5 +1,32 @@ +#textdomain wesnoth +#ifdef MULTIPLAYER + [modification] - id = "delay_advancements" - name = _ "Delay Advancements" - type = "hybrid" + id=plan_unit_advance + name=_"Plan Unit Advance" + description=_"When playing a multiplayer game, you do not control what a unit advances if they advances on another player's turn. With this modification you can set what your units advance to beforehand either for a specific unit or for all units of the same type." + + [options] + [checkbox] + id="pickadvance_force_choice" # WARNING: do not change this ID because other maps are relying on it + name=_"Force advancement planning" + description=_"You will be asked a question on choosing advancement whenever an undecided unit appears. + +Some eras and scenarios may automatically enable this option." + default=no + [/checkbox] + [/options] + + [event] + name=preload + first_time_only=no + [lua] + code= {./modifications/pick_advance/dialog.lua} + [/lua] + [lua] + code= {./modifications/pick_advance/main.lua} + [/lua] + [/event] [/modification] + +#endif diff --git a/data/modifications/pick_advance/README.md b/data/modifications/pick_advance/README.md new file mode 100644 index 000000000000..3c88645a5a9e --- /dev/null +++ b/data/modifications/pick_advance/README.md @@ -0,0 +1,12 @@ +## How it works + +dialog "set" actions: + +* client (local only) +* unit.advances_to +* wml.variables + +recruit, post advance events: + +* get from wml.variables, set +* get from local client, publicly set diff --git a/data/modifications/pick_advance/dialog.lua b/data/modifications/pick_advance/dialog.lua new file mode 100644 index 000000000000..fa15e80012bf --- /dev/null +++ b/data/modifications/pick_advance/dialog.lua @@ -0,0 +1,129 @@ +-- << pickadvance_dialog + +pickadvance = {} +local T = wesnoth.require("lua/helper.lua").set_wml_tag_metatable {} +local _ = wesnoth.textdomain "wesnoth" + +local function filter_false(arr) + local result = {} + for _, v in ipairs(arr) do + if v ~= false then + result[#result + 1] = v + end + end + return result +end + + +function pickadvance.show_dialog_unsynchronized(advance_info, unit) +-- dialog exit codes -- + local reset_code = -3 + local single_unit_code = -1 + local all_units_code = 1 +-- + local unit_type_options = advance_info.type_advances + local options = {} + for _, ut in ipairs(unit_type_options) do + options[#options + 1] = wesnoth.unit_types[ut] + end + + local unit_override_one = (advance_info.unit_override or {})[2] == nil + and (advance_info.unit_override or {})[1] or nil + local game_override_one = (advance_info.game_override or {})[2] == nil + and (advance_info.game_override or {})[1] or nil + + local description_row = T.row { + T.column { T.label { use_markup = true, label = _"Plan advance:" } }, + } + + local list_sub_row = T.row { + T.column { T.image { id = "the_icon" } }, + T.column { grow_factor = 0, T.label { use_markup = true, id = "the_label" } }, + T.column { grow_factor = 1, T.spacer {} }, + } + + local toggle_panel = T.toggle_panel { return_value = single_unit_code, T.grid { list_sub_row } } + + local list_definition = T.list_definition { T.row { T.column { horizontal_grow = true, toggle_panel } } } + + local listbox = T.listbox { id = "the_list", list_definition, has_minimum = true } + + local reset_button = T.button { + return_value = reset_code, + label = _"Reset", + tooltip = _"Reset advancements to default" + } + local unit_button = T.button { + return_value = single_unit_code, + label = _"Save", + tooltip = _"Save the advancement for this unit only" + } + local recruits_subbutton = T.button { + return_value = all_units_code, + label = _"Save (all)", + tooltip = _"Save the advancement for all units of this type" + } + local recruits_button = not unit.canrecruit and T.row { T.column { horizontal_grow = true, recruits_subbutton } } + +-- main dialog definition + local dialog = { + T.tooltip { id = "tooltip_large" }, + T.helptip { id = "tooltip_large" }, + T.grid(filter_false { + T.row { T.column { T.spacer { width = 250 } } }, + description_row, + T.row { T.column { horizontal_grow = true, listbox } }, + T.row { T.column { horizontal_grow = true, unit_button } }, + recruits_button, + T.row { T.column { horizontal_grow = true, (unit_override_one or game_override_one) and reset_button or T.spacer { width = 250 } } }, + }) + } + +-- dialog preshow function + local function preshow() + for i, advance_type in ipairs(options) do + local text = advance_type.name + if advance_type.id == game_override_one then + text = text .. _" (chosen, all)" + elseif advance_type.id == unit_override_one then + text = text .. _" (chosen)" + end + wesnoth.set_dialog_value(text, "the_list", i, "the_label") + local img = advance_type.__cfg.image + wesnoth.set_dialog_value(img or "misc/blank-hex.png", "the_list", i, "the_icon") + end + + wesnoth.set_dialog_focus("the_list") + + local function select() + local i = wesnoth.get_dialog_value "the_list" + if i > 0 then + local img = options[i].__cfg.image + wesnoth.set_dialog_value(img or "misc/blank-hex.png", "the_list", i, "the_icon") + end + end + wesnoth.set_dialog_callback(select, "the_list") + end + +-- dialog postshow function + local item_result + local function postshow() + item_result = wesnoth.get_dialog_value("the_list") + end + + local dialog_exit_code = wesnoth.show_dialog(dialog, preshow, postshow) + +-- determine the choice made + local is_reset = dialog_exit_code == reset_code + local is_ok = dialog_exit_code >= single_unit_code and item_result >= 1 + local game_scope = dialog_exit_code == all_units_code + return { + is_unit_override = is_reset or is_ok, + unit_override = is_ok and options[item_result].id or is_reset and table.concat(unit_type_options, ","), + + is_game_override = is_reset or game_scope, + game_override = game_scope and options[item_result].id or nil, + } +end + +-- >> diff --git a/data/modifications/pick_advance/main.lua b/data/modifications/pick_advance/main.lua new file mode 100644 index 000000000000..e5e1931c5a90 --- /dev/null +++ b/data/modifications/pick_advance/main.lua @@ -0,0 +1,250 @@ +-- << pick_advance/main.lua + +local on_event = wesnoth.require("lua/on_event.lua") +local T = wesnoth.require("lua/helper.lua").set_wml_tag_metatable {} +local _ = wesnoth.textdomain "wesnoth" + +wesnoth.wml_actions.set_menu_item { + id = "pickadvance", + description = _"Pick Advance", + T.show_if { + T.lua { + code = "return pickadvance.menu_available()" + }, + }, + T.command { + T.lua { + code = "pickadvance.pick_advance()" + } + } +} + +-- replace any non-alphanumeric characters with an underscore +local function clean_type_func(unit_type) + return string.gsub(unit_type, "[^a-zA-Z0-9]", "_") +end + +-- splits a comma delimited string of unit types +-- returns a table of unit types that aren't blank, "null", and that exist +local function split_comma_units(string_to_split) + local result = {} + local n = 1 + for s in string.gmatch(string_to_split or "", "[^,]+") do + if s ~= "" and s ~= "null" and wesnoth.unit_types[s] then + result[n] = s + n = n + 1 + end + end + return result +end + +-- returns a table of the original unit types +-- a comma delimited string containing the same values +local function original_advances(unit) + local clean_type = clean_type_func(unit.type) + local variable = unit.variables["pickadvance_orig_" .. clean_type] or "" + return split_comma_units(variable), clean_type_func(variable) +end + +-- replace the unit's current advancements with the new set of units via object/effect +local function set_advances(unit, array) + wesnoth.add_modification(unit, "object", { + id = "pickadvance", + take_only_once = false, + T.effect { + apply_to = "new_advancement", + replace = true, + types = table.concat(array, ",") + } + }) +end + +-- for table "arr" containing sets of [index,unit_type] +-- return table containing sets of [unit_type,true] +local function array_to_set(arr) + local result = {} + for _, v in ipairs(arr) do + result[v] = true + end + return result +end + +-- for table "arr" containing sets of [unit_type,true] +-- return table containing sets of [index,unit_type] +local function array_filter(arr, func) + local result = {} + for _, v in ipairs(arr) do + if func(v) then + result[#result + 1] = v + end + end + return result +end + +-- works as anti-cheat and fixes tricky bugs in [male]/[female]/undead variation overrides +local function filter_overrides(unit, overrides) + local possible_advances_array = original_advances(unit) + local possible_advances = array_to_set(possible_advances_array) + local filtered = array_filter(overrides, function(e) return possible_advances[e] end) + return #filtered > 0 and filtered or possible_advances_array +end + +-- returns a table with the unit's original advancements +-- the unit's currently overridden advancement or nil if not set +-- the unit's currently overridden advancement or nil if not set, but set by some other mechanism from the current game +local function get_advance_info(unit) + local type_advances, orig_options_sanitized = original_advances(unit) + local game_override_key = "pickadvance_side" .. unit.side .. "_" .. orig_options_sanitized + local game_override = wesnoth.get_variable(game_override_key) + local function correct(override) + return override and #override > 0 and #override < #type_advances and override or nil + end + + return { + type_advances = type_advances, + unit_override = correct(unit.advances_to), + game_override = correct(split_comma_units(game_override)), + } +end + +-- true if there's a unit at the selected hex +-- the unit has advancements +-- the unit is on a local human controlled side +-- the unit has multiple options in either its original set of advancements or current set of advancements +function pickadvance.menu_available() + local unit = wesnoth.get_unit(wml.variables.x1, wml.variables.y1) + return unit and + #unit.advances_to > 0 + and wesnoth.sides[unit.side].is_local and wesnoth.sides[unit.side].controller == "human" + and (#original_advances(unit) > 1 or #unit.advances_to > 1) +end + +-- if the unit doesn't have a set of original advancements present, remove any existing "pickadvance" object +-- set the unit's original advancements in its variables +-- and then set the unit's advancement to either a game-provided override or its default advancements +local function initialize_unit(unit) + local clean_type = clean_type_func(unit.type) + if unit.variables["pickadvance_orig_" .. clean_type] == nil then + wesnoth.wml_actions.remove_object { + object_id = "pickadvance", + id = unit.id + } + unit.variables["pickadvance_orig_" .. clean_type] = table.concat(unit.advances_to, ",") + local advance_info = get_advance_info(unit) + local desired = advance_info.game_override or unit.advances_to + desired = filter_overrides(unit, desired) + set_advances(unit, desired) + end +end + +-- let the player select the unit's advancement via dialog +function pickadvance.pick_advance(unit) + unit = unit or wesnoth.get_unit(wml.variables.x1, wml.variables.y1) + initialize_unit(unit) + local _, orig_options_sanitized = original_advances(unit) + local dialog_result = wesnoth.synchronize_choice(function() + local local_result = pickadvance.show_dialog_unsynchronized(get_advance_info(unit), unit) + return local_result + end, function() return { is_ai = true } end) + if dialog_result.is_ai then + return + end + dialog_result.unit_override = split_comma_units(dialog_result.unit_override) + dialog_result.game_override = split_comma_units(dialog_result.game_override) + dialog_result.unit_override = filter_overrides(unit, dialog_result.unit_override) + dialog_result.game_override = filter_overrides(unit, dialog_result.game_override) + if dialog_result.is_unit_override then + set_advances(unit, dialog_result.unit_override) + end + if dialog_result.is_game_override then + local key = "pickadvance_side" .. unit.side .. "_" .. orig_options_sanitized + wesnoth.set_variable(key, table.concat(dialog_result.game_override, ",")) + end +end + +-- make unit advancement tree viewable in the ingame help +local known_units = {} +local function make_unit_known(unit) -- can be both unit or unit type + local type = unit.type or unit.id + if known_units[type] then return end + known_units[type] = true + wesnoth.add_known_unit(type) + for _, advance in ipairs(unit.advances_to) do + make_unit_known(wesnoth.unit_types[advance]) + end +end + +-- initialize a unit for picking an advancement +-- make its advancements viewable +-- force picking an advancement if it has multiple and the force option was specified +local function initialize_unit_x1y1(ctx) + local unit = wesnoth.get_unit(ctx.x1, ctx.y1) + if not wesnoth.sides[unit.side].__cfg.allow_player then return end + initialize_unit(unit) + make_unit_known(unit) + if #unit.advances_to > 1 and wml.variables.pickadvance_force_choice and unit.side == wesnoth.current.side then + pickadvance.pick_advance(unit) + end +end + +-- return true if the side can be played and has either a recruit list set or non-leader units +local function humans_can_recruit() + for _, side in ipairs(wesnoth.sides) do + local units = wesnoth.get_units { side = side.side, canrecruit = false } + if side.__cfg.allow_player and (#side.recruit ~= 0 or #units > 0) then + return true + end + end +end +-- return true if any keeps exist +local function map_has_keeps() + local width,height,_ = wesnoth.get_map_size() + for x = 1, width do + for y = 1, height do + local terr = wesnoth.get_terrain(x, y) + local info = wesnoth.get_terrain_info(terr) + if info.keep then + return true + end + end + end +end + +-- on start determine whether choosing an advancement is force for each unit +on_event("start", function() + local map_has_recruits = humans_can_recruit() and map_has_keeps() + wml.variables.pickadvance_force_choice = wml.variables.pickadvance_force_choice or not map_has_recruits +end) + +-- set "fresh_turn" for the moveto event at the start of each side turn +local fresh_turn = false +on_event("turn refresh", function() + fresh_turn = true +end) + +-- the first time a unit moves at the start of each side's turn, check if there are any new units that need to be forced to make an advancement choice +on_event("moveto", function() + if fresh_turn then + fresh_turn = false + if not wesnoth.sides[wesnoth.current.side].__cfg.allow_player then return end + for _, unit in ipairs(wesnoth.get_units { side = wesnoth.current.side }) do + if #unit.advances_to > 1 and wml.variables.pickadvance_force_choice and wesnoth.current.turn > 1 then + pickadvance.pick_advance(unit) + if #unit.advances_to > 1 then + local len = #unit.advances_to + local rand = wesnoth.random(len) + unit.advances_to = { unit.advances_to[rand] } + end + else + initialize_unit(unit) + end + end + end +end) + +-- initialize units on recruit and after advancing, forcing another advancement choice if required +on_event("recruit", initialize_unit_x1y1) +on_event("post advance", initialize_unit_x1y1) + + +-- >> diff --git a/data/schema/core/addons.cfg b/data/schema/core/addons.cfg index 876ea5e48325..f6c3ca290d56 100644 --- a/data/schema/core/addons.cfg +++ b/data/schema/core/addons.cfg @@ -126,7 +126,7 @@ {SIMPLE_KEY id string} {DEFAULT_KEY first_time_only bool yes} {DEFAULT_KEY delayed_variable_substitution bool no} - + {FILTER_TAG "filter" unit ()} {FILTER_TAG "filter_second" unit ()} {FILTER_TAG "filter_attack" weapon ()} @@ -170,6 +170,7 @@ {SIMPLE_KEY icon string} {SIMPLE_KEY abbrev t_string} {SIMPLE_KEY image string} + {SIMPLE_KEY background string} {DEFAULT_KEY description_alignment text_alignment left} {DEFAULT_KEY type addon_type sp} {SIMPLE_KEY define string} diff --git a/data/test/scenarios/as_text.cfg b/data/test/scenarios/as_text.cfg new file mode 100644 index 000000000000..af7f5cd4efa4 --- /dev/null +++ b/data/test/scenarios/as_text.cfg @@ -0,0 +1,68 @@ +# Unit tests for wesnoth.as_text(...) + +{GENERIC_UNIT_TEST "as_text" ( + [event] + name = prestart + + [set_variables] + name=var + [value] + [one] + [first] + a=1 + b="5" + c=true + [/first] + [/one] + [two] + [second] + x=9 + y="3" + z=false + [/second] + [/two] + [/value] + [/set_variables] + + [lua] + code = << + local function assert_equal(source, result) + if source ~= result then + -- Fail the test + wesnoth.wml_actions.endlevel({test_result = "fail", linger_mode = true}) + end + end + local function assert_contains(source, fragment) + if not string.find(source, fragment, 1, true) then + -- Fail the test + wesnoth.wml_actions.endlevel({test_result = "fail", linger_mode = true}) + end + end + + assert_equal(wesnoth.as_text("a"), '"a"') + assert_equal(wesnoth.as_text(1), "1") + assert_equal(wesnoth.as_text(true), "true") + assert_equal(wesnoth.as_text({ "a", "b", "c" }), '{"1":"a","2":"b","3":"c"}') + + -- associative table iteration order not defined and can vary between runs even when the data remains identical + local tab_txt = wesnoth.as_text({ a = 1, b = false, c = "d" }) + assert_contains(tab_txt, '"a":1') + assert_contains(tab_txt, '"b":false') + assert_contains(tab_txt, '"c":"d"') + + local wml_tab_txt = wesnoth.as_text(wml.variables["var"]) + assert_contains(wml_tab_txt, '{"1":{"1":"one","2":{"1":{"1":"first","2":{') + assert_contains(wml_tab_txt, '"a":1') + assert_contains(wml_tab_txt, '"b":5') + assert_contains(wml_tab_txt, '"c":true') + assert_contains(wml_tab_txt, ',"2":{"1":"two","2":{"1":{"1":"second","2":{') + assert_contains(wml_tab_txt, '"x":9') + assert_contains(wml_tab_txt, '"y":3') + assert_contains(wml_tab_txt, '"z":false') + + -- Pass the test. Doesn't do anything if any of the above assertions has failed. + wesnoth.wml_actions.endlevel({test_result = "pass", linger_mode = true}) + >> + [/lua] + [/event] +)} diff --git a/data/tools/addon_manager/html.py b/data/tools/addon_manager/html.py index 386e1035ca71..c18f711d63bb 100755 --- a/data/tools/addon_manager/html.py +++ b/data/tools/addon_manager/html.py @@ -109,8 +109,8 @@ diff --git a/data/tools/helptrailer.html b/data/tools/helptrailer.html index 6c9061e60239..eeabec1bbe84 100644 --- a/data/tools/helptrailer.html +++ b/data/tools/helptrailer.html @@ -6,8 +6,8 @@ diff --git a/data/tools/unit_tree/html_output.py b/data/tools/unit_tree/html_output.py index 8433684b12f5..5dd612e46ae6 100644 --- a/data/tools/unit_tree/html_output.py +++ b/data/tools/unit_tree/html_output.py @@ -119,8 +119,8 @@ diff --git a/src/actions/advancement.cpp b/src/actions/advancement.cpp index 63fa8468bd6a..b91f5f662ff1 100644 --- a/src/actions/advancement.cpp +++ b/src/actions/advancement.cpp @@ -233,12 +233,11 @@ namespace } else { - //we are in the situation, that the unit is owned by a human, but he's not allowed to do this decision. - //because it's a mp game and it's not his turn. - //note that it doesn't matter whether we call randomness::generator->next_random() or rand(). - res = randomness::generator->get_random_int(0, nb_options_-1); + // we are in the situation, that the unit is owned by a human, but he's not allowed to do this decision. + // because it's a mp game and it's not his turn. + // default to the first unit listed in the unit's advancements } - LOG_NG << "unit at position " << loc_ << "choose advancement number " << res << "\n"; + LOG_NG << "unit at position " << loc_ << " chose advancement number " << res << "\n"; config retv; retv["value"] = res; return retv; diff --git a/src/play_controller.cpp b/src/play_controller.cpp index 93b313e02442..2893330720ec 100644 --- a/src/play_controller.cpp +++ b/src/play_controller.cpp @@ -522,18 +522,6 @@ void play_controller::do_init_side() // Make sure vision is accurate. actions::clear_shroud(current_side(), true); - { - const auto& active_mods = get_saved_game().classification().active_mods; - bool delay_advancements - = std::find(active_mods.begin(), active_mods.end(), "delay_advancements") != active_mods.end(); - - for(unit& u : resources::gameboard->units()) { - if(delay_advancements && u.side() == current_side()) { - advance_unit_at(u.get_location()); - } - } - } - init_side_end(); check_victory(); sync.do_final_checkup(); diff --git a/src/scripting/lua_audio.cpp b/src/scripting/lua_audio.cpp index 45ddb24a1d5d..28a0911c1401 100644 --- a/src/scripting/lua_audio.cpp +++ b/src/scripting/lua_audio.cpp @@ -234,7 +234,7 @@ static int intf_music_commit(lua_State*) { static int impl_track_get(lua_State* L) { lua_music_track* track = get_track(L, 1); - if(track == nullptr || !track->valid()) { + if(track == nullptr) { return luaL_error(L, "Error: Attempted to access an invalid music track.\n"); } const char* m = luaL_checkstring(L, 2); diff --git a/src/scripting/lua_kernel_base.cpp b/src/scripting/lua_kernel_base.cpp index d377708ee263..0c88042302c5 100644 --- a/src/scripting/lua_kernel_base.cpp +++ b/src/scripting/lua_kernel_base.cpp @@ -129,6 +129,23 @@ int lua_kernel_base::intf_print(lua_State* L) return 0; } +static void impl_warn(void* p, const char* msg, int tocont) { + static const char*const prefix = "Warning:\n "; + static std::ostringstream warning(prefix); + warning.seekp(0, std::ios::end); + warning << msg << ' '; + if(!tocont) { + auto& lk = lua_kernel_base::get_lua_kernel(reinterpret_cast(p)); + lk.add_log_to_console(warning.str()); + warning.str(prefix); + } +} + +void lua_kernel_base::add_log_to_console(const std::string& msg) { + cmd_log_ << msg << "\n"; + DBG_LUA << "'" << msg << "'\n"; +} + /** * Replacement load function. Mostly the same as regular load, but disallows loading binary chunks * due to CVE-2018-1999023. @@ -328,6 +345,7 @@ static int intf_deprecated_message(lua_State* L) { lua_push(L, msg); return lua_error(L); } + lua_warning(L, msg.c_str(), false); return 0; } @@ -485,6 +503,7 @@ lua_kernel_base::lua_kernel_base() lua_setglobal(L, "std_print"); //storing original impl as 'std_print' lua_settop(L, 0); //clear stack, just to be sure + lua_setwarnf(L, &::impl_warn, L); lua_pushcfunction(L, &dispatch<&lua_kernel_base::intf_print>); lua_setglobal(L, "print"); diff --git a/src/scripting/lua_kernel_base.hpp b/src/scripting/lua_kernel_base.hpp index 904a6dd86d0a..60adef50554f 100644 --- a/src/scripting/lua_kernel_base.hpp +++ b/src/scripting/lua_kernel_base.hpp @@ -115,6 +115,7 @@ class lua_kernel_base { // Print text to the command log for this lua kernel. Used as a replacement impl for lua print. int intf_print(lua_State * L); public: + void add_log_to_console(const std::string& msg); // Show the interactive lua console (for debugging purposes) int intf_show_lua_console(lua_State * L); protected: diff --git a/src/server/campaignd/server.cpp b/src/server/campaignd/server.cpp index e05767c295c3..f49359024754 100644 --- a/src/server/campaignd/server.cpp +++ b/src/server/campaignd/server.cpp @@ -982,7 +982,10 @@ void server::handle_request_campaign(const server::request& req) const auto& from = req.cfg["from_version"].str(); const auto& to = req.cfg["version"].str(version_map.rbegin()->first); - auto to_version_iter = version_map.find(version_info{to}); + const version_info from_parsed{from}; + const version_info to_parsed{to}; + + auto to_version_iter = version_map.find(to_parsed); if(to_version_iter == version_map.end()) { send_error("Could not find requested version " + to + " of the addon '" + name + "'.", req.sock); @@ -992,7 +995,13 @@ void server::handle_request_campaign(const server::request& req) auto full_pack_path = addon["filename"].str() + '/' + to_version_iter->second["filename"].str(); const int full_pack_size = filesystem::file_size(full_pack_path); - if(!from.empty() && version_map.count(version_info{from}) != 0) { + // Assert `From < To` before attempting to do build an update sequence, since std::distance(A, B) + // requires A <= B to avoid UB with std::map (which doesn't support random access iterators) and + // we're going to be using that a lot next. We also can't do anything fancy with downgrades anyway, + // and same-version downloads can be regarded as though no From version was specified in order to + // keep things simple. + + if(!from.empty() && from_parsed < to_parsed && version_map.count(from_parsed) != 0) { // Build a sequence of updates beginning from the client's old version to the // requested version. Every pair of incrementing versions on the server should // have an update pack written to disk during the original upload(s). @@ -1004,7 +1013,7 @@ void server::handle_request_campaign(const server::request& req) int delivery_size = 0; bool force_use_full = false; - auto start_point = version_map.find(version_info{from}); // Already known to exist + auto start_point = version_map.find(from_parsed); // Already known to exist auto end_point = std::next(to_version_iter, 1); // May be end() if(std::distance(start_point, end_point) <= 1) { @@ -1059,7 +1068,7 @@ void server::handle_request_campaign(const server::request& req) simple_wml::document doc(wml_text.c_str(), simple_wml::INIT_STATIC); doc.compress(); - LOG_CS << req << "Sending add-on '" << name << "' version: " << from << " -> " << to << " (delta))\n"; + LOG_CS << req << "Sending add-on '" << name << "' version: " << from << " -> " << to << " (delta)\n"; boost::system::error_code ec; coro_send_doc(req.sock, doc, req.yield[ec]); diff --git a/src/units/frame.cpp b/src/units/frame.cpp index f9f75a0e6cc6..27d54a925037 100644 --- a/src/units/frame.cpp +++ b/src/units/frame.cpp @@ -522,6 +522,7 @@ void unit_frame::redraw(const int frame_time, bool on_start_time, bool in_scope_ const int x = static_cast(tmp_offset * xdst + (1.0 - tmp_offset) * xsrc) + d2; const int y = static_cast(tmp_offset * ydst + (1.0 - tmp_offset) * ysrc) + d2; + const double disp_zoom = display::get_singleton()->get_zoom_factor(); if(image != nullptr) { bool facing_west = ( @@ -536,19 +537,19 @@ void unit_frame::redraw(const int frame_time, bool on_start_time, bool in_scope_ if(!current_data.auto_hflip) { facing_west = false; } if(!current_data.auto_vflip) { facing_north = true; } - int my_x = x + current_data.x - image->w / 2; - int my_y = y + current_data.y - image->h / 2; + int my_x = x + current_data.x * disp_zoom - image->w / 2; + int my_y = y + current_data.y * disp_zoom - image->h / 2; if(facing_west) { - my_x -= current_data.directional_x; + my_x -= current_data.directional_x * disp_zoom; } else { - my_x += current_data.directional_x; + my_x += current_data.directional_x * disp_zoom; } if(facing_north) { - my_y += current_data.directional_y; + my_y += current_data.directional_y * disp_zoom; } else { - my_y -= current_data.directional_y; + my_y -= current_data.directional_y * disp_zoom; } display::get_singleton()->render_image(my_x, my_y, @@ -602,16 +603,16 @@ void unit_frame::redraw(const int frame_time, bool on_start_time, bool in_scope_ if(direction != map_location::SOUTH_WEST && direction != map_location::NORTH_WEST) { halo_id = halo_man.add( - static_cast(x + current_data.halo_x * display::get_singleton()->get_zoom_factor()), - static_cast(y + current_data.halo_y * display::get_singleton()->get_zoom_factor()), + static_cast(x + current_data.halo_x * disp_zoom), + static_cast(y + current_data.halo_y * disp_zoom), current_data.halo + current_data.halo_mod, map_location(-1, -1), orientation ); } else { halo_id = halo_man.add( - static_cast(x - current_data.halo_x * display::get_singleton()->get_zoom_factor()), - static_cast(y + current_data.halo_y * display::get_singleton()->get_zoom_factor()), + static_cast(x - current_data.halo_x * disp_zoom), + static_cast(y + current_data.halo_y * disp_zoom), current_data.halo + current_data.halo_mod, map_location(-1, -1), orientation diff --git a/src/units/helper.cpp b/src/units/helper.cpp index b37eba1fa41c..15ec3fdc993d 100644 --- a/src/units/helper.cpp +++ b/src/units/helper.cpp @@ -36,13 +36,6 @@ bool will_certainly_advance(const unit_map::iterator &u) if(!u.valid()) { return false; } - if(resources::controller) { - const auto& active_mods = resources::controller->get_saved_game().classification().active_mods; - bool delay_advancements = std::find(active_mods.begin(), active_mods.end(), "delay_advancements") != active_mods.end(); - if(delay_advancements && resources::controller->current_side() != u->side()) { - return false; - } - } return u->advances() && number_of_possible_advances(*u) > 0; } diff --git a/src/utils/optional_reference.hpp b/src/utils/optional_reference.hpp index 0c0c437a0d14..9bedfa44aa60 100644 --- a/src/utils/optional_reference.hpp +++ b/src/utils/optional_reference.hpp @@ -74,14 +74,19 @@ class optional_reference return opt_.has_value(); } + /** Returns a pointer to the referenced object or nullptr if no reference is held. */ T* ptr() const { - return &value(); + if(opt_) { + return &value(); + } else { + return nullptr; + } } T* operator->() const { - return ptr(); + return &value(); } T& operator*() const diff --git a/wml_test_schedule b/wml_test_schedule index fcaec6b2ba95..6a382b752805 100644 --- a/wml_test_schedule +++ b/wml_test_schedule @@ -116,6 +116,7 @@ 0 test_wml_conditionals 0 lua_wml_tagnames 0 test_scoped_vars +0 as_text # # Pathfinding #