Skip to content

Commit

Permalink
Formatting and quality improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
syntaxaire committed Aug 3, 2022
1 parent cc3789b commit b77da51
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 49 deletions.
47 changes: 21 additions & 26 deletions hagadias/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
# Cherubim description templates
CHERUBIM_DESC = "Gallium veins press against the underside of =pronouns.possessive= crystalline *skin* and gleam warmly. =pronouns.Possessive= body is perfect, and the whole of it is wet with amniotic slick; could =pronouns.subjective= have just now peeled =pronouns.reflexive= off an oil canvas? =verb:Were:afterpronoun= =pronouns.subjective= cast into the material realm by a dreaming, dripping brain? Whatever the embryo, =pronouns.subjective= =verb:are:afterpronoun= now the archetypal *creatureType*; it's all there in impeccable simulacrum: *features*. Perfection is realized." # noqa E501
MECHANICAL_CHERUBIM_DESC = "Dials tick and vacuum tubes mantle under synthetic *skin* and inside plastic joints. *features* are wrought from a vast and furcate machinery into the ideal form of the *creatureType*. By the artistry of =pronouns.possessive= construction, =pronouns.subjective= closely =verb:resemble:afterpronoun= =pronouns.possessive= referent, but an exposed cog here and an exhaust valve there betray the truth of =pronouns.possessive= nature. =pronouns.Possessive= movements are short and mimetic; =pronouns.subjective= =verb:inhabit:afterpronoun= the valley between the mountains of life and imagination." # noqa E501

# BIT_TRANS: convert between the bit codes found in XML and the ones shown ingame.
bit_table = {"G": "B", "R": "A", "C": "D", "B": "C"}
bit_table = {
"G": "B",
"R": "A",
"C": "D",
"B": "C",
}
BIT_TRANS = "".maketrans(bit_table)

# ITEM_MOD_PROPS: difficulty and complexity changes when a mod is applied to an item
# ifcomplex means the change only applies if the item already has complexity > 0
# these values live in code, usually in ApplyModification() method of the Mod's .cs file
Expand Down Expand Up @@ -89,7 +92,6 @@
"ModSturdy": {"complexity": 0, "difficulty": 0, "ifcomplex": False, "prefix": "sturdy "},
"ModWired": {"complexity": 0, "difficulty": 1, "ifcomplex": True, "prefix": "&cwired &y"},
}

# This could be loaded from Factions.xml eventually, but for simplicity I'm putting it here for now.
FACTION_ID_TO_NAME = {
"Antelopes": "antelopes",
Expand Down Expand Up @@ -155,28 +157,27 @@
"Winged Mammals": "winged mammals",
"Worms": "worms",
}

CYBERNETICS_HARDCODED_INFIXES = {
"CyberneticsMedassistModule": "{{c|Current loadout:}}{{y| no injectors}}"
}

COMPUTE = "Compute power on the local lattice"
INCREASES = "increases this item's effectiveness"
CYBERNETICS_HARDCODED_POSTFIXES = {
"CyberneticsAnomalyFumigator": "Compute power on the local lattice increases this item's effectiveness.",
"CyberneticsCommunicationsInterlock": "Compute power on the local lattice increases this item's effectiveness.",
"CyberneticsAnomalyFumigator": f"{COMPUTE} {INCREASES}.",
"CyberneticsCommunicationsInterlock": f"{COMPUTE} {INCREASES}.",
"CyberneticsCustomVisage": "+300 reputation with <chosen faction>",
"CyberneticsHighFidelityMatterRecompositer": "Compute power on the local lattice reduces this item's cooldown.",
"CyberneticsInflatableAxons": "Compute power on the local lattice increases this item's effectiveness.",
"CyberneticsMatterRecompositer": "Compute power on the local lattice reduces this item's cooldown.",
"CyberneticsNocturnalApex": "Compute power on the local lattice increases this item's effectiveness.",
"CyberneticsOnboardRecoilerTeleporter": "Compute power on the local lattice reduces this item's cooldown.",
"CyberneticsCathedraBlackOpal": "Compute power on the local lattice increases this item's effectiveness.",
"CyberneticsCathedraRuby": "Compute power on the local lattice increases this item's effectiveness.",
"CyberneticsCathedraSapphire": "Compute power on the local lattice increases this item's effectiveness.",
"CyberneticsCathedraWhiteOpal": "Compute power on the local lattice increases this item's effectiveness.",
"CyberneticsPenetratingRadar": "Compute power on the local lattice increases this item's range.",
"CyberneticsStasisProjector": "Compute power on the local lattice increases this item's effectiveness.",
"CyberneticsHighFidelityMatterRecompositer": f"{COMPUTE} reduces this item's cooldown.",
"CyberneticsInflatableAxons": f"{COMPUTE} {INCREASES}.",
"CyberneticsMatterRecompositer": f"{COMPUTE} reduces this item's cooldown.",
"CyberneticsNocturnalApex": f"{COMPUTE} {INCREASES}.",
"CyberneticsOnboardRecoilerTeleporter": f"{COMPUTE} reduces this item's cooldown.",
"CyberneticsCathedraBlackOpal": f"{COMPUTE} {INCREASES}.",
"CyberneticsCathedraRuby": f"{COMPUTE} {INCREASES}.",
"CyberneticsCathedraSapphire": f"{COMPUTE} {INCREASES}.",
"CyberneticsCathedraWhiteOpal": f"{COMPUTE} {INCREASES}.",
"CyberneticsPenetratingRadar": f"{COMPUTE} increases this item's range.",
"CyberneticsStasisProjector": f"{COMPUTE} {INCREASES}.",
}

