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

@@ -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};
}
}