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
+4 -3
View File
@@ -391,8 +391,9 @@ donate = Donate
abandon = Abandon abandon = Abandon
abandon.text = This zone and all its resources will be lost to the enemy. abandon.text = This zone and all its resources will be lost to the enemy.
locked = Locked locked = Locked
complete = [lightgray]Reach: complete = [lightgray]Complete:
zone.requirement = Wave {0} in zone {1} zone.requirement.wave = Wave {0} in {1}
zone.requirement = Destroy core: {0}
resume = Resume Zone:\n[lightgray]{0} resume = Resume Zone:\n[lightgray]{0}
bestwave = [lightgray]Best Wave: {0} bestwave = [lightgray]Best Wave: {0}
launch = < LAUNCH > launch = < LAUNCH >
@@ -406,7 +407,7 @@ configure = Configure Loadout
configure.locked = [lightgray]Unlock configuring loadout: Wave {0}. configure.locked = [lightgray]Unlock configuring loadout: Wave {0}.
configure.invalid = Amount must be a number between 0 and {0}. configure.invalid = Amount must be a number between 0 and {0}.
zone.unlocked = [lightgray]{0} unlocked. zone.unlocked = [lightgray]{0} unlocked.
zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met. zone.requirements.met = {0}: zone requirements met.
zone.config.complete = Wave {0} reached:\nLoadout config unlocked. zone.config.complete = Wave {0} reached:\nLoadout config unlocked.
zone.resources = [lightgray]Resources Detected: zone.resources = [lightgray]Resources Detected:
zone.objective = [lightgray]Objective: [accent]{0} zone.objective = [lightgray]Objective: [accent]{0}
@@ -965,12 +965,12 @@ public class Blocks implements ContentList{
//region liquid //region liquid
mechanicalPump = new Pump("mechanical-pump"){{ 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; pumpAmount = 0.1f;
}}; }};
rotaryPump = new Pump("rotary-pump"){{ 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; pumpAmount = 0.8f;
consumes.power(0.15f); consumes.power(0.15f);
liquidCapacity = 30f; liquidCapacity = 30f;
@@ -979,7 +979,7 @@ public class Blocks implements ContentList{
}}; }};
thermalPump = new Pump("thermal-pump"){{ 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; pumpAmount = 1.5f;
consumes.power(0.30f); consumes.power(0.30f);
liquidCapacity = 40f; liquidCapacity = 40f;
@@ -993,13 +993,13 @@ public class Blocks implements ContentList{
}}; }};
pulseConduit = new Conduit("pulse-conduit"){{ 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; liquidCapacity = 16f;
health = 90; health = 90;
}}; }};
liquidRouter = new LiquidRouter("liquid-router"){{ 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; liquidCapacity = 20f;
}}; }};
@@ -1011,11 +1011,11 @@ public class Blocks implements ContentList{
}}; }};
liquidJunction = new LiquidJunction("liquid-junction"){{ 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"){{ 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; range = 4;
hasPower = false; hasPower = false;
}}; }};
@@ -146,7 +146,7 @@ public class Control implements ApplicationListener, Loadable{
}); });
Events.on(ZoneRequireCompleteEvent.class, e -> { 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 -> { Events.on(ZoneConfigureCompleteEvent.class, e -> {
@@ -180,6 +180,10 @@ public class Logic implements ApplicationListener{
Effects.effect(Fx.launch, tile); Effects.effect(Fx.launch, tile);
} }
if(world.getZone() != null){
world.getZone().setLaunched();
}
Time.runTask(30f, () -> { Time.runTask(30f, () -> {
for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){ for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){
for(Item item : content.items()){ for(Item item : content.items()){
@@ -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();
}
@@ -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;
}
}
}
@@ -19,6 +19,10 @@ public class ItemStack implements Comparable<ItemStack>{
item = Items.copper; item = Items.copper;
} }
public ItemStack copy(){
return new ItemStack(item, amount);
}
public boolean equals(ItemStack other){ public boolean equals(ItemStack other){
return other != null && other.item == item && other.amount == amount; return other != null && other.item == item && other.amount == amount;
} }
+38 -6
View File
@@ -5,8 +5,8 @@ import io.anuke.arc.collection.*;
import io.anuke.arc.function.*; import io.anuke.arc.function.*;
import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.scene.ui.layout.*; import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.ArcAnnotate.*; import io.anuke.arc.util.ArcAnnotate.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.content.*; import io.anuke.mindustry.content.*;
import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.*;
@@ -74,7 +74,7 @@ public class Zone extends UnlockableContent{
} }
for(ZoneRequirement other : zoneRequirements){ for(ZoneRequirement other : zoneRequirements){
if(other.zone.bestWave() < other.wave){ if(!other.isComplete()){
return false; return false;
} }
} }
@@ -104,6 +104,23 @@ public class Zone extends UnlockableContent{
defaultStartingItems.each(stack -> startingItems.add(new ItemStack(stack.item, stack.amount))); 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){ public void updateWave(int wave){
int value = Core.settings.getInt(name + "-wave", 0); int value = Core.settings.getInt(name + "-wave", 0);
if(value < wave){ if(value < wave){
@@ -112,7 +129,7 @@ public class Zone extends UnlockableContent{
for(Zone zone : content.zones()){ for(Zone zone : content.zones()){
ZoneRequirement req = Structs.find(zone.zoneRequirements, f -> f.zone == this); 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)); Events.fire(new ZoneRequireCompleteEvent(zone, this));
} }
} }
@@ -127,7 +144,8 @@ public class Zone extends UnlockableContent{
return Core.settings.getInt(name + "-wave", 0); return Core.settings.getInt(name + "-wave", 0);
} }
public boolean isCompleted(){ /** @return whether initial conditions to launch are met. */
public boolean isLaunchMet(){
return bestWave() >= conditionWave; return bestWave() >= conditionWave;
} }
@@ -208,19 +226,33 @@ public class Zone extends UnlockableContent{
return ContentType.zone; return ContentType.zone;
} }
/*
public static class ZoneRequirement{ public static class ZoneRequirement{
public @NonNull Zone zone; public @NonNull Zone zone;
public @NonNull int wave; public int wave;
public ZoneRequirement(Zone zone, int wave){ public ZoneRequirement(Zone zone, int wave){
this.zone = zone; this.zone = zone;
this.wave = wave; this.wave = wave;
} }
public ZoneRequirement(Zone zone){
this.zone = zone;
}
protected ZoneRequirement(){ protected ZoneRequirement(){
} }
public boolean isComplete(){
if(zone.getRules().attackMode){
return zone.hasLaunched();
}else{
return zone.bestWave() >= wave;
}
}
public static ZoneRequirement[] with(Object... objects){ public static ZoneRequirement[] with(Object... objects){
ZoneRequirement[] out = new ZoneRequirement[objects.length / 2]; ZoneRequirement[] out = new ZoneRequirement[objects.length / 2];
for(int i = 0; i < objects.length; i += 2){ for(int i = 0; i < objects.length; i += 2){
@@ -228,6 +260,6 @@ public class Zone extends UnlockableContent{
} }
return out; return out;
} }
} }*/
} }
@@ -1,16 +1,14 @@
package io.anuke.mindustry.ui.dialogs; package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.function.*; import io.anuke.arc.function.*;
import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.*;
import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*; import io.anuke.arc.util.*;
import io.anuke.mindustry.*; import io.anuke.mindustry.*;
import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.*;
import io.anuke.mindustry.content.Items; import io.anuke.mindustry.game.*;
import io.anuke.mindustry.game.Rules; import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.*;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.ItemType;
import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.tilesize;
@@ -69,13 +67,11 @@ public class CustomRulesDialog extends FloatingDialog{
main.addButton("$configure", main.addButton("$configure",
() -> loadoutDialog.show( () -> loadoutDialog.show(
Blocks.coreShard.itemCapacity, Blocks.coreShard.itemCapacity,
() -> rules.loadout, rules.loadout,
() -> { () -> {
rules.loadout.clear(); rules.loadout.clear();
rules.loadout.add(new ItemStack(Items.copper, 100)); rules.loadout.add(new ItemStack(Items.copper, 100));
}, }, () -> {}, () -> {}
() -> {}, () -> {},
item -> item.type == ItemType.material
)).left().width(300f); )).left().width(300f);
main.row(); main.row();
@@ -129,7 +129,7 @@ public class DeployDialog extends FloatingDialog{
button.defaults().colspan(2); button.defaults().colspan(2);
button.row(); button.row();
button.add(Core.bundle.format("save.wave", color + slot.getWave())); button.add(Core.bundle.format("save", color + slot.getWave()));
button.row(); button.row();
button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime())); button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime()));
button.row(); button.row();
@@ -2,9 +2,7 @@ package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.*; import io.anuke.arc.*;
import io.anuke.arc.collection.*; import io.anuke.arc.collection.*;
import io.anuke.arc.function.*;
import io.anuke.arc.input.*; import io.anuke.arc.input.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.*; import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*; import io.anuke.arc.util.*;
import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.*;
@@ -16,10 +14,12 @@ import static io.anuke.mindustry.Vars.*;
public class LoadoutDialog extends FloatingDialog{ public class LoadoutDialog extends FloatingDialog{
private Runnable hider; private Runnable hider;
private Supplier<Array<ItemStack>> supplier; //private Supplier<Array<ItemStack>> supplier;
private Runnable resetter; private Runnable resetter;
private Runnable updater; 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 Table items;
private int capacity; 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); shown(this::setup);
hidden(() -> { hidden(() -> {
originalStacks.selectFrom(stacks, s -> s.amount > 0);
updater.run();
if(hider != null){ if(hider != null){
hider.run(); hider.run();
} }
}); });
cont.row(); buttons.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f, 64f);
cont.addButton("$add", () -> { buttons.addImageTextButton("$settings.reset", Icon.refreshSmall, () -> {
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", () -> {
resetter.run(); resetter.run();
updater.run(); updater.run();
setup(); setup();
}).size(210f, 64f); }).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.resetter = reseter;
this.supplier = supplier;
this.updater = updater; this.updater = updater;
this.capacity = capacity; this.capacity = capacity;
this.hider = hider; this.hider = hider;
this.filter = filter; //this.filter = filter;
show(); show();
} }
@@ -88,41 +71,54 @@ public class LoadoutDialog extends FloatingDialog{
items.clearChildren(); items.clearChildren();
items.left(); items.left();
float bsize = 40f; float bsize = 40f;
int step = 50;
for(ItemStack stack : supplier.get()){ int i = 0;
items.addButton("x", Styles.clearPartialt, () -> {
supplier.get().remove(stack);
updater.run();
setup();
}).size(bsize);
items.addButton("-", Styles.clearPartialt, () -> { for(ItemStack stack : stacks){
stack.amount = Math.max(stack.amount - step, 0); items.table(Tex.pane, t -> {
updater.run(); t.margin(4).marginRight(8).left();
}).size(bsize); t.addButton("-", Styles.cleart, () -> {
stack.amount = Math.max(stack.amount - step(stack.amount), 0);
updater.run();
}).size(bsize);
items.addButton("+", Styles.clearPartialt, () -> { t.addButton("+", Styles.cleart, () -> {
stack.amount = Math.min(stack.amount + step, capacity); stack.amount = Math.min(stack.amount + step(stack.amount), capacity);
updater.run(); updater.run();
}).size(bsize); }).size(bsize);
items.addImageButton(Icon.pencilSmaller, Styles.clearPartial2i, () -> ui.showTextInput("$configure", stack.item.localizedName, 10, stack.amount + "", true, str -> { t.addImageButton(Icon.pencilSmaller, Styles.cleari, () -> ui.showTextInput("$configure", stack.item.localizedName, 10, stack.amount + "", true, str -> {
if(Strings.canParsePostiveInt(str)){ if(Strings.canParsePostiveInt(str)){
int amount = Strings.parseInt(str); int amount = Strings.parseInt(str);
if(amount >= 0 && amount <= capacity){ if(amount >= 0 && amount <= capacity){
stack.amount = amount; stack.amount = amount;
updater.run(); updater.run();
return; return;
}
} }
} ui.showInfo(Core.bundle.format("configure.invalid", capacity));
ui.showInfo(Core.bundle.format("configure.invalid", capacity)); })).size(bsize);
})).size(bsize);
items.addImage(stack.item.icon(Cicon.small)).size(8 * 3).padRight(4).padLeft(4); t.addImage(stack.item.icon(Cicon.small)).size(8 * 3).padRight(4).padLeft(4);
items.label(() -> stack.amount + "").left(); 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;
} }
} }
} }
@@ -66,10 +66,12 @@ public class ZoneInfoDialog extends FloatingDialog{
req.table(r -> { req.table(r -> {
r.add("$complete").colspan(2).left(); r.add("$complete").colspan(2).left();
r.row(); r.row();
for(ZoneRequirement other : zone.zoneRequirements){ for(ZoneRequirement zreq : zone.zoneRequirements){
r.addImage(Icon.terrain).padRight(4); r.addImage(Icon.terrain).padRight(4);
r.add(Core.bundle.format("zone.requirement", other.wave, other.zone.localizedName())).color(Color.lightGray); r.add(!zreq.zone.getRules().attackMode ?
r.addImage(other.zone.bestWave() >= other.wave ? Icon.checkSmall : Icon.cancelSmall, other.zone.bestWave() >= other.wave ? Color.lightGray : Color.scarlet).padLeft(3); 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(); r.row();
} }
}); });
@@ -82,8 +84,8 @@ public class ZoneInfoDialog extends FloatingDialog{
r.add("$research.list").colspan(2).left(); r.add("$research.list").colspan(2).left();
r.row(); r.row();
for(Block block : zone.blockRequirements){ for(Block block : zone.blockRequirements){
r.addImage(block.icon(Cicon.small)).size(8 * 3).padRight(4); r.addImage(block.icon(Cicon.small)).size(8 * 3).padRight(5);
r.add(block.localizedName).color(Color.lightGray); 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.addImage(data.isUnlocked(block) ? Icon.checkSmall : Icon.cancelSmall, data.isUnlocked(block) ? Color.lightGray : Color.scarlet).padLeft(3);
r.row(); r.row();
} }
@@ -136,7 +138,7 @@ public class ZoneInfoDialog extends FloatingDialog{
cont.row(); cont.row();
cont.addButton(zone.canConfigure() ? "$configure" : Core.bundle.format("configure.locked", zone.configureWave), 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()); ).fillX().pad(3).disabled(b -> !zone.canConfigure());
} }
cont.marginRight(12f); cont.marginRight(12f);