big upgrades to upgrade system
This commit is contained in:
@@ -68,5 +68,6 @@ configure_file("seagull.spec.in" "seagull.spec")
|
|||||||
add_custom_command(OUTPUT "dist/${binname}"
|
add_custom_command(OUTPUT "dist/${binname}"
|
||||||
DEPENDS "${rant_path}" "${CMAKE_CURRENT_BINARY_DIR}/basepak/rant/wordlist.rant" ${pydepends} ${basepakdepends}
|
DEPENDS "${rant_path}" "${CMAKE_CURRENT_BINARY_DIR}/basepak/rant/wordlist.rant" ${pydepends} ${basepakdepends}
|
||||||
COMMENT "Building ${binname}"
|
COMMENT "Building ${binname}"
|
||||||
|
BYPRODUCTS "pyinstaller"
|
||||||
COMMAND ${PYINSTALLER} --distpath "${CMAKE_CURRENT_BINARY_DIR}/dist" --workpath "${CMAKE_CURRENT_BINARY_DIR}/pyinstaller" seagull.spec)
|
COMMAND ${PYINSTALLER} --distpath "${CMAKE_CURRENT_BINARY_DIR}/dist" --workpath "${CMAKE_CURRENT_BINARY_DIR}/pyinstaller" seagull.spec)
|
||||||
add_custom_target(desktop ALL DEPENDS "dist/${binname}" pak)
|
add_custom_target(desktop ALL DEPENDS "dist/${binname}" pak)
|
2988
Doxyfile.bak
Normal file
2988
Doxyfile.bak
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
|
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
|
||||||
|
<uri name="seagull:rules" uri="rules.xsd" />
|
||||||
<uri name="seagull:rules/items" uri="items.xsd" />
|
<uri name="seagull:rules/items" uri="items.xsd" />
|
||||||
<uri name="seagull:rules/upgrades" uri="upgrades.xsd" />
|
<uri name="seagull:rules/upgrades" uri="upgrades.xsd" />
|
||||||
</catalog>
|
</catalog>
|
9
app/basepak/rules/schemas/rules.xsd
Normal file
9
app/basepak/rules/schemas/rules.xsd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="seagull:rules">
|
||||||
|
<xs:simpleType name="percentage">
|
||||||
|
<xs:restriction base="xs:integer">
|
||||||
|
<xs:minExclusive value="0" />
|
||||||
|
<xs:maxInclusive value="400" />
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:schema>
|
@@ -1,17 +1,18 @@
|
|||||||
<?xml version="1.0" standalone="yes"?>
|
<?xml version="1.0" standalone="yes"?>
|
||||||
<xs:schema id="UpgradeRules" targetNamespace="seagull:rules/upgrades" xmlns="seagull:rules/upgrades" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="unqualified" elementFormDefault="qualified">
|
<xs:schema id="UpgradeRules" targetNamespace="seagull:rules/upgrades" xmlns="seagull:rules/upgrades" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:rule="seagull:rules" attributeFormDefault="unqualified" elementFormDefault="qualified">
|
||||||
|
<xs:import namespace="seagull:rules" schemaLocation="rules.xsd" />
|
||||||
<xs:element name="UpgradeRules">
|
<xs:element name="UpgradeRules">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
<xs:sequence>
|
||||||
<xs:element name="TreeData" maxOccurs="1">
|
<xs:element name="TreeData" maxOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:choice maxOccurs="unbounded">
|
<xs:all>
|
||||||
<xs:element name="Name" maxOccurs="1" type="xs:string" />
|
<xs:element name="Name" type="xs:string" />
|
||||||
<xs:element name="PrimaryColor" maxOccurs="1" type="xs:string" />
|
<xs:element name="PrimaryColor" maxOccurs="1" type="xs:string" />
|
||||||
</xs:choice>
|
</xs:all>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="Upgrade">
|
<xs:element name="Upgrade" maxOccurs="unbounded">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:choice maxOccurs="unbounded">
|
<xs:choice maxOccurs="unbounded">
|
||||||
<xs:element name="Id" type="xs:string" minOccurs="1" maxOccurs="1" />
|
<xs:element name="Id" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||||
@@ -19,29 +20,38 @@
|
|||||||
<xs:element name="Desc" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
<xs:element name="Desc" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||||
<xs:element name="Modifiers" minOccurs="0" maxOccurs="unbounded">
|
<xs:element name="Modifiers" minOccurs="0" maxOccurs="unbounded">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:choice minOccurs="1" maxOccurs="unbounded">
|
||||||
<xs:element name="Mod" minOccurs="0" maxOccurs="unbounded">
|
<xs:element name="Mod" minOccurs="0" maxOccurs="unbounded">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:attribute name="Id" form="unqualified" type="xs:string" />
|
<xs:attribute name="Id" form="unqualified" type="xs:string" />
|
||||||
<xs:attribute name="Name" form="unqualified" type="xs:string" />
|
<xs:attribute name="Name" form="unqualified" type="xs:string" />
|
||||||
<xs:attribute name="Speed" form="unqualified" type="xs:int" />
|
<xs:attribute name="Speed" form="unqualified" type="xs:int" />
|
||||||
<xs:attribute name="ChanceSteal" form="unqualified" type="xs:int" />
|
<xs:attribute name="ChanceSteal" form="unqualified" type="rule:percentage" />
|
||||||
|
<xs:attribute name="ChanceRecruit" form="unqualified" type="rule:percentage" />
|
||||||
|
<xs:attribute name="StealPerc" form="unqualified" type="rule:percentage" />
|
||||||
|
<xs:attribute name="XPPerc" form="unqualified" type="rule:percentage" />
|
||||||
|
<xs:attribute name="OfflineGen" form="unqualified" type="rule:percentage" />
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
</xs:sequence>
|
</xs:choice>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="Requirements" maxOccurs="1" minOccurs="0">
|
<xs:element name="Requirements" maxOccurs="1" minOccurs="0">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:choice minOccurs="1" maxOccurs="unbounded">
|
||||||
<xs:element name="Require" maxOccurs="unbounded" type="xs:string" />
|
<xs:element name="Require" maxOccurs="unbounded" type="xs:string" />
|
||||||
</xs:sequence>
|
<xs:element name="Food" minOccurs="0" maxOccurs="1" type="xs:int" />
|
||||||
|
<xs:element name="Shinies" minOccurs="0" maxOccurs="1" type="xs:int" />
|
||||||
|
<xs:element name="Agility" minOccurs="0" maxOccurs="1" type="xs:int" />
|
||||||
|
<xs:element name="Instinct" minOccurs="0" maxOccurs="1" type="xs:int" />
|
||||||
|
<xs:element name="Leadership" minOccurs="0" maxOccurs="1" type="xs:int" />
|
||||||
|
</xs:choice>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
</xs:choice>
|
</xs:choice>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
</xs:choice>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
</xs:schema>
|
</xs:schema>
|
@@ -60,6 +60,9 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
if argo.debug:
|
if argo.debug:
|
||||||
desktop.api.debug_mode = True
|
desktop.api.debug_mode = True
|
||||||
|
|
||||||
|
pyi_splash.update_text("Validating game rules")
|
||||||
|
core.validate_xml_files()
|
||||||
pyi_splash.update_text("Starting browser shell")
|
pyi_splash.update_text("Starting browser shell")
|
||||||
storage_dir.mkdir(exist_ok=True, parents=True)
|
storage_dir.mkdir(exist_ok=True, parents=True)
|
||||||
webview.create_window("Seagull Game", core.app, js_api=desktop.api, width=1280, height=720)
|
webview.create_window("Seagull Game", core.app, js_api=desktop.api, width=1280, height=720)
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import glob
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
@@ -5,6 +6,7 @@ import sys
|
|||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
|
import lxml.etree as xmltree
|
||||||
|
|
||||||
log = logging.getLogger()
|
log = logging.getLogger()
|
||||||
pipe_stderr = logging.StreamHandler(sys.stderr)
|
pipe_stderr = logging.StreamHandler(sys.stderr)
|
||||||
@@ -30,6 +32,7 @@ CORS(app)
|
|||||||
orig_url_for = app.url_for
|
orig_url_for = app.url_for
|
||||||
|
|
||||||
xml_namespaces = {
|
xml_namespaces = {
|
||||||
|
"rule": "seagull:rules",
|
||||||
"items": "seagull:rules/items",
|
"items": "seagull:rules/items",
|
||||||
"upgrades": "seagull:rules/upgrades"
|
"upgrades": "seagull:rules/upgrades"
|
||||||
}
|
}
|
||||||
@@ -58,6 +61,25 @@ def url_for_override(endpoint, *posargs, _anchor=None, _method=None, _scheme=Non
|
|||||||
|
|
||||||
app.url_for = url_for_override
|
app.url_for = url_for_override
|
||||||
|
|
||||||
|
schemas = []
|
||||||
|
pth_common_rule_schema = path_appdir / "basepak/rules/schemas/rules.xsd"
|
||||||
|
doc_common_rule_schema = xmltree.parse(pth_common_rule_schema.as_posix())
|
||||||
|
common_rule_schema = xmltree.XMLSchema(doc_common_rule_schema)
|
||||||
|
|
||||||
|
## \brief Validates all XML files in gamedata.
|
||||||
|
# \internal
|
||||||
|
#
|
||||||
|
# This is typically run on program startup.
|
||||||
|
def validate_xml_files():
|
||||||
|
for schema in schemas:
|
||||||
|
for file in gamedata.vfs.vfs.glob(schema[1]):
|
||||||
|
pth_xml = file.path[1:]
|
||||||
|
fd_xml = gamedata.vfs.open(pth_xml)
|
||||||
|
doc = xmltree.parse(fd_xml)
|
||||||
|
|
||||||
|
if not schema[0].validate(doc):
|
||||||
|
log.error(f"Bogus XML document: {pth_xml}")
|
||||||
|
|
||||||
## \internal
|
## \internal
|
||||||
# \brief Base Flask rendering context. Generated with render_base_context().
|
# \brief Base Flask rendering context. Generated with render_base_context().
|
||||||
base_context = {}
|
base_context = {}
|
||||||
@@ -86,7 +108,7 @@ def render_base_context():
|
|||||||
domain_components = flask.request.host.split(".")
|
domain_components = flask.request.host.split(".")
|
||||||
base_domain = ".".join(domain_components[-2:])
|
base_domain = ".".join(domain_components[-2:])
|
||||||
|
|
||||||
gamedata.vfs.copy_out("static/js/mermaid.esm.min.mjs", dest=path_appdir.as_posix())
|
gamedata.vfs.copy_dir("static", dest=path_appdir.as_posix())
|
||||||
|
|
||||||
# all this wind up for...
|
# all this wind up for...
|
||||||
if base_domain == "otl-hga.net": # production, use assets from S3
|
if base_domain == "otl-hga.net": # production, use assets from S3
|
||||||
|
@@ -86,6 +86,19 @@ class GameVFSHandler(object):
|
|||||||
fs.copy.copy_file(self.vfs, filepath, dest, filepath)
|
fs.copy.copy_file(self.vfs, filepath, dest, filepath)
|
||||||
return (pth_dest / filepath).as_posix()
|
return (pth_dest / filepath).as_posix()
|
||||||
|
|
||||||
|
def copy_dir(self, dirpath, dest=None):
|
||||||
|
if not dest:
|
||||||
|
self.osfs_temp.makedirs(pathlib.Path(dirpath).parent.as_posix(), recreate=True)
|
||||||
|
fs.copy.copy_dir(self.vfs, dirpath, self.osfs_temp, dirpath)
|
||||||
|
return self.pth_temp / dirpath
|
||||||
|
else:
|
||||||
|
pth_dest = pathlib.Path(dest)
|
||||||
|
pth_file = pathlib.Path(dirpath)
|
||||||
|
osfs_dest = fs.osfs.OSFS(dest)
|
||||||
|
osfs_dest.makedirs(pth_file.parent.as_posix(), recreate=True)
|
||||||
|
fs.copy.copy_dir(self.vfs, dirpath, dest, dirpath)
|
||||||
|
return (pth_dest / dirpath).as_posix()
|
||||||
|
|
||||||
## \brief Primary VFS handler.
|
## \brief Primary VFS handler.
|
||||||
# \internal
|
# \internal
|
||||||
vfs = GameVFSHandler()
|
vfs = GameVFSHandler()
|
@@ -1,3 +1,5 @@
|
|||||||
|
import colorsys
|
||||||
|
import json
|
||||||
import io
|
import io
|
||||||
import logging
|
import logging
|
||||||
import textwrap
|
import textwrap
|
||||||
@@ -7,14 +9,16 @@ import flask
|
|||||||
import lxml.etree as xmltree
|
import lxml.etree as xmltree
|
||||||
import mermaid
|
import mermaid
|
||||||
|
|
||||||
from . import core, gamedata
|
from . import core, gamedata, jsonizer, util
|
||||||
|
|
||||||
pth_upgrade_schema = core.path_appdir / "basepak/rules/schemas/upgrades.xsd"
|
pth_upgrade_schema = core.path_appdir / "basepak/rules/schemas/upgrades.xsd"
|
||||||
doc_upgrade_schema = xmltree.parse(pth_upgrade_schema.as_posix())
|
doc_upgrade_schema = xmltree.parse(pth_upgrade_schema.as_posix())
|
||||||
upgrade_schema = xmltree.XMLSchema(doc_upgrade_schema)
|
upgrade_schema = xmltree.XMLSchema(doc_upgrade_schema)
|
||||||
upgrade_schema_parser = xmltree.XMLParser(schema=upgrade_schema)
|
upgrade_schema_parser = xmltree.XMLParser(schema=upgrade_schema)
|
||||||
|
|
||||||
UpgradeData = namedtuple("UpgradeData", ["id", "name", "desc", "requires"])
|
core.schemas.append((upgrade_schema, "rules/upgrades/**.xml"))
|
||||||
|
|
||||||
|
UpgradeData = namedtuple("UpgradeData", ["id", "name", "desc", "requires", "food", "shinies"])
|
||||||
|
|
||||||
## \brief Renders an upgrade tree.
|
## \brief Renders an upgrade tree.
|
||||||
# \param tree The upgrade tree to retrieve.
|
# \param tree The upgrade tree to retrieve.
|
||||||
@@ -26,19 +30,40 @@ def get_upgrade_tree(tree):
|
|||||||
rulefile = xmltree.parse(gamedata.vfs.open(f"/rules/upgrades/{tree}.xml"), upgrade_schema_parser)
|
rulefile = xmltree.parse(gamedata.vfs.open(f"/rules/upgrades/{tree}.xml"), upgrade_schema_parser)
|
||||||
ruleset = rulefile.getroot()
|
ruleset = rulefile.getroot()
|
||||||
|
|
||||||
|
unlocked = []
|
||||||
|
if len(flask.request.query_string) > 0:
|
||||||
|
for upgrade in flask.request.args.get("unlocked", "").split(","):
|
||||||
|
if len(upgrade) > 0:
|
||||||
|
unlocked.append(upgrade)
|
||||||
|
|
||||||
hnd_treedata = ruleset.xpath("./upgrades:TreeData", namespaces=core.xml_namespaces)[0]
|
hnd_treedata = ruleset.xpath("./upgrades:TreeData", namespaces=core.xml_namespaces)[0]
|
||||||
hnd_name = hnd_treedata.xpath("./upgrades:Name", namespaces=core.xml_namespaces)[0]
|
hnd_name = hnd_treedata.xpath("./upgrades:Name", namespaces=core.xml_namespaces)[0]
|
||||||
hnd_primary_color = hnd_treedata.xpath("./upgrades:PrimaryColor", namespaces=core.xml_namespaces)[0]
|
hnd_primary_color = hnd_treedata.xpath("./upgrades:PrimaryColor", namespaces=core.xml_namespaces)[0]
|
||||||
|
|
||||||
buf_mmd.write(textwrap.dedent(f"""
|
buf_mmd.write(textwrap.dedent(f"""
|
||||||
----
|
---
|
||||||
title: {hnd_name.text}
|
title: {hnd_name.text}
|
||||||
theme: base
|
securityLevel: loose
|
||||||
themeVariables:
|
---
|
||||||
primaryColor: {hnd_primary_color.text}
|
|
||||||
----
|
|
||||||
flowchart LR
|
flowchart LR
|
||||||
"""))
|
""").lstrip())
|
||||||
|
|
||||||
|
rgb_primary_color = util.hex_to_rgb(hnd_primary_color.text)
|
||||||
|
hsv_primary_color = colorsys.rgb_to_hsv(*rgb_primary_color)
|
||||||
|
print(f"{rgb_primary_color} ----> {hsv_primary_color}")
|
||||||
|
hsv_fill_open_color = (hsv_primary_color[0], hsv_primary_color[1] / 2, hsv_primary_color[2])
|
||||||
|
rgb_fill_open_color = colorsys.hsv_to_rgb(*hsv_fill_open_color)
|
||||||
|
hsv_stroke_unlock_color = (hsv_primary_color[0], 1.0, 55)
|
||||||
|
rgb_stroke_unlock_color = colorsys.hsv_to_rgb(*hsv_stroke_unlock_color)
|
||||||
|
hsv_fill_lock_color = (hsv_primary_color[0], 0.1, min(hsv_primary_color[2] * 1.5, 255))
|
||||||
|
rgb_fill_lock_color = colorsys.hsv_to_rgb(*hsv_fill_lock_color)
|
||||||
|
print(f"{hsv_fill_lock_color}, {rgb_fill_lock_color}")
|
||||||
|
hsv_stroke_lock_color = (hsv_primary_color[0], 0.1, 55)
|
||||||
|
rgb_stroke_lock_color = colorsys.hsv_to_rgb(*hsv_stroke_lock_color)
|
||||||
|
|
||||||
|
buf_mmd.write(f" classDef open fill:{util.rgb_to_hex(*rgb_fill_open_color)},stroke:{util.rgb_to_hex(*rgb_primary_color)}\n")
|
||||||
|
buf_mmd.write(f" classDef unlocked fill:{util.rgb_to_hex(*rgb_primary_color)},stroke:{util.rgb_to_hex(*rgb_stroke_unlock_color)}\n")
|
||||||
|
buf_mmd.write(f" classDef locked fill:{util.rgb_to_hex(*rgb_fill_lock_color)},stroke:{util.rgb_to_hex(*rgb_stroke_lock_color)}\n")
|
||||||
|
|
||||||
tree_upgrades = []
|
tree_upgrades = []
|
||||||
for hnd_upgrade in ruleset.iter("{seagull:rules/upgrades}Upgrade"):
|
for hnd_upgrade in ruleset.iter("{seagull:rules/upgrades}Upgrade"):
|
||||||
@@ -48,14 +73,27 @@ def get_upgrade_tree(tree):
|
|||||||
try:
|
try:
|
||||||
hnd_requires = hnd_upgrade.xpath("./upgrades:Requirements", namespaces=core.xml_namespaces)[0]
|
hnd_requires = hnd_upgrade.xpath("./upgrades:Requirements", namespaces=core.xml_namespaces)[0]
|
||||||
require_list = [elem.text for elem in hnd_requires.iter("{seagull:rules/upgrades}Require")]
|
require_list = [elem.text for elem in hnd_requires.iter("{seagull:rules/upgrades}Require")]
|
||||||
|
try:
|
||||||
|
hnd_food = hnd_requires.xpath("./upgrades:Food", namespaces=core.xml_namespaces)[0]
|
||||||
|
except IndexError:
|
||||||
|
hnd_food = None
|
||||||
|
try:
|
||||||
|
hnd_shinies = hnd_requires.xpath("./upgrades:Shinies", namespaces=core.xml_namespaces)[0]
|
||||||
|
except IndexError:
|
||||||
|
hnd_shinies = None
|
||||||
except IndexError:
|
except IndexError:
|
||||||
require_list = []
|
require_list = []
|
||||||
|
hnd_food = None
|
||||||
|
hnd_shinies = None
|
||||||
|
|
||||||
|
|
||||||
upgrade = UpgradeData(
|
upgrade = UpgradeData(
|
||||||
id=hnd_id.text,
|
id=hnd_id.text,
|
||||||
name=hnd_upgrade_name.text,
|
name=hnd_upgrade_name.text,
|
||||||
desc=hnd_desc.text,
|
desc=hnd_desc.text,
|
||||||
requires=require_list
|
requires=require_list,
|
||||||
|
food=int(hnd_food.text) if hnd_food is not None else 0,
|
||||||
|
shinies=int(hnd_shinies.text) if hnd_shinies is not None else 0
|
||||||
)
|
)
|
||||||
|
|
||||||
tree_upgrades.append(upgrade)
|
tree_upgrades.append(upgrade)
|
||||||
@@ -64,7 +102,9 @@ def get_upgrade_tree(tree):
|
|||||||
dependency_lines = []
|
dependency_lines = []
|
||||||
for upgrade in tree_upgrades:
|
for upgrade in tree_upgrades:
|
||||||
deptier = 0
|
deptier = 0
|
||||||
buf_mmd.write(f" {upgrade.id}@{{label: \"{upgrade.name}\"}}\n")
|
upgrade_food_costs = f"🍏{upgrade.food}" if upgrade.food > 0 else ""
|
||||||
|
upgrade_shinies_costs = f"🪙{upgrade.shinies}" if upgrade.shinies > 0 else ""
|
||||||
|
buf_mmd.write(f" {upgrade.id}@{{label: \"{upgrade.name}\n<span style='font-size:0.6em'>{upgrade_food_costs}{upgrade_shinies_costs}</span>\"}}\n")
|
||||||
collected_tiers = []
|
collected_tiers = []
|
||||||
for require in upgrade.requires:
|
for require in upgrade.requires:
|
||||||
if require in tiers:
|
if require in tiers:
|
||||||
@@ -75,14 +115,72 @@ def get_upgrade_tree(tree):
|
|||||||
if len(collected_tiers) > 0:
|
if len(collected_tiers) > 0:
|
||||||
deptier = max(collected_tiers)
|
deptier = max(collected_tiers)
|
||||||
|
|
||||||
tiers[upgrade.id] = deptier + 1
|
tier = deptier + 1
|
||||||
|
tiers[upgrade.id] = tier
|
||||||
|
|
||||||
|
all_requirements_met = True
|
||||||
|
if tier > 1:
|
||||||
|
while all_requirements_met:
|
||||||
|
for require in upgrade.requires:
|
||||||
|
all_requirements_met = require in unlocked
|
||||||
|
|
||||||
|
if not all_requirements_met:
|
||||||
|
buf_mmd.write(f" class {upgrade.id} locked\n")
|
||||||
|
elif upgrade in unlocked:
|
||||||
|
buf_mmd.write(f" class {upgrade.id} unlocked\n")
|
||||||
|
else:
|
||||||
|
buf_mmd.write(f" class {upgrade.id} open\n")
|
||||||
|
buf_mmd.write(f" click {upgrade.id} call purchase_upgrade('{tree}','{upgrade.id}')\n")
|
||||||
|
|
||||||
for line in dependency_lines:
|
for line in dependency_lines:
|
||||||
buf_mmd.write(line)
|
buf_mmd.write(line)
|
||||||
|
|
||||||
buf_mmd.seek(0)
|
buf_mmd.seek(0)
|
||||||
print(buf_mmd.read())
|
mmd_str = buf_mmd.read()
|
||||||
return get_upgrade_tree_mmd(tree) # TEMP
|
mmd_upgradetree = mermaid.Mermaid(mmd_str, height=400)
|
||||||
|
#print(mmd_str)
|
||||||
|
return mmd_upgradetree.svg_response.content
|
||||||
|
|
||||||
|
@core.app.route("/upgrades/<tree>/<upgrade>")
|
||||||
|
def get_upgrade_data(tree, upgrade):
|
||||||
|
rulefile = xmltree.parse(gamedata.vfs.open(f"/rules/upgrades/{tree}.xml"), upgrade_schema_parser)
|
||||||
|
ruleset = rulefile.getroot()
|
||||||
|
|
||||||
|
target_upgrade = None
|
||||||
|
hnd_id = None
|
||||||
|
for hnd_upgrade in ruleset.iter("{seagull:rules/upgrades}Upgrade"):
|
||||||
|
hnd_id = hnd_upgrade.xpath("./upgrades:Id", namespaces=core.xml_namespaces)[0]
|
||||||
|
if hnd_id.text == upgrade:
|
||||||
|
target_upgrade = hnd_upgrade
|
||||||
|
break
|
||||||
|
|
||||||
|
hnd_name = hnd_upgrade.xpath("./upgrades:Name", namespaces=core.xml_namespaces)[0]
|
||||||
|
hnd_desc = hnd_upgrade.xpath("./upgrades:Desc", namespaces=core.xml_namespaces)[0]
|
||||||
|
try:
|
||||||
|
hnd_requires = hnd_upgrade.xpath("./upgrades:Requirements", namespaces=core.xml_namespaces)[0]
|
||||||
|
require_list = [elem.text for elem in hnd_requires.iter("{seagull:rules/upgrades}Require")]
|
||||||
|
try:
|
||||||
|
hnd_food = hnd_requires.xpath("./upgrades:Food", namespaces=core.xml_namespaces)[0]
|
||||||
|
except IndexError:
|
||||||
|
hnd_food = None
|
||||||
|
try:
|
||||||
|
hnd_shinies = hnd_requires.xpath("./upgrades:Shinies", namespaces=core.xml_namespaces)[0]
|
||||||
|
except IndexError:
|
||||||
|
hnd_shinies = None
|
||||||
|
except IndexError:
|
||||||
|
hnd_requires = None
|
||||||
|
hnd_shinies = None
|
||||||
|
hnd_food = None
|
||||||
|
require_list = []
|
||||||
|
|
||||||
|
return flask.make_response(json.dumps({
|
||||||
|
"id": hnd_id.text,
|
||||||
|
"name": hnd_name.text,
|
||||||
|
"desc": hnd_desc.text,
|
||||||
|
"food": int(hnd_food.text) if hnd_food else 0,
|
||||||
|
"shinies": int(hnd_shinies.text) if hnd_shinies else 0,
|
||||||
|
"requires": require_list
|
||||||
|
}, cls=jsonizer.JSONizer), 200)
|
||||||
|
|
||||||
def get_upgrade_tree_mmd(tree):
|
def get_upgrade_tree_mmd(tree):
|
||||||
if not gamedata.vfs.exists(f"upgrades/{tree}.mmd"):
|
if not gamedata.vfs.exists(f"upgrades/{tree}.mmd"):
|
||||||
|
6
app/pylocal/util.py
Normal file
6
app/pylocal/util.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
def hex_to_rgb(hex: str):
|
||||||
|
hex = hex.lstrip("#")
|
||||||
|
return tuple(int(hex[i:i+2], 16) for i in (0, 2, 4))
|
||||||
|
|
||||||
|
def rgb_to_hex(r: int, g: int, b: int):
|
||||||
|
return f"#{int(r):0>2x}{int(g):0>2x}{int(b):0>2x}"
|
@@ -1,57 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
srcdir=$(pwd)
|
|
||||||
BUILD_DIR=${BUILD_DIR:-$srcdir/build}
|
|
||||||
CACHE_DIR=${CACHE_DIR:-$srcdir/build_cache}
|
|
||||||
echo "$srcdir => $BUILD_DIR"
|
|
||||||
|
|
||||||
die () {
|
|
||||||
echo "$@" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
findcmd () {
|
|
||||||
command -v $1 || die "missing command: $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
findcmd cargo
|
|
||||||
findcmd python
|
|
||||||
findcmd rsync
|
|
||||||
|
|
||||||
mkdir -p $BUILD_DIR && cd $BUILD_DIR
|
|
||||||
mkdir -p $CACHE_DIR
|
|
||||||
rsync -rv --include-from=$srcdir/.rsync-include $srcdir/ $BUILD_DIR/
|
|
||||||
|
|
||||||
# rant
|
|
||||||
if [[ -f $CACHE_DIR/rant.tar.zst ]]; then
|
|
||||||
pv -bprt -N "unpacking: rant" $CACHE_DIR/rant.tar.zst | tar -x --zstd -f -
|
|
||||||
else
|
|
||||||
mkdir -p opt/rant
|
|
||||||
cargo install rant --version 4.0.0-alpha.33 --root $BUILD_DIR/opt/rant --features cli
|
|
||||||
tar -c -f - --zstd opt/rant | pv -bprt -N "caching: rant" > $CACHE_DIR/rant.tar.zst
|
|
||||||
fi
|
|
||||||
python $srcdir/render-wordlists.py -i $srcdir/ext/imsky/wordlists -o rant $BUILD_DIR/app/rant/wordlist.rant
|
|
||||||
|
|
||||||
# python venv
|
|
||||||
if [[ -f $CACHE_DIR/pyvenv.tar.zst ]]; then
|
|
||||||
pv -bprt -N "unpacking: pyvenv" $CACHE_DIR/pyvenv.tar.zst | tar -x --zstd -f -
|
|
||||||
source pyvenv/bin/activate
|
|
||||||
else
|
|
||||||
python -m venv pyvenv
|
|
||||||
source pyvenv/bin/activate
|
|
||||||
pip install -r app/requirements.txt
|
|
||||||
pip install -r app/requirements-build-desktop.txt
|
|
||||||
pip install -r app/requirements-desktop.txt
|
|
||||||
[[ $(uname -s) == "Linux" ]] && pip install -r app/requirements-desktop-linux.txt
|
|
||||||
#[[ $(uname -s) == "Darwin" ]] && pip install -r app/requirements-desktop-macos.txt
|
|
||||||
tar -c -f - --zstd pyvenv | pv -bprt -N "caching: pyvenv" > $CACHE_DIR/pyvenv.tar.zst
|
|
||||||
fi
|
|
||||||
|
|
||||||
pyinstaller seagull.spec
|
|
||||||
deactivate
|
|
||||||
|
|
||||||
cd $srcdir
|
|
||||||
cp -fv $BUILD_DIR/dist/seagull $srcdir
|
|
||||||
rm -fr $BUILD_DIR
|
|
||||||
du -sh seagull
|
|
||||||
echo "You should be able to run ./seagull now"
|
|
10
build-pak.sh
10
build-pak.sh
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# ('app/templates', './templates'),
|
|
||||||
# ('app/rules', './rules'),
|
|
||||||
# ('static', './static'),
|
|
||||||
# ('app/rant', './rant'),
|
|
||||||
# ('opt', './opt')
|
|
||||||
|
|
||||||
zip -7rv seagull.pak static
|
|
||||||
cd app
|
|
||||||
zip -7rv ../seagull.pak templates rules rant
|
|
@@ -7,6 +7,10 @@
|
|||||||
<Upgrade>
|
<Upgrade>
|
||||||
<Id>speed1</Id>
|
<Id>speed1</Id>
|
||||||
<Name>Speedier Seagull</Name>
|
<Name>Speedier Seagull</Name>
|
||||||
|
<Requirements>
|
||||||
|
<Food>100</Food>
|
||||||
|
<Agility>1</Agility>
|
||||||
|
</Requirements>
|
||||||
<Modifiers>
|
<Modifiers>
|
||||||
<Mod Id="up_speed1" Name="Upgrade: Speedier Seagull" Speed="5" />
|
<Mod Id="up_speed1" Name="Upgrade: Speedier Seagull" Speed="5" />
|
||||||
</Modifiers>
|
</Modifiers>
|
||||||
@@ -18,6 +22,7 @@
|
|||||||
<Desc>Applying a thin coat of old french fry oil makes you much faster. Why do humans throw this stuff out?</Desc>
|
<Desc>Applying a thin coat of old french fry oil makes you much faster. Why do humans throw this stuff out?</Desc>
|
||||||
<Requirements>
|
<Requirements>
|
||||||
<Require>speed1</Require>
|
<Require>speed1</Require>
|
||||||
|
<Food>150</Food>
|
||||||
</Requirements>
|
</Requirements>
|
||||||
<Modifiers>
|
<Modifiers>
|
||||||
<Mod Id="up_speed2" Name="Upgrade: Greased Wings" Speed="10" />
|
<Mod Id="up_speed2" Name="Upgrade: Greased Wings" Speed="10" />
|
||||||
@@ -30,6 +35,10 @@
|
|||||||
<Mod Id="up_theft_chance1" Name="Upgrade: Swooping Techniques" ChanceSteal="10" />
|
<Mod Id="up_theft_chance1" Name="Upgrade: Swooping Techniques" ChanceSteal="10" />
|
||||||
</Modifiers>
|
</Modifiers>
|
||||||
<Desc>It's all in the neck. The wings are just the steering wheel. You gain a bonus on all dice rolls for stealing.</Desc>
|
<Desc>It's all in the neck. The wings are just the steering wheel. You gain a bonus on all dice rolls for stealing.</Desc>
|
||||||
|
<Requirements>
|
||||||
|
<Food>100</Food>
|
||||||
|
<Agility>1</Agility>
|
||||||
|
</Requirements>
|
||||||
</Upgrade>
|
</Upgrade>
|
||||||
<Upgrade>
|
<Upgrade>
|
||||||
<Id>theft_chance2</Id>
|
<Id>theft_chance2</Id>
|
||||||
@@ -37,6 +46,7 @@
|
|||||||
<Desc>It's a lot easier to steal things if the previous owner doesn't see you coming. This technique gives you a bigger bonus on stealing rolls.</Desc>
|
<Desc>It's a lot easier to steal things if the previous owner doesn't see you coming. This technique gives you a bigger bonus on stealing rolls.</Desc>
|
||||||
<Requirements>
|
<Requirements>
|
||||||
<Require>theft_chance1</Require>
|
<Require>theft_chance1</Require>
|
||||||
|
<Food>150</Food>
|
||||||
</Requirements>
|
</Requirements>
|
||||||
<Modifiers>
|
<Modifiers>
|
||||||
<Mod Id="up_theft_chance2" Name="Upgrade: The Element of Surprise" ChanceSteal="15" />
|
<Mod Id="up_theft_chance2" Name="Upgrade: The Element of Surprise" ChanceSteal="15" />
|
||||||
|
66
pak/rules/upgrades/instinct.xml
Normal file
66
pak/rules/upgrades/instinct.xml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<UpgradeRules xmlns="seagull:rules/upgrades">
|
||||||
|
<TreeData>
|
||||||
|
<Name>Instinct Upgrades</Name>
|
||||||
|
<PrimaryColor>#aa00ff</PrimaryColor>
|
||||||
|
</TreeData>
|
||||||
|
<Upgrade>
|
||||||
|
<Id>xp_bonus1</Id>
|
||||||
|
<Name>Stop and Smell</Name>
|
||||||
|
<Requirements>
|
||||||
|
<Food>100</Food>
|
||||||
|
<Instinct>1</Instinct>
|
||||||
|
</Requirements>
|
||||||
|
<Modifiers>
|
||||||
|
<Mod Id="up_xp_bonus1" Name="Upgrade: Stop and Smell" XPPerc="2" />
|
||||||
|
</Modifiers>
|
||||||
|
<Desc>Who knew taking in the smells could make you wiser? Enjoy a 2% bonus to XP.</Desc>
|
||||||
|
</Upgrade>
|
||||||
|
<Upgrade>
|
||||||
|
<Id>xp_bonus2</Id>
|
||||||
|
<Name>Ponder and Deliberate</Name>
|
||||||
|
<Modifiers>
|
||||||
|
<Mod Id="up_xp_bonus2" Name="Upgrade: Ponder and Deliberate" XPPerc="5" />
|
||||||
|
</Modifiers>
|
||||||
|
<Requirements>
|
||||||
|
<Require>xp_bonus1</Require>
|
||||||
|
<Food>150</Food>
|
||||||
|
</Requirements>
|
||||||
|
<Desc>Take a second to really think about what you're trying to steal. You'll get a 5% XP bonus if you do.</Desc>
|
||||||
|
</Upgrade>
|
||||||
|
<Upgrade>
|
||||||
|
<Id>xp_bonus3</Id>
|
||||||
|
<Name>Plan and Strategize</Name>
|
||||||
|
<Modifiers>
|
||||||
|
<Mod Id="up_xp_bonus3" Name="Upgrade: Plan and Strategize" XPPerc="10" />
|
||||||
|
</Modifiers>
|
||||||
|
<Requirements>
|
||||||
|
<Require>xp_bonus2</Require>
|
||||||
|
<Require>theft_results2</Require>
|
||||||
|
</Requirements>
|
||||||
|
<Desc>Have a plan to steal from everyone you meet. Even the ones you don't execute on will grant you an additional 10% XP.</Desc>
|
||||||
|
</Upgrade>
|
||||||
|
<Upgrade>
|
||||||
|
<Id>theft_results1</Id>
|
||||||
|
<Name>Go for the Pockets</Name>
|
||||||
|
<Desc>That's where they keep their stuff. Steal a little bit more from everyone.</Desc>
|
||||||
|
<Requirements>
|
||||||
|
<Food>100</Food>
|
||||||
|
</Requirements>
|
||||||
|
<Modifiers>
|
||||||
|
<Mod Id="up_theft_results1" Name="Upgrade: Go for the Pockets" StealPerc="5" />
|
||||||
|
</Modifiers>
|
||||||
|
</Upgrade>
|
||||||
|
<Upgrade>
|
||||||
|
<Id>theft_results2</Id>
|
||||||
|
<Name>Use the Winds</Name>
|
||||||
|
<Desc>The wind provides extra speed, making you both faster and capable of taking more.</Desc>
|
||||||
|
<Requirements>
|
||||||
|
<Require>theft_results1</Require>
|
||||||
|
<Food>200</Food>
|
||||||
|
</Requirements>
|
||||||
|
<Modifiers>
|
||||||
|
<Mod Id="up_theft_results2" Name="Upgrade: Use the Winds" Speed="2" StealPerc="10" />
|
||||||
|
</Modifiers>
|
||||||
|
</Upgrade>
|
||||||
|
</UpgradeRules>
|
20
pak/rules/upgrades/leadership.xml
Normal file
20
pak/rules/upgrades/leadership.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8"?>
|
||||||
|
<UpgradeRules xmlns="seagull:rules/upgrades">
|
||||||
|
<TreeData>
|
||||||
|
<Name>Leadership Upgrades</Name>
|
||||||
|
<PrimaryColor>#ffaa00</PrimaryColor>
|
||||||
|
</TreeData>
|
||||||
|
<Upgrade>
|
||||||
|
<Id>recruit_chance1</Id>
|
||||||
|
</Upgrade>
|
||||||
|
<Upgrade>
|
||||||
|
<Id>offline_gen</Id>
|
||||||
|
<Name>Tireless Colony</Name>
|
||||||
|
<Requirements>
|
||||||
|
<Food>100</Food>
|
||||||
|
<Shinies>100</Shinies>
|
||||||
|
<Leadership>1</Leadership>
|
||||||
|
</Requirements>
|
||||||
|
<Desc>Your colony starts taking shifts to get resources for you. A percentage of colony-generation continues even when you close the game.</Desc>
|
||||||
|
</Upgrade>
|
||||||
|
</UpgradeRules>
|
@@ -19,10 +19,16 @@ function update_charsheet() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function purchase_upgrade(tree, upgrade) {
|
||||||
|
var upgrade_data = await fetch(`/upgrades/${tree}/${upgrade}`)
|
||||||
|
.then(res => res.text())
|
||||||
|
console.log(upgrade_data)
|
||||||
|
}
|
||||||
|
|
||||||
async function display_tree(tree) {
|
async function display_tree(tree) {
|
||||||
var upgrade_tree = await fetch(`/upgrades/${tree}`)
|
var upgrade_tree = await fetch(`/upgrades/${tree}`)
|
||||||
.then(res => res.text())
|
.then(res => res.text())
|
||||||
console.log(upgrade_tree)
|
//console.log(upgrade_tree)
|
||||||
|
|
||||||
charsheet_elements["blk_tree"].innerHTML = upgrade_tree
|
charsheet_elements["blk_tree"].innerHTML = upgrade_tree
|
||||||
}
|
}
|
||||||
|
13
pak/static/js/seagull-cheats.mjs
Normal file
13
pak/static/js/seagull-cheats.mjs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
export function cheat_resources() {
|
||||||
|
hnd_direction = document.querySelector("#dev-resource-direction");
|
||||||
|
hnd_restype = document.querySelector("#dev-resource-type");
|
||||||
|
hnd_amount = document.querySelector("#dev-resource-amount");
|
||||||
|
|
||||||
|
if (!isEmpty(hnd_amount.value)) {
|
||||||
|
if (hnd_direction == "+") {
|
||||||
|
gamestate[hnd_restype.value] += Number(hnd_amount.value);
|
||||||
|
} else if (hnd_direction == "-") {
|
||||||
|
gamestate[hnd_restype.value] -= Number(hnd_amount.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -48,6 +48,10 @@ const tickdiffs_reset = {
|
|||||||
}
|
}
|
||||||
var tickdiffs = {}
|
var tickdiffs = {}
|
||||||
|
|
||||||
|
globalThis.isEmpty = str => !str.trim().length
|
||||||
|
|
||||||
|
import {cheat_resources} from "./seagull-cheats.mjs"
|
||||||
|
|
||||||
var bool_log_alt = false
|
var bool_log_alt = false
|
||||||
globalThis.record_log = function (text) {
|
globalThis.record_log = function (text) {
|
||||||
const div_logrow = document.createElement("div");
|
const div_logrow = document.createElement("div");
|
||||||
@@ -300,7 +304,7 @@ async function game_tick() {
|
|||||||
ticks_since_last_save += 1;
|
ticks_since_last_save += 1;
|
||||||
page_elements["lbl_tick"].innerHTML = gamestate["tick"];
|
page_elements["lbl_tick"].innerHTML = gamestate["tick"];
|
||||||
|
|
||||||
if (gamestate["tick"] % 5 == 0) {
|
if (gamestate["tick"] % 5 == 0 && gamestate["colony"] > 1) {
|
||||||
var colony_tickdata = await fetch("/tick/colony", {
|
var colony_tickdata = await fetch("/tick/colony", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
@@ -1,2 +1,12 @@
|
|||||||
{% if not desktop %}IP: {{ipaddr}}<br />{% endif %}
|
{% if not desktop %}IP: {{ipaddr}}<br />{% endif %}
|
||||||
<button id="dev-reset" onClick="reset_game()">Reset Game</button>
|
<button id="dev-reset" onClick="reset_game()">Reset Game</button><br />
|
||||||
|
<select id="dev-resource-direction">
|
||||||
|
<option value="+">Grant</option>
|
||||||
|
<option value="-">Remove</option>
|
||||||
|
</select>
|
||||||
|
<select id="dev-resource-type">
|
||||||
|
<option value="food">Food</option>
|
||||||
|
<option value="shinies">Shinies</option>
|
||||||
|
</select>
|
||||||
|
<input type="number" min="0" id="dev-resource-amount" placeholder="∞"/>
|
||||||
|
<button id="dev-resource-txn" onClick="cheat_resources()">➡️</button>
|
@@ -22,7 +22,7 @@ pyz = PYZ(a.pure)
|
|||||||
|
|
||||||
splash = Splash("@CMAKE_SOURCE_DIR@/pak/static/image/splash.png",
|
splash = Splash("@CMAKE_SOURCE_DIR@/pak/static/image/splash.png",
|
||||||
binaries=a.binaries, datas=a.datas,
|
binaries=a.binaries, datas=a.datas,
|
||||||
text_pos=(0,0), text_size=12, text_color="white")
|
text_pos=(10,1), text_size=24, text_color="white")
|
||||||
|
|
||||||
exe = EXE(
|
exe = EXE(
|
||||||
pyz,
|
pyz,
|
||||||
|
Reference in New Issue
Block a user