HARDCODED_CHARGE_USE = {
"Displacer Bracelet": 1,
"Force Bracelet": 500,
Expand All @@ -197,7 +198,6 @@
"Stopsvaalinn": "ForceEmitter",
"Food Processor": "Food Processing",
}

QUD_COLORS = {
"r": (166, 74, 46), # dark red
"R": (215, 66, 0), # bright red
Expand All @@ -219,9 +219,7 @@
"O": (233, 159, 16),
"transparent": (15, 64, 63, 0),
}

QUD_VIRIDIAN = (15, 64, 63, 255)

LIQUID_COLORS = {
"acid": "&G^g",
"algae": "&g^C",
Expand Down Expand Up @@ -250,7 +248,6 @@
"wax": "&y^Y",
"wine": "&m^r",
}

STAT_DISPLAY_NAMES = {
"AcidResistance": "acid resistance",
"ColdResistance": "cold resistance",
Expand All @@ -260,7 +257,6 @@
"MoveSpeed": "move speed",
"Speed": "quickness",
}

# The following includes all parts descending from IActivePart, which defines the IsEMPSensitive and
# PowerLoadSensitive fields. This holds the hard-coded defaults. These can be overridden in the XML.
# This list is accurate as of patch 202.84. There are also a few special cases not descending from
Expand Down Expand Up @@ -551,7 +547,6 @@
"WalltrapGas": {"IsEMPSensitive": True, "IsPowerLoadSensitive": False},
"WalltrapShock": {"IsEMPSensitive": True, "IsPowerLoadSensitive": False},
}

