We no longer use the GUI2 draw events. We should implement the appropriate interface provided by top_level_drawable instead. DRAW is still a valid event for now, but would probably be removed in the future.
Added code to convert all `[side]type=` to `[side][leader]` when the `[scenario]` is read, and the rest of the engine code to only work with [leader], this should fix all possible problems with `[leader]` and also simplify the code a bit
Fixes#7985Fixes#3742
This was unique to this class, since the base class only implemented the const version. It was only needed for the whiteboard, and on closer inspection none of of the mutable references therein actually needed to be mutable. Marked them all const and removed the offending getter from game_board.
Note that the non-const overload had the same functionality as the const overload in the base class, only implemented via `find_visible_unit`.
Little hacky, since this supports the case of manually hiding the grids instead of simply not populating them (see #9499), but it prevents needing to change widget::get_best_size while I figure out a more comprehensive solution.
previously the leader= attribute in [side] could be used to
make the engine choose a faction by its leader, similar to how
[side]faction_from_recruit worked.
However this was not documented in the wiki, and the name clash
with the [side][leader] subtag could also cause problems
and is also a litte confusing.
So it was decided to remove it. an alternative approach to fix the
name clash would be to rename it, but i can't think of
real usecases of this feature currently.
Instead, return the number of rows shown from filter_rows_by. We might re-add any_rows_shown in the future, but for now this covers the intended usecase.
This matches the behavior on the client where the events that
happen after end_turn (the "turn end" wml events) happen during
the last sides turn not the next sides turn. In particular this
fixes#2563. It also fixes#3899 because the new logic
automaticially skips empty sides already in init_side and not on
end_turn.
It also changes how description is updated, since carrying that
return value arround specifying whether it was updated was becoming
annoying.
With a few code improvements from soliton.
We now use a modified default carryover calculation,
the main advantage is it now uses the normal carryover
message on endlevel, and shows how it is calculated.
The idea is to make it easier for umc devs to implement
their own carryover / early finish bonus mechanics. Maybe
we can also make use of it in Worls Conquest.
previously it was unclear what the trailing number meant,
also the order couldn't be changed in the translation.
Also the player number was shown 2 times in the savefile name,
resulting in names like 'WC1-WCII 1 -Start-Auto-Save.gz' so i
removed it from the scenario name.
This returns true when the user is currently replaying the scenario
This not only includes the classic 'replay safefiles' but for
example also the 'replay turn' feature (field name suggested by celmin)
Don't animate unit advancements during a prestart event.
It woudl be better it u:advance() would automaticialyl not waste time animating advancements that can't be seen (during prestart events) but for this scenario this is already an improvement
Increases GCC requirement to 11 for Charconv support (which is part of c++17)
Technicially it also builds with older gcc versions when boost 1.85 is available but that combination seems unlikely and i didn't want to make INSTALL.md too complicated.
The upcoming clang 20 will also support charconv by itself, but again it felt silly to mention something that is not available yet.
* Re-added the ability to set a single sorter, this time by ID.
* Multi-sorter setting now uses the magic sort_N IDs.
* Cleaned up internal handling to remove reliance on header grid columns.
Sorters will still be looked for in the header, but rely on the specified ID.
This did (I'm pretty sure) work before, but now it's explicit.
* The order_pair typedef has been removed
* set_active_sorting_option has been removed set_active_sorter and now takes its arguments separately instead of as a pair.
* set_active_sorter will use the bound sorter header on-modified handler
instead of calling order_by_column directly
* set_sorting_options has been renamed to set_sorters
* get_active_sorting_option has been renamed get_sorter
This unifies handling of the scrollbar modes without having to manually set them in the builders. At one point, this wasn't too common, but it's become common enough that having a separate builder is cleaner
This makes attribute_value and lexical_cast use the "new" to/from_chars api.
Its main advantages are:
- It's guaranteed to be locale independent, hopefully fixing all cases of #3945 and similar
- It fixes some cases config serialization, in particular the test
```
cfg["x"] = "9.87654321";
BOOST_CHECK_EQUAL(cfg["x"], 9.87654321);
```
- Previously the lexical_cast implementation used exception
handling for invalid formats (catching std::invalid_argument)
which made noise during debugging (and is also slower if it
is not optimized out).
- It's faster
So far afaik the only compiler which has a complete and proper to/from_chars implementation is msvc, gccs implementation of from_chars sometimes uses strtod under the hood and clang simply hasn't implemented from_chars for floating point numbers yet at all (actually the upcomig clang 20 will have it). Luckily for us, there is now also boost::charconv that can be used. So this raises to minimum build requirement to have at least one of:
- msvc 2019 update 5
- gcc 11
- clang 14 (i have added a fallback implementation of from_chars for this case, that doesn't support all of its features, and is probably certainly not as fast as the boost version, but supports the features that we use from it)
- boost 1.85
Since in particular the gcc implementation isn't that good (at least it on gcc11), boost charconv is the preferred implementation that is used if available.
This also removes a strange overload for
pointers to integers in lexical_cast while changing lexical_cast to use the new api.
Fixed map editor crashing when creating or opening scenario after played local scenario before opening map editor. Resolves#9563. The cause of the bug was that the ai manager singleton pointer was not set to nullptr after it was destructed. Fixed this by making ai manager destructor set singleton to nullptr. Before this the ai_map_ map member has to be cleared in destructor because it might try to access the singleton when destructed.
---------
Co-authored-by: SomeName42 <>
These were added by clang-tidy's autofix, which both tried to convert
the parameters to const references and std::move them. The correct
behaviour is to convert only to a const reference.
Instead of two functions for translatable and non-translatable options, comparison will be determined by the return value of the sorter. Existing translatable sorting options have been adjusted to return t_string rather than string.
When Hahid dies, Grug or Dolburras, if present, say the "eulogy". There were problems in scenarios where they first appear (S06a for Dolburras and S07b for Grug) - they say it even before joining the player's side, which makes no sense. I changed the message tags in utils/deaths.cfg to use "id" and "side" instead of "speaker", so they only say it when they are on the same side as Hahid.
Also in S07b, Hahid's herodeath macro was duplicated, so the dialogue was displayed twice.
Also I changed Grug's herodeath to "id" and "side" and re-included it into S07b, so now Gweddry says the eulogy for Grug after Grug joins, but not before.
For whatever reason, callback_save_value had type
std::function<void(int)> in the .cpp file but
std::function<void(const int)> in the header file. This reconciles them
to both take in an integer as a parameter.
This was the last use of lg::format_timespan, which was only ever used in server code anyway. The server probably shouldn't be formatting this anyway, but as long as it is, we don't need a dedicated function or fancy formatting.
Bad design to return mutable reference to static object. This method has the possibility of creating a new default entry in the by_name map, but the remove call will be a no-op in that case (as it was before), so no harm done.
previously the game would return to titlescreen here if mp_info_
but was null but
`game_config::debug && state_.classification().is_multiplayer()`
returned true which happend when a multiplayer game was reloaded
via the sp loadgame dialog.
This fixes the issue by simply removing the "always show mp staging
between scenarios in debug mode" feature, which imo never was that
useful anyways.
This not only removes duplicate information which can always cause bugs if it's out of sync,
this can also be used an an easy way to detect the old undo stack format
this way even when enter/exit_hex events with [on_undo] are involved, undoing happens
in reverse order of the gamestate changes during the original action
This commit splits undo actions into multiple smaller steps. The main advantages:
- Its allows us always undo the parts of an action in the reverse order of which
they originally happen, preventing bugs that could be caused if the parts
interact with each other in a way where the order matters (like for example
an [on_undo] resetting a units moves, when the event happend in a move action
which would then also reset the units moves on undoing).
- It's easier to add (c++) undo steps for specific steps even if they are used
from wml, like spending gold.
- [do_command] no longer confused the undo stack (in fact it's by default now undoable).
- All actions are put onto the undo stack in the same way, previously it was
often unclear whether the undo stack is empty during a specific step during
the execution of an action, in particular when people tried to use
`undo_stack->empty()` to check whether an action could still be undone.
This also adjusts the periods for years and months. Previously, we were using values of 30 days for a month and 12 months for year. Now, we use the chrono values of a month as 1/12 of a year and a year as 365.2425 days.
In S04a, the event is added within his original "last breath" event - the one which switches him to the player's side. Without this additional event, he will die silently if killed by the elves after being "captured".
In S11, it looks like the event for him was simply forgotten (HERODEATH events are added for all other heroes).
Instead of simply returning a string, `is_ip_banned` now returns a struct with an error code, ban reason, and ban time remaining. This avoids doing time duration formatting on the server and allows the error message to be localized on the client. It also makes the ban handling interface more generic in server_base, which should hopefully allow forum bans to be handled this way as well.
* new ships Derelict Hulk and Fireship
* new "race" Ships - includes Transport Galleon, Pirate Galleon, Derelict Hulk, and Fireship
* Pirate Galleon chaotic
* animations for all four touched ships
* ship portraits for Derelict Hulk and Fireship
* crew portraits by LordBob for Boat, Galleon, Transport Galleon, and Pirate Galleon
* old (non-pixel art) transport galleon and pirate galleon images moved to scenery
Fixes#8488.
This is a simple setenv trick. Ideally we would instead figure out how
to fix Oldania ADF Std to work on newer macOS, but since we know the
Fontconfig backend works for us on Windows and Linux, we may as well
stick to it and hope there will never be a situation where CoreText
would prove superior somehow.
Fixed palette button not being clickable after scrolling in palette widget without moving the cursor. Resolves#1335. The cause of the bug was that scrolling doesnt change the highlighted state of the palette buttons and not highlighted buttons didnt process being clicked. Solved the bug by making not highlighted buttons process being clicked.
previously block_undo would clear the undo stack and send data even when its parameter is false
this commit also fixes a possible crash when dsu changed the gamestate during formula evauluation
also removed a is_simultanious_ since it basicialyl did the same thing as undo_blocked_
With this, finally all actions run though synced context::run,
so that we not only have a central place that happens before/after
synced actions, we also guarantee that there is no difference between
the original and the replay codepath for all actions.
This should also make upcoming changed to the undo code easier.
- Removed the now unused 'undo' parameter
- Removed the rareley used 'show' parameter, the actions now
check whether they should skip in replays
Replaced the error handler with the more generic 'spectator' parameter,
the idea is to use it also for the move_spectator so that the move action
can also go through synced_context::run()
- use_undo is not used anymore
- ignore_error_function has no effect since to_check()
already checks whether the unit exists
- show in whiteboard code was the default value.
- show is now determined inside the actions handler, this
has the advantage that the skip_ai_moves preference now
also works for networked ai sides.
-the attack code now used run_in_synced_context_if_not_already
just like the other commands
The comments said undo is disabled during ai turns to speed things up,
but since all the undo code does is adding a simple object once to a vector, its impact
on performance is really nonexistent.
Internal escaping causing markup failure when tags are nested.
See #9569 and #9572 for example. Functions in markup will no longer
escape their contents, and those should be escaped by caller if needed.
The outposts are east of River Weldyn in the campaign map. Also, in scenario 1, the castle is east of the river. The heartland of Wesnoth country is west of that river, so the eastern bank is the "far" one.
These words date back to the original campaign design by Eric S. Raymond. Back then, the campaign map had the outposts on the western bank of Weldyn.
But in aeb9ec7 the map was replaced with a newer one, with outpost on the eastern bank, which persists to this day with some minor changes (like the southern outpost was moved futher south).
In the existing code, on HARD difficulty, creating a unit with id="Hur" is done twice, first as a Troll Whelp, then as a Troll Rocklobber. As a result, the former unit is replaced with the latter one. As they are created at the same coordinates, I believe this is the intended behavior.
But according to https://wiki.wesnoth.org/SingleUnitWML , reusing the id "may produce unpredictable results in many cases". For example, (I tested it) if you create the new unit at the different coordinates, it instead appears at the former unit's coordinates.
I've added another preprocessor directive, so the unit with this id is created only once on both NORMAL and HARD.
If we need this, it should, as the comment says, be implemented as part of the draw manager. But it also seems like any optimizations on this front are better left to the OS and its compositor.
previously in `undoable_action->undo(side_) ` the undo stack was not in sync with the relpay stack because the code called `undos_.pop_back();` before that and `resources::recorder->undo_cut` after that, this could confuse the code which sends replay commands to the other clients.
In moving recursion_guard from matches_filter() to special_unit_matches() i has forgotten what [leadership] abilities called directly matches_filter().
hitpoints from 42 to 48
movement from 9 to 7
claws from 5x4 to 6x4, now usable on offense
bite from 15x2 to 9x2 charge, now usable in defense
arcane resistance from 20% to 10%
price from 21 to 30
This reverts commit b3802f44ea.
Since commit 70df290 restores the Elvish Outrider to essentially its original stats, the 1.18 balance fix for this one campaign scenario is no longer useful.
Redesigns the Naga Guard, Shield Guard, and High Guard to make their shield bash attack less redundant.
Also adds the new Unwieldy and Guard specials, and deprecates the Absorb special.
This is way more readable and more semantically correct. Essentially, instead of truncating the current and last timestamps to seconds and checking if we were "in" a different second, actually check the duration between the current frame and our last lap point .
Since we're relying on free functions to parse and serialize time_points, it makes more sense to do likewise for durations rather than relying on a config_attribute_value member function. Leaves the assignment support for now.
Includes adjustments to client code to likewise use chrono types. I decided to keep using time_t
(which is just an alias for long_long) for serializing time points. This avoids compatibility issues,
since we keep the same resolution (seconds since Unix epoch), and unless we're going to "properly"
store time points in config, the time_t's unitless value is a good a representation as any.
The pre-processing for --max-fps was basically identical to what draw_manager::get_frame_length does.
This replaces the draw_delay preference with a new refresh_rate preference that more accurately describes
what is being set. video::current_refresh_rate will now take this preference into account, meaning the
build info report will correctly report player-set FPS limits.
The Limit FPS option in the prefs UI was also removed. When it was first introduced (cca79afe4b)
it specifically affected the map rendering code, not the rendering pipeline as a whole. With the 1.17
rendering refactor, this is no longer the case, and so its current usage as the lower bound for frametime
calculations did nothing (all it did was change the lower bound from 0 to -1 when enabled).
It might be worth adding a slider to the UI to dynamically set max fps, but that's a separate change.
Only two places actually made use of the only thing it was useful for (the current tick count),
the countdown clock and the music thinker. The former was simpler to do without, and though it
was slightly useful for the latter, the music thinker really needs to be rethought.
The only thing this could be useful for is providing a stable timestamp for every process call.
That wasn't how it was designed, however. ticks() would populate its value the first time it was
called. Even if (as I considered doing) you change it to register the tick when constructing the
pump_info object, it's still easier (and easier to read) to just call steady_clock::now directly
as needed.
* Functions that return time values now return proper std::chrono::duration units (milliseconds,
seconds, etc.). This removes the need to do manual unit conversions.
* Simple time-to-execute logging was replaced with `utils::optimer`.
* Most uses of `SDL_GetTicks()` have been replaced with `std::chrono::steady_clock`.
* Uses of events::pump_info::ticks() have been replaced with direct calls to steady_clock::now().
This made the countdown_clock code significantly simpler. As for the music_tinker, that needs
to be rethought wholesale.
In special_id/type without the _'active' suffix only the encoding of the special in the attack is checked, and therefore the specials encoded in the [abilities] tags are de facto excluded, except that I forgot this logic in [filter_special] and I have to fix my error before updating the wikia.
uses portraits in the character selection and single click selection on pictures instead of buttons
also adds a dark background to hint messages to make them easier to read
adds arrow markers in the beginning on the units
Addresses https://github.com/wesnoth/wesnoth/issues/9309
when used, the amlas in [unit_type] are replaced by list of amlas in [modify_unit_type],i cannot done add [advancement] without erase amla already present.
GUI2 still does its own handling with double clicks. This doesn't touch that. The default SDL handling is either 500ms (unchanged) or queried from the OS on Windows (an improvement). The click radius defaults to 32, which honestly seems like an acceptable adjustment.
This interface was extremely confusing. pum_info is designed to set `ticks_` only once. This can lead to a situation (exemplified by the music code) where if ticks() is called multiple times in a row, the subsequent times with a counter, that counter would never be incremented since the condition that tests them short circuits on the is-ticks-not-set check.
Also, giving ticks() multiple side effects was very confusing.
These aren't used anymore as of #9332 (save one place, which has been inlined here), and they're not good to rely on, since they don't handle utf8 properly.
This removes `get_teams()`, `get_units()`, and `get_map()` from the display class. These only served as one of the many, many ways to access this data held by the display_context, and that shouldn't be the first-class responsibility of display. Instead, we either access them through the display_context pointer that display holds (whose getter has been renamed to `context()`) or through other more convenient paths (such as play_controller). The editor_display function `map()` has now taken up the mantle of `get_map()`, mostly because both `display::get_map()` and `editor_display::map()` are used, and the former outnumbered the latter.
Removed:
- debug_highlight et al. Unused, and we have the main "display coordinates" debug flag in the base class
- current_team_name. Only used in one place, clearer to just call team_name directly.
- get_terrain_on. Unimplemented
... to fix compile issues with boost 1.86.
Commit 9c665ae3c4 does the same
for wesnothd, but campaignd still fails to compile with
overload resolution failure.
References #9284
I have no idea what's going on with the transition from ubuntu-latest from 22.04 to 24.04. It switched to 24.04, and now it looks like it's back to 22.04...
See https://github.com/actions/runner-images/issues/10636
Rename location_palette::can_swap() to the correct name so that it
overrides as intended, thus making the UI disable the "swap fg and bg
items" button.
The class structure doesn't match the responsibilities here, as part
of UX isn't part of the palette, rather it's part of the tool that
decides whether there are fg and bg items - alternatively, the tool
decides whether right-click is "place bg item", "delete items", or
"show unit tool options". However, this change seems to be enough to
make the UX correct.
The "virtual" is redundant, but add it for consistency with the other
code in these classes.
When I use an ability id=A and include [filter][filter_adjacent]ability_id_active=A, the more units with the adjacent ability I add to it, the slower the game becomes, and at the third unit the game freezes, whereas with the direct comparison of the configs the game only slows down significantly after the 5th unit added.
The only place that used these was the lua show_dialog implementation. We can just construct the window object directly instead. Since this skips out on the finalize_build step (which in the case of modal/modeless_dialog was being called by those respective ctors), I've removed that function and merged it into the window ctor. No need to do it separately.
Builds on work in af81bba53b and 247e5ff055
Note that location_palette::get_help_string is not virtual as it does not inherit from editor_palette (where the pure virtual get_help_string is defined) but rather common_palette.
Resolves https://github.com/wesnoth/wesnoth/issues/7926
[filter_ability] and [filter_ability_active] have been merged into a single filter equipped with the 'active' attribute which when the value is 'true' checks the units affected by the sought ability and when the value is 'false' or unset will check the units carrying the ability even if they are not affected by it.
Because of the attribute strategy, I'm afraid that the developer will be mistaken about its function and that's why I'm not at all keen on it but I want to get out of this impasse.
all_directions better reflects the purpose of the former. Also made it return a value,
since the only places that used it immediately assigned it to a local variable.
The first SDL_KEY_DOWN handler is being called twice, while the second one is being called once.
The tab order handling is done by the first handler, which caused the focus to move *twice*, resulting in the erratic behavior when tab was pressed.
Moving the tab handling to the second one stops this and now focus moves only once when Tab is pressed.
With custom gui2 theme support in #9057, it is now possible to create addons that supply UI Themes or Skins.
This adds support so such addons are properly recognized and validated.
Resolves#9009, closes#9384. Besides the issues that came from having both int and bool conversions (even with bool marked explicit), it doesn't make sense to use int for all numeric assignments. I didn't test whether it would be an issue in practice, but it seems better to let callers be explicit about what type they want for numeric values than risking overflow or wrapping for very large values.
* Removed duplicate map_location hasher, removed unused teleport_id variable, dst_node reference is used at other possible locations, teleport destination heuristic distance now calculated before path finding loop only once, teleport source heuristic distance now stored in nodes, only calculated once and reused.
---------
Co-authored-by: SomeName42 <>
Change Jumpcat from level 1 to level 2
Increase HP from 32 to 40.
Reduce MP from 9 to 7.
Reduce arcane resist from 20 to 10.
Increase cost from 15 to 26
Replace claws' parry with backstab, but reduce damage from 6-3 to 5-3
Remove accuracy from tail, but increase damage from 11-2 to 13-2
* address bluffs-mountains transitions
* revise visual indicator of flood-filled elevation regions in editor
* small border versions of dry and basic mountain
* fix some frozen/elevated transitions
* address mini-map concerns in #8924
This is meant as a lightweight replacement for all_children_range in cases where the iterator doesn't need to be stored (most cases). It has several advantages:
First, it avoids the custom iterator classes, making the code easier to read. It also means it should be composable with STL ranges in C++20. Further, you no longer get a mutable reference on a const config. Finally, it means intellisense can properly display the key/cfg types in a structured binding. When unpacking `config::any_child`, for some reason it shows up as a key/value copy instead of reference...
This makes a lot more sense given how forgotten everything before the fall is by the time of UtBS. 300 AF is small enough for a few elves to remember the times before. 1000 AF is more sensible in my opinion.
Skeletal Dragon saw very major buffs in #8541, which causes some concern about rebalancing and UMC. This reduces their stats closer to 1.18, though still moderately stronger.
Was only used in two places, one of which was as the implementation of the version that took a vector. All the same arguments were accepted by both. Also use list initialization for the other overloads.
outside_area checks that the point is within the given rect reduced by hex_size(). Since that's the size of a location rect, the adjustment meant that a hex can't protrude outside the map area. This simplifies the logic using rect math instead of point math.
reuse partially 1493faeaee but don't remove check cfg. Thanks to @Pentarctagon
if for example the ability filter searches for the value of 'active_on' in an ability 'leadership' then the false value will be returned because active_on is not an attribute usable in [leadership]
on the other hand if the ability is of type 'dummy' its encoding remaining at the discretion of the UMC developer, the checking can be done normally
Although not perfect, this makes the page usable. Using the previous version leads to multiple complex bugs at this point.
also stops a y calculation bug in table.
It is now roughly a superset of Pango and supports the following new features
* XML character entities, including decimal and hex entities, common named entities (apos, quot, lt, gt, amp), and even unrecognized named entities
* Nesting tags within each other (new-style only)
* Attributes without a value
Attempting to launch it crashes the game (probably to do with a null video surface),
and since it's being replaced there's no point in restoring it to functionality.
The implementation details (help_menu, etc) have been left for now. Will remove soon.
This also means the GUI2 help browser is shown by default now.
This attribute, when set to a valid value of lawful|neutral|chaotic|liminal, will assign to the weapon a different alignment than the unit alignment used by default. This alignment is then used when attacking with this weapon.
The attribute is not accessible from lua so far since the fallback to unit alignment does not work.
Instead of passing all the arguments for an overlay to display::add_overlay, just take an rvalue-reference to an existing overlay object.
The overlay ctor was adjusted. It no longer takes a halo::handle argument, and the display class sets that manually.
Cut extra icon and lua code for 'stun' weapon special.
An identical copy was already moved to core by #7323 and stun in UtBS was removed long ago anyway.
* Makes it more type-safe by using chrono types more directly.
* Fixes a few design issues, such as the current time point being taken multiple times when updating the data.
* Fixes min and max FPS times being swapped
* Improved display
This can't be done in a simple loop over all_children_range since splice_children modifies
the source config. This adds a new getter method for a view over all tag names.
The purpose of this is to show all potential hooks in the output, not just the hooks that are currently assigned.
This alse adds an __index metamethod that returns no-op versions of each callback, so that the __dir output correctly shows them as functions.
This covers both wesnoth.current.schedule and the objects returned by wesnoth.map.get_area()
Also, the wesnoth.schedule module is no longer treated like the schedule metatable, since none of the functions in the module take a schedule as the first argument. This may be reverted in the future.
The attribute registration system has also been extended to permit registry tables to conditionally add certain keys.
Now the __metatable contains the list of member names.
This means that wesnoth.type won't treat named tuples with different members as the same thing – not evne if they're the same length. Which is probably a good thing!
* Rename the vector operations to hex_vector (to emphasize that they are NOT standard vector ops) and document them as official API
* Add new get_hexes_at_radius, which returns an unfilled ring (as opposed to get_hexes_in_radius which returns a filled circle)
* Expose the new cubic coordinate conversions
It was ONLY used in one place, to calculate rotate_right_around_center, and was likely not a very efficient way of calculating that anyway. I've included a different implementation of rotate_right_around_center that uses cubic coordinates.
This code sets orb color to can-still-make-an-action if unit has no moves left,
and has a visible enemy within max and min range of a weapon. This also affects
if the unit is selectable with 'N' (units that can move or attack).
Currently, it doesn't affect the mainline much, as no unit has a weapon
max/min_range different from 1, most notice-able, it marks units with no attack
as incapable of action, after having no moves left.
The purpose of this is part of getting real-ranged attacks into the mainline.
It should work even when the macro appears in the same event as the
attack; this tests that.
The new one uses the COMMON_KEEP macro, but I've left the existing
one unchanged, except for the renaming.
Unit description is not yet implemented. Once it is, I expect menu item is changed back to unit description, while the opened dialog has link to navigate to unit type description.
when two special weapons use multiply and divide with the same id, both operations are used, isn't that so why should it be different with 'add' and 'sub' where it's the larger value that is used (if asub=value_sub and add=value_add are used and value_sub>value_add then value_sub is used). This logic is counter-intuitive. that multiplication/division is applied to (base_value +- add/sub) is understandable but not this discrimination. For me add and sub should still be usable; even if it means changing the rules, but I think we will gain clarity in the end.
Fix a typo in the add_sub_separated test, because it was testing
exactly the same code as add_sub_cumulative.
Add two new tests and clarify documentation, because in these tests
the order of the abilities determines whether the add or sub value is
used, it isn't that sub always overrides add.
1. race/alignment/attack damage type/attack range show corresponding icons
2. attack damage type/range now use comboboxes for custom dmg types/ranges
3. quit confirmation added to cancel button so that user doesn't accidentally lose their data
1. When addon is selected using Add-ons > Select active Add-on, the Unit menu will get activated so that the unit type editor can be used
2. Simplify initialize_addon_if_empty, returns success value as bool
The tag_name check is deficient for two reasons:
1.when apply_to=both is used, in the case of [damage_type] [filter_opponent][filter_weapon]type= will check the modified type for application to the owner and the original type for application to the opponent, hence a risk of infinite recursion, especially if [filter_self][filter_weapon]type= is used in the same weapon.
2. in the case of apply_to=attacker/defender, the check for [filter_attacker/defender] must take into account both the value of the variable is_attacker but also the application AFFECT_SELF/OTHER, otherwise in the case apply_to=defender with [filter_defender][filter_weapon]type=, and[filter_attacker][filter_weapon]type= otherwise we end up in the same configuration as for apply_to=both
Finally tag_name is renamed check_if_recursion to mean that this variable is used to ensure that a recursion cannot be set up even if 743b146efc prevents it from causing a crash but with an error log
I changed some of the lines in NR The Pursuit to fit better with the different characters. Tallin, Abhai, Krash, etc.
I did not do it for every dialogue.
Addresses issues #8319 and #8772
More PR review feedback addressed by Wedge.
---------
Co-authored-by: Wedge009 <wedge009@wedge009.net>
- widget:add_item_of_type() now uses lua 1-based indicies and throws lua errors on wrong indicies. (previously used c++ 0-based indexing, and could lead to assertions when wrong indicies were used, )
- widget:add_item() now has a optional location pos parameter as claimed in the wiki
- the pos and count paraemters in widget:remove_items_at() are now optional and default to removing the last element
With this is matches the behavior of the standart lua functions table.insert and table.remove which is imo what lua writers expect.
1. remove obviously English and English sounding female names from Dunefolk female names list
2. remove 'bakri' from male name list (means 'goat', could be offensive)
3. remove one potentially offensive name from saurian name list
4. remove 'Dalal' from dunefolk female names (can be used as slang)
The arrow class shouldn't be in charge of adding to the drawing buffer. Also it meant that in a case of multiple arrows padding through one hex, multiple buffer entries would be added. Now it will use one per hex.
This function is implemented identically, though const, in display_context (the base class of game_board). We don't need the non-const game_board function here.
`side_colors` in `init_flags` was unused. It used to get passed to `image::set_team_colors`, but that was removed. Also, both calls to `init_flags_for_side_internal` were identical, so it makes more sense just to remove the private function. And it means less messy index handling of teams().
- give side 1 starting villages near the orc base
- move Kapou'e to his keep at start
Co-authored-by: Tahsin Jahin Khalid <5283677+knyghtmare@users.noreply.github.com>
* SOTBE-S3: make allied AI smarter
- they wont attack from poor defense anymore
- will only attack from hills where they have better defense
* SOTBE-S3: fix bad code in side AI
---------
Co-authored-by: Tahsin Jahin Khalid <5283677+knyghtmare@users.noreply.github.com>
if filtering type of damage in [damage_type] for both self and opponent when apply_to=both, it will create a recursion issue.
Idem for apply_to=attacker/defender when applied to opponent of owner of special.
1. config.cpp: replace angle quotes with typographic single quotes
2. config.hpp: typo fix
3. widget_definition.cpp, window_builder.cpp: show id for window/widget
4. wml_exception: implement missing tag message, use typographic single quotes in missing key/tag messages
* Death Squire optional advancement and damage nerf
The existing {ENABLE_DEATH_KNIGHT} macro allows Revenants to advance to Death Knights. The newly core-ed Death Squire also advances to Death Knight, but has no {ENABLE_DEATH_SQUIRE} macro.
I suggest adding a new {ENABLE_DEATH_SQUIRE} macro, while keeping the old {ENABLE_DEATH_KNIGHT} for backwards compatibility.
I also propose reducing the Death Squire's attack from 8x4 to 9x3, to make the Revenant a more competitive advancement.
Who's the current maintainer of SotA? Should {ENABLE_DEATH_SQUIRE} be used there, or should we continue using {ENABLE_DEATH_KNIGHT}?
Hejnewar, if you approve, what cost should the Death Squire be after this change?
* Reduce Death Squire damage from 8x4 to 9x3
* Update Skele_Death_Squire.cfg
Without the change build fails on upcoming `gcc-15` as:
In file included from src/desktop/paths.cpp:20:
src/filesystem.hpp:232:13: error: 'uint8_t' was not declared in this scope
232 | std::vector<uint8_t> read_file_binary(const std::string& fname);
| ^~~~~~~
Using four abilities instead of two means the C++ checking_tag
mechanism needs to handle multiple values, or needs to be supported
by recursion counting.
The branching test lets one level of recursion finish, and then tries
to go deeper. This tests for bugs where a recursion detection tool in
the engine gets its count reset when exiting one level of recursion.
This adds a recursion counter which runs on a per-weapon basis; if the
recursion limit is reached then the last level of recursion is assumed
to have returned false. A warning is printed (with error severity).
At the user-visible layer, that gives the following logic:
* Abilities that depend on another ability being active will be
inactive.
* Pairs of abilities, where X depends on Y being inactive and Y
depends on X being inactive, will end up with them both inactive.
The limit is defined by ATTACK_RECURSION_LIMIT in attack_type.cpp.
The minimum for passing all the unit tests is 2, but I've left some
headroom by setting it to 4.
With the recursion limit set to 1, the following tests fail, which
seems reasonable because they're checking that the special is on
a particular type of weapon.
* event_test_filter_attack_specials
* event_test_filter_attack_opponent_weapon_condition
* event_test_filter_attack_student_weapon_condition
Output from the four_cycle_recursion_branching test:
```
error unit: Recursion limit reached for weapon 'melee_attack' while checking filter 'special_type_active = parry'
error unit: Recursion limit reached for weapon 'melee_attack' while checking filter 'special_type_active = poison'
error unit: Recursion limit reached for weapon 'melee_attack' while checking filter 'special_type_active = damage'
```
There's deduplication to prevent the logfiles getting spammed during
AI turns. As implemented, the two tests mentioned below print 3
messages each; these tests are added in separate commits because the
tests are shared between PRs while we discuss the right mechanism for
guarding against recursion.
With no rate limit:
* four_cycle_recursion_branching prints 1280 logs
* event_test_filter_attack_student_weapon_condition prints 320
With a rate limit via a flag that's reset in recursion_guard's destructor:
* four_cycle_recursion_branching prints 80 logs
* event_test_filter_attack_student_weapon_condition prints 160
Resetting the flag in specials_context_t's destructor gets better numbers,
but splits the logic across .cpp files. I think the trade-off isn't worth it:
* four_cycle_recursion_branching prints 40 logs
* event_test_filter_attack_student_weapon_condition prints 132
Co-authored-by: newfrenchy83 <eric.belleux@gmail.com>
* Update xBRZ to v1.8 (resolves#8307)
This replaces our implementation with stock xBRZ sans any of our custom code. Made these changes from plain source:
- Renaming .h -> .hpp
- Conditionally use [[likely]]
- Added a trailing newline
- Comment out unused parameters
- Disable `-Wunused-function` warning on macOS
There are no callers in mainline. The functions are not meant to be called directly at all – for each, there are wrapper functions that are intended to be called instead, which are still exposed.
This specifically manifested with the new minimap rendering code. Since we were creating a new temp texture onto which to draw the minimap before drawing it to the window texture, the formerly set clip rect was incorrect when the old viewport was restored:
For a minimap texture of 738 x 912:
Clip before changing target: `[0,0|330,200]`
Clip after changing target: `[0,0|738,912]` (covers whole of new target)
Clip after old target is restored: `[476,55|330,200]`
It's unclear where the extra x,y values came from, but I suspect it's some issue with SDL's internal viewport handling.
This builds on the work in cca82c4c3a. There, I delegated the ctors to the `value` strict via a forwarding ctor, but it honestly seems better to just remove the value struct entirely and just have class members. There isn't anything that relies on `value` as a distinct type anymore anyway.
The change in minimap.cpp is to deal with build errors that suddenly emerged with this change.
This is a series of mostly minor changes to the encyclopedia:
- The Wesnoth Calendar has been renamed to Wesnothian Calendar.
- The calendar page now explains YW, BW, and AF. As far as I’m aware, these are not explained in-game despite their use.
- The unused file drakes.txt has been removed.
- The Great Ocean section now mentions the drakish name World Ocean and some drakish mythology from drakes.txt.
- The Great River page has had a section on the Ford of Abez added. This is partly copied from the wiki (section copied appears to have been added by Esr, 8 October 2008)
- Morogor has had Mount Krogor been added as a notable land feature in the encyclopedia, taken from drakes.txt.
- The Green Isle section has been greatly expanded to include details on settlements and terrain. I thought it would be useful to have this, as the Green Isle is the original home of the Wesnothians and a major part of the setting of TRoW.
- Added a short sentence on the Old Continent being the original homeland of orcs and humans.
- Westin has been added to the Wesnoth page.
- The Isle of Alduin has been added to the Wesnoth page.
- A section on the Green Swamp has been added to the Wesnoth page. This is copied from the wiki. (section copied appears to have been added by Octalot, 21 September 2021)
- The section on notable cities for the Southwestern Elves has been removed due to the lack of known cities in the region.
- The Northlands description has been modified.
- The local orcish names for the Heart Mountains are now mentioned on the page for the Heart Mountains.
- Tirigaz and Jotha now have short one-sentence descriptions.
- The Desert of Death has been added to the far north section.
- Various land features from the far north have had short descriptions added.
- A section on the Far South has been added. It does not expand much on current lore except for some mentions of monsters. It only includes the Mountains of Peril, Sandy Wastes, and the Black Forest (moved from Southwestern Elven Lands and slightly modified) and is intenced to be very vague to allow UMC creators to imagine details of the Far South.
Ensure that there is no coroutine yield between confirmation of login
and update of player_connections_. Otherwise another login under same
name could succeed if it happened before handle_player() which resulted
in an assert later.
Makes all the cache management functions local to the cache class. There's no reason
to publicly expose it through locator given that the actual cache objects which that
API needs to function are local to this translation unit anyway.
This also cleans up the cache implementation in order to take advantage of the switch
from a vector to map awhile back. `copy_from_cache` was removed in favor of bounds-
checked access.
Add two maintenance scripts, to help transition from external copyright tracking to putting all info in the file metadata.
- One script to read read copyrights.csv and write data to Exif tags.
- One script to read the image Exif tags, and write to a CSV
This comment existed when the unit was still in EI campaign. It's been moved to core ages ago and yet, the comment, now no longer relevant outside of EI still persisted...
The code was moved to abilities.cpp so that it can be called from the units or attack_type functions, the attack_type function state necessary for the tags [filter_special_active] and [remove_specials] which I plan to implement when the code for filter_ability] is validated in its final form.
This allows permanently hiding the obnoxious help text tooltip that
constantly dances between the top and bottom of the screen depending
on what you're doing in the editor.
Icons provided by babaissarkar.
It's honestly not entirely clear what the right behavior is here. The way it is, to_bool is implicitly being invoked, which, given that this is supposed to hold an int, would always return false. And checking the int value doesn't seem to make sense either, since that would only exclude turns=0 (which would be a dumb value, but I'm not sure that's what this is for. So I figured a 'has attribute' check is best.
This avoids issues when building with Clang in C++20 mode. It seems in C++20 (possibly as a
result of vector gaining constexpr functionality), the rule about not referencing incomplete
types in a vector is now more strictly enforced.
See also https://www.lukas-barth.net/blog/cpp20-vector-incomplete/
* New "Apply" button in preferences dialog that is used to quickly apply the GUI2 theme, no restart needed.
* gui initialization reorganized a bit. gui2::init() now responsible for reading themes from file only. Actual theme switching and activation done by gui2::switch_theme(). preferences dependency removed from gui and moved to caller of gui2::init(). gui2 tests updated accordingly.
Opens load map/save map as dialogs in the addon's map directory if an addon is selected.
With no addon selected they open in the editor/maps directory.
* make drop caps utf8 aware and use locale's script font
1. Uses utf8::insert to modify the string so that it works for non-ASCII characters.
2. Use the locale's script font from data/hardwired/fonts.cfg instead of using Oldania always.
* make the algorithm work for multiple start tags in the tip text
* update condition to prevent throwing exception and don't use utf8::size
* adds comment that the tags do not have multibyte characters
These may be less efficient in some cases, and there's even a couple of degenerate cases, but it's definitely easier to use like this.
This also adds an example of the original method, using a string to reference a separate list.
Previously `synced_context::undo_blocked()` sometimes returned the worng result, leading to OOS because `synced_context::undo_blocked()` was used to determine whether we can send action to the other clients.
With this patch `synced_context::undo_blocked()` not doesn't always return true when its called during "local choices".
I am curently not even sure whether that line is needed at all since using the rng should always set is_simultaneous_ to true.
Even tests that don't have "_bug" in the name shouldn't prevent
intentional changes to behavior, I've added a paragraph about that.
Rewrite the non-reservation of "break" and "error" for clarity.
* Eastern Invasion
* fixed Gweddry having the wrong HP values
* fixed the king being neutral instead of lawful
* fixed "Dark Shape" being neutral instead of chaotic
* the king can no longer wield the plague staff
* the king and generals can no longer recall undead veterans
In EI S11, the player encounters an orcish warlord named Dra-Nak. If not killed in S11, he continues pursuing the player in S12, but the current S12 gives him different traits and a different portrait. This PR fixes the issue.
EI's S17b has a gold refund mechanic, allowing enemies to build up large gold reserves in certain situations.
When gold gets high, enemies are supposed to start recruiting higher-level units so they can spend it faster. The former implementation had some inconsistent issues; this should restore the intended behavior.
In EI's S99, you gain gold from defeating and capturing hostile drakes. The drakes are physically moved to prison cells in the middle of the map.
Previously, the player could continue capturing drakes even if the prison cells were captured by enemies. This made it a strong strategy to abandon the center and turtle up in a corner of the map. Additionally, the prison cells stayed locked with prisoners inside.
This PR fixes this issue. This also adds 2 new strings; I'm planning to backport to 1.18.2, as this is arguably a bugfix.
EI's S11 and S99 have prison cells, one of which has an unintended backdoor entrance via an unwalkable deep water river. Flying units are involved in these scenarios, and can possibly fly into the cells through this unintended backdoor.
This PR changes the map hexes from unwalkable to impassable.
Game_title_background can be a comma separted list of backgrounds.
if multiple backgrounds are present, one of them will be chosen at random when the UI reloaded.
Behavior should be generally as in 1.18 except for interpreting relative paths
normally instead of under $HOME. The latter was warned about for quite a few
versions now.
Also make sure normalize_path does not cause the path to become empty.
Avoid discarding the entire copyrights.csv when running the update on Windows, and force slashes in file path strings if adding new files.
* Also rename hash object to avoid collision with built-in hash function.
* Clarified file object is representing a file path string as opposed to an actual open file object.
Reading the preferences will now:
* read the default preferences (if defined) and add them into the preferences config
* read the unsynced preferences and add them on top of any default preferences
* read the synced preferences and add them on top of the default and unsynced preferences.
Writing the preferences works basically the same way, just that it writes out preferences to either the synced or unsynced preferences file depending on the preference. This is determined by the std::arrays added to preferences.hpp and is checked at compile time via the static_assert these these arrays and the prefs_list are all constexpr - forgetting to add a new preference or remove an existing preference to these arrays will cause a compile error.
This also means that unknown preferences will not be written back out, so the removal of any existing "password" and "password_is_wrapped" preferences no longer needs to be explicitly done. Additionally, the clear() and erase() methods are removed:
* clear() is not desireable in the first place and it's not actually applicable to anything currently using it since they're just single attributes at the root of the config object anyway
* erase() is a one liner method that's not needed anymore since all handling now has access to the preferences_ config object
For GCC-13, cfb28fbfb5 (in master)
added -Wno-dangling-reference, and that commit explains why the
false positive is triggered by calling find_widget. For GCC-14
there's an attribute so we can flag this specific function as ok.
Clang complains about unknown attributes in the gnu:: namespace,
so has to have the #if, and the #if means we need the #ifdef.
There are still warnings in src/actions/attack.cpp, but that area is
being worked on for an infinite recursion bug, and those warnings log
in a single batch instead of being spread across multiple .cpp files.
(cherry picked from commit e42f83a8d2,
with an improvement to the documentation after cherry-picking)
These are causing warnings with GCC-14.
An iterator can often be a struct containing a single pointer, so
creating a reference to such a small struct doesn't make sense.
The structure returned by child_range is likely to be exactly two
pointers, so it's not a burden to keep it even though back() has
already finished accessing the child_iterator.
(cherry picked from commit 087fa65dc5)
Appears to be unused, and is still Python2 code. To be Python3, these
lines need to change:
- f = file(fn)
+ f = open(fn, encoding="utf-8")
- gettext = f.read().decode("utf8")
+ gettext = f.read()
Even knowing how to make it work, it still doesn't seem useful to keep.
wmlunits uses html_output.Translation, but that's not this class. It's
a wrapper around Python's standard gettext library, in html_output.py.
dawn.png was leftover from the Time of Day being shown with an overlay
image; 074e157400 removed dusk.png and
night.png. The image itself should be a transparent blue hexagon, but
the alpha channel was corrupted, and so it appeared completely
transparent.
In copyrights.csv, make the capitalisation of Kitty's name consistent,
and attribute the orb-disengaged.png image.
When the user types something into the filter box and then changes to
a different version, apply the filter immediately instead of showing
the full list of files.
The drop-down to switch between directories is hidden unless savegames
from other versions are detected. The button will appear at the
bottom-left in master, and at the top of the dialog in 1.18.
Map/Scenario Editor
* Rename Load Map to Load Map/Scenario (since it can load both), Edit Scenario to Edit Scenario Settings, Save Map to just Save.
* Rearrange menu order
* Add icon for the preferences menu item (used the preexisting settings.png icon)
* Open folder correctly at Add-on's scenario directory instead of editor/scenarios. (#8910)
* Show Save Scenario As only for Scenarios
* Use the settings.png icon for Preferences menu item
* Add functionality to "Loyal" checkbox (Unit tool -> Place unit -> Right click menu) (#8445)
* Show warning when maps are saved in scenarios folder or vice versa (#8911)
* Unit List moved to Units menu from File menu to reduce some pressure from the latter.
* Status Table menu item disabled since it does nothing. (Should be reenabled once the functionality has been added.)
* Improve reload functionality in Editor (F5). Reload happens directly from memory and no temp files are needed. Also, the undo/redo stacks will be preserved. (#9024)
Time Schedule Editor
* Browse buttons now set wesnoth style paths instead of just pasting the absolute path returned by the file dialog
* Change text boxes from inactive to uneditable.
* Code generation improvements
* Add copyright notice to tod_new_schedule
* Confirmation messages
* Preview buttons for image and sound files and new icons for the preview button (2 sets : preview image and preview sound)
Unit Type Editor
* Confirmation messages
* New icons for the preview button (2 sets : preview image and preview sound)
Add-on menu
* Two new menu entries for (1) opening the Add-on selection dialog, (2) opening the folder corresponding to the Add-on
The open add-on folder option shows a GUI2 file dialog at the add-on's folder which can be used to open any file. If it is a loadable map/scenario it will be opened in the editor, otherwise the OS's default application for that file will be opened.
File Dialog
* Redesigned with new icons
* New Open External button that opens selected file/folder in the platform's default application (independently of what pressing Open would do). This could be used to quickly open a folder or preview the file before actually selecting it.
* Extension checking and filename validation. (See #8911)
Since 05d1e4b9ba, the client interprets require_modification="" as
defaulting to "yes". However, wesnothd was still defaulting it to
"no", causing an error message when trying to join games.
Fixes#8805 "Add-on version check prevents joining game".
In the case of [leadership], the fact that the values of each ability can be added when cumulative=yes can justify the addition of limit values not to be exceeded, but this can also apply to heals and [regenerates] with the use of 'add' or 'multiply'.
As for [resistance], it already uses max_value, but if cumulative=yes, then all max_values can add up which could be problematic.
If [damage_type]apply_to= is applied to a unit that does not have the range attack equivalent to that of the user this type will still be shown, which should not be.
Changes:
* CHECK_STRIKES macro now takes a comma-delimited list of strike counts for when units have a different number of strikes for different weapons, and updates the existing usage in the attacks tests
* Fixed a typo in the attacks_zero test
* Adds tests for berserk as a weapon special ability.
Berserk's handling differs from attacks as a weapon special ability:
* A value less than 1 is treated as effectively infinite rounds of combat (undocumented)
* The cumulative attribute is handled differently - in some cases it sums the values instead of using the highest single value whereas for attacks it always uses the highest single value
Also now exclude data/tests/ from scons pot-update since it was hitting the argument limit for number of arguments to a script.
Flathub linter complains about mismatched id in flatpak manifest and
appstream. Based on appstream docs it seems that reverse-DNS name is
expected without .desktop extension so appstream should be changed.
Extra <provides> and <replaces> tags added as per
https://docs.flathub.org/docs/for-app-authors/metainfo-guidelines/#renaming-id-tag
Owaec has a crown but little other indicator that he's a leader, and this scenario requires him to be used to recruit. Make it more obvious to the player.
Formerly, EI S13 uses various Deathblades' max-moves status instead of [filter_second] for some reason. This breaks when deathblades get rebuild, which in the bug report was caused by the sentinel shield. Use [filter_second] instead.
Resolves#8969
In EI S10, Dacyn picks up a cursed amulet and his HP drops to 1. In EI S11, Dacyn remains on very low HP, and is surrounded by orcs. There's a convenient ford hex he can hide on and be protected, but several players did not notice this hex and complained about difficulty.
In S10, this commit also drops his XP to 0. 1) showing that the amulet interferes with his MoL-ing, and 2) preventing the player from deliberately AMLA-ing Dacyn in the next scenario (partially a difficulty issue, but mostly it's bad to punish blind playthroughs / reward foreknowledge).
In S11, this commit adds a gold pile on Easy/Normal hinting towards the hex, while on Easy Dacyn's HP is fully restored. Hard is unaffected.
In S12, this commit restores Dacyn's HP on Easy (since it would be odd if he had full HP S11 but low HP S12).
The current preferences handling is a mess:
* it's essentially a global config object that anything can modify in any way the caller wants, which is managed across multiple source files which have their own oddities and interdependencies.
* the general preferences has its own bit of SDL event handling and while I get the idea behind `events::sdl_handler` there's no reason to have SDL events handled in the preferences instead of just calling the relevant preferences setter for each event when it happens.
* the general preferences is where most of the preferences are handled and has its `base_manager` struct, which is part of the `manager` struct in the game preferences, which is then implicitly initialized as part of game_launcher's constructor.
* the editor preferences are the only preferences in a sub-namespace `preferences::editor` while all other preferences are just in the `preferences` namespace.
* the display, editor, and lobby preferences are all dependent on including the game preferences, the credentials are dependent on including the general preferences (but not the game preferences), the game preferences are dependent on including the general preferences, and the advanced preferences are entirely their own thing which is dependent on none of the other preference functionality and manages its own singleton.
* nothing checks whether the preferences file has actually been loaded before allowing values to be read from or written to the preferences config - if you attempt to get a value too early in wesnoth's initialization it will silently just give you whatever the default value for that preference happens to be.
With this there is instead a single access point (with exceptions handled via friend functions/classes), all predefined preferences are accessed via their own setter/getter, and all mainline preferences are defined in a single file (preference_list.hpp) so it's easily findable what preferences exist and where they're used. Having the list of all mainline preferences listed out also allows the lua preferences API to provide that full list rather than just the list of the preferences that have been set so far. Also it now checks for whether the location of the preferences file is known before attempting to load the preferences file and asserts if someone attempts to use the preferences too early.
https://www.reddit.com/r/wesnoth/comments/1d6a3e7/eastern_invasion_is_much_better_but_still_bad/
EI's S10 is overly hard on Normal, and especially on Easy (which is intended to be a very accessible difficulty). This PR increases the available gold and adds several villages, which aid in both defense and upkeep. This PR also drastically reduces the number of orcs on lower difficulties.
We also move Owaec to his keep to help imply his ability to recruit, and remove the related just-added [note] string to avoid violating 1.18.1 string freeze.
A weapon with poison, which does extra damage to poisoned opponents.
This tests that the weapon-special's filter is checked on each strike,
instead of being tested once and then cached during the battle.
(cherry picked from commit 55aa8b44cf)
Instead of needing to contain the exact string from the ability, 'apply_to' in the filter is now taken as a comma-separated list, where all elements need to be present in the ability.
For example if we filter for apply_to=fire,arcane given an ability [resistance]apply_to=arcane, fire, cold, it will match.
For an ability [resistance]apply_to=arcane, impact, cold, this will not match because 'fire' is missing.
When any of the images is missing, a text description is shown as a fallback.
The bug being fixed is that the search for the secondary PNGs used the basename
with neither the directory nor the ".png".
The existence of the files controls a single conditional block, but was using
three bools with two dedicated to single files and one shared between all the
alternate files. This changes it to a single bool shared between all files for
clarity.
A rich text label widget that can show text marked up with help markup.
Also includes the GUI Test Window, accessible in the title screen after launching wesnoth using --clock option. It can be used as dialog template/example or as a place to test GUI2 code.
In add-on form, EI used images to display "Part II" and "Part III". For translation reasons this got replaced with ugly title_text when the add-on went mainline.
This PR once again makes the "Part II" "Part III" storytext more fancy, while maintaining translatability.
When a [damage_type] affected an attack, the old code assumed that it would have an alternative_type.
If that assumption failed, it would add ("type_" + an empty string), causing "UNTLB type_" to be shown
in the sidebar.
UNTLB is itself a shorthand for "untranslatable", see language.cpp for an explanation.
There's no particular reason why Delfador should say this during HttT, but perhaps it will make the connection to the campaign clearer.
Closes#8365.
[ci skip]
The link with details about individual compaigns is useful to players,
even if they aren't looking to become translators. So move it upwards.
The text about first-time players seemed confusing to me, as the choice
is already limited to languages that the player can read. Reworded it,
but after discussion in the PR, neither version was better than just
removing it.
Currently for the vertical listbox only, since it does have some quirks. Removes the assert in the "show" policy checking if the callback is null. It won't be for the listbox, but doesn't really matter since it's not used.
Namely, it not working. At this point, the viewport had already been set to the local coordinates of the widget, so the draw origin needs to be 0,0, not the widget's position in screen space.
Many turns into EI S17b, a pre-existing lich changes sides and transforms into Mal-Ravanal.
Before this commit, this process would un-capture any villages previously captured by that side, causing Mal-Ravanal to waste turns retaking them.
To complete EI's S06b, the player must fight through a necromancer and his bodyguards. Prior to this commit, the necromancer's bodyguards did not vary by difficulty, making Easy disproportionately difficult.
Other leaders do not need to be fought directly to win. In addition, this is an optional mission labeled as more difficult. Therefore, I haven't adjusted other leaders' guards' difficulty scaling.
https://forums.wesnoth.org/viewtopic.php?t=57915
S04b's alternative objective involves collecting herbs that semi-randomly spawn around the map, hidden under fog. Herbs spawn in all directions, but the map layout and scenario design can lead players to expect herbs to all be in the east. This objective note clarifies herb placement.
https://forums.wesnoth.org/viewtopic.php?t=57915
Lua was getting this variable without being told it is a number rather than a string. On some systems it is interpreted as a string which breaks this monster spawner code and throws Lua error messages onto the player's screen.
EI's S09 has a small pile of gold some distance off the main path, visible through the shroud.
Without a label, players may over-commit units/upkeep to getting the gold without realizing it's only a small amount, and possibly worth skipping.
Units with traits may sometimes have quick and may sometimes not have quick. This causes civilians to randomly block certain castle hexes that the player can use to recruit.
Remove traits to prevent this random blocking. Increase MP 4->5 to prevent 2 castle hexes from always being blocked.
have external access to the preferences go through explicitly named accessors as much as possible rather than directly using get() and set(). also have the general preferences file directly use its `prefs` config.
it's a pet peeve of mine, but the name of a type is ie "toggle_button*" aka toggle_button pointer. the asterisk or ampersand is part of the type and should be separated.
The current S16 achievement requires that the player don't recall any units or have any items.
Some items are undroppable, which can make this achievement impossible if you give one to a loyal auto-recalled unit early in the campaign.
This PR alters the achievement to only care about droppable items.
* Redesigned the version dialog to serve as a general purpose About dialog.
* Credits button removed from title screen
* Moved community dialog contents to about dialog as new tab
Co-Authored-By: Pentarctagon
* Bugfixes to the tab_container widget
* Success indication mechanism on copy buttons
* bugfixes for unit type editor
1. accept space in unit type id
2. don't write translated string to generated wml
3. add textdomain at the top of the generated file
4. fix bad key in generated attack block
In "Ill Humors", 2 spawn regions for aswaldan herbs overlap, which can result in both spawning on the same hex without any special visual indicator.
Credit to PointMeAtTheDawn.
Instead store the preferences, credentials, and lua command history files in the userdata folder, same as is done on windows and macos.
Also removes another instance of _X11 for #8806
Instead set the Apple preferences folder from within the code rather than using -DPREFERENCES_DIR.
Remove -DHAS_RELATIVE_LOCALEDIR since that doesn't appear to actually do anything since its only usage is in filesystem_common.cpp, not filesystem.cpp.
Current implementation of translation::strftime() uses boost.
Boost docs do not appear to have a 'current' or 'latest' link, instead only making documentation available by explicit version number.
[ci skip]
Instead of the aliasing hack that the oasis terrain used to use, have
the help topic generator reuse the editor_default_base as a hint that it
should be included in that section.
The terrain_type class gets a new boolean method, and more documentation.
There's a couple of refactors to use the new method in old code too.
* Elvish Avenger - decreased ranged attack from 11×4 to 10×4, decreased cost from 66 to 60
* Elvish Sharpshooter - decreased ranged attack from 12×5 to 10×5, decreased cost from 62 to 55
* Elvish Shyde - decreased ranged slow attack from 8×3 to 7×3, decreased ranged magical attack from 14×3 to 10×3, decreased cost from 69 to 58
* Elvish Enchantress - decreased ranged slow attack from 7×4 to 6×4, decreased ranged magical attack from 13×4 to 11×4, decreased cost from 70 to 62, decreased XP requirement from 198 to 180
* Elvish Sylph - decreased ranged magical attack from 16×5 to 13×5, decreased cost from 161 to 135
Add-ons: checks for any that exist in the chosen other version but not in the current version.
Preferences: adds attributes that don't exist from the chosen other version's preferences that aren't in the current version's preferences. for attributes that exist in both, use the attributes from the file that was modified most recently.
Credentials: move if the credentials file doesn't exist.
Fixes#7936
* Moved the Show All Languages checkbox from the main body to the
bottom left of the dialog to save space and make it more obviously
connected to the listbox.
* Changed the Show All Languages checkbox label to reduce the word
count a tiny bit.
* Added text regarding translation percentages representing core
textdomains only.
* Added a link to gettext.wesnoth.org.
In 1.19 since 82499d0785, this will apply a
max_value of 15, which will also be the combined value.
The same test has surprising result on 1.18, the max_value attributes get added
together for a total max_value of 47, but the values don't, so the single
highest value of 30 is used.
(the corresponding 1.18 commit is 9632febdb5)
These tests clarify what "cumulative" means for non-leadership abilites,
which since Wesnoth 1.1.3 doesn't seem to fit the English word.
For cumulative abilities, if the base value from the unit is higher that
the ability's value, then the base value is used instead. In the case of
a Skeleton with 40% base resistance, "cumulative=yes" is equivalent to
"value,cumulative=40,no".
In all of these cases, a single ability's value is used; "cumulative"
doesn't mean that the values from multiple abilities interact.
This is all when using value=, not when using add= or sub=.
(cherry picked from commit 9b2016a4af)
I don't know if a bow attack is added in the objects but in any case I prefer to transfer the special oar in abilities in the same way as for the amulet
If two [damage_type]alternative_type= are used with two different types, the chosen type displayed in the pre-combat window will be the one to which the opponent is most vulnerable. That type will then also be used in the attack if it is stronger than the original/replacement_type.
In the sidebar (report) all alternative_types are displayed.
---------
Co-authored-by: Gunter Labes <soliton@wesnoth.org>
0aa8dc3 converted to a runtime test and broke the scons SDL version check since
it only links which trivially makes it work for cross compilation though.
Respect server options given as script arguments.
Fix killing background process in trap.
Use printf instead of echo.
Keep upper case variable names reserved for env variables.
Logfilter scripts converted to sed -E and removed GNUisms.
Original code from mesilliac in #6826. Made a separate PR for this since the relevant code moved to an entirely separate file and trying to "properly" fix the merge conflicts resulting from that isn't worth the time.
max_value is used to limit the increase in resistance with the "resistance" capability, but there was no equivalent for its reduction.
To be able to add min_value without redoing the "resistance" checking for the umpteenth time, I prefer to modify effect:: so that the checking of these two attributes is done at the same time as the other numerical attributes and keep the door open to a possible generalization of the proceed
The movetype data includes vulnerability to damage types, for example
`resistance_against("arcane")`. There was also a convenience wrapper
that took an attack_type, and returned the vulnerability to that
attack_type's damage type.
The logic of the wrapper is very basic, and does not use unit.cpp's
logic to check whether abilities that change the type are active.
Although it gained knowledge of alternative damage types in 3910817cf7,
it won't always return the same value as the unit.cpp function does.
The wrapper is now only used in FormulaAI, so let's move the code there,
which in effect marks it deprecated.
If a mouse click causes a delay and then a message to appear, for example
when moving a unit triggers an `[event]name=moveto`, then the message
would sometimes flash on screen and then disappear with barely enough time
to see which character's portrait was used, let alone to read it.
Although there's already logic to not be triggered by the same mouseclick that
caused the unit to move, it had a race condition if the MOUSE_UP happened
around the time the the dialog's pre_show() function was running.
(cherry picked from commit 26ead85914)
- `start_faded` was always true (the default value value was never used)
- 'skip_replay' was only set in playmp_controller which had already other
code to set it (also it is not used in the ctor)
From the ui point of view, there should be no difference between
network turns and ai turns, and the other play_.._turn functions
also work without such calls. (Furthermore this codes is really
old, so whatever the reason for its existance was probably doesn't
apply anymore)
Now its a bit easier to understand which functions are in play_controller adn which in playsingle_controller as all turn related functiosn are now in playsingle_controller
Previoulsy send_actions() was called at random
parts of the code in a "better safe than sorry"
manner, which made it hard to understand when
actions are sent or which of these calls is needed.
The new approach is:
- Chat, MapLabels and other unsynced messages are sent
regularily as part of playmp_controller::play_slice()
- Synced actions are sent as soon as they are undoable:
- which is immidiately in particular for end_turn and
init_side
- after every exceution of synced commands in the end
of synced_context::run() actions are send if the
actions cannot be undone.
Using this function lets te synced context know that the current
action cannot be undone, so that it will in particular send the
actions too all players as soon as possible. The intention is
less delay in networked games.
Currently there is some redundance between is_simultanious_
and is_undo_blocked_, maybe one of these will be removed
later.
process_network_data() Now always 'procecesses'
synced choices, since they are never exceuted
anyways just put on the recorder. so chat_only=yes
now only delayes new actions. This allows us to implement
receive_actions() by just calling
process_network_data().
This change also make the game execute other unsynced
actions like map labels sooner, along with chat messages.
We now handle the case that the player becomes host during
wait_for_upload() and make the code more robust in case
[notify_next_scenario] is received at a unexpected time.
I am not really sure whether this is actually needed or whether it
actually worked before for some other reason, in any case the new
code is simpler and safer.
To make the code simpler.
the sp linger function calls play_slice() which playmp_controller already overwrites, after a little fix of that we can remove a bit of code
All of its functions were moved to playmp_controller. Since they
were already so interconnected, this makes things a little easier.
Also it was always a bit confusing that this class was called
turn_info when all it did was to process network data.
Since 1.18 linger() is called indirectly by play_scenario_main_loop()
and play_scenario() which already catches therse erros and offers the option to save the game then.
The special handlng of ingame_wesnothd_error was removed since it
was only added to fix the case of the host leaving resulting in the
game aborting (which should no loner be the case)
1) We remove the syncmp_handler class which was a
bit too complicated for its rather simple task
2) We move network related stuff out of playsingle_controller
If the first trait of a unit has no name, then clicking on the units (other)
trait in the sidebar opened the wrong page in the help.
(cherry picked from commit f9af941f1e)
Not mentioned here, but turning on debug mode also affects which units,
and therefore which units' traits, are shown in help.
Having looked back into the history while wondering why it was done this way
in e9603e6e01, back then we needed a fix that could be backported to 1.14,
so couldn't add a new attribute to [unit_type].
s1m0n was in the credits for 1.16, but that was missed when his contributions
were copied to master. Fix that, along with adding his latest updates.
The fuzzy flag in -wof probably got readded by mistake when rebasing.
Setting up vcpkg tries to build xz from source, which fails because the
entire xz repo has now been made private or taken down. The vcpkg team
have been advised not to switch to an alternative repo [1], so for now
our Windows builds will always fail.
Turn those builds off, so that we don't get familiar with seeing red
status markers on all PR's CI results.
[1] `https://github.com/microsoft/vcpkg/pull/37957` - second comment is
the vcpkg team's "We have been explicitly asked by security folks to not
change the upstream [to a different repo] for liblzma at this time."
When [damage_type] is used but the opponent uses the resistance ability
against the added type, the ability filter only detected the original type and
the new type was not affected.
The original code was probably meant to strip trailing whitespace, which
turned out to be a bug when 4be9aa8584
fixed the buggy regexp so that it started working. That has now been
removed.
Fixed handling of multiline plural strings, which was broken too.
One feature has been left unimplemented, and will cause wmlxgettext to error
out. For "long bracketed" strings, Lua allows the contents to start with a
newline, which is automatically stripped from the resulting string. Trying to
understand the original purpose lead me to this feature of Lua strings which we
don't use in Wesnoth; and I finally concluded that, if someone wants to use
that feature, it can be their problem to implement it.
This fixes commit 4be9aa8584.
(cherry picked from commit e4239634e5)
While it sounds like a great idea on paper, in practice having the
language column have the same height on all rows causes issues because
of at least one entry having an unusually tall label because of
non-Latin characters involved in it.
[label] does not support setting the vertical alignment of text — only
the vertical alignment of the widget itself can be set. This doesn't
help in this case because the widget is always as tall as its row —
it's the text's positioning that needs adjusting.
It turns out to be a better look to have all text be vertically
centered by not letting the label's height be dictated by the row's,
and let the layout engine center the label if needed for any reason.
This overhaul introduces a GUI option to show all languages regardless
of their completion threshold, as well as a side panel including a
general explanation of community translations and how players can
potentially contribute to them, plus a link to the main translations
page on the wiki.
A few points to make here:
* The URL points to the main page on purpose, since it's meant to be
a catch-all for all languages regardless of which one the player
has got selected or configured (those are two different things at
the moment).
* There's an issue where when showing all translations, some of the
non-Latin translation names cause the baseline of the language
name labels to end up entirely misaligned with the completion
labels. I am not entirely sure how to fix this right now.
* Showing all translations alters the dialog's layout permanently. I
believe there's no way out of this with the current GUI API.
* We use the stock text colouring function used for unit defence
values. This might not be entirely ideal because they are all very
green for translation stats above the minimum threshold, so there's
basically no variance by default until all translations are shown
together.
* An idea could be to add a link to the gettext.wesnoth.org stats
page in the dialog.
Currently even though the results ultimately don't display duplicate information for the modifications used, the resultset coming back does have a row per modification and player, so it appears as though the player list is duplicated.
Fixes#8619
In EI's S05, Owaec briefly recounts the bloody fate of his local priestess, killed by undead.
The scenario's music consists of wanderer.ogg and traveling_minstrels.ogg, which are inappropriate for encountering a mangled corpse.
Instead, fade the music out during this section.
This changes the URL used for the changelog menu item from using a
direct GitHub file link to the master branch's changelog.md file to
using a https://changelog.wesnoth.org/X.Y.Z link, where X.Y.Z are
specifically the version number used in the macOS bundle's Info.plist
file.
Note that this may result in incorrect links for +dev versions, where
the Changelog link will simply send the user to the page for the
latest release and not the future release. This shouldn't be a problem
though, since people using those builds, especially on macOS, should
really already know where to find the most relevant changelog for the
version they're running -- in their own source tree.
EI's S14 involves traversing a swamp with hidden undead. To make it easier for the player to remember which hexes they've cleared, mark the uncleared hexes.
Derived from the core water-plant.png and water-plant2.png images.
Copyright attribution updates by octalot:
They've been darkened since the original commit, but the swamp water
tiles in data/core/images/terrain/swamp are clearly Tommy(yobbo)'s
images originally added in f7cc2f1079.
The current water-tile.png seems to be a later addition, so I've
left it attributed to "unknown".
Co-authored-by: Steve Cotton <steve@octalot.co.uk>
Due to confusion between NULL and std::nullopt, these filters used
zero instead of nullopt as the default value for this argument. However,
the effects are limited to experimental_filter_ability and that tag's _active
sibling, and result in a false positive when the filter matches a value of
zero. With those constraints, I (octalot) am happy to apply it to stable.
This was detected as a compilation error when building with musl libc,
thanks to iFoundSilentHouse for finding and reporting it.
Before this change villages had a certain set % chance to grant player a unit upon capture. Now the chance to get a unit is dependent on difficulty, value of units player has already received and the amount of villages already captured.
No string changes, just adjusting when the hints at the top-left of the screen
appear and disappear.
The hint about crowns now appears after recruiting both elves, so that there
are units to compare the leader to, who have the same orb color but no crown.
The hint about traits appears when told to attack the quintain with the elves.
The player will probably find a strong or dexterous trait, and Delfador already
comments about those traits after attacking. Even if neither elf has those,
speedy or robust could also influence whether to use melee or ranged attacks.
There's now no hint on screen when first choosing which village to use for
healing; previously it was the hint about crowns which didn't seem relevant.
No strings are added in this commit, but a hint about checking the quintain's
movement range would fit here, see <https://r.wesnoth.org/t54644>.
(cherry picked from commit f7a0f119de)
Give .jpg files the same logic that .png files were given in
8f06da1974, because many files
were renamed in 51b58ad218.
UMC using the old name for images will trigger a warning, but
the player will still see the image file.
This is just a cosmetic change that doesn't change compatibility,
because have_asset("images", "blah.jpg") won't be automatically
redirected to "blah.webp".
(cherry picked from commit 84ed5488e0)
It *appears* that the migration prompt doesn't show up for steam players because steam automatically creates the <userdata>/saves/steam_autocloud.vdf file on start, since the saves folder is what's synced. Since the migration logic is looking for whether the userdata folder exists, this means it always exists when launched from steam.
So, fix that by checking a different subfolder under userdata (checking the logs folder is arbitrary, it could be any of them aside from the saves folder).
Testing by effectively droiding the player's side, the enemy side still lost even with 480 gold and otherwise default difficulty settings. So upping enemy side gold to 480 for all difficulty levels.
Action bonus - is often thought as inconsisnent and generally not very well understood not only by new players but aslo by players with mid tier experience, so removing it from initial setting should improve overall experience of a new player.
Turn bonus - 60 seconds is way too low and initial 270 is also not much for the whole game. 240/240 does better job at keeping the game in good pace while not being too opressive in my opinion, 360 reserve is aslo ok if you can save some time for more intensive turns.
Found with Xcode 15.3:
/Users/iris/Projects/wesnoth/src/game_config.cpp:551:18 Implicit conversion turns floating-point number into integer: 'double' to 'const int'
This adds the human-readable version of each unit's alignment and
their (gendered) race name and plural race name as hints for the
filter box functionality, so that players can enter keywords such as
"liminal", "dwarves", "mermaid" and get what they expect even if those
words are not literally part of the unit type names.
This makes it easier to add any number of text criteria for filtering
without making the conditional increasingly unwieldy. Criteria that
shouldn't count because of conditions disabling them (such as the unit
type id only being considered when debug mode is eanbled) can just
become empty strings which will never match.
This adds the human-readable version of each unit's alignment and
their (gendered) race name and plural race name as hints for the
filter box functionality, so that players can enter keywords such as
"liminal", "dwarves", "mermaid" and get what they expect even if those
words are not literally part of the unit type names.
This is necessary with Xcode 15.3 to avoid about 750 warnings across
all of the codebase regarding "Implicit conversion loses integer
precision", most of which apply in cases where theoretical limits are
involved because of conversions from unsigned 64-bit integers (usually
size_t) to signed 32-bit (int).
Ideally we want to address these warnings, but given how many of them
there are all over the place this is not something that can reasonably
be done in such short notice before Wesnoth 1.18.0 is released, and in
the meantime they make the compiler output with Xcode unnecessarily
noisy and completely bury any relevant warnings from actual code
changes. In the meantime, this is best for productivity until we can
get to a place where we can fix all of them and force using
-Wshorten-64-to-32 for all platforms in CI.
@ -171,6 +171,7 @@ option(GLIBCXX_ASSERTIONS "Whether to define _GLIBCXX_ASSERTIONS" OFF)
option(GLIBCXX_DEBUG "Whether to define _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC. Requires a version of Boost's program_options that's compiled with __GLIBCXX_DEBUG too." OFF)
option(ENABLE_POT_UPDATE_TARGET "Enables the tools to update the pot files and manuals. This target has extra dependencies." OFF)
option(FORCE_COLOR_OUTPUT "Always produce ANSI-colored output (GNU/Clang only)." FALSE)
Wesnoth requires a compiler with sufficient C++17 support such as GCC 8 and
Wesnoth requires a compiler with sufficient C++17 support such as GCC 11 and
later, or a version of Clang with equivalent support.
You'll need to have these libraries and their development headers installed in
@ -19,8 +19,9 @@ order to build Wesnoth:
* System
* Coroutine
* Graph
* Charconv (This requires boost 1.85 or higher and is optional but reccomended especially for clang builds)
* SDL2 libraries:
* SDL2 >= 2.0.10 (macOS: 2.0.22 due to needing https://github.com/libsdl-org/SDL/commit/3bebdaccb7bff8c40438856081d404a7ce3def30)
* SDL2 >= 2.0.18 (macOS: 2.0.22 due to needing https://github.com/libsdl-org/SDL/commit/3bebdaccb7bff8c40438856081d404a7ce3def30)
* SDL2_image >= 2.0.2 (with PNG, JPEG, and WEBP support)
* SDL2_mixer >= 2.0.0 (with Ogg Vorbis support)
* Fontconfig >= 2.4.1
@ -173,7 +174,7 @@ false value.
| `strict=<boolean>` | `ENABLE_STRICT_COMPILATION=<boolean>` | Whether to treat compiler warnings as errors or not. Primarily intended for developers. |
| `prefsdir=<directory name>` | `PREFERENCES_DIR=<directory name>` | Hardcoded user preferences and user data directory. The default is to leave this unspecified so that Wesnoth will use separate XDG paths such as .config/wesnoth and .local/share/wesnoth/<version> for its user preferences and data, respectively. |
| `cxxtool=<program>` | `CMAKE_CXX_COMPILER=<program>` | Specifies which C++ compiler to use. By default, the system's default C++ compiler will be automatically selected during configuration. |
| `ccache=<boolean>` | | Whether to run the compiler through ccache first. Useful if the compiler executable is not a symbolic link to ccache. Requires ccache to be installed first. If using CMake, use CMAKE_C_COMPILER and CMAKE_CXX_COMPILER instead. |
| `ccache=<boolean>` | `CMAKE_CXX_COMPILER_LAUNCHER=ccache` | Whether to run the compiler through ccache first. Useful if the compiler executable is not a symbolic link to ccache. Requires ccache to be installed first. If using CMake, use CMAKE_C_COMPILER and CMAKE_CXX_COMPILER instead. |
| `extra_flags_<buildtype>=<flags>``extra_flags_config=<flags>` | `CXX_FLAGS_USER=<flags>` | Additional compiler flags to use when compiling a specific build type (SCons-only). To apply the same flags to all builds, use extra_flags_config (SCons) or CXX_FLAGS_USER (CMake) without a build type suffix. Alternatively, you may specify your flags in the CXXFLAGS environment variable. |
| `fifodir=<full path>``server_uid=<UID>``server_gid=<GID>` | `FIFO_DIR=<full path>``SERVER_UID=<UID>``SERVER_GID=<GID>` | Directory and owner id for the wesnothd control FIFO file. This is relevant only if you wish to be able to communicate with a local wesnothd instance through a named pipe. You must run wesnothd with the same UID specified at build time for this to work. |
| `enable_lto=<boolean>` | `ENABLE_LTO=<boolean>` | Controls using Link Time Optimization. Enabling will result in a smaller, faster executable at the cost of increased time to compile and link. For cmake, use LTO_JOBS=N tells how many threads to use during linking. |
Additionally, Wesnoth is available for [iOS](https://apps.apple.com/us/app/battle-for-wesnoth/id575852062) and [Android](https://play.google.com/store/apps/details?id=it.alessandropira.wesnoth114).
Additionally, Wesnoth is available for [iOS](https://apps.apple.com/us/app/battle-for-wesnoth/id575852062) and [Android](https://sourceforge.net/projects/wesnoth-on-android/files/).
To build the game from source, see [INSTALL](/INSTALL.md) for instructions.