Compare commits

..

3 Commits

65 changed files with 298 additions and 128 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "khguide"
version = "1.3.0"
version = "1.3.2"
edition = "2024"
[dependencies]

View File

@ -2,6 +2,7 @@ name = "Air Pirate"
[[world]]
name = "Neverland"
rooms = ["Pirate Ship"]
[[drops]]
name = "Hi-Potion"

View File

@ -2,6 +2,11 @@ name = "Air Soldier"
[[world]]
name = "Wonderland"
rooms = ["Lotus Forest"]
[[world]]
name = "End of the World"
rooms = ["World Terminus | Olympus Coliseum"]
[[drops]]
name = "Potion"

View File

@ -2,6 +2,7 @@ name = "Angel Star"
[[world]]
name = "End of the World"
rooms = ["Linked Worlds"]
[[drops]]
name = "Ether"

View File

@ -3,6 +3,10 @@ name = "Aquatank"
[[world]]
name = "Atlantica"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Atlantica"]
[[drops]]
name = "Mega-Potion"
kind = "item"

View File

@ -9,6 +9,7 @@ name = "Monstro"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Agrabah"]
[[drops]]
name = "Potion"

View File

@ -8,6 +8,7 @@ name = "Neverland"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Neverland"]
[[drops]]
name = "Camping Set"

View File

@ -2,6 +2,7 @@ name = "Battleship"
[[world]]
name = "Neverland"
rooms = ["Pirate Ship"]
[[drops]]
name = "Elixir"

View File

@ -2,6 +2,7 @@ name = "Black Ballade"
[[world]]
name = "Deep Jungle"
rooms = ["Bamboo Thicket"]
[[drops]]
name = "Lightning Stone"

View File

@ -5,15 +5,18 @@ name = "Traverse Town"
[[world]]
name = "Wonderland"
rooms = ["Lotus Forest"]
[[world]]
name = "Monstro"
[[world]]
name = "Hollow Bastion"
rooms = ["Entrance Hall"]
[[world]]
name = "End of the World"
rooms = ["World Terminus | Wonderland"]
[[drops]]
name = "Ether"

View File

@ -9,6 +9,7 @@ rooms = ["Bowels", "Stomach"]
[[world]]
name = "End of the World"
rooms = ["World Terminus | Deep Jungle"]
[[drops]]
name = "Hi-Potion"

View File

@ -2,6 +2,7 @@ name = "Chimera"
[[world]]
name = "Halloween Town"
rooms = ["Manor Ruins"]
[[drops]]
name = "Blazing Stone"

View File

@ -2,12 +2,24 @@ name = "Darkball"
[[world]]
name = "Traverse Town"
rooms = ["3rd District", "Gizmo Shop"]
rooms = ["3rd District", "Gizmo Shop", "Alleyway"]
[[world]]
name = "Agrabah"
rooms = ["Bazaar", "Palace Gates"]
[[world]]
name = "Deep Jungle"
rooms = ["Bamboo Thicket"]
[[world]]
name = "Wonderland"
rooms = ["Lotus Forest"]
[[world]]
name = "Halloween Town"
rooms = ["Moonlight Hill"]
[[world]]
name = "Hollow Bastion"

View File

@ -6,9 +6,11 @@ rooms = ["3rd District", "Hotel Hallway", "Gizmo Shop"]
[[world]]
name = "Hollow Bastion"
rooms = ["Entrance Hall"]
[[world]]
name = "End of the World"
rooms = ["World Terminus | Olympus Coliseum"]
[[drops]]
name = "Elixir"

View File

@ -8,6 +8,7 @@ name = "Monstro"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Agrabah"]
[[drops]]
name = "Hi-Potion"

View File

@ -1,10 +1,12 @@
name = "Gargoyle"
[[world]]
name = "Holloween Town"
name = "Halloween Town"
rooms = ["Graveyard"]
[[world]]
name = "End of the World"
rooms = ["World Terminus | Halloween Town"]
[[drops]]
name = "Ether"

