Coder Social home page Coder Social logo

trashmonks / hagadias Goto Github PK

View Code? Open in Web Editor NEW
10.0 10.0 5.0 1.46 MB

Python package to extract game data from the Caves of Qud roguelike.

License: GNU Affero General Public License v3.0

Python 100.00%
caves-of-qud python-library python3 qud

hagadias's People

Contributors

dependabot[bot] avatar egocarib avatar elvres avatar heladodebrownie avatar kernelmethod avatar librarianmage avatar robbyblum avatar syntaxaire avatar wreckstation avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

hagadias's Issues

Ignore upper/lower case for texture directory on Linux

While tile generation works great on Windows using the tile modding toolkit, on Linux certain tiles won't generate because of case differences in the directory structure.

Example:
Couldn't render tile for Great Magma Crab: creatures/sw_magmacrab.png not found
The creatures directory is actually Creatures, so this won't work on Linux.

This affects Cryptogull and should affect QBE users on Linux and potentially Mac OS.

Unidentified Artifact Tiles Are Now Cyan by Default

class StyleExaminerUnknown(TileStyle):
"""Styles for the UnknownTile attribute of the Examiner part."""
def __init__(self, _painter):
super().__init__(_painter, _priority=20,
_modifies=RenderProps.FILE, _allows=RenderProps.NONFILE)
self._unknown_tile = self.object.part_Examiner_UnknownTile
def _modification_count(self) -> int:
if self._unknown_tile is not None:
complexity = self.object.complexity
if complexity is not None and complexity > 0:
understanding = self.object.part_Examiner_Understanding
if understanding is None or int(understanding) < complexity:
unknown_name = self.object.part_Examiner_UnknownDisplayName
if unknown_name is None or unknown_name != '*med':
# tonics excluded due to their random coloring - they have their own style
return 2
return 0

StyleExaminerUnknown will need to be updated to account for the change, since it now involves a color element, not only a filepath element. A good example is Mechanical Wings, which use w and W as the tile colors, but when unidentified use C.

Load Sultan Mural Images

Would be cool to load the various sultan mural images for use on the wiki. I assume those are hard-coded into some class somewhere.

MA should be calculated for robots and other things with mental shields

We currently return None for MA for anything with a mental shield:

@cached_property
def ma(self) -> int | None:
"""The object's mental armor. For creatures, this is an averaged value.
For items, this can be a bonus to MA as specified in the Armor part."""
if self.hasmentalshield:
# things like Robots, Water, Stairs, etc. are not subject to mental effects.
return None
elif (char_type := self.active_or_inactive_character()) == INACTIVE_CHAR:
return 0
elif char_type == ACTIVE_CHAR:
# MA starts at base 4
ma = 4
# Add MA stat value if specified
if self.stat_MA_Value:
ma += int(self.stat_MA_Value)
# add willpower modifier to MA
ma += self.attribute_helper_mod('Willpower')
return ma
else: # items (char_type == 0)
return int_or_none(self.attribute_helper('MA'))

However, things with mental shields are still subject to some effects that use MA in their calculation, such as Rebuke Robot.

We should calculate MA for these creatures so it can surfaced on the wiki.

Redefine what is conisdered an ACTIVE_CHAR

currently, we check if something is an ACTIVE_CHAR if it inherits from certain objects, which is not ideal, because how the game determines something to be similar to it more granular. This is an open issue since I myself am not sure what specifically constitutes an active char, and want to get my thoughts organized. although here are my ideas:

ORIGINAL:
ACTIVE_CHARS = ['Creature', 'ActivePlant']
INACTIVE_CHARS = ['BaseFungus', 'Baetyl', 'Wall', 'Furniture']
which a method checks if the objects inherits from either of these. idk performance checks but this sounds slow

PROPOSED:
ALL_CHARS

  • has physics, and is nontakeable (takeable objects become items)

ACTIVE_CHARS

  • combat part exists
  • ?brain part exists? (except baetyls, ivories, which are inactive chars rn since they dont need attributes)

INACTIVE_CHARS

  • ALL_CHARS - ACTIVE_CHARS

These will no longer be a list of things that inherit, but rather a method that determines it on method call.

The purpose of ACTIVE_CHARS and stuff

It was a lil container i made up that hagadias checks against so we don't get pronouns/combat stats for inanimate objects.

the current definition in comments:

ACTIVE: What is typically considered a Character, with an inventory* and combat capabilities.

INACTIVE: What would still be helpful to have combat related stats, but have things that make them different from active characters. Usually immobile and have no attributes.

