From baa6c446644f1d4e9ff18fd968f8ca5054784a6d Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Mon, 22 Aug 2022 00:58:46 +0200 Subject: [PATCH 1/3] Add wonder information to the players dialog This shows information that has always been available, but was never shown. Similar to Freeciv osdn#883354. Closes #318. --- client/plrdlg.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/client/plrdlg.cpp b/client/plrdlg.cpp index ccefab8d06..43f3a55509 100644 --- a/client/plrdlg.cpp +++ b/client/plrdlg.cpp @@ -14,10 +14,14 @@ #include #include // utility +#include "astring.h" #include "fcintl.h" // common +#include "city.h" #include "colors_common.h" +#include "game.h" #include "government.h" +#include "improvement.h" #include "nation.h" #include "research.h" // client @@ -633,6 +637,38 @@ void plr_widget::nation_selected(const QItemSelection &sl, + QStringLiteral("") + sp; } } + // Wonder information + auto wonders = QStringList(); + for (int i = 0; i < improvement_count(); ++i) { + if (pplayer->wonders[i] == WONDER_NOT_BUILT) { + continue; + } + + const auto improve = improvement_by_number(i); + const auto name = + QString(improvement_name_translation(improve)).toHtmlEscaped(); + if (pplayer->wonders[i] == WONDER_LOST) { + // TRANS: %1 is a wonder name + wonders += QString(_("%1 (lost)")).arg(name); + } else if (const auto city = game_city_by_number(pplayer->wonders[i])) { + // TRANS: %1 is a wonder name, %2 is a city name + wonders += QString(_("%1 (in %2)")) + .arg(name) + .arg(QString(city_name_get(city)).toHtmlEscaped()); + } else { + wonders += name; + } + } + if (!tech_str.isEmpty()) { + tech_str += nl; + } + // TRANS: Followed by a list of wonders the player knows another player has + tech_str += QString(_("Known Wonders: ")); + if (wonders.isEmpty()) { + tech_str += QString(Q_("?wonder:None")); + } else { + tech_str += strvec_to_and_list(wonders.toVector()); + } plr->update_report(false); } From 90816d77bab9b266dda7ec2dc68df8b864f2ccc6 Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Mon, 22 Aug 2022 01:44:21 +0200 Subject: [PATCH 2/3] Add effect Wonder_Visible This effect controls whether information about small wonders is visible to players (and hence sent to the client). It lets one control it for each wonder type separately, or possibly make it depend on the government (it is sadly not possible to make it depend on the diplomatic state). See #318. --- ai/default/daieffects.cpp | 1 + common/effects.cpp | 1 + common/effects.h | 2 ++ common/game.cpp | 5 ++++- docs/Modding/Rulesets/effects.rst | 12 ++++++++++++ server/plrhand.cpp | 13 ++++++++++++- server/rscompat.cpp | 7 +++++++ server/ruleset.h | 4 +++- 8 files changed, 42 insertions(+), 3 deletions(-) diff --git a/ai/default/daieffects.cpp b/ai/default/daieffects.cpp index 216b437fd6..f38694df16 100644 --- a/ai/default/daieffects.cpp +++ b/ai/default/daieffects.cpp @@ -574,6 +574,7 @@ adv_want dai_effect_value(struct player *pplayer, struct government *gov, case EFT_STEALINGS_IGNORE: case EFT_MAPS_STOLEN_PCT: case EFT_UNIT_SHIELD_VALUE_PCT: + case EFT_WONDER_VISIBLE: break; // This has no effect for AI case EFT_VISIBLE_WALLS: diff --git a/common/effects.cpp b/common/effects.cpp index d802b19627..14242b7d08 100644 --- a/common/effects.cpp +++ b/common/effects.cpp @@ -1215,6 +1215,7 @@ QString effect_type_unit_text(effect_type type, int value) case EFT_BORDER_VISION: case EFT_STEALINGS_IGNORE: case EFT_CASUS_BELLI_COMPLETE: + case EFT_WONDER_VISIBLE: case EFT_COUNT: return QStringLiteral("%1").arg(value); } diff --git a/common/effects.h b/common/effects.h index f823209f2c..5c3fba8493 100644 --- a/common/effects.h +++ b/common/effects.h @@ -307,6 +307,8 @@ #define SPECENUM_VALUE130NAME "Bombard_Limit_Pct" #define SPECENUM_VALUE131 EFT_TRADE_REVENUE_EXPONENT #define SPECENUM_VALUE131NAME "Trade_Revenue_Exponent" +#define SPECENUM_VALUE132 EFT_WONDER_VISIBLE +#define SPECENUM_VALUE132NAME "Wonder_Visible" // keep this last #define SPECENUM_COUNT EFT_COUNT #include "specenum_gen.h" diff --git a/common/game.cpp b/common/game.cpp index ba899f8d12..cb2372476d 100644 --- a/common/game.cpp +++ b/common/game.cpp @@ -25,6 +25,7 @@ #include "ai.h" #include "city.h" #include "disaster.h" +#include "effects.h" #include "extras.h" #include "government.h" #include "idex.h" @@ -650,7 +651,9 @@ void initialize_globals() game.info.great_wonder_owners[improvement_index(pimprove)] = player_number(pplayer); } - pplayer->wonders[improvement_index(pimprove)] = pcity->id; + if (get_building_bonus(pcity, pimprove, EFT_WONDER_VISIBLE) > 0) { + pplayer->wonders[improvement_index(pimprove)] = pcity->id; + } } } city_built_iterate_end; diff --git a/docs/Modding/Rulesets/effects.rst b/docs/Modding/Rulesets/effects.rst index 3df9f9ee6a..8c83e62ffa 100644 --- a/docs/Modding/Rulesets/effects.rst +++ b/docs/Modding/Rulesets/effects.rst @@ -708,3 +708,15 @@ Bombard_Limit_Pct .. note:: This effect is added automatically with a value of 1 and no reqs. This behavior can be turned off by requiring the ``+Bombard_Limit_Pct`` option in ``effects.ruleset``. + +Wonder_Visible + If the value of this effect is larger than 0 for a Small Wonder, the wonder will be visible to all + players and reported in the intelligence screen. Great Wonders are always visible to everyone through the + Wonders Report. When a Small Wonder is lost (for instance, because the city it is in is lost or some of + its requirements become invalid), it also becomes visible to everyone (this is a limitation of the + server). + + .. note:: + This effect is added automatically with a value of 1 for Great Wonders (since they are shown in the + Wonders Report anyway). This behavior can be turned off by requiring the ``+Wonder_Visible`` option + in ``effects.ruleset``. diff --git a/server/plrhand.cpp b/server/plrhand.cpp index 4e293f676e..619c4f9bde 100644 --- a/server/plrhand.cpp +++ b/server/plrhand.cpp @@ -22,6 +22,7 @@ #include "citizens.h" #include "culture.h" #include "diptreaty.h" +#include "game.h" #include "government.h" #include "map.h" #include "multipliers.h" @@ -1135,7 +1136,17 @@ static void package_player_common(struct player *plr, packet->nturns_idle = plr->nturns_idle; for (i = 0; i < B_LAST /*improvement_count()*/; i++) { - packet->wonders[i] = plr->wonders[i]; + if (plr->wonders[i] <= 0) { + packet->wonders[i] = plr->wonders[i]; + } else { + const auto pimprove = improvement_by_number(i); + const auto pcity = game_city_by_number(plr->wonders[i]); + if (pimprove && pcity) { + if (get_building_bonus(pcity, pimprove, EFT_WONDER_VISIBLE) > 0) { + packet->wonders[i] = plr->wonders[i]; + } + } + } } packet->science_cost = plr->ai_common.science_cost; } diff --git a/server/rscompat.cpp b/server/rscompat.cpp index b0765617a2..54cfa37a04 100644 --- a/server/rscompat.cpp +++ b/server/rscompat.cpp @@ -1164,6 +1164,13 @@ static void rscompat_optional_capabilities(rscompat_info *info) unit_type_iterate_end; } + if (!has_capability(CAP_EFT_WONDER_VISIBLE, info->cap_effects.data())) { + // Make Great Wonders visible to everyone + auto effect = effect_new(EFT_WONDER_VISIBLE, 1, nullptr); + effect_req_append(effect, req_from_str("BuildingGenus", "Local", false, + true, false, "GreatWonder")); + } + if (!has_capability(CAP_VUT_VISIONLAYER, info->cap_effects.data())) { // Add vlayer=Main to existing vision effects iterate_effect_cache(rscompat_vision_effect_cb, info); diff --git a/server/ruleset.h b/server/ruleset.h index a2731652ce..e3c580d1d7 100644 --- a/server/ruleset.h +++ b/server/ruleset.h @@ -16,10 +16,12 @@ #define CAP_EFT_HP_REGEN_MIN "HP_Regen_Min" #define CAP_EFT_BOMBARD_LIMIT_PCT "Bombard_Limit_Pct" +#define CAP_EFT_WONDER_VISIBLE "Wonder_Visible" #define CAP_VUT_VISIONLAYER "Vision_Layer" #define RULESET_CAPABILITIES \ "+Freeciv-ruleset-Devel-2017.Jan.02 " CAP_EFT_HP_REGEN_MIN \ - " " CAP_EFT_BOMBARD_LIMIT_PCT " " CAP_VUT_VISIONLAYER + " " CAP_EFT_BOMBARD_LIMIT_PCT " " CAP_EFT_WONDER_VISIBLE \ + " " CAP_VUT_VISIONLAYER /* * Ruleset capabilities acceptable to this program: * From 9342ef6d515fa7a83c4cb07d0bce794d4de0e362 Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Mon, 22 Aug 2022 02:08:17 +0200 Subject: [PATCH 3/3] Allow using DiplRel with Wonder_Visible This sounds like something people may want (see wonders only if you have embassy or something like that), so make it possible to use DiplRel requirements with the Wonder_Visible effect. --- server/plrhand.cpp | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/server/plrhand.cpp b/server/plrhand.cpp index 619c4f9bde..bbcdf56607 100644 --- a/server/plrhand.cpp +++ b/server/plrhand.cpp @@ -24,6 +24,7 @@ #include "diptreaty.h" #include "game.h" #include "government.h" +#include "improvement.h" #include "map.h" #include "multipliers.h" #include "packets.h" @@ -1135,19 +1136,6 @@ static void package_player_common(struct player *plr, packet->phase_done = plr->phase_done; packet->nturns_idle = plr->nturns_idle; - for (i = 0; i < B_LAST /*improvement_count()*/; i++) { - if (plr->wonders[i] <= 0) { - packet->wonders[i] = plr->wonders[i]; - } else { - const auto pimprove = improvement_by_number(i); - const auto pcity = game_city_by_number(plr->wonders[i]); - if (pimprove && pcity) { - if (get_building_bonus(pcity, pimprove, EFT_WONDER_VISIBLE) > 0) { - packet->wonders[i] = plr->wonders[i]; - } - } - } - } packet->science_cost = plr->ai_common.science_cost; } @@ -1209,6 +1197,26 @@ static void package_player_info(struct player *plr, } players_iterate_end; + // Wonder information + for (int i = 0; i < B_LAST; ++i) { + // Lost, not built or doesn't exist (still need to fill the array) + if (plr->wonders[i] <= 0 || i >= improvement_count()) { + packet->wonders[i] = plr->wonders[i]; + continue; + } + + const auto pimprove = improvement_by_number(i); + const auto pcity = game_city_by_number(plr->wonders[i]); + const auto bonus = get_target_bonus_effects( + nullptr, city_owner(pcity), receiver, pcity, pimprove, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, EFT_WONDER_VISIBLE); + if (bonus > 0) { + packet->wonders[i] = plr->wonders[i]; + } else { + packet->wonders[i] = WONDER_NOT_BUILT; + } + } + if (plr->rgb != nullptr) { packet->color_valid = true; packet->color_red = plr->rgb->r;