diff --git a/core/assets-raw/fonts/Arturito Slab_v2.ttf b/core/assets-raw/fonts/Arturito Slab_v2.ttf new file mode 100755 index 0000000000..04096503fa Binary files /dev/null and b/core/assets-raw/fonts/Arturito Slab_v2.ttf differ diff --git a/core/assets-raw/fonts/RussoOne-Regular.ttf b/core/assets-raw/fonts/RussoOne-Regular.ttf deleted file mode 100644 index c0236b0547..0000000000 Binary files a/core/assets-raw/fonts/RussoOne-Regular.ttf and /dev/null differ diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index 83ac42defa..920a9c38ab 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -109,7 +109,7 @@ public class Control implements ApplicationListener, Loadable{ Events.on(GameOverEvent.class, event -> { state.stats.wavesLasted = state.wave; - Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); + Effect.shake(5, 6, Core.camera.position.x, Core.camera.position.y); //the restart dialog can show info for any number of scenarios Call.gameOver(event.winner); }); @@ -188,7 +188,7 @@ public class Control implements ApplicationListener, Loadable{ app.post(() -> Fx.coreLand.at(core.getX(), core.getY(), 0, core.block())); Time.run(Fx.coreLand.lifetime, () -> { Fx.launch.at(core); - Effects.shake(5f, 5f, core); + Effect.shake(5f, 5f, core); }); }); diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java index 19f1ec454e..cfa908ca59 100644 --- a/core/src/mindustry/core/NetClient.java +++ b/core/src/mindustry/core/NetClient.java @@ -2,6 +2,7 @@ package mindustry.core; import arc.*; import arc.func.*; +import arc.graphics.*; import arc.math.*; import arc.struct.*; import arc.util.*; @@ -11,6 +12,7 @@ import arc.util.serialization.*; import mindustry.*; import mindustry.annotations.Annotations.*; import mindustry.core.GameState.*; +import mindustry.entities.*; import mindustry.entities.units.*; import mindustry.game.EventType.*; import mindustry.game.*; @@ -314,7 +316,6 @@ public class NetClient implements ApplicationListener{ ui.showLabel(message, duration, worldx, worldy); } - /* @Remote(variants = Variant.both, unreliable = true) public static void onEffect(Effect effect, float x, float y, float rotation, Color color){ if(effect == null) return; @@ -325,7 +326,7 @@ public class NetClient implements ApplicationListener{ @Remote(variants = Variant.both) public static void onEffectReliable(Effect effect, float x, float y, float rotation, Color color){ onEffect(effect, x, y, rotation, color); - }*/ + } @Remote(variants = Variant.both) public static void infoToast(String message, float duration){ diff --git a/core/src/mindustry/entities/Damage.java b/core/src/mindustry/entities/Damage.java index a8d743a320..2650588cb8 100644 --- a/core/src/mindustry/entities/Damage.java +++ b/core/src/mindustry/entities/Damage.java @@ -59,7 +59,7 @@ public class Damage{ } float shake = Math.min(explosiveness / 4f + 3f, 9f); - Effects.shake(shake, shake, x, y); + Effect.shake(shake, shake, x, y); Fx.dynamicExplosion.at(x, y, radius / 8f); } diff --git a/core/src/mindustry/entities/Effect.java b/core/src/mindustry/entities/Effect.java index 37640b577b..7950c5375c 100644 --- a/core/src/mindustry/entities/Effect.java +++ b/core/src/mindustry/entities/Effect.java @@ -1,15 +1,26 @@ package mindustry.entities; +import arc.*; import arc.func.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.math.*; import arc.math.geom.*; +import arc.struct.*; +import arc.util.*; +import arc.util.ArcAnnotate.*; +import mindustry.*; +import mindustry.content.*; +import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.world.*; + +import static mindustry.Vars.*; public class Effect{ + private static final float shakeFalloff = 10000f; private static final EffectContainer container = new EffectContainer(); - private static int lastid = 0; + private static final Seq all = new Seq<>(); public final int id; public final Cons renderer; @@ -21,10 +32,11 @@ public class Effect{ public float groundDuration; public Effect(float life, float clipsize, Cons renderer){ - this.id = lastid++; + this.id = all.size; this.lifetime = life; this.renderer = renderer; this.size = clipsize; + all.add(this); } public Effect(float life, Cons renderer){ @@ -43,35 +55,35 @@ public class Effect{ } public void at(Position pos){ - Effects.create(this, pos.getX(), pos.getY(), 0, Color.white, null); + create(this, pos.getX(), pos.getY(), 0, Color.white, null); } public void at(Position pos, float rotation){ - Effects.create(this, pos.getX(), pos.getY(), rotation, Color.white, null); + create(this, pos.getX(), pos.getY(), rotation, Color.white, null); } public void at(float x, float y){ - Effects.create(this, x, y, 0, Color.white, null); + create(this, x, y, 0, Color.white, null); } public void at(float x, float y, float rotation){ - Effects.create(this, x, y, rotation, Color.white, null); + create(this, x, y, rotation, Color.white, null); } public void at(float x, float y, float rotation, Color color){ - Effects.create(this, x, y, rotation, color, null); + create(this, x, y, rotation, color, null); } public void at(float x, float y, Color color){ - Effects.create(this, x, y, 0, color, null); + create(this, x, y, 0, color, null); } public void at(float x, float y, float rotation, Color color, Object data){ - Effects.create(this, x, y, rotation, color, data); + create(this, x, y, rotation, color, data); } public void at(float x, float y, float rotation, Object data){ - Effects.create(this, x, y, rotation, Color.white, data); + create(this, x, y, rotation, Color.white, data); } public void render(int id, Color color, float life, float rotation, float x, float y, Object data){ @@ -81,6 +93,84 @@ public class Effect{ Draw.reset(); } + public static @Nullable Effect get(int id){ + return id >= all.size || id < 0 ? null : all.get(id); + } + + private static void shake(float intensity, float duration){ + if(!headless){ + Vars.renderer.shake(intensity, duration); + } + } + + public static void shake(float intensity, float duration, float x, float y){ + if(Core.camera == null) return; + + float distance = Core.camera.position.dst(x, y); + if(distance < 1) distance = 1; + + shake(Mathf.clamp(1f / (distance * distance / shakeFalloff)) * intensity, duration); + } + + public static void shake(float intensity, float duration, Position loc){ + shake(intensity, duration, loc.getX(), loc.getY()); + } + + public static void create(Effect effect, float x, float y, float rotation, Color color, Object data){ + if(headless || effect == Fx.none) return; + if(Core.settings.getBool("effects")){ + Rect view = Core.camera.bounds(Tmp.r1); + Rect pos = Tmp.r2.setSize(effect.size).setCenter(x, y); + + if(view.overlaps(pos)){ + EffectState entity = EffectState.create(); + entity.effect(effect); + entity.rotation(rotation); + entity.data(data); + entity.lifetime(effect.lifetime); + entity.set(x, y); + entity.color().set(color); + if(data instanceof Posc) entity.parent((Posc)data); + entity.add(); + } + } + } + + public static void decal(TextureRegion region, float x, float y, float rotation){ + decal(region, x, y, rotation, 3600f, Pal.rubble); + } + + public static void decal(TextureRegion region, float x, float y, float rotation, float lifetime, Color color){ + if(headless || region == null || !Core.atlas.isFound(region)) return; + + Tile tile = world.tileWorld(x, y); + if(tile == null || tile.floor().isLiquid) return; + + Decal decal = Decal.create(); + decal.set(x, y); + decal.rotation(rotation); + decal.lifetime(lifetime); + decal.color().set(color); + decal.region(region); + decal.add(); + } + + public static void scorch(float x, float y, int size){ + if(headless) return; + + size = Mathf.clamp(size, 0, 9); + + TextureRegion region = Core.atlas.find("scorch-" + size + "-" + Mathf.random(2)); + decal(region, x, y, Mathf.random(4) * 90, 3600, Pal.rubble); + } + + public static void rubble(float x, float y, int blockSize){ + if(headless) return; + + TextureRegion region = Core.atlas.find("rubble-" + blockSize + "-" + (Core.atlas.has("rubble-" + blockSize + "-1") ? Mathf.random(0, 1) : "0")); + decal(region, x, y, Mathf.random(4) * 90, 3600, Pal.rubble); + } + public static class EffectContainer implements Scaled{ public float x, y, time, lifetime, rotation; public Color color; diff --git a/core/src/mindustry/entities/Effects.java b/core/src/mindustry/entities/Effects.java deleted file mode 100644 index ed4cca412f..0000000000 --- a/core/src/mindustry/entities/Effects.java +++ /dev/null @@ -1,92 +0,0 @@ -package mindustry.entities; - -import arc.*; -import arc.graphics.*; -import arc.graphics.g2d.*; -import arc.math.*; -import arc.math.geom.*; -import arc.util.*; -import mindustry.content.*; -import mindustry.gen.*; -import mindustry.graphics.*; -import mindustry.world.*; - -import static mindustry.Vars.*; - -public class Effects{ - private static final float shakeFalloff = 10000f; - - private static void shake(float intensity, float duration){ - if(!headless){ - renderer.shake(intensity, duration); - } - } - - public static void shake(float intensity, float duration, float x, float y){ - if(Core.camera == null) return; - - float distance = Core.camera.position.dst(x, y); - if(distance < 1) distance = 1; - - shake(Mathf.clamp(1f / (distance * distance / shakeFalloff)) * intensity, duration); - } - - public static void shake(float intensity, float duration, Position loc){ - shake(intensity, duration, loc.getX(), loc.getY()); - } - - public static void create(Effect effect, float x, float y, float rotation, Color color, Object data){ - if(headless || effect == Fx.none) return; - if(Core.settings.getBool("effects")){ - Rect view = Core.camera.bounds(Tmp.r1); - Rect pos = Tmp.r2.setSize(effect.size).setCenter(x, y); - - if(view.overlaps(pos)){ - EffectState entity = EffectState.create(); - entity.effect(effect); - entity.rotation(rotation); - entity.data(data); - entity.lifetime(effect.lifetime); - entity.set(x, y); - entity.color().set(color); - if(data instanceof Posc) entity.parent((Posc)data); - entity.add(); - } - } - } - - public static void decal(TextureRegion region, float x, float y, float rotation){ - decal(region, x, y, rotation, 3600f, Pal.rubble); - } - - public static void decal(TextureRegion region, float x, float y, float rotation, float lifetime, Color color){ - if(headless || region == null || !Core.atlas.isFound(region)) return; - - Tile tile = world.tileWorld(x, y); - if(tile == null || tile.floor().isLiquid) return; - - Decal decal = Decal.create(); - decal.set(x, y); - decal.rotation(rotation); - decal.lifetime(lifetime); - decal.color().set(color); - decal.region(region); - decal.add(); - } - - public static void scorch(float x, float y, int size){ - if(headless) return; - - size = Mathf.clamp(size, 0, 9); - - TextureRegion region = Core.atlas.find("scorch-" + size + "-" + Mathf.random(2)); - decal(region, x, y, Mathf.random(4) * 90, 3600, Pal.rubble); - } - - public static void rubble(float x, float y, int blockSize){ - if(headless) return; - - TextureRegion region = Core.atlas.find("rubble-" + blockSize + "-" + (Core.atlas.has("rubble-" + blockSize + "-1") ? Mathf.random(0, 1) : "0")); - decal(region, x, y, Mathf.random(4) * 90, 3600, Pal.rubble); - } -} diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index 2d23d9eb4b..74f188f042 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -142,7 +142,7 @@ public abstract class BulletType extends Content{ hitEffect.at(x, y, b.rotation(), hitColor); hitSound.at(b); - Effects.shake(hitShake, hitShake, b); + Effect.shake(hitShake, hitShake, b); if(fragBullet != null){ for(int i = 0; i < fragBullets; i++){ diff --git a/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java b/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java index 1086fcd48e..34dd5d2c67 100644 --- a/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java +++ b/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java @@ -53,7 +53,7 @@ public class ContinuousLaserBulletType extends BulletType{ } if(shake > 0){ - Effects.shake(shake, shake, b); + Effect.shake(shake, shake, b); } } diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 1469853477..0f090a1893 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -879,7 +879,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, Damage.dynamicExplosion(x, y, flammability, explosiveness * 3.5f, power, tilesize * block.size / 2f, Pal.darkFlame); if(!floor().solid && !floor().isLiquid){ - Effects.rubble(x, y, block.size); + Effect.rubble(x, y, block.size); } } diff --git a/core/src/mindustry/entities/comp/LegsComp.java b/core/src/mindustry/entities/comp/LegsComp.java index e516c6befe..ece772c0d0 100644 --- a/core/src/mindustry/entities/comp/LegsComp.java +++ b/core/src/mindustry/entities/comp/LegsComp.java @@ -100,7 +100,7 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{ //shake when legs contact ground if(type.landShake > 0){ - Effects.shake(type.landShake, type.landShake, l.base); + Effect.shake(type.landShake, type.landShake, l.base); } if(type.legSplashDamage > 0){ diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java index d802236a53..a770a2e762 100644 --- a/core/src/mindustry/entities/comp/UnitComp.java +++ b/core/src/mindustry/entities/comp/UnitComp.java @@ -181,7 +181,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I @Override public void landed(){ if(type.landShake > 0f){ - Effects.shake(type.landShake, type.landShake, this); + Effect.shake(type.landShake, type.landShake, this); } type.landed(base()); @@ -283,9 +283,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I float shake = hitSize / 3f; - Effects.scorch(x, y, (int)(hitSize / 5)); + Effect.scorch(x, y, (int)(hitSize / 5)); Fx.explosion.at(this); - Effects.shake(shake, shake, this); + Effect.shake(shake, shake, this); type.deathSound.at(this); Events.fire(new UnitDestroyEvent(base())); @@ -304,7 +304,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I if(type.wreckRegions[i].found()){ float range = type.hitsize/4f; Tmp.v1.rnd(range); - Effects.decal(type.wreckRegions[i], x + Tmp.v1.x, y + Tmp.v1.y, rotation - 90); + Effect.decal(type.wreckRegions[i], x + Tmp.v1.x, y + Tmp.v1.y, rotation - 90); } } } diff --git a/core/src/mindustry/entities/comp/WeaponsComp.java b/core/src/mindustry/entities/comp/WeaponsComp.java index ef199f01fd..d464a7024f 100644 --- a/core/src/mindustry/entities/comp/WeaponsComp.java +++ b/core/src/mindustry/entities/comp/WeaponsComp.java @@ -156,7 +156,7 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{ } boolean parentize = ammo.keepVelocity; - Effects.shake(weapon.shake, weapon.shake, x, y); + Effect.shake(weapon.shake, weapon.shake, x, y); weapon.ejectEffect.at(x, y, rotation * side); ammo.shootEffect.at(x, y, rotation, parentize ? this : null); ammo.smokeEffect.at(x, y, rotation, parentize ? this : null); diff --git a/core/src/mindustry/io/TypeIO.java b/core/src/mindustry/io/TypeIO.java index ade16c63cf..baa0bcba64 100644 --- a/core/src/mindustry/io/TypeIO.java +++ b/core/src/mindustry/io/TypeIO.java @@ -10,6 +10,7 @@ import mindustry.annotations.Annotations.*; import mindustry.content.*; import mindustry.content.TechTree.*; import mindustry.ctype.*; +import mindustry.entities.*; import mindustry.entities.bullet.*; import mindustry.entities.units.*; import mindustry.game.*; @@ -384,14 +385,22 @@ public class TypeIO{ return AdminAction.values()[read.b()]; } - public static void writeUnitDef(Writes write, UnitType effect){ + public static void writeUnitType(Writes write, UnitType effect){ write.s(effect.id); } - public static UnitType readUnitDef(Reads read){ + public static UnitType readUnitType(Reads read){ return content.getByID(ContentType.unit, read.s()); } + public static void writeEffect(Writes write, Effect effect){ + write.s(effect.id); + } + + public static Effect readEffect(Reads read){ + return Effect.get(read.us()); + } + public static void writeColor(Writes write, Color color){ write.i(color.rgba()); } diff --git a/core/src/mindustry/maps/SectorDamage.java b/core/src/mindustry/maps/SectorDamage.java index cf0c785d45..da946ea686 100644 --- a/core/src/mindustry/maps/SectorDamage.java +++ b/core/src/mindustry/maps/SectorDamage.java @@ -44,7 +44,7 @@ public class SectorDamage{ //just remove all the buildings in the way - as long as they're not cores! if(other.build != null && other.team() == state.rules.defaultTeam && !(other.block() instanceof CoreBlock)){ if(rubble && !other.floor().solid && !other.floor().isLiquid && Mathf.chance(0.4)){ - Effects.rubble(other.build.x, other.build.y, other.block().size); + Effect.rubble(other.build.x, other.build.y, other.block().size); } other.remove(); @@ -86,7 +86,7 @@ public class SectorDamage{ if(other.build.health < 0){ //rubble if(rubble && !other.floor().solid && !other.floor().isLiquid && Mathf.chance(0.4)){ - Effects.rubble(other.build.x, other.build.y, other.block().size); + Effect.rubble(other.build.x, other.build.y, other.block().size); } other.remove(); diff --git a/core/src/mindustry/world/blocks/BuildBlock.java b/core/src/mindustry/world/blocks/BuildBlock.java index 50a6d45688..7692db85c8 100644 --- a/core/src/mindustry/world/blocks/BuildBlock.java +++ b/core/src/mindustry/world/blocks/BuildBlock.java @@ -163,7 +163,7 @@ public class BuildBlock extends Block{ Fx.blockExplosionSmoke.at(tile); if(!tile.floor().solid && !tile.floor().isLiquid){ - Effects.rubble(x, y, size); + Effect.rubble(x, y, size); } } diff --git a/core/src/mindustry/world/blocks/campaign/LaunchPad.java b/core/src/mindustry/world/blocks/campaign/LaunchPad.java index 3c2c69b25f..2713c5ef3d 100644 --- a/core/src/mindustry/world/blocks/campaign/LaunchPad.java +++ b/core/src/mindustry/world/blocks/campaign/LaunchPad.java @@ -104,7 +104,7 @@ public class LaunchPad extends Block{ entity.add(); Fx.launchPod.at(this); items.clear(); - Effects.shake(3f, 3f, this); + Effect.shake(3f, 3f, this); } } } diff --git a/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java b/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java index 9109937f95..b20d5ba0a2 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java @@ -98,7 +98,7 @@ public class LiquidTurret extends Turret{ shootSound.at(tile); if(shootShake > 0){ - Effects.shake(shootShake, shootShake, tile.build); + Effect.shake(shootShake, shootShake, tile.build); } recoil = recoilAmount; diff --git a/core/src/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/mindustry/world/blocks/defense/turrets/Turret.java index 101e0aa402..584998ce90 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/Turret.java @@ -369,7 +369,7 @@ public abstract class Turret extends Block{ shootSound.at(tile, Mathf.random(0.9f, 1.1f)); if(shootShake > 0){ - Effects.shake(shootShake, shootShake, this); + Effect.shake(shootShake, shootShake, this); } recoil = recoilAmount; diff --git a/core/src/mindustry/world/blocks/distribution/MassDriver.java b/core/src/mindustry/world/blocks/distribution/MassDriver.java index 6cd1e57d6c..b61f57f741 100644 --- a/core/src/mindustry/world/blocks/distribution/MassDriver.java +++ b/core/src/mindustry/world/blocks/distribution/MassDriver.java @@ -262,7 +262,7 @@ public class MassDriver extends Block{ smokeEffect.at(x + Angles.trnsx(angle, translation), y + Angles.trnsy(angle, translation), angle); - Effects.shake(shake, shake, this); + Effect.shake(shake, shake, this); } public void handlePayload(Bullet bullet, DriverBulletData data){ @@ -280,7 +280,7 @@ public class MassDriver extends Block{ } } - Effects.shake(shake, shake, this); + Effect.shake(shake, shake, this); receiveEffect.at(bullet); reload = 1f; diff --git a/core/src/mindustry/world/blocks/power/ImpactReactor.java b/core/src/mindustry/world/blocks/power/ImpactReactor.java index 545e07dca0..2dd54dd844 100644 --- a/core/src/mindustry/world/blocks/power/ImpactReactor.java +++ b/core/src/mindustry/world/blocks/power/ImpactReactor.java @@ -126,7 +126,7 @@ public class ImpactReactor extends PowerGenerator{ Sounds.explosionbig.at(tile); - Effects.shake(6f, 16f, x, y); + Effect.shake(6f, 16f, x, y); Fx.impactShockwave.at(x, y); for(int i = 0; i < 6; i++){ Time.run(Mathf.random(80), () -> Fx.impactcloud.at(x, y)); diff --git a/core/src/mindustry/world/blocks/power/NuclearReactor.java b/core/src/mindustry/world/blocks/power/NuclearReactor.java index ec8abc9176..231525cd4d 100644 --- a/core/src/mindustry/world/blocks/power/NuclearReactor.java +++ b/core/src/mindustry/world/blocks/power/NuclearReactor.java @@ -117,7 +117,7 @@ public class NuclearReactor extends PowerGenerator{ if((fuel < 5 && heat < 0.5f) || !state.rules.reactorExplosions) return; - Effects.shake(6f, 16f, x, y); + Effect.shake(6f, 16f, x, y); Fx.nuclearShockwave.at(x, y); for(int i = 0; i < 6; i++){ Time.run(Mathf.random(40), () -> Fx.nuclearcloud.at(x, y)); diff --git a/core/src/mindustry/world/blocks/units/Reconstructor.java b/core/src/mindustry/world/blocks/units/Reconstructor.java index fdd516fc51..ec09128fde 100644 --- a/core/src/mindustry/world/blocks/units/Reconstructor.java +++ b/core/src/mindustry/world/blocks/units/Reconstructor.java @@ -146,7 +146,7 @@ public class Reconstructor extends UnitBlock{ if(progress >= constructTime){ payload.unit = upgrade(payload.unit.type()).create(payload.unit.team()); progress = 0; - Effects.shake(2f, 3f, this); + Effect.shake(2f, 3f, this); Fx.producesmoke.at(this); consume(); }