1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

Merge pull request #1459 from IvanSavenko/mod_translations

Translation support for mods
This commit is contained in:
Ivan Savenko
2023-01-25 14:05:05 +02:00
committed by GitHub
18 changed files with 955 additions and 819 deletions

View File

@@ -0,0 +1,243 @@
{
"vcmi.adventureMap.monsterThreat.title" : "\n\n Threat: ",
"vcmi.adventureMap.monsterThreat.levels.0" : "Effortless",
"vcmi.adventureMap.monsterThreat.levels.1" : "Very Weak",
"vcmi.adventureMap.monsterThreat.levels.2" : "Weak",
"vcmi.adventureMap.monsterThreat.levels.3" : "A bit weaker",
"vcmi.adventureMap.monsterThreat.levels.4" : "Equal",
"vcmi.adventureMap.monsterThreat.levels.5" : "A bit stronger",
"vcmi.adventureMap.monsterThreat.levels.6" : "Strong",
"vcmi.adventureMap.monsterThreat.levels.7" : "Very Strong",
"vcmi.adventureMap.monsterThreat.levels.8" : "Challenging",
"vcmi.adventureMap.monsterThreat.levels.9" : "Overpowering",
"vcmi.adventureMap.monsterThreat.levels.10" : "Deadly",
"vcmi.adventureMap.monsterThreat.levels.11" : "Impossible",
"vcmi.adventureMap.confirmRestartGame" : "Are you sure you want to restart game?",
"vcmi.adventureMap.noTownWithMarket" : "No available marketplace!",
"vcmi.adventureMap.noTownWithTavern" : "No available town with tavern!",
"vcmi.adventureMap.spellUnknownProblem" : "Unknown problem with this spell, no more information available.",
"vcmi.adventureMap.playerAttacked" : "Player has been attacked: %s",
"vcmi.adventureMap.moveCostDetails" : "Movement points - Cost: %TURNS turns + %POINTS points, Remaining points: %REMAINING",
"vcmi.adventureMap.moveCostDetailsNoTurns" : "Movement points - Cost: %POINTS points, Remaining points: %REMAINING",
"vcmi.server.errors.existingProcess" : "Another vcmiserver process is running, please terminate it first",
"vcmi.server.errors.modsIncompatibility" : "Required mods to load game:",
"vcmi.server.confirmReconnect" : "Connect to the last session?",
"vcmi.systemOptions.fullscreenButton.hover" : "Fullscreen",
"vcmi.systemOptions.fullscreenButton.help" : "{Fullscreen}\n\n If selected, VCMI will run in fullscreen mode, othervice VCMI will run in window",
"vcmi.systemOptions.resolutionButton.hover" : "Resolution",
"vcmi.systemOptions.resolutionButton.help" : "{Select resolution}\n\n Change in-game screen resolution. Game restart required to apply new resolution.",
"vcmi.systemOptions.resolutionMenu.hover" : "Select resolution",
"vcmi.systemOptions.resolutionMenu.help" : "Change in-game screen resolution.",
"vcmi.townHall.missingBase" : "Base building %s must be built first",
"vcmi.townHall.noCreaturesToRecruit" : "There are no creatures to recruit!",
"vcmi.townHall.greetingManaVortex" : "As you near the %s your body is filled with new energy. You have doubled your normal spell points.",
"vcmi.townHall.greetingKnowledge" : "You study the glyphs on the %s and gain insight into the workings of various magics (+1 Knowledge).",
"vcmi.townHall.greetingSpellPower" : "The %s teaches you new ways to focus your magical powers (+1 Power).",
"vcmi.townHall.greetingExperience" : "A visit to the %s teaches you many new skills (+1000 Experience).",
"vcmi.townHall.greetingAttack" : "Some time spent at the %s allows you to learn more effective combat skills (+1 Attack Skill).",
"vcmi.townHall.greetingDefence" : "Spending time in the %s, the experienced warriors therein teach you additional defensive skills (+1 Defense).",
"vcmi.townHall.hasNotProduced" : "The %s has not produced anything yet.",
"vcmi.townHall.hasProduced" : "The %s produced %d %s this week.",
"vcmi.townHall.greetingCustomBonus" : "%s gives you +%d %s%s",
"vcmi.townHall.greetingCustomUntil" : " until next battle.",
"vcmi.townHall.greetingInTownMagicWell" : "%s has restored your spell points to maximum.",
"vcmi.logicalExpressions.anyOf" : "Any of the following:",
"vcmi.logicalExpressions.allOf" : "All of the following:",
"vcmi.logicalExpressions.noneOf" : "None of the following:",
"vcmi.heroWindow.openCommander.hover" : "Open commander window",
"vcmi.heroWindow.openCommander.help" : "Displays information about commander of this hero",
"vcmi.commanderWindow.artifactMessage" : "Do you want to give this artifact back to hero?",
"vcmi.creatureWindow.showBonuses.hover" : "Switch to bonuses view",
"vcmi.creatureWindow.showBonuses.help" : "Displays all active bonuses of the commander",
"vcmi.creatureWindow.showSkills.hover" : "Switch to skills view",
"vcmi.creatureWindow.showSkills.help" : "Displays all learned skills of the commander",
"vcmi.creatureWindow.returnArtifact.hover" : "Give back artifact",
"vcmi.creatureWindow.returnArtifact.help" : "Use this button to return stack artifact back into hero backpack",
"vcmi.questLog.hideComplete.hover" : "Hide complete quests",
"vcmi.questLog.hideComplete.help" : "Hide all quests that already completed",
"vcmi.randomMapTab.widgets.defaultTemplate" : "default",
"vcmi.randomMapTab.widgets.templateLabel" : "Template",
"vcmi.randomMapTab.widgets.teamAlignmentsButton" : "Setup...",
"vcmi.randomMapTab.widgets.teamAlignmentsLabel" : "Team alignments",
// few strings from WoG used by vcmi
"vcmi.stackExperience.description" : "» S t a c k E x p e r i e n c e D e t a i l s «\n\nCreature Type ................... : %s\nExperience Rank ................. : %s (%i)\nExperience Points ............... : %i\nExperience Points to Next Rank .. : %i\nMaximum Experience per Battle ... : %i%% (%i)\nNumber of Creatures in stack .... : %i\nMaximum New Recruits\n without losing current Rank .... : %i\nExperience Multiplier ........... : %.2f\nUpgrade Multiplier .............. : %.2f\nExperience after Rank 10 ........ : %i\nMaximum New Recruits to remain at\n Rank 10 if at Maximum Experience : %i",
"vcmi.stackExperience.rank.1" : "Basic",
"vcmi.stackExperience.rank.2" : "Novice",
"vcmi.stackExperience.rank.3" : "Trained",
"vcmi.stackExperience.rank.4" : "Skilled",
"vcmi.stackExperience.rank.5" : "Proven",
"vcmi.stackExperience.rank.6" : "Veteran",
"vcmi.stackExperience.rank.7" : "Adept",
"vcmi.stackExperience.rank.8" : "Expert",
"vcmi.stackExperience.rank.9" : "Elite",
"vcmi.stackExperience.rank.10" : "Master",
"vcmi.stackExperience.rank.11" : "Ace",
"core.bonus.ADDITIONAL_ATTACK.name": "Double Strike",
"core.bonus.ADDITIONAL_ATTACK.description": "Attacks twice",
"core.bonus.ADDITIONAL_RETALIATION.name": "Additional retaliations",
"core.bonus.ADDITIONAL_RETALIATION.description": "May Retaliate ${val} extra times",
"core.bonus.AIR_IMMUNITY.name": "Air immunity",
"core.bonus.AIR_IMMUNITY.description": "Immune to all Air school spells",
"core.bonus.ATTACKS_ALL_ADJACENT.name": "Attack all around",
"core.bonus.ATTACKS_ALL_ADJACENT.description": "Attacks all adjacent enemies",
"core.bonus.BLOCKS_RETALIATION.name": "No retaliation",
"core.bonus.BLOCKS_RETALIATION.description": "Enemy cannot Retaliate",
"core.bonus.BLOCKS_RANGED_RETALIATION.name": "No ranged retaliation",
"core.bonus.BLOCKS_RANGED_RETALIATION.description": "Enemy cannot Retaliate by shooting",
"core.bonus.CATAPULT.name": "Catapult",
"core.bonus.CATAPULT.description": "Attacks siege walls",
"core.bonus.CATAPULT_EXTRA_SHOTS.name": "Additional siege attacks",
"core.bonus.CATAPULT_EXTRA_SHOTS.description": "Can hit siege walls ${val} extra times per attack",
"core.bonus.CHANGES_SPELL_COST_FOR_ALLY.name": "Reduce Casting Cost (${val})",
"core.bonus.CHANGES_SPELL_COST_FOR_ALLY.description": "Reduces spell cost for hero",
"core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.name": "Magic Damper (${val})",
"core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.description": "Increases Cost of enemy spells",
"core.bonus.CHARGE_IMMUNITY.name": "Immune to Charge",
"core.bonus.CHARGE_IMMUNITY.description": "Immune to Champion charge",
"core.bonus.DARKNESS.name": "Darkness cover",
"core.bonus.DARKNESS.description": "Adds ${val} darkness radius",
"core.bonus.DEATH_STARE.name": "Death Stare (${val}%)",
"core.bonus.DEATH_STARE.description": "${val}% chance to kill single creature",
"core.bonus.DEFENSIVE_STANCE.name": "Defense Bonus",
"core.bonus.DEFENSIVE_STANCE.description": "+${val} Defense when defending",
"core.bonus.DESTRUCTION.name": "Destruction",
"core.bonus.DESTRUCTION.description": "Has ${val}% chance to kill extra units after attack",
"core.bonus.DOUBLE_DAMAGE_CHANCE.name": "Death Blow",
"core.bonus.DOUBLE_DAMAGE_CHANCE.description": "${val}% chance for double damage",
"core.bonus.DRAGON_NATURE.name": "Dragon",
"core.bonus.DRAGON_NATURE.description": "Creature has a Dragon Nature",
"core.bonus.DIRECT_DAMAGE_IMMUNITY.name": "Direct Damage Immunity",
"core.bonus.DIRECT_DAMAGE_IMMUNITY.description": "Immune to direct damage spells",
"core.bonus.EARTH_IMMUNITY.name": "Earth immunity",
"core.bonus.EARTH_IMMUNITY.description": "Immune to all Earth school spells",
"core.bonus.ENCHANTER.name": "Enchanter",
"core.bonus.ENCHANTER.description": "Can cast mass ${subtype.spell} every turn",
"core.bonus.ENCHANTED.name": "Enchanted",
"core.bonus.ENCHANTED.description": "Affected by permanent ${subtype.spell}",
"core.bonus.ENEMY_DEFENCE_REDUCTION.name": "Ignore Defense (${val}%)",
"core.bonus.ENEMY_DEFENCE_REDUCTION.description": "Ignores part of Defence for the attack",
"core.bonus.FIRE_IMMUNITY.name": "Fire immunity",
"core.bonus.FIRE_IMMUNITY.description": "Immune to all Fire school spells",
"core.bonus.FIRE_SHIELD.name": "Fire Shield (${val}%)",
"core.bonus.FIRE_SHIELD.description": "Reflects part of melee damage",
"core.bonus.FIRST_STRIKE.name": "First Strike",
"core.bonus.FIRST_STRIKE.description": "This creature attacks first instead of retaliating",
"core.bonus.FEAR.name": "Fear",
"core.bonus.FEAR.description": "Causes Fear on an enemy stack",
"core.bonus.FEARLESS.name": "Fearless",
"core.bonus.FEARLESS.description": "Immune to Fear ability",
"core.bonus.FLYING.name": "Fly",
"core.bonus.FLYING.description": "Can Fly (ignores obstacles)",
"core.bonus.FREE_SHOOTING.name": "Shoot Close",
"core.bonus.FREE_SHOOTING.description": "Can shoot in Close Combat",
"core.bonus.FULL_HP_REGENERATION.name": "Regeneration",
"core.bonus.FULL_HP_REGENERATION.description": "May Regenerate to full Health",
"core.bonus.GARGOYLE.name": "Gargoyle",
"core.bonus.GARGOYLE.description": "Cannot be rised or healed",
"core.bonus.GENERAL_DAMAGE_REDUCTION.name": "Reduce Damage (${val}%)",
"core.bonus.GENERAL_DAMAGE_REDUCTION.description": "Reduces physical damage from ranged or melee",
"core.bonus.HATE.name": "Hates ${subtype.creature}",
"core.bonus.HATE.description": "Does ${val}% more damage",
"core.bonus.HEALER.name": "Healer",
"core.bonus.HEALER.description": "Heals allied units",
"core.bonus.HP_REGENERATION.name": "Regeneration",
"core.bonus.HP_REGENERATION.description": "Heals ${val} hit points every round",
"core.bonus.JOUSTING.name": "Champion Charge",
"core.bonus.JOUSTING.description": "+5% damage per hex travelled",
"core.bonus.KING1.name": "King 1",
"core.bonus.KING1.description": "Vulnerable to basic SLAYER",
"core.bonus.KING2.name": "King 2",
"core.bonus.KING2.description": "Vulnerable to advanced SLAYER",
"core.bonus.KING3.name": "King 3",
"core.bonus.KING3.description":"Vulnerable to expert SLAYER",
"core.bonus.LEVEL_SPELL_IMMUNITY.name": "Spell immunity 1-${val}",
"core.bonus.LEVEL_SPELL_IMMUNITY.description": "Immune to spells of levels 1-${val}",
"core.bonus.LIMITED_SHOOTING_RANGE.name" : "Limited shooting range",
"core.bonus.LIMITED_SHOOTING_RANGE.description" : "",
"core.bonus.LIFE_DRAIN.name": "Drain life (${val}%)",
"core.bonus.LIFE_DRAIN.description": "Drains ${val}% of damage dealt",
"core.bonus.MANA_CHANNELING.name": "Magic Channel ${val}%",
"core.bonus.MANA_CHANNELING.description": "Gives your hero mana spent by enemy",
"core.bonus.MANA_DRAIN.name": "Mana Drain",
"core.bonus.MANA_DRAIN.description": "Drains ${val} mana every turn",
"core.bonus.MAGIC_MIRROR.name": "Magic Mirror (${val}%)",
"core.bonus.MAGIC_MIRROR.description": "${val}% chance to redirects an offensive spell to enemy",
"core.bonus.MAGIC_RESISTANCE.name": "Magic Resistance(${MR}%)",
"core.bonus.MAGIC_RESISTANCE.description": "${MR}% chance to resist enemy spell",
"core.bonus.MIND_IMMUNITY.name": "Mind Spell Immunity",
"core.bonus.MIND_IMMUNITY.description": "Immune to Mind-type spells",
"core.bonus.NO_DISTANCE_PENALTY.name": "No distance penalty",
"core.bonus.NO_DISTANCE_PENALTY.description": "Full damage from any distance",
"core.bonus.NO_MELEE_PENALTY.name": "No melee penalty",
"core.bonus.NO_MELEE_PENALTY.description": "Creature has no Melee Penalty",
"core.bonus.NO_MORALE.name": "Neutral Morale",
"core.bonus.NO_MORALE.description": "Creature is immune to morale effects",
"core.bonus.NO_WALL_PENALTY.name": "No wall penalty",
"core.bonus.NO_WALL_PENALTY.description": "Full damage during siege",
"core.bonus.NON_LIVING.name": "Non living",
"core.bonus.NON_LIVING.description": "Immunity to many effects",
"core.bonus.RANDOM_SPELLCASTER.name": "Random spellcaster",
"core.bonus.RANDOM_SPELLCASTER.description": "Can cast random spell",
"core.bonus.RANGED_RETALIATION.name": "Ranged retaliation",
"core.bonus.RANGED_RETALIATION.description": "Can perform ranged counterattack",
"core.bonus.RECEPTIVE.name": "Receptive",
"core.bonus.RECEPTIVE.description": "No Immunity to Friendly Spells",
"core.bonus.REBIRTH.name": "Rebirth (${val}%)",
"core.bonus.REBIRTH.description": "${val}% of stack will rise after death",
"core.bonus.RETURN_AFTER_STRIKE.name": "Attack and Return",
"core.bonus.RETURN_AFTER_STRIKE.description": "Returns after melee attack",
"core.bonus.SELF_LUCK.name": "Positive luck",
"core.bonus.SELF_LUCK.description": "Always has Positive Luck",
"core.bonus.SELF_MORALE.name": "Positive morale",
"core.bonus.SELF_MORALE.description": "Always has Positive Morale",
"core.bonus.SHOOTER.name": "Ranged",
"core.bonus.SHOOTER.description": "Creature can shoot",
"core.bonus.SHOOTS_ALL_ADJACENT.name": "Shoot all around",
"core.bonus.SHOOTS_ALL_ADJACENT.description": "This creature's ranged attacks strike all targets in a small area",
"core.bonus.SOUL_STEAL.name": "Soul Steal",
"core.bonus.SOUL_STEAL.description": "Gains ${val} new creatures for each enemy killed",
"core.bonus.SPELLCASTER.name": "Spellcaster",
"core.bonus.SPELLCASTER.description": "Can cast ${subtype.spell}",
"core.bonus.SPELL_AFTER_ATTACK.name": "Cast After Attack",
"core.bonus.SPELL_AFTER_ATTACK.description": "${val}% to cast ${subtype.spell} after attack",
"core.bonus.SPELL_BEFORE_ATTACK.name": "Cast Before Attack",
"core.bonus.SPELL_BEFORE_ATTACK.description": "${val}% to cast ${subtype.spell} before attack",
"core.bonus.SPELL_DAMAGE_REDUCTION.name": "Spell Resistance",
"core.bonus.SPELL_DAMAGE_REDUCTION.description": "Damage from spells reduced ${val}%.",
"core.bonus.SPELL_IMMUNITY.name": "Spell immunity",
"core.bonus.SPELL_IMMUNITY.description": "Immune to ${subtype.spell}",
"core.bonus.SPELL_LIKE_ATTACK.name": "Spell-like attack",
"core.bonus.SPELL_LIKE_ATTACK.description": "Attacks with ${subtype.spell}",
"core.bonus.SPELL_RESISTANCE_AURA.name": "Aura of Resistance",
"core.bonus.SPELL_RESISTANCE_AURA.description": "Nearby stacks get ${val}% resistance",
"core.bonus.SUMMON_GUARDIANS.name": "Summon guardians",
"core.bonus.SUMMON_GUARDIANS.description": "At battle start summons ${subtype.creature} (${val}%)",
"core.bonus.SYNERGY_TARGET.name": "Synergizable",
"core.bonus.SYNERGY_TARGET.description": "This creature is vulnerable to synergy effect",
"core.bonus.TWO_HEX_ATTACK_BREATH.name": "Breath",
"core.bonus.TWO_HEX_ATTACK_BREATH.description": "Breath Attack (2-hex range)",
"core.bonus.THREE_HEADED_ATTACK.name": "Three-headed attack",
"core.bonus.THREE_HEADED_ATTACK.description": "Attacks three adjacent units",
"core.bonus.TRANSMUTATION.name": "Transmutation",
"core.bonus.TRANSMUTATION.description": "${val}% chance to transform attacked unit to other type",
"core.bonus.UNDEAD.name": "Undead",
"core.bonus.UNDEAD.description": "Creature is Undead",
"core.bonus.UNLIMITED_RETALIATIONS.name": "Unlimited retaliations",
"core.bonus.UNLIMITED_RETALIATIONS.description": "Retaliates any number of attacks",
"core.bonus.WATER_IMMUNITY.name": "Water immunity",
"core.bonus.WATER_IMMUNITY.description": "Immune to all Water school spells",
"core.bonus.WIDE_BREATH.name": "Wide breath",
"core.bonus.WIDE_BREATH.description": "Wide breath attack (multiple hexes)"
}

