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;
|
||||
|
||||
DriverBulletData data = (DriverBulletData)b.getData();
|
||||
data.to.isRecieving = false;
|
||||
|
||||
for(int i = 0; i < data.items.length; 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.Remote;
|
||||
import io.anuke.arc.Core;
|
||||
import io.anuke.arc.collection.ObjectSet;
|
||||
import io.anuke.arc.graphics.Color;
|
||||
import io.anuke.arc.collection.OrderedSet;
|
||||
import io.anuke.arc.graphics.g2d.*;
|
||||
import io.anuke.arc.math.Angles;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
@@ -63,47 +62,6 @@ public class MassDriver extends Block{
|
||||
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
|
||||
public TextureRegion[] generateIcons(){
|
||||
return new TextureRegion[]{Core.atlas.find(name + "-base"), Core.atlas.find(name)};
|
||||
@@ -126,51 +84,78 @@ public class MassDriver extends Block{
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
MassDriverEntity entity = tile.entity();
|
||||
|
||||
Tile link = world.tile(entity.link);
|
||||
boolean hasLink = linkValid(tile);
|
||||
|
||||
if(entity.isUnloading){
|
||||
tryDump(tile);
|
||||
if(entity.items.total() <= 0){
|
||||
entity.isUnloading = false;
|
||||
}
|
||||
}
|
||||
|
||||
//reload regardless of state
|
||||
if(entity.reload > 0f){
|
||||
entity.reload = Mathf.clamp(entity.reload - entity.delta() / reloadTime);
|
||||
}
|
||||
|
||||
//unload when dest is full
|
||||
if(!linkValid(tile) || (link.entity.items.total() >= itemCapacity) && entity.items.total() > 0){
|
||||
entity.isUnloading = true;
|
||||
//cleanup waiting shooters that are not valid
|
||||
if(!shooterValid(tile, entity.currentShooter())){
|
||||
entity.waitingShooters.remove(entity.currentShooter());
|
||||
}
|
||||
|
||||
if(!entity.isRecieving){
|
||||
|
||||
if(entity.waiting.size > 0){ //accepting takes priority over shooting
|
||||
Tile waiter = entity.waiting.first();
|
||||
|
||||
entity.rotation = Mathf.slerpDelta(entity.rotation, tile.angleTo(waiter), rotateSpeed);
|
||||
}else if(tile.entity.items.total() >= minDistribute &&
|
||||
linkValid(tile) &&
|
||||
tile.entity.power.satisfaction >= powerPercentageUsed &&
|
||||
link.block().itemCapacity - link.entity.items.total() >= minDistribute && entity.reload <= 0.0001f){
|
||||
|
||||
MassDriverEntity other = link.entity();
|
||||
other.waiting.add(tile);
|
||||
|
||||
float target = tile.angleTo(link);
|
||||
|
||||
entity.rotation = Mathf.slerpDelta(entity.rotation, target, rotateSpeed);
|
||||
|
||||
if(Angles.near(entity.rotation, target, 1f) &&
|
||||
Angles.near(other.rotation, target + 180f, 1f)){
|
||||
Call.onMassDriverFire(tile, link);
|
||||
}
|
||||
//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;
|
||||
}
|
||||
}
|
||||
|
||||
entity.waiting.clear();
|
||||
//dump when idle or accepting
|
||||
if(entity.state == DriverState.idle || entity.state == DriverState.accepting){
|
||||
tryDump(tile);
|
||||
}
|
||||
|
||||
if(entity.state == DriverState.accepting){
|
||||
//if there's nothing shooting at this, bail
|
||||
if(entity.currentShooter() == null){
|
||||
entity.state = DriverState.idle;
|
||||
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();
|
||||
other.waitingShooters.add(tile);
|
||||
|
||||
//align to target location
|
||||
entity.rotation = Mathf.slerpDelta(entity.rotation, targetRotation, rotateSpeed);
|
||||
|
||||
//fire when it's the first in the queue and angles are ready.
|
||||
if(other.currentShooter() == tile &&
|
||||
other.state == DriverState.accepting &&
|
||||
Angles.near(entity.rotation, targetRotation, 2f) && Angles.near(other.rotation, targetRotation + 180f, 2f)){
|
||||
//actually fire
|
||||
fire(tile, link);
|
||||
//remove waiting shooters, it's done firing
|
||||
other.waitingShooters.remove(tile);
|
||||
//set both states to idle
|
||||
entity.state = DriverState.idle;
|
||||
other.state = DriverState.idle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -244,7 +229,71 @@ public class MassDriver extends Block{
|
||||
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){
|
||||
if(tile == null) return false;
|
||||
MassDriverEntity entity = tile.entity();
|
||||
if(entity == null || entity.link == -1) return false;
|
||||
Tile link = world.tile(entity.link);
|
||||
@@ -264,63 +313,39 @@ public class MassDriver extends Block{
|
||||
}
|
||||
|
||||
public class MassDriverEntity extends TileEntity{
|
||||
public int link = -1;
|
||||
public float rotation = 90;
|
||||
//set of tiles that currently want to distribute to this tile
|
||||
public ObjectSet<Tile> waiting = new ObjectSet<>();
|
||||
//whether this mass driver is waiting for a bullet to hit it and deliver items
|
||||
public boolean isRecieving;
|
||||
//whether this driver just recieved some items and is now unloading
|
||||
public boolean isUnloading = true;
|
||||
int link = -1;
|
||||
float rotation = 90;
|
||||
float reload = 0f;
|
||||
DriverState state = DriverState.idle;
|
||||
OrderedSet<Tile> waitingShooters = new OrderedSet<>();
|
||||
|
||||
public float reload = 0f;
|
||||
Tile currentShooter(){
|
||||
return waitingShooters.isEmpty() ? null : waitingShooters.first();
|
||||
}
|
||||
|
||||
public void handlePayload(Bullet 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;
|
||||
}
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
((MassDriver)block).handlePayload(this, bullet, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
stream.writeInt(link);
|
||||
stream.writeFloat(rotation);
|
||||
stream.writeByte((byte)state.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream) throws IOException{
|
||||
link = stream.readInt();
|
||||
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