mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Stardew Valley: Refactor Animals to use Content Packs (#4320)
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Dict, Iterable, Set, Any, Mapping, Type, Tuple, Union
|
from typing import Iterable, Set, Any, Mapping, Type, Tuple, Union
|
||||||
|
|
||||||
from .feature import booksanity, cropsanity, fishsanity, friendsanity, skill_progression, building_progression, tool_progression
|
from .feature import booksanity, cropsanity, fishsanity, friendsanity, skill_progression, building_progression, tool_progression
|
||||||
|
from ..data.animal import Animal
|
||||||
from ..data.building import Building
|
from ..data.building import Building
|
||||||
from ..data.fish_data import FishItem
|
from ..data.fish_data import FishItem
|
||||||
from ..data.game_item import GameItem, Source, ItemTag
|
from ..data.game_item import GameItem, Source, ItemTag
|
||||||
@@ -18,12 +19,13 @@ class StardewContent:
|
|||||||
|
|
||||||
# regions -> To be used with can reach rule
|
# regions -> To be used with can reach rule
|
||||||
|
|
||||||
game_items: Dict[str, GameItem] = field(default_factory=dict)
|
game_items: dict[str, GameItem] = field(default_factory=dict)
|
||||||
fishes: Dict[str, FishItem] = field(default_factory=dict)
|
fishes: dict[str, FishItem] = field(default_factory=dict)
|
||||||
villagers: Dict[str, Villager] = field(default_factory=dict)
|
villagers: dict[str, Villager] = field(default_factory=dict)
|
||||||
farm_buildings: Dict[str, Building] = field(default_factory=dict)
|
farm_buildings: dict[str, Building] = field(default_factory=dict)
|
||||||
skills: Dict[str, Skill] = field(default_factory=dict)
|
animals: dict[str, Animal] = field(default_factory=dict)
|
||||||
quests: Dict[str, Any] = field(default_factory=dict)
|
skills: dict[str, Skill] = field(default_factory=dict)
|
||||||
|
quests: dict[str, Any] = field(default_factory=dict)
|
||||||
|
|
||||||
def find_sources_of_type(self, types: Union[Type[Source], Tuple[Type[Source]]]) -> Iterable[Source]:
|
def find_sources_of_type(self, types: Union[Type[Source], Tuple[Type[Source]]]) -> Iterable[Source]:
|
||||||
for item in self.game_items.values():
|
for item in self.game_items.values():
|
||||||
@@ -109,6 +111,11 @@ class ContentPack:
|
|||||||
def farm_building_hook(self, content: StardewContent):
|
def farm_building_hook(self, content: StardewContent):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
animals: Iterable[Animal] = ()
|
||||||
|
|
||||||
|
def animal_hook(self, content: StardewContent):
|
||||||
|
...
|
||||||
|
|
||||||
skills: Iterable[Skill] = ()
|
skills: Iterable[Skill] = ()
|
||||||
|
|
||||||
def skill_hook(self, content: StardewContent):
|
def skill_hook(self, content: StardewContent):
|
||||||
|
@@ -65,6 +65,10 @@ def register_pack(content: StardewContent, pack: ContentPack):
|
|||||||
content.farm_buildings[building.name] = building
|
content.farm_buildings[building.name] = building
|
||||||
pack.farm_building_hook(content)
|
pack.farm_building_hook(content)
|
||||||
|
|
||||||
|
for animal in pack.animals:
|
||||||
|
content.animals[animal.name] = animal
|
||||||
|
pack.animal_hook(content)
|
||||||
|
|
||||||
for skill in pack.skills:
|
for skill in pack.skills:
|
||||||
content.skills[skill.name] = skill
|
content.skills[skill.name] = skill
|
||||||
pack.skill_hook(content)
|
pack.skill_hook(content)
|
||||||
|
@@ -1,15 +1,19 @@
|
|||||||
from .pelican_town import pelican_town as pelican_town_content_pack
|
from .pelican_town import pelican_town as pelican_town_content_pack
|
||||||
from ..game_content import ContentPack, StardewContent
|
from ..game_content import ContentPack, StardewContent
|
||||||
from ...data import villagers_data, fish_data
|
from ...data import villagers_data, fish_data
|
||||||
from ...data.game_item import ItemTag, Tag
|
from ...data.animal import Animal, AnimalName, OstrichIncubatorSource
|
||||||
|
from ...data.game_item import ItemTag, Tag, CustomRuleSource
|
||||||
from ...data.harvest import ForagingSource, HarvestFruitTreeSource, HarvestCropSource
|
from ...data.harvest import ForagingSource, HarvestFruitTreeSource, HarvestCropSource
|
||||||
from ...data.requirement import WalnutRequirement
|
from ...data.requirement import WalnutRequirement
|
||||||
from ...data.shop import ShopSource
|
from ...data.shop import ShopSource
|
||||||
|
from ...strings.animal_product_names import AnimalProduct
|
||||||
from ...strings.book_names import Book
|
from ...strings.book_names import Book
|
||||||
|
from ...strings.building_names import Building
|
||||||
from ...strings.crop_names import Fruit, Vegetable
|
from ...strings.crop_names import Fruit, Vegetable
|
||||||
from ...strings.fish_names import Fish
|
from ...strings.fish_names import Fish
|
||||||
from ...strings.forageable_names import Forageable, Mushroom
|
from ...strings.forageable_names import Forageable, Mushroom
|
||||||
from ...strings.fruit_tree_names import Sapling
|
from ...strings.fruit_tree_names import Sapling
|
||||||
|
from ...strings.generic_names import Generic
|
||||||
from ...strings.metal_names import Fossil, Mineral
|
from ...strings.metal_names import Fossil, Mineral
|
||||||
from ...strings.region_names import Region, LogicRegion
|
from ...strings.region_names import Region, LogicRegion
|
||||||
from ...strings.season_names import Season
|
from ...strings.season_names import Season
|
||||||
@@ -51,6 +55,13 @@ ginger_island_content_pack = GingerIslandContentPack(
|
|||||||
Vegetable.taro_root: (HarvestCropSource(seed=Seed.taro, seasons=(Season.summer,)),),
|
Vegetable.taro_root: (HarvestCropSource(seed=Seed.taro, seasons=(Season.summer,)),),
|
||||||
Fruit.pineapple: (HarvestCropSource(seed=Seed.pineapple, seasons=(Season.summer,)),),
|
Fruit.pineapple: (HarvestCropSource(seed=Seed.pineapple, seasons=(Season.summer,)),),
|
||||||
|
|
||||||
|
# Temporary animal stuff, will be moved once animal products are properly content-packed
|
||||||
|
AnimalProduct.ostrich_egg_starter: (CustomRuleSource(lambda logic: logic.tool.can_forage(Generic.any, Region.island_north, True)
|
||||||
|
& logic.has(Forageable.journal_scrap)
|
||||||
|
& logic.region.can_reach(Region.volcano_floor_5)),),
|
||||||
|
AnimalProduct.ostrich_egg: (CustomRuleSource(lambda logic: logic.has(AnimalProduct.ostrich_egg_starter)
|
||||||
|
| logic.animal.has_animal(AnimalName.ostrich)),),
|
||||||
|
|
||||||
},
|
},
|
||||||
shop_sources={
|
shop_sources={
|
||||||
Seed.taro: (ShopSource(items_price=((2, Fossil.bone_fragment),), shop_region=Region.island_trader),),
|
Seed.taro: (ShopSource(items_price=((2, Fossil.bone_fragment),), shop_region=Region.island_trader),),
|
||||||
@@ -81,5 +92,12 @@ ginger_island_content_pack = GingerIslandContentPack(
|
|||||||
),
|
),
|
||||||
villagers=(
|
villagers=(
|
||||||
villagers_data.leo,
|
villagers_data.leo,
|
||||||
|
),
|
||||||
|
animals=(
|
||||||
|
Animal(AnimalName.ostrich,
|
||||||
|
required_building=Building.barn,
|
||||||
|
sources=(
|
||||||
|
OstrichIncubatorSource(AnimalProduct.ostrich_egg_starter),
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@@ -1,7 +1,12 @@
|
|||||||
from .pelican_town import pelican_town as pelican_town_content_pack
|
from .pelican_town import pelican_town as pelican_town_content_pack
|
||||||
from ..game_content import ContentPack
|
from ..game_content import ContentPack
|
||||||
|
from ...data.animal import IncubatorSource, Animal, AnimalName
|
||||||
from ...data.harvest import FruitBatsSource, MushroomCaveSource
|
from ...data.harvest import FruitBatsSource, MushroomCaveSource
|
||||||
|
from ...data.shop import ShopSource
|
||||||
|
from ...strings.animal_product_names import AnimalProduct
|
||||||
|
from ...strings.building_names import Building
|
||||||
from ...strings.forageable_names import Forageable, Mushroom
|
from ...strings.forageable_names import Forageable, Mushroom
|
||||||
|
from ...strings.region_names import Region
|
||||||
|
|
||||||
the_farm = ContentPack(
|
the_farm = ContentPack(
|
||||||
"The Farm (Vanilla)",
|
"The Farm (Vanilla)",
|
||||||
@@ -39,5 +44,64 @@ the_farm = ContentPack(
|
|||||||
Mushroom.red: (
|
Mushroom.red: (
|
||||||
MushroomCaveSource(),
|
MushroomCaveSource(),
|
||||||
),
|
),
|
||||||
}
|
},
|
||||||
|
animals=(
|
||||||
|
Animal(AnimalName.chicken,
|
||||||
|
required_building=Building.coop,
|
||||||
|
sources=(
|
||||||
|
ShopSource(shop_region=Region.ranch, money_price=800),
|
||||||
|
# For now there is no way to obtain the starter item, so this adds additional rules in the system for nothing.
|
||||||
|
# IncubatorSource(AnimalProduct.egg_starter)
|
||||||
|
)),
|
||||||
|
Animal(AnimalName.cow,
|
||||||
|
required_building=Building.barn,
|
||||||
|
sources=(
|
||||||
|
ShopSource(shop_region=Region.ranch, money_price=1500),
|
||||||
|
)),
|
||||||
|
Animal(AnimalName.goat,
|
||||||
|
required_building=Building.big_barn,
|
||||||
|
sources=(
|
||||||
|
ShopSource(shop_region=Region.ranch, money_price=4000),
|
||||||
|
)),
|
||||||
|
Animal(AnimalName.duck,
|
||||||
|
required_building=Building.big_coop,
|
||||||
|
sources=(
|
||||||
|
ShopSource(shop_region=Region.ranch, money_price=1200),
|
||||||
|
# For now there is no way to obtain the starter item, so this adds additional rules in the system for nothing.
|
||||||
|
# IncubatorSource(AnimalProduct.duck_egg_starter)
|
||||||
|
)),
|
||||||
|
Animal(AnimalName.sheep,
|
||||||
|
required_building=Building.deluxe_barn,
|
||||||
|
sources=(
|
||||||
|
ShopSource(shop_region=Region.ranch, money_price=8000),
|
||||||
|
)),
|
||||||
|
Animal(AnimalName.rabbit,
|
||||||
|
required_building=Building.deluxe_coop,
|
||||||
|
sources=(
|
||||||
|
ShopSource(shop_region=Region.ranch, money_price=8000),
|
||||||
|
)),
|
||||||
|
Animal(AnimalName.pig,
|
||||||
|
required_building=Building.deluxe_barn,
|
||||||
|
sources=(
|
||||||
|
ShopSource(shop_region=Region.ranch, money_price=16000),
|
||||||
|
)),
|
||||||
|
Animal(AnimalName.void_chicken,
|
||||||
|
required_building=Building.big_coop,
|
||||||
|
sources=(
|
||||||
|
IncubatorSource(AnimalProduct.void_egg_starter),
|
||||||
|
)),
|
||||||
|
Animal(AnimalName.golden_chicken,
|
||||||
|
required_building=Building.big_coop,
|
||||||
|
sources=(
|
||||||
|
IncubatorSource(AnimalProduct.golden_egg_starter),
|
||||||
|
)),
|
||||||
|
Animal(AnimalName.dinosaur,
|
||||||
|
required_building=Building.big_coop,
|
||||||
|
sources=(
|
||||||
|
# We should use the starter item here, but since the dinosaur egg is also an artifact, it's part of the museum rules
|
||||||
|
# and I do not want to touch it yet.
|
||||||
|
# IncubatorSource(AnimalProduct.dinosaur_egg_starter),
|
||||||
|
IncubatorSource(AnimalProduct.dinosaur_egg),
|
||||||
|
)),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
23
worlds/stardew_valley/data/animal.py
Normal file
23
worlds/stardew_valley/data/animal.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
from .game_item import Source
|
||||||
|
from ..strings.animal_names import Animal as AnimalName
|
||||||
|
|
||||||
|
assert AnimalName
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Animal:
|
||||||
|
name: str
|
||||||
|
required_building: str = field(kw_only=True)
|
||||||
|
sources: tuple[Source, ...] = field(kw_only=True)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class IncubatorSource(Source):
|
||||||
|
egg_item: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class OstrichIncubatorSource(Source):
|
||||||
|
egg_item: str
|
@@ -143,7 +143,7 @@ duck_egg = BundleItem(AnimalProduct.duck_egg)
|
|||||||
rabbit_foot = BundleItem(AnimalProduct.rabbit_foot)
|
rabbit_foot = BundleItem(AnimalProduct.rabbit_foot)
|
||||||
dinosaur_egg = BundleItem(AnimalProduct.dinosaur_egg)
|
dinosaur_egg = BundleItem(AnimalProduct.dinosaur_egg)
|
||||||
void_egg = BundleItem(AnimalProduct.void_egg)
|
void_egg = BundleItem(AnimalProduct.void_egg)
|
||||||
ostrich_egg = BundleItem(AnimalProduct.ostrich_egg, source=BundleItem.Sources.island, )
|
ostrich_egg = BundleItem(AnimalProduct.ostrich_egg, source=BundleItem.Sources.content)
|
||||||
golden_egg = BundleItem(AnimalProduct.golden_egg)
|
golden_egg = BundleItem(AnimalProduct.golden_egg)
|
||||||
|
|
||||||
truffle_oil = BundleItem(ArtisanGood.truffle_oil)
|
truffle_oil = BundleItem(ArtisanGood.truffle_oil)
|
||||||
@@ -832,7 +832,7 @@ calico_items = [calico_egg.as_amount(200), calico_egg.as_amount(200), calico_egg
|
|||||||
magic_rock_candy, mega_bomb.as_amount(10), mystery_box.as_amount(10), mixed_seeds.as_amount(50),
|
magic_rock_candy, mega_bomb.as_amount(10), mystery_box.as_amount(10), mixed_seeds.as_amount(50),
|
||||||
strawberry_seeds.as_amount(20),
|
strawberry_seeds.as_amount(20),
|
||||||
spicy_eel.as_amount(5), crab_cakes.as_amount(5), eggplant_parmesan.as_amount(5),
|
spicy_eel.as_amount(5), crab_cakes.as_amount(5), eggplant_parmesan.as_amount(5),
|
||||||
pumpkin_soup.as_amount(5), lucky_lunch.as_amount(5)]
|
pumpkin_soup.as_amount(5), lucky_lunch.as_amount(5) ]
|
||||||
calico_bundle = BundleTemplate(CCRoom.bulletin_board, BundleName.calico, calico_items, 2, 2)
|
calico_bundle = BundleTemplate(CCRoom.bulletin_board, BundleName.calico, calico_items, 2, 2)
|
||||||
|
|
||||||
raccoon_bundle = BundleTemplate(CCRoom.bulletin_board, BundleName.raccoon, raccoon_foraging_items, 4, 4)
|
raccoon_bundle = BundleTemplate(CCRoom.bulletin_board, BundleName.raccoon, raccoon_foraging_items, 4, 4)
|
||||||
|
@@ -3,12 +3,13 @@ from __future__ import annotations
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import List, Tuple, Union, Optional
|
from typing import List, Tuple, Union, Optional
|
||||||
|
|
||||||
from ..strings.monster_names import Monster
|
from ..strings.animal_product_names import AnimalProduct
|
||||||
from ..strings.fish_names import WaterChest
|
from ..strings.fish_names import WaterChest
|
||||||
from ..strings.forageable_names import Forageable
|
from ..strings.forageable_names import Forageable
|
||||||
from ..strings.metal_names import Mineral, Artifact, Fossil
|
|
||||||
from ..strings.region_names import Region
|
|
||||||
from ..strings.geode_names import Geode
|
from ..strings.geode_names import Geode
|
||||||
|
from ..strings.metal_names import Mineral, Artifact, Fossil
|
||||||
|
from ..strings.monster_names import Monster
|
||||||
|
from ..strings.region_names import Region
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@@ -105,7 +106,7 @@ class Artifact:
|
|||||||
geodes=(Geode.artifact_trove, WaterChest.fishing_chest))
|
geodes=(Geode.artifact_trove, WaterChest.fishing_chest))
|
||||||
ornamental_fan = create_artifact("Ornamental Fan", 7.4, (Region.beach, Region.forest, Region.town),
|
ornamental_fan = create_artifact("Ornamental Fan", 7.4, (Region.beach, Region.forest, Region.town),
|
||||||
geodes=(Geode.artifact_trove, WaterChest.fishing_chest))
|
geodes=(Geode.artifact_trove, WaterChest.fishing_chest))
|
||||||
dinosaur_egg = create_artifact("Dinosaur Egg", 11.4, (Region.skull_cavern),
|
dinosaur_egg = create_artifact(AnimalProduct.dinosaur_egg, 11.4, (Region.skull_cavern),
|
||||||
monsters=Monster.pepper_rex)
|
monsters=Monster.pepper_rex)
|
||||||
rare_disc = create_artifact("Rare Disc", 5.6, Region.stardew_valley,
|
rare_disc = create_artifact("Rare Disc", 5.6, Region.stardew_valley,
|
||||||
geodes=(Geode.artifact_trove, WaterChest.fishing_chest),
|
geodes=(Geode.artifact_trove, WaterChest.fishing_chest),
|
||||||
|
@@ -1,25 +1,15 @@
|
|||||||
from typing import Union
|
import typing
|
||||||
|
|
||||||
from .base_logic import BaseLogicMixin, BaseLogic
|
from .base_logic import BaseLogicMixin, BaseLogic
|
||||||
from .building_logic import BuildingLogicMixin
|
from ..stardew_rule import StardewRule
|
||||||
from .has_logic import HasLogicMixin
|
|
||||||
from .money_logic import MoneyLogicMixin
|
|
||||||
from ..stardew_rule import StardewRule, true_
|
|
||||||
from ..strings.animal_names import Animal, coop_animals, barn_animals
|
|
||||||
from ..strings.building_names import Building
|
from ..strings.building_names import Building
|
||||||
from ..strings.forageable_names import Forageable
|
from ..strings.forageable_names import Forageable
|
||||||
from ..strings.generic_names import Generic
|
from ..strings.machine_names import Machine
|
||||||
from ..strings.region_names import Region
|
|
||||||
|
|
||||||
cost_and_building_by_animal = {
|
if typing.TYPE_CHECKING:
|
||||||
Animal.chicken: (800, Building.coop),
|
from .logic import StardewLogic
|
||||||
Animal.cow: (1500, Building.barn),
|
else:
|
||||||
Animal.goat: (4000, Building.big_barn),
|
StardewLogic = object
|
||||||
Animal.duck: (1200, Building.big_coop),
|
|
||||||
Animal.sheep: (8000, Building.deluxe_barn),
|
|
||||||
Animal.rabbit: (8000, Building.deluxe_coop),
|
|
||||||
Animal.pig: (16000, Building.deluxe_barn)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class AnimalLogicMixin(BaseLogicMixin):
|
class AnimalLogicMixin(BaseLogicMixin):
|
||||||
@@ -28,32 +18,19 @@ class AnimalLogicMixin(BaseLogicMixin):
|
|||||||
self.animal = AnimalLogic(*args, **kwargs)
|
self.animal = AnimalLogic(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class AnimalLogic(BaseLogic[Union[HasLogicMixin, MoneyLogicMixin, BuildingLogicMixin]]):
|
class AnimalLogic(BaseLogic[StardewLogic]):
|
||||||
|
|
||||||
def can_buy_animal(self, animal: str) -> StardewRule:
|
def can_incubate(self, egg_item: str) -> StardewRule:
|
||||||
try:
|
return self.logic.building.has_building(Building.coop) & self.logic.has(egg_item)
|
||||||
price, building = cost_and_building_by_animal[animal]
|
|
||||||
except KeyError:
|
|
||||||
return true_
|
|
||||||
return self.logic.money.can_spend_at(Region.ranch, price) & self.logic.building.has_building(building)
|
|
||||||
|
|
||||||
def has_animal(self, animal: str) -> StardewRule:
|
def can_ostrich_incubate(self, egg_item: str) -> StardewRule:
|
||||||
if animal == Generic.any:
|
return self.logic.building.has_building(Building.barn) & self.logic.has(Machine.ostrich_incubator) & self.logic.has(egg_item)
|
||||||
return self.has_any_animal()
|
|
||||||
elif animal == Building.coop:
|
|
||||||
return self.has_any_coop_animal()
|
|
||||||
elif animal == Building.barn:
|
|
||||||
return self.has_any_barn_animal()
|
|
||||||
return self.logic.has(animal)
|
|
||||||
|
|
||||||
def has_happy_animal(self, animal: str) -> StardewRule:
|
def has_animal(self, animal_name: str) -> StardewRule:
|
||||||
return self.has_animal(animal) & self.logic.has(Forageable.hay)
|
animal = self.content.animals.get(animal_name)
|
||||||
|
assert animal is not None, f"Animal {animal_name} not found."
|
||||||
|
|
||||||
def has_any_animal(self) -> StardewRule:
|
return self.logic.source.has_access_to_any(animal.sources) & self.logic.building.has_building(animal.required_building)
|
||||||
return self.has_any_coop_animal() | self.has_any_barn_animal()
|
|
||||||
|
|
||||||
def has_any_coop_animal(self) -> StardewRule:
|
def has_happy_animal(self, animal_name: str) -> StardewRule:
|
||||||
return self.logic.has_any(*coop_animals)
|
return self.logic.animal.has_animal(animal_name) & self.logic.has(Forageable.hay)
|
||||||
|
|
||||||
def has_any_barn_animal(self) -> StardewRule:
|
|
||||||
return self.logic.has_any(*barn_animals)
|
|
||||||
|
@@ -17,6 +17,7 @@ from .skill_logic import SkillLogicMixin
|
|||||||
from .time_logic import TimeLogicMixin
|
from .time_logic import TimeLogicMixin
|
||||||
from ..options import FestivalLocations
|
from ..options import FestivalLocations
|
||||||
from ..stardew_rule import StardewRule
|
from ..stardew_rule import StardewRule
|
||||||
|
from ..strings.animal_product_names import AnimalProduct
|
||||||
from ..strings.book_names import Book
|
from ..strings.book_names import Book
|
||||||
from ..strings.craftable_names import Fishing
|
from ..strings.craftable_names import Fishing
|
||||||
from ..strings.crop_names import Fruit, Vegetable
|
from ..strings.crop_names import Fruit, Vegetable
|
||||||
@@ -154,18 +155,37 @@ SkillLogicMixin, RegionLogicMixin, ActionLogicMixin, MonsterLogicMixin, Relation
|
|||||||
if self.options.festival_locations != FestivalLocations.option_hard:
|
if self.options.festival_locations != FestivalLocations.option_hard:
|
||||||
return self.logic.true_
|
return self.logic.true_
|
||||||
|
|
||||||
animal_rule = self.logic.animal.has_animal(Generic.any)
|
# Other animal products are not counted in the animal product category
|
||||||
|
good_animal_products = [
|
||||||
|
AnimalProduct.duck_egg, AnimalProduct.duck_feather, AnimalProduct.egg, AnimalProduct.goat_milk, AnimalProduct.golden_egg, AnimalProduct.large_egg,
|
||||||
|
AnimalProduct.large_goat_milk, AnimalProduct.large_milk, AnimalProduct.milk, AnimalProduct.ostrich_egg, AnimalProduct.rabbit_foot,
|
||||||
|
AnimalProduct.void_egg, AnimalProduct.wool
|
||||||
|
]
|
||||||
|
if AnimalProduct.ostrich_egg not in self.content.game_items:
|
||||||
|
# When ginger island is excluded, ostrich egg is not available
|
||||||
|
good_animal_products.remove(AnimalProduct.ostrich_egg)
|
||||||
|
animal_rule = self.logic.has_any(*good_animal_products)
|
||||||
|
|
||||||
artisan_rule = self.logic.artisan.can_keg(Generic.any) | self.logic.artisan.can_preserves_jar(Generic.any)
|
artisan_rule = self.logic.artisan.can_keg(Generic.any) | self.logic.artisan.can_preserves_jar(Generic.any)
|
||||||
cooking_rule = self.logic.money.can_spend_at(Region.saloon, 220) # Salads at the bar are good enough
|
|
||||||
|
# Salads at the bar are good enough
|
||||||
|
cooking_rule = self.logic.money.can_spend_at(Region.saloon, 220)
|
||||||
|
|
||||||
fish_rule = self.logic.skill.can_fish(difficulty=50)
|
fish_rule = self.logic.skill.can_fish(difficulty=50)
|
||||||
forage_rule = self.logic.region.can_reach_any((Region.forest, Region.backwoods)) # Hazelnut always available since the grange display is in fall
|
|
||||||
mineral_rule = self.logic.action.can_open_geode(Generic.any) # More than half the minerals are good enough
|
# Hazelnut always available since the grange display is in fall
|
||||||
|
forage_rule = self.logic.region.can_reach_any((Region.forest, Region.backwoods))
|
||||||
|
|
||||||
|
# More than half the minerals are good enough
|
||||||
|
mineral_rule = self.logic.action.can_open_geode(Generic.any)
|
||||||
|
|
||||||
good_fruits = (fruit
|
good_fruits = (fruit
|
||||||
for fruit in
|
for fruit in
|
||||||
(Fruit.apple, Fruit.banana, Forageable.coconut, Forageable.crystal_fruit, Fruit.mango, Fruit.orange, Fruit.peach, Fruit.pomegranate,
|
(Fruit.apple, Fruit.banana, Forageable.coconut, Forageable.crystal_fruit, Fruit.mango, Fruit.orange, Fruit.peach, Fruit.pomegranate,
|
||||||
Fruit.strawberry, Fruit.melon, Fruit.rhubarb, Fruit.pineapple, Fruit.ancient_fruit, Fruit.starfruit)
|
Fruit.strawberry, Fruit.melon, Fruit.rhubarb, Fruit.pineapple, Fruit.ancient_fruit, Fruit.starfruit)
|
||||||
if fruit in self.content.game_items)
|
if fruit in self.content.game_items)
|
||||||
fruit_rule = self.logic.has_any(*good_fruits)
|
fruit_rule = self.logic.has_any(*good_fruits)
|
||||||
|
|
||||||
good_vegetables = (vegeteable
|
good_vegetables = (vegeteable
|
||||||
for vegeteable in
|
for vegeteable in
|
||||||
(Vegetable.amaranth, Vegetable.artichoke, Vegetable.beet, Vegetable.cauliflower, Forageable.fiddlehead_fern, Vegetable.kale,
|
(Vegetable.amaranth, Vegetable.artichoke, Vegetable.beet, Vegetable.cauliflower, Forageable.fiddlehead_fern, Vegetable.kale,
|
||||||
@@ -173,8 +193,7 @@ SkillLogicMixin, RegionLogicMixin, ActionLogicMixin, MonsterLogicMixin, Relation
|
|||||||
if vegeteable in self.content.game_items)
|
if vegeteable in self.content.game_items)
|
||||||
vegetable_rule = self.logic.has_any(*good_vegetables)
|
vegetable_rule = self.logic.has_any(*good_vegetables)
|
||||||
|
|
||||||
return animal_rule & artisan_rule & cooking_rule & fish_rule & \
|
return animal_rule & artisan_rule & cooking_rule & fish_rule & forage_rule & fruit_rule & mineral_rule & vegetable_rule
|
||||||
forage_rule & fruit_rule & mineral_rule & vegetable_rule
|
|
||||||
|
|
||||||
def can_win_fishing_competition(self) -> StardewRule:
|
def can_win_fishing_competition(self) -> StardewRule:
|
||||||
return self.logic.skill.can_fish(difficulty=60)
|
return self.logic.skill.can_fish(difficulty=60)
|
||||||
|
@@ -149,42 +149,37 @@ class StardewLogic(ReceivedLogicMixin, HasLogicMixin, RegionLogicMixin, Travelin
|
|||||||
# self.received("Deluxe Fertilizer Recipe") & self.has(MetalBar.iridium) & self.has(SVItem.sap),
|
# self.received("Deluxe Fertilizer Recipe") & self.has(MetalBar.iridium) & self.has(SVItem.sap),
|
||||||
# | (self.ability.can_cook() & self.relationship.has_hearts(NPC.emily, 3) & self.has(Forageable.leek) & self.has(Forageable.dandelion) &
|
# | (self.ability.can_cook() & self.relationship.has_hearts(NPC.emily, 3) & self.has(Forageable.leek) & self.has(Forageable.dandelion) &
|
||||||
# | (self.ability.can_cook() & self.relationship.has_hearts(NPC.jodi, 7) & self.has(AnimalProduct.cow_milk) & self.has(Ingredient.sugar)),
|
# | (self.ability.can_cook() & self.relationship.has_hearts(NPC.jodi, 7) & self.has(AnimalProduct.cow_milk) & self.has(Ingredient.sugar)),
|
||||||
Animal.chicken: self.animal.can_buy_animal(Animal.chicken),
|
|
||||||
Animal.cow: self.animal.can_buy_animal(Animal.cow),
|
|
||||||
Animal.dinosaur: self.building.has_building(Building.big_coop) & self.has(AnimalProduct.dinosaur_egg),
|
|
||||||
Animal.duck: self.animal.can_buy_animal(Animal.duck),
|
|
||||||
Animal.goat: self.animal.can_buy_animal(Animal.goat),
|
|
||||||
Animal.ostrich: self.building.has_building(Building.barn) & self.has(AnimalProduct.ostrich_egg) & self.has(Machine.ostrich_incubator),
|
|
||||||
Animal.pig: self.animal.can_buy_animal(Animal.pig),
|
|
||||||
Animal.rabbit: self.animal.can_buy_animal(Animal.rabbit),
|
|
||||||
Animal.sheep: self.animal.can_buy_animal(Animal.sheep),
|
|
||||||
AnimalProduct.any_egg: self.has_any(AnimalProduct.chicken_egg, AnimalProduct.duck_egg),
|
AnimalProduct.any_egg: self.has_any(AnimalProduct.chicken_egg, AnimalProduct.duck_egg),
|
||||||
AnimalProduct.brown_egg: self.animal.has_animal(Animal.chicken),
|
AnimalProduct.brown_egg: self.animal.has_animal(Animal.chicken),
|
||||||
AnimalProduct.chicken_egg: self.has_any(AnimalProduct.egg, AnimalProduct.brown_egg, AnimalProduct.large_egg, AnimalProduct.large_brown_egg),
|
AnimalProduct.chicken_egg: self.has_any(AnimalProduct.egg, AnimalProduct.brown_egg, AnimalProduct.large_egg, AnimalProduct.large_brown_egg),
|
||||||
AnimalProduct.cow_milk: self.has_any(AnimalProduct.milk, AnimalProduct.large_milk),
|
AnimalProduct.cow_milk: self.has_any(AnimalProduct.milk, AnimalProduct.large_milk),
|
||||||
AnimalProduct.duck_egg: self.animal.has_animal(Animal.duck),
|
AnimalProduct.duck_egg: self.animal.has_animal(Animal.duck), # Should also check starter
|
||||||
AnimalProduct.duck_feather: self.animal.has_happy_animal(Animal.duck),
|
AnimalProduct.duck_feather: self.animal.has_happy_animal(Animal.duck),
|
||||||
AnimalProduct.egg: self.animal.has_animal(Animal.chicken),
|
AnimalProduct.egg: self.animal.has_animal(Animal.chicken), # Should also check starter
|
||||||
AnimalProduct.goat_milk: self.has(Animal.goat),
|
AnimalProduct.goat_milk: self.animal.has_animal(Animal.goat),
|
||||||
AnimalProduct.golden_egg: self.received(AnimalProduct.golden_egg) & (self.money.can_spend_at(Region.ranch, 100000) | self.money.can_trade_at(Region.qi_walnut_room, Currency.qi_gem, 100)),
|
AnimalProduct.golden_egg: self.has(AnimalProduct.golden_egg_starter), # Should also check golden chicken if there was an alternative to obtain it without golden egg
|
||||||
AnimalProduct.large_brown_egg: self.animal.has_happy_animal(Animal.chicken),
|
AnimalProduct.large_brown_egg: self.animal.has_happy_animal(Animal.chicken),
|
||||||
AnimalProduct.large_egg: self.animal.has_happy_animal(Animal.chicken),
|
AnimalProduct.large_egg: self.animal.has_happy_animal(Animal.chicken),
|
||||||
AnimalProduct.large_goat_milk: self.animal.has_happy_animal(Animal.goat),
|
AnimalProduct.large_goat_milk: self.animal.has_happy_animal(Animal.goat),
|
||||||
AnimalProduct.large_milk: self.animal.has_happy_animal(Animal.cow),
|
AnimalProduct.large_milk: self.animal.has_happy_animal(Animal.cow),
|
||||||
AnimalProduct.milk: self.animal.has_animal(Animal.cow),
|
AnimalProduct.milk: self.animal.has_animal(Animal.cow),
|
||||||
AnimalProduct.ostrich_egg: self.tool.can_forage(Generic.any, Region.island_north, True) & self.has(Forageable.journal_scrap) & self.region.can_reach(Region.volcano_floor_5),
|
|
||||||
AnimalProduct.rabbit_foot: self.animal.has_happy_animal(Animal.rabbit),
|
AnimalProduct.rabbit_foot: self.animal.has_happy_animal(Animal.rabbit),
|
||||||
AnimalProduct.roe: self.skill.can_fish() & self.building.has_building(Building.fish_pond),
|
AnimalProduct.roe: self.skill.can_fish() & self.building.has_building(Building.fish_pond),
|
||||||
AnimalProduct.squid_ink: self.mine.can_mine_in_the_mines_floor_81_120() | (self.building.has_building(Building.fish_pond) & self.has(Fish.squid)),
|
AnimalProduct.squid_ink: self.mine.can_mine_in_the_mines_floor_81_120() | (self.building.has_building(Building.fish_pond) & self.has(Fish.squid)),
|
||||||
AnimalProduct.sturgeon_roe: self.has(Fish.sturgeon) & self.building.has_building(Building.fish_pond),
|
AnimalProduct.sturgeon_roe: self.has(Fish.sturgeon) & self.building.has_building(Building.fish_pond),
|
||||||
AnimalProduct.truffle: self.animal.has_animal(Animal.pig) & self.season.has_any_not_winter(),
|
AnimalProduct.truffle: self.animal.has_animal(Animal.pig) & self.season.has_any_not_winter(),
|
||||||
AnimalProduct.void_egg: self.money.can_spend_at(Region.sewer, 5000) | (self.building.has_building(Building.fish_pond) & self.has(Fish.void_salmon)),
|
AnimalProduct.void_egg: self.has(AnimalProduct.void_egg_starter), # Should also check void chicken if there was an alternative to obtain it without void egg
|
||||||
AnimalProduct.wool: self.animal.has_animal(Animal.rabbit) | self.animal.has_animal(Animal.sheep),
|
AnimalProduct.wool: self.animal.has_animal(Animal.rabbit) | self.animal.has_animal(Animal.sheep),
|
||||||
AnimalProduct.slime_egg_green: self.has(Machine.slime_egg_press) & self.has(Loot.slime),
|
AnimalProduct.slime_egg_green: self.has(Machine.slime_egg_press) & self.has(Loot.slime),
|
||||||
AnimalProduct.slime_egg_blue: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(3),
|
AnimalProduct.slime_egg_blue: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(3),
|
||||||
AnimalProduct.slime_egg_red: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(6),
|
AnimalProduct.slime_egg_red: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(6),
|
||||||
AnimalProduct.slime_egg_purple: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(9),
|
AnimalProduct.slime_egg_purple: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(9),
|
||||||
AnimalProduct.slime_egg_tiger: self.has(Fish.lionfish) & self.building.has_building(Building.fish_pond),
|
AnimalProduct.slime_egg_tiger: self.has(Fish.lionfish) & self.building.has_building(Building.fish_pond),
|
||||||
|
AnimalProduct.duck_egg_starter: self.logic.false_, # It could be purchased at the Feast of the Winter Star, but it's random every year, so not considering it yet...
|
||||||
|
AnimalProduct.dinosaur_egg_starter: self.logic.false_, # Dinosaur eggs are also part of the museum rules, and I don't want to touch them yet.
|
||||||
|
AnimalProduct.egg_starter: self.logic.false_, # It could be purchased at the Desert Festival, but festival logic is quite a mess, so not considering it yet...
|
||||||
|
AnimalProduct.golden_egg_starter: self.received(AnimalProduct.golden_egg) & (self.money.can_spend_at(Region.ranch, 100000) | self.money.can_trade_at(Region.qi_walnut_room, Currency.qi_gem, 100)),
|
||||||
|
AnimalProduct.void_egg_starter: self.money.can_spend_at(Region.sewer, 5000) | (self.building.has_building(Building.fish_pond) & self.has(Fish.void_salmon)),
|
||||||
ArtisanGood.aged_roe: self.artisan.can_preserves_jar(AnimalProduct.roe),
|
ArtisanGood.aged_roe: self.artisan.can_preserves_jar(AnimalProduct.roe),
|
||||||
ArtisanGood.battery_pack: (self.has(Machine.lightning_rod) & self.season.has_any_not_winter()) | self.has(Machine.solar_panel),
|
ArtisanGood.battery_pack: (self.has(Machine.lightning_rod) & self.season.has_any_not_winter()) | self.has(Machine.solar_panel),
|
||||||
ArtisanGood.caviar: self.artisan.can_preserves_jar(AnimalProduct.sturgeon_roe),
|
ArtisanGood.caviar: self.artisan.can_preserves_jar(AnimalProduct.sturgeon_roe),
|
||||||
|
@@ -72,4 +72,16 @@ of source (Monster drop and fish can have foraging sources).
|
|||||||
if easy logic is disabled. For instance, anything that requires money could be accessible as soon as you can sell something to someone (even wood).
|
if easy logic is disabled. For instance, anything that requires money could be accessible as soon as you can sell something to someone (even wood).
|
||||||
|
|
||||||
Items are classified by their source. An item with a fishing or a crab pot source is considered a fish, an item dropping from a monster is a monster drop. An
|
Items are classified by their source. An item with a fishing or a crab pot source is considered a fish, an item dropping from a monster is a monster drop. An
|
||||||
item with a foraging source is a forageable. Items can fit in multiple categories.
|
item with a foraging source is a forageable. Items can fit in multiple categories.
|
||||||
|
|
||||||
|
## Prefer rich class to anemic list of sources
|
||||||
|
|
||||||
|
For game mechanic that might need more logic/interaction than a simple game item, prefer creating a class than just listing the sources and adding generic
|
||||||
|
requirements to them. This will simplify the implementation of more complex mechanics and increase cohesion.
|
||||||
|
|
||||||
|
For instance, `Building` can be upgraded. Instead of having a simple source for the `Big Coop` being a shop source with an additional requirement being having
|
||||||
|
the previous building, the `Building` class has knowledge of the upgrade system and know from which building it can be upgraded.
|
||||||
|
|
||||||
|
Another example is `Animal`. Instead of a shopping source with a requirement of having a `Coop`, the `Chicken` knows that a building is required. This way, a
|
||||||
|
potential source of chicken from incubating an egg would not require an additional requirement of having a coop (assuming the incubator could be obtained
|
||||||
|
without a big coop).
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import functools
|
import functools
|
||||||
from typing import Union, Any, Iterable
|
from typing import Union, Any, Iterable
|
||||||
|
|
||||||
|
from .animal_logic import AnimalLogicMixin
|
||||||
from .artisan_logic import ArtisanLogicMixin
|
from .artisan_logic import ArtisanLogicMixin
|
||||||
from .base_logic import BaseLogicMixin, BaseLogic
|
from .base_logic import BaseLogicMixin, BaseLogic
|
||||||
from .grind_logic import GrindLogicMixin
|
from .grind_logic import GrindLogicMixin
|
||||||
@@ -11,6 +12,7 @@ from .received_logic import ReceivedLogicMixin
|
|||||||
from .region_logic import RegionLogicMixin
|
from .region_logic import RegionLogicMixin
|
||||||
from .requirement_logic import RequirementLogicMixin
|
from .requirement_logic import RequirementLogicMixin
|
||||||
from .tool_logic import ToolLogicMixin
|
from .tool_logic import ToolLogicMixin
|
||||||
|
from ..data.animal import IncubatorSource, OstrichIncubatorSource
|
||||||
from ..data.artisan import MachineSource
|
from ..data.artisan import MachineSource
|
||||||
from ..data.game_item import GenericSource, Source, GameItem, CustomRuleSource
|
from ..data.game_item import GenericSource, Source, GameItem, CustomRuleSource
|
||||||
from ..data.harvest import ForagingSource, FruitBatsSource, MushroomCaveSource, SeasonalForagingSource, \
|
from ..data.harvest import ForagingSource, FruitBatsSource, MushroomCaveSource, SeasonalForagingSource, \
|
||||||
@@ -25,7 +27,7 @@ class SourceLogicMixin(BaseLogicMixin):
|
|||||||
|
|
||||||
|
|
||||||
class SourceLogic(BaseLogic[Union[SourceLogicMixin, HasLogicMixin, ReceivedLogicMixin, HarvestingLogicMixin, MoneyLogicMixin, RegionLogicMixin,
|
class SourceLogic(BaseLogic[Union[SourceLogicMixin, HasLogicMixin, ReceivedLogicMixin, HarvestingLogicMixin, MoneyLogicMixin, RegionLogicMixin,
|
||||||
ArtisanLogicMixin, ToolLogicMixin, RequirementLogicMixin, GrindLogicMixin]]):
|
ArtisanLogicMixin, ToolLogicMixin, RequirementLogicMixin, GrindLogicMixin, AnimalLogicMixin]]):
|
||||||
|
|
||||||
def has_access_to_item(self, item: GameItem):
|
def has_access_to_item(self, item: GameItem):
|
||||||
rules = []
|
rules = []
|
||||||
@@ -81,6 +83,14 @@ ArtisanLogicMixin, ToolLogicMixin, RequirementLogicMixin, GrindLogicMixin]]):
|
|||||||
def _(self, source: HarvestCropSource):
|
def _(self, source: HarvestCropSource):
|
||||||
return self.logic.harvesting.can_harvest_crop_from(source)
|
return self.logic.harvesting.can_harvest_crop_from(source)
|
||||||
|
|
||||||
|
@has_access_to.register
|
||||||
|
def _(self, source: IncubatorSource):
|
||||||
|
return self.logic.animal.can_incubate(source.egg_item)
|
||||||
|
|
||||||
|
@has_access_to.register
|
||||||
|
def _(self, source: OstrichIncubatorSource):
|
||||||
|
return self.logic.animal.can_ostrich_incubate(source.egg_item)
|
||||||
|
|
||||||
@has_access_to.register
|
@has_access_to.register
|
||||||
def _(self, source: MachineSource):
|
def _(self, source: MachineSource):
|
||||||
return self.logic.artisan.can_produce_from(source)
|
return self.logic.artisan.can_produce_from(source)
|
||||||
|
@@ -8,6 +8,5 @@ class Animal:
|
|||||||
rabbit = "Rabbit"
|
rabbit = "Rabbit"
|
||||||
goat = "Goat"
|
goat = "Goat"
|
||||||
ostrich = "Ostrich"
|
ostrich = "Ostrich"
|
||||||
|
void_chicken = "Void Chicken"
|
||||||
coop_animals = [Animal.chicken, "Rabbit", "Duck", "Dinosaur"]
|
golden_chicken = "Golden Chicken"
|
||||||
barn_animals = [Animal.cow, "Sheep", "Pig", "Ostrich"]
|
|
||||||
|
@@ -3,17 +3,32 @@ class AnimalProduct:
|
|||||||
brown_egg = "Egg (Brown)"
|
brown_egg = "Egg (Brown)"
|
||||||
chicken_egg = "Chicken Egg"
|
chicken_egg = "Chicken Egg"
|
||||||
cow_milk = "Cow Milk"
|
cow_milk = "Cow Milk"
|
||||||
|
dinosaur_egg_starter = "Dinosaur Egg (Starter)"
|
||||||
|
"""This item does not really exist and should never end up being displayed.
|
||||||
|
It's there to patch the loop in logic because of the Dinosaur-and-egg problem."""
|
||||||
dinosaur_egg = "Dinosaur Egg"
|
dinosaur_egg = "Dinosaur Egg"
|
||||||
|
duck_egg_starter = "Duck Egg (Starter)"
|
||||||
|
"""This item does not really exist and should never end up being displayed.
|
||||||
|
It's there to patch the loop in logic because of the Chicken-and-egg problem."""
|
||||||
duck_egg = "Duck Egg"
|
duck_egg = "Duck Egg"
|
||||||
duck_feather = "Duck Feather"
|
duck_feather = "Duck Feather"
|
||||||
|
egg_starter = "Egg (Starter)"
|
||||||
|
"""This item does not really exist and should never end up being displayed.
|
||||||
|
It's there to patch the loop in logic because of the Chicken-and-egg problem."""
|
||||||
egg = "Egg"
|
egg = "Egg"
|
||||||
goat_milk = "Goat Milk"
|
goat_milk = "Goat Milk"
|
||||||
|
golden_egg_starter = "Golden Egg (Starter)"
|
||||||
|
"""This item does not really exist and should never end up being displayed.
|
||||||
|
It's there to patch the loop in logic because of the Chicken-and-egg problem."""
|
||||||
golden_egg = "Golden Egg"
|
golden_egg = "Golden Egg"
|
||||||
large_brown_egg = "Large Egg (Brown)"
|
large_brown_egg = "Large Egg (Brown)"
|
||||||
large_egg = "Large Egg"
|
large_egg = "Large Egg"
|
||||||
large_goat_milk = "Large Goat Milk"
|
large_goat_milk = "Large Goat Milk"
|
||||||
large_milk = "Large Milk"
|
large_milk = "Large Milk"
|
||||||
milk = "Milk"
|
milk = "Milk"
|
||||||
|
ostrich_egg_starter = "Ostrich Egg (Starter)"
|
||||||
|
"""This item does not really exist and should never end up being displayed.
|
||||||
|
It's there to patch the loop in logic because of the Chicken-and-egg problem."""
|
||||||
ostrich_egg = "Ostrich Egg"
|
ostrich_egg = "Ostrich Egg"
|
||||||
rabbit_foot = "Rabbit's Foot"
|
rabbit_foot = "Rabbit's Foot"
|
||||||
roe = "Roe"
|
roe = "Roe"
|
||||||
@@ -25,6 +40,8 @@ class AnimalProduct:
|
|||||||
squid_ink = "Squid Ink"
|
squid_ink = "Squid Ink"
|
||||||
sturgeon_roe = "Sturgeon Roe"
|
sturgeon_roe = "Sturgeon Roe"
|
||||||
truffle = "Truffle"
|
truffle = "Truffle"
|
||||||
|
void_egg_starter = "Void Egg (Starter)"
|
||||||
|
"""This item does not really exist and should never end up being displayed.
|
||||||
|
It's there to patch the loop in logic because of the Chicken-and-egg problem."""
|
||||||
void_egg = "Void Egg"
|
void_egg = "Void Egg"
|
||||||
wool = "Wool"
|
wool = "Wool"
|
||||||
|
|
||||||
|
@@ -142,5 +142,3 @@ class ModFossil:
|
|||||||
pterodactyl_phalange = "Pterodactyl Phalange"
|
pterodactyl_phalange = "Pterodactyl Phalange"
|
||||||
pterodactyl_vertebra = "Pterodactyl Vertebra"
|
pterodactyl_vertebra = "Pterodactyl Vertebra"
|
||||||
pterodactyl_claw = "Pterodactyl Claw"
|
pterodactyl_claw = "Pterodactyl Claw"
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user