fix(balance): Startausruestung wird angelegt, Krit wirkt
Gemessen statt geschaetzt — es waren nicht die Zahlen: - on_create konnte nur give_item, die Startwaffe lag also im Beutel. Jeder Held schlug mit blossen Haenden zu: Schaden 2 statt 7,7, zehn Zuege pro Ratte statt zweieinhalb. Neue Aktion equip_item. - Der Dieb bekam gar keine Waffe. Jetzt ein Dolch (+3 Schaden, +5 Krit). - critical_chance percent = 15 auf einer Basis von 0 ist ein No-op — die Signaturzahl des Diebs tat nichts. Basis jetzt 5, Dieb traegt flat 10. Die Prozent-auf-Null-Falle steht im Glossar unter Modifikator: Sie folgt aus der Stapelregel aus Ticket 01 und schnappt sonst wieder zu.
This commit is contained in:
@@ -137,6 +137,14 @@ pub enum Action {
|
||||
#[serde(default = "one")]
|
||||
count: u32,
|
||||
},
|
||||
/// Gibt **und legt an**. Aus M9: `on_create` konnte bis dahin nur `give_item`,
|
||||
/// also startete jeder Held mit der Waffe im Beutel und schlug mit blossen
|
||||
/// Haenden zu. „Startausruestung" als eigener Engine-Begriff waere die
|
||||
/// falsche Antwort gewesen — das hier ist eine Aktion wie jede andere und
|
||||
/// steht ueberall, wo eine stehen darf.
|
||||
EquipItem {
|
||||
item: String,
|
||||
},
|
||||
}
|
||||
|
||||
fn one() -> u32 {
|
||||
@@ -163,7 +171,8 @@ impl Action {
|
||||
| Action::OpenShop
|
||||
| Action::GiveExp { .. }
|
||||
| Action::StartQuest { .. }
|
||||
| Action::GiveItem { .. } => Target::Zelf,
|
||||
| Action::GiveItem { .. }
|
||||
| Action::EquipItem { .. } => Target::Zelf,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,6 +116,11 @@ impl Default for Attributes {
|
||||
a.set(Attribute::MaxStamina, 100.0);
|
||||
a.set(Attribute::Damage, 2.0);
|
||||
a.set(Attribute::HitChance, 0.8);
|
||||
// **Befund aus M9:** Die Basis stand auf 0, und ein Modifikator mit
|
||||
// `percent` rechnet auf 0 immer 0 — die Signaturzahl des Diebs
|
||||
// („+15 % kritische Chance") tat schlicht nichts. Gegner tragen seit M3
|
||||
// eine Basis von 5; der Held hatte keine.
|
||||
a.set(Attribute::CriticalChance, 5.0);
|
||||
a.set(Attribute::CriticalFactor, 1.5);
|
||||
a.set(Attribute::CarryCapacity, 50.0);
|
||||
a
|
||||
|
||||
@@ -430,6 +430,15 @@ impl Game {
|
||||
|
||||
Action::StartQuest { quest } => self.start_quest(quest, reg),
|
||||
|
||||
Action::EquipItem { item } => {
|
||||
self.give(ItemInstance::new(item.clone()), reg);
|
||||
// Ueber den normalen Weg, damit Verdraengtes zurueck ins
|
||||
// Inventar wandert statt zu verschwinden.
|
||||
if let Some(i) = self.player.inventory.iter().rposition(|x| x.def == *item) {
|
||||
self.equip(i, reg);
|
||||
}
|
||||
}
|
||||
|
||||
Action::GiveItem { item, count } => {
|
||||
let inst = ItemInstance::stack(item.clone(), *count);
|
||||
let name = self.item_label(&inst, reg);
|
||||
@@ -2205,7 +2214,18 @@ mod tests {
|
||||
);
|
||||
|
||||
// `on_create` hat die Ausruestung gegeben — als gewoehnliche Aktionen.
|
||||
assert_eq!(game.count_of("core:iron_sword"), 1);
|
||||
// **Befund aus M9:** `equip_item`, nicht `give_item`. Vorher lag das
|
||||
// Schwert im Beutel und der Held schlug mit blossen Haenden zu.
|
||||
assert_eq!(
|
||||
game.player.equipment.get("core:hand").map(|i| i.def.as_str()),
|
||||
Some("core:iron_sword"),
|
||||
"die Waffe muss getragen werden, nicht getragen *werden koennen*"
|
||||
);
|
||||
assert!(
|
||||
game.attribute(p, Attribute::Damage, None, ®) > 7.0,
|
||||
"mit Waffe, nicht ohne: {}",
|
||||
game.attribute(p, Attribute::Damage, None, ®)
|
||||
);
|
||||
assert_eq!(game.count_of("core:health_potion"), 2, "der Stapel kommt als Stapel");
|
||||
|
||||
// Die Faehigkeiten von Rasse *und* Klasse stehen im Kampfmenue.
|
||||
@@ -2214,4 +2234,34 @@ mod tests {
|
||||
assert!(koennen.iter().any(|a| a == "core:power_strike"), "Klasse: {koennen:?}");
|
||||
assert!(koennen.iter().any(|a| a == "core:attack"), "und die impliziten bleiben");
|
||||
}
|
||||
|
||||
|
||||
/// **Befund aus M9:** Ein Modifikator mit `percent` rechnet auf einer Basis
|
||||
/// von 0 immer 0. `critical_chance` stand auf 0, also tat „+15 % kritische
|
||||
/// Chance" am Dieb schlicht nichts — die Signaturzahl der Klasse war ein
|
||||
/// No-op, und keine Zeile Code war daran falsch.
|
||||
#[test]
|
||||
fn prozent_auf_null_bleibt_null() {
|
||||
let (reg, _) = load_mods().expect("core");
|
||||
let mut game = Game::new(Creature::new("M"), ®, Rng::new(7)).expect("Etage 1");
|
||||
let p = CreatureRef::Player;
|
||||
|
||||
assert!(
|
||||
game.attribute(p, Attribute::CriticalChance, None, ®) > 0.0,
|
||||
"ohne Basis wirkt kein prozentualer Modifikator darauf"
|
||||
);
|
||||
|
||||
game.execute(
|
||||
Command::CreateCharacter(vec![
|
||||
String::from("core:elf"),
|
||||
String::from("core:thief"),
|
||||
]),
|
||||
®,
|
||||
);
|
||||
assert!(
|
||||
game.attribute(p, Attribute::CriticalChance, None, ®) >= 15.0,
|
||||
"der Dieb muss seine Signaturzahl auch spueren: {}",
|
||||
game.attribute(p, Attribute::CriticalChance, None, ®)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user