feat(debug): Werkbank auf F12
Gegenstandsliste mit Cursor, dazu heilen, absteigen und Raum leeren. Laeuft ueber ein Kommando Debug(Cheat) statt am Spielkern vorbei — die Zusage aus Ticket 11, dass Response::Command der einzige Weg nach game/ ist, gilt auch fuer Cheats. ClearRoom toetet die Gegner, statt die Liste zu leeren: So laeuft der normale Weg samt Todes-Triggern und "Der Raum ist geraeumt".
This commit is contained in:
@@ -14,7 +14,7 @@ pub mod rng;
|
||||
|
||||
pub use action::{Action, ActiveModifier, DamageType, StateField, Target};
|
||||
pub use attributes::{Attribute, Modifier};
|
||||
pub use command::{Command, Direction, Outcome};
|
||||
pub use command::{Cheat, Command, Direction, Outcome};
|
||||
pub use condition::{Check, Condition, Who};
|
||||
pub use creature::{Creature, CreatureRef, ItemInstance};
|
||||
pub use event::{Event, EventKind, Trigger};
|
||||
@@ -599,6 +599,8 @@ impl Game {
|
||||
// Sein eigenes Gold zurueckzuverkaufen ergibt keinen Sinn.
|
||||
Command::Sell(i) => (self.player.inventory[*i].def == "core:gold")
|
||||
.then_some("Gold verkauft man nicht"),
|
||||
// Ein Cheat wird nie abgewiesen — das ist sein Zweck.
|
||||
Command::Debug(_) => None,
|
||||
Command::Wait => None,
|
||||
}
|
||||
}
|
||||
@@ -746,6 +748,7 @@ impl Game {
|
||||
Command::Choose(i) => self.choose(*i, reg),
|
||||
Command::Buy(i) => self.buy(*i, reg),
|
||||
Command::Sell(i) => self.sell(*i, reg),
|
||||
Command::Debug(cheat) => self.cheat(cheat, reg),
|
||||
Command::Drop(i) => {
|
||||
let inst = self.player.inventory.remove(*i);
|
||||
let name = self.item_label(&inst, reg);
|
||||
@@ -837,6 +840,37 @@ impl Game {
|
||||
self.log(format!("{name} verkauft fuer {preis} Gold"));
|
||||
}
|
||||
|
||||
/// Die Werkbank. Steht im Spielkern und nicht in der UI, weil sie durch
|
||||
/// dieselbe Tuer muss wie alles andere: `Command` ist der einzige Weg
|
||||
/// hinein (Ticket 11).
|
||||
fn cheat(&mut self, cheat: &Cheat, reg: &Registries) {
|
||||
match cheat {
|
||||
Cheat::Give(id) => {
|
||||
let stapelbar = reg.items.get(id).is_some_and(|d| d.stackable);
|
||||
let inst = ItemInstance::stack(id.clone(), if stapelbar { 10 } else { 1 });
|
||||
let name = self.item_label(&inst, reg);
|
||||
self.give(inst, reg);
|
||||
self.log(format!("[debug] {name}"));
|
||||
}
|
||||
Cheat::Heal => {
|
||||
let p = CreatureRef::Player;
|
||||
self.player.health = self.attribute(p, Attribute::MaxHealth, None, reg);
|
||||
self.player.stamina = self.attribute(p, Attribute::MaxStamina, None, reg);
|
||||
self.log(String::from("[debug] geheilt"));
|
||||
}
|
||||
Cheat::Descend => {
|
||||
self.log(String::from("[debug] abgestiegen"));
|
||||
self.descend(reg);
|
||||
}
|
||||
Cheat::ClearRoom => {
|
||||
for e in &mut self.enemies {
|
||||
e.health = 0.0;
|
||||
}
|
||||
self.log(String::from("[debug] Raum geleert"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Nimmt **ein Stueck** aus dem Eintrag an `index` und gibt es zurueck.
|
||||
/// Ueber den Index, nicht ueber die `def`: Zwei Traenke mit verschiedenen
|
||||
/// Affixen teilen sich die `def`, und `take` naehme den erstbesten.
|
||||
@@ -1688,4 +1722,31 @@ mod tests {
|
||||
"der leere Eintrag muss verschwinden"
|
||||
);
|
||||
}
|
||||
|
||||
/// Die Werkbank laeuft durch dieselbe Tuer wie alles andere — sie ist ein
|
||||
/// `Command`, kein Seiteneingang in `Game`. Der Test haelt genau das fest.
|
||||
#[test]
|
||||
fn werkbank_gibt_stapelbares_im_stapel() {
|
||||
let (mut game, reg) = zwergenkrieger();
|
||||
|
||||
let cheat = Command::Debug;
|
||||
game.execute(cheat(Cheat::Give(String::from("core:gold"))), ®);
|
||||
game.execute(cheat(Cheat::Give(String::from("core:iron_sword"))), ®);
|
||||
assert_eq!(game.gold(), 10, "stapelbares kommt zu zehnt");
|
||||
assert_eq!(game.count_of("core:iron_sword"), 1, "der Rest einzeln");
|
||||
|
||||
game.player.health = 1.0;
|
||||
game.player.stamina = 0.0;
|
||||
game.execute(cheat(Cheat::Heal), ®);
|
||||
let voll = game.attribute(CreatureRef::Player, Attribute::MaxHealth, None, ®);
|
||||
assert_eq!(game.player.health, voll);
|
||||
|
||||
// Gegner werden getoetet, nicht entfernt — so laeuft der normale Weg
|
||||
// samt „Der Raum ist geräumt".
|
||||
let ratte = reg.creatures.get("core:rat").expect("Riesenratte");
|
||||
game.enemies = vec![Creature::from_def(ratte)];
|
||||
game.execute(cheat(Cheat::ClearRoom), ®);
|
||||
assert!(game.enemies.is_empty());
|
||||
assert!(game.journal.iter().any(|z| z.contains("geräumt")), "{:?}", game.journal);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user