More vent variants

This commit is contained in:
Anuken
2022-02-05 18:59:56 -05:00
parent 6675730571
commit 6c44f506fc
32 changed files with 290 additions and 73 deletions

View File

@@ -46,7 +46,9 @@ public class Blocks{
redmat, bluemat,
stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster,
redweed, purbush, yellowCoral,
regolithWall, yellowStoneWall, rhyoliteWall, steamVent, carbonWall, redIceWall, ferricStoneWall, beryllicStoneWall, arkyicWall, crystallineStoneWall, redStoneWall, redDiamondWall,
//TODO rename steamvent to rhyolite vent, maybe add red vent or crystal vent
rhyoliteVent, carbonVent, arkyicVent, yellowStoneVent, redStoneVent,
regolithWall, yellowStoneWall, rhyoliteWall, carbonWall, redIceWall, ferricStoneWall, beryllicStoneWall, arkyicWall, crystallineStoneWall, redStoneWall, redDiamondWall,
ferricStone, ferricCraters, carbonStone, beryllicStone, crystallineStone, crystalFloor, yellowStonePlates,
iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, grass, salt,
//boulders
@@ -382,11 +384,6 @@ public class Blocks{
variants = 3;
}};
steamVent = new SteamVent("steam-vent"){{
parent = blendGroup = rhyolite;
attributes.set(Attribute.vent, 1f);
}};
regolith = new Floor("regolith"){{
attributes.set(Attribute.water, -1f);
}};
@@ -457,10 +454,38 @@ public class Blocks{
albedo = 0.9f;
}};
arkyicStone = new Floor("arkyic-stone"){{
arkyicStone = new Floor("arkyic-stone"){{
variants = 3;
}};
//TODO different vent colors
rhyoliteVent = new SteamVent("rhyolite-vent"){{
parent = blendGroup = rhyolite;
attributes.set(Attribute.steam, 1f);
}};
carbonVent = new SteamVent("carbon-vent"){{
parent = blendGroup = carbonStone;
attributes.set(Attribute.steam, 1f);
}};
arkyicVent = new SteamVent("arkyic-vent"){{
parent = blendGroup = arkyicStone;
attributes.set(Attribute.steam, 1f);
}};
yellowStoneVent = new SteamVent("yellow-stone-vent"){{
//TODO ...or regolith
parent = blendGroup = yellowStone;
attributes.set(Attribute.steam, 1f);
}};
redStoneVent = new SteamVent("red-stone-vent"){{
//TODO ...or regolith
parent = blendGroup = denseRedStone;
attributes.set(Attribute.steam, 1f);
}};
redmat = new Floor("redmat");
bluemat = new Floor("bluemat");
@@ -879,10 +904,10 @@ public class Blocks{
}};
siliconArcFurnace = new GenericCrafter("silicon-arc-furnace"){{
requirements(Category.crafting, with(Items.beryllium, 60, Items.graphite, 80));
requirements(Category.crafting, with(Items.beryllium, 70, Items.graphite, 80));
craftEffect = Fx.none;
outputItem = new ItemStack(Items.silicon, 5);
craftTime = 40f;
outputItem = new ItemStack(Items.silicon, 4);
craftTime = 50f;
size = 3;
hasPower = true;
hasLiquids = false;
@@ -1138,6 +1163,7 @@ public class Blocks{
);
drawer.iconOverride = new String[]{"-bottom", ""};
regionRotated1 = 3;
continuousLiquidOutput = true;
outputLiquids = LiquidStack.with(Liquids.ozone, 4f / 60, Liquids.hydrogen, 6f / 60);
liquidOutputDirections = new int[]{1, 3};
@@ -1184,6 +1210,7 @@ public class Blocks{
drawer = new DrawMulti(new DrawRegion("-bottom"), new DrawLiquidRegion(), new DrawBlock(), new DrawHeatOutput());
drawer.iconOverride = new String[]{"-bottom", "", "-top1"};
regionRotated1 = 2;
craftTime = 60f * 3f;
liquidCapacity = 30f;
heatOutput = 5f;
@@ -2185,7 +2212,7 @@ public class Blocks{
turbineCondenser = new ThermalGenerator("turbine-condenser"){{
requirements(Category.power, with(Items.graphite, 40, Items.beryllium, 40));
attribute = Attribute.vent;
attribute = Attribute.steam;
displayEfficiencyScale = 1f / 9f;
minEfficiency = 9f - 0.0001f;
powerProduction = 3f / 9f;
@@ -2369,7 +2396,7 @@ public class Blocks{
//TODO output heat?
ventCondenser = new AttributeCrafter("vent-condenser"){{
requirements(Category.production, with(Items.graphite, 20, Items.beryllium, 60));
attribute = Attribute.vent;
attribute = Attribute.steam;
minEfficiency = 9f - 0.0001f;
baseEfficiency = 0f;
displayEfficiency = false;

View File

@@ -119,7 +119,7 @@ public class SectorPresets{
}};
aware = new SectorPreset("aware", erekir, 88){{
captureWave = 6;
captureWave = 5;
difficulty = 3;
}};

View File

@@ -328,6 +328,7 @@ public class Renderer implements ApplicationListener{
Draw.draw(Layer.plans, overlays::drawBottom);
if(animateShields && Shaders.shield != null){
//TODO would be nice if there were a way to detect if any shields or build beams actually *exist* before beginning/ending buffers, otherwise you're just blitting and swapping shaders for nothing
Draw.drawRange(Layer.shields, 1f, () -> effectBuffer.begin(Color.clear), () -> {
effectBuffer.end();
effectBuffer.blit(Shaders.shield);

View File

@@ -1036,6 +1036,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
int id = pos();
TextureRegion region = renderer.blocks.cracks[block.size - 1][Mathf.clamp((int)((1f - healthf()) * BlockRenderer.crackRegions), 0, BlockRenderer.crackRegions-1)];
Draw.colorl(0.2f, 0.1f + (1f - healthf())* 0.6f);
//TODO could be random, flipped, pseudorandom, etc
Draw.rect(region, x, y, (id%4)*90);
Draw.color();
}

View File

@@ -36,7 +36,7 @@ public class Rules{
/** Whether this is the editor gamemode. */
public boolean editor = false;
/** Whether a gameover can happen at all. Set this to false to implement custom gameover conditions. */
public boolean canGameOver = true;
public boolean canGameOver = false;
/** Whether cores change teams when they are destroyed. */
public boolean coreCapture = false;
/** Whether reactors can explode and damage other blocks. */

View File

@@ -359,7 +359,7 @@ public class BlockRenderer{
for(int i = 0; i < tileview.size; i++){
Tile tile = tileview.items[i];
Block block = tile.block();
Building entity = tile.build;
Building build = tile.build;
Draw.z(Layer.block);
@@ -374,20 +374,21 @@ public class BlockRenderer{
Draw.z(Layer.block);
}
if(entity != null){
if(build != null){
if(entity.damaged()){
entity.drawCracks();
if(build.damaged()){
Draw.z(Layer.blockCracks);
build.drawCracks();
Draw.z(Layer.block);
}
if(entity.team != player.team()){
entity.drawTeam();
if(build.team != player.team()){
build.drawTeam();
Draw.z(Layer.block);
}
if(entity.team == player.team() && renderer.drawStatus && block.consumes.any()){
entity.drawStatus();
if(build.team == player.team() && renderer.drawStatus && block.consumes.any()){
build.drawStatus();
}
}
Draw.reset();

View File

@@ -26,6 +26,12 @@ public class Layer{
//base block layer - most blocks go here
block = 30,
//layer for cracks over blocks, batched to prevent excessive texture swaps
blockCracks = 30f + 0.1f,
//some blocks need to draw stuff after cracks
blockAfterCracks = 30f + 0.2f,
//informal layer used for additive blending overlay, grouped together to reduce draw calls
blockAdditive = 31,

View File

@@ -61,7 +61,8 @@ public abstract class SaveFileReader{
"block-unloader", "payload-unloader",
"block-loader", "payload-loader",
"thermal-pump", "impulse-pump",
"alloy-smelter", "surge-smelter"
"alloy-smelter", "surge-smelter",
"steam-vent", "rhyolite-vent"
);
public static final ObjectMap<String, String> modContentNameMap = ObjectMap.of(

View File

@@ -324,10 +324,9 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
trimDark();
int minVents = rand.random(5, 8);
int minVents = rand.random(6, 8);
int ventCount = 0;
//TODO vents everywhere! rhyolite patches
//vents
outer:
for(Tile tile : tiles){
@@ -346,7 +345,7 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
ventCount ++;
for(var pos : SteamVent.offsets){
Tile other = tiles.get(pos.x + tile.x + 1, pos.y + tile.y + 1);
other.setFloor(Blocks.steamVent.asFloor());
other.setFloor(Blocks.rhyoliteVent.asFloor());
}
}
}
@@ -358,22 +357,52 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
while(ventCount < minVents && iterations++ < maxIterations){
outer:
for(Tile tile : tiles){
if(rand.chance(0.00018)){
if(rand.chance(0.00018 * (1 + iterations))){
//skip crystals, but only when directly on them
if(tile.floor() == Blocks.crystallineStone || tile.floor() == Blocks.crystalFloor){
continue;
}
int radius = 1;
for(int x = -radius; x <= radius; x++){
for(int y = -radius; y <= radius; y++){
Tile other = tiles.get(x + tile.x, y + tile.y);
//skip solids / other vents / arkycite / slag
if(other == null || other.block().solid || other.floor() == Blocks.steamVent || other.floor() == Blocks.slag || other.floor() == Blocks.arkyciteFloor){
if(other == null || other.block().solid || other.floor().attributes.get(Attribute.steam) != 0 || other.floor() == Blocks.slag || other.floor() == Blocks.arkyciteFloor){
continue outer;
}
}
}
Block
floor = Blocks.rhyolite,
secondFloor = Blocks.rhyoliteCrater,
vent = Blocks.rhyoliteVent;
int xDir = 1;
//set target material depending on what's encountered
if(tile.floor() == Blocks.beryllicStone || tile.floor() == Blocks.arkyicStone){
floor = secondFloor = Blocks.arkyicStone;
vent = Blocks.arkyicVent;
}else if(tile.floor() == Blocks.yellowStone || tile.floor() == Blocks.yellowStonePlates || tile.floor() == Blocks.regolith){
floor = Blocks.yellowStone;
secondFloor = Blocks.yellowStonePlates;
vent = Blocks.yellowStoneVent;
}else if(tile.floor() == Blocks.redStone || tile.floor() == Blocks.denseRedStone){
floor = Blocks.denseRedStone;
secondFloor = Blocks.redStone;
vent = Blocks.redStoneVent;
xDir = -1;
}else if(tile.floor() == Blocks.carbonStone){
floor = secondFloor = Blocks.carbonStone;
vent = Blocks.carbonVent;
}
ventCount ++;
for(var pos : SteamVent.offsets){
Tile other = tiles.get(pos.x + tile.x + 1, pos.y + tile.y + 1);
other.setFloor(Blocks.steamVent.asFloor());
other.setFloor(vent.asFloor());
}
//"circle" for blending
@@ -384,12 +413,14 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
int rx = cx + tile.x, ry = cy + tile.y;
//skew circle Y
float rcy = cy + cx*0.9f;
if(cx*cx + rcy*rcy <= crad2 - noise(rx, ry + rx*2f, 2, 0.7f, 8f, crad2 * 1.1f)){
if(cx*cx + rcy*rcy <= crad2 - noise(rx, ry + rx * 2f * xDir, 2, 0.7f, 8f, crad2 * 1.1f)){
Tile dest = tiles.get(rx, ry);
if(dest != null && dest.floor() != Blocks.steamVent && dest.floor() != Blocks.roughRhyolite && dest.floor() != Blocks.arkyciteFloor && dest.floor() != Blocks.slag){
dest.setFloor(rand.chance(0.08) ? Blocks.rhyoliteCrater.asFloor() : Blocks.rhyolite.asFloor());
if(dest != null && dest.floor().attributes.get(Attribute.steam) == 0 && dest.floor() != Blocks.roughRhyolite && dest.floor() != Blocks.arkyciteFloor && dest.floor() != Blocks.slag){
dest.setFloor(rand.chance(0.08) ? secondFloor.asFloor() : floor.asFloor());
if(dest.block().isStatic()){
dest.setBlock(Blocks.rhyoliteWall);
dest.setBlock(floor.asFloor().wall);
}
}
}

View File

@@ -149,13 +149,17 @@ public class ContentParser{
PartProgress base = (PartProgress)field(PartProgress.class, data.getString("type"));
JsonValue opval =
data.has("operation") ? data.get("operation") :
data.has("op") ? data.get("op") : null;
//no operations I guess (why would you do this?)
if(!data.has("operation")){
if(opval == null){
return base;
}
//this is the name of the method to call
String op = data.getString("operation");
String op = opval.asString();
//I have to hard-code this, no easy way of getting parameter names, unfortunately
return switch(op){

View File

@@ -171,6 +171,8 @@ public class UnitType extends UnlockableContent{
public boolean forceMultiTarget = false;
public boolean hidden = false;
public boolean internal = false;
/** A sample of the unit that this type creates. Do not modify! */
public Unit sample;
//for crawlers
public int segments = 0;
@@ -522,6 +524,9 @@ public class UnitType extends UnlockableContent{
dpsEstimate /= 25f;
}
}
//only do this after everything else was initialized
sample = constructor.get();
}
@CallSuper

View File

@@ -0,0 +1,107 @@
package mindustry.world.blocks.defense;
import arc.func.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
import mindustry.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.world.*;
import static mindustry.Vars.*;
public class BaseShield extends Block{
//TODO game rule? or field? should vary by base.
//public float radius = 400f;
protected static BaseShieldBuild paramBuild;
//protected static Effect paramEffect;
protected static final Cons<Bullet> bulletConsumer = bullet -> {
if(bullet.team != paramBuild.team && bullet.type.absorbable && bullet.within(paramBuild, paramBuild.radius())){
bullet.absorb();
//paramEffect.at(bullet);
//TODO effect, shield health go down?
//paramBuild.hit = 1f;
//paramBuild.buildup += bullet.damage;
}
};
protected static final Cons<Unit> unitConsumer = unit -> {
//if this is positive, repel the unit; if it exceeds the unit radius * 2, it's inside the forcefield and must be killed
float overlapDst = (unit.hitSize/2f + paramBuild.radius()) - unit.dst(paramBuild);
if(overlapDst > 0){
if(overlapDst > unit.hitSize){
//instakill units that are stuck inside the shield (TODO or maybe damage them instead?)
unit.kill();
}else{
unit.move(Tmp.v1.set(unit).sub(paramBuild).setLength(overlapDst));
}
}
};
public BaseShield(String name){
super(name);
hasPower = true;
}
public class BaseShieldBuild extends Building{
public boolean broken = false; //TODO
public float hit = 0f;
@Override
public void updateTile(){
//TODO smooth radius
float radius = radius();
if(radius > 0 && !broken){
paramBuild = this;
//paramEffect = absorbEffect;
Groups.bullet.intersect(x - radius, y - radius, radius * 2f, radius * 2f, bulletConsumer);
Units.nearbyEnemies(team,x ,y, radius, unitConsumer);
}
}
public float radius(){
//TODO bad rule?
return Vars.state.rules.enemyCoreBuildRadius;
}
@Override
public void draw(){
super.draw();
drawShield();
}
public void drawShield(){
if(!broken){
float radius = radius();
Draw.z(Layer.shields);
Draw.color(team.color, Color.white, Mathf.clamp(hit));
if(renderer.animateShields){
Fill.circle(x, y, radius);
}else{
Lines.stroke(1.5f);
Draw.alpha(0.09f + Mathf.clamp(0.08f * hit));
Fill.circle(x, y, radius);
Draw.alpha(1f);
//TODO
Lines.poly(x, y, 60, radius);
Draw.reset();
}
}
Draw.reset();
}
}
}

View File

@@ -39,12 +39,12 @@ public class ForceProjector extends Block{
protected static ForceBuild paramEntity;
protected static Effect paramEffect;
protected static final Cons<Bullet> shieldConsumer = trait -> {
if(trait.team != paramEntity.team && trait.type.absorbable && Intersector.isInsideHexagon(paramEntity.x, paramEntity.y, paramEntity.realRadius() * 2f, trait.x(), trait.y())){
trait.absorb();
paramEffect.at(trait);
protected static final Cons<Bullet> shieldConsumer = bullet -> {
if(bullet.team != paramEntity.team && bullet.type.absorbable && Intersector.isInsideHexagon(paramEntity.x, paramEntity.y, paramEntity.realRadius() * 2f, bullet.x, bullet.y)){
bullet.absorb();
paramEffect.at(bullet);
paramEntity.hit = 1f;
paramEntity.buildup += trait.damage();
paramEntity.buildup += bullet.damage;
}
};

View File

@@ -325,8 +325,10 @@ public class Drill extends Block{
float ts = 0.6f;
Draw.rect(region, x, y);
Draw.z(Layer.blockCracks);
drawDefaultCracks();
Draw.z(Layer.blockAfterCracks);
if(drawRim){
Draw.color(heatColor);
Draw.alpha(warmup * ts * (1f - s + Mathf.absin(Time.time, 3f, s)));

View File

@@ -103,7 +103,9 @@ public class SolidPump extends Pump{
@Override
public void draw(){
Draw.rect(region, x, y);
Draw.z(Layer.blockCracks);
super.drawCracks();
Draw.z(Layer.blockAfterCracks);
Drawf.liquid(liquidRegion, x, y, liquids.get(result) / liquidCapacity, result.color);
Drawf.spinSprite(rotatorRegion, x, y, pumpTime * rotateSpeed);

View File

@@ -21,7 +21,7 @@ public class Attribute{
/** Used for sand extraction. */
sand = add("sand"),
/** Used for erekir vents only. */
vent = add("vent");
steam = add("steam");
public final int id;
public final String name;