Merge branch '6.0' into crater
# Conflicts: # core/assets/icons/icons.properties # core/assets/sprites/block_colors.png # core/assets/sprites/sprites.atlas # core/assets/sprites/sprites.png # core/assets/sprites/sprites3.png # core/assets/sprites/sprites5.png # core/src/mindustry/content/Blocks.java # core/src/mindustry/ui/fragments/PlayerListFragment.java # core/src/mindustry/world/BlockStorage.java
This commit is contained in:
@@ -2,9 +2,10 @@ package mindustry.world.blocks;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import java.util.*;
|
||||
@@ -82,9 +83,8 @@ public interface Autotiler{
|
||||
}
|
||||
|
||||
default boolean blends(Tile tile, int rotation, int direction){
|
||||
Tile other = tile.getNearby(Mathf.mod(rotation - direction, 4));
|
||||
if(other != null) other = other.link();
|
||||
return other != null && other.getTeam() == tile.getTeam() && blends(tile, rotation, other.x, other.y, other.rotation(), other.block());
|
||||
Tilec other = tile.getNearbyEntity(Mathf.mod(rotation - direction, 4));
|
||||
return other != null && other.team() == tile.team() && blends(tile, rotation, other.tileX(), other.tileY(), other.rotation(), other.block());
|
||||
}
|
||||
|
||||
default boolean blendsArmored(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
package mindustry.world.blocks;
|
||||
|
||||
import mindustry.type.Item;
|
||||
import mindustry.type.Liquid;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
|
||||
/**
|
||||
* Used for multiblocks. Each block that is not the center of the multiblock is a part.
|
||||
* Think of these as delegates to the actual block; all events are passed to the target block.
|
||||
* They are made to share all properties from the linked tile/block.
|
||||
*/
|
||||
public class BlockPart extends Block{
|
||||
public final static int maxSize = 9;
|
||||
private final static BlockPart[][] parts = new BlockPart[maxSize][maxSize];
|
||||
|
||||
private final int dx, dy;
|
||||
|
||||
public BlockPart(int dx, int dy){
|
||||
super("part_" + dx + "_" + dy);
|
||||
this.dx = dx;
|
||||
this.dy = dy;
|
||||
solid = false;
|
||||
hasPower = hasItems = hasLiquids = true;
|
||||
parts[dx + maxSize/2][dy + maxSize/2] = this;
|
||||
}
|
||||
|
||||
public static BlockPart get(int dx, int dy){
|
||||
if(dx == -maxSize/2 && dy == -maxSize/2) throw new IllegalArgumentException("Why are you getting a [0,0] blockpart? Stop it.");
|
||||
return parts[dx + maxSize/2][dy + maxSize/2];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return tile.link().block().acceptItem(item, tile.link(), source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
tile.link().block().handleItem(item, tile.link(), source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
Block block = tile.link().block();
|
||||
block.handleLiquid(tile.link(), source, liquid, amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
Block block = tile.link().block();
|
||||
return block.hasLiquids && block.acceptLiquid(tile.link(), source, liquid, amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tile linked(Tile tile){
|
||||
Tile out = tile.getNearby(-dx, -dy);
|
||||
return out == null ? tile : out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTeam(Tile tile){}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){}
|
||||
|
||||
@Override
|
||||
public boolean synthetic(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "BlockPart[" + dx + ", " + dy + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,18 +1,17 @@
|
||||
package mindustry.world.blocks;
|
||||
|
||||
import arc.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import arc.Graphics.*;
|
||||
import arc.Graphics.Cursor.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.effect.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
@@ -22,12 +21,10 @@ import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.modules.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class BuildBlock extends Block{
|
||||
public static final int maxSize = 9;
|
||||
public static final int maxSize = 16;
|
||||
private static final BuildBlock[] buildBlocks = new BuildBlock[maxSize];
|
||||
|
||||
private static long lastTime = 0;
|
||||
@@ -42,8 +39,6 @@ public class BuildBlock extends Block{
|
||||
layer = Layer.placement;
|
||||
consumesTap = true;
|
||||
solidifes = true;
|
||||
entityType = BuildEntity::new;
|
||||
|
||||
buildBlocks[size - 1] = this;
|
||||
}
|
||||
|
||||
@@ -55,9 +50,9 @@ public class BuildBlock extends Block{
|
||||
|
||||
@Remote(called = Loc.server)
|
||||
public static void onDeconstructFinish(Tile tile, Block block, int builderID){
|
||||
Team team = tile.getTeam();
|
||||
Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size);
|
||||
Events.fire(new BlockBuildEndEvent(tile, playerGroup.getByID(builderID), team, true));
|
||||
Team team = tile.team();
|
||||
Fx.breakBlock.at(tile.drawx(), tile.drawy(), block.size);
|
||||
Events.fire(new BlockBuildEndEvent(tile, Groups.unit.getByID(builderID), team, true));
|
||||
tile.remove();
|
||||
if(shouldPlay()) Sounds.breaks.at(tile, calcPitch(false));
|
||||
}
|
||||
@@ -65,18 +60,16 @@ public class BuildBlock extends Block{
|
||||
@Remote(called = Loc.server)
|
||||
public static void onConstructFinish(Tile tile, Block block, int builderID, byte rotation, Team team, boolean skipConfig){
|
||||
if(tile == null) return;
|
||||
float healthf = tile.entity == null ? 1f : tile.entity.healthf();
|
||||
tile.set(block, team, rotation);
|
||||
if(tile.entity != null){
|
||||
tile.entity.health = block.health * healthf;
|
||||
}
|
||||
float healthf = tile.entity.healthf();
|
||||
tile.setBlock(block, team, (int)rotation);
|
||||
tile.entity.health(block.health * healthf);
|
||||
//last builder was this local client player, call placed()
|
||||
if(!headless && builderID == player.id){
|
||||
if(!headless && builderID == player.unit().id()){
|
||||
if(!skipConfig){
|
||||
tile.block().playerPlaced(tile);
|
||||
tile.entity.playerPlaced();
|
||||
}
|
||||
}
|
||||
Effects.effect(Fx.placeBlock, tile.drawx(), tile.drawy(), block.size);
|
||||
Fx.placeBlock.at(tile.drawx(), tile.drawy(), block.size);
|
||||
}
|
||||
|
||||
static boolean shouldPlay(){
|
||||
@@ -105,9 +98,9 @@ public class BuildBlock extends Block{
|
||||
|
||||
public static void constructed(Tile tile, Block block, int builderID, byte rotation, Team team, boolean skipConfig){
|
||||
Call.onConstructFinish(tile, block, builderID, rotation, team, skipConfig);
|
||||
tile.block().placed(tile);
|
||||
tile.entity.placed();
|
||||
|
||||
Events.fire(new BlockBuildEndEvent(tile, playerGroup.getByID(builderID), team, false));
|
||||
Events.fire(new BlockBuildEndEvent(tile, Groups.unit.getByID(builderID), team, false));
|
||||
if(shouldPlay()) Sounds.place.at(tile, calcPitch(true));
|
||||
}
|
||||
|
||||
@@ -116,95 +109,12 @@ public class BuildBlock extends Block{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(Tile tile){
|
||||
BuildEntity entity = tile.ent();
|
||||
return Core.bundle.format("block.constructing", entity.cblock == null ? entity.previous.localizedName : entity.cblock.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion getDisplayIcon(Tile tile){
|
||||
BuildEntity entity = tile.ent();
|
||||
return (entity.cblock == null ? entity.previous : entity.cblock).icon(mindustry.ui.Cicon.full);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolidFor(Tile tile){
|
||||
BuildEntity entity = tile.ent();
|
||||
return entity == null || (entity.cblock != null && entity.cblock.solid) || entity.previous == null || entity.previous.solid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor getCursor(Tile tile){
|
||||
return SystemCursor.hand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tapped(Tile tile, Player player){
|
||||
BuildEntity entity = tile.ent();
|
||||
|
||||
//if the target is constructible, begin constructing
|
||||
if(entity.cblock != null){
|
||||
if(player.buildWasAutoPaused && !player.isBuilding){
|
||||
player.isBuilding = true;
|
||||
}
|
||||
//player.clearBuilding();
|
||||
player.addBuildRequest(new BuildRequest(tile.x, tile.y, tile.rotation(), entity.cblock), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyed(Tile tile){
|
||||
Effects.effect(Fx.blockExplosionSmoke, tile);
|
||||
|
||||
if(!tile.floor().solid && !tile.floor().isLiquid){
|
||||
RubbleDecal.create(tile.drawx(), tile.drawy(), size);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
BuildEntity entity = tile.ent();
|
||||
|
||||
//When breaking, don't draw the previous block... since it's the thing you were breaking
|
||||
if(entity.cblock != null && entity.previous == entity.cblock){
|
||||
return;
|
||||
}
|
||||
|
||||
if(entity.previous == null || entity.cblock == null) return;
|
||||
|
||||
if(Core.atlas.isFound(entity.previous.icon(Cicon.full))){
|
||||
Draw.rect(entity.previous.icon(Cicon.full), tile.drawx(), tile.drawy(), entity.previous.rotate ? tile.rotation() * 90 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
|
||||
BuildEntity entity = tile.ent();
|
||||
|
||||
Shaders.blockbuild.color = Pal.accent;
|
||||
|
||||
Block target = entity.cblock == null ? entity.previous : entity.cblock;
|
||||
|
||||
if(target == null) return;
|
||||
|
||||
for(TextureRegion region : target.getGeneratedIcons()){
|
||||
Shaders.blockbuild.region = region;
|
||||
Shaders.blockbuild.progress = entity.progress;
|
||||
|
||||
Draw.rect(region, tile.drawx(), tile.drawy(), target.rotate ? tile.rotation() * 90 : 0);
|
||||
Draw.flush();
|
||||
}
|
||||
}
|
||||
|
||||
public class BuildEntity extends TileEntity{
|
||||
/**
|
||||
* The recipe of the block that is being constructed.
|
||||
* If there is no recipe for this block, as is the case with rocks, 'previous' is used.
|
||||
*/
|
||||
public @Nullable
|
||||
Block cblock;
|
||||
public @Nullable Block cblock;
|
||||
|
||||
public float progress = 0;
|
||||
public float buildCost;
|
||||
@@ -218,7 +128,78 @@ public class BuildBlock extends Block{
|
||||
private float[] accumulator;
|
||||
private float[] totalAccumulator;
|
||||
|
||||
public boolean construct(Unit builder, @Nullable TileEntity core, float amount, boolean configured){
|
||||
@Override
|
||||
public String getDisplayName(){
|
||||
return Core.bundle.format("block.constructing", cblock == null ? previous.localizedName : cblock.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion getDisplayIcon(){
|
||||
return (cblock == null ? previous : cblock).icon(Cicon.full);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkSolid(){
|
||||
return (cblock != null && cblock.solid) || previous == null || previous.solid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor getCursor(){
|
||||
return SystemCursor.hand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tapped(Playerc player){
|
||||
//if the target is constructible, begin constructing
|
||||
if(!headless && cblock != null){
|
||||
if(control.input.buildWasAutoPaused && !control.input.isBuilding && player.isBuilder()){
|
||||
control.input.isBuilding = true;
|
||||
}
|
||||
player.builder().addBuild(new BuildRequest(tile.x, tile.y, tile.rotation(), cblock), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyed(){
|
||||
Fx.blockExplosionSmoke.at(tile);
|
||||
|
||||
if(!tile.floor().solid && !tile.floor().isLiquid){
|
||||
Effects.rubble(x, y, size);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
//When breaking, don't draw the previous block... since it's the thing you were breaking
|
||||
if(cblock != null && previous == cblock){
|
||||
return;
|
||||
}
|
||||
|
||||
if(previous == null || cblock == null) return;
|
||||
|
||||
if(Core.atlas.isFound(previous.icon(Cicon.full))){
|
||||
Draw.rect(previous.icon(Cicon.full), x, y, previous.rotate ? tile.rotation() * 90 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(){
|
||||
Shaders.blockbuild.color = Pal.accent;
|
||||
|
||||
Block target = cblock == null ? previous : cblock;
|
||||
|
||||
if(target == null) return;
|
||||
|
||||
for(TextureRegion region : target.getGeneratedIcons()){
|
||||
Shaders.blockbuild.region = region;
|
||||
Shaders.blockbuild.progress = progress;
|
||||
|
||||
Draw.rect(region, x, y, target.rotate ? tile.rotation() * 90 : 0);
|
||||
Draw.flush();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean construct(Unitc builder, @Nullable Tilec core, float amount, boolean configured){
|
||||
if(cblock == null){
|
||||
kill();
|
||||
return false;
|
||||
@@ -228,7 +209,7 @@ public class BuildBlock extends Block{
|
||||
setConstruct(previous, cblock);
|
||||
}
|
||||
|
||||
float maxProgress = core == null ? amount : checkRequired(core.items, amount, false);
|
||||
float maxProgress = core == null ? amount : checkRequired(core.items(), amount, false);
|
||||
|
||||
for(int i = 0; i < cblock.requirements.length; i++){
|
||||
int reqamount = Math.round(state.rules.buildCostMultiplier * cblock.requirements[i].amount);
|
||||
@@ -236,22 +217,19 @@ public class BuildBlock extends Block{
|
||||
totalAccumulator[i] = Math.min(totalAccumulator[i] + reqamount * maxProgress, reqamount);
|
||||
}
|
||||
|
||||
maxProgress = core == null ? maxProgress : checkRequired(core.items, maxProgress, true);
|
||||
maxProgress = core == null ? maxProgress : checkRequired(core.items(), maxProgress, true);
|
||||
|
||||
progress = Mathf.clamp(progress + maxProgress);
|
||||
|
||||
if(builder instanceof Player){
|
||||
builderID = builder.getID();
|
||||
}
|
||||
builderID = builder.id();
|
||||
|
||||
if(progress >= 1f || state.rules.infiniteResources){
|
||||
constructed(tile, cblock, builderID, tile.rotation(), builder.getTeam(), configured);
|
||||
constructed(tile, cblock, builderID, tile.rotation(), builder.team(), configured);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void deconstruct(Unit builder, @Nullable TileEntity core, float amount){
|
||||
public void deconstruct(Unitc builder, @Nullable Tilec core, float amount){
|
||||
float deconstructMultiplier = state.rules.deconstructRefundMultiplier;
|
||||
|
||||
if(cblock != null){
|
||||
@@ -272,8 +250,8 @@ public class BuildBlock extends Block{
|
||||
|
||||
if(clampedAmount > 0 && accumulated > 0){ //if it's positive, add it to the core
|
||||
if(core != null){
|
||||
int accepting = core.tile.block().acceptStack(requirements[i].item, accumulated, core.tile, builder);
|
||||
core.tile.block().handleStack(requirements[i].item, accepting, core.tile, builder);
|
||||
int accepting = core.acceptStack(requirements[i].item, accumulated, builder);
|
||||
core.handleStack(requirements[i].item, accepting, builder);
|
||||
accumulator[i] -= accepting;
|
||||
}else{
|
||||
accumulator[i] -= accumulated;
|
||||
@@ -284,9 +262,7 @@ public class BuildBlock extends Block{
|
||||
|
||||
progress = Mathf.clamp(progress - amount);
|
||||
|
||||
if(builder instanceof Player){
|
||||
builderID = builder.getID();
|
||||
}
|
||||
builderID = builder.id();
|
||||
|
||||
if(progress <= 0 || state.rules.infiniteResources){
|
||||
Call.onDeconstructFinish(tile, this.cblock == null ? previous : this.cblock, builderID);
|
||||
@@ -351,37 +327,37 @@ public class BuildBlock extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeFloat(progress);
|
||||
stream.writeShort(previous == null ? -1 : previous.id);
|
||||
stream.writeShort(cblock == null ? -1 : cblock.id);
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.f(progress);
|
||||
write.s(previous == null ? -1 : previous.id);
|
||||
write.s(cblock == null ? -1 : cblock.id);
|
||||
|
||||
if(accumulator == null){
|
||||
stream.writeByte(-1);
|
||||
write.b(-1);
|
||||
}else{
|
||||
stream.writeByte(accumulator.length);
|
||||
write.b(accumulator.length);
|
||||
for(int i = 0; i < accumulator.length; i++){
|
||||
stream.writeFloat(accumulator[i]);
|
||||
stream.writeFloat(totalAccumulator[i]);
|
||||
write.f(accumulator[i]);
|
||||
write.f(totalAccumulator[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
progress = stream.readFloat();
|
||||
short pid = stream.readShort();
|
||||
short rid = stream.readShort();
|
||||
byte acsize = stream.readByte();
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
progress = read.f();
|
||||
short pid = read.s();
|
||||
short rid = read.s();
|
||||
byte acsize = read.b();
|
||||
|
||||
if(acsize != -1){
|
||||
accumulator = new float[acsize];
|
||||
totalAccumulator = new float[acsize];
|
||||
for(int i = 0; i < acsize; i++){
|
||||
accumulator[i] = stream.readFloat();
|
||||
totalAccumulator[i] = stream.readFloat();
|
||||
accumulator[i] = read.f();
|
||||
totalAccumulator[i] = read.f();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public class ItemSelection{
|
||||
int i = 0;
|
||||
|
||||
for(T item : items){
|
||||
if(!data.isUnlocked(item) && world.isZone()) continue;
|
||||
if(!data.isUnlocked(item) && state.isCampaign()) continue;
|
||||
|
||||
ImageButton button = cont.addImageButton(Tex.whiteui, Styles.clearToggleTransi, 24, () -> control.input.frag.config.hideConfig()).group(group).get();
|
||||
button.changed(() -> consumer.get(button.isChecked() ? item : null));
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
package mindustry.world.blocks;
|
||||
|
||||
import arc.Core;
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.graphics.g2d.TextureRegion;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.BlockGroup;
|
||||
import mindustry.world.modules.LiquidModule;
|
||||
|
||||
public class LiquidBlock extends Block{
|
||||
protected TextureRegion liquidRegion, bottomRegion, topRegion;
|
||||
|
||||
public LiquidBlock(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
solid = true;
|
||||
hasLiquids = true;
|
||||
group = BlockGroup.liquids;
|
||||
outputsLiquid = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
super.load();
|
||||
|
||||
liquidRegion = Core.atlas.find(name + "-liquid");
|
||||
topRegion = Core.atlas.find(name + "-top");
|
||||
bottomRegion = Core.atlas.find(name + "-bottom");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find(name + "-bottom"), Core.atlas.find(name + "-top")};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
LiquidModule mod = tile.entity.liquids;
|
||||
|
||||
int rotation = rotate ? tile.rotation() * 90 : 0;
|
||||
|
||||
Draw.rect(bottomRegion, tile.drawx(), tile.drawy(), rotation);
|
||||
|
||||
if(mod.total() > 0.001f){
|
||||
Draw.color(mod.current().color);
|
||||
Draw.alpha(mod.total() / liquidCapacity);
|
||||
Draw.rect(liquidRegion, tile.drawx(), tile.drawy(), rotation);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy(), rotation);
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package mindustry.world.blocks;
|
||||
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.net;
|
||||
|
||||
public class RespawnBlock{
|
||||
|
||||
public static void drawRespawn(Tile tile, float heat, float progress, float time, Player player, Mech to){
|
||||
progress = Mathf.clamp(progress);
|
||||
|
||||
Draw.color(Pal.darkMetal);
|
||||
Lines.stroke(2f * heat);
|
||||
Fill.poly(tile.drawx(), tile.drawy(), 4, 10f * heat);
|
||||
|
||||
Draw.reset();
|
||||
if(player != null){
|
||||
TextureRegion region = to.icon(Cicon.full);
|
||||
|
||||
Draw.color(0f, 0f, 0f, 0.4f * progress);
|
||||
Draw.rect("circle-shadow", tile.drawx(), tile.drawy(), region.getWidth() / 3f, region.getWidth() / 3f);
|
||||
Draw.color();
|
||||
|
||||
Shaders.build.region = region;
|
||||
Shaders.build.progress = progress;
|
||||
Shaders.build.color.set(Pal.accent);
|
||||
Shaders.build.time = -time / 10f;
|
||||
|
||||
Draw.shader(Shaders.build, true);
|
||||
Draw.rect(region, tile.drawx(), tile.drawy());
|
||||
Draw.shader();
|
||||
|
||||
Draw.color(Pal.accentBack);
|
||||
|
||||
float pos = Mathf.sin(time, 6f, 8f);
|
||||
|
||||
Lines.lineAngleCenter(tile.drawx() + pos, tile.drawy(), 90, 16f - Math.abs(pos) * 2f);
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
Lines.stroke(2f * heat);
|
||||
|
||||
Draw.color(Pal.accentBack);
|
||||
Lines.poly(tile.drawx(), tile.drawy(), 4, 8f * heat);
|
||||
|
||||
float oy = -7f, len = 6f * heat;
|
||||
Lines.stroke(5f);
|
||||
Draw.color(Pal.darkMetal);
|
||||
Lines.line(tile.drawx() - len, tile.drawy() + oy, tile.drawx() + len, tile.drawy() + oy, CapStyle.none);
|
||||
for(int i : Mathf.signs){
|
||||
Fill.tri(tile.drawx() + len * i, tile.drawy() + oy - Lines.getStroke()/2f, tile.drawx() + len * i, tile.drawy() + oy + Lines.getStroke()/2f, tile.drawx() + (len + Lines.getStroke() * heat) * i, tile.drawy() + oy);
|
||||
}
|
||||
|
||||
Lines.stroke(3f);
|
||||
Draw.color(Pal.accent);
|
||||
Lines.line(tile.drawx() - len, tile.drawy() + oy, tile.drawx() - len + len*2 * progress, tile.drawy() + oy, CapStyle.none);
|
||||
for(int i : Mathf.signs){
|
||||
Fill.tri(tile.drawx() + len * i, tile.drawy() + oy - Lines.getStroke()/2f, tile.drawx() + len * i, tile.drawy() + oy + Lines.getStroke()/2f, tile.drawx() + (len + Lines.getStroke() * heat) * i, tile.drawy() + oy);
|
||||
}
|
||||
Draw.reset();
|
||||
|
||||
if(net.active() && player != null){
|
||||
tile.block().drawPlaceText(player.name, tile.x, tile.y - (Math.max((tile.block().size-1)/2, 0)), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,7 @@ import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.type.Bullet;
|
||||
import mindustry.world.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
@@ -20,60 +18,60 @@ public class DeflectorWall extends Wall{
|
||||
|
||||
public DeflectorWall(String name){
|
||||
super(name);
|
||||
entityType = DeflectorEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
DeflectorEntity entity = tile.ent();
|
||||
|
||||
if(entity.hit < 0.0001f) return;
|
||||
|
||||
Draw.color(Color.white);
|
||||
Draw.alpha(entity.hit * 0.5f);
|
||||
Draw.blend(Blending.additive);
|
||||
Fill.rect(tile.drawx(), tile.drawy(), tilesize * size, tilesize * size);
|
||||
Draw.blend();
|
||||
Draw.reset();
|
||||
|
||||
entity.hit = Mathf.clamp(entity.hit - Time.delta() / hitTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleBulletHit(TileEntity entity, Bullet bullet){
|
||||
super.handleBulletHit(entity, bullet);
|
||||
|
||||
//doesn't reflect powerful bullets
|
||||
if(bullet.damage() > maxDamageDeflect || bullet.isDeflected()) return;
|
||||
|
||||
float penX = Math.abs(entity.x - bullet.x), penY = Math.abs(entity.y - bullet.y);
|
||||
|
||||
bullet.hitbox(rect2);
|
||||
|
||||
Vec2 position = Geometry.raycastRect(bullet.x - bullet.velocity().x*Time.delta(), bullet.y - bullet.velocity().y*Time.delta(), bullet.x + bullet.velocity().x*Time.delta(), bullet.y + bullet.velocity().y*Time.delta(),
|
||||
rect.setSize(size * tilesize + rect2.width*2 + rect2.height*2).setCenter(entity.x, entity.y));
|
||||
|
||||
if(position != null){
|
||||
bullet.set(position.x, position.y);
|
||||
}
|
||||
|
||||
if(penX > penY){
|
||||
bullet.velocity().x *= -1;
|
||||
}else{
|
||||
bullet.velocity().y *= -1;
|
||||
}
|
||||
|
||||
//bullet.updateVelocity();
|
||||
bullet.resetOwner(entity, entity.getTeam());
|
||||
bullet.scaleTime(1f);
|
||||
bullet.deflect();
|
||||
|
||||
((DeflectorEntity)entity).hit = 1f;
|
||||
}
|
||||
|
||||
public static class DeflectorEntity extends TileEntity{
|
||||
public class DeflectorEntity extends TileEntity{
|
||||
public float hit;
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
if(hit < 0.0001f) return;
|
||||
|
||||
Draw.color(Color.white);
|
||||
Draw.alpha(hit * 0.5f);
|
||||
Draw.blend(Blending.additive);
|
||||
Fill.rect(x, y, tilesize * size, tilesize * size);
|
||||
Draw.blend();
|
||||
Draw.reset();
|
||||
|
||||
hit = Mathf.clamp(hit - Time.delta() / hitTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collision(Bulletc bullet){
|
||||
super.collision(bullet);
|
||||
|
||||
//TODO fix and test
|
||||
//doesn't reflect powerful bullets
|
||||
if(bullet.damage() > maxDamageDeflect) return;
|
||||
|
||||
float penX = Math.abs(getX() - bullet.x()), penY = Math.abs(getY() - bullet.y());
|
||||
|
||||
bullet.hitbox(rect2);
|
||||
|
||||
Vec2 position = Geometry.raycastRect(bullet.x() - bullet.vel().x*Time.delta(), bullet.y() - bullet.vel().y*Time.delta(), bullet.x() + bullet.vel().x*Time.delta(), bullet.y() + bullet.vel().y*Time.delta(),
|
||||
rect.setSize(size * tilesize + rect2.width*2 + rect2.height*2).setCenter(getX(), getY()));
|
||||
|
||||
if(position != null){
|
||||
bullet.set(position.x, position.y);
|
||||
}
|
||||
|
||||
if(penX > penY){
|
||||
bullet.vel().x *= -1;
|
||||
}else{
|
||||
bullet.vel().y *= -1;
|
||||
}
|
||||
|
||||
//bullet.updateVelocity();
|
||||
bullet.owner(this);
|
||||
bullet.team(team());
|
||||
bullet.time(bullet.time() + 1f);
|
||||
//TODO deflect
|
||||
//bullet.deflect();
|
||||
|
||||
hit = 1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
package mindustry.world.blocks.defense;
|
||||
|
||||
import arc.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import arc.Graphics.*;
|
||||
import arc.Graphics.Cursor.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.Vars.pathfinder;
|
||||
|
||||
public class Door extends Wall{
|
||||
protected final static Rect rect = new Rect();
|
||||
@@ -31,24 +28,13 @@ public class Door extends Wall{
|
||||
solid = false;
|
||||
solidifes = true;
|
||||
consumesTap = true;
|
||||
entityType = DoorEntity::new;
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server)
|
||||
public static void onDoorToggle(Player player, Tile tile, boolean open){
|
||||
DoorEntity entity = tile.ent();
|
||||
if(entity != null){
|
||||
entity.open = open;
|
||||
Door door = (Door)tile.block();
|
||||
|
||||
pathfinder.updateTile(tile);
|
||||
if(!entity.open){
|
||||
Effects.effect(door.openfx, tile.drawx(), tile.drawy());
|
||||
}else{
|
||||
Effects.effect(door.closefx, tile.drawx(), tile.drawy());
|
||||
}
|
||||
Sounds.door.at(tile);
|
||||
}
|
||||
config(Boolean.class, (entity, open) -> {
|
||||
DoorEntity door = (DoorEntity)entity;
|
||||
door.open = open;
|
||||
pathfinder.updateTile(door.tile());
|
||||
(open ? closefx : openfx).at(door);
|
||||
Sounds.door.at(door);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,51 +44,52 @@ public class Door extends Wall{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
DoorEntity entity = tile.ent();
|
||||
|
||||
if(!entity.open){
|
||||
Draw.rect(region, tile.drawx(), tile.drawy());
|
||||
}else{
|
||||
Draw.rect(openRegion, tile.drawx(), tile.drawy());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor getCursor(Tile tile){
|
||||
return SystemCursor.hand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolidFor(Tile tile){
|
||||
DoorEntity entity = tile.ent();
|
||||
return !entity.open;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tapped(Tile tile, Player player){
|
||||
DoorEntity entity = tile.ent();
|
||||
|
||||
if((Units.anyEntities(tile) && entity.open) || !tile.entity.timer.get(timerToggle, 30f)){
|
||||
return;
|
||||
}
|
||||
|
||||
Call.onDoorToggle(null, tile, !entity.open);
|
||||
public TextureRegion getRequestRegion(BuildRequest req, Eachable<BuildRequest> list){
|
||||
return req.config == Boolean.TRUE ? openRegion : region;
|
||||
}
|
||||
|
||||
public class DoorEntity extends TileEntity{
|
||||
public boolean open = false;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeBoolean(open);
|
||||
public void draw(){
|
||||
Draw.rect(open ? openRegion : region, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
open = stream.readBoolean();
|
||||
public Cursor getCursor(){
|
||||
return SystemCursor.hand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkSolid(){
|
||||
return !open;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tapped(Playerc player){
|
||||
if((Units.anyEntities(tile) && open) || !timer(timerToggle, 30f)){
|
||||
return;
|
||||
}
|
||||
|
||||
tile.configure(!open);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean config(){
|
||||
return open;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.bool(open);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
open = read.bool();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,21 +5,16 @@ import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.type.BaseEntity;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
public class ForceProjector extends Block{
|
||||
public final int timerUse = timers++;
|
||||
@@ -36,14 +31,16 @@ public class ForceProjector extends Block{
|
||||
|
||||
private static Tile paramTile;
|
||||
private static ForceProjector paramBlock;
|
||||
private static ForceEntity paramEntity;
|
||||
private static Cons<AbsorbTrait> shieldConsumer = trait -> {
|
||||
if(trait.canBeAbsorbed() && trait.getTeam() != paramTile.getTeam() && Intersector.isInsideHexagon(trait.getX(), trait.getY(), paramBlock.realRadius(paramEntity) * 2f, paramTile.drawx(), paramTile.drawy())){
|
||||
private static ForceProjectorEntity paramEntity;
|
||||
private static Cons<Shielderc> shieldConsumer = trait -> {
|
||||
//TODO implement
|
||||
/*
|
||||
if(trait.team() != paramteam && Intersector.isInsideHexagon(trait.x(), trait.y(), paramEntity.realRadius() * 2f, paramx, paramy)){
|
||||
trait.absorb();
|
||||
Effects.effect(Fx.absorb, trait);
|
||||
paramEntity.hit = 1f;
|
||||
paramEntity.buildup += trait.getShieldDamage() * paramEntity.warmup;
|
||||
}
|
||||
Fx.absorb.at(trait);
|
||||
paramhit = 1f;
|
||||
parambuildup += trait.damage() * paramwarmup;
|
||||
}*/
|
||||
};
|
||||
|
||||
public ForceProjector(String name){
|
||||
@@ -55,7 +52,6 @@ public class ForceProjector extends Block{
|
||||
hasLiquids = true;
|
||||
hasItems = true;
|
||||
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.1f)).boost().update(false);
|
||||
entityType = ForceEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,83 +83,7 @@ public class ForceProjector extends Block{
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ForceEntity entity = tile.ent();
|
||||
|
||||
if(entity.shield == null){
|
||||
entity.shield = new ShieldEntity(tile);
|
||||
entity.shield.add();
|
||||
}
|
||||
|
||||
boolean phaseValid = consumes.get(ConsumeType.item).valid(tile.entity);
|
||||
|
||||
entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, Mathf.num(phaseValid), 0.1f);
|
||||
|
||||
if(phaseValid && !entity.broken && entity.timer.get(timerUse, phaseUseTime) && entity.efficiency() > 0){
|
||||
entity.cons.trigger();
|
||||
}
|
||||
|
||||
entity.radscl = Mathf.lerpDelta(entity.radscl, entity.broken ? 0f : entity.warmup, 0.05f);
|
||||
|
||||
if(Mathf.chance(Time.delta() * entity.buildup / breakage * 0.1f)){
|
||||
Effects.effect(Fx.reactorsmoke, tile.drawx() + Mathf.range(tilesize / 2f), tile.drawy() + Mathf.range(tilesize / 2f));
|
||||
}
|
||||
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, entity.efficiency(), 0.1f);
|
||||
|
||||
if(entity.buildup > 0){
|
||||
float scale = !entity.broken ? cooldownNormal : cooldownBrokenBase;
|
||||
ConsumeLiquidFilter cons = consumes.get(ConsumeType.liquid);
|
||||
if(cons.valid(entity)){
|
||||
cons.update(entity);
|
||||
scale *= (cooldownLiquid * (1f + (entity.liquids.current().heatCapacity - 0.4f) * 0.9f));
|
||||
}
|
||||
|
||||
entity.buildup -= Time.delta() * scale;
|
||||
}
|
||||
|
||||
if(entity.broken && entity.buildup <= 0){
|
||||
entity.broken = false;
|
||||
}
|
||||
|
||||
if(entity.buildup >= breakage && !entity.broken){
|
||||
entity.broken = true;
|
||||
entity.buildup = breakage;
|
||||
Effects.effect(Fx.shieldBreak, tile.drawx(), tile.drawy(), radius);
|
||||
}
|
||||
|
||||
if(entity.hit > 0f){
|
||||
entity.hit -= 1f / 5f * Time.delta();
|
||||
}
|
||||
|
||||
float realRadius = realRadius(entity);
|
||||
|
||||
paramTile = tile;
|
||||
paramEntity = entity;
|
||||
paramBlock = this;
|
||||
bulletGroup.intersect(tile.drawx() - realRadius, tile.drawy() - realRadius, realRadius*2f, realRadius * 2f, shieldConsumer);
|
||||
}
|
||||
|
||||
float realRadius(ForceEntity entity){
|
||||
return (radius + entity.phaseHeat * phaseRadiusBoost) * entity.radscl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
ForceEntity entity = tile.ent();
|
||||
|
||||
if(entity.buildup <= 0f) return;
|
||||
Draw.alpha(entity.buildup / breakage * 0.75f);
|
||||
Draw.blend(Blending.additive);
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||
Draw.blend();
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
class ForceEntity extends TileEntity{
|
||||
public class ForceProjectorEntity extends TileEntity{
|
||||
ShieldEntity shield;
|
||||
boolean broken = true;
|
||||
float buildup = 0f;
|
||||
@@ -173,37 +93,118 @@ public class ForceProjector extends Block{
|
||||
float phaseHeat;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeBoolean(broken);
|
||||
stream.writeFloat(buildup);
|
||||
stream.writeFloat(radscl);
|
||||
stream.writeFloat(warmup);
|
||||
stream.writeFloat(phaseHeat);
|
||||
public void updateTile(){
|
||||
if(shield == null){
|
||||
//TODO implement
|
||||
//shield = new ShieldEntity(tile);
|
||||
//shield.add();
|
||||
}
|
||||
|
||||
boolean phaseValid = consumes.get(ConsumeType.item).valid(tile.entity);
|
||||
|
||||
phaseHeat = Mathf.lerpDelta(phaseHeat, Mathf.num(phaseValid), 0.1f);
|
||||
|
||||
if(phaseValid && !broken && timer(timerUse, phaseUseTime) && efficiency() > 0){
|
||||
consume();
|
||||
}
|
||||
|
||||
radscl = Mathf.lerpDelta(radscl, broken ? 0f : warmup, 0.05f);
|
||||
|
||||
if(Mathf.chance(Time.delta() * buildup / breakage * 0.1f)){
|
||||
Fx.reactorsmoke.at(x + Mathf.range(tilesize / 2f), y + Mathf.range(tilesize / 2f));
|
||||
}
|
||||
|
||||
warmup = Mathf.lerpDelta(warmup, efficiency(), 0.1f);
|
||||
|
||||
if(buildup > 0){
|
||||
float scale = !broken ? cooldownNormal : cooldownBrokenBase;
|
||||
ConsumeLiquidFilter cons = consumes.get(ConsumeType.liquid);
|
||||
if(cons.valid(this)){
|
||||
cons.update(this);
|
||||
scale *= (cooldownLiquid * (1f + (liquids.current().heatCapacity - 0.4f) * 0.9f));
|
||||
}
|
||||
|
||||
buildup -= Time.delta() * scale;
|
||||
}
|
||||
|
||||
if(broken && buildup <= 0){
|
||||
broken = false;
|
||||
}
|
||||
|
||||
if(buildup >= breakage && !broken){
|
||||
broken = true;
|
||||
buildup = breakage;
|
||||
Fx.shieldBreak.at(x, y, radius);
|
||||
}
|
||||
|
||||
if(hit > 0f){
|
||||
hit -= 1f / 5f * Time.delta();
|
||||
}
|
||||
|
||||
float realRadius = realRadius();
|
||||
|
||||
paramTile = tile;
|
||||
paramEntity = this;
|
||||
paramBlock = ForceProjector.this;
|
||||
Groups.bullet.intersect(x - realRadius, y - realRadius, realRadius*2f, realRadius * 2f, shieldConsumer);
|
||||
}
|
||||
|
||||
float realRadius(){
|
||||
return (radius + phaseHeat * phaseRadiusBoost) * radscl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
broken = stream.readBoolean();
|
||||
buildup = stream.readFloat();
|
||||
radscl = stream.readFloat();
|
||||
warmup = stream.readFloat();
|
||||
phaseHeat = stream.readFloat();
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
if(buildup <= 0f) return;
|
||||
Draw.alpha(buildup / breakage * 0.75f);
|
||||
Draw.blend(Blending.additive);
|
||||
Draw.rect(topRegion, x, y);
|
||||
Draw.blend();
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.bool(broken);
|
||||
write.f(buildup);
|
||||
write.f(radscl);
|
||||
write.f(warmup);
|
||||
write.f(phaseHeat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
broken = read.bool();
|
||||
buildup = read.f();
|
||||
radscl = read.f();
|
||||
warmup = read.f();
|
||||
phaseHeat = read.f();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO fix
|
||||
class ShieldEntity{
|
||||
|
||||
}
|
||||
/*
|
||||
//@EntityDef({Drawc.class})
|
||||
//class ShieldDef{}
|
||||
|
||||
public class ShieldEntity extends BaseEntity implements DrawTrait{
|
||||
final ForceEntity entity;
|
||||
|
||||
public ShieldEntity(Tile tile){
|
||||
public ShieldEntity(){
|
||||
this.entity = tile.ent();
|
||||
set(tile.drawx(), tile.drawy());
|
||||
set(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
if(entity.isDead() || !entity.isAdded()){
|
||||
if(isDead() || !isAdded()){
|
||||
remove();
|
||||
}
|
||||
}
|
||||
@@ -221,10 +222,10 @@ public class ForceProjector extends Block{
|
||||
}
|
||||
|
||||
public void drawOver(){
|
||||
if(entity.hit <= 0f) return;
|
||||
if(hit <= 0f) return;
|
||||
|
||||
Draw.color(Color.white);
|
||||
Draw.alpha(entity.hit);
|
||||
Draw.alpha(hit);
|
||||
Fill.poly(x, y, 6, realRadius(entity));
|
||||
Draw.color();
|
||||
}
|
||||
@@ -236,7 +237,7 @@ public class ForceProjector extends Block{
|
||||
|
||||
Draw.color(Pal.accent);
|
||||
Lines.stroke(1.5f);
|
||||
Draw.alpha(0.09f + 0.08f * entity.hit);
|
||||
Draw.alpha(0.09f + 0.08f * hit);
|
||||
Fill.poly(x, y, 6, rad);
|
||||
Draw.alpha(1f);
|
||||
Lines.poly(x, y, 6, rad);
|
||||
@@ -247,5 +248,5 @@ public class ForceProjector extends Block{
|
||||
public EntityGroup targetGroup(){
|
||||
return shieldGroup;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
package mindustry.world.blocks.defense;
|
||||
|
||||
import arc.Core;
|
||||
import arc.struct.IntSet;
|
||||
import arc.graphics.Color;
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.Fx;
|
||||
import mindustry.entities.Effects;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class MendProjector extends Block{
|
||||
@@ -37,7 +35,6 @@ public class MendProjector extends Block{
|
||||
update = true;
|
||||
hasPower = true;
|
||||
hasItems = true;
|
||||
entityType = MendEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,98 +59,79 @@ public class MendProjector extends Block{
|
||||
stats.add(BlockStat.boostEffect, (phaseBoost + healPercent) / healPercent, StatUnit.timesSpeed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
MendEntity entity = tile.ent();
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, entity.cons.valid() || tile.isEnemyCheat() ? 1f : 0f, 0.08f);
|
||||
entity.charge += entity.heat * entity.delta();
|
||||
|
||||
entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, Mathf.num(entity.cons.optionalValid()), 0.1f);
|
||||
|
||||
if(entity.cons.optionalValid() && entity.timer.get(timerUse, useTime) && entity.efficiency() > 0){
|
||||
entity.cons.trigger();
|
||||
}
|
||||
|
||||
if(entity.charge >= reload){
|
||||
float realRange = range + entity.phaseHeat * phaseRangeBoost;
|
||||
entity.charge = 0f;
|
||||
|
||||
int tileRange = (int)(realRange / tilesize + 1);
|
||||
healed.clear();
|
||||
|
||||
for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){
|
||||
for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){
|
||||
if(!Mathf.within(x * tilesize, y * tilesize, tile.drawx(), tile.drawy(), realRange)) continue;
|
||||
|
||||
Tile other = world.ltile(x, y);
|
||||
|
||||
if(other == null) continue;
|
||||
|
||||
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.pos()) && other.entity != null && other.entity.health < other.entity.maxHealth()){
|
||||
other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat * phaseBoost) / 100f * entity.efficiency());
|
||||
Effects.effect(Fx.healBlockFull, Tmp.c1.set(baseColor).lerp(phaseColor, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size);
|
||||
healed.add(other.pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||
Drawf.dashCircle(x * tilesize + offset(), y * tilesize + offset(), range, Pal.accent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
MendEntity entity = tile.ent();
|
||||
float realRange = range + entity.phaseHeat * phaseRangeBoost;
|
||||
|
||||
Drawf.dashCircle(tile.drawx(), tile.drawy(), realRange, baseColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
MendEntity entity = tile.ent();
|
||||
float f = 1f - (Time.time() / 100f) % 1f;
|
||||
|
||||
Draw.color(baseColor, phaseColor, entity.phaseHeat);
|
||||
Draw.alpha(entity.heat * Mathf.absin(Time.time(), 10f, 1f) * 0.5f);
|
||||
//Draw.blend(Blending.additive);
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||
//Draw.blend();
|
||||
|
||||
Draw.alpha(1f);
|
||||
Lines.stroke((2f * f + 0.2f) * entity.heat);
|
||||
Lines.square(tile.drawx(), tile.drawy(), ((1f - f) * 8f) * size / 2f);
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(Tile tile){
|
||||
renderer.lights.add(tile.drawx(), tile.drawy(), 50f * tile.entity.efficiency(), baseColor, 0.7f * tile.entity.efficiency());
|
||||
}
|
||||
|
||||
class MendEntity extends TileEntity{
|
||||
public class MendEntity extends TileEntity{
|
||||
float heat;
|
||||
float charge = Mathf.random(reload);
|
||||
float phaseHeat;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeFloat(heat);
|
||||
stream.writeFloat(phaseHeat);
|
||||
public void updateTile(){
|
||||
heat = Mathf.lerpDelta(heat, consValid() || tile.isEnemyCheat() ? 1f : 0f, 0.08f);
|
||||
charge += heat * delta();
|
||||
|
||||
phaseHeat = Mathf.lerpDelta(phaseHeat, Mathf.num(cons().optionalValid()), 0.1f);
|
||||
|
||||
if(cons().optionalValid() && timer(timerUse, useTime) && efficiency() > 0){
|
||||
consume();
|
||||
}
|
||||
|
||||
if(charge >= reload){
|
||||
float realRange = range + phaseHeat * phaseRangeBoost;
|
||||
charge = 0f;
|
||||
|
||||
indexer.eachBlock(this, realRange, other -> other.damaged(), other -> {
|
||||
other.heal(other.maxHealth() * (healPercent + phaseHeat * phaseBoost) / 100f * efficiency());
|
||||
Fx.healBlockFull.at(other.x(), other.y(), other.block().size, Tmp.c1.set(baseColor).lerp(phaseColor, phaseHeat));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
heat = stream.readFloat();
|
||||
phaseHeat = stream.readFloat();
|
||||
public void drawSelect(){
|
||||
float realRange = range + phaseHeat * phaseRangeBoost;
|
||||
|
||||
Drawf.dashCircle(x, y, realRange, baseColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
float f = 1f - (Time.time() / 100f) % 1f;
|
||||
|
||||
Draw.color(baseColor, phaseColor, phaseHeat);
|
||||
Draw.alpha(heat * Mathf.absin(Time.time(), 10f, 1f) * 0.5f);
|
||||
Draw.rect(topRegion, x, y);
|
||||
|
||||
Draw.alpha(1f);
|
||||
Lines.stroke((2f * f + 0.2f) * heat);
|
||||
Lines.square(x, y, ((1f - f) * 8f) * size / 2f);
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(){
|
||||
renderer.lights.add(x, y, 50f * efficiency(), baseColor, 0.7f * efficiency());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.f(heat);
|
||||
write.f(phaseHeat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
heat = read.f();
|
||||
phaseHeat = read.f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
package mindustry.world.blocks.defense;
|
||||
|
||||
import arc.Core;
|
||||
import arc.struct.IntSet;
|
||||
import arc.graphics.Color;
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.Mathf;
|
||||
import arc.util.Time;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class OverdriveProjector extends Block{
|
||||
@@ -37,7 +36,6 @@ public class OverdriveProjector extends Block{
|
||||
hasPower = true;
|
||||
hasItems = true;
|
||||
canOverdrive = false;
|
||||
entityType = OverdriveEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,94 +65,71 @@ public class OverdriveProjector extends Block{
|
||||
stats.add(BlockStat.boostEffect, (int)((speedBoost + speedBoostPhase) * 100f), StatUnit.percent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(Tile tile){
|
||||
renderer.lights.add(tile.drawx(), tile.drawy(), 50f * tile.entity.efficiency(), baseColor, 0.7f * tile.entity.efficiency());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
OverdriveEntity entity = tile.ent();
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, entity.cons.valid() ? 1f : 0f, 0.08f);
|
||||
entity.charge += entity.heat * Time.delta();
|
||||
|
||||
entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, Mathf.num(entity.cons.optionalValid()), 0.1f);
|
||||
|
||||
if(entity.timer.get(timerUse, useTime) && entity.efficiency() > 0){
|
||||
entity.cons.trigger();
|
||||
}
|
||||
|
||||
if(entity.charge >= reload){
|
||||
float realRange = range + entity.phaseHeat * phaseRangeBoost;
|
||||
float realBoost = (speedBoost + entity.phaseHeat * speedBoostPhase) * entity.efficiency();
|
||||
|
||||
entity.charge = 0f;
|
||||
|
||||
int tileRange = (int)(realRange / tilesize + 1);
|
||||
healed.clear();
|
||||
|
||||
for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){
|
||||
for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){
|
||||
if(!Mathf.within(x * tilesize, y * tilesize, tile.drawx(), tile.drawy(), realRange)) continue;
|
||||
|
||||
Tile other = world.ltile(x, y);
|
||||
|
||||
if(other == null) continue;
|
||||
|
||||
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.pos()) && other.entity != null){
|
||||
if(other.entity.timeScale <= realBoost){
|
||||
other.entity.timeScaleDuration = Math.max(other.entity.timeScaleDuration, reload + 1f);
|
||||
other.entity.timeScale = Math.max(other.entity.timeScale, realBoost);
|
||||
}
|
||||
healed.add(other.pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
OverdriveEntity entity = tile.ent();
|
||||
float realRange = range + entity.phaseHeat * phaseRangeBoost;
|
||||
|
||||
Drawf.dashCircle(tile.drawx(), tile.drawy(), realRange, baseColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
OverdriveEntity entity = tile.ent();
|
||||
float f = 1f - (Time.time() / 100f) % 1f;
|
||||
|
||||
Draw.color(baseColor, phaseColor, entity.phaseHeat);
|
||||
Draw.alpha(entity.heat * Mathf.absin(Time.time(), 10f, 1f) * 0.5f);
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||
Draw.alpha(1f);
|
||||
Lines.stroke((2f * f + 0.2f) * entity.heat);
|
||||
Lines.square(tile.drawx(), tile.drawy(), (1f - f) * 8f);
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
class OverdriveEntity extends TileEntity{
|
||||
public class OverdriveEntity extends TileEntity{
|
||||
float heat;
|
||||
float charge = Mathf.random(reload);
|
||||
float phaseHeat;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeFloat(heat);
|
||||
stream.writeFloat(phaseHeat);
|
||||
public void drawLight(){
|
||||
renderer.lights.add(x, y, 50f * efficiency(), baseColor, 0.7f * efficiency());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
heat = stream.readFloat();
|
||||
phaseHeat = stream.readFloat();
|
||||
public void updateTile(){
|
||||
heat = Mathf.lerpDelta(heat, consValid() ? 1f : 0f, 0.08f);
|
||||
charge += heat * Time.delta();
|
||||
|
||||
phaseHeat = Mathf.lerpDelta(phaseHeat, Mathf.num(cons().optionalValid()), 0.1f);
|
||||
|
||||
if(timer(timerUse, useTime) && efficiency() > 0){
|
||||
consume();
|
||||
}
|
||||
|
||||
if(charge >= reload){
|
||||
float realRange = range + phaseHeat * phaseRangeBoost;
|
||||
float realBoost = (speedBoost + phaseHeat * speedBoostPhase) * efficiency();
|
||||
|
||||
charge = 0f;
|
||||
indexer.eachBlock(this, realRange, other -> other.timeScale() < realBoost, other -> other.applyBoost(realBoost, reload + 1f));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(){
|
||||
float realRange = range + phaseHeat * phaseRangeBoost;
|
||||
|
||||
Drawf.dashCircle(x, y, realRange, baseColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
float f = 1f - (Time.time() / 100f) % 1f;
|
||||
|
||||
Draw.color(baseColor, phaseColor, phaseHeat);
|
||||
Draw.alpha(heat * Mathf.absin(Time.time(), 10f, 1f) * 0.5f);
|
||||
Draw.rect(topRegion, x, y);
|
||||
Draw.alpha(1f);
|
||||
Lines.stroke((2f * f + 0.2f) * heat);
|
||||
Lines.square(x, y, (1f - f) * 8f);
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.f(heat);
|
||||
write.f(phaseHeat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
heat = read.f();
|
||||
phaseHeat = read.f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package mindustry.world.blocks.defense;
|
||||
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.graphics.g2d.Fill;
|
||||
import arc.math.Mathf;
|
||||
import mindustry.entities.effect.Lightning;
|
||||
import mindustry.entities.type.Unit;
|
||||
import mindustry.graphics.Layer;
|
||||
import mindustry.graphics.Pal;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class ShockMine extends Block{
|
||||
public final int timerDamage = timers++;
|
||||
@@ -29,32 +26,35 @@ public class ShockMine extends Block{
|
||||
rebuildable = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
super.draw(tile);
|
||||
Draw.color(tile.getTeam().color);
|
||||
Draw.alpha(0.22f);
|
||||
Fill.rect(tile.drawx(), tile.drawy(), 2f, 2f);
|
||||
Draw.color();
|
||||
}
|
||||
public class ShockMineEntity extends TileEntity{
|
||||
|
||||
@Override
|
||||
public void drawTeam(Tile tile){
|
||||
//no
|
||||
}
|
||||
@Override
|
||||
public void drawLayer(){
|
||||
super.draw();
|
||||
Draw.color(team.color);
|
||||
Draw.alpha(0.22f);
|
||||
Fill.rect(x, y, 2f, 2f);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
//nope
|
||||
}
|
||||
@Override
|
||||
public void drawTeam(){
|
||||
//no
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitOn(Tile tile, Unit unit){
|
||||
if(unit.getTeam() != tile.getTeam() && tile.entity.timer.get(timerDamage, cooldown)){
|
||||
for(int i = 0; i < tendrils; i++){
|
||||
Lightning.create(tile.getTeam(), Pal.lancerLaser, damage, tile.drawx(), tile.drawy(), Mathf.random(360f), length);
|
||||
@Override
|
||||
public void draw(){
|
||||
//nope
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitOn(Unitc unit){
|
||||
if(unit.team() != team && timer(timerDamage, cooldown)){
|
||||
for(int i = 0; i < tendrils; i++){
|
||||
Lightning.create(team, Pal.lancerLaser, damage, x, y, Mathf.random(360f), length);
|
||||
}
|
||||
damage(tileDamage);
|
||||
}
|
||||
tile.entity.damage(tileDamage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package mindustry.world.blocks.defense;
|
||||
|
||||
import arc.math.Mathf;
|
||||
import mindustry.entities.type.Bullet;
|
||||
import mindustry.entities.effect.Lightning;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.graphics.Pal;
|
||||
import arc.math.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
|
||||
public class SurgeWall extends Wall{
|
||||
public float lightningChance = 0.05f;
|
||||
@@ -15,11 +14,13 @@ public class SurgeWall extends Wall{
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleBulletHit(TileEntity entity, Bullet bullet){
|
||||
super.handleBulletHit(entity, bullet);
|
||||
if(Mathf.chance(lightningChance)){
|
||||
Lightning.create(entity.getTeam(), Pal.surge, lightningDamage, bullet.x, bullet.y, bullet.rot() + 180f, lightningLength);
|
||||
public class SurgeEntity extends TileEntity{
|
||||
@Override
|
||||
public void collision(Bulletc bullet){
|
||||
super.collision(bullet);
|
||||
if(Mathf.chance(lightningChance)){
|
||||
Lightning.create(team(), Pal.surge, lightningDamage, x, y, bullet.rotation() + 180f, lightningLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package mindustry.world.blocks.defense;
|
||||
|
||||
import arc.Core;
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.graphics.g2d.TextureRegion;
|
||||
import arc.math.Mathf;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.BlockGroup;
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class Wall extends Block{
|
||||
public int variants = 0;
|
||||
@@ -33,15 +32,6 @@ public class Wall extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
if(variants == 0){
|
||||
Draw.rect(region, tile.drawx(), tile.drawy());
|
||||
}else{
|
||||
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.drawx(), tile.drawy());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find(Core.atlas.has(name) ? name : name + "1")};
|
||||
@@ -51,4 +41,16 @@ public class Wall extends Block{
|
||||
public boolean canReplace(Block other){
|
||||
return super.canReplace(other) && health > other.health;
|
||||
}
|
||||
|
||||
public class WallEntity extends TileEntity{
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
if(variants == 0){
|
||||
Draw.rect(region, x, y);
|
||||
}else{
|
||||
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package mindustry.world.blocks.defense.turrets;
|
||||
|
||||
import arc.math.Mathf;
|
||||
import arc.math.geom.Vec2;
|
||||
import mindustry.entities.Predict;
|
||||
import mindustry.entities.type.Bullet;
|
||||
import mindustry.entities.bullet.BulletType;
|
||||
import mindustry.world.Tile;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
@@ -20,28 +18,28 @@ public class ArtilleryTurret extends ItemTurret{
|
||||
targetAir = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shoot(Tile tile, BulletType ammo){
|
||||
TurretEntity entity = tile.ent();
|
||||
public class ArtilleryTurretEntity extends ItemTurretEntity{
|
||||
@Override
|
||||
protected void shoot(BulletType ammo){
|
||||
recoil = recoilAmount;
|
||||
heat = 1f;
|
||||
|
||||
entity.recoil = recoil;
|
||||
entity.heat = 1f;
|
||||
BulletType type = peekAmmo();
|
||||
|
||||
BulletType type = peekAmmo(tile);
|
||||
tr.trns(rotation, size * tilesize / 2);
|
||||
|
||||
tr.trns(entity.rotation, size * tilesize / 2);
|
||||
Vec2 predict = Predict.intercept(tile, target, type.speed);
|
||||
|
||||
Vec2 predict = Predict.intercept(tile, entity.target, type.speed);
|
||||
float dst = dst(predict.x, predict.y);
|
||||
float maxTraveled = type.lifetime * type.speed;
|
||||
|
||||
float dst = entity.dst(predict.x, predict.y);
|
||||
float maxTraveled = type.lifetime * type.speed;
|
||||
for(int i = 0; i < shots; i++){
|
||||
ammo.create(tile.entity, team, x + tr.x, y + tr.y,
|
||||
rotation + Mathf.range(inaccuracy + type.inaccuracy), 1f + Mathf.range(velocityInaccuracy), (dst / maxTraveled));
|
||||
}
|
||||
|
||||
for(int i = 0; i < shots; i++){
|
||||
Bullet.create(ammo, tile.entity, tile.getTeam(), tile.drawx() + tr.x, tile.drawy() + tr.y,
|
||||
entity.rotation + Mathf.range(inaccuracy + type.inaccuracy), 1f + Mathf.range(velocityInaccuracy), (dst / maxTraveled));
|
||||
effects();
|
||||
useAmmo();
|
||||
}
|
||||
|
||||
effects(tile);
|
||||
useAmmo(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package mindustry.world.blocks.defense.turrets;
|
||||
|
||||
import arc.math.Mathf;
|
||||
import arc.util.Time;
|
||||
import mindustry.entities.bullet.BulletType;
|
||||
import mindustry.world.Tile;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
@@ -14,24 +13,24 @@ public class BurstTurret extends ItemTurret{
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shoot(Tile tile, BulletType ammo){
|
||||
TurretEntity entity = tile.ent();
|
||||
public class BurstTurretEntity extends ItemTurretEntity{
|
||||
|
||||
entity.heat = 1f;
|
||||
@Override
|
||||
protected void shoot(BulletType ammo){
|
||||
heat = 1f;
|
||||
|
||||
for(int i = 0; i < shots; i++){
|
||||
Time.run(burstSpacing * i, () -> {
|
||||
if(!(tile.entity instanceof TurretEntity) ||
|
||||
!hasAmmo(tile)) return;
|
||||
for(int i = 0; i < shots; i++){
|
||||
Time.run(burstSpacing * i, () -> {
|
||||
if(!(tile.entity instanceof TurretEntity) || !hasAmmo()) return;
|
||||
|
||||
entity.recoil = recoil;
|
||||
recoil = recoilAmount;
|
||||
|
||||
tr.trns(entity.rotation, size * tilesize / 2, Mathf.range(xRand));
|
||||
bullet(tile, ammo, entity.rotation + Mathf.range(inaccuracy));
|
||||
effects(tile);
|
||||
useAmmo(tile);
|
||||
});
|
||||
tr.trns(rotation, size * tilesize / 2, Mathf.range(xRand));
|
||||
bullet(ammo, rotation + Mathf.range(inaccuracy));
|
||||
effects();
|
||||
useAmmo();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
@@ -20,46 +18,42 @@ public class ChargeTurret extends PowerTurret{
|
||||
|
||||
public ChargeTurret(String name){
|
||||
super(name);
|
||||
entityType = LaserTurretEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shoot(Tile tile, BulletType ammo){
|
||||
LaserTurretEntity entity = tile.ent();
|
||||
public class ChargeTurretEntity extends PowerTurretEntity{
|
||||
public boolean shooting;
|
||||
|
||||
useAmmo(tile);
|
||||
@Override
|
||||
public void shoot(BulletType ammo){
|
||||
useAmmo();
|
||||
|
||||
tr.trns(entity.rotation, size * tilesize / 2);
|
||||
Effects.effect(chargeBeginEffect, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation);
|
||||
tr.trns(rotation, size * tilesize / 2);
|
||||
chargeBeginEffect.at(x + tr.x, y + tr.y, rotation);
|
||||
|
||||
for(int i = 0; i < chargeEffects; i++){
|
||||
Time.run(Mathf.random(chargeMaxDelay), () -> {
|
||||
if(!isTurret(tile)) return;
|
||||
tr.trns(entity.rotation, size * tilesize / 2);
|
||||
Effects.effect(chargeEffect, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation);
|
||||
for(int i = 0; i < chargeEffects; i++){
|
||||
Time.run(Mathf.random(chargeMaxDelay), () -> {
|
||||
if(!isValid()) return;
|
||||
tr.trns(rotation, size * tilesize / 2);
|
||||
chargeEffect.at(x + tr.x, y + tr.y, rotation);
|
||||
});
|
||||
}
|
||||
|
||||
shooting = true;
|
||||
|
||||
Time.run(chargeTime, () -> {
|
||||
if(!isValid()) return;
|
||||
tr.trns(rotation, size * tilesize / 2);
|
||||
recoil = recoilAmount;
|
||||
heat = 1f;
|
||||
bullet(ammo, rotation + Mathf.range(inaccuracy));
|
||||
effects();
|
||||
shooting = false;
|
||||
});
|
||||
}
|
||||
|
||||
entity.shooting = true;
|
||||
|
||||
Time.run(chargeTime, () -> {
|
||||
if(!isTurret(tile)) return;
|
||||
tr.trns(entity.rotation, size * tilesize / 2);
|
||||
entity.recoil = recoil;
|
||||
entity.heat = 1f;
|
||||
bullet(tile, ammo, entity.rotation + Mathf.range(inaccuracy));
|
||||
effects(tile);
|
||||
entity.shooting = false;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldTurn(Tile tile){
|
||||
LaserTurretEntity entity = tile.ent();
|
||||
return !entity.shooting;
|
||||
}
|
||||
|
||||
public class LaserTurretEntity extends TurretEntity{
|
||||
public boolean shooting;
|
||||
@Override
|
||||
public boolean shouldTurn(){
|
||||
return !shooting;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@ import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.meta.values.*;
|
||||
@@ -32,33 +31,36 @@ public class CooledTurret extends Turret{
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.booster, new BoosterListValue(reload, consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount, coolantMultiplier, true, l -> consumes.liquidfilters.get(l.id)));
|
||||
stats.add(BlockStat.booster, new BoosterListValue(reloadTime, consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount, coolantMultiplier, true, l -> consumes.liquidfilters.get(l.id)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
if(tile.entity.liquids.currentAmount() <= 0.001f){
|
||||
Events.fire(Trigger.turretCool);
|
||||
public class CooledTurretEntity extends TurretEntity{
|
||||
|
||||
@Override
|
||||
public void handleLiquid(Tilec source, Liquid liquid, float amount){
|
||||
if(liquids.currentAmount() <= 0.001f){
|
||||
Events.fire(Trigger.turretCool);
|
||||
}
|
||||
|
||||
super.handleLiquid(source, liquid, amount);
|
||||
}
|
||||
|
||||
super.handleLiquid(tile, source, liquid, amount);
|
||||
}
|
||||
@Override
|
||||
protected void updateShooting(){
|
||||
super.updateShooting();
|
||||
|
||||
@Override
|
||||
protected void updateShooting(Tile tile){
|
||||
super.updateShooting(tile);
|
||||
float maxUsed = consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount;
|
||||
|
||||
float maxUsed = consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount;
|
||||
Liquid liquid = liquids.current();
|
||||
|
||||
TurretEntity entity = tile.ent();
|
||||
Liquid liquid = entity.liquids.current();
|
||||
float used = Math.min(Math.min(liquids.get(liquid), maxUsed * Time.delta()), Math.max(0, ((reloadTime - reload) / coolantMultiplier) / liquid.heatCapacity)) * baseReloadSpeed();
|
||||
reload += used * liquid.heatCapacity * coolantMultiplier;
|
||||
liquids.remove(liquid, used);
|
||||
|
||||
float used = Math.min(Math.min(entity.liquids.get(liquid), maxUsed * Time.delta()), Math.max(0, ((reload - entity.reload) / coolantMultiplier) / liquid.heatCapacity)) * baseReloadSpeed(tile);
|
||||
entity.reload += used * liquid.heatCapacity * coolantMultiplier;
|
||||
entity.liquids.remove(liquid, used);
|
||||
|
||||
if(Mathf.chance(0.06 * used)){
|
||||
Effects.effect(coolEffect, tile.drawx() + Mathf.range(size * tilesize / 2f), tile.drawy() + Mathf.range(size * tilesize / 2f));
|
||||
if(Mathf.chance(0.06 * used)){
|
||||
coolEffect.at(x + Mathf.range(size * tilesize / 2f), y + Mathf.range(size * tilesize / 2f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package mindustry.world.blocks.defense.turrets;
|
||||
|
||||
import arc.math.Mathf;
|
||||
import mindustry.entities.bullet.BulletType;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.BlockStat;
|
||||
import mindustry.world.meta.StatUnit;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
public class DoubleTurret extends ItemTurret{
|
||||
public float shotWidth = 2f;
|
||||
|
||||
public DoubleTurret(String name){
|
||||
super(name);
|
||||
shots = 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.remove(BlockStat.reload);
|
||||
stats.add(BlockStat.reload, 60f / reload, StatUnit.none);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shoot(Tile tile, BulletType ammo){
|
||||
TurretEntity entity = tile.ent();
|
||||
entity.shots++;
|
||||
|
||||
int i = Mathf.signs[entity.shots % 2];
|
||||
|
||||
tr.trns(entity.rotation - 90, shotWidth * i, size * tilesize / 2);
|
||||
bullet(tile, ammo, entity.rotation + Mathf.range(inaccuracy));
|
||||
|
||||
effects(tile);
|
||||
useAmmo(tile);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,35 @@
|
||||
package mindustry.world.blocks.defense.turrets;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.meta.values.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class ItemTurret extends CooledTurret{
|
||||
public int maxAmmo = 30;
|
||||
public ObjectMap<Item, BulletType> ammo = new ObjectMap<>();
|
||||
public ObjectMap<Item, BulletType> ammoTypes = new ObjectMap<>();
|
||||
|
||||
public ItemTurret(String name){
|
||||
super(name);
|
||||
hasItems = true;
|
||||
entityType = ItemTurretEntity::new;
|
||||
}
|
||||
|
||||
/** Initializes accepted ammo map. Format: [item1, bullet1, item2, bullet2...] */
|
||||
protected void ammo(Object... objects){
|
||||
ammo = OrderedMap.of(objects);
|
||||
ammoTypes = OrderedMap.of(objects);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -41,19 +37,19 @@ public class ItemTurret extends CooledTurret{
|
||||
super.setStats();
|
||||
|
||||
stats.remove(BlockStat.itemCapacity);
|
||||
stats.add(BlockStat.ammo, new AmmoListValue<>(ammo));
|
||||
consumes.add(new ConsumeItemFilter(i -> ammo.containsKey(i)){
|
||||
stats.add(BlockStat.ammo, new AmmoListValue<>(ammoTypes));
|
||||
consumes.add(new ConsumeItemFilter(i -> ammoTypes.containsKey(i)){
|
||||
@Override
|
||||
public void build(Tile tile, Table table){
|
||||
public void build(Tilec tile, Table table){
|
||||
MultiReqImage image = new MultiReqImage();
|
||||
content.items().each(i -> filter.get(i) && (!world.isZone() || data.isUnlocked(i)), item -> image.add(new ReqImage(new ItemImage(item.icon(Cicon.medium)),
|
||||
() -> tile.entity != null && !((ItemTurretEntity)tile.entity).ammo.isEmpty() && ((ItemEntry)tile.<ItemTurretEntity>ent().ammo.peek()).item == item)));
|
||||
content.items().each(i -> filter.get(i) && (!state.isCampaign() || data.isUnlocked(i)), item -> image.add(new ReqImage(new ItemImage(item.icon(Cicon.medium)),
|
||||
() -> tile != null && !((ItemTurretEntity)tile).ammo.isEmpty() && ((ItemEntry)((ItemTurretEntity)tile).ammo.peek()).item == item)));
|
||||
|
||||
table.add(image).size(8 * 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean valid(TileEntity entity){
|
||||
public boolean valid(Tilec entity){
|
||||
//valid when there's any ammo in the turret
|
||||
return !((ItemTurretEntity)entity).ammo.isEmpty();
|
||||
}
|
||||
@@ -65,109 +61,101 @@ public class ItemTurret extends CooledTurret{
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityAdded(Tile tile){
|
||||
super.onProximityAdded(tile);
|
||||
|
||||
//add first ammo item to cheaty blocks so they can shoot properly
|
||||
if(tile.isEnemyCheat() && ammo.size > 0){
|
||||
handleItem(ammo.entries().next().key, tile, tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayBars(Tile tile, Table bars){
|
||||
super.displayBars(tile, bars);
|
||||
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
bars.add(new Bar("blocks.ammo", Pal.ammo, () -> (float)entity.totalAmmo / maxAmmo)).growX();
|
||||
bars.row();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
BulletType type = ammo.get(item);
|
||||
|
||||
if(type == null) return 0;
|
||||
|
||||
return Math.min((int)((maxAmmo - entity.totalAmmo) / ammo.get(item).ammoMultiplier), amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Tile tile, Unit source){
|
||||
for(int i = 0; i < amount; i++){
|
||||
handleItem(item, tile, null);
|
||||
}
|
||||
}
|
||||
|
||||
//currently can't remove items from turrets.
|
||||
@Override
|
||||
public int removeStack(Tile tile, Item item, int amount){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
TurretEntity entity = tile.ent();
|
||||
if(entity == null) return;
|
||||
|
||||
if(item == Items.pyratite){
|
||||
Events.fire(Trigger.flameAmmo);
|
||||
}
|
||||
|
||||
BulletType type = ammo.get(item);
|
||||
entity.totalAmmo += type.ammoMultiplier;
|
||||
|
||||
//find ammo entry by type
|
||||
for(int i = 0; i < entity.ammo.size; i++){
|
||||
ItemEntry entry = (ItemEntry)entity.ammo.get(i);
|
||||
|
||||
//if found, put it to the right
|
||||
if(entry.item == item){
|
||||
entry.amount += type.ammoMultiplier;
|
||||
entity.ammo.swap(i, entity.ammo.size - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//must not be found
|
||||
entity.ammo.add(new ItemEntry(item, (int)type.ammoMultiplier));
|
||||
|
||||
//fire events for the tutorial
|
||||
if(state.rules.tutorial){
|
||||
Events.fire(new TurretAmmoDeliverEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
return ammo != null && ammo.get(item) != null && entity.totalAmmo + ammo.get(item).ammoMultiplier <= maxAmmo;
|
||||
}
|
||||
|
||||
public class ItemTurretEntity extends TurretEntity{
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeByte(ammo.size);
|
||||
for(AmmoEntry entry : ammo){
|
||||
ItemEntry i = (ItemEntry)entry;
|
||||
stream.writeByte(i.item.id);
|
||||
stream.writeShort(i.amount);
|
||||
public void onProximityAdded(){
|
||||
super.onProximityAdded();
|
||||
|
||||
//add first ammo item to cheaty blocks so they can shoot properly
|
||||
if(tile.isEnemyCheat() && ammo.size > 0){
|
||||
handleItem(this, ammoTypes.entries().next().key);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
byte amount = stream.readByte();
|
||||
public void displayBars(Table bars){
|
||||
super.displayBars(bars);
|
||||
|
||||
bars.add(new Bar("blocks.ammo", Pal.ammo, () -> (float)totalAmmo / maxAmmo)).growX();
|
||||
bars.row();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Teamc source){
|
||||
BulletType type = ammoTypes.get(item);
|
||||
|
||||
if(type == null) return 0;
|
||||
|
||||
return Math.min((int)((maxAmmo - totalAmmo) / ammoTypes.get(item).ammoMultiplier), amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Teamc source){
|
||||
for(int i = 0; i < amount; i++){
|
||||
Item item = Vars.content.item(stream.readByte());
|
||||
short a = stream.readShort();
|
||||
handleItem(null, item);
|
||||
}
|
||||
}
|
||||
|
||||
//currently can't remove items from turrets.
|
||||
@Override
|
||||
public int removeStack(Item item, int amount){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Tilec source, Item item){
|
||||
|
||||
if(item == Items.pyratite){
|
||||
Events.fire(Trigger.flameAmmo);
|
||||
}
|
||||
|
||||
BulletType type = ammoTypes.get(item);
|
||||
totalAmmo += type.ammoMultiplier;
|
||||
|
||||
//find ammo entry by type
|
||||
for(int i = 0; i < ammo.size; i++){
|
||||
ItemEntry entry = (ItemEntry)ammo.get(i);
|
||||
|
||||
//if found, put it to the right
|
||||
if(entry.item == item){
|
||||
entry.amount += type.ammoMultiplier;
|
||||
ammo.swap(i, ammo.size - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//must not be found
|
||||
ammo.add(new ItemEntry(item, (int)type.ammoMultiplier));
|
||||
|
||||
//fire events for the tutorial
|
||||
if(state.rules.tutorial){
|
||||
Events.fire(new TurretAmmoDeliverEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return ammoTypes.get(item) != null && totalAmmo + ammoTypes.get(item).ammoMultiplier <= maxAmmo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.b(ammo.size);
|
||||
for(AmmoEntry entry : ammo){
|
||||
ItemEntry i = (ItemEntry)entry;
|
||||
write.b(i.item.id);
|
||||
write.s(i.amount);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
byte amount = read.b();
|
||||
for(int i = 0; i < amount; i++){
|
||||
Item item = Vars.content.item(read.b());
|
||||
short a = read.s();
|
||||
totalAmmo += a;
|
||||
ammo.add(new ItemEntry(item, a));
|
||||
}
|
||||
@@ -184,7 +172,7 @@ public class ItemTurret extends CooledTurret{
|
||||
|
||||
@Override
|
||||
public BulletType type(){
|
||||
return ammo.get(item);
|
||||
return ammoTypes.get(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@ package mindustry.world.blocks.defense.turrets;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.meta.values.*;
|
||||
@@ -23,7 +21,12 @@ public class LaserTurret extends PowerTurret{
|
||||
|
||||
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.01f)).update(false);
|
||||
coolantMultiplier = 1f;
|
||||
entityType = LaserTurretEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
consumes.powerCond(powerUse, entity -> ((LaserTurretEntity)entity).bullet != null || ((LaserTurretEntity)entity).target != null);
|
||||
super.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,84 +34,75 @@ public class LaserTurret extends PowerTurret{
|
||||
super.setStats();
|
||||
|
||||
stats.remove(BlockStat.booster);
|
||||
stats.add(BlockStat.input, new BoosterListValue(reload, consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount, coolantMultiplier, false, l -> consumes.liquidfilters.get(l.id)));
|
||||
stats.add(BlockStat.input, new BoosterListValue(reloadTime, consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount, coolantMultiplier, false, l -> consumes.liquidfilters.get(l.id)));
|
||||
stats.remove(BlockStat.damage);
|
||||
//damages every 5 ticks, at least in meltdown's case
|
||||
stats.add(BlockStat.damage, shootType.damage * 60f / 5f, StatUnit.perSecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
super.update(tile);
|
||||
|
||||
LaserTurretEntity entity = tile.ent();
|
||||
|
||||
if(entity.bulletLife > 0 && entity.bullet != null){
|
||||
tr.trns(entity.rotation, size * tilesize / 2f, 0f);
|
||||
entity.bullet.rot(entity.rotation);
|
||||
entity.bullet.set(tile.drawx() + tr.x, tile.drawy() + tr.y);
|
||||
entity.bullet.time(0f);
|
||||
entity.heat = 1f;
|
||||
entity.recoil = recoil;
|
||||
entity.bulletLife -= Time.delta();
|
||||
if(entity.bulletLife <= 0f){
|
||||
entity.bullet = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateShooting(Tile tile){
|
||||
LaserTurretEntity entity = tile.ent();
|
||||
|
||||
if(entity.bulletLife > 0 && entity.bullet != null){
|
||||
return;
|
||||
}
|
||||
|
||||
if(entity.reload >= reload && (entity.cons.valid() || tile.isEnemyCheat())){
|
||||
BulletType type = peekAmmo(tile);
|
||||
|
||||
shoot(tile, type);
|
||||
|
||||
entity.reload = 0f;
|
||||
}else{
|
||||
Liquid liquid = entity.liquids.current();
|
||||
float maxUsed = consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount;
|
||||
|
||||
float used = baseReloadSpeed(tile) * (tile.isEnemyCheat() ? maxUsed : Math.min(entity.liquids.get(liquid), maxUsed * Time.delta())) * liquid.heatCapacity * coolantMultiplier;
|
||||
entity.reload += used;
|
||||
entity.liquids.remove(liquid, used);
|
||||
|
||||
if(Mathf.chance(0.06 * used)){
|
||||
Effects.effect(coolEffect, tile.drawx() + Mathf.range(size * tilesize / 2f), tile.drawy() + Mathf.range(size * tilesize / 2f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void turnToTarget(Tile tile, float targetRot){
|
||||
LaserTurretEntity entity = tile.ent();
|
||||
|
||||
entity.rotation = Angles.moveToward(entity.rotation, targetRot, rotatespeed * entity.delta() * (entity.bulletLife > 0f ? firingMoveFract : 1f));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bullet(Tile tile, BulletType type, float angle){
|
||||
LaserTurretEntity entity = tile.ent();
|
||||
|
||||
entity.bullet = Bullet.create(type, tile.entity, tile.getTeam(), tile.drawx() + tr.x, tile.drawy() + tr.y, angle);
|
||||
entity.bulletLife = shootDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldActiveSound(Tile tile){
|
||||
LaserTurretEntity entity = tile.ent();
|
||||
|
||||
return entity.bulletLife > 0 && entity.bullet != null;
|
||||
}
|
||||
|
||||
class LaserTurretEntity extends TurretEntity{
|
||||
Bullet bullet;
|
||||
public class LaserTurretEntity extends PowerTurretEntity{
|
||||
Bulletc bullet;
|
||||
float bulletLife;
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
super.updateTile();
|
||||
|
||||
if(bulletLife > 0 && bullet != null){
|
||||
tr.trns(rotation, size * tilesize / 2f, 0f);
|
||||
bullet.rotation(rotation);
|
||||
bullet.set(x + tr.x, y + tr.y);
|
||||
bullet.time(0f);
|
||||
heat = 1f;
|
||||
recoil = recoilAmount;
|
||||
bulletLife -= Time.delta() / Math.max(efficiency(), 0.00001f);
|
||||
if(bulletLife <= 0f){
|
||||
bullet = null;
|
||||
}
|
||||
}else if(reload > 0){
|
||||
Liquid liquid = liquids().current();
|
||||
float maxUsed = consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount;
|
||||
|
||||
float used = (tile.isEnemyCheat() ? maxUsed * Time.delta() : Math.min(liquids.get(liquid), maxUsed * Time.delta())) * liquid.heatCapacity * coolantMultiplier;
|
||||
reload -= used;
|
||||
liquids.remove(liquid, used);
|
||||
|
||||
if(Mathf.chance(0.06 * used)){
|
||||
coolEffect.at(x + Mathf.range(size * tilesize / 2f), y + Mathf.range(size * tilesize / 2f));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateShooting(){
|
||||
if(bulletLife > 0 && bullet != null){
|
||||
return;
|
||||
}
|
||||
|
||||
if(reload <= 0 && (consValid() || tile.isEnemyCheat())){
|
||||
BulletType type = peekAmmo();
|
||||
|
||||
shoot(type);
|
||||
|
||||
reload = reloadTime;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void turnToTarget(float targetRot){
|
||||
rotation = Angles.moveToward(rotation, targetRot, efficiency() * rotatespeed * delta() * (bulletLife > 0f ? firingMoveFract : 1f));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bullet(BulletType type, float angle){
|
||||
bullet = type.create(tile.entity, team, x + tr.x, y + tr.y, angle);
|
||||
bulletLife = shootDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldActiveSound(){
|
||||
return bulletLife > 0 && bullet != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,19 +5,16 @@ import arc.graphics.g2d.*;
|
||||
import arc.struct.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.entities.effect.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.meta.values.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
public class LiquidTurret extends Turret{
|
||||
public ObjectMap<Liquid, BulletType> ammo = new ObjectMap<>();
|
||||
public ObjectMap<Liquid, BulletType> ammoTypes = new ObjectMap<>();
|
||||
public int liquidRegion;
|
||||
|
||||
public LiquidTurret(String name){
|
||||
@@ -29,31 +26,18 @@ public class LiquidTurret extends Turret{
|
||||
|
||||
/** Initializes accepted ammo map. Format: [liquid1, bullet1, liquid2, bullet2...] */
|
||||
protected void ammo(Object... objects){
|
||||
ammo = OrderedMap.of(objects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
super.drawLayer(tile);
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
if(Core.atlas.isFound(reg(liquidRegion))){
|
||||
Draw.color(entity.liquids.current().color);
|
||||
Draw.alpha(entity.liquids.total() / liquidCapacity);
|
||||
Draw.rect(reg(liquidRegion), tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90);
|
||||
Draw.color();
|
||||
}
|
||||
ammoTypes = OrderedMap.of(objects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.ammo, new AmmoListValue<>(ammo));
|
||||
consumes.add(new ConsumeLiquidFilter(i -> ammo.containsKey(i), 1f){
|
||||
stats.add(BlockStat.ammo, new AmmoListValue<>(ammoTypes));
|
||||
consumes.add(new ConsumeLiquidFilter(i -> ammoTypes.containsKey(i), 1f){
|
||||
@Override
|
||||
public boolean valid(TileEntity entity){
|
||||
return !((TurretEntity)entity).ammo.isEmpty();
|
||||
public boolean valid(Tilec entity){
|
||||
return entity.liquids().total() > 0.001f;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,85 +47,85 @@ public class LiquidTurret extends Turret{
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldActiveSound(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
return entity.target != null && hasAmmo(tile);
|
||||
}
|
||||
public class LiquidTurretEntity extends TurretEntity{
|
||||
|
||||
@Override
|
||||
protected boolean validateTarget(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
if(entity.liquids.current().canExtinguish() && entity.target instanceof Tile){
|
||||
return Fire.has(((Tile)entity.target).x, ((Tile)entity.target).y);
|
||||
}
|
||||
return super.validateTarget(tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void findTarget(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
if(entity.liquids.current().canExtinguish()){
|
||||
int tr = (int)(range / tilesize);
|
||||
for(int x = -tr; x <= tr; x++){
|
||||
for(int y = -tr; y <= tr; y++){
|
||||
if(Fire.has(x + tile.x, y + tile.y)){
|
||||
entity.target = world.tile(x + tile.x, y + tile.y);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void drawLayer(){
|
||||
super.drawLayer();
|
||||
|
||||
if(Core.atlas.isFound(reg(liquidRegion))){
|
||||
Draw.color(liquids.current().color);
|
||||
Draw.alpha(liquids.total() / liquidCapacity);
|
||||
Draw.rect(reg(liquidRegion), x + tr2.x, y + tr2.y, rotation - 90);
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
super.findTarget(tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void effects(Tile tile){
|
||||
BulletType type = peekAmmo(tile);
|
||||
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
Effects.effect(type.shootEffect, entity.liquids.current().color, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation);
|
||||
Effects.effect(type.smokeEffect, entity.liquids.current().color, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation);
|
||||
//shootSound.at(tile);
|
||||
|
||||
if(shootShake > 0){
|
||||
Effects.shake(shootShake, shootShake, tile.entity);
|
||||
@Override
|
||||
public boolean shouldActiveSound(){
|
||||
return target != null && hasAmmo();
|
||||
}
|
||||
|
||||
entity.recoil = recoil;
|
||||
}
|
||||
@Override
|
||||
protected void findTarget(){
|
||||
if(liquids.current().canExtinguish()){
|
||||
int tr = (int)(range / tilesize);
|
||||
for(int x = -tr; x <= tr; x++){
|
||||
for(int y = -tr; y <= tr; y++){
|
||||
if(Fires.has(x + tile.x, y + tile.y)){
|
||||
target = Fires.get(x + tile.x, y + tile.y);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulletType useAmmo(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
if(tile.isEnemyCheat()) return ammo.get(entity.liquids.current());
|
||||
BulletType type = ammo.get(entity.liquids.current());
|
||||
entity.liquids.remove(entity.liquids.current(), type.ammoMultiplier);
|
||||
return type;
|
||||
}
|
||||
super.findTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulletType peekAmmo(Tile tile){
|
||||
return ammo.get(tile.entity.liquids.current());
|
||||
}
|
||||
@Override
|
||||
protected void effects(){
|
||||
BulletType type = peekAmmo();
|
||||
|
||||
@Override
|
||||
public boolean hasAmmo(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
return ammo.get(entity.liquids.current()) != null && entity.liquids.total() >= ammo.get(entity.liquids.current()).ammoMultiplier;
|
||||
}
|
||||
type.shootEffect.at(x + tr.x, y + tr.y, rotation, liquids.current().color);
|
||||
type.smokeEffect.at(x + tr.x, y + tr.y, rotation, liquids.current().color);
|
||||
shootSound.at(tile);
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return false;
|
||||
}
|
||||
if(shootShake > 0){
|
||||
Effects.shake(shootShake, shootShake, tile.entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
return ammo.get(liquid) != null
|
||||
&& (tile.entity.liquids.current() == liquid || (ammo.containsKey(tile.entity.liquids.current()) && tile.entity.liquids.get(tile.entity.liquids.current()) <= ammo.get(tile.entity.liquids.current()).ammoMultiplier + 0.001f));
|
||||
}
|
||||
recoil = recoilAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulletType useAmmo(){
|
||||
if(tile.isEnemyCheat()) return ammoTypes.get(liquids.current());
|
||||
BulletType type = ammoTypes.get(liquids.current());
|
||||
liquids.remove(liquids.current(), type.ammoMultiplier);
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulletType peekAmmo(){
|
||||
return ammoTypes.get(liquids.current());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAmmo(){
|
||||
return ammoTypes.get(liquids.current()) != null && liquids.total() >= ammoTypes.get(liquids.current()).ammoMultiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tilec source, Liquid liquid, float amount){
|
||||
return ammoTypes.get(liquid) != null
|
||||
&& (liquids.current() == liquid || (ammoTypes.containsKey(liquids.current())
|
||||
&& liquids.get(liquids.current()) <= ammoTypes.get(liquids.current()).ammoMultiplier + 0.001f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package mindustry.world.blocks.defense.turrets;
|
||||
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.entities.bullet.BulletType;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.BlockStat;
|
||||
import mindustry.world.meta.StatUnit;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class PowerTurret extends CooledTurret{
|
||||
public @NonNull BulletType shootType;
|
||||
@@ -28,25 +26,28 @@ public class PowerTurret extends CooledTurret{
|
||||
super.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulletType useAmmo(Tile tile){
|
||||
//nothing used directly
|
||||
return shootType;
|
||||
}
|
||||
public class PowerTurretEntity extends CooledTurretEntity{
|
||||
|
||||
@Override
|
||||
public boolean hasAmmo(Tile tile){
|
||||
//you can always rotate, but never shoot if there's no power
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public BulletType useAmmo(){
|
||||
//nothing used directly
|
||||
return shootType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulletType peekAmmo(Tile tile){
|
||||
return shootType;
|
||||
}
|
||||
@Override
|
||||
public boolean hasAmmo(){
|
||||
//you can always rotate, but never shoot if there's no power
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float baseReloadSpeed(Tile tile){
|
||||
return tile.isEnemyCheat() ? 1f : tile.entity.power.status;
|
||||
@Override
|
||||
public BulletType peekAmmo(){
|
||||
return shootType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float baseReloadSpeed(){
|
||||
return tile.isEnemyCheat() ? 1f : power.status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,21 @@
|
||||
package mindustry.world.blocks.defense.turrets;
|
||||
|
||||
import arc.Core;
|
||||
import arc.*;
|
||||
import arc.audio.*;
|
||||
import arc.struct.Array;
|
||||
import arc.struct.EnumSet;
|
||||
import arc.func.Cons2;
|
||||
import arc.graphics.Blending;
|
||||
import arc.graphics.Color;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.Angles;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.geom.Vec2;
|
||||
import arc.util.Time;
|
||||
import mindustry.content.Fx;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.Effect;
|
||||
import mindustry.entities.type.Bullet;
|
||||
import mindustry.entities.bullet.BulletType;
|
||||
import mindustry.entities.traits.TargetTrait;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
@@ -40,17 +33,18 @@ public abstract class Turret extends Block{
|
||||
public int ammoPerShot = 1;
|
||||
public float ammoEjectBack = 1f;
|
||||
public float range = 50f;
|
||||
public float reload = 10f;
|
||||
public float reloadTime = 10f;
|
||||
public float inaccuracy = 0f;
|
||||
public int shots = 1;
|
||||
public float spread = 4f;
|
||||
public float recoil = 1f;
|
||||
public float recoilAmount = 1f;
|
||||
public float restitution = 0.02f;
|
||||
public float cooldown = 0.02f;
|
||||
public float rotatespeed = 5f; //in degrees per tick
|
||||
public float shootCone = 8f;
|
||||
public float shootShake = 0f;
|
||||
public float xRand = 0f;
|
||||
public boolean alternate = false;
|
||||
public boolean targetAir = true;
|
||||
public boolean targetGround = true;
|
||||
|
||||
@@ -59,12 +53,12 @@ public abstract class Turret extends Block{
|
||||
|
||||
public TextureRegion baseRegion, heatRegion;
|
||||
|
||||
public Cons2<Tile, TurretEntity> drawer = (tile, entity) -> Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90);
|
||||
public Cons2<Tile, TurretEntity> heatDrawer = (tile, entity) -> {
|
||||
if(entity.heat <= 0.00001f) return;
|
||||
Draw.color(heatColor, entity.heat);
|
||||
public Cons<TurretEntity> drawer = tile -> Draw.rect(region, tile.x() + tr2.x, tile.y() + tr2.y, tile.rotation - 90);
|
||||
public Cons<TurretEntity> heatDrawer = tile -> {
|
||||
if(tile.heat <= 0.00001f) return;
|
||||
Draw.color(heatColor, tile.heat);
|
||||
Draw.blend(Blending.additive);
|
||||
Draw.rect(heatRegion, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90);
|
||||
Draw.rect(heatRegion, tile.x() + tr2.x, tile.y() + tr2.y, tile.rotation - 90);
|
||||
Draw.blend();
|
||||
Draw.color();
|
||||
};
|
||||
@@ -78,7 +72,6 @@ public abstract class Turret extends Block{
|
||||
group = BlockGroup.turrets;
|
||||
flags = EnumSet.of(BlockFlag.turret);
|
||||
outlineIcon = true;
|
||||
entityType = TurretEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,224 +94,228 @@ public abstract class Turret extends Block{
|
||||
|
||||
stats.add(BlockStat.shootRange, range / tilesize, StatUnit.blocks);
|
||||
stats.add(BlockStat.inaccuracy, (int)inaccuracy, StatUnit.degrees);
|
||||
stats.add(BlockStat.reload, 60f / reload, StatUnit.none);
|
||||
stats.add(BlockStat.reload, 60f / reloadTime, StatUnit.none);
|
||||
stats.add(BlockStat.shots, shots, StatUnit.none);
|
||||
stats.add(BlockStat.targetsAir, targetAir);
|
||||
stats.add(BlockStat.targetsGround, targetGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
Draw.rect(baseRegion, tile.drawx(), tile.drawy());
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
tr2.trns(entity.rotation, -entity.recoil);
|
||||
|
||||
drawer.get(tile, entity);
|
||||
|
||||
if(heatRegion != Core.atlas.find("error")){
|
||||
heatDrawer.get(tile, entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find("block-" + size), Core.atlas.find(name)};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
Drawf.dashCircle(tile.drawx(), tile.drawy(), range, tile.getTeam().color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||
Drawf.dashCircle(x * tilesize + offset(), y * tilesize + offset(), range, Pal.placing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
if(!validateTarget(tile)) entity.target = null;
|
||||
|
||||
entity.recoil = Mathf.lerpDelta(entity.recoil, 0f, restitution);
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, 0f, cooldown);
|
||||
|
||||
if(hasAmmo(tile)){
|
||||
|
||||
if(entity.timer.get(timerTarget, targetInterval)){
|
||||
findTarget(tile);
|
||||
}
|
||||
|
||||
if(validateTarget(tile)){
|
||||
|
||||
BulletType type = peekAmmo(tile);
|
||||
float speed = type.speed;
|
||||
if(speed < 0.1f) speed = 9999999f;
|
||||
|
||||
Vec2 result = Predict.intercept(entity, entity.target, speed);
|
||||
if(result.isZero()){
|
||||
result.set(entity.target.getX(), entity.target.getY());
|
||||
}
|
||||
|
||||
float targetRot = result.sub(tile.drawx(), tile.drawy()).angle();
|
||||
|
||||
if(Float.isNaN(entity.rotation)){
|
||||
entity.rotation = 0;
|
||||
}
|
||||
|
||||
if(shouldTurn(tile)){
|
||||
turnToTarget(tile, targetRot);
|
||||
}
|
||||
|
||||
if(Angles.angleDist(entity.rotation, targetRot) < shootCone){
|
||||
updateShooting(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean validateTarget(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
return !Units.invalidateTarget(entity.target, tile.getTeam(), tile.drawx(), tile.drawy());
|
||||
}
|
||||
|
||||
protected void findTarget(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
if(targetAir && !targetGround){
|
||||
entity.target = Units.closestEnemy(tile.getTeam(), tile.drawx(), tile.drawy(), range, e -> !e.isDead() && e.isFlying());
|
||||
}else{
|
||||
entity.target = Units.closestTarget(tile.getTeam(), tile.drawx(), tile.drawy(), range, e -> !e.isDead() && (!e.isFlying() || targetAir) && (e.isFlying() || targetGround));
|
||||
}
|
||||
}
|
||||
|
||||
protected void turnToTarget(Tile tile, float targetRot){
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
entity.rotation = Angles.moveToward(entity.rotation, targetRot, rotatespeed * entity.delta() * baseReloadSpeed(tile));
|
||||
}
|
||||
|
||||
public boolean shouldTurn(Tile tile){
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Consume ammo and return a type. */
|
||||
public BulletType useAmmo(Tile tile){
|
||||
if(tile.isEnemyCheat()) return peekAmmo(tile);
|
||||
|
||||
TurretEntity entity = tile.ent();
|
||||
AmmoEntry entry = entity.ammo.peek();
|
||||
entry.amount -= ammoPerShot;
|
||||
if(entry.amount == 0) entity.ammo.pop();
|
||||
entity.totalAmmo -= ammoPerShot;
|
||||
Time.run(reload / 2f, () -> ejectEffects(tile));
|
||||
return entry.type();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ammo type that will be returned if useAmmo is called.
|
||||
*/
|
||||
public BulletType peekAmmo(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
return entity.ammo.peek().type();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the turret has ammo.
|
||||
*/
|
||||
public boolean hasAmmo(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
return entity.ammo.size > 0 && entity.ammo.peek().amount >= ammoPerShot;
|
||||
}
|
||||
|
||||
protected void updateShooting(Tile tile){
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
if(entity.reload >= reload){
|
||||
BulletType type = peekAmmo(tile);
|
||||
|
||||
shoot(tile, type);
|
||||
|
||||
entity.reload = 0f;
|
||||
}else{
|
||||
entity.reload += tile.entity.delta() * peekAmmo(tile).reloadMultiplier * baseReloadSpeed(tile);
|
||||
}
|
||||
}
|
||||
|
||||
protected void shoot(Tile tile, BulletType type){
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
entity.recoil = recoil;
|
||||
entity.heat = 1f;
|
||||
|
||||
tr.trns(entity.rotation, size * tilesize / 2f, Mathf.range(xRand));
|
||||
|
||||
for(int i = 0; i < shots; i++){
|
||||
bullet(tile, type, entity.rotation + Mathf.range(inaccuracy + type.inaccuracy) + (i - shots / 2) * spread);
|
||||
}
|
||||
|
||||
effects(tile);
|
||||
useAmmo(tile);
|
||||
}
|
||||
|
||||
protected void bullet(Tile tile, BulletType type, float angle){
|
||||
Bullet.create(type, tile.entity, tile.getTeam(), tile.drawx() + tr.x, tile.drawy() + tr.y, angle);
|
||||
}
|
||||
|
||||
protected void effects(Tile tile){
|
||||
Effect shootEffect = this.shootEffect == Fx.none ? peekAmmo(tile).shootEffect : this.shootEffect;
|
||||
Effect smokeEffect = this.smokeEffect == Fx.none ? peekAmmo(tile).smokeEffect : this.smokeEffect;
|
||||
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
Effects.effect(shootEffect, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation);
|
||||
Effects.effect(smokeEffect, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation);
|
||||
shootSound.at(tile, Mathf.random(0.9f, 1.1f));
|
||||
|
||||
if(shootShake > 0){
|
||||
Effects.shake(shootShake, shootShake, tile.entity);
|
||||
}
|
||||
|
||||
entity.recoil = recoil;
|
||||
}
|
||||
|
||||
protected void ejectEffects(Tile tile){
|
||||
if(!isTurret(tile)) return;
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
Effects.effect(ammoUseEffect, tile.drawx() - Angles.trnsx(entity.rotation, ammoEjectBack),
|
||||
tile.drawy() - Angles.trnsy(entity.rotation, ammoEjectBack), entity.rotation);
|
||||
}
|
||||
|
||||
protected float baseReloadSpeed(Tile tile){
|
||||
return 1f;
|
||||
}
|
||||
|
||||
protected boolean isTurret(Tile tile){
|
||||
return (tile.entity instanceof TurretEntity);
|
||||
}
|
||||
|
||||
public static abstract class AmmoEntry{
|
||||
public int amount;
|
||||
|
||||
public abstract BulletType type();
|
||||
}
|
||||
|
||||
public static class TurretEntity extends TileEntity{
|
||||
public class TurretEntity extends TileEntity{
|
||||
public Array<AmmoEntry> ammo = new Array<>();
|
||||
public int totalAmmo;
|
||||
public float reload;
|
||||
public float rotation = 90;
|
||||
public float recoil = 0f;
|
||||
public float heat;
|
||||
public int shots;
|
||||
public TargetTrait target;
|
||||
public float reload, rotation = 90, recoil, heat;
|
||||
public int shotCounter;
|
||||
public Posc target;
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect(baseRegion, x, y);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(){
|
||||
tr2.trns(rotation, -recoil);
|
||||
|
||||
drawer.get(this);
|
||||
|
||||
if(heatRegion != Core.atlas.find("error")){
|
||||
heatDrawer.get(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(!validateTarget()) target = null;
|
||||
|
||||
recoil = Mathf.lerpDelta(recoil, 0f, restitution);
|
||||
heat = Mathf.lerpDelta(heat, 0f, cooldown);
|
||||
|
||||
if(hasAmmo()){
|
||||
|
||||
if(timer(timerTarget, targetInterval)){
|
||||
findTarget();
|
||||
}
|
||||
|
||||
if(validateTarget()){
|
||||
|
||||
BulletType type = peekAmmo();
|
||||
float speed = type.speed;
|
||||
if(speed < 0.1f) speed = 9999999f;
|
||||
|
||||
Vec2 result = Predict.intercept(this, target, speed);
|
||||
if(result.isZero()){
|
||||
result.set(target.getX(), target.getY());
|
||||
}
|
||||
|
||||
float targetRot = result.sub(x, y).angle();
|
||||
|
||||
if(Float.isNaN(rotation)){
|
||||
rotation = 0;
|
||||
}
|
||||
|
||||
if(shouldTurn()){
|
||||
turnToTarget(targetRot);
|
||||
}
|
||||
|
||||
if(Angles.angleDist(rotation, targetRot) < shootCone){
|
||||
updateShooting();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void drawSelect(){
|
||||
Drawf.dashCircle(x, y, range, team.color);
|
||||
}
|
||||
|
||||
protected boolean validateTarget(){
|
||||
return !Units.invalidateTarget(target, team, x, y);
|
||||
}
|
||||
|
||||
protected void findTarget(){
|
||||
if(targetAir && !targetGround){
|
||||
target = Units.closestEnemy(team, x, y, range, e -> !e.dead() && !e.isGrounded());
|
||||
}else{
|
||||
target = Units.closestTarget(team, x, y, range, e -> !e.dead() && (e.isGrounded() || targetAir) && (!e.isGrounded() || targetGround));
|
||||
}
|
||||
}
|
||||
|
||||
protected void turnToTarget(float targetRot){
|
||||
rotation = Angles.moveToward(rotation, targetRot, rotatespeed * delta() * baseReloadSpeed());
|
||||
}
|
||||
|
||||
public boolean shouldTurn(){
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Consume ammo and return a type. */
|
||||
public BulletType useAmmo(){
|
||||
if(tile.isEnemyCheat()) return peekAmmo();
|
||||
|
||||
AmmoEntry entry = ammo.peek();
|
||||
entry.amount -= ammoPerShot;
|
||||
if(entry.amount == 0) ammo.pop();
|
||||
totalAmmo -= ammoPerShot;
|
||||
Time.run(reloadTime / 2f, () -> ejectEffects());
|
||||
return entry.type();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ammo type that will be returned if useAmmo is called.
|
||||
*/
|
||||
public BulletType peekAmmo(){
|
||||
return ammo.peek().type();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the turret has ammo.
|
||||
*/
|
||||
public boolean hasAmmo(){
|
||||
return ammo.size > 0 && ammo.peek().amount >= ammoPerShot;
|
||||
}
|
||||
|
||||
protected void updateShooting(){
|
||||
if(reload >= reloadTime){
|
||||
BulletType type = peekAmmo();
|
||||
|
||||
shoot(type);
|
||||
|
||||
reload = 0f;
|
||||
}else{
|
||||
reload += delta() * peekAmmo().reloadMultiplier * baseReloadSpeed();
|
||||
}
|
||||
}
|
||||
|
||||
protected void shoot(BulletType type){
|
||||
recoil = recoilAmount;
|
||||
heat = 1f;
|
||||
|
||||
if(alternate){
|
||||
float i = (shotCounter % shots) - shots/2f + (((shots+1)%2) / 2f);
|
||||
|
||||
tr.trns(rotation - 90, spread * i + Mathf.range(xRand), size * tilesize / 2);
|
||||
bullet(type, rotation + Mathf.range(inaccuracy));
|
||||
}else{
|
||||
tr.trns(rotation, size * tilesize / 2f, Mathf.range(xRand));
|
||||
|
||||
for(int i = 0; i < shots; i++){
|
||||
bullet(type, rotation + Mathf.range(inaccuracy + type.inaccuracy) + (i - shots / 2f) * spread);
|
||||
}
|
||||
}
|
||||
|
||||
shotCounter++;
|
||||
|
||||
effects();
|
||||
useAmmo();
|
||||
}
|
||||
|
||||
protected void bullet(BulletType type, float angle){
|
||||
type.create(this, team, x + tr.x, y + tr.y, angle);
|
||||
}
|
||||
|
||||
protected void effects(){
|
||||
Effect fshootEffect = shootEffect == Fx.none ? peekAmmo().shootEffect : shootEffect;
|
||||
Effect fsmokeEffect = smokeEffect == Fx.none ? peekAmmo().smokeEffect : smokeEffect;
|
||||
|
||||
fshootEffect.at(x + tr.x, y + tr.y, rotation);
|
||||
fsmokeEffect.at(x + tr.x, y + tr.y, rotation);
|
||||
shootSound.at(tile, Mathf.random(0.9f, 1.1f));
|
||||
|
||||
if(shootShake > 0){
|
||||
Effects.shake(shootShake, shootShake, this);
|
||||
}
|
||||
|
||||
recoil = recoilAmount;
|
||||
}
|
||||
|
||||
protected void ejectEffects(){
|
||||
if(!isValid()) return;
|
||||
|
||||
ammoUseEffect.at(x - Angles.trnsx(rotation, ammoEjectBack), y - Angles.trnsy(rotation, ammoEjectBack), rotation);
|
||||
}
|
||||
|
||||
protected float baseReloadSpeed(){
|
||||
return 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.f(reload);
|
||||
write.f(rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
if(revision == 1){
|
||||
reload = read.f();
|
||||
rotation = read.f();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte version(){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
@@ -9,13 +10,15 @@ public class ArmoredConveyor extends Conveyor{
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return super.acceptItem(item, tile, source) && (source.block() instanceof Conveyor || Edges.getFacingEdge(source, tile).relativeTo(tile) == tile.rotation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock) {
|
||||
return otherblock.outputsItems() && blendsArmored(tile, rotation, otherx, othery, otherrot, otherblock);
|
||||
}
|
||||
|
||||
public class ArmoredConveyorEntity extends ConveyorEntity{
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return super.acceptItem(source, item) && (source.block() instanceof Conveyor || Edges.getFacingEdge(source.tile(), tile).relativeTo(tile) == tile.rotation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class BufferedItemBridge extends ExtendingItemBridge{
|
||||
public final int timerAccept = timers++;
|
||||
|
||||
@@ -16,40 +16,37 @@ public class BufferedItemBridge extends ExtendingItemBridge{
|
||||
super(name);
|
||||
hasPower = false;
|
||||
hasItems = true;
|
||||
entityType = BufferedItemBridgeEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTransport(Tile tile, Tile other){
|
||||
BufferedItemBridgeEntity entity = tile.ent();
|
||||
|
||||
if(entity.buffer.accepts() && entity.items.total() > 0){
|
||||
entity.buffer.accept(entity.items.take());
|
||||
}
|
||||
|
||||
Item item = entity.buffer.poll();
|
||||
if(entity.timer.get(timerAccept, 4) && item != null && other.block().acceptItem(item, other, tile)){
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 4f, 0.05f);
|
||||
other.block().handleItem(item, other, tile);
|
||||
entity.buffer.remove();
|
||||
}else{
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 0f, 0.008f);
|
||||
}
|
||||
}
|
||||
|
||||
class BufferedItemBridgeEntity extends ItemBridgeEntity{
|
||||
public class BufferedItemBridgeEntity extends ExtendingItemBridgeEntity{
|
||||
ItemBuffer buffer = new ItemBuffer(bufferCapacity, speed);
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
buffer.write(stream);
|
||||
public void updateTransport(Tilec other){
|
||||
if(buffer.accepts() && items.total() > 0){
|
||||
buffer.accept(items.take());
|
||||
}
|
||||
|
||||
Item item = buffer.poll();
|
||||
if(timer(timerAccept, 4) && item != null && other.acceptItem(this, item)){
|
||||
cycleSpeed = Mathf.lerpDelta(cycleSpeed, 4f, 0.05f);
|
||||
other.handleItem(this, item);
|
||||
buffer.remove();
|
||||
}else{
|
||||
cycleSpeed = Mathf.lerpDelta(cycleSpeed, 0f, 0.008f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
buffer.read(stream);
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
buffer.write(write);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
buffer.read(read);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
@@ -19,8 +19,6 @@ import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Conveyor extends Block implements Autotiler{
|
||||
@@ -43,7 +41,6 @@ public class Conveyor extends Block implements Autotiler{
|
||||
hasItems = true;
|
||||
itemCapacity = 4;
|
||||
conveyorPlacement = true;
|
||||
entityType = ConveyorEntity::new;
|
||||
|
||||
idleSound = Sounds.conveyor;
|
||||
idleSoundVolume = 0.004f;
|
||||
@@ -70,39 +67,6 @@ public class Conveyor extends Block implements Autotiler{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
ConveyorEntity entity = tile.ent();
|
||||
byte rotation = tile.rotation();
|
||||
|
||||
int frame = entity.clogHeat <= 0.5f ? (int)(((Time.time() * speed * 8f * entity.timeScale)) % 4) : 0;
|
||||
Draw.rect(regions[Mathf.clamp(entity.blendbits, 0, regions.length - 1)][Mathf.clamp(frame, 0, regions[0].length - 1)], tile.drawx(), tile.drawy(),
|
||||
tilesize * entity.blendsclx, tilesize * entity.blendscly, rotation * 90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(Tile tile){
|
||||
ConveyorEntity entity = tile.ent();
|
||||
return entity.clogHeat <= 0.5f ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(Tile tile){
|
||||
super.onProximityUpdate(tile);
|
||||
|
||||
ConveyorEntity entity = tile.ent();
|
||||
int[] bits = buildBlending(tile, tile.rotation(), null, true);
|
||||
entity.blendbits = bits[0];
|
||||
entity.blendsclx = bits[1];
|
||||
entity.blendscly = bits[2];
|
||||
|
||||
if(tile.front() != null && tile.front().entity != null){
|
||||
entity.next = tile.front().entity;
|
||||
entity.nextc = entity.next instanceof ConveyorEntity && entity.next.getTeam() == tile.getTeam() ? (ConveyorEntity)entity.next : null;
|
||||
entity.aligned = entity.nextc != null && tile.rotation() == entity.next.tile.rotation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRequestRegion(BuildRequest req, Eachable<BuildRequest> list){
|
||||
int[] bits = getTiling(req, list);
|
||||
@@ -123,99 +87,6 @@ public class Conveyor extends Block implements Autotiler{
|
||||
return new TextureRegion[]{Core.atlas.find(name + "-0-0")};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
ConveyorEntity e = tile.ent();
|
||||
byte rotation = tile.rotation();
|
||||
|
||||
for(int i = 0; i < e.len; i++){
|
||||
Item item = e.ids[i];
|
||||
tr1.trns(rotation * 90, tilesize, 0);
|
||||
tr2.trns(rotation * 90, -tilesize / 2f, e.xs[i] * tilesize / 2f);
|
||||
|
||||
Draw.rect(item.icon(Cicon.medium),
|
||||
(tile.x * tilesize + tr1.x * e.ys[i] + tr2.x),
|
||||
(tile.y * tilesize + tr1.y * e.ys[i] + tr2.y), itemSize, itemSize);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitOn(Tile tile, Unit unit){
|
||||
ConveyorEntity entity = tile.ent();
|
||||
|
||||
if(entity.clogHeat > 0.5f){
|
||||
return;
|
||||
}
|
||||
|
||||
entity.noSleep();
|
||||
|
||||
float speed = this.speed * tilesize / 2.4f;
|
||||
float centerSpeed = 0.1f;
|
||||
float centerDstScl = 3f;
|
||||
float tx = Geometry.d4[tile.rotation()].x, ty = Geometry.d4[tile.rotation()].y;
|
||||
|
||||
float centerx = 0f, centery = 0f;
|
||||
|
||||
if(Math.abs(tx) > Math.abs(ty)){
|
||||
centery = Mathf.clamp((tile.worldy() - unit.y) / centerDstScl, -centerSpeed, centerSpeed);
|
||||
if(Math.abs(tile.worldy() - unit.y) < 1f) centery = 0f;
|
||||
}else{
|
||||
centerx = Mathf.clamp((tile.worldx() - unit.x) / centerDstScl, -centerSpeed, centerSpeed);
|
||||
if(Math.abs(tile.worldx() - unit.x) < 1f) centerx = 0f;
|
||||
}
|
||||
|
||||
if(entity.len * itemSpace < 0.9f){
|
||||
unit.applyImpulse((tx * speed + centerx) * entity.delta(), (ty * speed + centery) * entity.delta());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ConveyorEntity e = tile.ent();
|
||||
e.minitem = 1f;
|
||||
e.mid = 0;
|
||||
|
||||
//skip updates if possible
|
||||
if(e.len == 0){
|
||||
e.clogHeat = 0f;
|
||||
e.sleep();
|
||||
return;
|
||||
}
|
||||
|
||||
float nextMax = e.aligned ? 1f - Math.max(itemSpace - e.nextc.minitem, 0) : 1f;
|
||||
|
||||
for(int i = e.len - 1; i >= 0; i--){
|
||||
float nextpos = (i == e.len - 1 ? 100f : e.ys[i + 1]) - itemSpace;
|
||||
float maxmove = Mathf.clamp(nextpos - e.ys[i], 0, speed * e.delta());
|
||||
|
||||
e.ys[i] += maxmove;
|
||||
|
||||
if(e.ys[i] > nextMax) e.ys[i] = nextMax;
|
||||
if(e.ys[i] > 0.5 && i > 0) e.mid = i - 1;
|
||||
e.xs[i] = Mathf.approachDelta(e.xs[i], 0, speed*2);
|
||||
|
||||
if(e.ys[i] >= 1f && offloadDir(tile, e.ids[i])){
|
||||
//align X position if passing forwards
|
||||
if(e.aligned){
|
||||
e.nextc.xs[e.nextc.lastInserted] = e.xs[i];
|
||||
}
|
||||
//remove last item
|
||||
e.items.remove(e.ids[i], e.len - i);
|
||||
e.len = Math.min(i, e.len);
|
||||
}else if(e.ys[i] < e.minitem){
|
||||
e.minitem = e.ys[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(e.minitem < itemSpace + (e.blendbits == 1 ? 0.3f : 0f)){
|
||||
e.clogHeat = Mathf.lerpDelta(e.clogHeat, 1f, 0.02f);
|
||||
}else{
|
||||
e.clogHeat = 0f;
|
||||
}
|
||||
|
||||
e.noSleep();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccessible(){
|
||||
return true;
|
||||
@@ -231,88 +102,7 @@ public class Conveyor extends Block implements Autotiler{
|
||||
Mathf.mod(req.tile().rotation() - req.rotation, 2) == 1 ? Blocks.junction : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeStack(Tile tile, Item item, int amount){
|
||||
ConveyorEntity e = tile.ent();
|
||||
e.noSleep();
|
||||
int removed = 0;
|
||||
|
||||
for(int j = 0; j < amount; j++){
|
||||
for(int i = 0; i < e.len; i++){
|
||||
if(e.ids[i] == item){
|
||||
e.remove(i);
|
||||
removed ++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e.items.remove(item, removed);
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getStackOffset(Item item, Tile tile, Vec2 trns){
|
||||
trns.trns(tile.rotation() * 90 + 180f, tilesize / 2f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||
ConveyorEntity entity = tile.ent();
|
||||
return Math.min((int)(entity.minitem / itemSpace), amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Tile tile, Unit source){
|
||||
ConveyorEntity e = tile.ent();
|
||||
amount = Math.min(amount, itemCapacity - e.len);
|
||||
|
||||
for(int i = amount - 1; i >= 0; i--){
|
||||
e.add(0);
|
||||
e.xs[0] = 0;
|
||||
e.ys[0] = i * itemSpace;
|
||||
e.ids[0] = item;
|
||||
e.items.add(item, 1);
|
||||
}
|
||||
|
||||
e.noSleep();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
ConveyorEntity e = tile.ent();
|
||||
if(e.len >= capacity) return false;
|
||||
int direction = source == null ? 0 : Math.abs(source.relativeTo(tile.x, tile.y) - tile.rotation());
|
||||
return (((direction == 0) && e.minitem >= itemSpace) || ((direction % 2 == 1) && e.minitem > 0.7f)) && (source == null || !(source.block().rotate && (source.rotation() + 2) % 4 == tile.rotation()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
ConveyorEntity e = tile.ent();
|
||||
if(e.len >= capacity) return;
|
||||
|
||||
byte r = tile.rotation();
|
||||
int ang = ((source.relativeTo(tile.x, tile.y) - r));
|
||||
float x = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0;
|
||||
|
||||
e.noSleep();
|
||||
e.items.add(item, 1);
|
||||
|
||||
if(Math.abs(source.relativeTo(tile.x, tile.y) - r) == 0){ //idx = 0
|
||||
e.add(0);
|
||||
e.xs[0] = x;
|
||||
e.ys[0] = 0;
|
||||
e.ids[0] = item;
|
||||
}else{ //idx = mid
|
||||
e.add(e.mid);
|
||||
e.xs[e.mid] = x;
|
||||
e.ys[e.mid] = 0.5f;
|
||||
e.ids[e.mid] = item;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConveyorEntity extends TileEntity{
|
||||
public class ConveyorEntity extends TileEntity{
|
||||
//parallel array data
|
||||
Item[] ids = new Item[capacity];
|
||||
float[] xs = new float[capacity];
|
||||
@@ -320,7 +110,7 @@ public class Conveyor extends Block implements Autotiler{
|
||||
//amount of items, always < capacity
|
||||
int len = 0;
|
||||
//next entity
|
||||
@Nullable TileEntity next;
|
||||
@Nullable Tilec next;
|
||||
@Nullable ConveyorEntity nextc;
|
||||
//whether the next conveyor's rotation == tile rotation
|
||||
boolean aligned;
|
||||
@@ -333,6 +123,231 @@ public class Conveyor extends Block implements Autotiler{
|
||||
|
||||
float clogHeat = 0f;
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
byte rotation = tile.rotation();
|
||||
int frame = clogHeat <= 0.5f ? (int)(((Time.time() * speed * 8f * timeScale())) % 4) : 0;
|
||||
Draw.rect(regions[Mathf.clamp(blendbits, 0, regions.length - 1)][Mathf.clamp(frame, 0, regions[0].length - 1)], x, y,
|
||||
tilesize * blendsclx, tilesize * blendscly, rotation * 90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(){
|
||||
return clogHeat <= 0.5f ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(){
|
||||
super.onProximityUpdate();
|
||||
|
||||
int[] bits = buildBlending(tile, rotation(), null, true);
|
||||
blendbits = bits[0];
|
||||
blendsclx = bits[1];
|
||||
blendscly = bits[2];
|
||||
|
||||
if(tile.front() != null && tile.front() != null){
|
||||
next = tile.front();
|
||||
nextc = next instanceof ConveyorEntity && next.team() == team ? (ConveyorEntity)next : null;
|
||||
aligned = nextc != null && tile.rotation() == next.tile().rotation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(){
|
||||
byte rotation = tile.rotation();
|
||||
|
||||
for(int i = 0; i < len; i++){
|
||||
Item item = ids[i];
|
||||
tr1.trns(rotation * 90, tilesize, 0);
|
||||
tr2.trns(rotation * 90, -tilesize / 2f, xs[i] * tilesize / 2f);
|
||||
|
||||
Draw.rect(item.icon(Cicon.medium),
|
||||
(tile.x * tilesize + tr1.x * ys[i] + tr2.x),
|
||||
(tile.y * tilesize + tr1.y * ys[i] + tr2.y), itemSize, itemSize);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitOn(Unitc unit){
|
||||
if(clogHeat > 0.5f){
|
||||
return;
|
||||
}
|
||||
|
||||
noSleep();
|
||||
|
||||
float mspeed = speed * tilesize / 2.4f;
|
||||
float centerSpeed = 0.1f;
|
||||
float centerDstScl = 3f;
|
||||
float tx = Geometry.d4[tile.rotation()].x, ty = Geometry.d4[tile.rotation()].y;
|
||||
|
||||
float centerx = 0f, centery = 0f;
|
||||
|
||||
if(Math.abs(tx) > Math.abs(ty)){
|
||||
centery = Mathf.clamp((y - unit.y()) / centerDstScl, -centerSpeed, centerSpeed);
|
||||
if(Math.abs(y - unit.y()) < 1f) centery = 0f;
|
||||
}else{
|
||||
centerx = Mathf.clamp((x - unit.x()) / centerDstScl, -centerSpeed, centerSpeed);
|
||||
if(Math.abs(x - unit.x()) < 1f) centerx = 0f;
|
||||
}
|
||||
|
||||
if(len * itemSpace < 0.9f){
|
||||
unit.impulse((tx * mspeed + centerx) * delta(), (ty * mspeed + centery) * delta());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
minitem = 1f;
|
||||
mid = 0;
|
||||
|
||||
//skip updates if possible
|
||||
if(len == 0){
|
||||
clogHeat = 0f;
|
||||
sleep();
|
||||
return;
|
||||
}
|
||||
|
||||
float nextMax = aligned ? 1f - Math.max(itemSpace - nextc.minitem, 0) : 1f;
|
||||
|
||||
for(int i = len - 1; i >= 0; i--){
|
||||
float nextpos = (i == len - 1 ? 100f : ys[i + 1]) - itemSpace;
|
||||
float maxmove = Mathf.clamp(nextpos - ys[i], 0, speed * delta());
|
||||
|
||||
ys[i] += maxmove;
|
||||
|
||||
if(ys[i] > nextMax) ys[i] = nextMax;
|
||||
if(ys[i] > 0.5 && i > 0) mid = i - 1;
|
||||
xs[i] = Mathf.approachDelta(xs[i], 0, speed*2);
|
||||
|
||||
if(ys[i] >= 1f && moveForward(ids[i])){
|
||||
//align X position if passing forwards
|
||||
if(aligned){
|
||||
nextc.xs[nextc.lastInserted] = xs[i];
|
||||
}
|
||||
//remove last item
|
||||
items.remove(ids[i], len - i);
|
||||
len = Math.min(i, len);
|
||||
}else if(ys[i] < minitem){
|
||||
minitem = ys[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(minitem < itemSpace + (blendbits == 1 ? 0.3f : 0f)){
|
||||
clogHeat = Mathf.lerpDelta(clogHeat, 1f, 0.02f);
|
||||
}else{
|
||||
clogHeat = 0f;
|
||||
}
|
||||
|
||||
noSleep();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeStack(Item item, int amount){
|
||||
noSleep();
|
||||
int removed = 0;
|
||||
|
||||
for(int j = 0; j < amount; j++){
|
||||
for(int i = 0; i < len; i++){
|
||||
if(ids[i] == item){
|
||||
remove(i);
|
||||
removed ++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
items.remove(item, removed);
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getStackOffset(Item item, Vec2 trns){
|
||||
trns.trns(tile.rotation() * 90 + 180f, tilesize / 2f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Teamc source){
|
||||
return Math.min((int)(minitem / itemSpace), amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Teamc source){
|
||||
amount = Math.min(amount, itemCapacity - len);
|
||||
|
||||
for(int i = amount - 1; i >= 0; i--){
|
||||
add(0);
|
||||
xs[0] = 0;
|
||||
ys[0] = i * itemSpace;
|
||||
ids[0] = item;
|
||||
items.add(item, 1);
|
||||
}
|
||||
|
||||
noSleep();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
if(len >= capacity) return false;
|
||||
Tile facing = Edges.getFacingEdge(source.tile(), tile);
|
||||
int direction = Math.abs(facing.relativeTo(tile.x, tile.y) - tile.rotation());
|
||||
return (((direction == 0) && minitem >= itemSpace) || ((direction % 2 == 1) && minitem > 0.7f)) && !(source.block().rotate && (source.rotation() + 2) % 4 == tile.rotation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Tilec source, Item item){
|
||||
if(len >= capacity) return;
|
||||
|
||||
byte r = tile.rotation();
|
||||
Tile facing = Edges.getFacingEdge(source.tile(), tile);
|
||||
int ang = ((facing.relativeTo(tile.x, tile.y) - r));
|
||||
float x = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0;
|
||||
|
||||
noSleep();
|
||||
items.add(item, 1);
|
||||
|
||||
if(Math.abs(facing.relativeTo(tile.x, tile.y) - r) == 0){ //idx = 0
|
||||
add(0);
|
||||
xs[0] = x;
|
||||
ys[0] = 0;
|
||||
ids[0] = item;
|
||||
}else{ //idx = mid
|
||||
add(mid);
|
||||
xs[mid] = x;
|
||||
ys[mid] = 0.5f;
|
||||
ids[mid] = item;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.i(len);
|
||||
|
||||
for(int i = 0; i < len; i++){
|
||||
write.i(Pack.intBytes((byte)ids[i].id, (byte)(xs[i] * 127), (byte)(ys[i] * 255 - 128), (byte)0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
int amount = read.i();
|
||||
len = Math.min(amount, capacity);
|
||||
|
||||
for(int i = 0; i < amount; i++){
|
||||
int val = read.i();
|
||||
byte id = (byte)(val >> 24);
|
||||
float x = (float)((byte)(val >> 16)) / 127f;
|
||||
float y = ((float)((byte)(val >> 8)) + 128f) / 255f;
|
||||
if(i < capacity){
|
||||
ids[i] = content.item(id);
|
||||
xs[i] = x;
|
||||
ys[i] = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final void add(int o){
|
||||
for(int i = Math.max(o + 1, len); i > o; i--){
|
||||
ids[i] = ids[i - 1];
|
||||
@@ -352,34 +367,5 @@ public class Conveyor extends Block implements Autotiler{
|
||||
|
||||
len--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeInt(len);
|
||||
|
||||
for(int i = 0; i < len; i++){
|
||||
stream.writeInt(Pack.intBytes((byte)ids[i].id, (byte)(xs[i] * 127), (byte)(ys[i] * 255 - 128), (byte)0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
int amount = stream.readInt();
|
||||
len = Math.min(amount, capacity);
|
||||
|
||||
for(int i = 0; i < amount; i++){
|
||||
int val = stream.readInt();
|
||||
byte id = (byte)(val >> 24);
|
||||
float x = (float)((byte)(val >> 16)) / 127f;
|
||||
float y = ((float)((byte)(val >> 8)) + 128f) / 255f;
|
||||
if(i < capacity){
|
||||
ids[i] = content.item(id);
|
||||
xs[i] = x;
|
||||
ys[i] = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@ import arc.func.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
@@ -17,8 +16,6 @@ import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class CraterConveyor extends Block implements Autotiler{
|
||||
@@ -65,44 +62,8 @@ public class CraterConveyor extends Block implements Autotiler{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
CraterConveyorEntity entity = tile.ent();
|
||||
|
||||
draw(tile, entity.blendbit1);
|
||||
if(entity.blendbit2 == 0) return;
|
||||
draw(tile, entity.blendbit2);
|
||||
}
|
||||
|
||||
private void draw(Tile tile, int bit){
|
||||
CraterConveyorEntity entity = tile.ent();
|
||||
|
||||
Draw.rect(regions[Mathf.clamp(bit, 0, regions.length - 1)], tile.drawx(), tile.drawy(), tilesize * entity.blendsclx, tilesize * entity.blendscly, tile.rotation() * 90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
CraterConveyorEntity entity = tile.ent();
|
||||
|
||||
if(entity.from == Pos.invalid) return;
|
||||
|
||||
// offset
|
||||
Tile from = world.tile(entity.from);
|
||||
Tmp.v1.set(from);
|
||||
Tmp.v2.set(tile);
|
||||
Tmp.v1.interpolate(Tmp.v2, 1f - entity.cooldown, Interpolation.linear);
|
||||
|
||||
// fixme
|
||||
float a = (from.rotation()%4) * 90;
|
||||
float b = (tile.rotation()%4) * 90;
|
||||
if((from.rotation()%4) == 3 && (tile.rotation()%4) == 0) a = -1 * 90;
|
||||
if((from.rotation()%4) == 0 && (tile.rotation()%4) == 3) a = 4 * 90;
|
||||
|
||||
// crater
|
||||
Draw.rect(regions[7], Tmp.v1.x, Tmp.v1.y, Mathf.lerp(a, b, Interpolation.smooth.apply(1f - Mathf.clamp(entity.cooldown * 2, 0f, 1f))));
|
||||
|
||||
// item
|
||||
float size = (itemSize / 2f) + entity.items.total() * 0.1f / (itemCapacity / 8f);
|
||||
Draw.rect(entity.items.first().icon(Cicon.medium), Tmp.v1.x, Tmp.v1.y, size, size, 0);
|
||||
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock) {
|
||||
return otherblock.outputsItems() && blendsArmored(tile, rotation, otherx, othery, otherrot, otherblock) && otherblock instanceof CraterConveyor; // blend with nothing but crater conveyors
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,179 +76,206 @@ public class CraterConveyor extends Block implements Autotiler{
|
||||
Draw.rect(region, req.drawx(), req.drawy(), region.getWidth() * bits[1] * Draw.scl * req.animScale, region.getHeight() * bits[2] * Draw.scl * req.animScale, req.rotation * 90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock) {
|
||||
return otherblock.outputsItems() && blendsArmored(tile, rotation, otherx, othery, otherrot, otherblock) && otherblock instanceof CraterConveyor; // blend with nothing but crater conveyors
|
||||
}
|
||||
class CraterConveyorEntity extends TileEntity{
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(Tile tile){
|
||||
super.onProximityUpdate(tile);
|
||||
int blendbit1, blendbit2;
|
||||
int blendsclx, blendscly;
|
||||
|
||||
CraterConveyorEntity entity = tile.ent();
|
||||
int[] bits = buildBlending(tile, tile.rotation(), null, true);
|
||||
int link = -1;
|
||||
float cooldown;
|
||||
|
||||
entity.blendbit2 = 0;
|
||||
if(bits[0] == 0 && blends(tile, tile.rotation(), 0) && !blends(tile, tile.rotation(), 2)) entity.blendbit2 = 5; // a 0 that faces into a crater conveyor with none behind it
|
||||
if(bits[0] == 0 && !blends(tile, tile.rotation(), 0) && blends(tile, tile.rotation(), 2)) entity.blendbit2 = 6; // a 0 that faces into none with a crater conveyor behind it
|
||||
|
||||
entity.blendbit1 = bits[0];
|
||||
entity.blendsclx = bits[1];
|
||||
entity.blendscly = bits[2];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
CraterConveyorEntity entity = tile.ent();
|
||||
|
||||
// reel in crater
|
||||
if(entity.cooldown > 0f) entity.cooldown = Mathf.clamp(entity.cooldown - speed, 0f, 1f);
|
||||
|
||||
// sleep when idle
|
||||
if(entity.from == Pos.invalid){
|
||||
if(entity.cooldown == 0f) tile.entity.sleep();
|
||||
return;
|
||||
@Override
|
||||
public void draw(){
|
||||
draw(blendbit1);
|
||||
if(blendbit2 == 0) return;
|
||||
draw(blendbit2);
|
||||
}
|
||||
|
||||
// crater needs to be centered
|
||||
if(entity.cooldown > 0f) return;
|
||||
|
||||
if(entity.blendbit2 == 6){
|
||||
while(tryDump(tile)) if(entity.items.total() == 0) poofOut(tile);
|
||||
private void draw(int bit){
|
||||
Draw.rect(regions[Mathf.clamp(bit, 0, regions.length - 1)], x, y, tilesize * blendsclx, tilesize * blendscly, rotation() * 90);
|
||||
}
|
||||
|
||||
/* unload */ else /* transfer */
|
||||
@Override
|
||||
public void onProximityUpdate(){
|
||||
super.onProximityUpdate();
|
||||
|
||||
if(entity.blendbit2 != 5 || (entity.items.total() >= getMaximumAccepted(tile, entity.items.first()))){
|
||||
if(tile.front() != null
|
||||
&& tile.front().getTeam() == tile.getTeam()
|
||||
&& tile.front().block() instanceof CraterConveyor){
|
||||
CraterConveyorEntity e = tile.front().ent();
|
||||
int[] bits = buildBlending(tile, tile.rotation(), null, true);
|
||||
|
||||
// sleep if its occupied
|
||||
if(e.from != Pos.invalid){
|
||||
entity.sleep();
|
||||
}else{
|
||||
e.items.addAll(entity.items);
|
||||
e.from = tile.pos();
|
||||
// ▲ new | old ▼
|
||||
entity.from = Pos.invalid;
|
||||
entity.items.clear();
|
||||
blendbit2 = 0;
|
||||
if(bits[0] == 0 && blends(tile, tile.rotation(), 0) && !blends(tile, tile.rotation(), 2)) blendbit2 = 5; // a 0 that faces into a crater conveyor with none behind it
|
||||
if(bits[0] == 0 && !blends(tile, tile.rotation(), 0) && blends(tile, tile.rotation(), 2)) blendbit2 = 6; // a 0 that faces into none with a crater conveyor behind it
|
||||
|
||||
e.cooldown = entity.cooldown = 1;
|
||||
e.noSleep();
|
||||
bump(tile);
|
||||
blendbit1 = bits[0];
|
||||
blendsclx = bits[1];
|
||||
blendscly = bits[2];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(){
|
||||
if(link == -1) return;
|
||||
|
||||
// offset
|
||||
Tile from = world.tile(link);
|
||||
Tmp.v1.set(from);
|
||||
Tmp.v2.set(tile);
|
||||
Tmp.v1.interpolate(Tmp.v2, 1f - cooldown, Interpolation.linear);
|
||||
|
||||
// fixme
|
||||
float a = (from.rotation()%4) * 90;
|
||||
float b = (tile.rotation()%4) * 90;
|
||||
if((from.rotation()%4) == 3 && (tile.rotation()%4) == 0) a = -1 * 90;
|
||||
if((from.rotation()%4) == 0 && (tile.rotation()%4) == 3) a = 4 * 90;
|
||||
|
||||
// crater
|
||||
Draw.rect(regions[7], Tmp.v1.x, Tmp.v1.y, Mathf.lerp(a, b, Interpolation.smooth.apply(1f - Mathf.clamp(cooldown * 2, 0f, 1f))));
|
||||
|
||||
// item
|
||||
float size = (itemSize / 2f) + items.total() * 0.1f / (itemCapacity / 8f);
|
||||
Draw.rect(items.first().icon(Cicon.medium), Tmp.v1.x, Tmp.v1.y, size, size, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAccepted(Item item){
|
||||
return Mathf.round(super.getMaximumAccepted(item) * timeScale); // increased item capacity while boosted
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(){
|
||||
return false; // has no moving parts;
|
||||
}
|
||||
|
||||
private void poofIn(){
|
||||
link = tile.pos();
|
||||
Fx.plasticburn.at(this);
|
||||
tile.entity.noSleep();
|
||||
}
|
||||
|
||||
private void poofOut(){
|
||||
Fx.plasticburn.at(this);
|
||||
link = -1;
|
||||
bump(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Tilec source, Item item){
|
||||
if(items.total() == 0) poofIn();
|
||||
super.handleItem(source, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Teamc source){
|
||||
if(items.total() == 0) poofIn();
|
||||
super.handleStack(item, amount, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeStack(Item item, int amount){
|
||||
try{
|
||||
return super.removeStack(item, amount);
|
||||
}finally{
|
||||
if(items.total() == 0) poofOut();
|
||||
}
|
||||
}
|
||||
|
||||
// crater conveyor tiles that input into this one
|
||||
private void upstream(Tilec tile, Cons<Tilec> cons){
|
||||
CraterConveyorEntity entity = (CraterConveyorEntity)tile;
|
||||
|
||||
if( entity.blendbit1 == 0 // 1 input from the back, 0 from the sides
|
||||
|| entity.blendbit1 == 2 // 1 input from the back, 1 from the sides
|
||||
|| entity.blendbit1 == 3 // 1 input from the back, 2 from the sides
|
||||
) cons.get(back()); // fixme, fires for 0 while nothing behind
|
||||
|
||||
if( entity.blendbit1 == 3 // 1 input from the back, 2 from the sides
|
||||
|| entity.blendbit1 == 4 // 0 input from the back, 2 from the sides
|
||||
||(entity.blendbit1 == 1 && entity.blendscly == -1) // side is open
|
||||
||(entity.blendbit1 == 2 && entity.blendscly == +1) // side is open
|
||||
) cons.get(right());
|
||||
|
||||
if( entity.blendbit1 == 3 // 1 input from the back, 2 from the sides
|
||||
|| entity.blendbit1 == 4 // 0 input from the back, 2 from the sides
|
||||
||(entity.blendbit1 == 1 && entity.blendscly == +1) // side is open
|
||||
||(entity.blendbit1 == 2 && entity.blendscly == -1) // side is open
|
||||
) cons.get(left());
|
||||
}
|
||||
|
||||
// awaken inputting conveyors
|
||||
private void bump(Tilec tile){
|
||||
upstream(tile, t -> {
|
||||
if(t == null || !t.isSleeping() || t.items().total() <= 0) return;
|
||||
t.noSleep();
|
||||
bump(t);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
if (this == source) return true; // player threw items
|
||||
if (cooldown > 0f) return false; // still cooling down
|
||||
return!((blendbit2 != 5) // not a loading dock
|
||||
|| (items.total() > 0 && !items.has(item)) // incompatible items
|
||||
|| (items.total() >= getMaximumAccepted(item)) // filled to capacity
|
||||
|| (tile.front() == source));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
|
||||
write.i(link);
|
||||
write.f(cooldown);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
|
||||
link = read.i();
|
||||
cooldown = read.f();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
// reel in crater
|
||||
if(cooldown > 0f) cooldown = Mathf.clamp(cooldown - speed, 0f, 1f);
|
||||
|
||||
// sleep when idle
|
||||
if(link == -1){
|
||||
if(cooldown == 0f) sleep();
|
||||
return;
|
||||
}
|
||||
|
||||
// crater needs to be centered
|
||||
if(cooldown > 0f) return;
|
||||
|
||||
if(blendbit2 == 6){
|
||||
while(dump()) if(items.total() == 0) poofOut();
|
||||
}
|
||||
|
||||
/* unload */ else /* transfer */
|
||||
|
||||
if(blendbit2 != 5 || (items.total() >= getMaximumAccepted(items.first()))){
|
||||
if(front() != null
|
||||
&& front().team() == team()
|
||||
&& front().block() instanceof CraterConveyor){
|
||||
CraterConveyorEntity e = (CraterConveyorEntity)tile.front();
|
||||
|
||||
// sleep if its occupied
|
||||
if(e.link != -1){
|
||||
sleep();
|
||||
}else{
|
||||
e.items.addAll(items);
|
||||
e.link = tile.pos();
|
||||
// ▲ new | old ▼
|
||||
link = -1;
|
||||
items.clear();
|
||||
|
||||
e.cooldown = cooldown = 1;
|
||||
e.noSleep();
|
||||
bump(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void poofIn(Tile tile){
|
||||
tile.<CraterConveyorEntity>ent().from = tile.pos();
|
||||
Effects.effect(Fx.plasticburn, tile.drawx(), tile.drawy());
|
||||
tile.entity.noSleep();
|
||||
}
|
||||
|
||||
private void poofOut(Tile tile){
|
||||
Effects.effect(Fx.plasticburn, tile.drawx(), tile.drawy());
|
||||
tile.<CraterConveyorEntity>ent().from = Pos.invalid;
|
||||
bump(tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
if(tile.entity.items.total() == 0) poofIn(tile);
|
||||
super.handleItem(item, tile, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Tile tile, Unit source){
|
||||
if(tile.entity.items.total() == 0) poofIn(tile);
|
||||
super.handleStack(item, amount, tile, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeStack(Tile tile, Item item, int amount){
|
||||
try{return super.removeStack(tile, item, amount);
|
||||
}finally{
|
||||
if(tile.entity.items.total() == 0) poofOut(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAccepted(Tile tile, Item item){
|
||||
return Mathf.round(super.getMaximumAccepted(tile, item) * tile.entity.timeScale); // increased item capacity while boosted
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(Tile tile){
|
||||
return false; // has no moving parts
|
||||
}
|
||||
|
||||
class CraterConveyorEntity extends TileEntity{
|
||||
int blendbit1, blendbit2;
|
||||
int blendsclx, blendscly;
|
||||
|
||||
int from = Pos.invalid;
|
||||
float cooldown;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
|
||||
stream.writeInt(from);
|
||||
stream.writeFloat(cooldown);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
|
||||
from = stream.readInt();
|
||||
cooldown = stream.readFloat();
|
||||
}
|
||||
}
|
||||
|
||||
// crater conveyor tiles that input into this one
|
||||
private void upstream(Tile tile, Cons<Tile> cons){
|
||||
CraterConveyorEntity entity = tile.ent();
|
||||
|
||||
if( entity.blendbit1 == 0 // 1 input from the back, 0 from the sides
|
||||
|| entity.blendbit1 == 2 // 1 input from the back, 1 from the sides
|
||||
|| entity.blendbit1 == 3 // 1 input from the back, 2 from the sides
|
||||
) cons.get(tile.back()); // fixme, fires for 0 while nothing behind
|
||||
|
||||
if( entity.blendbit1 == 3 // 1 input from the back, 2 from the sides
|
||||
|| entity.blendbit1 == 4 // 0 input from the back, 2 from the sides
|
||||
||(entity.blendbit1 == 1 && entity.blendscly == -1) // side is open
|
||||
||(entity.blendbit1 == 2 && entity.blendscly == +1) // side is open
|
||||
) cons.get(tile.right());
|
||||
|
||||
if( entity.blendbit1 == 3 // 1 input from the back, 2 from the sides
|
||||
|| entity.blendbit1 == 4 // 0 input from the back, 2 from the sides
|
||||
||(entity.blendbit1 == 1 && entity.blendscly == +1) // side is open
|
||||
||(entity.blendbit1 == 2 && entity.blendscly == -1) // side is open
|
||||
) cons.get(tile.left());
|
||||
}
|
||||
|
||||
// awaken inputting conveyors
|
||||
private void bump(Tile tile){
|
||||
upstream(tile, t -> {
|
||||
if(t == null || t.entity == null || !t.entity.isSleeping() || t.entity.items.total() <= 0) return;
|
||||
t.entity.noSleep();
|
||||
bump(t);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
CraterConveyorEntity entity = tile.ent();
|
||||
|
||||
if (tile == source) return true; // player threw items
|
||||
if (entity.cooldown > 0f) return false; // still cooling down
|
||||
return!((entity.blendbit2 != 5) // not a loading dock
|
||||
|| (entity.items.total() > 0 && !entity.items.has(item)) // incompatible items
|
||||
|| (entity.items.total() >= getMaximumAccepted(tile, item)) // filled to capacity
|
||||
|| (tile.front() == source)); // fed from the front
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,52 +14,52 @@ public class ExtendingItemBridge extends ItemBridge{
|
||||
super(name);
|
||||
hasItems = true;
|
||||
}
|
||||
|
||||
public class ExtendingItemBridgeEntity extends ItemBridgeEntity{
|
||||
@Override
|
||||
public void drawLayer(){
|
||||
Tile other = world.tile(link);
|
||||
if(!linkValid(tile, other)) return;
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
int i = tile.absoluteRelativeTo(other.x, other.y);
|
||||
|
||||
Tile other = world.tile(entity.link);
|
||||
if(!linkValid(tile, other)) return;
|
||||
float ex = other.worldx() - x - Geometry.d4[i].x * tilesize / 2f,
|
||||
ey = other.worldy() - y - Geometry.d4[i].y * tilesize / 2f;
|
||||
|
||||
int i = tile.absoluteRelativeTo(other.x, other.y);
|
||||
float uptime = state.isEditor() ? 1f : this.uptime;
|
||||
|
||||
float ex = other.worldx() - tile.worldx() - Geometry.d4[i].x * tilesize / 2f,
|
||||
ey = other.worldy() - tile.worldy() - Geometry.d4[i].y * tilesize / 2f;
|
||||
ex *= uptime;
|
||||
ey *= uptime;
|
||||
|
||||
float uptime = state.isEditor() ? 1f : entity.uptime;
|
||||
float opacity = Core.settings.getInt("bridgeopacity") / 100f;
|
||||
if(Mathf.zero(opacity)) return;
|
||||
Draw.alpha(opacity);
|
||||
|
||||
ex *= uptime;
|
||||
ey *= uptime;
|
||||
Lines.stroke(8f);
|
||||
Lines.line(bridgeRegion,
|
||||
x + Geometry.d4[i].x * tilesize / 2f,
|
||||
y + Geometry.d4[i].y * tilesize / 2f,
|
||||
x + ex,
|
||||
y + ey, CapStyle.none, 0f);
|
||||
|
||||
float opacity = Core.settings.getInt("bridgeopacity") / 100f;
|
||||
if(Mathf.zero(opacity)) return;
|
||||
Draw.alpha(opacity);
|
||||
Draw.rect(endRegion, x, y, i * 90 + 90);
|
||||
Draw.rect(endRegion,
|
||||
x + ex + Geometry.d4[i].x * tilesize / 2f,
|
||||
y + ey + Geometry.d4[i].y * tilesize / 2f, i * 90 + 270);
|
||||
|
||||
Lines.stroke(8f);
|
||||
Lines.line(bridgeRegion,
|
||||
tile.worldx() + Geometry.d4[i].x * tilesize / 2f,
|
||||
tile.worldy() + Geometry.d4[i].y * tilesize / 2f,
|
||||
tile.worldx() + ex,
|
||||
tile.worldy() + ey, CapStyle.none, 0f);
|
||||
int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y));
|
||||
|
||||
Draw.rect(endRegion, tile.drawx(), tile.drawy(), i * 90 + 90);
|
||||
Draw.rect(endRegion,
|
||||
tile.worldx() + ex + Geometry.d4[i].x * tilesize / 2f,
|
||||
tile.worldy() + ey + Geometry.d4[i].y * tilesize / 2f, i * 90 + 270);
|
||||
int arrows = (dist) * tilesize / 6 - 1;
|
||||
|
||||
int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y));
|
||||
Draw.color();
|
||||
|
||||
int arrows = (dist) * tilesize / 6 - 1;
|
||||
|
||||
Draw.color();
|
||||
|
||||
for(int a = 0; a < arrows; a++){
|
||||
Draw.alpha(Mathf.absin(a / (float)arrows - entity.time / 100f, 0.1f, 1f) * uptime * opacity);
|
||||
Draw.rect(arrowRegion,
|
||||
tile.worldx() + Geometry.d4[i].x * (tilesize / 2f + a * 6f + 2) * uptime,
|
||||
tile.worldy() + Geometry.d4[i].y * (tilesize / 2f + a * 6f + 2) * uptime, i * 90f);
|
||||
for(int a = 0; a < arrows; a++){
|
||||
Draw.alpha(Mathf.absin(a / (float)arrows - time / 100f, 0.1f, 1f) * uptime * opacity);
|
||||
Draw.rect(arrowRegion,
|
||||
x + Geometry.d4[i].x * (tilesize / 2f + a * 6f + 2) * uptime,
|
||||
y + Geometry.d4[i].y * (tilesize / 2f + a * 6f + 2) * uptime, i * 90f);
|
||||
}
|
||||
Draw.reset();
|
||||
}
|
||||
Draw.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.struct.IntSet.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.struct.IntSet.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class ItemBridge extends Block{
|
||||
@@ -26,7 +25,7 @@ public class ItemBridge extends Block{
|
||||
public TextureRegion endRegion, bridgeRegion, arrowRegion;
|
||||
|
||||
private static BuildRequest otherReq;
|
||||
private static int lastPlaced = Pos.invalid;
|
||||
private static int lastPlaced = -1;
|
||||
|
||||
public ItemBridge(String name){
|
||||
super(name);
|
||||
@@ -36,17 +35,14 @@ public class ItemBridge extends Block{
|
||||
layer = Layer.power;
|
||||
expanded = true;
|
||||
itemCapacity = 10;
|
||||
posConfig = true;
|
||||
configurable = true;
|
||||
hasItems = true;
|
||||
unloadable = false;
|
||||
group = BlockGroup.transportation;
|
||||
entityType = ItemBridgeEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configured(Tile tile, Player player, int value){
|
||||
tile.<ItemBridgeEntity>ent().link = value;
|
||||
//point2 config is relative
|
||||
config(Point2.class, (tile, i) -> ((ItemBridgeEntity)tile).link = Point2.pack(i.x + tile.tileX(), i.y + tile.tileY()));
|
||||
//integer is not
|
||||
config(Integer.class, (tile, i) -> ((ItemBridgeEntity)tile).link = i);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,7 +58,7 @@ public class ItemBridge extends Block{
|
||||
public void drawRequestConfigTop(BuildRequest req, Eachable<BuildRequest> list){
|
||||
otherReq = null;
|
||||
list.each(other -> {
|
||||
if(other.block == this && req.config == Pos.get(other.x, other.y)){
|
||||
if(other.block == this && req != other && req.config instanceof Point2 && ((Point2)req.config).equals(other.x - req.x, other.y - req.y)){
|
||||
otherReq = other;
|
||||
}
|
||||
});
|
||||
@@ -79,23 +75,6 @@ public class ItemBridge extends Block{
|
||||
Angles.angle(req.drawx(), req.drawy(), otherReq.drawx(), otherReq.drawy()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerPlaced(Tile tile){
|
||||
Tile link = findLink(tile.x, tile.y);
|
||||
if(linkValid(tile, link)){
|
||||
link.configure(tile.pos());
|
||||
}
|
||||
|
||||
lastPlaced = tile.pos();
|
||||
}
|
||||
|
||||
public Tile findLink(int x, int y){
|
||||
if(world.tile(x, y) != null && linkValid(world.tile(x, y), world.tile(lastPlaced)) && lastPlaced != Pos.get(x, y)){
|
||||
return world.tile(lastPlaced);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||
Tile link = findLink(x, y);
|
||||
@@ -124,226 +103,6 @@ public class ItemBridge extends Block{
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawConfigure(Tile tile){
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
|
||||
Draw.color(Pal.accent);
|
||||
Lines.stroke(1f);
|
||||
Lines.square(tile.drawx(), tile.drawy(),
|
||||
tile.block().size * tilesize / 2f + 1f);
|
||||
|
||||
for(int i = 1; i <= range; i++){
|
||||
for(int j = 0; j < 4; j++){
|
||||
Tile other = tile.getNearby(Geometry.d4[j].x * i, Geometry.d4[j].y * i);
|
||||
if(linkValid(tile, other)){
|
||||
boolean linked = other.pos() == entity.link;
|
||||
Draw.color(linked ? Pal.place : Pal.breakInvalid);
|
||||
|
||||
Lines.square(other.drawx(), other.drawy(),
|
||||
other.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Time.time(), 4f, 1f)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConfigureTileTapped(Tile tile, Tile other){
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
|
||||
if(linkValid(tile, other)){
|
||||
if(entity.link == other.pos()){
|
||||
tile.configure(Pos.invalid);
|
||||
}else{
|
||||
tile.configure(other.pos());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
|
||||
entity.time += entity.cycleSpeed * entity.delta();
|
||||
entity.time2 += (entity.cycleSpeed - 1f) * entity.delta();
|
||||
|
||||
IntSetIterator it = entity.incoming.iterator();
|
||||
while(it.hasNext){
|
||||
int i = it.next();
|
||||
Tile other = world.tile(i);
|
||||
if(!linkValid(tile, other, false) || other.<ItemBridgeEntity>ent().link != tile.pos()){
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
Tile other = world.tile(entity.link);
|
||||
if(!linkValid(tile, other)){
|
||||
tryDump(tile);
|
||||
entity.uptime = 0f;
|
||||
}else{
|
||||
((ItemBridgeEntity)world.tile(entity.link).entity).incoming.add(tile.pos());
|
||||
|
||||
if(entity.cons.valid() && Mathf.zero(1f - entity.efficiency())){
|
||||
entity.uptime = Mathf.lerpDelta(entity.uptime, 1f, 0.04f);
|
||||
}else{
|
||||
entity.uptime = Mathf.lerpDelta(entity.uptime, 0f, 0.02f);
|
||||
}
|
||||
|
||||
updateTransport(tile, other);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTransport(Tile tile, Tile other){
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
|
||||
if(entity.uptime >= 0.5f && entity.timer.get(timerTransport, transportTime)){
|
||||
Item item = entity.items.take();
|
||||
if(item != null && other.block().acceptItem(item, other, tile)){
|
||||
other.block().handleItem(item, other, tile);
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 4f, 0.05f);
|
||||
}else{
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 1f, 0.01f);
|
||||
if(item != null) entity.items.add(item, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
|
||||
Tile other = world.tile(entity.link);
|
||||
if(!linkValid(tile, other)) return;
|
||||
|
||||
float opacity = Core.settings.getInt("bridgeopacity") / 100f;
|
||||
if(Mathf.zero(opacity)) return;
|
||||
|
||||
int i = tile.absoluteRelativeTo(other.x, other.y);
|
||||
|
||||
Draw.color(Color.white, Color.black, Mathf.absin(Time.time(), 6f, 0.07f));
|
||||
Draw.alpha(Math.max(entity.uptime, 0.25f) * opacity);
|
||||
|
||||
Draw.rect(endRegion, tile.drawx(), tile.drawy(), i * 90 + 90);
|
||||
Draw.rect(endRegion, other.drawx(), other.drawy(), i * 90 + 270);
|
||||
|
||||
Lines.stroke(8f);
|
||||
Lines.line(bridgeRegion,
|
||||
tile.worldx(),
|
||||
tile.worldy(),
|
||||
other.worldx(),
|
||||
other.worldy(), CapStyle.none, -tilesize / 2f);
|
||||
|
||||
int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y));
|
||||
|
||||
float time = entity.time2 / 1.7f;
|
||||
int arrows = (dist) * tilesize / 4 - 2;
|
||||
|
||||
Draw.color();
|
||||
|
||||
for(int a = 0; a < arrows; a++){
|
||||
Draw.alpha(Mathf.absin(a / (float)arrows - entity.time / 100f, 0.1f, 1f) * entity.uptime * opacity);
|
||||
Draw.rect(arrowRegion,
|
||||
tile.worldx() + Geometry.d4[i].x * (tilesize / 2f + a * 4f + time % 4f),
|
||||
tile.worldy() + Geometry.d4[i].y * (tilesize / 2f + a * 4f + time % 4f), i * 90f);
|
||||
}
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
if(tile.getTeam() != source.getTeam()) return false;
|
||||
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
Tile other = world.tile(entity.link);
|
||||
|
||||
if(linkValid(tile, other)){
|
||||
int rel = tile.absoluteRelativeTo(other.x, other.y);
|
||||
int rel2 = tile.relativeTo(source.x, source.y);
|
||||
|
||||
if(rel == rel2) return false;
|
||||
}else{
|
||||
return source.block() instanceof ItemBridge && source.<ItemBridgeEntity>ent().link == tile.pos() && tile.entity.items.total() < itemCapacity;
|
||||
}
|
||||
|
||||
return tile.entity.items.total() < itemCapacity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canDumpLiquid(Tile tile, Tile to, Liquid liquid){
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
|
||||
Tile other = world.tile(entity.link);
|
||||
if(!linkValid(tile, other)){
|
||||
Tile edge = Edges.getFacingEdge(to, tile);
|
||||
int i = tile.absoluteRelativeTo(edge.x, edge.y);
|
||||
|
||||
IntSetIterator it = entity.incoming.iterator();
|
||||
|
||||
while(it.hasNext){
|
||||
int v = it.next();
|
||||
if(tile.absoluteRelativeTo(Pos.x(v), Pos.y(v)) == i){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int rel = tile.absoluteRelativeTo(other.x, other.y);
|
||||
int rel2 = tile.relativeTo(to.x, to.y);
|
||||
|
||||
return rel != rel2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
if(tile.getTeam() != source.getTeam() || !hasLiquids) return false;
|
||||
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
Tile other = world.tile(entity.link);
|
||||
|
||||
if(linkValid(tile, other)){
|
||||
int rel = tile.absoluteRelativeTo(other.x, other.y);
|
||||
int rel2 = tile.relativeTo(source.x, source.y);
|
||||
|
||||
if(rel == rel2) return false;
|
||||
}else if(!(source.block() instanceof ItemBridge && source.<ItemBridgeEntity>ent().link == tile.pos())){
|
||||
return false;
|
||||
}
|
||||
|
||||
return tile.entity.liquids.get(liquid) + amount < liquidCapacity && (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.2f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDump(Tile tile, Tile to, Item item){
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
|
||||
Tile other = world.tile(entity.link);
|
||||
if(!linkValid(tile, other)){
|
||||
Tile edge = Edges.getFacingEdge(to, tile);
|
||||
int i = tile.absoluteRelativeTo(edge.x, edge.y);
|
||||
|
||||
IntSetIterator it = entity.incoming.iterator();
|
||||
|
||||
while(it.hasNext){
|
||||
int v = it.next();
|
||||
if(tile.absoluteRelativeTo(Pos.x(v), Pos.y(v)) == i){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int rel = tile.absoluteRelativeTo(other.x, other.y);
|
||||
int rel2 = tile.relativeTo(to.x, to.y);
|
||||
|
||||
return rel != rel2;
|
||||
}
|
||||
|
||||
public boolean linkValid(Tile tile, Tile other){
|
||||
return linkValid(tile, other, true);
|
||||
}
|
||||
@@ -358,11 +117,18 @@ public class ItemBridge extends Block{
|
||||
return false;
|
||||
}
|
||||
|
||||
return other.block() == this && (!checkDouble || other.<ItemBridgeEntity>ent().link != tile.pos());
|
||||
return other.block() == this && (other.team() == tile.team() || tile.block() != this) && (!checkDouble || other.<ItemBridgeEntity>ent().link != tile.pos());
|
||||
}
|
||||
|
||||
public static class ItemBridgeEntity extends TileEntity{
|
||||
public int link = Pos.invalid;
|
||||
public Tile findLink(int x, int y){
|
||||
if(world.tiles.in(x, y) && linkValid(world.tile(x, y), world.tile(lastPlaced)) && lastPlaced != Point2.pack(x, y)){
|
||||
return world.tile(lastPlaced);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public class ItemBridgeEntity extends TileEntity{
|
||||
public int link = -1;
|
||||
public IntSet incoming = new IntSet();
|
||||
public float uptime;
|
||||
public float time;
|
||||
@@ -370,32 +136,250 @@ public class ItemBridge extends Block{
|
||||
public float cycleSpeed = 1f;
|
||||
|
||||
@Override
|
||||
public int config(){
|
||||
return link;
|
||||
public void playerPlaced(){
|
||||
Tile link = findLink(tile.x, tile.y);
|
||||
if(linkValid(tile, link)){
|
||||
link.configure(tile.pos());
|
||||
}
|
||||
|
||||
lastPlaced = tile.pos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeInt(link);
|
||||
stream.writeFloat(uptime);
|
||||
stream.writeByte(incoming.size);
|
||||
public void drawConfigure(){
|
||||
Draw.color(Pal.accent);
|
||||
Lines.stroke(1f);
|
||||
Lines.square(x, y,
|
||||
tile.block().size * tilesize / 2f + 1f);
|
||||
|
||||
for(int i = 1; i <= range; i++){
|
||||
for(int j = 0; j < 4; j++){
|
||||
Tile other = tile.getNearby(Geometry.d4[j].x * i, Geometry.d4[j].y * i);
|
||||
if(linkValid(tile, other)){
|
||||
boolean linked = other.pos() == link;
|
||||
Draw.color(linked ? Pal.place : Pal.breakInvalid);
|
||||
|
||||
Lines.square(other.drawx(), other.drawy(),
|
||||
other.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Time.time(), 4f, 1f)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConfigureTileTapped(Tilec other){
|
||||
if(linkValid(tile, other.tile())){
|
||||
if(link == other.pos()){
|
||||
tile.configure(-1);
|
||||
}else{
|
||||
tile.configure(other.pos());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void checkIncoming(){
|
||||
IntSetIterator it = incoming.iterator();
|
||||
while(it.hasNext){
|
||||
int i = it.next();
|
||||
Tile other = world.tile(i);
|
||||
if(!linkValid(tile, other, false) || other.<ItemBridgeEntity>ent().link != tile.pos()){
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
time += cycleSpeed * delta();
|
||||
time2 += (cycleSpeed - 1f) * delta();
|
||||
|
||||
checkIncoming();
|
||||
|
||||
Tile other = world.tile(link);
|
||||
if(!linkValid(tile, other)){
|
||||
dump();
|
||||
uptime = 0f;
|
||||
}else{
|
||||
((ItemBridgeEntity)other.entity).incoming.add(tile.pos());
|
||||
|
||||
if(consValid() && Mathf.zero(1f - efficiency())){
|
||||
uptime = Mathf.lerpDelta(uptime, 1f, 0.04f);
|
||||
}else{
|
||||
uptime = Mathf.lerpDelta(uptime, 0f, 0.02f);
|
||||
}
|
||||
|
||||
updateTransport(other.entity);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTransport(Tilec other){
|
||||
if(uptime >= 0.5f && timer(timerTransport, transportTime)){
|
||||
Item item = items.take();
|
||||
if(item != null && other.acceptItem(this, item)){
|
||||
other.handleItem(this, item);
|
||||
cycleSpeed = Mathf.lerpDelta(cycleSpeed, 4f, 0.05f);
|
||||
}else{
|
||||
cycleSpeed = Mathf.lerpDelta(cycleSpeed, 1f, 0.01f);
|
||||
if(item != null) items.add(item, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(){
|
||||
Tile other = world.tile(link);
|
||||
if(!linkValid(tile, other)) return;
|
||||
|
||||
float opacity = Core.settings.getInt("bridgeopacity") / 100f;
|
||||
if(Mathf.zero(opacity)) return;
|
||||
|
||||
int i = tile.absoluteRelativeTo(other.x, other.y);
|
||||
|
||||
Draw.color(Color.white, Color.black, Mathf.absin(Time.time(), 6f, 0.07f));
|
||||
Draw.alpha(Math.max(uptime, 0.25f) * opacity);
|
||||
|
||||
Draw.rect(endRegion, x, y, i * 90 + 90);
|
||||
Draw.rect(endRegion, other.drawx(), other.drawy(), i * 90 + 270);
|
||||
|
||||
Lines.stroke(8f);
|
||||
Lines.line(bridgeRegion,
|
||||
x,
|
||||
y,
|
||||
other.worldx(),
|
||||
other.worldy(), CapStyle.none, -tilesize / 2f);
|
||||
|
||||
int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y));
|
||||
|
||||
float time = time2 / 1.7f;
|
||||
int arrows = (dist) * tilesize / 4 - 2;
|
||||
|
||||
Draw.color();
|
||||
|
||||
for(int a = 0; a < arrows; a++){
|
||||
Draw.alpha(Mathf.absin(a / (float)arrows - time / 100f, 0.1f, 1f) * uptime * opacity);
|
||||
Draw.rect(arrowRegion,
|
||||
x + Geometry.d4[i].x * (tilesize / 2f + a * 4f + time % 4f),
|
||||
y + Geometry.d4[i].y * (tilesize / 2f + a * 4f + time % 4f), i * 90f);
|
||||
}
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
if(team != source.team()) return false;
|
||||
|
||||
Tile other = world.tile(link);
|
||||
|
||||
if(linkValid(tile, other)){
|
||||
int rel = tile.absoluteRelativeTo(other.x, other.y);
|
||||
int rel2 = tile.relativeTo(source.tileX(), source.tileY());
|
||||
|
||||
if(rel == rel2) return false;
|
||||
}else{
|
||||
return source.block() instanceof ItemBridge && ((ItemBridgeEntity)source).link == tile.pos() && items.total() < itemCapacity;
|
||||
}
|
||||
|
||||
return items.total() < itemCapacity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canDumpLiquid(Tilec to, Liquid liquid){
|
||||
Tile other = world.tile(link);
|
||||
if(!linkValid(tile, other)){
|
||||
Tile edge = Edges.getFacingEdge(to.tile(), tile);
|
||||
int i = tile.absoluteRelativeTo(edge.x, edge.y);
|
||||
|
||||
IntSetIterator it = incoming.iterator();
|
||||
|
||||
while(it.hasNext){
|
||||
int v = it.next();
|
||||
if(tile.absoluteRelativeTo(Point2.x(v), Point2.y(v)) == i){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int rel = tile.absoluteRelativeTo(other.x, other.y);
|
||||
int rel2 = tile.relativeTo(to.tileX(), to.tileY());
|
||||
|
||||
return rel != rel2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tilec source, Liquid liquid, float amount){
|
||||
if(team != source.team() || !hasLiquids) return false;
|
||||
|
||||
Tile other = world.tile(link);
|
||||
|
||||
if(linkValid(tile, other)){
|
||||
int rel = tile.absoluteRelativeTo(other.x, other.y);
|
||||
int rel2 = tile.relativeTo(source.tileX(), source.tileY());
|
||||
|
||||
if(rel == rel2) return false;
|
||||
}else if(!(source.block() instanceof ItemBridge && ((ItemBridgeEntity)source).link == tile.pos())){
|
||||
return false;
|
||||
}
|
||||
|
||||
return liquids.get(liquid) + amount < liquidCapacity && (liquids.current() == liquid || liquids.get(liquids.current()) < 0.2f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDump(Tilec to, Item item){
|
||||
Tile other = world.tile(link);
|
||||
if(!linkValid(tile, other)){
|
||||
Tile edge = Edges.getFacingEdge(to.tile(), tile);
|
||||
int i = tile.absoluteRelativeTo(edge.x, edge.y);
|
||||
|
||||
IntSetIterator it = incoming.iterator();
|
||||
|
||||
while(it.hasNext){
|
||||
int v = it.next();
|
||||
if(tile.absoluteRelativeTo(Point2.x(v), Point2.y(v)) == i){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int rel = tile.absoluteRelativeTo(other.x, other.y);
|
||||
int rel2 = tile.relativeTo(to.tileX(), to.tileY());
|
||||
|
||||
return rel != rel2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point2 config(){
|
||||
return Point2.unpack(link).sub(tile.x, tile.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.i(link);
|
||||
write.f(uptime);
|
||||
write.b(incoming.size);
|
||||
|
||||
IntSetIterator it = incoming.iterator();
|
||||
|
||||
while(it.hasNext){
|
||||
stream.writeInt(it.next());
|
||||
write.i(it.next());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
link = stream.readInt();
|
||||
uptime = stream.readFloat();
|
||||
byte links = stream.readByte();
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
link = read.i();
|
||||
uptime = read.f();
|
||||
byte links = read.b();
|
||||
for(int i = 0; i < links; i++){
|
||||
incoming.add(stream.readInt());
|
||||
incoming.add(read.i());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.util.Time;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.entities.type.Unit;
|
||||
import mindustry.gen.BufferItem;
|
||||
import mindustry.type.Item;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.DirectionalItemBuffer;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.BlockGroup;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.content;
|
||||
|
||||
@@ -26,12 +19,6 @@ public class Junction extends Block{
|
||||
solid = true;
|
||||
group = BlockGroup.transportation;
|
||||
unloadable = false;
|
||||
entityType = JunctionEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -39,66 +26,66 @@ public class Junction extends Block{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
JunctionEntity entity = tile.ent();
|
||||
DirectionalItemBuffer buffer = entity.buffer;
|
||||
|
||||
for(int i = 0; i < 4; i++){
|
||||
if(buffer.indexes[i] > 0){
|
||||
if(buffer.indexes[i] > capacity) buffer.indexes[i] = capacity;
|
||||
long l = buffer.buffers[i][0];
|
||||
float time = BufferItem.time(l);
|
||||
|
||||
if(Time.time() >= time + speed || Time.time() < time){
|
||||
|
||||
Item item = content.item(BufferItem.item(l));
|
||||
Tile dest = tile.getNearby(i);
|
||||
if(dest != null) dest = dest.link();
|
||||
|
||||
//skip blocks that don't want the item, keep waiting until they do
|
||||
if(dest == null || !dest.block().acceptItem(item, dest, tile) || dest.getTeam() != tile.getTeam()){
|
||||
continue;
|
||||
}
|
||||
|
||||
dest.block().handleItem(item, dest, tile);
|
||||
System.arraycopy(buffer.buffers[i], 1, buffer.buffers[i], 0, buffer.indexes[i] - 1);
|
||||
buffer.indexes[i] --;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
JunctionEntity entity = tile.ent();
|
||||
int relative = source.relativeTo(tile.x, tile.y);
|
||||
entity.buffer.accept(relative, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
JunctionEntity entity = tile.ent();
|
||||
int relative = source.relativeTo(tile.x, tile.y);
|
||||
|
||||
if(entity == null || relative == -1 || !entity.buffer.accepts(relative)) return false;
|
||||
Tile to = tile.getNearby(relative);
|
||||
return to != null && to.link().entity != null && to.getTeam() == tile.getTeam();
|
||||
}
|
||||
|
||||
class JunctionEntity extends TileEntity{
|
||||
public class JunctionEntity extends TileEntity{
|
||||
DirectionalItemBuffer buffer = new DirectionalItemBuffer(capacity, speed);
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
buffer.write(stream);
|
||||
public int acceptStack(Item item, int amount, Teamc source){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
buffer.read(stream);
|
||||
public void updateTile(){
|
||||
|
||||
for(int i = 0; i < 4; i++){
|
||||
if(buffer.indexes[i] > 0){
|
||||
if(buffer.indexes[i] > capacity) buffer.indexes[i] = capacity;
|
||||
long l = buffer.buffers[i][0];
|
||||
float time = BufferItem.time(l);
|
||||
|
||||
if(Time.time() >= time + speed || Time.time() < time){
|
||||
|
||||
Item item = content.item(BufferItem.item(l));
|
||||
Tilec dest = nearby(i);
|
||||
|
||||
//skip blocks that don't want the item, keep waiting until they do
|
||||
if(dest == null || !dest.acceptItem(this, item) || dest.team() != team){
|
||||
continue;
|
||||
}
|
||||
|
||||
dest.handleItem(this, item);
|
||||
System.arraycopy(buffer.buffers[i], 1, buffer.buffers[i], 0, buffer.indexes[i] - 1);
|
||||
buffer.indexes[i] --;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Tilec source, Item item){
|
||||
int relative = source.relativeTo(tile.x, tile.y);
|
||||
buffer.accept(relative, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
int relative = source.relativeTo(tile.x, tile.y);
|
||||
|
||||
if(relative == -1 || !buffer.accepts(relative)) return false;
|
||||
Tilec to = nearby(relative);
|
||||
return to != null && to.team() == team;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
buffer.write(write);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
buffer.read(read);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
262
core/src/mindustry/world/blocks/distribution/MassConveyor.java
Normal file
262
core/src/mindustry/world/blocks/distribution/MassConveyor.java
Normal file
@@ -0,0 +1,262 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.input.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
//TODO rename
|
||||
public class MassConveyor extends Block{
|
||||
public float moveTime = 70f;
|
||||
public TextureRegion topRegion, edgeRegion;
|
||||
public Interpolation interp = Interpolation.pow5;
|
||||
|
||||
public MassConveyor(String name){
|
||||
super(name);
|
||||
|
||||
layer = Layer.overlay;
|
||||
size = 3;
|
||||
rotate = true;
|
||||
update = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
super.load();
|
||||
|
||||
topRegion = Core.atlas.find(name + "-top");
|
||||
edgeRegion = Core.atlas.find(name + "-edge");
|
||||
}
|
||||
|
||||
public class MassConveyorEntity extends TileEntity implements MassAcceptor{
|
||||
public @Nullable Payload item;
|
||||
public float progress, itemRotation, animation;
|
||||
public @Nullable MassAcceptor next;
|
||||
public boolean blocked;
|
||||
public int step = -1, stepAccepted = -1;
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(){
|
||||
super.onProximityUpdate();
|
||||
|
||||
Tilec accept = nearby(Geometry.d4[rotation()].x * size, Geometry.d4[rotation()].y * size);
|
||||
//next block must be aligned and of the same size
|
||||
if(accept instanceof MassAcceptor && accept.block().size == size &&
|
||||
tileX() + Geometry.d4[rotation()].x * size == accept.tileX() && tileY() + Geometry.d4[rotation()].y * size == accept.tileY()){
|
||||
next = (MassAcceptor)accept;
|
||||
}
|
||||
|
||||
int ntrns = 1 + size/2;
|
||||
Tile next = tile.getNearby(Geometry.d4[rotation()].x * ntrns, Geometry.d4[rotation()].y * ntrns);
|
||||
blocked = (next != null && next.solid()) || (this.next != null && (this.next.rotation() + 2)%4 == rotation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
progress = Time.time() % moveTime;
|
||||
|
||||
//TODO DEBUG
|
||||
if(Core.input.keyTap(KeyCode.G) && world.entWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y) == this){
|
||||
item = new UnitPayload((Mathf.chance(0.5) ? UnitTypes.wraith : UnitTypes.dagger).create(Team.sharded));
|
||||
itemRotation = rotation() * 90;
|
||||
animation = 0f;
|
||||
}
|
||||
|
||||
int curStep = curStep();
|
||||
if(curStep > step){
|
||||
boolean valid = step != -1;
|
||||
step = curStep;
|
||||
|
||||
if(valid && stepAccepted != curStep && item != null){
|
||||
if(next != null){
|
||||
//trigger update forward
|
||||
next.updateTile();
|
||||
|
||||
if(next.acceptMass(item, this)){
|
||||
//move forward.
|
||||
next.handleMass(item, this);
|
||||
item = null;
|
||||
}
|
||||
}else if(!blocked){
|
||||
//dump item forward
|
||||
float trnext = size * tilesize / 2f, cx = Geometry.d4[rotation()].x, cy = Geometry.d4[rotation()].y, rot = rotation() * 90;
|
||||
|
||||
item.dump(x + cx * trnext, y + cy * trnext, rotation() * 90);
|
||||
item = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
float dst = 0.8f;
|
||||
|
||||
float glow = Math.max((dst - (Math.abs(fract() - 0.5f) * 2)) / dst, 0);
|
||||
Draw.mixcol(Pal.accent, glow);
|
||||
|
||||
float trnext = fract() * size * tilesize, trprev = size * tilesize * (fract() - 1), rot = rotation() * 90;
|
||||
|
||||
TextureRegion clipped = clipRegion(tile.getHitbox(Tmp.r1), tile.getHitbox(Tmp.r2).move(trnext, 0), topRegion);
|
||||
float s = tilesize * size;
|
||||
|
||||
//next
|
||||
Tmp.v1.set((s-clipped.getWidth()*Draw.scl) + clipped.getWidth()/2f*Draw.scl - s/2f, s-clipped.getHeight()*Draw.scl + clipped.getHeight()/2f*Draw.scl - s/2f).rotate(rot);
|
||||
Draw.rect(clipped, x + Tmp.v1.x, y + Tmp.v1.y, rot);
|
||||
|
||||
clipped = clipRegion(tile.getHitbox(Tmp.r1), tile.getHitbox(Tmp.r2).move(trprev, 0), topRegion);
|
||||
|
||||
//prev
|
||||
Tmp.v1.set(- s/2f + clipped.getWidth()/2f*Draw.scl, - s/2f + clipped.getHeight()/2f*Draw.scl).rotate(rot);
|
||||
Draw.rect(clipped, x + Tmp.v1.x, y + Tmp.v1.y, rot);
|
||||
|
||||
for(int i = 0; i < 4; i++){
|
||||
if(blends(i) && i != rotation()){
|
||||
Draw.alpha(1f - Interpolation.pow5In.apply(fract()));
|
||||
//prev from back
|
||||
Tmp.v1.set(- s/2f + clipped.getWidth()/2f*Draw.scl, - s/2f + clipped.getHeight()/2f*Draw.scl).rotate(i * 90 + 180);
|
||||
Draw.rect(clipped, x + Tmp.v1.x, y + Tmp.v1.y, i * 90 + 180);
|
||||
}
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
|
||||
for(int i = 0; i < 4; i++){
|
||||
if(!blends(i)){
|
||||
Draw.rect(edgeRegion, x, y, i * 90);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(){
|
||||
//fract:
|
||||
//0: arriving
|
||||
//0.5: middle
|
||||
//1: leaving
|
||||
|
||||
if(animation > fract()){
|
||||
animation = Mathf.lerp(animation, 0.8f, 0.15f);
|
||||
}
|
||||
|
||||
animation = Math.max(animation, fract());
|
||||
|
||||
float fract = animation;
|
||||
float rot = Mathf.slerp(itemRotation, rotation() * 90, fract);
|
||||
|
||||
if(fract < 0.5f){
|
||||
Tmp.v1.trns(itemRotation + 180, (0.5f - fract) * tilesize * size);
|
||||
}else{
|
||||
Tmp.v1.trns(rotation() * 90, (fract - 0.5f) * tilesize * size);
|
||||
}
|
||||
|
||||
float vx = Tmp.v1.x, vy = Tmp.v1.y;
|
||||
|
||||
if(item != null){
|
||||
item.draw(x + vx, y + vy, rot);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptMass(Payload item, Tilec source){
|
||||
return this.item == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMass(Payload item, Tilec source){
|
||||
this.item = item;
|
||||
this.stepAccepted = curStep();
|
||||
this.itemRotation = source.rotation() * 90;
|
||||
this.animation = 0;
|
||||
}
|
||||
|
||||
boolean blends(int direction){
|
||||
if(direction == rotation()){
|
||||
return !blocked || next != null;
|
||||
}else{
|
||||
Tilec accept = nearby(Geometry.d4[direction].x * size, Geometry.d4[direction].y * size);
|
||||
return accept instanceof MassAcceptor && accept.block().size == size &&
|
||||
accept.tileX() + Geometry.d4[accept.rotation()].x * size == tileX() && accept.tileY() + Geometry.d4[accept.rotation()].y * size == tileY();
|
||||
}
|
||||
}
|
||||
|
||||
TextureRegion clipRegion(Rect bounds, Rect sprite, TextureRegion region){
|
||||
Rect over = Tmp.r3;
|
||||
|
||||
boolean overlaps = Intersector.intersectRectangles(bounds, sprite, over);
|
||||
|
||||
TextureRegion out = Tmp.tr1;
|
||||
out.set(region.getTexture());
|
||||
|
||||
if(overlaps){
|
||||
float w = region.getU2() - region.getU();
|
||||
float h = region.getV2() - region.getV();
|
||||
float x = region.getU(), y = region.getV();
|
||||
float newX = (over.x - sprite.x) / sprite.width * w + x;
|
||||
float newY = (over.y - sprite.y) / sprite.height * h + y;
|
||||
float newW = (over.width / sprite.width) * w, newH = (over.height / sprite.height) * h;
|
||||
|
||||
out.set(newX, newY, newX + newW, newY + newH);
|
||||
}else{
|
||||
out.set(0f, 0f, 0f, 0f);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int curStep(){
|
||||
return (int)(Time.time() / moveTime);
|
||||
}
|
||||
|
||||
float fract(){
|
||||
return interp.apply(progress / moveTime);
|
||||
}
|
||||
}
|
||||
|
||||
public interface MassAcceptor extends Tilec{
|
||||
boolean acceptMass(Payload item, Tilec source);
|
||||
void handleMass(Payload item, Tilec source);
|
||||
}
|
||||
|
||||
public interface Payload{
|
||||
void draw(float x, float y, float rotation);
|
||||
void dump(float x, float y, float rotation);
|
||||
}
|
||||
|
||||
public static class UnitPayload implements Payload{
|
||||
public Unitc unit;
|
||||
|
||||
public UnitPayload(Unitc unit){
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(float x, float y, float rotation){
|
||||
unit.set(x, y);
|
||||
unit.rotation(rotation);
|
||||
unit.add();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(float x, float y, float rotation){
|
||||
Drawf.shadow(x, y, 24);
|
||||
Draw.rect("pneumatic-drill", x, y, rotation);
|
||||
Drawf.shadow(x, y, 20);
|
||||
Draw.rect(unit.type().icon(Cicon.full), x, y, rotation - 90);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,21 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import arc.util.pooling.Pool.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class MassDriver extends Block{
|
||||
@@ -36,18 +35,14 @@ public class MassDriver extends Block{
|
||||
super(name);
|
||||
update = true;
|
||||
solid = true;
|
||||
posConfig = true;
|
||||
configurable = true;
|
||||
hasItems = true;
|
||||
layer = Layer.turret;
|
||||
hasPower = true;
|
||||
outlineIcon = true;
|
||||
entityType = MassDriverEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configured(Tile tile, Player player, int value){
|
||||
tile.<MassDriverEntity>ent().link = value;
|
||||
//point2 is relative
|
||||
config(Point2.class, (tile, point) -> ((MassDriverEntity)tile).link = Point2.pack(point.x + tile.tileX(), point.y + tile.tileY()));
|
||||
config(Integer.class, (tile, point) -> ((MassDriverEntity)tile).link = point);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,117 +57,20 @@ public class MassDriver extends Block{
|
||||
baseRegion = Core.atlas.find(name + "-base");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
MassDriverEntity entity = tile.ent();
|
||||
Tile link = world.tile(entity.link);
|
||||
boolean hasLink = linkValid(tile);
|
||||
|
||||
//reload regardless of state
|
||||
if(entity.reload > 0f){
|
||||
entity.reload = Mathf.clamp(entity.reload - entity.delta() / reloadTime * entity.efficiency());
|
||||
}
|
||||
|
||||
//cleanup waiting shooters that are not valid
|
||||
if(!shooterValid(tile, entity.currentShooter())){
|
||||
entity.waitingShooters.remove(entity.currentShooter());
|
||||
}
|
||||
|
||||
//switch states
|
||||
if(entity.state == DriverState.idle){
|
||||
//start accepting when idle and there's space
|
||||
if(!entity.waitingShooters.isEmpty() && (itemCapacity - entity.items.total() >= minDistribute)){
|
||||
entity.state = DriverState.accepting;
|
||||
}else if(hasLink){ //switch to shooting if there's a valid link.
|
||||
entity.state = DriverState.shooting;
|
||||
}
|
||||
}
|
||||
|
||||
//dump when idle or accepting
|
||||
if(entity.state == DriverState.idle || entity.state == DriverState.accepting){
|
||||
tryDump(tile);
|
||||
}
|
||||
|
||||
//skip when there's no power
|
||||
if(!entity.cons.valid()){
|
||||
return;
|
||||
}
|
||||
|
||||
if(entity.state == DriverState.accepting){
|
||||
//if there's nothing shooting at this, bail - OR, items full
|
||||
if(entity.currentShooter() == null || (itemCapacity - entity.items.total() < minDistribute)){
|
||||
entity.state = DriverState.idle;
|
||||
return;
|
||||
}
|
||||
|
||||
//align to shooter rotation
|
||||
entity.rotation = Mathf.slerpDelta(entity.rotation, tile.angleTo(entity.currentShooter()), rotateSpeed * entity.efficiency());
|
||||
}else if(entity.state == DriverState.shooting){
|
||||
//if there's nothing to shoot at OR someone wants to shoot at this thing, bail
|
||||
if(!hasLink || (!entity.waitingShooters.isEmpty() && (itemCapacity - entity.items.total() >= minDistribute))){
|
||||
entity.state = DriverState.idle;
|
||||
return;
|
||||
}
|
||||
|
||||
float targetRotation = tile.angleTo(link);
|
||||
|
||||
if(
|
||||
tile.entity.items.total() >= minDistribute && //must shoot minimum amount of items
|
||||
link.block().itemCapacity - link.entity.items.total() >= minDistribute //must have minimum amount of space
|
||||
){
|
||||
MassDriverEntity other = link.ent();
|
||||
other.waitingShooters.add(tile);
|
||||
|
||||
if(entity.reload <= 0.0001f){
|
||||
|
||||
//align to target location
|
||||
entity.rotation = Mathf.slerpDelta(entity.rotation, targetRotation, rotateSpeed * entity.efficiency());
|
||||
|
||||
//fire when it's the first in the queue and angles are ready.
|
||||
if(other.currentShooter() == tile &&
|
||||
other.state == DriverState.accepting &&
|
||||
Angles.near(entity.rotation, targetRotation, 2f) && Angles.near(other.rotation, targetRotation + 180f, 2f)){
|
||||
//actually fire
|
||||
fire(tile, link);
|
||||
//remove waiting shooters, it's done firing
|
||||
other.waitingShooters.remove(tile);
|
||||
//set both states to idle
|
||||
entity.state = DriverState.idle;
|
||||
other.state = DriverState.idle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
Draw.rect(baseRegion, tile.drawx(), tile.drawy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
MassDriverEntity entity = tile.ent();
|
||||
|
||||
Draw.rect(region,
|
||||
tile.drawx() + Angles.trnsx(entity.rotation + 180f, entity.reload * knockback),
|
||||
tile.drawy() + Angles.trnsy(entity.rotation + 180f, entity.reload * knockback), entity.rotation - 90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||
Drawf.dashCircle(x * tilesize, y*tilesize, range, Pal.accent);
|
||||
|
||||
//check if a mass driver is selected while placing this driver
|
||||
if(!control.input.frag.config.isShown()) return;
|
||||
Tile selected = control.input.frag.config.getSelectedTile();
|
||||
Tilec selected = control.input.frag.config.getSelectedTile();
|
||||
if(selected == null || !(selected.block() instanceof MassDriver) || !(selected.dst(x * tilesize, y * tilesize) <= range)) return;
|
||||
|
||||
//if so, draw a dotted line towards it while it is in range
|
||||
float sin = Mathf.absin(Time.time(), 6f, 1f);
|
||||
Tmp.v1.set(x * tilesize + offset(), y * tilesize + offset()).sub(selected.drawx(), selected.drawy()).limit((size / 2f + 1) * tilesize + sin + 0.5f);
|
||||
Tmp.v1.set(x * tilesize + offset(), y * tilesize + offset()).sub(selected.x(), selected.y()).limit((size / 2f + 1) * tilesize + sin + 0.5f);
|
||||
float x2 = x * tilesize - Tmp.v1.x, y2 = y * tilesize - Tmp.v1.y,
|
||||
x1 = selected.drawx() + Tmp.v1.x, y1 = selected.drawy() + Tmp.v1.y;
|
||||
x1 = selected.x() + Tmp.v1.x, y1 = selected.y() + Tmp.v1.y;
|
||||
int segs = (int)(selected.dst(x * tilesize, y * tilesize) / tilesize);
|
||||
|
||||
Lines.stroke(4f, Pal.gray);
|
||||
@@ -182,126 +80,7 @@ public class MassDriver extends Block{
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawConfigure(Tile tile){
|
||||
float sin = Mathf.absin(Time.time(), 6f, 1f);
|
||||
|
||||
Draw.color(Pal.accent);
|
||||
Lines.stroke(1f);
|
||||
Drawf.circles(tile.drawx(), tile.drawy(), (tile.block().size / 2f + 1) * tilesize + sin - 2f, Pal.accent);
|
||||
|
||||
MassDriverEntity entity = tile.ent();
|
||||
|
||||
for(Tile shooter : entity.waitingShooters){
|
||||
Drawf.circles(shooter.drawx(), shooter.drawy(), (tile.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place);
|
||||
Drawf.arrow(shooter.drawx(), shooter.drawy(), tile.drawx(), tile.drawy(), size * tilesize + sin, 4f + sin, Pal.place);
|
||||
}
|
||||
|
||||
if(linkValid(tile)){
|
||||
Tile target = world.tile(entity.link);
|
||||
Drawf.circles(target.drawx(), target.drawy(), (target.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place);
|
||||
Drawf.arrow(tile.drawx(), tile.drawy(), target.drawx(), target.drawy(), size * tilesize + sin, 4f + sin);
|
||||
}
|
||||
|
||||
Drawf.dashCircle(tile.drawx(), tile.drawy(), range, Pal.accent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConfigureTileTapped(Tile tile, Tile other){
|
||||
if(tile == other) return false;
|
||||
|
||||
MassDriverEntity entity = tile.ent();
|
||||
|
||||
if(entity.link == other.pos()){
|
||||
tile.configure(-1);
|
||||
return false;
|
||||
}else if(other.block() instanceof MassDriver && other.dst(tile) <= range && other.getTeam() == tile.getTeam()){
|
||||
tile.configure(other.pos());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
//mass drivers that ouput only cannot accept items
|
||||
return tile.entity.items.total() < itemCapacity && linkValid(tile);
|
||||
}
|
||||
|
||||
protected void fire(Tile tile, Tile target){
|
||||
MassDriverEntity entity = tile.ent();
|
||||
MassDriverEntity other = target.ent();
|
||||
|
||||
//reset reload, use power.
|
||||
entity.reload = 1f;
|
||||
|
||||
DriverBulletData data = Pools.obtain(DriverBulletData.class, DriverBulletData::new);
|
||||
data.from = entity;
|
||||
data.to = other;
|
||||
int totalUsed = 0;
|
||||
for(int i = 0; i < content.items().size; i++){
|
||||
int maxTransfer = Math.min(entity.items.get(content.item(i)), ((MassDriver)tile.block()).itemCapacity - totalUsed);
|
||||
data.items[i] = maxTransfer;
|
||||
totalUsed += maxTransfer;
|
||||
entity.items.remove(content.item(i), maxTransfer);
|
||||
}
|
||||
|
||||
float angle = tile.angleTo(target);
|
||||
|
||||
Bullet.create(Bullets.driverBolt, entity, entity.getTeam(),
|
||||
tile.drawx() + Angles.trnsx(angle, translation), tile.drawy() + Angles.trnsy(angle, translation),
|
||||
angle, 1f, 1f, data);
|
||||
|
||||
Effects.effect(shootEffect, tile.drawx() + Angles.trnsx(angle, translation),
|
||||
tile.drawy() + Angles.trnsy(angle, translation), angle);
|
||||
|
||||
Effects.effect(smokeEffect, tile.drawx() + Angles.trnsx(angle, translation),
|
||||
tile.drawy() + Angles.trnsy(angle, translation), angle);
|
||||
|
||||
Effects.shake(shake, shake, entity);
|
||||
}
|
||||
|
||||
protected void handlePayload(MassDriverEntity entity, Bullet bullet, DriverBulletData data){
|
||||
int totalItems = entity.items.total();
|
||||
|
||||
//add all the items possible
|
||||
for(int i = 0; i < data.items.length; i++){
|
||||
int maxAdd = Math.min(data.items[i], itemCapacity * 2 - totalItems);
|
||||
entity.items.add(content.item(i), maxAdd);
|
||||
data.items[i] -= maxAdd;
|
||||
totalItems += maxAdd;
|
||||
|
||||
if(totalItems >= itemCapacity * 2){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Effects.shake(shake, shake, entity);
|
||||
Effects.effect(recieveEffect, bullet);
|
||||
|
||||
entity.reload = 1f;
|
||||
bullet.remove();
|
||||
}
|
||||
|
||||
protected boolean shooterValid(Tile tile, Tile other){
|
||||
|
||||
if(other == null) return true;
|
||||
if(!(other.block() instanceof MassDriver)) return false;
|
||||
MassDriverEntity entity = other.ent();
|
||||
return entity.link == tile.pos() && tile.dst(other) <= range;
|
||||
}
|
||||
|
||||
protected boolean linkValid(Tile tile){
|
||||
if(tile == null) return false;
|
||||
MassDriverEntity entity = tile.ent();
|
||||
if(entity == null || entity.link == -1) return false;
|
||||
Tile link = world.tile(entity.link);
|
||||
|
||||
return link != null && link.block() instanceof MassDriver && link.getTeam() == tile.getTeam() && tile.dst(link) <= range;
|
||||
}
|
||||
|
||||
public static class DriverBulletData implements Poolable{
|
||||
public class DriverBulletData implements Poolable{
|
||||
public MassDriverEntity from, to;
|
||||
public int[] items = new int[content.items().size];
|
||||
|
||||
@@ -323,29 +102,230 @@ public class MassDriver extends Block{
|
||||
return waitingShooters.isEmpty() ? null : waitingShooters.first();
|
||||
}
|
||||
|
||||
public void handlePayload(Bullet bullet, DriverBulletData data){
|
||||
((MassDriver)block).handlePayload(this, bullet, data);
|
||||
@Override
|
||||
public void updateTile(){
|
||||
Tilec link = world.ent(this.link);
|
||||
boolean hasLink = linkValid();
|
||||
|
||||
//reload regardless of state
|
||||
if(reload > 0f){
|
||||
reload = Mathf.clamp(reload - delta() / reloadTime * efficiency());
|
||||
}
|
||||
|
||||
//cleanup waiting shooters that are not valid
|
||||
if(!shooterValid(currentShooter())){
|
||||
waitingShooters.remove(currentShooter());
|
||||
}
|
||||
|
||||
//switch states
|
||||
if(state == DriverState.idle){
|
||||
//start accepting when idle and there's space
|
||||
if(!waitingShooters.isEmpty() && (itemCapacity - items.total() >= minDistribute)){
|
||||
state = DriverState.accepting;
|
||||
}else if(hasLink){ //switch to shooting if there's a valid link.
|
||||
state = DriverState.shooting;
|
||||
}
|
||||
}
|
||||
|
||||
//dump when idle or accepting
|
||||
if(state == DriverState.idle || state == DriverState.accepting){
|
||||
dump();
|
||||
}
|
||||
|
||||
//skip when there's no power
|
||||
if(!consValid()){
|
||||
return;
|
||||
}
|
||||
|
||||
if(state == DriverState.accepting){
|
||||
//if there's nothing shooting at this, bail - OR, items full
|
||||
if(currentShooter() == null || (itemCapacity - items.total() < minDistribute)){
|
||||
state = DriverState.idle;
|
||||
return;
|
||||
}
|
||||
|
||||
//align to shooter rotation
|
||||
rotation = Mathf.slerpDelta(rotation, tile.angleTo(currentShooter()), rotateSpeed * efficiency());
|
||||
}else if(state == DriverState.shooting){
|
||||
//if there's nothing to shoot at OR someone wants to shoot at this thing, bail
|
||||
if(!hasLink || (!waitingShooters.isEmpty() && (itemCapacity - items.total() >= minDistribute))){
|
||||
state = DriverState.idle;
|
||||
return;
|
||||
}
|
||||
|
||||
float targetRotation = tile.angleTo(link);
|
||||
|
||||
if(
|
||||
items.total() >= minDistribute && //must shoot minimum amount of items
|
||||
link.block().itemCapacity - link.items().total() >= minDistribute //must have minimum amount of space
|
||||
){
|
||||
MassDriverEntity other = (MassDriverEntity)link;
|
||||
other.waitingShooters.add(tile);
|
||||
|
||||
if(reload <= 0.0001f){
|
||||
|
||||
//align to target location
|
||||
rotation = Mathf.slerpDelta(rotation, targetRotation, rotateSpeed * efficiency());
|
||||
|
||||
//fire when it's the first in the queue and angles are ready.
|
||||
if(other.currentShooter() == tile &&
|
||||
other.state == DriverState.accepting &&
|
||||
Angles.near(rotation, targetRotation, 2f) && Angles.near(other.rotation, targetRotation + 180f, 2f)){
|
||||
//actually fire
|
||||
fire(other);
|
||||
//remove waiting shooters, it's done firing
|
||||
other.waitingShooters.remove(tile);
|
||||
//set both states to idle
|
||||
state = DriverState.idle;
|
||||
other.state = DriverState.idle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int config(){
|
||||
return link;
|
||||
public void draw(){
|
||||
Draw.rect(baseRegion, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeInt(link);
|
||||
stream.writeFloat(rotation);
|
||||
stream.writeByte((byte)state.ordinal());
|
||||
public void drawLayer(){
|
||||
Draw.rect(region,
|
||||
x + Angles.trnsx(rotation + 180f, reload * knockback),
|
||||
y + Angles.trnsy(rotation + 180f, reload * knockback), rotation - 90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
link = stream.readInt();
|
||||
rotation = stream.readFloat();
|
||||
state = DriverState.values()[stream.readByte()];
|
||||
public void drawConfigure(){
|
||||
float sin = Mathf.absin(Time.time(), 6f, 1f);
|
||||
|
||||
Draw.color(Pal.accent);
|
||||
Lines.stroke(1f);
|
||||
Drawf.circles(x, y, (tile.block().size / 2f + 1) * tilesize + sin - 2f, Pal.accent);
|
||||
|
||||
for(Tile shooter : waitingShooters){
|
||||
Drawf.circles(shooter.drawx(), shooter.drawy(), (tile.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place);
|
||||
Drawf.arrow(shooter.drawx(), shooter.drawy(), x, y, size * tilesize + sin, 4f + sin, Pal.place);
|
||||
}
|
||||
|
||||
if(linkValid()){
|
||||
Tile target = world.tile(link);
|
||||
Drawf.circles(target.drawx(), target.drawy(), (target.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place);
|
||||
Drawf.arrow(x, y, target.drawx(), target.drawy(), size * tilesize + sin, 4f + sin);
|
||||
}
|
||||
|
||||
Drawf.dashCircle(x, y, range, Pal.accent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConfigureTileTapped(Tilec other){
|
||||
if(this == other) return false;
|
||||
|
||||
if(link == other.pos()){
|
||||
tile.configure(-1);
|
||||
return false;
|
||||
}else if(other.block() instanceof MassDriver && other.dst(tile) <= range && other.team() == team){
|
||||
tile.configure(other.pos());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
//mass drivers that ouput only cannot accept items
|
||||
return items.total() < itemCapacity && linkValid();
|
||||
}
|
||||
|
||||
protected void fire(MassDriverEntity target){
|
||||
//reset reload, use power.
|
||||
reload = 1f;
|
||||
|
||||
DriverBulletData data = Pools.obtain(DriverBulletData.class, DriverBulletData::new);
|
||||
data.from = this;
|
||||
data.to = target;
|
||||
int totalUsed = 0;
|
||||
for(int i = 0; i < content.items().size; i++){
|
||||
int maxTransfer = Math.min(items.get(content.item(i)), ((MassDriver)tile.block()).itemCapacity - totalUsed);
|
||||
data.items[i] = maxTransfer;
|
||||
totalUsed += maxTransfer;
|
||||
items.remove(content.item(i), maxTransfer);
|
||||
}
|
||||
|
||||
float angle = tile.angleTo(target);
|
||||
|
||||
Bullets.driverBolt.create(this, team(),
|
||||
x + Angles.trnsx(angle, translation), y + Angles.trnsy(angle, translation),
|
||||
angle, -1f, 1f, 1f, data);
|
||||
|
||||
shootEffect.at(x + Angles.trnsx(angle, translation),
|
||||
y + Angles.trnsy(angle, translation), angle);
|
||||
|
||||
smokeEffect.at(x + Angles.trnsx(angle, translation),
|
||||
y + Angles.trnsy(angle, translation), angle);
|
||||
|
||||
Effects.shake(shake, shake, this);
|
||||
}
|
||||
|
||||
public void handlePayload(Bulletc bullet, DriverBulletData data){
|
||||
int totalItems = items.total();
|
||||
|
||||
//add all the items possible
|
||||
for(int i = 0; i < data.items.length; i++){
|
||||
int maxAdd = Math.min(data.items[i], itemCapacity * 2 - totalItems);
|
||||
items.add(content.item(i), maxAdd);
|
||||
data.items[i] -= maxAdd;
|
||||
totalItems += maxAdd;
|
||||
|
||||
if(totalItems >= itemCapacity * 2){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Effects.shake(shake, shake, this);
|
||||
recieveEffect.at(bullet);
|
||||
|
||||
reload = 1f;
|
||||
bullet.remove();
|
||||
}
|
||||
|
||||
protected boolean shooterValid(Tile other){
|
||||
|
||||
if(other == null) return true;
|
||||
if(!(other.block() instanceof MassDriver)) return false;
|
||||
MassDriverEntity entity = other.ent();
|
||||
return link == tile.pos() && tile.dst(other) <= range;
|
||||
}
|
||||
|
||||
protected boolean linkValid(){
|
||||
if(tile == null) return false;
|
||||
if(link == -1) return false;
|
||||
Tilec link = world.ent(this.link);
|
||||
|
||||
return link != null && link.block() instanceof MassDriver && link.team() == team && tile.dst(link) <= range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point2 config(){
|
||||
return Point2.unpack(link).sub(tile.x, tile.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.i(link);
|
||||
write.f(rotation);
|
||||
write.b((byte)state.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
link = read.i();
|
||||
rotation = read.f();
|
||||
state = DriverState.values()[read.b()];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.math.Mathf;
|
||||
import arc.util.Time;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.type.Item;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.BlockGroup;
|
||||
|
||||
import java.io.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.world;
|
||||
|
||||
@@ -22,7 +21,6 @@ public class OverflowGate extends Block{
|
||||
update = true;
|
||||
group = BlockGroup.transportation;
|
||||
unloadable = false;
|
||||
entityType = OverflowGateEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -30,125 +28,116 @@ public class OverflowGate extends Block{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeStack(Tile tile, Item item, int amount){
|
||||
OverflowGateEntity entity = tile.ent();
|
||||
int result = super.removeStack(tile, item, amount);
|
||||
if(result != 0 && item == entity.lastItem){
|
||||
entity.lastItem = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
OverflowGateEntity entity = tile.ent();
|
||||
|
||||
if(entity.lastItem == null && entity.items.total() > 0){
|
||||
entity.items.clear();
|
||||
}
|
||||
|
||||
if(entity.lastItem != null){
|
||||
if(entity.lastInput == null){
|
||||
entity.lastItem = null;
|
||||
return;
|
||||
}
|
||||
|
||||
entity.time += 1f / speed * Time.delta();
|
||||
Tile target = getTileTarget(tile, entity.lastItem, entity.lastInput, false);
|
||||
|
||||
if(target != null && (entity.time >= 1f)){
|
||||
getTileTarget(tile, entity.lastItem, entity.lastInput, true);
|
||||
target.block().handleItem(entity.lastItem, target, Edges.getFacingEdge(tile, target));
|
||||
entity.items.remove(entity.lastItem, 1);
|
||||
entity.lastItem = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
OverflowGateEntity entity = tile.ent();
|
||||
|
||||
return tile.getTeam() == source.getTeam() && entity.lastItem == null && entity.items.total() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
OverflowGateEntity entity = tile.ent();
|
||||
entity.items.add(item, 1);
|
||||
entity.lastItem = item;
|
||||
entity.time = 0f;
|
||||
entity.lastInput = source;
|
||||
|
||||
update(tile);
|
||||
}
|
||||
|
||||
public Tile getTileTarget(Tile tile, Item item, Tile src, boolean flip){
|
||||
int from = tile.relativeTo(src.x, src.y);
|
||||
if(from == -1) return null;
|
||||
Tile to = tile.getNearby((from + 2) % 4);
|
||||
if(to == null) return null;
|
||||
Tile edge = Edges.getFacingEdge(tile, to);
|
||||
boolean canForward = to.block().acceptItem(item, to, edge) && to.getTeam() == tile.getTeam() && !(to.block() instanceof OverflowGate);
|
||||
|
||||
if(!canForward || invert){
|
||||
Tile a = tile.getNearby(Mathf.mod(from - 1, 4));
|
||||
Tile b = tile.getNearby(Mathf.mod(from + 1, 4));
|
||||
boolean ac = a != null && a.block().acceptItem(item, a, edge) && !(a.block() instanceof OverflowGate) && a.getTeam() == tile.getTeam();
|
||||
boolean bc = b != null && b.block().acceptItem(item, b, edge) && !(b.block() instanceof OverflowGate) && b.getTeam() == tile.getTeam();
|
||||
|
||||
if(!ac && !bc){
|
||||
return invert && canForward ? to : null;
|
||||
}
|
||||
|
||||
if(ac && !bc){
|
||||
to = a;
|
||||
}else if(bc && !ac){
|
||||
to = b;
|
||||
}else{
|
||||
if(tile.rotation() == 0){
|
||||
to = a;
|
||||
if(flip) tile.rotation((byte) 1);
|
||||
}else{
|
||||
to = b;
|
||||
if(flip) tile.rotation((byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
public class OverflowGateEntity extends TileEntity{
|
||||
Item lastItem;
|
||||
Tile lastInput;
|
||||
float time;
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Teamc source){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeStack(Item item, int amount){
|
||||
int result = super.removeStack(item, amount);
|
||||
if(result != 0 && item == lastItem){
|
||||
lastItem = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(lastItem == null && items.total() > 0){
|
||||
items.clear();
|
||||
}
|
||||
|
||||
if(lastItem != null){
|
||||
if(lastInput == null){
|
||||
lastItem = null;
|
||||
return;
|
||||
}
|
||||
|
||||
time += 1f / speed * Time.delta();
|
||||
Tilec target = getTileTarget(lastItem, lastInput, false);
|
||||
|
||||
if(target != null && (time >= 1f)){
|
||||
getTileTarget(lastItem, lastInput, true);
|
||||
target.handleItem(this, lastItem);
|
||||
items.remove(lastItem, 1);
|
||||
lastItem = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return team == source.team() && lastItem == null && items.total() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Tilec source, Item item){
|
||||
items.add(item, 1);
|
||||
lastItem = item;
|
||||
time = 0f;
|
||||
lastInput = source.tile();
|
||||
|
||||
updateTile();
|
||||
}
|
||||
|
||||
public Tilec getTileTarget(Item item, Tile src, boolean flip){
|
||||
int from = relativeTo(src.x, src.y);
|
||||
if(from == -1) return null;
|
||||
Tilec to = nearby((from + 2) % 4);
|
||||
if(to == null) return null;
|
||||
boolean canForward = to.acceptItem(this, item) && to.team() == team && !(to.block() instanceof OverflowGate);
|
||||
|
||||
if(!canForward || invert){
|
||||
Tilec a = nearby(Mathf.mod(from - 1, 4));
|
||||
Tilec b = nearby(Mathf.mod(from + 1, 4));
|
||||
boolean ac = a != null && a.acceptItem(this, item) && !(a.block() instanceof OverflowGate) && a.team() == team;
|
||||
boolean bc = b != null && b.acceptItem(this, item) && !(b.block() instanceof OverflowGate) && b.team() == team;
|
||||
|
||||
if(!ac && !bc){
|
||||
return invert && canForward ? to : null;
|
||||
}
|
||||
|
||||
if(ac && !bc){
|
||||
to = a;
|
||||
}else if(bc && !ac){
|
||||
to = b;
|
||||
}else{
|
||||
if(tile.rotation() == 0){
|
||||
to = a;
|
||||
if(flip) tile.rotation((byte) 1);
|
||||
}else{
|
||||
to = b;
|
||||
if(flip) tile.rotation((byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte version(){
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeInt(lastInput == null ? Pos.invalid : lastInput.pos());
|
||||
public void write(Writes write){
|
||||
write.i(lastInput == null ? -1 : lastInput.pos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
if(revision == 1){
|
||||
new DirectionalItemBuffer(25, 50f).read(stream);
|
||||
new DirectionalItemBuffer(25, 50f).read(read);
|
||||
}else if(revision == 3){
|
||||
lastInput = world.tile(stream.readInt());
|
||||
lastInput = world.tile(read.i());
|
||||
lastItem = items.first();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.struct.Array;
|
||||
import arc.util.Time;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.type.Item;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.BlockGroup;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class Router extends Block{
|
||||
public float speed = 8f;
|
||||
@@ -19,73 +18,65 @@ public class Router extends Block{
|
||||
itemCapacity = 1;
|
||||
group = BlockGroup.transportation;
|
||||
unloadable = false;
|
||||
entityType = RouterEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
RouterEntity entity = tile.ent();
|
||||
|
||||
if(entity.lastItem == null && entity.items.total() > 0){
|
||||
entity.items.clear();
|
||||
}
|
||||
|
||||
if(entity.lastItem != null){
|
||||
entity.time += 1f / speed * Time.delta();
|
||||
Tile target = getTileTarget(tile, entity.lastItem, entity.lastInput, false);
|
||||
|
||||
if(target != null && (entity.time >= 1f || !(target.block() instanceof Router))){
|
||||
getTileTarget(tile, entity.lastItem, entity.lastInput, true);
|
||||
target.block().handleItem(entity.lastItem, target, Edges.getFacingEdge(tile, target));
|
||||
entity.items.remove(entity.lastItem, 1);
|
||||
entity.lastItem = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
RouterEntity entity = tile.ent();
|
||||
|
||||
return tile.getTeam() == source.getTeam() && entity.lastItem == null && entity.items.total() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
RouterEntity entity = tile.ent();
|
||||
entity.items.add(item, 1);
|
||||
entity.lastItem = item;
|
||||
entity.time = 0f;
|
||||
entity.lastInput = source;
|
||||
}
|
||||
|
||||
Tile getTileTarget(Tile tile, Item item, Tile from, boolean set){
|
||||
Array<Tile> proximity = tile.entity.proximity();
|
||||
int counter = tile.rotation();
|
||||
for(int i = 0; i < proximity.size; i++){
|
||||
Tile other = proximity.get((i + counter) % proximity.size);
|
||||
if(set) tile.rotation((byte)((tile.rotation() + 1) % proximity.size));
|
||||
if(other == from && from.block() == Blocks.overflowGate) continue;
|
||||
if(other.block().acceptItem(item, other, Edges.getFacingEdge(tile, other))){
|
||||
return other;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeStack(Tile tile, Item item, int amount){
|
||||
RouterEntity entity = tile.ent();
|
||||
int result = super.removeStack(tile, item, amount);
|
||||
if(result != 0 && item == entity.lastItem){
|
||||
entity.lastItem = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public class RouterEntity extends TileEntity{
|
||||
Item lastItem;
|
||||
Tile lastInput;
|
||||
float time;
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(lastItem == null && items.total() > 0){
|
||||
items.clear();
|
||||
}
|
||||
|
||||
if(lastItem != null){
|
||||
time += 1f / speed * Time.delta();
|
||||
Tilec target = getTileTarget(lastItem, lastInput, false);
|
||||
|
||||
if(target != null && (time >= 1f || !(target.block() instanceof Router))){
|
||||
getTileTarget(lastItem, lastInput, true);
|
||||
target.handleItem(this, lastItem);
|
||||
items.remove(lastItem, 1);
|
||||
lastItem = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return team == source.team() && lastItem == null && items.total() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Tilec source, Item item){
|
||||
items.add(item, 1);
|
||||
lastItem = item;
|
||||
time = 0f;
|
||||
lastInput = source.tile();
|
||||
}
|
||||
|
||||
Tilec getTileTarget(Item item, Tile from, boolean set){
|
||||
int counter = tile.rotation();
|
||||
for(int i = 0; i < proximity.size; i++){
|
||||
Tilec other = proximity.get((i + counter) % proximity.size);
|
||||
if(set) tile.rotation((byte)((tile.rotation() + 1) % proximity.size));
|
||||
if(other.tile() == from && from.block() == Blocks.overflowGate) continue;
|
||||
if(other.acceptItem(this, item)){
|
||||
return other;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeStack(Item item, int amount){
|
||||
int result = super.removeStack(item, amount);
|
||||
if(result != 0 && item == lastItem){
|
||||
lastItem = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,14 @@ import arc.math.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Sorter extends Block{
|
||||
@@ -28,7 +27,13 @@ public class Sorter extends Block{
|
||||
group = BlockGroup.transportation;
|
||||
configurable = true;
|
||||
unloadable = false;
|
||||
entityType = SorterEntity::new;
|
||||
config(Item.class, (tile, item) -> ((SorterEntity)tile).sortItem = item);
|
||||
configClear(tile -> ((SorterEntity)tile).sortItem = null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRequestConfig(BuildRequest req, Eachable<BuildRequest> list){
|
||||
drawRequestConfigCenter(req, (Item)req.config, "center");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,118 +41,111 @@ public class Sorter extends Block{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerPlaced(Tile tile){
|
||||
if(lastItem != null){
|
||||
tile.configure(lastItem.id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configured(Tile tile, Player player, int value){
|
||||
tile.<SorterEntity>ent().sortItem = content.item(value);
|
||||
if(!headless){
|
||||
renderer.minimap.update(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRequestConfig(BuildRequest req, Eachable<BuildRequest> list){
|
||||
drawRequestConfigCenter(req, content.item(req.config), "center");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
SorterEntity entity = tile.ent();
|
||||
if(entity.sortItem == null) return;
|
||||
|
||||
Draw.color(entity.sortItem.color);
|
||||
Draw.rect("center", tile.worldx(), tile.worldy());
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int minimapColor(Tile tile){
|
||||
return tile.<SorterEntity>ent().sortItem == null ? 0 : tile.<SorterEntity>ent().sortItem.color.rgba();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
Tile to = getTileTarget(item, tile, source, false);
|
||||
|
||||
return to != null && to.block().acceptItem(item, to, tile) && to.getTeam() == tile.getTeam();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
Tile to = getTileTarget(item, tile, source, true);
|
||||
|
||||
to.block().handleItem(item, to, tile);
|
||||
}
|
||||
|
||||
boolean isSame(Tile tile, Tile other){
|
||||
//uncomment comment below to prevent sorter/gate chaining (hacky)
|
||||
return other != null && (other.block() instanceof Sorter/* || other.block() instanceof OverflowGate */);
|
||||
}
|
||||
|
||||
Tile getTileTarget(Item item, Tile dest, Tile source, boolean flip){
|
||||
SorterEntity entity = dest.ent();
|
||||
|
||||
int dir = source.relativeTo(dest.x, dest.y);
|
||||
if(dir == -1) return null;
|
||||
Tile to;
|
||||
|
||||
if((item == entity.sortItem) != invert){
|
||||
//prevent 3-chains
|
||||
if(isSame(dest, source) && isSame(dest, dest.getNearby(dir))){
|
||||
return null;
|
||||
}
|
||||
to = dest.getNearby(dir);
|
||||
}else{
|
||||
Tile a = dest.getNearby(Mathf.mod(dir - 1, 4));
|
||||
Tile b = dest.getNearby(Mathf.mod(dir + 1, 4));
|
||||
boolean ac = a != null && !(a.block().instantTransfer && source.block().instantTransfer) &&
|
||||
a.block().acceptItem(item, a, dest);
|
||||
boolean bc = b != null && !(b.block().instantTransfer && source.block().instantTransfer) &&
|
||||
b.block().acceptItem(item, b, dest);
|
||||
|
||||
if(ac && !bc){
|
||||
to = a;
|
||||
}else if(bc && !ac){
|
||||
to = b;
|
||||
}else if(!bc){
|
||||
return null;
|
||||
}else{
|
||||
if(dest.rotation() == 0){
|
||||
to = a;
|
||||
if(flip) dest.rotation((byte)1);
|
||||
}else{
|
||||
to = b;
|
||||
if(flip) dest.rotation((byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
SorterEntity entity = tile.ent();
|
||||
ItemSelection.buildTable(table, content.items(), () -> entity.sortItem, item -> {
|
||||
lastItem = item;
|
||||
tile.configure(item == null ? -1 : item.id);
|
||||
});
|
||||
}
|
||||
|
||||
public class SorterEntity extends TileEntity{
|
||||
@Nullable Item sortItem;
|
||||
|
||||
@Override
|
||||
public int config(){
|
||||
return sortItem == null ? -1 : sortItem.id;
|
||||
public void playerPlaced(){
|
||||
if(lastItem != null){
|
||||
tile.configure(lastItem);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configured(Playerc player, Object value){
|
||||
super.configured(player, value);
|
||||
|
||||
if(!headless){
|
||||
renderer.minimap.update(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
if(sortItem == null){
|
||||
Draw.rect("cross", x, y);
|
||||
}else{
|
||||
Draw.color(sortItem.color);
|
||||
Draw.rect("center", x, y);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
Tilec to = getTileTarget(item, source, false);
|
||||
|
||||
return to != null && to.acceptItem(this, item) && to.team() == team;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Tilec source, Item item){
|
||||
Tilec to = getTileTarget(item, source, true);
|
||||
|
||||
to.handleItem(this, item);
|
||||
}
|
||||
|
||||
boolean isSame(Tilec other){
|
||||
//uncomment comment below to prevent sorter/gate chaining (hacky)
|
||||
return other != null && (other.block() instanceof Sorter/* || other.block() instanceof OverflowGate */);
|
||||
}
|
||||
|
||||
Tilec getTileTarget(Item item, Tilec source, boolean flip){
|
||||
int dir = source.relativeTo(tile.x, tile.y);
|
||||
if(dir == -1) return null;
|
||||
Tilec to;
|
||||
|
||||
if((item == sortItem) != invert){
|
||||
//prevent 3-chains
|
||||
if(isSame(source) && isSame(nearby(dir))){
|
||||
return null;
|
||||
}
|
||||
to = nearby(dir);
|
||||
}else{
|
||||
Tilec a = nearby(Mathf.mod(dir - 1, 4));
|
||||
Tilec b = nearby(Mathf.mod(dir + 1, 4));
|
||||
boolean ac = a != null && !(a.block().instantTransfer && source.block().instantTransfer) &&
|
||||
a.acceptItem(this, item);
|
||||
boolean bc = b != null && !(b.block().instantTransfer && source.block().instantTransfer) &&
|
||||
b.acceptItem(this, item);
|
||||
|
||||
if(ac && !bc){
|
||||
to = a;
|
||||
}else if(bc && !ac){
|
||||
to = b;
|
||||
}else if(!bc){
|
||||
return null;
|
||||
}else{
|
||||
if(rotation() == 0){
|
||||
to = a;
|
||||
if(flip) rotation((byte)1);
|
||||
}else{
|
||||
to = b;
|
||||
if(flip) rotation((byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ItemSelection.buildTable(table, content.items(), () -> sortItem, item -> tile.configure(lastItem = item));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item config(){
|
||||
return sortItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,17 +154,18 @@ public class Sorter extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeShort(sortItem == null ? -1 : sortItem.id);
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.s(sortItem == null ? -1 : sortItem.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
sortItem = content.item(stream.readShort());
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
sortItem = content.item(read.s());
|
||||
|
||||
if(revision == 1){
|
||||
new DirectionalItemBuffer(20, 45f).read(stream);
|
||||
new DirectionalItemBuffer(20, 45f).read(read);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
36
core/src/mindustry/world/blocks/environment/Cliff.java
Normal file
36
core/src/mindustry/world/blocks/environment/Cliff.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package mindustry.world.blocks.environment;
|
||||
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.util.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class Cliff extends Block{
|
||||
|
||||
public Cliff(String name){
|
||||
super(name);
|
||||
breakable = alwaysReplace = false;
|
||||
solid = true;
|
||||
cacheLayer = CacheLayer.walls;
|
||||
fillsTile = false;
|
||||
hasShadow = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBase(Tile tile){
|
||||
int r = tile.rotation();
|
||||
for(int i = 0; i < 8; i++){
|
||||
if((r & (1 << i)) != 0){
|
||||
Draw.color(Tmp.c1.set(tile.floor().mapColor).mul(1.3f + (i >= 4 ? -0.4f : 0.3f)));
|
||||
Draw.rect(region, tile.worldx(), tile.worldy(), 11f, 11f, i * 45f);
|
||||
}
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int minimapColor(Tile tile){
|
||||
return Tmp.c1.set(tile.floor().mapColor).mul(1.2f).rgba();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package mindustry.world.blocks;
|
||||
package mindustry.world.blocks.environment;
|
||||
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.math.Mathf;
|
||||
import mindustry.world.Tile;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class DoubleOverlayFloor extends OverlayFloor{
|
||||
|
||||
@@ -11,7 +11,7 @@ public class DoubleOverlayFloor extends OverlayFloor{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
public void drawBase(Tile tile){
|
||||
Draw.colorl(0.4f);
|
||||
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy() - 0.75f);
|
||||
Draw.color();
|
||||
@@ -1,21 +1,23 @@
|
||||
package mindustry.world.blocks;
|
||||
package mindustry.world.blocks.environment;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.graphics.g2d.TextureAtlas.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.graphics.MultiPacker.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Floor extends Block{
|
||||
/** number of different variant regions to use */
|
||||
@@ -35,13 +37,13 @@ public class Floor extends Block{
|
||||
/** Effect displayed when drowning on this floor. */
|
||||
public Effect drownUpdateEffect = Fx.bubble;
|
||||
/** Status effect applied when walking on. */
|
||||
public StatusEffect status = StatusEffects.none;
|
||||
public @NonNull StatusEffect status = StatusEffects.none;
|
||||
/** Intensity of applied status effect. */
|
||||
public float statusDuration = 60f;
|
||||
/** liquids that drop from this block, used for pumps */
|
||||
public Liquid liquidDrop = null;
|
||||
public @Nullable Liquid liquidDrop = null;
|
||||
/** item that drops from this block, used for drills */
|
||||
public Item itemDrop = null;
|
||||
public @Nullable Item itemDrop = null;
|
||||
/** whether this block can be drowned in */
|
||||
public boolean isLiquid;
|
||||
/** if true, this block cannot be mined by players. useful for annoying things like sand. */
|
||||
@@ -56,9 +58,12 @@ public class Floor extends Block{
|
||||
public boolean oreDefault = false;
|
||||
/** Ore generation params. */
|
||||
public float oreScale = 24f, oreThreshold = 0.828f;
|
||||
/** Wall variant of this block. May be Blocks.air if not found. */
|
||||
public Block wall = Blocks.air;
|
||||
/** Decoration block. Usually a rock. May be air. */
|
||||
public Block decoration = Blocks.air;
|
||||
|
||||
protected TextureRegion[][] edges;
|
||||
protected byte eq = 0;
|
||||
protected Array<Block> blenders = new Array<>();
|
||||
protected IntSet blended = new IntSet();
|
||||
protected TextureRegion edgeRegion;
|
||||
@@ -91,6 +96,24 @@ public class Floor extends Block{
|
||||
edgeRegion = Core.atlas.find("edge");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
super.init();
|
||||
|
||||
if(wall == Blocks.air){
|
||||
wall = content.block(name + "Rocks");
|
||||
if(wall == null) wall = content.block(name + "rocks");
|
||||
if(wall == null) wall = content.block(name.replace("darksand", "dune") + "rocks");
|
||||
}
|
||||
|
||||
//keep default value if not found...
|
||||
if(wall == null) wall = Blocks.air;
|
||||
|
||||
if(decoration == Blocks.air){
|
||||
decoration = content.blocks().min(b -> b instanceof Rock && b.breakable ? mapColor.diff(b.mapColor) : Float.POSITIVE_INFINITY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createIcons(MultiPacker packer){
|
||||
super.createIcons(packer);
|
||||
@@ -129,7 +152,7 @@ public class Floor extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
public void drawBase(Tile tile){
|
||||
Mathf.random.setSeed(tile.pos());
|
||||
|
||||
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
|
||||
@@ -138,7 +161,7 @@ public class Floor extends Block{
|
||||
|
||||
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.draw(tile);
|
||||
floor.drawBase(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +182,6 @@ public class Floor extends Block{
|
||||
protected void drawEdges(Tile tile, boolean sameLayer){
|
||||
blenders.clear();
|
||||
blended.clear();
|
||||
eq = 0;
|
||||
|
||||
for(int i = 0; i < 8; i++){
|
||||
Point2 point = Geometry.d8[i];
|
||||
@@ -168,11 +190,10 @@ public class Floor extends Block{
|
||||
if(blended.add(other.floor().id)){
|
||||
blenders.add(other.floor());
|
||||
}
|
||||
eq |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
blenders.sort((a, b) -> Integer.compare(a.id, b.id));
|
||||
blenders.sort(a -> a.id);
|
||||
|
||||
for(Block block : blenders){
|
||||
for(int i = 0; i < 8; i++){
|
||||
@@ -196,7 +217,7 @@ public class Floor extends Block{
|
||||
for(int i = 0; i < 4; i++){
|
||||
Tile other = tile.getNearby(i);
|
||||
if(other != null && doEdge(other.floor(), sameLayer)){
|
||||
Color color = other.floor().color;
|
||||
Color color = other.floor().mapColor;
|
||||
Draw.color(color.r, color.g, color.b, 1f);
|
||||
Draw.rect(edgeRegion, tile.worldx(), tile.worldy(), i*90);
|
||||
}
|
||||
@@ -210,11 +231,7 @@ public class Floor extends Block{
|
||||
}
|
||||
|
||||
protected boolean doEdge(Floor other, boolean sameLayer){
|
||||
return (other.blendGroup.id > blendGroup.id || edges() == null) && other.edgeOnto(this) && (other.cacheLayer.ordinal() > this.cacheLayer.ordinal() || !sameLayer);
|
||||
}
|
||||
|
||||
protected boolean edgeOnto(Floor other){
|
||||
return true;
|
||||
return (((other.blendGroup.id > blendGroup.id) || edges() == null) && (other.cacheLayer.ordinal() > this.cacheLayer.ordinal() || !sameLayer));
|
||||
}
|
||||
|
||||
TextureRegion edge(Floor block, int x, int y){
|
||||
@@ -1,4 +1,4 @@
|
||||
package mindustry.world.blocks;
|
||||
package mindustry.world.blocks.environment;
|
||||
|
||||
import arc.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
@@ -19,7 +19,7 @@ public class OreBlock extends OverlayFloor{
|
||||
this.localizedName = ore.localizedName;
|
||||
this.itemDrop = ore;
|
||||
this.variants = 3;
|
||||
this.color.set(ore.color);
|
||||
this.mapColor.set(ore.color);
|
||||
}
|
||||
|
||||
/** For mod use only!*/
|
||||
@@ -31,7 +31,7 @@ public class OreBlock extends OverlayFloor{
|
||||
public void setup(Item ore){
|
||||
this.localizedName = ore.localizedName;
|
||||
this.itemDrop = ore;
|
||||
this.color.set(ore.color);
|
||||
this.mapColor.set(ore.color);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,4 +1,4 @@
|
||||
package mindustry.world.blocks;
|
||||
package mindustry.world.blocks.environment;
|
||||
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.math.Mathf;
|
||||
@@ -12,7 +12,7 @@ public class OverlayFloor extends Floor{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
public void drawBase(Tile tile){
|
||||
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package mindustry.world.blocks;
|
||||
package mindustry.world.blocks.environment;
|
||||
|
||||
import arc.Core;
|
||||
import arc.graphics.g2d.Draw;
|
||||
@@ -17,7 +17,7 @@ public class Rock extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
public void drawBase(Tile tile){
|
||||
if(variants > 0){
|
||||
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
|
||||
}else{
|
||||
@@ -0,0 +1,24 @@
|
||||
package mindustry.world.blocks.environment;
|
||||
|
||||
import mindustry.world.*;
|
||||
|
||||
//do not use in mods!
|
||||
public class ShallowLiquid extends Floor{
|
||||
public Floor liquidBase, floorBase;
|
||||
public float liquidOpacity = 0.35f;
|
||||
|
||||
public ShallowLiquid(String name){
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void set(Block liquid, Block floor){
|
||||
this.liquidBase = liquid.asFloor();
|
||||
this.floorBase = floor.asFloor();
|
||||
|
||||
isLiquid = true;
|
||||
variants = floorBase.variants;
|
||||
status = liquidBase.status;
|
||||
liquidDrop = liquidBase.liquidDrop;
|
||||
cacheLayer = liquidBase.cacheLayer;
|
||||
}
|
||||
}
|
||||
43
core/src/mindustry/world/blocks/environment/StaticTree.java
Normal file
43
core/src/mindustry/world/blocks/environment/StaticTree.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package mindustry.world.blocks.environment;
|
||||
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.util.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
public class StaticTree extends StaticWall{
|
||||
|
||||
public StaticTree(String name){
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBase(Tile tile){
|
||||
TextureRegion r = Tmp.tr1;
|
||||
r.set(region);
|
||||
int crop = (region.getWidth() - tilesize*4) / 2;
|
||||
float ox = 0;
|
||||
float oy = 0;
|
||||
|
||||
for(int i = 0; i < 4; i++){
|
||||
if(tile.getNearby(i) != null && tile.getNearby(i).block() instanceof StaticWall){
|
||||
|
||||
if(i == 0){
|
||||
r.setWidth(r.getWidth() - crop);
|
||||
ox -= crop /2f;
|
||||
}else if(i == 1){
|
||||
r.setY(r.getY() + crop);
|
||||
oy -= crop /2f;
|
||||
}else if(i == 2){
|
||||
r.setX(r.getX() + crop);
|
||||
ox += crop /2f;
|
||||
}else{
|
||||
r.setHeight(r.getHeight() - crop);
|
||||
oy += crop /2f;
|
||||
}
|
||||
}
|
||||
}
|
||||
Draw.rect(r, tile.drawx() + ox * Draw.scl, tile.drawy() + oy * Draw.scl);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
package mindustry.world.blocks;
|
||||
package mindustry.world.blocks.environment;
|
||||
|
||||
import arc.Core;
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.Mathf;
|
||||
import mindustry.graphics.CacheLayer;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.Vars.world;
|
||||
|
||||
public class StaticWall extends Rock{
|
||||
TextureRegion large;
|
||||
@@ -21,11 +22,11 @@ public class StaticWall extends Rock{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
public void drawBase(Tile tile){
|
||||
int rx = tile.x / 2 * 2;
|
||||
int ry = tile.y / 2 * 2;
|
||||
|
||||
if(Core.atlas.isFound(large) && eq(rx, ry) && Mathf.randomSeed(Pos.get(rx, ry)) < 0.5){
|
||||
if(Core.atlas.isFound(large) && eq(rx, ry) && Mathf.randomSeed(Point2.pack(rx, ry)) < 0.5){
|
||||
Draw.rect(split[tile.x % 2][1 - tile.y % 2], tile.worldx(), tile.worldy());
|
||||
}else if(variants > 0){
|
||||
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
|
||||
@@ -1,4 +1,4 @@
|
||||
package mindustry.world.blocks;
|
||||
package mindustry.world.blocks.environment;
|
||||
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.math.Mathf;
|
||||
@@ -16,10 +16,10 @@ public class TreeBlock extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){}
|
||||
public void drawBase(Tile tile){}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
Draw.rect(region, tile.drawx(), tile.drawy(), Mathf.randomSeed(tile.pos(), 0, 4) * 90);
|
||||
Draw.rect(region, tile.worldx(), tile.worldy(), Mathf.randomSeed(tile.pos(), 0, 4) * 90);
|
||||
}
|
||||
}
|
||||
11
core/src/mindustry/world/blocks/legacy/LegacyBlock.java
Normal file
11
core/src/mindustry/world/blocks/legacy/LegacyBlock.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package mindustry.world.blocks.legacy;
|
||||
|
||||
import mindustry.world.*;
|
||||
|
||||
/** Any subclass of this will be removed upon world load. */
|
||||
public class LegacyBlock extends Block{
|
||||
|
||||
public LegacyBlock(String name){
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package mindustry.world.blocks.legacy;
|
||||
|
||||
import arc.util.io.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class LegacyCommandCenter extends Block{
|
||||
|
||||
public LegacyCommandCenter(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
}
|
||||
|
||||
public class LegacyCommandCenterEntity extends TileEntity{
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
read.b();
|
||||
}
|
||||
}
|
||||
}
|
||||
25
core/src/mindustry/world/blocks/legacy/LegacyMechPad.java
Normal file
25
core/src/mindustry/world/blocks/legacy/LegacyMechPad.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package mindustry.world.blocks.legacy;
|
||||
|
||||
import arc.util.io.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
public class LegacyMechPad extends LegacyBlock{
|
||||
|
||||
public LegacyMechPad(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
hasPower = true;
|
||||
}
|
||||
|
||||
public class LegacyMechPadEntity extends TileEntity{
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
//read 3 floats for pad data, and discard them
|
||||
read.f();
|
||||
read.f();
|
||||
read.f();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package mindustry.world.blocks.legacy;
|
||||
|
||||
import arc.util.io.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class LegacyUnitFactory extends Block{
|
||||
|
||||
public LegacyUnitFactory(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
hasPower = true;
|
||||
hasItems = true;
|
||||
solid = false;
|
||||
}
|
||||
|
||||
public class LegacyUnitFactoryEntity extends TileEntity{
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
//build time
|
||||
read.f();
|
||||
|
||||
if(revision == 0){
|
||||
//spawn count
|
||||
read.i();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
package mindustry.world.blocks.liquid;
|
||||
|
||||
import arc.Core;
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.graphics.g2d.TextureRegion;
|
||||
import mindustry.type.Liquid;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Edges;
|
||||
import mindustry.world.Tile;
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class ArmoredConduit extends Conduit{
|
||||
public TextureRegion capRegion;
|
||||
@@ -22,24 +20,26 @@ public class ArmoredConduit extends Conduit{
|
||||
capRegion = Core.atlas.find(name + "-cap");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
// draw the cap when a conduit would normally leak
|
||||
Tile next = tile.front();
|
||||
if(next != null && next.getTeam() == tile.getTeam() && next.block().hasLiquids) return;
|
||||
|
||||
Draw.rect(capRegion, tile.drawx(), tile.drawy(), tile.rotation() * 90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
return super.acceptLiquid(tile, source, liquid, amount) && (source.block() instanceof Conduit) || Edges.getFacingEdge(source, tile).relativeTo(tile) == tile.rotation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
||||
return otherblock.outputsLiquid && blendsArmored(tile, rotation, otherx, othery, otherrot, otherblock);
|
||||
}
|
||||
|
||||
public class ArmoredConduitEntity extends ConduitEntity{
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
// draw the cap when a conduit would normally leak
|
||||
Tilec next = tile.front();
|
||||
if(next != null && next.team() == team && next.block().hasLiquids) return;
|
||||
|
||||
Draw.rect(capRegion, x, y, tile.rotation() * 90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tilec source, Liquid liquid, float amount){
|
||||
return super.acceptLiquid(source, liquid, amount) && (source.block() instanceof Conduit) || Edges.getFacingEdge(source.tile(), tile).absoluteRelativeTo(tile.x, tile.y) == tile.rotation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
@@ -28,7 +28,6 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
solid = false;
|
||||
floating = true;
|
||||
conveyorPlacement = true;
|
||||
entityType = ConduitEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,15 +41,6 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(Tile tile){
|
||||
super.onProximityUpdate(tile);
|
||||
|
||||
ConduitEntity entity = tile.ent();
|
||||
int[] bits = buildBlending(tile, tile.rotation(), null, true);
|
||||
entity.blendbits = bits[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRequestRegion(BuildRequest req, Eachable<BuildRequest> list){
|
||||
int[] bits = getTiling(req, list);
|
||||
@@ -88,50 +78,54 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
return otherblock.hasLiquids && otherblock.outputsLiquid && lookingAt(tile, rotation, otherx, othery, otherrot, otherblock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
ConduitEntity entity = tile.ent();
|
||||
int rotation = tile.rotation() * 90;
|
||||
|
||||
Draw.colorl(0.34f);
|
||||
Draw.rect(botRegions[entity.blendbits], tile.drawx(), tile.drawy(), rotation);
|
||||
|
||||
Draw.color(tile.entity.liquids.current().color);
|
||||
Draw.alpha(entity.smoothLiquid);
|
||||
Draw.rect(botRegions[entity.blendbits], tile.drawx(), tile.drawy(), rotation);
|
||||
Draw.color();
|
||||
|
||||
Draw.rect(topRegions[entity.blendbits], tile.drawx(), tile.drawy(), rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ConduitEntity entity = tile.ent();
|
||||
entity.smoothLiquid = Mathf.lerpDelta(entity.smoothLiquid, entity.liquids.currentAmount() / liquidCapacity, 0.05f);
|
||||
|
||||
if(tile.entity.liquids.total() > 0.001f && tile.entity.timer.get(timerFlow, 1)){
|
||||
tryMoveLiquid(tile, tile.getNearby(tile.rotation()), leakResistance, tile.entity.liquids.current());
|
||||
entity.noSleep();
|
||||
}else{
|
||||
entity.sleep();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find("conduit-bottom"), Core.atlas.find(name + "-top-0")};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
tile.entity.noSleep();
|
||||
return tile.entity.liquids.get(liquid) + amount < liquidCapacity && (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.2f)
|
||||
&& ((source.absoluteRelativeTo(tile.x, tile.y) + 2) % 4 != tile.rotation());
|
||||
}
|
||||
|
||||
public static class ConduitEntity extends TileEntity{
|
||||
public class ConduitEntity extends LiquidBlockEntity{
|
||||
public float smoothLiquid;
|
||||
|
||||
int blendbits;
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
int rotation = rotation() * 90;
|
||||
|
||||
Draw.colorl(0.34f);
|
||||
Draw.rect(botRegions[blendbits], x, y, rotation);
|
||||
|
||||
Draw.color(liquids.current().color);
|
||||
Draw.alpha(smoothLiquid);
|
||||
Draw.rect(botRegions[blendbits], x, y, rotation);
|
||||
Draw.color();
|
||||
|
||||
Draw.rect(topRegions[blendbits], x, y, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(){
|
||||
super.onProximityUpdate();
|
||||
|
||||
blendbits = buildBlending(tile, rotation(), null, true)[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tilec source, Liquid liquid, float amount){
|
||||
noSleep();
|
||||
return liquids.get(liquid) + amount < liquidCapacity && (liquids.current() == liquid || liquids.currentAmount() < 0.2f)
|
||||
&& ((source.absoluteRelativeTo(tile.x, tile.y) + 2) % 4 != tile.rotation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
smoothLiquid = Mathf.lerpDelta(smoothLiquid, liquids.currentAmount() / liquidCapacity, 0.05f);
|
||||
|
||||
if(liquids.total() > 0.001f && timer(timerFlow, 1)){
|
||||
moveLiquid(tile.getNearbyEntity(rotation()), leakResistance, liquids.current());
|
||||
noSleep();
|
||||
}else{
|
||||
sleep();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
51
core/src/mindustry/world/blocks/liquid/LiquidBlock.java
Normal file
51
core/src/mindustry/world/blocks/liquid/LiquidBlock.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package mindustry.world.blocks.liquid;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class LiquidBlock extends Block{
|
||||
protected TextureRegion liquidRegion, bottomRegion, topRegion;
|
||||
|
||||
public LiquidBlock(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
solid = true;
|
||||
hasLiquids = true;
|
||||
group = BlockGroup.liquids;
|
||||
outputsLiquid = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
super.load();
|
||||
|
||||
liquidRegion = Core.atlas.find(name + "-liquid");
|
||||
topRegion = Core.atlas.find(name + "-top");
|
||||
bottomRegion = Core.atlas.find(name + "-bottom");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find(name + "-bottom"), Core.atlas.find(name + "-top")};
|
||||
}
|
||||
|
||||
public class LiquidBlockEntity extends TileEntity{
|
||||
@Override
|
||||
public void draw(){
|
||||
int rotation = rotate ? rotation() * 90 : 0;
|
||||
Draw.rect(bottomRegion, x, y, rotation);
|
||||
|
||||
if(liquids.total() > 0.001f){
|
||||
Draw.color(liquids.current().color);
|
||||
Draw.alpha(liquids.total() / liquidCapacity);
|
||||
Draw.rect(liquidRegion, x, y, rotation);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
Draw.rect(topRegion, x, y, rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
package mindustry.world.blocks.liquid;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.distribution.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
@@ -19,42 +18,44 @@ public class LiquidBridge extends ItemBridge{
|
||||
group = BlockGroup.liquids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
public class LiquidBridgeEntity extends ItemBridgeEntity{
|
||||
@Override
|
||||
public void updateTile(){
|
||||
time += cycleSpeed * delta();
|
||||
time2 += (cycleSpeed - 1f) * delta();
|
||||
|
||||
entity.time += entity.cycleSpeed * Time.delta();
|
||||
entity.time2 += (entity.cycleSpeed - 1f) * Time.delta();
|
||||
checkIncoming();
|
||||
|
||||
Tile other = world.tile(entity.link);
|
||||
if(!linkValid(tile, other)){
|
||||
tryDumpLiquid(tile, entity.liquids.current());
|
||||
}else{
|
||||
((ItemBridgeEntity)world.tile(entity.link).entity).incoming.add(tile.pos());
|
||||
|
||||
if(entity.cons.valid()){
|
||||
float alpha = 0.04f;
|
||||
if(hasPower){
|
||||
alpha *= entity.efficiency(); // Exceed boot time unless power is at max.
|
||||
}
|
||||
entity.uptime = Mathf.lerpDelta(entity.uptime, 1f, alpha);
|
||||
Tilec other = world.ent(link);
|
||||
if(other == null || !linkValid(tile, other.tile())){
|
||||
dumpLiquid(liquids.current());
|
||||
}else{
|
||||
entity.uptime = Mathf.lerpDelta(entity.uptime, 0f, 0.02f);
|
||||
}
|
||||
((ItemBridgeEntity)other).incoming.add(tile.pos());
|
||||
|
||||
if(entity.uptime >= 0.5f){
|
||||
|
||||
if(tryMoveLiquid(tile, other, false, entity.liquids.current()) > 0.1f){
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 4f, 0.05f);
|
||||
if(consValid()){
|
||||
float alpha = 0.04f;
|
||||
if(hasPower){
|
||||
alpha *= efficiency(); // Exceed boot time unless power is at max.
|
||||
}
|
||||
uptime = Mathf.lerpDelta(uptime, 1f, alpha);
|
||||
}else{
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 1f, 0.01f);
|
||||
uptime = Mathf.lerpDelta(uptime, 0f, 0.02f);
|
||||
}
|
||||
|
||||
if(uptime >= 0.5f){
|
||||
|
||||
if(moveLiquid(other, false, liquids.current()) > 0.1f){
|
||||
cycleSpeed = Mathf.lerpDelta(cycleSpeed, 4f, 0.05f);
|
||||
}else{
|
||||
cycleSpeed = Mathf.lerpDelta(cycleSpeed, 1f, 0.01f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return false;
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package mindustry.world.blocks.liquid;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.distribution.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
@@ -19,37 +18,39 @@ public class LiquidExtendingBridge extends ExtendingItemBridge{
|
||||
group = BlockGroup.liquids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ItemBridgeEntity entity = tile.ent();
|
||||
public class LiquidExtendingBridgeEntity extends ExtendingItemBridgeEntity{
|
||||
@Override
|
||||
public void updateTile(){
|
||||
time += cycleSpeed * delta();
|
||||
time2 += (cycleSpeed - 1f) * delta();
|
||||
|
||||
entity.time += entity.cycleSpeed * Time.delta();
|
||||
entity.time2 += (entity.cycleSpeed - 1f) * Time.delta();
|
||||
checkIncoming();
|
||||
|
||||
Tile other = world.tile(entity.link);
|
||||
if(!linkValid(tile, other)){
|
||||
tryDumpLiquid(tile, entity.liquids.current());
|
||||
}else{
|
||||
((ItemBridgeEntity)world.tile(entity.link).entity).incoming.add(tile.pos());
|
||||
|
||||
if(entity.cons.valid()){
|
||||
entity.uptime = Mathf.lerpDelta(entity.uptime, 1f, 0.04f);
|
||||
Tilec other = world.ent(link);
|
||||
if(other == null || !linkValid(tile, other.tile())){
|
||||
dumpLiquid(liquids.current());
|
||||
}else{
|
||||
entity.uptime = Mathf.lerpDelta(entity.uptime, 0f, 0.02f);
|
||||
}
|
||||
((ItemBridgeEntity)other).incoming.add(tile.pos());
|
||||
|
||||
if(entity.uptime >= 0.5f){
|
||||
if(tryMoveLiquid(tile, other, false, entity.liquids.current()) > 0.1f){
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 4f, 0.05f);
|
||||
if(consValid()){
|
||||
uptime = Mathf.lerpDelta(uptime, 1f, 0.04f);
|
||||
}else{
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 1f, 0.01f);
|
||||
uptime = Mathf.lerpDelta(uptime, 0f, 0.02f);
|
||||
}
|
||||
|
||||
if(uptime >= 0.5f){
|
||||
if(moveLiquid(other, false, liquids.current()) > 0.1f){
|
||||
cycleSpeed = Mathf.lerpDelta(cycleSpeed, 4f, 0.05f);
|
||||
}else{
|
||||
cycleSpeed = Mathf.lerpDelta(cycleSpeed, 1f, 0.01f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return false;
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@ package mindustry.world.blocks.liquid;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class LiquidJunction extends LiquidBlock{
|
||||
@@ -25,24 +24,28 @@ public class LiquidJunction extends LiquidBlock{
|
||||
bars.remove("liquid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
Draw.rect(name, tile.worldx(), tile.worldy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find(name)};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tile getLiquidDestination(Tile tile, Tile source, Liquid liquid){
|
||||
int dir = source.relativeTo(tile.x, tile.y);
|
||||
dir = (dir + 4) % 4;
|
||||
Tile next = tile.getNearbyLink(dir);
|
||||
if(next == null || !next.block().acceptLiquid(next, tile, liquid, 0f) && !(next.block() instanceof LiquidJunction)){
|
||||
return tile;
|
||||
public class LiquidJunctionEntity extends TileEntity{
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect(region, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tilec getLiquidDestination(Tilec source, Liquid liquid){
|
||||
int dir = source.absoluteRelativeTo(tile.x, tile.y);
|
||||
dir = (dir + 4) % 4;
|
||||
Tilec next = nearby(dir);
|
||||
if(next == null || (!next.acceptLiquid(this, liquid, 0f) && !(next.block() instanceof LiquidJunction))){
|
||||
return this;
|
||||
}
|
||||
return next.getLiquidDestination(this, liquid);
|
||||
}
|
||||
return next.block().getLiquidDestination(next, tile, liquid);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package mindustry.world.blocks.liquid;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
//TODO implement later
|
||||
public class LiquidOverflowGate extends LiquidBlock{
|
||||
public int topRegion;
|
||||
|
||||
public LiquidOverflowGate(String name){
|
||||
super(name);
|
||||
rotate = true;
|
||||
topRegion = reg("-top");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
stats.remove(BlockStat.liquidCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBars(){
|
||||
super.setBars();
|
||||
bars.remove("liquid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
Draw.rect(name, tile.drawx(), tile.drawy());
|
||||
Draw.rect(reg(topRegion), tile.drawx(), tile.drawy(), tile.rotation() * 90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-top")};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tile getLiquidDestination(Tile tile, Tile source, Liquid liquid){
|
||||
int dir = source.relativeTo(tile.x, tile.y);
|
||||
dir = (dir + 4) % 4;
|
||||
Tile next = tile.getNearby(dir).link();
|
||||
if(!next.block().acceptLiquid(next, tile, liquid, 0.0001f) && !(next.block() instanceof LiquidOverflowGate || next.block() instanceof LiquidJunction)){
|
||||
return tile;
|
||||
}
|
||||
return next.block().getLiquidDestination(next, tile, liquid);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
package mindustry.world.blocks.liquid;
|
||||
|
||||
import mindustry.type.Liquid;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.blocks.LiquidBlock;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
public class LiquidRouter extends LiquidBlock{
|
||||
|
||||
@@ -10,16 +9,17 @@ public class LiquidRouter extends LiquidBlock{
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
public class LiquidRouterEntity extends LiquidBlockEntity{
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(liquids.total() > 0.01f){
|
||||
dumpLiquid(liquids.current());
|
||||
}
|
||||
}
|
||||
|
||||
if(tile.entity.liquids.total() > 0.01f){
|
||||
tryDumpLiquid(tile, tile.entity.liquids.current());
|
||||
@Override
|
||||
public boolean acceptLiquid(Tilec source, Liquid liquid, float amount){
|
||||
return liquids.get(liquid) + amount < liquidCapacity && (liquids.current() == liquid || liquids.currentAmount() < 0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
return tile.entity.liquids.get(liquid) + amount < liquidCapacity && (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package mindustry.world.blocks.liquid;
|
||||
|
||||
public class LiquidTank extends LiquidRouter{
|
||||
|
||||
public LiquidTank(String name){
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package mindustry.world.blocks.logic;
|
||||
|
||||
import mindustry.world.Block;
|
||||
|
||||
public class LogicBlock extends Block{
|
||||
|
||||
public LogicBlock(String name){
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
113
core/src/mindustry/world/blocks/logic/LogicExecutor.java
Normal file
113
core/src/mindustry/world/blocks/logic/LogicExecutor.java
Normal file
@@ -0,0 +1,113 @@
|
||||
package mindustry.world.blocks.logic;
|
||||
|
||||
import arc.math.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
public class LogicExecutor{
|
||||
Instruction[] instructions;
|
||||
int[] registers = new int[256];
|
||||
int counter;
|
||||
|
||||
void step(){
|
||||
if(instructions.length == 0) return;
|
||||
|
||||
instructions[counter].exec();
|
||||
counter ++;
|
||||
|
||||
//loop counter
|
||||
if(counter >= instructions.length) counter = 0;
|
||||
}
|
||||
|
||||
Tilec device(short id){
|
||||
return null; //TODO
|
||||
}
|
||||
|
||||
interface Instruction{
|
||||
void exec();
|
||||
}
|
||||
|
||||
class RegisterI implements Instruction{
|
||||
/** operation to perform */
|
||||
Op op;
|
||||
/** destination register */
|
||||
short dest;
|
||||
/** registers to take data from. -1 for no register. */
|
||||
short left, right;
|
||||
/** left/right immediate values, only used if no registers are present. */
|
||||
int ileft, iright;
|
||||
|
||||
@Override
|
||||
public void exec(){
|
||||
registers[dest] = op.function.get(left == -1 ? ileft : registers[left], right == -1 ? iright : registers[right]);
|
||||
}
|
||||
}
|
||||
|
||||
class ReadI implements Instruction{
|
||||
/** register to write result to */
|
||||
short dest;
|
||||
/** device to read from */
|
||||
short device;
|
||||
/** the type of data to be read */
|
||||
ReadOp op;
|
||||
/** any additional read parameters */
|
||||
int parameter;
|
||||
|
||||
@Override
|
||||
public void exec(){
|
||||
registers[dest] = op.function.get(device(device), parameter);
|
||||
}
|
||||
}
|
||||
|
||||
class WriteI implements Instruction{
|
||||
|
||||
@Override
|
||||
public void exec(){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
enum ReadOp{
|
||||
item((tile, id) -> tile.items() == null ? 0 : tile.items().get(id)),
|
||||
itemTotal((tile, param) -> tile.items() == null ? 0 : tile.items().total());
|
||||
|
||||
final ReadOpLambda function;
|
||||
final String symbol;
|
||||
|
||||
ReadOp(ReadOpLambda function){
|
||||
this.symbol = name();
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
interface ReadOpLambda{
|
||||
int get(Tilec tile, int parameter);
|
||||
}
|
||||
}
|
||||
|
||||
enum Op{
|
||||
add("+", (a, b) -> a + b),
|
||||
sub("-", (a, b) -> a - b),
|
||||
mul("*", (a, b) -> a * b),
|
||||
div("/", (a, b) -> a / b),
|
||||
mod("%", (a, b) -> a % b),
|
||||
pow("^", Mathf::pow),
|
||||
shl(">>", (a, b) -> a >> b),
|
||||
shr("<<", (a, b) -> a << b),
|
||||
or("or", (a, b) -> a | b),
|
||||
and("and", (a, b) -> a & b),
|
||||
xor("xor", (a, b) -> a ^ b);
|
||||
|
||||
final OpLambda function;
|
||||
final String symbol;
|
||||
|
||||
Op(String symbol, OpLambda function){
|
||||
this.symbol = symbol;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
interface OpLambda{
|
||||
int get(int a, int b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package mindustry.world.blocks.logic;
|
||||
|
||||
import arc.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import arc.Input.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
@@ -9,141 +8,52 @@ import arc.math.geom.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.dialogs.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class MessageBlock extends Block{
|
||||
protected static int maxTextLength = 220;
|
||||
protected static int maxNewlines = 24;
|
||||
//don't change this too much unless you want to run into issues with packet sizes
|
||||
public int maxTextLength = 220;
|
||||
public int maxNewlines = 24;
|
||||
|
||||
public MessageBlock(String name){
|
||||
super(name);
|
||||
configurable = true;
|
||||
solid = true;
|
||||
destructible = true;
|
||||
entityType = MessageBlockEntity::new;
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.both, forward = true)
|
||||
public static void setMessageBlockText(Player player, Tile tile, String text){
|
||||
if(!Units.canInteract(player, tile)) return;
|
||||
if(net.server() && text.length() > maxTextLength){
|
||||
throw new ValidateException(player, "Player has gone above text limit.");
|
||||
}
|
||||
config(String.class, (tile, text) -> {
|
||||
MessageBlockEntity entity = (MessageBlockEntity)tile;
|
||||
|
||||
//can be broken while a player is typing
|
||||
if(!(tile.block() instanceof MessageBlock)){
|
||||
return;
|
||||
}
|
||||
if(net.server() && text.length() > maxTextLength){
|
||||
throw new ValidateException(player, "Player has gone above text limit.");
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder(text.length());
|
||||
text = text.trim();
|
||||
int count = 0;
|
||||
for(int i = 0; i < text.length(); i++){
|
||||
char c = text.charAt(i);
|
||||
if(c == '\n' || c == '\r'){
|
||||
count ++;
|
||||
if(count <= maxNewlines){
|
||||
result.append('\n');
|
||||
StringBuilder result = new StringBuilder(text.length());
|
||||
text = text.trim();
|
||||
int count = 0;
|
||||
for(int i = 0; i < text.length(); i++){
|
||||
char c = text.charAt(i);
|
||||
if(c == '\n' || c == '\r'){
|
||||
count ++;
|
||||
if(count <= maxNewlines){
|
||||
result.append('\n');
|
||||
}
|
||||
}else{
|
||||
result.append(c);
|
||||
}
|
||||
}else{
|
||||
result.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
MessageBlockEntity entity = tile.ent();
|
||||
if(entity != null){
|
||||
entity.message = result.toString();
|
||||
entity.lines = entity.message.split("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
MessageBlockEntity entity = tile.ent();
|
||||
BitmapFont font = Fonts.outline;
|
||||
GlyphLayout l = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
|
||||
boolean ints = font.usesIntegerPositions();
|
||||
font.getData().setScale(1 / 4f / Scl.scl(1f));
|
||||
font.setUseIntegerPositions(false);
|
||||
|
||||
String text = entity.message == null || entity.message.isEmpty() ? "[lightgray]" + Core.bundle.get("empty") : entity.message;
|
||||
|
||||
l.setText(font, text, Color.white, 90f, Align.left, true);
|
||||
float offset = 1f;
|
||||
|
||||
Draw.color(0f, 0f, 0f, 0.2f);
|
||||
Fill.rect(tile.drawx(), tile.drawy() - tilesize/2f - l.height/2f - offset, l.width + offset*2f, l.height + offset*2f);
|
||||
Draw.color();
|
||||
font.setColor(Color.white);
|
||||
font.draw(text, tile.drawx() - l.width/2f, tile.drawy() - tilesize/2f - offset, 90f, Align.left, true);
|
||||
font.setUseIntegerPositions(ints);
|
||||
|
||||
font.getData().setScale(1f);
|
||||
|
||||
Pools.free(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
MessageBlockEntity entity = tile.ent();
|
||||
|
||||
table.addImageButton(Icon.pencil, () -> {
|
||||
if(mobile){
|
||||
Core.input.getTextInput(new TextInput(){{
|
||||
text = entity.message;
|
||||
multiline = true;
|
||||
maxLength = maxTextLength;
|
||||
accepted = out -> {
|
||||
Call.setMessageBlockText(player, tile, out);
|
||||
};
|
||||
}});
|
||||
}else{
|
||||
FloatingDialog dialog = new FloatingDialog("$editmessage");
|
||||
dialog.setFillParent(false);
|
||||
TextArea a = dialog.cont.add(new TextArea(entity.message.replace("\n", "\r"))).size(380f, 160f).get();
|
||||
a.setFilter((textField, c) -> {
|
||||
if(c == '\n' || c == '\r'){
|
||||
int count = 0;
|
||||
for(int i = 0; i < textField.getText().length(); i++){
|
||||
if(textField.getText().charAt(i) == '\n' || textField.getText().charAt(i) == '\r'){
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count < maxNewlines;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
a.setMaxLength(maxTextLength);
|
||||
dialog.buttons.addButton("$ok", () -> {
|
||||
Call.setMessageBlockText(player, tile, a.getText());
|
||||
dialog.hide();
|
||||
}).size(130f, 60f);
|
||||
dialog.update(() -> {
|
||||
if(!entity.isValid()){
|
||||
dialog.hide();
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
control.input.frag.config.hideConfig();
|
||||
}).size(40f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTableAlign(Tile tile, Table table){
|
||||
Vec2 pos = Core.input.mouseScreen(tile.drawx(), tile.drawy() + tile.block().size * tilesize / 2f + 1);
|
||||
table.setPosition(pos.x, pos.y, Align.bottom);
|
||||
});
|
||||
}
|
||||
|
||||
public class MessageBlockEntity extends TileEntity{
|
||||
@@ -151,15 +61,93 @@ public class MessageBlock extends Block{
|
||||
public String[] lines = {""};
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeUTF(message);
|
||||
public void drawSelect(){
|
||||
BitmapFont font = Fonts.outline;
|
||||
GlyphLayout l = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
|
||||
boolean ints = font.usesIntegerPositions();
|
||||
font.getData().setScale(1 / 4f / Scl.scl(1f));
|
||||
font.setUseIntegerPositions(false);
|
||||
|
||||
String text = message == null || message.isEmpty() ? "[lightgray]" + Core.bundle.get("empty") : message;
|
||||
|
||||
l.setText(font, text, Color.white, 90f, Align.left, true);
|
||||
float offset = 1f;
|
||||
|
||||
Draw.color(0f, 0f, 0f, 0.2f);
|
||||
Fill.rect(x, y - tilesize/2f - l.height/2f - offset, l.width + offset*2f, l.height + offset*2f);
|
||||
Draw.color();
|
||||
font.setColor(Color.white);
|
||||
font.draw(text, x - l.width/2f, y - tilesize/2f - offset, 90f, Align.left, true);
|
||||
font.setUseIntegerPositions(ints);
|
||||
|
||||
font.getData().setScale(1f);
|
||||
|
||||
Pools.free(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
message = stream.readUTF();
|
||||
public void buildConfiguration(Table table){
|
||||
table.addImageButton(Icon.pencil, () -> {
|
||||
if(mobile){
|
||||
Core.input.getTextInput(new TextInput(){{
|
||||
text = message;
|
||||
multiline = true;
|
||||
maxLength = maxTextLength;
|
||||
accepted = tile::configure;
|
||||
}});
|
||||
}else{
|
||||
FloatingDialog dialog = new FloatingDialog("$editmessage");
|
||||
dialog.setFillParent(false);
|
||||
TextArea a = dialog.cont.add(new TextArea(message.replace("\n", "\r"))).size(380f, 160f).get();
|
||||
a.setFilter((textField, c) -> {
|
||||
if(c == '\n' || c == '\r'){
|
||||
int count = 0;
|
||||
for(int i = 0; i < textField.getText().length(); i++){
|
||||
if(textField.getText().charAt(i) == '\n' || textField.getText().charAt(i) == '\r'){
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count < maxNewlines;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
a.setMaxLength(maxTextLength);
|
||||
dialog.buttons.addButton("$ok", () -> {
|
||||
tile.configure(a.getText());
|
||||
dialog.hide();
|
||||
}).size(130f, 60f);
|
||||
dialog.update(() -> {
|
||||
if(tile.block() != MessageBlock.this){
|
||||
dialog.hide();
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
control.input.frag.config.hideConfig();
|
||||
}).size(40f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTableAlign(Table table){
|
||||
Vec2 pos = Core.input.mouseScreen(x, y + size * tilesize / 2f + 1);
|
||||
table.setPosition(pos.x, pos.y, Align.bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String config(){
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.str(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
message = read.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
37
core/src/mindustry/world/blocks/logic/ProcessorBlock.java
Normal file
37
core/src/mindustry/world/blocks/logic/ProcessorBlock.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package mindustry.world.blocks.logic;
|
||||
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class ProcessorBlock extends Block{
|
||||
|
||||
public ProcessorBlock(String name){
|
||||
super(name);
|
||||
configurable = true;
|
||||
}
|
||||
|
||||
public class ProcessorEntity extends TileEntity{
|
||||
//all tiles in the block network - does not include itself
|
||||
Array<Tilec> network = new Array<>();
|
||||
|
||||
@Override
|
||||
public boolean onConfigureTileTapped(Tilec other){
|
||||
if(other == this) return true;
|
||||
|
||||
if(!network.contains(other)){
|
||||
network.add(other);
|
||||
}else{
|
||||
network.remove(other);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
super.buildConfiguration(table);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package mindustry.world.blocks.power;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
@@ -18,12 +18,14 @@ public class Battery extends PowerDistributor{
|
||||
consumesPower = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
Draw.color(emptyLightColor, fullLightColor, tile.entity.power.status);
|
||||
Fill.square(tile.drawx(), tile.drawy(), tilesize * size / 2f - 1);
|
||||
Draw.color();
|
||||
public class BatteryEntity extends TileEntity{
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.color(emptyLightColor, fullLightColor, power.status);
|
||||
Fill.square(x, y, tilesize * size / 2f - 1);
|
||||
Draw.color();
|
||||
|
||||
Draw.rect(reg(topRegion), tile.drawx(), tile.drawy());
|
||||
Draw.rect(reg(topRegion), x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
package mindustry.world.blocks.power;
|
||||
|
||||
import arc.func.Boolf;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.consumers.ConsumePower;
|
||||
|
||||
/** A power consumer that only activates sometimes. */
|
||||
public class ConditionalConsumePower extends ConsumePower{
|
||||
private final Boolf<TileEntity> consume;
|
||||
private final Boolf<Tilec> consume;
|
||||
|
||||
public ConditionalConsumePower(float usage, Boolf<TileEntity> consume){
|
||||
public ConditionalConsumePower(float usage, Boolf<Tilec> consume){
|
||||
super(usage, 0, false);
|
||||
this.consume = consume;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float requestedPower(TileEntity entity){
|
||||
public float requestedPower(Tilec entity){
|
||||
return consume.get(entity) ? usage : 0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,17 +5,15 @@ import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class ImpactReactor extends PowerGenerator{
|
||||
@@ -38,8 +36,6 @@ public class ImpactReactor extends PowerGenerator{
|
||||
liquidCapacity = 30f;
|
||||
hasItems = true;
|
||||
outputsPower = consumesPower = true;
|
||||
entityType = FusionReactorEntity::new;
|
||||
|
||||
bottomRegion = reg("-bottom");
|
||||
plasmaRegions = new int[plasmas];
|
||||
for(int i = 0; i < plasmas; i++){
|
||||
@@ -53,7 +49,7 @@ public class ImpactReactor extends PowerGenerator{
|
||||
|
||||
bars.add("poweroutput", entity -> new Bar(() ->
|
||||
Core.bundle.format("bar.poweroutput",
|
||||
Strings.fixed(Math.max(entity.block.getPowerProduction(entity.tile) - consumes.getPower().usage, 0) * 60 * entity.timeScale, 1)),
|
||||
Strings.fixed(Math.max(entity.getPowerProduction() - consumes.getPower().usage, 0) * 60 * entity.timeScale(), 1)),
|
||||
() -> Pal.powerBar,
|
||||
() -> ((GeneratorEntity)entity).productionEfficiency));
|
||||
}
|
||||
@@ -67,113 +63,108 @@ public class ImpactReactor extends PowerGenerator{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
FusionReactorEntity entity = tile.ent();
|
||||
|
||||
if(entity.cons.valid() && entity.power.status >= 0.99f){
|
||||
boolean prevOut = getPowerProduction(tile) <= consumes.getPower().requestedPower(entity);
|
||||
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, warmupSpeed);
|
||||
if(Mathf.equal(entity.warmup, 1f, 0.001f)){
|
||||
entity.warmup = 1f;
|
||||
}
|
||||
|
||||
if(!prevOut && (getPowerProduction(tile) > consumes.getPower().requestedPower(entity))){
|
||||
Events.fire(Trigger.impactPower);
|
||||
}
|
||||
|
||||
if(entity.timer.get(timerUse, itemDuration / entity.timeScale)){
|
||||
entity.cons.trigger();
|
||||
}
|
||||
}else{
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.01f);
|
||||
}
|
||||
|
||||
entity.productionEfficiency = Mathf.pow(entity.warmup, 5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
FusionReactorEntity entity = tile.ent();
|
||||
|
||||
Draw.rect(reg(bottomRegion), tile.drawx(), tile.drawy());
|
||||
|
||||
for(int i = 0; i < plasmas; i++){
|
||||
float r = size * tilesize - 3f + Mathf.absin(Time.time(), 2f + i * 1f, 5f - i * 0.5f);
|
||||
|
||||
Draw.color(plasma1, plasma2, (float)i / plasmas);
|
||||
Draw.alpha((0.3f + Mathf.absin(Time.time(), 2f + i * 2f, 0.3f + i * 0.05f)) * entity.warmup);
|
||||
Draw.blend(Blending.additive);
|
||||
Draw.rect(reg(plasmaRegions[i]), tile.drawx(), tile.drawy(), r, r, Time.time() * (12 + i * 6f) * entity.warmup);
|
||||
Draw.blend();
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
|
||||
Draw.rect(region, tile.drawx(), tile.drawy());
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(Tile tile){
|
||||
float fract = tile.<FusionReactorEntity>ent().warmup;
|
||||
renderer.lights.add(tile.drawx(), tile.drawy(), (110f + Mathf.absin(5, 5f)) * fract, Tmp.c1.set(plasma2).lerp(plasma1, Mathf.absin(7f, 0.2f)), 0.8f * fract);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find(name + "-bottom"), Core.atlas.find(name)};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyed(Tile tile){
|
||||
super.onDestroyed(tile);
|
||||
|
||||
FusionReactorEntity entity = tile.ent();
|
||||
|
||||
if(entity.warmup < 0.4f || !state.rules.reactorExplosions) return;
|
||||
|
||||
Sounds.explosionbig.at(tile);
|
||||
|
||||
Effects.shake(6f, 16f, tile.worldx(), tile.worldy());
|
||||
Effects.effect(Fx.impactShockwave, tile.worldx(), tile.worldy());
|
||||
for(int i = 0; i < 6; i++){
|
||||
Time.run(Mathf.random(80), () -> Effects.effect(Fx.impactcloud, tile.worldx(), tile.worldy()));
|
||||
}
|
||||
|
||||
Damage.damage(tile.worldx(), tile.worldy(), explosionRadius * tilesize, explosionDamage * 4);
|
||||
|
||||
|
||||
for(int i = 0; i < 20; i++){
|
||||
Time.run(Mathf.random(80), () -> {
|
||||
Tmp.v1.rnd(Mathf.random(40f));
|
||||
Effects.effect(Fx.explosion, Tmp.v1.x + tile.worldx(), Tmp.v1.y + tile.worldy());
|
||||
});
|
||||
}
|
||||
|
||||
for(int i = 0; i < 70; i++){
|
||||
Time.run(Mathf.random(90), () -> {
|
||||
Tmp.v1.rnd(Mathf.random(120f));
|
||||
Effects.effect(Fx.impactsmoke, Tmp.v1.x + tile.worldx(), Tmp.v1.y + tile.worldy());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static class FusionReactorEntity extends GeneratorEntity{
|
||||
public class FusionReactorEntity extends GeneratorEntity{
|
||||
public float warmup;
|
||||
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeFloat(warmup);
|
||||
public void updateTile(){
|
||||
if(consValid() && power.status >= 0.99f){
|
||||
boolean prevOut = getPowerProduction() <= consumes.getPower().requestedPower(this);
|
||||
|
||||
warmup = Mathf.lerpDelta(warmup, 1f, warmupSpeed);
|
||||
if(Mathf.equal(warmup, 1f, 0.001f)){
|
||||
warmup = 1f;
|
||||
}
|
||||
|
||||
if(!prevOut && (getPowerProduction() > consumes.getPower().requestedPower(this))){
|
||||
Events.fire(Trigger.impactPower);
|
||||
}
|
||||
|
||||
if(timer(timerUse, itemDuration / timeScale())){
|
||||
consume();
|
||||
}
|
||||
}else{
|
||||
warmup = Mathf.lerpDelta(warmup, 0f, 0.01f);
|
||||
}
|
||||
|
||||
productionEfficiency = Mathf.pow(warmup, 5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
warmup = stream.readFloat();
|
||||
public void draw(){
|
||||
Draw.rect(reg(bottomRegion), x, y);
|
||||
|
||||
for(int i = 0; i < plasmas; i++){
|
||||
float r = size * tilesize - 3f + Mathf.absin(Time.time(), 2f + i * 1f, 5f - i * 0.5f);
|
||||
|
||||
Draw.color(plasma1, plasma2, (float)i / plasmas);
|
||||
Draw.alpha((0.3f + Mathf.absin(Time.time(), 2f + i * 2f, 0.3f + i * 0.05f)) * warmup);
|
||||
Draw.blend(Blending.additive);
|
||||
Draw.rect(reg(plasmaRegions[i]), x, y, r, r, Time.time() * (12 + i * 6f) * warmup);
|
||||
Draw.blend();
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
|
||||
Draw.rect(region, x, y);
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(){
|
||||
float fract = tile.<FusionReactorEntity>ent().warmup;
|
||||
renderer.lights.add(x, y, (110f + Mathf.absin(5, 5f)) * fract, Tmp.c1.set(plasma2).lerp(plasma1, Mathf.absin(7f, 0.2f)), 0.8f * fract);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyed(){
|
||||
super.onDestroyed();
|
||||
|
||||
if(warmup < 0.4f || !state.rules.reactorExplosions) return;
|
||||
|
||||
Sounds.explosionbig.at(tile);
|
||||
|
||||
Effects.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));
|
||||
}
|
||||
|
||||
Damage.damage(x, y, explosionRadius * tilesize, explosionDamage * 4);
|
||||
|
||||
|
||||
for(int i = 0; i < 20; i++){
|
||||
Time.run(Mathf.random(80), () -> {
|
||||
Tmp.v1.rnd(Mathf.random(40f));
|
||||
Fx.explosion.at(Tmp.v1.x + x, Tmp.v1.y + y);
|
||||
});
|
||||
}
|
||||
|
||||
for(int i = 0; i < 70; i++){
|
||||
Time.run(Mathf.random(90), () -> {
|
||||
Tmp.v1.rnd(Mathf.random(120f));
|
||||
Fx.impactsmoke.at(Tmp.v1.x + x, Tmp.v1.y + y);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.f(warmup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
warmup = read.f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,7 @@ import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
@@ -85,101 +83,6 @@ public class ItemLiquidGenerator extends PowerGenerator{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean productionValid(Tile tile){
|
||||
ItemLiquidGeneratorEntity entity = tile.ent();
|
||||
return entity.generateTime > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ItemLiquidGeneratorEntity entity = tile.ent();
|
||||
|
||||
//Note: Do not use this delta when calculating the amount of power or the power efficiency, but use it for resource consumption if necessary.
|
||||
//Power amount is delta'd by PowerGraph class already.
|
||||
float calculationDelta = entity.delta();
|
||||
|
||||
if(!entity.cons.valid()){
|
||||
entity.productionEfficiency = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
Liquid liquid = null;
|
||||
for(Liquid other : content.liquids()){
|
||||
if(hasLiquids && entity.liquids.get(other) >= 0.001f && getLiquidEfficiency(other) >= minLiquidEfficiency){
|
||||
liquid = other;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, entity.generateTime >= 0.001f ? 1f : 0f, 0.05f);
|
||||
|
||||
//liquid takes priority over solids
|
||||
if(hasLiquids && liquid != null && entity.liquids.get(liquid) >= 0.001f){
|
||||
float baseLiquidEfficiency = getLiquidEfficiency(liquid);
|
||||
float maximumPossible = maxLiquidGenerate * calculationDelta;
|
||||
float used = Math.min(entity.liquids.get(liquid) * calculationDelta, maximumPossible);
|
||||
|
||||
entity.liquids.remove(liquid, used * entity.power.graph.getUsageFraction());
|
||||
entity.productionEfficiency = baseLiquidEfficiency * used / maximumPossible;
|
||||
|
||||
if(used > 0.001f && Mathf.chance(0.05 * entity.delta())){
|
||||
Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f));
|
||||
}
|
||||
}else if(hasItems){
|
||||
// No liquids accepted or none supplied, try using items if accepted
|
||||
if(entity.generateTime <= 0f && entity.items.total() > 0){
|
||||
Effects.effect(generateEffect, tile.worldx() + Mathf.range(3f), tile.worldy() + Mathf.range(3f));
|
||||
Item item = entity.items.take();
|
||||
entity.productionEfficiency = getItemEfficiency(item);
|
||||
entity.explosiveness = item.explosiveness;
|
||||
entity.generateTime = 1f;
|
||||
}
|
||||
|
||||
if(entity.generateTime > 0f){
|
||||
entity.generateTime -= Math.min(1f / itemDuration * entity.delta() * entity.power.graph.getUsageFraction(), entity.generateTime);
|
||||
|
||||
if(randomlyExplode && state.rules.reactorExplosions && Mathf.chance(entity.delta() * 0.06 * Mathf.clamp(entity.explosiveness - 0.5f))){
|
||||
//this block is run last so that in the event of a block destruction, no code relies on the block type
|
||||
Core.app.post(() -> {
|
||||
entity.damage(Mathf.random(11f));
|
||||
Effects.effect(explodeEffect, tile.worldx() + Mathf.range(size * tilesize / 2f), tile.worldy() + Mathf.range(size * tilesize / 2f));
|
||||
});
|
||||
}
|
||||
}else{
|
||||
entity.productionEfficiency = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
ItemLiquidGeneratorEntity entity = tile.ent();
|
||||
|
||||
if(hasItems){
|
||||
Draw.color(heatColor);
|
||||
Draw.alpha(entity.heat * 0.4f + Mathf.absin(Time.time(), 8f, 0.6f) * entity.heat);
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
if(hasLiquids){
|
||||
Draw.color(entity.liquids.current().color);
|
||||
Draw.alpha(entity.liquids.currentAmount() / liquidCapacity);
|
||||
Draw.rect(liquidRegion, tile.drawx(), tile.drawy());
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(Tile tile){
|
||||
ItemLiquidGeneratorEntity entity = tile.ent();
|
||||
|
||||
renderer.lights.add(tile.drawx(), tile.drawy(), (60f + Mathf.absin(10f, 5f)) * entity.productionEfficiency * size, Color.orange, 0.5f);
|
||||
}
|
||||
|
||||
protected float getItemEfficiency(Item item){
|
||||
return 0.0f;
|
||||
}
|
||||
@@ -188,8 +91,96 @@ public class ItemLiquidGenerator extends PowerGenerator{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
public static class ItemLiquidGeneratorEntity extends GeneratorEntity{
|
||||
public class ItemLiquidGeneratorEntity extends GeneratorEntity{
|
||||
public float explosiveness;
|
||||
public float heat;
|
||||
|
||||
@Override
|
||||
public boolean productionValid(){
|
||||
return generateTime > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
//Note: Do not use this delta when calculating the amount of power or the power efficiency, but use it for resource consumption if necessary.
|
||||
//Power amount is delta'd by PowerGraph class already.
|
||||
float calculationDelta = delta();
|
||||
|
||||
if(!consValid()){
|
||||
productionEfficiency = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
Liquid liquid = null;
|
||||
for(Liquid other : content.liquids()){
|
||||
if(hasLiquids && liquids.get(other) >= 0.001f && getLiquidEfficiency(other) >= minLiquidEfficiency){
|
||||
liquid = other;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
heat = Mathf.lerpDelta(heat, generateTime >= 0.001f ? 1f : 0f, 0.05f);
|
||||
|
||||
//liquid takes priority over solids
|
||||
if(hasLiquids && liquid != null && liquids.get(liquid) >= 0.001f){
|
||||
float baseLiquidEfficiency = getLiquidEfficiency(liquid);
|
||||
float maximumPossible = maxLiquidGenerate * calculationDelta;
|
||||
float used = Math.min(liquids.get(liquid) * calculationDelta, maximumPossible);
|
||||
|
||||
liquids.remove(liquid, used * power.graph.getUsageFraction());
|
||||
productionEfficiency = baseLiquidEfficiency * used / maximumPossible;
|
||||
|
||||
if(used > 0.001f && Mathf.chance(0.05 * delta())){
|
||||
generateEffect.at(x + Mathf.range(3f), y + Mathf.range(3f));
|
||||
}
|
||||
}else if(hasItems){
|
||||
// No liquids accepted or none supplied, try using items if accepted
|
||||
if(generateTime <= 0f && items.total() > 0){
|
||||
generateEffect.at(x + Mathf.range(3f), y + Mathf.range(3f));
|
||||
Item item = items.take();
|
||||
productionEfficiency = getItemEfficiency(item);
|
||||
explosiveness = item.explosiveness;
|
||||
generateTime = 1f;
|
||||
}
|
||||
|
||||
if(generateTime > 0f){
|
||||
generateTime -= Math.min(1f / itemDuration * delta() * power.graph.getUsageFraction(), generateTime);
|
||||
|
||||
if(randomlyExplode && state.rules.reactorExplosions && Mathf.chance(delta() * 0.06 * Mathf.clamp(explosiveness - 0.5f))){
|
||||
//this block is run last so that in the event of a block destruction, no code relies on the block type
|
||||
Core.app.post(() -> {
|
||||
damage(Mathf.random(11f));
|
||||
explodeEffect.at(x + Mathf.range(size * tilesize / 2f), y + Mathf.range(size * tilesize / 2f));
|
||||
});
|
||||
}
|
||||
}else{
|
||||
productionEfficiency = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
if(hasItems){
|
||||
Draw.color(heatColor);
|
||||
Draw.alpha(heat * 0.4f + Mathf.absin(Time.time(), 8f, 0.6f) * heat);
|
||||
Draw.rect(topRegion, x, y);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
if(hasLiquids){
|
||||
Draw.color(liquids.current().color);
|
||||
Draw.alpha(liquids.currentAmount() / liquidCapacity);
|
||||
Draw.rect(liquidRegion, x, y);
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(){
|
||||
renderer.lights.add(x, y, (60f + Mathf.absin(10f, 5f)) * productionEfficiency * size, Color.orange, 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,11 @@ import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.type.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class LightBlock extends Block{
|
||||
@@ -26,70 +24,60 @@ public class LightBlock extends Block{
|
||||
update = true;
|
||||
topRegion = reg("-top");
|
||||
configurable = true;
|
||||
entityType = LightEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerPlaced(Tile tile){
|
||||
if(lastColor != 0){
|
||||
tile.configure(lastColor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
LightEntity entity = tile.ent();
|
||||
|
||||
Draw.blend(Blending.additive);
|
||||
Draw.color(Tmp.c1.set(entity.color), entity.efficiency() * 0.3f);
|
||||
Draw.rect(reg(topRegion), tile.drawx(), tile.drawy());
|
||||
Draw.color();
|
||||
Draw.blend();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
LightEntity entity = tile.ent();
|
||||
|
||||
table.addImageButton(Icon.pencil, () -> {
|
||||
ui.picker.show(Tmp.c1.set(entity.color).a(0.5f), false, res -> {
|
||||
entity.color = res.rgba();
|
||||
lastColor = entity.color;
|
||||
});
|
||||
control.input.frag.config.hideConfig();
|
||||
}).size(40f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configured(Tile tile, Player player, int value){
|
||||
tile.<LightEntity>ent().color = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(Tile tile){
|
||||
LightEntity entity = tile.ent();
|
||||
renderer.lights.add(tile.drawx(), tile.drawy(), radius, Tmp.c1.set(entity.color), brightness * tile.entity.efficiency());
|
||||
config(Integer.class, (tile, value) -> ((LightEntity)tile).color = value);
|
||||
}
|
||||
|
||||
public class LightEntity extends TileEntity{
|
||||
public int color = Pal.accent.rgba();
|
||||
|
||||
@Override
|
||||
public int config(){
|
||||
public void playerPlaced(){
|
||||
if(lastColor != 0){
|
||||
tile.configure(lastColor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
Draw.blend(Blending.additive);
|
||||
Draw.color(Tmp.c1.set(color), efficiency() * 0.3f);
|
||||
Draw.rect(reg(topRegion), x, y);
|
||||
Draw.color();
|
||||
Draw.blend();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
table.addImageButton(Icon.pencil, () -> {
|
||||
ui.picker.show(Tmp.c1.set(color).a(0.5f), false, res -> {
|
||||
color = res.rgba();
|
||||
lastColor = color;
|
||||
});
|
||||
control.input.frag.config.hideConfig();
|
||||
}).size(40f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(){
|
||||
renderer.lights.add(x, y, radius, Tmp.c1.set(color), brightness * efficiency());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer config(){
|
||||
return color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeInt(color);
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.i(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
color = stream.readInt();
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
color = read.i();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
@@ -13,12 +14,9 @@ import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class NuclearReactor extends PowerGenerator{
|
||||
@@ -45,7 +43,6 @@ public class NuclearReactor extends PowerGenerator{
|
||||
liquidCapacity = 30;
|
||||
hasItems = true;
|
||||
hasLiquids = true;
|
||||
entityType = NuclearReactorEntity::new;
|
||||
rebuildable = false;
|
||||
}
|
||||
|
||||
@@ -72,129 +69,121 @@ public class NuclearReactor extends PowerGenerator{
|
||||
bars.add("heat", entity -> new Bar("bar.heat", Pal.lightOrange, () -> ((NuclearReactorEntity)entity).heat));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
NuclearReactorEntity entity = tile.ent();
|
||||
|
||||
ConsumeLiquid cliquid = consumes.get(ConsumeType.liquid);
|
||||
Item item = consumes.<ConsumeItems>get(ConsumeType.item).items[0].item;
|
||||
|
||||
int fuel = entity.items.get(item);
|
||||
float fullness = (float)fuel / itemCapacity;
|
||||
entity.productionEfficiency = fullness;
|
||||
|
||||
if(fuel > 0){
|
||||
entity.heat += fullness * heating * Math.min(entity.delta(), 4f);
|
||||
|
||||
if(entity.timer.get(timerFuel, itemDuration / entity.timeScale)){
|
||||
entity.cons.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
Liquid liquid = cliquid.liquid;
|
||||
|
||||
if(entity.heat > 0){
|
||||
float maxUsed = Math.min(entity.liquids.get(liquid), entity.heat / coolantPower);
|
||||
entity.heat -= maxUsed * coolantPower;
|
||||
entity.liquids.remove(liquid, maxUsed);
|
||||
}
|
||||
|
||||
if(entity.heat > smokeThreshold){
|
||||
float smoke = 1.0f + (entity.heat - smokeThreshold) / (1f - smokeThreshold); //ranges from 1.0 to 2.0
|
||||
if(Mathf.chance(smoke / 20.0 * entity.delta())){
|
||||
Effects.effect(Fx.reactorsmoke, tile.worldx() + Mathf.range(size * tilesize / 2f),
|
||||
tile.worldy() + Mathf.random(size * tilesize / 2f));
|
||||
}
|
||||
}
|
||||
|
||||
entity.heat = Mathf.clamp(entity.heat);
|
||||
|
||||
if(entity.heat >= 0.999f){
|
||||
Events.fire(Trigger.thoriumReactorOverheat);
|
||||
entity.kill();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyed(Tile tile){
|
||||
super.onDestroyed(tile);
|
||||
|
||||
Sounds.explosionbig.at(tile);
|
||||
|
||||
NuclearReactorEntity entity = tile.ent();
|
||||
|
||||
int fuel = entity.items.get(consumes.<ConsumeItems>get(ConsumeType.item).items[0].item);
|
||||
|
||||
if((fuel < 5 && entity.heat < 0.5f) || !state.rules.reactorExplosions) return;
|
||||
|
||||
Effects.shake(6f, 16f, tile.worldx(), tile.worldy());
|
||||
Effects.effect(Fx.nuclearShockwave, tile.worldx(), tile.worldy());
|
||||
for(int i = 0; i < 6; i++){
|
||||
Time.run(Mathf.random(40), () -> Effects.effect(Fx.nuclearcloud, tile.worldx(), tile.worldy()));
|
||||
}
|
||||
|
||||
Damage.damage(tile.worldx(), tile.worldy(), explosionRadius * tilesize, explosionDamage * 4);
|
||||
|
||||
for(int i = 0; i < 20; i++){
|
||||
Time.run(Mathf.random(50), () -> {
|
||||
tr.rnd(Mathf.random(40f));
|
||||
Effects.effect(Fx.explosion, tr.x + tile.worldx(), tr.y + tile.worldy());
|
||||
});
|
||||
}
|
||||
|
||||
for(int i = 0; i < 70; i++){
|
||||
Time.run(Mathf.random(80), () -> {
|
||||
tr.rnd(Mathf.random(120f));
|
||||
Effects.effect(Fx.nuclearsmoke, tr.x + tile.worldx(), tr.y + tile.worldy());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(Tile tile){
|
||||
NuclearReactorEntity entity = tile.ent();
|
||||
float fract = entity.productionEfficiency;
|
||||
renderer.lights.add(tile.drawx(), tile.drawy(), (90f + Mathf.absin(5, 5f)) * fract, Tmp.c1.set(lightColor).lerp(Color.scarlet, entity.heat), 0.6f * fract);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
NuclearReactorEntity entity = tile.ent();
|
||||
|
||||
Draw.color(coolColor, hotColor, entity.heat);
|
||||
Fill.rect(tile.drawx(), tile.drawy(), size * tilesize, size * tilesize);
|
||||
|
||||
Draw.color(entity.liquids.current().color);
|
||||
Draw.alpha(entity.liquids.currentAmount() / liquidCapacity);
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||
|
||||
if(entity.heat > flashThreshold){
|
||||
float flash = 1f + ((entity.heat - flashThreshold) / (1f - flashThreshold)) * 5.4f;
|
||||
entity.flash += flash * Time.delta();
|
||||
Draw.color(Color.red, Color.yellow, Mathf.absin(entity.flash, 9f, 1f));
|
||||
Draw.alpha(0.6f);
|
||||
Draw.rect(lightsRegion, tile.drawx(), tile.drawy());
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
public static class NuclearReactorEntity extends GeneratorEntity{
|
||||
public class NuclearReactorEntity extends GeneratorEntity{
|
||||
public float heat;
|
||||
public float flash;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeFloat(heat);
|
||||
public void updateTile(){
|
||||
ConsumeLiquid cliquid = consumes.get(ConsumeType.liquid);
|
||||
Item item = consumes.<ConsumeItems>get(ConsumeType.item).items[0].item;
|
||||
|
||||
int fuel = items.get(item);
|
||||
float fullness = (float)fuel / itemCapacity;
|
||||
productionEfficiency = fullness;
|
||||
|
||||
if(fuel > 0){
|
||||
heat += fullness * heating * Math.min(delta(), 4f);
|
||||
|
||||
if(timer(timerFuel, itemDuration / timeScale())){
|
||||
consume();
|
||||
}
|
||||
}
|
||||
|
||||
Liquid liquid = cliquid.liquid;
|
||||
|
||||
if(heat > 0){
|
||||
float maxUsed = Math.min(liquids.get(liquid), heat / coolantPower);
|
||||
heat -= maxUsed * coolantPower;
|
||||
liquids.remove(liquid, maxUsed);
|
||||
}
|
||||
|
||||
if(heat > smokeThreshold){
|
||||
float smoke = 1.0f + (heat - smokeThreshold) / (1f - smokeThreshold); //ranges from 1.0 to 2.0
|
||||
if(Mathf.chance(smoke / 20.0 * delta())){
|
||||
Fx.reactorsmoke.at(x + Mathf.range(size * tilesize / 2f),
|
||||
y + Mathf.random(size * tilesize / 2f));
|
||||
}
|
||||
}
|
||||
|
||||
heat = Mathf.clamp(heat);
|
||||
|
||||
if(heat >= 0.999f){
|
||||
Events.fire(Trigger.thoriumReactorOverheat);
|
||||
kill();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
heat = stream.readFloat();
|
||||
public void onDestroyed(){
|
||||
super.onDestroyed();
|
||||
|
||||
Sounds.explosionbig.at(tile);
|
||||
|
||||
int fuel = items.get(consumes.<ConsumeItems>get(ConsumeType.item).items[0].item);
|
||||
|
||||
if((fuel < 5 && heat < 0.5f) || !state.rules.reactorExplosions) return;
|
||||
|
||||
Effects.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));
|
||||
}
|
||||
|
||||
Damage.damage(x, y, explosionRadius * tilesize, explosionDamage * 4);
|
||||
|
||||
for(int i = 0; i < 20; i++){
|
||||
Time.run(Mathf.random(50), () -> {
|
||||
tr.rnd(Mathf.random(40f));
|
||||
Fx.explosion.at(tr.x + x, tr.y + y);
|
||||
});
|
||||
}
|
||||
|
||||
for(int i = 0; i < 70; i++){
|
||||
Time.run(Mathf.random(80), () -> {
|
||||
tr.rnd(Mathf.random(120f));
|
||||
Fx.nuclearsmoke.at(tr.x + x, tr.y + y);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(){
|
||||
float fract = productionEfficiency;
|
||||
renderer.lights.add(x, y, (90f + Mathf.absin(5, 5f)) * fract, Tmp.c1.set(lightColor).lerp(Color.scarlet, heat), 0.6f * fract);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
Draw.color(coolColor, hotColor, heat);
|
||||
Fill.rect(x, y, size * tilesize, size * tilesize);
|
||||
|
||||
Draw.color(liquids.current().color);
|
||||
Draw.alpha(liquids.currentAmount() / liquidCapacity);
|
||||
Draw.rect(topRegion, x, y);
|
||||
|
||||
if(heat > flashThreshold){
|
||||
float flash = 1f + ((heat - flashThreshold) / (1f - flashThreshold)) * 5.4f;
|
||||
flash += flash * Time.delta();
|
||||
Draw.color(Color.red, Color.yellow, Mathf.absin(flash, 9f, 1f));
|
||||
Draw.alpha(0.6f);
|
||||
Draw.rect(lightsRegion, x, y);
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.f(heat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
heat = read.f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package mindustry.world.blocks;
|
||||
package mindustry.world.blocks.power;
|
||||
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.meta.BlockGroup;
|
||||
@@ -2,6 +2,8 @@ package mindustry.world.blocks.power;
|
||||
|
||||
import arc.Core;
|
||||
import arc.math.Mathf;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.ui.Bar;
|
||||
import arc.util.Eachable;
|
||||
import mindustry.ui.Cicon;
|
||||
@@ -10,7 +12,7 @@ import mindustry.world.Block;
|
||||
import arc.graphics.g2d.Draw;
|
||||
import mindustry.graphics.Pal;
|
||||
import arc.graphics.g2d.TextureRegion;
|
||||
import mindustry.entities.traits.BuilderTrait;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class PowerDiode extends Block{
|
||||
public TextureRegion arrow;
|
||||
@@ -21,45 +23,15 @@ public class PowerDiode extends Block{
|
||||
update = true;
|
||||
solid = true;
|
||||
insulated = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
super.update(tile);
|
||||
|
||||
if(tile.front() == null || tile.back() == null || !tile.back().block().hasPower || !tile.front().block().hasPower || tile.back().getTeam() != tile.front().getTeam()) return;
|
||||
|
||||
PowerGraph backGraph = tile.back().entity.power.graph;
|
||||
PowerGraph frontGraph = tile.front().entity.power.graph;
|
||||
if(backGraph == frontGraph) return;
|
||||
|
||||
// 0f - 1f of battery capacity in use
|
||||
float backStored = backGraph.getBatteryStored() / backGraph.getTotalBatteryCapacity();
|
||||
float frontStored = frontGraph.getBatteryStored() / frontGraph.getTotalBatteryCapacity();
|
||||
|
||||
// try to send if the back side has more % capacity stored than the front side
|
||||
if(backStored > frontStored) {
|
||||
// send half of the difference
|
||||
float amount = backGraph.getBatteryStored() * (backStored - frontStored) / 2;
|
||||
// prevent sending more than the front can handle
|
||||
amount = Mathf.clamp(amount, 0, frontGraph.getTotalBatteryCapacity() * (1 - frontStored));
|
||||
|
||||
backGraph.useBatteries(amount);
|
||||
frontGraph.chargeBatteries(amount);
|
||||
}
|
||||
}
|
||||
|
||||
// battery % of the graph on either side, defaults to zero
|
||||
public float bar(Tile tile){
|
||||
return (tile != null && tile.block().hasPower) ? tile.entity.power.graph.getBatteryStored() / tile.entity.power.graph.getTotalBatteryCapacity() : 0f;
|
||||
group = BlockGroup.power;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBars(){
|
||||
super.setBars();
|
||||
|
||||
bars.add("back", entity -> new Bar("bar.input", Pal.powerBar, () -> bar(entity.tile.back())));
|
||||
bars.add("front", entity -> new Bar("bar.output", Pal.powerBar, () -> bar(entity.tile.front())));
|
||||
bars.add("back", entity -> new Bar("bar.input", Pal.powerBar, () -> bar(entity.back())));
|
||||
bars.add("front", entity -> new Bar("bar.output", Pal.powerBar, () -> bar(entity.front())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,13 +41,7 @@ public class PowerDiode extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
Draw.rect(region, tile.drawx(), tile.drawy(), 0);
|
||||
Draw.rect(arrow, tile.drawx(), tile.drawy(), rotate ? tile.rotation() * 90 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRequestRegion(BuilderTrait.BuildRequest req, Eachable<BuilderTrait.BuildRequest> list) {
|
||||
public void drawRequestRegion(BuildRequest req, Eachable<BuildRequest> list) {
|
||||
TextureRegion reg = icon(Cicon.full);
|
||||
Draw.rect(icon(Cicon.full), req.drawx(), req.drawy(),
|
||||
reg.getWidth() * req.animScale * Draw.scl,
|
||||
@@ -86,4 +52,43 @@ public class PowerDiode extends Block{
|
||||
arrow.getHeight() * req.animScale * Draw.scl,
|
||||
!rotate ? 0 : req.rotation * 90);
|
||||
}
|
||||
|
||||
// battery % of the graph on either side, defaults to zero
|
||||
public float bar(Tilec tile){
|
||||
return (tile != null && tile.block().hasPower) ? tile.power().graph.getBatteryStored() / tile.power().graph.getTotalBatteryCapacity() : 0f;
|
||||
}
|
||||
|
||||
public class PowerDiodeEntity extends TileEntity{
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect(region, x, y, 0);
|
||||
Draw.rect(arrow, x, y, rotate ? tile.rotation() * 90 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
super.updateTile();
|
||||
|
||||
if(tile.front() == null || tile.back() == null || !tile.back().block().hasPower || !tile.front().block().hasPower || tile.back().team() != tile.front().team()) return;
|
||||
|
||||
PowerGraph backGraph = tile.back().power().graph;
|
||||
PowerGraph frontGraph = tile.front().power().graph;
|
||||
if(backGraph == frontGraph) return;
|
||||
|
||||
// 0f - 1f of battery capacity in use
|
||||
float backStored = backGraph.getBatteryStored() / backGraph.getTotalBatteryCapacity();
|
||||
float frontStored = frontGraph.getBatteryStored() / frontGraph.getTotalBatteryCapacity();
|
||||
|
||||
// try to send if the back side has more % capacity stored than the front side
|
||||
if(backStored > frontStored) {
|
||||
// send half of the difference
|
||||
float amount = backGraph.getBatteryStored() * (backStored - frontStored) / 2;
|
||||
// prevent sending more than the front can handle
|
||||
amount = Mathf.clamp(amount, 0, frontGraph.getTotalBatteryCapacity() * (1 - frontStored));
|
||||
|
||||
backGraph.useBatteries(amount);
|
||||
frontGraph.chargeBatteries(amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package mindustry.world.blocks.power;
|
||||
|
||||
import mindustry.world.blocks.PowerBlock;
|
||||
|
||||
public class PowerDistributor extends PowerBlock{
|
||||
|
||||
public PowerDistributor(String name){
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
package mindustry.world.blocks.power;
|
||||
|
||||
import arc.Core;
|
||||
import arc.struct.EnumSet;
|
||||
import arc.util.Strings;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.graphics.Pal;
|
||||
import mindustry.ui.Bar;
|
||||
import mindustry.world.Tile;
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class PowerGenerator extends PowerDistributor{
|
||||
/** The amount of power produced per tick in case of an efficiency of 1.0, which represents 100%. */
|
||||
public float powerProduction;
|
||||
@@ -21,7 +19,6 @@ public class PowerGenerator extends PowerDistributor{
|
||||
sync = true;
|
||||
baseExplosiveness = 5f;
|
||||
flags = EnumSet.of(BlockFlag.producer);
|
||||
entityType = GeneratorEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -37,37 +34,37 @@ public class PowerGenerator extends PowerDistributor{
|
||||
if(hasPower && outputsPower && !consumes.hasPower()){
|
||||
bars.add("power", entity -> new Bar(() ->
|
||||
Core.bundle.format("bar.poweroutput",
|
||||
Strings.fixed(entity.block.getPowerProduction(entity.tile) * 60 * entity.timeScale, 1)),
|
||||
Strings.fixed(entity.getPowerProduction() * 60 * entity.timeScale(), 1)),
|
||||
() -> Pal.powerBar,
|
||||
() -> ((GeneratorEntity)entity).productionEfficiency));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPowerProduction(Tile tile){
|
||||
return powerProduction * tile.<GeneratorEntity>ent().productionEfficiency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outputsItems(){
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class GeneratorEntity extends TileEntity{
|
||||
public class GeneratorEntity extends TileEntity{
|
||||
public float generateTime;
|
||||
/** The efficiency of the producer. An efficiency of 1.0 means 100% */
|
||||
public float productionEfficiency = 0.0f;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeFloat(productionEfficiency);
|
||||
public float getPowerProduction(){
|
||||
return powerProduction * productionEfficiency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
productionEfficiency = stream.readFloat();
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.f(productionEfficiency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
productionEfficiency = read.f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,19 @@ import arc.*;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.consumers.*;
|
||||
|
||||
public class PowerGraph{
|
||||
private final static Queue<Tile> queue = new Queue<>();
|
||||
private final static Array<Tile> outArray1 = new Array<>();
|
||||
private final static Array<Tile> outArray2 = new Array<>();
|
||||
private final static Queue<Tilec> queue = new Queue<>();
|
||||
private final static Array<Tilec> outArray1 = new Array<>();
|
||||
private final static Array<Tilec> outArray2 = new Array<>();
|
||||
private final static IntSet closedSet = new IntSet();
|
||||
|
||||
private final ObjectSet<Tile> producers = new ObjectSet<>();
|
||||
private final ObjectSet<Tile> consumers = new ObjectSet<>();
|
||||
private final ObjectSet<Tile> batteries = new ObjectSet<>();
|
||||
private final ObjectSet<Tile> all = new ObjectSet<>();
|
||||
private final ObjectSet<Tilec> producers = new ObjectSet<>();
|
||||
private final ObjectSet<Tilec> consumers = new ObjectSet<>();
|
||||
private final ObjectSet<Tilec> batteries = new ObjectSet<>();
|
||||
private final ObjectSet<Tilec> all = new ObjectSet<>();
|
||||
|
||||
private final WindowedMean powerBalance = new WindowedMean(60);
|
||||
private float lastPowerProduced, lastPowerNeeded, lastUsageFraction;
|
||||
@@ -62,21 +62,20 @@ public class PowerGraph{
|
||||
|
||||
public float getPowerProduced(){
|
||||
float powerProduced = 0f;
|
||||
for(Tile producer : producers){
|
||||
if(producer.entity == null) continue;
|
||||
powerProduced += producer.block().getPowerProduction(producer) * producer.entity.delta();
|
||||
for(Tilec producer : producers){
|
||||
powerProduced += producer.getPowerProduction() * producer.delta();
|
||||
}
|
||||
return powerProduced;
|
||||
}
|
||||
|
||||
public float getPowerNeeded(){
|
||||
float powerNeeded = 0f;
|
||||
for(Tile consumer : consumers){
|
||||
for(Tilec consumer : consumers){
|
||||
Consumers consumes = consumer.block().consumes;
|
||||
if(consumes.hasPower()){
|
||||
ConsumePower consumePower = consumes.getPower();
|
||||
if(otherConsumersAreValid(consumer, consumePower)){
|
||||
powerNeeded += consumePower.requestedPower(consumer.entity) * consumer.entity.delta();
|
||||
powerNeeded += consumePower.requestedPower(consumer) * consumer.delta();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,10 +84,10 @@ public class PowerGraph{
|
||||
|
||||
public float getBatteryStored(){
|
||||
float totalAccumulator = 0f;
|
||||
for(Tile battery : batteries){
|
||||
for(Tilec battery : batteries){
|
||||
Consumers consumes = battery.block().consumes;
|
||||
if(consumes.hasPower()){
|
||||
totalAccumulator += battery.entity.power.status * consumes.getPower().capacity;
|
||||
totalAccumulator += battery.power().status * consumes.getPower().capacity;
|
||||
}
|
||||
}
|
||||
return totalAccumulator;
|
||||
@@ -96,10 +95,10 @@ public class PowerGraph{
|
||||
|
||||
public float getBatteryCapacity(){
|
||||
float totalCapacity = 0f;
|
||||
for(Tile battery : batteries){
|
||||
for(Tilec battery : batteries){
|
||||
if(battery.block().consumes.hasPower()){
|
||||
ConsumePower power = battery.block().consumes.getPower();
|
||||
totalCapacity += (1f - battery.entity.power.status) * power.capacity;
|
||||
totalCapacity += (1f - battery.power().status) * power.capacity;
|
||||
}
|
||||
}
|
||||
return totalCapacity;
|
||||
@@ -107,7 +106,7 @@ public class PowerGraph{
|
||||
|
||||
public float getTotalBatteryCapacity(){
|
||||
float totalCapacity = 0f;
|
||||
for(Tile battery : batteries){
|
||||
for(Tilec battery : batteries){
|
||||
if(battery.block().consumes.hasPower()){
|
||||
totalCapacity += battery.block().consumes.getPower().capacity;
|
||||
}
|
||||
@@ -121,10 +120,10 @@ public class PowerGraph{
|
||||
|
||||
float used = Math.min(stored, needed);
|
||||
float consumedPowerPercentage = Math.min(1.0f, needed / stored);
|
||||
for(Tile battery : batteries){
|
||||
for(Tilec battery : batteries){
|
||||
Consumers consumes = battery.block().consumes;
|
||||
if(consumes.hasPower()){
|
||||
battery.entity.power.status *= (1f-consumedPowerPercentage);
|
||||
battery.power().status *= (1f-consumedPowerPercentage);
|
||||
}
|
||||
}
|
||||
return used;
|
||||
@@ -136,12 +135,12 @@ public class PowerGraph{
|
||||
float chargedPercent = Math.min(excess/capacity, 1f);
|
||||
if(Mathf.equal(capacity, 0f)) return 0f;
|
||||
|
||||
for(Tile battery : batteries){
|
||||
for(Tilec battery : batteries){
|
||||
Consumers consumes = battery.block().consumes;
|
||||
if(consumes.hasPower()){
|
||||
ConsumePower consumePower = consumes.getPower();
|
||||
if(consumePower.capacity > 0f){
|
||||
battery.entity.power.status += (1f-battery.entity.power.status) * chargedPercent;
|
||||
battery.power().status += (1f-battery.power().status) * chargedPercent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,25 +150,25 @@ public class PowerGraph{
|
||||
public void distributePower(float needed, float produced){
|
||||
//distribute even if not needed. this is because some might be requiring power but not using it; it updates consumers
|
||||
float coverage = Mathf.zero(needed) && Mathf.zero(produced) ? 0f : Mathf.zero(needed) ? 1f : Math.min(1, produced / needed);
|
||||
for(Tile consumer : consumers){
|
||||
for(Tilec consumer : consumers){
|
||||
Consumers consumes = consumer.block().consumes;
|
||||
if(consumes.hasPower()){
|
||||
ConsumePower consumePower = consumes.getPower();
|
||||
if(consumePower.buffered){
|
||||
if(!Mathf.zero(consumePower.capacity)){
|
||||
// Add an equal percentage of power to all buffers, based on the global power coverage in this graph
|
||||
float maximumRate = consumePower.requestedPower(consumer.entity) * coverage * consumer.entity.delta();
|
||||
consumer.entity.power.status = Mathf.clamp(consumer.entity.power.status + maximumRate / consumePower.capacity);
|
||||
float maximumRate = consumePower.requestedPower(consumer) * coverage * consumer.delta();
|
||||
consumer.power().status = Mathf.clamp(consumer.power().status + maximumRate / consumePower.capacity);
|
||||
}
|
||||
}else{
|
||||
//valid consumers get power as usual
|
||||
if(otherConsumersAreValid(consumer, consumePower)){
|
||||
consumer.entity.power.status = coverage;
|
||||
consumer.power().status = coverage;
|
||||
}else{ //invalid consumers get an estimate, if they were to activate
|
||||
consumer.entity.power.status = Math.min(1, produced / (needed + consumePower.usage * consumer.entity.delta()));
|
||||
consumer.power().status = Math.min(1, produced / (needed + consumePower.usage * consumer.delta()));
|
||||
//just in case
|
||||
if(Float.isNaN(consumer.entity.power.status)){
|
||||
consumer.entity.power.status = 0f;
|
||||
if(Float.isNaN(consumer.power().status)){
|
||||
consumer.power().status = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,10 +179,10 @@ public class PowerGraph{
|
||||
public void update(){
|
||||
if(Core.graphics.getFrameId() == lastFrameUpdated){
|
||||
return;
|
||||
}else if(!consumers.isEmpty() && consumers.first().isEnemyCheat()){
|
||||
}else if(!consumers.isEmpty() && consumers.first().tile().isEnemyCheat()){
|
||||
//when cheating, just set status to 1
|
||||
for(Tile tile : consumers){
|
||||
tile.entity.power.status = 1f;
|
||||
for(Tilec tile : consumers){
|
||||
tile.power().status = 1f;
|
||||
}
|
||||
|
||||
lastPowerNeeded = lastPowerProduced = lastUsageFraction = 1f;
|
||||
@@ -224,14 +223,14 @@ public class PowerGraph{
|
||||
}
|
||||
|
||||
public void add(PowerGraph graph){
|
||||
for(Tile tile : graph.all){
|
||||
for(Tilec tile : graph.all){
|
||||
add(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public void add(Tile tile){
|
||||
if(tile.entity == null || tile.entity.power == null) return;
|
||||
tile.entity.power.graph = this;
|
||||
public void add(Tilec tile){
|
||||
if(tile == null || tile.power() == null) return;
|
||||
tile.power().graph = this;
|
||||
all.add(tile);
|
||||
|
||||
if(tile.block().outputsPower && tile.block().consumesPower && !tile.block().consumes.getPower().buffered){
|
||||
@@ -246,14 +245,14 @@ public class PowerGraph{
|
||||
}
|
||||
}
|
||||
|
||||
public void reflow(Tile tile){
|
||||
public void reflow(Tilec tile){
|
||||
queue.clear();
|
||||
queue.addLast(tile);
|
||||
closedSet.clear();
|
||||
while(queue.size > 0){
|
||||
Tile child = queue.removeFirst();
|
||||
Tilec child = queue.removeFirst();
|
||||
add(child);
|
||||
for(Tile next : child.block().getPowerConnections(child, outArray2)){
|
||||
for(Tilec next : child.getPowerConnections(outArray2)){
|
||||
if(!closedSet.contains(next.pos())){
|
||||
queue.addLast(next);
|
||||
closedSet.add(next.pos());
|
||||
@@ -262,22 +261,22 @@ public class PowerGraph{
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSingle(Tile tile){
|
||||
private void removeSingle(Tilec tile){
|
||||
all.remove(tile);
|
||||
producers.remove(tile);
|
||||
consumers.remove(tile);
|
||||
batteries.remove(tile);
|
||||
}
|
||||
|
||||
public void remove(Tile tile){
|
||||
public void remove(Tilec tile){
|
||||
removeSingle(tile);
|
||||
//begin by clearing the closed set
|
||||
closedSet.clear();
|
||||
|
||||
//go through all the connections of this tile
|
||||
for(Tile other : tile.block().getPowerConnections(tile, outArray1)){
|
||||
for(Tilec other : tile.getPowerConnections(outArray1)){
|
||||
//a graph has already been assigned to this tile from a previous call, skip it
|
||||
if(other.entity.power.graph != this) continue;
|
||||
if(other.power().graph != this) continue;
|
||||
|
||||
//create graph for this branch
|
||||
PowerGraph graph = new PowerGraph();
|
||||
@@ -287,16 +286,16 @@ public class PowerGraph{
|
||||
queue.addLast(other);
|
||||
while(queue.size > 0){
|
||||
//get child from queue
|
||||
Tile child = queue.removeFirst();
|
||||
Tilec child = queue.removeFirst();
|
||||
//remove it from this graph
|
||||
removeSingle(child);
|
||||
//add it to the new branch graph
|
||||
graph.add(child);
|
||||
//go through connections
|
||||
for(Tile next : child.block().getPowerConnections(child, outArray2)){
|
||||
for(Tilec next : child.getPowerConnections(outArray2)){
|
||||
//make sure it hasn't looped back, and that the new graph being assigned hasn't already been assigned
|
||||
//also skip closed tiles
|
||||
if(next != tile && next.entity.power.graph != graph && !closedSet.contains(next.pos())){
|
||||
if(next != tile && next.power().graph != graph && !closedSet.contains(next.pos())){
|
||||
queue.addLast(next);
|
||||
closedSet.add(next.pos());
|
||||
}
|
||||
@@ -307,9 +306,9 @@ public class PowerGraph{
|
||||
}
|
||||
}
|
||||
|
||||
private boolean otherConsumersAreValid(Tile tile, Consume consumePower){
|
||||
private boolean otherConsumersAreValid(Tilec tile, Consume consumePower){
|
||||
for(Consume cons : tile.block().consumes.all()){
|
||||
if(cons != consumePower && !cons.isOptional() && !cons.valid(tile.ent())){
|
||||
if(cons != consumePower && !cons.isOptional() && !cons.valid(tile)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
package mindustry.world.blocks.power;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.entities.type.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.modules.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class PowerNode extends PowerBlock{
|
||||
protected static boolean returnValue = false;
|
||||
protected static BuildRequest otherReq;
|
||||
|
||||
protected final ObjectSet<PowerGraph> graphs = new ObjectSet<>();
|
||||
protected final Vec2 t1 = new Vec2(), t2 = new Vec2();
|
||||
@@ -35,45 +37,52 @@ public class PowerNode extends PowerBlock{
|
||||
configurable = true;
|
||||
consumesPower = false;
|
||||
outputsPower = false;
|
||||
}
|
||||
config(Integer.class, (entity, value) -> {
|
||||
PowerModule power = entity.power();
|
||||
Tilec other = world.ent(value);
|
||||
boolean contains = power.links.contains(value), valid = other != null && other.power() != null;
|
||||
|
||||
@Override
|
||||
public void configured(Tile tile, Player player, int value){
|
||||
TileEntity entity = tile.entity;
|
||||
Tile other = world.tile(value);
|
||||
boolean contains = entity.power.links.contains(value), valid = other != null && other.entity != null && other.entity.power != null;
|
||||
if(contains){
|
||||
//unlink
|
||||
power.links.removeValue(value);
|
||||
if(valid) other.power().links.removeValue(entity.pos());
|
||||
|
||||
if(contains){
|
||||
//unlink
|
||||
entity.power.links.removeValue(value);
|
||||
if(valid) other.entity.power.links.removeValue(tile.pos());
|
||||
PowerGraph newgraph = new PowerGraph();
|
||||
|
||||
PowerGraph newgraph = new PowerGraph();
|
||||
//reflow from this point, covering all tiles on this side
|
||||
newgraph.reflow(entity);
|
||||
|
||||
//reflow from this point, covering all tiles on this side
|
||||
newgraph.reflow(tile);
|
||||
if(valid && other.power().graph != newgraph){
|
||||
//create new graph for other end
|
||||
PowerGraph og = new PowerGraph();
|
||||
//reflow from other end
|
||||
og.reflow(other);
|
||||
}
|
||||
}else if(linkValid(entity, other) && valid && power.links.size < maxNodes){
|
||||
|
||||
if(valid && other.entity.power.graph != newgraph){
|
||||
//create new graph for other end
|
||||
PowerGraph og = new PowerGraph();
|
||||
//reflow from other end
|
||||
og.reflow(other);
|
||||
if(!power.links.contains(other.pos())){
|
||||
power.links.add(other.pos());
|
||||
}
|
||||
|
||||
if(other.team() == entity.team()){
|
||||
|
||||
if(!other.power().links.contains(entity.pos())){
|
||||
other.power().links.add(entity.pos());
|
||||
}
|
||||
}
|
||||
|
||||
power.graph.add(other.power().graph);
|
||||
}
|
||||
}else if(linkValid(tile, other) && valid && entity.power.links.size < maxNodes){
|
||||
});
|
||||
|
||||
if(!entity.power.links.contains(other.pos())){
|
||||
entity.power.links.add(other.pos());
|
||||
}
|
||||
|
||||
if(other.getTeamID() == tile.getTeamID()){
|
||||
|
||||
if(!other.entity.power.links.contains(tile.pos())){
|
||||
other.entity.power.links.add(tile.pos());
|
||||
config(Point2[].class, (tile, value) -> {
|
||||
tile.power().links.clear();
|
||||
for(Point2 p : value){
|
||||
if(tile.power().links.size < maxNodes){
|
||||
tile.power().links.add(Point2.pack(p.x + tile.tileX(), p.y + tile.tileY()));
|
||||
}
|
||||
}
|
||||
|
||||
entity.power.graph.add(other.entity.power.graph);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,72 +98,15 @@ public class PowerNode extends PowerBlock{
|
||||
super.setBars();
|
||||
bars.add("power", entity -> new Bar(() ->
|
||||
Core.bundle.format("bar.powerbalance",
|
||||
((entity.power.graph.getPowerBalance() >= 0 ? "+" : "") + Strings.fixed(entity.power.graph.getPowerBalance() * 60, 1))),
|
||||
() -> Pal.powerBar,
|
||||
() -> Mathf.clamp(entity.power.graph.getLastPowerProduced() / entity.power.graph.getLastPowerNeeded())));
|
||||
((entity.power().graph.getPowerBalance() >= 0 ? "+" : "") + Strings.fixed(entity.power().graph.getPowerBalance() * 60, 1))),
|
||||
() -> Pal.powerBar,
|
||||
() -> Mathf.clamp(entity.power().graph.getLastPowerProduced() / entity.power().graph.getLastPowerNeeded())));
|
||||
|
||||
bars.add("batteries", entity -> new Bar(() ->
|
||||
Core.bundle.format("bar.powerstored",
|
||||
(ui.formatAmount((int)entity.power.graph.getBatteryStored())), ui.formatAmount((int)entity.power.graph.getTotalBatteryCapacity())),
|
||||
() -> Pal.powerBar,
|
||||
() -> Mathf.clamp(entity.power.graph.getBatteryStored() / entity.power.graph.getTotalBatteryCapacity())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placed(Tile tile){
|
||||
if(net.client()) return;
|
||||
|
||||
Boolf<Tile> valid = other -> other != null && other != tile && ((!other.block().outputsPower && other.block().consumesPower) || (other.block().outputsPower && !other.block().consumesPower) || other.block() instanceof PowerNode) && linkValid(tile, other)
|
||||
&& !other.entity.proximity().contains(tile) && other.entity.power.graph != tile.entity.power.graph;
|
||||
|
||||
tempTiles.clear();
|
||||
Geometry.circle(tile.x, tile.y, (int)(laserRange + 2), (x, y) -> {
|
||||
Tile other = world.ltile(x, y);
|
||||
if(valid.get(other)){
|
||||
if(!insulated(tile, other)){
|
||||
tempTiles.add(other);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tempTiles.sort((a, b) -> {
|
||||
int type = -Boolean.compare(a.block() instanceof PowerNode, b.block() instanceof PowerNode);
|
||||
if(type != 0) return type;
|
||||
return Float.compare(a.dst2(tile), b.dst2(tile));
|
||||
});
|
||||
tempTiles.each(valid, other -> {
|
||||
if(!tile.entity.power.links.contains(other.pos())){
|
||||
tile.configureAny(other.pos());
|
||||
}
|
||||
});
|
||||
|
||||
super.placed(tile);
|
||||
}
|
||||
|
||||
private void getPotentialLinks(Tile tile, Cons<Tile> others){
|
||||
Boolf<Tile> valid = other -> other != null && other != tile && other.entity != null && other.entity.power != null &&
|
||||
((!other.block().outputsPower && other.block().consumesPower) || (other.block().outputsPower && !other.block().consumesPower) || other.block() instanceof PowerNode) &&
|
||||
overlaps(tile.x * tilesize + offset(), tile.y * tilesize + offset(), other, laserRange * tilesize) && other.getTeam() == player.getTeam()
|
||||
&& !other.entity.proximity().contains(tile) && !graphs.contains(other.entity.power.graph);
|
||||
|
||||
tempTiles.clear();
|
||||
graphs.clear();
|
||||
Geometry.circle(tile.x, tile.y, (int)(laserRange + 2), (x, y) -> {
|
||||
Tile other = world.ltile(x, y);
|
||||
if(valid.get(other) && !tempTiles.contains(other)){
|
||||
tempTiles.add(other);
|
||||
}
|
||||
});
|
||||
|
||||
tempTiles.sort((a, b) -> {
|
||||
int type = -Boolean.compare(a.block() instanceof PowerNode, b.block() instanceof PowerNode);
|
||||
if(type != 0) return type;
|
||||
return Float.compare(a.dst2(tile), b.dst2(tile));
|
||||
});
|
||||
tempTiles.each(valid, t -> {
|
||||
graphs.add(t.entity.power.graph);
|
||||
others.get(t);
|
||||
});
|
||||
(ui.formatAmount((int)entity.power().graph.getBatteryStored())), ui.formatAmount((int)entity.power().graph.getTotalBatteryCapacity())),
|
||||
() -> Pal.powerBar,
|
||||
() -> Mathf.clamp(entity.power().graph.getBatteryStored() / entity.power().graph.getTotalBatteryCapacity())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,81 +117,6 @@ public class PowerNode extends PowerBlock{
|
||||
stats.add(BlockStat.powerConnections, maxNodes, StatUnit.none);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
tile.entity.power.graph.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConfigureTileTapped(Tile tile, Tile other){
|
||||
TileEntity entity = tile.ent();
|
||||
other = other.link();
|
||||
|
||||
if(linkValid(tile, other)){
|
||||
tile.configure(other.pos());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(tile == other){
|
||||
if(other.entity.power.links.size == 0){
|
||||
int[] total = {0};
|
||||
getPotentialLinks(tile, link -> {
|
||||
if(!insulated(tile, link) && total[0]++ < maxNodes){
|
||||
tile.configure(link.pos());
|
||||
}
|
||||
});
|
||||
}else{
|
||||
while(entity.power.links.size > 0){
|
||||
tile.configure(entity.power.links.get(0));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
super.drawSelect(tile);
|
||||
|
||||
Lines.stroke(1f);
|
||||
|
||||
Draw.color(Pal.accent);
|
||||
Drawf.circles(tile.drawx(), tile.drawy(), laserRange * tilesize);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawConfigure(Tile tile){
|
||||
|
||||
Draw.color(Pal.accent);
|
||||
|
||||
Lines.stroke(1.5f);
|
||||
Lines.circle(tile.drawx(), tile.drawy(),
|
||||
tile.block().size * tilesize / 2f + 1f + Mathf.absin(Time.time(), 4f, 1f));
|
||||
|
||||
Drawf.circles(tile.drawx(), tile.drawy(), laserRange * tilesize);
|
||||
|
||||
Lines.stroke(1.5f);
|
||||
|
||||
for(int x = (int)(tile.x - laserRange - 2); x <= tile.x + laserRange + 2; x++){
|
||||
for(int y = (int)(tile.y - laserRange - 2); y <= tile.y + laserRange + 2; y++){
|
||||
Tile link = world.ltile(x, y);
|
||||
|
||||
if(link != tile && linkValid(tile, link, false)){
|
||||
boolean linked = linked(tile, link);
|
||||
|
||||
if(linked){
|
||||
Drawf.square(link.drawx(), link.drawy(), link.block().size * tilesize / 2f + 1f, Pal.place);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||
Tile tile = world.tile(x, y);
|
||||
@@ -251,59 +128,47 @@ public class PowerNode extends PowerBlock{
|
||||
Drawf.circles(x * tilesize + offset(), y * tilesize + offset(), laserRange * tilesize);
|
||||
|
||||
getPotentialLinks(tile, other -> {
|
||||
Drawf.square(other.drawx(), other.drawy(), other.block().size * tilesize / 2f + 2f, Pal.place);
|
||||
Drawf.square(other.x(), other.y(), other.block().size * tilesize / 2f + 2f, Pal.place);
|
||||
|
||||
insulators(tile.x, tile.y, other.x, other.y, cause -> {
|
||||
Drawf.square(cause.drawx(), cause.drawy(), cause.block().size * tilesize / 2f + 2f, Pal.plastanium);
|
||||
insulators(tile.x, tile.y, other.tileX(), other.tileY(), cause -> {
|
||||
Drawf.square(cause.x(), cause.y(), cause.block().size * tilesize / 2f + 2f, Pal.plastanium);
|
||||
});
|
||||
});
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
if(Core.settings.getInt("lasersopacity") == 0) return;
|
||||
protected void drawLaser(float x1, float y1, float x2, float y2, float satisfaction, int size1, int size2){
|
||||
int opacityPercentage = Core.settings.getInt("lasersopacity");
|
||||
if(opacityPercentage == 0) return;
|
||||
|
||||
TileEntity entity = tile.ent();
|
||||
float opacity = opacityPercentage / 100f;
|
||||
|
||||
for(int i = 0; i < entity.power.links.size; i++){
|
||||
Tile link = world.tile(entity.power.links.get(i));
|
||||
float angle1 = Angles.angle(x1, y1, x2, y2);
|
||||
t1.trns(angle1, size1 * tilesize / 2f - 1.5f);
|
||||
t2.trns(angle1 + 180f, size2 * tilesize / 2f - 1.5f);
|
||||
|
||||
if(!linkValid(tile, link)) continue;
|
||||
x1 += t1.x;
|
||||
y1 += t1.y;
|
||||
x2 += t2.x;
|
||||
y2 += t2.y;
|
||||
|
||||
if(link.block() instanceof PowerNode && !(link.pos() < tile.pos())) continue;
|
||||
float fract = 1f - satisfaction;
|
||||
|
||||
drawLaser(tile, link);
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
protected boolean linked(Tile tile, Tile other){
|
||||
return tile.entity.power.links.contains(other.pos());
|
||||
}
|
||||
|
||||
public boolean linkValid(Tile tile, Tile link){
|
||||
return linkValid(tile, link, true);
|
||||
}
|
||||
|
||||
public boolean linkValid(Tile tile, Tile link, boolean checkMaxNodes){
|
||||
if(tile == link || link == null || link.entity == null || tile.entity == null || !link.block().hasPower || tile.getTeam() != link.getTeam()) return false;
|
||||
|
||||
if(overlaps(tile, link, laserRange * tilesize) || (link.block() instanceof PowerNode && overlaps(link, tile, link.<PowerNode>cblock().laserRange * tilesize))){
|
||||
if(checkMaxNodes && link.block() instanceof PowerNode){
|
||||
return link.entity.power.links.size < link.<PowerNode>cblock().maxNodes || link.entity.power.links.contains(tile.pos());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
Draw.color(Color.white, Pal.powerLight, fract * 0.86f + Mathf.absin(3f, 0.1f));
|
||||
Draw.alpha(opacity);
|
||||
Drawf.laser(laser, laserEnd, x1, y1, x2, y2, 0.25f);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
protected boolean overlaps(float srcx, float srcy, Tile other, float range){
|
||||
return Intersector.overlaps(Tmp.cr1.set(srcx, srcy, range), other.getHitbox(Tmp.r1));
|
||||
}
|
||||
|
||||
protected boolean overlaps(Tilec src, Tilec other, float range){
|
||||
return overlaps(src.x(), src.y(), other.tile(), range);
|
||||
}
|
||||
|
||||
protected boolean overlaps(Tile src, Tile other, float range){
|
||||
return overlaps(src.drawx(), src.drawy(), other, range);
|
||||
}
|
||||
@@ -313,51 +178,233 @@ public class PowerNode extends PowerBlock{
|
||||
return Intersector.overlaps(Tmp.cr1.set(src.worldx() + offset(), src.worldy() + offset(), laserRange * tilesize), Tmp.r1.setSize(size * tilesize).setCenter(other.worldx() + offset(), other.worldy() + offset()));
|
||||
}
|
||||
|
||||
protected void drawLaser(Tile tile, Tile target){
|
||||
int opacityPercentage = Core.settings.getInt("lasersopacity");
|
||||
if(opacityPercentage == 0) return;
|
||||
protected void getPotentialLinks(Tile tile, Cons<Tilec> others){
|
||||
Boolf<Tilec> valid = other -> other != null && other.tile() != tile && other.power() != null &&
|
||||
((!other.block().outputsPower && other.block().consumesPower) || (other.block().outputsPower && !other.block().consumesPower) || other.block() instanceof PowerNode) &&
|
||||
overlaps(tile.x * tilesize + offset(), tile.y * tilesize + offset(), other.tile(), laserRange * tilesize) && other.team() == player.team()
|
||||
&& !other.proximity().contains(e -> e.tile() == tile) && !graphs.contains(other.power().graph);
|
||||
|
||||
float opacity = opacityPercentage / 100f;
|
||||
tempTileEnts.clear();
|
||||
graphs.clear();
|
||||
Geometry.circle(tile.x, tile.y, (int)(laserRange + 2), (x, y) -> {
|
||||
Tilec other = world.ent(x, y);
|
||||
if(valid.get(other) && !tempTileEnts.contains(other)){
|
||||
tempTileEnts.add(other);
|
||||
}
|
||||
});
|
||||
|
||||
float x1 = tile.drawx(), y1 = tile.drawy(),
|
||||
x2 = target.drawx(), y2 = target.drawy();
|
||||
tempTileEnts.sort((a, b) -> {
|
||||
int type = -Boolean.compare(a.block() instanceof PowerNode, b.block() instanceof PowerNode);
|
||||
if(type != 0) return type;
|
||||
return Float.compare(a.dst2(tile), b.dst2(tile));
|
||||
});
|
||||
|
||||
float angle1 = Angles.angle(x1, y1, x2, y2);
|
||||
t1.trns(angle1, tile.block().size * tilesize / 2f - 1.5f);
|
||||
t2.trns(angle1 + 180f, target.block().size * tilesize / 2f - 1.5f);
|
||||
tempTileEnts.each(valid, t -> {
|
||||
graphs.add(t.power().graph);
|
||||
others.get(t);
|
||||
});
|
||||
}
|
||||
|
||||
x1 += t1.x;
|
||||
y1 += t1.y;
|
||||
x2 += t2.x;
|
||||
y2 += t2.y;
|
||||
@Override
|
||||
public void drawRequestConfigTop(BuildRequest req, Eachable<BuildRequest> list){
|
||||
if(req.config instanceof Point2[]){
|
||||
for(Point2 point : (Point2[])req.config){
|
||||
otherReq = null;
|
||||
list.each(other -> {
|
||||
if((other.x == req.x + point.x && other.y == req.y + point.y) && other != req){
|
||||
otherReq = other;
|
||||
}
|
||||
});
|
||||
|
||||
float fract = 1f - tile.entity.power.graph.getSatisfaction();
|
||||
if(otherReq == null || otherReq.block == null) return;
|
||||
|
||||
Draw.color(Color.white, Pal.powerLight, fract * 0.86f + Mathf.absin(3f, 0.1f));
|
||||
Draw.alpha(opacity);
|
||||
Drawf.laser(laser, laserEnd, x1, y1, x2, y2, 0.25f);
|
||||
Draw.color();
|
||||
drawLaser(req.drawx(), req.drawy(), otherReq.drawx(), otherReq.drawy(), 1f, size, otherReq.block.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean linkValid(Tilec tile, Tilec link){
|
||||
return linkValid(tile, link, true);
|
||||
}
|
||||
|
||||
public boolean linkValid(Tilec tile, Tilec link, boolean checkMaxNodes){
|
||||
if(tile == link || link == null || !link.block().hasPower || tile.team() != link.team()) return false;
|
||||
|
||||
if(overlaps(tile, link, laserRange * tilesize) || (link.block() instanceof PowerNode && overlaps(link, tile, ((PowerNode)link.block()).laserRange * tilesize))){
|
||||
if(checkMaxNodes && link.block() instanceof PowerNode){
|
||||
return link.power().links.size < ((PowerNode)link.block()).maxNodes || link.power().links.contains(tile.pos());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean insulated(Tile tile, Tile other){
|
||||
return insulated(tile.x, tile.y, other.x, other.y);
|
||||
}
|
||||
|
||||
public static boolean insulated(Tilec tile, Tilec other){
|
||||
return insulated(tile.tileX(), tile.tileY(), other.tileX(), other.tileY());
|
||||
}
|
||||
|
||||
public static boolean insulated(int x, int y, int x2, int y2){
|
||||
returnValue = false;
|
||||
insulators(x, y, x2, y2, cause -> returnValue = true);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public static void insulators(int x, int y, int x2, int y2, Cons<Tile> iterator){
|
||||
public static void insulators(int x, int y, int x2, int y2, Cons<Tilec> iterator){
|
||||
world.raycastEach(x, y, x2, y2, (wx, wy) -> {
|
||||
|
||||
Tile tile = world.ltile(wx, wy);
|
||||
if(tile != null && tile.block() != null && tile.block().insulated){
|
||||
Tilec tile = world.ent(wx, wy);
|
||||
if(tile != null && tile.block().insulated){
|
||||
iterator.get(tile);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public class PowerNodeEntity extends TileEntity{
|
||||
|
||||
@Override
|
||||
public void placed(){
|
||||
if(net.client()) return;
|
||||
|
||||
Boolf<Tilec> valid = other -> other != null && other != tile && ((!other.block().outputsPower && other.block().consumesPower) ||
|
||||
(other.block().outputsPower && !other.block().consumesPower) || other.block() instanceof PowerNode) && linkValid(this, other)
|
||||
&& !other.proximity().contains(this) && other.power().graph != power.graph;
|
||||
|
||||
tempTileEnts.clear();
|
||||
Geometry.circle(tile.x, tile.y, (int)(laserRange + 2), (x, y) -> {
|
||||
Tilec other = world.ent(x, y);
|
||||
if(valid.get(other)){
|
||||
if(!insulated(this, other)){
|
||||
tempTileEnts.add(other);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tempTileEnts.sort((a, b) -> {
|
||||
int type = -Boolean.compare(a.block() instanceof PowerNode, b.block() instanceof PowerNode);
|
||||
if(type != 0) return type;
|
||||
return Float.compare(a.dst2(tile), b.dst2(tile));
|
||||
});
|
||||
tempTileEnts.each(valid, other -> {
|
||||
if(!power.links.contains(other.pos())){
|
||||
tile.configureAny(other.pos());
|
||||
}
|
||||
});
|
||||
|
||||
super.placed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
power.graph.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConfigureTileTapped(Tilec other){
|
||||
if(linkValid(this, other)){
|
||||
tile.configure(other.pos());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this == other){
|
||||
if(other.power().links.size == 0){
|
||||
int[] total = {0};
|
||||
getPotentialLinks(tile, link -> {
|
||||
if(!insulated(this, link) && total[0]++ < maxNodes){
|
||||
tile.configure(link.pos());
|
||||
}
|
||||
});
|
||||
}else{
|
||||
while(power.links.size > 0){
|
||||
tile.configure(power.links.get(0));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(){
|
||||
super.drawSelect();
|
||||
|
||||
Lines.stroke(1f);
|
||||
|
||||
Draw.color(Pal.accent);
|
||||
Drawf.circles(x, y, laserRange * tilesize);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawConfigure(){
|
||||
|
||||
Draw.color(Pal.accent);
|
||||
|
||||
Lines.stroke(1.5f);
|
||||
Lines.circle(x, y,
|
||||
tile.block().size * tilesize / 2f + 1f + Mathf.absin(Time.time(), 4f, 1f));
|
||||
|
||||
Drawf.circles(x, y, laserRange * tilesize);
|
||||
|
||||
Lines.stroke(1.5f);
|
||||
|
||||
for(int x = (int)(tile.x - laserRange - 2); x <= tile.x + laserRange + 2; x++){
|
||||
for(int y = (int)(tile.y - laserRange - 2); y <= tile.y + laserRange + 2; y++){
|
||||
Tilec link = world.ent(x, y);
|
||||
|
||||
if(link != this && linkValid(this, link, false)){
|
||||
boolean linked = linked(link);
|
||||
|
||||
if(linked){
|
||||
Drawf.square(link.x(), link.y(), link.block().size * tilesize / 2f + 1f, Pal.place);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(){
|
||||
if(Core.settings.getInt("lasersopacity") == 0) return;
|
||||
|
||||
Tilec entity = tile.ent();
|
||||
|
||||
for(int i = 0; i < power.links.size; i++){
|
||||
Tilec link = world.ent(power.links.get(i));
|
||||
|
||||
if(!linkValid(this, link)) continue;
|
||||
|
||||
if(link.block() instanceof PowerNode && !(link.pos() < tile.pos())) continue;
|
||||
|
||||
drawLaserTo(link);
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
protected boolean linked(Tilec other){
|
||||
return power.links.contains(other.pos());
|
||||
}
|
||||
|
||||
protected void drawLaserTo(Tilec target){
|
||||
drawLaser(x, y, target.x(), target.y(), power.graph.getSatisfaction(), size, target.block().size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point2[] config(){
|
||||
Point2[] out = new Point2[power.links.size];
|
||||
for(int i = 0; i < out.length; i++){
|
||||
out[i] = Point2.unpack(power.links.get(i)).sub(tile.x, tile.y);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package mindustry.world.blocks.power;
|
||||
|
||||
import arc.struct.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.state;
|
||||
@@ -10,21 +9,21 @@ public class SolarGenerator extends PowerGenerator{
|
||||
|
||||
public SolarGenerator(String name){
|
||||
super(name);
|
||||
// Remove the BlockFlag.producer flag to make this a lower priority target than other generators.
|
||||
//remove the BlockFlag.producer flag to make this a lower priority target than other generators.
|
||||
flags = EnumSet.of();
|
||||
entityType = GeneratorEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
tile.<GeneratorEntity>ent().productionEfficiency = state.rules.solarPowerMultiplier < 0 ? (state.rules.lighting ? 1f - state.rules.ambientLight.a : 1f) : state.rules.solarPowerMultiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
// Solar Generators don't really have an efficiency (yet), so for them 100% = 1.0f
|
||||
stats.remove(generationType);
|
||||
stats.add(generationType, powerProduction * 60.0f, StatUnit.powerSecond);
|
||||
}
|
||||
|
||||
public class SolarGeneratorEntity extends GeneratorEntity{
|
||||
@Override
|
||||
public void updateTile(){
|
||||
productionEfficiency = state.rules.solarPowerMultiplier < 0 ? (state.rules.lighting ? 1f - state.rules.ambientLight.a : 1f) : state.rules.solarPowerMultiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import arc.graphics.*;
|
||||
import arc.math.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
@@ -26,44 +25,42 @@ public class ThermalGenerator extends PowerGenerator{
|
||||
stats.add(BlockStat.tiles, attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
GeneratorEntity entity = tile.ent();
|
||||
|
||||
if(entity.productionEfficiency > 0.1f && Mathf.chance(0.05 * entity.delta())){
|
||||
Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||
drawPlaceText(Core.bundle.formatFloat("bar.efficiency", sumAttribute(attribute, x, y) * 100, 1), x, y, valid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(Tile tile){
|
||||
GeneratorEntity entity = tile.ent();
|
||||
renderer.lights.add(tile.drawx(), tile.drawy(), (40f + Mathf.absin(10f, 5f)) * entity.productionEfficiency * size, Color.scarlet, 0.4f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityAdded(Tile tile){
|
||||
super.onProximityAdded(tile);
|
||||
|
||||
GeneratorEntity entity = tile.ent();
|
||||
entity.productionEfficiency = sumAttribute(attribute, tile.x, tile.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPowerProduction(Tile tile){
|
||||
//in this case, productionEfficiency means 'total heat'
|
||||
//thus, it may be greater than 1.0
|
||||
return powerProduction * tile.<GeneratorEntity>ent().productionEfficiency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlaceOn(Tile tile){
|
||||
//make sure there's heat at this location
|
||||
return tile.getLinkedTilesAs(this, tempTiles).sumf(other -> other.floor().attributes.get(attribute)) > 0.01f;
|
||||
}
|
||||
|
||||
public class ThermalGeneratorEntity extends GeneratorEntity{
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(productionEfficiency > 0.1f && Mathf.chance(0.05 * delta())){
|
||||
generateEffect.at(x + Mathf.range(3f), y + Mathf.range(3f));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(){
|
||||
renderer.lights.add(x, y, (40f + Mathf.absin(10f, 5f)) * productionEfficiency * size, Color.scarlet, 0.4f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityAdded(){
|
||||
super.onProximityAdded();
|
||||
|
||||
productionEfficiency = sumAttribute(attribute, tile.x, tile.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPowerProduction(){
|
||||
//in this case, productionEfficiency means 'total heat'
|
||||
//thus, it may be greater than 1.0
|
||||
return powerProduction * productionEfficiency;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,12 @@ import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class Cultivator extends GenericCrafter{
|
||||
public Color plantColor = Color.valueOf("5541b1");
|
||||
public Color plantColorLight = Color.valueOf("7457ce");
|
||||
@@ -27,7 +24,6 @@ public class Cultivator extends GenericCrafter{
|
||||
public Cultivator(String name){
|
||||
super(name);
|
||||
craftEffect = Fx.none;
|
||||
entityType = CultivatorEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -38,14 +34,6 @@ public class Cultivator extends GenericCrafter{
|
||||
topRegion = Core.atlas.find(name + "-top");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
super.update(tile);
|
||||
|
||||
CultivatorEntity entity = tile.ent();
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, entity.cons.valid() ? 1f : 0f, 0.015f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBars(){
|
||||
super.setBars();
|
||||
@@ -68,67 +56,70 @@ public class Cultivator extends GenericCrafter{
|
||||
drawPlaceText(Core.bundle.formatFloat("bar.efficiency", (1 + sumAttribute(attribute, x, y)) * 100, 1), x, y, valid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
CultivatorEntity entity = tile.ent();
|
||||
|
||||
Draw.rect(region, tile.drawx(), tile.drawy());
|
||||
|
||||
Draw.color(plantColor);
|
||||
Draw.alpha(entity.warmup);
|
||||
Draw.rect(middleRegion, tile.drawx(), tile.drawy());
|
||||
|
||||
Draw.color(bottomColor, plantColorLight, entity.warmup);
|
||||
|
||||
random.setSeed(tile.pos());
|
||||
for(int i = 0; i < 12; i++){
|
||||
float offset = random.nextFloat() * 999999f;
|
||||
float x = random.range(4f), y = random.range(4f);
|
||||
float life = 1f - (((Time.time() + offset) / 50f) % recurrence);
|
||||
|
||||
if(life > 0){
|
||||
Lines.stroke(entity.warmup * (life * 1f + 0.2f));
|
||||
Lines.poly(tile.drawx() + x, tile.drawy() + y, 8, (1f - life) * 3f);
|
||||
}
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-top"),};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityAdded(Tile tile){
|
||||
super.onProximityAdded(tile);
|
||||
|
||||
CultivatorEntity entity = tile.ent();
|
||||
entity.boost = sumAttribute(attribute, tile.x, tile.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getProgressIncrease(TileEntity entity, float baseTime){
|
||||
CultivatorEntity c = (CultivatorEntity)entity;
|
||||
return super.getProgressIncrease(entity, baseTime) * (1f + c.boost);
|
||||
}
|
||||
|
||||
public static class CultivatorEntity extends GenericCrafterEntity{
|
||||
public class CultivatorEntity extends GenericCrafterEntity{
|
||||
public float warmup;
|
||||
public float boost;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeFloat(warmup);
|
||||
public void updateTile(){
|
||||
super.updateTile();
|
||||
|
||||
warmup = Mathf.lerpDelta(warmup, consValid() ? 1f : 0f, 0.015f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
warmup = stream.readFloat();
|
||||
public void draw(){
|
||||
Draw.rect(region, x, y);
|
||||
|
||||
Draw.color(plantColor);
|
||||
Draw.alpha(warmup);
|
||||
Draw.rect(middleRegion, x, y);
|
||||
|
||||
Draw.color(bottomColor, plantColorLight, warmup);
|
||||
|
||||
random.setSeed(tile.pos());
|
||||
for(int i = 0; i < 12; i++){
|
||||
float offset = random.nextFloat() * 999999f;
|
||||
float x = random.range(4f), y = random.range(4f);
|
||||
float life = 1f - (((Time.time() + offset) / 50f) % recurrence);
|
||||
|
||||
if(life > 0){
|
||||
Lines.stroke(warmup * (life * 1f + 0.2f));
|
||||
Lines.poly(x + x, y + y, 8, (1f - life) * 3f);
|
||||
}
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
Draw.rect(topRegion, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(){
|
||||
super.onProximityAdded();
|
||||
|
||||
boost = sumAttribute(attribute, tile.x, tile.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getProgressIncrease(float baseTime){
|
||||
return super.getProgressIncrease(baseTime) * (1f + boost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.f(warmup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
warmup = read.f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package mindustry.world.blocks.production;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
@@ -64,8 +62,6 @@ public class Drill extends Block{
|
||||
hasLiquids = true;
|
||||
liquidCapacity = 5f;
|
||||
hasItems = true;
|
||||
entityType = DrillEntity::new;
|
||||
|
||||
idleSound = Sounds.drill;
|
||||
idleSoundVolume = 0.003f;
|
||||
}
|
||||
@@ -77,7 +73,7 @@ public class Drill extends Block{
|
||||
bars.add("drillspeed", e -> {
|
||||
DrillEntity entity = (DrillEntity)e;
|
||||
|
||||
return new Bar(() -> Core.bundle.format("bar.drillspeed", Strings.fixed(entity.lastDrillSpeed * 60 * entity.timeScale, 2)), () -> Pal.ammo, () -> entity.warmup);
|
||||
return new Bar(() -> Core.bundle.format("bar.drillspeed", Strings.fixed(entity.lastDrillSpeed * 60 * entity.timeScale(), 2)), () -> Pal.ammo, () -> entity.warmup);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -89,52 +85,22 @@ public class Drill extends Block{
|
||||
topRegion = Core.atlas.find(name + "-top");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawCracks(Tile tile){}
|
||||
public Item getDrop(Tile tile){
|
||||
return tile.drop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
float s = 0.3f;
|
||||
float ts = 0.6f;
|
||||
|
||||
DrillEntity entity = tile.ent();
|
||||
|
||||
Draw.rect(region, tile.drawx(), tile.drawy());
|
||||
super.drawCracks(tile);
|
||||
|
||||
if(drawRim){
|
||||
Draw.color(heatColor);
|
||||
Draw.alpha(entity.warmup * ts * (1f - s + Mathf.absin(Time.time(), 3f, s)));
|
||||
Draw.blend(Blending.additive);
|
||||
Draw.rect(rimRegion, tile.drawx(), tile.drawy());
|
||||
Draw.blend();
|
||||
Draw.color();
|
||||
public boolean canPlaceOn(Tile tile){
|
||||
if(isMultiblock()){
|
||||
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
||||
if(canMine(other)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}else{
|
||||
return canMine(tile);
|
||||
}
|
||||
|
||||
Draw.rect(rotatorRegion, tile.drawx(), tile.drawy(), entity.drillTime * rotateSpeed);
|
||||
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||
|
||||
if(entity.dominantItem != null && drawMineItem){
|
||||
Draw.color(entity.dominantItem.color);
|
||||
Draw.rect("drill-top", tile.drawx(), tile.drawy(), 1f);
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-rotator"), Core.atlas.find(name + "-top")};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldConsume(Tile tile){
|
||||
return tile.entity.items.total() < itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(Tile tile){
|
||||
return tile.entity.efficiency() > 0.01f;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -160,19 +126,6 @@ public class Drill extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
DrillEntity entity = tile.ent();
|
||||
|
||||
if(entity.dominantItem != null){
|
||||
float dx = tile.drawx() - size * tilesize/2f, dy = tile.drawy() + size * tilesize/2f;
|
||||
Draw.mixcol(Color.darkGray, 1f);
|
||||
Draw.rect(entity.dominantItem.icon(Cicon.small), dx, dy - 1);
|
||||
Draw.reset();
|
||||
Draw.rect(entity.dominantItem.icon(Cicon.small), dx, dy);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
@@ -203,6 +156,11 @@ public class Drill extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-rotator"), Core.atlas.find(name + "-top")};
|
||||
}
|
||||
|
||||
void countOre(Tile tile){
|
||||
returnItem = null;
|
||||
returnCount = 0;
|
||||
@@ -211,7 +169,7 @@ public class Drill extends Block{
|
||||
itemArray.clear();
|
||||
|
||||
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
||||
if(isValid(other)){
|
||||
if(canMine(other)){
|
||||
oreCount.getAndIncrement(getDrop(other), 0, 1);
|
||||
}
|
||||
}
|
||||
@@ -236,97 +194,126 @@ public class Drill extends Block{
|
||||
returnCount = oreCount.get(itemArray.peek(), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
DrillEntity entity = tile.ent();
|
||||
|
||||
if(entity.dominantItem == null){
|
||||
countOre(tile);
|
||||
if(returnItem == null) return;
|
||||
entity.dominantItem = returnItem;
|
||||
entity.dominantItems = returnCount;
|
||||
}
|
||||
|
||||
if(entity.timer.get(timerDump, dumpTime)){
|
||||
tryDump(tile, entity.dominantItem);
|
||||
}
|
||||
|
||||
entity.drillTime += entity.warmup * entity.delta();
|
||||
|
||||
if(entity.items.total() < itemCapacity && entity.dominantItems > 0 && entity.cons.valid()){
|
||||
|
||||
float speed = 1f;
|
||||
|
||||
if(entity.cons.optionalValid()){
|
||||
speed = liquidBoostIntensity;
|
||||
}
|
||||
|
||||
speed *= entity.efficiency(); // Drill slower when not at full power
|
||||
|
||||
entity.lastDrillSpeed = (speed * entity.dominantItems * entity.warmup) / (drillTime + hardnessDrillMultiplier * entity.dominantItem.hardness);
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, speed, warmupSpeed);
|
||||
entity.progress += entity.delta()
|
||||
* entity.dominantItems * speed * entity.warmup;
|
||||
|
||||
if(Mathf.chance(Time.delta() * updateEffectChance * entity.warmup))
|
||||
Effects.effect(updateEffect, entity.x + Mathf.range(size * 2f), entity.y + Mathf.range(size * 2f));
|
||||
}else{
|
||||
entity.lastDrillSpeed = 0f;
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, warmupSpeed);
|
||||
return;
|
||||
}
|
||||
|
||||
if(entity.dominantItems > 0 && entity.progress >= drillTime + hardnessDrillMultiplier * entity.dominantItem.hardness && tile.entity.items.total() < itemCapacity){
|
||||
|
||||
offloadNear(tile, entity.dominantItem);
|
||||
|
||||
useContent(tile, entity.dominantItem);
|
||||
|
||||
entity.index++;
|
||||
entity.progress = 0f;
|
||||
|
||||
Effects.effect(drillEffect, entity.dominantItem.color,
|
||||
entity.x + Mathf.range(size), entity.y + Mathf.range(size));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlaceOn(Tile tile){
|
||||
if(isMultiblock()){
|
||||
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
||||
if(isValid(other)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}else{
|
||||
return isValid(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public int tier(){
|
||||
return tier;
|
||||
}
|
||||
|
||||
public Item getDrop(Tile tile){
|
||||
return tile.drop();
|
||||
}
|
||||
|
||||
public boolean isValid(Tile tile){
|
||||
public boolean canMine(Tile tile){
|
||||
if(tile == null) return false;
|
||||
Item drops = tile.drop();
|
||||
return drops != null && drops.hardness <= tier;
|
||||
}
|
||||
|
||||
public static class DrillEntity extends TileEntity{
|
||||
public class DrillEntity extends TileEntity{
|
||||
float progress;
|
||||
int index;
|
||||
float warmup;
|
||||
float drillTime;
|
||||
float timeDrilled;
|
||||
float lastDrillSpeed;
|
||||
|
||||
int dominantItems;
|
||||
Item dominantItem;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean shouldConsume(){
|
||||
return items.total() < itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(){
|
||||
return efficiency() > 0.01f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(){
|
||||
if(dominantItem != null){
|
||||
float dx = x - size * tilesize/2f, dy = y + size * tilesize/2f;
|
||||
Draw.mixcol(Color.darkGray, 1f);
|
||||
Draw.rect(dominantItem.icon(Cicon.small), dx, dy - 1);
|
||||
Draw.reset();
|
||||
Draw.rect(dominantItem.icon(Cicon.small), dx, dy);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(){
|
||||
countOre(tile);
|
||||
dominantItem = returnItem;
|
||||
dominantItems = returnCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(dominantItem == null){
|
||||
return;
|
||||
}
|
||||
|
||||
if(timer(timerDump, dumpTime)){
|
||||
dump(dominantItem);
|
||||
}
|
||||
|
||||
timeDrilled += warmup * delta();
|
||||
|
||||
if(items.total() < itemCapacity && dominantItems > 0 && consValid()){
|
||||
|
||||
float speed = 1f;
|
||||
|
||||
if(cons().optionalValid()){
|
||||
speed = liquidBoostIntensity;
|
||||
}
|
||||
|
||||
speed *= efficiency(); // Drill slower when not at full power
|
||||
|
||||
lastDrillSpeed = (speed * dominantItems * warmup) / (drillTime + hardnessDrillMultiplier * dominantItem.hardness);
|
||||
warmup = Mathf.lerpDelta(warmup, speed, warmupSpeed);
|
||||
progress += delta() * dominantItems * speed * warmup;
|
||||
|
||||
if(Mathf.chance(Time.delta() * updateEffectChance * warmup))
|
||||
updateEffect.at(getX() + Mathf.range(size * 2f), getY() + Mathf.range(size * 2f));
|
||||
}else{
|
||||
lastDrillSpeed = 0f;
|
||||
warmup = Mathf.lerpDelta(warmup, 0f, warmupSpeed);
|
||||
return;
|
||||
}
|
||||
|
||||
if(dominantItems > 0 && progress >= drillTime + hardnessDrillMultiplier * dominantItem.hardness && items.total() < itemCapacity){
|
||||
offloadNear(dominantItem);
|
||||
useContent(dominantItem);
|
||||
|
||||
index++;
|
||||
progress = 0f;
|
||||
|
||||
drillEffect.at(getX() + Mathf.range(size), getY() + Mathf.range(size), dominantItem.color);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawCracks(){}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
float s = 0.3f;
|
||||
float ts = 0.6f;
|
||||
|
||||
Draw.rect(region, x, y);
|
||||
super.drawCracks();
|
||||
|
||||
if(drawRim){
|
||||
Draw.color(heatColor);
|
||||
Draw.alpha(warmup * ts * (1f - s + Mathf.absin(Time.time(), 3f, s)));
|
||||
Draw.blend(Blending.additive);
|
||||
Draw.rect(rimRegion, x, y);
|
||||
Draw.blend();
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
Draw.rect(rotatorRegion, x, y, timeDrilled * rotateSpeed);
|
||||
|
||||
Draw.rect(topRegion, x, y);
|
||||
|
||||
if(dominantItem != null && drawMineItem){
|
||||
Draw.color(dominantItem.color);
|
||||
Draw.rect("drill-top", x, y, 1f);
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package mindustry.world.blocks.production;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class Fracker extends SolidPump{
|
||||
@@ -15,7 +14,6 @@ public class Fracker extends SolidPump{
|
||||
public Fracker(String name){
|
||||
super(name);
|
||||
hasItems = true;
|
||||
entityType = FrackerEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -39,58 +37,54 @@ public class Fracker extends SolidPump{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawCracks(Tile tile){}
|
||||
|
||||
@Override
|
||||
public boolean shouldConsume(Tile tile){
|
||||
return tile.entity.liquids.get(result) < liquidCapacity - 0.01f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
FrackerEntity entity = tile.ent();
|
||||
|
||||
Draw.rect(region, tile.drawx(), tile.drawy());
|
||||
super.drawCracks(tile);
|
||||
|
||||
Draw.color(result.color);
|
||||
Draw.alpha(tile.entity.liquids.get(result) / liquidCapacity);
|
||||
Draw.rect(liquidRegion, tile.drawx(), tile.drawy());
|
||||
Draw.color();
|
||||
|
||||
Draw.rect(rotatorRegion, tile.drawx(), tile.drawy(), entity.pumpTime);
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-rotator"), Core.atlas.find(name + "-top")};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
FrackerEntity entity = tile.ent();
|
||||
public class FrackerEntity extends SolidPumpEntity{
|
||||
public float accumulator;
|
||||
|
||||
if(entity.cons.valid()){
|
||||
if(entity.accumulator >= itemUseTime){
|
||||
entity.cons.trigger();
|
||||
entity.accumulator -= itemUseTime;
|
||||
@Override
|
||||
public void drawCracks(){}
|
||||
|
||||
@Override
|
||||
public boolean shouldConsume(){
|
||||
return liquids.get(result) < liquidCapacity - 0.01f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect(region, x, y);
|
||||
super.drawCracks();
|
||||
|
||||
Draw.color(result.color);
|
||||
Draw.alpha(liquids.get(result) / liquidCapacity);
|
||||
Draw.rect(liquidRegion, x, y);
|
||||
Draw.color();
|
||||
|
||||
Draw.rect(rotatorRegion, x, y, pumpTime);
|
||||
Draw.rect(topRegion, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(consValid()){
|
||||
if(accumulator >= itemUseTime){
|
||||
consume();
|
||||
accumulator -= itemUseTime;
|
||||
}
|
||||
|
||||
super.updateTile();
|
||||
accumulator += delta() * efficiency();
|
||||
}else{
|
||||
dumpLiquid(result);
|
||||
}
|
||||
}
|
||||
|
||||
super.update(tile);
|
||||
entity.accumulator += entity.delta() * entity.efficiency();
|
||||
}else{
|
||||
tryDumpLiquid(tile, result);
|
||||
@Override
|
||||
public float typeLiquid(){
|
||||
return liquids.get(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float typeLiquid(Tile tile){
|
||||
return tile.entity.liquids.get(result);
|
||||
}
|
||||
|
||||
public static class FrackerEntity extends SolidPumpEntity{
|
||||
public float accumulator;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,15 @@ import arc.func.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class GenericCrafter extends Block{
|
||||
public ItemStack outputItem;
|
||||
public LiquidStack outputLiquid;
|
||||
@@ -25,7 +22,7 @@ public class GenericCrafter extends Block{
|
||||
public Effect updateEffect = Fx.none;
|
||||
public float updateEffectChance = 0.04f;
|
||||
|
||||
public Cons<Tile> drawer = null;
|
||||
public Cons<GenericCrafterEntity> drawer = null;
|
||||
public Prov<TextureRegion[]> drawIcons = null;
|
||||
|
||||
public GenericCrafter(String name){
|
||||
@@ -37,7 +34,6 @@ public class GenericCrafter extends Block{
|
||||
idleSound = Sounds.machine;
|
||||
sync = true;
|
||||
idleSoundVolume = 0.03f;
|
||||
entityType = GenericCrafterEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,111 +55,109 @@ public class GenericCrafter extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(Tile tile){
|
||||
return tile.entity.cons.valid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
outputsLiquid = outputLiquid != null;
|
||||
super.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
if(drawer == null){
|
||||
super.draw(tile);
|
||||
}else{
|
||||
drawer.get(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] generateIcons(){
|
||||
return drawIcons == null ? super.generateIcons() : drawIcons.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
GenericCrafterEntity entity = tile.ent();
|
||||
|
||||
if(entity.cons.valid()){
|
||||
|
||||
entity.progress += getProgressIncrease(entity, craftTime);
|
||||
entity.totalProgress += entity.delta();
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.02f);
|
||||
|
||||
if(Mathf.chance(Time.delta() * updateEffectChance)){
|
||||
Effects.effect(updateEffect, entity.x + Mathf.range(size * 4f), entity.y + Mathf.range(size * 4));
|
||||
}
|
||||
}else{
|
||||
entity.warmup = Mathf.lerp(entity.warmup, 0f, 0.02f);
|
||||
}
|
||||
|
||||
if(entity.progress >= 1f){
|
||||
entity.cons.trigger();
|
||||
|
||||
if(outputItem != null){
|
||||
useContent(tile, outputItem.item);
|
||||
for(int i = 0; i < outputItem.amount; i++){
|
||||
offloadNear(tile, outputItem.item);
|
||||
}
|
||||
}
|
||||
|
||||
if(outputLiquid != null){
|
||||
useContent(tile, outputLiquid.liquid);
|
||||
handleLiquid(tile, tile, outputLiquid.liquid, outputLiquid.amount);
|
||||
}
|
||||
|
||||
Effects.effect(craftEffect, tile.drawx(), tile.drawy());
|
||||
entity.progress = 0f;
|
||||
}
|
||||
|
||||
if(outputItem != null && tile.entity.timer.get(timerDump, dumpTime)){
|
||||
tryDump(tile, outputItem.item);
|
||||
}
|
||||
|
||||
if(outputLiquid != null){
|
||||
tryDumpLiquid(tile, outputLiquid.liquid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outputsItems(){
|
||||
return outputItem != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldConsume(Tile tile){
|
||||
if(outputItem != null && tile.entity.items.get(outputItem.item) >= itemCapacity){
|
||||
return false;
|
||||
}
|
||||
return outputLiquid == null || !(tile.entity.liquids.get(outputLiquid.liquid) >= liquidCapacity - 0.001f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAccepted(Tile tile, Item item){
|
||||
return itemCapacity;
|
||||
}
|
||||
|
||||
public static class GenericCrafterEntity extends TileEntity{
|
||||
public class GenericCrafterEntity extends TileEntity{
|
||||
public float progress;
|
||||
public float totalProgress;
|
||||
public float warmup;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeFloat(progress);
|
||||
stream.writeFloat(warmup);
|
||||
public void draw(){
|
||||
if(drawer == null){
|
||||
super.draw();
|
||||
}else{
|
||||
drawer.get(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
progress = stream.readFloat();
|
||||
warmup = stream.readFloat();
|
||||
public boolean shouldConsume(){
|
||||
if(outputItem != null && items.get(outputItem.item) >= itemCapacity){
|
||||
return false;
|
||||
}
|
||||
return outputLiquid == null || !(liquids.get(outputLiquid.liquid) >= liquidCapacity - 0.001f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(consValid()){
|
||||
|
||||
progress += getProgressIncrease(craftTime);
|
||||
totalProgress += delta();
|
||||
warmup = Mathf.lerpDelta(warmup, 1f, 0.02f);
|
||||
|
||||
if(Mathf.chance(Time.delta() * updateEffectChance)){
|
||||
updateEffect.at(getX() + Mathf.range(size * 4f), getY() + Mathf.range(size * 4));
|
||||
}
|
||||
}else{
|
||||
warmup = Mathf.lerp(warmup, 0f, 0.02f);
|
||||
}
|
||||
|
||||
if(progress >= 1f){
|
||||
consume();
|
||||
|
||||
if(outputItem != null){
|
||||
useContent(outputItem.item);
|
||||
for(int i = 0; i < outputItem.amount; i++){
|
||||
offloadNear(outputItem.item);
|
||||
}
|
||||
}
|
||||
|
||||
if(outputLiquid != null){
|
||||
useContent(outputLiquid.liquid);
|
||||
handleLiquid(this, outputLiquid.liquid, outputLiquid.amount);
|
||||
}
|
||||
|
||||
craftEffect.at(x, y);
|
||||
progress = 0f;
|
||||
}
|
||||
|
||||
if(outputItem != null && timer(timerDump, dumpTime)){
|
||||
dump(outputItem.item);
|
||||
}
|
||||
|
||||
if(outputLiquid != null){
|
||||
dumpLiquid(outputLiquid.liquid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAccepted(Item item){
|
||||
return itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(){
|
||||
return cons.valid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.f(progress);
|
||||
write.f(warmup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
progress = read.f();
|
||||
warmup = read.f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.renderer;
|
||||
|
||||
@@ -24,34 +23,32 @@ public class GenericSmelter extends GenericCrafter{
|
||||
topRegion = Core.atlas.find(name + "-top");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
public class SmelterEntity extends GenericCrafterEntity{
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
GenericCrafterEntity entity = tile.ent();
|
||||
//draw glowing center
|
||||
if(warmup > 0f && flameColor.a > 0.001f){
|
||||
float g = 0.3f;
|
||||
float r = 0.06f;
|
||||
float cr = Mathf.random(0.1f);
|
||||
|
||||
//draw glowing center
|
||||
if(entity.warmup > 0f && flameColor.a > 0.001f){
|
||||
float g = 0.3f;
|
||||
float r = 0.06f;
|
||||
float cr = Mathf.random(0.1f);
|
||||
Draw.alpha(((1f - g) + Mathf.absin(Time.time(), 8f, g) + Mathf.random(r) - r) * warmup);
|
||||
|
||||
Draw.alpha(((1f - g) + Mathf.absin(Time.time(), 8f, g) + Mathf.random(r) - r) * entity.warmup);
|
||||
Draw.tint(flameColor);
|
||||
Fill.circle(x, y, 3f + Mathf.absin(Time.time(), 5f, 2f) + cr);
|
||||
Draw.color(1f, 1f, 1f, warmup);
|
||||
Draw.rect(topRegion, x, y);
|
||||
Fill.circle(x, y, 1.9f + Mathf.absin(Time.time(), 5f, 1f) + cr);
|
||||
|
||||
Draw.tint(flameColor);
|
||||
Fill.circle(tile.drawx(), tile.drawy(), 3f + Mathf.absin(Time.time(), 5f, 2f) + cr);
|
||||
Draw.color(1f, 1f, 1f, entity.warmup);
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||
Fill.circle(tile.drawx(), tile.drawy(), 1.9f + Mathf.absin(Time.time(), 5f, 1f) + cr);
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
@Override
|
||||
public void drawLight(){
|
||||
renderer.lights.add(x, y, (60f + Mathf.absin(10f, 5f)) * warmup * size, flameColor, 0.65f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(Tile tile){
|
||||
GenericCrafterEntity entity = tile.ent();
|
||||
|
||||
renderer.lights.add(tile.drawx(), tile.drawy(), (60f + Mathf.absin(10f, 5f)) * entity.warmup * size, flameColor, 0.65f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
package mindustry.world.blocks.production;
|
||||
|
||||
import arc.graphics.Color;
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.graphics.g2d.Fill;
|
||||
import arc.math.Mathf;
|
||||
import arc.util.Time;
|
||||
import mindustry.content.Fx;
|
||||
import mindustry.entities.Effects;
|
||||
import mindustry.entities.Effects.Effect;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.type.Item;
|
||||
import mindustry.type.Liquid;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class Incinerator extends Block{
|
||||
public Effect effect = Fx.fuelburn;
|
||||
@@ -24,68 +20,61 @@ public class Incinerator extends Block{
|
||||
hasLiquids = true;
|
||||
update = true;
|
||||
solid = true;
|
||||
entityType = IncineratorEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
IncineratorEntity entity = tile.ent();
|
||||
|
||||
if(entity.cons.valid()){
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, 1f, 0.04f);
|
||||
}else{
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, 0f, 0.02f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
IncineratorEntity entity = tile.ent();
|
||||
|
||||
if(entity.heat > 0f){
|
||||
float g = 0.3f;
|
||||
float r = 0.06f;
|
||||
|
||||
Draw.alpha(((1f - g) + Mathf.absin(Time.time(), 8f, g) + Mathf.random(r) - r) * entity.heat);
|
||||
|
||||
Draw.tint(flameColor);
|
||||
Fill.circle(tile.drawx(), tile.drawy(), 2f);
|
||||
Draw.color(1f, 1f, 1f, entity.heat);
|
||||
Fill.circle(tile.drawx(), tile.drawy(), 1f);
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
if(Mathf.chance(0.3)){
|
||||
Effects.effect(effect, tile.drawx(), tile.drawy());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
IncineratorEntity entity = tile.ent();
|
||||
return entity.heat > 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
if(Mathf.chance(0.02)){
|
||||
Effects.effect(effect, tile.drawx(), tile.drawy());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
IncineratorEntity entity = tile.ent();
|
||||
return entity.heat > 0.5f;
|
||||
}
|
||||
|
||||
public static class IncineratorEntity extends TileEntity{
|
||||
public class IncineratorEntity extends TileEntity{
|
||||
public float heat;
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(consValid()){
|
||||
heat = Mathf.lerpDelta(heat, 1f, 0.04f);
|
||||
}else{
|
||||
heat = Mathf.lerpDelta(heat, 0f, 0.02f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
if(heat > 0f){
|
||||
float g = 0.3f;
|
||||
float r = 0.06f;
|
||||
|
||||
Draw.alpha(((1f - g) + Mathf.absin(Time.time(), 8f, g) + Mathf.random(r) - r) * heat);
|
||||
|
||||
Draw.tint(flameColor);
|
||||
Fill.circle(x, y, 2f);
|
||||
Draw.color(1f, 1f, 1f, heat);
|
||||
Fill.circle(x, y, 1f);
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Tilec source, Item item){
|
||||
if(Mathf.chance(0.3)){
|
||||
effect.at(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return heat > 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLiquid(Tilec source, Liquid liquid, float amount){
|
||||
if(Mathf.chance(0.02)){
|
||||
effect.at(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tilec source, Liquid liquid, float amount){
|
||||
return heat > 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package mindustry.world.blocks.production;
|
||||
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.consumers.ConsumeLiquidBase;
|
||||
import mindustry.world.consumers.ConsumeType;
|
||||
import mindustry.world.meta.BlockStat;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class LiquidConverter extends GenericCrafter{
|
||||
|
||||
@@ -32,30 +30,31 @@ public class LiquidConverter extends GenericCrafter{
|
||||
stats.add(BlockStat.output, outputLiquid.liquid, outputLiquid.amount * craftTime, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(Tile tile){
|
||||
if(hasLiquids && drawLiquidLight && outputLiquid.liquid.lightColor.a > 0.001f){
|
||||
drawLiquidLight(tile, outputLiquid.liquid, tile.entity.liquids.get(outputLiquid.liquid));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
GenericCrafterEntity entity = tile.ent();
|
||||
ConsumeLiquidBase cl = consumes.get(ConsumeType.liquid);
|
||||
|
||||
if(tile.entity.cons.valid()){
|
||||
float use = Math.min(cl.amount * entity.delta(), liquidCapacity - entity.liquids.get(outputLiquid.liquid)) * entity.efficiency();
|
||||
|
||||
useContent(tile, outputLiquid.liquid);
|
||||
entity.progress += use / cl.amount / craftTime;
|
||||
entity.liquids.add(outputLiquid.liquid, use);
|
||||
if(entity.progress >= 1f){
|
||||
entity.cons.trigger();
|
||||
entity.progress = 0f;
|
||||
public class LiquidConverterEntity extends GenericCrafterEntity{
|
||||
@Override
|
||||
public void drawLight(){
|
||||
if(hasLiquids && drawLiquidLight && outputLiquid.liquid.lightColor.a > 0.001f){
|
||||
drawLiquidLight(outputLiquid.liquid, liquids.get(outputLiquid.liquid));
|
||||
}
|
||||
}
|
||||
|
||||
tryDumpLiquid(tile, outputLiquid.liquid);
|
||||
@Override
|
||||
public void updateTile(){
|
||||
ConsumeLiquidBase cl = consumes.get(ConsumeType.liquid);
|
||||
|
||||
if(cons.valid()){
|
||||
float use = Math.min(cl.amount * delta(), liquidCapacity - liquids.get(outputLiquid.liquid)) * efficiency();
|
||||
|
||||
useContent(outputLiquid.liquid);
|
||||
progress += use / cl.amount / craftTime;
|
||||
liquids.add(outputLiquid.liquid, use);
|
||||
if(progress >= 1f){
|
||||
consume();
|
||||
progress = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
dumpLiquid(outputLiquid.liquid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,18 @@
|
||||
package mindustry.world.blocks.production;
|
||||
|
||||
import arc.Core;
|
||||
import arc.struct.Array;
|
||||
import arc.graphics.Color;
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.graphics.g2d.TextureRegion;
|
||||
import mindustry.graphics.Layer;
|
||||
import mindustry.type.Liquid;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.blocks.LiquidBlock;
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.liquid.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
import static mindustry.Vars.world;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Pump extends LiquidBlock{
|
||||
protected final Array<Tile> drawTiles = new Array<>();
|
||||
protected final Array<Tile> updateTiles = new Array<>();
|
||||
|
||||
public final int timerContentCheck = timers++;
|
||||
|
||||
/** Pump amount, total. */
|
||||
@@ -44,16 +38,6 @@ public class Pump extends LiquidBlock{
|
||||
stats.add(BlockStat.output, 60f * pumpAmount, StatUnit.liquidSecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
Draw.rect(name, tile.drawx(), tile.drawy());
|
||||
|
||||
Draw.color(tile.entity.liquids.current().color);
|
||||
Draw.alpha(tile.entity.liquids.total() / liquidCapacity);
|
||||
Draw.rect(liquidRegion, tile.drawx(), tile.drawy());
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPlace(int x, int y, int rotation, boolean valid) {
|
||||
Tile tile = world.tile(x, y);
|
||||
@@ -63,7 +47,7 @@ public class Pump extends LiquidBlock{
|
||||
Liquid liquidDrop = null;
|
||||
|
||||
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
||||
if(isValid(other)){
|
||||
if(canPump(other)){
|
||||
liquidDrop = other.floor().liquidDrop;
|
||||
tiles++;
|
||||
}
|
||||
@@ -88,7 +72,7 @@ public class Pump extends LiquidBlock{
|
||||
public boolean canPlaceOn(Tile tile){
|
||||
if(isMultiblock()){
|
||||
Liquid last = null;
|
||||
for(Tile other : tile.getLinkedTilesAs(this, drawTiles)){
|
||||
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
||||
if(other.floor().liquidDrop == null)
|
||||
continue;
|
||||
if(other.floor().liquidDrop != last && last != null)
|
||||
@@ -97,41 +81,54 @@ public class Pump extends LiquidBlock{
|
||||
}
|
||||
return last != null;
|
||||
}else{
|
||||
return isValid(tile);
|
||||
return canPump(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
float tiles = 0f;
|
||||
Liquid liquidDrop = null;
|
||||
|
||||
if(isMultiblock()){
|
||||
for(Tile other : tile.getLinkedTiles(updateTiles)){
|
||||
if(isValid(other)){
|
||||
liquidDrop = other.floor().liquidDrop;
|
||||
tiles++;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
tiles = 1f;
|
||||
liquidDrop = tile.floor().liquidDrop;
|
||||
}
|
||||
|
||||
if(tile.entity.cons.valid() && liquidDrop != null){
|
||||
float maxPump = Math.min(liquidCapacity - tile.entity.liquids.total(), tiles * pumpAmount * tile.entity.delta() / size / size) * tile.entity.efficiency();
|
||||
tile.entity.liquids.add(liquidDrop, maxPump);
|
||||
}
|
||||
|
||||
if(tile.entity.liquids.currentAmount() > 0f && tile.entity.timer.get(timerContentCheck, 10)){
|
||||
useContent(tile, tile.entity.liquids.current());
|
||||
}
|
||||
|
||||
tryDumpLiquid(tile, tile.entity.liquids.current());
|
||||
}
|
||||
|
||||
protected boolean isValid(Tile tile){
|
||||
protected boolean canPump(Tile tile){
|
||||
return tile != null && tile.floor().liquidDrop != null;
|
||||
}
|
||||
|
||||
public class PumpEntity extends LiquidBlockEntity{
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect(name, x, y);
|
||||
|
||||
Draw.color(liquids.current().color);
|
||||
Draw.alpha(liquids.total() / liquidCapacity);
|
||||
Draw.rect(liquidRegion, x, y);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
float tiles = 0f;
|
||||
Liquid liquidDrop = null;
|
||||
|
||||
if(isMultiblock()){
|
||||
for(Tile other : tile.getLinkedTiles(tempTiles)){
|
||||
if(canPump(other)){
|
||||
liquidDrop = other.floor().liquidDrop;
|
||||
tiles++;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
tiles = 1f;
|
||||
liquidDrop = tile.floor().liquidDrop;
|
||||
}
|
||||
|
||||
if(cons.valid() && liquidDrop != null){
|
||||
float maxPump = Math.min(liquidCapacity - liquids.total(), tiles * pumpAmount * delta() / size / size) * efficiency();
|
||||
liquids.add(liquidDrop, maxPump);
|
||||
}
|
||||
|
||||
if(liquids.currentAmount() > 0f && timer(timerContentCheck, 10)){
|
||||
useContent(liquids.current());
|
||||
}
|
||||
|
||||
dumpLiquid(liquids.current());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,9 +4,10 @@ import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.production.GenericCrafter.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.meta.values.*;
|
||||
@@ -30,7 +31,6 @@ public class Separator extends Block{
|
||||
|
||||
liquidRegion = reg("-liquid");
|
||||
spinnerRegion = reg("-spinner");
|
||||
entityType = GenericCrafterEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,68 +52,88 @@ public class Separator extends Block{
|
||||
stats.add(BlockStat.productionTime, craftTime / 60f, StatUnit.seconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldConsume(Tile tile){
|
||||
return tile.entity.items.total() < itemCapacity;
|
||||
}
|
||||
public class SeparatorEntity extends TileEntity{
|
||||
public float progress;
|
||||
public float totalProgress;
|
||||
public float warmup;
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
GenericCrafterEntity entity = tile.ent();
|
||||
|
||||
Draw.color(tile.entity.liquids.current().color);
|
||||
Draw.alpha(tile.entity.liquids.total() / liquidCapacity);
|
||||
Draw.rect(reg(liquidRegion), tile.drawx(), tile.drawy());
|
||||
|
||||
Draw.reset();
|
||||
if(Core.atlas.isFound(reg(spinnerRegion))){
|
||||
Draw.rect(reg(spinnerRegion), tile.drawx(), tile.drawy(), entity.totalProgress * spinnerSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
GenericCrafterEntity entity = tile.ent();
|
||||
|
||||
entity.totalProgress += entity.warmup * entity.delta();
|
||||
|
||||
if(entity.cons.valid()){
|
||||
entity.progress += getProgressIncrease(entity, craftTime);
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.02f);
|
||||
}else{
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.02f);
|
||||
@Override
|
||||
public boolean shouldIdleSound(){
|
||||
return cons.valid();
|
||||
}
|
||||
|
||||
if(entity.progress >= 1f){
|
||||
entity.progress = 0f;
|
||||
int sum = 0;
|
||||
for(ItemStack stack : results) sum += stack.amount;
|
||||
@Override
|
||||
public boolean shouldConsume(){
|
||||
return items.total() < itemCapacity;
|
||||
}
|
||||
|
||||
int i = Mathf.random(sum);
|
||||
int count = 0;
|
||||
Item item = null;
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
//TODO guaranteed desync since items are random
|
||||
for(ItemStack stack : results){
|
||||
if(i >= count && i < count + stack.amount){
|
||||
item = stack.item;
|
||||
break;
|
||||
Draw.color(liquids.current().color);
|
||||
Draw.alpha(liquids.total() / liquidCapacity);
|
||||
Draw.rect(reg(liquidRegion), x, y);
|
||||
|
||||
Draw.reset();
|
||||
if(Core.atlas.isFound(reg(spinnerRegion))){
|
||||
Draw.rect(reg(spinnerRegion), x, y, totalProgress * spinnerSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
totalProgress += warmup * delta();
|
||||
|
||||
if(consValid()){
|
||||
progress += getProgressIncrease(craftTime);
|
||||
warmup = Mathf.lerpDelta(warmup, 1f, 0.02f);
|
||||
}else{
|
||||
warmup = Mathf.lerpDelta(warmup, 0f, 0.02f);
|
||||
}
|
||||
|
||||
if(progress >= 1f){
|
||||
progress = 0f;
|
||||
int sum = 0;
|
||||
for(ItemStack stack : results) sum += stack.amount;
|
||||
|
||||
int i = Mathf.random(sum);
|
||||
int count = 0;
|
||||
Item item = null;
|
||||
|
||||
//TODO guaranteed desync since items are random
|
||||
for(ItemStack stack : results){
|
||||
if(i >= count && i < count + stack.amount){
|
||||
item = stack.item;
|
||||
break;
|
||||
}
|
||||
count += stack.amount;
|
||||
}
|
||||
|
||||
consume();
|
||||
|
||||
if(item != null && items.get(item) < itemCapacity){
|
||||
offloadNear(item);
|
||||
}
|
||||
count += stack.amount;
|
||||
}
|
||||
|
||||
entity.cons.trigger();
|
||||
|
||||
if(item != null && entity.items.get(item) < itemCapacity){
|
||||
useContent(tile, item);
|
||||
offloadNear(tile, item);
|
||||
if(timer(timerDump, dumpTime)){
|
||||
dump();
|
||||
}
|
||||
}
|
||||
|
||||
if(entity.timer.get(timerDump, dumpTime)){
|
||||
tryDump(tile);
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.f(progress);
|
||||
write.f(warmup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
progress = read.f();
|
||||
warmup = read.f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
package mindustry.world.blocks.production;
|
||||
|
||||
import arc.Core;
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.graphics.g2d.TextureRegion;
|
||||
import arc.math.Mathf;
|
||||
import arc.util.*;
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.content.Fx;
|
||||
import mindustry.content.Liquids;
|
||||
import mindustry.entities.Effects;
|
||||
import mindustry.entities.Effects.Effect;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.graphics.Pal;
|
||||
import mindustry.type.Liquid;
|
||||
import mindustry.ui.Bar;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.Attribute;
|
||||
import mindustry.world.meta.BlockStat;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
/**
|
||||
* Pump that makes liquid from solids and takes in power. Only works on solid floor blocks.
|
||||
@@ -32,7 +27,6 @@ public class SolidPump extends Pump{
|
||||
public SolidPump(String name){
|
||||
super(name);
|
||||
hasPower = true;
|
||||
entityType = SolidPumpEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,7 +39,7 @@ public class SolidPump extends Pump{
|
||||
@Override
|
||||
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||
if(attribute != null){
|
||||
drawPlaceText(Core.bundle.formatFloat("bar.efficiency", (sumAttribute(attribute, x, y) + 1f) * 100 * percentSolid(x, y), 1), x, y, valid);
|
||||
drawPlaceText(Core.bundle.formatFloat("bar.efficiency", Math.max(sumAttribute(attribute, x, y) + 1f, 0f) * 100 * percentSolid(x, y), 1), x, y, valid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,16 +65,22 @@ public class SolidPump extends Pump{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
SolidPumpEntity entity = tile.ent();
|
||||
public boolean canPlaceOn(Tile tile){
|
||||
if(isMultiblock()){
|
||||
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
||||
if(canPump(other)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}else{
|
||||
return canPump(tile);
|
||||
}
|
||||
}
|
||||
|
||||
Draw.rect(region, tile.drawx(), tile.drawy());
|
||||
Draw.color(tile.entity.liquids.current().color);
|
||||
Draw.alpha(tile.entity.liquids.total() / liquidCapacity);
|
||||
Draw.rect(liquidRegion, tile.drawx(), tile.drawy());
|
||||
Draw.color();
|
||||
Draw.rect(name + "-rotator", tile.drawx(), tile.drawy(), entity.pumpTime * rotateSpeed);
|
||||
Draw.rect(name + "-top", tile.drawx(), tile.drawy());
|
||||
@Override
|
||||
protected boolean canPump(Tile tile){
|
||||
return tile != null && !tile.floor().isLiquid;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,79 +88,69 @@ public class SolidPump extends Pump{
|
||||
return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-rotator"), Core.atlas.find(name + "-top")};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
SolidPumpEntity entity = tile.ent();
|
||||
|
||||
float fraction = 0f;
|
||||
|
||||
if(isMultiblock()){
|
||||
for(Tile other : tile.getLinkedTiles(tempTiles)){
|
||||
if(isValid(other)){
|
||||
fraction += 1f / (size * size);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(isValid(tile)) fraction = 1f;
|
||||
}
|
||||
|
||||
fraction += entity.boost;
|
||||
|
||||
if(tile.entity.cons.valid() && typeLiquid(tile) < liquidCapacity - 0.001f){
|
||||
float maxPump = Math.min(liquidCapacity - typeLiquid(tile), pumpAmount * entity.delta() * fraction * entity.efficiency());
|
||||
tile.entity.liquids.add(result, maxPump);
|
||||
entity.lastPump = maxPump;
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.02f);
|
||||
if(tile.entity.timer.get(timerContentCheck, 10)) useContent(tile, result);
|
||||
if(Mathf.chance(entity.delta() * updateEffectChance))
|
||||
Effects.effect(updateEffect, entity.x + Mathf.range(size * 2f), entity.y + Mathf.range(size * 2f));
|
||||
}else{
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.02f);
|
||||
entity.lastPump = 0f;
|
||||
}
|
||||
|
||||
entity.pumpTime += entity.warmup * entity.delta();
|
||||
|
||||
tryDumpLiquid(tile, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlaceOn(Tile tile){
|
||||
if(isMultiblock()){
|
||||
for(Tile other : tile.getLinkedTilesAs(this, drawTiles)){
|
||||
if(isValid(other)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}else{
|
||||
return isValid(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValid(Tile tile){
|
||||
return tile != null && !tile.floor().isLiquid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityAdded(Tile tile){
|
||||
super.onProximityAdded(tile);
|
||||
|
||||
if(attribute != null){
|
||||
SolidPumpEntity entity = tile.ent();
|
||||
entity.boost = sumAttribute(attribute, tile.x, tile.y);
|
||||
}
|
||||
}
|
||||
|
||||
public float typeLiquid(Tile tile){
|
||||
return tile.entity.liquids.total();
|
||||
}
|
||||
|
||||
public static class SolidPumpEntity extends TileEntity{
|
||||
public class SolidPumpEntity extends PumpEntity{
|
||||
public float warmup;
|
||||
public float pumpTime;
|
||||
public float boost;
|
||||
public float lastPump;
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect(region, x, y);
|
||||
Draw.color(liquids.current().color);
|
||||
Draw.alpha(liquids.total() / liquidCapacity);
|
||||
Draw.rect(liquidRegion, x, y);
|
||||
Draw.color();
|
||||
Draw.rect(name + "-rotator", x, y, pumpTime * rotateSpeed);
|
||||
Draw.rect(name + "-top", x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
float fraction = 0f;
|
||||
|
||||
if(isMultiblock()){
|
||||
for(Tile other : tile.getLinkedTiles(tempTiles)){
|
||||
if(canPump(other)){
|
||||
fraction += 1f / (size * size);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(canPump(tile)) fraction = 1f;
|
||||
}
|
||||
|
||||
fraction += boost;
|
||||
fraction = Math.max(fraction, 0);
|
||||
|
||||
if(cons.valid() && typeLiquid() < liquidCapacity - 0.001f){
|
||||
float maxPump = Math.min(liquidCapacity - typeLiquid(), pumpAmount * delta() * fraction * efficiency());
|
||||
liquids.add(result, maxPump);
|
||||
lastPump = maxPump;
|
||||
warmup = Mathf.lerpDelta(warmup, 1f, 0.02f);
|
||||
if(timer(timerContentCheck, 10)) useContent(result);
|
||||
if(Mathf.chance(delta() * updateEffectChance))
|
||||
updateEffect.at(getX() + Mathf.range(size * 2f), getY() + Mathf.range(size * 2f));
|
||||
}else{
|
||||
warmup = Mathf.lerpDelta(warmup, 0f, 0.02f);
|
||||
lastPump = 0f;
|
||||
}
|
||||
|
||||
pumpTime += warmup * delta();
|
||||
|
||||
dumpLiquid(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(){
|
||||
super.onProximityAdded();
|
||||
|
||||
if(attribute != null){
|
||||
boost = sumAttribute(attribute, tile.x, tile.y);
|
||||
}
|
||||
}
|
||||
|
||||
public float typeLiquid(){
|
||||
return liquids.total();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,14 @@ import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.content;
|
||||
|
||||
public class ItemSource extends Block{
|
||||
@@ -25,19 +24,8 @@ public class ItemSource extends Block{
|
||||
solid = true;
|
||||
group = BlockGroup.transportation;
|
||||
configurable = true;
|
||||
entityType = ItemSourceEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configured(Tile tile, Player player, int value){
|
||||
tile.<ItemSourceEntity>ent().outputItem = content.item(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerPlaced(Tile tile){
|
||||
if(lastItem != null){
|
||||
Core.app.post(() -> tile.configure(lastItem.id));
|
||||
}
|
||||
config(Item.class, (tile, item) -> ((ItemSourceEntity)tile).outputItem = item);
|
||||
configClear(tile -> ((ItemSourceEntity)tile).outputItem = null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,7 +36,7 @@ public class ItemSource extends Block{
|
||||
|
||||
@Override
|
||||
public void drawRequestConfig(BuildRequest req, Eachable<BuildRequest> list){
|
||||
drawRequestConfigCenter(req, content.item(req.config), "center");
|
||||
drawRequestConfigCenter(req, req.config, "center");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,60 +44,61 @@ public class ItemSource extends Block{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
ItemSourceEntity entity = tile.ent();
|
||||
if(entity.outputItem == null) return;
|
||||
|
||||
Draw.color(entity.outputItem.color);
|
||||
Draw.rect("center", tile.worldx(), tile.worldy());
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ItemSourceEntity entity = tile.ent();
|
||||
if(entity.outputItem == null) return;
|
||||
|
||||
entity.items.set(entity.outputItem, 1);
|
||||
tryDump(tile, entity.outputItem);
|
||||
entity.items.set(entity.outputItem, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
ItemSourceEntity entity = tile.ent();
|
||||
ItemSelection.buildTable(table, content.items(), () -> entity.outputItem, item -> {
|
||||
lastItem = item;
|
||||
tile.configure(item == null ? -1 : item.id);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return false;
|
||||
}
|
||||
|
||||
public class ItemSourceEntity extends TileEntity{
|
||||
Item outputItem;
|
||||
|
||||
@Override
|
||||
public int config(){
|
||||
return outputItem == null ? -1 : outputItem.id;
|
||||
public void playerPlaced(){
|
||||
if(lastItem != null){
|
||||
Core.app.post(() -> tile.configure(lastItem));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeShort(outputItem == null ? -1 : outputItem.id);
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
if(outputItem == null) return;
|
||||
|
||||
Draw.color(outputItem.color);
|
||||
Draw.rect("center", x, y);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
outputItem = content.item(stream.readShort());
|
||||
public void updateTile(){
|
||||
if(outputItem == null) return;
|
||||
|
||||
items.set(outputItem, 1);
|
||||
dump(outputItem);
|
||||
items.set(outputItem, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ItemSelection.buildTable(table, content.items(), () -> outputItem, item -> tile.configure(lastItem = item));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item config(){
|
||||
return outputItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.s(outputItem == null ? -1 : outputItem.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
outputItem = content.item(read.s());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package mindustry.world.blocks.sandbox;
|
||||
|
||||
import mindustry.type.Item;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class ItemVoid extends Block{
|
||||
|
||||
@@ -11,12 +11,13 @@ public class ItemVoid extends Block{
|
||||
update = solid = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
}
|
||||
public class ItemVoidEntity extends TileEntity{
|
||||
@Override
|
||||
public void handleItem(Tilec source, Item item){}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return true;
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ import arc.graphics.g2d.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.content;
|
||||
|
||||
public class LiquidSource extends Block{
|
||||
@@ -26,14 +26,8 @@ public class LiquidSource extends Block{
|
||||
liquidCapacity = 100f;
|
||||
configurable = true;
|
||||
outputsLiquid = true;
|
||||
entityType = LiquidSourceEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerPlaced(Tile tile){
|
||||
if(lastLiquid != null){
|
||||
Core.app.post(() -> tile.configure(lastLiquid.id));
|
||||
}
|
||||
config(Liquid.class, (tile, l) -> ((LiquidSourceEntity)tile).source = l);
|
||||
configClear(tile -> ((LiquidSourceEntity)tile).source = null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -43,69 +37,62 @@ public class LiquidSource extends Block{
|
||||
bars.remove("liquid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
LiquidSourceEntity entity = tile.ent();
|
||||
|
||||
if(entity.source == null){
|
||||
tile.entity.liquids.clear();
|
||||
}else{
|
||||
tile.entity.liquids.add(entity.source, liquidCapacity);
|
||||
tryDumpLiquid(tile, entity.source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRequestConfig(BuildRequest req, Eachable<BuildRequest> list){
|
||||
drawRequestConfigCenter(req, content.liquid(req.config), "center");
|
||||
drawRequestConfigCenter(req, (Content)req.config, "center");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
LiquidSourceEntity entity = tile.ent();
|
||||
|
||||
if(entity.source != null){
|
||||
Draw.color(entity.source.color);
|
||||
Draw.rect("center", tile.worldx(), tile.worldy());
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
LiquidSourceEntity entity = tile.ent();
|
||||
|
||||
ItemSelection.buildTable(table, content.liquids(), () -> entity.source, liquid -> {
|
||||
lastLiquid = liquid;
|
||||
tile.configure(liquid == null ? -1 : liquid.id);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configured(Tile tile, Player player, int value){
|
||||
tile.<LiquidSourceEntity>ent().source = value == -1 ? null : content.liquid(value);
|
||||
}
|
||||
|
||||
class LiquidSourceEntity extends TileEntity{
|
||||
public class LiquidSourceEntity extends TileEntity{
|
||||
public @Nullable Liquid source = null;
|
||||
|
||||
@Override
|
||||
public int config(){
|
||||
return source == null ? -1 : source.id;
|
||||
public void updateTile(){
|
||||
if(source == null){
|
||||
liquids.clear();
|
||||
}else{
|
||||
liquids.add(source, liquidCapacity);
|
||||
dumpLiquid(source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeByte(source == null ? -1 : source.id);
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
if(source != null){
|
||||
Draw.color(source.color);
|
||||
Draw.rect("center", x, y);
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
byte id = stream.readByte();
|
||||
public void buildConfiguration(Table table){
|
||||
ItemSelection.buildTable(table, content.liquids(), () -> source, liquid -> tile.configure(lastLiquid = liquid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerPlaced(){
|
||||
if(lastLiquid != null){
|
||||
Core.app.post(() -> tile.configure(lastLiquid));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Liquid config(){
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.b(source == null ? -1 : source.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
byte id = read.b();
|
||||
source = id == -1 ? null : content.liquid(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.world.blocks.sandbox;
|
||||
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
@@ -18,12 +19,15 @@ public class LiquidVoid extends Block{
|
||||
bars.remove("liquid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
return true;
|
||||
public class LiquidVoidEntity extends TileEntity{
|
||||
@Override
|
||||
public boolean acceptLiquid(Tilec source, Liquid liquid, float amount){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLiquid(Tilec source, Liquid liquid, float amount){
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLiquid(Tile tile, Tile source, Liquid liquid, float amount){}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package mindustry.world.blocks.sandbox;
|
||||
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.blocks.power.PowerNode;
|
||||
import mindustry.world.blocks.power.*;
|
||||
|
||||
public class PowerSource extends PowerNode{
|
||||
|
||||
@@ -12,9 +11,11 @@ public class PowerSource extends PowerNode{
|
||||
consumesPower = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPowerProduction(Tile tile){
|
||||
return 10000f;
|
||||
public class PowerSourceEntity extends PowerNodeEntity{
|
||||
@Override
|
||||
public float getPowerProduction(){
|
||||
return 10000f;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package mindustry.world.blocks.sandbox;
|
||||
|
||||
import mindustry.world.blocks.PowerBlock;
|
||||
import mindustry.world.blocks.power.PowerBlock;
|
||||
import mindustry.world.meta.BlockStat;
|
||||
|
||||
public class PowerVoid extends PowerBlock{
|
||||
|
||||
@@ -1,30 +1,26 @@
|
||||
package mindustry.world.blocks.storage;
|
||||
|
||||
import arc.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import arc.struct.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.modules.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class CoreBlock extends StorageBlock{
|
||||
public Mech mech = Mechs.starter;
|
||||
public UnitType unitType = UnitTypes.phantom;
|
||||
|
||||
public CoreBlock(String name){
|
||||
super(name);
|
||||
@@ -36,20 +32,22 @@ public class CoreBlock extends StorageBlock{
|
||||
activeSound = Sounds.respawning;
|
||||
activeSoundVolume = 1f;
|
||||
layer = Layer.overlay;
|
||||
entityType = CoreEntity::new;
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server)
|
||||
public static void onUnitRespawn(Tile tile, Player player){
|
||||
if(player == null || tile.entity == null) return;
|
||||
public static void onPlayerSpawn(Tile tile, Playerc player){
|
||||
if(player == null || tile == null) return;
|
||||
|
||||
CoreEntity entity = tile.ent();
|
||||
Effects.effect(Fx.spawn, entity);
|
||||
CoreBlock block = (CoreBlock)tile.block();
|
||||
Fx.spawn.at(entity);
|
||||
entity.progress = 0;
|
||||
entity.spawnPlayer = player;
|
||||
entity.spawnPlayer.onRespawn(tile);
|
||||
entity.spawnPlayer.applyImpulse(0, 8f);
|
||||
entity.spawnPlayer = null;
|
||||
|
||||
Unitc unit = block.unitType.create(tile.team());
|
||||
unit.set(entity);
|
||||
unit.impulse(0f, 8f);
|
||||
unit.controller(player);
|
||||
unit.add();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,197 +58,177 @@ public class CoreBlock extends StorageBlock{
|
||||
new Bar(
|
||||
() -> Core.bundle.format("bar.capacity", ui.formatAmount(((CoreEntity)e).storageCapacity)),
|
||||
() -> Pal.items,
|
||||
() -> e.items.total() / (float)(((CoreEntity)e).storageCapacity * content.items().count(i -> i.type == ItemType.material))
|
||||
() -> e.items().total() / (float)(((CoreEntity)e).storageCapacity * content.items().count(i -> i.type == ItemType.material))
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(Tile tile){
|
||||
renderer.lights.add(tile.drawx(), tile.drawy(), 30f * size, Pal.accent, 0.5f + Mathf.absin(20f, 0.1f));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return tile.entity.items.get(item) < getMaximumAccepted(tile, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAccepted(Tile tile, Item item){
|
||||
CoreEntity entity = tile.ent();
|
||||
return item.type == ItemType.material ? entity.storageCapacity : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(Tile tile){
|
||||
CoreEntity entity = tile.ent();
|
||||
|
||||
for(TileEntity other : state.teams.cores(tile.getTeam())){
|
||||
if(other.tile != tile){
|
||||
entity.items = other.items;
|
||||
}
|
||||
}
|
||||
state.teams.registerCore(entity);
|
||||
|
||||
entity.storageCapacity = itemCapacity + entity.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
||||
entity.proximity().each(this::isContainer, t -> {
|
||||
t.entity.items = entity.items;
|
||||
t.<StorageBlockEntity>ent().linkedCore = tile;
|
||||
});
|
||||
|
||||
for(TileEntity other : state.teams.cores(tile.getTeam())){
|
||||
if(other.tile == tile) continue;
|
||||
entity.storageCapacity += other.block.itemCapacity + other.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
||||
}
|
||||
|
||||
if(!world.isGenerating()){
|
||||
for(Item item : content.items()){
|
||||
entity.items.set(item, Math.min(entity.items.get(item), entity.storageCapacity));
|
||||
}
|
||||
}
|
||||
|
||||
for(CoreEntity other : state.teams.cores(tile.getTeam())){
|
||||
other.storageCapacity = entity.storageCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
Lines.stroke(1f, Pal.accent);
|
||||
Cons<Tile> outline = t -> {
|
||||
for(int i = 0; i < 4; i++){
|
||||
Point2 p = Geometry.d8edge[i];
|
||||
float offset = -Math.max(t.block().size - 1, 0) / 2f * tilesize;
|
||||
Draw.rect("block-select", t.drawx() + offset * p.x, t.drawy() + offset * p.y, i * 90);
|
||||
}
|
||||
};
|
||||
if(tile.entity.proximity().contains(e -> isContainer(e) && e.entity.items == tile.entity.items)){
|
||||
outline.get(tile);
|
||||
}
|
||||
tile.entity.proximity().each(e -> isContainer(e) && e.entity.items == tile.entity.items, outline);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
|
||||
public boolean isContainer(Tile tile){
|
||||
return tile.entity instanceof StorageBlockEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float handleDamage(Tile tile, float amount){
|
||||
if(player != null && tile.getTeam() == player.getTeam()){
|
||||
Events.fire(Trigger.teamCoreDamage);
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBreak(Tile tile){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(Tile tile){
|
||||
CoreEntity entity = tile.ent();
|
||||
int total = tile.entity.proximity().count(e -> e.entity != null && e.entity.items != null && e.entity.items == tile.entity.items);
|
||||
float fract = 1f / total / state.teams.cores(tile.getTeam()).size;
|
||||
|
||||
tile.entity.proximity().each(e -> isContainer(e) && e.entity.items == tile.entity.items, t -> {
|
||||
StorageBlockEntity ent = (StorageBlockEntity)t.entity;
|
||||
ent.linkedCore = null;
|
||||
ent.items = new ItemModule();
|
||||
for(Item item : content.items()){
|
||||
ent.items.set(item, (int)(fract * tile.entity.items.get(item)));
|
||||
}
|
||||
});
|
||||
|
||||
state.teams.unregisterCore(entity);
|
||||
|
||||
int max = itemCapacity * state.teams.cores(tile.getTeam()).size;
|
||||
for(Item item : content.items()){
|
||||
tile.entity.items.set(item, Math.min(tile.entity.items.get(item), max));
|
||||
}
|
||||
|
||||
for(CoreEntity other : state.teams.cores(tile.getTeam())){
|
||||
other.block.onProximityUpdate(other.tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placed(Tile tile){
|
||||
super.placed(tile);
|
||||
CoreEntity entity = tile.ent();
|
||||
state.teams.registerCore(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
CoreEntity entity = tile.ent();
|
||||
|
||||
if(entity.heat > 0.001f){
|
||||
RespawnBlock.drawRespawn(tile, entity.heat, entity.progress, entity.time, entity.spawnPlayer, mech);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
if(net.server() || !net.active()){
|
||||
super.handleItem(item, tile, source);
|
||||
if(state.rules.tutorial){
|
||||
Events.fire(new CoreItemDeliverEvent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
CoreEntity entity = tile.ent();
|
||||
|
||||
if(entity.spawnPlayer != null){
|
||||
if(!entity.spawnPlayer.isDead() || !entity.spawnPlayer.isAdded()){
|
||||
entity.spawnPlayer = null;
|
||||
return;
|
||||
}
|
||||
|
||||
entity.spawnPlayer.set(tile.drawx(), tile.drawy());
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, 1f, 0.1f);
|
||||
entity.time += entity.delta();
|
||||
entity.progress += 1f / state.rules.respawnTime * entity.delta();
|
||||
|
||||
if(entity.progress >= 1f){
|
||||
Call.onUnitRespawn(tile, entity.spawnPlayer);
|
||||
}
|
||||
}else{
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, 0f, 0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldActiveSound(Tile tile){
|
||||
CoreEntity entity = tile.ent();
|
||||
|
||||
return entity.spawnPlayer != null;
|
||||
}
|
||||
|
||||
public class CoreEntity extends TileEntity implements SpawnerTrait{
|
||||
protected Player spawnPlayer;
|
||||
protected float progress;
|
||||
protected float time;
|
||||
protected float heat;
|
||||
public class CoreEntity extends TileEntity{
|
||||
// protected Playerc spawnPlayer;
|
||||
protected float time, heat, progress;
|
||||
protected int storageCapacity;
|
||||
protected boolean shouldBuild;
|
||||
protected Playerc lastRequested;
|
||||
|
||||
@Override
|
||||
public boolean hasUnit(Unit unit){
|
||||
return unit == spawnPlayer;
|
||||
public void requestSpawn(Playerc player){
|
||||
shouldBuild = true;
|
||||
if(lastRequested == null){
|
||||
lastRequested = player;
|
||||
}
|
||||
|
||||
if(progress >= 1f){
|
||||
Call.onPlayerSpawn(tile, player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSpawning(Player player){
|
||||
if(!netServer.isWaitingForPlayers() && spawnPlayer == null){
|
||||
spawnPlayer = player;
|
||||
progress = 0f;
|
||||
player.mech = mech;
|
||||
player.beginRespawning(this);
|
||||
public void drawLight(){
|
||||
renderer.lights.add(x, y, 30f * size, Pal.accent, 0.5f + Mathf.absin(20f, 0.1f));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return items.get(item) < getMaximumAccepted(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAccepted(Item item){
|
||||
return item.type == ItemType.material ? storageCapacity : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(){
|
||||
for(Tilec other : state.teams.cores(team)){
|
||||
if(other.tile() != tile){
|
||||
items(other.items());
|
||||
}
|
||||
}
|
||||
state.teams.registerCore(this);
|
||||
|
||||
storageCapacity = itemCapacity + proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
||||
proximity.each(this::isContainer, t -> {
|
||||
t.items(items);
|
||||
((StorageBlockEntity)t).linkedCore = this;
|
||||
});
|
||||
|
||||
for(Tilec other : state.teams.cores(team)){
|
||||
if(other.tile() == tile) continue;
|
||||
storageCapacity += other.block().itemCapacity + other.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
||||
}
|
||||
|
||||
if(!world.isGenerating()){
|
||||
for(Item item : content.items()){
|
||||
items.set(item, Math.min(items.get(item), storageCapacity));
|
||||
}
|
||||
}
|
||||
|
||||
for(CoreEntity other : state.teams.cores(team)){
|
||||
other.storageCapacity = storageCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(){
|
||||
Lines.stroke(1f, Pal.accent);
|
||||
Cons<Tilec> outline = t -> {
|
||||
for(int i = 0; i < 4; i++){
|
||||
Point2 p = Geometry.d8edge[i];
|
||||
float offset = -Math.max(t.block().size - 1, 0) / 2f * tilesize;
|
||||
Draw.rect("block-select", t.x() + offset * p.x, t.y() + offset * p.y, i * 90);
|
||||
}
|
||||
};
|
||||
if(proximity.contains(e -> isContainer(e) && e.items() == items)){
|
||||
outline.get(this);
|
||||
}
|
||||
proximity.each(e -> isContainer(e) && e.items() == items, outline);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
|
||||
public boolean isContainer(Tilec tile){
|
||||
return tile instanceof StorageBlockEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float handleDamage(float amount){
|
||||
if(player != null && team == player.team()){
|
||||
Events.fire(Trigger.teamCoreDamage);
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoved(){
|
||||
int total = proximity.count(e -> e.items() != null && e.items() == items);
|
||||
float fract = 1f / total / state.teams.cores(team).size;
|
||||
|
||||
proximity.each(e -> isContainer(e) && e.items() == items, t -> {
|
||||
StorageBlockEntity ent = (StorageBlockEntity)t;
|
||||
ent.linkedCore = null;
|
||||
ent.items(new ItemModule());
|
||||
for(Item item : content.items()){
|
||||
ent.items().set(item, (int)(fract * items.get(item)));
|
||||
}
|
||||
});
|
||||
|
||||
state.teams.unregisterCore(this);
|
||||
|
||||
int max = itemCapacity * state.teams.cores(team).size;
|
||||
for(Item item : content.items()){
|
||||
items.set(item, Math.min(items.get(item), max));
|
||||
}
|
||||
|
||||
for(CoreEntity other : state.teams.cores(team)){
|
||||
other.onProximityUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placed(){
|
||||
super.placed();
|
||||
state.teams.registerCore(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(){
|
||||
if(heat > 0.001f){
|
||||
Drawf.drawRespawn(this, heat, progress, time, unitType, lastRequested);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Tilec source, Item item){
|
||||
if(net.server() || !net.active()){
|
||||
super.handleItem(source, item);
|
||||
if(state.rules.tutorial){
|
||||
Events.fire(new CoreItemDeliverEvent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
|
||||
if(shouldBuild){
|
||||
heat = Mathf.lerpDelta(heat, 1f, 0.1f);
|
||||
time += delta();
|
||||
progress += 1f / state.rules.respawnTime * delta();
|
||||
}else{
|
||||
progress = 0f;
|
||||
heat = Mathf.lerpDelta(heat, 0f, 0.1f);
|
||||
}
|
||||
|
||||
shouldBuild = false;
|
||||
lastRequested = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldActiveSound(){
|
||||
return shouldBuild;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,8 @@
|
||||
package mindustry.world.blocks.storage;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.graphics.g2d.Lines;
|
||||
import arc.math.Mathf;
|
||||
import arc.util.Time;
|
||||
import mindustry.Vars;
|
||||
import mindustry.content.Fx;
|
||||
import mindustry.entities.Effects;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.graphics.Pal;
|
||||
import mindustry.type.Item;
|
||||
import mindustry.type.ItemType;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.BlockStat;
|
||||
import mindustry.world.meta.StatUnit;
|
||||
|
||||
import static mindustry.Vars.data;
|
||||
import static mindustry.Vars.world;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class LaunchPad extends StorageBlock{
|
||||
public final int timerLaunch = timers++;
|
||||
@@ -39,49 +23,55 @@ public class LaunchPad extends StorageBlock{
|
||||
stats.add(BlockStat.launchTime, launchTime / 60f, StatUnit.seconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return item.type == ItemType.material && tile.entity.items.total() < itemCapacity;
|
||||
}
|
||||
public class LaunchPadEntity extends StorageBlockEntity{
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
//TODO
|
||||
/*
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
//TODO broken
|
||||
float progress = Mathf.clamp(Mathf.clamp((items.total() / (float)itemCapacity)) * ((timer().getTime(timerLaunch) / (launchTime / timeScale()))));
|
||||
float scale = size / 3f;
|
||||
|
||||
float progress = Mathf.clamp(Mathf.clamp((tile.entity.items.total() / (float)itemCapacity)) * ((tile.entity.timer.getTime(timerLaunch) / (launchTime / tile.entity.timeScale))));
|
||||
float scale = size / 3f;
|
||||
Lines.stroke(2f);
|
||||
Draw.color(Pal.accentBack);
|
||||
Lines.poly(x, y, 4, scale * 10f * (1f - progress), 45 + 360f * progress);
|
||||
|
||||
Lines.stroke(2f);
|
||||
Draw.color(Pal.accentBack);
|
||||
Lines.poly(tile.drawx(), tile.drawy(), 4, scale * 10f * (1f - progress), 45 + 360f * progress);
|
||||
Draw.color(Pal.accent);
|
||||
|
||||
Draw.color(Pal.accent);
|
||||
if(cons.valid()){
|
||||
for(int i = 0; i < 3; i++){
|
||||
float f = (Time.time() / 200f + i * 0.5f) % 1f;
|
||||
|
||||
if(tile.entity.cons.valid()){
|
||||
for(int i = 0; i < 3; i++){
|
||||
float f = (Time.time() / 200f + i * 0.5f) % 1f;
|
||||
|
||||
Lines.stroke(((2f * (2f - Math.abs(0.5f - f) * 2f)) - 2f + 0.2f));
|
||||
Lines.poly(tile.drawx(), tile.drawy(), 4, (1f - f) * 10f * scale);
|
||||
Lines.stroke(((2f * (2f - Math.abs(0.5f - f) * 2f)) - 2f + 0.2f));
|
||||
Lines.poly(x, y, 4, (1f - f) * 10f * scale);
|
||||
}
|
||||
}
|
||||
|
||||
Draw.reset();*/
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return item.type == ItemType.material && super.acceptItem(source, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
TileEntity entity = tile.entity;
|
||||
@Override
|
||||
public void updateTile(){
|
||||
//TODO
|
||||
/*
|
||||
|
||||
if(world.isZone() && entity.cons.valid() && entity.items.total() >= itemCapacity && entity.timer.get(timerLaunch, launchTime / entity.timeScale)){
|
||||
for(Item item : Vars.content.items()){
|
||||
Events.fire(Trigger.itemLaunch);
|
||||
Effects.effect(Fx.padlaunch, tile);
|
||||
int used = Math.min(entity.items.get(item), itemCapacity);
|
||||
data.addItem(item, used);
|
||||
entity.items.remove(item, used);
|
||||
Events.fire(new LaunchItemEvent(item, used));
|
||||
}
|
||||
if(state.isCampaign() && consValid() && items.total() >= itemCapacity && timer(timerLaunch, launchTime / timeScale())){
|
||||
for(Item item : Vars.content.items()){
|
||||
Events.fire(Trigger.itemLaunch);
|
||||
Fx.padlaunch.at(tile);
|
||||
int used = Math.min(items.get(item), itemCapacity);
|
||||
data.addItem(item, used);
|
||||
items.remove(item, used);
|
||||
Events.fire(new LaunchItemEvent(item, used));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,18 @@
|
||||
package mindustry.world.blocks.storage;
|
||||
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.type.Item;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public abstract class StorageBlock extends Block{
|
||||
|
||||
public StorageBlock(String name){
|
||||
super(name);
|
||||
hasItems = true;
|
||||
entityType = StorageBlockEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
StorageBlockEntity entity = tile.ent();
|
||||
return entity.linkedCore != null ? entity.linkedCore.block().acceptItem(item, entity.linkedCore, source) : tile.entity.items.get(item) < getMaximumAccepted(tile, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAccepted(Tile tile, Item item){
|
||||
return itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
StorageBlockEntity entity = tile.ent();
|
||||
if(entity.linkedCore != null){
|
||||
entity.linkedCore.block().drawSelect(entity.linkedCore);
|
||||
}
|
||||
solid = true;
|
||||
update = false;
|
||||
destructible = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -38,40 +20,54 @@ public abstract class StorageBlock extends Block{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item and returns it. If item is not null, it should return the item.
|
||||
* Returns null if no items are there.
|
||||
*/
|
||||
public Item removeItem(Tile tile, Item item){
|
||||
TileEntity entity = tile.entity;
|
||||
|
||||
if(item == null){
|
||||
return entity.items.take();
|
||||
}else{
|
||||
if(entity.items.has(item)){
|
||||
entity.items.remove(item, 1);
|
||||
return item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this storage block has the specified item.
|
||||
* If the item is null, it should return whether it has ANY items.
|
||||
*/
|
||||
public boolean hasItem(Tile tile, Item item){
|
||||
TileEntity entity = tile.entity;
|
||||
if(item == null){
|
||||
return entity.items.total() > 0;
|
||||
}else{
|
||||
return entity.items.has(item);
|
||||
}
|
||||
}
|
||||
|
||||
public class StorageBlockEntity extends TileEntity{
|
||||
protected @Nullable
|
||||
Tile linkedCore;
|
||||
protected @Nullable Tilec linkedCore;
|
||||
|
||||
/**
|
||||
* Removes an item and returns it. If item is not null, it should return the item.
|
||||
* Returns null if no items are there.
|
||||
*/
|
||||
@Nullable
|
||||
public Item removeItem(@Nullable Item item){
|
||||
if(item == null){
|
||||
return items.take();
|
||||
}else{
|
||||
if(items.has(item)){
|
||||
items.remove(item, 1);
|
||||
return item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this storage block has the specified item.
|
||||
* If the item is null, it should return whether it has ANY items.
|
||||
*/
|
||||
public boolean hasItem(@Nullable Item item){
|
||||
if(item == null){
|
||||
return items.total() > 0;
|
||||
}else{
|
||||
return items.has(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Tilec source, Item item){
|
||||
return linkedCore != null ? linkedCore.acceptItem(source, item) : items.get(item) < getMaximumAccepted(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAccepted(Item item){
|
||||
return itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(){
|
||||
if(linkedCore != null){
|
||||
linkedCore.drawSelect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,13 @@ import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.content;
|
||||
|
||||
public class Unloader extends Block{
|
||||
@@ -27,17 +26,17 @@ public class Unloader extends Block{
|
||||
health = 70;
|
||||
hasItems = true;
|
||||
configurable = true;
|
||||
entityType = UnloaderEntity::new;
|
||||
config(Item.class, (tile, item) -> {
|
||||
tile.items().clear();
|
||||
((UnloaderEntity)tile).sortItem = item;
|
||||
});
|
||||
|
||||
configClear(tile -> ((UnloaderEntity)tile).sortItem = null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRequestConfig(BuildRequest req, Eachable<BuildRequest> list){
|
||||
drawRequestConfigCenter(req, content.item(req.config), "unloader-center");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDump(Tile tile, Tile to, Item item){
|
||||
return !(to.block() instanceof StorageBlock);
|
||||
drawRequestConfigCenter(req, (Item)req.config, "unloader-center");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -46,107 +45,85 @@ public class Unloader extends Block{
|
||||
bars.remove("items");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerPlaced(Tile tile){
|
||||
if(lastItem != null){
|
||||
tile.configure(lastItem.id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configured(Tile tile, Player player, int value){
|
||||
tile.entity.items.clear();
|
||||
tile.<UnloaderEntity>ent().sortItem = content.item(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
UnloaderEntity entity = tile.ent();
|
||||
|
||||
if(tile.entity.timer.get(timerUnload, speed / entity.timeScale) && tile.entity.items.total() == 0){
|
||||
for(Tile other : tile.entity.proximity()){
|
||||
if(other.interactable(tile.getTeam()) && other.block().unloadable && other.block().hasItems && entity.items.total() == 0 &&
|
||||
((entity.sortItem == null && other.entity.items.total() > 0) || hasItem(other, entity.sortItem))){
|
||||
offloadNear(tile, removeItem(other, entity.sortItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(entity.items.total() > 0){
|
||||
tryDump(tile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item and returns it. If item is not null, it should return the item.
|
||||
* Returns null if no items are there.
|
||||
*/
|
||||
private Item removeItem(Tile tile, Item item){
|
||||
TileEntity entity = tile.entity;
|
||||
|
||||
if(item == null){
|
||||
return entity.items.take();
|
||||
}else{
|
||||
if(entity.items.has(item)){
|
||||
entity.items.remove(item, 1);
|
||||
return item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this storage block has the specified item.
|
||||
* If the item is null, it should return whether it has ANY items.
|
||||
*/
|
||||
private boolean hasItem(Tile tile, Item item){
|
||||
TileEntity entity = tile.entity;
|
||||
if(item == null){
|
||||
return entity.items.total() > 0;
|
||||
}else{
|
||||
return entity.items.has(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
UnloaderEntity entity = tile.ent();
|
||||
|
||||
Draw.color(entity.sortItem == null ? Color.clear : entity.sortItem.color);
|
||||
Draw.rect("unloader-center", tile.worldx(), tile.worldy());
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
UnloaderEntity entity = tile.ent();
|
||||
ItemSelection.buildTable(table, content.items(), () -> entity.sortItem, item -> {
|
||||
lastItem = item;
|
||||
tile.configure(item == null ? -1 : item.id);
|
||||
});
|
||||
}
|
||||
|
||||
public static class UnloaderEntity extends TileEntity{
|
||||
public class UnloaderEntity extends TileEntity{
|
||||
public Item sortItem = null;
|
||||
|
||||
@Override
|
||||
public int config(){
|
||||
return sortItem == null ? -1 : sortItem.id;
|
||||
private Item removeItem(Tilec tile, Item item){
|
||||
if(item == null){
|
||||
return tile.items().take();
|
||||
}else{
|
||||
if(tile.items().has(item)){
|
||||
tile.items().remove(item, 1);
|
||||
return item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasItem(Tilec tile, Item item){
|
||||
if(item == null){
|
||||
return tile.items().total() > 0;
|
||||
}else{
|
||||
return tile.items().has(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeByte(sortItem == null ? -1 : sortItem.id);
|
||||
public void playerPlaced(){
|
||||
if(lastItem != null){
|
||||
tile.configure(lastItem);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
byte id = stream.readByte();
|
||||
public void updateTile(){
|
||||
if(timer(timerUnload, speed / timeScale()) && items.total() == 0){
|
||||
for(Tilec other : proximity){
|
||||
if(other.interactable(team) && other.block().unloadable && other.block().hasItems && items.total() == 0 &&
|
||||
((sortItem == null && items.total() > 0) || hasItem(other, sortItem))){
|
||||
offloadNear(removeItem(other, sortItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dump();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
Draw.color(sortItem == null ? Color.clear : sortItem.color);
|
||||
Draw.rect("unloader-center", x, y);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ItemSelection.buildTable(table, content.items(), () -> tile.<UnloaderEntity>ent().sortItem, item -> tile.configure(lastItem = item));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDump(Tilec to, Item item){
|
||||
return !(to.block() instanceof StorageBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item config(){
|
||||
return sortItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.b(sortItem == null ? -1 : sortItem.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
byte id = read.b();
|
||||
sortItem = id == -1 ? null : content.items().get(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package mindustry.world.blocks.storage;
|
||||
|
||||
public class Vault extends StorageBlock{
|
||||
|
||||
public Vault(String name){
|
||||
super(name);
|
||||
solid = true;
|
||||
update = false;
|
||||
destructible = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,19 +8,18 @@ import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.ai.BlockIndexer.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class CommandCenter extends Block{
|
||||
@@ -36,30 +35,20 @@ public class CommandCenter extends Block{
|
||||
destructible = true;
|
||||
solid = true;
|
||||
configurable = true;
|
||||
entityType = CommandCenterEntity::new;
|
||||
}
|
||||
config(Integer.class, (tile, value) -> {
|
||||
UnitCommand command = UnitCommand.all[value];
|
||||
((CommandCenter)tile.block()).effect.at(tile);
|
||||
|
||||
@Override
|
||||
public void placed(Tile tile){
|
||||
super.placed(tile);
|
||||
ObjectSet<Tile> set = indexer.getAllied(tile.getTeam(), BlockFlag.comandCenter);
|
||||
for(Tile center : indexer.getAllied(tile.team(), BlockFlag.comandCenter)){
|
||||
if(center.block() instanceof CommandCenter){
|
||||
CommandCenterEntity entity = center.ent();
|
||||
entity.command = command;
|
||||
}
|
||||
}
|
||||
|
||||
if(set.size > 0){
|
||||
CommandCenterEntity entity = tile.ent();
|
||||
CommandCenterEntity oe = set.first().ent();
|
||||
entity.command = oe.command;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(Tile tile){
|
||||
super.removed(tile);
|
||||
|
||||
ObjectSet<Tile> set = indexer.getAllied(tile.getTeam(), BlockFlag.comandCenter);
|
||||
|
||||
if(set.size == 1){
|
||||
Units.each(tile.getTeam(), u -> u.onCommand(UnitCommand.all[0]));
|
||||
}
|
||||
Groups.unit.each(t -> t.team() == tile.team(), u -> u.controller().command(command));
|
||||
Events.fire(new CommandIssueEvent(tile, command));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,69 +62,73 @@ public class CommandCenter extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
CommandCenterEntity entity = tile.ent();
|
||||
super.draw(tile);
|
||||
|
||||
float size = 6f;
|
||||
|
||||
Draw.color(bottomColor);
|
||||
Draw.rect(commandRegions[entity.command.ordinal()].getRegion(), tile.drawx(), tile.drawy() - 1, size, size);
|
||||
Draw.color(topColor);
|
||||
Draw.rect(commandRegions[entity.command.ordinal()].getRegion(), tile.drawx(), tile.drawy(), size, size);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
CommandCenterEntity entity = tile.ent();
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
Table buttons = new Table();
|
||||
|
||||
for(UnitCommand cmd : UnitCommand.all){
|
||||
buttons.addImageButton(commandRegions[cmd.ordinal()], Styles.clearToggleTransi, () -> tile.configure(cmd.ordinal()))
|
||||
.size(44).group(group).update(b -> b.setChecked(entity.command == cmd));
|
||||
}
|
||||
table.add(buttons);
|
||||
table.row();
|
||||
table.label(() -> entity.command.localized()).style(Styles.outlineLabel).center().growX().get().setAlignment(Align.center);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configured(Tile tile, Player player, int value){
|
||||
UnitCommand command = UnitCommand.all[value];
|
||||
Effects.effect(((CommandCenter)tile.block()).effect, tile);
|
||||
|
||||
for(Tile center : indexer.getAllied(tile.getTeam(), BlockFlag.comandCenter)){
|
||||
if(center.block() instanceof CommandCenter){
|
||||
CommandCenterEntity entity = center.ent();
|
||||
entity.command = command;
|
||||
}
|
||||
}
|
||||
|
||||
Units.each(tile.getTeam(), u -> u.onCommand(command));
|
||||
Events.fire(new CommandIssueEvent(tile, command));
|
||||
}
|
||||
|
||||
public class CommandCenterEntity extends TileEntity{
|
||||
public UnitCommand command = UnitCommand.attack;
|
||||
|
||||
@Override
|
||||
public int config(){
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
float size = 6f;
|
||||
|
||||
Draw.color(bottomColor);
|
||||
Draw.rect(commandRegions[command.ordinal()].getRegion(), x, y - 1, size, size);
|
||||
Draw.color(topColor);
|
||||
Draw.rect(commandRegions[command.ordinal()].getRegion(), x, y, size, size);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
Table buttons = new Table();
|
||||
|
||||
for(UnitCommand cmd : UnitCommand.all){
|
||||
buttons.addImageButton(commandRegions[cmd.ordinal()], Styles.clearToggleTransi, () -> tile.configure(cmd.ordinal()))
|
||||
.size(44).group(group).update(b -> b.setChecked(command == cmd));
|
||||
}
|
||||
table.add(buttons);
|
||||
table.row();
|
||||
table.label(() -> command.localized()).style(Styles.outlineLabel).center().growX().get().setAlignment(Align.center);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placed(){
|
||||
super.placed();
|
||||
TileArray set = indexer.getAllied(team, BlockFlag.comandCenter);
|
||||
|
||||
if(set.size() > 0){
|
||||
CommandCenterEntity oe = set.first().ent();
|
||||
command = oe.command;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoved(){
|
||||
super.onRemoved();
|
||||
|
||||
TileArray set = indexer.getAllied(team, BlockFlag.comandCenter);
|
||||
|
||||
if(set.size() == 1){
|
||||
Groups.unit.each(t -> t.team() == team, u -> u.controller().command(UnitCommand.all[0]));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer config(){
|
||||
return command.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeByte(command.ordinal());
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.b(command.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte version) throws IOException{
|
||||
super.read(stream, version);
|
||||
command = UnitCommand.all[stream.readByte()];
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
command = UnitCommand.all[read.b()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
package mindustry.world.blocks.units;
|
||||
|
||||
import arc.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import arc.struct.EnumSet;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class MechPad extends Block{
|
||||
public @NonNull Mech mech;
|
||||
public float buildTime = 60 * 5;
|
||||
|
||||
public MechPad(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
solid = false;
|
||||
hasPower = true;
|
||||
layer = Layer.overlay;
|
||||
flags = EnumSet.of(BlockFlag.mechPad);
|
||||
entityType = MechFactoryEntity::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.productionTime, buildTime / 60f, StatUnit.seconds);
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.server)
|
||||
public static void onMechFactoryTap(Player player, Tile tile){
|
||||
if(player == null || tile == null || !(tile.block() instanceof MechPad) || !checkValidTap(tile, player)) return;
|
||||
|
||||
MechFactoryEntity entity = tile.ent();
|
||||
|
||||
if(!entity.cons.valid()) return;
|
||||
player.beginRespawning(entity);
|
||||
entity.sameMech = false;
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server)
|
||||
public static void onMechFactoryDone(Tile tile){
|
||||
if(!(tile.entity instanceof MechFactoryEntity)) return;
|
||||
|
||||
MechFactoryEntity entity = tile.ent();
|
||||
|
||||
Effects.effect(Fx.spawn, entity);
|
||||
|
||||
if(entity.player == null) return;
|
||||
Mech mech = ((MechPad)tile.block()).mech;
|
||||
boolean resetSpawner = !entity.sameMech && entity.player.mech == mech;
|
||||
entity.player.mech = !entity.sameMech && entity.player.mech == mech ? Mechs.starter : mech;
|
||||
|
||||
Player player = entity.player;
|
||||
|
||||
entity.progress = 0;
|
||||
entity.player.onRespawn(tile);
|
||||
if(resetSpawner) entity.player.lastSpawner = null;
|
||||
entity.player = null;
|
||||
|
||||
Events.fire(new MechChangeEvent(player, player.mech));
|
||||
}
|
||||
|
||||
protected static boolean checkValidTap(Tile tile, Player player){
|
||||
MechFactoryEntity entity = tile.ent();
|
||||
return !player.isDead() && tile.interactable(player.getTeam()) && Math.abs(player.x - tile.drawx()) <= tile.block().size * tilesize &&
|
||||
Math.abs(player.y - tile.drawy()) <= tile.block().size * tilesize && entity.cons.valid() && entity.player == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
Draw.color(Pal.accent);
|
||||
for(int i = 0; i < 4; i++){
|
||||
float length = tilesize * size / 2f + 3 + Mathf.absin(Time.time(), 5f, 2f);
|
||||
Draw.rect("transfer-arrow", tile.drawx() + Geometry.d4[i].x * length, tile.drawy() + Geometry.d4[i].y * length, (i + 2) * 90);
|
||||
}
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tapped(Tile tile, Player player){
|
||||
MechFactoryEntity entity = tile.ent();
|
||||
|
||||
if(checkValidTap(tile, player)){
|
||||
Call.onMechFactoryTap(player, tile);
|
||||
}else if(player.isLocal && mobile && !player.isDead() && entity.cons.valid() && entity.player == null){
|
||||
//deselect on double taps
|
||||
player.moveTarget = player.moveTarget == tile.entity ? null : tile.entity;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
MechFactoryEntity entity = tile.ent();
|
||||
|
||||
if(entity.player != null){
|
||||
RespawnBlock.drawRespawn(tile, entity.heat, entity.progress, entity.time, entity.player, (!entity.sameMech && entity.player.mech == mech ? Mechs.starter : mech));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
MechFactoryEntity entity = tile.ent();
|
||||
|
||||
if(entity.player != null){
|
||||
entity.player.set(tile.drawx(), tile.drawy());
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, 1f, 0.1f);
|
||||
entity.progress += 1f / buildTime * entity.delta();
|
||||
|
||||
entity.time += 0.5f * entity.delta();
|
||||
|
||||
if(entity.progress >= 1f){
|
||||
Call.onMechFactoryDone(tile);
|
||||
}
|
||||
}else{
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, 0f, 0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
public class MechFactoryEntity extends TileEntity implements SpawnerTrait{
|
||||
Player player;
|
||||
boolean sameMech;
|
||||
float progress;
|
||||
float time;
|
||||
float heat;
|
||||
|
||||
@Override
|
||||
public boolean hasUnit(Unit unit){
|
||||
return unit == player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSpawning(Player unit){
|
||||
if(player == null){
|
||||
progress = 0f;
|
||||
player = unit;
|
||||
sameMech = true;
|
||||
|
||||
player.beginRespawning(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeFloat(progress);
|
||||
stream.writeFloat(time);
|
||||
stream.writeFloat(heat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
progress = stream.readFloat();
|
||||
time = stream.readFloat();
|
||||
heat = stream.readFloat();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user