Merge pull request #2 from Zukero/master

merge from zukero
This commit is contained in:
NutAndor
2018-09-11 23:13:14 +02:00
committed by GitHub
49 changed files with 24989 additions and 44367 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1629
AndorsTrail/assets/translation/cs.po Executable file → Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,11 @@
"requireID":"lodar2",
"value":50,
"negate":true
},
{
"requireType":"questProgress",
"requireID":"shortcut_lodar",
"value":10
}
]
},
@@ -25,6 +30,16 @@
"requireID":"shortcut_lodar",
"value":22,
"negate":true
},
{
"requireType":"questProgress",
"requireID":"shortcut_lodar",
"value":20
},
{
"requireType":"questProgress",
"requireID":"lodar2",
"value":50
}
]
},

File diff suppressed because it is too large Load Diff

View File

@@ -1,288 +1,288 @@
[
{
"id":"teksin_10",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin11",
"requires":[
{
"requireType":"questProgress",
"requireID":"nondisplay_2",
"value":140
}
]
},
{
"text":"N",
"nextPhraseID":"teksin12",
"requires":[
{
"requireType":"questProgress",
"requireID":"nondisplay_2",
"value":140,
"negate":true
}
]
}
]
},
{
"id":"teksin11",
"message":"Hello again.",
"replies":[
{
"text":"How do I get to Remgard?",
"nextPhraseID":"teksin70",
"requires":[
{
"requireType":"questProgress",
"requireID":"nondisplay_2",
"value":160
}
]
},
{
"text":"What can you tell me about Remgard?",
"nextPhraseID":"teksin60",
"requires":[
{
"requireType":"questProgress",
"requireID":"nondisplay_2",
"value":160
}
]
},
{
"text":"Do you have anything to trade?",
"nextPhraseID":"teksin80"
},
{
"text":"I'm looking for my brother, Andor. He looks a bit like me.",
"nextPhraseID":"teksin20"
}
]
},
{
"id":"teksin12",
"message":"Hello. My name is Teksin. I'm a trader. Who are you?",
"replies":[
{
"text":"I am $playername. I am looking for my brother, Andor. He looks a bit like me.",
"nextPhraseID":"teksin20"
}
],
"rewards":[
{
"rewardType":"questProgress",
"rewardID":"nondisplay_2",
"value":140
}
]
},
{
"id":"teksin20",
"message":"Sorry. I haven't seen anyone that looks like you. ",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin30"
}
]
},
{
"id":"teksin30",
"message":"I have been out in the wild for while, and have seen nobody since I left the main road weeks ago.",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin40"
}
]
},
{
"id":"teksin40",
"message":"I decided that I should find a better route to Remgard. The road through the mountains to the east is plagued by terrible monsters. My quest for a better route was a mistake though.",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin50"
}
]
},
{
"id":"teksin50",
"message":"This is as close as I can get coming this way. I am an experienced traveler, and I know that Remgard is close. It's north across this lake, but there is no way to cross, or to go further east around the lake.",
"replies":[
{
"text":"It sounds like you are not quite the experienced traveler you claim to be.",
"nextPhraseID":"X"
},
{
"text":"I guess it was worth a try. What can you tell me about Remgard?",
"nextPhraseID":"teksin60"
},
{
"text":"How do I get to Remgard?",
"nextPhraseID":"teksin70"
},
{
"text":"Do you have anything to trade?",
"nextPhraseID":"teksin80"
}
],
"rewards":[
{
"rewardType":"questProgress",
"rewardID":"nondisplay_2",
"value":160
}
]
},
{
"id":"teksin60",
"message":"Remgard is a town that is well protected by the lake that we are next to. It is peaceful, and far from any enemies, which makes it somewhat surprising that they make excellent armor there. The high quality of the goods available in Remgard is the reason it is on my trading route, even though it is so hard to get to. ",
"replies":[
{
"text":"How do I get to Remgard?",
"nextPhraseID":"teksin70"
},
{
"text":"Thanks for the information, but I have to leave now.",
"nextPhraseID":"X"
}
]
},
{
"id":"teksin70",
"message":"You have to go back down to the river, then south until you find some caves. Go through the caves, up through the mountains, and then around the lake we are now standing next to. It's a long way, and as I said, there are some very bad monsters. A kid like you should probably not attempt it.",
"replies":[
{
"text":"I can handle it. I'm on my way.",
"nextPhraseID":"X"
},
{
"text":"It sounds dangerous. I think I'll go somewhere else.",
"nextPhraseID":"X"
},
{
"text":"Thanks for the information. Do you have anything to trade?",
"nextPhraseID":"teksin80"
}
]
},
{
"id":"teksin80",
"message":"Yes. I think you will see that I sell quality items from many places.\nUnder the circumstances I can only sell you limited provisions though.",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin85"
}
]
},
{
"id":"teksin90",
"message":"I do also have one special item. It is a potion that increases your attack speed.\nIt is very rare, and therefore expensive, but I am willing to part with it if the price is right.",
"replies":[
{
"text":"No thanks. Show me what else you have.",
"nextPhraseID":"S"
},
{
"text":"How expensive is \"expensive\"?",
"nextPhraseID":"teksin100"
}
]
},
{
"id":"teksin85",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin90",
"requires":[
{
"requireType":"questProgress",
"requireID":"nondisplay_2",
"value":150,
"negate":true
}
]
},
{
"text":"OK. Show me what you have.",
"nextPhraseID":"S"
}
]
},
{
"id":"teksin100",
"message":"For you, I will offer the special price of 4999 gold.",
"replies":[
{
"text":"I don't have that much gold. Please show me what else you have.",
"nextPhraseID":"S",
"requires":[
{
"requireType":"inventoryKeep",
"requireID":"gold",
"value":4999
}
]
},
{
"text":"That's too expensive. Please show me what else you have.",
"nextPhraseID":"S",
"requires":[
{
"requireType":"inventoryKeep",
"requireID":"gold",
"value":4999
}
]
},
{
"text":"OK. I'll take it.",
"nextPhraseID":"teksin110",
"requires":[
{
"requireType":"inventoryRemove",
"requireID":"gold",
"value":4999
}
]
},
{
"text":"I think I'll just be on my way.",
"nextPhraseID":"X"
}
]
},
{
"id":"teksin110",
"message":"Use it wisely. Such a potion is very hard to obtain. \nIt is unlikely I will have any more to sell in the future.",
"replies":[
{
"text":"Thanks for the advice. Please show me what else you have to trade.",
"nextPhraseID":"S"
},
{
"text":"Thanks for the advice. I need to go now.",
"nextPhraseID":"X"
}
],
"rewards":[
{
"rewardType":"questProgress",
"rewardID":"nondisplay_2",
"value":150
},
{
"rewardType":"giveItem",
"rewardID":"pot_light_attack",
"value":1
}
]
}
[
{
"id":"teksin_10",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin11",
"requires":[
{
"requireType":"questProgress",
"requireID":"nondisplay_2",
"value":140
}
]
},
{
"text":"N",
"nextPhraseID":"teksin12",
"requires":[
{
"requireType":"questProgress",
"requireID":"nondisplay_2",
"value":140,
"negate":true
}
]
}
]
},
{
"id":"teksin11",
"message":"Hello again.",
"replies":[
{
"text":"How do I get to Remgard?",
"nextPhraseID":"teksin70",
"requires":[
{
"requireType":"questProgress",
"requireID":"nondisplay_2",
"value":160
}
]
},
{
"text":"What can you tell me about Remgard?",
"nextPhraseID":"teksin60",
"requires":[
{
"requireType":"questProgress",
"requireID":"nondisplay_2",
"value":160
}
]
},
{
"text":"Do you have anything to trade?",
"nextPhraseID":"teksin80"
},
{
"text":"I'm looking for my brother, Andor. He looks a bit like me.",
"nextPhraseID":"teksin20"
}
]
},
{
"id":"teksin12",
"message":"Hello. My name is Teksin. I'm a trader. Who are you?",
"replies":[
{
"text":"I am $playername. I am looking for my brother, Andor. He looks a bit like me.",
"nextPhraseID":"teksin20"
}
],
"rewards":[
{
"rewardType":"questProgress",
"rewardID":"nondisplay_2",
"value":140
}
]
},
{
"id":"teksin20",
"message":"Sorry. I haven't seen anyone that looks like you. ",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin30"
}
]
},
{
"id":"teksin30",
"message":"I have been out in the wild for a while, and have seen nobody since I left the main road weeks ago.",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin40"
}
]
},
{
"id":"teksin40",
"message":"I decided that I should find a better route to Remgard. The road through the mountains to the east is plagued by terrible monsters. My quest for a better route was a mistake though.",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin50"
}
]
},
{
"id":"teksin50",
"message":"This is as close as I can get coming this way. I am an experienced traveler, and I know that Remgard is close. It's north across this lake, but there is no way to cross, or to go further east around the lake.",
"replies":[
{
"text":"It sounds like you are not quite the experienced traveler you claim to be.",
"nextPhraseID":"X"
},
{
"text":"I guess it was worth a try. What can you tell me about Remgard?",
"nextPhraseID":"teksin60"
},
{
"text":"How do I get to Remgard?",
"nextPhraseID":"teksin70"
},
{
"text":"Do you have anything to trade?",
"nextPhraseID":"teksin80"
}
],
"rewards":[
{
"rewardType":"questProgress",
"rewardID":"nondisplay_2",
"value":160
}
]
},
{
"id":"teksin60",
"message":"Remgard is a town that is well protected by the lake that we are next to. It is peaceful, and far from any enemies, which makes it somewhat surprising that they make excellent armor there. The high quality of the goods available in Remgard is the reason it is on my trading route, even though it is so hard to get to. ",
"replies":[
{
"text":"How do I get to Remgard?",
"nextPhraseID":"teksin70"
},
{
"text":"Thanks for the information, but I have to leave now.",
"nextPhraseID":"X"
}
]
},
{
"id":"teksin70",
"message":"You have to go back down to the river, then south until you find some caves. Go through the caves, up through the mountains, and then around the lake we are now standing next to. It's a long way, and as I said, there are some very bad monsters. A kid like you should probably not attempt it.",
"replies":[
{
"text":"I can handle it. I'm on my way.",
"nextPhraseID":"X"
},
{
"text":"It sounds dangerous. I think I'll go somewhere else.",
"nextPhraseID":"X"
},
{
"text":"Thanks for the information. Do you have anything to trade?",
"nextPhraseID":"teksin80"
}
]
},
{
"id":"teksin80",
"message":"Yes. I think you will see that I sell quality items from many places.\nUnder the circumstances I can only sell you limited provisions though.",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin85"
}
]
},
{
"id":"teksin90",
"message":"I do also have one special item. It is a potion that increases your attack speed.\nIt is very rare, and therefore expensive, but I am willing to part with it if the price is right.",
"replies":[
{
"text":"No thanks. Show me what else you have.",
"nextPhraseID":"S"
},
{
"text":"How expensive is \"expensive\"?",
"nextPhraseID":"teksin100"
}
]
},
{
"id":"teksin85",
"replies":[
{
"text":"N",
"nextPhraseID":"teksin90",
"requires":[
{
"requireType":"questProgress",
"requireID":"nondisplay_2",
"value":150,
"negate":true
}
]
},
{
"text":"OK. Show me what you have.",
"nextPhraseID":"S"
}
]
},
{
"id":"teksin100",
"message":"For you, I will offer the special price of 4999 gold.",
"replies":[
{
"text":"I don't have that much gold. Please show me what else you have.",
"nextPhraseID":"S",
"requires":[
{
"requireType":"inventoryKeep",
"requireID":"gold",
"value":4999
}
]
},
{
"text":"That's too expensive. Please show me what else you have.",
"nextPhraseID":"S",
"requires":[
{
"requireType":"inventoryKeep",
"requireID":"gold",
"value":4999
}
]
},
{
"text":"OK. I'll take it.",
"nextPhraseID":"teksin110",
"requires":[
{
"requireType":"inventoryRemove",
"requireID":"gold",
"value":4999
}
]
},
{
"text":"I think I'll just be on my way.",
"nextPhraseID":"X"
}
]
},
{
"id":"teksin110",
"message":"Use it wisely. Such a potion is very hard to obtain. \nIt is unlikely I will have any more to sell in the future.",
"replies":[
{
"text":"Thanks for the advice. Please show me what else you have to trade.",
"nextPhraseID":"S"
},
{
"text":"Thanks for the advice. I need to go now.",
"nextPhraseID":"X"
}
],
"rewards":[
{
"rewardType":"questProgress",
"rewardID":"nondisplay_2",
"value":150
},
{
"rewardType":"giveItem",
"rewardID":"pot_light_attack",
"value":1
}
]
}
]

View File