*note that inactive chars like tables can still have inventories, so it really is just combat capabilities

Current usages of ACTIVE_CHARS and INACTIVE_CHARS

  • in attribute_helper and attribute_boost_factor which gives attributes to everything (combat check?)
    • in dv, where inactive = -10, but active chars has a check for part_brain_mobile anyway
  • in method ma, which all inactive have 0, and active default to 4
  • in method marange, which returns none for inactive and active has 4 and calculates range from will
  • in demeanor, which can easily be a brain check instead
  • in gender

also, usages of ALL_CHARS:

  • AV
  • HP

Cherubim should inherit faction membership normally for wiki templates

I think the issue is lines 953-955 of hagadias/qudobject_props.py:

if self.name[-6:] == 'Cherub':
If you look at "all attributes" in QBE for, e.g. the cats cherub, you see 'Brain': {'Factions': 'Beasts-100', 'Hostile': 'false', 'Wanders': 'true'} (accurate to what happens in-game), but the template says faction = {{creature faction|{{FactionID to name|Cherubim}}|100}} (no longer correct).

Parse 'Look' Description Grammar

As I was working on ?wikipage embeds for cryptogull, I ended up having to make an extra API call to the expandtemplates API to remotely call Template:Grammar in order to parse look descriptions correctly to be displayed on Discord.

It would be nice if we can parse those descriptions in hagadias before uploading to the wiki instead. This would improve performance of the ?wikipage embed by removing the need for the extra API call.

If we do address this issue at some point, we should completely remove the _parse_grammar method from cryptogull's wiki_page.py module, and we can also remove the single call to that method (self._look_description = await self._parse_grammar(self._look_description, wiki_text))

Mod Descriptions Aren't Added to Item Descriptions

Example, the scoped and masterwork lines don't get added to the Sparbine automatically.

image

Also would affect other items that come with Mods pre-assigned, like Yal or Shayna.

Possible solutions:

  • Load Mods.xml data and use that
  • Add description overrides to config.yml for stuff this

Derived Creature DV is incorrect

When DV is specified, it is a sum to the already base 6 DV in addition to agility + spry/tumble. If self.stat_DV_Value is a pointless check because all creatures inherit a base bonus +0 DV. however, in this conditional branch it only returns that bonus without calculating the rest of the agility. (see: cave spider with an DV of 2 in code, but in game has 9 because 6+ 2(bonus) + 1 (agi modifier) )

Dicebag: lonely - signs are ignored instead of throwing an error

regex only works by splitting by -, but if it's not valid it ignores the input. This causes some inputs to be parsed even if they should not:
input: ----
output: 0 (nothing is read, but no error because string is not blank and contains legal characters)

input: 7--2
output: 5 (expected: 9 but hagadias reads it as (7)(- or just 0)(-2) = 5)
This type of arithmetic is likely never going to be used normally, so just throwing an error here instead of properly negating the -2 would be fine.

RandomTile Part Isn't Accounted For

A good example is Aloe Volta, which looks like this in game (1 of 4 similar-looking variations):
image
But is rendered like this on the wiki (using it's inherited Render tile, which isn't ever shown in game):
image

EaterStatue is one of the objects with the most random tiles.

Even if we're not able to import all the variations, we should at least choose the tile from the first tile in the list of RandomTile part, to avoid having a completely incorrect tile, like in the case of the Aloe Volta.

dice bag average is incorrectly floored

the average of a dice roll needs to be able to be a fractional number in order to allow two dice distributions to be accurately compared. the int call needs to be removed (and it needs to be tested working correctly with cryptogull)

Try to find a way of reading tiles directly from game data

This is desired for several reasons:

  • allow the wiki to be updated immediately after a patch with new tiles comes out - especially after wiki updating is made an automatic process driven by patches
  • remove the burden of maintaining the modding toolkit zip from Brian and Jason
  • decrease the overhead required to set up hagadias, cryptogull and QBE

There may be a Python package capable of reading this data:
https://github.com/HearthSim/UnityPack

Tiles rendered by Discord with artifacts

Some artificing shows up on mobile Discord when viewing the tiles generated by Cryptogull using hagadias on Linux. Check to see if it is Discord introducing these using a dirty resize method when it shows the tile larger on mobile.

Clockwork Beetle Properties Aren't Fully Loaded

Clockwork beetle now gets a lot of its properties from the Roboticized part, but those aren't currently loaded onto the wiki. For example, it becomes a robot and gains certain elemental resistances from the Roboticized part.

We may need to add some custom logic for the clockwork beetle to account for this.

Walls that inherit tile from "Wall" don't render correctly