View File

@@ -0,0 +1,222 @@
{
"vcmi.adventureMap.monsterThreat.title" : "\n\n Bedrohung: ",
"vcmi.adventureMap.monsterThreat.levels.0" : "Mühelos",
"vcmi.adventureMap.monsterThreat.levels.1" : "Sehr schwach",
"vcmi.adventureMap.monsterThreat.levels.2" : "Schwach",
"vcmi.adventureMap.monsterThreat.levels.3" : "Ein bisschen schwächer",
"vcmi.adventureMap.monsterThreat.levels.4" : "Gleichauf",
"vcmi.adventureMap.monsterThreat.levels.5" : "Ein bisschen stärker",
"vcmi.adventureMap.monsterThreat.levels.6" : "Stark",
"vcmi.adventureMap.monsterThreat.levels.7" : "Sehr Stark",
"vcmi.adventureMap.monsterThreat.levels.8" : "Herausfordernd",
"vcmi.adventureMap.monsterThreat.levels.9" : "Überwältigend",
"vcmi.adventureMap.monsterThreat.levels.10" : "Tötlich",
"vcmi.adventureMap.monsterThreat.levels.11" : "Unmöglich",
"vcmi.adventureMap.confirmRestartGame" : "Seid Ihr sicher, dass Ihr das Spiel neu starten wollt?",
"vcmi.adventureMap.noTownWithMarket" : "Kein Marktplatz verfügbar!",
"vcmi.adventureMap.noTownWithTavern" : "Keine Stadt mit Taverne verfügbar!",
"vcmi.adventureMap.spellUnknownProblem" : "Unbekanntes Problem mit diesem Zauberspruch, keine weiteren Informationen verfügbar.",
"vcmi.adventureMap.playerAttacked" : "Spieler wurde attackiert: %s",
"vcmi.server.errors.existingProcess" : "Es läuft ein weiterer vcmiserver-Prozess, bitte beendet diesen zuerst",
"vcmi.server.errors.modsIncompatibility" : "Erforderliche Mods um das Spiel zu laden:",
"vcmi.systemOptions.fullscreenButton.hover" : "Vollbild",
"vcmi.systemOptions.fullscreenButton.help" : "{Fullscreen}\n\n Wenn ausgewählt wird VCMI im Vollbildmodus laufen, ansonsten im Fenstermodus",
"vcmi.systemOptions.resolutionButton.hover" : "Auflösung",
"vcmi.systemOptions.resolutionButton.help" : "{Select resolution}\n\n Ändert die Spielauflösung. Spielneustart ist erforderlich um neue Auflösung zu übernehmen.",
"vcmi.systemOptions.resolutionMenu.hover" : "Wähle Auflösung",
"vcmi.systemOptions.resolutionMenu.help" : "Ändere die Spielauflösung.",
"vcmi.townHall.missingBase" : "Basis Gebäude %s muss als erstes gebaut werden",
"vcmi.townHall.noCreaturesToRecruit" : "Es gibt keine Kreaturen zu rekrutieren!",
"vcmi.townHall.greetingManaVortex" : "Wenn Ihr Euch den %s nähert, wird Euer Körper mit neuer Energie gefüllt. Ihr habt Eure normalen Zauberpunkte verdoppelt.",
"vcmi.townHall.greetingKnowledge" : "Ihr studiert die Glyphen auf dem %s und erhaltet Einblick in die Funktionsweise verschiedener Magie (+1 Wissen).",
"vcmi.townHall.greetingSpellPower" : "Der %s lehrt Euch neue Wege, Eure magischen Kräfte zu bündeln (+1 Kraft).",
"vcmi.townHall.greetingExperience" : "Ein Besuch bei den %s bringt Euch viele neue Fähigkeiten bei (+1000 Erfahrung).",
"vcmi.townHall.greetingAttack" : "Nach einiger Zeit im %s könnt Ihr effizientere Kampffertigkeiten erlernen (+1 Angriffsfertigkeit).",
"vcmi.townHall.greetingDefence" : "Wenn Ihr Zeit im %s verbringt, bringen Euch die erfahrenen Krieger dort zusätzliche Verteidigungsfähigkeiten bei (+1 Verteidigung).",
"vcmi.townHall.hasNotProduced" : "Die %s hat noch nichts produziert.",
"vcmi.townHall.hasProduced" : "Die %s hat diese Woche %d %s produziert.",
"vcmi.townHall.greetingCustomBonus" : "%s gibt Ihnen +%d %s%s",
"vcmi.townHall.greetingCustomUntil" : " bis zur nächsten Schlacht.",
"vcmi.townHall.greetingInTownMagicWell" : "%s hat Eure Zauberpunkte wieder auf das Maximum erhöht.",
"vcmi.logicalExpressions.anyOf" : "Eines der folgenden:",
"vcmi.logicalExpressions.allOf" : "Alles der folgenden:",
"vcmi.logicalExpressions.noneOf" : "Keines der folgenden:",
"vcmi.heroWindow.openCommander.hover" : "Öffne Kommandanten-Fenster",
"vcmi.heroWindow.openCommander.help" : "Zeige Informationen über Kommandanten dieses Helden",
"vcmi.commanderWindow.artifactMessage" : "Möchtet Ihr diesen Artefakt dem Helden zurückgeben?",
"vcmi.creatureWindow.showBonuses.hover" : "Wechsle zur Bonus-Ansicht",
"vcmi.creatureWindow.showBonuses.help" : "Zeige alle aktiven Boni des Kommandanten",
"vcmi.creatureWindow.showSkills.hover" : "Wechsle zur Fertigkeits-Ansicht",
"vcmi.creatureWindow.showSkills.help" : "Zeige alle erlernten Fertigkeiten des Kommandanten",
"vcmi.creatureWindow.returnArtifact.hover" : "Artefekt zurückgeben",
"vcmi.creatureWindow.returnArtifact.help" : "Nutze diese Schaltfläche, um Stapel-Artefakt in den Rucksack des Helden zurückzugeben",
"vcmi.questLog.hideComplete.hover" : "Verstecke abgeschlossene Quests",
"vcmi.questLog.hideComplete.help" : "Verstecke alle Quests die bereits abgeschlossen sind",
"core.bonus.ADDITIONAL_ATTACK.name": "Doppelschlag",
"core.bonus.ADDITIONAL_ATTACK.description": "Greift zweimal an",
"core.bonus.ADDITIONAL_RETALIATION.name": "Zusätzliche Vergeltungsmaßnahmen",
"core.bonus.ADDITIONAL_RETALIATION.description": "Kann ${val} zusätzliche Male vergelten",
"core.bonus.AIR_IMMUNITY.name": "Luftimmunität",
"core.bonus.AIR_IMMUNITY.description": "Immun gegen alle Luftschulzauber",
"core.bonus.ATTACKS_ALL_ADJACENT.name": "Rundum angreifen",
"core.bonus.ATTACKS_ALL_ADJACENT.description": "Greift alle benachbarten Gegner an",
"core.bonus.BLOCKS_RETALIATION.name": "Keine Vergeltung",
"core.bonus.BLOCKS_RETALIATION.description": "Feind kann nicht vergelten",
"core.bonus.BLOCKS_RANGED_RETALIATION.name": "Keine Reichweitenverschiebung",
"core.bonus.BLOCKS_RANGED_RETALIATION.description": "Feind kann nicht durch Schießen vergelten",
"core.bonus.CATAPULT.name": "Katapult",
"core.bonus.CATAPULT.description": "Greift Belagerungsmauern an",
"core.bonus.CATAPULT_EXTRA_SHOTS.name": "Zusätzliche Belagerungsangriffe",
"core.bonus.CATAPULT_EXTRA_SHOTS.description": "Kann Belagerungsmauern ${val} zusätzliche Male pro Angriff treffen",
"core.bonus.CHANGES_SPELL_COST_FOR_ALLY.name": "Reduziere Zauberkosten (${val})",
"core.bonus.CHANGES_SPELL_COST_FOR_ALLY.description": "Reduziert die Zauberkosten für den Helden",
"core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.name": "Zauberdämpfer (${val})",
"core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.description": "Erhöht die Kosten von gegnerischen Zaubern",
"core.bonus.CHARGE_IMMUNITY.name": "Immun gegen Aufladung",
"core.bonus.CHARGE_IMMUNITY.description": "Immune to Champion charge",
"core.bonus.DAEMON_SUMMONING.name": "Beschwörer (${subtype.creature})",
"core.bonus.DAEMON_SUMMONING.description": "Kann Kreaturen aus Leichen auferstehen lassen",
"core.bonus.DARKNESS.name": "Darkness cover",
"core.bonus.DARKNESS.description": "Fügt ${val} Dunkelheitsradius hinzu",
"core.bonus.DEATH_STARE.name": "Todesstarren (${val}%)",
"core.bonus.DEATH_STARE.description": "${val}% Chance, eine einzelne Kreatur zu töten",
"core.bonus.DEFENSIVE_STANCE.name": "Verteidigungsbonus",
"core.bonus.DEFENSIVE_STANCE.description": "+${val} Verteidigung beim Verteidigen",
"core.bonus.DESTRUCTION.name": "Zerstörung",
"core.bonus.DESTRUCTION.description": "Hat ${val}% Chance, zusätzliche Einheiten nach dem Angriff zu töten",
"core.bonus.DOUBLE_DAMAGE_CHANCE.name": "Todesstoß",
"core.bonus.DOUBLE_DAMAGE_CHANCE.description": "${val}% Chance auf doppelten Schaden",
"core.bonus.DRAGON_NATURE.name": "Drache",
"core.bonus.DRAGON_NATURE.description": "Kreatur hat eine Drachennatur",
"core.bonus.DIRECT_DAMAGE_IMMUNITY.name": "Direkte Schadensimmunität",
"core.bonus.DIRECT_DAMAGE_IMMUNITY.description": "Immun gegen Direktschadenszauber",
"core.bonus.EARTH_IMMUNITY.name": "Erdimmunität",
"core.bonus.EARTH_IMMUNITY.description": "Immun gegen alle Zauber der Erdschule",
"core.bonus.ENCHANTER.name": "Verzauberer",
"core.bonus.ENCHANTER.description": "Kann jede Runde eine Masse von ${subtype.spell} zaubern",
"core.bonus.ENCHANTED.name": "Verzaubert",
"core.bonus.ENCHANTED.description": "Beeinflusst von permanentem ${subtype.spell}",
"core.bonus.ENEMY_DEFENCE_REDUCTION.name": "Ignoriere Verteidigung (${val}%)",
"core.bonus.ENEMY_DEFENCE_REDUCTION.description": "Ignoriert einen Teil der Verteidigung für den Angriff",
"core.bonus.FIRE_IMMUNITY.name": "Feuerimmunität",
"core.bonus.FIRE_IMMUNITY.description": "Immun gegen alle Zauber der Schule des Feuers",
"core.bonus.FIRE_SHIELD.name": "Feuerschild (${val}%)",
"core.bonus.FIRE_SHIELD.description": "Reflektiert einen Teil des Nahkampfschadens",
"core.bonus.FIRST_STRIKE.name": "Erstschlag",
"core.bonus.FIRST_STRIKE.description": "Diese Kreatur greift zuerst an, anstatt zu vergelten",
"core.bonus.FEAR.name": "Furcht",
"core.bonus.FEAR.description": "Verursacht Furcht bei einem gegnerischen Stapel",
"core.bonus.FEARLESS.name": "Furchtlos",
"core.bonus.FEARLESS.description": "immun gegen die Fähigkeit Furcht",
"core.bonus.FLYING.name": "Fliegen",
"core.bonus.FLYING.description": "Kann fliegen (ignoriert Hindernisse)",
"core.bonus.FREE_SHOOTING.name": "Nah schießen",
"core.bonus.FREE_SHOOTING.description": "Kann im Nahkampf schießen",
"core.bonus.FULL_HP_REGENERATION.name": "Regeneration",
"core.bonus.FULL_HP_REGENERATION.description": "Kann auf volle Lebenspunkte regenerieren",
"core.bonus.GARGOYLE.name": "Gargoyle",
"core.bonus.GARGOYLE.description": "Kann nicht aufgerichtet oder geheilt werden",
"core.bonus.GENERAL_DAMAGE_REDUCTION.name": "Schaden vermindern (${val}%)",
"core.bonus.GENERAL_DAMAGE_REDUCTION.description": "Reduziert physischen Schaden aus dem Fern- oder Nahkampf",
"core.bonus.HATE.name": "Hasst ${subtype.creature}",
"core.bonus.HATE.description": "Macht ${val}% mehr Schaden",
"core.bonus.HEALER.name": "Heiler",
"core.bonus.HEALER.description": "Heilt verbündete Einheiten",
"core.bonus.HP_REGENERATION.name": "Regeneration",
"core.bonus.HP_REGENERATION.description": "Heilt ${val} Trefferpunkte jede Runde",
"core.bonus.JOUSTING.name": "Champion Charge",
"core.bonus.JOUSTING.description": "+5% Schaden pro zurückgelegtem Feld",
"core.bonus.KING1.name": "König 1",
"core.bonus.KING1.description": "Anfällig für grundlegende SLAYER",
"core.bonus.KING2.name": "König 2",
"core.bonus.KING2.description": "Anfällig für erweiterte SLAYER",
"core.bonus.KING3.name": "König3",
"core.bonus.KING3.description": "Anfällig für Experten-SLAYER",
"core.bonus.LEVEL_SPELL_IMMUNITY.name": "Zauberimmunität 1-${val}",
"core.bonus.LEVEL_SPELL_IMMUNITY.description": "Immun gegen Zaubersprüche der Stufen 1-${val}",
"core.bonus.LIFE_DRAIN.name": "Leben entziehen (${val}%)",
"core.bonus.LIFE_DRAIN.description": "Drainiert ${val}% des zugefügten Schadens",
"core.bonus.MANA_CHANNELING.name": "Magiekanal ${val}%",
"core.bonus.MANA_CHANNELING.description": "Gibt Ihrem Helden Mana, das vom Gegner ausgegeben wird",
"core.bonus.MANA_DRAIN.name": "Mana-Entzug",
"core.bonus.MANA_DRAIN.description": "Entzieht ${val} Mana jede Runde",
"core.bonus.MAGIC_MIRROR.name": "Zauberspiegel (${val}%)",
"core.bonus.MAGIC_MIRROR.description": "${val}% Chance, einen Angriffszauber auf den Gegner umzulenken",
"core.bonus.MAGIC_RESISTANCE.name": "Magie-Widerstand(${MR}%)",
"core.bonus.MAGIC_RESISTANCE.description": "${MR}% Chance, gegnerischem Zauber zu widerstehen",
"core.bonus.MIND_IMMUNITY.name": "Geist-Zauber-Immunität",
"core.bonus.MIND_IMMUNITY.description": "Immun gegen Zauber vom Typ Geist",
"core.bonus.NO_DISTANCE_PENALTY.name": "Keine Entfernungsstrafe",
"core.bonus.NO_DISTANCE_PENALTY.description": "Voller Schaden aus beliebiger Entfernung",
"core.bonus.NO_MELEE_PENALTY.name": "Keine Nahkampf-Strafe",
"core.bonus.NO_MELEE_PENALTY.description": "Kreatur hat keinen Nahkampf-Malus",
"core.bonus.NO_MORALE.name": "Neutrale Moral",
"core.bonus.NO_MORALE.description": "Kreatur ist immun gegen Moral-Effekte",
"core.bonus.NO_WALL_PENALTY.name": "Keine Wand-Strafe",
"core.bonus.NO_WALL_PENALTY.description": "Voller Schaden bei Belagerung",
"core.bonus.NON_LIVING.name": "Nicht lebend",
"core.bonus.NON_LIVING.description": "Immunität gegen viele Effekte",
"core.bonus.RANDOM_SPELLCASTER.name": "Zufälliger Zauberwirker",
"core.bonus.RANDOM_SPELLCASTER.description": "Kann einen zufälligen Zauberspruch wirken",
"core.bonus.RANGED_RETALIATION.name": "Fernkampf-Vergeltung",
"core.bonus.RANGED_RETALIATION.description": "Kann einen Fernkampf-Gegenangriff durchführen",
"core.bonus.RECEPTIVE.name": "Empfänglich",
"core.bonus.RECEPTIVE.description": "Keine Immunität gegen Freundschaftszauber",
"core.bonus.REBIRTH.name": "Wiedergeburt (${val}%)",
"core.bonus.REBIRTH.description": "${val}% des Stacks wird nach dem Tod auferstehen",
"core.bonus.RETURN_AFTER_STRIKE.name": "Angriff und Rückkehr",
"core.bonus.RETURN_AFTER_STRIKE.description": "Kehrt nach Nahkampfangriff zurück",
"core.bonus.SELF_LUCK.name": "Positives Glück",
"core.bonus.SELF_LUCK.description": "Hat immer positives Glück",
"core.bonus.SELF_MORALE.name": "Positive Moral",
"core.bonus.SELF_MORALE.description": "Hat immer positive Moral",
"core.bonus.SHOOTER.name": "Fernkämpfer",
"core.bonus.SHOOTER.description": "Kreatur kann schießen",
"core.bonus.SHOOTS_ALL_ADJACENT.name": "Schießt rundherum",
"core.bonus.SHOOTS_ALL_ADJACENT.description": "Die Fernkampfangriffe dieser Kreatur treffen alle Ziele in einem kleinen Bereich",
"core.bonus.SOUL_STEAL.name": "Seelenraub",
"core.bonus.SOUL_STEAL.description": "Gewinnt ${val} neue Kreaturen für jeden getöteten Gegner",
"core.bonus.SPELLCASTER.name": "Zauberer",
"core.bonus.SPELLCASTER.description": "Kann ${subtype.spell} zaubern",
"core.bonus.SPELL_AFTER_ATTACK.name": "Nach Angriff zaubern",
"core.bonus.SPELL_AFTER_ATTACK.description": "${val}%, um ${subtype.spell} nach dem Angriff zu wirken",
"core.bonus.SPELL_BEFORE_ATTACK.name": "Zauber vor Angriff",
"core.bonus.SPELL_BEFORE_ATTACK.description": "${val}% um ${subtype.spell} vor dem Angriff zu wirken",
"core.bonus.SPELL_DAMAGE_REDUCTION.name": "Zauberwiderstand",
"core.bonus.SPELL_DAMAGE_REDUCTION.description": "Schaden von Zaubern reduziert ${val}%.",
"core.bonus.SPELL_IMMUNITY.name": "Zauberimmunität",
"core.bonus.SPELL_IMMUNITY.description": "Immun gegen ${subtype.spell}",
"core.bonus.SPELL_LIKE_ATTACK.name": "zauberähnlicher Angriff",
"core.bonus.SPELL_LIKE_ATTACK.description": "Angriffe mit ${subtype.spell}",
"core.bonus.SPELL_RESISTANCE_AURA.name": "Aura des Widerstands",
"core.bonus.SPELL_RESISTANCE_AURA.description": "Stapel in der Nähe erhalten ${val}% Widerstand",
"core.bonus.SUMMON_GUARDIANS.name": "Wächter beschwören",
"core.bonus.SUMMON_GUARDIANS.description": "Beschwört bei Kampfbeginn ${subtype.creature} (${val}%)",
"core.bonus.SYNERGY_TARGET.name": "Synergierbar",
"core.bonus.SYNERGY_TARGET.description": "Diese Kreatur ist anfällig für Synergieeffekte",
"core.bonus.TWO_HEX_ATTACK_BREATH.name": "Breath",
"core.bonus.TWO_HEX_ATTACK_BREATH.description": "Atem-Angriff (2-Hex-Bereich)",
"core.bonus.THREE_HEADED_ATTACK.name": "Dreiköpfiger Angriff",
"core.bonus.THREE_HEADED_ATTACK.description": "Greift drei benachbarte Einheiten an",
"core.bonus.TRANSMUTATION.name": "Transmutation",
"core.bonus.TRANSMUTATION.description": "${val}% Chance, angegriffene Einheit in einen anderen Typ zu verwandeln",
"core.bonus.UNDEAD.name": "Untot",
"core.bonus.UNDEAD.description": "Kreatur ist untot",
"core.bonus.UNLIMITED_RETALIATIONS.name": "Unbegrenzte Vergeltungsmaßnahmen",
"core.bonus.UNLIMITED_RETALIATIONS.description": "Vergeltungen für eine beliebige Anzahl von Angriffen",
"core.bonus.WATER_IMMUNITY.name": "Wasser-Immunität",
"core.bonus.WATER_IMMUNITY.description": "Immun gegen alle Zauber der Wasserschule",
"core.bonus.WIDE_BREATH.name": "Breiter Atem",
"core.bonus.WIDE_BREATH.description": "Breiter Atem-Angriff (mehrere Felder)"
}

