New unstable mass driver code
This commit is contained in:
@@ -88,7 +88,6 @@ public class MassDriverBolt extends BulletType{
|
|||||||
if(!(b.getData() instanceof DriverBulletData)) return;
|
if(!(b.getData() instanceof DriverBulletData)) return;
|
||||||
|
|
||||||
DriverBulletData data = (DriverBulletData)b.getData();
|
DriverBulletData data = (DriverBulletData)b.getData();
|
||||||
data.to.isRecieving = false;
|
|
||||||
|
|
||||||
for(int i = 0; i < data.items.length; i++){
|
for(int i = 0; i < data.items.length; i++){
|
||||||
int amountDropped = Mathf.random(0, data.items[i]);
|
int amountDropped = Mathf.random(0, data.items[i]);
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ package io.anuke.mindustry.world.blocks.distribution;
|
|||||||
import io.anuke.annotations.Annotations.Loc;
|
import io.anuke.annotations.Annotations.Loc;
|
||||||
import io.anuke.annotations.Annotations.Remote;
|
import io.anuke.annotations.Annotations.Remote;
|
||||||
import io.anuke.arc.Core;
|
import io.anuke.arc.Core;
|
||||||
import io.anuke.arc.collection.ObjectSet;
|
import io.anuke.arc.collection.OrderedSet;
|
||||||
import io.anuke.arc.graphics.Color;
|
|
||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
import io.anuke.arc.math.Angles;
|
import io.anuke.arc.math.Angles;
|
||||||
import io.anuke.arc.math.Mathf;
|
import io.anuke.arc.math.Mathf;
|
||||||
@@ -63,47 +62,6 @@ public class MassDriver extends Block{
|
|||||||
entity.link = position;
|
entity.link = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server)
|
|
||||||
public static void onMassDriverFire(Tile tile, Tile target){
|
|
||||||
//just in case the client has invalid data
|
|
||||||
if(!(tile.entity instanceof MassDriverEntity) || !(target.entity instanceof MassDriverEntity)) return;
|
|
||||||
|
|
||||||
MassDriver driver = (MassDriver)tile.block();
|
|
||||||
|
|
||||||
MassDriverEntity entity = tile.entity();
|
|
||||||
MassDriverEntity other = target.entity();
|
|
||||||
|
|
||||||
entity.reload = 1f;
|
|
||||||
|
|
||||||
entity.power.satisfaction -= Math.min(entity.power.satisfaction, driver.powerPercentageUsed);
|
|
||||||
|
|
||||||
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.clear();
|
|
||||||
|
|
||||||
float angle = tile.angleTo(target);
|
|
||||||
|
|
||||||
other.isRecieving = true;
|
|
||||||
Bullet.create(Bullets.driverBolt, entity, entity.getTeam(),
|
|
||||||
tile.drawx() + Angles.trnsx(angle, driver.translation), tile.drawy() + Angles.trnsy(angle, driver.translation),
|
|
||||||
angle, 1f, 1f, data);
|
|
||||||
|
|
||||||
Effects.effect(driver.shootEffect, tile.drawx() + Angles.trnsx(angle, driver.translation),
|
|
||||||
tile.drawy() + Angles.trnsy(angle, driver.translation), angle);
|
|
||||||
|
|
||||||
Effects.effect(driver.smokeEffect, tile.drawx() + Angles.trnsx(angle, driver.translation),
|
|
||||||
tile.drawy() + Angles.trnsy(angle, driver.translation), angle);
|
|
||||||
|
|
||||||
Effects.shake(driver.shake, driver.shake, entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TextureRegion[] generateIcons(){
|
public TextureRegion[] generateIcons(){
|
||||||
return new TextureRegion[]{Core.atlas.find(name + "-base"), Core.atlas.find(name)};
|
return new TextureRegion[]{Core.atlas.find(name + "-base"), Core.atlas.find(name)};
|
||||||
@@ -126,51 +84,78 @@ public class MassDriver extends Block{
|
|||||||
@Override
|
@Override
|
||||||
public void update(Tile tile){
|
public void update(Tile tile){
|
||||||
MassDriverEntity entity = tile.entity();
|
MassDriverEntity entity = tile.entity();
|
||||||
|
|
||||||
Tile link = world.tile(entity.link);
|
Tile link = world.tile(entity.link);
|
||||||
|
boolean hasLink = linkValid(tile);
|
||||||
|
|
||||||
if(entity.isUnloading){
|
//reload regardless of state
|
||||||
tryDump(tile);
|
|
||||||
if(entity.items.total() <= 0){
|
|
||||||
entity.isUnloading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(entity.reload > 0f){
|
if(entity.reload > 0f){
|
||||||
entity.reload = Mathf.clamp(entity.reload - entity.delta() / reloadTime);
|
entity.reload = Mathf.clamp(entity.reload - entity.delta() / reloadTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
//unload when dest is full
|
//cleanup waiting shooters that are not valid
|
||||||
if(!linkValid(tile) || (link.entity.items.total() >= itemCapacity) && entity.items.total() > 0){
|
if(!shooterValid(tile, entity.currentShooter())){
|
||||||
entity.isUnloading = true;
|
entity.waitingShooters.remove(entity.currentShooter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!entity.isRecieving){
|
//switch states
|
||||||
|
if(entity.state == DriverState.idle){
|
||||||
|
//start accepting when idle
|
||||||
|
if(!entity.waitingShooters.isEmpty()){
|
||||||
|
entity.state = DriverState.accepting;
|
||||||
|
}else if(hasLink){ //switch to shooting if there's a valid link.
|
||||||
|
entity.state = DriverState.shooting;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(entity.waiting.size > 0){ //accepting takes priority over shooting
|
//dump when idle or accepting
|
||||||
Tile waiter = entity.waiting.first();
|
if(entity.state == DriverState.idle || entity.state == DriverState.accepting){
|
||||||
|
tryDump(tile);
|
||||||
|
}
|
||||||
|
|
||||||
entity.rotation = Mathf.slerpDelta(entity.rotation, tile.angleTo(waiter), rotateSpeed);
|
if(entity.state == DriverState.accepting){
|
||||||
}else if(tile.entity.items.total() >= minDistribute &&
|
//if there's nothing shooting at this, bail
|
||||||
linkValid(tile) &&
|
if(entity.currentShooter() == null){
|
||||||
tile.entity.power.satisfaction >= powerPercentageUsed &&
|
entity.state = DriverState.idle;
|
||||||
link.block().itemCapacity - link.entity.items.total() >= minDistribute && entity.reload <= 0.0001f){
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//align to shooter rotation
|
||||||
|
entity.rotation = Mathf.slerpDelta(entity.rotation, tile.angleTo(entity.currentShooter()), rotateSpeed);
|
||||||
|
}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()){
|
||||||
|
entity.state = DriverState.idle;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float targetRotation = tile.angleTo(link);
|
||||||
|
|
||||||
|
if(
|
||||||
|
tile.entity.items.total() >= minDistribute && //must shoot minimum amount of items
|
||||||
|
tile.entity.power.satisfaction >= powerPercentageUsed && //must have power
|
||||||
|
link.block().itemCapacity - link.entity.items.total() >= minDistribute && //must have minimum amount of space
|
||||||
|
entity.reload <= 0.0001f //must have reloaded
|
||||||
|
){
|
||||||
MassDriverEntity other = link.entity();
|
MassDriverEntity other = link.entity();
|
||||||
other.waiting.add(tile);
|
other.waitingShooters.add(tile);
|
||||||
|
|
||||||
float target = tile.angleTo(link);
|
//align to target location
|
||||||
|
entity.rotation = Mathf.slerpDelta(entity.rotation, targetRotation, rotateSpeed);
|
||||||
|
|
||||||
entity.rotation = Mathf.slerpDelta(entity.rotation, target, rotateSpeed);
|
//fire when it's the first in the queue and angles are ready.
|
||||||
|
if(other.currentShooter() == tile &&
|
||||||
if(Angles.near(entity.rotation, target, 1f) &&
|
other.state == DriverState.accepting &&
|
||||||
Angles.near(other.rotation, target + 180f, 1f)){
|
Angles.near(entity.rotation, targetRotation, 2f) && Angles.near(other.rotation, targetRotation + 180f, 2f)){
|
||||||
Call.onMassDriverFire(tile, link);
|
//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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.waiting.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -244,7 +229,71 @@ public class MassDriver extends Block{
|
|||||||
return new MassDriverEntity();
|
return new MassDriverEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void fire(Tile tile, Tile target){
|
||||||
|
MassDriverEntity entity = tile.entity();
|
||||||
|
MassDriverEntity other = target.entity();
|
||||||
|
|
||||||
|
//reset reload, use power.
|
||||||
|
entity.reload = 1f;
|
||||||
|
entity.power.satisfaction -= Math.min(entity.power.satisfaction, powerPercentageUsed);
|
||||||
|
|
||||||
|
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.clear();
|
||||||
|
|
||||||
|
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.entity();
|
||||||
|
return entity.link == tile.pos() && tile.dst(other) <= range;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean linkValid(Tile tile){
|
protected boolean linkValid(Tile tile){
|
||||||
|
if(tile == null) return false;
|
||||||
MassDriverEntity entity = tile.entity();
|
MassDriverEntity entity = tile.entity();
|
||||||
if(entity == null || entity.link == -1) return false;
|
if(entity == null || entity.link == -1) return false;
|
||||||
Tile link = world.tile(entity.link);
|
Tile link = world.tile(entity.link);
|
||||||
@@ -264,63 +313,39 @@ public class MassDriver extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class MassDriverEntity extends TileEntity{
|
public class MassDriverEntity extends TileEntity{
|
||||||
public int link = -1;
|
int link = -1;
|
||||||
public float rotation = 90;
|
float rotation = 90;
|
||||||
//set of tiles that currently want to distribute to this tile
|
float reload = 0f;
|
||||||
public ObjectSet<Tile> waiting = new ObjectSet<>();
|
DriverState state = DriverState.idle;
|
||||||
//whether this mass driver is waiting for a bullet to hit it and deliver items
|
OrderedSet<Tile> waitingShooters = new OrderedSet<>();
|
||||||
public boolean isRecieving;
|
|
||||||
//whether this driver just recieved some items and is now unloading
|
|
||||||
public boolean isUnloading = true;
|
|
||||||
|
|
||||||
public float reload = 0f;
|
Tile currentShooter(){
|
||||||
|
return waitingShooters.isEmpty() ? null : waitingShooters.first();
|
||||||
|
}
|
||||||
|
|
||||||
public void handlePayload(Bullet bullet, DriverBulletData data){
|
public void handlePayload(Bullet bullet, DriverBulletData data){
|
||||||
int totalItems = items.total();
|
((MassDriver)block).handlePayload(this, bullet, data);
|
||||||
|
|
||||||
//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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//drop all items remaining on the ground
|
|
||||||
for(int i = 0; i < data.items.length; i++){
|
|
||||||
int amountDropped = Mathf.random(0, data.items[i]);
|
|
||||||
if(amountDropped > 0){
|
|
||||||
float angle = Mathf.range(180f);
|
|
||||||
Effects.effect(Fx.dropItem, Color.WHITE, bullet.x, bullet.y, angle, content.item(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reload = 1f;
|
|
||||||
Effects.shake(shake, shake, this);
|
|
||||||
Effects.effect(recieveEffect, bullet);
|
|
||||||
|
|
||||||
isRecieving = false;
|
|
||||||
bullet.remove();
|
|
||||||
|
|
||||||
if(!linkValid(tile)){
|
|
||||||
isUnloading = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutput stream) throws IOException{
|
public void write(DataOutput stream) throws IOException{
|
||||||
stream.writeInt(link);
|
stream.writeInt(link);
|
||||||
stream.writeFloat(rotation);
|
stream.writeFloat(rotation);
|
||||||
|
stream.writeByte((byte)state.ordinal());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(DataInput stream) throws IOException{
|
public void read(DataInput stream) throws IOException{
|
||||||
link = stream.readInt();
|
link = stream.readInt();
|
||||||
rotation = stream.readFloat();
|
rotation = stream.readFloat();
|
||||||
|
state = DriverState.values()[stream.readByte()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DriverState{
|
||||||
|
idle, //nothing is shooting at this mass driver and it does not have any target
|
||||||
|
accepting, //currently getting shot at, unload items
|
||||||
|
shooting,
|
||||||
|
unloading
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user