Compare commits

...

99 commits

Author SHA1 Message Date
phosit
a2cae4d69f
Update appdata for next RC
(cherry picked from commit a2c59cf87f)
Signed-off-by: phosit <phosit@autistici.org>
2026-02-15 18:46:25 +01:00
Vladislav Belov
72c6aad939
Fixes Atlas Terrain panel in dark mode
(cherry picked from commit 70c15abadb)
Signed-off-by: phosit <phosit@autistici.org>
2026-02-15 18:46:25 +01:00
phosit
a56ffcfd25
Update appdata for next RC
(cherry picked from commit 45c3a03a2e)
Signed-off-by: phosit <phosit@autistici.org>
2026-02-04 20:16:52 +01:00
real_tabasco_sauce
72e0ace313
German balance emergency changes
-Seeresses "Soldier" class removed as they are support units.
-Seeresses given correct vision value.
-Seeresses are unaffected by healer discount.
-germans no longer access archery spread tech since they have no archers.

(cherry picked from commit 87ed9c8092)
Signed-off-by: phosit <phosit@autistici.org>
2026-02-04 20:16:52 +01:00
Atrik
7033b81ce6
Default hotkeys changes
Reassign 'Toggle mouse grab' to F3 to avoid conflicts with gameplay hotkeys

Unassign 'Show status bars' often toggled by mistake by new players and confused for a selection bug

Assign 'Bird eye view' to Shift+Tab

(cherry picked from commit 426693ebef)
Signed-off-by: phosit <phosit@autistici.org>
2026-02-04 20:16:52 +01:00
phosit
30b741f8ba
Update appdata for next RC
(cherry picked from commit 72591b7608)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-29 21:56:19 +01:00
Ralph Sennhauser
2da2c3394f
Cleanly fail autostart for invalid map type
As for any invalid argument reject them and cleanly exit with failure
status.

Fixes: #7687
Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
(cherry picked from commit 958e6de9d3)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-29 21:56:19 +01:00
Ralph Sennhauser
f578a5b34d
Readd JS API function Engine.Exit()
Requested in #8244 for scripting purposes and automated testing. Extend
the original design by adding a means to pass an exit status. This also
comes in handy in case one wants to cleanly error out from JS on parsing
errors of command line arguments as reported in #7967.

Fixes: #8244
Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
(cherry picked from commit 0d60bdfd2e)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-29 21:56:19 +01:00
Vantha
8fee4dbb76
Temporary workaround for font baseline issue
Quick temporary fix for #8505 for the release of R28.

(cherry picked from commit 2483e7172b)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-29 21:56:19 +01:00
Vantha
baa18fd57d
Temporary workaround for icon misalignment
Quick temporary fix for #8194 for the release of R28.

(cherry picked from commit 7fd788af0f)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-29 21:56:19 +01:00
Atrik
231750edf1
Fix errors if promoted units change attack range
While in combat, if units are promoted and the promotion results
in a change in their attack range, this could trigger some errors
as 'this.template[type]' had a chance to be undefined when performing
a 'RepeatRangeCheck'.

Fixes #8670

(cherry picked from commit 68e625ab7a)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-29 21:56:18 +01:00
Ralph Sennhauser
0d1cdc0eaa
Workaround renamed property in gamereport
The gendered citizen feature changed stat counter names in
3592814aa8 which are submitted to echelon
for rated games with the game report, the change in name for the property
means it no longer matches the database column name effectively breaking
rated games.

Translate the property name on the fly.

Fixes: #8687
Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
(cherry picked from commit 0691e7f0ff)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-29 21:56:18 +01:00
phosit
63d4513ebf
Serialize canPlay property in Petra
This was forgotten in 7b1d4426aa.

Fixes: #8674
(cherry picked from commit a6357322e9)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-22 20:43:57 +01:00
Dunedan
a1cb3055d9
Fix string extraction of new game settings
5741f77c6e and b5256ce014 added new translatable strings for game
settings, but missed adding them to
binaries/data/mods/public/l10n/messages.json to get them properly
extracted into the PO-templates for translation. This commit fixes that.

(cherry picked from commit f4c52e49a7)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-15 18:06:48 +01:00
Dunedan
7fd034a2c0
Fix translatable strings in XML files
Some translatable strings in XML files have leading and trailing line
breaks and tabs. As these characters are significant in text in XML
files, they don't belong there.

Refs: #8649
(cherry picked from commit 8f8d1195c2)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-14 20:59:47 +01:00
phosit
0f21853bd8
Update appdata for next RC
(cherry picked from commit b77ee3c5dc)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-05 21:09:03 +01:00
phosit
b7fe462045
Revert "Add myself to the community credits (for packaging work)"
This reverts commit 7f0486e18e.
2026-01-01 17:33:45 +01:00
phosit
bf0034f694
Close register-page before opening login-page
The `onTick` of the register-page was still running when connecting to
the lobby. This lead to an error when the `connect` message was
received.
With this commit returning from the login-page will always return to the
entrance-page. Previously it returned to the register-page when it was
opened by through that page.

(cherry picked from commit 0b83e24065)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:46 +01:00
Olivier Tilloy
b228b611de
Add myself to the community credits (for packaging work)
(cherry picked from commit 7f0486e18e)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:46 +01:00
Olivier Tilloy
72b56d9fe5
Spidermonkey build: do not unpack unneeded test files
This change reduces the disk space requirement by 50%, from 1.1 GB down to 564 MB.
It is relevant when building 0AD in resource-constrained environments (e.g. in CI).

(cherry picked from commit 8bd0d0b84f)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:46 +01:00
Itms
fb12d00c70
Build the Actor Editor during the nightly build
This is a regression of a fix in 7e481b73cd,
lost during the git migration. Refs #1819

(cherry picked from commit d1319179f8)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:46 +01:00
Vantha
1690efeb72
Complete the per-player pop cap implementation
The 'PopulationLimit' attribute of each player seems to have been
without effect for a long time, but this patch fixes it.

Fixes #7850

(cherry picked from commit 9b8ff77265)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:46 +01:00
Vantha
5c8cf9a470
Add fallback values for pop cap and pop cap type
Make InitGame.js responsible for providing proper (defined) values.

Refs #7850
Fixes #7695

(cherry picked from commit 3a73dffc1c)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:46 +01:00
Vantha
d9ae2f8503
Remove inconsistent override in CDropdown.h
It was added in 670f1e5d42 and, while not illegal, was inconsistent with the
rest of the header file, which caused compiler warnings.
As a quick solution the override keyword is simply removed again.
In the long run, it would be good to still modernise the style of all files
in that directory (at once).

(cherry picked from commit 2e450f0f52)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:45 +01:00
trompetin17
b71cd96d12
Fix exceeding input boundaries in console
After 734386ce9f the new font system calculate height and cap height,
previously was having some magic number. Now we are using cap height
divide 2 to give a more nice space.

Remove an extra pixel in the buffer and improves background color for
better reading and eye care.

This also support the change console font option added in d549cbeeaa

Fixes: #8351
(cherry picked from commit 8e820a988e)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:45 +01:00
Vladislav Belov
d93722a023
Fixes ProfilerViewer when drawing empty cells
Currently CalculateStringSize can't handle empty string (see #8630).
As a simple fix for RC just avoid drawing empty texts.

Refs: #8630
(cherry picked from commit df9c6f510c)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:45 +01:00
Itms
7d2647d59a
Fix NSIS auto-uninstall
The NSIS script incorrectly passes the default installation dir as
argument for the auto-uninstaller of previous installs.

This is supposed to avoid moving the uninstaller to a temp file, but it
is unclear why that was done, as this leaves the uninstaller behind.

More importantly, now that we have changed the default installation
directory, the auto-uninstall tries to remove the previous install from
the new location, which does nothing and leaves behind several GB on the
disk.

(cherry picked from commit 771bf0ba08)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:45 +01:00
Vladislav Belov
1dff943455
Fixes TerrainTextureManager after refactoring
In fb98f5059a the manager was refactored
and the order of deinitialization was incorrectly changed.

(cherry picked from commit cea77c497c)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:45 +01:00
real_tabasco_sauce
ce7a180e73
update scenario map to account for changed template name for clubman
(cherry picked from commit 621b4f96cc)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:45 +01:00
real_tabasco_sauce
ca1ad508a4
mixed improvements to germans
-Make clubmen champion macemen and remove buiding ability to ensure they are not mistaken for CS units.
-Decrease obstruction size of houses (clunky to place in staff match)
-Encampents only allowed in own/neutral territory
-'fear' icon used for Lugius vision aura instead of movement speed.
- Make covered wagons unable to research house techs and train civilians.

(cherry picked from commit ec19e5d663)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:45 +01:00
Vladislav Belov
6d531e0303
Fixes uninitialized GPUSkinning in Atlas
Currently CRenderingOptions are initialized only once on the application
start. It means changed m_GPUSkinning wasn't reset on the switch to Atlas.

Fixes #8596

(cherry picked from commit f43e98da09)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:45 +01:00
phosit
e6e5d61b22
Allow swapped in pages to close themselves
This wasn't possible because init functions are called inside each
other and the outer one overwrites the result of the inner one.
Now the outer result doesn't overwrite the inner result but stores it to
the pointed to location.

(cherry picked from commit e62eb96092)
Signed-off-by: phosit <phosit@autistici.org>
2026-01-01 16:08:45 +01:00
Vantha
7386a5d514
Improve Engine.GetTextSize deprecation message
(cherry picked from commit 4d08446285)
Signed-off-by: phosit <phosit@autistici.org>
2025-12-23 20:18:16 +01:00
Vantha
4140858066
Fix warnings on the charts tab of summary screen
Engine.GetTextWidth has been deprecated since e845da025a

Idea:
If you look at a dropdown as just a text field (its header) that can
change caption like any other, then getPreferredHeaderTextSize is the
equivalent to getPreferredTextSize (present on buttons and text fields).

Fixes #8493

(cherry picked from commit 670f1e5d42)
Signed-off-by: phosit <phosit@autistici.org>
2025-12-23 20:18:16 +01:00
Vantha
cc56bafc66
Fix oversight in 83f4d8789b
(cherry picked from commit fbb6052c30)
Signed-off-by: phosit <phosit@autistici.org>
2025-12-23 20:18:16 +01:00
phosit
10408b46c2
Propagate error from autostart
The JavaScript error wasn't propagated leading to an infinite loop.

Fixes: #7967
(cherry picked from commit 14a5ccee52)
Signed-off-by: phosit <phosit@autistici.org>
2025-12-23 20:18:16 +01:00
Itms
e2764dcee1
Do not use Jenkins custom SVN client on Windows
It is extremely prone to timeouts and failures in this environment.

