mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-02-25 22:17:59 +07:00
Fixed disappearing blocks / Unit tech tree entries
This commit is contained in:
parent
bf22b601f7
commit
6bbbd5ab01
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)), () -> {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user