Fixed disappearing blocks / Unit tech tree entries

This commit is contained in:
Anuken 2022-02-07 10:58:22 -05:00
parent bf22b601f7
commit 6bbbd5ab01
11 changed files with 149 additions and 21 deletions

View File

@ -837,6 +837,7 @@ bar.heatamount = Heat: {0}
bar.heatpercent = Heat: {0} ({1}%)
bar.power = Power
bar.progress = Build Progress
bar.loadprogress = Progress
bar.launchcooldown = Launch Cooldown
bar.input = Input
bar.output = Output

View File

@ -3470,8 +3470,8 @@ public class Blocks{
tankAssembler = new UnitAssembler("tank-assembler"){{
requirements(Category.units, with(Items.graphite, 600, Items.beryllium, 600, Items.oxide, 200, Items.tungsten, 500));
size = 5;
plans.add(new AssemblerUnitPlan(UnitTypes.vanquish, 60f * 10f, BlockStack.list(Blocks.tungstenWallLarge, 5, Blocks.duct, 2)));
consumes.power(2f);
plans.add(new AssemblerUnitPlan(UnitTypes.vanquish, 60f * 10f, BlockStack.list(Blocks.tungstenWallLarge, 6, Blocks.duct, 14, Blocks.cliffCrusher, 10)));
consumes.power(3f);
areaSize = 13;
//TODO unit production is rarely continuous, can be double
@ -3480,7 +3480,7 @@ public class Blocks{
//TODO requirements
shipAssembler = new UnitAssembler("ship-assembler"){{
requirements(Category.units, with(Items.graphite, 600, Items.beryllium, 600, Items.oxide, 200, Items.tungsten, 500));
requirements(Category.units, with(Items.beryllium, 700, Items.oxide, 150, Items.tungsten, 500, Items.silicon, 800));
size = 5;
plans.add(new AssemblerUnitPlan(UnitTypes.quell, 60f * 4f, BlockStack.list(Blocks.tungstenWallLarge, 5, Blocks.plasmaBore, 2)));
consumes.power(2f);

View File

@ -21,6 +21,9 @@ public class ErekirTechTree{
costMultipliers.put(Items.thorium, 9);
costMultipliers.put(Items.graphite, 9);
//TODO remove
Objective tmpNever = new Research(Items.fissileMatter);
//TODO gate behind capture
Planets.erekir.techTree = nodeRoot("erekir", coreBastion, true, () -> {
@ -202,6 +205,30 @@ public class ErekirTechTree{
});
});
node(tankAssembler, Seq.with(new OnSector(four), new Research(constructor), new Research(slagCentrifuge), new Research(Liquids.gallium)), () -> {
node(UnitTypes.vanquish, () -> {
node(UnitTypes.conquer, Seq.with(tmpNever), () -> {
});
});
node(shipAssembler, Seq.with(tmpNever), () -> {
node(UnitTypes.quell, () -> {
node(UnitTypes.disrupt, Seq.with(tmpNever), () -> {
});
});
node(mechAssembler, () -> {
node(UnitTypes.bulwark, () -> {
node(UnitTypes.krepost, Seq.with(tmpNever), () -> {
});
});
});
});
});
//TODO more sectors
node(onset, () -> {
node(aware, Seq.with(new SectorComplete(onset), new Research(ductRouter)), () -> {

View File

@ -2737,7 +2737,7 @@ public class UnitTypes{
velocityRnd = 0.33f;
heatColor = Color.red;
bullet = new MissileBulletType(4.2f, 34){{
bullet = new MissileBulletType(4.2f, 40){{
homingPower = 0.2f;
weaveMag = 4;
weaveScale = 4;
@ -2745,7 +2745,7 @@ public class UnitTypes{
//TODO better
shootEffect = Fx.shootBig2;
smokeEffect = Fx.shootSmokeTitan;
splashDamage = 40f;
splashDamage = 50f;
splashDamageRadius = 30f;
frontColor = Color.white;
hitSound = Sounds.none;
@ -2918,7 +2918,7 @@ public class UnitTypes{
y = 5 / 4f;
rotate = true;
rotateSpeed = 2f;
reload = 70f;
reload = 60f;
layerOffset = -0.001f;
recoil = 1f;
rotationLimit = 60f;

View File

@ -32,7 +32,7 @@ public class EntityGroup<T extends Entityc> implements Iterable<T>{
/** Makes sure the next ID counter is higher than this number, so future entities cannot possibly use this ID. */
public static void checkNextId(int id){
lastId = id + 1;
lastId = Math.max(lastId, id + 1);
}
public EntityGroup(Class<T> type, boolean spatial, boolean mapping){
@ -47,6 +47,18 @@ public class EntityGroup<T extends Entityc> implements Iterable<T>{
}
}
/** @return entities with colliding IDs, or an empty array. */
public Seq<T> checkIDCollisions(){
Seq<T> out = new Seq<>();
IntSet ints = new IntSet();
each(u -> {
if(!ints.add(u.id())){
out.add(u);
}
});
return out;
}
public void sort(Comparator<? super T> comp){
array.sort(comp);
}

View File

@ -173,6 +173,22 @@ public class Units{
return boolResult;
}
public static boolean anyEntities(float x, float y, float width, float height, Boolf<Unit> check){
boolResult = false;
nearby(x, y, width, height, unit -> {
if(boolResult) return;
if(check.get(unit)){
unit.hitboxTile(hitrect);
if(hitrect.overlaps(aeX, aeY, aeW, aeH)){
boolResult = true;
}
}
});
return boolResult;
}
/** Returns the nearest damaged tile. */
public static Building findDamagedTile(Team team, float x, float y){
return indexer.getDamaged(team).min(b -> b.dst2(x, y));

View File

@ -682,6 +682,7 @@ public class UnitType extends UnlockableContent{
/** @return item requirements based on reconstructors or factories found; returns previous unit in array if provided */
public @Nullable ItemStack[] getRequirements(@Nullable UnitType[] prevReturn, @Nullable float[] timeReturn){
//find reconstructor
var rec = (Reconstructor)content.blocks().find(b -> b instanceof Reconstructor re && re.upgrades.contains(u -> u[1] == this));
if(rec != null && rec.consumes.has(ConsumeType.item) && rec.consumes.get(ConsumeType.item) instanceof ConsumeItems ci){
@ -693,6 +694,7 @@ public class UnitType extends UnlockableContent{
}
return ci.items;
}else{
//find a factory
var factory = (UnitFactory)content.blocks().find(u -> u instanceof UnitFactory uf && uf.plans.contains(p -> p.unit == this));
if(factory != null){
@ -701,6 +703,23 @@ public class UnitType extends UnlockableContent{
timeReturn[0] = plan.time;
}
return plan.requirements;
}else{
//find an assembler
var assembler = (UnitAssembler)content.blocks().find(u -> u instanceof UnitAssembler a && a.plans.contains(p -> p.unit == this));
if(assembler != null){
var plan = assembler.plans.find(p -> p.unit == this);
if(timeReturn != null){
timeReturn[0] = plan.time;
}
ItemSeq reqs = new ItemSeq();
for(var bstack : plan.requirements){
for(var stack : bstack.block.requirements){
reqs.add(stack.item, stack.amount * bstack.amount);
}
}
return reqs.toArray();
}
}
}
return null;

View File

@ -166,7 +166,7 @@ public class PayloadBlock extends Block{
if(rotate){
payRotation = Angles.moveToward(payRotation, rotate ? rotdeg() : 90f, payloadRotateSpeed * edelta());
}
payVector.approach(Vec2.ZERO, payloadSpeed * delta());
payVector.approach(Vec2.ZERO, payloadSpeed * edelta());
return hasArrived();
}

View File

@ -2,6 +2,7 @@ package mindustry.world.blocks.payloads;
import arc.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.entities.units.*;
@ -19,12 +20,17 @@ public class PayloadLoader extends PayloadBlock{
public int itemsLoaded = 8;
public float liquidsLoaded = 40f;
public int maxBlockSize = 3;
public float maxPowerConsumption = 40f;
//initialized in init(), do not touch
protected float basePowerUse = 0f;
public PayloadLoader(String name){
super(name);
hasItems = true;
hasLiquids = true;
hasPower = true;
itemCapacity = 100;
liquidCapacity = 100f;
update = true;
@ -47,7 +53,9 @@ public class PayloadLoader extends PayloadBlock{
public void setBars(){
super.setBars();
bars.add("progress", (PayloadLoaderBuild entity) -> new Bar(() -> Core.bundle.format("bar.items", entity.payload == null ? 0 : entity.payload.build.items.total()), () -> Pal.items, entity::fraction));
bars.add("progress", (PayloadLoaderBuild build) -> new Bar(() ->
Core.bundle.format(build.payload != null && build.payload.block().hasItems ? "bar.items" : "bar.loadprogress",
build.payload == null || !build.payload.block().hasItems ? 0 : build.payload.build.items.total()), () -> Pal.items, build::fraction));
}
@Override
@ -58,6 +66,14 @@ public class PayloadLoader extends PayloadBlock{
Draw.rect(topRegion, plan.drawx(), plan.drawy());
}
@Override
public void init(){
basePowerUse = consumes.hasPower() ? consumes.getPower().usage : 0f;
consumes.powerDynamic((PayloadLoaderBuild loader) -> loader.hasBattery() && !loader.exporting ? maxPowerConsumption + basePowerUse : basePowerUse);
super.init();
}
public class PayloadLoaderBuild extends PayloadBlockBuild<BuildPayload>{
public boolean exporting = false;
@ -65,9 +81,14 @@ public class PayloadLoader extends PayloadBlock{
public boolean acceptPayload(Building source, Payload payload){
return super.acceptPayload(source, payload) &&
payload.fits(maxBlockSize) &&
payload instanceof BuildPayload build &&
((build.build.block.hasItems && build.block().unloadable && build.block().itemCapacity >= 10 && build.block().size <= maxBlockSize) ||
build.build.block().hasLiquids && build.block().liquidCapacity >= 10f);
payload instanceof BuildPayload build && (
//item container
(build.build.block.hasItems && build.block().unloadable && build.block().itemCapacity >= 10 && build.block().size <= maxBlockSize) ||
//liquid container
(build.build.block().hasLiquids && build.block().liquidCapacity >= 10f) ||
//battery
(build.build.block.consumes.hasPower() && build.build.block.consumes.getPower().buffered)
);
}
@Override
@ -150,18 +171,45 @@ public class PayloadLoader extends PayloadBlock{
liquids.remove(liq, flow);
}
}
//load up power
if(hasBattery()){
//base power input that in raw units
float powerInput = power.status * (basePowerUse + maxPowerConsumption);
//how much is actually usable
float availableInput = Math.max(powerInput - basePowerUse, 0f);
//charge the battery
float cap = payload.block().consumes.getPower().capacity;
payload.build.power.status += availableInput / cap * Time.delta;
//export if full
if(payload.build.power.status >= 1f){
exporting = true;
payload.build.power.status = Mathf.clamp(payload.build.power.status);
}
}
}
}
public float fraction(){
return payload == null ? 0f : payload.build.items.total() / (float)payload.build.block.itemCapacity;
return payload == null ? 0f :
payload.build.items != null ? payload.build.items.total() / (float)payload.build.block.itemCapacity :
payload.build.liquids != null ? payload.build.liquids.currentAmount() / payload.block().liquidCapacity :
hasBattery() ? payload.build.power.status :
0f;
}
public boolean shouldExport(){
return payload != null && (
exporting ||
(payload.block().hasLiquids && liquids.currentAmount() >= 0.1f && payload.build.liquids.currentAmount() >= payload.block().liquidCapacity - 0.001f) ||
(payload.block().hasItems && items.any() && payload.block().separateItemCapacity && content.items().contains(i -> payload.build.items.get(i) >= payload.block().itemCapacity)));
(payload.block().hasItems && items.any() && payload.block().separateItemCapacity && content.items().contains(i -> payload.build.items.get(i) >= payload.block().itemCapacity)) ||
(hasBattery() && payload.build.power.status >= 0.999999999f));
}
public boolean hasBattery(){
return payload != null && payload.block().hasPower && payload.block().consumes.getPower().buffered;
}
@Override

View File

@ -30,7 +30,7 @@ public class Battery extends PowerDistributor{
@Override
public void draw(){
Draw.color(emptyLightColor, fullLightColor, power.status);
Fill.square(x, y, tilesize * size / 2f - 1);
Fill.square(x, y, (tilesize * size / 2f - 1) * Draw.xscl);
Draw.color();
Draw.rect(topRegion, x, y);

View File

@ -172,7 +172,7 @@ public class UnitAssembler extends PayloadBlock{
public Seq<Unit> units = new Seq<>();
public Seq<UnitAssemblerModuleBuild> modules = new Seq<>();
public BlockSeq blocks = new BlockSeq();
public float progress, warmup, droneWarmup, powerWarmup;
public float progress, warmup, droneWarmup, powerWarmup, sameTypeWarmup;
public float invalidWarmup = 0f;
public int currentTier = 0;
public boolean wasOccupied = false;
@ -318,10 +318,12 @@ public class UnitAssembler extends PayloadBlock{
ai.targetAngle = i * 90f + 45f + 180f;
}
wasOccupied = checkSolid(spawn);
wasOccupied = checkSolid(spawn, false);
boolean visualOccupied = checkSolid(spawn, true);
float eff = (units.count(u -> ((AssemblerAI)u.controller()).inPosition()) / (float)dronesCreated);
invalidWarmup = Mathf.lerpDelta(invalidWarmup, wasOccupied ? 1f : 0f, 0.1f);
sameTypeWarmup = Mathf.lerpDelta(sameTypeWarmup, wasOccupied && !visualOccupied ? 0f : 1f, 0.1f);
invalidWarmup = Mathf.lerpDelta(invalidWarmup, visualOccupied ? 1f : 0f, 0.1f);
var plan = plan();
@ -401,7 +403,7 @@ public class UnitAssembler extends PayloadBlock{
//draw unit silhouette
Draw.mixcol(Tmp.c1.set(Pal.accent).lerp(Pal.remove, invalidWarmup), 1f);
Draw.alpha(powerWarmup);
Draw.alpha(Math.min(powerWarmup, sameTypeWarmup));
Draw.rect(plan.unit.fullIcon, spawn.x, spawn.y);
//build beams do not draw when invalid
@ -442,9 +444,12 @@ public class UnitAssembler extends PayloadBlock{
Draw.reset();
}
public boolean checkSolid(Vec2 v){
public boolean checkSolid(Vec2 v, boolean same){
var output = unit();
return !output.flying && (collisions.overlapsTile(Tmp.r1.setCentered(v.x, v.y, output.hitSize), EntityCollisions::solid) || Units.anyEntities(v.x, v.y, output.hitSize * 1.4f));
//TODO CHECK TO MAKE SURE IT'S NOT THE SAME UNIT
float hsize = output.hitSize * 1.4f;
return !output.flying && (collisions.overlapsTile(Tmp.r1.setCentered(v.x, v.y, output.hitSize), EntityCollisions::solid) ||
(!same ? Units.anyEntities(v.x, v.y, hsize) : Units.anyEntities(v.x - hsize/2f, v.y - hsize/2f, hsize, hsize, u -> u.type != output && u.isGrounded())));
}
/** @return true if this block is ready to produce units, e.g. requirements met */