(cherry picked from commit ac36758b21)
Signed-off-by: phosit <phosit@autistici.org>
2025-12-14 10:37:17 +01:00
phosit
5c333770ee
Increase home island size on River Archipelago
With some settings mines weren't able to be placed.
Refs: #8579

(cherry picked from commit c02764e17a)
Signed-off-by: phosit <phosit@autistici.org>
2025-12-14 10:37:17 +01:00
real_tabasco_sauce
3cba40b5c8
buff new carthage unique mercenary slinger with increased crush damage and greater accuracy.
(cherry picked from commit e96d981319)
Signed-off-by: phosit <phosit@autistici.org>
2025-12-06 20:46:21 +01:00
cube002
2b85f5abf6
Fix carthage stone bonus
Add a civ restriction to make the bonus only apply to Carthage.

(cherry picked from commit 8d38ecda26)
(cherry picked from commit a03b01c935)
(cherry picked from commit f30271e955)
(cherry picked from commit 9c836d39e6)
(cherry picked from commit 91baeeb94e)
(cherry picked from commit cb3fecfce9)
Signed-off-by: phosit <phosit@autistici.org>
2025-12-06 20:37:01 +01:00
phosit
a6403f27d5
Update appdata for the next RC
(cherry picked from commit 759406dd77)
Signed-off-by: phosit <phosit@autistici.org>
2025-12-03 18:15:06 +01:00
Ralph Sennhauser
d90f4400ed
Fix autostart-host
Commit b90280855f added support for
multiplayer saved games changing the signature of StartNetworkHost
without updating all callers.

Fixes: #7684
Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
(cherry picked from commit 31a262ff7e)
Signed-off-by: phosit <phosit@autistici.org>
2025-12-03 18:15:05 +01:00
Dunedan
7575a04305
Add Vietnamese as supported language
As 0 A.D. supports full unicode now and Vietnamese language coverage is
at a good level, let's include Vietnamese as supported language.

(cherry picked from commit 0086f005d4)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-30 14:24:26 +01:00
Dunedan
3e8f296c72
Re-add Catalan as supported language
While Catalan got removed for Alpha 27 because of low coverage, its
coverage is now good enough again to get re-added as supported language.

(cherry picked from commit ed1bd1d75b)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-30 14:24:26 +01:00
real_tabasco_sauce
1087e020d1
Add capture animations for citizens
Fixes #8557

(cherry picked from commit a32a28a5e3)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-30 14:24:26 +01:00
Vantha
e961288e89
Correct some settings of the Germans' sandbox map
(cherry picked from commit 36e93989d4)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-30 14:24:26 +01:00
phosit
7ec2d3f0e0
Throw error when simulation script can't be loaded
When a script in "simulation/helpers/" contained an error. Files in
"simulation/components" aren't loaded. The return value of
`LoadDefaultScripts` indicated an error but was ignored. The simulation
still tried to start.

Now instead of returning a ignoreable error code the error is thrown. In
the common path the error is implicitly rethrown to the JS-function
which tried to start the game.

fixes: #8133
(cherry picked from commit 9a526bcae1)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-24 20:20:17 +01:00
phosit
97eca26d58
Don't pass the AppHooks as pointer
It's not permitted to pass a nullptr to the `app_hooks_update`. So a
reference should be used.

CppCheck says one shouldn't take pointer to a temporary.

(cherry picked from commit 977bf5c0d1)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-24 20:20:17 +01:00
phosit
2e4caf5d19
Use designatet initializers for AppHooks
CppCheck wasn't able to handle `{0}`. C++20 allows to use designated
initializers.

(cherry picked from commit b17c2fb80f)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-24 20:20:17 +01:00
Vantha
490434948d
Remove some invalid entries from messages.json
'StatusName', 'ApplierTooltip' and 'ReceiverTooltip' are attributes of status
effects, which are defined in JSON files (and already extracted
correctly from there), not XMLs.

(cherry picked from commit 44984699f1)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-19 20:28:48 +01:00
Vantha
6a55830f1f
Add context and comment attributes where useful
Add context and comment attributes to all translated XML elements in the
simulation that can specify any string -- unlike "Rank", which has to be
"Basic", "Advanced", or "Elite".
Most of them aren't used right now, but they can be in the
future and by mods, without touching the schemas again.

Fixes #8540

(cherry picked from commit 7032293207)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-19 20:28:48 +01:00
Ralph Sennhauser
bf314cbb4c
Add Atlas support to Appimage
Include the shared library libAtlasUI.

Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
(cherry picked from commit 5609492731)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-19 20:28:48 +01:00
phosit
d3406f4509
Extend appdata.xml for 0.28.0
(cherry picked from commit 354ed957dc)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-11 18:40:46 +01:00
joeybadz
adb6a05ae7
Remove duplicate fertility festival tech in German tech tree
(cherry picked from commit c6b8593bdf)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-11 18:16:35 +01:00
Vladislav Belov
e590a7cd4e
Replaces choosedDeviceIt by chosenDeviceIt
(cherry picked from commit c0ea17f06e)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-11 18:16:35 +01:00
Vladislav Belov
8420377789
Disables Vulkan devices sorting by default
Currently we always choose the best device. But it's not always
desirable. A more safe approach is to use the default device (with
index 0). The only downside of that is if a user didn't adjust
settings then the game might run on an integrated GPU instead of a
discrete one. In the future it'll be solved by selecting GPU in
options: #8529

Fixes #8455

(cherry picked from commit 485200342d)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-11 18:16:34 +01:00
obelix
fbc1b160e1
Change BuildTime of Gaul Arrow Ship
(cherry picked from commit 479995bc6f)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-11 18:16:34 +01:00
obelix
e07aba6d37
Change BuildTime of Brit Arrow Ship
(cherry picked from commit 90847e0591)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-11 18:16:34 +01:00
Vantha
2de2084b5b
Improve the SpecificName of Celtic civilians
While "Brogiacos" and "Tegesacos" fit in terms of meaning, they are only
reconstructed words, "Ambactos" on the other hand is attested and
actually historically relevant.

(cherry picked from commit 19f6dd031d)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-11 18:16:34 +01:00
Ralph Sennhauser
526deb30f0
Fix reloading config for cinema
This fixes 7df7566d7c, which added
automatic switching off silhouettes in cinema mode while resetting the
value when leaving cinema mode. Reloading can only be done for a given
config namespace.

Fixes: #7552
Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
(cherry picked from commit 32edc28cda)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-11 18:16:34 +01:00
Vladislav Belov
1e1db43854
Adds an option to destroy Vulkan old swapchain before
Now it's possible to destroy the old swapchain before creating a new
one. It might make the swapchain creation a bit slower but with a
lower memory peak.

(cherry picked from commit c4bc6c9627)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-10 20:15:31 +01:00
Vladislav Belov
b08f2d1d33
Waits Vulkan device idle also on window resize
Fixes the case when a swapchain was recreated on resize rather than
by VK_ERROR_OUT_OF_DATE_KHR.

(cherry picked from commit 8a64182ca2)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-10 20:15:31 +01:00
Vladislav Belov
d4736962ab
Deletes Vulkan resources on swapchain recreation
The change tries to minimize a memory peak during a window resizing.

Refs #6864

(cherry picked from commit de36c75023)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-10 20:15:31 +01:00
Vantha
68a7d8a03a
Provide context for the translation of "Germans"
(cherry picked from commit be83ba4029)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-10 20:15:31 +01:00
Vantha
c0d569162b
Improve the description of the Germans' civ bonus
Importantly, the word "Germans" is removed since it is prone to being
translated incorrectly and the other civ bonus descriptions don't
contain the civ's name either.

(cherry picked from commit 5d4eab73f9)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-10 20:15:31 +01:00
Vantha
6043ab248b
Add SpecificNames to the Germanic units
The names are in Proto-Germanic and mostly taken from Wiktionary.
They can be confirmed by directly searching the individual
Proto-Germanic terms online.

Champion Cavalry: "Aþalaridjô" (noble+rider)
Cavalry Spearman: "Gaizaridjô" (spear+rider)
Cavalry Javelineer: "Skeutaridjô" (quick+rider)
Worker: "Būraz" (dweller, farmer) -- deliberately decided against the most literal translation,
	which would be "Arbijaz", because that seems to be more connected to serfdom and the unit
	rather represents a generic commoner.
Infantry Swordsman: "Swerdamannaz" (sword+man)
Infantry Spearman: "Gaizamannaz" (spear+man)
Infantry Clubman: "Kulbawigô" (staff/club+warrior)
Infantry Javelineer: "Gaizawerpanaz" (spear/javelin+thrower)
Infantry Slinger: "Slingwanaz" (swinger/slinger)
Scout Ship: "Skeutabaitaz" (quick+boat)
Fishing Boat: "Fiskārijaz" (fisherman)
Fire Ship: "Brandabaitaz" (fire+boat)
Arrow Ship: "Harjaskipą" (army/war+ship)
Wagon: "Wagnaz" (direct translation)
Priest: "Gudjô" (direct translation)
Ram: "Rammabagmaz" (strong+tree/beam)
Trader: "Kaupô" (direct translation, also part of the word used for the market)
Merchant(ship): "Mangārī" (direct translation, very similar to "Kaupô")

(cherry picked from commit f38bc89611)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-10 20:15:31 +01:00
Vantha
6958a5edd0
Correct an overlooked 'Women' to 'Workers'
(cherry picked from commit 05b1ac4559)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-10 20:15:31 +01:00
Vantha
86bcb03f6e
Remove incorrect Germanic SpecificName
The SpecificName tag is meant to contain the name in the civ's native
language, Proto-Germanic for the Germans.
"Kriegsschiff", "Übungsbereich" and "Stadttor" on the other hand are
modern German words.

(cherry picked from commit a71688fc2c)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-10 20:15:31 +01:00
Vantha
f6a6c19132
Convert wrong Germanic SpecificNames to GenericNames
SpecificNames are meant to contain the names in the civ's native
language. The English names are supposed to in be the GenericName tag.

(cherry picked from commit 4d9fc0bb53)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-10 20:15:30 +01:00
Vladislav Belov
76337efe76
Fixes missing Vulkan application version
Missing after dc830ccf55.

(cherry picked from commit 8b1b1d28f8)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-10 20:15:30 +01:00
Stan
93fecf3720
Add credits for Obskurias
(cherry picked from commit 93706ae37c)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-10 20:15:30 +01:00
Vantha
df8b313a74
Add a sandbox map for the Germans
(cherry picked from commit 75feace618)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-05 14:20:35 +01:00
real_tabasco_sauce
e65e031344
adjust corsica vs sard
(cherry picked from commit 83dba854e5)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-05 14:20:35 +01:00
phosit
83832545ae
Add Boiorix as the codename for Release 28
(cherry picked from commit 9588da1d94)
Signed-off-by: phosit <phosit@autistici.org>
2025-11-02 21:54:37 +01:00
real_tabasco_sauce
0b7323c096
Fix market exploit by basing the price change on the amount purchased.
Fix credit to Atrik
Credit for test fix goes to Itms

