Skip to content

Commit 0dcc4d0

Browse files
authored
Merge pull request #214 from mathsman5133/feature/th16-content
Feature/th16 content
2 parents 4a2cc3b + 63e4315 commit 0dcc4d0

19 files changed

+40356
-421364
lines changed

coc/abc.py

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ def __init__(self, data, townhall):
171171

172172
self._townhall = townhall
173173

174+
# copies for a static hash
175+
self.__name = data['name']
176+
self.__level = data['level']
177+
self.__village = data['village']
178+
self.__is_active = data.get("superTroopIsActive")
179+
174180
def __repr__(self):
175181
attrs = [
176182
("name", self.name),
@@ -180,20 +186,27 @@ def __repr__(self):
180186
return "<%s %s>" % (
181187
self.__class__.__name__, " ".join("%s=%r" % t for t in attrs),)
182188

189+
def __eq__(self, other):
190+
return self.name == other.name and self.level == other.level \
191+
and self.village == other.village and self.is_active == other.is_active
192+
193+
def __hash__(self):
194+
return hash((self.__name, self.__level, self.__village, self.__is_active))
195+
183196
@classmethod
184-
def _load_json_meta(cls, troop_meta, id, name, lab_to_townhall):
197+
def _load_json_meta(cls, json_meta, id, name, lab_to_townhall):
185198
cls.id = int(id)
186199
cls.name = name
187200
cls.lab_to_townhall = lab_to_townhall
188201

189-
cls.range = try_enum(UnitStat, troop_meta.get("AttackRange"))
190-
cls.dps = try_enum(UnitStat, troop_meta.get("DPS"))
191-
cls.ground_target = _get_maybe_first(troop_meta, "GroundTargets",
202+
cls.range = try_enum(UnitStat, json_meta.get("AttackRange"))
203+
cls.dps = try_enum(UnitStat, json_meta.get("DPS"))
204+
cls.ground_target = _get_maybe_first(json_meta, "GroundTargets",
192205
default=True)
193-
cls.hitpoints = try_enum(UnitStat, troop_meta.get("Hitpoints"))
206+
cls.hitpoints = try_enum(UnitStat, json_meta.get("Hitpoints"))
194207

195208
# get production building
196-
production_building = troop_meta.get("ProductionBuilding", [None])[0] if troop_meta.get("ProductionBuilding") else None
209+
production_building = json_meta.get("ProductionBuilding", [None])[0] if json_meta.get("ProductionBuilding") else None
197210
if production_building == "Barrack":
198211
cls.is_elixir_troop = True
199212
elif production_building == "Dark Elixir Barrack":
@@ -213,16 +226,16 @@ def _load_json_meta(cls, troop_meta, id, name, lab_to_townhall):
213226

214227
# without production_building, it is a hero
215228
if not production_building:
216-
laboratory_levels = troop_meta.get("LaboratoryLevel")
229+
laboratory_levels = json_meta.get("LaboratoryLevel")
217230
else:
218231
# it is a troop or spell or siege
219232
prod_unit = buildings.get(production_building)
220233
if production_building in ("SiegeWorkshop", "Spell Forge", "Mini Spell Factory",
221234
"Dark Elixir Barrack", "Barrack", "Barrack2"):
222-
min_prod_unit_level = troop_meta.get("BarrackLevel", [None, ])[0]
235+
min_prod_unit_level = json_meta.get("BarrackLevel", [None, ])[0]
223236
# there are some special troops, which have no BarrackLevel attribute
224237
if not min_prod_unit_level:
225-
laboratory_levels = troop_meta.get("LaboratoryLevel")
238+
laboratory_levels = json_meta.get("LaboratoryLevel")
226239
else:
227240
# get the min th level were we can unlock by the required level of the production building
228241
min_th_level = [th for i, th in
@@ -235,10 +248,10 @@ def _load_json_meta(cls, troop_meta, id, name, lab_to_townhall):
235248
# the first_lab_level is the lowest possible (there are some inconsistencies with siege machines)
236249
# To handle them properly, replacing all lab_level lower than first_lab_level with first_lab_level
237250
laboratory_levels = []
238-
for lab_level in troop_meta.get("LaboratoryLevel"):
251+
for lab_level in json_meta.get("LaboratoryLevel"):
239252
laboratory_levels.append(max(lab_level, first_lab_level))
240253
elif production_building == "Pet Shop":
241-
min_prod_unit_level = troop_meta.get("LaboratoryLevel", [None, ])[0]
254+
min_prod_unit_level = json_meta.get("LaboratoryLevel", [None, ])[0]
242255
# there are some special troops, which have no BarrackLevel attribute
243256

244257
# get the min th level were we can unlock by the required level of the production building
@@ -252,35 +265,35 @@ def _load_json_meta(cls, troop_meta, id, name, lab_to_townhall):
252265
# the first_lab_level is the lowest possible (there are some inconsistencies with siege machines)
253266
# To handle them properly, replacing all lab_level lower than first_lab_level with first_lab_level
254267
laboratory_levels = []
255-
for lab_level in troop_meta.get("LaboratoryLevel"):
268+
for lab_level in json_meta.get("LaboratoryLevel"):
256269
laboratory_levels.append(max(lab_level, first_lab_level))
257270
else:
258271
return
259272

260273
cls.lab_level = try_enum(UnitStat, laboratory_levels)
261-
cls.housing_space = _get_maybe_first(troop_meta, "HousingSpace", default=0)
262-
cls.speed = try_enum(UnitStat, troop_meta.get("Speed"))
274+
cls.housing_space = _get_maybe_first(json_meta, "HousingSpace", default=0)
275+
cls.speed = try_enum(UnitStat, json_meta.get("Speed"))
263276
cls.level = cls.dps and UnitStat(range(1, len(cls.dps) + 1))
264277

265278
# all 3
266-
cls.upgrade_cost = try_enum(UnitStat, troop_meta.get("UpgradeCost"))
267-
cls.upgrade_resource = Resource(value=troop_meta["UpgradeResource"][0])
279+
cls.upgrade_cost = try_enum(UnitStat, json_meta.get("UpgradeCost"))
280+
cls.upgrade_resource = Resource(value=json_meta["UpgradeResource"][0])
268281
cls.upgrade_time = try_enum(UnitStat,
269282
[TimeDelta(hours=hours) for hours in
270-
troop_meta.get("UpgradeTimeH", [])])
271-
cls._is_home_village = False if troop_meta.get("VillageType") else True
283+
json_meta.get("UpgradeTimeH", [])])
284+
cls._is_home_village = False if json_meta.get("VillageType") else True
272285
cls.village = "home" if cls._is_home_village else "builderBase"
273286

274287
# spells and troops
275-
cls.training_cost = try_enum(UnitStat, troop_meta.get("TrainingCost"))
276-
cls.training_time = try_enum(UnitStat, troop_meta.get("TrainingTime"))
288+
cls.training_cost = try_enum(UnitStat, json_meta.get("TrainingCost"))
289+
cls.training_time = try_enum(UnitStat, json_meta.get("TrainingTime"))
277290

278291
# only heroes
279-
cls.ability_time = try_enum(UnitStat, troop_meta.get("AbilityTime"))
280-
cls.ability_troop_count = try_enum(UnitStat, troop_meta.get("AbilitySummonTroopCount"))
281-
cls.required_th_level = try_enum(UnitStat, troop_meta.get("RequiredTownHallLevel") or laboratory_levels)
292+
cls.ability_time = try_enum(UnitStat, json_meta.get("AbilityTime"))
293+
cls.ability_troop_count = try_enum(UnitStat, json_meta.get("AbilitySummonTroopCount"))
294+
cls.required_th_level = try_enum(UnitStat, json_meta.get("RequiredTownHallLevel") or laboratory_levels)
282295
cls.regeneration_time = try_enum(
283-
UnitStat, [TimeDelta(minutes=value) for value in troop_meta.get("RegenerationTimeMinutes", [])]
296+
UnitStat, [TimeDelta(minutes=value) for value in json_meta.get("RegenerationTimeMinutes", [])]
284297
)
285298

286299
cls.is_loaded = True
@@ -345,6 +358,10 @@ def _load_json(self, english_aliases, lab_to_townhall):
345358
if True in meta.get("DisableProduction", [False]) and "pets" not in str(self.FILE_PATH):
346359
continue
347360

361+
# ignore deprecated content
362+
if True in meta.get("Deprecated", [False]):
363+
continue
364+
348365
#hacky but the aliases convert so that isnt great
349366
IGNORED_PETS = ["Unused", "PhoenixEgg"]
350367
if "pets" in str(self.FILE_PATH) and supercell_name in IGNORED_PETS:

coc/client.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
from .errors import Forbidden, GatewayError, NotFound, PrivateWarLog
3636
from .enums import WarRound
3737
from .miscmodels import BaseLeague, GoldPassSeason, Label, League, Location, LoadGameData
38-
from .hero import HeroHolder, PetHolder
38+
from .hero import HeroHolder, PetHolder, EquipmentHolder
3939
from .http import HTTPClient, BasicThrottler, BatchThrottler
4040
from .iterators import (
4141
PlayerIterator,
@@ -173,6 +173,7 @@ class Client:
173173
"_spell_holder",
174174
"_hero_holder",
175175
"_pet_holder",
176+
"_equipment_holder"
176177
)
177178

178179
def __init__(
@@ -249,25 +250,31 @@ def _load_holders(self):
249250
with open(BUILDING_FILE_PATH) as fp:
250251
buildings = ujson.load(fp)
251252

253+
# defaults for if loading fails
254+
lab_to_townhall = {i - 2: i for i in range(1, 17)}
255+
smithy_to_townhall = {i - 7: i for i in range(8, 17)}
256+
252257
for supercell_name, data in buildings.items():
253258
if supercell_name == "Laboratory":
254259
lab_to_townhall = {index: th_level for index, th_level in enumerate(data["TownHallLevel"], start=1)}
255260
# there are troops with no lab ...
256261
lab_to_townhall[-1] = 1
257262
lab_to_townhall[0] = 2
258-
break
259-
else:
260-
# if the files failed to load, fallback to the old formula of lab level = TH level - 2
261-
lab_to_townhall = {i-2: i for i in range(1, 15)}
263+
elif supercell_name =='Smithy':
264+
smithy_to_townhall = {index: th_level for index, th_level in enumerate(data["TownHallLevel"], start=1)}
262265

266+
# load holders tied to the lab
263267
for holder in (self._troop_holder, self._spell_holder, self._hero_holder, self._pet_holder):
264268
holder._load_json(english_aliases, lab_to_townhall)
269+
# load holders tied to the smithy
270+
self._equipment_holder._load_json(english_aliases, smithy_to_townhall)
265271

266272
def _create_holders(self):
267-
self._troop_holder, self._spell_holder, self._hero_holder, self._pet_holder = TroopHolder(), \
268-
SpellHolder(), \
269-
HeroHolder(), \
270-
PetHolder()
273+
self._troop_holder = TroopHolder()
274+
self._spell_holder = SpellHolder()
275+
self._hero_holder = HeroHolder()
276+
self._pet_holder = PetHolder()
277+
self._equipment_holder = EquipmentHolder()
271278

272279
if not self.load_game_data.never:
273280
self._load_holders()

coc/enums.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ class Resource(Enum):
7777
builder_elixir = "Elixir2"
7878
dark_elixir = "DarkElixir"
7979
gold = "Gold"
80+
builder_gold = "Gold2"
81+
shiny_ore = "CommonOre"
82+
glowy_ore = "RareOre"
83+
starry_ore = "EpicOre"
8084

8185

8286
HOME_TROOP_ORDER = [
@@ -105,7 +109,8 @@ class Resource(Enum):
105109
"Bowler",
106110
"Ice Golem",
107111
"Headhunter",
108-
"Apprentice Warden"
112+
"Apprentice Warden",
113+
"Root Rider",
109114
]
110115

111116
SIEGE_MACHINE_ORDER = [
@@ -186,6 +191,24 @@ class Resource(Enum):
186191
"Diggy",
187192
"Poison Lizard",
188193
"Phoenix",
194+
"Spirit Fox"
195+
]
196+
197+
EQUIPMENT = [
198+
"Barbarian Puppet",
199+
"Rage Vial",
200+
"Archer Puppet",
201+
"Invisibility Vial",
202+
"Eternal Tome",
203+
"Life Gem",
204+
"Seeking Shield",
205+
"Royal Gem",
206+
"Earthquake Boots",
207+
"Vampstache",
208+
"Giant Arrow",
209+
"Healer Puppet",
210+
"Rage Gem",
211+
"Healing Tome"
189212
]
190213

191214
ACHIEVEMENT_ORDER = [

0 commit comments

Comments
 (0)