Fourth master: dwarves get their own side so the yellow AI works; yellow colours and texts; AI cores use the player's throne and heart in their colour
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
450e55d693
commit
b29e312e6b
25 files changed
+136
-55
No files matched your search
@@ -777,6 +777,8 @@ msg.rival1_attack = Mossgrim, zelený mistr, na tebe posílá tvory ({0})!
|
||||
msg.rival2_attack = Lady Nightwell, modrá mistryně, na tebe posílá tvory ({0})!
|
||||
msg.rival1_out = Mossgrim je poražen - jeho jádro duše se roztříštilo!
|
||||
msg.rival2_out = Lady Nightwell je poražena - její jádro duše se roztříštilo!
|
||||
msg.rival3_attack = Saffrax, žlutý pán, posílá proti tobě {0} tvorů!
|
||||
msg.rival3_out = Saffrax je poražen - jeho jádro duše se roztříštilo!
|
||||
msg.rival_unit_slain = Padl tvor soupeřícího mistra: {0}! +{1} zlata.
|
||||
msg.wave_on_rival1 = Vlna {0}: hrdinové ({1}) táhnou na zeleného mistra.
|
||||
msg.wave_on_rival2 = Vlna {0}: hrdinové ({1}) táhnou na modrou mistryni.
|
||||
|
||||
@@ -776,6 +776,8 @@ msg.rival1_attack = Mossgrim, den grønne mester, sender {0} væsner mod dig!
|
||||
msg.rival2_attack = Lady Nightwell, den blå mester, sender {0} væsner mod dig!
|
||||
msg.rival1_out = Mossgrim er besejret - hans sjælekerne er splintret!
|
||||
msg.rival2_out = Lady Nightwell er besejret - hendes sjælekerne er splintret!
|
||||
msg.rival3_attack = Saffrax, den gule mester, sender {0} væsner mod dig!
|
||||
msg.rival3_out = Saffrax er besejret - hans sjælekerne er knust!
|
||||
msg.rival_unit_slain = En {0} fra en rivaliserende mester falder! +{1} guld.
|
||||
msg.wave_on_rival1 = Bølge {0}: {1} helte marcherer mod den grønne mester.
|
||||
msg.wave_on_rival2 = Bølge {0}: {1} helte marcherer mod den blå mester.
|
||||
|
||||
@@ -776,6 +776,8 @@ msg.rival1_attack = Mossgrim, der grüne Meister, schickt {0} Kreaturen gegen di
|
||||
msg.rival2_attack = Lady Nightwell, die blaue Meisterin, schickt {0} Kreaturen gegen dich!
|
||||
msg.rival1_out = Mossgrim ist besiegt - sein Seelenkern ist zersplittert!
|
||||
msg.rival2_out = Lady Nightwell ist besiegt - ihr Seelenkern ist zersplittert!
|
||||
msg.rival3_attack = Saffrax, der gelbe Meister, schickt {0} Kreaturen gegen dich!
|
||||
msg.rival3_out = Saffrax ist besiegt - sein Seelenkern ist zersplittert!
|
||||
msg.rival_unit_slain = Ein {0} eines Rivalen fällt! +{1} Gold.
|
||||
msg.wave_on_rival1 = Welle {0}: {1} Helden ziehen gegen den grünen Meister.
|
||||
msg.wave_on_rival2 = Welle {0}: {1} Helden ziehen gegen den blauen Meister.
|
||||
|
||||
@@ -777,6 +777,8 @@ msg.rival1_attack = Ο Μόσγκριμ, ο πράσινος άρχοντας,
|
||||
msg.rival2_attack = Η Λαίδη Νάιτγουελ, η γαλάζια άρχοντας, στέλνει {0} πλάσματα εναντίον σου!
|
||||
msg.rival1_out = Ο Μόσγκριμ νικήθηκε - ο πυρήνας ψυχής του θρυμματίστηκε!
|
||||
msg.rival2_out = Η Λαίδη Νάιτγουελ νικήθηκε - ο πυρήνας ψυχής της θρυμματίστηκε!
|
||||
msg.rival3_attack = Ο Σάφραξ, ο κίτρινος άρχοντας, στέλνει {0} πλάσματα εναντίον σου!
|
||||
msg.rival3_out = Ο Σάφραξ νικήθηκε - ο πυρήνας ψυχής του θρυμματίστηκε!
|
||||
msg.rival_unit_slain = Πέφτει πλάσμα αντίπαλου άρχοντα: {0}! +{1} χρυσός.
|
||||
msg.wave_on_rival1 = Κύμα {0}: {1} ήρωες βαδίζουν κατά του πράσινου άρχοντα.
|
||||
msg.wave_on_rival2 = Κύμα {0}: {1} ήρωες βαδίζουν κατά της γαλάζιας άρχοντος.
|
||||
|
||||
@@ -777,6 +777,8 @@ msg.rival1_attack = Mossgrim, the green master, sends {0} creatures against you!
|
||||
msg.rival2_attack = Lady Nightwell, the blue master, sends {0} creatures against you!
|
||||
msg.rival1_out = Mossgrim is defeated - his soul core has shattered!
|
||||
msg.rival2_out = Lady Nightwell is defeated - her soul core has shattered!
|
||||
msg.rival3_attack = Saffrax, the yellow master, sends {0} creatures against you!
|
||||
msg.rival3_out = Saffrax is defeated - his soul core has shattered!
|
||||
msg.rival_unit_slain = A {0} of a rival master falls! +{1} gold.
|
||||
msg.wave_on_rival1 = Wave {0}: {1} heroes march on the green master.
|
||||
msg.wave_on_rival2 = Wave {0}: {1} heroes march on the blue master.
|
||||
|
||||
@@ -769,6 +769,8 @@ msg.rival1_attack = ¡Mossgrim, el señor verde, envía {0} criaturas contra ti!
|
||||
msg.rival2_attack = ¡Lady Nightwell, la señora azul, envía {0} criaturas contra ti!
|
||||
msg.rival1_out = Mossgrim ha sido derrotado: ¡su núcleo de alma se ha hecho añicos!
|
||||
msg.rival2_out = Lady Nightwell ha sido derrotada: ¡su núcleo de alma se ha hecho añicos!
|
||||
msg.rival3_attack = ¡Saffrax, el amo amarillo, envía {0} criaturas contra ti!
|
||||
msg.rival3_out = Saffrax ha sido derrotado: ¡su núcleo de alma se ha hecho añicos!
|
||||
msg.rival_unit_slain = ¡Cae un {0} de un señor rival! +{1} de oro.
|
||||
msg.wave_on_rival1 = Oleada {0}: {1} héroes marchan contra el señor verde.
|
||||
msg.wave_on_rival2 = Oleada {0}: {1} héroes marchan contra la señora azul.
|
||||
|
||||
@@ -777,6 +777,8 @@ msg.rival1_attack = Mossgrim, vihreä mestari, lähettää kimppuusi {0} olentoa
|
||||
msg.rival2_attack = Lady Nightwell, sininen mestari, lähettää kimppuusi {0} olentoa!
|
||||
msg.rival1_out = Mossgrim on voitettu - hänen sieluytimensä on murskattu!
|
||||
msg.rival2_out = Lady Nightwell on voitettu - hänen sieluytimensä on murskattu!
|
||||
msg.rival3_attack = Saffrax, keltainen mestari, lähettää {0} olentoa sinua vastaan!
|
||||
msg.rival3_out = Saffrax on lyöty - hänen sieluydin on murskattu!
|
||||
msg.rival_unit_slain = Kilpailevan mestarin olento kaatuu: {0}! +{1} kultaa.
|
||||
msg.wave_on_rival1 = Aalto {0}: {1} sankaria marssii vihreää mestaria vastaan.
|
||||
msg.wave_on_rival2 = Aalto {0}: {1} sankaria marssii sinistä mestaria vastaan.
|
||||
|
||||
@@ -777,6 +777,8 @@ msg.rival1_attack = Mossgrim, zeleni gospodar, šalje stvorenja na tebe: {0}!
|
||||
msg.rival2_attack = Lady Nightwell, plava gospodarica, šalje stvorenja na tebe: {0}!
|
||||
msg.rival1_out = Mossgrim je poražen - njegova jezgra duše se razbila!
|
||||
msg.rival2_out = Lady Nightwell je poražena - njezina jezgra duše se razbila!
|
||||
msg.rival3_attack = Saffrax, žuti gospodar, šalje {0} stvorenja na tebe!
|
||||
msg.rival3_out = Saffrax je poražen - njegova jezgra duše je razbijena!
|
||||
msg.rival_unit_slain = Palo je stvorenje suparničkog gospodara: {0}! +{1} zlata.
|
||||
msg.wave_on_rival1 = Val {0}: junaci ({1}) marširaju na zelenog gospodara.
|
||||
msg.wave_on_rival2 = Val {0}: junaci ({1}) marširaju na plavu gospodaricu.
|
||||
|
||||
@@ -777,6 +777,8 @@ msg.rival1_attack = Mossgrim, a zöld mester, {0} lényt küld ellened!
|
||||
msg.rival2_attack = Lady Nightwell, a kék mester, {0} lényt küld ellened!
|
||||
msg.rival1_out = Mossgrim legyőzve - a lélekmagja darabokra tört!
|
||||
msg.rival2_out = Lady Nightwell legyőzve - a lélekmagja darabokra tört!
|
||||
msg.rival3_attack = Saffrax, a sárga mester, {0} lényt küld ellened!
|
||||
msg.rival3_out = Saffrax legyőzve - a lélekmagja darabokra tört!
|
||||
msg.rival_unit_slain = Elesett egy rivális mester lénye: {0}! +{1} arany.
|
||||
msg.wave_on_rival1 = {0}. hullám: {1} hős vonul a zöld mester ellen.
|
||||
msg.wave_on_rival2 = {0}. hullám: {1} hős vonul a kék mester ellen.
|
||||
|
||||
@@ -769,6 +769,8 @@ msg.rival1_attack = Mossgrim, il maestro verde, ti manda contro {0} creature!
|
||||
msg.rival2_attack = Lady Nightwell, la maestra blu, ti manda contro {0} creature!
|
||||
msg.rival1_out = Mossgrim è sconfitto - il suo nucleo dell'anima è in frantumi!
|
||||
msg.rival2_out = Lady Nightwell è sconfitta - il suo nucleo dell'anima è in frantumi!
|
||||
msg.rival3_attack = Saffrax, il signore giallo, manda {0} creature contro di te!
|
||||
msg.rival3_out = Saffrax è sconfitto: il suo nucleo dell'anima è andato in frantumi!
|
||||
msg.rival_unit_slain = Cade una creatura di un maestro rivale: {0}! +{1} oro.
|
||||
msg.wave_on_rival1 = Ondata {0}: {1} eroi marciano sul maestro verde.
|
||||
msg.wave_on_rival2 = Ondata {0}: {1} eroi marciano sulla maestra blu.
|
||||
|
||||
@@ -777,6 +777,8 @@ msg.rival1_attack = Mossgrim, de groene meester, stuurt {0} wezens op je af!
|
||||
msg.rival2_attack = Lady Nightwell, de blauwe meester, stuurt {0} wezens op je af!
|
||||
msg.rival1_out = Mossgrim is verslagen - zijn zielenkern is verbrijzeld!
|
||||
msg.rival2_out = Lady Nightwell is verslagen - haar zielenkern is verbrijzeld!
|
||||
msg.rival3_attack = Saffrax, de gele meester, stuurt {0} wezens op je af!
|
||||
msg.rival3_out = Saffrax is verslagen - zijn zielskern is verbrijzeld!
|
||||
msg.rival_unit_slain = Een {0} van een rivaliserende meester valt! +{1} goud.
|
||||
msg.wave_on_rival1 = Golf {0}: {1} helden trekken op tegen de groene meester.
|
||||
msg.wave_on_rival2 = Golf {0}: {1} helden trekken op tegen de blauwe meester.
|
||||
|
||||
@@ -776,6 +776,8 @@ msg.rival1_attack = Mossgrim, den grønne mesteren, sender {0} skapninger mot de
|
||||
msg.rival2_attack = Lady Nightwell, den blå mesteren, sender {0} skapninger mot deg!
|
||||
msg.rival1_out = Mossgrim er beseiret - sjelekjernen hans er knust!
|
||||
msg.rival2_out = Lady Nightwell er beseiret - sjelekjernen hennes er knust!
|
||||
msg.rival3_attack = Saffrax, den gule mesteren, sender {0} vesener mot deg!
|
||||
msg.rival3_out = Saffrax er beseiret - sjelekjernen hans er knust!
|
||||
msg.rival_unit_slain = En {0} fra en rivaliserende mester faller! +{1} gull.
|
||||
msg.wave_on_rival1 = Bølge {0}: {1} helter marsjerer mot den grønne mesteren.
|
||||
msg.wave_on_rival2 = Bølge {0}: {1} helter marsjerer mot den blå mesteren.
|
||||
|
||||
@@ -777,6 +777,8 @@ msg.rival1_attack = Mossgrim, o mestre verde, manda {0} criaturas contra ti!
|
||||
msg.rival2_attack = Lady Nightwell, a mestra azul, manda {0} criaturas contra ti!
|
||||
msg.rival1_out = Mossgrim foi derrotado - o núcleo de alma dele despedaçou-se!
|
||||
msg.rival2_out = Lady Nightwell foi derrotada - o núcleo de alma dela despedaçou-se!
|
||||
msg.rival3_attack = Saffrax, o mestre amarelo, envia {0} criaturas contra ti!
|
||||
msg.rival3_out = Saffrax foi derrotado - o seu núcleo de alma estilhaçou-se!
|
||||
msg.rival_unit_slain = Cai um {0} de um mestre rival! +{1} de ouro.
|
||||
msg.wave_on_rival1 = Vaga {0}: {1} heróis marcham contra o mestre verde.
|
||||
msg.wave_on_rival2 = Vaga {0}: {1} heróis marcham contra a mestra azul.
|
||||
|
||||
@@ -777,6 +777,8 @@ msg.rival1_attack = Mossgrim, stăpânul verde, trimite {0} creaturi împotriva
|
||||
msg.rival2_attack = Lady Nightwell, stăpâna albastră, trimite {0} creaturi împotriva ta!
|
||||
msg.rival1_out = Mossgrim e învins - miezul sufletului său s-a sfărâmat!
|
||||
msg.rival2_out = Lady Nightwell e învinsă - miezul sufletului ei s-a sfărâmat!
|
||||
msg.rival3_attack = Saffrax, stăpânul galben, trimite {0} creaturi împotriva ta!
|
||||
msg.rival3_out = Saffrax este învins - nucleul său de suflet s-a sfărâmat!
|
||||
msg.rival_unit_slain = Un {0} al unui stăpân rival cade! +{1} aur.
|
||||
msg.wave_on_rival1 = Valul {0}: {1} eroi mărșăluiesc asupra stăpânului verde.
|
||||
msg.wave_on_rival2 = Valul {0}: {1} eroi mărșăluiesc asupra stăpânei albastre.
|
||||
|
||||
@@ -769,6 +769,8 @@ msg.rival1_attack = Моссгрим, зелёный хозяин, шлёт на
|
||||
msg.rival2_attack = Леди Найтвелл, синяя хозяйка, шлёт на тебя {0} существ!
|
||||
msg.rival1_out = Моссгрим повержен - его ядро души разбито!
|
||||
msg.rival2_out = Леди Найтвелл повержена - её ядро души разбито!
|
||||
msg.rival3_attack = Саффракс, жёлтый хозяин, шлёт на тебя {0} существ!
|
||||
msg.rival3_out = Саффракс повержен - его ядро души разбито!
|
||||
msg.rival_unit_slain = Пал боец соперника: {0}! +{1} золота.
|
||||
msg.wave_on_rival1 = Волна {0}: {1} героев идут на зелёного хозяина.
|
||||
msg.wave_on_rival2 = Волна {0}: {1} героев идут на синюю хозяйку.
|
||||
|
||||
@@ -777,6 +777,8 @@ msg.rival1_attack = Mossgrim, zelený majster, na teba posiela tvory ({0})!
|
||||
msg.rival2_attack = Lady Nightwell, modrá majsterka, na teba posiela tvory ({0})!
|
||||
msg.rival1_out = Mossgrim je porazený - jeho jadro duše sa roztrieštilo!
|
||||
msg.rival2_out = Lady Nightwell je porazená - jej jadro duše sa roztrieštilo!
|
||||
msg.rival3_attack = Saffrax, žltý pán, posiela proti tebe {0} tvorov!
|
||||
msg.rival3_out = Saffrax je porazený - jeho jadro duše sa roztrieštilo!
|
||||
msg.rival_unit_slain = Padol tvor súperiaceho majstra: {0}! +{1} zlata.
|
||||
msg.wave_on_rival1 = Vlna {0}: hrdinovia ({1}) tiahnu na zeleného majstra.
|
||||
msg.wave_on_rival2 = Vlna {0}: hrdinovia ({1}) tiahnu na modrú majsterku.
|
||||
|
||||
@@ -777,6 +777,8 @@ msg.rival1_attack = Мосгрим, зелени господар, шаље ст
|
||||
msg.rival2_attack = Лејди Најтвел, плава господарица, шаље створења на тебе: {0}!
|
||||
msg.rival1_out = Мосгрим је поражен - његово језгро душе се разбило!
|
||||
msg.rival2_out = Лејди Најтвел је поражена - њено језгро душе се разбило!
|
||||
msg.rival3_attack = Сафракс, жути господар, шаље {0} створења на тебе!
|
||||
msg.rival3_out = Сафракс је поражен - његово језгро душе је разбијено!
|
||||
msg.rival_unit_slain = Пало је створење супарничког господара: {0}! +{1} злата.
|
||||
msg.wave_on_rival1 = Талас {0}: хероји ({1}) марширају на зеленог господара.
|
||||
msg.wave_on_rival2 = Талас {0}: хероји ({1}) марширају на плаву господарицу.
|
||||
|
||||
@@ -777,6 +777,8 @@ msg.rival1_attack = Mossgrim, den gröna mästaren, skickar {0} varelser mot dig
|
||||
msg.rival2_attack = Lady Nightwell, den blå mästaren, skickar {0} varelser mot dig!
|
||||
msg.rival1_out = Mossgrim är besegrad - hans själskärna har krossats!
|
||||
msg.rival2_out = Lady Nightwell är besegrad - hennes själskärna har krossats!
|
||||
msg.rival3_attack = Saffrax, den gula mästaren, skickar {0} varelser mot dig!
|
||||
msg.rival3_out = Saffrax är besegrad - hans själskärna har krossats!
|
||||
msg.rival_unit_slain = En {0} hos en rivaliserande mästare faller! +{1} guld.
|
||||
msg.wave_on_rival1 = Våg {0}: {1} hjältar marscherar mot den gröna mästaren.
|
||||
msg.wave_on_rival2 = Våg {0}: {1} hjältar marscherar mot den blå mästaren.
|
||||
|
||||
@@ -296,7 +296,11 @@ impl Game {
|
||||
self.rivals[k].attacking = true;
|
||||
self.rivals[k].army0 = army;
|
||||
if t == self.local_side {
|
||||
let key = if side == 2 { "msg.rival1_attack" } else { "msg.rival2_attack" };
|
||||
let key = match side {
|
||||
2 => "msg.rival1_attack",
|
||||
3 => "msg.rival2_attack",
|
||||
_ => "msg.rival3_attack",
|
||||
};
|
||||
let n = self.creature_count().to_string();
|
||||
self.tell_local(key, vec![n], Some(Sfx::WaveAlarm));
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ use crate::game::*;
|
||||
use crate::map::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub const DWARF_SIDE: u8 = 4;
|
||||
pub const DWARF_SIDE: u8 = 6; // its own side (4 is the fourth master)
|
||||
const LEASH: f32 = 7.0; // dwarves do not chase enemies further from the cave centre
|
||||
const CHEST_CHANCE: f32 = 0.3;
|
||||
|
||||
|
||||
+2
-2
@@ -299,7 +299,7 @@ pub struct Ent {
|
||||
#[serde(default)]
|
||||
pub pay_t: f32, // seconds until the creature goes for its wage
|
||||
#[serde(default)]
|
||||
pub side: u8, // 0 player, 2 and 3 rival masters (heroes: see side())
|
||||
pub side: u8, // 0 player, 2..=4 the other masters, 6 dwarves (heroes: see side())
|
||||
#[serde(default)]
|
||||
pub target: Option<u8>, // attackers: side whose core (or gate) they march on
|
||||
#[serde(default)]
|
||||
@@ -409,7 +409,7 @@ impl Ent {
|
||||
}
|
||||
// a unit of a rival master
|
||||
pub fn rival(&self) -> bool {
|
||||
!self.hero && (self.side == 2 || self.side == 3)
|
||||
!self.hero && (2..=4).contains(&self.side)
|
||||
}
|
||||
// a dwarf of a dwarf cave (neutral, never an opponent for victory)
|
||||
pub fn dwarf(&self) -> bool {
|
||||
|
||||
+55
-43
@@ -1336,7 +1336,7 @@ impl R3d {
|
||||
}
|
||||
for rv in g.rivals.iter().filter(|r| r.alive) {
|
||||
let (rx, rz) = rv.centre();
|
||||
let c = if rv.side == 2 { vec3(0.3, 1.0, 0.4) } else { vec3(0.35, 0.55, 1.0) };
|
||||
let c = master_rgb(rv.side);
|
||||
push(vec3(rx, 1.4, rz), 7.0, c, 1.1, 50.0);
|
||||
}
|
||||
// glowing lava near the camera (every third tile)
|
||||
@@ -2319,10 +2319,8 @@ fn ring(c: Vec3, r: f32, color: Color) {
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_landmarks_solid(g: &Game, t: f32) {
|
||||
// soul core: an obsidian throne whose four curved spikes hold the crystal heart in chains
|
||||
let (cx, cy) = g.map.core;
|
||||
let c = vec3(cx as f32 + 1.5, 0.0, cy as f32 + 1.5);
|
||||
// the obsidian throne of a soul core (centre c on the floor)
|
||||
fn draw_throne(c: Vec3, t: f32) {
|
||||
let obs = |k: u8| Color::from_rgba(28 + k, 14 + k / 2, 20 + k / 2, 255);
|
||||
draw_cube(c + vec3(0.0, 0.08, 0.0), vec3(2.9, 0.16, 2.9), None, obs(6));
|
||||
draw_cube(c + vec3(0.0, 0.22, 0.0), vec3(2.3, 0.14, 2.3), None, obs(14));
|
||||
@@ -2352,15 +2350,16 @@ fn draw_landmarks_solid(g: &Game, t: f32) {
|
||||
line3(p0, p1, if q % 2 == 0 { 0.06 } else { 0.035 }, iron);
|
||||
}
|
||||
}
|
||||
// rival masters' cores: obsidian pedestal (the orb glows in the glow pass)
|
||||
}
|
||||
|
||||
fn draw_landmarks_solid(g: &Game, t: f32) {
|
||||
// soul core: an obsidian throne whose four curved spikes hold the crystal heart in chains
|
||||
let (cx, cy) = g.map.core;
|
||||
draw_throne(vec3(cx as f32 + 1.5, 0.0, cy as f32 + 1.5), t);
|
||||
// the other masters' cores: the same throne (their hearts glow in their colours)
|
||||
for rv in g.rivals.iter().filter(|r| r.alive && g.map.shown(idx(r.core.0 + 1, r.core.1 + 1))) {
|
||||
let (rx, rz) = rv.centre();
|
||||
let c = vec3(rx, 0.0, rz);
|
||||
draw_cube(c + vec3(0.0, 0.08, 0.0), vec3(2.6, 0.16, 2.6), None, Color::from_rgba(24, 22, 30, 255));
|
||||
draw_cube(c + vec3(0.0, 0.22, 0.0), vec3(1.8, 0.14, 1.8), None, Color::from_rgba(34, 32, 42, 255));
|
||||
for (dx, dz) in [(-1.1f32, -1.1f32), (1.1, -1.1), (1.1, 1.1), (-1.1, 1.1)] {
|
||||
draw_cube(c + vec3(dx, 0.5, dz), vec3(0.22, 1.0, 0.22), None, Color::from_rgba(30, 28, 38, 255));
|
||||
}
|
||||
draw_throne(vec3(rx, 0.0, rz), t + rv.side as f32);
|
||||
}
|
||||
// portals: a demon gate - an arch of stone blocks with bone ribs and horns on a stepped
|
||||
// platform (the vortex glows in the glow pass); grey and dead until claimed
|
||||
@@ -2447,46 +2446,64 @@ fn draw_landmarks_solid(g: &Game, t: f32) {
|
||||
let _ = t;
|
||||
}
|
||||
|
||||
fn draw_landmarks_glow(g: &Game, t: f32, cam_r: Vec3) {
|
||||
// soul core: a faceted crystal heart beating lub-dub (faster when hurt, cracked when badly
|
||||
// hurt), glowing veins across the floor, rising embers
|
||||
let (cx, cy) = g.map.core;
|
||||
let hp = (g.core_hp / CORE_HP).clamp(0.0, 1.0);
|
||||
// the colour of a master side (the first master red, rivals green, blue and yellow)
|
||||
pub fn master_rgb(side: u8) -> Vec3 {
|
||||
match side {
|
||||
2 => vec3(0.3, 0.95, 0.4),
|
||||
3 => vec3(0.35, 0.55, 1.0),
|
||||
4 => vec3(1.0, 0.85, 0.25),
|
||||
_ => vec3(1.0, 0.2, 0.2),
|
||||
}
|
||||
}
|
||||
|
||||
// recolours a red-tinted colour into `tint`: keeps its brightness and whiteness, swaps the hue
|
||||
fn hue_to(tint: Option<Vec3>, c: Color) -> Color {
|
||||
let Some(t) = tint else { return c };
|
||||
let hi = c.r.max(c.g).max(c.b);
|
||||
let lo = c.r.min(c.g).min(c.b);
|
||||
let m = t.x.max(t.y).max(t.z).max(0.001);
|
||||
let k = (hi - lo) / m;
|
||||
Color::new(lo + t.x * k, lo + t.y * k, lo + t.z * k, c.a)
|
||||
}
|
||||
|
||||
// a soul core's crystal heart beating lub-dub (faster when hurt, cracked when badly hurt),
|
||||
// glowing veins across the floor, rising embers; `tint`: another master's colour for the red
|
||||
fn draw_heart(base: Vec3, hp: f32, t: f32, cam_r: Vec3, tint: Option<Vec3>) {
|
||||
let tc = |r: f32, g: f32, b: f32, a: f32| hue_to(tint, Color::new(r, g, b, a));
|
||||
let rate = 0.9 + (1.0 - hp) * 1.6;
|
||||
let ph = (t * rate).fract();
|
||||
let beat = (-((ph - 0.02) / 0.06).powi(2)).exp() + 0.65 * (-((ph - 0.2) / 0.06).powi(2)).exp();
|
||||
let pulse = 1.0 + beat * 0.09;
|
||||
let base = vec3(cx as f32 + 1.5, 0.0, cy as f32 + 1.5);
|
||||
let hc = base + vec3(0.0, 1.55 + (t * 1.1).sin() * 0.03, 0.0);
|
||||
let right = vec3(cam_r.x, 0.0, cam_r.z).normalize_or_zero();
|
||||
let up = Vec3::Y;
|
||||
let eye = EYE.with(|e| e.get());
|
||||
let front = vec3(eye.x, 0.0, eye.z).normalize_or_zero(); // towards the viewer
|
||||
let red = Color::new(0.38 + 0.38 * hp + 0.2 * beat, 0.02 + 0.04 * beat, 0.07, 1.0);
|
||||
let hot = Color::new(1.0, 0.35 + 0.25 * beat, 0.3, 0.7);
|
||||
let red = tc(0.38 + 0.38 * hp + 0.2 * beat, 0.02 + 0.04 * beat, 0.07, 1.0);
|
||||
let hot = tc(1.0, 0.35 + 0.25 * beat, 0.3, 0.7);
|
||||
// two lobes and the point below, then the facets as bright chips
|
||||
let s0 = 0.36 * pulse;
|
||||
for sgn in [-1.0f32, 1.0] {
|
||||
draw_sphere(hc + right * (sgn * 0.21 * pulse) + up * (0.12 * pulse), s0 * 0.85, None, red);
|
||||
}
|
||||
for (k, (y, r)) in [(-0.05f32, 0.36f32), (-0.22, 0.28), (-0.36, 0.18), (-0.46, 0.09)].iter().enumerate() {
|
||||
draw_sphere(hc + up * (y * pulse), r * pulse, None, if k == 0 { red } else { Color::new(red.r * 0.9, red.g, red.b, 1.0) });
|
||||
draw_sphere(hc + up * (y * pulse), r * pulse, None, if k == 0 { red } else { tc(red.r * 0.9, red.g, red.b, 1.0) });
|
||||
}
|
||||
draw_sphere(hc + right * (-0.12 * pulse) + up * (0.2 * pulse), 0.1 * pulse, None, Color::new(1.0, 0.75, 0.7, 0.75));
|
||||
draw_sphere(hc + right * (-0.12 * pulse) + up * (0.2 * pulse), 0.1 * pulse, None, tc(1.0, 0.75, 0.7, 0.75));
|
||||
for k in 0..7 {
|
||||
let a = k as f32 * 0.9 + 0.4;
|
||||
let p = hc + right * (a.cos() * 0.22 * pulse) + up * (a.sin() * 0.2 * pulse - 0.05) + front * 0.3;
|
||||
draw_cube(p, Vec3::splat(0.05), None, Color::new(1.0, 0.5 + 0.3 * ((t * 3.0 + k as f32).sin() * 0.5 + 0.5), 0.45, 0.8));
|
||||
draw_cube(p, Vec3::splat(0.05), None, tc(1.0, 0.5 + 0.3 * ((t * 3.0 + k as f32).sin() * 0.5 + 0.5), 0.45, 0.8));
|
||||
}
|
||||
draw_sphere(hc, 0.75 * pulse, None, Color::new(1.0, 0.15, 0.15, 0.16 + 0.12 * beat));
|
||||
draw_sphere(hc, 1.1 * pulse, None, Color::new(1.0, 0.1, 0.1, 0.06 + 0.05 * beat));
|
||||
draw_sphere(hc, 0.75 * pulse, None, tc(1.0, 0.15, 0.15, 0.16 + 0.12 * beat));
|
||||
draw_sphere(hc, 1.1 * pulse, None, tc(1.0, 0.1, 0.1, 0.06 + 0.05 * beat));
|
||||
// cracks when hurt
|
||||
let cracks = ((1.0 - hp) * 7.0) as usize;
|
||||
for k in 0..cracks.min(6) {
|
||||
let a = k as f32 * 2.3;
|
||||
let p0 = hc + right * (a.cos() * 0.08) + up * (a.sin() * 0.1);
|
||||
let p1 = p0 + right * (a.cos() * 0.25) + up * ((a * 1.7).sin() * 0.22);
|
||||
line3(p0 + front * 0.37, p1 + front * 0.33, 0.025, Color::new(0.08, 0.0, 0.02, 1.0));
|
||||
line3(p0 + front * 0.37, p1 + front * 0.33, 0.025, tc(0.08, 0.0, 0.02, 1.0));
|
||||
}
|
||||
// veins across the floor, a pulse running outwards with every beat
|
||||
for k in 0..8 {
|
||||
@@ -2497,7 +2514,7 @@ fn draw_landmarks_glow(g: &Game, t: f32, cam_r: Vec3) {
|
||||
let wig = ((k * 7 + q * 3) as f32).sin() * 0.18;
|
||||
let next = base + vec3(a.cos() * (1.3 + f * 2.2) - a.sin() * wig, 0.02, a.sin() * (1.3 + f * 2.2) + a.cos() * wig);
|
||||
let wave = (-((f - ph * 1.6) / 0.18).powi(2)).exp();
|
||||
line3(prev, next, 0.05, Color::new(1.0, 0.15 + 0.3 * wave, 0.1, (0.25 + 0.7 * wave) * (1.0 - f * 0.5) * (0.4 + 0.6 * hp)));
|
||||
line3(prev, next, 0.05, tc(1.0, 0.15 + 0.3 * wave, 0.1, (0.25 + 0.7 * wave) * (1.0 - f * 0.5) * (0.4 + 0.6 * hp)));
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
@@ -2506,22 +2523,20 @@ fn draw_landmarks_glow(g: &Game, t: f32, cam_r: Vec3) {
|
||||
let e = (t * 0.35 + k as f32 * 0.137).fract();
|
||||
let a = k as f32 * 2.4;
|
||||
let p = hc + vec3(a.cos() * (0.2 + e * 0.5), -0.2 + e * 2.0, a.sin() * (0.2 + e * 0.5));
|
||||
draw_cube(p, Vec3::splat(0.04 * (1.0 - e) + 0.01), None, Color::new(1.0, 0.45 + 0.4 * (1.0 - e), 0.15, 1.0 - e));
|
||||
draw_cube(p, Vec3::splat(0.04 * (1.0 - e) + 0.01), None, tc(1.0, 0.45 + 0.4 * (1.0 - e), 0.15, 1.0 - e));
|
||||
}
|
||||
let _ = hot;
|
||||
// rival masters' cores in their colours
|
||||
}
|
||||
|
||||
fn draw_landmarks_glow(g: &Game, t: f32, cam_r: Vec3) {
|
||||
let (cx, cy) = g.map.core;
|
||||
let hp = (g.core_hp / CORE_HP).clamp(0.0, 1.0);
|
||||
draw_heart(vec3(cx as f32 + 1.5, 0.0, cy as f32 + 1.5), hp, t, cam_r, None);
|
||||
// the other masters' hearts: the same heart in their colours
|
||||
for rv in g.rivals.iter().filter(|r| r.alive && g.map.shown(idx(r.core.0 + 1, r.core.1 + 1))) {
|
||||
let (rx, rz) = rv.centre();
|
||||
let hp = (rv.hp / crate::rival::RIVAL_CORE_HP).clamp(0.0, 1.0);
|
||||
let col = if rv.side == 2 { vec3(0.3, 0.95, 0.4) } else { vec3(0.35, 0.55, 1.0) };
|
||||
let pulse = 1.0 + (t * (2.0 + (1.0 - hp) * 6.0) + rv.side as f32).sin() * 0.06;
|
||||
let c = vec3(rx, 1.3 + (t * 1.2).sin() * 0.05, rz);
|
||||
draw_sphere(c, 0.55 * pulse, None, Color::new(col.x * (0.4 + 0.6 * hp), col.y * (0.4 + 0.6 * hp), col.z * (0.4 + 0.6 * hp), 1.0));
|
||||
draw_sphere(c, 0.85 * pulse, None, Color::new(col.x, col.y, col.z, 0.22));
|
||||
for k in 0..4 {
|
||||
let a = t * 0.8 + k as f32 * 1.57;
|
||||
draw_cube(c + vec3(a.cos() * 0.9, (t + k as f32).sin() * 0.2, a.sin() * 0.9), vec3(0.08, 0.14, 0.04), None, Color::new(col.x, col.y, col.z, 0.8));
|
||||
}
|
||||
draw_heart(vec3(rx, 0.0, rz), hp, t + rv.side as f32 * 0.37, cam_r, Some(master_rgb(rv.side)));
|
||||
}
|
||||
// portals: runes on the arch and a vertical vortex inside it, sparks pouring out and falling
|
||||
for (pk, &(px, py)) in g.map.portals.iter().enumerate() {
|
||||
@@ -2604,11 +2619,8 @@ fn draw_shadows(g: &Game) {
|
||||
} else if e.dwarf() {
|
||||
Color::new(0.85, 0.55, 0.25, 0.85)
|
||||
} else if e.rival() {
|
||||
if e.side == 2 {
|
||||
Color::new(0.35, 0.95, 0.4, 0.85)
|
||||
} else {
|
||||
Color::new(0.4, 0.6, 1.0, 0.85)
|
||||
}
|
||||
let c = master_rgb(e.side);
|
||||
Color::new(c.x, c.y, c.z, 0.85)
|
||||
} else if e.guard {
|
||||
Color::new(1.0, 0.85, 0.3, 0.9)
|
||||
} else if e.hero {
|
||||
|
||||
+22
-1
@@ -206,8 +206,10 @@ impl Game {
|
||||
"msg.partner_out"
|
||||
} else if side == 2 {
|
||||
"msg.rival1_out"
|
||||
} else {
|
||||
} else if side == 3 {
|
||||
"msg.rival2_out"
|
||||
} else {
|
||||
"msg.rival3_out"
|
||||
};
|
||||
self.msg(key, vec![]);
|
||||
// its creatures scatter and vanish, its ground is free
|
||||
@@ -447,6 +449,25 @@ mod tests {
|
||||
assert!(g.torches.iter().any(|t| g.map.t[t.wall].owner == owner || g.map.t[t.wall].solid()), "torches");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_fourth_master_works_too_and_is_no_dwarf() {
|
||||
let mut g = (1..200u32).map(|s| Game::new_free(s, 96, 96, 1)).find(|g| g.rivals.len() == 1 && !g.gate_on).unwrap();
|
||||
let far = |g: &Game, (x, y): (i32, i32)| {
|
||||
let d = |(a, b): (i32, i32)| (a - x).pow(2) + (b - y).pow(2);
|
||||
d(g.map.core).min(d(g.rivals[0].core))
|
||||
};
|
||||
let spot = [(14, 14), (80, 14), (14, 80), (80, 80)].into_iter().max_by_key(|&p| far(&g, p)).unwrap();
|
||||
g.add_rival(4, spot.0, spot.1, 1);
|
||||
let owner = Owner::of_side(4);
|
||||
let ground0 = g.map.t.iter().filter(|t| t.owner == owner).count();
|
||||
for _ in 0..(6 * 60 * 20) {
|
||||
g.update(0.05);
|
||||
}
|
||||
assert!(g.ents.iter().any(|e| e.alive && e.side == 4 && e.rival() && !e.dwarf()), "its units belong to a master");
|
||||
let ground = g.map.t.iter().filter(|t| t.owner == owner).count();
|
||||
assert!(ground > ground0 + 20, "the yellow master digs and claims: {} -> {}", ground0, ground);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ai_dig_marks_carry_the_masters_side() {
|
||||
let mut g = rival_game(1);
|
||||
|
||||
@@ -52,6 +52,12 @@ pub fn from_bytes(data: &[u8]) -> Result<Loaded, &'static str> {
|
||||
return Err("save.err_version");
|
||||
}
|
||||
let mut game = s.game;
|
||||
// older saves kept the dwarves on side 4, which is now the fourth master
|
||||
if !game.is_master(4) && !game.rivals.iter().any(|r| r.side == 4) {
|
||||
for e in game.ents.iter_mut().filter(|e| !e.hero && e.side == 4) {
|
||||
e.side = crate::dwarves::DWARF_SIDE;
|
||||
}
|
||||
}
|
||||
game.map.activate();
|
||||
game.recount();
|
||||
Ok(Loaded { game, camera: s.camera })
|
||||
|
||||
@@ -765,8 +765,13 @@ impl Ui {
|
||||
}
|
||||
// the soul cores of the rival masters
|
||||
for rv in g.rivals.iter().filter(|r| r.alive) {
|
||||
let col = if rv.side == 2 { Color::new(0.4, 0.95, 0.45, 1.0) } else { Color::new(0.45, 0.65, 1.0, 1.0) };
|
||||
let key = if rv.side == 2 { "hud.rival1" } else { "hud.rival2" };
|
||||
let c = crate::render3d::master_rgb(rv.side);
|
||||
let col = Color::new(c.x, c.y, c.z, 1.0);
|
||||
let key = match rv.side {
|
||||
2 => "hud.rival1",
|
||||
3 => "hud.rival2",
|
||||
_ => "net.side4",
|
||||
};
|
||||
segs.insert(3, vec![txt(tr(key), col), Part::Gap, Part::Bar(rv.hp / crate::rival::RIVAL_CORE_HP, col)]);
|
||||
}
|
||||
if g.waves_on() {
|
||||
@@ -995,11 +1000,8 @@ impl Ui {
|
||||
} else if e.dwarf() {
|
||||
Color::new(0.85, 0.55, 0.25, 1.0)
|
||||
} else if e.rival() {
|
||||
if e.side == 2 {
|
||||
Color::new(0.3, 0.95, 0.4, 1.0)
|
||||
} else {
|
||||
Color::new(0.4, 0.6, 1.0, 1.0)
|
||||
}
|
||||
let c = crate::render3d::master_rgb(e.side);
|
||||
Color::new(c.x, c.y, c.z, 1.0)
|
||||
} else if e.kind == EK::Worker { Color::new(1.0, 0.6, 0.3, 1.0) } else { Color::new(1.0, 0.25, 0.25, 1.0) };
|
||||
draw_rectangle((mrx + e.disp_x.floor() * ms).floor(), (mry + e.disp_y.floor() * ms).floor(), dot, dot, c);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user