Skip to content

Commit

Permalink
Merge branch 'master' into cheat_enable_buildings
Browse files Browse the repository at this point in the history
  • Loading branch information
Flamefire authored Jan 21, 2025
2 parents e36a78e + 6b51676 commit 293be34
Show file tree
Hide file tree
Showing 17 changed files with 158 additions and 118 deletions.
Binary file modified data/RTTR/assets/base/fonts.lst
Binary file not shown.
1 change: 1 addition & 0 deletions data/RTTR/assets/base/languages.ini
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ Norwegian Bokmal=nb
Slovenian=sl
Latin=la
Portuguese=pt
Chinese=zh_CN
2 changes: 1 addition & 1 deletion data/RTTR/campaigns/roman/campaign.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ campaign = {
maxHumanPlayers = 1,
difficulty = "easy",
mapFolder = "<RTTR_GAME>/DATA/MAPS",
luaFolder = "<RTTR_RTTR>/campaigns/roman",
luaFolder = "",
maps = { "MISS200.WLD","MISS201.WLD","MISS202.WLD","MISS203.WLD","MISS204.WLD","MISS205.WLD","MISS206.WLD","MISS207.WLD","MISS208.WLD","MISS209.WLD"}
}
2 changes: 1 addition & 1 deletion data/RTTR/campaigns/world/campaign.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ campaign = {
maxHumanPlayers= 1,
difficulty = "easy",
mapFolder = "<RTTR_GAME>/DATA/MAPS2",
luaFolder = "<RTTR_RTTR>/CAMPAIGNS/WORLD",
luaFolder = "",
maps = { "EUROPE.WLD","NAMERICA.WLD","SAMERICA.WLD","GREEN.WLD","AFRICA.WLD","NASIA.WLD","SASIA.WLD","JAPAN.WLD","AUSTRA.WLD"},
selectionMap = {
background = {"<RTTR_GAME>/GFX/PICS/SETUP990.LBM", 0},
Expand Down
61 changes: 33 additions & 28 deletions doc/AddingCustomCampaign.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,16 @@ We will now create an example campaign `garden`.

## Location for adding a new campaign

To add a new custom campaign you have to create a new subfolder with your campaign name under `RTTR/campaigns/` in the install directory or under `<RTTR_USERDATA>/campaigns/`.
`<RTTR_USERDATA>` is the placeholder for the RttR folder in your user dir, e.g. `~/.s25rttr` on Linux or "Saved Games" on Windows.
To add a new custom campaign you have to create a new subfolder with your campaign name under `RTTR/campaigns/` in the installation directory or under `<RTTR_USERDATA>/campaigns/`.
`<RTTR_USERDATA>` is the placeholder for the RttR folder in your user directory, e.g. `~/.s25rttr` on Linux or "Saved Games" on Windows.
This subfolder will be filled with all the needed data for the campaign.
We create the subfolder `RTTR/campaigns/garden` for our new example campaign.


## Lua campaign description file

First we have to add a `campaign.lua` file to our campaign folder `RTTR/campaigns/garden`. This file describes the settings and needed stuff for our new campaign `garden`.

```
```lua
function getRequiredLuaVersion()
return 1
end
Expand Down Expand Up @@ -64,63 +63,70 @@ campaign = {
}
```

## Explaination of the semantic of the campaign.lua file
## Explanation of the semantic of the campaign Lua file

The `rttr:RegisterTranslations` function is used for the possibility of providing translation support for the texts displayed in the rttr campaign selection screen. If you do not want to provide any translation you can delete this function from the lua file and write your text directly in the specific fields below.
The `campaign` dict describes your campaign. The `getRequiredLuaVersion` function returns the version of the lua campaign interface.
The `rttr:RegisterTranslations` function is used for the possibility of providing translation support for the texts displayed in the RttR campaign selection screen.
If you do not want to provide any translation you can delete this function from the Lua file and write your text directly in the specific fields below.
The `campaign` dict describes your campaign. The `getRequiredLuaVersion` function returns the version of the Lua campaign interface.

### Versioning

The lua campaign interface is versioned using a major version. Everytime a feature is added or a breaking change is made (e.g. a function is removed or changes behavior considerably) the major version is increased.
The Lua campaign interface is versioned using a major version. Every time a feature is added, or a breaking change is made (e.g. a function is removed or changes behavior considerably) the major version is increased.

Every map script must have 1 function:
getRequiredLuaVersion()
`getRequiredLuaVersion()`
You need to implement this and return the version your script works with. If it does not match the current version an error will be shown and the script will not be used.

### Explanation of the campaign table fields

If you want a field to be translated you have to add the translation as described above and set the variable to _"<key>". The _"..." will translate the text during application execution depending on your language settings.
If you want a field to be translated you have to add the translation as described above and set the variable to `_"<key>"`. The `_"..."` will translate the text during application execution depending on your language settings.

1. `version`: Simple a number for versioning of the campaign
2. `author`: Human readable string of the campaign creator
3. `name`: The name of the campaign
4. `shortDescription`: Short description of the campaign (like a head line to get a rough imagination of the campaign)
4. `shortDescription`: Short description of the campaign (like a headline to get a rough imagination of the campaign)
5. `longDescription`: Extended description describing the campaign in detail. Will be shown in the campaign selection screen, when the campaign is selected.
6. `image`: Path to an image displayed in the campaign selection screen. You can omit this if you do no want to provide an image.
7. `maxHumanPlayers`: For now this is always 1 until we support multiplayer campaigns
8. `difficulty`: Difficulty of the campaign. Should be one of the valus easy, medium or hard.
9. `mapFolder` and `luaFolder`: Path to the folder containing the campaign maps and associated lua files. Usually your campaign folder or a subfolder of it.
10. `maps`: List of the names of the files of the campaigns mission maps
8. `difficulty`: Difficulty of the campaign. Should be one of the values easy, medium or hard.
9. `mapFolder` and `luaFolder`: Path to the folder containing the campaign maps and associated Lua files. Usually your campaign folder or a subfolder of it.
10. `maps`: List of the names of the files of the campaigns' mission maps
11. `selectionMap`: Optional parameter. See [map selection screen](#selection-map) for detailed explanations.

Hints:
- To work on case sensitive os (like linux) the file name of the lua file must have the same case as the map file name. This applies to the map names in the campaign.lua file too.
For example: `MISS01.WLD, MISS01.lua` is correct and `MISS01.WLD, miss01.lua` will not work on linux
- The lua file of a map must have the same name as the map itself but with the extension `.lua` to be found.
- The lua and the map file don't need to be in the same folder because the path can be specified separately.
- If `mapFolder` is not specified or empty it defaults to the folder containing the campaign lua file.
- If `luaFolder` is not specified it defaults to the `mapFolder`.
- Both paths can start with placeholders like `<RTTR_GAME>`, otherwise they need to be only the name of a folder relative to the folder containing the campaign lua file. I.e. multiple levels are not supported.

- To work on case-sensitive OS (like Linux) the file name of the Lua file must have the same case as the map file name. This applies to the map names in the campaign.lua file too.
For example: `MISS01.WLD, MISS01.lua` is correct and `MISS01.WLD, miss01.lua` will not work on Linux
- The Lua file of a map must have the same name as the map itself but with the extension `.lua` to be found.
- The Lua and the map file don't need to be in the same folder because the path can be specified separately.
- If `luaFolder` is not specified it defaults to the `mapFolder`, which defaults to an empty value.
- Both paths can start with placeholders like `<RTTR_GAME>`,
otherwise they must be (only) the name of a folder relative to the folder containing the campaign Lua file.
I.e. multiple levels are not supported.
In particular an empty value refers to the folder containing the campaign Lua file itself.

### Optional map selection screen {#selection-map}

This parameter is optional and can be obmitted in the lua campaign file. If this parameter is specified the selection screen for the missions of a campaign is replaced by a selection map. Like the one used in the original settler 2 world campaign.
This parameter is optional and can be omitted in the Lua campaign file. If this parameter is specified the selection screen for the missions of a campaign is replaced by a selection map. Like the one used in the original settlers 2 world campaign.

We have the following parameters:

1. `background` background image for the selection map
2. `map` the map image itself
3. `missionMapMask` this image is a mask that describes the mission areas of the `map` image. It must be the same size as the `map` image where the color of each pixel determines the mission it belongs to. Each mission must have a unique color (specified in the `missionSelectionInfos`). Any other color is treated as neutral area and ignored.
4. `marker` the marker image shown when a mission is selected
5. `conquered` the image shown when a mission is already finished
6. `backgroundOffset` offset of the `map` image and `missionMapMask` image relative to the `background` image. Can be (0,0) if no offset exists.
7. `disabledColor` color for drawing missions not playable yet. Usually this should be a partly transparent color
8. `missionSelectionInfos` contains an entry for each mission and must be the same order as specified in `maps` lua parameter. Each entry consists of three elements. The first is the `maskAreaColor` and the two following are the `ankerPos` x and y position. The `ankerPos` is the position the `conquered` image and the `cursor` image, if mission is selected, are displayed for this mission. The offset is always counted from the origin of the `map` image. The `maskAreaColor` is the color for the mission used in the `missionMapMask`.
8. `missionSelectionInfos` contains an entry for each mission and must be the same order as specified in `maps` Lua parameter. Each entry consists of three elements. The first is the `maskAreaColor` and the two following are the `ankerPos` x and y position. The `ankerPos` is the position the `conquered` image and the `cursor` image, if mission is selected, are displayed for this mission. The offset is always counted from the origin of the `map` image. The `maskAreaColor` is the color for the mission used in the `missionMapMask`.

Hints:
- All the images are described by the path to the image file and an index parameter. Usually the index parameter is zero. For special image formats containing multiple images in an archive this is the index of the image to use.
Hint:
All the images are described by the path to the image file and an index parameter. Usually the index parameter is zero.
For special image formats containing multiple images in an archive this is the index of the image to use.

## Final view of the example garden campaign folder
```

```sh
RTTR/campaigns/garden
RTTR/campaigns/garden/campaign.lua
RTTR/campaigns/garden/garden.bmp
Expand All @@ -133,5 +139,4 @@ RTTR/campaigns/garden/mapscreen/map.bmp
RTTR/campaigns/garden/mapscreen/map_mask.bmp
RTTR/campaigns/garden/mapscreen/marker.bmp
RTTR/campaigns/garden/mapscreen/conquered.bmp
```
```
2 changes: 1 addition & 1 deletion external/languages
Submodule languages updated 29 files
+3 −3 .github/workflows/sanity_check.yml
+25 −20 .github/workflows/synchronize-launchpad.yml
+623 −427 rttr-cs.po
+623 −424 rttr-de.po
+623 −427 rttr-en_GB.po
+619 −423 rttr-es.po
+619 −423 rttr-et.po
+619 −423 rttr-fi.po
+623 −424 rttr-fr.po
+613 −423 rttr-he.po
+619 −423 rttr-hu.po
+616 −423 rttr-it.po
+610 −423 rttr-ko.po
+613 −423 rttr-la.po
+616 −423 rttr-lt.po
+617 −424 rttr-nb.po
+616 −423 rttr-nds.po
+623 −427 rttr-nl.po
+623 −427 rttr-pl.po
+619 −423 rttr-pt.po
+619 −423 rttr-pt_BR.po
+645 −446 rttr-ru.po
+610 −423 rttr-rw.po
+616 −423 rttr-sk.po
+620 −424 rttr-sl.po
+619 −423 rttr-sv.po
+610 −423 rttr-tr.po
+1,394 −1,170 rttr-zh_CN.po
+660 −454 rttr.pot
2 changes: 1 addition & 1 deletion external/s25update
Submodule s25update updated 1 files
+7 −3 src/s25update.cpp
4 changes: 2 additions & 2 deletions extras/videoDrivers/SDL2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Copyright (C) 2005 - 2021 Settlers Freaks <sf-team at siedler25.org>
# Copyright (C) 2005 - 2024 Settlers Freaks <sf-team at siedler25.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later

set(SDL2_BUILDING_LIBRARY ON)
find_package(SDL2 2.0.2)
find_package(SDL2 2.0.5)

if(SDL2_FOUND)
add_library(videoSDL2 SHARED ${RTTR_DRIVER_INTERFACE} VideoSDL2.cpp VideoSDL2.h icon.h icon.cpp)
Expand Down
18 changes: 3 additions & 15 deletions extras/videoDrivers/SDL2/VideoSDL2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,9 @@ bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bo

const auto requestedSize = fullscreen ? FindClosestVideoMode(size) : size;
unsigned commonFlags = SDL_WINDOW_OPENGL;

#if SDL_VERSION_ATLEAST(2, 0, 1)
commonFlags |= SDL_WINDOW_ALLOW_HIGHDPI;
#endif
// TODO: Fix GUI scaling with High DPI support enabled.
// See https://github.com/Return-To-The-Roots/s25client/issues/1621
// commonFlags |= SDL_WINDOW_ALLOW_HIGHDPI;

window = SDL_CreateWindow(title.c_str(), wndPos, wndPos, requestedSize.width, requestedSize.height,
commonFlags | (fullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE));
Expand Down Expand Up @@ -193,9 +192,7 @@ bool VideoSDL2::ResizeScreen(const VideoMode& newSize, bool fullscreen)
isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
if(!isFullscreen_)
{
#if SDL_VERSION_ATLEAST(2, 0, 5)
SDL_SetWindowResizable(window, SDL_TRUE);
#endif
MoveWindowToCenter();
}
}
Expand Down Expand Up @@ -391,10 +388,8 @@ bool VideoSDL2::MessageLoop()
case SDL_MOUSEWHEEL:
{
int y = ev.wheel.y;
#if SDL_VERSION_ATLEAST(2, 0, 4)
if(ev.wheel.direction == SDL_MOUSEWHEEL_FLIPPED)
y = -y;
#endif
if(y > 0)
CallBack->Msg_WheelUp(mouse_xy);
else if(y < 0)
Expand Down Expand Up @@ -471,18 +466,11 @@ void* VideoSDL2::GetMapPointer() const
void VideoSDL2::MoveWindowToCenter()
{
SDL_Rect usableBounds;
#if SDL_VERSION_ATLEAST(2, 0, 5)
CHECK_SDL(SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(window), &usableBounds));
int top, left, bottom, right;
CHECK_SDL(SDL_GetWindowBordersSize(window, &top, &left, &bottom, &right));
usableBounds.w -= left + right;
usableBounds.h -= top + bottom;
#else
CHECK_SDL(SDL_GetDisplayBounds(SDL_GetWindowDisplayIndex(window), &usableBounds));
// rough estimates
usableBounds.w -= 10;
usableBounds.h -= 30;
#endif
if(usableBounds.w < GetWindowSize().width || usableBounds.h < GetWindowSize().height)
{
SDL_SetWindowSize(window, usableBounds.w, usableBounds.h);
Expand Down
16 changes: 7 additions & 9 deletions libs/s25main/Ware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,27 +338,25 @@ unsigned Ware::CheckNewGoalForLostWare(const noBaseBuilding& newgoal) const
Ware::RouteParams Ware::CalcPathToGoal(const noBaseBuilding& newgoal) const
{
RTTR_Assert(location);
unsigned length = 0xFFFFFFFF;
unsigned length;
RoadPathDirection possibledir = world->FindPathForWareOnRoads(*location, newgoal, &length);
if(possibledir != RoadPathDirection::None) // there is a valid path to the goal? -> ordered!
{
// in case the ware is right in front of the goal building the ware has to be moved away 1 flag and then back
// because non-warehouses cannot just carry in new wares they need a helper to do this
if(possibledir == RoadPathDirection::NorthWest && newgoal.GetFlagPos() == location->GetPos())
{
// Not executed for road from flag to the warehouse as that is handled directly by the warehouse
RTTR_Assert(!BuildingProperties::IsWareHouse(newgoal.GetBuildingType()));
for(const auto dir : helpers::EnumRange<Direction>{})
{
// Bounce of in this direction
if(dir != Direction::NorthWest && location->GetRoute(dir))
{
possibledir = toRoadPathDirection(dir);
break;
}
return {1, toRoadPathDirection(dir)};
}
if(possibledir == RoadPathDirection::NorthWest) // got no other route from the flag -> impossible
return {0xFFFFFFFF, RoadPathDirection::None};
// got no other route from the flag -> impossible
return {0xFFFFFFFF, RoadPathDirection::None};
}
// at this point there either is a road to the goal
// or we are at the flag of the goal and have a road to a different flag to bounce off of to get to the goal
return {length, possibledir};
}
return {0xFFFFFFFF, RoadPathDirection::None};
Expand Down
4 changes: 2 additions & 2 deletions libs/s25main/buildings/nobHarborBuilding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,8 +839,8 @@ std::vector<nobHarborBuilding::ShipConnection> nobHarborBuilding::GetShipConnect
{
ShipConnection sc;
sc.dest = harbor_building;
// Als Kantengewicht nehmen wir die doppelte Entfernung (evtl muss ja das Schiff erst kommen)
// plus einer Kopfpauschale (Ein/Ausladen usw. dauert ja alles)
// Use twice the distance as cost (ship might need to arrive first) and a fixed value to represent
// loading&unloading
sc.way_costs = 2 * world->CalcHarborDistance(GetHarborPosID(), harbor_building->GetHarborPosID()) + 10;
connections.push_back(sc);
}
Expand Down
26 changes: 19 additions & 7 deletions libs/s25main/nodeObjs/noFlag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,13 +228,14 @@ unsigned noFlag::GetNumWaresForRoad(const Direction dir) const
return helpers::count_if(wares, [roadDir](const auto& ware) { return ware->GetNextDir() == roadDir; });
}

/**
* Gibt Wegstrafpunkte für das Pathfinden für Waren, die in eine bestimmte
* Richtung noch transportiert werden müssen.
*/
unsigned noFlag::GetPunishmentPoints(const Direction dir) const
{
// Waren zählen, die in diese Richtung transportiert werden müssen
constexpr auto PATHFINDING_PENALTY_CARRIER_ARRIVING = 50;
constexpr auto PATHFINDING_PENALTY_NO_CARRIER = 500;
// This must be the same as "NO_CARRIER" for replay compatibility
// TODO(Replay): Move to `way_costs` in nobHarborBuilding::GetShipConnections
constexpr auto PATHFINDING_PENALTY_START_SHIPPING = 500;
// 2 Points per ware as carrier has to walk to other point and back for each ware
unsigned points = GetNumWaresForRoad(dir) * 2;

const RoadSegment* routeInDir = GetRoute(dir);
Expand All @@ -243,9 +244,20 @@ unsigned noFlag::GetPunishmentPoints(const Direction dir) const
{
// normal carrier has been ordered from the warehouse but has not yet arrived and no donkey
if(humanCarrier->GetCarrierState() == CarrierState::FigureWork && !routeInDir->hasCarrier(1))
points += 50;
points += PATHFINDING_PENALTY_CARRIER_ARRIVING;
} else if(!routeInDir->hasCarrier(1))
points += 500; // No carrier at all -> Large penalty
{
// Routes are either between flags or from a flag to a building, see the ctor of noBaseBuilding
const bool isBuildingEntry = (dir == Direction::NorthWest) && (routeInDir->GetF2()->GetGOT() != GO_Type::Flag);
// For entering a building no carrier is required
// Only roads to buildings considered by path finding are those to harbors
if(isBuildingEntry)
{
RTTR_Assert(routeInDir->GetF2()->GetGOT() == GO_Type::NobHarborbuilding);
points += PATHFINDING_PENALTY_START_SHIPPING;
} else
points += PATHFINDING_PENALTY_NO_CARRIER;
}

return points;
}
Expand Down
3 changes: 1 addition & 2 deletions libs/s25main/nodeObjs/noFlag.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ class noFlag : public noRoadNode
std::unique_ptr<Ware> SelectWare(Direction roadDir, bool swap_wares, const noFigure* carrier);
/// Prüft, ob es Waren gibt, die auf den Weg in Richtung dir getragen werden müssen.
unsigned GetNumWaresForRoad(Direction dir) const;
/// Gibt Wegstrafpunkte für das Pathfinden für Waren, die in eine bestimmte Richtung noch transportiert werden
/// müssen.
/// Penalty for transporting a ware in a specific direction
unsigned GetPunishmentPoints(Direction dir) const override;
/// Zerstört evtl. vorhandenes Gebäude bzw. Baustelle vor der Flagge.
void DestroyAttachedBuilding();
Expand Down
Loading

0 comments on commit 293be34

Please sign in to comment.