Research in the library: rooms, spells, towers, traps and doors are discovered in a fixed order
- studying creatures collect research points (mages and owls best, higher levels faster); studying gives less mana than before - free play starts with the basics; campaign missions know what their story allows and can research what the next four missions would bring - research shown in the top bar; the library's info lists the current item and what comes next; locked tools say whether they can be researched Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4f20223c93
commit
a54316c86e
8 files changed
+210
-3
No files matched your search
@@ -789,3 +789,11 @@ best.b.frost.text = Kälte macht Helden langsam, und langsame Helden sind leicht
|
|||||||
best.b.door_wood.text = Hält Zugluft und Ritter draußen - eine Weile.
|
best.b.door_wood.text = Hält Zugluft und Ritter draußen - eine Weile.
|
||||||
best.b.door_iron.text = Schwer, genietet, stur. Bringt einen Rammbock mit, Helden.
|
best.b.door_iron.text = Schwer, genietet, stur. Bringt einen Rammbock mit, Helden.
|
||||||
best.b.door_magic.text = Schlag zu, und sie schlägt zurück. Verschlossen ist sie das Ende jedes Ganges.
|
best.b.door_magic.text = Schlag zu, und sie schlägt zurück. Verschlossen ist sie das Ende jedes Ganges.
|
||||||
|
|
||||||
|
# research
|
||||||
|
hud.research = Forschung
|
||||||
|
research.now = Erforscht: {0} ({1}%)
|
||||||
|
research.next = danach: {0}
|
||||||
|
research.done = Hier gibt es nichts mehr zu erforschen.
|
||||||
|
msg.researched = Erforscht: {0}! Jetzt im Baumenü.
|
||||||
|
msg.tool_research = Noch nicht erforscht - Kreaturen in der Bibliothek arbeiten daran.
|
||||||
@@ -790,3 +790,11 @@ best.b.frost.text = Cold makes heroes slow, and slow heroes make easy targets.
|
|||||||
best.b.door_wood.text = Keeps the draught and the knights out - for a while.
|
best.b.door_wood.text = Keeps the draught and the knights out - for a while.
|
||||||
best.b.door_iron.text = Heavy, riveted, stubborn. Bring a battering ram, heroes.
|
best.b.door_iron.text = Heavy, riveted, stubborn. Bring a battering ram, heroes.
|
||||||
best.b.door_magic.text = Strike it and it strikes back. Locked, it is the end of every corridor.
|
best.b.door_magic.text = Strike it and it strikes back. Locked, it is the end of every corridor.
|
||||||
|
|
||||||
|
# research
|
||||||
|
hud.research = Research
|
||||||
|
research.now = Researching: {0} ({1}%)
|
||||||
|
research.next = then: {0}
|
||||||
|
research.done = Nothing left to research here.
|
||||||
|
msg.researched = Researched: {0}! It is in the build menu now.
|
||||||
|
msg.tool_research = Not researched yet - creatures studying in the library work on it.
|
||||||
@@ -504,6 +504,7 @@ pub fn start_mission(i: usize, carry: Option<&Carry>) -> Game {
|
|||||||
g.add_rival(side, x, y, diff);
|
g.add_rival(side, x, y, diff);
|
||||||
}
|
}
|
||||||
g.place_dwarf_caves(d.seed);
|
g.place_dwarf_caves(d.seed);
|
||||||
|
g.init_research(Some(i));
|
||||||
let heart = d.gate || d.forts.iter().any(|f| f.heart);
|
let heart = d.gate || d.forts.iter().any(|f| f.heart);
|
||||||
if !heart {
|
if !heart {
|
||||||
g.gate_hp = 0.0;
|
g.gate_hp = 0.0;
|
||||||
|
|||||||
+22
-1
@@ -462,6 +462,12 @@ pub struct Game {
|
|||||||
pub rollers: Vec<crate::traps::Roller>,
|
pub rollers: Vec<crate::traps::Roller>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub clouds: Vec<crate::traps::Cloud>,
|
pub clouds: Vec<crate::traps::Cloud>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub known: Vec<bool>, // tools known (ui::TOOLS order; empty = old savegame: everything)
|
||||||
|
#[serde(default)]
|
||||||
|
pub researchable: Vec<bool>, // tools that can be researched in the library
|
||||||
|
#[serde(default)]
|
||||||
|
pub research: f32, // research points towards the current item
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub forge_work: f32, // work done in the forge this frame
|
pub forge_work: f32, // work done in the forge this frame
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
@@ -555,6 +561,7 @@ impl Game {
|
|||||||
g.wave_timer = FIRST_WAVE + ((dist - 45.0) * 1.5).clamp(0.0, 300.0);
|
g.wave_timer = FIRST_WAVE + ((dist - 45.0) * 1.5).clamp(0.0, 300.0);
|
||||||
g.guard_treasures();
|
g.guard_treasures();
|
||||||
g.place_dwarf_caves(seed);
|
g.place_dwarf_caves(seed);
|
||||||
|
g.init_research(None);
|
||||||
g.msg("msg.welcome1", vec![]);
|
g.msg("msg.welcome1", vec![]);
|
||||||
g.msg("msg.welcome2", vec![]);
|
g.msg("msg.welcome2", vec![]);
|
||||||
g.msg("msg.welcome3", vec![]);
|
g.msg("msg.welcome3", vec![]);
|
||||||
@@ -631,6 +638,9 @@ impl Game {
|
|||||||
rollers: Vec::new(),
|
rollers: Vec::new(),
|
||||||
clouds: Vec::new(),
|
clouds: Vec::new(),
|
||||||
forge_work: 0.0,
|
forge_work: 0.0,
|
||||||
|
known: Vec::new(),
|
||||||
|
researchable: Vec::new(),
|
||||||
|
research: 0.0,
|
||||||
parts: Vec::new(),
|
parts: Vec::new(),
|
||||||
stuck: Vec::new(),
|
stuck: Vec::new(),
|
||||||
vrng: crate::particles::vrng(),
|
vrng: crate::particles::vrng(),
|
||||||
@@ -678,6 +688,9 @@ impl Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn tool_allowed(&self, tool: usize) -> bool {
|
pub fn tool_allowed(&self, tool: usize) -> bool {
|
||||||
|
if !self.known.is_empty() {
|
||||||
|
return self.known(tool);
|
||||||
|
}
|
||||||
self.mission.as_ref().map_or(true, |m| m.tools.get(tool).copied().unwrap_or(true))
|
self.mission.as_ref().map_or(true, |m| m.tools.get(tool).copied().unwrap_or(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1069,6 +1082,7 @@ impl Game {
|
|||||||
self.update_units(dt);
|
self.update_units(dt);
|
||||||
self.update_towers(dt);
|
self.update_towers(dt);
|
||||||
self.update_forge(dt);
|
self.update_forge(dt);
|
||||||
|
self.update_research();
|
||||||
if !self.rivals.is_empty() {
|
if !self.rivals.is_empty() {
|
||||||
self.update_rivals(dt);
|
self.update_rivals(dt);
|
||||||
}
|
}
|
||||||
@@ -3063,7 +3077,14 @@ impl Game {
|
|||||||
}
|
}
|
||||||
e.working = true;
|
e.working = true;
|
||||||
let rate = if e.kind == EK::Mage { 1.2 } else { 0.5 };
|
let rate = if e.kind == EK::Mage { 1.2 } else { 0.5 };
|
||||||
self.mana = (self.mana + rate * dt).min(self.mana_max());
|
self.mana = (self.mana + rate * 0.5 * dt).min(self.mana_max());
|
||||||
|
// research: mages and owls are the scholars
|
||||||
|
let points = match e.kind {
|
||||||
|
EK::Mage => 1.6,
|
||||||
|
EK::Owl => 1.3,
|
||||||
|
_ => 0.5,
|
||||||
|
} * (1.0 + 0.12 * (e.level - 1) as f32);
|
||||||
|
self.add_research(points * dt);
|
||||||
e.xp += 3.0 * dt;
|
e.xp += 3.0 * dt;
|
||||||
e.timer -= dt;
|
e.timer -= dt;
|
||||||
if e.timer <= 0.0 {
|
if e.timer <= 0.0 {
|
||||||
|
|||||||
+3
-1
@@ -14,6 +14,7 @@ mod menu;
|
|||||||
mod platform;
|
mod platform;
|
||||||
mod particles;
|
mod particles;
|
||||||
mod props;
|
mod props;
|
||||||
|
mod research;
|
||||||
mod rival;
|
mod rival;
|
||||||
mod render3d;
|
mod render3d;
|
||||||
mod save;
|
mod save;
|
||||||
@@ -862,7 +863,8 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
UiAction::OpenMenu => menu.page = Some(Page::Pause),
|
UiAction::OpenMenu => menu.page = Some(Page::Pause),
|
||||||
UiAction::Locked => {
|
UiAction::Locked => {
|
||||||
app.game.msg("msg.tool_locked", vec![]);
|
let locked = ui.last_locked.unwrap_or(usize::MAX);
|
||||||
|
app.game.msg(if app.game.can_research(locked) { "msg.tool_research" } else { "msg.tool_locked" }, vec![]);
|
||||||
app.game.sfx_ui(game::Sfx::Error);
|
app.game.sfx_ui(game::Sfx::Error);
|
||||||
}
|
}
|
||||||
UiAction::CloseHelp | UiAction::SelectLanguage(_) | UiAction::Consumed => {}
|
UiAction::CloseHelp | UiAction::SelectLanguage(_) | UiAction::Consumed => {}
|
||||||
|
|||||||
+140
@@ -0,0 +1,140 @@
|
|||||||
|
// Research: creatures studying in the library collect research points, and rooms, spells,
|
||||||
|
// towers, traps and doors are discovered one after another in a fixed order. Free play starts
|
||||||
|
// with the basics; a campaign mission knows what its story allows and may research what the
|
||||||
|
// next few missions would bring.
|
||||||
|
|
||||||
|
use crate::game::*;
|
||||||
|
|
||||||
|
// what is researched, in this order: (index in ui::TOOLS, research points)
|
||||||
|
pub const RESEARCH: &[(usize, f32)] = &[
|
||||||
|
(5, 200.0), // training hall
|
||||||
|
(10, 250.0), // heal
|
||||||
|
(21, 300.0), // forge
|
||||||
|
(22, 250.0), // spike pit
|
||||||
|
(29, 250.0), // wooden door
|
||||||
|
(15, 400.0), // cannon tower
|
||||||
|
(12, 450.0), // torture chamber
|
||||||
|
(26, 300.0), // alarm bell
|
||||||
|
(11, 500.0), // summon
|
||||||
|
(13, 550.0), // temple
|
||||||
|
(23, 500.0), // poison vent
|
||||||
|
(30, 500.0), // iron door
|
||||||
|
(18, 550.0), // aerie
|
||||||
|
(16, 650.0), // magic tower
|
||||||
|
(24, 650.0), // fire jet
|
||||||
|
(25, 650.0), // stone roller
|
||||||
|
(19, 700.0), // steel walls
|
||||||
|
(28, 800.0), // frost glow
|
||||||
|
(27, 900.0), // rune mine
|
||||||
|
(31, 1100.0), // magic door
|
||||||
|
];
|
||||||
|
|
||||||
|
// known from the start in free play
|
||||||
|
pub const BASE_TOOLS: &[usize] = &[0, 1, 2, 3, 4, 6, 7, 8, 9, 14, 17, 20];
|
||||||
|
|
||||||
|
// campaign: what the next missions bring may be researched early
|
||||||
|
const LOOKAHEAD: usize = 4;
|
||||||
|
|
||||||
|
impl Game {
|
||||||
|
// free play (None) or campaign mission i: what is known, what can be researched
|
||||||
|
pub fn init_research(&mut self, mission: Option<usize>) {
|
||||||
|
let n = crate::ui::TOOLS.len();
|
||||||
|
match mission {
|
||||||
|
None => {
|
||||||
|
self.known = (0..n).map(|i| BASE_TOOLS.contains(&i)).collect();
|
||||||
|
self.researchable = vec![true; n];
|
||||||
|
}
|
||||||
|
Some(m) => {
|
||||||
|
let unlock = |i: usize| crate::campaign::TOOL_UNLOCK.get(i).copied().unwrap_or(0);
|
||||||
|
self.known = (0..n).map(|i| unlock(i) <= m).collect();
|
||||||
|
self.researchable = (0..n).map(|i| unlock(i) <= m + LOOKAHEAD && i != crate::game::RUNE_TOOL).collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.research = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn known(&self, tool: usize) -> bool {
|
||||||
|
self.known.get(tool).copied().unwrap_or(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// the item being researched now: (index in RESEARCH)
|
||||||
|
pub fn research_target(&self) -> Option<usize> {
|
||||||
|
if self.known.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
RESEARCH.iter().position(|&(t, _)| !self.known(t) && self.researchable.get(t).copied().unwrap_or(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// the next items after the current one (for the library's info)
|
||||||
|
pub fn research_queue(&self, n: usize) -> Vec<usize> {
|
||||||
|
RESEARCH.iter().enumerate().filter(|(_, &(t, _))| !self.known(t) && self.researchable.get(t).copied().unwrap_or(false)).map(|(k, _)| k).take(n).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
// could this tool still be researched (for the locked-tool message)?
|
||||||
|
pub fn can_research(&self, tool: usize) -> bool {
|
||||||
|
!self.known(tool) && self.researchable.get(tool).copied().unwrap_or(false) && RESEARCH.iter().any(|&(t, _)| t == tool)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_research(&mut self, points: f32) {
|
||||||
|
if self.research_target().is_some() {
|
||||||
|
self.research += points;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_research(&mut self) {
|
||||||
|
let Some(k) = self.research_target() else { return };
|
||||||
|
let (tool, cost) = RESEARCH[k];
|
||||||
|
if self.research >= cost {
|
||||||
|
self.research -= cost;
|
||||||
|
if let Some(v) = self.known.get_mut(tool) {
|
||||||
|
*v = true;
|
||||||
|
}
|
||||||
|
let name = crate::ui::tool_info(crate::ui::TOOLS[tool]).name;
|
||||||
|
self.msg("msg.researched", vec![name]);
|
||||||
|
self.sfx_ui(Sfx::LevelUp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::map::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn studying_discovers_the_next_item() {
|
||||||
|
let mut g = Game::new(9, 64, 64);
|
||||||
|
assert!(!g.tool_allowed(5), "training hall must be researched");
|
||||||
|
assert!(g.tool_allowed(2) && g.tool_allowed(6));
|
||||||
|
let (cx, cy) = g.map.core;
|
||||||
|
for y in cy - 8..=cy - 5 {
|
||||||
|
for x in cx..=cx + 4 {
|
||||||
|
let t = &mut g.map.t[idx(x, y)];
|
||||||
|
t.kind = Kind::Library;
|
||||||
|
t.owner = Owner::Player;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.recount();
|
||||||
|
for k in 0..4 {
|
||||||
|
g.spawn(EK::Mage, false, cx as f32 + 0.5 + k as f32, cy as f32 - 6.5, 3);
|
||||||
|
}
|
||||||
|
let mut found = false;
|
||||||
|
for _ in 0..(20 * 400) {
|
||||||
|
g.update(0.05);
|
||||||
|
if g.tool_allowed(5) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(found, "research points {}", g.research);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn missions_know_their_tools_and_research_ahead() {
|
||||||
|
let g = crate::campaign::start_mission(2, None);
|
||||||
|
assert!(g.tool_allowed(5), "training hall known from mission 3");
|
||||||
|
assert!(!g.tool_allowed(12));
|
||||||
|
assert!(g.can_research(10), "heal comes soon and can be researched");
|
||||||
|
assert!(!g.can_research(31), "magic doors are far away");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -85,6 +85,7 @@ impl Game {
|
|||||||
g.msg("msg.welcome1", vec![]);
|
g.msg("msg.welcome1", vec![]);
|
||||||
g.msg("msg.welcome2", vec![]);
|
g.msg("msg.welcome2", vec![]);
|
||||||
g.msg(if rivals == 0 { "msg.welcome_humans" } else if humans { "msg.welcome_both" } else { "msg.welcome_rivals" }, vec![rivals.to_string()]);
|
g.msg(if rivals == 0 { "msg.welcome_humans" } else if humans { "msg.welcome_both" } else { "msg.welcome_rivals" }, vec![rivals.to_string()]);
|
||||||
|
g.init_research(None);
|
||||||
g.place_dwarf_caves(seed);
|
g.place_dwarf_caves(seed);
|
||||||
g
|
g
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -327,6 +327,7 @@ pub struct Ui {
|
|||||||
minimap_tex: Texture2D,
|
minimap_tex: Texture2D,
|
||||||
minimap_t: f64,
|
minimap_t: f64,
|
||||||
minimap_rect: Rect,
|
minimap_rect: Rect,
|
||||||
|
pub last_locked: Option<usize>, // the locked tool clicked last
|
||||||
end_buttons: Vec<(Rect, u8)>,
|
end_buttons: Vec<(Rect, u8)>,
|
||||||
goals_rect: Rect, // mission goals panel (click: briefing) // end dialog: 0 new game, 1 next/again, 2 campaign
|
goals_rect: Rect, // mission goals panel (click: briefing) // end dialog: 0 new game, 1 next/again, 2 campaign
|
||||||
lang_rects: Vec<(Rect, String)>,
|
lang_rects: Vec<(Rect, String)>,
|
||||||
@@ -378,6 +379,7 @@ impl Ui {
|
|||||||
minimap_tex: tex,
|
minimap_tex: tex,
|
||||||
minimap_t: -1.0,
|
minimap_t: -1.0,
|
||||||
minimap_rect: Rect::new(0.0, 0.0, 0.0, 0.0),
|
minimap_rect: Rect::new(0.0, 0.0, 0.0, 0.0),
|
||||||
|
last_locked: None,
|
||||||
end_buttons: Vec::new(),
|
end_buttons: Vec::new(),
|
||||||
goals_rect: Rect::new(0.0, 0.0, 0.0, 0.0),
|
goals_rect: Rect::new(0.0, 0.0, 0.0, 0.0),
|
||||||
lang_rects: Vec::new(),
|
lang_rects: Vec::new(),
|
||||||
@@ -433,7 +435,10 @@ impl Ui {
|
|||||||
self.open_cat = None;
|
self.open_cat = None;
|
||||||
UiAction::OpenMenu
|
UiAction::OpenMenu
|
||||||
}
|
}
|
||||||
TBtn::Tool(i) if !g.tool_allowed(i) => UiAction::Locked,
|
TBtn::Tool(i) if !g.tool_allowed(i) => {
|
||||||
|
self.last_locked = Some(i);
|
||||||
|
UiAction::Locked
|
||||||
|
}
|
||||||
TBtn::Tool(i) => {
|
TBtn::Tool(i) => {
|
||||||
self.open_cat = None;
|
self.open_cat = None;
|
||||||
self.tip = Some((i, get_time()));
|
self.tip = Some((i, get_time()));
|
||||||
@@ -442,6 +447,7 @@ impl Ui {
|
|||||||
TBtn::Cat(c) => {
|
TBtn::Cat(c) => {
|
||||||
let tools = CATS[c].1;
|
let tools = CATS[c].1;
|
||||||
if tools.len() == 1 && !g.tool_allowed(tools[0]) {
|
if tools.len() == 1 && !g.tool_allowed(tools[0]) {
|
||||||
|
self.last_locked = Some(tools[0]);
|
||||||
UiAction::Locked
|
UiAction::Locked
|
||||||
} else if tools.len() == 1 {
|
} else if tools.len() == 1 {
|
||||||
self.open_cat = None;
|
self.open_cat = None;
|
||||||
@@ -518,6 +524,11 @@ impl Ui {
|
|||||||
let left = (limit - g.time).max(0.0);
|
let left = (limit - g.time).max(0.0);
|
||||||
segs.insert(0, vec![txt(tr("hud.time_left"), if left < 120.0 { RED } else { GOLD }), Part::Gap, txt(mmss(left), TXT)]);
|
segs.insert(0, vec![txt(tr("hud.time_left"), if left < 120.0 { RED } else { GOLD }), Part::Gap, txt(mmss(left), TXT)]);
|
||||||
}
|
}
|
||||||
|
if let Some(k) = g.research_target().filter(|_| g.counts[4] > 0) {
|
||||||
|
let (tool, cost) = crate::research::RESEARCH[k];
|
||||||
|
let name: String = tool_info(TOOLS[tool]).name.chars().take(18).collect();
|
||||||
|
segs.push(vec![txt(tr("hud.research"), BLUE), Part::Gap, txt(name, TXT), Part::Gap, Part::Bar(g.research / cost, BLUE)]);
|
||||||
|
}
|
||||||
segs.push(vec![txt(tr("hud.payday"), if g.payday <= PAYDAY_WARN { RED } else { GOLD }), Part::Gap, txt(mmss(g.payday), TXT)]);
|
segs.push(vec![txt(tr("hud.payday"), if g.payday <= PAYDAY_WARN { RED } else { GOLD }), Part::Gap, txt(mmss(g.payday), TXT)]);
|
||||||
segs.push(vec![txt(tr("hud.army"), TXT), Part::Gap, txt((g.army_value() as i32).to_string(), TXT)]);
|
segs.push(vec![txt(tr("hud.army"), TXT), Part::Gap, txt((g.army_value() as i32).to_string(), TXT)]);
|
||||||
if !g.hand.is_empty() {
|
if !g.hand.is_empty() {
|
||||||
@@ -1215,6 +1226,21 @@ pub fn hover_info(g: &Game, ent: Option<usize>, tile: Option<(i32, i32)>) -> Vec
|
|||||||
out.push((tr(ROOM_NAMES[r]), FRAME_HI));
|
out.push((tr(ROOM_NAMES[r]), FRAME_HI));
|
||||||
match k {
|
match k {
|
||||||
Kind::Farm => out.push((trf("farm.food", &[(t.food as i32).to_string()]), GREEN)),
|
Kind::Farm => out.push((trf("farm.food", &[(t.food as i32).to_string()]), GREEN)),
|
||||||
|
Kind::Library => {
|
||||||
|
let q = g.research_queue(4);
|
||||||
|
if q.is_empty() {
|
||||||
|
out.push((tr("research.done"), DIM));
|
||||||
|
}
|
||||||
|
for (n, k) in q.iter().enumerate() {
|
||||||
|
let (tool, cost) = crate::research::RESEARCH[*k];
|
||||||
|
let name = tool_info(TOOLS[tool]).name;
|
||||||
|
if n == 0 {
|
||||||
|
out.push((trf("research.now", &[name, ((g.research / cost * 100.0).min(99.0) as i32).to_string()]), BLUE));
|
||||||
|
} else {
|
||||||
|
out.push((trf("research.next", &[name]), DIM));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Kind::Treasury if t.gold > 0 => {
|
Kind::Treasury if t.gold > 0 => {
|
||||||
let what = ["res.gold", "res.silver", "res.ruby", "res.diamond"][(t.res & 3) as usize];
|
let what = ["res.gold", "res.silver", "res.ruby", "res.diamond"][(t.res & 3) as usize];
|
||||||
out.push((trf("treasury.content", &[t.gold.to_string(), tr(what)]), GOLD));
|
out.push((trf("treasury.content", &[t.gold.to_string(), tr(what)]), GOLD));
|
||||||
|
|||||||
Reference in new issue
Block a user