Rubble and Debris don't render correctly. Here's what they look like in game (Rubble is in the upper right, Debris is the darker one):
image

It wasn't immediately obvious to me why these tiles aren't working when I browsed the code. Might take some debugging to understand what's going on.

Handle RandomColors part

We don't currently handle the RandomColors part. Would be nice to take that into consideration eventually.

Tiers of tinkerable objects are derived incorrectly

Right now, the Hand-e-nuke is listed as a tier 1 object due to inheriting the 1 tier from the base grenade object. However, because its rarest bit is 8, it is actually tier 8. Hagadias needs to derive tier from most significant bit if the object can be disassembled AND does not have any tier other than those inherited. (HE Missile has bits BC1 but is specified to be tier 4, and cannot be disassembled)

XP value is being taken from property Name="*XPValue" even though this appears to have no direct effect on XP value in game

There are currently 5 blueprints that have *XPValue in them instead of XPValue. I don't know if *XPValue does anything or if it's just a placeholder, but it doesn't appear to directly determine the actual XP value like XPValue does.

example: ickslug contains <property Name="*XPValue" Value="0" />, but actual XP earned on kill in game is 210.

I think this might be related to variable names being dynamically generated and stripping out the asterisk? I dunno.

Leave adding mod displaynames to the wiki side and not Hagadias

Stuff like Casinlard and Polluxus currently adds mods names like electrified to the title parameter. While more accurate, it makes it harder to favilink (the name to search is electrified Polluxus, for example. just Polluxus will not work) unless I add a specific alternate display name. Mods already have all of their display names stored inside cargo, so moving it over to the wiki is not too difficult. This way, the plain title can be stored for favilinking, and the mod display names can be added afterwards.

This is just a suggestion so I'm open to debate about this.

part_MentalShield is not inherited by children correctly

Added test_MentalShield in qudobject_props_test.py:

def test_mentalshield(qindex):
    assert qindex['Sawhander'].ma == None
    assert qindex['Lurking Beth'].ma == None

Sawhanders's MA : 10 (should be None)
Lurking Beths's MA: -4 (should be None)
Both base objects Plant and Robot have MentalShield and should be inherited.

Obsoletion of MutatedPlant extra info

For the purposes of defoliant, checking whether it is a mutated plant or not is no longer sufficient; I have made a new extra info titled hurtbydefoliant that checks the tag LivePlant (which defoliant targets). it will do significant damage if it does not have a combat part OR has the tag GasDamageAsIfInanimate Eventually i'll be looking to see what queries currently use MutatedPlant, and replace it with the new info. once that's done i'll delete MutatedPlant

Object Inheritance Should Not Be Sensitive to Order of Appearance in ObjectBlueprints.xml

We previously made an attempt to resolve inheritance order issues in 1f205b6

However, inheritance remains sensitive to order of appearance in ObjectBlueprints, and that needs to be fixed. For example, right now Vase does not properly inherit stat_AV from PhysicalObject.

More info in this discord conversation:
image

One possible solution might be to set a flag after an object has its inheritance resolved, and then check that flag on the parent before attempting to inherit from it. But we might want to take another look at how the game handles this first.

From what I can tell, only these two objects are currently affected by inheriting a parent that comes after them:

  • ProjectileSwarmRocket (BaseRocketProjectile)
  • Vessel (WaterContainer)

Note:
The following stop-gap should be reverted after we fix this issue: 412f14a

Fix Stat Calculations for Creatures with a "Boost"

We've been incorrectly factoring in the Boost attribute of the stat tag.

Currently, hagadias just adds the Boost to the calculated sValue for the stat.

boost = getattr(self, f'stat_{attr}_Boost')
if boost:
    val += f'+{boost}'

However, the game instead scales this boost based on the stat value itself, often resulting in a higher increase than the Boost value alone. The game does essentially StatValue * 0.25 * Boost, rounded up

if (statistic.Boost > 0)
{
    statistic.BaseValue += (int)Math.Ceiling((double)((float)num2 * 0.25f * (float)statistic.Boost));
}
else
{
    statistic.BaseValue += (int)Math.Ceiling((double)((float)num2 * 0.2f * (float)statistic.Boost));
}

As a result, any creature with a Boost has lower-than-expected stats on the wiki. Some discussion on the discord here.

Load SecurityClearance info

Certain objects can be opened or deactivated by either security cards or Psychometry. This is always defined by the SecurityClearance attribute on the following parts: Door, PowerSwitch, and ForceProjector. The modes of access that correspond with the SecurityClearance attribute value are defined in XRL.World.Capabilities.SecurityClearance.

