diff --git a/data/core/macros/special-notes.cfg b/data/core/macros/special-notes.cfg index f45af03712d..c6d993c0e7e 100644 --- a/data/core/macros/special-notes.cfg +++ b/data/core/macros/special-notes.cfg @@ -1,125 +1,323 @@ #textdomain wesnoth-help #define SPECIAL_NOTES - _" +#deprecated 2 Use [special_note]note= tags instead to apply special notes, or use the {NOTE_*} macros (note the singular). + " -Special Notes:"#enddef +"+_"Special Notes:"#enddef + +# SPECIAL_NOTES_* are the deprecated versions that provide the strings. +# NOTE_* are the new versions that provide an entire tag. +# For now, the new are defined in terms of the old, but when adding new special notes, +# only a NOTE_* form should be added. #define SPECIAL_NOTES_SPIRIT -_" -• Spirits have very unusual resistances to damage, and move quite slowly over open water."#enddef +#deprecated 1 Use {NOTE_SPIRIT} instead (note the singular), which generates a [special_note] tag. +_"Spirits have very unusual resistances to damage, and move quite slowly over open water."#enddef #define SPECIAL_NOTES_ARCANE -_" -• This unit’s arcane attack deals tremendous damage to magical creatures, and even some to mundane creatures."#enddef +#deprecated 1 Use {NOTE_ARCANE} instead (note the singular), which generates a [special_note] tag. +_"This unit’s arcane attack deals tremendous damage to magical creatures, and even some to mundane creatures."#enddef #define SPECIAL_NOTES_HEALS -_" -• This unit is capable of basic healing."#enddef +#deprecated 1 Use {NOTE_HEALS} instead (note the singular), which generates a [special_note] tag. +_"This unit is capable of basic healing."#enddef #define SPECIAL_NOTES_EXTRA_HEAL -_" -• This unit is capable of rapid healing."#enddef +#deprecated 1 Use {NOTE_EXTRA_HEAL} instead (note the singular), which generates a [special_note] tag. +_"This unit is capable of rapid healing."#enddef #define SPECIAL_NOTES_CURES -_" -• This unit is capable of healing those around it, and curing them of poison."#enddef +#deprecated 1 Use {NOTE_CURES} instead (note the singular), which generates a [special_note] tag. +_"This unit is capable of healing those around it, and curing them of poison."#enddef #define SPECIAL_NOTES_UNPOISON -_" -• This unit is capable of neutralizing the effects of poison in units around it."#enddef +#deprecated 1 Use {NOTE_UNPOISON} instead (note the singular), which generates a [special_note] tag. +_"This unit is capable of neutralizing the effects of poison in units around it."#enddef #define SPECIAL_NOTES_REGENERATES -_" -• This unit regenerates, which allows it to heal as though always stationed in a village."#enddef +#deprecated 1 Use {NOTE_REGENERATES} instead (note the singular), which generates a [special_note] tag. +_"This unit regenerates, which allows it to heal as though always stationed in a village."#enddef #define SPECIAL_NOTES_STEADFAST -_" -• The steadiness of this unit reduces damage from some attacks, but only while defending."#enddef +#deprecated 1 Use {NOTE_STEADFAST} instead (note the singular), which generates a [special_note] tag. +_"The steadiness of this unit reduces damage from some attacks, but only while defending."#enddef #define SPECIAL_NOTES_LEADERSHIP -_" -• The leadership of this unit enables adjacent units of the same side to deal more damage in combat, though this only applies to units of lower level."#enddef +#deprecated 1 Use {NOTE_LEADERSHIP} instead (note the singular), which generates a [special_note] tag. +_"The leadership of this unit enables adjacent units of the same side to deal more damage in combat, though this only applies to units of lower level."#enddef #define SPECIAL_NOTES_SKIRMISHER -_" -• This unit’s skill at skirmishing allows it to ignore enemies’ zones of control and thus move unhindered around them."#enddef +#deprecated 1 Use {NOTE_SKIRMISHER} instead (note the singular), which generates a [special_note] tag. +_"This unit’s skill at skirmishing allows it to ignore enemies’ zones of control and thus move unhindered around them."#enddef #define SPECIAL_NOTES_ILLUMINATES -_" -• Illumination increases the lighting level in adjacent areas."#enddef +#deprecated 1 Use {NOTE_ILLUMINATES} instead (note the singular), which generates a [special_note] tag. +_"Illumination increases the lighting level in adjacent areas."#enddef #define SPECIAL_NOTES_TELEPORT -_" -• This unit can use one move to teleport between any two empty villages controlled by its side."#enddef +#deprecated 1 Use {NOTE_TELEPORT} instead (note the singular), which generates a [special_note] tag. +_"This unit can use one move to teleport between any two empty villages controlled by its side."#enddef #define SPECIAL_NOTES_AMBUSH -_" -• In woodlands, this unit’s ambush skill renders it invisible to enemies unless it is immediately adjacent or has revealed itself by attacking."#enddef +#deprecated 1 Use {NOTE_AMBUSH} instead (note the singular), which generates a [special_note] tag. +_"In woodlands, this unit’s ambush skill renders it invisible to enemies unless it is immediately adjacent or has revealed itself by attacking."#enddef #define SPECIAL_NOTES_NIGHTSTALK -_" -• This unit is able to hide at night, leaving no trace of its presence."#enddef +#deprecated 1 Use {NOTE_NIGHTSTALK} instead (note the singular), which generates a [special_note] tag. +_"This unit is able to hide at night, leaving no trace of its presence."#enddef #define SPECIAL_NOTES_CONCEALMENT -_" -• This unit can hide in villages (with the exception of water villages), and remain undetected by its enemies, except by those standing next to it."#enddef +#deprecated 1 Use {NOTE_CONCEALMENT} instead (note the singular), which generates a [special_note] tag. +_"This unit can hide in villages (with the exception of water villages), and remain undetected by its enemies, except by those standing next to it."#enddef #define SPECIAL_NOTES_SUBMERGE -_" -• This unit can move unseen in deep water, requiring no air from the surface."#enddef +#deprecated 1 Use {NOTE_SUBMERGE} instead (note the singular), which generates a [special_note] tag. +_"This unit can move unseen in deep water, requiring no air from the surface."#enddef #define SPECIAL_NOTES_FEEDING -_" -• This unit gains 1 hitpoint added to its maximum whenever it kills a living unit."#enddef +#deprecated 1 Use {NOTE_FEEDING} instead (note the singular), which generates a [special_note] tag. +_"This unit gains 1 hitpoint added to its maximum whenever it kills a living unit."#enddef #define SPECIAL_NOTES_BERSERK -_" -• Whenever its berserk attack is used, this unit continues to push the attack until either it or its enemy lies dead."#enddef +#deprecated 1 Use {NOTE_BERSERK} instead (note the singular), which generates a [special_note] tag. +_"Whenever its berserk attack is used, this unit continues to push the attack until either it or its enemy lies dead."#enddef #define SPECIAL_NOTES_BACKSTAB -_" -• If there is an enemy of the target on the opposite side of the target while attacking it, this unit may backstab, inflicting double damage by creeping around behind that enemy."#enddef +#deprecated 1 Use {NOTE_BACKSTAB} instead (note the singular), which generates a [special_note] tag. +_"If there is an enemy of the target on the opposite side of the target while attacking it, this unit may backstab, inflicting double damage by creeping around behind that enemy."#enddef #define SPECIAL_NOTES_PLAGUE -_" -• Foes who lose their life to the plague will rise again in unlife, unless they are standing on a village."#enddef +#deprecated 1 Use {NOTE_PLAGUE} instead (note the singular), which generates a [special_note] tag. +_"Foes who lose their life to the plague will rise again in unlife, unless they are standing on a village."#enddef #define SPECIAL_NOTES_SLOW -_" -• This unit is able to slow its enemies, halving their movement speed and attack damage until they end a turn."#enddef +#deprecated 1 Use {NOTE_SLOW} instead (note the singular), which generates a [special_note] tag. +_"This unit is able to slow its enemies, halving their movement speed and attack damage until they end a turn."#enddef #define SPECIAL_NOTES_PETRIFY -_" -• The ability to turn the living to stone makes this unit extremely dangerous."#enddef +#deprecated 1 Use {NOTE_PETRIFY} instead (note the singular), which generates a [special_note] tag. +_"The ability to turn the living to stone makes this unit extremely dangerous."#enddef + +#define SPECIAL_NOTES_STONE +#deprecated 1 Use {NOTE_PETRIFY} instead (note the singular), which generates a [special_note] tag. +{SPECIAL_NOTES_PETRIFY}#enddef #define SPECIAL_NOTES_MARKSMAN -_" -• This unit’s marksmanship gives it a high chance of hitting targeted enemies, but only on the attack."#enddef +#deprecated 1 Use {NOTE_MARKSMAN} instead (note the singular), which generates a [special_note] tag. +_"This unit’s marksmanship gives it a high chance of hitting targeted enemies, but only on the attack."#enddef #define SPECIAL_NOTES_MAGICAL -_" -• This unit has magical attacks, which always have a high chance of hitting an opponent."#enddef +#deprecated 1 Use {NOTE_MAGICAL} instead (note the singular), which generates a [special_note] tag. +_"This unit has magical attacks, which always have a high chance of hitting an opponent."#enddef #define SPECIAL_NOTES_SWARM -_" -• The swarming attacks of this unit become less deadly whenever its members are wounded."#enddef +#deprecated 1 Use {NOTE_SWARM} instead (note the singular), which generates a [special_note] tag. +_"The swarming attacks of this unit become less deadly whenever its members are wounded."#enddef #define SPECIAL_NOTES_CHARGE -_" -• Using a charging attack doubles both damage dealt and received; this does not affect defensive retaliation."#enddef +#deprecated 1 Use {NOTE_CHARGE} instead (note the singular), which generates a [special_note] tag. +_"Using a charging attack doubles both damage dealt and received; this does not affect defensive retaliation."#enddef #define SPECIAL_NOTES_DRAIN -_" -• During battle, this unit can drain life from victims to renew its own health."#enddef +#deprecated 1 Use {NOTE_DRAIN} instead (note the singular), which generates a [special_note] tag. +_"During battle, this unit can drain life from victims to renew its own health."#enddef #define SPECIAL_NOTES_FIRSTSTRIKE -_" -• The length of this unit’s weapon allows it to strike first in melee, even in defense."#enddef +#deprecated 1 Use {NOTE_FIRSTRIKE} instead (note the singular), which generates a [special_note] tag. +_"The length of this unit’s weapon allows it to strike first in melee, even in defense."#enddef #define SPECIAL_NOTES_POISON -_" -• The victims of this unit’s poison will continually take damage until they can be cured in town or by a unit which cures."#enddef +#deprecated 1 Use {NOTE_POISON} instead (note the singular), which generates a [special_note] tag. +_"The victims of this unit’s poison will continually take damage until they can be cured in town or by a unit which cures."#enddef #define SPECIAL_NOTES_DEFENSE_CAP -_" -• This unit has a defense cap on certain terrain types — it cannot achieve a higher defense rating on mixed terrains with such terrain types."#enddef +#deprecated 1 Use {NOTE_DEFENSE_CAP} instead (note the singular), which generates a [special_note] tag. +_"This unit has a defense cap on certain terrain types — it cannot achieve a higher defense rating on mixed terrains with such terrain types."#enddef + +# New versions start here! + +#define NOTE_SPIRIT +[special_note] + note={SPECIAL_NOTES_SPIRIT} +[/special_note] +#enddef + +#define NOTE_ARCANE +[special_note] + note={SPECIAL_NOTES_ARCANE} +[/special_note] +#enddef + +#define NOTE_HEALS +[special_note] + note={SPECIAL_NOTES_HEALS} +[/special_note] +#enddef + +#define NOTE_EXTRA_HEAL +[special_note] + note={SPECIAL_NOTES_EXTRA_HEAL} +[/special_note] +#enddef + +#define NOTE_CURES +[special_note] + note={SPECIAL_NOTES_CURES} +[/special_note] +#enddef + +#define NOTE_UNPOISON +[special_note] + note={SPECIAL_NOTES_UNPOISON} +[/special_note] +#enddef + +#define NOTE_REGENERATES +[special_note] + note={SPECIAL_NOTES_REGENERATES} +[/special_note] +#enddef + +#define NOTE_SELF_HEAL +[special_note] + note=_"This unit heals itself each turn, though not as much as if stationed in a village." +[/special_note] +#enddef + +#define NOTE_STEADFAST +[special_note] + note={SPECIAL_NOTES_STEADFAST} +[/special_note] +#enddef + +#define NOTE_LEADERSHIP +[special_note] + note={SPECIAL_NOTES_LEADERSHIP} +[/special_note] +#enddef + +#define NOTE_SKIRMISHER +[special_note] + note={SPECIAL_NOTES_SKIRMISHER} +[/special_note] +#enddef + +#define NOTE_ILLUMINATES +[special_note] + note={SPECIAL_NOTES_ILLUMINATES} +[/special_note] +#enddef + +#define NOTE_TELEPORT +[special_note] + note={SPECIAL_NOTES_TELEPORT} +[/special_note] +#enddef + +#define NOTE_AMBUSH +[special_note] + note={SPECIAL_NOTES_AMBUSH} +[/special_note] +#enddef + +#define NOTE_NIGHTSTALK +[special_note] + note={SPECIAL_NOTES_NIGHTSTALK} +[/special_note] +#enddef + +#define NOTE_CONCEALMENT +[special_note] + note={SPECIAL_NOTES_CONCEALMENT} +[/special_note] +#enddef + +#define NOTE_SUBMERGE +[special_note] + note={SPECIAL_NOTES_SUBMERGE} +[/special_note] +#enddef + +#define NOTE_FEEDING +[special_note] + note={SPECIAL_NOTES_FEEDING} +[/special_note] +#enddef + +#define NOTE_BERSERK +[special_note] + note={SPECIAL_NOTES_BERSERK} +[/special_note] +#enddef + +#define NOTE_BACKSTAB +[special_note] + note={SPECIAL_NOTES_BACKSTAB} +[/special_note] +#enddef + +#define NOTE_PLAGUE +[special_note] + note={SPECIAL_NOTES_PLAGUE} +[/special_note] +#enddef + +#define NOTE_SLOW +[special_note] + note={SPECIAL_NOTES_SLOW} +[/special_note] +#enddef + +#define NOTE_PETRIFY +[special_note] + note={SPECIAL_NOTES_PETRIFY} +[/special_note] +#enddef + +#define NOTE_MARKSMAN +[special_note] + note={SPECIAL_NOTES_MARKSMAN} +[/special_note] +#enddef + +#define NOTE_MAGICAL +[special_note] + note={SPECIAL_NOTES_MAGICAL} +[/special_note] +#enddef + +#define NOTE_SWARM +[special_note] + note={SPECIAL_NOTES_SWARM} +[/special_note] +#enddef + +#define NOTE_CHARGE +[special_note] + note={SPECIAL_NOTES_CHARGE} +[/special_note] +#enddef + +#define NOTE_DRAIN +[special_note] + note={SPECIAL_NOTES_DRAIN} +[/special_note] +#enddef + +#define NOTE_FIRSTSTRIKE +[special_note] + note={SPECIAL_NOTES_FIRSTSTRIKE} +[/special_note] +#enddef + +#define NOTE_POISON +[special_note] + note={SPECIAL_NOTES_POISON} +[/special_note] +#enddef + +#define NOTE_DEFENSE_CAP +[special_note] + note={SPECIAL_NOTES_DEFENSE_CAP} +[/special_note] +#enddef diff --git a/data/schema/units/types.cfg b/data/schema/units/types.cfg index 938153dd1d0..b2a22e7b854 100644 --- a/data/schema/units/types.cfg +++ b/data/schema/units/types.cfg @@ -65,6 +65,10 @@ name="abilities" {./abilities.cfg} [/tag] + [tag] + name="special_note" + {REQUIRED_KEY note t_string} + [/tag] {LINK_TAG "units/movetype/resistance"} {LINK_TAG "units/movetype/defense"} {LINK_TAG "units/movetype/movement_costs"} diff --git a/data/tools/wmllint b/data/tools/wmllint index 6d29b149630..8708862c142 100755 --- a/data/tools/wmllint +++ b/data/tools/wmllint @@ -155,7 +155,7 @@ # # A comment of the form # -# #wmllint: match {ABILITY_FOO} with {SPECIAL_NOTES_IOO} +# #wmllint: match {ABILITY_FOO} with {NOTE_FOO} # # will declare an ability macro and a special-notes macro to be tied # together for reference-checking purposes. @@ -1035,44 +1035,45 @@ def standard_unit_filter(): # Associations for the ability sanity checks. notepairs = [ - ("movement_type=mounted", "{SPECIAL_NOTES_DEFENSE_CAP}"), - ("movement_type=undeadspirit", "{SPECIAL_NOTES_SPIRIT}"), - ("type=arcane", "{SPECIAL_NOTES_ARCANE}"), - ("{ABILITY_HEALS}", "{SPECIAL_NOTES_HEALS}"), - ("{ABILITY_EXTRA_HEAL}", "{SPECIAL_NOTES_EXTRA_HEAL}"), - ("{ABILITY_UNPOISON}", "{SPECIAL_NOTES_UNPOISON}"), - ("{ABILITY_CURES}", "{SPECIAL_NOTES_CURES}"), - ("{ABILITY_REGENERATES}", "{SPECIAL_NOTES_REGENERATES}"), - ("{ABILITY_STEADFAST}", "{SPECIAL_NOTES_STEADFAST}"), - ("{ABILITY_LEADERSHIP}", "{SPECIAL_NOTES_LEADERSHIP}"), - ("{ABILITY_SKIRMISHER}", "{SPECIAL_NOTES_SKIRMISHER}"), - ("{ABILITY_ILLUMINATES}", "{SPECIAL_NOTES_ILLUMINATES}"), - ("{ABILITY_TELEPORT}", "{SPECIAL_NOTES_TELEPORT}"), - ("{ABILITY_AMBUSH}", "{SPECIAL_NOTES_AMBUSH}"), - ("{ABILITY_NIGHTSTALK}", "{SPECIAL_NOTES_NIGHTSTALK}"), - ("{ABILITY_CONCEALMENT}", "{SPECIAL_NOTES_CONCEALMENT}"), - ("{ABILITY_SUBMERGE}", "{SPECIAL_NOTES_SUBMERGE}"), - ("{ABILITY_FEEDING}", "{SPECIAL_NOTES_FEEDING}"), - ("{ABILITY_INSPIRE}", "{SPECIAL_NOTES_INSPIRE}"), - ("{ABILITY_INITIATIVE}", "{SPECIAL_NOTES_INITIATIVE}"), - ("{ABILITY_DISTRACT}", "{SPECIAL_NOTES_DISTRACT}"), - ("{ABILITY_DISENGAGE}", "{SPECIAL_NOTES_DISENGAGE}"), - ("{ABILITY_FORMATION}", "{SPECIAL_NOTES_FORMATION}"), - ("{WEAPON_SPECIAL_BERSERK}", "{SPECIAL_NOTES_BERSERK}"), - ("{WEAPON_SPECIAL_BACKSTAB}", "{SPECIAL_NOTES_BACKSTAB}"), - ("{WEAPON_SPECIAL_PLAGUE", "{SPECIAL_NOTES_PLAGUE}"), # No } deliberately - ("{WEAPON_SPECIAL_SLOW}", "{SPECIAL_NOTES_SLOW}"), - ("{WEAPON_SPECIAL_PETRIFY}", "{SPECIAL_NOTES_PETRIFY}"), - ("{WEAPON_SPECIAL_MARKSMAN}", "{SPECIAL_NOTES_MARKSMAN}"), - ("{WEAPON_SPECIAL_MAGICAL}", "{SPECIAL_NOTES_MAGICAL}"), - ("{WEAPON_SPECIAL_SWARM}", "{SPECIAL_NOTES_SWARM}"), - ("{WEAPON_SPECIAL_CHARGE}", "{SPECIAL_NOTES_CHARGE}"), - ("{WEAPON_SPECIAL_DRAIN}", "{SPECIAL_NOTES_DRAIN}"), - ("{WEAPON_SPECIAL_FIRSTSTRIKE}", "{SPECIAL_NOTES_FIRSTSTRIKE}"), - ("{WEAPON_SPECIAL_POISON}", "{SPECIAL_NOTES_POISON}"), - ("{WEAPON_SPECIAL_STUN}", "{SPECIAL_NOTES_STUN}"), - ("{WEAPON_SPECIAL_SHOCK}", "{SPECIAL_NOTES_SHOCK}"), - ("{WEAPON_SPECIAL_DAZE}", "{SPECIAL_NOTES_DAZE}"), + ("movement_type=mounted", "{NOTE_DEFENSE_CAP}"), + ("movement_type=undeadspirit", "{NOTE_SPIRIT}"), + ("type=arcane", "{NOTE_ARCANE}"), + ("{ABILITY_HEALS}", "{NOTE_HEALS}"), + ("{ABILITY_EXTRA_HEAL}", "{NOTE_EXTRA_HEAL}"), + ("{ABILITY_UNPOISON}", "{NOTE_UNPOISON}"), + ("{ABILITY_CURES}", "{NOTE_CURES}"), + ("{ABILITY_REGENERATES}", "{NOTE_REGENERATES}"), + ("{ABILITY_SELF_HEAL}", "{NOTE_SELF_HEAL}"), + ("{ABILITY_STEADFAST}", "{NOTE_STEADFAST}"), + ("{ABILITY_LEADERSHIP}", "{NOTE_LEADERSHIP}"), + ("{ABILITY_SKIRMISHER}", "{NOTE_SKIRMISHER}"), + ("{ABILITY_ILLUMINATES}", "{NOTE_ILLUMINATES}"), + ("{ABILITY_TELEPORT}", "{NOTE_TELEPORT}"), + ("{ABILITY_AMBUSH}", "{NOTE_AMBUSH}"), + ("{ABILITY_NIGHTSTALK}", "{NOTE_NIGHTSTALK}"), + ("{ABILITY_CONCEALMENT}", "{NOTE_CONCEALMENT}"), + ("{ABILITY_SUBMERGE}", "{NOTE_SUBMERGE}"), + ("{ABILITY_FEEDING}", "{NOTE_FEEDING}"), + ("{ABILITY_INSPIRE}", "{NOTE_INSPIRE}"), + ("{ABILITY_INITIATIVE}", "{NOTE_INITIATIVE}"), + ("{ABILITY_DISTRACT}", "{NOTE_DISTRACT}"), + ("{ABILITY_DISENGAGE}", "{NOTE_DISENGAGE}"), + ("{ABILITY_FORMATION}", "{NOTE_FORMATION}"), + ("{WEAPON_SPECIAL_BERSERK}", "{NOTE_BERSERK}"), + ("{WEAPON_SPECIAL_BACKSTAB}", "{NOTE_BACKSTAB}"), + ("{WEAPON_SPECIAL_PLAGUE", "{NOTE_PLAGUE}"), # No } deliberately + ("{WEAPON_SPECIAL_SLOW}", "{NOTE_SLOW}"), + ("{WEAPON_SPECIAL_PETRIFY}", "{NOTE_PETRIFY}"), + ("{WEAPON_SPECIAL_MARKSMAN}", "{NOTE_MARKSMAN}"), + ("{WEAPON_SPECIAL_MAGICAL}", "{NOTE_MAGICAL}"), + ("{WEAPON_SPECIAL_SWARM}", "{NOTE_SWARM}"), + ("{WEAPON_SPECIAL_CHARGE}", "{NOTE_CHARGE}"), + ("{WEAPON_SPECIAL_DRAIN}", "{NOTE_DRAIN}"), + ("{WEAPON_SPECIAL_FIRSTSTRIKE}", "{NOTE_FIRSTSTRIKE}"), + ("{WEAPON_SPECIAL_POISON}", "{NOTE_POISON}"), + ("{WEAPON_SPECIAL_STUN}", "{NOTE_STUN}"), + ("{WEAPON_SPECIAL_SHOCK}", "{NOTE_SHOCK}"), + ("{WEAPON_SPECIAL_DAZE}", "{NOTE_DAZE}"), ] # This dictionary will pair macros with the characters they recall or create, @@ -1470,21 +1471,19 @@ def global_sanity_check(filename, lines): nt = note_trait[note] if nt not in traits and nt not in missing_traits: missing_traits.append(nt) - if (notes or traits) and not has_special_notes: - missing_notes = ["{SPECIAL_NOTES}"] + missing_notes # If the unit didn't specify hitpoints, there is some wacky # stuff going on (possibly pseudo-[base_unit] behavior via # macro generation) so disable some of the consistency checks. if not hitpoints_specified: continue if notecheck and missing_notes: - print('"%s", line %d: unit %s is missing notes +%s' \ - % (filename, in_unit_type, unit_id, "+".join(missing_notes))) + print('"%s", line %d: unit %s is missing notes %s' \ + % (filename, in_unit_type, unit_id, " ".join(missing_notes))) if missing_traits: print('"%s", line %d: unit %s is missing traits %s' \ - % (filename, in_unit_type, unit_id, "+".join(missing_traits))) + % (filename, in_unit_type, unit_id, " ".join(missing_traits))) if notecheck and not (notes or traits) and has_special_notes: - print('"%s", line %d: unit %s has superfluous {SPECIAL_NOTES}' \ + print('"%s", line %d: unit %s has superfluous {NOTE_*}' \ % (filename, in_unit_type, unit_id)) if "[theme]" not in nav.ancestors() and "[base_unit]" not in nav.ancestors() and not unit_race: print('"%s", line %d: unit %s has no race' \ @@ -1496,6 +1495,8 @@ def global_sanity_check(filename, lines): base_unit = "" has_special_notes = False unit_race = None + elif nav.element == "[special_note]": + has_special_notes = True if '[unit_type]' in nav.ancestors() and "[filter_attack]" not in nav.ancestors(): try: (key, prefix, value, comment) = parse_attribute(nav.text) @@ -1531,7 +1532,7 @@ def global_sanity_check(filename, lines): precomment = nav.text if '#' in nav.text: precomment = nav.text[:nav.text.find("#")] - if "{SPECIAL_NOTES}" in precomment: + if "{NOTE" in precomment: has_special_notes = True for (p, q) in notepairs: if p in precomment: @@ -3371,7 +3372,7 @@ In your case, your system interprets your arguments as: print(fn + ":") spellcheck(fn, d) except ImportError: - print("wmllint: spell check unavailable, install python3-enchant to enable", file=sys.stderr) + print("wmllint: spell check unavailable, install python-enchant to enable", file=sys.stderr) if failed_any_dirs: sys.exit(1) except KeyboardInterrupt: diff --git a/src/help/help_topic_generators.cpp b/src/help/help_topic_generators.cpp index 4ecae75371a..33c0a6416bf 100644 --- a/src/help/help_topic_generators.cpp +++ b/src/help/help_topic_generators.cpp @@ -12,6 +12,8 @@ See the COPYING file for more details. */ +#define GETTEXT_DOMAIN "wesnoth-help" + #include "help/help_topic_generators.hpp" #include "font/sdl_ttf.hpp" // for line_width @@ -544,7 +546,13 @@ std::string unit_topic_generator::operator()() const { } // Print the detailed description about the unit. - ss << "\n\n" << detailed_description; + ss << "\n\n" << detailed_description; + if(type_.has_special_notes()) { + ss << "\n\n" << _("Special Notes:") << '\n'; + for(const auto& note : type_.special_notes()) { + ss << "• " << note << '\n'; + } + } // Print the different attacks a unit has, if it has any. if (!type_.attacks().empty()) { diff --git a/src/units/types.cpp b/src/units/types.cpp index 19673633fb2..e1221ec3128 100644 --- a/src/units/types.cpp +++ b/src/units/types.cpp @@ -241,6 +241,10 @@ void unit_type::build_help_index( icon_ = cfg_["image_icon"].str(); small_profile_ = cfg_["small_profile"].str(); profile_ = cfg_["profile"].str(); + + for(const config& sn : cfg_.child_range("special_note")) { + special_notes_.push_back(sn["note"]); + } adjust_profile(profile_); @@ -482,6 +486,15 @@ t_string unit_type::unit_description() const } } +bool unit_type::has_special_notes() const +{ + return !special_notes_.empty(); +} + +const std::vector& unit_type::special_notes() const { + return special_notes_; +} + const std::vector& unit_type::animations() const { if(animations_.empty()) { diff --git a/src/units/types.hpp b/src/units/types.hpp index 14b03b594e7..dc34243266e 100644 --- a/src/units/types.hpp +++ b/src/units/types.hpp @@ -143,6 +143,8 @@ public: // NOTE: this used to be a const object reference, but it messed up with the // translation engine upon changing the language in the same session. t_string unit_description() const; + bool has_special_notes() const; + const std::vector& special_notes() const; int hitpoints() const { return hitpoints_; } double hp_bar_scaling() const { return hp_bar_scaling_; } double xp_bar_scaling() const { return xp_bar_scaling_; } @@ -296,6 +298,7 @@ private: std::string base_id_; /// The id of the top ancestor of this unit_type. t_string type_name_; t_string description_; + std::vector special_notes_; int hitpoints_; double hp_bar_scaling_, xp_bar_scaling_; int level_;