View File

@@ -0,0 +1,70 @@
{
"vcmi.adventureMap.monsterThreat.title" : "\n\n Poziom zagrożenia: ",
"vcmi.adventureMap.monsterThreat.levels.0" : "Zerowy",
"vcmi.adventureMap.monsterThreat.levels.1" : "Bardzo słaby",
"vcmi.adventureMap.monsterThreat.levels.2" : "Słaby",
"vcmi.adventureMap.monsterThreat.levels.3" : "Nieco słabszy",
"vcmi.adventureMap.monsterThreat.levels.4" : "Równie silny",
"vcmi.adventureMap.monsterThreat.levels.5" : "Nieco silniejszy",
"vcmi.adventureMap.monsterThreat.levels.6" : "Silny",
"vcmi.adventureMap.monsterThreat.levels.7" : "Bardzo silny",
"vcmi.adventureMap.monsterThreat.levels.8" : "Wyzwanie",
"vcmi.adventureMap.monsterThreat.levels.9" : "Przytłaczający",
"vcmi.adventureMap.monsterThreat.levels.10" : "Śmiertelny",
"vcmi.adventureMap.monsterThreat.levels.11" : "Nie do pokonania",
"vcmi.adventureMap.confirmRestartGame" : "Czy na pewno chcesz zrestartować grę?",
"vcmi.adventureMap.noTownWithMarket" : "Brak dostępnego targowiska!",
"vcmi.adventureMap.noTownWithTavern" : "Brak dostępnego miasta z karczmą!",
"vcmi.adventureMap.spellUnknownProblem" : "Nieznany problem z zaklęciem, brak dodatkowych informacji.",
"vcmi.adventureMap.playerAttacked" : "Gracz został zaatakowany: %s",
"vcmi.server.errors.existingProcess" : "Inny proces vcmiserver został już uruchomiony, zakończ go nim przejdziesz dalej",
"vcmi.server.errors.modsIncompatibility" : "Mody wymagane do wczytania gry:",
"vcmi.server.confirmReconnect" : "Połączyć z ostatnią sesją?",
"vcmi.systemOptions.fullscreenButton.hover" : "Pełny ekran",
"vcmi.systemOptions.fullscreenButton.help" : "{Fullscreen}\n\n Po wybraniu VCMI uruchomi się w trybie pełnoekranowym, w przeciwnym wypadku uruchomi się w oknie",
"vcmi.systemOptions.resolutionButton.hover" : "Rozdzielczość",
"vcmi.systemOptions.resolutionButton.help" : "{Select resolution}\n\n Zmień rozdzielczość ekranu w grze. Restart gry jest wymagany, by zmiany zostały uwzględnione.",
"vcmi.systemOptions.resolutionMenu.hover" : "Wybierz rozdzielczość",
"vcmi.systemOptions.resolutionMenu.help" : "Zmień rozdzielczość ekranu w grze.",
"vcmi.townHall.missingBase" : "Podstawowy budynek %s musi zostać najpierw wybudowany",
"vcmi.townHall.noCreaturesToRecruit" : "Brak stworzeń do rekrutacji!",
"vcmi.townHall.greetingManaVortex" : "Zbliżając się do %s czujesz jak twoje ciało wypełnia energia. Ilość pkt. magii, które posiadasz, zwiększa się dwukrotnie.",
"vcmi.townHall.greetingKnowledge" : "Studiując napisy na %s odkrywasz nowe aspekty stosowania magii (wiedza +1).",
"vcmi.townHall.greetingSpellPower" : "Odwiedzając %s dowiadujesz się, jak zwiększyć potęgę swojej mocy magicznej (moc +1).",
"vcmi.townHall.greetingExperience" : "Wizyta w %s zwiększa twoje doświadczenie (doświadczenie +1000).",
"vcmi.townHall.greetingAttack" : "Krótka wizyka w %s umożliwia ci polepszenie technik walki (atak +1).",
"vcmi.townHall.greetingDefence" : "Odwiedzasz %s. Doświadczeni żołnierze, którzy tam przebywają, uczą cię sztuki skutecznej obrony (obrona +1).",
"vcmi.townHall.hasNotProduced" : "%s nic jeszcze nie wyprodukował.",
"vcmi.townHall.hasProduced" : "%s wyprodukował w tym tygodniu: %d %s.",
"vcmi.townHall.greetingCustomBonus" : "%s daje tobie +%d %s%s",
"vcmi.townHall.greetingCustomUntil" : " do następnej bitwy.",
"vcmi.townHall.greetingInTownMagicWell" : "%s przywraca ci wszystkie punkty magii.",
"vcmi.logicalExpressions.anyOf" : "Dowolne spośród:",
"vcmi.logicalExpressions.allOf" : "Wszystkie spośród:",
"vcmi.logicalExpressions.noneOf" : "Żadne spośród:",
"vcmi.heroWindow.openCommander.hover" : "Otwórz okno dowódcy",
"vcmi.heroWindow.openCommander.help" : "Wyświetla informacje o dowódcy przynależącym do tego bohatera",
"vcmi.commanderWindow.artifactMessage" : "Czy chcesz zwrócić ten artefakt bohaterowi?",
"vcmi.creatureWindow.showBonuses.hover" : "Przełącz do widoku bonusów",
"vcmi.creatureWindow.showBonuses.help" : "Wyświetla wszystkie aktywne bonusy dowódcy",
"vcmi.creatureWindow.showSkills.hover" : "Przełącz do widoku umiejętności",
"vcmi.creatureWindow.showSkills.help" : "Wyświetla wszystkie nauczone umiejętności dowódcy",
"vcmi.creatureWindow.returnArtifact.hover" : "Zwróć artefakt",
"vcmi.creatureWindow.returnArtifact.help" : "Użyj tego przycisku by zwrócić artefakt do sakwy bohatera",
"vcmi.questLog.hideComplete.hover" : "Ukryj ukończone misje",
"vcmi.questLog.hideComplete.help" : "Ukrywa wszystkie misje, które zostały zakończone",
"vcmi.randomMapTab.widgets.defaultTemplate" : "domyślny",
"vcmi.randomMapTab.widgets.templateLabel" : "Szablon",
"vcmi.randomMapTab.widgets.teamAlignmentsButton" : "Ustaw...",
"vcmi.randomMapTab.widgets.teamAlignmentsLabel" : "Sojusze"
}

