1
0
mirror of https://github.com/Anuken/Mindustry.git synced 2024-09-22 22:07:31 +03:00

Fixed most errors in block package

This commit is contained in:
Anuken 2020-03-06 14:41:38 -05:00
parent 4744465986
commit 73c0ebb75f
32 changed files with 1269 additions and 1523 deletions

View File

@ -10,7 +10,6 @@ uniform vec3 u_ambientColor;
varying vec4 v_col;
const vec3 ambientColor = vec3(1.0);
const vec3 ambientDir = normalize(vec3(1.0, 1.0, 1.0));
const vec3 diffuse = vec3(0.2);
const vec3 v1 = vec3(1.0, 0.0, 1.0);
const vec3 v2 = vec3(1.0, 0.5, 0.0);

View File

@ -409,6 +409,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
public void offloadNear(Item item){
Array<Tilec> proximity = proximity();
int dump = rotation();
useContent(item);
for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size);
@ -544,8 +545,8 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
return out;
}
public float getProgressIncrease(Tilec entity, float baseTime){
return 1f / baseTime * entity.delta() * entity.efficiency();
public float getProgressIncrease(float baseTime){
return 1f / baseTime * delta() * efficiency();
}
/** @return whether this block should play its active sound.*/
@ -654,16 +655,6 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
}
}
public float percentSolid(int x, int y){
Tile tile = world.tile(x, y);
if(tile == null) return 0;
float sum = 0;
for(Tile other : tile.getLinkedTilesAs(block, tempTiles)){
sum += !other.floor().isLiquid ? 1f : 0f;
}
return sum / block.size / block.size;
}
/** Called when arbitrary configuration is applied to a tile. */
public void configured(@Nullable Playerc player, @Nullable Object value){
//null is of type Void.class; anonymous classes use their superclass.

View File

@ -51,10 +51,10 @@ public class EventType{
public static class MapPublishEvent{}
public static class CommandIssueEvent{
public final Tile tile;
public final Tilec tile;
public final UnitCommand command;
public CommandIssueEvent(Tile tile, UnitCommand command){
public CommandIssueEvent(Tilec tile, UnitCommand command){
this.tile = tile;
this.command = command;
}

View File

@ -168,6 +168,7 @@ public class Block extends UnlockableContent{
//TODO move
public static TextureRegion[][] cracks;
protected static final Array<Tile> tempTiles = new Array<>();
protected static final Array<Tilec> tempTileEnts = new Array<>();
/** Dump timer ID.*/
protected final int timerDump = timers++;
@ -189,6 +190,16 @@ public class Block extends UnlockableContent{
}
}
public float percentSolid(int x, int y){
Tile tile = world.tile(x, y);
if(tile == null) return 0;
float sum = 0;
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
sum += !other.floor().isLiquid ? 1f : 0f;
}
return sum / size / size;
}
public void drawLayer(Tile tile){
if(tile.entity != null) tile.entity.drawLayer();
}

View File

@ -37,7 +37,7 @@ public interface Autotiler{
return buildBlending(req.tile(), req.rotation, directionals, req.worldContext);
}
default int[] buildBlending(int rotation, BuildRequest[] directional, boolean world){
default int[] buildBlending(Tile tile, int rotation, BuildRequest[] directional, boolean world){
int[] blendresult = AutotilerHolder.blendresult;
blendresult[0] = 0;
blendresult[1] = blendresult[2] = 1;
@ -71,7 +71,7 @@ public interface Autotiler{
}
}
default boolean blends(int rotation, @Nullable BuildRequest[] directional, int direction, boolean checkWorld){
default boolean blends(Tile tile, int rotation, @Nullable BuildRequest[] directional, int direction, boolean checkWorld){
int realDir = Mathf.mod(rotation - direction, 4);
if(directional != null && directional[realDir] != null){
BuildRequest req = directional[realDir];
@ -82,21 +82,21 @@ public interface Autotiler{
return checkWorld && blends(tile, rotation, direction);
}
default boolean blends(int rotation, int direction){
default boolean blends(Tile tile, int rotation, int direction){
Tilec other = tile.getNearbyEntity(Mathf.mod(rotation - direction, 4));
return other != null && other.team() == team && blends(tile, rotation, other.tileX(), other.tileY(), other.rotation(), other.block());
return other != null && other.team() == tile.team() && blends(tile, rotation, other.tileX(), other.tileY(), other.rotation(), other.block());
}
default boolean blendsArmored(int rotation, int otherx, int othery, int otherrot, Block otherblock){
default boolean blendsArmored(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
return (Point2.equals(tile.x + Geometry.d4(rotation).x, tile.y + Geometry.d4(rotation).y, otherx, othery)
|| ((!otherblock.rotate && Edges.getFacingEdge(otherblock, otherx, othery, tile) != null &&
Edges.getFacingEdge(otherblock, otherx, othery, tile).relativeTo(tile) == rotation) || (otherblock.rotate && Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y))));
}
default boolean lookingAt(int rotation, int otherx, int othery, int otherrot, Block otherblock){
default boolean lookingAt(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
return (Point2.equals(tile.x + Geometry.d4(rotation).x, tile.y + Geometry.d4(rotation).y, otherx, othery)
|| (!otherblock.rotate || Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y)));
}
boolean blends(int rotation, int otherx, int othery, int otherrot, Block otherblock);
boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock);
}

View File

@ -49,27 +49,27 @@ public class BuildBlock extends Block{
}
@Remote(called = Loc.server)
public static void onDeconstructFinish(Block block, int builderID){
Team team = team;
Fx.breakBlock.at(x, y, block.size);
public static void onDeconstructFinish(Tile tile, Block block, int builderID){
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));
}
@Remote(called = Loc.server)
public static void onConstructFinish(Block block, int builderID, byte rotation, Team team, boolean skipConfig){
public static void onConstructFinish(Tile tile, Block block, int builderID, byte rotation, Team team, boolean skipConfig){
if(tile == null) return;
float healthf = tile.healthf();
float healthf = tile.entity.healthf();
tile.setBlock(block, team, (int)rotation);
tile.health(block.health * healthf);
tile.entity.health(block.health * healthf);
//last builder was this local client player, call placed()
if(!headless && builderID == player.unit().id()){
if(!skipConfig){
tile.playerPlaced();
tile.entity.playerPlaced();
}
}
Fx.placeBlock.at(x, y, block.size);
Fx.placeBlock.at(tile.drawx(), tile.drawy(), block.size);
}
static boolean shouldPlay(){
@ -96,9 +96,9 @@ public class BuildBlock extends Block{
}
}
public static void constructed(Block block, int builderID, byte rotation, Team team, boolean skipConfig){
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.placed();
tile.entity.placed();
Events.fire(new BlockBuildEndEvent(tile, Groups.unit.getByID(builderID), team, false));
if(shouldPlay()) Sounds.place.at(tile, calcPitch(true));

View File

@ -11,8 +11,8 @@ public class ArmoredConveyor extends Conveyor{
}
@Override
public boolean blends(int rotation, int otherx, int othery, int otherrot, Block otherblock) {
return otherblock.outputsItems() && blendsArmored(rotation, otherx, othery, otherrot, otherblock);
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{

View File

@ -76,8 +76,8 @@ public class Conveyor extends Block implements Autotiler{
}
@Override
public boolean blends(int rotation, int otherx, int othery, int otherrot, Block otherblock){
return otherblock.outputsItems() && lookingAt(rotation, otherx, othery, otherrot, otherblock);
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
return otherblock.outputsItems() && lookingAt(tile, rotation, otherx, othery, otherrot, otherblock);
}
@Override
@ -138,7 +138,7 @@ public class Conveyor extends Block implements Autotiler{
public void onProximityUpdate(){
super.onProximityUpdate();
int[] bits = buildBlending(rotation(), null, true);
int[] bits = buildBlending(tile, rotation(), null, true);
blendbits = bits[0];
blendsclx = bits[1];
blendscly = bits[2];

View File

@ -41,8 +41,8 @@ public class MassDriver extends Block{
hasPower = true;
outlineIcon = true;
//point2 is relative
config(Point2.class, (tile, point) -> tile.<MassDriverEntity>ent().link = Point2.pack(point.x + tile.x, point.y + tile.y));
config(Integer.class, (tile, point) -> tile.<MassDriverEntity>ent().link = point);
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
@ -57,114 +57,20 @@ public class MassDriver extends Block{
baseRegion = Core.atlas.find(name + "-base");
}
@Override
public void updateTile(){
Tile link = world.tile(link);
boolean hasLink = linkValid(tile);
//reload regardless of state
if(reload > 0f){
reload = Mathf.clamp(reload - delta() / reloadTime * efficiency());
}
//cleanup waiting shooters that are not valid
if(!shooterValid(tile, 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){
tryDump(tile);
}
//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(
tile.items.total() >= minDistribute && //must shoot minimum amount of items
link.block().itemCapacity - link.items.total() >= minDistribute //must have minimum amount of space
){
MassDriverEntity other = link.ent();
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(tile, link);
//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 void draw(){
Draw.rect(baseRegion, x, y);
}
@Override
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 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);
@ -174,119 +80,6 @@ public class MassDriver extends Block{
Draw.reset();
}
@Override
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)){
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(Tile other){
if(tile == 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 tile.items.total() < itemCapacity && linkValid(tile);
}
protected void fire(Tile target){
MassDriverEntity other = target.ent();
//reset reload, use power.
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(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(entity, 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, entity);
}
protected void handlePayload(MassDriverEntity entity, 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, entity);
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(entity == null || link == -1) return false;
Tile link = world.tile(link);
return link != null && link.block() instanceof MassDriver && link.team() == team && tile.dst(link) <= range;
}
public class DriverBulletData implements Poolable{
public MassDriverEntity from, to;
public int[] items = new int[content.items().size];
@ -309,8 +102,209 @@ public class MassDriver extends Block{
return waitingShooters.isEmpty() ? null : waitingShooters.first();
}
@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 void draw(){
Draw.rect(baseRegion, x, y);
}
@Override
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 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){
((MassDriver)block()).handlePayload(this, bullet, 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

View File

@ -21,8 +21,8 @@ public class ArmoredConduit extends Conduit{
}
@Override
public boolean blends(int rotation, int otherx, int othery, int otherrot, Block otherblock){
return otherblock.outputsLiquid && blendsArmored(rotation, otherx, othery, otherrot, otherblock);
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 TileEntity{

View File

@ -74,8 +74,8 @@ public class Conduit extends LiquidBlock implements Autotiler{
}
@Override
public boolean blends(int rotation, int otherx, int othery, int otherrot, Block otherblock){
return otherblock.hasLiquids && otherblock.outputsLiquid && lookingAt(rotation, otherx, othery, otherrot, otherblock);
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
return otherblock.hasLiquids && otherblock.outputsLiquid && lookingAt(tile, rotation, otherx, othery, otherrot, otherblock);
}
@Override
@ -106,7 +106,7 @@ public class Conduit extends LiquidBlock implements Autotiler{
public void onProximityUpdate(){
super.onProximityUpdate();
blendbits = buildBlending(rotation(), null, true)[0];
blendbits = buildBlending(tile, rotation(), null, true)[0];
}
@Override

View File

@ -128,10 +128,10 @@ 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);
});
});
@ -165,6 +165,10 @@ public class PowerNode extends PowerBlock{
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);
}
@ -177,26 +181,26 @@ public class PowerNode extends PowerBlock{
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, laserRange * tilesize) && other.team() == player.team()
&& !other.proximity().contains(tile) && !graphs.contains(other.power().graph);
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);
tempTiles.clear();
tempTileEnts.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);
Tilec other = world.ent(x, y);
if(valid.get(other) && !tempTileEnts.contains(other)){
tempTileEnts.add(other);
}
});
tempTiles.sort((a, b) -> {
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));
});
tempTiles.each(valid, t -> {
graphs.add(t.power.graph);
tempTileEnts.each(valid, t -> {
graphs.add(t.power().graph);
others.get(t);
});
}
@ -219,6 +223,26 @@ public class PowerNode extends PowerBlock{
}
}
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());
}
@ -251,23 +275,23 @@ public class PowerNode extends PowerBlock{
(other.block().outputsPower && !other.block().consumesPower) || other.block() instanceof PowerNode) && linkValid(this, other)
&& !other.proximity().contains(this) && other.power().graph != power.graph;
tempTiles.clear();
tempTileEnts.clear();
Geometry.circle(tile.x, tile.y, (int)(laserRange + 2), (x, y) -> {
Tile other = world.ltile(x, y);
Tilec other = world.ent(x, y);
if(valid.get(other)){
if(!insulated(tile, other)){
tempTiles.add(other);
if(!insulated(this, other)){
tempTileEnts.add(other);
}
}
});
tempTiles.sort((a, b) -> {
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));
});
tempTiles.each(valid, other -> {
if(!tile.power.links.contains(other.pos())){
tempTileEnts.each(valid, other -> {
if(!power.links.contains(other.pos())){
tile.configureAny(other.pos());
}
});
@ -277,24 +301,21 @@ public class PowerNode extends PowerBlock{
@Override
public void updateTile(){
tile.power.graph.update();
power.graph.update();
}
@Override
public boolean onConfigureTileTapped(Tile other){
Tilec entity = tile.ent();
other = other.link();
if(linkValid(tile, other)){
public boolean onConfigureTileTapped(Tilec other){
if(linkValid(this, other)){
tile.configure(other.pos());
return false;
}
if(tile == other){
if(other.power.links.size == 0){
if(this == other){
if(other.power().links.size == 0){
int[] total = {0};
getPotentialLinks(tile, link -> {
if(!insulated(tile, link) && total[0]++ < maxNodes){
if(!insulated(this, link) && total[0]++ < maxNodes){
tile.configure(link.pos());
}
});
@ -335,13 +356,13 @@ public class PowerNode extends PowerBlock{
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);
Tilec link = world.ent(x, y);
if(link != tile && linkValid(tile, link, false)){
boolean linked = linked(tile, link);
if(link != this && linkValid(this, link, false)){
boolean linked = linked(link);
if(linked){
Drawf.square(link.drawx(), link.drawy(), link.block().size * tilesize / 2f + 1f, Pal.place);
Drawf.square(link.x(), link.y(), link.block().size * tilesize / 2f + 1f, Pal.place);
}
}
}
@ -357,40 +378,24 @@ public class PowerNode extends PowerBlock{
Tilec entity = tile.ent();
for(int i = 0; i < power.links.size; i++){
Tile link = world.tile(power.links.get(i));
Tilec link = world.ent(power.links.get(i));
if(!linkValid(tile, link)) continue;
if(!linkValid(this, link)) continue;
if(link.block() instanceof PowerNode && !(link.pos() < tile.pos())) continue;
drawLaser(tile, link);
drawLaserTo(link);
}
Draw.reset();
}
protected boolean linked(Tile other){
return tile.power.links.contains(other.pos());
protected boolean linked(Tilec other){
return power.links.contains(other.pos());
}
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 || team != link.team()) 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.power.links.size < link.<PowerNode>cblock().maxNodes || link.power.links.contains(tile.pos());
}
return true;
}
return false;
}
protected void drawLaser(Tile target){
drawLaser(x, y, target.drawx(), target.drawy(), power.graph.getSatisfaction(), size, target.block().size);
protected void drawLaserTo(Tilec target){
drawLaser(x, y, target.x(), target.y(), power.graph.getSatisfaction(), size, target.block().size);
}
@Override

View File

@ -7,14 +7,10 @@ import arc.math.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.content.*;
import mindustry.gen.*;
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");
@ -38,13 +34,6 @@ public class Cultivator extends GenericCrafter{
topRegion = Core.atlas.find(name + "-top");
}
@Override
public void updateTile(){
super.updateTile();
warmup = Mathf.lerpDelta(warmup, consValid() ? 1f : 0f, 0.015f);
}
@Override
public void setBars(){
super.setBars();
@ -67,54 +56,60 @@ 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(){
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 TextureRegion[] generateIcons(){
return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-top"),};
}
@Override
public void onProximityAdded(){
super.onProximityAdded();
boost = sumAttribute(attribute, tile.x, tile.y);
}
@Override
protected float getProgressIncrease(Tilec entity, float baseTime){
CultivatorEntity c = (CultivatorEntity)entity;
return super.getProgressIncrease(entity, baseTime) * (1f + c.boost);
}
public class CultivatorEntity extends GenericCrafterEntity{
public float warmup;
public float boost;
@Override
public void updateTile(){
super.updateTile();
warmup = Mathf.lerpDelta(warmup, consValid() ? 1f : 0f, 0.015f);
}
@Override
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);

View File

@ -1,10 +1,10 @@
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.*;
@ -62,7 +62,7 @@ public class Drill extends Block{
hasLiquids = true;
liquidCapacity = 5f;
hasItems = true;
idleSound = Sounds.drill;
idleSound = Sounds.drill;
idleSoundVolume = 0.003f;
}
@ -73,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(lastDrillSpeed * 60 * timeScale(), 2)), () -> Pal.ammo, () -> warmup);
return new Bar(() -> Core.bundle.format("bar.drillspeed", Strings.fixed(entity.lastDrillSpeed * 60 * entity.timeScale(), 2)), () -> Pal.ammo, () -> entity.warmup);
});
}
@ -85,50 +85,22 @@ public class Drill extends Block{
topRegion = Core.atlas.find(name + "-top");
}
@Override
public void drawCracks(){}
public Item getDrop(Tile tile){
return tile.drop();
}
@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();
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, x, y, drillTime * rotateSpeed);
Draw.rect(topRegion, x, y);
if(dominantItem != null && drawMineItem){
Draw.color(dominantItem.color);
Draw.rect("drill-top", x, y, 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(){
return tile.items.total() < itemCapacity;
}
@Override
public boolean shouldIdleSound(){
return tile.efficiency() > 0.01f;
}
@Override
@ -154,17 +126,6 @@ public class Drill extends Block{
}
}
@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 setStats(){
super.setStats();
@ -195,7 +156,12 @@ public class Drill extends Block{
}
}
void countOre(){
@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;
@ -203,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);
}
}
@ -228,84 +194,7 @@ public class Drill extends Block{
returnCount = oreCount.get(itemArray.peek(), 0);
}
@Override
public void onProximityUpdate(){
countOre(tile);
dominantItem = returnItem;
dominantItems = returnCount;
}
@Override
public void updateTile(){
if(dominantItem == null){
return;
}
if(timer(timerDump, dumpTime)){
tryDump(tile, dominantItem);
}
drillTime += 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 && tile.items.total() < itemCapacity){
offloadNear(tile, dominantItem);
useContent(tile, dominantItem);
index++;
progress = 0f;
drillEffect.at(getX() + Mathf.range(size), getY() + Mathf.range(size), dominantItem.color);
}
}
@Override
public boolean canPlaceOn(){
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(){
return tile.drop();
}
public boolean isValid(){
public boolean canMine(Tile tile){
if(tile == null) return false;
Item drops = tile.drop();
return drops != null && drops.hardness <= tier;
@ -320,6 +209,112 @@ public class Drill extends Block{
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);
}
drillTime += 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, drillTime * rotateSpeed);
Draw.rect(topRegion, x, y);
if(dominantItem != null && drawMineItem){
Draw.color(dominantItem.color);
Draw.rect("drill-top", x, y, 1f);
Draw.color();
}
}
}
}

View File

@ -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{
@ -38,54 +37,54 @@ public class Fracker extends SolidPump{
return false;
}
@Override
public void drawCracks(){}
@Override
public boolean shouldConsume(){
return tile.liquids.get(result) < liquidCapacity - 0.01f;
}
@Override
public void draw(){
Draw.rect(region, x, y);
super.drawCracks();
Draw.color(result.color);
Draw.alpha(tile.liquids.get(result) / liquidCapacity);
Draw.rect(liquidRegion, x, y);
Draw.color();
Draw.rect(rotatorRegion, x, y, pumpTime);
Draw.rect(topRegion, x, y);
}
@Override
public TextureRegion[] generateIcons(){
return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-rotator"), Core.atlas.find(name + "-top")};
}
@Override
public void updateTile(){
if(consValid()){
if(accumulator >= itemUseTime){
consume();
accumulator -= itemUseTime;
}
super.updateTile();
accumulator += delta() * efficiency();
}else{
tryDumpLiquid(tile, result);
}
}
@Override
public float typeLiquid(){
return tile.liquids.get(result);
}
public class FrackerEntity extends SolidPumpEntity{
public float accumulator;
@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);
}
}
@Override
public float typeLiquid(){
return liquids.get(result);
}
}
}

View File

@ -55,97 +55,97 @@ public class GenericCrafter extends Block{
}
}
@Override
public boolean shouldIdleSound(Tilec tile){
return tile.cons().valid();
}
@Override
public void init(){
outputsLiquid = outputLiquid != null;
super.init();
}
@Override
public void draw(){
if(drawer == null){
super.draw();
}else{
drawer.get(tile);
}
}
@Override
public TextureRegion[] generateIcons(){
return drawIcons == null ? super.generateIcons() : drawIcons.get();
}
@Override
public void updateTile(){
if(consValid()){
progress += getProgressIncrease(entity, 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(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);
}
craftEffect.at(x, y);
progress = 0f;
}
if(outputItem != null && timer(timerDump, dumpTime)){
tryDump(tile, outputItem.item);
}
if(outputLiquid != null){
tryDumpLiquid(tile, outputLiquid.liquid);
}
}
@Override
public boolean outputsItems(){
return outputItem != null;
}
@Override
public boolean shouldConsume(){
if(outputItem != null && tile.items.get(outputItem.item) >= itemCapacity){
return false;
}
return outputLiquid == null || !(tile.liquids.get(outputLiquid.liquid) >= liquidCapacity - 0.001f);
}
@Override
public int getMaximumAccepted(Item item){
return itemCapacity;
}
public class GenericCrafterEntity extends TileEntity{
public float progress;
public float totalProgress;
public float warmup;
@Override
public void draw(){
if(drawer == null){
super.draw();
}else{
drawer.get(this);
}
}
@Override
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);