It would be nice to load this info in hagadias (and then downstream on the wiki)

Better Support for Liquid Tile Rendering

Liquid colors aren't currently properly supported for tile rendering (since the colors are hard coded in the game). We should define those colors as constants and properly support the colors for the purposes of tile rendering. (Liquids now use RandomTile for single-tile puddles, with 8 variations, which could be shown off on the wiki instead of the outdated puddle tile we use now).

Walls Aren't Inheriting Electric Resistance

For some reason, Walls seem to no longer be inheriting Electric resistance values in their template. I'm a bit rusty so it's not really clear to me why this is the case. stat_ColdResistance works fine but stat_ElectricResistance isn't getting pulled in for some reason.

Example: Shale

image

Enhancement Idea: Animate Tiles

It might be interesting to animate tiles by generating a secondary gif animation when relevant. For example, all of the Ereshkigal mainframe tiles could be animated to look like they do in game.

This seems to be supported with the Pillow Image library we already use in a somewhat straightforward manner (brief example tutorial). Here are the official docs: https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#saving

If we would go forward with this enhancement, we would want to do something on the wiki side to prevent the gifs from playing on every page. Probably it would be best to generate them as a secondary image referenced in the template, and then use some CSS magic or javascript to hide them on first page load. When someone clicks the "play animation" button, they can see the tile animated. On the discord side, it would probably be fine to show the gif images unfiltered.

This project would involve a bit of complexity because many of the animated tiles in the game don't use a single unified framework to control their animations, so it would require simulating a few different code paths in the base game.

Unable to pipenv sync with msys2 environment

ontoclasm reports:

ERROR:pip.subprocessor:Command errored out with exit status 1:
 command: 'C:\Users\user\.virtualenvs\qud-wiki-FCW-qFpB\Scripts\python.exe' -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\\Users\\user\\.virtualenvs\\qud-wiki-FCW-qFpB\\src\\hagadias\\setup.py'"'"'; __file__='"'"'C:\\Users\\user\\.virtualenvs\\qud-wiki-FCW-qFpB\\src\\hagadias\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info
     cwd: C:\Users\user\.virtualenvs\qud-wiki-FCW-qFpB\src\hagadias\
Complete output (33 lines):
[...]
FileNotFoundError: [WinError 3] The system cannot find the path specified: '/c/Users/user/.virtualenvs/qud-wiki-FCW-qFpB/src/hagadias'

This path was confirmed to exist in the msys2 environment.

Chargeuse for Programmable/Reprogrammable recoiler

QBE shows the "program" chargeuse cost to set Programmable or Reprogrammable recoiler to a new target location, instead of the chargeuse cost to use the recoiler to recoil to the location. The teleport chargeuse should still be 2500.

We should probably just note the higher "programming" charge use cost on the wiki page itself and update QBE to not import that value.

Load Inventory List from PopulationTables.xml

It is now becoming common practice for the game to use population tables for creature inventories - this is how pretty much all the new creatures for Palladium Reef patch are done (and there are others from Tomb patch that did this too).

As a result, the wiki is missing a lot of info about character inventories.

We should figure out a good way to load inventory objects from PopulationTables.xml

A few options to consider:

  • Load PopulationTables.xml in hagadias directly, and use it for this (and potentially other things)
  • Load PopulationTables.xml in qud-wiki and add an override to def inventory in qudobject_wiki.py that resolves the population (would require hagadias to return the pop table from object blueprints first)

The first option would probably be nicest since there are already a lot of other things we could be using this for (like the BUTCHERABLE_POPTABLES dictionary in hagadias' constants.py). The second option is more along the lines of what we do with cryptogull today.

Recent Template Tweaks / Issues

A few recent template edits that should be reviewed and potentially accounted for in QBE logic:

Plus some similar discord-reported issues:

Skillsofts display names need manual overrides

Because of how all of the skillsoft names are derived in cs code, we need manual renames of the displayname and with TreeSkillsoft, a page move to its proper name.

SingleSkillsoft1 -> Skillsoft [low SP]
SingleSkillsoft2 -> Skillsoft [medium SP]
SingleSkillsoft3 -> Skillsoft [high SP]
TreeSkillsoft -> Skillsoft Plus [tree]

Alternative: Move all skillsofts into one page like all the cybernetics wedges.

Calculate liquid volume display names

Liquid volumes are all calculated only as "pool" right now. We should add some logic to properly calculate their display names (in the game engine, this is dynamically determined in the code).

Not a big priority because liquids are currently disabled for QBE upload, but still would be nice.

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.