View File

@@ -0,0 +1,225 @@
{
"vcmi.adventureMap.monsterThreat.title" : "\n\n Сила загону: ",
"vcmi.adventureMap.monsterThreat.levels.0" : "Безсилий",
"vcmi.adventureMap.monsterThreat.levels.1" : "Дуже слабкий",
"vcmi.adventureMap.monsterThreat.levels.2" : "Слабкий",
"vcmi.adventureMap.monsterThreat.levels.3" : "Трохи слабша",
"vcmi.adventureMap.monsterThreat.levels.4" : "Відповідна",
"vcmi.adventureMap.monsterThreat.levels.5" : "Трохи сильніша",
"vcmi.adventureMap.monsterThreat.levels.6" : "Сильніша",
"vcmi.adventureMap.monsterThreat.levels.7" : "Дуже сильна",
"vcmi.adventureMap.monsterThreat.levels.8" : "Кидає виклик",
"vcmi.adventureMap.monsterThreat.levels.9" : "Нездоланна",
"vcmi.adventureMap.monsterThreat.levels.10" : "Смертельна",
"vcmi.adventureMap.monsterThreat.levels.11" : "Неможлива",
"vcmi.adventureMap.confirmRestartGame" : "Ви впевнені, що хочете перезапустити гру?",
"vcmi.adventureMap.noTownWithMarket" : "Немає доступних ринків!",
"vcmi.adventureMap.noTownWithTavern" : "Немає доступного міста з таверною!",
"vcmi.adventureMap.spellUnknownProblem" : "Невідома проблема з цим заклинанням, більше інформації немає.",
"vcmi.adventureMap.playerAttacked" : "Гравця атаковано: %s",
"vcmi.server.errors.existingProcess" : "Працює інший процес vcmiserver, будь ласка, спочатку завершіть його",
"vcmi.server.errors.modsIncompatibility" : "Потрібні модифікації для завантаження гри:",
"vcmi.server.confirmReconnect" : "Підключитися до минулої сесії?",
"vcmi.systemOptions.fullscreenButton.hover" : "Режим на весь екран",
"vcmi.systemOptions.fullscreenButton.help" : "{Режим на весь екран}\n\n Якщо обрано, VCMI буде запускатися в режимі на весь екран, інакше — віконний режим",
"vcmi.systemOptions.resolutionButton.hover" : "Розширення екрану",
"vcmi.systemOptions.resolutionButton.help" : "{Розширення екрану}\n\n Зміна розширення екрану в грі. Аби зміни набули чинності необхідно перезавантажити гру.",
"vcmi.systemOptions.resolutionMenu.hover" : "Обрати розширення екрану",
"vcmi.systemOptions.resolutionMenu.help" : "Змінити розширення екрану в грі.",
"vcmi.townHall.missingBase" : "Спочатку необхідно звести початкову будівлю: %s",
"vcmi.townHall.noCreaturesToRecruit" : "Немає істот, яких можна завербувати!",
"vcmi.townHall.greetingManaVortex" : "Неподалік %s ваше тіло наповнюється новою силою. Ваша звична магічна енергія сьогодні подвоєна.",
"vcmi.townHall.greetingKnowledge" : "Ви вивчили знаки на %s, і на вас зійшло прозріння у справах магії. (+1 Knowledge).",
"vcmi.townHall.greetingSpellPower" : "В %s вас навчили новим методам концентрації магічної сили. (+1 Power).",
"vcmi.townHall.greetingExperience" : "Відвідавши %s, ви дізналися багато нового. (+1000 Experience).",
"vcmi.townHall.greetingAttack" : "Перебування у %s дозволило вам краще використовувати бойові навички (+1 Attack Skill).",
"vcmi.townHall.greetingDefence" : "У %s досвідчені воїни виклали вам свої захисні вміння. (+1 Defense).",
"vcmi.townHall.hasNotProduced" : "Поки що %s нічого не створило.",
"vcmi.townHall.hasProduced" : "Цього тижня %s створило %d одиниць, цього разу це %s.",
"vcmi.townHall.greetingCustomBonus" : "%s дає вам +%d %s%s",
"vcmi.townHall.greetingCustomUntil" : " до наступної битви.",
"vcmi.townHall.greetingInTownMagicWell" : "%s повністю відновлює ваш запас очків магії.",
"vcmi.logicalExpressions.anyOf" : "Будь-що з перерахованого:",
"vcmi.logicalExpressions.allOf" : "Все з перерахованого:",
"vcmi.logicalExpressions.noneOf" : "Нічого з перерахованого:",
"vcmi.heroWindow.openCommander.hover" : "Відкрити вікно командира",
"vcmi.heroWindow.openCommander.help" : "Показує інформацію про командира героя",
"vcmi.commanderWindow.artifactMessage" : "Бажаєте передати цей артефакт герою?",
"vcmi.creatureWindow.showBonuses.hover" : "Перейти до перегляду бонусів",
"vcmi.creatureWindow.showBonuses.help" : "Відображає всі активні бонуси командира",
"vcmi.creatureWindow.showSkills.hover" : "Перейдіть до перегляду вмінь",
"vcmi.creatureWindow.showSkills.help" : "Відображає всі вивчені командиром вміння",
"vcmi.creatureWindow.returnArtifact.hover" : "Повернути артефакт",
"vcmi.creatureWindow.returnArtifact.help" : "Використовуйте цю кнопку, щоб повернути артефакт загону назад у рюкзак героя",
"vcmi.questLog.hideComplete.hover" : "Приховати завершені квести",
"vcmi.questLog.hideComplete.help" : "Приховує всі квести, які вже мають стан виконаних",
"vcmi.randomMapTab.widgets.defaultTemplate" : "за замовчуванням",
"vcmi.randomMapTab.widgets.templateLabel" : "Шаблон",
"vcmi.randomMapTab.widgets.teamAlignmentsButton" : "Налаштувати...",
"vcmi.randomMapTab.widgets.teamAlignmentsLabel" : "Розподіл команд",
"core.bonus.ADDITIONAL_ATTACK.name" : "Подвійний удар",
"core.bonus.ADDITIONAL_ATTACK.description" : "Атакує двічі",
"core.bonus.ADDITIONAL_RETALIATION.name" : "Додаткові відплати",
"core.bonus.ADDITIONAL_RETALIATION.description" : "Може нанести ${val} додаткових ударів у відповідь",
"core.bonus.AIR_IMMUNITY.name" : "Імунітет до повітря",
"core.bonus.AIR_IMMUNITY.description" : "Імунітет до всіх заклять школи повітря",
"core.bonus.ATTACKS_ALL_ADJACENT.name" : "Атакує всіх навколо",
"core.bonus.ATTACKS_ALL_ADJACENT.description" : "Атакує всіх сусідніх ворогів",
"core.bonus.BLOCKS_RETALIATION.name" : "Ворог не відповідає",
"core.bonus.BLOCKS_RETALIATION.description" : "Ворог не може атакувати у відповідь",
"core.bonus.BLOCKS_RANGED_RETALIATION.name" : "Немає дальнього удару у відповідь",
"core.bonus.BLOCKS_RANGED_RETALIATION.description" : "Ворог не може відповісти пострілом",
"core.bonus.CATAPULT.name" : "Катапульта",
"core.bonus.CATAPULT.description" : "Атакує стіни фортеці",
"core.bonus.CATAPULT_EXTRA_SHOTS.name" : "Додаткові атаки стін",
"core.bonus.CATAPULT_EXTRA_SHOTS.description" : "Може вражати стіни фортеці ${val} додаткових разів за атаку",
"core.bonus.CHANGES_SPELL_COST_FOR_ALLY.name" : "Зменшує вартість закляття (${value})",
"core.bonus.CHANGES_SPELL_COST_FOR_ALLY.description" : "Зменшує вартість закляття для героя",
"core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.name" : "Демпфер магії (${value})",
"core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.description" : "Збільшує вартість ворожих заклять",
"core.bonus.CHARGE_IMMUNITY.name" : "Імунітет до атак з розгону",
"core.bonus.CHARGE_IMMUNITY.description" : "Імунітет до турнірної переваги",
"core.bonus.DARKNESS.name" : "Покриття темряви",
"core.bonus.DARKNESS.description" : "Додає ${val} радіусу темряви",
"core.bonus.DEATH_STARE.name" : "Погляд смерті (${val}%)",
"core.bonus.DEATH_STARE.description" : "${val}% шанс вбити одну істоту",
"core.bonus.DEFENSIVE_STANCE.name" : "Бонус до захисту",
"core.bonus.DEFENSIVE_STANCE.description" : "+${val} Захист при обороні",
"core.bonus.DESTRUCTION.name" : "Знищення",
"core.bonus.DESTRUCTION.description" : "Має ${val}% шанс вбити додаткових юнітів після атаки",
"core.bonus.DOUBLE_DAMAGE_CHANCE.name" : "Смертельний удар",
"core.bonus.DOUBLE_DAMAGE_CHANCE.description" : "${val}% шанс нанести подвійний шкоди",
"core.bonus.DRAGON_NATURE.name" : "Дракон",
"core.bonus.DRAGON_NATURE.description" : "Істота має драконячу природу",
"core.bonus.DIRECT_DAMAGE_IMMUNITY.name" : "Імунітет до прямої шкоди",
"core.bonus.DIRECT_DAMAGE_IMMUNITY.description" : "Імунітет до заклять, що завдають прямої шкоди",
"core.bonus.EARTH_IMMUNITY.name" : "Імунітет Землі",
"core.bonus.EARTH_IMMUNITY.description" : "Імунітет до всіх заклять школи Землі",
"core.bonus.ENCHANTER.name" : "Чарівник",
"core.bonus.ENCHANTER.description" : "Може використовувати масове закляття ${subtype.spell} кожного ходу",
"core.bonus.ENCHANTED.name" : "Зачарований",
"core.bonus.ENCHANTED.description" : "Піддається впливу постійних закляття ${subtype.spell}",
"core.bonus.ENEMY_DEFENCE_REDUCTION.name" : "Ігнорує ${val}% захисту",
"core.bonus.ENEMY_DEFENCE_REDUCTION.description" : "Ігнорує частину захисту для атаки",
"core.bonus.FIRE_IMMUNITY.name" : "Імунітет до вогню",
"core.bonus.FIRE_IMMUNITY.description" : "Імунітет до всіх заклять школи вогню",
"core.bonus.FIRE_SHIELD.name" : "Вогняний щит (${value}%)",
"core.bonus.FIRE_SHIELD.description" : "Повертає частину шкоди ближнього бою тому, хто їх завдав",
"core.bonus.FIRST_STRIKE.name" : "Перший удар",
"core.bonus.FIRST_STRIKE.description" : "Цей загін атакує першим замість того, щоб відповідати",
"core.bonus.FEAR.name" : "Страх",
"core.bonus.FEAR.description" : "Спричиняє страх у загоні ворога",
"core.bonus.FEARLESS.name" : "Безстрашний",
"core.bonus.FEARLESS.description" : "Імунітет до страху",
"core.bonus.FLYING.name" : "Літає",
"core.bonus.FLYING.description" : "Може літати (ігнорує перешкоди)",
"core.bonus.FREE_SHOOTING.name" : "Стріляє впритул",
"core.bonus.FREE_SHOOTING.description" : "Може стріляти в ближньому бою",
"core.bonus.FULL_HP_REGENERATION.name" : "Регенерація",
"core.bonus.FULL_HP_REGENERATION.description" : "Може регенерувати до повного здоров'я",
"core.bonus.GARGOYLE.name" : "Горгулья",
"core.bonus.GARGOYLE.description" : "Не може бути відроджена або зцілена",
"core.bonus.GENERAL_DAMAGE_REDUCTION.name" : "Зменшує шкоду (${val}%)",
"core.bonus.GENERAL_DAMAGE_REDUCTION.description" : "Зменшує фізичний урон від ударів з дальньої та ближньої дистанції",
"core.bonus.HATE.name" : "Ненавидить ${subtype.creature}",
"core.bonus.HATE.description" : "Завдає на ${val}% більше шкоди",
"core.bonus.HEALER.name" : "Цілитель",
"core.bonus.HEALER.description" : "Лікує союзників",
"core.bonus.HP_REGENERATION.name" : "Регенерація",
"core.bonus.HP_REGENERATION.description" : "Відновлює ${val} очок здоров'я кожного раунду",
"core.bonus.JOUSTING.name" : "Турнірна перевага",
"core.bonus.JOUSTING.description" : "+5% шкоди за кожен пройдений гекс",
"core.bonus.KING1.name" : "Король 1",
"core.bonus.KING1.description" : "Вразливий до 1-го рівня закляття Вбивця",
"core.bonus.KING2.name" : "Король 2",
"core.bonus.KING2.description" : "Вразливий до 2-го рівня закляття Вбивця",
"core.bonus.KING3.name" : "Король 3",
"core.bonus.KING3.description" : "Вразливий до 3-го рівня закляття Вбивця",
"core.bonus.LEVEL_SPELL_IMMUNITY.name" : "Імунітет до заклять 1-${val}",
"core.bonus.LEVEL_SPELL_IMMUNITY.description" : "Імунітет до заклять рівнів 1-${val}",
"core.bonus.LIFE_DRAIN.name" : "Висмоктує життя (${val}%)",
"core.bonus.LIFE_DRAIN.description" : "Висмоктує ${val}% від завданої шкоди",
"core.bonus.MANA_CHANNELING.name" : "Магічний канал ${val}%",
"core.bonus.MANA_CHANNELING.description" : "Повертає вашому герою ману, витрачену ворогом",
"core.bonus.MANA_DRAIN.name" : "Викрадання мани",
"core.bonus.MANA_DRAIN.description" : "Викрадає ${val} мани кожного ходу",
"core.bonus.MAGIC_MIRROR.name" : "Магічне дзеркало (${val}%)",
"core.bonus.MAGIC_MIRROR.description" : "Відбиває ворожі заклинання до випадкової істоти ворога з силою в ${val}%",
"core.bonus.MAGIC_RESISTANCE.name" : "Опір магії (${MR}%)",
"core.bonus.MAGIC_RESISTANCE.description" : "${MR}% шанс протистояти ворожим закляттям",
"core.bonus.MIND_IMMUNITY.name" : "Імунітет до заклять розуму",
"core.bonus.MIND_IMMUNITY.description" : "Імунітет до заклять типу ",
"core.bonus.NO_DISTANCE_PENALTY.name" : "Немає штрафу за відстань",
"core.bonus.NO_DISTANCE_PENALTY.description" : "Повна шкода з будь-якої відстані",
"core.bonus.NO_MELEE_PENALTY.name" : "Немає штрафу за ближній бій",
"core.bonus.NO_MELEE_PENALTY.description" : "Загін не має штрафу за ближній бій",
"core.bonus.NO_MORALE.name" : "Нейтральний бойовий дух",
"core.bonus.NO_MORALE.description" : "Загін має імунітет до ефектів моралі",
"core.bonus.NO_WALL_PENALTY.name" : "Немає штрафу за перешкоди",
"core.bonus.NO_WALL_PENALTY.description" : "Повна шкода при пострілах через стіни",
"core.bonus.NON_LIVING.name" : "Не жива",
"core.bonus.NON_LIVING.description" : "Імунітет до багатьох ефектів",
"core.bonus.RANDOM_SPELLCASTER.name" : "Випадковий заклинатель",
"core.bonus.RANDOM_SPELLCASTER.description" : "Може накласти випадкове закляття",
"core.bonus.RANGED_RETALIATION.name" : "Дистанційне відплата",
"core.bonus.RANGED_RETALIATION.description" : "Може наносити контратаку пострілом",
"core.bonus.RECEPTIVE.name" : "Сприйнятливий",
"core.bonus.RECEPTIVE.description" : "Не має імунітету до дружніх заклять",
"core.bonus.REBIRTH.name" : "Відродження (${val}%)",
"core.bonus.REBIRTH.description" : "${val}% загону відродиться після смерті",
"core.bonus.RETURN_AFTER_STRIKE.name" : "Атакує і повертається",
"core.bonus.RETURN_AFTER_STRIKE.description" : "Повертається після атаки ближнього бою",
"core.bonus.SELF_LUCK.name" : "Позитивна удача",
"core.bonus.SELF_LUCK.description" : "Завжди має позитивну удачу",
"core.bonus.SELF_MORALE.name" : "Позитивний бойовий дух",
"core.bonus.SELF_MORALE.description" : "Завжди має позитивний бойовий дух",
"core.bonus.SHOOTER.name" : "Стрілок",
"core.bonus.SHOOTER.description" : "Істота може стріляти",
"core.bonus.SHOOTS_ALL_ADJACENT.name" : "Стріляйте по площі",
"core.bonus.SHOOTS_ALL_ADJACENT.description" : "Дистанційні атаки цієї істоти вражають всі цілі на невеликій площі",
"core.bonus.SOUL_STEAL.name" : "Викрадення душ",
"core.bonus.SOUL_STEAL.description" : "Отримує ${val} нових істот за кожного вбитого ворога",
"core.bonus.SPELLCASTER.name" : "Заклинатель",
"core.bonus.SPELLCASTER.description" : "Може використовувати закляття ${subtype.spell}",
"core.bonus.SPELL_AFTER_ATTACK.name" : "Після атаки",
"core.bonus.SPELL_AFTER_ATTACK.description" : "${val}%, щоб застосувати ${subtype.spell} після атаки",
"core.bonus.SPELL_BEFORE_ATTACK.name" : "закляття перед атакою",
"core.bonus.SPELL_BEFORE_ATTACK.description" : "Застосовує ${subtype.spell} з вірогідністю ${value}% перед атакою",
"core.bonus.SPELL_DAMAGE_REDUCTION.name" : "Стійкість до заклять",
"core.bonus.SPELL_DAMAGE_REDUCTION.description" : "Шкода від заклять зменшується на ${val}%.",
"core.bonus.SPELL_IMMUNITY.name" : "Імунітет до заклять",
"core.bonus.SPELL_IMMUNITY.description" : "Імунітет до ${subtype.spell}",
"core.bonus.SPELL_LIKE_ATTACK.name" : "Атака, схожа на закляття",
"core.bonus.SPELL_LIKE_ATTACK.description" : "Атакує за допомогою ${subtype.spell}",
"core.bonus.SPELL_RESISTANCE_AURA.name" : "Аура стійкості",
"core.bonus.SPELL_RESISTANCE_AURA.description" : "Поруч розташовані стеки отримують ${val}% опору",
"core.bonus.SUMMON_GUARDIANS.name" : "Закликати охоронців",
"core.bonus.SUMMON_GUARDIANS.description" : "На початку бою викликає ${subtype.creature} (${val}%)",
"core.bonus.SYNERGY_TARGET.name" : "Синергізм",
"core.bonus.SYNERGY_TARGET.description" : "Ця істота вразлива до ефекту синергії",
"core.bonus.TWO_HEX_ATTACK_BREATH.name" : "Подих",
"core.bonus.TWO_HEX_ATTACK_BREATH.description" : "Атакує додаткову ціль позаду",
"core.bonus.THREE_HEADED_ATTACK.name" : "Триголова атака",
"core.bonus.THREE_HEADED_ATTACK.description" : "Атакує до трьох сусідніх загонів",
"core.bonus.TRANSMUTATION.name" : "Трансмутація",
"core.bonus.TRANSMUTATION.description" : "${val}% шанс перетворити атакованого юніта в інший тип",
"core.bonus.UNDEAD.name" : "Нежить",
"core.bonus.UNDEAD.description" : "Істота є нежить",
"core.bonus.UNLIMITED_RETALIATIONS.name" : "Необмежена кількість ударів у відповідь",
"core.bonus.UNLIMITED_RETALIATIONS.description" : "Відбиває будь-яку кількість атак",
"core.bonus.WATER_IMMUNITY.name" : "Імунітет до води",
"core.bonus.WATER_IMMUNITY.description" : "Імунітет до всіх заклять школи Води",
"core.bonus.WIDE_BREATH.name" : "Широкий подих",
"core.bonus.WIDE_BREATH.description" : "Атака широким подихом",
}