Fixes #6760

(cherry picked from commit 94d3699ce4)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:50 +01:00
Ralph Sennhauser
d503ae6da6
Replace boost::filesystem std::filyestem
Bumping the minimum version of macOS to 10.15 for spidermonky [1] also
allows us to use std::filesystem instead of boosts implementation.

[1] f14a98e26f

Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
(cherry picked from commit eba8439295)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:50 +01:00
Ralph Sennhauser
48b9be5bb6
Require boost-1.69, drop boost_system lib
Boost 1.89 no longer offers the deprecated library for boost_system [1], so
drop it from the list of libraries to link against. This effectively
bumps the minimum required boost version to 1.69 [2].

[1] 7a495bb46d
[1] 2fa0a00583

Fixes: #8471
Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
(cherry picked from commit 618ffc7bf9)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:50 +01:00
Ralph Sennhauser
a7f6171063
Do not require literal message ids in Atlas
In >=wxWidgets-3.3 there is a new static check for literal message
ids[1] so that xgettext would reliable work to extract strings to
translate. As we don't translate Atlas at all nor use xgettext just
disable the check to allow building against >=wxWidgets-3.3.

[1] https://wxwidgets.org/help/msgid-literals/

Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
(cherry picked from commit e97f43b692)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:50 +01:00
phosit
8f4750db15
Remove the relaypoint before training units
While not as efficient this order is easier to reason and let's player
pause.

(cherry picked from commit 75805f4b23)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:50 +01:00
phosit
39a5a680d2
Rewrite the phrase about production availability
It's easier to understand and to translate in a language where a
formulation with "Respectively" is not common.

(cherry picked from commit e195c52e30)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:50 +01:00
phosit
61af0a0c26
Rewrite the phrase about building multiple houses
It was hard to understand.

(cherry picked from commit c3727a6a79)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:50 +01:00
phosit
53c806c0c4
Replace hunt by slaughter in phrase about chicken
It's not really hunting when nobody flees.
"Slaughter" is used later when talking about the same action.

(cherry picked from commit 727be2fb45)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:50 +01:00
phosit
b5bf9fd3e2
Replace civ by player in phrase about color
The color is not specivic to the civ but to the player.

(cherry picked from commit a6e4e22ca2)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:50 +01:00
phosit
7a72578517
Don't hardcode Shift as a hotkey in tutorial
It's not possible to format warnings. "a hotkey" is used instead.

Also when the hoplite icon is pressed, without using batches, the
warning doesn't restate that the hopplite should be pressed.

(cherry picked from commit 29ac569511)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:49 +01:00
phosit
1db46eaf9b
Replace "I" with the hotkey in eco walkthrough
(cherry picked from commit 4f38600c39)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:49 +01:00
phosit
819a875fcc
Only make existing Civilians invulnerable
On "Survival of the Fittest" the treasure-collector are made
invulnerable.
Thous Civilian might not exist when the player is removed.

Fixes: #8421
(cherry picked from commit e0481b283b)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:49 +01:00
Itms
1b50d731fc
Store NSIS registry keys under a consistent root
Reviewed-At: https://gitea.wildfiregames.com/0ad/0ad/pulls/8476
(cherry picked from commit 4716a230ab)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:49 +01:00
Itms
621aa9d7a9
Wipe NSIS install preferences when uninstalling
The user language and start menu folder name were saved, which goes
against recommendations in the NSIS documentation.

The installation directory was also saved, which might make sense,
but prevents us from dropping the "alpha" label.

Reviewed-At: https://gitea.wildfiregames.com/0ad/0ad/pulls/8476
Fixes: #7594
(cherry picked from commit 18df61517c)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:49 +01:00
Itms
6a6712799c
Fix install and Start Menu folder names on Windows
Those cannot end with a period.

Reviewed-At: https://gitea.wildfiregames.com/0ad/0ad/pulls/8476
(cherry picked from commit f772181501)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:49 +01:00
Itms
a7f0678dad
Add an engine "compatible" version
When a patch version is released, it must declare compatibility with the
previous patch versions of the same main release. This allows players to
keep replaying their games and to keep playing online with users of
other patches of the same main release.

This should have anticipated for dae7a8c394

(cherry picked from commit 866d6f0527)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:49 +01:00
Itms
4fca5ed21c
Use the PYROGENESIS_VERSION macro instead of a global
Reviewed-At: https://gitea.wildfiregames.com/0ad/0ad/pulls/8222
(cherry picked from commit 50f6da2a13)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:49 +01:00
Itms
abc83a7dfb
Address cppcheck uninitialized warning
Reviewed-At: https://gitea.wildfiregames.com/0ad/0ad/pulls/8222
(cherry picked from commit f0c8db6422)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-31 13:43:48 +01:00
Vladislav Belov
52e6d08e79
Fixes lseek for big files on Windows
It was broken in ef69c37f66, before that we were using _lseeki64.

Fixes #8459

(cherry picked from commit cb58116270)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-26 15:06:35 +01:00
Vantha
46e9585bce
PetraBot: Never play when the region analysis fails
If the region analysis at the start of the game fails, the bot can't
actually play and the managers aren't initialised. And to prevent errors
from the update functions, the OnUpdate at the root had an early return
if the entity count was 0. However, in some edge cases the region
analysis can fail even if the AI has entities.
This patch fixes this potential error by storing the result of the
region analysis directly and checking that instead.

(cherry picked from commit 7b1d4426aa)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-26 15:05:49 +01:00
Itms
8d05176032
Lock Linux CI cbindgen version and dependencies
This allows us to keep testing building with the minimal supported
Rust version.

(cherry picked from commit 59d28fed9b)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-26 15:03:08 +01:00
abian
41dac8bb20
Hide Abort Unit Order button when idle or guarding
Reviewed-By: bb
Fixes #6854

(cherry picked from commit 95467c2327)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-26 15:02:34 +01:00
Timothy Pearson
9dee4e4617
Fix FTBFS on ppc64le systems
Tested to compile and function normally under Debian Trixie ppc64le / POWER9

Signed-off-by: Timothy Pearson <tpearson@raptorcs.com>
(cherry picked from commit 2c9928e4cb)
Signed-off-by: phosit <phosit@autistici.org>
2025-10-26 15:00:27 +01:00
Ralph Sennhauser
981b3b898e
Support running individual tests or suites
Add back some functionality that got dropped with the move to a custom
runner in 39ea3b6ea5

Add option --list to print all available test grouped by suite.

Add option --suite to limit the run to a specific testsuite.

Add option --test to limit the run to a specific test.

Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
(cherry picked from commit a7d65d4a34)
2025-10-17 13:31:20 +02:00
phosit
d3239591b8
Bump copyright year for windows build 2025-10-15 17:58:23 +02:00
198 changed files with 22492 additions and 448 deletions

View file

@ -138,6 +138,10 @@ renderer.backend.gl.enableframebufferinvalidating = false
renderer.backend.vulkan.disabledescriptorindexing = false
renderer.backend.vulkan.deviceindexoverride = -1
renderer.backend.vulkan.destroyoldswapchainbefore = false
; In case index override isn't enough we might choose a device automatically.
renderer.backend.vulkan.choosebestdevice = false
renderer.backend.vulkan.debugbarrierafterframebufferpass = false
renderer.backend.vulkan.debugwaitidlebeforeacquire = false
@ -212,7 +216,7 @@ togglefullscreen = "Alt+Return" ; Toggle fullscreen/windowed mode
screenshot.watermark = "Alt+K" ; Toggle product/company watermark for official screenshots
wireframe = "Alt+Shift+W" ; Toggle wireframe mode
silhouettes = "Alt+Shift+S" ; Toggle unit silhouettes
mousegrabtoggle = "Ctrl+Alt" ; Toggle mouse grabbing mode
mousegrabtoggle = F3 ; Toggle mouse grabbing mode
; > DIALOG HOTKEYS
summary = "Ctrl+Tab" ; Toggle in-game summary
@ -248,7 +252,7 @@ reset = "R" ; Reset camera rotation to default
follow = "" ; Follow the first unit in the selection
rallypointfocus = "" ; Focus the camera on the rally point of the selected building
lastattackfocus = "Space" ; Focus the camera on the last notified attack
togglebirdseyeview = "" ; Toggle bird's eye view
togglebirdseyeview = "Shift+Tab" ; Toggle bird's eye view
zoom.in = Plus, NumPlus ; Zoom camera in (continuous control)
zoom.out = Minus, NumMinus ; Zoom camera out (continuous control)
zoom.wheel.in = WheelUp ; Zoom camera in (stepped control)
@ -388,7 +392,7 @@ flareactivate = "" ; Modifier to activate the mode to send a flare to
calltoarms = "" ; Modifier to call the selected units to the arms.
focusfire = "F" ; Modifier to control exclusively a building's arrows if it can attack
; Overlays
showstatusbars = Tab ; Toggle display of status bars
showstatusbars = "" ; Toggle display of status bars
devcommands.toggle = "Alt+D" ; Toggle developer commands panel
highlightguarding = PageDown ; Toggle highlight of guarding units
highlightguarded = PageUp ; Toggle highlight of guarded units

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant file="others/waypoints/base.xml" frequency="1" name="German Waypoint Flag">
<variant file="others/waypoints/base.xml" frequency="1" name="Germanic Waypoint Flag">
<textures>
<texture file="props/banner_germans.png" name="baseTex"/>
<texture file="default_norm.png" name="normTex"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Longboat">
<variant frequency="1" name="Germanic Longboat">
<mesh>props/germ_boat_head.dae</mesh>
<textures>
<texture file="structural/germ_boat.png" name="baseTex"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Longboat">
<variant frequency="1" name="Germanic Longboat">
<mesh>props/germ_boat_props.dae</mesh>
<textures>
<texture file="structural/germ_boat.png" name="baseTex"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant name="German Karvi sail">
<variant name="Germanic Karvi sail">
<mesh>props/germ_karvi_sail.dae</mesh>
<animations>
<animation file="other/germ_sail_idle.dae" name="idle" speed="50"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German fishing boat prop">
<variant frequency="1" name="Germanic fishing boat prop">
<mesh>props/germ_dock_boat.dae</mesh>
<textures>
<texture file="structural/germ_fishing_boat.png" name="baseTex"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Karvi">
<variant frequency="1" name="Germanic Karvi">
<mesh>props/germ_karvi_props.dae</mesh>
<textures>
<texture file="structural/germ_snekkja.png" name="baseTex"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Karvi sail">
<variant frequency="1" name="Germanic Karvi sail">
<mesh>props/germ_karvi_sail.dae</mesh>
<animations>
<animation file="other/germ_sail_idle.dae" name="idle" speed="50"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Knarr Props">
<variant frequency="1" name="Germanic Knarr Props">
<mesh>props/germ_knarr_props.dae</mesh>
<textures>
<texture file="structural/germ_snekkja.png" name="baseTex"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Longboat">
<variant frequency="1" name="Germanic Longboat">
<mesh>props/germ_snekkja_head.dae</mesh>
<textures>
<texture file="structural/germ_snekkja.png" name="baseTex"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Longboat">
<variant frequency="1" name="Germanic Longboat">
<mesh>props/germ_snekkja_props.dae</mesh>
<textures>
<texture file="structural/germ_snekkja.png" name="baseTex"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant name="German Snekkja Sail">
<variant name="Germanic Snekkja Sail">
<mesh>props/germ_snekkja_sail.dae</mesh>
<animations>
<animation file="other/germ_sail_idle.dae" name="idle" speed="50"/>