View File

@ -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,30 +23,32 @@ public class GenericSmelter extends GenericCrafter{
topRegion = Core.atlas.find(name + "-top");
}
@Override
public void draw(){
super.draw();
public class SmelterEntity extends GenericCrafterEntity{
@Override
public void draw(){
super.draw();
//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(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) * 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(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.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(){
renderer.lights.add(x, y, (60f + Mathf.absin(10f, 5f)) * warmup * size, flameColor, 0.65f);
}
}

View File

@ -1,17 +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 arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.type.Item;
import mindustry.type.Liquid;
import mindustry.world.Block;
import mindustry.world.Tile;
import mindustry.type.*;
import mindustry.world.*;
public class Incinerator extends Block{
public Effect effect = Fx.fuelburn;
@ -25,59 +22,59 @@ public class Incinerator extends Block{
solid = true;
}
@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(Tile source, Liquid liquid, float amount){
if(Mathf.chance(0.02)){
effect.at(x, y);
}
}
@Override
public boolean acceptLiquid(Tile source, Liquid liquid, float amount){
return heat > 0.5f;
}
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;
}
}
}

View File

@ -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,29 +30,31 @@ public class LiquidConverter extends GenericCrafter{
stats.add(BlockStat.output, outputLiquid.liquid, outputLiquid.amount * craftTime, false);
}
@Override
public void drawLight(){
if(hasLiquids && drawLiquidLight && outputLiquid.liquid.lightColor.a > 0.001f){
drawLiquidLight(tile, outputLiquid.liquid, tile.liquids.get(outputLiquid.liquid));
}
}
@Override
public void updateTile(){
ConsumeLiquidBase cl = consumes.get(ConsumeType.liquid);
if(tile.cons().valid()){
float use = Math.min(cl.amount * delta(), liquidCapacity - liquids.get(outputLiquid.liquid)) * efficiency();
useContent(tile, outputLiquid.liquid);
progress += use / cl.amount / craftTime;
liquids.add(outputLiquid.liquid, use);
if(progress >= 1f){
consume();
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);
}
}
}