View File

@@ -7,6 +7,21 @@
"description" : "Grundlegende Dateien, die für die korrekte Ausführung von VCMI erforderlich sind",
"author" : "VCMI-Team",
"modType" : "Grafik",
"translations" : [
"config/vcmi/german.json"
]
},
"polish" : {
"name" : "VCMI essential files",
"description" : "Essential files required for VCMI to run correctly",
"author" : "VCMI Team",
"modType" : "Graphical",
"translations" : [
"config/vcmi/polish.json"
]
},
"ukrainian" : {
@@ -14,15 +29,23 @@
"description" : "Ключові файли необхідні для повноцінної роботи VCMI",
"author" : "Команда VCMI",
"modType" : "Графіка",
"translations" : [
"config/vcmi/ukrainian.json"
]
},
"version" : "1.1",
"version" : "1.1.1",
"author" : "VCMI Team",
"contact" : "http://forum.vcmi.eu/index.php",
"modType" : "Graphical",
"factions" : [ "config/vcmi/towerFactions" ],
"creatures" : [ "config/vcmi/towerCreature" ],
"translations" : [
"config/vcmi/english.json"
],
"filesystem":
{

View File

@@ -1,476 +0,0 @@
// macros:
// ${val} - value of bonuses; Selector: type,subtype
// ${subtype.creature} - creature name
// ${subtype.spell} - spell name
// ${MR} - magic resistance of bearer
{
"ADDITIONAL_ATTACK":
{
"name": "Double Strike",
"description": "Attacks twice"
},
"ADDITIONAL_RETALIATION":
{
"name": "Additional retaliations",
"description": "May Retaliate ${val} extra times"
},
"AIR_IMMUNITY":
{
"name": "Air immunity",
"description": "Immune to all Air school spells"
},
"ATTACKS_ALL_ADJACENT":
{
"name": "Attack all around",
"description": "Attacks all adjacent enemies"
},
"BLOCKS_RETALIATION":
{
"name": "No retaliation",
"description": "Enemy cannot Retaliate"
},
"BLOCKS_RANGED_RETALIATION":
{
"name": "No ranged retaliation",
"description": "Enemy cannot Retaliate by shooting"
},
"CATAPULT":
{
"name": "Catapult",
"description": "Attacks siege walls"
},
"CATAPULT_EXTRA_SHOTS":
{
"name": "Additional siege attacks",
"description": "Can hit siege walls ${val} extra times per attack"
},
"CHANGES_SPELL_COST_FOR_ALLY":
{
"name": "Reduce Casting Cost (${val})",
"description": "Reduces spell cost for hero"
},
"CHANGES_SPELL_COST_FOR_ENEMY":
{
"name": "Magic Damper (${val})",
"description": "Increases Cost of enemy spells"
},
"CHARGE_IMMUNITY":
{
"name": "Immune to Charge",
"description": "Immune to Champion charge"
},
"DARKNESS":
{
"name": "Darkness cover",
"description": "Adds ${val} darkness radius"
},
"DEATH_STARE":
{
"name": "Death Stare (${val}%)",
"description": "${val}% chance to kill single creature"
},
"DEFENSIVE_STANCE":
{
"name": "Defense Bonus",
"description": "+${val} Defense when defending"
},
"DESTRUCTION":
{
"name": "Destruction",
"description": "Has ${val}% chance to kill extra units after attack"
},
"DOUBLE_DAMAGE_CHANCE":
{
"name": "Death Blow",
"description": "${val}% chance for double damage"
},
"DRAGON_NATURE":
{
"name": "Dragon",
"description": "Creature has a Dragon Nature"
},
"DIRECT_DAMAGE_IMMUNITY":
{
"name": "Direct Damage Immunity",
"description": "Immune to direct damage spells"
},
"EARTH_IMMUNITY":
{
"name": "Earth immunity",
"description": "Immune to all Earth school spells"
},
"ENCHANTER":
{
"name": "Enchanter",
"description": "Can cast mass ${subtype.spell} every turn"
},
"ENCHANTED":
{
"name": "Enchanted",
"description": "Affected by permanent ${subtype.spell}"
},
"ENEMY_DEFENCE_REDUCTION":
{
"name": "Ignore Defense (${val}%)",
"description": "Ignores part of Defence for the attack"
},
"FIRE_IMMUNITY":
{
"name": "Fire immunity",
"description": "Immune to all Fire school spells"
},
"FIRE_SHIELD":
{
"name": "Fire Shield (${val}%)",
"description": "Reflects part of melee damage"
},
"FIRST_STRIKE":
{
"name": "First Strike",
"description": "This creature attacks first instead of retaliating"
},
"FEAR":
{
"name": "Fear",
"description": "Causes Fear on an enemy stack"
},
"FEARLESS":
{
"name": "Fearless",
"description": "Immune to Fear ability"
},
"FLYING":
{
"name": "Fly",
"description": "Can Fly (ignores obstacles)"
},
"FREE_SHOOTING":
{
"name": "Shoot Close",
"description": "Can shoot in Close Combat"
},
"FULL_HP_REGENERATION":
{
"name": "Regeneration",
"description": "May Regenerate to full Health"
},
"GARGOYLE":
{
"name": "Gargoyle",
"description": "Cannot be rised or healed"
},
"GENERAL_DAMAGE_REDUCTION":
{
"name": "Reduce Damage (${val}%)",
"description": "Reduces physical damage from ranged or melee"
},
"HATE":
{
"name": "Hates ${subtype.creature}",
"description": "Does ${val}% more damage"
},
"HEALER":
{
"name": "Healer",
"description": "Heals allied units"
},
"HP_REGENERATION":
{
"name": "Regeneration",
"description": "Heals ${val} hit points every round"
},
"JOUSTING":
{
"name": "Champion Charge",
"description": "+5% damage per hex travelled"
},
"KING1":
{
"name": "King 1",
"description": "Vulnerable to basic SLAYER"
},
"KING2":
{
"name": "King 2",
"description": "Vulnerable to advanced SLAYER"
},
"KING3":
{
"name": "King 3",
"description":"Vulnerable to expert SLAYER"
},
"LEVEL_SPELL_IMMUNITY":
{
"name": "Spell immunity 1-${val}",
"description": "Immune to spells of levels 1-${val}"
},
"LIFE_DRAIN":
{
"name": "Drain life (${val}%)",
"description": "Drains ${val}% of damage dealt"
},
"LIMITED_SHOOTING_RANGE":
{
"name": "Limited shooting range",
"description": "Cannot shoot targets beyond ${val} hexes away"
},
"MANA_CHANNELING":
{
"name": "Magic Channel ${val}%",
"description": "Gives your hero mana spent by enemy"
},
"MANA_DRAIN":
{
"name": "Mana Drain",
"description": "Drains ${val} mana every turn"
},
"MAGIC_MIRROR":
{
"name": "Magic Mirror (${val}%)",
"description": "${val}% chance to redirects an offensive spell to enemy"
},
"MAGIC_RESISTANCE":
{
"name": "Magic Resistance(${MR}%)",
"description": "${MR}% chance to resist enemy spell"
},
"MIND_IMMUNITY":
{
"name": "Mind Spell Immunity",
"description": "Immune to Mind-type spells"
},
"NO_DISTANCE_PENALTY":
{
"name": "No distance penalty",
"description": "Full damage from any distance"
},
"NO_MELEE_PENALTY":
{
"name": "No melee penalty",
"description": "Creature has no Melee Penalty"
},
"NO_MORALE":
{
"name": "Neutral Morale",
"description": "Creature is immune to morale effects"
},
"NO_WALL_PENALTY":
{
"name": "No wall penalty",
"description": "Full damage during siege"
},
"NON_LIVING":
{
"name": "Non living",
"description": "Immunity to many effects"
},
"RANDOM_SPELLCASTER":
{
"name": "Random spellcaster",
"description": "Can cast random spell"
},
"RANGED_RETALIATION":
{
"name": "Ranged retaliation",
"description": "Can perform ranged counterattack"
},
"RECEPTIVE":
{
"name": "Receptive",
"description": "No Immunity to Friendly Spells"
},
"REBIRTH":
{
"name": "Rebirth (${val}%)",
"description": "${val}% of stack will rise after death"
},
"RETURN_AFTER_STRIKE":
{
"name": "Attack and Return",
"description": "Returns after melee attack"
},
"SELF_LUCK":
{
"name": "Positive luck",
"description": "Always has Positive Luck"
},
"SELF_MORALE":
{
"name": "Positive morale",
"description": "Always has Positive Morale"
},
"SHOOTER":
{
"name": "Ranged",
"description": "Creature can shoot"
},
"SHOOTS_ALL_ADJACENT":
{
"name": "Shoot all around",
"description": "This creature's ranged attacks strike all targets in a small area"
},
"SOUL_STEAL":
{
"name": "Soul Steal",
"description": "Gains ${val} new creatures for each enemy killed"
},
"SPELLCASTER":
{
"name": "Spellcaster",
"description": "Can cast ${subtype.spell}"
},
"SPELL_AFTER_ATTACK":
{
"name": "Cast After Attack",
"description": "${val}% to cast ${subtype.spell} after attack"
},
"SPELL_BEFORE_ATTACK":
{
"name": "Cast Before Attack",
"description": "${val}% to cast ${subtype.spell} before attack"
},
"SPELL_DAMAGE_REDUCTION":
{
"name": "Spell Resistance",
"description": "Damage from spells reduced ${val}%."
},
"SPELL_IMMUNITY":
{
"name": "Spell immunity",
"description": "Immune to ${subtype.spell}"
},
"SPELL_LIKE_ATTACK":
{
"name": "Spell-like attack",
"description": "Attacks with ${subtype.spell}"
},
"SPELL_RESISTANCE_AURA":
{
"name": "Aura of Resistance",
"description": "Nearby stacks get ${val}% resistance"
},
"SUMMON_GUARDIANS":
{
"name": "Summon guardians",
"description": "At battle start summons ${subtype.creature} (${val}%)"
},
"SYNERGY_TARGET":
{
"name": "Synergizable",
"description": "This creature is vulnerable to synergy effect"
},
"TWO_HEX_ATTACK_BREATH":
{
"name": "Breath",
"description": "Breath Attack (2-hex range)"
},
"THREE_HEADED_ATTACK":
{
"name": "Three-headed attack",
"description": "Attacks three adjacent units"
},
"TRANSMUTATION":
{
"name": "Transmutation",
"description": "${val}% chance to transform attacked unit to other type"
},
"UNDEAD":
{
"name": "Undead",
"description": "Creature is Undead"
},
"UNLIMITED_RETALIATIONS":
{
"name": "Unlimited retaliations",
"description": "Retaliates any number of attacks"
},
"WATER_IMMUNITY":
{
"name": "Water immunity",
"description": "Immune to all Water school spells"
},
"WIDE_BREATH":
{
"name": "Wide breath",
"description": "Wide breath attack (multiple hexes)"
}
}

View File

@@ -66,8 +66,7 @@
"bonuses" :
[
"config/bonuses.json",
"config/bonuses_texts.json"
"config/bonuses.json"
],
"spells" :
[

View File

@@ -8,7 +8,7 @@
"localizable" : {
"type":"object",
"additionalProperties" : false,
"required" : [ "name", "description", "author", "modType" ],
"required" : [ "name", "description", "modType" ],
"properties":{
"name": {
"type":"string",
@@ -18,7 +18,6 @@
"type":"string",
"description": "More lengthy description of mod. No hard limit"
},
"modType" : {
"type":"string",
"description": "Type of mod, e.g. Town, Artifacts, Graphical."
@@ -27,6 +26,11 @@
"type":"string",
"description": "Author of the mod. Can be nickname, real name or name of team"
},
"translations":{
"type":"array",
"description": "List of files with translations for this language",
"items": { "type":"string", "format" : "textFile" }
},
"changelog" : {
"type":"object",
"description": "List of changes/new features in each version",
@@ -112,27 +116,26 @@
"type":"boolean",
"description": "If set to true, mod will not be enabled automatically on install"
},
"english" : {
"$ref" : "#/definitions/localizable"
},
"german" : {
"$ref" : "#/definitions/localizable"
},
"polish" : {
"$ref" : "#/definitions/localizable"
},
"russian" : {
"$ref" : "#/definitions/localizable"
},
"ukrainian" : {
"$ref" : "#/definitions/localizable"
},
"translations":{
"type":"array",
"description": "List of files with translations for this language",
"items": { "type":"string", "format" : "textFile" }
},
"artifacts": {
"type":"array",
"description": "List of configuration files for artifacts",

View File

@@ -1,13 +0,0 @@
// Several probably missing sounds of creature abilities
// ACID.WAV Acid breath Rust Dragons
// DEATHBLO.WAV Deathblow Death knigts
// DRAINLIF.WAV Drain life Vampires
// FEAR.WAV Fear Azure dragons
// MAGCHDRN.WAV Steal mana Imps
// MAGCHFIL.WAV Steal mana Either for upgrades or for receiving mana by hero
// MAGICRES.WAV Magic resist Dwarves
// MANADRAI.WAV Mana drain Ghosts
// REGENER.WAV Regeneration Ghosts, Trolls
// RESURECT.WAV Resurrection Both archangels and Demons
// SPONTCOMB.WAV Fireball Magogs

View File

@@ -1,86 +0,0 @@
{
"vcmi.adventureMap.monsterThreat.title" : "\n\n Threat: ",
"vcmi.adventureMap.monsterThreat.levels.0" : "Effortless",
"vcmi.adventureMap.monsterThreat.levels.1" : "Very Weak",
"vcmi.adventureMap.monsterThreat.levels.2" : "Weak",
"vcmi.adventureMap.monsterThreat.levels.3" : "A bit weaker",
"vcmi.adventureMap.monsterThreat.levels.4" : "Equal",
"vcmi.adventureMap.monsterThreat.levels.5" : "A bit stronger",
"vcmi.adventureMap.monsterThreat.levels.6" : "Strong",
"vcmi.adventureMap.monsterThreat.levels.7" : "Very Strong",
"vcmi.adventureMap.monsterThreat.levels.8" : "Challenging",
"vcmi.adventureMap.monsterThreat.levels.9" : "Overpowering",
"vcmi.adventureMap.monsterThreat.levels.10" : "Deadly",
"vcmi.adventureMap.monsterThreat.levels.11" : "Impossible",
"vcmi.adventureMap.confirmRestartGame" : "Are you sure you want to restart game?",
"vcmi.adventureMap.noTownWithMarket" : "No available marketplace!",
"vcmi.adventureMap.noTownWithTavern" : "No available town with tavern!",
"vcmi.adventureMap.spellUnknownProblem" : "Unknown problem with this spell, no more information available.",
"vcmi.adventureMap.playerAttacked" : "Player has been attacked: %s",
"vcmi.adventureMap.moveCostDetails" : "Movement points - Cost: %TURNS turns + %POINTS points, Remaining points: %REMAINING",
"vcmi.adventureMap.moveCostDetailsNoTurns" : "Movement points - Cost: %POINTS points, Remaining points: %REMAINING",
"vcmi.server.errors.existingProcess" : "Another vcmiserver process is running, please terminate it first",
"vcmi.server.errors.modsIncompatibility" : "Required mods to load game:",
"vcmi.server.confirmReconnect" : "Connect to the last session?",
"vcmi.systemOptions.fullscreenButton.hover" : "Fullscreen",
"vcmi.systemOptions.fullscreenButton.help" : "{Fullscreen}\n\n If selected, VCMI will run in fullscreen mode, othervice VCMI will run in window",
"vcmi.systemOptions.resolutionButton.hover" : "Resolution",
"vcmi.systemOptions.resolutionButton.help" : "{Select resolution}\n\n Change in-game screen resolution. Game restart required to apply new resolution.",
"vcmi.systemOptions.resolutionMenu.hover" : "Select resolution",
"vcmi.systemOptions.resolutionMenu.help" : "Change in-game screen resolution.",
"vcmi.townHall.missingBase" : "Base building %s must be built first",
"vcmi.townHall.noCreaturesToRecruit" : "There are no creatures to recruit!",
"vcmi.townHall.greetingManaVortex" : "As you near the %s your body is filled with new energy. You have doubled your normal spell points.",
"vcmi.townHall.greetingKnowledge" : "You study the glyphs on the %s and gain insight into the workings of various magics (+1 Knowledge).",
"vcmi.townHall.greetingSpellPower" : "The %s teaches you new ways to focus your magical powers (+1 Power).",
"vcmi.townHall.greetingExperience" : "A visit to the %s teaches you many new skills (+1000 Experience).",
"vcmi.townHall.greetingAttack" : "Some time spent at the %s allows you to learn more effective combat skills (+1 Attack Skill).",
"vcmi.townHall.greetingDefence" : "Spending time in the %s, the experienced warriors therein teach you additional defensive skills (+1 Defense).",
"vcmi.townHall.hasNotProduced" : "The %s has not produced anything yet.",
"vcmi.townHall.hasProduced" : "The %s produced %d %s this week.",
"vcmi.townHall.greetingCustomBonus" : "%s gives you +%d %s%s",
"vcmi.townHall.greetingCustomUntil" : " until next battle.",
"vcmi.townHall.greetingInTownMagicWell" : "%s has restored your spell points to maximum.",
"vcmi.logicalExpressions.anyOf" : "Any of the following:",
"vcmi.logicalExpressions.allOf" : "All of the following:",
"vcmi.logicalExpressions.noneOf" : "None of the following:",
"vcmi.heroWindow.openCommander.hover" : "Open commander window",
"vcmi.heroWindow.openCommander.help" : "Displays information about commander of this hero",
"vcmi.commanderWindow.artifactMessage" : "Do you want to give this artifact back to hero?",
"vcmi.creatureWindow.showBonuses.hover" : "Switch to bonuses view",
"vcmi.creatureWindow.showBonuses.help" : "Displays all active bonuses of the commander",
"vcmi.creatureWindow.showSkills.hover" : "Switch to skills view",
"vcmi.creatureWindow.showSkills.help" : "Displays all learned skills of the commander",
"vcmi.creatureWindow.returnArtifact.hover" : "Give back artifact",
"vcmi.creatureWindow.returnArtifact.help" : "Use this button to return stack artifact back into hero backpack",
"vcmi.questLog.hideComplete.hover" : "Hide complete quests",
"vcmi.questLog.hideComplete.help" : "Hide all quests that already completed",
"vcmi.randomMapTab.widgets.defaultTemplate" : "default",
"vcmi.randomMapTab.widgets.templateLabel" : "Template",
"vcmi.randomMapTab.widgets.teamAlignmentsButton" : "Setup...",
"vcmi.randomMapTab.widgets.teamAlignmentsLabel" : "Team alignments",
// few strings from WoG used by vcmi
"vcmi.stackExperience.description" : "» S t a c k E x p e r i e n c e D e t a i l s «\n\nCreature Type ................... : %s\nExperience Rank ................. : %s (%i)\nExperience Points ............... : %i\nExperience Points to Next Rank .. : %i\nMaximum Experience per Battle ... : %i%% (%i)\nNumber of Creatures in stack .... : %i\nMaximum New Recruits\n without losing current Rank .... : %i\nExperience Multiplier ........... : %.2f\nUpgrade Multiplier .............. : %.2f\nExperience after Rank 10 ........ : %i\nMaximum New Recruits to remain at\n Rank 10 if at Maximum Experience : %i",
"vcmi.stackExperience.rank.1" : "Basic",
"vcmi.stackExperience.rank.2" : "Novice",
"vcmi.stackExperience.rank.3" : "Trained",
"vcmi.stackExperience.rank.4" : "Skilled",
"vcmi.stackExperience.rank.5" : "Proven",
"vcmi.stackExperience.rank.6" : "Veteran",
"vcmi.stackExperience.rank.7" : "Adept",
"vcmi.stackExperience.rank.8" : "Expert",
"vcmi.stackExperience.rank.9" : "Elite",
"vcmi.stackExperience.rank.10" : "Master",
"vcmi.stackExperience.rank.11" : "Ace"
}

View File

@@ -18,99 +18,29 @@
#include "GameConstants.h"
#include "CCreatureHandler.h"
#include "CGeneralTextHandler.h"
#include "spells/CSpellHandler.h"
template class std::vector<VCMI_LIB_WRAP_NAMESPACE(CBonusType)>;
VCMI_LIB_NAMESPACE_BEGIN
///MacroString
MacroString::MacroString(const std::string & format)
{
static const std::string MACRO_START = "${";
static const std::string MACRO_END = "}";
static const size_t MACRO_START_L = 2;
static const size_t MACRO_END_L = 1;
size_t end_pos = 0;
size_t start_pos = std::string::npos;
do
{
start_pos = format.find(MACRO_START, end_pos);
if(!(start_pos == std::string::npos))
{
//chunk before macro
items.push_back(Item(Item::STRING, format.substr(end_pos, start_pos - end_pos)));
start_pos += MACRO_START_L;
end_pos = format.find(MACRO_END, start_pos);
if(end_pos == std::string::npos)
{
logBonus->warn("Format error in: %s", format);
end_pos = start_pos;
break;
}
else
{
items.push_back(Item(Item::MACRO, format.substr(start_pos, end_pos - start_pos)));
end_pos += MACRO_END_L;
}
}
}
while(start_pos != std::string::npos);
//no more macros
items.push_back(Item(Item::STRING, format.substr(end_pos)));
}
std::string MacroString::build(const GetValue & getValue) const
{
std::string result;
for(const Item & i : items)
{
switch(i.type)
{
case Item::MACRO:
{
result += getValue(i.value);
break;
}
case Item::STRING:
{
result += i.value;
break;
}
}
}
return result;
}
///CBonusType
CBonusType::CBonusType()
CBonusType::CBonusType():
hidden(true)
{}
std::string CBonusType::getNameTextID() const
{
hidden = true;
icon.clear();
nameTemplate.clear();
descriptionTemplate.clear();
return TextIdentifier( "core", "bonus", identifier, "name").get();
}
CBonusType::~CBonusType()
std::string CBonusType::getDescriptionTextID() const
{
return TextIdentifier( "core", "bonus", identifier, "description").get();
}
void CBonusType::buildMacros()
{
name = MacroString(nameTemplate);
description = MacroString(descriptionTemplate);
}
///CBonusTypeHandler
CBonusTypeHandler::CBonusTypeHandler()
@@ -136,39 +66,26 @@ CBonusTypeHandler::~CBonusTypeHandler()
std::string CBonusTypeHandler::bonusToString(const std::shared_ptr<Bonus> & bonus, const IBonusBearer * bearer, bool description) const
{
auto getValue = [=](const std::string & name) -> std::string
{
if(name == "val")
{
return boost::lexical_cast<std::string>(bearer->valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype)));
}
else if(name == "subtype.creature")
{
const CreatureID cre(bonus->subtype);
return cre.toCreature()->getNamePluralTranslated();
}
else if(name == "subtype.spell")
{
const SpellID sp(bonus->subtype);
return sp.toSpell()->getNameTranslated();
}
else if(name == "MR")
{
return boost::lexical_cast<std::string>(bearer->magicResistance());
}
else
{
logBonus->warn("Unknown macro in bonus config: %s", name);
return "[error]";
}
};
const CBonusType & bt = bonusTypes[bonus->type];
if(bt.hidden)
return "";
const MacroString & macro = description ? bt.description : bt.name;
return macro.build(getValue);
std::string textID = description ? bt.getDescriptionTextID() : bt.getNameTextID();
std::string text = VLC->generaltexth->translate(textID);
if (text.find("${val}") != std::string::npos)
boost::algorithm::replace_all(text, "${val}", std::to_string(bearer->valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype))));
if (text.find("${subtype.creature}") != std::string::npos)
boost::algorithm::replace_all(text, "${subtype.creature}", CreatureID(bonus->subtype).toCreature()->getNamePluralTranslated());
if (text.find("${subtype.spell}") != std::string::npos)
boost::algorithm::replace_all(text, "${subtype.spell}", SpellID(bonus->subtype).toSpell()->getNameTranslated());
if (text.find("${MR}") != std::string::npos)
boost::algorithm::replace_all(text, "${MR}", std::to_string(bearer->magicResistance()));
return text;
}
std::string CBonusTypeHandler::bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const
@@ -304,31 +221,33 @@ void CBonusTypeHandler::load(const JsonNode & config)
//
// bonusTypes.push_back(bt);
logBonus->warn("Adding new bonuses not implemented (%s)", node.first);
logBonus->warn("Unrecognized bonus name! (%s)", node.first);
}
else
{
CBonusType & bt = bonusTypes[it->second];
loadItem(node.second, bt);
loadItem(node.second, bt, node.first);
logBonus->trace("Loaded bonus type %s", node.first);
}
}
}
void CBonusTypeHandler::loadItem(const JsonNode & source, CBonusType & dest)
void CBonusTypeHandler::loadItem(const JsonNode & source, CBonusType & dest, const std::string & name)
{
dest.nameTemplate = source["name"].String();
dest.descriptionTemplate = source["description"].String();
dest.identifier = name;
dest.hidden = source["hidden"].Bool(); //Null -> false
if (!dest.hidden)
{
VLC->generaltexth->registerString(dest.getNameTextID(), source["name"].String());
VLC->generaltexth->registerString(dest.getDescriptionTextID(), source["description"].String());
}
const JsonNode & graphics = source["graphics"];
if(!graphics.isNull())
{
dest.icon = graphics["icon"].String();
}
dest.buildMacros();
}
VCMI_LIB_NAMESPACE_END