# The 'Butcherable' part can contain a population tables reference if it begins with an '@' symbol.
# One day, we could potentially replace this if we start loading data from PopulationTables.xml.
BUTCHERABLE_POPTABLES = {
Expand Down
15 changes: 8 additions & 7 deletions hagadias/gameroot.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Functionality for loading the Qud game data from various game files."""

import logging
import time
from pathlib import Path
Expand All @@ -10,6 +9,8 @@
from hagadias.qudpopulation import QudPopulation
from lxml import etree as et

log = logging.getLogger(__name__)


class GameRoot:
"""Gather together the various data sources provided in a Caves of Qud game root.
Expand Down Expand Up @@ -76,21 +77,21 @@ def get_object_tree(self, cls=QudObjectProps):
path = self._xmlroot / "ObjectBlueprints"
qindex = {} # fast lookup of name->QudObject
for blueprint_file in path.glob("*.xml"):
logging.info(f"Loading {blueprint_file.stem} object blueprints:")
log.info(f"Loading {blueprint_file.stem} object blueprints:")
with blueprint_file.open("r", encoding="utf-8") as f:
contents = f.read()

# Do some repair of invalid XML specifically for ObjectBlueprints files: First,
# replace some invalid control characters intended for CP437 with their Unicode equiv
start = time.time()
logging.info("Repairing invalid XML characters... ")
log.debug("Repairing invalid XML characters... ")
contents = repair_invalid_chars(contents)
logging.info(f"done in {time.time() - start:.2f} seconds")
log.debug(f"done in {time.time() - start:.2f} seconds")
# Second, replace line breaks inside attributes with proper XML line breaks
start = time.time()
logging.info("Repairing invalid XML line breaks... ")
log.debug("Repairing invalid XML line breaks... ")
contents = repair_invalid_linebreaks(contents)
logging.info(f"done in {time.time() - start:.2f} seconds")
log.debug(f"done in {time.time() - start:.2f} seconds")
raw = et.fromstring(contents)
# Objects must receive the qindex and add themselves, rather than doing it here, because
# they need access to their parent by name lookup during creation for inheritance
Expand All @@ -103,7 +104,7 @@ def get_object_tree(self, cls=QudObjectProps):
cls(element, qindex, self)

# second pass - resolve object inheritance
logging.info("Resolving Qud object hierarchy and adding tiles...")
log.debug("Resolving Qud object hierarchy and adding tiles...")
for object_id, qud_object in qindex.items():
qud_object.resolve_inheritance()

Expand Down
29 changes: 13 additions & 16 deletions hagadias/qudobject_props.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import logging
import math
from functools import cached_property
from typing import Tuple, List
Expand Down Expand Up @@ -37,6 +38,7 @@
from hagadias.qudobject import QudObject
from hagadias.svalue import sValue

log = logging.getLogger(__name__)
# STATIC GROUPS
# Many combat properties can come from anything that inherits from either of these.
# Use For: self.active_or_inactive_character() == ACTIVE_CHAR
Expand Down Expand Up @@ -330,9 +332,9 @@ def av(self) -> int | None:
try:
av = int(self.stat_AV_Value) # first, creature's intrinsic AV
except TypeError:
print(
f'FIXME: "{self.name}" has no AV value (probably shouldn\'t be considered'
+ " an inactive character)?"
log.error(
"%s has no AV value (probably shouldn't be considered an inactive character?)",
self.name,
)
return None
applied_body_av = False
Expand Down Expand Up @@ -394,7 +396,7 @@ def butcheredinto(self) -> List[dict] | None:
if butcher_obj:
if butcher_obj[:1] == "@":
if butcher_obj[1:] not in BUTCHERABLE_POPTABLES:
print(f"FIXME: Butcherable poptable {butcher_obj} not recognized.")
log.error("Butcherable poptable %s not recognized.", butcher_obj)
else:
outcomes = []
for butcherable, info in BUTCHERABLE_POPTABLES[butcher_obj[1:]].items():
Expand All @@ -404,15 +406,15 @@ def butcheredinto(self) -> List[dict] | None:

@cached_property
def canbuild(self) -> bool | None:
"""Whether or not the player can tinker up this item."""
"""Whether the player can tinker up this item."""
if self.part_TinkerItem_CanBuild == "true":
return True
elif self.part_TinkerItem_CanDisassemble == "true":
return False # it's interesting if an item can't be built but can be disassembled

@cached_property
def candisassemble(self) -> bool | None:
"""Whether or not the player can disassemble this item."""
"""Whether the player can disassemble this item."""
if self.part_TinkerItem_CanDisassemble == "true":
return True
elif self.part_TinkerItem_CanBuild == "true":
Expand Down Expand Up @@ -497,14 +499,9 @@ def chargefunction(self) -> str | None:
+ f"Maintain Domination [{self.part_Teleprojector_MaintainChargeUse}]"
)
if part == "ForceProjector":
return (
"Basic Operation ["
+ str_or_default(self.part_ForceProjector_BaseOperatingCharge, "1")
+ "], "
+ "Per-Tile Projection ["
+ str_or_default(self.part_ForceProjector_ChargePerProjection, "90")
+ "]"
)
basic = str_or_default(self.part_ForceProjector_BaseOperatingCharge, "1")
projection = str_or_default(self.part_ForceProjector_ChargePerProjection, "90")
return f"Basic Operation [{basic}], Per-Tile Projection [{projection}]"
chg = getattr(self, f"part_{part}_ChargeUse")
if chg is not None and int(chg) > 0:
match part:
Expand Down Expand Up @@ -1461,12 +1458,12 @@ def faction(self) -> list | None:
faction, value = part.split("-")
ret.append((faction, int(value)))
else:
print(f"FIXME: unexpected faction format: {part} in {self.name}")
log.error("Unexpected faction format: %s in %s", part, self.name)
return ret

@cached_property
def flametemperature(self) -> int | None:
"""The temperature that this object sets on fire. Only for items."""
"""The temperature at which this object ignites. Only for items."""
if self.inherits_from("Item") and self.is_specified("part_Physics"):
return int_or_none(self.part_Physics_FlameTemperature)

Expand Down

0 comments on commit b77da51

Please sign in to comment.