View File

@ -2,6 +2,7 @@ name = "Gigas Shadow"
[[world]]
name = "Wonderland"
rooms = ["Bizzare Room"]
[[drops]]
name = "Lucid Shard"

View File

@ -11,13 +11,14 @@ name = "Monstro"
[[world]]
name = "Deep Jungle"
rooms = ["Jungle: Cliff"]
rooms = ["Cliff"]
[[world]]
name = "Hollow Bastion"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Wonderland"]
[[drops]]
name = "Ether"

View File

@ -2,6 +2,7 @@ name = "Invisible"
[[world]]
name = "End of the World"
rooms = ["Linked Worlds"]
[[drops]]
name = "Hi-Potion"

View File

@ -2,6 +2,7 @@ name = "Jet Balloon"
[[world]]
name = "Neverland"
rooms = ["Pirate Ship"]
[[drops]]
name = "Dazzling Stone"

View File

@ -15,9 +15,11 @@ name = "Monstro"
[[world]]
name = "Hollow Bastion"
rooms = ["Entrance Hall", "Grand Hall"]
[[world]]
name = "End of the World"
rooms = ["World Terminus | Traverse Town"]
[[drops]]
name = "Hi-Potion"

View File

@ -2,6 +2,7 @@ name = "Neoshadow"
[[world]]
name = "End of the World"
rooms = ["Linked Worlds"]
[[drops]]
name = "Stormy Stone"

View File

@ -9,6 +9,7 @@ name = "Monstro"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Neverland"]
[[drops]]
name = "Hi-Potion"

View File

@ -2,6 +2,7 @@ name = "Powerwild"
[[world]]
name = "Deep Jungle"
rooms = ["Camp", "Cliff"]
[[world]]
name = "Monstro"
@ -9,6 +10,7 @@ rooms = ["Chamber 5", "Chamber 6"]
[[world]]
name = "End of the World"
rooms = ["World Terminus | Deep Jungle"]
[[drops]]
name = "Potion"

View File

@ -4,8 +4,13 @@ name = "Red Nocturne"
name = "Monstro"
rooms = ["Chamber 6"]
[[world]]
name = "Hollow Bastion"
rooms = ["Castle Gates"]
[[world]]
name = "End of the World"
rooms = ["World Terminus | Wonderland"]
[[drops]]
name = "Ether"

View File

@ -5,6 +5,7 @@ name = "Atlantica"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Atlantica"]
[[drops]]
name = "Hi-Potion"

View File

@ -5,6 +5,7 @@ name = "Atlantica"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Atlantica"]
[[drops]]
name = "Ether"

View File

@ -8,12 +8,14 @@ name = "Monstro"
[[world]]
name = "Traverse Town"
rooms = ["2nd District"]
[[world]]
name = "Atlantica"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Halloween Town"]
[[drops]]
name = "Hi-Potion"

View File

@ -5,6 +5,7 @@ name = "Atlantica"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Atlantica"]
[[drops]]
name = "Ether"

View File

@ -2,6 +2,7 @@ name = "Sniperwild"
[[world]]
name = "Traverse Town"
rooms = ["2nd District"]
[[drops]]
name = "Power Stone"

View File

@ -4,6 +4,10 @@ name = "Soldier"
name = "Agrabah"
rooms = ["Main Street"]
[[world]]
name = "End of the World"
rooms = ["World Terminus | Traverse Town"]
[[drops]]
name = "Spirit Shard"
kind = "material"

View File

@ -2,6 +2,7 @@ name = "Stealth Soldier"
[[world]]
name = "Hollow Bastion"
rooms = ["Entrance Hall", "Grand Hall"]
[[drops]]
name = "Energy Stone"

View File

