Prototype unit cap mechanic
This commit is contained in:
@@ -591,6 +591,7 @@ bar.poweramount = Power: {0}
|
||||
bar.poweroutput = Power Output: {0}
|
||||
bar.items = Items: {0}
|
||||
bar.capacity = Capacity: {0}
|
||||
bar.units = Units: {0}/{1}
|
||||
bar.liquid = Liquid
|
||||
bar.heat = Heat
|
||||
bar.power = Power
|
||||
|
||||
@@ -39,8 +39,10 @@ public class BlockIndexer{
|
||||
private ObjectSet<Item> allOres = new ObjectSet<>();
|
||||
/** Stores teams that are present here as tiles. */
|
||||
private Array<Team> activeTeams = new Array<>();
|
||||
/** Maps teams to a map of flagged tiles by type. */
|
||||
/** Maps teams to a map of flagged tiles by flag. */
|
||||
private TileArray[][] flagMap = new TileArray[Team.all().length][BlockFlag.all.length];
|
||||
/** Max units by team. */
|
||||
private int[] unitCaps = new int[Team.all().length];
|
||||
/** Maps tile positions to their last known tile index data. */
|
||||
private IntMap<TileIndex> typeMap = new IntMap<>();
|
||||
/** Empty set used for returning. */
|
||||
@@ -55,6 +57,10 @@ public class BlockIndexer{
|
||||
for(BlockFlag flag : index.flags){
|
||||
getFlagged(index.team)[flag.ordinal()].remove(event.tile);
|
||||
}
|
||||
|
||||
if(index.flags.contains(BlockFlag.unitModifier)){
|
||||
updateCap(index.team);
|
||||
}
|
||||
}
|
||||
process(event.tile);
|
||||
updateQuadrant(event.tile);
|
||||
@@ -65,6 +71,7 @@ public class BlockIndexer{
|
||||
scanOres.addAll(Item.getAllOres());
|
||||
damagedTiles = new TileArray[Team.all().length];
|
||||
flagMap = new TileArray[Team.all().length][BlockFlag.all.length];
|
||||
unitCaps = new int[Team.all().length];
|
||||
|
||||
for(int i = 0; i < flagMap.length; i++){
|
||||
for(int j = 0; j < BlockFlag.all.length; j++){
|
||||
@@ -296,6 +303,19 @@ public class BlockIndexer{
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return extra unit cap of a team. This is added onto the base value. */
|
||||
public int getExtraUnits(Team team){
|
||||
return unitCaps[team.id];
|
||||
}
|
||||
|
||||
private void updateCap(Team team){
|
||||
TileArray capped = getFlagged(team)[BlockFlag.unitModifier.ordinal()];
|
||||
unitCaps[team.id] = 0;
|
||||
for(Tile capper : capped){
|
||||
unitCaps[team.id] += capper.block().unitCapModifier;
|
||||
}
|
||||
}
|
||||
|
||||
private void process(Tile tile){
|
||||
if(tile.block().flags.size() > 0 && tile.team() != Team.derelict){
|
||||
TileArray[] map = getFlagged(tile.team());
|
||||
@@ -308,6 +328,11 @@ public class BlockIndexer{
|
||||
|
||||
map[flag.ordinal()] = arr;
|
||||
}
|
||||
|
||||
if(tile.block().flags.contains(BlockFlag.unitModifier)){
|
||||
updateCap(tile.team());
|
||||
}
|
||||
|
||||
typeMap.put(tile.pos(), new TileIndex(tile.block().flags, tile.team()));
|
||||
}
|
||||
if(!activeTeams.contains(tile.team())){
|
||||
|
||||
@@ -11,6 +11,7 @@ import mindustry.gen.*;
|
||||
public class TeamIndexProcess implements AsyncProcess{
|
||||
private QuadTree<Unitc>[] trees = new QuadTree[Team.all().length];
|
||||
private Array<Team> active = new Array<>();
|
||||
private int[] counts = new int[Team.all().length];
|
||||
|
||||
public QuadTree<Unitc> tree(Team team){
|
||||
if(trees[team.uid] == null) trees[team.uid] = new QuadTree<>(Vars.world.getQuadBounds(new Rect()));
|
||||
@@ -18,9 +19,18 @@ public class TeamIndexProcess implements AsyncProcess{
|
||||
return trees[team.uid];
|
||||
}
|
||||
|
||||
public int count(Team team){
|
||||
return counts[team.id];
|
||||
}
|
||||
|
||||
public void updateCount(Team team, int amount){
|
||||
counts[team.id] += amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(){
|
||||
active.clear();
|
||||
counts = new int[Team.all().length];
|
||||
trees = new QuadTree[Team.all().length];
|
||||
}
|
||||
|
||||
@@ -38,8 +48,13 @@ public class TeamIndexProcess implements AsyncProcess{
|
||||
}
|
||||
}
|
||||
|
||||
for(Team team : active){
|
||||
counts[team.id] = 0;
|
||||
}
|
||||
|
||||
for(Unitc unit : Groups.unit){
|
||||
tree(unit.team()).insert(unit);
|
||||
counts[unit.team().id] ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -293,7 +293,10 @@ public class NetServer implements ApplicationListener{
|
||||
});
|
||||
|
||||
clientCommands.<Playerc>register("t", "<message...>", "Send a message only to your teammates.", (args, player) -> {
|
||||
Groups.player.each(p -> p.team() == player.team(), o -> o.sendMessage(args[0], player, "[#" + player.team().color.toString() + "]<T>" + NetClient.colorizeName(player.id(), player.name())));
|
||||
String message = admins.filterMessage(player, args[0]);
|
||||
if(message != null){
|
||||
Groups.player.each(p -> p.team() == player.team(), o -> o.sendMessage(message, player, "[#" + player.team().color.toString() + "]<T>" + NetClient.colorizeName(player.id(), player.name())));
|
||||
}
|
||||
});
|
||||
|
||||
//duration of a a kick in seconds
|
||||
|
||||
@@ -15,6 +15,15 @@ public class Units{
|
||||
private static float cdist;
|
||||
private static boolean boolResult;
|
||||
|
||||
/** @return whether a new instance of a unit of this team can be created. */
|
||||
public static boolean canCreate(Team team){
|
||||
return teamIndex.count(team) < getCap(team);
|
||||
}
|
||||
|
||||
public static int getCap(Team team){
|
||||
return state.rules.unitCap + indexer.getExtraUnits(team);
|
||||
}
|
||||
|
||||
/** @return whether this player can interact with a specific tile. if either of these are null, returns true.*/
|
||||
public static boolean canInteract(Playerc player, Tilec tile){
|
||||
return player == null || tile == null || tile.interactable(player.team());
|
||||
|
||||
@@ -115,6 +115,16 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
type(this.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(){
|
||||
teamIndex.updateCount(team(), 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(){
|
||||
teamIndex.updateCount(team(), -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
drag(type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f));
|
||||
|
||||
@@ -58,6 +58,8 @@ public class Rules{
|
||||
public float bossWaveMultiplier = 3f;
|
||||
/** How many times longer a launch wave takes. */
|
||||
public float launchWaveMultiplier = 2f;
|
||||
/** Base unit cap. Can still be increased by blocks. */
|
||||
public int unitCap = 10;
|
||||
/** Sector for saves that have them.*/
|
||||
public @Nullable Sector sector;
|
||||
/** Region that save is on. Indicates campaign. TODO not implemented. */
|
||||
|
||||
@@ -106,6 +106,9 @@ public class Block extends UnlockableContent{
|
||||
public EnumSet<BlockFlag> flags = EnumSet.of();
|
||||
/** Targeting priority of this block, as seen by enemies.*/
|
||||
public TargetPriority priority = TargetPriority.base;
|
||||
/** How much this block affects the unit cap by.
|
||||
* The block flags must contain unitModifier in order for this to work. */
|
||||
public int unitCapModifier = 0;
|
||||
/** Whether the block can be tapped and selected to configure. */
|
||||
public boolean configurable;
|
||||
/** Whether this block consumes touchDown events when tapped. */
|
||||
|
||||
@@ -8,6 +8,7 @@ import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
@@ -28,7 +29,8 @@ public class CoreBlock extends StorageBlock{
|
||||
solid = true;
|
||||
update = true;
|
||||
hasItems = true;
|
||||
flags = EnumSet.of(BlockFlag.core, BlockFlag.producer);
|
||||
flags = EnumSet.of(BlockFlag.core, BlockFlag.producer, BlockFlag.unitModifier);
|
||||
unitCapModifier = 30;
|
||||
activeSound = Sounds.respawning;
|
||||
activeSoundVolume = 1f;
|
||||
}
|
||||
@@ -59,6 +61,13 @@ public class CoreBlock extends StorageBlock{
|
||||
() -> Pal.items,
|
||||
() -> e.items().total() / (float)(((CoreEntity)e).storageCapacity * content.items().count(i -> i.type == ItemType.material))
|
||||
));
|
||||
|
||||
bars.add("units", e ->
|
||||
new Bar(
|
||||
() -> Core.bundle.format("bar.units", teamIndex.count(e.team()), Units.getCap(e.team())),
|
||||
() -> Pal.power,
|
||||
() -> (float)teamIndex.count(e.team()) / Units.getCap(e.team())
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
package mindustry.world.blocks.units;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.ai.BlockIndexer.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class CommandCenter extends Block{
|
||||
protected TextureRegionDrawable[] commandRegions = new TextureRegionDrawable[UnitCommand.all.length];
|
||||
protected Color topColor = Pal.command;
|
||||
protected Color bottomColor = Color.valueOf("5e5e5e");
|
||||
protected Effect effect = Fx.commandSend;
|
||||
|
||||
public CommandCenter(String name){
|
||||
super(name);
|
||||
|
||||
flags = EnumSet.of(BlockFlag.comandCenter);
|
||||
destructible = true;
|
||||
solid = true;
|
||||
configurable = true;
|
||||
config(Integer.class, (tile, value) -> {
|
||||
UnitCommand command = UnitCommand.all[value];
|
||||
((CommandCenter)tile.block()).effect.at(tile);
|
||||
|
||||
for(Tile center : indexer.getAllied(tile.team(), BlockFlag.comandCenter)){
|
||||
if(center.block() instanceof CommandCenter){
|
||||
CommandCenterEntity entity = center.ent();
|
||||
entity.command = command;
|
||||
}
|
||||
}
|
||||
|
||||
Groups.unit.each(t -> t.team() == tile.team(), u -> u.controller().command(command));
|
||||
Events.fire(new CommandIssueEvent(tile, command));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
super.load();
|
||||
|
||||
if(ui != null){
|
||||
for(UnitCommand cmd : UnitCommand.all){
|
||||
commandRegions[cmd.ordinal()] = ui.getIcon("command" + Strings.capitalize(cmd.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CommandCenterEntity extends TileEntity{
|
||||
public UnitCommand command = UnitCommand.attack;
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
float size = 6f;
|
||||
|
||||
Draw.color(bottomColor);
|
||||
Draw.rect(commandRegions[command.ordinal()].getRegion(), x, y - 1, size, size);
|
||||
Draw.color(topColor);
|
||||
Draw.rect(commandRegions[command.ordinal()].getRegion(), x, y, size, size);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
Table buttons = new Table();
|
||||
|
||||
for(UnitCommand cmd : UnitCommand.all){
|
||||
buttons.button(commandRegions[cmd.ordinal()], Styles.clearToggleTransi, () -> configure(cmd.ordinal()))
|
||||
.size(44).group(group).update(b -> b.setChecked(command == cmd));
|
||||
}
|
||||
table.add(buttons);
|
||||
table.row();
|
||||
table.label(() -> command.localized()).style(Styles.outlineLabel).center().growX().get().setAlignment(Align.center);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placed(){
|
||||
super.placed();
|
||||
TileArray set = indexer.getAllied(team, BlockFlag.comandCenter);
|
||||
|
||||
if(set.size() > 0){
|
||||
CommandCenterEntity oe = set.first().ent();
|
||||
command = oe.command;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoved(){
|
||||
super.onRemoved();
|
||||
|
||||
TileArray set = indexer.getAllied(team, BlockFlag.comandCenter);
|
||||
|
||||
if(set.size() == 1){
|
||||
Groups.unit.each(t -> t.team() == team, u -> u.controller().command(UnitCommand.all[0]));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer config(){
|
||||
return command.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.b(command.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
command = UnitCommand.all[read.b()];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,7 +220,7 @@ public class UnitFactory extends Block{
|
||||
if(currentPlan != -1){
|
||||
UnitPlan plan = plans[currentPlan];
|
||||
|
||||
if(progress >= plan.time/* && !Units.anyEntities(tile, !plan.unit.flying)*/){
|
||||
if(progress >= plan.time/* && !Units.anyEntities(tile, !plan.unit.flying)*/ && Units.canCreate(team)){
|
||||
progress = 0f;
|
||||
|
||||
Call.onUnitFactorySpawn(tile);
|
||||
|
||||
@@ -4,18 +4,14 @@ package mindustry.world.meta;
|
||||
public enum BlockFlag{
|
||||
/** Enemy core; primary target for all units. */
|
||||
core,
|
||||
/** Rally point for units.*/
|
||||
rally,
|
||||
/** Producer of important goods. */
|
||||
producer,
|
||||
/** A turret. */
|
||||
turret,
|
||||
/** Only the command center block.*/
|
||||
comandCenter,
|
||||
/** Repair point. */
|
||||
repair,
|
||||
/** Upgrade pad. */
|
||||
mechPad;
|
||||
/** Any block that boosts unit capacity. */
|
||||
unitModifier;
|
||||
|
||||
public final static BlockFlag[] all = values();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
org.gradle.daemon=true
|
||||
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
||||
archash=a9ac74c4165c71b4a2cddffe2d560717b9698d15
|
||||
archash=64304225a74ee3e2c2bd97fd1f23dc4042ba29e2
|
||||
|
||||
Reference in New Issue
Block a user