View file

@ -2,7 +2,7 @@
<actor version="1">
<castshadow/>
<group>
<variant name="German wagon_unyoked">
<variant name="Germanic wagon_unyoked">
<mesh>props/germ_wagon_cc.dae</mesh>
<textures>
<texture file="structural/germ_struct.png" name="baseTex"/>

View file

@ -2,7 +2,7 @@
<actor version="1">
<castshadow/>
<group>
<variant name="German wagon_unyoked">
<variant name="Germanic wagon_unyoked">
<mesh>props/germ_wagon_cc.dae</mesh>
<textures>
<texture file="structural/germ_struct.png" name="baseTex"/>

View file

@ -2,7 +2,7 @@
<actor version="1">
<castshadow/>
<group>
<variant name="German wagon_unyoked">
<variant name="Germanic wagon_unyoked">
<mesh>props/germ_wagon_cc.dae</mesh>
<textures>
<texture file="structural/germ_struct.png" name="baseTex"/>

View file

@ -2,7 +2,7 @@
<actor version="1">
<castshadow/>
<group>
<variant name="German wagon_unyoked">
<variant name="Germanic wagon_unyoked">
<mesh>props/germ_wagon_cc.dae</mesh>
<textures>
<texture file="structural/germ_struct.png" name="baseTex"/>

View file

@ -2,7 +2,7 @@
<actor version="1">
<castshadow/>
<group>
<variant name="German wagon_unyoked">
<variant name="Germanic wagon_unyoked">
<mesh>props/germ_wagon_cc.dae</mesh>
<textures>
<texture file="structural/germ_struct.png" name="baseTex"/>

View file

@ -2,7 +2,7 @@
<actor version="1">
<castshadow/>
<group>
<variant name="German wagon_unyoked">
<variant name="Germanic wagon_unyoked">
<mesh>props/germ_wagon_cc.dae</mesh>
<textures>
<texture file="structural/germ_struct.png" name="baseTex"/>

View file

@ -2,7 +2,7 @@
<actor version="1">
<castshadow/>
<group>
<variant name="German Blacksmith">
<variant name="Germanic Blacksmith">
<mesh>structural/germans/blacksmith.dae</mesh>
<props>
<prop actor="props/structures/decals/dirt_4x4.xml" attachpoint="root"/>

View file

@ -2,7 +2,7 @@
<actor version="1">
<castshadow/>
<group>
<variant frequency="1" name="German Civic Center" file="structures/defensive_building.xml">
<variant frequency="1" name="Germanic Civic Center" file="structures/defensive_building.xml">
<mesh>structural/germans/cc.dae</mesh>
<props>
<prop actor="props/structures/decals/spart_5x5.xml" attachpoint="root"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="100" name="German fishing boat">
<variant frequency="100" name="Germanic fishing boat">
<mesh>structural/germans/fishing_boat.dae</mesh>
<props>
<prop actor="units/germans/fisherman.xml" attachpoint="fisherman"/>

View file

@ -2,7 +2,7 @@
<actor version="1">
<castshadow/>
<group>
<variant frequency="1" name="German House A">
<variant frequency="1" name="Germanic House A">
<mesh>structural/germans/house_a.dae</mesh>
<textures>
<texture file="structural/germ_struct_03.png" name="baseTex"/>
@ -38,7 +38,7 @@
<prop actor="props/special/eyecandy/sack_1.xml" attachpoint="sack_2"/>
</props>
</variant>
<variant frequency="1" name="German House A 2">
<variant frequency="1" name="Germanic House A 2">
<mesh>structural/germans/house_a_2.dae</mesh>
<textures>
<texture file="structural/germ_struct.png" name="baseTex"/>
@ -74,7 +74,7 @@
<prop actor="props/special/eyecandy/sack_1.xml" attachpoint="sack_2"/>
</props>
</variant>
<variant frequency="1" name="German House B">
<variant frequency="1" name="Germanic House B">
<mesh>structural/germans/house_b.dae</mesh>
<textures>
<texture file="structural/germ_struct_03.png" name="baseTex"/>
@ -105,7 +105,7 @@
<prop actor="particle/smoke_blacksmith.xml" attachpoint="smoke"/>
</props>
</variant>
<variant frequency="1" name="German House C">
<variant frequency="1" name="Germanic House C">
<mesh>structural/germans/house_c.dae</mesh>
<textures>
<texture file="structural/germ_struct_03.png" name="baseTex"/>

View file

@ -2,7 +2,7 @@
<actor version="1">
<castshadow/>
<group>
<variant frequency="1" name="German Sentry Tower" file="structures/defensive_building.xml">
<variant frequency="1" name="Germanic Sentry Tower" file="structures/defensive_building.xml">
<mesh>structural/germans/wood_tower.dae</mesh>
<props>
<prop actor="props/structures/decals/dirt_1x1.xml" attachpoint="root"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Longboat">
<variant frequency="1" name="Germanic Longboat">
<mesh>structural/germans/ship_arrow.dae</mesh>
<props>
<prop actor="props/structures/germans/boat_props.xml" attachpoint="mast"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Longboat">
<variant frequency="1" name="Germanic Longboat">
<mesh>structural/germans/ship_karvi.dae</mesh>
<props>
<prop actor="props/units/weapons/bolt_tower.xml" attachpoint="projectile"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Merchant Ship">
<variant frequency="1" name="Germanic Merchant Ship">
<mesh>structural/germans/ship_knarr.dae</mesh>
<props>
<prop actor="props/structures/germans/knarr_props.xml" attachpoint="root"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Longboat">
<variant frequency="1" name="Germanic Longboat">
<mesh>structural/germans/ship_scout.dae</mesh>
<props>
<prop actor="props/units/weapons/bolt_tower.xml" attachpoint="projectile"/>

View file

@ -3,7 +3,7 @@
<castshadow/>
<float/>
<group>
<variant frequency="1" name="German Longboat">
<variant frequency="1" name="Germanic Longboat">
<mesh>structural/germans/ship_snekkja.dae</mesh>
<props>
<prop actor="props/units/weapons/bolt_tower.xml" attachpoint="projectile"/>

View file

@ -2,7 +2,7 @@
<actor version="1">
<castshadow/>
<group>
<variant name="German Wall Tower" file="structures/defensive_building.xml">
<variant name="Germanic Wall Tower" file="structures/defensive_building.xml">
<mesh>structural/germans/wooden_wall_tower.dae</mesh>
<textures>
<texture file="structural/germ_struct_03.png" name="baseTex"/>

View file

@ -32,6 +32,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -32,6 +32,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/gather_tree.xml"/>

View file

@ -48,6 +48,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -48,6 +48,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/attack_capture.xml"/>

View file

@ -32,6 +32,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -68,6 +68,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/attack_capture.xml"/>

View file

@ -63,6 +63,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -48,6 +48,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/gather_tree.xml"/>

View file

@ -73,6 +73,7 @@
</group>
<group>
<variant name="Idle" frequency="1"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -75,6 +75,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/attack_capture.xml"/>

View file

@ -36,6 +36,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -36,6 +36,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/attack_capture.xml"/>

View file

@ -32,6 +32,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -17,6 +17,7 @@
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/gather_tree.xml"/>

View file

@ -54,6 +54,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -58,6 +58,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/gather_tree.xml"/>

View file

@ -139,6 +139,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -79,6 +79,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/gather_tree.xml"/>

View file

@ -51,6 +51,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -97,6 +97,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/attack_capture.xml"/>

View file

@ -54,6 +54,7 @@
</group>
<group>
<variant name="Idle" frequency="1"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -77,6 +77,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/gather_tree.xml"/>

View file

@ -35,6 +35,7 @@
<group>
<!-- In this group, define overloads for other animation types, since they presumably do not collide with each other -->
<variant name="Idle" frequency="1"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -32,6 +32,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/gather_tree.xml"/>

View file

@ -40,6 +40,7 @@
<group>
<!-- In this group, define overloads for other animation types, since they presumably do not collide with each other -->
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -32,6 +32,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/gather_tree.xml"/>

View file

@ -45,6 +45,7 @@
<group>
<!-- In this group, define overloads for other animation types, since they presumably do not collide with each other -->
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -75,6 +75,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/attack_capture.xml"/>

View file

@ -78,6 +78,7 @@
<group>
<!-- In this group, define overloads for other animation types, since they presumably do not collide with each other -->
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/female_death.xml"/>

View file

@ -48,6 +48,7 @@
</group>
<group>
<variant frequency="1" name="Idle"/>
<variant file="biped/attack_capture.xml"/>
<variant file="biped/attack_melee_female.xml"/>
<variant file="biped/attack_slaughter.xml"/>
<variant file="biped/gather_tree.xml"/>

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ba424950305b85425bcd63d601bc3e49b8546e5d34ffc96c57b23b2b7cbce95a
size 112876
oid sha256:6e79ff8aed597b9c97eb7a1aeccdcc6a0a62aac4fe3ac3f5708a6dc210fba18c
size 124346

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e0d32bf35b91ce84c6567cd6c925ec61e47f247b4a7713dcbe6e9cccc4a68fd2
size 271942

View file

