WIP terrible-looking regen projector

This commit is contained in:
Anuken
2021-12-03 20:45:19 -05:00
parent 61bb4d2dac
commit 8e4fdc92ec
27 changed files with 342 additions and 46 deletions

View File

@@ -56,7 +56,7 @@ public class Blocks{
oreTungsten,
//wall ores
wallOreBeryl, graphiticWall,
wallOreBeryl, graphiticWall, wallOreTungsten,
//crafting
siliconSmelter, siliconCrucible, kiln, graphitePress, plastaniumCompressor, multiPress, phaseWeaver, surgeSmelter, pyratiteMixer, blastMixer, cryofluidMixer,
@@ -72,10 +72,15 @@ public class Blocks{
//defense
copperWall, copperWallLarge, titaniumWall, titaniumWallLarge, plastaniumWall, plastaniumWallLarge, thoriumWall, thoriumWallLarge, door, doorLarge,
phaseWall, phaseWallLarge, surgeWall, surgeWallLarge, mender, mendProjector, overdriveProjector, overdriveDome, forceProjector, shockMine,
buildTower,
phaseWall, phaseWallLarge, surgeWall, surgeWallLarge,
mender, mendProjector, overdriveProjector, overdriveDome, forceProjector, shockMine,
scrapWall, scrapWallLarge, scrapWallHuge, scrapWallGigantic, thruster, //ok, these names are getting ridiculous, but at least I don't have humongous walls yet
//defense - erekir
buildTower,
//TODO name
regenProjector,
//transport
conveyor, titaniumConveyor, plastaniumConveyor, armoredConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, invertedSorter, router,
overflowGate, underflowGate, massDriver,
@@ -689,6 +694,8 @@ public class Blocks{
variants = 3;
}};
wallOreTungsten = new WallOreBlock(Items.tungsten);
//endregion
//region crafting
@@ -1011,7 +1018,7 @@ public class Blocks{
}}
);
iconOverride = new String[]{"-bottom", ""};
drawer.iconOverride = new String[]{"-bottom", ""};
outputLiquids = LiquidStack.with(Liquids.ozone, 2f * craftTime / 60, Liquids.hydrogen, 3f * craftTime / 60);
liquidOutputDirections = new int[]{1, 3};
}};
@@ -1052,9 +1059,8 @@ public class Blocks{
rotateDraw = false;
//TODO vent?
iconOverride = new String[]{"-bottom", "", "-top1"};
drawer = new DrawMulti(new DrawRegion("-bottom"), new DrawLiquidRegion(), new DrawBlock(), new DrawHeatOutput());
drawer.iconOverride = new String[]{"-bottom", "", "-top1"};
craftTime = 60f * 3f;
liquidCapacity = 30f;
@@ -1065,7 +1071,7 @@ public class Blocks{
requirements(Category.crafting, with(Items.tungsten, 30, Items.graphite, 30));
drawer = new DrawMulti(new DrawRegion("-bottom"), new DrawLiquidTile(Liquids.slag, 9f), new DrawHeatOutput(true));
iconOverride = new String[]{"-bottom", ""};
drawer.iconOverride = new String[]{"-bottom", ""};
size = 2;
craftTime = 60f * 1f;
heatOutput = 2f;
@@ -1101,7 +1107,7 @@ public class Blocks{
itemCapacity = 20;
hasPower = hasItems = true;
drawer = new DrawMulti(new DrawRegion("-bottom"), new DrawCrucible(), new DrawBlock(), new DrawHeatInput());
iconOverride = new String[]{"-bottom", ""};
drawer.iconOverride = new String[]{"-bottom", ""};
ambientSound = Sounds.smelter;
ambientSoundVolume = 0.07f;
@@ -1134,7 +1140,7 @@ public class Blocks{
}
drawer = new DrawMulti(drawers.and(new DrawBlock()));
iconOverride = new String[]{"-bottom", ""};
drawer.iconOverride = new String[]{"-bottom", ""};
craftTime = 60f * 2f;
@@ -1172,7 +1178,7 @@ public class Blocks{
new DrawHeatRegion("-vents"){{
color.a = 1f;
}});
iconOverride = new String[]{"-bottom", ""};
drawer.iconOverride = new String[]{"-bottom", ""};
consumes.item(Items.silicon, 3);
//TODO must consume from 2 pumps, 1, or 1.5?
@@ -1199,7 +1205,7 @@ public class Blocks{
particleSizeInterp = Interp.one;
}}, new DrawBlock(), new DrawHeatInput(), new DrawHeatRegion("-heat-top"));
iconOverride = new String[]{"-bottom", ""};
drawer.iconOverride = new String[]{"-bottom", ""};
size = 3;
@@ -1240,7 +1246,7 @@ public class Blocks{
}}, new DrawBlock(), new DrawHeatInput(), new DrawHeatRegion("-vents"){{
color = new Color(1f, 0.4f, 0.3f, 1f);
}});
iconOverride = new String[]{"-bottom", "-weave", ""};
drawer.iconOverride = new String[]{"-bottom", "-weave", ""};
consumes.items(with(Items.thorium, 2, Items.sand, 6));
consumes.liquid(Liquids.ozone, 2f / 60f);
@@ -1479,10 +1485,29 @@ public class Blocks{
consumes.power(3f);
range = 120f;
size = 3;
health = 80;
buildSpeed = 1.5f;
}};
//TODO green looks bad switch to orange
regenProjector = new RegenProjector("regen-projector"){{
requirements(Category.effect, with(Items.silicon, 60, Items.tungsten, 60, Items.oxide, 40));
size = 3;
consumes.power(1f);
rangeWidth = 4;
rangeLength = 20;
consumes.liquid(Liquids.hydrogen, 1f / 60f);
healPercent = 4f / 60f;
drawer = new DrawMulti(new DrawRegion("-bottom"), new DrawLiquidTile(Liquids.hydrogen, 9f / 4f), new DrawSideRegion(true), new DrawGlowRegion(){{
//color = Color.valueOf("1eff21");
}}, new DrawGlowRegion(true){{
suffix = "-side-glow";
alpha = 1f;
}});
}};
//endregion
//region distribution
@@ -1892,7 +1917,7 @@ public class Blocks{
consumes.liquid(Liquids.water, 0.1f);
hasLiquids = true;
size = 2;
iconOverride = new String[]{"", "-turbine0", "-turbine1"};
drawer.iconOverride = new String[]{"", "-turbine0", "-turbine1"};
ambientSound = Sounds.smelter;
ambientSoundVolume = 0.06f;
@@ -1994,7 +2019,7 @@ public class Blocks{
glowScale = 5f;
color = Color.valueOf("c967b099");
}});
iconOverride = new String[]{"-bottom", ""};
drawer.iconOverride = new String[]{"-bottom", ""};
generateEffect = Fx.none;
liquidCapacity = 20f * 5;
@@ -2028,7 +2053,7 @@ public class Blocks{
liquidOutput = new LiquidStack(Liquids.water, 5f / 60f);
iconOverride = new String[]{"-bottom", ""};
drawer.iconOverride = new String[]{"-bottom", ""};
generateEffect = Fx.none;
ambientSound = Sounds.smelter;
@@ -2785,13 +2810,13 @@ public class Blocks{
trailLength = 10;
hitEffect = despawnEffect = Fx.hitBulletColor;
}},
Items.tungsten, new BasicBulletType(6.6f, 46){{
Items.tungsten, new BasicBulletType(6.6f, 47){{
width = 9f;
height = 14f;
shootEffect = Fx.tungstenSpark;
smokeEffect = Fx.shootBigSmoke;
ammoMultiplier = 1;
reloadMultiplier = 1.4f;
reloadMultiplier = 0.7f;
pierce = true;
pierceBuilding = true;
hitColor = backColor = trailColor = Pal.tungstenShot;

View File

@@ -1353,6 +1353,12 @@ public class Fx{
});
}),
regenParticle = new Effect(100f, e -> {
color(Pal.accent);
Fill.square(e.x, e.y, e.fslope() * 1.5f + 0.14f, 45f);
}),
surgeCruciSmoke = new Effect(160f, e -> {
color(Pal.slagOrange);
alpha(0.6f);

View File

@@ -189,6 +189,10 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
}else if(block != Blocks.carbonWall && noise(x + 782, y, 4, 0.8f, 37f, 1f) > 0.68f){
ore = Blocks.wallOreBeryl;
}
//TODO generate tungsten, or not?
//else if(block == Blocks.yellowStoneWall && noise(x, y + 942, 4, 0.7f, 38f, 1f) > 0.71f){
// ore = Blocks.wallOreTungsten;
//}
}
}else if(!nearWall(x, y)){

View File

@@ -66,10 +66,7 @@ public class MendProjector extends Block{
}
public class MendBuild extends Building implements Ranged{
float heat;
float charge = Mathf.random(reload);
float phaseHeat;
float smoothEfficiency;
public float heat, charge = Mathf.random(reload), phaseHeat, smoothEfficiency;
@Override
public float range(){

View File

@@ -0,0 +1,215 @@
package mindustry.world.blocks.defense;
import arc.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.world.*;
import mindustry.world.draw.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
public class RegenProjector extends Block{
private static final IntSet taken = new IntSet();
//map ID to mend amount
private static final IntFloatMap mendMap = new IntFloatMap();
private static long lastUpdateFrame = -1;
//cached points per-block for drawing convenience
protected @Nullable Vec2[] drawPoints;
public int rangeLength = 14, rangeWidth = 5;
//per frame
public float healPercent = 12f / 60f;
public DrawBlock drawer = new DrawMulti(new DrawRegion("-bottom"), new DrawSideRegion(true));
public float effectChance = 0.011f;
public Effect effect = Fx.regenParticle;
public float beamSpacing = 60f * 7f, beamWidening = 5f, beamLenScl = 1.2f, beamStroke = 2f;
public Interp beamInterp = Interp.pow2Out;
public int beams = 6;
public RegenProjector(String name){
super(name);
solid = true;
update = true;
rotate = true;
group = BlockGroup.projectors;
hasPower = true;
hasItems = true;
emitLight = true;
envEnabled |= Env.space;
rotateDraw = false;
}
@Override
public void drawPlace(int x, int y, int rotation, boolean valid){
super.drawPlace(x, y, rotation, valid);
drawBounds(x * tilesize + offset, y * tilesize + offset, rotation);
}
public void drawBounds(float x, float y, int rotation){
if(drawPoints == null){
drawPoints = new Vec2[]{
new Vec2(1f, -rangeWidth),
new Vec2(1f + rangeLength, -rangeWidth),
new Vec2(1f + rangeLength, rangeWidth),
new Vec2(1f + 0f, rangeWidth),
};
for(var v : drawPoints){
v.scl(tilesize);
}
}
for(int i = 0; i < 4; i++){
Tmp.v1.set(drawPoints[i]).rotate(rotation * 90).add(x, y);
Tmp.v2.set(drawPoints[(i + 1) % 4]).rotate(rotation * 90).add(x, y);
Drawf.dashLine(Pal.accent, Tmp.v1.x, Tmp.v1.y, Tmp.v2.x, Tmp.v2.y);
}
}
@Override
public void drawRequestRegion(BuildPlan plan, Eachable<BuildPlan> list){
drawer.drawPlan(this, plan, list);
}
@Override
public boolean outputsItems(){
return false;
}
@Override
public TextureRegion[] icons(){
return drawer.finalIcons(this);
}
@Override
public void load(){
super.load();
drawer.load(this);
}
public class RegenProjectorBuild extends Building{
public Seq<Building> targets = new Seq<>();
public int lastChange = -2;
public float warmup, totalTime;
public void updateTargets(){
targets.clear();
taken.clear();
float rot = rotation * 90;
for(int cy = -rangeWidth; cy <= rangeWidth; cy++){
for(int cx = 1; cx <= rangeLength + 1; cx++){
//TODO handle offset
float wx = x/tilesize + Angles.trnsx(rot, cx, cy), wy = y/tilesize + Angles.trnsy(rot, cx, cy);
Building build = world.build((int)wx, (int)wy);
if(build != null && build.team == team && taken.add(build.id)){
targets.add(build);
}
}
}
}
@Override
public void updateTile(){
if(lastChange != world.tileChanges){
lastChange = world.tileChanges;
updateTargets();
}
warmup = Mathf.approachDelta(warmup, consValid() ? 1f : 0f, 1f / 70f);
totalTime += warmup * Time.delta;
if(consValid()){
//use Math.max to prevent stacking
for(Building build : targets){
if(!build.damaged()) continue;
int pos = build.pos();
//TODO periodic effect
float value = mendMap.get(pos);
mendMap.put(pos, Math.min(Math.max(value, healPercent * edelta() * build.block.health / 100f), build.block.health - build.health));
if(Mathf.chanceDelta(effectChance)){
effect.at(build.x + Mathf.range(build.block.size * tilesize/2f - 1f), build.y + Mathf.range(build.block.size * tilesize/2f - 1f));
}
}
}
if(lastUpdateFrame != Core.graphics.getFrameId()){
lastUpdateFrame = Core.graphics.getFrameId();
for(var entry : mendMap.entries()){
var build = world.build(entry.key);
if(build != null){
build.heal(entry.value);
}
}
mendMap.clear();
}
}
@Override
public void drawSelect(){
super.drawSelect();
drawBounds(x, y, rotation);
}
@Override
public float warmup(){
return warmup;
}
@Override
public float totalProgress(){
return totalTime;
}
@Override
public void draw(){
drawer.drawBase(this);
for(int i = 0; i < beams; i++){
float life = beamInterp.apply((totalTime / beamSpacing + i / (float)beams) % 1f);
float len = life * rangeLength*beamLenScl * tilesize + size * tilesize/2f;
float width = Math.min(life * rangeWidth * 2f * tilesize * beamWidening, rangeWidth * 2f * tilesize);
float stroke = (0.5f + beamStroke * life) * warmup;
Draw.z(Layer.effect);
Lines.stroke(stroke, Pal.accent);
Draw.alpha(1f - Mathf.curve(life, 0.5f));
Lines.lineAngleCenter(
x + Angles.trnsx(rotdeg(), len),
y + Angles.trnsy(rotdeg(), len),
rotdeg() + 90f,
width
);
Draw.reset();
}
}
@Override
public void drawLight(){
super.drawLight();
drawer.drawLights(this);
}
}
}

View File

@@ -148,7 +148,7 @@ public class Turret extends ReloadTurret{
@Override
public TextureRegion[] icons(){
return draw.icons(this);
return draw.finalIcons(this);
}
@Override

View File

@@ -18,7 +18,6 @@ public class PowerGenerator extends PowerDistributor{
public float powerProduction;
public Stat generationType = Stat.basePowerGeneration;
public DrawBlock drawer = new DrawBlock();
public @Nullable String[] iconOverride;
public PowerGenerator(String name){
super(name);
@@ -29,14 +28,7 @@ public class PowerGenerator extends PowerDistributor{
@Override
public TextureRegion[] icons(){
if(iconOverride != null){
var out = new TextureRegion[iconOverride.length];
for(int i = 0; i < out.length; i++){
out[i] = Core.atlas.find(name + iconOverride[i]);
}
return out;
}
return drawer.icons(this);
return drawer.finalIcons(this);
}
@Override

View File

@@ -1,6 +1,5 @@
package mindustry.world.blocks.production;
import arc.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.struct.*;
@@ -40,8 +39,6 @@ public class GenericCrafter extends Block{
public boolean legacyReadWarmup = false;
public DrawBlock drawer = new DrawBlock();
/** If set, the icon is overridden to be these strings, in order. Each string is a suffix. */
public @Nullable String[] iconOverride = null;
public GenericCrafter(String name){
super(name);
@@ -129,14 +126,7 @@ public class GenericCrafter extends Block{
@Override
public TextureRegion[] icons(){
if(iconOverride != null){
var out = new TextureRegion[iconOverride.length];
for(int i = 0; i < out.length; i++){
out[i] = Core.atlas.find(name + iconOverride[i]);
}
return out;
}
return drawer.icons(this);
return drawer.finalIcons(this);
}
@Override

View File

@@ -73,7 +73,7 @@ public class Pump extends LiquidBlock{
@Override
public TextureRegion[] icons(){
return draw.icons(this);
return draw.finalIcons(this);
}
@Override

View File

@@ -1,5 +1,6 @@
package mindustry.world.draw;
import arc.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.struct.*;
@@ -15,6 +16,9 @@ import mindustry.world.blocks.production.GenericCrafter.*;
public class DrawBlock{
protected static final Rand rand = new Rand();
/** If set, the icon is overridden to be these strings, in order. Each string is a suffix. */
public @Nullable String[] iconOverride = null;
/** @deprecated no longer called! not specific to generic crafters! */
@Deprecated
public void draw(GenericCrafterBuild build){}
@@ -52,6 +56,17 @@ public class DrawBlock{
return new TextureRegion[]{block.region};
}
public final TextureRegion[] finalIcons(Block block){
if(iconOverride != null){
var out = new TextureRegion[iconOverride.length];
for(int i = 0; i < out.length; i++){
out[i] = Core.atlas.find(block.name + iconOverride[i]);
}
return out;
}
return icons(block);
}
public GenericCrafter expectCrafter(Block block){
if(!(block instanceof GenericCrafter crafter)) throw new ClassCastException("This drawer requires the block to be a GenericCrafter. Use a different drawer.");
return crafter;

View File

@@ -17,6 +17,7 @@ public class DrawGlowRegion extends DrawBlock{
public float alpha = 0.9f, glowScale = 10f, glowIntensity = 0.5f;
public float rotateSpeed = 0f;
public float layer = Layer.blockAdditive;
public boolean rotate = false;
public Color color = Color.red.cpy();
public TextureRegion region;
@@ -27,6 +28,10 @@ public class DrawGlowRegion extends DrawBlock{
this.layer = layer;
}
public DrawGlowRegion(boolean rotate){
this.rotate = rotate;
}
@Override
public void drawBase(Building build){
if(build.warmup() <= 0.001f) return;
@@ -36,7 +41,7 @@ public class DrawGlowRegion extends DrawBlock{
Draw.blend(blending);
Draw.color(color);
Draw.alpha((Mathf.absin(build.totalProgress(), glowScale, alpha) * glowIntensity + 1f - glowIntensity) * build.warmup() * alpha);
Draw.rect(region, build.x, build.y, build.totalProgress() * rotateSpeed);
Draw.rect(region, build.x, build.y, build.totalProgress() * rotateSpeed + (rotate ? build.rotdeg() : 0f));
Draw.reset();
Draw.blend();
Draw.z(z);

View File

@@ -0,0 +1,45 @@
package mindustry.world.draw;
import arc.*;
import arc.graphics.g2d.*;
import arc.util.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.world.*;
public class DrawSideRegion extends DrawBlock{
public boolean drawRegion = false;
public TextureRegion top1, top2;
public DrawSideRegion(){
}
public DrawSideRegion(boolean drawRegion){
this.drawRegion = drawRegion;
}
@Override
public void drawBase(Building build){
if(drawRegion) Draw.rect(build.block.region, build.x, build.y);
Draw.rect(build.rotation > 1 ? top2 : top1, build.x, build.y, build.rotdeg());
}
@Override
public void drawPlan(Block block, BuildPlan plan, Eachable<BuildPlan> list){
if(drawRegion) Draw.rect(block.region, plan.drawx(), plan.drawy());
Draw.rect(plan.rotation > 1 ? top2 : top1, plan.drawx(), plan.drawy(), plan.rotation * 90);
}
@Override
public void load(Block block){
top1 = Core.atlas.find(block.name + "-top1");
top2 = Core.atlas.find(block.name + "-top2");
}
@Override
public TextureRegion[] icons(Block block){
return new TextureRegion[]{block.region, top1};
}
}