Loadout selection + custom loadout schematics

This commit is contained in:
Anuken
2020-06-27 23:04:38 -04:00
parent 63356e96ec
commit bd274f804a
11 changed files with 137 additions and 15 deletions

View File

@@ -36,6 +36,8 @@ public class Vars implements Loadable{
public static boolean loadLocales = true;
/** Whether the logger is loaded. */
public static boolean loadedLogger = false, loadedFileLogger = false;
/** Maximum extra padding around deployment schematics. */
public static final int maxLoadoutSchematicPad = 4;
/** Maximum schematic size.*/
public static final int maxSchematicSize = 32;
/** All schematic base64 starts with this string.*/

View File

@@ -6,14 +6,12 @@ import mindustry.game.*;
public class Loadouts implements ContentList{
public static Schematic
basicShard,
advancedShard,
basicFoundation,
basicNucleus;
@Override
public void load(){
basicShard = Schematics.readBase64("bXNjaAB4nD2K2wqAIBiD5ymibnoRn6YnEP1BwUMoBL19FuJ2sbFvUFgYZDaJsLeQrkinN9UJHImsNzlYE7WrIUastuSbnlKx2VJJt+8IQGGKdfO/8J5yrGJSMegLg+YUIA==");
advancedShard = Schematics.readBase64("bXNjaAB4nD2LjQqAIAyET7OMIOhFfJqeYMxBgSkYCL199gu33fFtB4tOwUTaBCP5QpHFzwtl32DahBeKK1NwPq8hoOcUixwpY+CUxe3XIwBbB/pa6tadVCUP02hgHvp5vZq/0b7pBHPYFOQ=");
basicFoundation = Schematics.readBase64("bXNjaAB4nD1OSQ6DMBBzFhVu8BG+0X8MQyoiJTNSukj8nlCi2Adbtg/GA4OBF8oB00rvyE/9ykafqOIw58A7SWRKy1ZiShhZ5RcOLZhYS1hefQ1gRIeptH9jq/qW2lvc1d2tgWsOfVX/tOwE86AYBA==");
basicNucleus = Schematics.readBase64("bXNjaAB4nD2MUQqAIBBEJy0s6qOLdJXuYNtCgikYBd2+LNmdj308hkGHtkId7M4YFns4mk/yfB4a48602eDI+mlNznu0FMPFd0wYKCaewl8F0EOueqM+yKSLVfJrNKWnSw/FZGzEGXFG9sy/px4gEBW1");
}

View File

@@ -43,7 +43,7 @@ import static mindustry.Vars.*;
*/
public class Control implements ApplicationListener, Loadable{
public Saves saves;
public mindustry.audio.MusicControl music;
public MusicControl music;
public Tutorial tutorial;
public InputHandler input;
@@ -265,6 +265,7 @@ public class Control implements ApplicationListener, Loadable{
state.rules.sector = sector;
//if there is no base, simulate a new game and place the right loadout at the spawn position
//TODO this is broken?
if(state.rules.defaultTeam.cores().isEmpty()){
//kill all friendly units, since they should be dead anwyay
@@ -276,7 +277,7 @@ public class Control implements ApplicationListener, Loadable{
Tile spawn = world.tile(sector.getSpawnPosition());
//TODO PLACE CORRECT LOADOUT
Schematics.placeLoadout(Loadouts.advancedShard, spawn.x, spawn.y);
Schematics.placeLoadout(universe.getLastLoadout(), spawn.x, spawn.y);
//set up camera/player locations
player.set(spawn.x * tilesize, spawn.y * tilesize);

View File

@@ -55,6 +55,7 @@ public class Schematics implements Loadable{
private Seq<Schematic> all = new Seq<>();
private OrderedMap<Schematic, FrameBuffer> previews = new OrderedMap<>();
private ObjectSet<Schematic> errored = new ObjectSet<>();
private ObjectMap<CoreBlock, Seq<Schematic>> loadouts = new ObjectMap<>();
private FrameBuffer shadowBuffer;
private Texture errorTexture;
private long lastClearTime;
@@ -85,6 +86,8 @@ public class Schematics implements Loadable{
public void load(){
all.clear();
loadLoadouts();
for(Fi file : schematicDirectory.list()){
loadFile(file);
}
@@ -109,6 +112,10 @@ public class Schematics implements Loadable{
bases.load();
}
private void loadLoadouts(){
Seq.with(Loadouts.basicShard, Loadouts.basicFoundation, Loadouts.basicNucleus).each(s -> checkLoadout(s,false));
}
public void overwrite(Schematic target, Schematic newSchematic){
if(previews.containsKey(target)){
previews.get(target).dispose();
@@ -136,6 +143,7 @@ public class Schematics implements Loadable{
try{
Schematic s = read(file);
all.add(s);
checkLoadout(s, true);
//external file from workshop
if(!s.file.parent().equals(schematicDirectory)){
@@ -275,6 +283,22 @@ public class Schematics implements Loadable{
.removeAll(s -> !s.block.isVisible() || !s.block.unlockedNow());
}
/** @return all the valid loadouts for a specific core type. */
public Seq<Schematic> getLoadouts(CoreBlock block){
return loadouts.get(block, Seq::new);
}
/** Checks a schematic for deployment validity and adds it to the cache. */
private void checkLoadout(Schematic s, boolean validate){
Stile core = s.tiles.find(t -> t.block instanceof CoreBlock);
//make sure a core exists, and that the schematic is small enough.
if(core == null || (validate && (s.width > core.block.size + maxLoadoutSchematicPad *2 || s.height > core.block.size + maxLoadoutSchematicPad *2))) return;
//place in the cache
loadouts.get((CoreBlock)core.block, Seq::new).add(s);
}
/** Adds a schematic to the list, also copying it into the files.*/
public void add(Schematic schematic){
all.add(schematic);
@@ -286,11 +310,14 @@ public class Schematics implements Loadable{
ui.showException(e);
Log.err(e);
}
checkLoadout(schematic, true);
all.sort();
}
public void remove(Schematic s){
all.remove(s);
loadouts.each((block, seq) -> seq.remove(s));
if(s.file != null){
s.file.delete();
}

View File

@@ -10,6 +10,7 @@ import mindustry.game.EventType.*;
import mindustry.game.SectorInfo.*;
import mindustry.io.*;
import mindustry.type.*;
import mindustry.world.blocks.storage.*;
import static mindustry.Vars.*;
@@ -19,6 +20,7 @@ public class Universe{
private float secondCounter;
private int turn;
private float turnCounter;
private Schematic lastLoadout = Loadouts.basicShard;
public Universe(){
load();
@@ -73,6 +75,31 @@ public class Universe{
}
}
/** Updates selected loadout for future deployment. */
public void updateLoadout(CoreBlock block, Schematic schem){
Core.settings.put("lastloadout-" + block.name, schem.file == null ? "" : schem.file.nameWithoutExtension());
lastLoadout = schem;
}
public Schematic getLastLoadout(){
return lastLoadout;
}
/** @return the last selected loadout for this specific core type. */
public Schematic getLoadout(CoreBlock core){
//for tools - schem
if(schematics == null) return Loadouts.basicShard;
//find last used loadout file name
String file = Core.settings.getString("lastloadout-" + core.name, "");
//use default (first) schematic if not found
Seq<Schematic> all = schematics.getLoadouts(core);
Schematic schem = all.find(s -> s.file != null && s.file.nameWithoutExtension().equals(file));
return schem == null ? all.first() : schem;
}
public int[] getTotalExports(){
int[] exports = new int[Vars.content.items().size];

View File

@@ -54,8 +54,7 @@ public class FileMapGenerator implements WorldGenerator{
}
if(tile.isCenter() && tile.block() instanceof CoreBlock && tile.team() == state.rules.defaultTeam && !anyCores){
//TODO PLACE THE (CORRECT) LOADOUT
Schematics.placeLoadout(Loadouts.basicShard, tile.x, tile.y);
Schematics.placeLoadout(universe.getLastLoadout(), tile.x, tile.y);
anyCores = true;
}

View File

@@ -279,8 +279,7 @@ public class TODOPlanetGenerator extends PlanetGenerator{
}
});
//TODO PLACE CORRECT LOADOUT
Schematics.placeLoadout(Loadouts.advancedShard, spawn.x, spawn.y);
Schematics.placeLoadout(universe.getLastLoadout(), spawn.x, spawn.y);
if(sector.hasEnemyBase()){
basegen.generate(tiles, enemies.map(r -> tiles.getn(r.x, r.y)), tiles.get(spawn.x, spawn.y), state.rules.waveTeam, sector);

View File

@@ -0,0 +1,56 @@
package mindustry.ui.dialogs;
import arc.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.ui.*;
import mindustry.ui.dialogs.SchematicsDialog.*;
import mindustry.world.blocks.storage.*;
import static mindustry.Vars.*;
/** Dialog for selecting loadout at sector launch. */
public class LaunchLoadoutDialog extends BaseDialog{
Schematic selected;
public LaunchLoadoutDialog(){
super("$configure");
}
public void show(CoreBlock core, Building build, Runnable confirm){
cont.clear();
buttons.clear();
addCloseButton();
buttons.button("$ok", () -> {
universe.updateLoadout(core, selected);
confirm.run();
hide();
});
int cols = Math.max((int)(Core.graphics.getWidth() / Scl.scl(230)), 1);
ButtonGroup<Button> group = new ButtonGroup<>();
selected = universe.getLoadout(core);
cont.pane(t -> {
int i = 0;
for(Schematic s : schematics.getLoadouts(core)){
t.button(b -> b.add(new SchematicImage(s)), Styles.togglet, () -> selected = s)
.group(group).pad(4).disabled(!build.items.has(s.requirements())).checked(s == selected).size(200f);
if(++i % cols == 0){
t.row();
}
}
}).growX().get().setScrollingDisabled(true, false);
//TODO configure items to launch with
show();
}
}

View File

@@ -32,6 +32,7 @@ import static mindustry.ui.dialogs.PlanetDialog.Mode.*;
public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
private final FrameBuffer buffer = new FrameBuffer(2, 2, true);
private final PlanetRenderer planets = renderer.planets;
private final LaunchLoadoutDialog loadouts = new LaunchLoadoutDialog();
private final Table stable = new Table().background(Styles.black3);
private int launchRange;
@@ -331,7 +332,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
return;
}
hide();
boolean shouldHide = true;
//save before launch.
if(control.saves.getCurrent() != null && state.isGame()){
@@ -344,14 +345,19 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
}
if(mode == launch){
control.handleLaunch(launcher);
zoom = 0.5f;
shouldHide = false;
loadouts.show((CoreBlock)launcher.block, launcher, () -> {
control.handleLaunch(launcher);
zoom = 0.5f;
ui.hudfrag.showLaunchDirect();
Time.runTask(launchDuration, () -> control.playSector(sector));
ui.hudfrag.showLaunchDirect();
Time.runTask(launchDuration, () -> control.playSector(sector));
});
}else{
control.playSector(sector);
}
if(shouldHide) hide();
}).growX().padTop(2f).height(50f).minWidth(170f);
}

View File

@@ -70,7 +70,7 @@ public class SchematicsDialog extends BaseDialog{
});
rebuildPane[0] = () -> {
int maxwidth = Math.max((int)(Core.graphics.getWidth() / Scl.scl(230)), 1);
int cols = Math.max((int)(Core.graphics.getWidth() / Scl.scl(230)), 1);
t.clear();
int i = 0;
@@ -153,7 +153,7 @@ public class SchematicsDialog extends BaseDialog{
sel[0].getStyle().up = Tex.pane;
if(++i % maxwidth == 0){
if(++i % cols == 0){
t.row();
}
}

View File

@@ -116,6 +116,13 @@ public class ItemModule extends BlockModule{
return true;
}
public boolean has(Iterable<ItemStack> stacks){
for(ItemStack stack : stacks){
if(!has(stack.item, stack.amount)) return false;
}
return true;
}
public boolean has(ItemStack[] stacks, float multiplier){
for(ItemStack stack : stacks){
if(!has(stack.item, Math.round(stack.amount * multiplier))) return false;