@ -14,7 +14,7 @@ class AutoStartHost
const port = +(cmdLineArgs['autostart-port'] ?? 5073);
// Password not implemented for autostart.
Engine.StartNetworkHost(playerName, port, "", !('autostart-disable-replay' in cmdLineArgs));
Engine.StartNetworkHost(playerName, port, "", false, !('autostart-disable-replay' in cmdLineArgs));
}
catch (e)
{

View file

@ -66,11 +66,20 @@ function parseCmdLineArgs(settings, cmdLineArgs)
{
// eslint-disable-next-line dot-notation
const mapType = cmdLineArgs['autostart'].substring(0, cmdLineArgs['autostart'].indexOf('/'));
settings.map.setType({
"scenarios": "scenario",
"random": "random",
"skirmishes": "skirmish",
}[mapType]);
switch (mapType)
{
case "random":
settings.map.setType("random");
break;
case "scenarios":
settings.map.setType("scenario");
break;
case "skirmishes":
settings.map.setType("skirmish");
break;
default:
throw new Error(`Unknown map type ${mapType}`);
}
// eslint-disable-next-line dot-notation
settings.map.selectMap("maps/" + cmdLineArgs['autostart']);

View file

@ -44,6 +44,7 @@
{ "name": "Micha L. Rieser" },
{ "nick": "Nescio" },
{ "nick": "nifa" },
{ "nick": "Obskurias", "name": "Alejandro Liaño" },
{ "name": "Paul Maritz" },
{ "nick": "pedro_blanco", "name": "Pedro Blanco" },
{ "name": "Pete Unseth" },

View file

@ -146,6 +146,7 @@
{ "nick": "javiergodas", "name": "Javier Godas Vieitez" },
{ "nick": "JCWasmx86" },
{ "nick": "Jgwman" },
{ "nick": "joeybadz", "name": "Joe Badlato" },
{ "nick": "JonBaer", "name": "Jon Baer" },
{ "nick": "Josh", "name": "Joshua J. Bakita" },
{ "nick": "joskar", "name": "Johnny Oskarsson" },

View file

@ -8,7 +8,5 @@
<translatableAttribute id="caption">Saved game</translatableAttribute>
<translatableAttribute id="tooltip">
The controller loaded a saved game.
</translatableAttribute>
<translatableAttribute id="tooltip">The controller loaded a saved game.</translatableAttribute>
</object>

View file

@ -24,7 +24,8 @@ class PersistentMatchSettings
Engine.FileExists(this.filename) &&
Engine.ReadJSONFile(this.filename);
const persistedSettings = data?.engine_info?.engine_version == this.engineInfo.engine_version &&
const persistedSettings = data?.engine_info?.engine_serialization_version &&
data.engine_info.engine_serialization_version == this.engineInfo.engine_serialization_version &&
hasSameMods(data?.engine_info?.mods, this.engineInfo.mods) &&
data.attributes || {};

View file

@ -174,8 +174,8 @@ class SavegameList
isCompatibleSavegame(metadata, engineInfo)
{
return engineInfo &&
metadata.engine_version &&
metadata.engine_version == engineInfo.engine_version &&
metadata.engine_serialization_version &&
metadata.engine_serialization_version == engineInfo.engine_serialization_version &&
hasSameMods(metadata.mods, engineInfo.mods);
}

View file

@ -24,9 +24,9 @@ class SavegameLoader
// Check compatibility before really loading it
const engineInfo = Engine.GetEngineInfo();
const sameMods = hasSameMods(metadata.mods, engineInfo.mods);
const sameEngineVersion = metadata.engine_version && metadata.engine_version == engineInfo.engine_version;
const compatibleEngineVersions = metadata.engine_serialization_version && metadata.engine_serialization_version == engineInfo.engine_serialization_version;
if (sameEngineVersion && sameMods)
if (compatibleEngineVersions && sameMods)
{
this.closePageCallback(gameId);
return;
@ -35,14 +35,17 @@ class SavegameLoader
// Version not compatible ... ask for confirmation
let message = "";
if (!sameEngineVersion)
if (metadata.engine_version)
message += sprintf(translate("This savegame needs 0 A.D. version %(requiredVersion)s, while you are running version %(currentVersion)s."), {
"requiredVersion": metadata.engine_version,
"currentVersion": engineInfo.engine_version
if (!compatibleEngineVersions)
{
if (metadata.engine_serialization_version)
message += sprintf(translate("This savegame needs 0 A.D. version %(requiredCompatibleVersion)s or compatible. You are running version %(currentVersion)s, compatible down to %(compatibleVersion)s."), {
"requiredCompatibleVersion": metadata.engine_serialization_version,
"currentVersion": engineInfo.engine_version,
"compatibleVersion": engineInfo.engine_serialization_version,
}) + "\n";
else
message += translate("This savegame needs an older version of 0 A.D.") + "\n";
}
if (!sameMods)
{

View file

@ -15,7 +15,7 @@ export const projectInformation = {
"caption": getBuildString()
},
"productDescription": {
"caption": setStringTags(translate("Release XXVIII: B——"), { "font": "sans-bold-16" }) + "\n\n" +
"caption": setStringTags(translate("Release XXVIII: Boiorix"), { "font": "sans-bold-16" }) + "\n\n" +
translate("Notice: This game is under development and many features have not been added yet.")
}
};

View file

@ -42,4 +42,6 @@ async function cancelButton()
await new Promise(resolve => { Engine.GetGUIObjectByName("cancel").onPress = resolve; });
if (Engine.HasXmppClient())
Engine.StopXmppClient();
return false;
}

View file

@ -13,7 +13,8 @@ function loginButton()
Engine.OpenChildPage("page_prelobby_login.xml");
}
function registerButton()
async function registerButton()
{
Engine.OpenChildPage("page_prelobby_register.xml");
if (await Engine.OpenChildPage("page_prelobby_register.xml"))
Engine.OpenChildPage("page_prelobby_login.xml");
}

View file

@ -40,6 +40,5 @@ async function onRegistered()
setFeedback(translate("Registered"));
Engine.StopXmppClient();
Engine.OpenChildPage("page_prelobby_login.xml");
return true;
}

View file

@ -1,7 +1,8 @@
/**
* Override style so we can get a bigger primary name.
*/
g_TooltipTextFormats.namePrimaryBig.font = "sans-bold-20";
// Temporarily overwritten in order to hide a baseline issue in the font engine.
g_TooltipTextFormats.namePrimaryBig.font = /* "sans-bold-20" */ "sans-bold-16";
g_TooltipTextFormats.namePrimarySmall.font = "sans-bold-16";
g_TooltipTextFormats.nameSecondary.font = "sans-bold-16";

View file

@ -84,7 +84,7 @@ function reallyStartVisualReplay(replayDirectory)
function displayReplayCompatibilityError(replay)
{
var errMsg;
if (replayHasSameEngineVersion(replay))
if (replayHasCompatibleEngineVersion(replay))
{
const gameMods = replay.attribs.mods || [];
errMsg = translate("This replay needs a different sequence of mods:") + "\n" +
@ -93,8 +93,9 @@ function displayReplayCompatibilityError(replay)
else
{
errMsg = translate("This replay is not compatible with your version of the game!") + "\n";
errMsg += sprintf(translate("Your version: %(version)s"), { "version": g_EngineInfo.engine_version }) + "\n";
errMsg += sprintf(translate("Required version: %(version)s"), { "version": replay.attribs.engine_version });
errMsg += sprintf(translate("Your version: %(version)s, compatible down to %(compatibleVersion)s"), { "version": g_EngineInfo.engine_version, "compatibleVersion": g_EngineInfo.engine_serialization_version }) + "\n";
if (replay.attribs.engine_serialization_version)
errMsg += sprintf(translate("Replay version: %(version)s"), { "version": replay.attribs.engine_serialization_version });
}
messageBox(500, 200, errMsg, translate("Incompatible replay"));

View file

@ -360,13 +360,13 @@ function getReplayDuration(replay)
*/
function isReplayCompatible(replay)
{
return replayHasSameEngineVersion(replay) && hasSameMods(replay.attribs.mods, g_EngineInfo.mods);
return replayHasCompatibleEngineVersion(replay) && hasSameMods(replay.attribs.mods, g_EngineInfo.mods);
}
/**
* True if we can start the given replay with the currently loaded mods.
*/
function replayHasSameEngineVersion(replay)
function replayHasCompatibleEngineVersion(replay)
{
return replay.attribs.engine_version && replay.attribs.engine_version == g_EngineInfo.engine_version;
return replay.attribs.engine_serialization_version && replay.attribs.engine_serialization_version == g_EngineInfo.engine_serialization_version;
}

View file

@ -705,7 +705,7 @@ function updateCinemaPath()
{
// TODO: Keyboard shortcuts can still try to toggle silhouettes
// which would behave incorrectly on reset.
Engine.ConfigDB_Reload();
Engine.ConfigDB_Reload("user");
g_HasHiddenSilhouettes = false;
}
}

View file

@ -3,7 +3,7 @@
<!-- IMPORTANT: remember to update pregame/ProjectInformation.js in sync with this: -->
<object type="text" style="ModernLabelText" text_valign="top" ghost="true" size="0% 1 100% 100%">
<translatableAttribute id="caption">Release XXVIII: B——</translatableAttribute>
<translatableAttribute id="caption">Release XXVIII: Boiorix</translatableAttribute>
</object>
<!-- Displays build date and build version-->

View file

@ -1550,7 +1550,8 @@ var g_EntityCommands =
"stop": {
"getInfo": function(entStates)
{
if (entStates.every(entState => !entState.unitAI))
// Don't show generic option to abort if not applicable or in case of guard, which has its own abort action
if (entStates.every(entState => !entState.unitAI || entState.unitAI.isIdle || entState.unitAI.isGuarding))
return false;
return {

View file

@ -23,25 +23,19 @@
<object>
<object name="icon1" type="image" sprite="stretched:pregame/icons/experimental.png"/>
<object name="text1" type="text" textcolor="white" font="sans-16">
<translatableAttribute id="caption">
This game is still in development. You may encounter bugs, and some features are not as fleshed out as we would like.
</translatableAttribute>
<translatableAttribute id="caption">This game is still in development. You may encounter bugs, and some features are not as fleshed out as we would like.</translatableAttribute>
</object>
</object>
<object>
<object name="icon2" type="image" sprite="stretched:pregame/icons/lag.png"/>
<object name="text2" type="text" textcolor="white" font="sans-16">
<translatableAttribute id="caption">
The game can have performance problems, especially with large maps and a great number of units.
</translatableAttribute>
<translatableAttribute id="caption">The game can have performance problems, especially with large maps and a great number of units.</translatableAttribute>
</object>
</object>
<object>
<object name="icon3" type="image" sprite="stretched:pregame/icons/map.png"/>
<object name="text3" type="text" textcolor="white" font="sans-16">
<translatableAttribute id="caption">
0 A.D. is Free Software: you can participate in its development. If you want to help with art, sound, gameplay or programming, make sure to join our official forum.
</translatableAttribute>
<translatableAttribute id="caption">0 A.D. is Free Software: you can participate in its development. If you want to help with art, sound, gameplay or programming, make sure to join our official forum.</translatableAttribute>
</object>
</object>
</object>

View file

@ -265,8 +265,8 @@ function initGUICharts()
function resizeDropdown(dropdown)
{
dropdown.size.bottom = dropdown.size.top +
(Engine.GetTextWidth(dropdown.font, dropdown.list[dropdown.selected]) >
dropdown.size.right - dropdown.size.left - 28 &&
(dropdown.getPreferredHeaderTextSize().width >
dropdown.size.right - dropdown.size.left - dropdown.button_width &&
dropdown.list[dropdown.selected].indexOf(" ") !== -1 ? 42 : 28);
}

View file

@ -480,15 +480,6 @@
"AttackName": {
"customContext": "Name of an attack, usually the weapon."
},
"StatusName": {
"customContext": "status effect"
},
"ApplierTooltip": {
"customContext": "status effect"
},
"ReceiverTooltip": {
"customContext": "status effect"
},
"GenericName": {},
"SpecificName": {},
"History": {},
@ -523,15 +514,6 @@
"AttackName": {
"customContext": "Name of an attack, usually the weapon."
},
"StatusName": {
"customContext": "status effect"
},
"ApplierTooltip": {
"customContext": "status effect"
},
"ReceiverTooltip": {
"customContext": "status effect"
},
"GenericName": {},
"SpecificName": {},
"History": {},
@ -774,6 +756,32 @@
}
}
},
{
"extractor": "json",
"filemasks": [
"simulation/data/settings/player_placements.json"
],
"options": {
"keywords": {
"Name": {},
"Description": {}
}
}
},
{
"extractor": "json",
"filemasks": [
"simulation/data/settings/population_capacities.json"
],
"options": {
"keywords": {
"Title": {},
"Tooltip": {},
"CapTitle": {},
"CapTooltip": {}
}
}
},
{
"extractor": "json",
"filemasks": [

View file

@ -30,7 +30,7 @@ export function* generateMap()
const ePine = "gaia/tree/aleppo_pine";
const ePalmTall = "gaia/tree/cretan_date_palm_tall";
const eFanPalm = "gaia/tree/medit_fan_palm";
const eApple = "gaia/fruit/apple";
const eCypress = "gaia/tree/cypress";
const eBush = "gaia/fruit/berry_01";
const eFish = "gaia/fish/generic";
const ePig = "gaia/fauna_pig";
@ -68,6 +68,7 @@ export function* generateMap()
const clCreek = g_Map.createTileClass();
const clWater = g_Map.createTileClass();
const clCliffs = g_Map.createTileClass();
const clFish = g_Map.createTileClass();
const clForest = g_Map.createTileClass();
const clShore = g_Map.createTileClass();
const clPlayer = g_Map.createTileClass();
@ -75,19 +76,19 @@ export function* generateMap()
const clPassage = g_Map.createTileClass();
const clSettlement = g_Map.createTileClass();
const radiusBeach = fractionToTiles(0.57);
const radiusCreeks = fractionToTiles(0.52);
const radiusIsland = fractionToTiles(0.4);
const radiusLevel1 = fractionToTiles(0.35);
const radiusPlayer = fractionToTiles(0.25);
const radiusLevel2 = fractionToTiles(0.2);
const radiusBeach = fractionToTiles(0.65);
const radiusCreeks = fractionToTiles(0.60);
const radiusIsland = fractionToTiles(0.46);
const radiusLevel1 = fractionToTiles(0.40);
const radiusPlayer = fractionToTiles(0.29);
const radiusLevel2 = fractionToTiles(0.20);
const creeksArea = () => randBool() ? randFloat(10, 50) : scaleByMapSize(75, 100) + randFloat(0, 20);
const nbCreeks = scaleByMapSize(6, 15);
const nbCreeks = scaleByMapSize(7, 9);
const nbSubIsland = 5;
const nbBeaches = scaleByMapSize(2, 5);
const nbPassagesLevel1 = scaleByMapSize(4, 8);
const nbBeaches = scaleByMapSize(6, 10);
const nbPassagesLevel1 = scaleByMapSize(6, 8);
const nbPassagesLevel2 = scaleByMapSize(2, 4);
g_Map.log("Creating Corsica and Sardinia");
@ -183,9 +184,9 @@ export function* generateMap()
new Vector2D(radiusLevel1 + 10, 0).rotate(-angle)),
"end": Vector2D.add(islandLocations[island],
new Vector2D(radiusLevel1 - 4, 0).rotate(-angle)),
"startWidth": 10,
"endWidth": 6,
"smoothWidth": 3,
"startWidth": 20,
"endWidth": 20,
"smoothWidth": 2,
"tileClass": clPassage
});
}
@ -212,8 +213,8 @@ export function* generateMap()
new Vector2D(radiusLevel2 + 3, 0).rotate(-angle)),
"end": Vector2D.add(islandLocations[island],
new Vector2D(radiusLevel2 - 6, 0).rotate(-angle)),
"startWidth": 4,
"endWidth": 6,
"startWidth": 20,
"endWidth": 20,
"smoothWidth": 2,
"tileClass": clPassage
});
@ -409,7 +410,7 @@ export function* generateMap()
new SimpleObject(ePine, 3, 6, 1, 3),
new SimpleObject(ePalmTall, 1, 3, 1, 3),
new SimpleObject(eFanPalm, 0, 2, 0, 2),
new SimpleObject(eApple, 0, 1, 1, 2)
new SimpleObject(eCypress, 0, 1, 1, 2)
],
true,
clForest),
@ -515,36 +516,34 @@ export function* generateMap()
50);
g_Map.log("Creating fish");
createObjectGroupsDeprecated(
new SimpleGroup([new SimpleObject(eFish, 1, 2, 0, 3)]),
0,
[
stayClasses(clWater, 3),
avoidClasses(clCreek, 3, clShore, 3)
],
scaleByMapSize(100, 150),
300);
createFood(
[
[new SimpleObject(eFish, 2, 3, 0, 2)]
],
[
50 * numPlayers
],
[
avoidClasses(clCreek, 2, clShore, 3, clFish, 8),
stayClasses(clWater, 3)
],
clFish);
g_Map.log("Creating shore fish");
createObjectGroupsDeprecated(
new SimpleGroup([new SimpleObject(eFish, 1, 2, 0, 3)]),
0,
[
stayClasses(clCreek, 1),
],
scaleByMapSize(200, 300),
500);
g_Map.log("Creating shore fish");
createObjectGroupsDeprecated(
new SimpleGroup([new SimpleObject(eFish, 1, 2, 0, 3)]),
0,
createFood(
[
stayClasses(clShore, 3)
[new SimpleObject(eFish, 2, 3, 0, 2)]
],
scaleByMapSize(200, 300),
500);
[
70 * numPlayers
],
[
avoidClasses(clFish, 6),
stayClasses(clWater, 3, clShore, 0)
],
clFish);
yield 95;