View File

@@ -21,53 +21,27 @@ class JsonNode;
typedef Bonus::BonusType BonusTypeID;
class MacroString
{
struct Item
{
enum ItemType
{
STRING, MACRO
};
Item(ItemType _type, std::string _value): type(_type), value(_value){};
ItemType type;
std::string value; //constant string or macro name
};
std::vector<Item> items;
public:
typedef std::function<std::string(const std::string &)> GetValue;
MacroString() = default;
~MacroString() = default;
explicit MacroString(const std::string & format);
std::string build(const GetValue & getValue) const;
};
class DLL_LINKAGE CBonusType
{
public:
CBonusType();
~CBonusType();
std::string getNameTextID() const;
std::string getDescriptionTextID() const;
template <typename Handler> void serialize(Handler & h, const int version)
{
h & icon;
h & nameTemplate;
h & descriptionTemplate;
h & identifier;
h & hidden;
if (!h.saving)
buildMacros();
}
private:
void buildMacros();
MacroString name, description;
friend class CBonusTypeHandler;
std::string icon;
std::string nameTemplate, descriptionTemplate;
std::string identifier;
bool hidden;
};
@@ -91,7 +65,7 @@ public:
private:
void load();
void load(const JsonNode & config);
void loadItem(const JsonNode & source, CBonusType & dest);
void loadItem(const JsonNode & source, CBonusType & dest, const std::string & name);
std::vector<CBonusType> bonusTypes; //index = BonusTypeID
};

