diff --git a/core/assets-raw/sprites/status/burning.png b/core/assets-raw/sprites/status/burning.png deleted file mode 100644 index 7e82dd4482..0000000000 Binary files a/core/assets-raw/sprites/status/burning.png and /dev/null differ diff --git a/core/assets-raw/sprites/status/disarmed.png b/core/assets-raw/sprites/status/disarmed.png deleted file mode 100644 index c1cfb764ba..0000000000 Binary files a/core/assets-raw/sprites/status/disarmed.png and /dev/null differ diff --git a/core/assets-raw/sprites/status/freezing.png b/core/assets-raw/sprites/status/freezing.png deleted file mode 100644 index 5be529ab12..0000000000 Binary files a/core/assets-raw/sprites/status/freezing.png and /dev/null differ diff --git a/core/assets-raw/sprites/status/melting.png b/core/assets-raw/sprites/status/melting.png deleted file mode 100644 index e3b4e54b54..0000000000 Binary files a/core/assets-raw/sprites/status/melting.png and /dev/null differ diff --git a/core/assets-raw/sprites/status/muddy.png b/core/assets-raw/sprites/status/muddy.png deleted file mode 100644 index 41946e670d..0000000000 Binary files a/core/assets-raw/sprites/status/muddy.png and /dev/null differ diff --git a/core/assets-raw/sprites/status/overclock.png b/core/assets-raw/sprites/status/overclock.png deleted file mode 100644 index ede85bb8e9..0000000000 Binary files a/core/assets-raw/sprites/status/overclock.png and /dev/null differ diff --git a/core/assets-raw/sprites/status/overdrive.png b/core/assets-raw/sprites/status/overdrive.png deleted file mode 100644 index 79a4d561c3..0000000000 Binary files a/core/assets-raw/sprites/status/overdrive.png and /dev/null differ diff --git a/core/assets-raw/sprites/status/spore-slowed.png b/core/assets-raw/sprites/status/spore-slowed.png deleted file mode 100644 index 939584437d..0000000000 Binary files a/core/assets-raw/sprites/status/spore-slowed.png and /dev/null differ diff --git a/core/assets-raw/sprites/status/wet.png b/core/assets-raw/sprites/status/wet.png deleted file mode 100644 index 3a26c4974a..0000000000 Binary files a/core/assets-raw/sprites/status/wet.png and /dev/null differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index b9dd75fe05..e1d487b504 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -628,11 +628,10 @@ status.melting.name = Melting status.sapped.name = Sapped status.spore-slowed.name = Spore Slowed status.tarred.name = Tarred -status.overdrive.name = Overdrive status.overclock.name = Overclock status.shocked.name = Shocked status.blasted.name = Blasted -status.disarmed.name = Disarmed +status.unmoving = Unmoving settings.language = Language settings.data = Game Data diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index e2dcae538f..88c6b9ccb7 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -315,3 +315,22 @@ 63418=legacy-unit-factory-ground|block-legacy-unit-factory-ground-medium 63417=interplanetary-accelerator|block-interplanetary-accelerator-medium 63416=basalt-boulder|block-basalt-boulder-medium +63415=none|status-none-icon +63414=burning|status-burning-icon +63413=freezing|status-freezing-icon +63412=unmoving|status-unmoving-icon +63411=slow|status-slow-icon +63410=wet|status-wet-icon +63409=muddy|status-muddy-icon +63408=melting|status-melting-icon +63407=sapped|status-sapped-icon +63406=spore-slowed|status-spore-slowed-icon +63405=tarred|status-tarred-icon +63404=overdrive|status-overdrive-icon +63403=overclock|status-overclock-icon +63402=shielded|status-shielded-icon +63401=boss|status-boss-icon +63400=shocked|status-shocked-icon +63399=blasted|status-blasted-icon +63398=corroded|status-corroded-icon +63397=disarmed|status-disarmed-icon diff --git a/core/src/mindustry/content/StatusEffects.java b/core/src/mindustry/content/StatusEffects.java index 798adb92db..39db9cad6b 100644 --- a/core/src/mindustry/content/StatusEffects.java +++ b/core/src/mindustry/content/StatusEffects.java @@ -12,7 +12,7 @@ import mindustry.graphics.*; import static mindustry.Vars.*; public class StatusEffects implements ContentList{ - public static StatusEffect none, burning, freezing, unmoving, slow, wet, muddy, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, corroded, boss, sporeSlowed, disarmed; + public static StatusEffect none, burning, freezing, unmoving, slow, wet, muddy, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, boss, sporeSlowed, disarmed; @Override public void load(){ @@ -20,14 +20,15 @@ public class StatusEffects implements ContentList{ none = new StatusEffect("none"); burning = new StatusEffect("burning"){{ - color = Pal.lightFlame; + color = Color.valueOf("ffc455"); damage = 0.12f; //over 8 seconds, this would be ~60 damage effect = Fx.burning; + transitionDamage = 8f; init(() -> { opposite(wet, freezing); affinity(tarred, ((unit, time, newTime, result) -> { - unit.damagePierce(8f); + unit.damagePierce(transitionDamage); Fx.burning.at(unit.x + Mathf.range(unit.bounds() / 2f), unit.y + Mathf.range(unit.bounds() / 2f)); result.set(burning, Math.min(time + newTime, 300f)); })); @@ -39,12 +40,13 @@ public class StatusEffects implements ContentList{ speedMultiplier = 0.6f; healthMultiplier = 0.8f; effect = Fx.freezing; + transitionDamage = 18f; init(() -> { opposite(melting, burning); affinity(blasted, ((unit, time, newTime, result) -> { - unit.damagePierce(18f); + unit.damagePierce(transitionDamage); result.set(freezing, time); })); }); @@ -65,10 +67,11 @@ public class StatusEffects implements ContentList{ speedMultiplier = 0.94f; effect = Fx.wet; effectChance = 0.09f; + transitionDamage = 14; init(() -> { affinity(shocked, ((unit, time, newTime, result) -> { - unit.damagePierce(14f); + unit.damagePierce(transitionDamage); if(unit.team == state.rules.waveTeam){ Events.fire(Trigger.shock); } @@ -169,11 +172,6 @@ public class StatusEffects implements ContentList{ reactive = true; }}; - corroded = new StatusEffect("corroded"){{ - color = Pal.plastanium; - damage = 0.1f; - }}; - disarmed = new StatusEffect("disarmed"){{ color = Color.valueOf("e9ead3"); disarm = true; diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index 2ca30a2d51..1b1e2b6a5c 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -139,7 +139,9 @@ public class Control implements ApplicationListener, Loadable{ })); Events.on(UnlockEvent.class, e -> { - ui.hudfrag.showUnlock(e.content); + if(e.content.showUnlock()){ + ui.hudfrag.showUnlock(e.content); + } checkAutoUnlocks(); diff --git a/core/src/mindustry/ctype/UnlockableContent.java b/core/src/mindustry/ctype/UnlockableContent.java index a08dab1b67..85b29469ae 100644 --- a/core/src/mindustry/ctype/UnlockableContent.java +++ b/core/src/mindustry/ctype/UnlockableContent.java @@ -95,6 +95,10 @@ public abstract class UnlockableContent extends MappableContent{ return cicons[icon.ordinal()]; } + public Cicon prefDatabaseIcon(){ + return Cicon.xlarge; + } + /** Iterates through any implicit dependencies of this content. * For blocks, this would be the items required to build it. */ public void getDependencies(Cons cons){ @@ -115,6 +119,11 @@ public abstract class UnlockableContent extends MappableContent{ return false; } + /** @return whether to show a notification toast when this is unlocked */ + public boolean showUnlock(){ + return true; + } + /** Makes this piece of content unlocked; if it already unlocked, nothing happens. */ public void unlock(){ if(!unlocked && !alwaysUnlocked){ diff --git a/core/src/mindustry/entities/comp/StatusComp.java b/core/src/mindustry/entities/comp/StatusComp.java index bce8444361..89ed591fab 100644 --- a/core/src/mindustry/entities/comp/StatusComp.java +++ b/core/src/mindustry/entities/comp/StatusComp.java @@ -33,6 +33,11 @@ abstract class StatusComp implements Posc, Flyingc{ void apply(StatusEffect effect, float duration){ if(effect == StatusEffects.none || effect == null || isImmune(effect)) return; //don't apply empty or immune effects + //unlock status effects regardless of whether they were applied to friendly units + if(state.isCampaign()){ + effect.unlock(); + } + if(statuses.size > 0){ //check for opposite effects for(int i = 0; i < statuses.size; i ++){ diff --git a/core/src/mindustry/io/JsonIO.java b/core/src/mindustry/io/JsonIO.java index c8e43d5a20..d6ef8f8e17 100644 --- a/core/src/mindustry/io/JsonIO.java +++ b/core/src/mindustry/io/JsonIO.java @@ -208,9 +208,7 @@ public class JsonIO{ static class CustomJson extends Json{ private Object baseObject; - { - apply(this); - } + { apply(this); } @Override public T fromJson(Class type, String json){ diff --git a/core/src/mindustry/type/StatusEffect.java b/core/src/mindustry/type/StatusEffect.java index 015b79abfb..3e322deb2c 100644 --- a/core/src/mindustry/type/StatusEffect.java +++ b/core/src/mindustry/type/StatusEffect.java @@ -1,7 +1,6 @@ package mindustry.type; import arc.graphics.*; -import arc.graphics.g2d.*; import arc.math.*; import arc.struct.*; import arc.util.*; @@ -10,8 +9,8 @@ import mindustry.ctype.*; import mindustry.entities.*; import mindustry.entities.units.*; import mindustry.gen.*; -import mindustry.world.meta.*; import mindustry.ui.*; +import mindustry.world.meta.*; public class StatusEffect extends UnlockableContent{ /** Damage dealt by the unit with the effect. */ @@ -24,6 +23,8 @@ public class StatusEffect extends UnlockableContent{ public float reloadMultiplier = 1f; /** Unit build speed multiplier. */ public float buildSpeedMultiplier = 1f; + /** Damage dealt upon transition to an affinity. */ + public float transitionDamage = 0f; /** Unit weapon(s) disabled. */ public boolean disarm = false; /** Damage per frame. */ @@ -66,37 +67,39 @@ public class StatusEffect extends UnlockableContent{ @Override public void setStats(){ - if(damageMultiplier != 1){ - stats.addPercent(Stat.damageMultiplier, damageMultiplier); + if(damageMultiplier != 1) stats.addPercent(Stat.damageMultiplier, damageMultiplier); + if(healthMultiplier != 1) stats.addPercent(Stat.healthMultiplier, healthMultiplier); + if(speedMultiplier != 1) stats.addPercent(Stat.speedMultiplier, speedMultiplier); + if(reloadMultiplier != 1) stats.addPercent(Stat.reloadMultiplier, reloadMultiplier); + if(buildSpeedMultiplier != 1) stats.addPercent(Stat.buildSpeedMultiplier, buildSpeedMultiplier); + if(damage > 0) stats.add(Stat.damage, damage * 60f, StatUnit.perSecond); + + var afseq = affinities.asArray().sort(); + var opseq = opposites.asArray().sort(); + + for(int i = 0; i < afseq.size; i++){ + var e = afseq.get(i); + stats.add(Stat.affinities, e.emoji() + "" + e.toString()); + } + + if(afseq.any() && transitionDamage != 0){ + stats.add(Stat.affinities, "/ [accent]" + (int)transitionDamage + " " + Stat.damage.localized()); } - if(healthMultiplier != 1){ - stats.addPercent(Stat.healthMultiplier, healthMultiplier); + for(int i = 0; i < opseq.size; i++){ + var e = opseq.get(i); + stats.add(Stat.opposites, e.emoji() + "" + e.toString()); } + } - if(speedMultiplier != 1){ - stats.addPercent(Stat.speedMultiplier, speedMultiplier); - } + @Override + public Cicon prefDatabaseIcon(){ + return Cicon.large; + } - if(reloadMultiplier != 1){ - stats.addPercent(Stat.reloadMultiplier, reloadMultiplier); - } - - if(buildSpeedMultiplier != 1){ - stats.addPercent(Stat.buildSpeedMultiplier, buildSpeedMultiplier); - } - - if(damage > 0){ - stats.add(Stat.damage, damage * 60f, StatUnit.perSecond); - } - - for(StatusEffect e : affinities){ - stats.add(Stat.affinities, e.toString(), StatUnit.none); - } - - for(StatusEffect e : opposites){ - stats.add(Stat.opposites, e.toString(), StatUnit.none); - } + @Override + public boolean showUnlock(){ + return false; } /** Runs every tick on the affected unit while time is greater than 0. */ diff --git a/core/src/mindustry/ui/dialogs/ContentInfoDialog.java b/core/src/mindustry/ui/dialogs/ContentInfoDialog.java index b076d4b766..1d03d360f3 100644 --- a/core/src/mindustry/ui/dialogs/ContentInfoDialog.java +++ b/core/src/mindustry/ui/dialogs/ContentInfoDialog.java @@ -6,7 +6,6 @@ import arc.struct.*; import arc.util.*; import mindustry.ctype.*; import mindustry.graphics.*; -import mindustry.ui.*; import mindustry.world.meta.*; public class ContentInfoDialog extends BaseDialog{ @@ -27,9 +26,9 @@ public class ContentInfoDialog extends BaseDialog{ content.checkStats(); table.table(title1 -> { - int size = 8 * 6; + var size = content.prefDatabaseIcon(); - title1.image(content.icon(Cicon.xlarge)).size(size).scaling(Scaling.fit); + title1.image(content.icon(size)).size(size.size).scaling(Scaling.fit); title1.add("[accent]" + content.localizedName).padLeft(5); }); diff --git a/core/src/mindustry/world/blocks/logic/MessageBlock.java b/core/src/mindustry/world/blocks/logic/MessageBlock.java index 0e34825b49..d279e079d9 100644 --- a/core/src/mindustry/world/blocks/logic/MessageBlock.java +++ b/core/src/mindustry/world/blocks/logic/MessageBlock.java @@ -44,8 +44,7 @@ public class MessageBlock extends Block{ for(int i = 0; i < text.length(); i++){ char c = text.charAt(i); if(c == '\n'){ - count ++; - if(count <= maxNewlines){ + if(count++ <= maxNewlines){ tile.message.append('\n'); } }else{ diff --git a/tools/src/mindustry/tools/Generators.java b/tools/src/mindustry/tools/Generators.java index 2cc68f1eff..baf23762bf 100644 --- a/tools/src/mindustry/tools/Generators.java +++ b/tools/src/mindustry/tools/Generators.java @@ -376,8 +376,24 @@ public class Generators{ }); ImagePacker.generate("item-icons", () -> { - for(UnlockableContent item : Seq.withArrays(content.items(), content.liquids())){ + for(UnlockableContent item : Seq.withArrays(content.items(), content.liquids(), content.statusEffects())){ + if(item instanceof StatusEffect && !ImagePacker.has(item.getContentType().name() + "-" + item.name)){ + continue; + } + Image base = ImagePacker.get(item.getContentType().name() + "-" + item.name); + //tint status effect icon color + if(item instanceof StatusEffect){ + StatusEffect stat = (StatusEffect)item; + Image tint = base; + base.each((x, y) -> tint.draw(x, y, tint.getColor(x, y).mul(stat.color))); + + //outline the image + Image container = new Image(38, 38); + container.draw(base, 3, 3); + base = container.outline(3, Pal.gray); + } + for(Cicon icon : Cicon.scaled){ //if(icon.size == base.width) continue; Image image = new Image(icon.size, icon.size); diff --git a/tools/src/mindustry/tools/ImagePacker.java b/tools/src/mindustry/tools/ImagePacker.java index 1142de8a26..25c5fa6b27 100644 --- a/tools/src/mindustry/tools/ImagePacker.java +++ b/tools/src/mindustry/tools/ImagePacker.java @@ -106,7 +106,7 @@ public class ImagePacker{ ObjectMap content2id = new ObjectMap<>(); map.each((key, val) -> content2id.put(val.split("\\|")[0], key)); - Seq cont = Seq.withArrays(Vars.content.blocks(), Vars.content.items(), Vars.content.liquids(), Vars.content.units()); + Seq cont = Seq.withArrays(Vars.content.blocks(), Vars.content.items(), Vars.content.liquids(), Vars.content.units(), Vars.content.statusEffects()); cont.removeAll(u -> u instanceof ConstructBlock || u == Blocks.air); int minid = 0xF8FF;