View file

@ -136,7 +136,7 @@ export function* generateMap(mapSettings)
const playerIDs = randBool() ? sortAllPlayers() : primeSortAllPlayers();
g_Map.log("Ensuring player territory");
const playerRadius = scaleByMapSize(12, 20);
const playerRadius = scaleByMapSize(15, 20);
for (let i = 0; i < numPlayers; ++i)
createArea(
new ChainPlacer(1, 6, 40, 1, playerPosition[i], 0, [Math.floor(playerRadius)]),

View file

@ -149,7 +149,11 @@ Trigger.prototype.InitStartingUnits = function()
{
this.playerCivicCenter[playerID] = TriggerHelper.GetPlayerEntitiesByClass(playerID, "CivilCentre")[0];
this.treasureCivilian[playerID] = TriggerHelper.GetPlayerEntitiesByClass(playerID, "Civilian")[0];
Engine.QueryInterface(this.treasureCivilian[playerID], IID_Resistance).SetInvulnerability(true);
if (this.treasureCivilian[playerID])
{
Engine.QueryInterface(this.treasureCivilian[playerID], IID_Resistance)
.SetInvulnerability(true);
}
}
};

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:64c4b5bcd2aa0594fe563636ae2591a280c266b7d3d5acf3ed93342591dbd728
size 656879

File diff suppressed because it is too large Load diff

View file