View File

@ -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.liquid.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(){
Draw.rect(name, x, y);
Draw.color(tile.liquids.current().color);
Draw.alpha(tile.liquids.total() / liquidCapacity);
Draw.rect(liquidRegion, x, y);
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++;
}
@ -85,10 +69,10 @@ public class Pump extends LiquidBlock{
}
@Override
public boolean canPlaceOn(){
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 updateTile(){
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.cons().valid() && liquidDrop != null){
float maxPump = Math.min(liquidCapacity - tile.liquids.total(), tiles * pumpAmount * tile.delta() / size / size) * tile.efficiency();
tile.liquids.add(liquidDrop, maxPump);
}
if(tile.liquids.currentAmount() > 0f && timer(timerContentCheck, 10)){
useContent(tile, tile.liquids.current());
}
tryDumpLiquid(tile, tile.liquids.current());
}
protected boolean isValid(){
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());
}
}
}

View File

@ -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.*;
@ -51,64 +52,88 @@ public class Separator extends Block{
stats.add(BlockStat.productionTime, craftTime / 60f, StatUnit.seconds);
}
@Override
public boolean shouldConsume(){
return tile.items.total() < itemCapacity;
}
public class SeparatorEntity extends TileEntity{
public float progress;
public float totalProgress;
public float warmup;
@Override
public void draw(){
super.draw();
Draw.color(tile.liquids.current().color);
Draw.alpha(tile.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(entity, craftTime);
warmup = Mathf.lerpDelta(warmup, 1f, 0.02f);
}else{
warmup = Mathf.lerpDelta(warmup, 0f, 0.02f);
@Override
public boolean shouldIdleSound(){
return cons.valid();
}
if(progress >= 1f){
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;
}
consume();
if(item != null && items.get(item) < itemCapacity){
useContent(tile, item);
offloadNear(tile, item);
if(timer(timerDump, dumpTime)){
dump();
}
}
if(timer(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();
}
}
}

View File

@ -1,21 +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 arc.util.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
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 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.
@ -69,14 +65,22 @@ public class SolidPump extends Pump{
}
@Override
public void draw(){
Draw.rect(region, x, y);
Draw.color(tile.liquids.current().color);
Draw.alpha(tile.liquids.total() / liquidCapacity);
Draw.rect(liquidRegion, x, y);
Draw.color();
Draw.rect(name + "-rotator", x, y, pumpTime * rotateSpeed);
Draw.rect(name + "-top", x, y);
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);
}
}
@Override
protected boolean canPump(Tile tile){
return tile != null && !tile.floor().isLiquid;
}
@Override
@ -84,76 +88,68 @@ 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 updateTile(){
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 += boost;
if(tile.cons().valid() && typeLiquid(tile) < liquidCapacity - 0.001f){
float maxPump = Math.min(liquidCapacity - typeLiquid(tile), pumpAmount * delta() * fraction * efficiency());
tile.liquids.add(result, maxPump);
lastPump = maxPump;
warmup = Mathf.lerpDelta(warmup, 1f, 0.02f);
if(timer(timerContentCheck, 10)) useContent(tile, 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();
tryDumpLiquid(tile, result);
}
@Override
public boolean canPlaceOn(){
if(isMultiblock()){
for(Tile other : tile.getLinkedTilesAs(this, drawTiles)){
if(isValid(other)){
return true;
}
}
return false;
}else{
return isValid(tile);
}
}
@Override
protected boolean isValid(){
return tile != null && !tile.floor().isLiquid;
}
@Override
public void onProximityAdded(){
super.onProximityAdded();
if(attribute != null){
boost = sumAttribute(attribute, tile.x, tile.y);
}
}
public float typeLiquid(){
return tile.liquids.total();
}
public 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;
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();
}
}
}