@ -1,10 +1,12 @@
name = "Wight Knight"
[[world]]
name = "Holloween Town"
name = "Halloween Town"
rooms = ["Graveyard", "Manor Ruins"]
[[world]]
name = "End of the World"
rooms = ["World Terminus | Halloween Town"]
[[drops]]
name = "Hi-Potion"

View File

@ -1,22 +1,29 @@
name = "Wizard"
[[world]]
name = "Holloween Town"
name = "Halloween Town"
[[world]]
name = "Traverse Town"
rooms = ["Alleyway", "Hotel Hallway"]
[[world]]
name = "Wonderland"
[[world]]
name = "Deep Jungle"
rooms = ["Camp", "Bamboo Thicket"]
[[world]]
name = "Agrabah"
[[world]]
name = "Hollow Bastion"
rooms = ["Castle Gates", "Entrance Hall", "Grand Hall"]
[[world]]
name = "End of the World"
rooms = ["World Terminus | Wonderland"]
[[drops]]
name = "Ether"

View File

@ -5,15 +5,18 @@ name = "Hollow Bastion"
[[world]]
name = "Traverse Town"
rooms = ["2nd District"]
[[world]]
name = "Deep Jungle"
rooms = ["Camp", "Cliff"]
[[world]]
name = "Agrabah"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Olympus Coliseum"]
[[drops]]
name = "Hi-Potion"

View File