@@ -56,7 +56,7 @@
},
{
"id":"guynmart_guard_guide",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"unique":1,
"monsterClass":"humanoid",
@@ -64,7 +64,7 @@
},
{
"id":"guynmart_gguard",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"unique":1,
"monsterClass":"humanoid",
@@ -73,7 +73,7 @@
},
{
"id":"guynmart_player",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"unique":1,
"monsterClass":"humanoid",
@@ -81,7 +81,7 @@
},
{
"id":"guynmart_mguard",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"unique":1,
"monsterClass":"humanoid",
@@ -90,7 +90,7 @@
},
{
"id":"guynmart_wguard",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"unique":1,
"monsterClass":"humanoid",
@@ -99,7 +99,7 @@
},
{
"id":"guynmart_wguard1",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"maxHP":120,
"maxAP":10,
@@ -118,7 +118,7 @@
},
{
"id":"guynmart_wguard9a",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"maxHP":120,
"maxAP":10,
@@ -137,7 +137,7 @@
},
{
"id":"guynmart_guard_store",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"unique":1,
"monsterClass":"humanoid",
@@ -146,7 +146,7 @@
},
{
"id":"guynmart_guard_storea",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"maxHP":120,
"maxAP":10,
@@ -165,7 +165,7 @@
},
{
"id":"guynmart_guard_storea2",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"maxHP":120,
"maxAP":10,
@@ -184,7 +184,7 @@
},
{
"id":"guynmart_guard_arms",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"unique":1,
"monsterClass":"humanoid",
@@ -193,7 +193,7 @@
},
{
"id":"guynmart_tguard",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"unique":1,
"monsterClass":"humanoid",
@@ -202,7 +202,7 @@
},
{
"id":"guynmart_tguard2",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"unique":1,
"monsterClass":"humanoid",
@@ -260,7 +260,7 @@
},
{
"id":"guynmart_gateguard",
"name":"Guynmart Guard",
"name":"Guynmart guard",
"iconID":"monsters_ld1:0",
"maxHP":120,
"maxAP":10,
@@ -798,14 +798,14 @@
},
{
"id":"guynmart_dog1",
"name":"Shephards Dog",
"name":"Shepherd's dog",
"iconID":"monsters_dogs:4",
"monsterClass":"animal",
"phraseID":"guynmart_dog10_10"
},
{
"id":"guynmart_dog2",
"name":"Shephards Dog",
"name":"Shepherd's dog",
"iconID":"monsters_dogs:4",
"monsterClass":"animal",
"phraseID":"guynmart_dog10_10"

View File

@@ -38,13 +38,13 @@
},
{
"id":"stoutford_gateguard",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik2:43",
"phraseID":"stoutford_gateguard_0"
},
{
"id":"stoutford_guard1",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik2:44",
"phraseID":"stoutford_guard1_0"
},
@@ -126,7 +126,7 @@
},
{
"id":"stoutford_thief",
"name":"Quiet Thief",
"name":"Quiet thief",
"iconID":"monsters_rogue1:0",
"monsterClass":"humanoid",
"spawnGroup":"stoutford_thief",

View File

@@ -1,7 +1,7 @@
[
{
"id":"stoutford_farmer2",
"name":"Busy Farmer",
"name":"Busy farmer",
"iconID":"monsters_man1:0",
"monsterClass":"humanoid",
"spawnGroup":"stoutford_farmer2",
@@ -9,7 +9,7 @@
},
{
"id":"stoutford_farmer3",
"name":"Old Farmer",
"name":"Old farmer",
"iconID":"monsters_mage2:0",
"monsterClass":"humanoid",
"spawnGroup":"stoutford_farmer3",
@@ -188,7 +188,7 @@
},
{
"id":"lakecave2_key",
"name":"Glade Key",
"name":"Glade key",
"iconID":"items_japozero:387",
"unique":1,
"spawnGroup":"lakecave2_key",
@@ -196,7 +196,7 @@
},
{
"id":"lakecave2_key2",
"name":"Glade Key",
"name":"Glade key",
"iconID":"items_japozero:387",
"unique":1,
"spawnGroup":"lakecave2_key2",
@@ -602,40 +602,40 @@
},
{
"id":"stoutford_guard1_b",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik2:44",
"spawnGroup":"stoutford_guard1",
"phraseID":"stoutford_guard1_0b"
},
{
"id":"stoutford_guard1_c",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik2:44",
"spawnGroup":"stoutford_guard1",
"phraseID":"stoutford_guard1_0c"
},
{
"id":"stoutford_guard1a",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik2:44",
"spawnGroup":"stoutford_guard1a",
"phraseID":"stoutford_guard1_0"
},
{
"id":"stoutford_guard1b",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik2:44",
"phraseID":"stoutford_guard1_0"
},
{
"id":"stoutford_guard1c",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik2:44",
"phraseID":"stoutford_guard1_0"
},
{
"id":"stoutford_guard2",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik2:45",
"monsterClass":"humanoid",
"spawnGroup":"stoutford_guard1",
@@ -643,7 +643,7 @@
},
{
"id":"stoutford_guard3",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik7:71",
"monsterClass":"humanoid",
"spawnGroup":"stoutford_guard1",
@@ -651,21 +651,21 @@
},
{
"id":"stoutford_guard4",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik7:71",
"monsterClass":"humanoid",
"phraseID":"stoutford_guard4"
},
{
"id":"stoutford_guard_wild21a",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik7:71",
"monsterClass":"humanoid",
"phraseID":"key_wild21a"
},
{
"id":"stoutford_guard_camp1",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik7:71",
"maxHP":40,
"moveCost":5,
@@ -685,7 +685,7 @@
},
{
"id":"stoutford_guard_camp2",
"name":"Stoutford Guard",
"name":"Stoutford guard",
"iconID":"monsters_tometik7:71",
"maxHP":40,
"moveCost":5,

View File

@@ -537,4 +537,79 @@
<string name="preferences_ui_use_localized_resources">Выкарыстоўваць пераклад інтэрфейсу і зместу, калі ён даступен. (Патрабуецца перазапуск)</string>
<string name="change_locale_requires_restart">Змяненне мовы патрабуе перазапуск. Andor\'s Trail закрытая.</string>
<string name="dialog_recenter">У зыходны</string>
<string name="dialog_more">Больш</string>
<string name="dialog_monsterencounter_conditions">Умовы</string>
<string name="heroinfo_skill_categories">Катэгорыя</string>
<string name="heroinfo_skill_sort">Сартаваць</string>
<string name="heroinfo_inventory_categories">Катэгорыя</string>
<string name="heroinfo_inventory_sort">Сартаваць па</string>
<string name="heroinfo_healthpoints">Пункты здароўя (ПЗ):</string>
<string name="heroinfo_experiencepoints">Пункты вопыту (ПВ):</string>
<string name="combat_taunt_monster">Вы ўкпілі %1$s!</string>
<string name="combat_condition_player_apply">Вы пацярпелі ад %1$s.</string>
<string name="combat_condition_player_clear">Вы ачышчаны ад %1$s.</string>
<string name="combat_condition_player_immune">У вас імунітэт ад %1$s.</string>
<string name="combat_condition_monster_apply">%1$s залежыць ад %2$s.</string>
<string name="combat_condition_monster_clear">%1$s чысціцца ад %2$s.</string>
<string name="combat_condition_monster_immune">%1$s цяпер мае імунітэт ад %2$s.</string>
<string name="startscreen_newgame_start">Пачаць гульню</string>
<string name="startscreen_selectherosprite">Абярыце свайго героя</string>
<string name="shop_item_sort">Сартаваць</string>
<string name="actorcondition_info_immunity">Імунітэт ад %1$s</string>
<string name="iteminfo_effect_works_on_attacker">На нападніку</string>
<string name="iteminfo_effect_works_when_hit_by_attacker">Пры пападанні нападніка</string>
<string name="iteminfo_effect_works_when_killed_by_attacker">Пры забойстве нападніка</string>
<string name="inventory_selectitem">Абярыце прадмет для прызначэння</string>
<string name="combat_log_noentries">Пакуль няма запісаў.</string>
<string name="inventory_category_all">Усе</string>
<string name="inventory_category_favorites">Абраныя</string>
<string name="inventory_category_weapons">Зброя</string>
<string name="inventory_category_armor">Браня</string>
<string name="inventory_category_usable">Спажываемыя</string>
<string name="inventory_category_quest">Квэставыя прадметы</string>
<string name="inventory_category_other">Іншыя</string>
<string name="inventory_sort_custom">Без сартавання</string>
<string name="inventory_sort_name">назве</string>
<string name="inventory_sort_price">кошту</string>
<string name="inventory_sort_quantity">колькасці</string>
<string name="inventory_sort_rarity">рэдкасці</string>
<string name="inventory_sort_type">тыпу</string>
<string name="shoplist_sort_custom">Без сартавання</string>
<string name="shoplist_sort_name">назве</string>
<string name="shoplist_sort_price">кошту</string>
<string name="shoplist_sort_quantity">колькасці</string>
<string name="shoplist_sort_rarity">рэдкасці</string>
<string name="shoplist_sort_type">тыпу</string>
<string name="skill_category_all">Усе</string>
<string name="skill_category_offense">Напад</string>
<string name="skill_category_defense">Абарона</string>
<string name="skill_category_criticals">Крытычныя ўдары</string>
<string name="skill_category_immunity">Імунітэт</string>
<string name="skill_category_utility">Дапаможныя</string>
<string name="skill_category_speciality">Спецыяльнасці</string>
<string name="skill_category_proficiency">Уменні</string>
<string name="skill_sort_unsorted">Без сартавання</string>
<string name="skill_sort_name">назве</string>
<string name="skill_sort_points">пунктах</string>
<string name="skill_sort_unlocked">адкрытыя</string>
<string name="preferences_display_theme_title">Тэма</string>
<string name="preferences_display_theme">Абраць тэму інтэрфейсу. (патрабуецца перазапуск)</string>
<string name="preferences_display_theme_blue">Кобальт</string>
<string name="preferences_display_theme_green">Малахіт</string>
<string name="preferences_display_theme_charcoal">Абсідыян</string>
<string name="change_theme_requires_restart">Змяненне тэмы інтэрфейсу патрабуе перазапуск. «Andor\'s Trail» закрыты.</string>
</resources>

View File

@@ -1,4 +1,625 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="localize_resources_from_mo_filename">cs.mo</string>
</resources>
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="localize_resources_from_mo_filename">cs.mo</string>
<string name="app_name">Andor\'s Trail</string>
<string name="app_description">RPG pátrací hra s prvky fantasy</string>
<string name="exit_to_menu">Hlavní nabídka</string>
<string name="menu_settings">Nastavení</string>
<string name="menu_save">Uložit</string>
<string name="menu_save_gamesaved">Hra uložena na pozici %1$d</string>
<string name="menu_save_failed">Chyba ukládání! Je správně vložena a připojena SD karta?</string>
<string name="loadsave_title_save">Uložit hru</string>
<string name="loadsave_title_load">Načíst hru</string>
<string name="loadsave_selectslot">Výběr pozice</string>
<string name="savegame_currenthero_displayinfo">Úroveň: %1$d, zkušeností: %2$d, zlaťáků: %3$d</string>
<string name="dialog_loading_message">Načítání zdrojů…</string>
<string name="dialog_loading_failed_title">Chyba při načítání hry</string>
<string name="dialog_loading_failed_message">Andor\'s Trail nebyl schopen načíst uloženou hru.
\n
\n:(
\n
\nSoubor může být poškozený nebo nekompletní.</string>
<string name="dialog_loading_failed_incorrectversion">Andor\'s Trail nebyl schopen načíst uloženou hru. Soubor byl vytvořen novější verzí hry než která je nyní spuštěna.</string>
<string name="dialog_recenter">Centrovat</string>
<string name="dialog_close">Zavřít</string>
<string name="dialog_more">Více</string>
<string name="dialog_monsterencounter_title">Souboj</string>
<string name="dialog_monsterencounter_message">Chceš zaútočit?
\nObtížnost: %1$s</string>
<string name="dialog_monsterencounter_info">Info</string>
<string name="dialog_monsterencounter_conditions">Stav</string>
<string name="status_hp">PŽ:</string>
<string name="status_ap">AB:</string>
<string name="status_exp">Zk.:</string>
<string name="heroinfo_char">Přehled</string>
<string name="heroinfo_inv">Inventář</string>
<string name="heroinfo_skill">Dovednosti</string>
<string name="heroinfo_skill_categories">Kategorie</string>
<string name="heroinfo_skill_sort">Srovnat</string>
<string name="heroinfo_levelup">Nová úroveň</string>
<string name="heroinfo_level">Úroveň</string>
<string name="heroinfo_totalexperience">Zkušeností celkem</string>
<string name="heroinfo_wornequipment">Výstroj</string>
<string name="heroinfo_inventory">Inventář</string>
<string name="heroinfo_inventory_categories">Kategorie</string>
<string name="heroinfo_inventory_sort">Srovnat podle</string>
<string name="heroinfo_gold">Zlaťáky: %1$d</string>
<string name="heroinfo_healthpoints">Počet životů (PŽ):</string>
<string name="heroinfo_experiencepoints">Zkušenosti (Zk.):</string>
<string name="heroinfo_actionpoints">Akční body (AB):</string>
<string name="heroinfo_quests">Mise</string>
<string name="combat_attack">Útok (%1$d AB)</string>
<string name="combat_move">Pohyb (%1$d AB)</string>
<string name="combat_use">Použít</string>
<string name="combat_endturn">Kolec kola</string>
<string name="combat_flee">Utéct</string>
<string name="combat_begin_flee">Nyní můžeš utéci z boje kliknutím ve směru, kterým chceš utíkat.</string>
<string name="combat_flee_failed">Útěk se nezdařil!</string>
<string name="combat_status_ap">AB: %1$d</string>
<string name="combat_monsterhealth">PŽ:</string>
<string name="combat_monsteraction">%1$s útočí.</string>
<string name="combat_result_monstermiss">%1$s se netrefuje!</string>
<string name="combat_result_monsterhit">%1$s tě zraňuje za %2$d BŽ!</string>
<string name="combat_result_monsterhitcritical">%1$s zasahuje kritickým útokem za %2$d BŽ!</string>
<string name="combat_result_heromiss">Tvůj útok je neúspěšný.</string>
<string name="combat_result_herohit">Trefuješ: %1$s ztrácí %2$d BŽ!</string>
<string name="combat_result_herohitcritical">Povedl se ti kritický zásah: %1$s ztrácí %2$d BŽ!</string>
<string name="combat_result_herokillsmonster">%1$s umírá!</string>
<string name="combat_not_enough_ap">V tomto kole už nemáš dostatečný počet AB.</string>
<string name="combat_hero_dies">Upadáš do bezvědomí, ale naštěstí se probouzíš - sice s pocitem omámenosti a únavy, ale s plným počtem životů. Ztrácíš %1$d zkušeností.</string>
<string name="combat_miss_animation_message">VEDLE</string>
<string name="combat_taunt_monster">Vysmíváš se nepříteli: %1$s!</string>
<string name="combat_condition_player_apply">Působí na tebe: %1$s.</string>
<string name="combat_condition_player_clear">Zbavuješ se: %1$s.</string>
<string name="combat_condition_player_immune">Jsi nyní imunní vůči: %1$s.</string>
<string name="combat_condition_monster_apply">%1$s působí na: %2$s.</string>
<string name="combat_condition_monster_clear">%1$s se zbavuje: %2$s.</string>
<string name="combat_condition_monster_immune">%1$s je nyní imunní vůči: %2$s.</string>
<string name="inventory_info">Info</string>
<string name="inventory_equip">Vzít na sebe</string>
<string name="inventory_unequip">Sundat</string>
<string name="inventory_use">Použít</string>
<string name="inventory_drop">Odložit</string>
<string name="inventory_item_used">Používáš: %1$s.</string>
<string name="inventory_item_dropped">Odkládáš: %1$s.</string>
<string name="inventory_item_equipped">Bereš si: %1$s.</string>
<string name="dialog_loot_pickall">Vzít vše</string>
<string name="dialog_loot_foundgold">Našel jsi %1$d ks zlaťáků.</string>
<string name="dialog_loot_pickedupitem">Sbíráš jeden předmět.</string>
<string name="dialog_loot_pickedupitems">Sbíráš %1$d ks předmětů.</string>
<string name="dialog_groundloot_title">Nález</string>
<string name="dialog_groundloot_message">Našel jsi nějaké věci.</string>
<string name="dialog_monsterloot_title">Vítěztví</string>
<string name="dialog_monsterloot_message">Přežíváš souboj.</string>
<string name="dialog_monsterloot_gainedexp">Získáváš zkušenosti: %1$d.</string>
<string name="monster_difficulty_veryeasy">Nejlehčí</string>
<string name="monster_difficulty_easy">Lehčí</string>
<string name="monster_difficulty_normal">Normální</string>
<string name="monster_difficulty_hard">Težší</string>
<string name="monster_difficulty_veryhard">Nejtežší</string>
<string name="monster_difficulty_impossible">Absurdní</string>
<string name="actorinfo_class">Třída:</string>
<string name="actorinfo_difficulty">Obtížnost:</string>
<string name="actorinfo_health">Počet životů:</string>
<string name="actorinfo_attack">Útok:</string>
<string name="actorinfo_defense">Obrana:</string>
<string name="actorinfo_movecost">Cena pohybu (AB):</string>
<string name="actorinfo_basetraits">Základní bojové statistiky (bez výbavy a dovedností)</string>
<string name="actorinfo_currenttraits">Bojové statistiky (aktuální)</string>
<string name="traitsinfo_attack_cost">Cena útoku (AB):</string>
<string name="traitsinfo_attack_chance">Šance na zásah:</string>
<string name="traitsinfo_attack_damage">Zranění způsobená útokem:</string>
<string name="traitsinfo_criticalhit_skill">Úroveň kritického zásahu:</string>
<string name="traitsinfo_criticalhit_multiplier">Násobitel kritického zásahu:</string>
<string name="traitsinfo_defense_chance">Šance odvrácení útoku:</string>
<string name="traitsinfo_defense_damageresist">Redukce zranění:</string>
<string name="iteminfo_category">Kategorie:</string>
<string name="iteminfo_action_use">Použít</string>
<string name="iteminfo_action_equip">Vzít na sebe</string>
<string name="iteminfo_action_unequip">Sundat</string>
<string name="iteminfo_action_use_ap">Použít (%1$d AP)</string>
<string name="iteminfo_action_equip_ap">Vzít na sebe (%1$d AB)</string>
<string name="iteminfo_action_unequip_ap">Sundat (%1$d AB)</string>
<string name="startscreen_continue">Pokračovat ve hře</string>
<string name="startscreen_newgame">Nová hra</string>
<string name="startscreen_newgame_start">Začít hru</string>
<string name="startscreen_newgame_confirm">Aktuální hra bude přepsána. Skutečně chceš začít hrát novou hru?</string>
<string name="startscreen_about">O hře/Nápověda</string>
<string name="startscreen_selectherosprite">Vyber si hrdinu</string>
<string name="startscreen_enterheroname">Pojmenuj svého hrdinu</string>
<string name="startscreen_load">Načíst</string>
<string name="conversation_rewardexp">[Získáváš zkušenosti: %1$d]</string>
<string name="conversation_rewardgold">[Získáváš zlaťáky: %1$d]</string>
<string name="conversation_lostgold">[Ztrácíš zlaťáky: %1$d]</string>
<string name="conversation_rewarditem">[Získáváš předmět]</string>
<string name="conversation_rewarditems">[Získáváš předměty: %1$d ks]</string>
<string name="conversation_next">Dál</string>
<string name="conversation_leave">Konec</string>
<string name="shop_buy">Nákup</string>
<string name="shop_sell">Prodej</string>
<string name="shop_infoitem">Info</string>
<string name="shop_buyitem">Nákup (%1$d ks zlatých)</string>
<string name="shop_sellitem">Prodej (%1$d ks zlatých)</string>
<string name="shop_yourgold">Tvé zlaťáky: %1$d</string>
<string name="shop_item_bought">Kupuješ: %1$s.</string>
<string name="shop_item_sold">Prodáváš: %1$s.</string>
<string name="shop_item_sort">Srovnat</string>
<string name="levelup_title">Nová úroveň</string>
<string name="levelup_description">Vítej na úrovni %1$d!</string>
<string name="levelup_buttontext">Nová úroveň</string>
<string name="levelup_add_health">Zvýšit zdraví (+%1$d PŽ)</string>
<string name="levelup_add_health_description">Zvýší tvůj celkový počet životů o%1$d.</string>
<string name="levelup_add_attackchance">Zvýšit šanci na zásah (+%1$d)</string>
<string name="levelup_add_attackchance_description">Zvýší tvou základní šanci na zásah o %1$d.</string>
<string name="levelup_add_attackdamage">Zvýšit zranění způsobené útokem (+%1$d)</string>
<string name="levelup_add_attackdamage_description">Zvýší základní zranění tvého útoku o %1$d.</string>
<string name="dialog_rest_title">Spánek</string>
<string name="dialog_rest_confirm_message">Chceš si zde odpočinout?</string>
<string name="dialog_rest_message">Po osvěžujícím spánku se vzbouzíš plně zdráv.</string>
<string name="about_button1">Nápověda</string>
<string name="about_button2">Tvůrci</string>
<string name="about_button3">Licence</string>
<string name="about_contents1">Vítej ve hře Andor\'s Trail. Jedná se o \'Open Source\' RPG hru s prvky rogue-like a fantasy pro Android&lt;br /&gt;
\n &lt;br /&gt;
\n &lt;a href=http://andorstrail.com/&gt;Fórum na andorstrail.com, kde lze klást otázky a vést diskuze o hře.&lt;/a&gt;&lt;br /&gt;
\n &lt;br /&gt;
\n &lt;a href=http://andorstrail.com/wiki&gt;Wiki o hře Andor\'s Trail, kde lze najít podrobnější informace o světě hry Andor\'s Trail (mytologie).&lt;/a&gt;&lt;br /&gt;
\n &lt;br /&gt;
\n &lt;a href=http://github.com/Zukero/andors-trail/&gt;Projekt na github.com pro vývojáře.&lt;/a&gt;&lt;br /&gt;
\n &lt;br /&gt;
\nPokud máš otázky ke hře, navštiv prosím herní fórum.&lt;br /&gt;</string>
<string name="levelup_add_blockchance">Zvýšit šanci odvrácení útoku (+%1$d)</string>
<string name="levelup_add_blockchance_description">Zvýší šanci odvrácení útoku o %1$d.</string>
<string name="about_contents3">Tento program je svobodný. Můžeš jej za splnění podmínek licence GNU General Public License (verze 2 nebo novější) vydanou Free Software Foundation dále šířit a/nebo upravovat.&lt;br /&gt;
\n &lt;br /&gt;
\n Tento program je distribuován s vírou, že je dobrý, ale BEZ JAKÉKOLIV ZÁRUKY, JAKÉHOKOLI DRUHU, AŤ VÝSLOVNÉ NEBO VYPLÝVAJÍCÍ, VČETNĚ, ALE NIKOLI JEN, ZÁRUK OBCHODOVATELNOSTI A VHODNOSTI PRO URČITÝ ÚČEL. Detaily najdeš v GNU General Public License.&lt;br /&gt;
\n &lt;br /&gt;
\n Společně s touto kopií jsi obdržel/a jeden exemplář GNU General Public License. Pokud tomu tak není, navštiv:&lt;a href=http://www.gnu.org/licenses&gt;http://www.gnu.org/licenses&lt;/a&gt;&lt;br /&gt;
\n &lt;br /&gt;
\n Zdrojový kód a/nebo požadavky na vylepšení můžeš stáhnout/najít/zadat na této stránce:&lt;a href=http://github.com/Zukero/andors-trail/&gt;http://github.com/Zukero/andors-trail/&lt;/a&gt;&lt;br /&gt;</string>
<string name="about_interface">&lt;div&gt;&lt;b&gt;Nastavení&lt;/b&gt; je přístupné z hlavní nabídky (stiskni tlačítko zpět).&lt;/div&gt; &lt;p&gt;________________&lt;/p&gt; &lt;h1&gt;Herní ikony&lt;/h1&gt; &lt;div&gt;&lt;b&gt;Truhla&lt;/b&gt;&lt;img alt=chest src=chest.png /&gt;&lt;/div&gt; &lt;p&gt;Pozice okamžitého použití [Podržením prstu na vacích se zobrazí nabídka předmětů k okamžitému použití]&lt;/p&gt; &lt;div&gt;&lt;b&gt;Hrdina&lt;/b&gt;&lt;img alt=hero src=char_hero.png /&gt;&lt;/div&gt; &lt;p&gt;Menu [Přehled, Mise, Dovednosti a Inventář *]&lt;/p&gt; &lt;p&gt;* (Informace o předmětu zobrazí tak, že v inventáři klikneš na daný předmět; podržením prstu na předmětu zobrazíš další možností)&lt;/p&gt; &lt;div&gt;&lt;b&gt;Nepřítel&lt;/b&gt;&lt;img alt=monster src=monster.png /&gt;&lt;/div&gt; &lt;p&gt;Informace [Pouze během boje]&lt;/p&gt; &lt;p&gt;________________&lt;/p&gt; &lt;h1&gt;Boj&lt;/h1&gt; &lt;p&gt;Akce vykonané v boji stojí akční body (AB)...&lt;/p&gt; &lt;div&gt;&lt;b&gt;Útok&lt;/b&gt; - [3AP] *&lt;/div&gt; &lt;img alt=attacking src=doubleattackexample.png /&gt; &lt;p&gt;* (Případná výstroj a výbava může změnit časovou náročnost provedení akce - útoku, použití předmětu apod.)&lt;/p&gt; &lt;div&gt;&lt;b&gt;Použití předmětu&lt;/b&gt; - [5AP]&lt;/div&gt; &lt;div&gt;&lt;b&gt;Útěk&lt;/b&gt; - [6AP]&lt;/div&gt; &lt;p&gt;________________&lt;/p&gt; &lt;h1&gt;Souboj detailněji&lt;/h1&gt; &lt;div&gt;Během souboje podrž prst na políčku vedle hrdiny...&lt;/div&gt; &lt;div&gt;&lt;b&gt;Pro útěk&lt;/b&gt;&lt;/div&gt; &lt;p&gt;(vybrané políčko se zvýrazní - tlačítko útoku se změní na tlačítko pohybu)&lt;/p&gt; &lt;img alt=flee src=flee_example.png /&gt; &lt;p&gt;[aktivován mód útěku - podrž prst na nepříteli pro návrat k boji]&lt;/p&gt; &lt;div&gt;&lt;b&gt;Pro změnu cíle útoku&lt;/b&gt;&lt;/div&gt; &lt;p&gt;(červené zvýraznění cíle útoku se přesune na nového nepřítele)&lt;/p&gt; &lt;p&gt;[cíl útoku byl změněn]&lt;/p&gt;</string>
<string name="dialog_newversion_title">Vítej</string>
<string name="dialog_newversion_message">Děkujeme, že jsi si naistaloval hru Andor\'s Trail!
\n
\n Prosím uvědom si, že tato verze hry Andor\'s Trail není konečná, jedná se o hru ve VÝVOJI, z čehož vyplývá, že ne všechny mapy jsou kompletní.
\n Prosím navštiv fórum o hře. Tam lze diskutovat s jinými hráči a vývojáři této hry, nebo dokonce můžeš pomoci tuto hru zlepšit (viz O hře).
\n
\n Děkujeme za veškerou zpětnou vazbu!</string>
<string name="questlog_includecompleted_prompt">Vyber zobrazované mise</string>
<string name="questlog_includecompleted_hidecompleted">Skrýt dokončené mise</string>
<string name="questlog_includecompleted_includecompleted">Všechny mise</string>
<string name="questlog_includecompleted_onlycompleted">Jen dokončené mise</string>
<string name="questlog_queststatus">Stav: %1$s</string>
<string name="questlog_queststatus_inprogress">Aktivní</string>
<string name="questlog_queststatus_completed">Dokončená</string>
<string name="preferences_display_category">Vzhled</string>
<string name="preferences_display_fullscreen_title">Celo-obrazový mód</string>
<string name="preferences_display_fullscreen">Hra přes celý displej. (vyžaduje restart)</string>
<string name="preferences_dialog_category">Potvrzování akcí</string>
<string name="preferences_dialog_confirmrest_title">Potvrzení spánku</string>
<string name="preferences_dialog_confirmrest">Je vyžadováno potvrzení spánku při vstupu na postel. Pokud není zaškrtnuto, hrdina se automaticky vyspí.</string>
<string name="preferences_dialog_confirmattack_title">Potvrzení útoku</string>
<string name="preferences_dialog_confirmattack">Útoku na nepřítele předchází otázka \'Chceš zaútočit na nepřítele..?\'.</string>
<string name="preferences_dialog_monsterloot_title">Zobrazení bojové kořisti</string>
<string name="preferences_dialog_monsterloot">Výběr způsobu zobrazení tvé bojové kořisti po vyhraném boji (zlaťáky, zkušenosti, předměty).</string>
<string name="preferences_combat_category">Boj</string>
<string name="preferences_combat_speed_title">Rychlost průběhu boje</string>
<string name="preferences_combat_speed">Nastavení rychlosti útoku nepřítele.</string>
<string name="preferences_display_loot_dialog">Vždy zobrazí bojovou kořist</string>
<string name="preferences_display_loot_dialog_on_items">Zobrazí bojovou kořist pouze pokud kořist obsahuje předměty</string>
<string name="preferences_display_loot_dialog_on_items_or_toast">Zobrazí předměty, ostatní do oznámení</string>
<string name="preferences_display_loot_toast">Zobrazí krátké oznámení</string>
<string name="preferences_display_loot_toast_on_items">Oznámení pouze pokud bojová kořist obsahuje předměty</string>
<string name="preferences_display_loot_never">Nezobrazovat</string>
<string name="preferences_attackspeed_instant">Okamžitý útok (bez animace)</string>
<string name="preferences_attackspeed_fast">Rychlý útok</string>
<string name="preferences_attackspeed_normal">Běžný útok</string>
<string name="preferences_attackspeed_slow">Pomalý útok</string>
<string name="preferences_movement_category">Pohyb</string>
<string name="preferences_movementmethod_title">Typ pohybu</string>
<string name="preferences_movementmethod">Typ pohybu a způsob vyhýbání se překážkám.</string>
<string name="preferences_movementmethods_straight">Přímý pohyb (výchozí)</string>
<string name="preferences_movementmethods_avoid">Vyhýbat se překážkám</string>
<string name="actorinfo_currentconditions">Aktuální stav</string> <string name="actorcondition_info_removes_all">Odstraní zcela: %1$s</string>
<string name="actorcondition_info_immunity">Imunita vůči: %1$s</string>
<string name="iteminfo_effect_chance_of">%1$s šance na: %2$s</string>
<string name="iteminfo_effect_duration">(Počet kol: %1$d)</string>
<string name="iteminfo_effect_works_on_source">Na nositele</string>
<string name="iteminfo_effect_works_on_target">Na cíl</string>
<string name="iteminfo_effect_works_on_attacker">Na útočníka</string>
<string name="iteminfo_effect_works_when_hitting_target">Při zásahu</string>
<string name="iteminfo_effect_works_when_killing_target">Při každém zabití</string>
<string name="iteminfo_effect_works_when_used">Při použití</string>
<string name="iteminfo_effect_works_when_equipped">Když je použitý ve výstroji</string>
<string name="iteminfo_effect_works_when_hit_by_attacker">Při zásahu útočníkem</string>
<string name="iteminfo_effect_works_when_killed_by_attacker">Při zabití útočníkem</string>
<string name="iteminfo_effect_decrease_current_hp">"Vysává PŽ: %1$s "</string>
<string name="iteminfo_effect_increase_current_hp">Obnovuje PŽ: %1$s</string>
<string name="iteminfo_effect_decrease_current_ap">Vysává AB: %1$s</string>
<string name="iteminfo_effect_increase_current_ap">Obnovuje AB: %1$s</string>
<string name="iteminfo_effect_increase_max_hp">Zvyšuje maximální PŽ: +%1$d</string>
<string name="iteminfo_effect_decrease_max_hp">Snižuje maximální PŽ: +%1$d</string>
<string name="iteminfo_effect_increase_max_ap">Zvyšuje maximální počet AB: +%1$d</string>
<string name="iteminfo_effect_decrease_max_ap">Snižuje maximální počet AB: +%1$d</string>
<string name="iteminfo_effect_increase_movecost">Zvyšuje cenu pohybu o +%1$d AB</string>
<string name="iteminfo_effect_decrease_movecost">Snižuje cenu pohybu o%1$d AB</string>
<string name="preferences_display_scaling_factor_title">Měřítko</string>
<string name="preferences_display_scaling_factor">Změna velikosti vykreslených objektů a textů.</string>
<string name="preferences_display_scaling_factor_normal">Běžná velikost</string>
<string name="preferences_display_scaling_factor_50_percent_larger">1,5krát větší</string>
<string name="preferences_display_scaling_factor_double">Dvojnásobná velikost</string>
<string name="inventory_assign">Přiřazení položek okamžitého použití</string>
<string name="inventory_selectitem">Vyber předmět pro přiřazení</string>
<string name="inventory_assign_slot1">Položka 1</string>
<string name="inventory_assign_slot2">Položka 2</string>
<string name="inventory_assign_slot3">Položka 3</string>
<string name="inventory_unassign">Zrušit přiřazení položky</string>
<string name="preferences_movement_dpad_position_title">Virtuální d-pad</string>
<string name="preferences_movement_dpad_position">Zobrazí virtuální d-pad s jehož pomocí se ovládá pohyb.</string>
<string name="preferences_movement_dpad_minimizeable_title">Minimalizovatelný d-pad</string>
<string name="preferences_movement_dpad_minimizeable">Zaškrtnutí tohoto nastavení dovolí - v případě zapnutého d-padu - jeho minimalizaci stisknutím středu d-padu.</string>
<string name="preferences_movement_dpad_positions_disabled">Neaktivní</string>
<string name="preferences_movement_dpad_positions_lower_right">Spodní pravý roh</string>
<string name="preferences_movement_dpad_positions_lower_left">Spodní levý roh</string>
<string name="preferences_movement_dpad_positions_center_bottom">Spodní střed</string>
<string name="preferences_movement_dpad_positions_center_left">Vlevo uprostřed</string>
<string name="preferences_movement_dpad_positions_center_right">Vpravo uprostřed</string>
<string name="preferences_movement_dpad_positions_upper_left">Horní levý roh</string>
<string name="preferences_movement_dpad_positions_upper_right">Horní pravý roh</string>
<string name="preferences_movement_dpad_positions_center_top">Horní střed</string>
<string name="actorconditioninfo_constant_effect">Stálý efekt</string>
<string name="actorconditioninfo_effect_every_round">Každé kolo</string>
<string name="actorconditioninfo_effect_every_full_round">Každé celé kolo</string>
<string name="bulkselection_totalcost_buy">Celková cena: %1$d ks zlaťáků</string>
<string name="bulkselection_totalcost_sell">Celková cena: %1$d ks zlaťáků</string>
<string name="bulkselection_select_all">Vše</string>
<string name="bulkselection_sell_confirmation_title">Skutečně prodat?</string>
<string name="bulkselection_sell_confirmation">Skutečně chceš prodat tento předmět: %1$s? Jedná se o %2$s předmět a pravděpodobně jej už nikdy nezískáš.</string>
<string name="skill_title_weapon_chance">Přesné zbraně</string>
<string name="skill_title_weapon_dmg">Mocný úder</string>
<string name="skill_title_barter">Obchodník</string>
<string name="skill_title_dodge">Úhyb</string>
<string name="skill_title_barkskin">Hroší kůže</string>
<string name="skill_title_more_criticals">Více kritických zásahů</string>
<string name="skill_title_better_criticals">Účinnější kritické zásahy</string>
<string name="skill_title_speed">Bojová rychlost</string>
<string name="skill_title_coinfinder">Lovec pokladů</string>
<string name="skill_title_more_exp">Rychlý učeň</string>
<string name="skill_title_cleave">Kosič nepřátel</string>
<string name="skill_title_eater">Pojídač mrtvol</string>
<string name="skill_title_fortitude">Zvýšená vytrvalost</string>
<string name="skill_title_evasion">Úskok</string>
<string name="skill_title_regeneration">Zotavení</string>
<string name="skill_title_lower_exploss">Ovládnutí selhání</string>
<string name="skill_title_magicfinder">Lovec artefaktů</string>
<string name="skill_title_resistance_mental">Silná mysl</string>
<string name="skill_title_resistance_physical_capacity">Fyzická odolnost</string>
<string name="skill_title_resistance_blood_disorder">Čistá krev</string>
<string name="skill_shortdescription_weapon_chance">Zvyšuje šanci na zásah</string>
<string name="skill_shortdescription_weapon_dmg">Zvyšuje zranění způsobené útokem</string>
<string name="skill_shortdescription_barter">Lepší ceny u obchodníků</string>
<string name="skill_shortdescription_dodge">Zvyšuje šanci vykrytí útoku</string>
<string name="skill_shortdescription_barkskin">Zvyšuje redukci zranění</string>
<string name="skill_shortdescription_more_criticals">Zvyšuje úroveň kritického zásahu</string>
<string name="skill_shortdescription_better_criticals">Zvyšuje zranění způsobená kritickým zásahem</string>
<string name="skill_shortdescription_speed">Zvyšuje maximální počet akčních bodů</string>
<string name="skill_shortdescription_coinfinder">Zvyšuje šanci na nalezení zlaťáků</string>
<string name="skill_shortdescription_more_exp">Více zkušeností za zabité nepřátele</string>
<string name="skill_shortdescription_cleave">Každé zabití obnoví jeden akční bod</string>
<string name="skill_shortdescription_eater">Každé zabití obnoví životy</string>
<string name="skill_shortdescription_fortitude">Zvyšuje maximální počet životů na každé nové úrovni</string>
<string name="skill_shortdescription_evasion">Zvyšuje šanci na útěk</string>
<string name="skill_shortdescription_regeneration">Léčí životy každé kolo</string>
<string name="skill_shortdescription_lower_exploss">Snížuje počet ztracených zkušeností pokud hráč zemře</string>
<string name="skill_shortdescription_magicfinder">Zvyšuje šanci na nalezení kouzelných předmětů</string>
<string name="skill_shortdescription_resistance_mental">Odolnost vůči duševním podmínkám</string>
<string name="skill_shortdescription_resistance_physical_capacity">Odolnost vůči fyzickým (tělesným) podmínkám</string>
<string name="skill_shortdescription_resistance_blood_disorder">Odolnost vůči krevním potížím</string>
<string name="skill_longdescription_weapon_chance">Zvýší šanci na zásah o %1$d %% za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_weapon_dmg">Zvýší zranění způsobená útokem o %1$d za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_barter">Každá získaná úroveň osvojení dovednosti sníží nákupní i prodejní přirážku o %1$d procentní body.</string>
<string name="skill_longdescription_dodge">Zvýší šanci na vykrytí útoku o %1$d %% za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_barkskin">Zvýší redukci zranění o %1$d za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_more_criticals">Zvýší stávající úroveň kritického zásahu výstroje o %1$d %% za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_better_criticals">Zvýší stávající násobitel kritického zásahu výstroje o %1$d %% za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_speed">Zvýší maximální počet akčních bodů (AB) o %1$d za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_coinfinder">Zvýší šanci na nález zlaťáků po zabití nepřítele o %1$d %% a zvýší počet nalezených zlaťáků o %2$d %% za každou úroveň osvojení dovednosti (až do maximální výše zlaťáků, které nepřítel může mít).</string>
<string name="skill_longdescription_more_exp">Zvýší množství zkušeností získaných zabitím nepřítele o %1$d %% za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_cleave">Za každého zabitého nepřítele obnoví +%1$d akční bod (AB) za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_eater">Za každého zabitého nepřítele obnoví +%1$d život (PŽ) za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_fortitude">Při každém zvýšení úrovně zvýší maximální počet životů (PŽ) o %1$d za každou úroveň osvojení dovednosti. Toto neplatí zpětně, ale pouze pro následující nové úrovně.</string>
<string name="skill_longdescription_evasion">Každá úroveň osvojení dovednosti sníží jak šanci na neúspěch při útěku o %1$d %%, tak šanci, že nepřítel na sousedním políčku zaútočí o %2$d %%.</string>
<string name="skill_longdescription_regeneration">V případě, kdy na sousedním políčku není žádná nestvůra, obnoví každé kolo (cca 6 sekund) +%1$d život (PČ) za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_lower_exploss">Každá úroveň osvojení dovednosti sníží množství ztracených zkušeností způsobené úmrtím o %1$d %% (procent ze současného množství ztracených zkušeností, ne procent celkově). %2$d úrovní osvojení dovednosti zcela zruší ztrátu zkušeností způsobenou úmrtím.</string>
<string name="skill_longdescription_magicfinder">Zvýší šanci na nález výjimečných předmětů o %1$d %% za každou úroveň osvojení dovednosti.</string>
<string name="skill_longdescription_resistance_mental">Sníží šanci na postižení duševním stavem o %1$d %% za každou úroveň osvojení dovednosti. To zahrnuje stavy způsobené útoky nepřátel jako např. Omámení nebo Oslabení zbraně.</string>
<string name="skill_longdescription_resistance_physical_capacity">Sníží šanci na postižení stavem působícím na tvé fyzické schopnosti o %1$d %% za každou úroveň osvojení dovednosti, až do maximální výše %2$d %%. To zahrnuje stavy způsobené útoky nepřátel jako např. Únava.</string>
<string name="skill_longdescription_resistance_blood_disorder">Sníží šanci na postižení krve o %1$d %% za každou úroveň osvojení dovednosti, až do maximální výše %2$d %%. To zahrnuje stavy způsobené útoky nepřátel jako např. Otrava nebo Krvácející rána.</string>
<string name="skillinfo_action_levelup">Osvojit si</string>
<string name="skill_current_level">Současná úroveň: %1$d</string>
<string name="skill_current_level_with_maximum">Současná úroveň: %1$d / %2$d</string>
<string name="skill_prerequisite_other_skill">Pro osvojení této dovednosti je zapotřebí mít alespoň úroveň %1$d dovednosti: %2$s.</string>
<string name="skill_prerequisite_level">Pro osvojení této dovednosti je zapotřebí být alespoň na úrovni %1$d.</string>
<string name="skill_prerequisite_stat">Pro osvojení této dovednosti potřebuješ mít základní bojovou statistiku %2$s alespoň na hodnotě %1$d.</string>
<string name="skill_number_of_increases_one">Můžeš si vybrat jednu dovednost, kterou si osvojíš.</string>
<string name="skill_number_of_increases_several">Můžeš si vybrat %1$d dovednosti/í, které si osvojíš.</string>
<string name="levelup_adds_new_skillpoint">Získáváš také možnost osvojit si jednu dovednost!</string>
<string name="loadsave_save_to_new_slot">Vytvořit novou pozici</string>
<string name="loadsave_save_overwrite_confirmation_title">Přepsat uloženou hru?</string>
<string name="loadsave_save_overwrite_confirmation">Tato uložená hra má jiné jméno hrdiny (%1$s) než je současné jméno hrdiny (%2$s). Opravdu si přeješ tuto hru přepsat?</string>
<string name="iteminfo_displaytypes_ordinary">Běžný</string>
<string name="iteminfo_displaytypes_quest">Předmět mise</string>
<string name="iteminfo_displaytypes_legendary">Legendární</string>
<string name="iteminfo_displaytypes_extraordinary">Mimořádný</string>
<string name="iteminfo_displaytypes_rare">Vzácný</string>
<string name="actorconditioninfo_category">"Kategorie: "</string>
<string name="actorcondition_categories_spiritual">Duchovní</string>
<string name="actorcondition_categories_mental">Duševní</string>
<string name="actorcondition_categories_physical">Fyzická</string>
<string name="actorcondition_categories_blood">Krevní potíže</string>
<string name="traitsinfo_base_max_hp">Max PŽ:</string>
<string name="traitsinfo_base_max_ap">Počet AB:</string>
<string name="menu_save_saving_not_allowed_in_combat">Během souboje nelze hru uložit.</string>
<string name="preferences_optimized_drawing_title">Optimalizované vykreslení</string>
<string name="preferences_optimized_drawing">Vypni toto nastavení, pokud se zobrazují chyby ve vykreslení. Pokud je tato volba vybrána, překreslují se pouze měněné části obrazovky.</string>
<string name="skill_title_shadow_bless">Tmavé požehnání Přítmí</string>
<string name="skill_shortdescription_shadow_bless">Odolnost vůči všem typům postižení</string>
<string name="skill_longdescription_shadow_bless">Sníží šanci na postižení všech druhů o %1$d %%. To zahrnuje všechny stavy způsobené útokem nepřátel jako např. Jed, Omráčení, Únava.</string>
<string name="inventory_movetop">Posunout nahoru</string>
<string name="inventory_movebottom">Posunout dolů</string>
<string name="actorinfo_immune_criticals">Imunní vůči kritickým zásahům</string>
<string name="traitsinfo_criticalhit_effectivechance">Skutečná šance na kritický zásah:</string>
<string name="skill_title_crit1">Vnitřní krvácení</string>
<string name="skill_shortdescription_crit1">Šance na vnitřní krvácení</string>
<string name="skill_longdescription_crit1">Každý kritický zásah má %1$d %% šanci na způsobení vnitřního krvácení, což cíli přivodí stav \'Vnitřní krvácení\'. Vnitřní krvácení významně sníží útočné statistiky cíle a to znamená, že cíl má menší šanci na úspěšný zásah.</string>
<string name="skill_title_crit2">Lamač kostí</string>
<string name="skill_shortdescription_crit2">Šance na zlomení kostí</string>
<string name="skill_longdescription_crit2">Každý kritický zásah má %1$d %% šanci na zlomení kostí protivníka, což cíli přivodí stav \'Zlomenina\'. To významně sníží obranné statistiky cíle a to znamená, že cíl má meší šanci na vykrytí útoku.</string>
<string name="skill_title_rejuvenation">Omlazení</string>
<string name="skill_shortdescription_rejuvenation">Šance na ukončení negativního stavu</string>
<string name="skill_longdescription_rejuvenation">V každém kole (6 sekund) je %1$d %% šance, že závažnost jednoho působícího negativního stavu bude snížena o jeden stupeň. To platí pro všechny dočasně působící stavy; duševní jako např. Omámení, fyzické jako např. Únava a také na krevní potíže jako např. Otravu.</string>
<string name="skill_title_taunt">Výsměch</string>
<string name="skill_shortdescription_taunt">Útočník ztrácí AB při každém útoku, kterým míjí</string>
<string name="skill_longdescription_taunt">V případě, že útočník svým útokem míjí, existuje %1$d %% šance, že útočník ztratí %2$d akční body (AB). To platí pro všechny typy útoků vůči tobě.</string>
<string name="skill_title_concussion">Otřes mozku</string>
<string name="skill_shortdescription_concussion">Šance na způsobení otřesu mozku</string>
<string name="skill_longdescription_concussion">Pokud je při útoku šance cíle na vykrytí útoku (VÚ) alespoň o %1$d nižší než je tvá šance na zásah, je %2$d %% šance, že takový zásah způsobí cíli otřes mozku. To zásadně sníží útočné bojové statistiky cíle, především zmenší šanci na úspěšný zásah.</string>
<string name="about_button4">O hře</string>
<string name="preferences_ui_category">Rozhraní</string>
<string name="preferences_ui_enable_animations_title">Zapnutí animací</string>
<string name="preferences_ui_enable_animations">Zobrazí animace pro různé prvky herního rozhraní.</string>
<string name="menu_button_worldmap">Mapa</string>
<string name="menu_button_worldmap_failed">Mapa nemůže být zobrazena.</string>
<string name="display_worldmap_not_available">Na tomto místě nelze zobrazit mapu.</string>
<string name="display_worldmap_title">Mapa</string>
<string name="inventory_equip_offhand">Vem do levé ruky</string>
<string name="iteminfo_effect_weapon_attack_cost">Cena útoku: %1$d AB</string>
<string name="iteminfo_effect_increase_attack_cost">Zvyšuje cenu útoku o %1$d AB</string>
<string name="iteminfo_effect_decrease_attack_cost">Snižuje cenu útoku o %1$d AB</string>
<string name="iteminfo_effect_weapon_attack_chance">Šance na zásah: %1$d</string>
<string name="iteminfo_effect_increase_attack_chance">Zvyšuje šanci na zásah o %1$d</string>
<string name="iteminfo_effect_decrease_attack_chance">Snižuje šanci na zásah o %1$d</string>
<string name="iteminfo_effect_weapon_attack_damage">Zranění: %1$d</string>
<string name="iteminfo_effect_weapon_attack_damage_minmax">Zranění: %1$d-%2$d</string>
<string name="iteminfo_effect_increase_attack_damage">Zvyšuje zranění o %1$d</string>
<string name="iteminfo_effect_increase_attack_damage_minmax">Zvyšuje zranění o %1$d-%2$d</string>
<string name="iteminfo_effect_decrease_attack_damage">Snižuje zranění o %1$d</string>
<string name="iteminfo_effect_decrease_attack_damage_minmax">Snižuje zranění o %1$d-%2$d</string>
<string name="iteminfo_effect_increase_critical_skill">Zvyšuje úroveň kritického zásahu o %1$d</string>
<string name="iteminfo_effect_decrease_critical_skill">Snižuje úroveň kritického zásahu o %1$d</string>
<string name="iteminfo_effect_critical_multiplier">"Umožňuje kritický zásah s násobitelem x%1$.1f"</string>
<string name="iteminfo_effect_increase_block_chance">Zvyšuje šanci na vykrytí útoku o %1$d</string>
<string name="iteminfo_effect_decrease_block_chance">Snižuje šanci na vykrytí útoku o %1$d</string>
<string name="iteminfo_effect_increase_damage_resistance">Zvyšuje redukci zranění o %1$d</string>
<string name="iteminfo_effect_decrease_damage_resistance">Snižuje redukci zranění o %1$d</string>
<string name="iteminfo_effect_increase_use_cost">Zvyšuje cenu používání (AB) předmětů během boje o %1$d AB</string>
<string name="iteminfo_effect_decrease_use_cost">Snižuje cenu používání (AB) předmětů během boje o %1$d AB</string>
<string name="iteminfo_effect_increase_reequip_cost">Zvyšuje cenu vystrojení (AB) předmětů během boje o %1$d AB</string>
<string name="iteminfo_effect_decrease_reequip_cost">Snižuje cenu vystrojení (AB) předmětů během boje o %1$d AB</string>
<string name="loadsave_save_overwrite_confirmation_all">Skutečně přepsat uloženou hru?</string>
<string name="loadsave_save_overwrite_confirmation_slot">(pozice %1$d)</string>
<string name="preferences_display_overwrite_savegame_entries_always_confirm">Vždy zobrazit potvrzovací okno</string>
<string name="preferences_display_overwrite_savegame_entries_confirm_overwrite">Zobrazit pouze v případě, že hrdina má jiné jméno</string>
<string name="preferences_display_overwrite_savegame_entries_never_confirm">Nezobrazovat potvrzovací okna</string>
<string name="preferences_dialog_overwrite_savegame_title">Potvrzení při přepsání uložené hry</string>
<string name="preferences_dialog_overwrite_savegame">Zobrazit potvrzovací okno pokud se chystáš přepsat existující uloženou hru.</string>
<string name="heroinfo_reequip_cost">Cena změny výstroje (AB):</string>
<string name="heroinfo_useitem_cost">Cena užití předmětu (AB):</string>
<string name="combat_result_monstermoved">%1$s se pohybuje.</string>
<string name="combat_log_title">Záznam souboje</string>
<string name="combat_log_noentries">Bez záznamu.</string>
<string name="conversation_reward_quest_finished">[Dokončených misí: \"%1$s\"]</string>
<string name="conversation_reward_quest_updated">[Mise aktualizována: \"%1$s\"]</string>
<string name="skill_title_weapon_prof_dagger">Zručnost: dýky</string>
<string name="skill_title_weapon_prof_1hsword">Zručnost: jedno-ruční meče</string>
<string name="skill_title_weapon_prof_2hsword">Zručnost: obou-ruční meče</string>
<string name="skill_title_weapon_prof_axe">Zručnost: sekery</string>
<string name="skill_title_weapon_prof_blunt">Zručnost: tupé zbraně</string>
<string name="skill_title_weapon_prof_unarmed">Boj beze zbraní</string>
<string name="skill_title_armor_prof_shield">Zručnost: štíty</string>
<string name="skill_title_armor_prof_unarmored">Boj be zbroje</string>
<string name="skill_title_armor_prof_light">Zručnost: lehká brnění</string>
<string name="skill_title_armor_prof_heavy">Zručnost: těžká brnění</string>
<string name="skill_title_fightstyle_dualwield">Bojový styl: dvě zbraně</string>
<string name="skill_title_fightstyle_2hand">Bojový styl: obou-ruční zbraně</string>
<string name="skill_title_fightstyle_weapon_shield">Bojový styl: zbraň a štít</string>
<string name="skill_title_specialization_dualwield">Specializace: Dvě zbraně</string>
<string name="skill_title_specialization_2hand">Specializace: Obou-ruční zbraně</string>
<string name="skill_title_specialization_weapon_shield">Specializace: Zbraň a štít</string>
<string name="skill_shortdescription_weapon_prof_dagger">Zvyšuje útočné statistiky pro boj s noži a dýkami</string>
<string name="skill_shortdescription_weapon_prof_1hsword">Zvyšuje útočné statistiky pro boj s jedno-ručními meči</string>
<string name="skill_shortdescription_weapon_prof_2hsword">Zvyšuje útočné statistiky pro boj s obou-ručními meči</string>
<string name="skill_shortdescription_weapon_prof_axe">Zvyšuje útočné statistiky pro boj se sekerami</string>
<string name="skill_shortdescription_weapon_prof_blunt">Zvyšuje útočné statistiky pro boj s tupými zbraněmi</string>
<string name="skill_shortdescription_weapon_prof_unarmed">Zvyšuje útočné statistiky pro boj beze zbraní</string>
<string name="skill_shortdescription_armor_prof_shield">Zvyšuje obranné statistiky při použití štítu</string>
<string name="skill_shortdescription_armor_prof_unarmored">Zvyšuje obranné statistiky při boji bez brnění</string>
<string name="skill_shortdescription_armor_prof_light">Zvyšuje obranné statistiky při použití lehkého brnění</string>
<string name="skill_shortdescription_armor_prof_heavy">Zvyšuje obranné statistiky při použití těžkého brnění</string>
<string name="skill_shortdescription_fightstyle_dualwield">Útoky dvěma zbraněmi zároveň</string>
<string name="skill_shortdescription_fightstyle_2hand">Účinější útoky obou-ručními zbraněmi</string>
<string name="skill_shortdescription_fightstyle_weapon_shield">Efektivnější boj za použití zbraně a štítu</string>
<string name="skill_shortdescription_specialization_dualwield">Expert na použití dvou zbraní současně</string>
<string name="skill_shortdescription_specialization_2hand">Expert na použití obou-ručních zbraní</string>
<string name="skill_shortdescription_specialization_weapon_shield">Expert na boj se zbraní a štítem</string>
<string name="skill_longdescription_weapon_prof_dagger">Při použití nože, dýky nebo krátkého meče zvýší každá úroveň osvojení dovednosti šanci na zásah o %1$d %% základní šance za zásah zbraně, zvýší šanci na vykrytí útoku o %2$d %% základní šance na vykrytí útoku zbraně a zvýší úroveň kritického zásahu o %3$d %% základní úrovně kritického zásahu zbraně.</string>
<string name="skill_longdescription_weapon_prof_1hsword">Při použití dlouhého meče, kordu nebo širokého meče zvýší každá úroveň osvojení dovednosti šanci na zásah o %1$d %% základní šance za zásah zbraně, zvýší šanci na vykrytí útoku o %2$d %% základní šance na vykrytí útoku zbraně a zvýší úroveň kritického zásahu o %3$d %% základní úrovně kritického zásahu zbraně.</string>
<string name="skill_longdescription_weapon_prof_2hsword">Při použití obou-ručního meče zvýší každá úroveň osvojení dovednosti šanci na zásah o %1$d %% základní šance za zásah zbraně, zvýší šanci na vykrytí útoku o %2$d %% základní šance na vykrytí útoku zbraně a zvýší úroveň kritického zásahu o %3$d %% základní úrovně kritického zásahu zbraně.</string>
<string name="skill_longdescription_weapon_prof_axe">Při použití sekery nebo válečné sekery zvýší každá úroveň osvojení dovednosti šanci na zásah o %1$d %% základní šance za zásah zbraně, zvýší šanci na vykrytí útoku o %2$d %% základní šance na vykrytí útoku zbraně a zvýší úroveň kritického zásahu o %3$d %% základní úrovně kritického zásahu zbraně.</string>
<string name="skill_longdescription_weapon_prof_blunt">Při použití tupých zbraní zvýší každá úroveň osvojení dovednosti šanci na zásah o %1$d %% základní šance za zásah zbraně, zvýší šanci na vykrytí útoku o %2$d %% základní šance na vykrytí útoku zbraně a zvýší úroveň kritického zásahu o %3$d %% základní úrovně kritického zásahu zbraně. Mezi tupé se počítají kyje, tyče, palice, žezla, válečné a obří kladiva.</string>
<string name="skill_longdescription_weapon_prof_unarmed">Při boji bez zbraně a štítu zvýší každá úroveň osvojení dovednosti šanci na zásah o %1$d %%, šanci na vykrytí útoku o %2$d %% a zvýší úroveň kritického zásahu o %3$d %%.</string>
<string name="skill_longdescription_armor_prof_shield">Zvýší redukci zranění o %1$d za každou úroveň osvojení dovednosti v případech, když je použit štít.</string>
<string name="skill_longdescription_armor_prof_unarmored">Zvýší šanci na vykrytí o %1$d za každou úroveň osvojení dovednosti v případech, kdy není použita zbroj. Předměty vyrobené z látky nejsou považovány za zbroj.</string>
<string name="skill_longdescription_armor_prof_light">Zvýší šanci na vykrytí útoku každého kusu nošeného lehkého brnění o %1$d %% z jeho výchozí hodnoty za každou osvojenou úroveň dovednosti. Lehké brnění zahrnuje kožená, usňová brnění a brnění z lehkých kovů.</string>
<string name="skill_longdescription_armor_prof_heavy">Zvýší šanci na vykrytí útoku každého vystrojeného těžkého brnění o %1$d %% z jeho výchozí hodnoty za každou úroveň osvojení dovednosti. Dále sníží postih ceny pohybu o %2$d %% za každou úroveň osvojení dovednosti a také sníží postih ceny útoku o %3$d %% za každou úroveň osvojení dovednosti. Těžké brnění zahrnuje kované, kroužkové a plátové brnění.</string>
<string name="preferences_quickslots_placement">Pozice položek okamžitého použití</string>
<string name="preferences_quickslots_placement_summary">Kde se zobrazí položky okamžitého použití</string>
<string name="preferences_quickslots_placements_horizontal_center_bottom">Uprostřed dole</string>
<string name="preferences_quickslots_placements_vertical_center_left">Uprostřed vlevo</string>
<string name="preferences_quickslots_placements_vertical_center_right">Uprostřed vpravo</string>
<string name="preferences_quickslots_placements_vertical_bottom_left">Dole vlevo, podle levého okraje</string>
<string name="preferences_quickslots_placements_horizontal_bottom_left">Dole vlevo, podle spodního okraje</string>
<string name="preferences_quickslots_placements_horizontal_bottom_right">Dole vpravo, podle spodního okraje</string>
<string name="preferences_quickslots_placements_vertical_bottom_right">Dole vpravo, podle pravého okraje</string>
<string name="preferences_ui_show_quickslots_when_toolbox_is_visible_title">Zobrazí položky rychlého použití, když je otevřený panel nástrojů</string>
<string name="preferences_ui_show_quickslots_when_toolbox_is_visible">Položky rychlého použití se zobrazí v okamžiku otevření panelu nástrojů</string>
<string name="startscreen_incompatible_savegames">Tato verze hry Andor\'s Trail je stále ve vývoji. Uložené hry vytvořené touto verzí nejsou kompatibilní s veřejně vydanou verzí hry.</string>
<string name="startscreen_non_release_version">Toto je testovací verze hry Andor\'s Trail. Uložené hry vytvořené touto verzí nejsou kompatibilní s veřejně vydanou verzí hry.</string>
<string name="heroinfo_gamestats">Herní statistiky</string>
<string name="heroinfo_gamestats_quests">Dokončené mise</string>
<string name="heroinfo_gamestats_deaths">Počet upadnutí do bezvědomí</string>
<string name="heroinfo_gamestats_spent_gold">Zlaťáky utracené v obchodech</string>
<string name="heroinfo_gamestats_bonemeals">Počet vypitých lektvarů z kostní moučky</string>
<string name="heroinfo_gamestats_num_used_items">Počet použitých předmětů</string>
<string name="heroinfo_gamestats_visited_maps">Počet navštívených míst</string>
<string name="heroinfo_gamestats_fav_item">Nejčastěji použitý předmět</string>
<string name="heroinfo_gamestats_num_killed_monsters">Zabito nepřátel</string>
<string name="heroinfo_gamestats_top_boss">Nejsilnější zabitý nepřítel</string>
<string name="heroinfo_gamestats_fav_monsters">Nejčastěji zabitý nepřítel</string>
<string name="heroinfo_gamestats_name_and_qty">%1$s (%2$d)</string>
<string name="preferences_ui_use_localized_resources_title">Lokalizované zdroje</string>
<string name="preferences_ui_use_localized_resources">Pokud je překlad k dispozici, zobrazí se (vyžadován restart)</string>
<string name="change_locale_requires_restart">Změna lokalizovaných zdrojů vyžeduje restart. Hra Andor\'s Trail byla zavřena.</string>
<string name="inventory_category_all">Vše</string>
<string name="inventory_category_favorites">Oblíbené</string>
<string name="inventory_category_weapons">Zbraně</string>
<string name="inventory_category_armor">Zbroje</string>
<string name="inventory_category_usable">Spotřebovatelné</string>
<string name="inventory_category_quest">Předměty misí</string>
<string name="inventory_category_other">Jiné</string>
<string name="inventory_sort_custom">Nesrovnané</string>
<string name="inventory_sort_name">Dle jména</string>
<string name="inventory_sort_price">Dle ceny</string>
<string name="inventory_sort_quantity">Dle množství</string>
<string name="inventory_sort_rarity">Dle vzácnosti</string>
<string name="inventory_sort_type">Dle typu</string>
<string name="shoplist_sort_custom">Nesrovnané</string>
<string name="shoplist_sort_name">Dle jména</string>
<string name="shoplist_sort_price">Dle ceny</string>
<string name="shoplist_sort_quantity">Dle množství</string>
<string name="shoplist_sort_rarity">Dle vzácnosti</string>
<string name="shoplist_sort_type">Dle typu</string>
<string name="skill_category_all">Vše</string>
<string name="skill_category_offense">Útočné</string>
<string name="skill_category_defense">Obrané</string>
<string name="skill_category_criticals">Kritické zásahy</string>
<string name="skill_category_immunity">Imunitní</string>
<string name="skill_category_utility">Užitné</string>
<string name="skill_category_speciality">Specializace</string>
<string name="skill_sort_unsorted">Nesrovnané</string>
<string name="skill_sort_name">Dle jména</string>
<string name="skill_sort_points">Dle úrovně osvojení</string>
<string name="skill_sort_unlocked">Dle dostupnosti</string>
<string name="preferences_display_theme_title">Motiv</string>
<string name="preferences_display_theme">Vyber motiv zobrazení (vyžaduje restart)</string>
<string name="preferences_display_theme_blue">Kobalt</string>
<string name="preferences_display_theme_green">Malachit</string>
<string name="preferences_display_theme_charcoal">Obsidián</string>
<string name="change_theme_requires_restart">Změna motivu vyžaduje restart. Hra Andor\'s Trail byla zavřena.</string>
<string name="skill_longdescription_fightstyle_dualwield">Poskytne bojový bonus, když je útok veden dvěma zbraněmi současně, jedna je v pravé ruce a druhá je v levé ruce.
\n
\nBez osvojení této dovednosti se využije pouze %1$d %% z charakteristik zbraně vybavené v levé ruce. To obsahuje šanci na zásah, úroveň kritického zásahu, zranění způsobená útokem a šanci na vykrytí útoku. Bez znalosti této dovednosti je časová náročnost (počet AB) útoku rovna součtu časové náročnosti útoku obou zbraní.
\n
\nPři osvojení jedné úrovně této dovednosti se využije %2$d %% z charakteristik zbraně vybavené v levé ruce a časová náročnost útoku je rovna součtu časové náročnosti útoku zbraně s vyšší časovou náročností a %3$d %% časové náročnosti zbraně s menší časovou náročností.
\n
\nPři osvojení dvou úrovní této dovednosti se využije %4$d %% z charakteristik zbraně vybavené v levé ruce a časová náročnost útoku je rovna časové náročnosti útoku zbraně s vyšší časovou náročností.</string>
<string name="skill_longdescription_fightstyle_2hand">Poskytne bojový bonus, když je útok veden obou-ruční zbraní jako je např. obou-ruční meč, válečná sekera, obří kladivo.
\n
\nKaždá úroveň osvojení dovednosti zvýší zbrani zranění způsobená útokem o %1$d %% základního zranění způsobeného útokem zbraně.</string>
<string name="skill_longdescription_fightstyle_weapon_shield">Poskytne bojový bonus, když je útok veden zbraní v pravé ruce a štít je v levé ruce.
\n
\nKaždá úroveň osvojení dovednosti zvýší šanci na zásah zbraně o %1$d %% její základní šance na zásah a zvýší šanci štítu na vykrytí útoku o %2$d %% jeho základní šance na vykrytí útoku.</string>
<string name="skill_longdescription_specialization_dualwield">Zvýší oběma zbraním jak šanci na zásah, tak šanci na vykrytí útoku. Šanci na zásah zvýší o %1$d %% základní šance na zásah (navíc k bonusu za bojový styl), šanci na vykrytí útoku zvýší o %2$d %% základní šance na vykrytí útoku.</string>
<string name="skill_longdescription_specialization_2hand">Zvýší obourujční zbrani jak šanci na zásah, tak zranění způsobená útokem. Šanci na zásah zvýší o %2$d %% základní šance na zásah, zranění způsobená útokem zvýší o %1$d %% základního zranění způsobeného útokem (navíc k bonusu získaného díky bojovému stylu).</string>
<string name="skill_longdescription_specialization_weapon_shield">Zvýší zbrani jak šanci na zásah, tak zranění způsobená útokem. Šanci na zásah zvýší o %1$d %% základní šance na zásah, zranění způsobená útokem zvýší o %2$d %% základního zranění způsobeného útokem.</string>
<string name="skill_category_proficiency">Zručnosti</string>
</resources>

View File

@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">Andors Pfad</string>
<string name="app_name">Andor\'s Trail</string>
<string name="app_description">Questbasiertes Fantasy-Rollenspiel</string>
<string name="exit_to_menu">Zum Menü</string>
@@ -160,14 +160,14 @@
<string name="about_button1">Hilfe</string>
<string name="about_button2">Autoren</string>
<string name="about_button3">Lizenz</string>
<string name="about_contents1">Willkommen bei Andors Pfad, einem rogue-like Open-Source Rollenspiel für Android&lt;br /&gt;
\n &lt;br /&gt;
\n &lt;a href=http://andorstrail.com/&gt;Forum auf andorstrail.com für Fragen und Diskussionen.&lt;/a&gt;&lt;br /&gt;
\n &lt;br /&gt;
\n &lt;a href=http://andorstrail.com/wiki&gt;Game-Wiki über die Welt von Andors Pfad und weitergehende Informationen.&lt;/a&gt;&lt;br /&gt;
\n &lt;br /&gt;
\n &lt;a href=http://github.com/Zukero/andors-trail/&gt;Projekt-Homepage auf github.com für Entwickler.&lt;/a&gt;&lt;br /&gt;
\n &lt;br /&gt;
<string name="about_contents1">Willkommen bei Andor\'s Trail, einem rogue-like Open-Source Rollenspiel für Android&lt;br /&gt;
\n &lt;br /&gt;
\n &lt;a href=http://andorstrail.com/&gt;Forum auf andorstrail.com für Fragen und Diskussionen.&lt;/a&gt;&lt;br /&gt;
\n &lt;br /&gt;
\n &lt;a href=http://andorstrail.com/wiki&gt;Game-Wiki über die Welt von Andors Pfad und weitergehende Informationen.&lt;/a&gt;&lt;br /&gt;
\n &lt;br /&gt;
\n &lt;a href=http://github.com/Zukero/andors-trail/&gt;Projekt-Homepage auf github.com für Entwickler.&lt;/a&gt;&lt;br /&gt;
\n &lt;br /&gt;
\n Bitte besuche das Forum, um das Spiel mit anderen Spielern zu diskutieren.&lt;br /&gt;</string>
<!--
@@ -629,4 +629,7 @@ Jeder Level des Skills erhöht die Angriffschance von Waffen um %1$d %% ihrer ur
<string name="combat_miss_animation_message">MISS</string>
<string name="dialog_recenter">Zentrieren</string>
</resources>
<string name="change_theme_requires_restart">Änderung des Benutzer Interface erfordert Neustart. Andor\'s Trail wurde beendet.</string>
</resources>

View File

@@ -14,7 +14,7 @@
<string name="savegame_currenthero_displayinfo">Maila %1$d, %2$d esp, %3$d txanpon</string>
<string name="dialog_loading_message">Baliabideak kargatzen…</string>
<string name="dialog_loading_failed_title">Kargak huts egin du</string>
<string name="dialog_loading_failed_title">Load Faile😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎djj</string>
<string name="dialog_loading_failed_message">Aplikazioak ezin izan du gordetako partida kargatu.
:(
@@ -401,4 +401,5 @@ Zure iruzkinak ongi etorriak dira!
<string name="combat_log_title">Borrokaren egunkaria</string>
<string name="skill_title_weapon_prof_unarmed">Armarik gabeko borroka</string>
<string name="localize_resources_from_mo_filename">eu.mo</string>
<string name="dialog_recenter">kkk</string>
</resources>

View File

@@ -456,7 +456,7 @@
<string name="heroinfo_reequip_cost">Coût de rééquipement (PA) :</string>
<string name="heroinfo_useitem_cost">Utiliser le coût de lobjet (PA) :</string>
<string name="combat_result_monstermoved">%1$d se déplace.</string>
<string name="combat_result_monstermoved">%1$s se déplace.</string>
<string name="combat_log_title">Journal de combat</string>
<string name="conversation_reward_quest_finished">[Quête accomplie : « %1$s»]</string>
<string name="conversation_reward_quest_updated">[Quête mise à jour : « %1$s»]</string>

View File

@@ -506,4 +506,12 @@
<string name="preferences_ui_use_localized_resources">Vertaling gebruiken voor de spelomgeving en -inhoud. (herstart vereist)</string>
<string name="change_locale_requires_restart">De taalwijziging vereist een herstart. Andor\'s Trail is afgesloten.</string>
</resources>
<string name="dialog_recenter">opnieuw centreren</string>
<string name="dialog_more">Meer</string>
<string name="dialog_monsterencounter_conditions">Voorwaarden</string>
<string name="heroinfo_skill_categories">Categorie</string>
<string name="heroinfo_skill_sort">Sorteren</string>
<string name="heroinfo_inventory_sort">Sorteren op</string>
</resources>

View File

@@ -27,7 +27,7 @@
<string name="status_hp">PŻ:</string>
<string name="status_ap">PA:</string>
<string name="status_exp">Poziom:</string>
<string name="status_exp">Dośw.:</string>
<string name="heroinfo_char">Przegląd</string>
<string name="heroinfo_inv">Ekwipunek</string>
@@ -65,7 +65,7 @@
<string name="inventory_info">Informacje</string>
<string name="inventory_equip">Wyekwipuj</string>
<string name="inventory_unequip">Zrezygnuj</string>
<string name="inventory_unequip">Zdejmij</string>
<string name="inventory_use">Użyj</string>
<string name="inventory_drop">Porzuć</string>
<string name="inventory_item_used">Użyłeś %1$s.</string>
@@ -345,25 +345,25 @@ W celu pobrania kodu źródłowego i opisu gry odwiedź stronę projektu: &lt;a
<string name="bulkselection_sell_confirmation">Czy jesteś pewien że chcesz sprzedać %1$s? Ten przedmiot jest %2$s i możliwe jest, że już nigdy go nie odzyskasz.</string>
<string name="skill_title_weapon_chance">Celny cios</string>
<string name="skill_title_weapon_dmg">Potężny cios</string>
<string name="skill_title_barter">Kupiec</string>
<string name="skill_title_weapon_dmg">Silne uderzenie</string>
<string name="skill_title_barter">Handlarz</string>
<string name="skill_title_dodge">Unik</string>
<string name="skill_title_barkskin">Zdrewniała skóra</string>
<string name="skill_title_more_criticals">Częstsze ciosy krytyczne</string>
<string name="skill_title_better_criticals">Mocniejsze ciosy krytyczne</string>
<string name="skill_title_speed">Błyskawiczny cios</string>
<string name="skill_title_coinfinder">Poszukiwacz skarbów</string>
<string name="skill_title_more_exp">Dobry uczeń</string>
<string name="skill_title_speed">Szybkość Walki</string>
<string name="skill_title_coinfinder">Poszukiwacz Skarbów</string>
<string name="skill_title_more_exp">Dobry Uczeń</string>
<string name="skill_title_cleave">Rozłupanie</string>
<string name="skill_title_eater">Zjadacz ciał</string>
<string name="skill_title_fortitude">Zwiększony hart</string>
<string name="skill_title_eater">Zjadacz Ciał</string>
<string name="skill_title_fortitude">Zwiększona Wytrzymałość</string>
<string name="skill_title_evasion">Odskok</string>
<string name="skill_title_regeneration">Regeneracja</string>
<string name="skill_title_lower_exploss">Mistrz Upadków</string>
<string name="skill_title_magicfinder">Poszukiwacz artefaktów</string>
<string name="skill_title_resistance_mental">Silny umysł</string>
<string name="skill_title_resistance_physical_capacity">Wytrzymałe ciało</string>
<string name="skill_title_resistance_blood_disorder">Czysta krew</string>
<string name="skill_title_lower_exploss">Mistrzostwo w Porażkach</string>
<string name="skill_title_magicfinder">Poszukiwacz Artefaktów</string>
<string name="skill_title_resistance_mental">Silny Umysł</string>
<string name="skill_title_resistance_physical_capacity">Wytrzymałe Ciało</string>
<string name="skill_title_resistance_blood_disorder">Czysta Krew</string>
<string name="skill_shortdescription_weapon_chance">Zwiększa szansę trafienia.</string>
<string name="skill_shortdescription_weapon_dmg">Zwiększa zadawane obrażenia.</string>
@@ -522,7 +522,7 @@ W celu pobrania kodu źródłowego i opisu gry odwiedź stronę projektu: &lt;a
<string name="heroinfo_useitem_cost">Koszt użycia przedmiotu (PA):</string>
<string name="combat_result_monstermoved">%1$s przemieszcza się.</string>
<string name="combat_log_title">Dziennik walki</string>
<string name="localize_resources_from_mo_filename">pl.po</string>
<string name="localize_resources_from_mo_filename"></string>
<string name="conversation_reward_quest_finished">[Zadanie ukończone: \"%1$s\"]</string>
<string name="conversation_reward_quest_updated">[Zaktualizowano zadanie: \"%1$s\"]</string>
@@ -616,4 +616,80 @@ Każdy poziom umiejętności podnosi szansę trafienia broni o %1$d %% (licząc
<string name="combat_miss_animation_message">PUDŁO</string>
</resources>
<string name="dialog_recenter">Wyśrodkuj ponownie</string>
<string name="dialog_more">Więcej</string>
<string name="dialog_monsterencounter_conditions">Warunki</string>
<string name="heroinfo_skill_categories">Kategorie</string>
<string name="heroinfo_skill_sort">Sortowanie</string>
<string name="heroinfo_inventory_categories">Kategorie</string>
<string name="heroinfo_inventory_sort">Sortuj według</string>
<string name="heroinfo_healthpoints">Punkty życia (HP):</string>
<string name="heroinfo_experiencepoints">Punkty doświadczenia (XP):</string>
<string name="combat_taunt_monster">Szydzisz %1$s!</string>
<string name="combat_condition_player_apply">Jesteś dotknięty %1$s.</string>
<string name="combat_condition_player_clear">Jesteś oczyszczony z %1$s.</string>
<string name="combat_condition_player_immune">Jesteś teraz odporny na %1$s.</string>
<string name="combat_condition_monster_apply">%2$s wpływa na %1$s.</string>
<string name="combat_condition_monster_clear">%2$s przestał wpływać na %1$s.</string>
<string name="combat_condition_monster_immune">%1$s jest teraz odporny na %2$s.</string>
<string name="startscreen_newgame_start">Start gry</string>
<string name="startscreen_selectherosprite">Wybierz swojego bohatera</string>
<string name="shop_item_sort">Rodzaj</string>
<string name="actorcondition_info_immunity">Odporność na %1$s</string>
<string name="iteminfo_effect_works_on_attacker">Na atakującego</string>
<string name="iteminfo_effect_works_when_hit_by_attacker">Kiedy uderzony przez atakującego</string>
<string name="iteminfo_effect_works_when_killed_by_attacker">Kiedy zabity przez atakującego</string>
<string name="inventory_selectitem">Wybierz przedmiot do przydzielenia</string>
<string name="combat_log_noentries">Nie ma jeszcze wpisów.</string>
<string name="inventory_category_all">Dodane w 0.7.2</string>
<string name="inventory_category_favorites">Ulubione</string>
<string name="inventory_category_weapons">Broń</string>
<string name="inventory_category_armor">Zbroja</string>
<string name="inventory_category_usable">Jadalny</string>
<string name="inventory_category_quest">Przedmiot do zadania</string>
<string name="inventory_category_other">Inne</string>
<string name="inventory_sort_custom">Nieposortowany</string>
<string name="inventory_sort_name">Nazwa</string>
<string name="inventory_sort_price">Cena</string>
<string name="inventory_sort_quantity">Ilość</string>
<string name="inventory_sort_rarity">Rzadkość</string>
<string name="inventory_sort_type">Typ</string>
<string name="shoplist_sort_custom">Nieposortowany</string>
<string name="shoplist_sort_name">Nazwa</string>
<string name="shoplist_sort_price">Cena</string>
<string name="shoplist_sort_quantity">Ilość</string>
<string name="shoplist_sort_rarity">Rzadkość</string>
<string name="shoplist_sort_type">Typ</string>
<string name="skill_category_all">Wszystkie</string>
<string name="skill_category_offense">Ofensywa</string>
<string name="skill_category_defense">Defensywa</string>
<string name="skill_category_criticals">Krytyki</string>
<string name="skill_category_immunity">Odporność</string>
<string name="skill_category_utility">Użyteczność</string>
<string name="skill_category_speciality">Specjalizacja</string>
<string name="skill_category_proficiency">Wyszkolenie</string>
<string name="skill_sort_unsorted">Nieposortowane</string>
<string name="skill_sort_name">Nazwa</string>
<string name="skill_sort_points">Punkty</string>
<string name="skill_sort_unlocked">Odblokowany</string>
<string name="preferences_display_theme_title">Motyw</string>
<string name="preferences_display_theme">Wybierz motyw UI. (Wymagane ponowne uruchomienie gry)</string>
<string name="preferences_display_theme_blue">Kobalt</string>
<string name="preferences_display_theme_green">Malachit</string>
<string name="preferences_display_theme_charcoal">Obsydian</string>
<string name="change_theme_requires_restart">Zmiana motywu UI wymaga restartu.
\nAndor\'s Trail został zamknięty.</string>
</resources>

View File

@@ -160,13 +160,13 @@
<string name="about_button3">Лицензия</string>
<string name="about_contents3">" Это бесплатное приложение; вы можете изменять ее и модифицировать согласно правилам GNU General Public License изданными Free Software Foundation; либо лицензии версии 2, либо (на ваше усмотрение) более поздней версией. &lt;br /&gt; &lt;br /&gt; Игра создана с надеждой что она будет интересна, но БЕЗ ВСЯКИХ ГАРАНТИЙ; даже без подразумеваемых гарантии ТОВАРНОЙ ПРИГОДНОСТИ или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Смотрите GNU General Public License для больших подробностей.&lt;br /&gt; &lt;br /&gt; Вы принимаете условия GNU General Public License вместе с установкой этой программы; если нет, смотрите &lt;a href=http://www.gnu.org/licenses&gt;http://www.gnu.org/licenses&lt;/a&gt;&lt;br /&gt; &lt;br /&gt; За исходным кодом и пожеланиями, пожалуйста, посетите страницу проекта на &lt;a href=https://github.com/Zukero/andors-trail/&gt;https://github.com/Zukero/andors-trail/&lt;/a&gt;&lt;br /&gt; "</string>
<string name="dialog_newversion_title">Приветствуем</string>
<string name="dialog_newversion_message">"Спасибо за загрузку игры След Эндора!
\n
\n\tЗапомните, игра находится в СТАДИИ РАЗРАБОТКИ, это означает что не все карты еще закончены.
\n
\n\tПожалуйста, посетите форум проекта, чтобы получить более подробную информацию или внести свой вклад в проект (см. Об игре).
\n
\n\tСпасибо всем за отзывы! "</string>
<string name="dialog_newversion_message">Спасибо за загрузку игры След Эндора!
\n
\n\tЗапомните, игра находится в СТАДИИ РАЗРАБОТКИ, это означает что не все карты еще закончены.
\n
\n\tПожалуйста, посетите форум проекта, чтобы получить более подробную информацию или внести свой вклад в проект (см. Об игре).
\n
\n\tСпасибо всем за отзывы!</string>
<string name="questlog_includecompleted_prompt">Выберите квесты для отображения</string>
<string name="questlog_includecompleted_hidecompleted">Скрыть завершенные квесты</string>

View File

@@ -195,7 +195,7 @@
</layer>
<layer name="Above" width="22" height="8">
<data encoding="base64" compression="zlib">
eJxjYMAE+ySxCJII7hBhBkjNXRzqYOLIakBsfHoodds7Sez2kgpA+tDD8B0V3I0LwMy+QyJNS7dsBOJNNLIDBGB+AADatiUc
eJxjYMAE+ySxCJII7hBhBkjNXUnsau9KoqqBsZH51HAbMvudJHZ7SQUgfehh+I4K7sYF3iGFIyk0Ld2yEYg30cgOEID5AQCq7CcG
</data>
</layer>
<layer name="Walkable" width="22" height="8">

View File

@@ -1,5 +1,7 @@
package com.gpl.rpg.AndorsTrail;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import android.app.Activity;
@@ -7,24 +9,26 @@ import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Environment;
import android.view.Window;
import android.view.WindowManager;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.Constants;
public final class AndorsTrailApplication extends Application {
public static final boolean DEVELOPMENT_DEBUGRESOURCES = false;
public static final boolean DEVELOPMENT_FORCE_STARTNEWGAME = false;
public static final boolean DEVELOPMENT_FORCE_CONTINUEGAME = false;
public static final boolean DEVELOPMENT_DEBUGBUTTONS = true;
public static final boolean DEVELOPMENT_DEBUGBUTTONS = false;
public static final boolean DEVELOPMENT_FASTSPEED = false;
public static final boolean DEVELOPMENT_VALIDATEDATA = true;
public static final boolean DEVELOPMENT_DEBUGMESSAGES = true;
public static final boolean DEVELOPMENT_INCOMPATIBLE_SAVEGAMES = true; //DEVELOPMENT_DEBUGRESOURCES || DEVELOPMENT_DEBUGBUTTONS || DEVELOPMENT_FASTSPEED;
public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? 999 : 43;
public static final String CURRENT_VERSION_DISPLAY = "0.7.2_alpha1";
public static final String CURRENT_VERSION_DISPLAY = "0.7.2_beta1";
public static final boolean IS_RELEASE_VERSION = !CURRENT_VERSION_DISPLAY.matches(".*[a-d].*");
private final AndorsTrailPreferences preferences = new AndorsTrailPreferences();
@@ -69,4 +73,58 @@ public final class AndorsTrailApplication extends Application {
this.getResources().updateConfiguration(conf, res.getDisplayMetrics());
return true;
}
/**
* Logging to text file system as found on https://stackoverflow.com/questions/19565685/saving-logcat-to-a-text-file-in-android-device
*/
public void onCreate() {
super.onCreate();
if ( DEVELOPMENT_DEBUGMESSAGES && isExternalStorageWritable() ) {
File root = Environment.getExternalStorageDirectory();
File appDirectory = new File(root, Constants.FILENAME_SAVEGAME_DIRECTORY);
File logDirectory = new File( appDirectory, "log" );
File logFile = new File( logDirectory, "logcat" + System.currentTimeMillis() + ".txt" );
// create app folder
if ( !appDirectory.exists() ) {
appDirectory.mkdir();
}
// create log folder
if ( !logDirectory.exists() ) {
logDirectory.mkdir();
}
// clear the previous logcat and then write the new one to the file
try {
Process process = Runtime.getRuntime().exec("logcat -c");
process = Runtime.getRuntime().exec("logcat -f " + logFile+" *:W");
} catch ( IOException e ) {
e.printStackTrace();
}
}
}
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if ( Environment.MEDIA_MOUNTED.equals( state ) ) {
return true;
}
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if ( Environment.MEDIA_MOUNTED.equals( state ) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals( state ) ) {
return true;
}
return false;
}
}

View File

@@ -1,174 +1,176 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.TextView;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.WorldSetup;
import com.gpl.rpg.AndorsTrail.WorldSetup.OnResourcesLoadedListener;
import com.gpl.rpg.AndorsTrail.WorldSetup.OnSceneLoadedListener;
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CloudsAnimatorView;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
public final class LoadingActivity extends Activity implements OnResourcesLoadedListener, OnSceneLoadedListener {
private WorldSetup setup;
private Dialog progressDialog;
private CloudsAnimatorView clouds_back, clouds_mid, clouds_front;
boolean loaded = false;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getBaseTheme());
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
app.setWindowParameters(this);
setContentView(R.layout.startscreen);
TextView tv = (TextView) findViewById(R.id.startscreen_version);
tv.setVisibility(View.GONE);
clouds_back = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_back);
if (clouds_back != null) clouds_back.setCloudsCountAndLayer(40, CloudsAnimatorView.Layer.below);
clouds_mid = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_mid);
if (clouds_mid != null) clouds_mid.setCloudsCountAndLayer(15, CloudsAnimatorView.Layer.center);
clouds_front = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_front);
if (clouds_front != null) clouds_front.setCloudsCountAndLayer(8, CloudsAnimatorView.Layer.above);
this.setup = app.getWorldSetup();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
((AnimationDrawable)((ImageView)findViewById(R.id.title_logo)).getDrawable()).start();
ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
int ivWidth = iv.getWidth();
int drawableWidth = iv.getDrawable().getIntrinsicWidth();
float ratio = ((float)ivWidth) / ((float)drawableWidth);
if (clouds_back != null) {
clouds_back.setScalingRatio(ratio);
}
if (clouds_mid != null) {
clouds_mid.setScalingRatio(ratio);
}
if (clouds_front != null) {
clouds_front.setScalingRatio(ratio);
}
if (progressDialog == null) {
progressDialog = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_message),
getResources().getDrawable(R.drawable.loading_anim), null, null, false, false);
synchronized (progressDialog) {
if (!loaded) {
progressDialog.setOwnerActivity(this);
CustomDialogFactory.show(progressDialog);
}
}
}
}
}
@Override
public void onResume() {
super.onResume();
setup.setOnResourcesLoadedListener(this);
final ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
iv.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
float[] point = new float[]{0f,0.25f * iv.getDrawable().getIntrinsicHeight()};
iv.getImageMatrix().mapPoints(point);
int imgY = (int) (iv.getTop() + point[1]);
if (clouds_back != null) {
clouds_back.setYMax(imgY);
}
if (clouds_mid != null) {
clouds_mid.setYMax(imgY);
}
if (clouds_front != null) {
clouds_front.setYMax(imgY);
}
iv.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
if (clouds_back != null)clouds_back.resumeAnimation();
if (clouds_mid != null)clouds_mid.resumeAnimation();
if (clouds_front != null)clouds_front.resumeAnimation();
}
@Override
public void onPause() {
super.onPause();
setup.setOnResourcesLoadedListener(null);
setup.removeOnSceneLoadedListener(this);
if (clouds_back != null)clouds_back.pauseAnimation();
if (clouds_mid != null)clouds_mid.pauseAnimation();
if (clouds_front != null)clouds_front.pauseAnimation();
}
@Override
public void onResourcesLoaded() {
loaded = false;
setup.startCharacterSetup(this);
}
@Override
public void onSceneLoaded() {
synchronized (progressDialog) {
if (progressDialog != null) progressDialog.dismiss();
loaded =true;
}
startActivity(new Intent(this, MainActivity.class));
this.finish();
}
@Override
public void onSceneLoadFailed(Savegames.LoadSavegameResult loadResult) {
synchronized (progressDialog) {
if (progressDialog != null) progressDialog.dismiss();
loaded =true;
}
if (loadResult == Savegames.LoadSavegameResult.savegameIsFromAFutureVersion) {
showLoadingFailedDialog(R.string.dialog_loading_failed_incorrectversion);
} else {
showLoadingFailedDialog(R.string.dialog_loading_failed_message);
}
}
private void showLoadingFailedDialog(int messageResourceID) {
final Dialog d = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_failed_title), null, getResources().getString(messageResourceID), null, true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
CustomDialogFactory.setDismissListener(d, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
LoadingActivity.this.finish();
}
});
CustomDialogFactory.show(d);
}
}
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.TextView;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.WorldSetup;
import com.gpl.rpg.AndorsTrail.WorldSetup.OnResourcesLoadedListener;
import com.gpl.rpg.AndorsTrail.WorldSetup.OnSceneLoadedListener;
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CloudsAnimatorView;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
public final class LoadingActivity extends Activity implements OnResourcesLoadedListener, OnSceneLoadedListener {
private WorldSetup setup;
private Dialog progressDialog;
private CloudsAnimatorView clouds_back, clouds_mid, clouds_front;
boolean loaded = false;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getBaseTheme());
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
app.setWindowParameters(this);
setContentView(R.layout.startscreen);
TextView tv = (TextView) findViewById(R.id.startscreen_version);
tv.setVisibility(View.GONE);
clouds_back = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_back);
if (clouds_back != null) clouds_back.setCloudsCountAndLayer(40, CloudsAnimatorView.Layer.below);
clouds_mid = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_mid);
if (clouds_mid != null) clouds_mid.setCloudsCountAndLayer(15, CloudsAnimatorView.Layer.center);
clouds_front = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_front);
if (clouds_front != null) clouds_front.setCloudsCountAndLayer(8, CloudsAnimatorView.Layer.above);
this.setup = app.getWorldSetup();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
((AnimationDrawable)((ImageView)findViewById(R.id.title_logo)).getDrawable()).start();
ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
int ivWidth = iv.getWidth();
int drawableWidth = iv.getDrawable().getIntrinsicWidth();
float ratio = ((float)ivWidth) / ((float)drawableWidth);
if (clouds_back != null) {
clouds_back.setScalingRatio(ratio);
}
if (clouds_mid != null) {
clouds_mid.setScalingRatio(ratio);
}
if (clouds_front != null) {
clouds_front.setScalingRatio(ratio);
}
if (progressDialog == null) {
progressDialog = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_message),
getResources().getDrawable(R.drawable.loading_anim), null, null, false, false);
synchronized (progressDialog) {
if (!loaded) {
progressDialog.setOwnerActivity(this);
CustomDialogFactory.show(progressDialog);
}
}
}
}
}
@Override
public void onResume() {
super.onResume();
setup.setOnResourcesLoadedListener(this);
final ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
iv.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
float[] point = new float[]{0f,0.25f * iv.getDrawable().getIntrinsicHeight()};
iv.getImageMatrix().mapPoints(point);
int imgY = (int) (iv.getTop() + point[1]);
if (clouds_back != null) {
clouds_back.setYMax(imgY);
}
if (clouds_mid != null) {
clouds_mid.setYMax(imgY);
}
if (clouds_front != null) {
clouds_front.setYMax(imgY);
}
iv.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
if (clouds_back != null)clouds_back.resumeAnimation();
if (clouds_mid != null)clouds_mid.resumeAnimation();
if (clouds_front != null)clouds_front.resumeAnimation();
}
@Override
public void onPause() {
super.onPause();
setup.setOnResourcesLoadedListener(null);
setup.removeOnSceneLoadedListener(this);
if (clouds_back != null)clouds_back.pauseAnimation();
if (clouds_mid != null)clouds_mid.pauseAnimation();
if (clouds_front != null)clouds_front.pauseAnimation();
}
@Override
public void onResourcesLoaded() {
loaded = false;
setup.startCharacterSetup(this);
}
@Override
public void onSceneLoaded() {
if (progressDialog != null) {
synchronized (progressDialog) {
if (progressDialog != null) progressDialog.dismiss();
loaded =true;
}
}
startActivity(new Intent(this, MainActivity.class));
this.finish();
}
@Override
public void onSceneLoadFailed(Savegames.LoadSavegameResult loadResult) {
synchronized (progressDialog) {
if (progressDialog != null) progressDialog.dismiss();
loaded =true;
}
if (loadResult == Savegames.LoadSavegameResult.savegameIsFromAFutureVersion) {
showLoadingFailedDialog(R.string.dialog_loading_failed_incorrectversion);
} else {
showLoadingFailedDialog(R.string.dialog_loading_failed_message);
}
}
private void showLoadingFailedDialog(int messageResourceID) {
final Dialog d = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_failed_title), null, getResources().getString(messageResourceID), null, true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
CustomDialogFactory.setDismissListener(d, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
LoadingActivity.this.finish();
}
});
CustomDialogFactory.show(d);
}
}