@ -16,12 +16,12 @@ Trigger.prototype.tutorialGoals = [
},
{
"instructions": [
markForTranslation("To start off, select your building, the Civic Center, by clicking on it. A selection ring in the color of your civilization will be displayed after clicking.")
markForTranslation("To start off, select your building, the Civic Center, by clicking on it. A selection ring in the color of your player will be displayed after clicking.")
]
},
{
"instructions": [
markForTranslation("Now that the Civic Center is selected, you will notice that a production panel will appear on the lower right of your screen detailing the actions that the buildings supports. For the production panel, available actions are not masked in any color, while an icon masked in either gray or red indicates that the action has not been unlocked or you do not have sufficient resources to perform that action, respectively. Additionally, you can hover the cursor over any icon to show a tooltip with more details.\n"),
markForTranslation("Now that the Civic Center is selected, you will notice that a production panel will appear on the lower right of your screen detailing the actions that the buildings supports. For the production panel, available actions are not masked in any color, while an icon masked in gray indicates that the action has not been unlocked and a red mask indicates that you do not have sufficient resources to perform that action. Additionally, you can hover the cursor over any icon to show a tooltip with more details.\n"),
markForTranslation("The top row of buttons contains portraits of units that may be trained at the building while the bottom one or two rows will have researchable technologies. Hover the cursor over the II icon. The tooltip will tell us that advancing to Town Phase requires both more constructed structures as well as more food and wood resources.")
]
},
@ -40,7 +40,10 @@ Trigger.prototype.tutorialGoals = [
markForTranslation("At this point, food and wood are the most important resources for developing your economy, so let's start with gathering food. Civilians gather vegetables faster than other units.\n"),
markForTranslation("There are primarily three ways to select units:\n"),
markForTranslation("1) Hold the left mouse button and drag a selection rectangle that encloses the units you want to select.\n"),
markForTranslation("2) Click on one of them and then add additional units to your selection by holding Shift and clicking each additional unit (or also via the above selection rectangle).\n"),
{
"text": markForTranslation("2) Click on one of them and then add additional units to your selection by holding %(hotkey)s and clicking each additional unit (or also via the above selection rectangle).\n"),
"hotkey": "selection.add"
},
{
"text": markForTranslation("3) Double-click on a unit. This will select every unit of the same type as the specified unit in your visible window. %(hotkey)s+double-click will select all units of the same type on the entire map.\n"),
"hotkey": "selection.offscreen"
@ -67,7 +70,7 @@ Trigger.prototype.tutorialGoals = [
},
{
"instructions": [
markForTranslation("Cavalry Citizen Soldiers are good for hunting. Select your Cavalry and order him to hunt the chickens around your Civic Center in similar fashion.")
markForTranslation("Cavalry Citizen Soldiers are good for hunting. Select your Cavalry and order him to slaughter the chickens around your Civic Center in similar fashion.")
],
"OnPlayerCommand": function(msg)
{
@ -98,7 +101,10 @@ Trigger.prototype.tutorialGoals = [
{
"instructions": [
markForTranslation("Now that the rally point is set, we can produce additional units and they will do their assigned task automatically.\n"),
markForTranslation("Citizen Soldiers gather wood faster than Civilians. Select the Civic Center and, while holding Shift, click on the second unit icon, the Hoplites (holding Shift trains a batch of five units). You can also train units individually by simply clicking, but training 5 units together takes less time than training 5 units individually.")
{
"text": markForTranslation("Citizen Soldiers gather wood faster than Civilians. Select the Civic Center and, while holding %(hotkey)s, click on the second unit icon, the Hoplites (holding %(hotkey)s trains a batch of five units). You can also train units individually by simply clicking, but training 5 units together takes less time than training 5 units individually."),
"hotkey": "session.batchtrain"
}
],
"OnTrainingQueued": function(msg)
{
@ -108,8 +114,8 @@ Trigger.prototype.tutorialGoals = [
const cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue);
cmpProductionQueue.ResetQueue();
const txt = +msg.count == 1 ?
markForTranslation("Do not forget to hold Shift while clicking to train several units.") :
markForTranslation("Hold Shift and click on the Hoplite icon.");
markForTranslation("Do not forget to hold the hotkey while clicking to train several units.") :
markForTranslation("The second icon represents the Hoplites.");
this.WarningMessage(txt);
return;
}
@ -153,7 +159,24 @@ Trigger.prototype.tutorialGoals = [
{
"instructions": [
markForTranslation("When construction finishes, the builders default to gathering wood automatically.\n"),
markForTranslation("Let's train some Civilians to gather more food. Select the Civic Center, hold Shift and click on the Civilian icon to train five Civilians.")
markForTranslation("In the meantime, we seem to have enough workers gathering wood. We should remove the current rally point of the Civic Center away from gathering wood. For that purpose, right-click on the Civic Center when it is selected (and the flag icon indicating the rally point is crossed out).")
],
"OnPlayerCommand": function(msg)
{
if (msg.cmd.type == "unset-rallypoint")
this.NextGoal();
},
"OnTrainingFinished": function(msg)
{
this.trainingDone = true;
}
},
{
"instructions": [
{
"text": markForTranslation("Let's train some Civilians to gather more food. Select the Civic Center, hold %(hotkey)s and click on the Civilian icon to train five Civilians."),
"hotkey": "session.batchtrain"
}
],
"Init": function()
{
@ -167,29 +190,14 @@ Trigger.prototype.tutorialGoals = [
const cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue);
cmpProductionQueue.ResetQueue();
const txt = +msg.count == 1 ?
markForTranslation("Do not forget to hold Shift and click to train several units.") :
markForTranslation("Hold shift and click on the Civilian icon.");
markForTranslation("Do not forget to hold the hotkey and click to train several units.") :
markForTranslation("The first icon represents the Civilians.");
this.WarningMessage(txt);
return;
}
this.NextGoal();
}
},
{
"instructions": [
markForTranslation("Let's wait for the units to be trained.\n"),
markForTranslation("In the meantime, we seem to have enough workers gathering wood. We should remove the current rally point of the Civic Center away from gathering wood. For that purpose, right-click on the Civic Center when it is selected (and the flag icon indicating the rally point is crossed out).")
],
"OnPlayerCommand": function(msg)
{
if (msg.cmd.type == "unset-rallypoint")
this.NextGoal();
},
"OnTrainingFinished": function(msg)
{
this.trainingDone = true;
}
},
{
"instructions": [
markForTranslation("The units should be ready soon.\n"),
@ -212,8 +220,14 @@ Trigger.prototype.tutorialGoals = [
},
{
"instructions": [
markForTranslation("Select two of your newly-trained Civilians and ask them to build these Houses in the empty space to the east of the Civic Center. To do so, after selecting the Civilians, click on the House icon in the bottom right panel and, while holding Shift, click first on the position in the map where you want to build the first House, and then click on the position where you want to build the second House (when you give a command while holding Shift, you put the command in a queue; units automatically switch to the next command in their queue when they finish their current command). Press Escape to get rid of the House cursor so you don't spam Houses all over the map.\n"),
markForTranslation("Reminder: to select only two Civilians, click on the first one and then hold Shift and click on the second one.")
{
"text": markForTranslation("Select two of your newly-trained Civilians and order them to build these Houses in the empty space to the east of the Civic Center. Click on the House icon in the bottom right panel. While holding %(hotkey)s click on positions on the map where you want to build Houses. The Civilians will then start to build the houses in order. (When you give a command while holding %(hotkey)s, you put the command in a queue; units automatically switch to the next command in their queue when they finish their current command). Press Escape to get rid of the House cursor so you don't spam Houses all over the map.\n"),
"hotkey": "selection.queue"
},
{
"text": markForTranslation("Reminder: to select only two Civilians, click on the first one and then hold %(hotkey) and click on the second one."),
"hotkey": "selection.add"
}
],
"Init": function()
{
@ -260,7 +274,10 @@ Trigger.prototype.tutorialGoals = [
"instructions": [
markForTranslation("Select the three remaining (idle) Civilians and order them to build a Farmstead in the center of the large open area to the west of the Civic Center.\n"),
markForTranslation("We will need a decent chunk of space around the Farmstead to build Fields. In addition, we can see goats on the west side to further improve our food gathering efficiency should we ever decide to hunt them.\n"),
markForTranslation("If you try to select the three idle Civilians by clicking and dragging a selection rectangle over them, you might accidentally select additional units. To avoid that, hold the I key while selecting so that only idle units are selected. If you accidentally select a cavalry unit, hold Ctrl and click on the cavalry unit icon of the selection panel at the bottom of the screen to remove the cavalry unit from the current selection.")
{
"text": markForTranslation("If you try to select the three idle Civilians by clicking and dragging a selection rectangle over them, you might accidentally select additional units. To avoid that, hold %(hotkey)s while selecting so that only idle units are selected. If you accidentally select a cavalry unit, hold Ctrl and click on the cavalry unit icon of the selection panel at the bottom of the screen to remove the cavalry unit from the current selection."),
"hotkey": "selection.idleonly"
}
],
"OnPlayerCommand": function(msg)
{
@ -344,7 +361,7 @@ Trigger.prototype.tutorialGoals = [
const cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue);
cmpProductionQueue.ResetQueue();
const txt = +msg.count != 1 ?
markForTranslation("Click without holding Shift to train a single unit.") :
markForTranslation("Click without holding a hotkey to train a single unit.") :
markForTranslation("Click on the Civilian icon.");
this.WarningMessage(txt);
return;
@ -415,7 +432,10 @@ Trigger.prototype.tutorialGoals = [
},
{
"instructions": [
markForTranslation("Thus, we should order them to deposit their wood in the Civic Center along the way. To do so, we will hold Shift while clicking to queue orders: select your soldiers, hold Shift and right-click on the Civic Center to deposit their wood and then hold Shift and right-click on the stone quarry to gather it.\n"),
{
"text": markForTranslation("Thus, we should order them to deposit their wood in the Civic Center along the way. To do so, we will hold %(hotkey)s while clicking to queue orders: select your soldiers, hold %(hotkey)s and right-click on the Civic Center to deposit their wood and then hold %(hotkey)s and right-click on the stone quarry to gather it.\n"),
"hotkey": "selection.queue"
},
markForTranslation("Perform a similar order queue with the remaining soldiers and the metal mine in the west.")
],
"Init": function()

View file

@ -9,9 +9,9 @@ export function aiWarn(output)
/**
* Useful for simulating consecutive AI matches.
*/
export function exit()
export function exit(exitStatus)
{
Engine.Exit();
Engine.Exit(exitStatus);
}
export function VectorDistance(a, b)

View file

@ -31,6 +31,7 @@ PetraBot.prototype.CustomInit = function(gameState)
if (this.isDeserialized)
{
// WARNING: the deserializations should not modify the metadatas infos inside their init functions
this.canPlay = this.data.canPlay;
this.turn = this.data.turn;
this.playedTurn = this.data.playedTurn;
this.elapsedTime = this.data.elapsedTime;
@ -84,8 +85,8 @@ PetraBot.prototype.CustomInit = function(gameState)
this.HQ.init(gameState, this.queues);
// Analyze our starting position and set a strategy
this.HQ.gameAnalysis(gameState);
// Try to analyze our starting position and set a strategy.
this.canPlay = this.HQ.gameAnalysis(gameState);
}
};
@ -112,10 +113,10 @@ PetraBot.prototype.OnUpdate = function(sharedScript)
this.playedTurn++;
if (this.gameState.getOwnEntities().length === 0)
if (!this.canPlay)
{
Engine.ProfileStop();
return; // With no entities to control the AI cannot do anything
return;
}
this.HQ.update(this.gameState, this.queues, this.savedEvents);
@ -151,6 +152,7 @@ PetraBot.prototype.Serialize = function()
}
return {
"canPlay": this.canPlay,
"uniqueIDs": this.uniqueIDs,
"turn": this.turn,
"playedTurn": this.playedTurn,

View file

@ -17,7 +17,7 @@ Headquarters.prototype.gameAnalysis = function(gameState)
{
// Analysis of the terrain and the different access regions
if (!this.regionAnalysis(gameState))
return;
return false;
this.attackManager.init(gameState);
this.buildManager.init(gameState);
@ -57,6 +57,8 @@ Headquarters.prototype.gameAnalysis = function(gameState)
// configure our first base strategy
if (this.hasPotentialBase())
this.configFirstBase(gameState);
return true;
};
/**

View file

@ -105,12 +105,17 @@ Attack.prototype.Schema =
"<element>" +
"<anyName a:help='Currently one of Melee, Ranged, Capture or Slaughter.'/>" +
"<interleave>" +
"<element name='AttackName' a:help='Name of the attack, to be displayed in the GUI. Optionally includes a translate context attribute.'>" +
"<element name='AttackName' a:help='Name of the attack, to be displayed in the GUI.'>" +
"<optional>" +
"<attribute name='context'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<optional>" +
"<attribute name='comment'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<text/>" +
"</element>" +
AttackHelper.BuildAttackEffectsSchema() +
@ -444,7 +449,7 @@ Attack.prototype.GetSplashData = function(type)
Attack.prototype.GetRange = function(type)
{
if (!type)
if (!type || !this.template[type])
return this.GetFullAttackRange();
let max = +this.template[type].MaxRange;

View file

@ -113,7 +113,7 @@ Barter.prototype.ExchangeResources = function(playerID, resourceToSell, resource
cmpStatisticsTracker.IncreaseResourcesBoughtCounter(resourceToBuy, amountToAdd);
}
const difference = this.DIFFERENCE_PER_DEAL * amount / this.DEAL_AMOUNT;
const difference = this.DIFFERENCE_PER_DEAL * amountToAdd / this.DEAL_AMOUNT;
// Overall price difference (dynamic +/- constant) can't exceed +-99%.
const maxDifference = this.DEAL_AMOUNT * 0.99;

View file

@ -44,6 +44,16 @@ BuildRestrictions.prototype.Schema =
"<element name='Distance' a:help='Specifies distance restrictions on this building, relative to buildings from the given category.'>" +
"<interleave>" +
"<element name='FromClass'>" +
"<optional>" +
"<attribute name='context'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<optional>" +
"<attribute name='comment'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<text/>" +
"</element>" +
"<optional><element name='MinDistance'><data type='positiveInteger'/></element></optional>" +

View file

@ -9,6 +9,16 @@ Formation.prototype.Schema =
"</data>" +
"</element>" +
"<element name='DisabledTooltip' a:help='Tooltip shown when the formation is disabled.'>" +
"<optional>" +
"<attribute name='context'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<optional>" +
"<attribute name='comment'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<text/>" +
"</element>" +
"<element name='SpeedMultiplier' a:help='The speed of the formation is determined by the minimum speed of all members, multiplied with this number.'>" +

View file

@ -25,10 +25,30 @@ Identity.prototype.Schema =
"</element>" +
"</optional>" +
"<element name='GenericName' a:help='Generic English-language name for this entity.'>" +
"<optional>" +
"<attribute name='context'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<optional>" +
"<attribute name='comment'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<text/>" +
"</element>" +
"<optional>" +
"<element name='SpecificName' a:help='Specific native-language name for this entity.'>" +
"<optional>" +
"<attribute name='context'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<optional>" +
"<attribute name='comment'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<text/>" +
"</element>" +
"</optional>" +
@ -39,16 +59,46 @@ Identity.prototype.Schema =
"</optional>" +
"<optional>" +
"<element name='Tooltip'>" +
"<optional>" +
"<attribute name='context'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<optional>" +
"<attribute name='comment'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<text/>" +
"</element>" +
"</optional>" +
"<optional>" +
"<element name='History'>" +
"<optional>" +
"<attribute name='context'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<optional>" +
"<attribute name='comment'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<text/>" +
"</element>" +
"</optional>" +
"<optional>" +
"<element name='Rank'>" +
"<optional>" +
"<attribute name='context'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<optional>" +
"<attribute name='comment'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<choice>" +
"<value>Basic</value>" +
"<value>Advanced</value>" +
@ -66,6 +116,16 @@ Identity.prototype.Schema =
"</optional>" +
"<optional>" +
"<element name='VisibleClasses' a:help='Optional list of space-separated classes applying to this entity. These classes will also be visible in various GUI elements. Choices include: Academy, Amphitheater, Archer, ArmyCamp, ArrowShip, Arsenal, ArtilleryTower, Auxiliary, Axeman, Barracks, BoltShooter, BoltTower, Bribable, Builder, Camel, Cataphract, Cavalry, Centurion, Champion, Chariot, Citizen, City, Civilian, Civic, CivilCentre, Colony, Corral, Council, Crossbowman, Defensive, Dock, Dog, Economic, Elephant, ElephantStable, Embassy, Farmstead, Field, Fireship, FishingBoat, Forge, Fortress, Gate, Gladiator, GreatTower, Gymnasium, Hall, Healer, Heavy, Hero, House, IceHouse, Ignited, Immortal, ImperialCourt, ImperialMinistry, Infantry, Javelineer, Kennel, LaoziGate, Legionary, Library, Lighthouse, Longsword, Maceman, Melee, Market, Mercenary, Military, Minister, Monument, Naval, NavalRam, NavalSiege, Outpost, Palace, Palisade, Pikeman, Pillar, Pirate, Pyramid, Ram, Range, Ranged, Relic, Resource, RotaryMill, ScoutShip, SentryTower, Ship, Shipyard, Shrine, Siege, SiegeTower, SiegeWall, Slave, Slinger, Soldier, Spearman, Stable, Stoa, StoneThrower, StoneTower, Storehouse, Support, Swordsman, Syssiton, Temple, TempleOfAmun, TempleOfApedemak, TempleOfIsis, TempleOfMars, TempleOfVesta, Tent, Theater, Tower, Town, Trade, Trader, TriumphalArch, Trumpeter, Village, Wall, Warship, Wonder, Worker.'>" +
"<optional>" +
"<attribute name='context'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<optional>" +
"<attribute name='comment'>" +
"<text/>" +
"</attribute>" +
"</optional>" +
"<attribute name='datatype'>" +
"<value>tokens</value>" +
"</attribute>" +

View file

@ -17,13 +17,11 @@ PopulationCapManager.prototype.Init = function()
*/
PopulationCapManager.prototype.SetPopulationCapType = function(type)
{
if ([this.CAPTYPE_PLAYER_POPULATION, this.CAPTYPE_TEAM_POPULATION, this.CAPTYPE_WORLD_POPULATION].includes(type))
this.popCapType = type;
else
{
warn(`Attempted to set an unknown population capacity type: '${type}'. Continuing with type 'Player Population'...`);
this.popCapType = this.CAPTYPE_PLAYER_POPULATION;
}
if (![this.CAPTYPE_PLAYER_POPULATION, this.CAPTYPE_TEAM_POPULATION, this.CAPTYPE_WORLD_POPULATION].includes(type))
error("Invalid population cap type specified: " + type);
this.popCapType = type;
if (this.popCap)
this.InitializePopCaps();
};
@ -48,6 +46,13 @@ PopulationCapManager.prototype.SetPopulationCap = function(cap)
this.InitializePopCaps();
};
PopulationCapManager.prototype.SetPerPlayerPopulationCaps = function(playerCaps)
{
this.perPlayerPopCaps = playerCaps;
this.popCapType = this.CAPTYPE_PLAYER_POPULATION;
this.InitializePopCaps();
};
/**
* Get the current pop cap.
* @returns {number}
@ -86,10 +91,10 @@ PopulationCapManager.prototype.InitializePopCaps = function()
*/
PopulationCapManager.prototype.InitializePlayerPopCaps = function()
{
const players = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetActivePlayers();
for (const player of players)
QueryPlayerIDInterface(player, IID_Player)
.SetMaxPopulation(this.popCap);
const players = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNonGaiaPlayers();
for (const i in players)
QueryPlayerIDInterface(players[i], IID_Player)
.SetMaxPopulation(this.perPlayerPopCaps ? this.perPlayerPopCaps[i] : this.popCap);
};
/**

View file

@ -100,7 +100,7 @@ cmpBarter.priceDifferences = { "wood": 0, "stone": 0, "metal": 0 };
cmpBarter.ExchangeResources(playerID, "wood", "stone", 100);
TS_ASSERT_EQUALS(cmpBarter.restoreTimer, 7);
TS_ASSERT(timerActivated);
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.priceDifferences, { "wood": -cmpBarter.DIFFERENCE_PER_DEAL, "stone": cmpBarter.DIFFERENCE_PER_DEAL, "metal": 0 });
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.priceDifferences, { "wood": -cmpBarter.DIFFERENCE_PER_DEAL * bought / 100, "stone": cmpBarter.DIFFERENCE_PER_DEAL * bought / 100, "metal": 0 });
TS_ASSERT_EQUALS(sold, 100);
TS_ASSERT_EQUALS(bought, Math.round(100 * (100 - cmpBarter.CONSTANT_DIFFERENCE + 0) / (100 + cmpBarter.CONSTANT_DIFFERENCE + 0)));
@ -125,12 +125,12 @@ TS_ASSERT_EQUALS(bought, 0);
cmpBarter.priceDifferences = { "wood": 0, "stone": 99 - cmpBarter.CONSTANT_DIFFERENCE, "metal": 0 };
cmpBarter.ExchangeResources(playerID, "wood", "stone", 100);
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.priceDifferences, { "wood": -cmpBarter.DIFFERENCE_PER_DEAL, "stone": 99 - cmpBarter.CONSTANT_DIFFERENCE, "metal": 0 });
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.priceDifferences, { "wood": -cmpBarter.DIFFERENCE_PER_DEAL * bought / 100, "stone": 99 - cmpBarter.CONSTANT_DIFFERENCE, "metal": 0 });
TS_ASSERT_EQUALS(bought, Math.round(100 * (100 - cmpBarter.CONSTANT_DIFFERENCE + 0) / (100 + cmpBarter.CONSTANT_DIFFERENCE + 99 - cmpBarter.CONSTANT_DIFFERENCE)));
cmpBarter.priceDifferences = { "wood": -99 + cmpBarter.CONSTANT_DIFFERENCE, "stone": 0, "metal": 0 };
cmpBarter.ExchangeResources(playerID, "wood", "stone", 100);
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.priceDifferences, { "wood": -99 + cmpBarter.CONSTANT_DIFFERENCE, "stone": cmpBarter.DIFFERENCE_PER_DEAL, "metal": 0 });
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.priceDifferences, { "wood": -99 + cmpBarter.CONSTANT_DIFFERENCE, "stone": cmpBarter.DIFFERENCE_PER_DEAL * bought / 100, "metal": 0 });
TS_ASSERT_EQUALS(bought, Math.round(100 * (100 - cmpBarter.CONSTANT_DIFFERENCE - 99 + cmpBarter.CONSTANT_DIFFERENCE) / (100 + cmpBarter.CONSTANT_DIFFERENCE + 0)));
cmpBarter.priceDifferences = { "wood": 0, "stone": 0, "metal": 0 };

View file

@ -11,5 +11,5 @@
],
"auraName": "Terror Cimbricus",
"auraDescription": "Enemy Soldiers, Ships, Siege, and Structures -20 meters vision range.",
"overlayIcon": "art/textures/ui/session/auras/speed_bonus.png"
}
"overlayIcon": "art/textures/ui/session/auras/fear.png"
}

View file

@ -27,8 +27,8 @@
"CivBonuses": [
{
"Name": "Seeresses",
"History": "Seeresses accompanied the German armies and envisioned prophecies of victory from sacrifices.",
"Description": "Germans can access a Champion Healer unit in City Phase."
"History": "Seeresses accompanied the Germanic armies and envisioned prophecies of victory from sacrifices.",
"Description": "A unique Champion Healer unit is available in City Phase."
}
],
"WallSets":

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