Bannable units / Show tech tree icon for unresearched units
This commit is contained in:
@@ -539,6 +539,7 @@ configure = Configure Loadout
|
|||||||
loadout = Loadout
|
loadout = Loadout
|
||||||
resources = Resources
|
resources = Resources
|
||||||
bannedblocks = Banned Blocks
|
bannedblocks = Banned Blocks
|
||||||
|
bannedunits = Banned Units
|
||||||
addall = Add All
|
addall = Add All
|
||||||
launch.from = Launching From: [accent]{0}
|
launch.from = Launching From: [accent]{0}
|
||||||
launch.destination = Destination: {0}
|
launch.destination = Destination: {0}
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ public class Rules{
|
|||||||
public Seq<WeatherEntry> weather = new Seq<>(1);
|
public Seq<WeatherEntry> weather = new Seq<>(1);
|
||||||
/** Blocks that cannot be placed. */
|
/** Blocks that cannot be placed. */
|
||||||
public ObjectSet<Block> bannedBlocks = new ObjectSet<>();
|
public ObjectSet<Block> bannedBlocks = new ObjectSet<>();
|
||||||
|
/** Units that cannot be built. */
|
||||||
|
public ObjectSet<UnitType> bannedUnits = new ObjectSet<>();
|
||||||
/** Reveals blocks normally hidden by build visibility. */
|
/** Reveals blocks normally hidden by build visibility. */
|
||||||
public ObjectSet<Block> revealedBlocks = new ObjectSet<>();
|
public ObjectSet<Block> revealedBlocks = new ObjectSet<>();
|
||||||
/** Unlocked content names. Only used in multiplayer when the campaign is enabled. */
|
/** Unlocked content names. Only used in multiplayer when the campaign is enabled. */
|
||||||
|
|||||||
@@ -40,11 +40,7 @@ public class MinimapRenderer{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(BuildTeamChangeEvent.class, event -> {
|
Events.on(BuildTeamChangeEvent.class, event -> update(event.build.tile));
|
||||||
if(!ui.editor.isShown()){
|
|
||||||
update(event.build.tile);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pixmap getPixmap(){
|
public Pixmap getPixmap(){
|
||||||
|
|||||||
@@ -233,6 +233,10 @@ public class UnitType extends UnlockableContent{
|
|||||||
return (envEnabled & env) != 0 && (envDisabled & env) == 0 && (envRequired == 0 || (envRequired & env) == envRequired);
|
return (envEnabled & env) != 0 && (envDisabled & env) == 0 && (envRequired == 0 || (envRequired & env) == envRequired);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isBanned(){
|
||||||
|
return state.rules.bannedUnits.contains(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getDependencies(Cons<UnlockableContent> cons){
|
public void getDependencies(Cons<UnlockableContent> cons){
|
||||||
//units require reconstructors being researched
|
//units require reconstructors being researched
|
||||||
|
|||||||
@@ -28,87 +28,93 @@ public class CustomRulesDialog extends BaseDialog{
|
|||||||
private Table main;
|
private Table main;
|
||||||
private Prov<Rules> resetter;
|
private Prov<Rules> resetter;
|
||||||
private LoadoutDialog loadoutDialog;
|
private LoadoutDialog loadoutDialog;
|
||||||
private BaseDialog banDialog;
|
|
||||||
|
|
||||||
public CustomRulesDialog(){
|
public CustomRulesDialog(){
|
||||||
super("@mode.custom");
|
super("@mode.custom");
|
||||||
|
|
||||||
loadoutDialog = new LoadoutDialog();
|
loadoutDialog = new LoadoutDialog();
|
||||||
banDialog = new BaseDialog("@bannedblocks");
|
|
||||||
banDialog.addCloseButton();
|
|
||||||
|
|
||||||
banDialog.shown(this::rebuildBanned);
|
|
||||||
banDialog.buttons.button("@addall", Icon.add, () -> {
|
|
||||||
rules.bannedBlocks.addAll(content.blocks().select(Block::canBeBuilt));
|
|
||||||
rebuildBanned();
|
|
||||||
}).size(180, 64f);
|
|
||||||
|
|
||||||
banDialog.buttons.button("@clear", Icon.trash, () -> {
|
|
||||||
rules.bannedBlocks.clear();
|
|
||||||
rebuildBanned();
|
|
||||||
}).size(180, 64f);
|
|
||||||
|
|
||||||
setFillParent(true);
|
setFillParent(true);
|
||||||
shown(this::setup);
|
shown(this::setup);
|
||||||
addCloseButton();
|
addCloseButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rebuildBanned(){
|
private <T extends UnlockableContent> void showBanned(String title, ContentType type, ObjectSet<T> set, Boolf<T> pred){
|
||||||
float previousScroll = banDialog.cont.getChildren().isEmpty() ? 0f : ((ScrollPane)banDialog.cont.getChildren().first()).getScrollY();
|
BaseDialog bd = new BaseDialog(title);
|
||||||
banDialog.cont.clear();
|
bd.addCloseButton();
|
||||||
banDialog.cont.pane(t -> {
|
|
||||||
t.margin(10f);
|
|
||||||
|
|
||||||
if(rules.bannedBlocks.isEmpty()){
|
Runnable[] rebuild = {null};
|
||||||
t.add("@empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
Seq<Block> array = Seq.with(rules.bannedBlocks);
|
rebuild[0] = () -> {
|
||||||
array.sort();
|
float previousScroll = bd.cont.getChildren().isEmpty() ? 0f : ((ScrollPane)bd.cont.getChildren().first()).getScrollY();
|
||||||
|
bd.cont.clear();
|
||||||
|
bd.cont.pane(t -> {
|
||||||
|
t.margin(10f);
|
||||||
|
|
||||||
int cols = mobile && Core.graphics.isPortrait() ? 1 : mobile ? 2 : 3;
|
if(set.isEmpty()){
|
||||||
int i = 0;
|
t.add("@empty");
|
||||||
|
|
||||||
for(Block block : array){
|
|
||||||
t.table(Tex.underline, b -> {
|
|
||||||
b.left().margin(4f);
|
|
||||||
b.image(block.uiIcon).size(iconMed).padRight(3);
|
|
||||||
b.add(block.localizedName).color(Color.lightGray).padLeft(3).growX().left().wrap();
|
|
||||||
|
|
||||||
b.button(Icon.cancel, Styles.clearPartiali, () -> {
|
|
||||||
rules.bannedBlocks.remove(block);
|
|
||||||
rebuildBanned();
|
|
||||||
}).size(70f).pad(-4f).padLeft(0f);
|
|
||||||
}).size(300f, 70f).padRight(5);
|
|
||||||
|
|
||||||
if(++i % cols == 0){
|
|
||||||
t.row();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}).get().setScrollYForce(previousScroll);
|
|
||||||
banDialog.cont.row();
|
|
||||||
banDialog.cont.button("@add", Icon.add, () -> {
|
|
||||||
BaseDialog dialog = new BaseDialog("@add");
|
|
||||||
dialog.cont.pane(t -> {
|
|
||||||
t.left().margin(14f);
|
|
||||||
int[] i = {0};
|
|
||||||
content.blocks().each(b -> !rules.bannedBlocks.contains(b) && b.canBeBuilt(), b -> {
|
|
||||||
int cols = mobile && Core.graphics.isPortrait() ? 4 : 12;
|
|
||||||
t.button(new TextureRegionDrawable(b.uiIcon), Styles.cleari, iconMed, () -> {
|
|
||||||
rules.bannedBlocks.add(b);
|
|
||||||
rebuildBanned();
|
|
||||||
dialog.hide();
|
|
||||||
}).size(60f);
|
|
||||||
|
|
||||||
if(++i[0] % cols == 0){
|
Seq<T> array = set.asArray();
|
||||||
|
array.sort();
|
||||||
|
|
||||||
|
int cols = mobile && Core.graphics.isPortrait() ? 1 : mobile ? 2 : 3;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for(T con : array){
|
||||||
|
t.table(Tex.underline, b -> {
|
||||||
|
b.left().margin(4f);
|
||||||
|
b.image(con.uiIcon).size(iconMed).padRight(3);
|
||||||
|
b.add(con.localizedName).color(Color.lightGray).padLeft(3).growX().left().wrap();
|
||||||
|
|
||||||
|
b.button(Icon.cancel, Styles.clearPartiali, () -> {
|
||||||
|
set.remove(con);
|
||||||
|
rebuild[0].run();
|
||||||
|
}).size(70f).pad(-4f).padLeft(0f);
|
||||||
|
}).size(300f, 70f).padRight(5);
|
||||||
|
|
||||||
|
if(++i % cols == 0){
|
||||||
t.row();
|
t.row();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
});
|
}).get().setScrollYForce(previousScroll);
|
||||||
|
bd.cont.row();
|
||||||
|
bd.cont.button("@add", Icon.add, () -> {
|
||||||
|
BaseDialog dialog = new BaseDialog("@add");
|
||||||
|
dialog.cont.pane(t -> {
|
||||||
|
t.left().margin(14f);
|
||||||
|
int[] i = {0};
|
||||||
|
content.<T>getBy(type).each(b -> !set.contains(b) && pred.get(b), b -> {
|
||||||
|
int cols = mobile && Core.graphics.isPortrait() ? 4 : 12;
|
||||||
|
t.button(new TextureRegionDrawable(b.uiIcon), Styles.cleari, iconMed, () -> {
|
||||||
|
set.add(b);
|
||||||
|
rebuild[0].run();
|
||||||
|
dialog.hide();
|
||||||
|
}).size(60f);
|
||||||
|
|
||||||
dialog.addCloseButton();
|
if(++i[0] % cols == 0){
|
||||||
dialog.show();
|
t.row();
|
||||||
}).size(300f, 64f);
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.addCloseButton();
|
||||||
|
dialog.show();
|
||||||
|
}).size(300f, 64f);
|
||||||
|
};
|
||||||
|
|
||||||
|
bd.shown(rebuild[0]);
|
||||||
|
bd.buttons.button("@addall", Icon.add, () -> {
|
||||||
|
set.addAll(content.<T>getBy(type).select(pred));
|
||||||
|
rebuild[0].run();
|
||||||
|
}).size(180, 64f);
|
||||||
|
|
||||||
|
bd.buttons.button("@clear", Icon.trash, () -> {
|
||||||
|
set.clear();
|
||||||
|
rebuild[0].run();
|
||||||
|
}).size(180, 64f);
|
||||||
|
|
||||||
|
bd.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void show(Rules rules, Prov<Rules> resetter){
|
public void show(Rules rules, Prov<Rules> resetter){
|
||||||
@@ -157,7 +163,7 @@ public class CustomRulesDialog extends BaseDialog{
|
|||||||
)).left().width(300f);
|
)).left().width(300f);
|
||||||
main.row();
|
main.row();
|
||||||
|
|
||||||
main.button("@bannedblocks", banDialog::show).left().width(300f);
|
main.button("@bannedblocks", () -> showBanned("@bannedblocks", ContentType.block, rules.bannedBlocks, Block::canBeBuilt)).left().width(300f);
|
||||||
main.row();
|
main.row();
|
||||||
|
|
||||||
title("@rules.title.unit");
|
title("@rules.title.unit");
|
||||||
@@ -167,6 +173,9 @@ public class CustomRulesDialog extends BaseDialog{
|
|||||||
number("@rules.unitdamagemultiplier", f -> rules.unitDamageMultiplier = f, () -> rules.unitDamageMultiplier);
|
number("@rules.unitdamagemultiplier", f -> rules.unitDamageMultiplier = f, () -> rules.unitDamageMultiplier);
|
||||||
number("@rules.unitbuildspeedmultiplier", f -> rules.unitBuildSpeedMultiplier = f, () -> rules.unitBuildSpeedMultiplier, 0.001f, 50f);
|
number("@rules.unitbuildspeedmultiplier", f -> rules.unitBuildSpeedMultiplier = f, () -> rules.unitBuildSpeedMultiplier, 0.001f, 50f);
|
||||||
|
|
||||||
|
main.button("@bannedunits", () -> showBanned("@bannedunits", ContentType.unit, rules.bannedUnits, u -> !u.isHidden())).left().width(300f);
|
||||||
|
main.row();
|
||||||
|
|
||||||
title("@rules.title.enemy");
|
title("@rules.title.enemy");
|
||||||
check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode);
|
check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode);
|
||||||
check("@rules.buildai", b -> rules.teams.get(rules.waveTeam).ai = rules.teams.get(rules.waveTeam).infiniteResources = b, () -> rules.teams.get(rules.waveTeam).ai);
|
check("@rules.buildai", b -> rules.teams.get(rules.waveTeam).ai = rules.teams.get(rules.waveTeam).infiniteResources = b, () -> rules.teams.get(rules.waveTeam).ai);
|
||||||
|
|||||||
@@ -71,11 +71,11 @@ public class PayloadSource extends PayloadBlock{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean canProduce(Block b){
|
public boolean canProduce(Block b){
|
||||||
return b.isVisible() && b.size < size && !(b instanceof CoreBlock);
|
return b.isVisible() && b.size < size && !(b instanceof CoreBlock) && !state.rules.bannedBlocks.contains(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canProduce(UnitType t){
|
public boolean canProduce(UnitType t){
|
||||||
return !t.isHidden();
|
return !t.isHidden() && !t.isBanned();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PayloadSourceBuild extends PayloadBlockBuild<Payload>{
|
public class PayloadSourceBuild extends PayloadBlockBuild<Payload>{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import arc.*;
|
|||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
|
import arc.scene.style.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import arc.util.io.*;
|
import arc.util.io.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
@@ -13,16 +14,31 @@ import mindustry.entities.*;
|
|||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class UnitPayload implements Payload{
|
public class UnitPayload implements Payload{
|
||||||
public static final float deactiveDuration = 40f;
|
public static final float overlayDuration = 40f;
|
||||||
|
|
||||||
public Unit unit;
|
public Unit unit;
|
||||||
public float deactiveTime = 0f;
|
public float overlayTime = 0f;
|
||||||
|
public @Nullable TextureRegion overlayRegion;
|
||||||
|
|
||||||
public UnitPayload(Unit unit){
|
public UnitPayload(Unit unit){
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Flashes a red overlay region. */
|
||||||
|
public void showOverlay(TextureRegion icon){
|
||||||
|
overlayRegion = icon;
|
||||||
|
overlayTime = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Flashes a red overlay region. */
|
||||||
|
public void showOverlay(TextureRegionDrawable icon){
|
||||||
|
if(icon == null || headless) return;
|
||||||
|
showOverlay(icon.getRegion());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(Writes write){
|
public void write(Writes write){
|
||||||
write.b(payloadUnit);
|
write.b(payloadUnit);
|
||||||
@@ -62,7 +78,8 @@ public class UnitPayload implements Payload{
|
|||||||
if(unit.type == null) return true;
|
if(unit.type == null) return true;
|
||||||
|
|
||||||
if(!Units.canCreate(unit.team, unit.type)){
|
if(!Units.canCreate(unit.team, unit.type)){
|
||||||
deactiveTime = 1f;
|
overlayTime = 1f;
|
||||||
|
overlayRegion = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,16 +120,17 @@ public class UnitPayload implements Payload{
|
|||||||
unit.type.drawCell(unit);
|
unit.type.drawCell(unit);
|
||||||
|
|
||||||
//draw warning
|
//draw warning
|
||||||
if(deactiveTime > 0){
|
if(overlayTime > 0){
|
||||||
|
var region = overlayRegion == null ? Icon.warning.getRegion() : overlayRegion;
|
||||||
Draw.color(Color.scarlet);
|
Draw.color(Color.scarlet);
|
||||||
Draw.alpha(0.8f * Interp.exp5Out.apply(deactiveTime));
|
Draw.alpha(0.8f * Interp.exp5Out.apply(overlayTime));
|
||||||
|
|
||||||
float size = 8f;
|
float size = 8f;
|
||||||
Draw.rect(Icon.warning.getRegion(), unit.x, unit.y, size, size);
|
Draw.rect(region, unit.x, unit.y, size, size);
|
||||||
|
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
|
|
||||||
deactiveTime = Math.max(deactiveTime - Time.delta/deactiveDuration, 0f);
|
overlayTime = Math.max(overlayTime - Time.delta/overlayDuration, 0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,11 +116,28 @@ public class Reconstructor extends UnitBlock{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptPayload(Building source, Payload payload){
|
public boolean acceptPayload(Building source, Payload payload){
|
||||||
return this.payload == null
|
if(!(this.payload == null
|
||||||
&& (this.enabled || source == this)
|
&& (this.enabled || source == this)
|
||||||
&& relativeTo(source) != rotation
|
&& relativeTo(source) != rotation
|
||||||
&& payload instanceof UnitPayload pay
|
&& payload instanceof UnitPayload pay)){
|
||||||
&& hasUpgrade(pay.unit.type);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var upgrade = upgrade(pay.unit.type);
|
||||||
|
|
||||||
|
if(upgrade != null){
|
||||||
|
if(!upgrade.unlockedNow()){
|
||||||
|
//flash "not researched"
|
||||||
|
pay.showOverlay(Icon.tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(upgrade.isBanned()){
|
||||||
|
//flash an X, meaning 'banned'
|
||||||
|
pay.showOverlay(Icon.cancel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return upgrade != null && upgrade.unlockedNow() && !upgrade.isBanned();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -224,7 +241,7 @@ public class Reconstructor extends UnitBlock{
|
|||||||
|
|
||||||
public boolean hasUpgrade(UnitType type){
|
public boolean hasUpgrade(UnitType type){
|
||||||
UnitType t = upgrade(type);
|
UnitType t = upgrade(type);
|
||||||
return t != null && t.unlockedNow();
|
return t != null && t.unlockedNow() && !type.isBanned();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnitType upgrade(UnitType type){
|
public UnitType upgrade(UnitType type){
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ public class UnitFactory extends UnitBlock{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void buildConfiguration(Table table){
|
public void buildConfiguration(Table table){
|
||||||
Seq<UnitType> units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow());
|
Seq<UnitType> units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow() && !u.isBanned());
|
||||||
|
|
||||||
if(units.any()){
|
if(units.any()){
|
||||||
ItemSelection.buildTable(table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit)));
|
ItemSelection.buildTable(table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit)));
|
||||||
@@ -225,6 +225,12 @@ public class UnitFactory extends UnitBlock{
|
|||||||
if(currentPlan != -1 && payload == null){
|
if(currentPlan != -1 && payload == null){
|
||||||
UnitPlan plan = plans.get(currentPlan);
|
UnitPlan plan = plans.get(currentPlan);
|
||||||
|
|
||||||
|
//make sure to reset plan when the unit got banned after placement
|
||||||
|
if(plan.unit.isBanned()){
|
||||||
|
currentPlan = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(progress >= plan.time && consValid()){
|
if(progress >= plan.time && consValid()){
|
||||||
progress %= 1f;
|
progress %= 1f;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user