mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-12-05 18:30:22 -08:00
Finalized launch pad mechanics
This commit is contained in:
parent
c6d82bec66
commit
7aee34bafa
19 changed files with 310 additions and 52 deletions
Binary file not shown.
|
After Width: | Height: | Size: 187 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
core/assets-raw/sprites/blocks/campaign/advanced-launch-pad.png
Normal file
BIN
core/assets-raw/sprites/blocks/campaign/advanced-launch-pad.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
BIN
core/assets-raw/sprites/blocks/campaign/landing-pad.png
Normal file
BIN
core/assets-raw/sprites/blocks/campaign/landing-pad.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
|
|
@ -737,6 +737,8 @@ addall = Add All
|
|||
launch.from = Launching From: [accent]{0}
|
||||
launch.capacity = Launching Item Capacity: [accent]{0}
|
||||
launch.destination = Destination: {0}
|
||||
landing.sources = Source Sectors: [accent]{0}[]
|
||||
landing.import = Max Total Import: {0}[accent]{1}[lightgray]/min
|
||||
configure.invalid = Amount must be a number between 0 and {0}.
|
||||
add = Add...
|
||||
guardian = Guardian
|
||||
|
|
@ -778,6 +780,7 @@ sectors.launch = Launch
|
|||
sectors.select = Select
|
||||
sectors.launchselect = Select Launch Destination
|
||||
sectors.nonelaunch = [lightgray]none (sun)
|
||||
sectors.redirect = Redirect Launch Pads
|
||||
sectors.rename = Rename Sector
|
||||
sectors.enemybase = [scarlet]Enemy Base
|
||||
sectors.vulnerable = [scarlet]Vulnerable
|
||||
|
|
@ -1748,7 +1751,10 @@ block.spectre.name = Spectre
|
|||
block.meltdown.name = Meltdown
|
||||
block.foreshadow.name = Foreshadow
|
||||
block.container.name = Container
|
||||
block.launch-pad.name = Launch Pad (Legacy)
|
||||
block.launch-pad.name = Launch Pad [lightgray](Legacy)
|
||||
block.advanced-launch-pad.name = Launch Pad
|
||||
block.landing-pad.name = Landing Pad
|
||||
|
||||
block.segment.name = Segment
|
||||
block.ground-factory.name = Ground Factory
|
||||
block.air-factory.name = Air Factory
|
||||
|
|
@ -2198,7 +2204,9 @@ block.vault.description = Stores a large amount of items of each type. Expands s
|
|||
block.container.description = Stores a small amount of items of each type. Expands storage when placed next to a core. Contents can be retrieved with an unloader.
|
||||
block.unloader.description = Unloads the selected item from nearby blocks.
|
||||
block.launch-pad.description = Launches batches of items to selected sectors.
|
||||
block.launch-pad.details = Sub-orbital system for point-to-point transportation of resources. Payload pods are fragile and incapable of surviving re-entry.
|
||||
block.advanced-launch-pad.description = Launches batches of items to selected sectors. Only accepts one item type at a time.
|
||||
block.advanced-launch-pad.details = Sub-orbital system for point-to-point transportation of resources.
|
||||
block.landing-pad.description = Receives items from launch pads in other sectors. Requires large amounts of water to protect against impacts of landings.
|
||||
block.duo.description = Fires alternating bullets at enemies.
|
||||
block.scatter.description = Fires clumps of lead, scrap or metaglass flak at enemy aircraft.
|
||||
block.scorch.description = Burns any ground enemies close to it. Highly effective at close range.
|
||||
|
|
|
|||
|
|
@ -595,3 +595,5 @@
|
|||
63087=scathe-missile-phase|unit-scathe-missile-phase-ui
|
||||
63086=scathe-missile-surge|unit-scathe-missile-surge-ui
|
||||
63085=scathe-missile-surge-split|unit-scathe-missile-surge-split-ui
|
||||
63084=advanced-launch-pad|block-advanced-launch-pad-ui
|
||||
63083=landing-pad|block-landing-pad-ui
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -6364,23 +6364,26 @@ public class Blocks{
|
|||
}};
|
||||
|
||||
advancedLaunchPad = new LaunchPad("advanced-launch-pad"){{
|
||||
requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.copper, 350, Items.silicon, 140, Items.lead, 200, Items.titanium, 150));
|
||||
requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.copper, 350, Items.silicon, 250, Items.lead, 300, Items.titanium, 200));
|
||||
size = 4;
|
||||
itemCapacity = 100;
|
||||
launchTime = 60f * 30;
|
||||
liquidCapacity = 40f;
|
||||
hasPower = true;
|
||||
drawLiquid = Liquids.oil;
|
||||
consumeLiquid(Liquids.oil, 9f/60f);
|
||||
consumePower(8f);
|
||||
}};
|
||||
|
||||
landingPad = new LandingPad("landing-pad"){{
|
||||
requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.copper, 350, Items.silicon, 140, Items.lead, 200, Items.titanium, 150));
|
||||
requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.copper, 300, Items.graphite, 200, Items.titanium, 150));
|
||||
size = 4;
|
||||
|
||||
itemCapacity = 100;
|
||||
|
||||
liquidCapacity = 4000f;
|
||||
consumeLiquidAmount = 2000f;
|
||||
coolingEffect = new RadialEffect(Fx.steamCoolSmoke, 4, 90f, 9.5f, 180f);
|
||||
liquidCapacity = 5000f;
|
||||
consumeLiquidAmount = 2500f;
|
||||
}};
|
||||
|
||||
interplanetaryAccelerator = new Accelerator("interplanetary-accelerator"){{
|
||||
|
|
|
|||
|
|
@ -1474,6 +1474,12 @@ public class Fx{
|
|||
Lines.circle(e.x, e.y, e.fin() * (e.rotation + 50f));
|
||||
}),
|
||||
|
||||
podLandShockwave = new Effect(12f, 80f, e -> {
|
||||
color(Pal.accent);
|
||||
stroke(e.fout() * 2f + 0.2f);
|
||||
Lines.circle(e.x, e.y, e.fin() * 26f);
|
||||
}),
|
||||
|
||||
explosion = new Effect(30, e -> {
|
||||
e.scaled(7, i -> {
|
||||
stroke(3f * i.fout());
|
||||
|
|
@ -1624,6 +1630,15 @@ public class Fx{
|
|||
});
|
||||
}),
|
||||
|
||||
steamCoolSmoke = new Effect(35f, e -> {
|
||||
color(Pal.water, Color.lightGray, e.fin(Interp.pow2Out));
|
||||
alpha(e.fout(Interp.pow3Out));
|
||||
|
||||
randLenVectors(e.id, 4, e.finpow() * 7f, e.rotation, 30f, (x, y) -> {
|
||||
Fill.circle(e.x + x, e.y + y, Math.max(e.fout(), Math.min(1f, e.fin() * 8f)) * 2.8f);
|
||||
});
|
||||
}),
|
||||
|
||||
smokePuff = new Effect(30, e -> {
|
||||
color(e.color);
|
||||
|
||||
|
|
@ -2574,6 +2589,13 @@ public class Fx{
|
|||
Fill.circle(e.x + Tmp.v1.x, e.y + Tmp.v1.y, 8f * rand.random(0.6f, 1f) * e.fout(0.2f));
|
||||
}).layer(Layer.groundUnit + 1f),
|
||||
|
||||
podLandDust = new Effect(70f, e -> {
|
||||
color(e.color, e.fout(0.1f));
|
||||
rand.setSeed(e.id);
|
||||
Tmp.v1.trns(e.rotation, e.finpow() * 35f * rand.random(0.2f, 1f));
|
||||
Fill.circle(e.x + Tmp.v1.x, e.y + Tmp.v1.y, 5f * rand.random(0.6f, 1f) * e.fout(0.2f));
|
||||
}).layer(Layer.groundUnit + 1f),
|
||||
|
||||
unitShieldBreak = new Effect(35, e -> {
|
||||
if(!(e.data instanceof Unit unit)) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,10 @@ public class SerpuloTechTree{
|
|||
node(junction, () -> {
|
||||
node(router, () -> {
|
||||
node(advancedLaunchPad, Seq.with(new SectorComplete(extractionOutpost)), () -> {
|
||||
node(interplanetaryAccelerator, Seq.with(new SectorComplete(planetaryTerminal)), () -> {
|
||||
node(landingPad, () -> {
|
||||
node(interplanetaryAccelerator, Seq.with(new SectorComplete(planetaryTerminal)), () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import mindustry.entities.*;
|
|||
/** Renders one particle effect repeatedly at specified angle intervals. */
|
||||
public class RadialEffect extends Effect{
|
||||
public Effect effect = Fx.none;
|
||||
public float rotationSpacing = 90f, rotationOffset = 0f;
|
||||
public float rotationSpacing = 90f, rotationOffset = 0f, effectRotationOffset = 0f;
|
||||
public float lengthOffset = 0f;
|
||||
public int amount = 4;
|
||||
|
||||
|
|
@ -16,14 +16,19 @@ public class RadialEffect extends Effect{
|
|||
clip = 100f;
|
||||
}
|
||||
|
||||
public RadialEffect(Effect effect, int amount, float spacing, float lengthOffset){
|
||||
public RadialEffect(Effect effect, int amount, float spacing, float lengthOffset, float effectRotationOffset){
|
||||
this();
|
||||
this.amount = amount;
|
||||
this.effect = effect;
|
||||
this.effectRotationOffset = effectRotationOffset;
|
||||
this.rotationSpacing = spacing;
|
||||
this.lengthOffset = lengthOffset;
|
||||
}
|
||||
|
||||
public RadialEffect(Effect effect, int amount, float spacing, float lengthOffset){
|
||||
this(effect, amount, spacing, lengthOffset, 0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(float x, float y, float rotation, Color color, Object data){
|
||||
if(!shouldCreate()) return;
|
||||
|
|
@ -31,7 +36,7 @@ public class RadialEffect extends Effect{
|
|||
rotation += rotationOffset;
|
||||
|
||||
for(int i = 0; i < amount; i++){
|
||||
effect.create(x + Angles.trnsx(rotation, lengthOffset), y + Angles.trnsy(rotation, lengthOffset), rotation, color, data);
|
||||
effect.create(x + Angles.trnsx(rotation, lengthOffset), y + Angles.trnsy(rotation, lengthOffset), rotation + effectRotationOffset, color, data);
|
||||
rotation += rotationSpacing;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ public class SectorInfo{
|
|||
public ObjectMap<Item, ExportStat> rawProduction = new ObjectMap<>();
|
||||
/** Export statistics. */
|
||||
public ObjectMap<Item, ExportStat> export = new ObjectMap<>();
|
||||
//TODO: there is an obvious exploit with launch pad redirection here; pads can be redirected after leaving a sector, which doesn't update calculations.
|
||||
/** Import statistics, based on what launch pads are actually receiving. TODO: this is not actually used or displayed anywhere (yet) */
|
||||
public ObjectMap<Item, ExportStat> imports = new ObjectMap<>();
|
||||
/** Items stored in all cores. */
|
||||
public ItemSeq items = new ItemSeq();
|
||||
/** The best available core type. */
|
||||
|
|
@ -118,10 +121,20 @@ public class SectorInfo{
|
|||
export.get(item, ExportStat::new).counter += amount;
|
||||
}
|
||||
|
||||
/** Updates import statistics. */
|
||||
public void handleItemImport(Item item, int amount){
|
||||
imports.get(item, ExportStat::new).counter += amount;
|
||||
}
|
||||
|
||||
public float getExport(Item item){
|
||||
return export.get(item, ExportStat::new).mean;
|
||||
}
|
||||
|
||||
public boolean hasExport(Item item){
|
||||
var exp = export.get(item);
|
||||
return exp != null && exp.mean > 0f;
|
||||
}
|
||||
|
||||
public void refreshImportRates(Planet planet){
|
||||
if(importRateCache == null || importRateCache.length != content.items().size){
|
||||
importRateCache = new float[content.items().size];
|
||||
|
|
@ -140,7 +153,7 @@ public class SectorInfo{
|
|||
return importRateCache;
|
||||
}
|
||||
|
||||
/** @return the import rate of an item as item/second. */
|
||||
/** @return the import rate of an item as item/second. This is the *raw* max import rate, not what landing pads are actually using. */
|
||||
public float getImportRate(Planet planet, Item item){
|
||||
return getImportRates(planet)[item.id];
|
||||
}
|
||||
|
|
@ -239,19 +252,8 @@ public class SectorInfo{
|
|||
//refresh throughput
|
||||
if(time.get(refreshPeriod)){
|
||||
|
||||
//refresh export
|
||||
export.each((item, stat) -> {
|
||||
//initialize stat after loading
|
||||
if(!stat.loaded){
|
||||
stat.means.fill(stat.mean);
|
||||
stat.loaded = true;
|
||||
}
|
||||
|
||||
//add counter, subtract how many items were taken from the core during this time
|
||||
stat.means.add(Math.max(stat.counter, 0));
|
||||
stat.counter = 0;
|
||||
stat.mean = stat.means.rawMean();
|
||||
});
|
||||
updateStats(export);
|
||||
updateStats(imports);
|
||||
|
||||
if(coreDeltas == null) coreDeltas = new int[content.items().size];
|
||||
if(productionDeltas == null) productionDeltas = new int[content.items().size];
|
||||
|
|
@ -268,6 +270,11 @@ public class SectorInfo{
|
|||
//export can, at most, be the raw items being produced from factories + the items being taken from the core
|
||||
export.get(item).mean = Math.min(export.get(item).mean, rawProduction.get(item).mean + Math.max(-production.get(item).mean, 0));
|
||||
}
|
||||
|
||||
if(imports.containsKey(item)){
|
||||
//import can't exceed max import rate
|
||||
imports.get(item).mean = Math.min(imports.get(item).mean, getImportRate(state.getPlanet(), item));
|
||||
}
|
||||
}
|
||||
|
||||
Arrays.fill(coreDeltas, 0);
|
||||
|
|
@ -275,6 +282,20 @@ public class SectorInfo{
|
|||
}
|
||||
}
|
||||
|
||||
void updateStats(ObjectMap<Item, ExportStat> map){
|
||||
map.each((item, stat) -> {
|
||||
//initialize stat after loading
|
||||
if(!stat.loaded){
|
||||
stat.means.fill(stat.mean);
|
||||
stat.loaded = true;
|
||||
}
|
||||
|
||||
stat.means.add(Math.max(stat.counter, 0));
|
||||
stat.counter = 0;
|
||||
stat.mean = stat.means.rawMean();
|
||||
});
|
||||
}
|
||||
|
||||
void updateDelta(Item item, ObjectMap<Item, ExportStat> map, int[] deltas){
|
||||
ExportStat stat = map.get(item, ExportStat::new);
|
||||
if(!stat.loaded){
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import arc.graphics.*;
|
|||
public class Pal{
|
||||
public static Color
|
||||
|
||||
water = Color.valueOf("596ab8"),
|
||||
darkOutline = Color.valueOf("2d2f39"),
|
||||
thoriumPink = Color.valueOf("f9a3c7"),
|
||||
coalBlack = Color.valueOf("272727"),
|
||||
|
|
@ -107,7 +108,7 @@ public class Pal{
|
|||
redderDust = Color.valueOf("ff7b69"),
|
||||
|
||||
plasticSmoke = Color.valueOf("f1e479"),
|
||||
|
||||
|
||||
adminChat = Color.valueOf("ff4000"),
|
||||
|
||||
neoplasmOutline = Color.valueOf("2e191d"),
|
||||
|
|
|
|||
|
|
@ -962,7 +962,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||
|
||||
//import
|
||||
if(sector.hasBase()){
|
||||
displayItems(c, 1f, sector.info.importStats(sector.planet), "@sectors.import", t -> {
|
||||
displayItems(c, 1f, sector.info.imports, "@sectors.import", t -> {
|
||||
sector.info.eachImport(sector.planet, other -> {
|
||||
String ic = other.iconChar();
|
||||
t.add(Iconc.rightOpen + " " + (ic == null || ic.isEmpty() ? "" : ic + " ") + other.name()).padLeft(10f).row();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package mindustry.world.blocks.campaign;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
|
|
@ -8,6 +10,7 @@ import arc.util.*;
|
|||
import arc.util.io.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
|
|
@ -16,6 +19,7 @@ import mindustry.type.*;
|
|||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.liquid.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
|
|
@ -32,10 +36,19 @@ public class LandingPad extends Block{
|
|||
});
|
||||
}
|
||||
|
||||
public float cooldownTime = 12f;
|
||||
public @Load(value = "@-pod", fallback = "advanced-launch-pad-pod") TextureRegion podRegion;
|
||||
public float arrivalDuration = 150f;
|
||||
public float cooldownTime = 180f;
|
||||
public float consumeLiquidAmount = 100f;
|
||||
public Liquid consumeLiquid = Liquids.water;
|
||||
|
||||
public Effect landEffect = Fx.podLandShockwave;
|
||||
public Effect coolingEffect = Fx.none;
|
||||
public float coolingEffectChance = 0.2f;
|
||||
|
||||
public float liquidPad = 2f;
|
||||
public Color bottomColor = Pal.darkerMetal;
|
||||
|
||||
public LandingPad(String name){
|
||||
super(name);
|
||||
|
||||
|
|
@ -45,6 +58,8 @@ public class LandingPad extends Block{
|
|||
update = true;
|
||||
configurable = true;
|
||||
acceptsItems = false;
|
||||
emitLight = true;
|
||||
lightRadius = 90f;
|
||||
|
||||
config(Item.class, (LandingPadBuild build, Item item) -> build.config = item);
|
||||
configClear((LandingPadBuild build) -> build.config = null);
|
||||
|
|
@ -97,21 +112,19 @@ public class LandingPad extends Block{
|
|||
public @Nullable Item config;
|
||||
//priority collisions are possible, but should be extremely rare
|
||||
public int priority = Mathf.rand.nextInt();
|
||||
public float cooldown = 0f;
|
||||
public float cooldown = 0f, landParticleTimer;
|
||||
|
||||
public float arrivingTimer = 0f;
|
||||
public @Nullable Item arriving;
|
||||
public float liquidRemoved;
|
||||
|
||||
public void handleLanding(){
|
||||
if(!state.isCampaign() || config == null) return;
|
||||
//TODO animation, etc
|
||||
|
||||
cooldown = 1f;
|
||||
items.set(config, itemCapacity);
|
||||
liquids.remove(consumeLiquid, consumeLiquidAmount);
|
||||
for(int i = 0; i < 10; i++){
|
||||
Fx.steam.at(this);
|
||||
}
|
||||
//TODO this is a temporary effect
|
||||
Fx.shockwave.at(this);
|
||||
arriving = config;
|
||||
arrivingTimer = 0f;
|
||||
liquidRemoved = 0f;
|
||||
|
||||
state.rules.sector.info.importCooldownTimers.put(config, 0f);
|
||||
}
|
||||
|
|
@ -128,6 +141,9 @@ public class LandingPad extends Block{
|
|||
float framesBetweenArrival = itemCapacity / importedPerFrame;
|
||||
|
||||
state.rules.sector.info.importCooldownTimers.increment(item, 0f, 1f / framesBetweenArrival * Time.delta);
|
||||
}else{
|
||||
//nothing is being imported, so reset the timer
|
||||
state.rules.sector.info.importCooldownTimers.put(item, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,32 +156,144 @@ public class LandingPad extends Block{
|
|||
|
||||
Call.landingPadLanded(first.tile);
|
||||
|
||||
|
||||
//swap priorities, moving this block to the end of the list (if there is only one block waiting, this does nothing)
|
||||
var tmp = first.priority;
|
||||
first.priority = head.priority;
|
||||
head.priority = tmp;
|
||||
|
||||
|
||||
pads.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
if(consumeLiquid != null){
|
||||
Draw.color(bottomColor);
|
||||
Fill.square(x, y, size * tilesize/2f - liquidPad);
|
||||
Draw.color();
|
||||
LiquidBlock.drawTiledFrames(block.size, x, y, liquidPad, liquidPad, liquidPad, liquidPad, consumeLiquid, liquids.get(consumeLiquid) / liquidCapacity);
|
||||
}
|
||||
|
||||
super.draw();
|
||||
|
||||
if(arriving != null){
|
||||
float fin = Mathf.clamp(arrivingTimer), fout = 1f - fin;
|
||||
float alpha = Interp.pow5Out.apply(fin);
|
||||
float scale = (1f - alpha) * 1.3f + 1f;
|
||||
float
|
||||
cx = x,
|
||||
cy = y + Interp.pow4In.apply(fout) * (100f + Mathf.randomSeedRange(id() + 2, 30f));
|
||||
|
||||
float rotation = fout * (90f + Mathf.randomSeedRange(id(), 50f));
|
||||
|
||||
Draw.z(Layer.effect + 0.001f);
|
||||
|
||||
Draw.color(Pal.engine);
|
||||
|
||||
float rad = 0.15f + Interp.pow5Out.apply(Mathf.slope(fin));
|
||||
|
||||
Fill.light(cx, cy, 10, 25f * (rad + scale-1f), Tmp.c2.set(Pal.engine).a(alpha), Tmp.c1.set(Pal.engine).a(0f));
|
||||
|
||||
Draw.alpha(alpha);
|
||||
for(int i = 0; i < 4; i++){
|
||||
Drawf.tri(cx, cy, 6f, 40f * (rad + scale-1f), i * 90f + rotation);
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
|
||||
Draw.z(Layer.weather - 1);
|
||||
|
||||
scale *= podRegion.scl();
|
||||
float rw = podRegion.width * scale, rh = podRegion.height * scale;
|
||||
|
||||
Draw.alpha(alpha);
|
||||
Drawf.shadow(cx, cy, size * tilesize, fin);
|
||||
Draw.rect(podRegion, cx, cy, rw, rh, rotation);
|
||||
|
||||
Tmp.v1.trns(225f, Interp.pow3In.apply(fout) * 250f);
|
||||
|
||||
Draw.z(Layer.flyingUnit + 1);
|
||||
Draw.color(0, 0, 0, 0.22f * alpha);
|
||||
|
||||
Draw.rect(podRegion, cx + Tmp.v1.x, cy + Tmp.v1.y, rw, rh, rotation);
|
||||
|
||||
}else if(cooldown > 0f){
|
||||
|
||||
Drawf.shadow(x, y, size * tilesize, cooldown);
|
||||
Draw.alpha(cooldown);
|
||||
Draw.mixcol(Pal.accent, 1f - cooldown);
|
||||
Draw.rect(podRegion, x, y);
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLight(){
|
||||
Drawf.light(x, y, lightRadius, Pal.accent, Mathf.clamp(Math.max(cooldown, arrivingTimer * 1.5f)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
updateTimers();
|
||||
|
||||
if(arriving != null){
|
||||
if(!headless){ //pod particles
|
||||
float fin = arrivingTimer;
|
||||
float tsize = Interp.pow5Out.apply(fin);
|
||||
|
||||
landParticleTimer += tsize * Time.delta / 2f;
|
||||
if(landParticleTimer >= 1f){
|
||||
tile.getLinkedTiles(t -> {
|
||||
if(Mathf.chance(0.1f)){
|
||||
Fx.podLandDust.at(t.worldx(), t.worldy(), angleTo(t.worldx(), t.worldy()) + Mathf.range(30f), Tmp.c1.set(t.floor().mapColor).mul(1.5f + Mathf.range(0.15f)));
|
||||
}
|
||||
});
|
||||
|
||||
landParticleTimer = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
arrivingTimer += Time.delta / arrivalDuration;
|
||||
|
||||
float toRemove = Math.min(consumeLiquidAmount / arrivalDuration * Time.delta, consumeLiquidAmount - liquidRemoved);
|
||||
liquidRemoved += toRemove;
|
||||
|
||||
liquids.remove(consumeLiquid, toRemove);
|
||||
|
||||
if(Mathf.chanceDelta(coolingEffectChance * Interp.pow5Out.apply(arrivingTimer))){
|
||||
coolingEffect.at(this);
|
||||
}
|
||||
|
||||
if(arrivingTimer >= 1f){
|
||||
//remove any leftovers to make sure it's precise
|
||||
liquids.remove(consumeLiquid, consumeLiquidAmount - liquidRemoved);
|
||||
|
||||
landEffect.at(this);
|
||||
Effect.shake(3f, 3f, this);
|
||||
|
||||
items.set(arriving, itemCapacity);
|
||||
state.getSector().info.handleItemImport(arriving, itemCapacity);
|
||||
|
||||
arriving = null;
|
||||
arrivingTimer = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
if(items.total() > 0){
|
||||
dumpAccumulate(config == null || items.get(config) != items.total() ? null : config);
|
||||
}
|
||||
|
||||
if(arriving == null){
|
||||
cooldown -= delta() / cooldownTime;
|
||||
cooldown = Mathf.clamp(cooldown);
|
||||
}
|
||||
|
||||
if(config != null && state.isCampaign()){
|
||||
|
||||
cooldown -= delta() / cooldownTime;
|
||||
|
||||
if(cooldown <= 0f && efficiency > 0f && items.total() == 0 && state.rules.sector.info.importCooldownTimers.get(config, 0f) >= 1f){
|
||||
if(cooldown <= 0f && efficiency > 0f && items.total() == 0 && state.rules.sector.info.getImportRate(state.getPlanet(), config) > 0f && state.rules.sector.info.importCooldownTimers.get(config, 0f) >= 1f){
|
||||
|
||||
//queue landing for next frame
|
||||
waiting.get(config, Seq::new).add(this);
|
||||
|
|
@ -184,6 +312,58 @@ public class LandingPad extends Block{
|
|||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ItemSelection.buildTable(LandingPad.this, table, content.items(), () -> config, this::configure, selectionRows, selectionColumns);
|
||||
|
||||
if(!net.client()){
|
||||
table.row();
|
||||
|
||||
table.table(t -> {
|
||||
t.background(Styles.black6);
|
||||
|
||||
t.button(Icon.downOpen, Styles.clearNonei, 40f, () -> {
|
||||
if(config != null && state.isCampaign()){
|
||||
for(Sector sector : state.getPlanet().sectors){
|
||||
if(sector.hasBase() && sector != state.getSector() && sector.info.destination != state.getSector() && sector.info.hasExport(config)){
|
||||
sector.info.destination = state.getSector();
|
||||
sector.saveInfo();
|
||||
}
|
||||
}
|
||||
state.getSector().info.refreshImportRates(state.getPlanet());
|
||||
}
|
||||
}).disabled(b -> config == null || !state.isCampaign() || (!state.getPlanet().sectors.contains(s -> s.hasBase() && s.info.hasExport(config) && s.info.destination != state.getSector())))
|
||||
.tooltip("@sectors.redirect").get();
|
||||
}).fillX().left();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(Table table){
|
||||
super.display(table);
|
||||
|
||||
if(!state.isCampaign() || net.client() || team != player.team()) return;
|
||||
|
||||
table.row();
|
||||
table.label(() -> {
|
||||
if(config == null || !state.isCampaign()){
|
||||
return "";
|
||||
}
|
||||
int sources = 0;
|
||||
float perSecond = 0f;
|
||||
for(var s : state.getPlanet().sectors){
|
||||
if(s != state.getSector() && s.hasBase() && s.info.destination == state.getSector()){
|
||||
float amount = s.info.getExport(config);
|
||||
if(amount > 0){
|
||||
sources ++;
|
||||
perSecond += s.info.getExport(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String str = Core.bundle.format("landing.sources", sources == 0 ? Core.bundle.get("none") : sources);
|
||||
if(perSecond > 0){
|
||||
str += "\n" + Core.bundle.format("landing.import", config.emoji(), (int)(perSecond * 60f));
|
||||
}
|
||||
return str;
|
||||
}).pad(4).wrap().width(200f).left();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import mindustry.logic.*;
|
|||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.liquid.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
|
@ -36,6 +37,13 @@ public class LaunchPad extends Block{
|
|||
public Color lightColor = Color.valueOf("eab678");
|
||||
public boolean acceptMultipleItems = false;
|
||||
|
||||
public float lightStep = 1f;
|
||||
public int lightSteps = 3;
|
||||
|
||||
public float liquidPad = 2f;
|
||||
public @Nullable Liquid drawLiquid;
|
||||
public Color bottomColor = Pal.darkerMetal;
|
||||
|
||||
public LaunchPad(String name){
|
||||
super(name);
|
||||
hasItems = true;
|
||||
|
|
@ -87,6 +95,13 @@ public class LaunchPad extends Block{
|
|||
|
||||
@Override
|
||||
public void draw(){
|
||||
if(hasLiquids && drawLiquid != null){
|
||||
Draw.color(bottomColor);
|
||||
Fill.square(x, y, size * tilesize/2f - liquidPad);
|
||||
Draw.color();
|
||||
LiquidBlock.drawTiledFrames(block.size, x, y, liquidPad, liquidPad, liquidPad, liquidPad, drawLiquid, liquids.get(drawLiquid) / liquidCapacity);
|
||||
}
|
||||
|
||||
super.draw();
|
||||
|
||||
if(!state.isCampaign()) return;
|
||||
|
|
@ -94,13 +109,11 @@ public class LaunchPad extends Block{
|
|||
if(lightRegion.found()){
|
||||
Draw.color(lightColor);
|
||||
float progress = Math.min((float)items.total() / itemCapacity, launchCounter / launchTime);
|
||||
int steps = 3;
|
||||
float step = 1f;
|
||||
|
||||
for(int i = 0; i < 4; i++){
|
||||
for(int j = 0; j < steps; j++){
|
||||
float alpha = Mathf.curve(progress, (float)j / steps, (j+1f) / steps);
|
||||
float offset = -(j - 1f) * step;
|
||||
for(int j = 0; j < lightSteps; j++){
|
||||
float alpha = Mathf.curve(progress, (float)j / lightSteps, (j+1f) / lightSteps);
|
||||
float offset = -(j - 1f) * lightStep;
|
||||
|
||||
Draw.color(Pal.metalGrayDark, lightColor, alpha);
|
||||
Draw.rect(lightRegion, x + Geometry.d8edge(i).x * offset, y + Geometry.d8edge(i).y * offset, i * 90);
|
||||
|
|
@ -110,6 +123,7 @@ public class LaunchPad extends Block{
|
|||
Draw.reset();
|
||||
}
|
||||
|
||||
Drawf.shadow(x, y, size * tilesize);
|
||||
Draw.rect(podRegion, x, y);
|
||||
|
||||
Draw.reset();
|
||||
|
|
@ -169,7 +183,11 @@ public class LaunchPad extends Block{
|
|||
table.button(Icon.upOpen, Styles.cleari, () -> {
|
||||
ui.planet.showSelect(state.rules.sector, other -> {
|
||||
if(state.isCampaign() && other.planet == state.rules.sector.planet){
|
||||
var prev = state.rules.sector.info.destination;
|
||||
state.rules.sector.info.destination = other;
|
||||
if(prev != null){
|
||||
prev.info.refreshImportRates(state.getPlanet());
|
||||
}
|
||||
}
|
||||
});
|
||||
deselect();
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ public class StatValues{
|
|||
t.add(Strings.autoFixed(amount, 2)).style(Styles.outlineLabel);
|
||||
add(t);
|
||||
}
|
||||
}}).size(iconMed).padRight(3 + (amount != 0 && Strings.autoFixed(amount, 2).length() > 2 ? 8 : 0)).with(s -> withTooltip(s, liquid, false));
|
||||
}}).size(iconMed).padRight(3 + (amount != 0 ? (Strings.autoFixed(amount, 2).length() - 1) * 10 : 0)).with(s -> withTooltip(s, liquid, false));
|
||||
|
||||
if(perSecond && amount != 0){
|
||||
t.add(StatUnit.perSecond.localized()).padLeft(2).padRight(5).color(Color.lightGray).style(Styles.outlineLabel);
|
||||
|
|
|
|||
|
|
@ -26,4 +26,4 @@ org.gradle.caching=true
|
|||
org.gradle.internal.http.socketTimeout=100000
|
||||
org.gradle.internal.http.connectionTimeout=100000
|
||||
android.enableR8.fullMode=false
|
||||
archash=99a42db331
|
||||
archash=c8004178c4
|
||||
|
|
|
|||
|
|
@ -15,10 +15,6 @@ if(new File(settingsDir, 'local.properties').exists()){
|
|||
if(System.getenv("JITPACK") == "true") hasSdk = false
|
||||
|
||||
if(hasSdk){
|
||||
//hack: pretend the Android module doesn't exist when imported through IntelliJ
|
||||
//why? because IntelliJ chokes on the new version of the Android plugin
|
||||
|
||||
//UPDATE: it no longer chokes on AGP with the latest version, but instead gives a completely different error. brilliant.
|
||||
include 'android'
|
||||
}else{
|
||||
println("No Android SDK found. Skipping Android module.")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue