Zone objective abstraction, cleanup

This commit is contained in:
Anuken
2019-10-05 00:21:48 -04:00
parent 1b93da20f4
commit c1ff7812d8
12 changed files with 182 additions and 97 deletions

View File

@@ -965,12 +965,12 @@ public class Blocks implements ContentList{
//region liquid
mechanicalPump = new Pump("mechanical-pump"){{
requirements(Category.liquid, ItemStack.with(Items.copper, 15, Items.lead, 10));
requirements(Category.liquid, ItemStack.with(Items.copper, 15, Items.metaglass, 10));
pumpAmount = 0.1f;
}};
rotaryPump = new Pump("rotary-pump"){{
requirements(Category.liquid, ItemStack.with(Items.copper, 70, Items.lead, 50, Items.silicon, 20, Items.titanium, 35));
requirements(Category.liquid, ItemStack.with(Items.copper, 70, Items.metaglass, 50, Items.silicon, 20, Items.titanium, 35));
pumpAmount = 0.8f;
consumes.power(0.15f);
liquidCapacity = 30f;
@@ -979,7 +979,7 @@ public class Blocks implements ContentList{
}};
thermalPump = new Pump("thermal-pump"){{
requirements(Category.liquid, ItemStack.with(Items.copper, 80, Items.lead, 65, Items.silicon, 30, Items.titanium, 40, Items.thorium, 35));
requirements(Category.liquid, ItemStack.with(Items.copper, 80, Items.metaglass, 70, Items.silicon, 30, Items.titanium, 40, Items.thorium, 35));
pumpAmount = 1.5f;
consumes.power(0.30f);
liquidCapacity = 40f;
@@ -993,13 +993,13 @@ public class Blocks implements ContentList{
}};
pulseConduit = new Conduit("pulse-conduit"){{
requirements(Category.liquid, ItemStack.with(Items.titanium, 1, Items.metaglass, 1));
requirements(Category.liquid, ItemStack.with(Items.titanium, 2, Items.metaglass, 1));
liquidCapacity = 16f;
health = 90;
}};
liquidRouter = new LiquidRouter("liquid-router"){{
requirements(Category.liquid, ItemStack.with(Items.titanium, 2, Items.metaglass, 2));
requirements(Category.liquid, ItemStack.with(Items.graphite, 4, Items.metaglass, 2));
liquidCapacity = 20f;
}};
@@ -1011,11 +1011,11 @@ public class Blocks implements ContentList{
}};
liquidJunction = new LiquidJunction("liquid-junction"){{
requirements(Category.liquid, ItemStack.with(Items.titanium, 2, Items.metaglass, 2));
requirements(Category.liquid, ItemStack.with(Items.graphite, 2, Items.metaglass, 2));
}};
bridgeConduit = new LiquidExtendingBridge("bridge-conduit"){{
requirements(Category.liquid, ItemStack.with(Items.titanium, 4, Items.metaglass, 4));
requirements(Category.liquid, ItemStack.with(Items.graphite, 4, Items.metaglass, 8));
range = 4;
hasPower = false;
}};

View File

@@ -146,7 +146,7 @@ public class Control implements ApplicationListener, Loadable{
});
Events.on(ZoneRequireCompleteEvent.class, e -> {
ui.hudfrag.showToast(Core.bundle.format("zone.requirement.complete", state.wave, e.zone.localizedName));
ui.hudfrag.showToast(Core.bundle.format("zone.requirements.met", e.zone.localizedName));
});
Events.on(ZoneConfigureCompleteEvent.class, e -> {

View File

@@ -180,6 +180,10 @@ public class Logic implements ApplicationListener{
Effects.effect(Fx.launch, tile);
}
if(world.getZone() != null){
world.getZone().setLaunched();
}
Time.runTask(30f, () -> {
for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){
for(Item item : content.items()){

View File

@@ -0,0 +1,12 @@
package io.anuke.mindustry.game;
/** Defines a specific objective for a game. */
public interface Objective{
/** @return whether this objective is met. */
boolean complete();
/** @return the string displayed when this objective is completed, in imperative form.
* e.g. when the objective is 'complete 10 waves', this would display "complete 10 waves".*/
String display();
}

View File

@@ -0,0 +1,38 @@
package io.anuke.mindustry.game;
/** Holds objective classes. */
public class Objectives{
public static class WaveObjective implements Objective{
public int wave;
public WaveObjective(int wave){
this.wave = wave;
}
protected WaveObjective(){}
@Override
public boolean complete(){
return false;
}
@Override
public String display(){
return null;
}
}
public static class LaunchObjective implements Objective{
@Override
public boolean complete(){
return false;
}
@Override
public String display(){
return null;
}
}
}

View File

@@ -19,6 +19,10 @@ public class ItemStack implements Comparable<ItemStack>{
item = Items.copper;
}
public ItemStack copy(){
return new ItemStack(item, amount);
}
public boolean equals(ItemStack other){
return other != null && other.item == item && other.amount == amount;
}

View File

@@ -5,8 +5,8 @@ import io.anuke.arc.collection.*;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.ArcAnnotate.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.*;
@@ -74,7 +74,7 @@ public class Zone extends UnlockableContent{
}
for(ZoneRequirement other : zoneRequirements){
if(other.zone.bestWave() < other.wave){
if(!other.isComplete()){
return false;
}
}
@@ -104,6 +104,23 @@ public class Zone extends UnlockableContent{
defaultStartingItems.each(stack -> startingItems.add(new ItemStack(stack.item, stack.amount)));
}
public boolean hasLaunched(){
return Core.settings.getBool(name + "-launched", false);
}
public void setLaunched(){
if(!hasLaunched() && getRules().attackMode){
for(Zone zone : content.zones()){
ZoneRequirement req = Structs.find(zone.zoneRequirements, f -> f.zone == this);
if(req != null && req.isComplete()){
Events.fire(new ZoneRequireCompleteEvent(zone, this));
}
}
}
Core.settings.put(name + "-launched", true);
data.modified();
}
public void updateWave(int wave){
int value = Core.settings.getInt(name + "-wave", 0);
if(value < wave){
@@ -112,7 +129,7 @@ public class Zone extends UnlockableContent{
for(Zone zone : content.zones()){
ZoneRequirement req = Structs.find(zone.zoneRequirements, f -> f.zone == this);
if(req != null && wave == req.wave + 1){
if(req != null && wave == req.wave + 1 && req.isComplete()){
Events.fire(new ZoneRequireCompleteEvent(zone, this));
}
}
@@ -127,7 +144,8 @@ public class Zone extends UnlockableContent{
return Core.settings.getInt(name + "-wave", 0);
}
public boolean isCompleted(){
/** @return whether initial conditions to launch are met. */
public boolean isLaunchMet(){
return bestWave() >= conditionWave;
}
@@ -208,19 +226,33 @@ public class Zone extends UnlockableContent{
return ContentType.zone;
}
/*
public static class ZoneRequirement{
public @NonNull Zone zone;
public @NonNull int wave;
public int wave;
public ZoneRequirement(Zone zone, int wave){
this.zone = zone;
this.wave = wave;
}
public ZoneRequirement(Zone zone){
this.zone = zone;
}
protected ZoneRequirement(){
}
public boolean isComplete(){
if(zone.getRules().attackMode){
return zone.hasLaunched();
}else{
return zone.bestWave() >= wave;
}
}
public static ZoneRequirement[] with(Object... objects){
ZoneRequirement[] out = new ZoneRequirement[objects.length / 2];
for(int i = 0; i < objects.length; i += 2){
@@ -228,6 +260,6 @@ public class Zone extends UnlockableContent{
}
return out;
}
}
}*/
}

View File

@@ -1,16 +1,14 @@
package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.graphics.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.content.Items;
import io.anuke.mindustry.game.Rules;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.ItemType;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.type.*;
import static io.anuke.mindustry.Vars.tilesize;
@@ -69,13 +67,11 @@ public class CustomRulesDialog extends FloatingDialog{
main.addButton("$configure",
() -> loadoutDialog.show(
Blocks.coreShard.itemCapacity,
() -> rules.loadout,
rules.loadout,
() -> {
rules.loadout.clear();
rules.loadout.add(new ItemStack(Items.copper, 100));
},
() -> {}, () -> {},
item -> item.type == ItemType.material
}, () -> {}, () -> {}
)).left().width(300f);
main.row();

View File

@@ -129,7 +129,7 @@ public class DeployDialog extends FloatingDialog{
button.defaults().colspan(2);
button.row();
button.add(Core.bundle.format("save.wave", color + slot.getWave()));
button.add(Core.bundle.format("save", color + slot.getWave()));
button.row();
button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime()));
button.row();

View File

@@ -2,9 +2,7 @@ package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.function.*;
import io.anuke.arc.input.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.game.*;
@@ -16,10 +14,12 @@ import static io.anuke.mindustry.Vars.*;
public class LoadoutDialog extends FloatingDialog{
private Runnable hider;
private Supplier<Array<ItemStack>> supplier;
//private Supplier<Array<ItemStack>> supplier;
private Runnable resetter;
private Runnable updater;
private Predicate<Item> filter;
private Array<ItemStack> stacks = new Array<>();
private Array<ItemStack> originalStacks = new Array<>();
//private Predicate<Item> filter;
private Table items;
private int capacity;
@@ -33,54 +33,37 @@ public class LoadoutDialog extends FloatingDialog{
}
});
cont.add(items = new Table()).left();
cont.pane(t -> items = t.margin(10f)).left();
shown(this::setup);
hidden(() -> {
originalStacks.selectFrom(stacks, s -> s.amount > 0);
updater.run();
if(hider != null){
hider.run();
}
});
cont.row();
buttons.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f, 64f);
cont.addButton("$add", () -> {
FloatingDialog dialog = new FloatingDialog("");
dialog.setFillParent(false);
for(Item item : content.items().select(item -> filter.test(item) && item.type == ItemType.material && supplier.get().find(stack -> stack.item == item) == null)){
TextButton button = dialog.cont.addButton("", Styles.cleart, () -> {
dialog.hide();
supplier.get().add(new ItemStack(item, 0));
updater.run();
setup();
}).size(300f, 36f).get();
button.clearChildren();
button.left();
button.addImage(item.icon(Cicon.small)).size(8 * 3).pad(4);
button.add(item.localizedName);
dialog.cont.row();
}
dialog.show();
}).size(100f, 40).left().disabled(b -> !content.items().contains(item -> filter.test(item) && !supplier.get().contains(stack -> stack.item == item)));
cont.row();
cont.addButton("$settings.reset", () -> {
buttons.addImageTextButton("$settings.reset", Icon.refreshSmall, () -> {
resetter.run();
updater.run();
setup();
}).size(210f, 64f);
cont.row();
cont.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f, 64f);
}
public void show(int capacity, Supplier<Array<ItemStack>> supplier, Runnable reseter, Runnable updater, Runnable hider, Predicate<Item> filter){
public void show(int capacity, Array<ItemStack> stacks, Runnable reseter, Runnable updater, Runnable hider){
this.originalStacks = stacks;
this.stacks = stacks.map(ItemStack::copy);
this.stacks.addAll(content.items().select(i -> i.type == ItemType.material &&
!stacks.contains(stack -> stack.item == i)).map(i -> new ItemStack(i, 0)));
this.stacks.sort(Structs.comparingInt(s -> s.item.id));
this.resetter = reseter;
this.supplier = supplier;
this.updater = updater;
this.capacity = capacity;
this.hider = hider;
this.filter = filter;
//this.filter = filter;
show();
}
@@ -88,41 +71,54 @@ public class LoadoutDialog extends FloatingDialog{
items.clearChildren();
items.left();
float bsize = 40f;
int step = 50;
for(ItemStack stack : supplier.get()){
items.addButton("x", Styles.clearPartialt, () -> {
supplier.get().remove(stack);
updater.run();
setup();
}).size(bsize);
int i = 0;
items.addButton("-", Styles.clearPartialt, () -> {
stack.amount = Math.max(stack.amount - step, 0);
updater.run();
}).size(bsize);
for(ItemStack stack : stacks){
items.table(Tex.pane, t -> {
t.margin(4).marginRight(8).left();
t.addButton("-", Styles.cleart, () -> {
stack.amount = Math.max(stack.amount - step(stack.amount), 0);
updater.run();
}).size(bsize);
items.addButton("+", Styles.clearPartialt, () -> {
stack.amount = Math.min(stack.amount + step, capacity);
updater.run();
}).size(bsize);
t.addButton("+", Styles.cleart, () -> {
stack.amount = Math.min(stack.amount + step(stack.amount), capacity);
updater.run();
}).size(bsize);
items.addImageButton(Icon.pencilSmaller, Styles.clearPartial2i, () -> ui.showTextInput("$configure", stack.item.localizedName, 10, stack.amount + "", true, str -> {
if(Strings.canParsePostiveInt(str)){
int amount = Strings.parseInt(str);
if(amount >= 0 && amount <= capacity){
stack.amount = amount;
updater.run();
return;
t.addImageButton(Icon.pencilSmaller, Styles.cleari, () -> ui.showTextInput("$configure", stack.item.localizedName, 10, stack.amount + "", true, str -> {
if(Strings.canParsePostiveInt(str)){
int amount = Strings.parseInt(str);
if(amount >= 0 && amount <= capacity){
stack.amount = amount;
updater.run();
return;
}
}
}
ui.showInfo(Core.bundle.format("configure.invalid", capacity));
})).size(bsize);
ui.showInfo(Core.bundle.format("configure.invalid", capacity));
})).size(bsize);
items.addImage(stack.item.icon(Cicon.small)).size(8 * 3).padRight(4).padLeft(4);
items.label(() -> stack.amount + "").left();
t.addImage(stack.item.icon(Cicon.small)).size(8 * 3).padRight(4).padLeft(4);
t.label(() -> stack.amount + "").left().width(90f);
}).pad(2).left().fillX();
items.row();
if(++i % 2 == 0 || (mobile && Core.graphics.isPortrait())){
items.row();
}
}
}
private int step(int amount){
if(amount < 1000){
return 100;
}else if(amount < 2000){
return 200;
}else if(amount < 5000){
return 500;
}else{
return 1000;
}
}
}

View File

@@ -66,10 +66,12 @@ public class ZoneInfoDialog extends FloatingDialog{
req.table(r -> {
r.add("$complete").colspan(2).left();
r.row();
for(ZoneRequirement other : zone.zoneRequirements){
for(ZoneRequirement zreq : zone.zoneRequirements){
r.addImage(Icon.terrain).padRight(4);
r.add(Core.bundle.format("zone.requirement", other.wave, other.zone.localizedName())).color(Color.lightGray);
r.addImage(other.zone.bestWave() >= other.wave ? Icon.checkSmall : Icon.cancelSmall, other.zone.bestWave() >= other.wave ? Color.lightGray : Color.scarlet).padLeft(3);
r.add(!zreq.zone.getRules().attackMode ?
Core.bundle.format("zone.requirement.wave", zreq.wave, zreq.zone.localizedName()) :
Core.bundle.format("zone.requirement", zreq.zone.localizedName)).color(Color.lightGray);
r.addImage(zreq.isComplete() ? Icon.checkSmall : Icon.cancelSmall, zreq.isComplete() ? Color.lightGray : Color.scarlet).padLeft(3);
r.row();
}
});
@@ -82,8 +84,8 @@ public class ZoneInfoDialog extends FloatingDialog{
r.add("$research.list").colspan(2).left();
r.row();
for(Block block : zone.blockRequirements){
r.addImage(block.icon(Cicon.small)).size(8 * 3).padRight(4);
r.add(block.localizedName).color(Color.lightGray);
r.addImage(block.icon(Cicon.small)).size(8 * 3).padRight(5);
r.add(block.localizedName).color(Color.lightGray).left();
r.addImage(data.isUnlocked(block) ? Icon.checkSmall : Icon.cancelSmall, data.isUnlocked(block) ? Color.lightGray : Color.scarlet).padLeft(3);
r.row();
}
@@ -136,7 +138,7 @@ public class ZoneInfoDialog extends FloatingDialog{
cont.row();
cont.addButton(zone.canConfigure() ? "$configure" : Core.bundle.format("configure.locked", zone.configureWave),
() -> loadout.show(zone.loadout.core().itemCapacity, zone::getStartingItems, zone::resetStartingItems, zone::updateLaunchCost, rebuildItems, item -> data.getItem(item) > 0 && item.type == ItemType.material)
() -> loadout.show(zone.loadout.core().itemCapacity, zone.getStartingItems(), zone::resetStartingItems, zone::updateLaunchCost, rebuildItems)
).fillX().pad(3).disabled(b -> !zone.canConfigure());
}
cont.marginRight(12f);