View File

@@ -1,203 +1,203 @@
package com.gpl.rpg.AndorsTrail.model.map;
import java.util.Collection;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.Size;
public final class LayeredTileMap {
private static final ColorFilter colorFilterBlack20 = createGrayScaleColorFilter(0.8f);
private static final ColorFilter colorFilterBlack40 = createGrayScaleColorFilter(0.6f);
private static final ColorFilter colorFilterBlack60 = createGrayScaleColorFilter(0.4f);
private static final ColorFilter colorFilterBlack80 = createGrayScaleColorFilter(0.2f);
private static final ColorFilter colorFilterInvert = createInvertColorFilter();
private static final ColorFilter colorFilterBW = createBWColorFilter();
private static final ColorFilter colorFilterRedTint = createRedTintColorFilter();
private static final ColorFilter colorFilterGreenTint = createGreenTintColorFilter();
private static final ColorFilter colorFilterBlueTint = createBlueTintColorFilter();
public enum ColorFilterId {
none,
black20,
black40,
black60,
black80,
invert,
bw,
redtint,
greentint,
bluetint
}
private final Size size;
public final MapSection currentLayout;
private String currentLayoutHash;
public final ReplaceableMapSection[] replacements;
public final ColorFilterId originalColorFilter;
public ColorFilterId colorFilter;
public final Collection<Integer> usedTileIDs;
public LayeredTileMap(
Size size
, MapSection layout
, ReplaceableMapSection[] replacements
, ColorFilterId colorFilter
, Collection<Integer> usedTileIDs
) {
this.size = size;
this.currentLayout = layout;
this.replacements = replacements;
this.originalColorFilter = colorFilter;
colorFilter = originalColorFilter;
this.usedTileIDs = usedTileIDs;
this.currentLayoutHash = currentLayout.calculateHash(colorFilter.name());
}
public final boolean isWalkable(final Coord p) {
if (isOutside(p.x, p.y)) return false;
return currentLayout.isWalkable[p.x][p.y];
}
public final boolean isWalkable(final int x, final int y) {
if (isOutside(x, y)) return false;
return currentLayout.isWalkable[x][y];
}
public final boolean isWalkable(final CoordRect p) {
for (int y = 0; y < p.size.height; ++y) {
for (int x = 0; x < p.size.width; ++x) {
if (!isWalkable(p.topLeft.x + x, p.topLeft.y + y)) return false;
}
}
return true;
}
public final boolean isOutside(final Coord p) { return isOutside(p.x, p.y); }
public final boolean isOutside(final int x, final int y) {
if (x < 0) return true;
if (y < 0) return true;
if (x >= size.width) return true;
if (y >= size.height) return true;
return false;
}
public final boolean isOutside(final CoordRect area) {
if (isOutside(area.topLeft)) return true;
if (area.topLeft.x + area.size.width > size.width) return true;
if (area.topLeft.y + area.size.height > size.height) return true;
return false;
}
public void setColorFilter(Paint mPaint) {
mPaint.setColorFilter(getColorFilter());
}
public ColorFilter getColorFilter() {
if (colorFilter == null) return null;
switch (colorFilter) {
case black20:
return colorFilterBlack20;
case black40:
return colorFilterBlack40;
case black60:
return colorFilterBlack60;
case black80:
return colorFilterBlack80;
case invert:
return colorFilterInvert;
case bw:
return colorFilterBW;
case redtint:
return colorFilterRedTint;
case greentint:
return colorFilterGreenTint;
case bluetint:
return colorFilterBlueTint;
default:
return null;
}
}
private static ColorMatrixColorFilter createGrayScaleColorFilter(float blackOpacity) {
final float f = blackOpacity;
return new ColorMatrixColorFilter(new float[] {
f, 0.00f, 0.00f, 0.0f, 0.0f,
0.00f, f, 0.00f, 0.0f, 0.0f,
0.00f, 0.00f, f, 0.0f, 0.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
private static ColorMatrixColorFilter createInvertColorFilter() {
return new ColorMatrixColorFilter(new float[] {
-1.00f, 0.00f, 0.00f, 0.0f, 255.0f,
0.00f, -1.00f, 0.00f, 0.0f, 255.0f,
0.00f, 0.00f, -1.00f, 0.0f, 255.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
private static ColorMatrixColorFilter createBWColorFilter() {
return new ColorMatrixColorFilter(new float[] {
0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
private static ColorMatrixColorFilter createRedTintColorFilter() {
return new ColorMatrixColorFilter(new float[] {
1.20f, 0.20f, 0.20f, 0.0f, 25.0f,
0.00f, 0.80f, 0.00f, 0.0f, 0.0f,
0.00f, 0.00f, 0.80f, 0.0f, 0.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
private static ColorMatrixColorFilter createGreenTintColorFilter() {
return new ColorMatrixColorFilter(new float[] {
0.85f, 0.00f, 0.00f, 0.0f, 0.0f,
0.15f, 1.15f, 0.15f, 0.0f, 15.0f,
0.00f, 0.00f, 0.85f, 0.0f, 0.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
private static ColorMatrixColorFilter createBlueTintColorFilter() {
return new ColorMatrixColorFilter(new float[] {
0.70f, 0.00f, 0.00f, 0.0f, 0.0f,
0.00f, 0.70f, 0.00f, 0.0f, 0.0f,
0.30f, 0.30f, 1.30f, 0.0f, 40.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
public String getCurrentLayoutHash() {
return currentLayoutHash;
}
public void applyReplacement(ReplaceableMapSection replacement) {
replacement.apply(currentLayout);
currentLayoutHash = currentLayout.calculateHash(colorFilter.name());
}
public void changeColorFilter(ColorFilterId id) {
if (colorFilter == id) return;
colorFilter = id;
currentLayoutHash = currentLayout.calculateHash(colorFilter.name());
}
public void changeColorFilter(String idString) {
ColorFilterId id;
if (idString == null) id = originalColorFilter;
else id = ColorFilterId.valueOf(idString);
if (id != null) {
changeColorFilter(id);
}
}
}
package com.gpl.rpg.AndorsTrail.model.map;
import java.util.Collection;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.Size;
public final class LayeredTileMap {
private static final ColorFilter colorFilterBlack20 = createGrayScaleColorFilter(0.8f);
private static final ColorFilter colorFilterBlack40 = createGrayScaleColorFilter(0.6f);
private static final ColorFilter colorFilterBlack60 = createGrayScaleColorFilter(0.4f);
private static final ColorFilter colorFilterBlack80 = createGrayScaleColorFilter(0.2f);
private static final ColorFilter colorFilterInvert = createInvertColorFilter();
private static final ColorFilter colorFilterBW = createBWColorFilter();
private static final ColorFilter colorFilterRedTint = createRedTintColorFilter();
private static final ColorFilter colorFilterGreenTint = createGreenTintColorFilter();
private static final ColorFilter colorFilterBlueTint = createBlueTintColorFilter();
public enum ColorFilterId {
none,
black20,
black40,
black60,
black80,
invert,
bw,
redtint,
greentint,
bluetint
}
private final Size size;
public final MapSection currentLayout;
private String currentLayoutHash;
public final ReplaceableMapSection[] replacements;
public final ColorFilterId originalColorFilter;
public ColorFilterId colorFilter;
public final Collection<Integer> usedTileIDs;
public LayeredTileMap(
Size size
, MapSection layout
, ReplaceableMapSection[] replacements
, ColorFilterId colorFilter
, Collection<Integer> usedTileIDs
) {
this.size = size;
this.currentLayout = layout;
this.replacements = replacements;
this.originalColorFilter = colorFilter;
colorFilter = originalColorFilter;
this.usedTileIDs = usedTileIDs;
this.currentLayoutHash = currentLayout.calculateHash(colorFilter.name());
}
public final boolean isWalkable(final Coord p) {
if (isOutside(p.x, p.y)) return false;
return currentLayout.isWalkable[p.x][p.y];
}
public final boolean isWalkable(final int x, final int y) {
if (isOutside(x, y)) return false;
return currentLayout.isWalkable[x][y];
}
public final boolean isWalkable(final CoordRect p) {
for (int y = 0; y < p.size.height; ++y) {
for (int x = 0; x < p.size.width; ++x) {
if (!isWalkable(p.topLeft.x + x, p.topLeft.y + y)) return false;
}
}
return true;
}
public final boolean isOutside(final Coord p) { return isOutside(p.x, p.y); }
public final boolean isOutside(final int x, final int y) {
if (x < 0) return true;
if (y < 0) return true;
if (x >= size.width) return true;
if (y >= size.height) return true;
return false;
}
public final boolean isOutside(final CoordRect area) {
if (isOutside(area.topLeft)) return true;
if (area.topLeft.x + area.size.width > size.width) return true;
if (area.topLeft.y + area.size.height > size.height) return true;
return false;
}
public void setColorFilter(Paint mPaint) {
mPaint.setColorFilter(getColorFilter());
}
public ColorFilter getColorFilter() {
if (colorFilter == null) return null;
switch (colorFilter) {
case black20:
return colorFilterBlack20;
case black40:
return colorFilterBlack40;
case black60:
return colorFilterBlack60;
case black80:
return colorFilterBlack80;
case invert:
return colorFilterInvert;
case bw:
return colorFilterBW;
case redtint:
return colorFilterRedTint;
case greentint:
return colorFilterGreenTint;
case bluetint:
return colorFilterBlueTint;
default:
return null;
}
}
private static ColorMatrixColorFilter createGrayScaleColorFilter(float blackOpacity) {
final float f = blackOpacity;
return new ColorMatrixColorFilter(new float[] {
f, 0.00f, 0.00f, 0.0f, 0.0f,
0.00f, f, 0.00f, 0.0f, 0.0f,
0.00f, 0.00f, f, 0.0f, 0.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
private static ColorMatrixColorFilter createInvertColorFilter() {
return new ColorMatrixColorFilter(new float[] {
-1.00f, 0.00f, 0.00f, 0.0f, 255.0f,
0.00f, -1.00f, 0.00f, 0.0f, 255.0f,
0.00f, 0.00f, -1.00f, 0.0f, 255.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
private static ColorMatrixColorFilter createBWColorFilter() {
return new ColorMatrixColorFilter(new float[] {
0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
private static ColorMatrixColorFilter createRedTintColorFilter() {
return new ColorMatrixColorFilter(new float[] {
1.20f, 0.20f, 0.20f, 0.0f, 25.0f,
0.00f, 0.80f, 0.00f, 0.0f, 0.0f,
0.00f, 0.00f, 0.80f, 0.0f, 0.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
private static ColorMatrixColorFilter createGreenTintColorFilter() {
return new ColorMatrixColorFilter(new float[] {
0.85f, 0.00f, 0.00f, 0.0f, 0.0f,
0.15f, 1.15f, 0.15f, 0.0f, 15.0f,
0.00f, 0.00f, 0.85f, 0.0f, 0.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
private static ColorMatrixColorFilter createBlueTintColorFilter() {
return new ColorMatrixColorFilter(new float[] {
0.70f, 0.00f, 0.00f, 0.0f, 0.0f,
0.00f, 0.70f, 0.00f, 0.0f, 0.0f,
0.30f, 0.30f, 1.30f, 0.0f, 40.0f,
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
});
}
public String getCurrentLayoutHash() {
return currentLayoutHash;
}
public void applyReplacement(ReplaceableMapSection replacement) {
replacement.apply(currentLayout);
currentLayoutHash = currentLayout.calculateHash(colorFilter == ColorFilterId.none ? null : colorFilter.name());
}
public void changeColorFilter(ColorFilterId id) {
if (colorFilter == id) return;
colorFilter = id;
currentLayoutHash = currentLayout.calculateHash(colorFilter == ColorFilterId.none ? null : colorFilter.name());
}
public void changeColorFilter(String idString) {
ColorFilterId id;
if (idString == null) id = originalColorFilter;
else id = ColorFilterId.valueOf(idString);
if (id != null) {
changeColorFilter(id);
}
}
}

View File

@@ -1,59 +1,59 @@
package com.gpl.rpg.AndorsTrail.model.map;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
public final class MapSection {
public final MapLayer layerGround;
public final MapLayer layerObjects;
public final MapLayer layerAbove;
public final MapLayer layerTop;
public final boolean[][] isWalkable;
private final byte[] layoutHash;
public MapSection(
MapLayer layerGround
, MapLayer layerObjects
, MapLayer layerAbove
, MapLayer layerTop
, boolean[][] isWalkable
, byte[] layoutHash
) {
this.layerGround = layerGround;
this.layerObjects = layerObjects;
this.layerAbove = layerAbove;
this.layerTop = layerTop;
this.isWalkable = isWalkable;
this.layoutHash = layoutHash;
}
public void replaceLayerContentsWith(final MapSection replaceLayersWith, final CoordRect replacementArea) {
replaceTileLayerSection(layerGround, replaceLayersWith.layerGround, replacementArea);
replaceTileLayerSection(layerObjects, replaceLayersWith.layerObjects, replacementArea);
replaceTileLayerSection(layerAbove, replaceLayersWith.layerAbove, replacementArea);
replaceTileLayerSection(layerTop, replaceLayersWith.layerTop, replacementArea);
if (replaceLayersWith.isWalkable != null) {
final int dy = replacementArea.topLeft.y;
final int height = replacementArea.size.height;
for (int sx = 0, dx = replacementArea.topLeft.x; sx < replacementArea.size.width; ++sx, ++dx) {
System.arraycopy(replaceLayersWith.isWalkable[sx], 0, isWalkable[dx], dy, height);
}
}
ByteUtils.xorArray(layoutHash, replaceLayersWith.layoutHash);
}
private static void replaceTileLayerSection(MapLayer dest, MapLayer src, CoordRect area) {
if (src == null) return;
final int dy = area.topLeft.y;
final int height = area.size.height;
for (int sx = 0, dx = area.topLeft.x; sx < area.size.width; ++sx, ++dx) {
System.arraycopy(src.tiles[sx], 0, dest.tiles[dx], dy, height);
}
}
public String calculateHash(String filter) {
byte[] hash = layoutHash.clone();
ByteUtils.xorArray(hash, filter.getBytes());
return ByteUtils.toHexString(hash, 4);
}
}
package com.gpl.rpg.AndorsTrail.model.map;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
public final class MapSection {
public final MapLayer layerGround;
public final MapLayer layerObjects;
public final MapLayer layerAbove;
public final MapLayer layerTop;
public final boolean[][] isWalkable;
private final byte[] layoutHash;
public MapSection(
MapLayer layerGround
, MapLayer layerObjects
, MapLayer layerAbove
, MapLayer layerTop
, boolean[][] isWalkable
, byte[] layoutHash
) {
this.layerGround = layerGround;
this.layerObjects = layerObjects;
this.layerAbove = layerAbove;
this.layerTop = layerTop;
this.isWalkable = isWalkable;
this.layoutHash = layoutHash;
}
public void replaceLayerContentsWith(final MapSection replaceLayersWith, final CoordRect replacementArea) {
replaceTileLayerSection(layerGround, replaceLayersWith.layerGround, replacementArea);
replaceTileLayerSection(layerObjects, replaceLayersWith.layerObjects, replacementArea);
replaceTileLayerSection(layerAbove, replaceLayersWith.layerAbove, replacementArea);
replaceTileLayerSection(layerTop, replaceLayersWith.layerTop, replacementArea);
if (replaceLayersWith.isWalkable != null) {
final int dy = replacementArea.topLeft.y;
final int height = replacementArea.size.height;
for (int sx = 0, dx = replacementArea.topLeft.x; sx < replacementArea.size.width; ++sx, ++dx) {
System.arraycopy(replaceLayersWith.isWalkable[sx], 0, isWalkable[dx], dy, height);
}
}
ByteUtils.xorArray(layoutHash, replaceLayersWith.layoutHash);
}
private static void replaceTileLayerSection(MapLayer dest, MapLayer src, CoordRect area) {
if (src == null) return;
final int dy = area.topLeft.y;
final int height = area.size.height;
for (int sx = 0, dx = area.topLeft.x; sx < area.size.width; ++sx, ++dx) {
System.arraycopy(src.tiles[sx], 0, dest.tiles[dx], dy, height);
}
}
public String calculateHash(String filter) {
byte[] hash = layoutHash.clone();
if (filter != null) ByteUtils.xorArray(hash, filter.getBytes());
return ByteUtils.toHexString(hash, 4);
}
}

View File

@@ -1,474 +1,475 @@
package com.gpl.rpg.AndorsTrail.model.map;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import android.content.res.Resources;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.model.actor.MonsterType;
import com.gpl.rpg.AndorsTrail.model.actor.MonsterTypeCollection;
import com.gpl.rpg.AndorsTrail.model.item.DropList;
import com.gpl.rpg.AndorsTrail.model.item.DropListCollection;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXLayer;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXLayerMap;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXMap;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXObject;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXObjectGroup;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXObjectMap;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXProperty;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXTileSet;
import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
import com.gpl.rpg.AndorsTrail.model.script.Requirement;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCache;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.L;
import com.gpl.rpg.AndorsTrail.util.Range;
import com.gpl.rpg.AndorsTrail.util.Size;
public final class TMXMapTranslator {
private final ArrayList<TMXObjectMap> maps = new ArrayList<TMXObjectMap>();
public void read(Resources r, int xmlResourceId, String name) {
maps.add(TMXMapFileParser.readObjectMap(r, xmlResourceId, name));
}
public static LayeredTileMap readLayeredTileMap(Resources res, TileCache tileCache, PredefinedMap map) {
TMXLayerMap resultMap = TMXMapFileParser.readLayerMap(res, map.xmlResourceId, map.name);
return transformMap(resultMap, tileCache);
}
public ArrayList<PredefinedMap> transformMaps(MonsterTypeCollection monsterTypes, DropListCollection dropLists) {
return transformMaps(maps, monsterTypes, dropLists);
}
public ArrayList<PredefinedMap> transformMaps(Collection<TMXObjectMap> maps, MonsterTypeCollection monsterTypes, DropListCollection dropLists) {
ArrayList<PredefinedMap> result = new ArrayList<PredefinedMap>();
for (TMXObjectMap m : maps) {
assert(m.name != null);
assert(m.name.length() > 0);
assert(m.width > 0);
assert(m.height > 0);
boolean isOutdoors = false;
for (TMXProperty p : m.properties) {
if(p.name.equalsIgnoreCase("outdoors")) isOutdoors = (Integer.parseInt(p.value) != 0);
else if(AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) L.log("OPTIMIZE: Map " + m.name + " has unrecognized property \"" + p.name + "\".");
}
final Size mapSize = new Size(m.width, m.height);
List<MapObject> mapObjects = new LinkedList<MapObject>();
List<MonsterSpawnArea> spawnAreas = new LinkedList<MonsterSpawnArea>();
List<String> activeGroups = new LinkedList<String>();
for (TMXObjectGroup group : m.objectGroups) {
boolean active = true;
for (TMXProperty p : group.properties) {
if (p.name.equalsIgnoreCase("active")) {
active = Boolean.parseBoolean(p.value);
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", group " + group.name + " has unrecognized property \"" + p.name + "\".");
}
}
if (active) {
activeGroups.add(group.name);
}
for (TMXObject object : group.objects) {
final CoordRect position = getTMXObjectPosition(object, m);
final Coord topLeft = position.topLeft;
if (object.type == null) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA)
L.log("WARNING: Map " + m.name + ", object \"" + object.name + "\"@" + topLeft.toString() + " has null type.");
} else if (object.type.equalsIgnoreCase("sign")) {
String phraseID = object.name;
for (TMXProperty p : object.properties) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) L.log("OPTIMIZE: Map " + m.name + ", sign " + object.name + "@" + topLeft.toString() + " has unrecognized property \"" + p.name + "\".");
}
mapObjects.add(MapObject.createMapSignEvent(position, phraseID, group.name));
} else if (object.type.equalsIgnoreCase("mapchange")) {
String map = null;
String place = null;
for (TMXProperty p : object.properties) {
if (p.name.equalsIgnoreCase("map")) {
map = p.value;
} else if (p.name.equalsIgnoreCase("place")) {
place = p.value;
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", mapchange " + object.name + "@" + topLeft.toString() + " has unrecognized property \"" + p.name + "\".");
}
}
mapObjects.add(MapObject.createMapChangeArea(position, object.name, map, place, group.name));
} else if (object.type.equalsIgnoreCase("spawn")) {
boolean isActiveForNewGame = true;
boolean ignoreAreas = false;
int maxQuantity = 1;
int spawnChance = 10;
String spawnGroup = object.name;
for (TMXProperty p : object.properties) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
if (p.value.equals("")) {
L.log("OPTIMIZE: Map " + m.name + ", spawn " + object.name + "@" + topLeft.toString() + " has property \"" + p.name + "\" without value.");
continue;
}
}
if (p.name.equalsIgnoreCase("quantity")) {
maxQuantity = Integer.parseInt(p.value);
} else if (p.name.equalsIgnoreCase("spawnchance")) {
spawnChance = Integer.parseInt(p.value);
} else if (p.name.equalsIgnoreCase("active")) {
isActiveForNewGame = Boolean.parseBoolean(p.value);
} else if (p.name.equalsIgnoreCase("ignoreAreas")) {
ignoreAreas = Boolean.parseBoolean(p.value);
} else if (p.name.equalsIgnoreCase("spawngroup")) {
spawnGroup = p.value;
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", spawn " + object.name + "@" + topLeft.toString() + " has unrecognized property \"" + p.name + "\".");
}
}
ArrayList<MonsterType> types = monsterTypes.getMonsterTypesFromSpawnGroup(spawnGroup);
if (types.isEmpty()) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + " contains spawn \"" + object.name + "\"@" + topLeft.toString() + " that does not correspond to any monsters. The spawn will be removed.");
}
continue;
}
String[] monsterTypeIDs = new String[types.size()];
boolean isUnique = types.get(0).isUnique;
for (int i = 0; i < monsterTypeIDs.length; ++i) {
monsterTypeIDs[i] = types.get(i).id;
}
MonsterSpawnArea area = new MonsterSpawnArea(
position
,new Range(maxQuantity, 0)
,new Range(1000, spawnChance)
,object.name
,monsterTypeIDs
,isUnique
,ignoreAreas
,group.name
,isActiveForNewGame
);
spawnAreas.add(area);
} else if (object.type.equalsIgnoreCase("key")) {
String phraseID = "";
for (TMXProperty p : object.properties) {
if (p.name.equalsIgnoreCase("phrase")) {
phraseID = p.value;
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
if (!requirementPropertiesNames.contains(p.name.toLowerCase())) {
L.log("OPTIMIZE: Map " + m.name + ", key " + object.name + "@" + topLeft.toString() + " has unrecognized property \"" + p.name + "\".");
}
}
}
Requirement req = parseRequirement(object);
mapObjects.add(MapObject.createKeyArea(position, phraseID, req, group.name));
} else if (object.type.equals("rest")) {
mapObjects.add(MapObject.createRestArea(position, object.name, group.name));
} else if (object.type.equals("container")) {
DropList dropList = dropLists.getDropList(object.name);
if (dropList == null) continue;
mapObjects.add(MapObject.createContainerArea(position, dropList, group.name));
} else if (object.type.equals("replace")) {
// Do nothing. Will be handled when reading map layers instead.
} else if (object.type.equalsIgnoreCase("script")) {
String phraseID = object.name;
MapObject.MapObjectEvaluationType evaluateWhen = MapObject.MapObjectEvaluationType.whenEntering;
for (TMXProperty p : object.properties) {
if (p.name.equalsIgnoreCase("when")) {
if (p.value.equalsIgnoreCase("enter")) {
evaluateWhen = MapObject.MapObjectEvaluationType.whenEntering;
} else if (p.value.equalsIgnoreCase("step")) {
evaluateWhen = MapObject.MapObjectEvaluationType.onEveryStep;
} else if (p.value.equalsIgnoreCase("round")) {
evaluateWhen = MapObject.MapObjectEvaluationType.afterEveryRound;
} else if (p.value.equalsIgnoreCase("always")) {
evaluateWhen = MapObject.MapObjectEvaluationType.continuously;
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", script " + object.name + "@" + topLeft.toString() + " has unrecognized value for \"when\" property: \"" + p.value + "\".");
}
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", script " + object.name + "@" + topLeft.toString() + " has unrecognized property \"" + p.name + "\".");
}
}
mapObjects.add(MapObject.createScriptArea(position, phraseID, evaluateWhen, group.name));
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", has unrecognized object type \"" + object.type + "\" for name \"" + object.name + "\".");
}
}
}
MapObject[] _eventObjects = new MapObject[mapObjects.size()];
_eventObjects = mapObjects.toArray(_eventObjects);
MonsterSpawnArea[] _spawnAreas = new MonsterSpawnArea[spawnAreas.size()];
_spawnAreas = spawnAreas.toArray(_spawnAreas);
result.add(new PredefinedMap(m.xmlResourceId, m.name, mapSize, _eventObjects, _spawnAreas, activeGroups, isOutdoors));
}
return result;
}
private static final List<String> requirementPropertiesNames = Arrays.asList(new String[]{"requireType".toLowerCase(), "requireId".toLowerCase(), "requireValue".toLowerCase(), "requireNegation".toLowerCase()});
private static Requirement parseRequirement(TMXObject object) {
Requirement.RequirementType requireType = Requirement.RequirementType.questProgress;
String requireId = null;
int requireValue = 0;
boolean requireNegation = false;
for (TMXProperty p : object.properties) {
if (p.name.equalsIgnoreCase("requireType")) {
try {
requireType = Requirement.RequirementType.valueOf(p.value);
} catch (IllegalArgumentException e) {
requireType = null;
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Unrecognized requirement type: "+p.value);
}
}
} else if (p.name.equalsIgnoreCase("requireId")) {
requireId = p.value;
} else if (p.name.equalsIgnoreCase("requireValue")) {
requireValue = Integer.parseInt(p.value);
} else if (p.name.equalsIgnoreCase("requireNegation")) {
requireNegation = Boolean.parseBoolean(p.value);
}
}
if (requireType == null) return null;
return new Requirement(requireType, requireId, requireValue, requireNegation);
}
private static CoordRect getTMXObjectPosition(TMXObject object, TMXMap m) {
final Coord topLeft = new Coord(
Math.round(((float)object.x) / m.tilewidth)
,Math.round(((float)object.y) / m.tileheight)
);
final int width = Math.round(((float)object.width) / m.tilewidth);
final int height = Math.round(((float)object.height) / m.tileheight);
return new CoordRect(topLeft, new Size(width, height));
}
private static final String LAYERNAME_GROUND = "ground";
private static final String LAYERNAME_OBJECTS = "objects";
private static final String LAYERNAME_ABOVE = "above";
private static final String LAYERNAME_TOP = "top";
private static final String LAYERNAME_WALKABLE = "walkable";
private static final String PROPNAME_FILTER = "colorfilter";
private static final SetOfLayerNames defaultLayerNames = new SetOfLayerNames(LAYERNAME_GROUND, LAYERNAME_OBJECTS, LAYERNAME_ABOVE, LAYERNAME_TOP, LAYERNAME_WALKABLE);
private static LayeredTileMap transformMap(TMXLayerMap map, TileCache tileCache) {
final Size mapSize = new Size(map.width, map.height);
LayeredTileMap.ColorFilterId colorFilter = LayeredTileMap.ColorFilterId.none;
for (TMXProperty prop : map.properties) {
if (prop.name.equalsIgnoreCase(PROPNAME_FILTER)) {
String filterId = prop.value;
if (filterId != null) {
colorFilter = LayeredTileMap.ColorFilterId.valueOf(filterId);
}
}
}
HashSet<Integer> usedTileIDs = new HashSet<Integer>();
HashMap<String, TMXLayer> layersPerLayerName = new HashMap<String, TMXLayer>();
for (TMXLayer layer : map.layers) {
String layerName = layer.name;
assert(layerName != null);
assert(layerName.length() > 0);
layerName = layerName.toLowerCase();
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
if (layersPerLayerName.containsKey(layerName)) {
L.log("WARNING: Map \"" + map.name + "\" contains multiple layers with name \"" + layerName + "\".");
}
}
layersPerLayerName.put(layerName, layer);
}
MapSection defaultLayout = transformMapSection(map,
tileCache,
new CoordRect(new Coord(0,0), mapSize),
layersPerLayerName,
usedTileIDs,
defaultLayerNames);
ArrayList<ReplaceableMapSection> replaceableSections = new ArrayList<ReplaceableMapSection>();
for (TMXObjectGroup objectGroup : map.objectGroups) {
for(TMXObject obj : objectGroup.objects) {
if ("replace".equals(obj.type)) {
final CoordRect position = getTMXObjectPosition(obj, map);
SetOfLayerNames layerNames = new SetOfLayerNames();
for (TMXProperty prop : obj.properties) {
if (prop.name.equalsIgnoreCase(LAYERNAME_GROUND)) layerNames.groundLayerName = prop.value;
else if (prop.name.equalsIgnoreCase(LAYERNAME_OBJECTS)) layerNames.objectsLayerName = prop.value;
else if (prop.name.equalsIgnoreCase(LAYERNAME_ABOVE)) layerNames.aboveLayersName = prop.value;
else if (prop.name.equalsIgnoreCase(LAYERNAME_TOP)) layerNames.topLayersName = prop.value;
else if (prop.name.equalsIgnoreCase(LAYERNAME_WALKABLE)) layerNames.walkableLayersName = prop.value;
else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
if (!requirementPropertiesNames.contains(prop.name))
L.log("OPTIMIZE: Map " + map.name + " contains replace area with unknown property \"" + prop.name + "\".");
}
}
MapSection replacementSection = transformMapSection(map, tileCache, position, layersPerLayerName, usedTileIDs, layerNames);
Requirement req = parseRequirement(obj);
if (req == null || !req.isValid()) {
QuestProgress qp = QuestProgress.parseQuestProgress(obj.name);
if (qp != null) req = new Requirement(qp);
}
if (req == null || !req.isValid()) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("WARNING: Map " + map.name + " contains replace area "+obj.name+" with unparsable requirement");
}
continue;
}
replaceableSections.add(new ReplaceableMapSection(position, replacementSection, req, objectGroup.name));
}
}
}
ReplaceableMapSection[] replaceableSections_ = null;
if (!replaceableSections.isEmpty()) {
replaceableSections_ = replaceableSections.toArray(new ReplaceableMapSection[replaceableSections.size()]);
}
return new LayeredTileMap(mapSize, defaultLayout, replaceableSections_, colorFilter, usedTileIDs);
}
private static MapSection transformMapSection(
TMXLayerMap srcMap,
TileCache tileCache,
CoordRect area,
HashMap<String, TMXLayer> layersPerLayerName,
HashSet<Integer> usedTileIDs,
SetOfLayerNames layerNames
) {
final MapLayer layerGround = transformMapLayer(layersPerLayerName, layerNames.groundLayerName, srcMap, tileCache, area, usedTileIDs);
final MapLayer layerObjects = transformMapLayer(layersPerLayerName, layerNames.objectsLayerName, srcMap, tileCache, area, usedTileIDs);
final MapLayer layerAbove = transformMapLayer(layersPerLayerName, layerNames.aboveLayersName, srcMap, tileCache, area, usedTileIDs);
final MapLayer layerTop = transformMapLayer(layersPerLayerName, layerNames.topLayersName, srcMap, tileCache, area, usedTileIDs);
boolean[][] isWalkable = transformWalkableMapLayer(findLayer(layersPerLayerName, layerNames.walkableLayersName, srcMap.name), area);
byte[] layoutHash = calculateLayoutHash(srcMap, layersPerLayerName, layerNames);
return new MapSection(layerGround, layerObjects, layerAbove, layerTop, isWalkable, layoutHash);
}
private static TMXLayer findLayer(HashMap<String, TMXLayer> layersPerLayerName, String layerName, String mapName) {
if (layerName == null) return null;
if (layerName.length() == 0) return null;
TMXLayer result = layersPerLayerName.get(layerName.toLowerCase());
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
if (result == null) {
L.log("WARNING: Cannot find maplayer \"" + layerName + "\" requested by map \"" + mapName + "\".");
}
}
return result;
}
private static MapLayer transformMapLayer(
HashMap<String, TMXLayer> layersPerLayerName,
String layerName,
TMXLayerMap srcMap,
TileCache tileCache,
CoordRect area,
HashSet<Integer> usedTileIDs
) {
TMXLayer srcLayer = findLayer(layersPerLayerName, layerName, srcMap.name);
if (srcLayer == null) return null;
final MapLayer result = new MapLayer(area.size);
Tile tile = new Tile();
for (int dy = 0, sy = area.topLeft.y; dy < area.size.height; ++dy, ++sy) {
for (int dx = 0, sx = area.topLeft.x; dx < area.size.width; ++dx, ++sx) {
int gid = srcLayer.gids[sx][sy];
if (gid <= 0) continue;
if (!getTile(srcMap, gid, tile)) continue;
int tileID = tileCache.getTileID(tile.tilesetName, tile.localId);
result.tiles[dx][dy] = tileID;
usedTileIDs.add(tileID);
}
}
return result;
}
private static boolean[][] transformWalkableMapLayer(TMXLayer srcLayer, CoordRect area) {
if (srcLayer == null) return null;
final boolean[][] isWalkable = new boolean[area.size.width][area.size.height];
for (int x = 0; x < area.size.width; ++x) {
Arrays.fill(isWalkable[x], true);
}
for (int dy = 0, sy = area.topLeft.y; dy < area.size.height; ++dy, ++sy) {
for (int dx = 0, sx = area.topLeft.x; dx < area.size.width; ++dx, ++sx) {
int gid = srcLayer.gids[sx][sy];
if (gid > 0) {
isWalkable[dx][dy] = false;
}
}
}
return isWalkable;
}
private static byte[] calculateLayoutHash(TMXLayerMap map, HashMap<String, TMXLayer> layersPerLayerName, SetOfLayerNames layerNames) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
digestLayer(layersPerLayerName, layerNames.groundLayerName, map, digest);
digestLayer(layersPerLayerName, layerNames.objectsLayerName, map, digest);
digestLayer(layersPerLayerName, layerNames.aboveLayersName, map, digest);
return digest.digest();
} catch (NoSuchAlgorithmException e) {
L.log("ERROR: Failed to create layout hash for map " + map.name + " : " + e.toString());
}
return new byte[0];
}
private static void digestLayer(HashMap<String, TMXLayer> layersPerLayerName, String layerName, TMXLayerMap map, MessageDigest digest) {
TMXLayer srcLayer = findLayer(layersPerLayerName, layerName, map.name);
if (srcLayer == null) return;
if (srcLayer.layoutHash == null) return;
digest.update(srcLayer.layoutHash);
}
private static boolean getTile(final TMXLayerMap map, final int gid, final Tile dest) {
for(int i = map.tileSets.length - 1; i >= 0; --i) {
TMXTileSet ts = map.tileSets[i];
if (ts.firstgid <= gid) {
dest.tilesetName = ts.name;
dest.localId = (gid - ts.firstgid);
return true;
}
}
L.log("WARNING: Cannot find tile for gid " + gid);
return false;
}
private static final class Tile {
public String tilesetName;
public int localId;
}
private static final class SetOfLayerNames {
public String groundLayerName;
public String objectsLayerName;
public String aboveLayersName;
public String topLayersName;
public String walkableLayersName;
public SetOfLayerNames() {
this.groundLayerName = null;
this.objectsLayerName = null;
this.aboveLayersName = null;
this.topLayersName = null;
this.walkableLayersName = null;
}
public SetOfLayerNames(String groundLayerName, String objectsLayerName, String aboveLayersName, String topLayersName, String walkableLayersName) {
this.groundLayerName = groundLayerName;
this.objectsLayerName = objectsLayerName;
this.aboveLayersName = aboveLayersName;
this.topLayersName = topLayersName;
this.walkableLayersName = walkableLayersName;
}
}
}
package com.gpl.rpg.AndorsTrail.model.map;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import android.content.res.Resources;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.model.actor.MonsterType;
import com.gpl.rpg.AndorsTrail.model.actor.MonsterTypeCollection;
import com.gpl.rpg.AndorsTrail.model.item.DropList;
import com.gpl.rpg.AndorsTrail.model.item.DropListCollection;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXLayer;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXLayerMap;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXMap;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXObject;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXObjectGroup;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXObjectMap;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXProperty;
import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXTileSet;
import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
import com.gpl.rpg.AndorsTrail.model.script.Requirement;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCache;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.L;
import com.gpl.rpg.AndorsTrail.util.Range;
import com.gpl.rpg.AndorsTrail.util.Size;
public final class TMXMapTranslator {
private final ArrayList<TMXObjectMap> maps = new ArrayList<TMXObjectMap>();
public void read(Resources r, int xmlResourceId, String name) {
maps.add(TMXMapFileParser.readObjectMap(r, xmlResourceId, name));
}
public static LayeredTileMap readLayeredTileMap(Resources res, TileCache tileCache, PredefinedMap map) {
TMXLayerMap resultMap = TMXMapFileParser.readLayerMap(res, map.xmlResourceId, map.name);
return transformMap(resultMap, tileCache);
}
public ArrayList<PredefinedMap> transformMaps(MonsterTypeCollection monsterTypes, DropListCollection dropLists) {
return transformMaps(maps, monsterTypes, dropLists);
}
public ArrayList<PredefinedMap> transformMaps(Collection<TMXObjectMap> maps, MonsterTypeCollection monsterTypes, DropListCollection dropLists) {
ArrayList<PredefinedMap> result = new ArrayList<PredefinedMap>();
for (TMXObjectMap m : maps) {
assert(m.name != null);
assert(m.name.length() > 0);
assert(m.width > 0);
assert(m.height > 0);
boolean isOutdoors = false;
for (TMXProperty p : m.properties) {
if(p.name.equalsIgnoreCase("outdoors")) isOutdoors = (Integer.parseInt(p.value) != 0);
else if(AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) L.log("OPTIMIZE: Map " + m.name + " has unrecognized property \"" + p.name + "\".");
}
final Size mapSize = new Size(m.width, m.height);
List<MapObject> mapObjects = new LinkedList<MapObject>();
List<MonsterSpawnArea> spawnAreas = new LinkedList<MonsterSpawnArea>();
List<String> activeGroups = new LinkedList<String>();
for (TMXObjectGroup group : m.objectGroups) {
boolean active = true;
for (TMXProperty p : group.properties) {
if (p.name.equalsIgnoreCase("active")) {
active = Boolean.parseBoolean(p.value);
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", group " + group.name + " has unrecognized property \"" + p.name + "\".");
}
}
if (active) {
activeGroups.add(group.name);
}
for (TMXObject object : group.objects) {
final CoordRect position = getTMXObjectPosition(object, m);
final Coord topLeft = position.topLeft;
if (object.type == null) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA)
L.log("WARNING: Map " + m.name + ", object \"" + object.name + "\"@" + topLeft.toString() + " has null type.");
} else if (object.type.equalsIgnoreCase("sign")) {
String phraseID = object.name;
for (TMXProperty p : object.properties) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) L.log("OPTIMIZE: Map " + m.name + ", sign " + object.name + "@" + topLeft.toString() + " has unrecognized property \"" + p.name + "\".");
}
mapObjects.add(MapObject.createMapSignEvent(position, phraseID, group.name));
} else if (object.type.equalsIgnoreCase("mapchange")) {
String map = null;
String place = null;
for (TMXProperty p : object.properties) {
if (p.name.equalsIgnoreCase("map")) {
map = p.value;
} else if (p.name.equalsIgnoreCase("place")) {
place = p.value;
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", mapchange " + object.name + "@" + topLeft.toString() + " has unrecognized property \"" + p.name + "\".");
}
}
mapObjects.add(MapObject.createMapChangeArea(position, object.name, map, place, group.name));
} else if (object.type.equalsIgnoreCase("spawn")) {
boolean isActiveForNewGame = true;
boolean ignoreAreas = false;
int maxQuantity = 1;
int spawnChance = 10;
String spawnGroup = object.name;
for (TMXProperty p : object.properties) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
if (p.value.equals("")) {
L.log("OPTIMIZE: Map " + m.name + ", spawn " + object.name + "@" + topLeft.toString() + " has property \"" + p.name + "\" without value.");
continue;
}
}
if (p.name.equalsIgnoreCase("quantity")) {
maxQuantity = Integer.parseInt(p.value);
} else if (p.name.equalsIgnoreCase("spawnchance")) {
spawnChance = Integer.parseInt(p.value);
} else if (p.name.equalsIgnoreCase("active")) {
isActiveForNewGame = Boolean.parseBoolean(p.value);
} else if (p.name.equalsIgnoreCase("ignoreAreas")) {
ignoreAreas = Boolean.parseBoolean(p.value);
} else if (p.name.equalsIgnoreCase("spawngroup")) {
spawnGroup = p.value;
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", spawn " + object.name + "@" + topLeft.toString() + " has unrecognized property \"" + p.name + "\".");
}
}
ArrayList<MonsterType> types = monsterTypes.getMonsterTypesFromSpawnGroup(spawnGroup);
if (types.isEmpty()) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + " contains spawn \"" + object.name + "\"@" + topLeft.toString() + " that does not correspond to any monsters. The spawn will be removed.");
}
continue;
}
String[] monsterTypeIDs = new String[types.size()];
boolean isUnique = types.get(0).isUnique;
for (int i = 0; i < monsterTypeIDs.length; ++i) {
monsterTypeIDs[i] = types.get(i).id;
}
MonsterSpawnArea area = new MonsterSpawnArea(
position
,new Range(maxQuantity, 0)
,new Range(1000, spawnChance)
,object.name
,monsterTypeIDs
,isUnique
,ignoreAreas
,group.name
,isActiveForNewGame
);
spawnAreas.add(area);
} else if (object.type.equalsIgnoreCase("key")) {
String phraseID = "";
for (TMXProperty p : object.properties) {
if (p.name.equalsIgnoreCase("phrase")) {
phraseID = p.value;
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
if (!requirementPropertiesNames.contains(p.name.toLowerCase())) {
L.log("OPTIMIZE: Map " + m.name + ", key " + object.name + "@" + topLeft.toString() + " has unrecognized property \"" + p.name + "\".");
}
}
}
Requirement req = parseRequirement(object);
mapObjects.add(MapObject.createKeyArea(position, phraseID, req, group.name));
} else if (object.type.equals("rest")) {
mapObjects.add(MapObject.createRestArea(position, object.name, group.name));
} else if (object.type.equals("container")) {
DropList dropList = dropLists.getDropList(object.name);
if (dropList == null) continue;
mapObjects.add(MapObject.createContainerArea(position, dropList, group.name));
} else if (object.type.equals("replace")) {
// Do nothing. Will be handled when reading map layers instead.
} else if (object.type.equalsIgnoreCase("script")) {
String phraseID = object.name;
MapObject.MapObjectEvaluationType evaluateWhen = MapObject.MapObjectEvaluationType.whenEntering;
for (TMXProperty p : object.properties) {
if (p.name.equalsIgnoreCase("when")) {
if (p.value.equalsIgnoreCase("enter")) {
evaluateWhen = MapObject.MapObjectEvaluationType.whenEntering;
} else if (p.value.equalsIgnoreCase("step")) {
evaluateWhen = MapObject.MapObjectEvaluationType.onEveryStep;
} else if (p.value.equalsIgnoreCase("round")) {
evaluateWhen = MapObject.MapObjectEvaluationType.afterEveryRound;
} else if (p.value.equalsIgnoreCase("always")) {
evaluateWhen = MapObject.MapObjectEvaluationType.continuously;
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", script " + object.name + "@" + topLeft.toString() + " has unrecognized value for \"when\" property: \"" + p.value + "\".");
}
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", script " + object.name + "@" + topLeft.toString() + " has unrecognized property \"" + p.name + "\".");
}
}
mapObjects.add(MapObject.createScriptArea(position, phraseID, evaluateWhen, group.name));
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Map " + m.name + ", has unrecognized object type \"" + object.type + "\" for name \"" + object.name + "\".");
}
}
}
MapObject[] _eventObjects = new MapObject[mapObjects.size()];
_eventObjects = mapObjects.toArray(_eventObjects);
MonsterSpawnArea[] _spawnAreas = new MonsterSpawnArea[spawnAreas.size()];
_spawnAreas = spawnAreas.toArray(_spawnAreas);
result.add(new PredefinedMap(m.xmlResourceId, m.name, mapSize, _eventObjects, _spawnAreas, activeGroups, isOutdoors));
}
return result;
}
private static final List<String> requirementPropertiesNames = Arrays.asList(new String[]{"requireType".toLowerCase(), "requireId".toLowerCase(), "requireValue".toLowerCase(), "requireNegation".toLowerCase()});
private static Requirement parseRequirement(TMXObject object) {
Requirement.RequirementType requireType = Requirement.RequirementType.questProgress;
String requireId = null;
int requireValue = 0;
boolean requireNegation = false;
for (TMXProperty p : object.properties) {
if (p.name.equalsIgnoreCase("requireType")) {
try {
requireType = Requirement.RequirementType.valueOf(p.value);
} catch (IllegalArgumentException e) {
requireType = null;
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("OPTIMIZE: Unrecognized requirement type: "+p.value);
}
}
} else if (p.name.equalsIgnoreCase("requireId")) {
requireId = p.value;
} else if (p.name.equalsIgnoreCase("requireValue")) {
requireValue = Integer.parseInt(p.value);
} else if (p.name.equalsIgnoreCase("requireNegation")) {
requireNegation = Boolean.parseBoolean(p.value);
}
}
if (requireType == null) return null;
return new Requirement(requireType, requireId, requireValue, requireNegation);
}
private static CoordRect getTMXObjectPosition(TMXObject object, TMXMap m) {
final Coord topLeft = new Coord(
Math.round(((float)object.x) / m.tilewidth)
,Math.round(((float)object.y) / m.tileheight)
);
final int width = Math.round(((float)object.width) / m.tilewidth);
final int height = Math.round(((float)object.height) / m.tileheight);
return new CoordRect(topLeft, new Size(width, height));
}
private static final String LAYERNAME_GROUND = "ground";
private static final String LAYERNAME_OBJECTS = "objects";
private static final String LAYERNAME_ABOVE = "above";
private static final String LAYERNAME_TOP = "top";
private static final String LAYERNAME_WALKABLE = "walkable";
private static final String PROPNAME_FILTER = "colorfilter";
private static final SetOfLayerNames defaultLayerNames = new SetOfLayerNames(LAYERNAME_GROUND, LAYERNAME_OBJECTS, LAYERNAME_ABOVE, LAYERNAME_TOP, LAYERNAME_WALKABLE);
private static LayeredTileMap transformMap(TMXLayerMap map, TileCache tileCache) {
final Size mapSize = new Size(map.width, map.height);
LayeredTileMap.ColorFilterId colorFilter = LayeredTileMap.ColorFilterId.none;
for (TMXProperty prop : map.properties) {
if (prop.name.equalsIgnoreCase(PROPNAME_FILTER)) {
String filterId = prop.value;
if (filterId != null) {
colorFilter = LayeredTileMap.ColorFilterId.valueOf(filterId);
}
}
}
HashSet<Integer> usedTileIDs = new HashSet<Integer>();
HashMap<String, TMXLayer> layersPerLayerName = new HashMap<String, TMXLayer>();
for (TMXLayer layer : map.layers) {
String layerName = layer.name;
assert(layerName != null);
assert(layerName.length() > 0);
layerName = layerName.toLowerCase();
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
if (layersPerLayerName.containsKey(layerName)) {
L.log("WARNING: Map \"" + map.name + "\" contains multiple layers with name \"" + layerName + "\".");
}
}
layersPerLayerName.put(layerName, layer);
}
MapSection defaultLayout = transformMapSection(map,
tileCache,
new CoordRect(new Coord(0,0), mapSize),
layersPerLayerName,
usedTileIDs,
defaultLayerNames);
ArrayList<ReplaceableMapSection> replaceableSections = new ArrayList<ReplaceableMapSection>();
for (TMXObjectGroup objectGroup : map.objectGroups) {
for(TMXObject obj : objectGroup.objects) {
if ("replace".equals(obj.type)) {
final CoordRect position = getTMXObjectPosition(obj, map);
SetOfLayerNames layerNames = new SetOfLayerNames();
for (TMXProperty prop : obj.properties) {
if (prop.name.equalsIgnoreCase(LAYERNAME_GROUND)) layerNames.groundLayerName = prop.value;
else if (prop.name.equalsIgnoreCase(LAYERNAME_OBJECTS)) layerNames.objectsLayerName = prop.value;
else if (prop.name.equalsIgnoreCase(LAYERNAME_ABOVE)) layerNames.aboveLayersName = prop.value;
else if (prop.name.equalsIgnoreCase(LAYERNAME_TOP)) layerNames.topLayersName = prop.value;
else if (prop.name.equalsIgnoreCase(LAYERNAME_WALKABLE)) layerNames.walkableLayersName = prop.value;
else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
if (!requirementPropertiesNames.contains(prop.name))
L.log("OPTIMIZE: Map " + map.name + " contains replace area with unknown property \"" + prop.name + "\".");
}
}
MapSection replacementSection = transformMapSection(map, tileCache, position, layersPerLayerName, usedTileIDs, layerNames);
Requirement req = parseRequirement(obj);
if (req == null || !req.isValid()) {
QuestProgress qp = QuestProgress.parseQuestProgress(obj.name);
if (qp != null) req = new Requirement(qp);
}
if (req == null || !req.isValid()) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
L.log("WARNING: Map " + map.name + " contains replace area "+obj.name+" with unparsable requirement");
}
continue;
}
replaceableSections.add(new ReplaceableMapSection(position, replacementSection, req, objectGroup.name));
}
}
}
ReplaceableMapSection[] replaceableSections_ = null;
if (!replaceableSections.isEmpty()) {
replaceableSections_ = replaceableSections.toArray(new ReplaceableMapSection[replaceableSections.size()]);
}
return new LayeredTileMap(mapSize, defaultLayout, replaceableSections_, colorFilter, usedTileIDs);
}
private static MapSection transformMapSection(
TMXLayerMap srcMap,
TileCache tileCache,
CoordRect area,
HashMap<String, TMXLayer> layersPerLayerName,
HashSet<Integer> usedTileIDs,
SetOfLayerNames layerNames
) {
final MapLayer layerGround = transformMapLayer(layersPerLayerName, layerNames.groundLayerName, srcMap, tileCache, area, usedTileIDs);
final MapLayer layerObjects = transformMapLayer(layersPerLayerName, layerNames.objectsLayerName, srcMap, tileCache, area, usedTileIDs);
final MapLayer layerAbove = transformMapLayer(layersPerLayerName, layerNames.aboveLayersName, srcMap, tileCache, area, usedTileIDs);
final MapLayer layerTop = transformMapLayer(layersPerLayerName, layerNames.topLayersName, srcMap, tileCache, area, usedTileIDs);
boolean[][] isWalkable = transformWalkableMapLayer(findLayer(layersPerLayerName, layerNames.walkableLayersName, srcMap.name), area);
byte[] layoutHash = calculateLayoutHash(srcMap, layersPerLayerName, layerNames);
return new MapSection(layerGround, layerObjects, layerAbove, layerTop, isWalkable, layoutHash);
}
private static TMXLayer findLayer(HashMap<String, TMXLayer> layersPerLayerName, String layerName, String mapName) {
if (layerName == null) return null;
if (layerName.length() == 0) return null;
TMXLayer result = layersPerLayerName.get(layerName.toLowerCase());
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
if (result == null) {
L.log("WARNING: Cannot find maplayer \"" + layerName + "\" requested by map \"" + mapName + "\".");
}
}
return result;
}
private static MapLayer transformMapLayer(
HashMap<String, TMXLayer> layersPerLayerName,
String layerName,
TMXLayerMap srcMap,
TileCache tileCache,
CoordRect area,
HashSet<Integer> usedTileIDs
) {
TMXLayer srcLayer = findLayer(layersPerLayerName, layerName, srcMap.name);
if (srcLayer == null) return null;
final MapLayer result = new MapLayer(area.size);
Tile tile = new Tile();
for (int dy = 0, sy = area.topLeft.y; dy < area.size.height; ++dy, ++sy) {
for (int dx = 0, sx = area.topLeft.x; dx < area.size.width; ++dx, ++sx) {
int gid = srcLayer.gids[sx][sy];
if (gid <= 0) continue;
if (!getTile(srcMap, gid, tile)) continue;
int tileID = tileCache.getTileID(tile.tilesetName, tile.localId);
result.tiles[dx][dy] = tileID;
usedTileIDs.add(tileID);
}
}
return result;
}
private static boolean[][] transformWalkableMapLayer(TMXLayer srcLayer, CoordRect area) {
if (srcLayer == null) return null;
final boolean[][] isWalkable = new boolean[area.size.width][area.size.height];
for (int x = 0; x < area.size.width; ++x) {
Arrays.fill(isWalkable[x], true);
}
for (int dy = 0, sy = area.topLeft.y; dy < area.size.height; ++dy, ++sy) {
for (int dx = 0, sx = area.topLeft.x; dx < area.size.width; ++dx, ++sx) {
int gid = srcLayer.gids[sx][sy];
if (gid > 0) {
isWalkable[dx][dy] = false;
}
}
}
return isWalkable;
}
private static byte[] calculateLayoutHash(TMXLayerMap map, HashMap<String, TMXLayer> layersPerLayerName, SetOfLayerNames layerNames) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
digestLayer(layersPerLayerName, layerNames.groundLayerName, map, digest);
digestLayer(layersPerLayerName, layerNames.objectsLayerName, map, digest);
digestLayer(layersPerLayerName, layerNames.aboveLayersName, map, digest);
digestLayer(layersPerLayerName, layerNames.topLayersName, map, digest);
return digest.digest();
} catch (NoSuchAlgorithmException e) {
L.log("ERROR: Failed to create layout hash for map " + map.name + " : " + e.toString());
}
return new byte[0];
}
private static void digestLayer(HashMap<String, TMXLayer> layersPerLayerName, String layerName, TMXLayerMap map, MessageDigest digest) {
TMXLayer srcLayer = findLayer(layersPerLayerName, layerName, map.name);
if (srcLayer == null) return;
if (srcLayer.layoutHash == null) return;
digest.update(srcLayer.layoutHash);
}
private static boolean getTile(final TMXLayerMap map, final int gid, final Tile dest) {
for(int i = map.tileSets.length - 1; i >= 0; --i) {
TMXTileSet ts = map.tileSets[i];
if (ts.firstgid <= gid) {
dest.tilesetName = ts.name;
dest.localId = (gid - ts.firstgid);
return true;
}
}
L.log("WARNING: Cannot find tile for gid " + gid);
return false;
}
private static final class Tile {
public String tilesetName;
public int localId;
}
private static final class SetOfLayerNames {
public String groundLayerName;
public String objectsLayerName;
public String aboveLayersName;
public String topLayersName;
public String walkableLayersName;
public SetOfLayerNames() {
this.groundLayerName = null;
this.objectsLayerName = null;
this.aboveLayersName = null;
this.topLayersName = null;
this.walkableLayersName = null;
}
public SetOfLayerNames(String groundLayerName, String objectsLayerName, String aboveLayersName, String topLayersName, String walkableLayersName) {
this.groundLayerName = groundLayerName;
this.objectsLayerName = objectsLayerName;
this.aboveLayersName = aboveLayersName;
this.topLayersName = topLayersName;
this.walkableLayersName = walkableLayersName;
}
}
}