View File

@ -99,7 +99,7 @@ public class CoreBlock extends StorageBlock{
storageCapacity = itemCapacity + proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
proximity.each(this::isContainer, t -> {
t.items(items);
((StorageBlockEntity)t).linkedCore = tile;
((StorageBlockEntity)t).linkedCore = this;
});
for(Tilec other : state.teams.cores(team)){

View File

@ -1,20 +1,16 @@
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.gen.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
import mindustry.*;
import mindustry.content.*;
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 mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
@ -37,49 +33,50 @@ public class LaunchPad extends StorageBlock{
stats.add(BlockStat.launchTime, launchTime / 60f, StatUnit.seconds);
}
@Override
public boolean acceptItem(Tilec source, Item item){
return item.type == ItemType.material && tile.items.total() < itemCapacity;
}
public class LaunchPadEntity extends StorageBlockEntity{
@Override
public void draw(){
super.draw();
@Override
public void draw(){
super.draw();
//TODO broken
float progress = Mathf.clamp(Mathf.clamp((items.total() / (float)itemCapacity)) * ((timer().getTime(timerLaunch) / (launchTime / timeScale()))));
float scale = size / 3f;
//TODO broken
float progress = Mathf.clamp(Mathf.clamp((tile.items.total() / (float)itemCapacity)) * ((timer().getTime(timerLaunch) / (launchTime / tile.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(x, y, 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.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(x, y, 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 && items.total() < itemCapacity;
}
@Override
public void updateTile(){
Tilec entity = tile.entity;
@Override
public void updateTile(){
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));
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));
}
}
}
}

View File

@ -2,32 +2,17 @@ package mindustry.world.blocks.storage;
import arc.util.ArcAnnotate.*;
import mindustry.gen.*;
import mindustry.type.Item;
import mindustry.world.Block;
import mindustry.world.Tile;
import mindustry.type.*;
import mindustry.world.*;
public abstract class StorageBlock extends Block{
public StorageBlock(String name){
super(name);
hasItems = true;
}
@Override
public boolean acceptItem(Tilec source, Item item){
return linkedCore != null ? linkedCore.acceptItem(linkedCore, source, item) : tile.items.get(item) < getMaximumAccepted(tile, item);
}
@Override
public int getMaximumAccepted(Item item){
return itemCapacity;
}
@Override
public void drawSelect(){
if(linkedCore != null){
linkedCore.block().drawSelect(linkedCore);
}
solid = true;
update = false;
destructible = true;
}
@Override
@ -35,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(Item item){
Tilec entity = tile.entity;
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(Item item){
Tilec entity = tile.entity;
if(item == null){
return items.total() > 0;
}else{
return 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();
}
}
}
}

View File

@ -26,12 +26,12 @@ public class Unloader extends Block{
health = 70;
hasItems = true;
configurable = true;
config(Item.class, (tile, item) -> {
tile.items.clear();
tile.<UnloaderEntity>ent().sortItem = item;
config(Item.class, (tile, item) -> {
tile.items().clear();
((UnloaderEntity)tile).sortItem = item;
});
configClear(tile -> tile.<UnloaderEntity>ent().sortItem = null);
configClear(tile -> ((UnloaderEntity)tile).sortItem = null);
}
@Override
@ -39,89 +39,76 @@ public class Unloader extends Block{
drawRequestConfigCenter(req, (Item)req.config, "unloader-center");
}
@Override
public boolean canDump(Tile to, Item item){
return !(to.block() instanceof StorageBlock);
}
@Override
public void setBars(){
super.setBars();
bars.remove("items");
}
@Override
public void playerPlaced(){
if(lastItem != null){
tile.configure(lastItem);
}
}
@Override
public void updateTile(){
if(timer(timerUnload, speed / timeScale()) && tile.items.total() == 0){
for(Tile other : tile.proximity()){
if(other.interactable(team) && other.block().unloadable && other.block().hasItems && items.total() == 0 &&
((sortItem == null && other.items.total() > 0) || hasItem(other, sortItem))){
offloadNear(tile, removeItem(other, sortItem));
}
}
}
if(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(Item item){
Tilec entity = tile.entity;
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.
*/
private boolean hasItem(Item item){
Tilec entity = tile.entity;
if(item == null){
return items.total() > 0;
}else{
return items.has(item);
}
}
@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));
}
public class UnloaderEntity extends TileEntity{
public Item sortItem = null;
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 playerPlaced(){
if(lastItem != null){
tile.configure(lastItem);
}
}
@Override
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;

View File

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

View File

@ -34,44 +34,22 @@ public class CommandCenter extends Block{
destructible = true;
solid = true;
configurable = true;
config(Integer.class, (tile, value) -> {
config(Integer.class, (tile, value) -> {
UnitCommand command = UnitCommand.all[value];
((CommandCenter)tile.block()).effect.at(tile);
for(Tile center : indexer.getAllied(team, BlockFlag.comandCenter)){
for(Tile center : indexer.getAllied(tile.team(), BlockFlag.comandCenter)){
if(center.block() instanceof CommandCenter){
CommandCenterEntity entity = center.ent();
command = command;
entity.command = command;
}
}
Groups.unit.each(t -> t.team() == team, u -> u.controller().command(command));
Groups.unit.each(t -> t.team() == tile.team(), u -> u.controller().command(command));
Events.fire(new CommandIssueEvent(tile, command));
});
}
@Override
public void placed(){
super.placed();
ObjectSet<Tile> set = indexer.getAllied(team, BlockFlag.comandCenter);
if(set.size > 0){
CommandCenterEntity oe = set.first().ent();
command = oe.command;
}
}
@Override
public void removed(){
super.removed();
ObjectSet<Tile> 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 void load(){
super.load();
@ -83,36 +61,58 @@ public class CommandCenter extends Block{
}
}
@Override
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);
}
public class CommandCenterEntity extends TileEntity{
public UnitCommand command = UnitCommand.attack;
@Override
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();
ObjectSet<Tile> set = indexer.getAllied(team, BlockFlag.comandCenter);
if(set.size > 0){
CommandCenterEntity oe = set.first().ent();
command = oe.command;
}
}
@Override
public void onRemoved(){
super.onRemoved();
ObjectSet<Tile> 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();

View File

@ -1,147 +0,0 @@
package mindustry.world.blocks.units;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.meta.*;
import java.io.*;
import static mindustry.Vars.*;
//TODO remove
public class MechPad extends Block{
public @NonNull UnitType 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);
}
@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(Playerc player, Tile tile){
if(player == null || tile == null || !(tile.block() instanceof MechPad) || !checkValidTap(tile, player)) return;
if(!consValid()) return;
//player.beginRespawning(entity);
sameMech = false;
}
@Remote(called = Loc.server)
public static void onMechFactoryDone(){
if(!(tile.entity instanceof MechFactoryEntity)) return;
Fx.spawn.at(entity);
if(player == null) return;
//Mech mech = ((MechPad)tile.block()).mech;
//boolean resetSpawner = !sameMech && player.mech == mech;
//player.mech = !sameMech && player.mech == mech ? UnitTypes.starter : mech;
Playerc player = player;
//progress = 0;
//player.onRespawn(tile);
//if(resetSpawner) player.lastSpawner = null;
//player = null;
//Events.fire(new MechChangeEvent(player, player.mech));
}
protected static boolean checkValidTap(Playerc player){
return false;//!player.dead() && tile.interactable(player.team()) && Math.abs(player.x - x) <= tile.block().size * tilesize &&
//Math.abs(player.y - y) <= tile.block().size * tilesize && consValid() && player == null;
}
@Override
public void drawSelect(){
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", x + Geometry.d4[i].x * length, y + Geometry.d4[i].y * length, (i + 2) * 90);
}
Draw.color();
}
@Override
public void tapped(Playerc player){
if(checkValidTap(tile, player)){
Call.onMechFactoryTap(player, tile);
}else if(player.isLocal() && mobile && !player.dead() && consValid() && player == null){
//deselect on double taps
//TODO remove
//player.moveTarget = player.moveTarget == tile.entity ? null : tile.entity;
}
}
@Override
public void drawLayer(){
if(player != null){
//TODO remove
//RespawnBlock.drawRespawn(tile, heat, progress, time, player, (!sameMech && player.mech == mech ? UnitTypes.starter : mech));
}
}
@Override
public void updateTile(){
if(player != null){
player.set(x, y);
heat = Mathf.lerpDelta(heat, 1f, 0.1f);
progress += 1f / buildTime * delta();
time += 0.5f * delta();
if(progress >= 1f){
Call.onMechFactoryDone(tile);
}
}else{
heat = Mathf.lerpDelta(heat, 0f, 0.1f);
}
}
public class MechFactoryEntity extends TileEntity{
Playerc player;
boolean sameMech;
float progress;
float time;
float heat;
@Override
public void write(Writes write){
super.write(write);
write.f(progress);
write.f(time);
write.f(heat);
}
@Override
public void read(Reads read, byte revision){
super.read(read, revision);
progress = read.f();
time = read.f();
heat = read.f();
}
}
}

View File

@ -1,18 +1,16 @@
package mindustry.world.blocks.units;
import arc.Core;
import arc.struct.EnumSet;
import arc.graphics.Color;
import arc.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.Angles;
import arc.math.Mathf;
import arc.math.geom.Rect;
import arc.util.Time;
import mindustry.entities.Units;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.entities.*;
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;
@ -60,76 +58,76 @@ public class RepairPoint extends Block{
super.init();
}
@Override
public void drawSelect(){
Drawf.dashCircle(x, y, repairRadius, Pal.accent);
}
@Override
public void drawPlace(int x, int y, int rotation, boolean valid){
Drawf.dashCircle(x * tilesize + offset(), y * tilesize + offset(), repairRadius, Pal.accent);
}
@Override
public void draw(){
Draw.rect(baseRegion, x, y);
}
@Override
public void drawLayer(){
Draw.rect(region, x, y, rotation - 90);
}
@Override
public void drawLayer2(){
if(target != null &&
Angles.angleDist(angleTo(target), rotation) < 30f){
float ang = angleTo(target);
float len = 5f;
Draw.color(Color.valueOf("e8ffd7"));
Drawf.laser(laser, laserEnd,
x + Angles.trnsx(ang, len), y + Angles.trnsy(ang, len),
target.x(), target.y(), strength);
Draw.color();
}
}
@Override
public TextureRegion[] generateIcons(){
return new TextureRegion[]{Core.atlas.find(name + "-base"), Core.atlas.find(name)};
}
@Override
public void updateTile(){
boolean targetIsBeingRepaired = false;
if(target != null && (target.dead() || target.dst(tile) > repairRadius || target.health() >= target.maxHealth())){
target = null;
}else if(target != null && consValid()){
target.heal(repairSpeed * Time.delta() * strength * efficiency());
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.5f);
targetIsBeingRepaired = true;
}
if(target != null && targetIsBeingRepaired){
strength = Mathf.lerpDelta(strength, 1f, 0.08f * Time.delta());
}else{
strength = Mathf.lerpDelta(strength, 0f, 0.07f * Time.delta());
}
if(timer(timerTarget, 20)){
rect.setSize(repairRadius * 2).setCenter(x, y);
target = Units.closest(team, x, y, repairRadius, Unitc::damaged);
}
}
@Override
public boolean shouldConsume(){
return target != null;
}
public class RepairPointEntity extends TileEntity{
public Unitc target;
public float strength, rotation = 90;
@Override
public void draw(){
Draw.rect(baseRegion, x, y);
}
@Override
public void drawLayer(){
Draw.rect(region, x, y, rotation - 90);
}
@Override
public void drawLayer2(){
if(target != null &&
Angles.angleDist(angleTo(target), rotation) < 30f){
float ang = angleTo(target);
float len = 5f;
Draw.color(Color.valueOf("e8ffd7"));
Drawf.laser(laser, laserEnd,
x + Angles.trnsx(ang, len), y + Angles.trnsy(ang, len),
target.x(), target.y(), strength);
Draw.color();
}
}
@Override
public void drawSelect(){
Drawf.dashCircle(x, y, repairRadius, Pal.accent);
}
@Override
public void updateTile(){
boolean targetIsBeingRepaired = false;
if(target != null && (target.dead() || target.dst(tile) > repairRadius || target.health() >= target.maxHealth())){
target = null;
}else if(target != null && consValid()){
target.heal(repairSpeed * Time.delta() * strength * efficiency());
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.5f);
targetIsBeingRepaired = true;
}
if(target != null && targetIsBeingRepaired){
strength = Mathf.lerpDelta(strength, 1f, 0.08f * Time.delta());
}else{
strength = Mathf.lerpDelta(strength, 0f, 0.07f * Time.delta());
}
if(timer(timerTarget, 20)){
rect.setSize(repairRadius * 2).setCenter(x, y);
target = Units.closest(team, x, y, repairRadius, Unitc::damaged);
}
}
@Override
public boolean shouldConsume(){
return target != null;
}
}
}

View File

@ -1,74 +0,0 @@
package mindustry.world.blocks.units;
import arc.graphics.g2d.*;
import arc.math.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
import static mindustry.Vars.net;
//TODO remove ?
public class RespawnBlock{
public static void drawRespawn(float heat, float progress, float time, Playerc player, UnitType to){
progress = Mathf.clamp(progress);
Draw.color(Pal.darkMetal);
Lines.stroke(2f * heat);
Fill.poly(x, y, 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", x, y, 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, x, y);
Draw.shader();
Draw.color(Pal.accentBack);
float pos = Mathf.sin(time, 6f, 8f);
Lines.lineAngleCenter(x + pos, y, 90, 16f - Math.abs(pos) * 2f);
Draw.reset();
}
Lines.stroke(2f * heat);
Draw.color(Pal.accentBack);
Lines.poly(x, y, 4, 8f * heat);
float oy = -7f, len = 6f * heat;
Lines.stroke(5f);
Draw.color(Pal.darkMetal);
Lines.line(x - len, y + oy, x + len, y + oy, CapStyle.none);
for(int i : Mathf.signs){
Fill.tri(x + len * i, y + oy - Lines.getStroke()/2f, x + len * i, y + oy + Lines.getStroke()/2f, x + (len + Lines.getStroke() * heat) * i, y + oy);
}
Lines.stroke(3f);
Draw.color(Pal.accent);
Lines.line(x - len, y + oy, x - len + len*2 * progress, y + oy, CapStyle.none);
for(int i : Mathf.signs){
Fill.tri(x + len * i, y + oy - Lines.getStroke()/2f, x + len * i, y + oy + Lines.getStroke()/2f, x + (len + Lines.getStroke() * heat) * i, y + oy);
}
Draw.reset();
if(net.active() && player != null){
tile.drawPlaceText(player.name(), tile.x, tile.y - (Math.max((tile.block().size-1)/2, 0)), true);
}
}
}

View File

@ -18,8 +18,6 @@ import mindustry.world.*;
import mindustry.world.consumers.*;
import mindustry.world.meta.*;
import java.io.*;
import static mindustry.Vars.net;
public class UnitFactory extends Block{
@ -40,20 +38,21 @@ public class UnitFactory extends Block{
}
@Remote(called = Loc.server)
public static void onUnitFactorySpawn(int spawns){
public static void onUnitFactorySpawn(Tile tile, int spawns){
if(!(tile.entity instanceof UnitFactoryEntity) || !(tile.block() instanceof UnitFactory)) return;
UnitFactory factory = (UnitFactory)tile.block();
UnitFactoryEntity entity = tile.ent();
buildTime = 0f;
spawned = spawns;
entity.buildTime = 0f;
entity.spawned = spawns;
Effects.shake(2f, 3f, entity);
Fx.producesmoke.at(x, y);
Fx.producesmoke.at(entity);
if(!net.client()){
Unitc unit = factory.unitType.create(team);
unit.set(x + Mathf.range(4), y + Mathf.range(4));
Unitc unit = factory.unitType.create(entity.team());
unit.set(entity.x() + Mathf.range(4), entity.y() + Mathf.range(4));
unit.add();
unit.vel().y = factory.launchVelocity;
Events.fire(new UnitCreateEvent(unit));
@ -101,87 +100,81 @@ public class UnitFactory extends Block{
stats.add(BlockStat.maxUnits, maxSpawn, StatUnit.none);
}
@Override
public void unitRemoved(Unitc unit){
spawned--;
spawned = Math.max(spawned, 0);
}
@Override
public TextureRegion[] generateIcons(){
return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-top")};
}
@Override
public void draw(){
TextureRegion region = unitType.icon(Cicon.full);
Draw.rect(name, x, y);
Shaders.build.region = region;
Shaders.build.progress = buildTime / produceTime;
Shaders.build.color.set(Pal.accent);
Shaders.build.color.a = speedScl;
Shaders.build.time = -time / 20f;
Draw.shader(Shaders.build);
Draw.rect(region, x, y);
Draw.shader();
Draw.color(Pal.accent);
Draw.alpha(speedScl);
Lines.lineAngleCenter(
x + Mathf.sin(time, 20f, Vars.tilesize / 2f * size - 2f),
y,
90,
size * Vars.tilesize - 4f);
Draw.reset();
Draw.rect(topRegion, x, y);
}
@Override
public void updateTile(){
if(spawned >= maxSpawn){
return;
}
if(consValid() || tile.isEnemyCheat()){
time += delta() * speedScl * Vars.state.rules.unitBuildSpeedMultiplier * efficiency();
buildTime += delta() * efficiency() * Vars.state.rules.unitBuildSpeedMultiplier;
speedScl = Mathf.lerpDelta(speedScl, 1f, 0.05f);
}else{
speedScl = Mathf.lerpDelta(speedScl, 0f, 0.05f);
}
if(buildTime >= produceTime){
buildTime = 0f;
Call.onUnitFactorySpawn(tile, spawned + 1);
useContent(tile, unitType);
consume();
}
}
@Override
public int getMaximumAccepted(Item item){
return capacities[item.id];
}
@Override
public boolean shouldConsume(){
return spawned < maxSpawn;
}
public class UnitFactoryEntity extends TileEntity{
float buildTime;
float time;
float speedScl;
int spawned;
@Override
public void draw(){
TextureRegion region = unitType.icon(Cicon.full);
Draw.rect(name, x, y);
Shaders.build.region = region;
Shaders.build.progress = buildTime / produceTime;
Shaders.build.color.set(Pal.accent);
Shaders.build.color.a = speedScl;
Shaders.build.time = -time / 20f;
Draw.shader(Shaders.build);
Draw.rect(region, x, y);
Draw.shader();
Draw.color(Pal.accent);
Draw.alpha(speedScl);
Lines.lineAngleCenter(
x + Mathf.sin(time, 20f, Vars.tilesize / 2f * size - 2f),
y,
90,
size * Vars.tilesize - 4f);
Draw.reset();
Draw.rect(topRegion, x, y);
}
@Override
public void updateTile(){
if(spawned >= maxSpawn){
return;
}
if(consValid() || tile.isEnemyCheat()){
time += delta() * speedScl * Vars.state.rules.unitBuildSpeedMultiplier * efficiency();
buildTime += delta() * efficiency() * Vars.state.rules.unitBuildSpeedMultiplier;
speedScl = Mathf.lerpDelta(speedScl, 1f, 0.05f);
}else{
speedScl = Mathf.lerpDelta(speedScl, 0f, 0.05f);
}
if(buildTime >= produceTime){
buildTime = 0f;
Call.onUnitFactorySpawn(tile, spawned + 1);
useContent(unitType);
consume();
}
}
@Override
public int getMaximumAccepted(Item item){
return capacities[item.id];
}
@Override
public boolean shouldConsume(){
return spawned < maxSpawn;
}
@Override
public void write(Writes write){
super.write(write);