@ -4,7 +4,8 @@ name = "Yellow Opera"
name = "Traverse Town"
[[world]]
name = "Neverland"
name = "Wonderland"
rooms = ["Lotus Forest"]
[[world]]
name = "Agrabah"
@ -17,6 +18,7 @@ name = "Monstro"
[[world]]
name = "End of the World"
rooms = ["World Terminus | Wonderland"]
[[drops]]
name = "Ether"

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -14,26 +14,35 @@ function toggleWorldDisplay(display) {
const enemyWorlds = display.querySelector(".worlds");
const worldsWrapper = display.querySelectorAll(".worlds > div");
const worldsIcons = display.querySelectorAll(".worlds > div > img");
const worldsIcons = display.querySelectorAll(".worlds > div > .icon");
const worldsNames = display.querySelectorAll(".worlds > div > .info");
if (!showWorlds) {
enemyWorlds.style.width = "32px";
for (const wrapper of worldsWrapper) {
wrapper.style.height = "32px";
wrapper.style["margin-bottom"] = "16px";
}
for (const icon of worldsIcons) {
icon.width = "32";
icon.height = "32";
}
for (const name of worldsNames) {
name.style.display = "none";
}
} else {
enemyWorlds.style.width = "256px";
for (const wrapper of worldsWrapper) {
wrapper.style.height = "auto";
wrapper.style["margin-bottom"] = "0px";
}
for (const icon of worldsIcons) {
icon.width = "64";
icon.height = "64";
}
for (const name of worldsNames) {
name.style.display = "block";
}
}
display.dataset["showWorlds"] = !showWorlds;

View File

@ -30,7 +30,7 @@ table {
margin-top: 10px;
thead th {
background-color: #252525;
background-color: var(--bg-dark-color);
}
}
@ -39,39 +39,34 @@ ul {
}
a {
color: #00ff00;
color: var(--link-color);
text-decoration: none;
&:hover {
color: #9dff9d;
&:visited {
color: var(--link-visited-color);
}
&:visited {
color: #00a200;
&:hover {
color: #65a565;
}
&:hover {
color: var(--link-hover-color);
}
}
button {
margin-left: 16px;
background: #444;
color: #fff;
background: var(--button-bg-color);
color: var(--text-color);
padding: 8px;
border-color: #555;
border-bottom-color: rgb(85, 85, 85);
border-color: var(--button-border-color);
border-style: groove;
border-bottom-color: #0a0;
border-bottom-color: var(--primary-color);
transition-duration: 0.1s;
&:hover {
background: #4f4f4f;
background: var(--button-hover-bg-color);
}
&:active {
background: #3f3f3f;
background: var(--button-active-bg-color);
transform: translateY(1px);
}
@ -80,3 +75,46 @@ button {
cursor: not-allowed;
}
}
input[type="checkbox"] {
appearance: none;
position: relative;
cursor: pointer;
width: 24px;
height: 24px;
padding-top: 8px;
& + label {
cursor: pointer;
}
&::before {
position: absolute;
width: 100%;
height: 100%;
content: "";
background-color: var(--bg-dark-color);
border: 1px solid var(--button-border-color);
border-radius: 5px;
}
&:hover::before {
background-color: var(--bg-light-color);
}
&:checked::after {
position: absolute;
content: "\2713";
color: var(--primary-color);
font-size: 48px;
top: -10px;
left: -4px;
align-content: center;
text-align: center;
white-space: pre;
}
&:checked:hover::after {
color: var(--primary-light-color);
}
}

View File

@ -1,4 +1,18 @@
:root {
--bg-color: #333;
--bg-dark-color: #252525;
--bg-light-color: #545454;
--text-color: #fff;
--link-color: #0f0;
--link-hover-color: #9dff9d;
--link-visited-color: #00a200;
--button-bg-color: #444;
--button-hover-bg-color: #4f4f4f;
--button-active-bg-color: #3f3f3f;
--button-border-color: #555;
--primary-color: #00aa00;
--primary-light-color: #60de60;
}

View File

@ -55,15 +55,45 @@
overflow-x: hidden;
overflow-y: auto;
:first-child {
margin-top: 16px;
}
div {
display: inline-flex;
margin-bottom: 16px;
font-size: 14px;
align-items: center;
p {
.icon {
background-repeat: no-repeat;
background-position: center;
background-size: contain;
width: 64px;
height: 64px;
}
.info {
margin-left: 8px;
margin-bottom: 0px;
ul {
padding-left: 24px;
margin-bottom: 0;
}
}
}
}
}
.material-filters {
display: flex;
flex-wrap: wrap;
width: 40%;
row-gap: 20px;
position: relative;
}
.tracked-filter {
margin-bottom: 16px;
}

View File

@ -1,6 +1,7 @@
use serde::Deserialize;
pub mod direction;
pub mod drops;
pub mod enemy;
pub mod materials;
pub mod synthesis;

View File

@ -0,0 +1,45 @@
use itertools::Itertools;
use super::{Game, enemy::Enemy, materials::MaterialDrops};
#[derive(Debug, PartialEq, Eq)]
pub struct Drops {
pub game: Game,
pub drops: Vec<MaterialDrops>,
pub material_kinds: Vec<String>,
filter_max_len: usize,
}
impl Drops {
pub fn new(game: Game, enemies: Vec<Enemy>) -> Self {
let drops = MaterialDrops::new(enemies);
let material_kinds = drops
.iter()
.map(|d| d.category.get_category(&Game::Kh1))
.dedup()
.collect::<Vec<_>>();
let mut filter_max_len: usize = 0;
for kind in &material_kinds {
if kind.len() > filter_max_len {
filter_max_len = kind.len();
}
}
filter_max_len *= 10;
filter_max_len += 60;
Self {
game,
drops,
material_kinds,
filter_max_len,
}
}
pub fn get_filter_len(&self) -> usize {
self.filter_max_len
}
}

View File

@ -3,15 +3,15 @@ use std::collections::HashMap;
use serde::Deserialize;
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq)]
pub struct SynthesisData {
pub struct Synthesis {
pub sets: Vec<SynthesisSet>,
pub recipes: Vec<SynthesisRecipe>,
}
impl SynthesisData {
pub fn new(path: &str) -> SynthesisData {
impl Synthesis {
pub fn new(path: &str) -> Synthesis {
let str = std::fs::read_to_string(path).unwrap();
let mut data = toml::from_str::<SynthesisData>(&str).unwrap();
let mut data = toml::from_str::<Synthesis>(&str).unwrap();
for recipe in &mut data.recipes {
for set in &data.sets {

View File

@ -1,9 +1,8 @@
use askama::Template;
use itertools::Itertools;
use crate::{
RuntimeModule,
common::{Game, enemy::Enemy, materials::MaterialDrops, synthesis::SynthesisData},
common::{Game, drops::Drops, enemy::Enemy, synthesis::Synthesis},
create_file,
};
@ -13,15 +12,13 @@ const SYNTHESIS_PATH: &str = "./input/kh1/synthesis.toml";
#[derive(Template)]
#[template(path = "pages/kh1/drops.html")]
struct DropsTemplate {
pub game: Game,
pub drops: Vec<MaterialDrops>,
pub material_kinds: Vec<String>,
pub data: Drops,
}
#[derive(Template)]
#[template(path = "pages/kh1/synth.html")]
struct SynthTemplate {
pub data: SynthesisData,
pub data: Synthesis,
}
pub struct Module;
@ -31,22 +28,13 @@ impl RuntimeModule for Module {
tracing::info!("Loading enemy data from {}", ENEMIES_PATH);
let enemies = Enemy::import(ENEMIES_PATH);
let drops = MaterialDrops::new(enemies);
let material_kinds = drops
.iter()
.map(|d| d.category.get_category(&Game::Kh1))
.dedup()
.collect();
let drops = Drops::new(Game::Kh1, enemies);
tracing::info!("Loading synthesis data from {}", SYNTHESIS_PATH);
let synth = SynthesisData::new(SYNTHESIS_PATH);
let synth = Synthesis::new(SYNTHESIS_PATH);
tracing::info!("Generating the KH1 drops template");
let drops_template = DropsTemplate {
game: Game::Kh1,
drops,
material_kinds,
};
let drops_template = DropsTemplate { data: drops };
create_file("./out/kh1", "drops", drops_template).unwrap();

View File

@ -1,9 +1,8 @@
use askama::Template;
use itertools::Itertools;
use crate::{
RuntimeModule,
common::{Game, enemy::Enemy, materials::MaterialDrops},
common::{Game, drops::Drops, enemy::Enemy},
create_file,
};
@ -12,9 +11,7 @@ const ENEMIES_PATH: &str = "./input/kh2/enemies";
#[derive(Template)]
#[template(path = "pages/kh2/drops.html")]
struct DropsTemplate {
pub game: Game,
pub drops: Vec<MaterialDrops>,
pub material_kinds: Vec<String>,
pub data: Drops,
}
pub struct Module;
@ -24,19 +21,10 @@ impl RuntimeModule for Module {
tracing::info!("Loading enemy data from {}", ENEMIES_PATH);
let enemies = Enemy::import(ENEMIES_PATH);
let drops = MaterialDrops::new(enemies);
let material_kinds = drops
.iter()
.map(|d| d.category.get_category(&Game::Kh2))
.dedup()
.collect();
let drops = Drops::new(Game::Kh2, enemies);
tracing::info!("Generating the KH2 drops template");
let drops_template = DropsTemplate {
game: Game::Kh2,
drops,
material_kinds,
};
let drops_template = DropsTemplate { data: drops };
create_file("./out/kh2", "drops", drops_template).unwrap();
}

View File

@ -1,10 +1,9 @@
use askama::Template;
use food::Recipes;
use itertools::Itertools;
use crate::{
RuntimeModule,
common::{Game, enemy::Enemy, materials::MaterialDrops},
common::{Game, drops::Drops, enemy::Enemy},
create_file,
};
@ -16,9 +15,7 @@ const RECIPES_PATH: &str = "./input/kh3/recipes.toml";
#[derive(Template)]
#[template(path = "pages/kh3/drops.html")]
struct DropsTemplate {
pub game: Game,
pub drops: Vec<MaterialDrops>,
pub material_kinds: Vec<String>,
pub data: Drops,
}
#[derive(Template)]
@ -34,23 +31,14 @@ impl RuntimeModule for Module {
tracing::info!("Loading enemy data from {}", ENEMIES_PATH);
let enemies = Enemy::import(ENEMIES_PATH);
let drops = MaterialDrops::new(enemies);
let material_kinds = drops
.iter()
.map(|d| d.category.get_category(&Game::Kh3))
.dedup()
.collect();
let drops = Drops::new(Game::Kh3, enemies);
tracing::info!("Loading recipes data from {}", RECIPES_PATH);
let recipes_str = std::fs::read_to_string(RECIPES_PATH).unwrap();
let recipes = toml::from_str::<Recipes>(&recipes_str).unwrap();
tracing::info!("Generating the KH3 drops template");
let drops_template = DropsTemplate {
game: Game::Kh3,
drops,
material_kinds,
};
let drops_template = DropsTemplate { data: drops };
create_file("./out/kh3", "drops", drops_template).unwrap();

View File

@ -1,9 +1,31 @@
{% include "components/common/only-tracked-filter.html" %}
<br />
{% include "components/common/kind-filters.html" %}
<div class="tracked-filter">
<input
type="checkbox"
id="onlyTracked"
name="onlyTracked"
autocomplete="off"
value=""
/>
<label for="onlyTracked">Show only tracked</label>
</div>
<div class="material-filters">
{% for kind in data.material_kinds %}
<div style="flex: 0 1 {{+ data.get_filter_len() }}px;">
<input
type="checkbox"
id="{{ kind }}Filter"
name="kindFilter"
autocomplete="off"
value="{{ kind }}"
/>
<label for="{{ kind }}Filter">{{ kind|capitalize }}</label>
</div>
{% endfor %}
</div>
<br />
{% for drop in drops %}
{% for drop in data.drops %}
{% call macros::drop("shard") %}
{% call macros::drop("stone") %}
{% call macros::drop("gem") %}

View File

@ -1,13 +0,0 @@
{% for kind in material_kinds %}
<input
type="checkbox"
id="{{ kind }}Filter"
name="kindFilter"
autocomplete="off"
value="{{ kind }}"
/>
<label for="{{ kind }}Filter">{{ kind|capitalize }}</label>
{% if loop.index0 == 6 %}
<br />
{% endif %}
{% endfor %}

View File

@ -1,8 +0,0 @@
<input
type="checkbox"
id="onlyTracked"
name="onlyTracked"
autocomplete="off"
value=""
/>
<label for="onlyTracked">Show only tracked</label>

View File

@ -3,12 +3,12 @@
{% if drops.len() > 0 %}
<div
class="category-wrapper"
data-mat-kind="{{ drop.category.get_category(game) }}"
data-mat-kind="{{ drop.category.get_category(data.game) }}"
data-mat-type="{{ label }}"
>
<div class="category">
<img
src="../public/assets/materials/{{ drop.texture(game) }}.webp"
src="../public/assets/materials/{{ drop.texture(data.game) }}.webp"
width="64"
height="64"
/>
@ -27,29 +27,20 @@
</div>
<div class="worlds">
{% for spawn in drop.spawns %}
{% if spawn.rooms.len() > 0 %}
{% for room in spawn.rooms %}
<div>
<img
src="../public/assets/worlds/{{ spawn.texture() }}.webp"
width="64"
height="64"
/>
<p>
{{ spawn.name +}} - {{+ room }}
</p>
</div>
{% endfor %}
{% else %}
<div>
<img
src="../public/assets/worlds/{{ spawn.texture() }}.webp"
width="64"
height="64"
/>
<div>
<div
class="icon"
style="background-image: url('../public/assets/worlds/{{ spawn.texture() }}.webp');"
></div>
<div class="info">
<p>{{ spawn.name }}</p>
<ul>
{% for room in spawn.rooms %}
<li>{{+ room }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>