View File

@@ -103,42 +103,25 @@ bool Unicode::isValidString(const char * data, size_t size)
return true;
}
static std::string getSelectedEncoding()
/// Detects language and encoding of H3 text files based on matching against pregenerated footprints of H3 file
void CGeneralTextHandler::detectInstallParameters() const
{
auto explicitSetting = settings["general"]["encoding"].String();
if (explicitSetting != "auto")
return explicitSetting;
return settings["session"]["encoding"].String();
}
struct LanguageFootprint
{
std::string language;
std::string encoding;
std::array<double, 16> footprint;
};
/// Detects encoding of H3 text files based on matching against pregenerated footprints of H3 file
/// Can also detect language of H3 install, however right now this is not necessary
static void detectEncoding()
{
static const size_t knownCount = 6;
// "footprints" of data collected from known versions of H3
static const std::array<std::array<double, 16>, knownCount> knownFootprints =
{ {
{ { 0.0559, 0.0000, 0.1983, 0.0051, 0.0222, 0.0183, 0.4596, 0.2405, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000 } },
{ { 0.0493, 0.0000, 0.1926, 0.0047, 0.0230, 0.0121, 0.4133, 0.2780, 0.0002, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0259, 0.0008 } },
{ { 0.0534, 0.0000, 0.1705, 0.0047, 0.0418, 0.0208, 0.4775, 0.2191, 0.0001, 0.0000, 0.0000, 0.0000, 0.0000, 0.0005, 0.0036, 0.0080 } },
{ { 0.0534, 0.0000, 0.1701, 0.0067, 0.0157, 0.0133, 0.4328, 0.2540, 0.0001, 0.0043, 0.0000, 0.0244, 0.0000, 0.0000, 0.0181, 0.0071 } },
{ { 0.0548, 0.0000, 0.1744, 0.0061, 0.0031, 0.0009, 0.0046, 0.0136, 0.0000, 0.0004, 0.0000, 0.0000, 0.0227, 0.0061, 0.4882, 0.2252 } },
{ { 0.0559, 0.0000, 0.1807, 0.0059, 0.0036, 0.0013, 0.0046, 0.0134, 0.0000, 0.0004, 0.0000, 0.0487, 0.0209, 0.0060, 0.4615, 0.1972 } }
} };
// languages of known footprints
static const std::array<std::string, knownCount> knownLanguages =
{ {
"English", "French", "German", "Polish", "Russian", "Ukrainian"
} };
// encoding that should be used for known footprints
static const std::array<std::string, knownCount> knownEncodings =
{ {
"CP1252", "CP1252", "CP1252", "CP1250", "CP1251", "CP1251"
} };
static const std::vector<LanguageFootprint> knownFootprints =
{
{ "English", "CP1252", { { 0.0559, 0.0000, 0.1983, 0.0051, 0.0222, 0.0183, 0.4596, 0.2405, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000 } } },
{ "French", "CP1252", { { 0.0493, 0.0000, 0.1926, 0.0047, 0.0230, 0.0121, 0.4133, 0.2780, 0.0002, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0259, 0.0008 } } },
{ "German", "CP1252", { { 0.0534, 0.0000, 0.1705, 0.0047, 0.0418, 0.0208, 0.4775, 0.2191, 0.0001, 0.0000, 0.0000, 0.0000, 0.0000, 0.0005, 0.0036, 0.0080 } } },
{ "Polish", "CP1250", { { 0.0534, 0.0000, 0.1701, 0.0067, 0.0157, 0.0133, 0.4328, 0.2540, 0.0001, 0.0043, 0.0000, 0.0244, 0.0000, 0.0000, 0.0181, 0.0071 } } },
{ "Russian", "CP1251", { { 0.0548, 0.0000, 0.1744, 0.0061, 0.0031, 0.0009, 0.0046, 0.0136, 0.0000, 0.0004, 0.0000, 0.0000, 0.0227, 0.0061, 0.4882, 0.2252 } } },
{ "Ukrainian", "CP1251", { { 0.0559, 0.0000, 0.1807, 0.0059, 0.0036, 0.0013, 0.0046, 0.0134, 0.0000, 0.0004, 0.0000, 0.0487, 0.0209, 0.0060, 0.4615, 0.1972 } } },
};
// load file that will be used for footprint generation
// this is one of the most text-heavy files in game and consists solely from translated texts
@@ -146,11 +129,11 @@ static void detectEncoding()
std::array<size_t, 256> charCount;
std::array<double, 16> footprint;
std::array<double, knownCount> deviations;
std::vector<double> deviations;
boost::range::fill(charCount, 0);
boost::range::fill(footprint, 0.0);
boost::range::fill(deviations, 0.0);
deviations.resize(knownFootprints.size(), 0.0);
auto data = resource->readAll();
@@ -173,21 +156,21 @@ static void detectEncoding()
for (size_t i = 0; i < deviations.size(); ++i)
{
for (size_t j = 0; j < footprint.size(); ++j)
deviations[i] += std::abs((footprint[j] - knownFootprints[i][j]));
deviations[i] += std::abs((footprint[j] - knownFootprints[i].footprint[j]));
}
size_t bestIndex = boost::range::min_element(deviations) - deviations.begin();
for (size_t i = 0; i < deviations.size(); ++i)
logGlobal->debug("Comparing to %s: %f", knownLanguages[i], deviations[i]);
logGlobal->debug("Comparing to %s: %f", knownFootprints[i].language, deviations[i]);
Settings s = settings.write["session"]["encoding"];
s->String() = knownEncodings[bestIndex];
Settings encoding = settings.write["session"]["encoding"];
encoding->String() = knownFootprints[bestIndex].encoding;
}
std::string Unicode::toUnicode(const std::string &text)
{
return toUnicode(text, getSelectedEncoding());
return toUnicode(text, CGeneralTextHandler::getInstalledEncoding());
}
std::string Unicode::toUnicode(const std::string &text, const std::string &encoding)
@@ -197,7 +180,7 @@ std::string Unicode::toUnicode(const std::string &text, const std::string &encod
std::string Unicode::fromUnicode(const std::string & text)
{
return fromUnicode(text, getSelectedEncoding());
return fromUnicode(text, CGeneralTextHandler::getInstalledEncoding());
}
std::string Unicode::fromUnicode(const std::string &text, const std::string &encoding)
@@ -389,16 +372,14 @@ void CGeneralTextHandler::readToVector(std::string const & sourceID, std::string
while (parser.endLine());
}
const std::string & CGeneralTextHandler::serialize(const std::string & identifier) const
{
assert(stringsIdentifiers.count(identifier));
return stringsIdentifiers.at(identifier);
}
const std::string & CGeneralTextHandler::deserialize(const TextIdentifier & identifier) const
{
if(stringsOverrides.count(identifier.get()))
return stringsOverrides.at(identifier.get());
if(stringsLocalizations.count(identifier.get()))
return stringsLocalizations.at(identifier.get());
logGlobal->error("Unable to find localization for string '%s'", identifier.get());
return identifier.get();
}
@@ -406,11 +387,20 @@ const std::string & CGeneralTextHandler::deserialize(const TextIdentifier & iden
void CGeneralTextHandler::registerString(const TextIdentifier & UID, const std::string & localized)
{
assert(UID.get().find("..") == std::string::npos);
stringsIdentifiers[localized] = UID.get();
stringsLocalizations[UID.get()] = localized;
}
void CGeneralTextHandler::registerStringOverride(const TextIdentifier & UID, const std::string & localized)
{
stringsOverrides[UID.get()] = localized;
}
void CGeneralTextHandler::loadTranslationOverrides(const JsonNode & config)
{
for ( auto const & node : config.Struct())
registerStringOverride(node.first, node.second.String());
}
CGeneralTextHandler::CGeneralTextHandler():
victoryConditions(*this, "core.vcdesc" ),
lossCondtions (*this, "core.lcdesc" ),
@@ -441,8 +431,7 @@ CGeneralTextHandler::CGeneralTextHandler():
znpc00 (*this, "vcmi.znpc00" ), // technically - wog
qeModCommands (*this, "vcmi.quickExchange" )
{
if (getSelectedEncoding().empty())
detectEncoding();
detectInstallParameters();
readToVector("core.vcdesc", "DATA/VCDESC.TXT" );
readToVector("core.lcdesc", "DATA/LCDESC.TXT" );
@@ -472,11 +461,6 @@ CGeneralTextHandler::CGeneralTextHandler():
if (CResourceHandler::get()->existsResource(ResourceID(QE_MOD_COMMANDS, EResType::TEXT)))
readToVector("vcmi.quickExchange", QE_MOD_COMMANDS);
auto vcmiTexts = JsonNode(ResourceID("config/translate.json", EResType::TEXT));
for ( auto const & node : vcmiTexts.Struct())
registerString(node.first, node.second.String());
{
CLegacyConfigParser parser("DATA/RANDTVRN.TXT");
parser.endLine();
@@ -638,18 +622,25 @@ int32_t CGeneralTextHandler::pluralText(const int32_t textIndex, const int32_t c
void CGeneralTextHandler::dumpAllTexts()
{
auto escapeString = [](std::string input)
{
boost::replace_all(input, "\\", "\\\\");
boost::replace_all(input, "\n", "\\n");
boost::replace_all(input, "\r", "\\r");
boost::replace_all(input, "\t", "\\t");
boost::replace_all(input, "\"", "\\\"");
return input;
};
logGlobal->info("BEGIN TEXT EXPORT");
for ( auto const & entry : stringsLocalizations)
{
auto cleanString = entry.second;
boost::replace_all(cleanString, "\\", "\\\\");
boost::replace_all(cleanString, "\n", "\\n");
boost::replace_all(cleanString, "\r", "\\r");
boost::replace_all(cleanString, "\t", "\\t");
boost::replace_all(cleanString, "\"", "\\\"");
if (stringsOverrides.count(entry.first) == 0)
logGlobal->info("\"%s\" : \"%s\",", entry.first, escapeString(entry.second));
for ( auto const & entry : stringsOverrides)
logGlobal->info("\"%s\" : \"%s\",", entry.first, escapeString(entry.second));
logGlobal->info("\"%s\" : \"%s\",", entry.first, cleanString);
}
logGlobal->info("END TEXT EXPORT");
}
@@ -662,6 +653,19 @@ size_t CGeneralTextHandler::getCampaignLength(size_t campaignID) const
return 0;
}
std::string CGeneralTextHandler::getInstalledLanguage()
{
return settings["general"]["language"].String();
}
std::string CGeneralTextHandler::getInstalledEncoding()
{
auto explicitSetting = settings["general"]["encoding"].String();
if (explicitSetting != "auto")
return explicitSetting;
return settings["session"]["encoding"].String();
}
std::vector<std::string> CGeneralTextHandler::findStringsWithPrefix(std::string const & prefix)
{
std::vector<std::string> result;
@@ -698,5 +702,4 @@ std::pair<std::string, std::string> LegacyHelpContainer::operator[](size_t index
};
}
VCMI_LIB_NAMESPACE_END

View File

@@ -149,17 +149,27 @@ class DLL_LINKAGE CGeneralTextHandler
/// map identifier -> localization
std::unordered_map<std::string, std::string> stringsLocalizations;
/// map localization -> identifier
std::unordered_map<std::string, std::string> stringsIdentifiers;
/// map identifier -> localization, high-priority strings from translation json
std::unordered_map<std::string, std::string> stringsOverrides;
void readToVector(const std::string & sourceID, const std::string & sourceName);
/// number of scenarios in specific campaign. TODO: move to a better location
std::vector<size_t> scenariosCountPerCampaign;
/// Attempts to detect encoding & language of H3 files
void detectInstallParameters() const;
public:
/// Loads translation from provided json
/// Any entries loaded by this will have priority over texts registered normally
void loadTranslationOverrides(JsonNode const & file);
/// add selected string to internal storage
void registerString(const TextIdentifier & UID, const std::string & localized);
/// add selected string to internal storage as high-priority strings
void registerStringOverride(const TextIdentifier & UID, const std::string & localized);
// returns true if identifier with such name was registered, even if not translated to current language
// not required right now, can be added if necessary
// bool identifierExists( const std::string identifier) const;
@@ -172,9 +182,6 @@ public:
return deserialize(id);
}
/// converts translated string into locale-independent text that can be sent to another client
const std::string & serialize(const std::string & identifier) const;
/// converts identifier into user-readable string
const std::string & deserialize(const TextIdentifier & identifier) const;
@@ -226,6 +233,12 @@ public:
CGeneralTextHandler();
CGeneralTextHandler(const CGeneralTextHandler&) = delete;
CGeneralTextHandler operator=(const CGeneralTextHandler&) = delete;
/// Returns name of language preferred by user
static std::string getInstalledLanguage();
/// Returns name of encoding of Heroes III text files
static std::string getInstalledEncoding();
};
VCMI_LIB_NAMESPACE_END

View File

@@ -24,6 +24,7 @@
#include "IHandlerBase.h"
#include "spells/CSpellHandler.h"
#include "CSkillHandler.h"
#include "CGeneralTextHandler.h"
#include "ScriptHandler.h"
#include "RoadHandler.h"
#include "RiverHandler.h"
@@ -455,7 +456,7 @@ CContentHandler::CContentHandler()
void CContentHandler::init()
{
handlers.insert(std::make_pair("heroClasses", ContentTypeHandler(&VLC->heroh->classes, "heroClass")));
handlers.insert(std::make_pair("heroClasses", ContentTypeHandler(&VLC->heroh->classes, "heroClass")));
handlers.insert(std::make_pair("artifacts", ContentTypeHandler(VLC->arth, "artifact")));
handlers.insert(std::make_pair("creatures", ContentTypeHandler(VLC->creh, "creature")));
handlers.insert(std::make_pair("factions", ContentTypeHandler(VLC->townh, "faction")));
@@ -687,7 +688,7 @@ void CModInfo::loadLocalData(const JsonNode & data)
validated = data["validated"].Bool();
checksum = strtol(data["checksum"].String().c_str(), nullptr, 16);
}
//check compatibility
bool wasEnabled = enabled;
enabled = enabled && (vcmiCompatibleMin.isNull() || Version::GameVersion().compatible(vcmiCompatibleMin));
@@ -704,10 +705,10 @@ void CModInfo::loadLocalData(const JsonNode & data)
CModHandler::CModHandler() : content(std::make_shared<CContentHandler>())
{
modules.COMMANDERS = false;
modules.STACK_ARTIFACT = false;
modules.STACK_EXP = false;
modules.MITHRIL = false;
modules.COMMANDERS = false;
modules.STACK_ARTIFACT = false;
modules.STACK_EXP = false;
modules.MITHRIL = false;
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i)
{
identifiers.registerObject(CModHandler::scopeBuiltin(), "resource", GameConstants::RESOURCE_NAMES[i], i);
@@ -841,7 +842,7 @@ std::vector <TModID> CModHandler::validateAndSortDependencies(std::vector <TModI
// Topological sort algorithm.
// TODO: Investigate possible ways to improve performance.
boost::range::sort(modsToResolve); // Sort mods per name
std::vector <TModID> sortedValidMods; // Vector keeps order of elements (LIFO)
std::vector <TModID> sortedValidMods; // Vector keeps order of elements (LIFO)
sortedValidMods.reserve(modsToResolve.size()); // push_back calls won't cause memory reallocation
std::set <TModID> resolvedModIDs; // Use a set for validation for performance reason, but set does not keep order of elements
@@ -876,7 +877,7 @@ std::vector <TModID> CModHandler::validateAndSortDependencies(std::vector <TModI
if(resolvedOnCurrentTreeLevel.size())
{
resolvedModIDs.insert(resolvedOnCurrentTreeLevel.begin(), resolvedOnCurrentTreeLevel.end());
continue;
continue;
}
// If there're no valid mods on the current mods tree level, no more mod can be resolved, should be end.
break;
@@ -1098,6 +1099,18 @@ void CModHandler::initializeConfig()
loadConfigFromFile("defaultMods.json");
}
void CModHandler::loadTranslation(TModID modName)
{
auto const & mod = allMods[modName];
std::string language = VLC->generaltexth->getInstalledLanguage();
for (auto const & config : mod.config["translations"].Vector())
VLC->generaltexth->loadTranslationOverrides(JsonNode(ResourceID(config.String(), EResType::TEXT)));
for (auto const & config : mod.config[language]["translations"].Vector())
VLC->generaltexth->loadTranslationOverrides(JsonNode(ResourceID(config.String(), EResType::TEXT)));
}
void CModHandler::load()
{
CStopWatch totalTime, timer;
@@ -1123,6 +1136,9 @@ void CModHandler::load()
for(const TModID & modName : activeMods)
content->load(allMods[modName]);
for(const TModID & modName : activeMods)
loadTranslation(modName);
#if SCRIPTING_ENABLED
VLC->scriptHandler->performRegistration(VLC);//todo: this should be done before any other handlers load
#endif

View File

@@ -282,6 +282,7 @@ class DLL_LINKAGE CModHandler
std::vector<std::string> getModList(std::string path);
void loadMods(std::string path, std::string parent, const JsonNode & modSettings, bool enableMods);
void loadOneMod(std::string modName, std::string parent, const JsonNode & modSettings, bool enableMods);
void loadTranslation(TModID modName);
public:
/// returns true if scope is reserved for internal use and can not be used by mods

View File

@@ -198,14 +198,14 @@ void LibClasses::init(bool onlyEssential)
modh->initializeConfig();
createHandler(generaltexth, "General text", pomtime);
createHandler(bth, "Bonus type", pomtime);
createHandler(roadTypeHandler, "Road", pomtime);
createHandler(riverTypeHandler, "River", pomtime);
createHandler(terrainTypeHandler, "Terrain", pomtime);
createHandler(generaltexth, "General text", pomtime);
createHandler(heroh, "Hero", pomtime);
createHandler(arth, "Artifact", pomtime);

View File

@@ -14,8 +14,8 @@
VCMI_LIB_NAMESPACE_BEGIN
const ui32 SERIALIZATION_VERSION = 812;
const ui32 MINIMAL_SERIALIZATION_VERSION = 812;
const ui32 SERIALIZATION_VERSION = 813;
const ui32 MINIMAL_SERIALIZATION_VERSION = 813;
const std::string SAVEGAME_MAGIC = "VCMISVG";
class CHero;