Skip to content

Commit 2007dcb

Browse files
committed
Warn about auto calc spell vendors
1 parent ff5452f commit 2007dcb

6 files changed

Lines changed: 44 additions & 10 deletions

File tree

WARNINGS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ This NPC has a class that is not suitable for use in this province.
113113
Spells have names that are visible to the player (either when buying them or when being affected by them.)
114114
These names imply a certain culture, meaning NPCs outside of Morrowind should not receive vanilla spells.
115115

116+
### Is a spell vendor with auto calculated spells
117+
Auto calculated spell lists tend to be trash.
118+
116119
### Is not using unique head/hair
117120
This NPC should be using the asset designed for it.
118121

crates/codegen/data/services.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,14 @@
2020
"Trader Service",
2121
"T_Glb_TraderService",
2222
"Wise Woman Service"
23+
],
24+
"spells": [
25+
"Battlemage Service",
26+
"T_Sky_Clever-Man",
27+
"Healer Service",
28+
"Mage Service",
29+
"Nightblade Service",
30+
"Priest Service",
31+
"Sorcerer Service"
2332
]
2433
}

crates/codegen/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ pub fn get_barter_classes(_: TokenStream) -> TokenStream {
4848
services_data::generate_barter_classes().into()
4949
}
5050

51+
#[proc_macro]
52+
pub fn get_spell_vendor_classes(_: TokenStream) -> TokenStream {
53+
services_data::generate_spell_vendor_classes().into()
54+
}
55+
5156
#[proc_macro]
5257
pub fn get_spell_data(_: TokenStream) -> TokenStream {
5358
spells_data::generate().into()

crates/codegen/src/services_data.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ use serde::Deserialize;
55
#[derive(Deserialize)]
66
pub struct Services {
77
barter: Vec<String>,
8+
spells: Vec<String>,
89
}
910

10-
pub fn generate_barter_classes() -> TokenStream {
11-
let data: Services = serde_json::from_str(include_str!("../data/services.json")).unwrap();
12-
13-
let len = data.barter.len();
14-
let values = data.barter.iter().map(|id| id.to_ascii_lowercase());
11+
fn get_class_tokens(classes: Vec<String>) -> TokenStream {
12+
let len = classes.len();
13+
let values = classes.iter().map(|id| id.to_ascii_lowercase());
1514

1615
quote! {
1716
{
@@ -24,3 +23,13 @@ pub fn generate_barter_classes() -> TokenStream {
2423
}
2524
.into_token_stream()
2625
}
26+
27+
pub fn generate_barter_classes() -> TokenStream {
28+
let data: Services = serde_json::from_str(include_str!("../data/services.json")).unwrap();
29+
get_class_tokens(data.barter)
30+
}
31+
32+
pub fn generate_spell_vendor_classes() -> TokenStream {
33+
let data: Services = serde_json::from_str(include_str!("../data/services.json")).unwrap();
34+
get_class_tokens(data.spells)
35+
}

src/validators/ids.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ impl Handler<'_> for IdValidator {
9898
println!("Found dirty {} {}", record.type_name(), record.editor_id());
9999
}
100100
TES3Object::GlobalVariable(_) => {
101-
if context.mode != Mode::TD || !record.editor_id().eq_ignore_ascii_case("MWSE_BUILD")
101+
if context.mode != Mode::TD
102+
|| !record.editor_id().eq_ignore_ascii_case("MWSE_BUILD")
102103
{
103104
check_id(context, record);
104105
self.check_known(record);

src/validators/services.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::collections::HashSet;
22

33
use super::Context;
44
use crate::{handlers::Handler, util::is_autocalc};
5-
use codegen::get_barter_classes;
5+
use codegen::{get_barter_classes, get_spell_vendor_classes};
66
use tes3::esp::{AiData, ServiceFlags, TES3Object};
77

88
const SERVICE_FLAGS_BARTERS_ANY: ServiceFlags = ServiceFlags::from_bits_truncate(
@@ -32,6 +32,7 @@ fn buy_magic_items(ai_data: &AiData) -> bool {
3232

3333
pub struct ServiceValidator {
3434
barter_classes: HashSet<String>,
35+
spell_vendor_classes: HashSet<String>,
3536
}
3637

3738
impl Handler<'_> for ServiceValidator {
@@ -68,9 +69,14 @@ impl Handler<'_> for ServiceValidator {
6869
let mut barter_menu = false;
6970
if is_autocalc(npc) {
7071
if !npc.class.is_empty() {
71-
barter_menu = self
72-
.barter_classes
73-
.contains(&npc.class.to_ascii_lowercase());
72+
let lower = npc.class.to_ascii_lowercase();
73+
barter_menu = self.barter_classes.contains(&lower);
74+
if self.spell_vendor_classes.contains(&lower) {
75+
println!(
76+
"Npc {} is a spell vendor with auto calculated spells",
77+
npc.id
78+
);
79+
}
7480
}
7581
} else {
7682
barter_menu = barters(&npc.ai_data);
@@ -106,6 +112,7 @@ impl ServiceValidator {
106112
pub fn new() -> Self {
107113
Self {
108114
barter_classes: get_barter_classes!(),
115+
spell_vendor_classes: get_spell_vendor_classes!(),
109116
}
110117
}
111118
}

0 commit comments

Comments
 (0)