diff --git a/core/assets-raw/sprites/blocks/environment/steam-vent1.png b/core/assets-raw/sprites/blocks/environment/steam-vent1.png new file mode 100644 index 0000000000..8ab218732f Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/steam-vent1.png differ diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index ffe341fdc9..d8453cd7eb 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -409,3 +409,4 @@ 63299=breach|block-breach-ui 63298=core-bastion|block-core-bastion-ui 63297=plasma-bore|block-plasma-bore-ui +63296=steam-vent|block-steam-vent-ui diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 225d96c73b..bd989e8082 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -40,7 +40,7 @@ public class Blocks implements ContentList{ redmat, bluemat, stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster, redweed, purbush, coralChunk, yellowCoral, - regolithWall, yellowStoneWall, rhyoliteWall, carbonWall, redIceWall, ferricStoneWall, beryllicStoneWall, + regolithWall, yellowStoneWall, rhyoliteWall, steamVent, carbonWall, redIceWall, ferricStoneWall, beryllicStoneWall, ferricStone, ferricCraters, carbonStone, beryllicStone, iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, grass, salt, shaleBoulder, sandBoulder, daciteBoulder, boulder, snowBoulder, basaltBoulder, carbonBoulder, ferricBoulder, beryllicBoulder, @@ -334,6 +334,10 @@ public class Blocks implements ContentList{ blendGroup = rhyolite; }}; + steamVent = new SteamVent("steam-vent"){{ + parent = blendGroup = rhyolite; + }}; + regolith = new Floor("regolith"){{ attributes.set(Attribute.water, -1f); }}; diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 7b5ccfbd42..7d9c1c5f7a 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -941,6 +941,17 @@ public class Fx{ }); }), + ventSteam = new Effect(140f, e -> { + color(Pal.vent, e.fslope() * 0.85f); + + float length = 3f + e.finpow() * 10f; + rand.setSeed(e.id); + for(int i = 0; i < rand.random(3, 5); i++){ + v.trns(rand.random(360f), rand.random(length)); + Fill.circle(e.x + v.x, e.y + v.y, rand.random(1.2f, 3.5f) + e.fslope() * 1.1f); + } + }), + vapor = new Effect(110f, e -> { color(e.color); alpha(e.fout()); diff --git a/core/src/mindustry/graphics/BlockRenderer.java b/core/src/mindustry/graphics/BlockRenderer.java index 0bdd40bfa3..1704942886 100644 --- a/core/src/mindustry/graphics/BlockRenderer.java +++ b/core/src/mindustry/graphics/BlockRenderer.java @@ -14,6 +14,7 @@ import mindustry.game.EventType.*; import mindustry.game.Teams.*; import mindustry.gen.*; import mindustry.world.*; +import mindustry.world.blocks.environment.Floor.*; import mindustry.world.blocks.power.*; import static arc.Core.*; @@ -30,6 +31,7 @@ public class BlockRenderer{ private Seq tileview = new Seq<>(false, initialRequests, Tile.class); private Seq lightview = new Seq<>(false, initialRequests, Tile.class); + private Seq updateFloors = new Seq<>(UpdateRenderState.class); private int lastCamX, lastCamY, lastRangeX, lastRangeY; private float brokenFade = 0f; @@ -78,6 +80,7 @@ public class BlockRenderer{ Draw.color(); shadows.end(); + updateFloors.clear(); dark.getTexture().setFilter(TextureFilter.linear); dark.resize(world.width(), world.height()); dark.begin(); @@ -87,6 +90,10 @@ public class BlockRenderer{ for(Tile tile : world.tiles){ recordIndex(tile); + if(tile.floor().updateRender(tile)){ + updateFloors.add(new UpdateRenderState(tile, tile.floor())); + } + float darkness = world.getDarkness(tile.x, tile.y); if(darkness > 0){ @@ -271,6 +278,16 @@ public class BlockRenderer{ int rangex = (int)(camera.width / tilesize / 2); int rangey = (int)(camera.height / tilesize / 2); + if(!state.isPaused()){ + int updates = updateFloors.size; + var uitems = updateFloors.items; + for(int i = 0; i < updates; i++){ + var tile = uitems[i]; + tile.floor.renderUpdate(tile); + } + } + + if(avgx == lastCamX && avgy == lastCamY && lastRangeX == rangex && lastRangeY == rangey){ return; } diff --git a/core/src/mindustry/graphics/Pal.java b/core/src/mindustry/graphics/Pal.java index 073fb01f9d..54e3d9afe6 100644 --- a/core/src/mindustry/graphics/Pal.java +++ b/core/src/mindustry/graphics/Pal.java @@ -118,5 +118,7 @@ public class Pal{ plasticBurn = Color.valueOf("e9ead3"), - muddy = Color.valueOf("432722"); + muddy = Color.valueOf("432722"), + + vent = Color.valueOf("6b4e4e"); } diff --git a/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java b/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java index 215c215449..9be868a050 100644 --- a/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java +++ b/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java @@ -11,6 +11,7 @@ import mindustry.game.*; import mindustry.maps.generators.*; import mindustry.type.*; import mindustry.world.*; +import mindustry.world.blocks.environment.*; import mindustry.world.meta.*; import static mindustry.Vars.*; @@ -169,6 +170,27 @@ public class ErekirPlanetGenerator extends PlanetGenerator{ } }); + //vents + outer: + for(Tile tile : tiles){ + if(floor == Blocks.rhyolite && rand.chance(0.001)){ + int radius = 2; + for(int x = -radius; x <= radius; x++){ + for(int y = -radius; y <= radius; y++){ + Tile other = tiles.get(x + tile.x, y + tile.y); + if(other == null || other.floor() != Blocks.rhyolite || other.block().solid){ + continue outer; + } + } + } + + for(var pos : SteamVent.offsets){ + Tile other = tiles.get(pos.x + tile.x + 1, pos.y + tile.y + 1); + other.setFloor(Blocks.steamVent.asFloor()); + } + } + } + //it is very hot state.rules.attributes.set(Attribute.heat, 0.8f); state.rules.environment = Env.scorching | Env.terrestrial | Env.groundWater; diff --git a/core/src/mindustry/world/blocks/environment/Floor.java b/core/src/mindustry/world/blocks/environment/Floor.java index 91d677825b..22f72762e4 100644 --- a/core/src/mindustry/world/blocks/environment/Floor.java +++ b/core/src/mindustry/world/blocks/environment/Floor.java @@ -149,11 +149,13 @@ public class Floor extends Block{ @Override public void drawBase(Tile tile){ Mathf.rand.setSeed(tile.pos()); - Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); drawEdges(tile); + drawOverlay(tile); + } + public void drawOverlay(Tile tile){ Floor floor = tile.overlay(); if(floor != Blocks.air && floor != this){ //ore should never have itself on top, but it's possible, so prevent a crash in that case floor.drawBase(tile); @@ -165,6 +167,16 @@ public class Floor extends Block{ return new TextureRegion[]{Core.atlas.find(Core.atlas.has(name) ? name : name + "1")}; } + //TODO currently broken for dynamically edited floor tiles + /** @return true if this floor should be updated in the render loop, e.g. for effects. Do NOT overuse this! */ + public boolean updateRender(Tile tile){ + return false; + } + + public void renderUpdate(UpdateRenderState tile){ + + } + /** @return whether this floor has a valid surface on which to place things, e.g. scorch marks. */ public boolean hasSurface(){ return !isLiquid && !solid; @@ -251,4 +263,15 @@ public class Floor extends Block{ return block.edges()[x][2 - y]; } + public static class UpdateRenderState{ + public Tile tile; + public Floor floor; + public float data; + + public UpdateRenderState(Tile tile, Floor floor){ + this.tile = tile; + this.floor = floor; + } + } + } diff --git a/core/src/mindustry/world/blocks/environment/SteamVent.java b/core/src/mindustry/world/blocks/environment/SteamVent.java index 3157c22baa..a979e4e196 100644 --- a/core/src/mindustry/world/blocks/environment/SteamVent.java +++ b/core/src/mindustry/world/blocks/environment/SteamVent.java @@ -1,2 +1,76 @@ -package mindustry.world.blocks.environment;public class SteamVent { +package mindustry.world.blocks.environment; + +import arc.graphics.g2d.*; +import arc.math.*; +import arc.math.geom.*; +import arc.util.*; +import mindustry.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.world.*; + +import static mindustry.Vars.*; + +//can't use an overlay for this because it spans multiple tiles +public class SteamVent extends Floor{ + public static final Point2[] offsets = { + new Point2(0, 0), + new Point2(1, 0), + new Point2(1, 1), + new Point2(0, 1), + new Point2(-1, 1), + new Point2(-1, 0), + new Point2(-1, -1), + new Point2(0, -1), + new Point2(1, -1), + }; + + public Block parent = Blocks.air; + public Effect effect = Fx.ventSteam; + public float effectSpacing = 15f; + + static{ + for(var p : offsets){ + p.sub(1, 1); + } + } + + public SteamVent(String name){ + super(name); + variants = 1; + inEditor = false; + } + + @Override + public void drawBase(Tile tile){ + parent.drawBase(tile); + + if(checkAdjacent(tile)){ + Mathf.rand.setSeed(tile.pos()); + Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx() - tilesize, tile.worldy() - tilesize); + } + } + + @Override + public boolean updateRender(Tile tile){ + return checkAdjacent(tile); + } + + @Override + public void renderUpdate(UpdateRenderState state){ + if(state.tile.block() == Blocks.air && (state.data += Time.delta) >= effectSpacing){ + effect.at(state.tile.x * tilesize - tilesize, state.tile.y * tilesize - tilesize); + state.data = 0f; + } + } + + public boolean checkAdjacent(Tile tile){ + for(var point : offsets){ + Tile other = Vars.world.tile(tile.x + point.x, tile.y + point.y); + if(other == null || other.floor() != this){ + return false; + } + } + return true; + } }