Internal loadout system / Starting drills / Bugfixes

This commit is contained in:
Anuken
2019-02-23 22:31:38 -05:00
parent b6c5f202e4
commit 1ed4e9f5bb
15 changed files with 194 additions and 57 deletions

View File

@@ -47,6 +47,8 @@ public class Vars{
public static final Team waveTeam = Team.red;
/**how many times longer a boss wave takes*/
public static final float bossWaveMultiplier = 3f;
/**how many times longer a launch wave takes*/
public static final float launchWaveMultiplier = 2f;
/**max chat message length*/
public static final int maxTextLength = 150;
/**max player name length in bytes*/

View File

@@ -12,6 +12,7 @@ import io.anuke.mindustry.game.EventType.WorldLoadEvent;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Teams.TeamData;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.world.Pos;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.BlockFlag;
@@ -162,7 +163,7 @@ public class Pathfinder{
if(other != null && (path.weights[dx][dy] > cost + other.cost || path.searches[dx][dy] < path.search)
&& passable(other, team)){
if(other.cost < 0) throw new IllegalArgumentException("Tile cost cannot be negative! " + other);
path.frontier.addFirst(world.tile(dx, dy).pos());
path.frontier.addFirst(Pos.get(dx, dy));
path.weights[dx][dy] = cost + other.cost;
path.searches[dx][dy] = (short)path.search;
}

View File

@@ -1,10 +1,44 @@
package io.anuke.mindustry.content;
import io.anuke.mindustry.game.ContentList;
import io.anuke.mindustry.type.Loadout;
public class Loadouts implements ContentList{
public static Loadout
basicShard,
basicFoundation,
basicNucleus;
@Override
public void load(){
basicShard = new Loadout(
" ### ",
" #1# ",
" ### ",
" ^ ^ ",
" ## ## ",
" C# C# "
);
basicFoundation = new Loadout(
" #### ",
" #### ",
" #2## ",
" #### ",
" ^ ^ ",
" ## ## ",
" C# C# "
);
basicNucleus = new Loadout(
" ##### ",
" ##### ",
" ##3## ",
" ##### ",
" >#####< ",
" ^ ^ ^ ^ ",
"#### ####",
"C#C# C#C#"
);
}
}

View File

@@ -116,8 +116,8 @@ public class Zones implements ContentList{
}};
frozenForest = new Zone("frozenForest", new MapGenerator("frozenForest", 2)
.decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.02))
.core(Blocks.coreFoundation)){{
.decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.02))){{
loadout = Loadouts.basicFoundation;
baseLaunchCost = ItemStack.with(Items.copper, 100);
startingItems = ItemStack.list(Items.copper, 400);
conditionWave = 10;
@@ -186,8 +186,8 @@ public class Zones implements ContentList{
}};
}};
ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1)
.core(Blocks.coreFoundation)){{
ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1)){{
loadout = Loadouts.basicFoundation;
baseLaunchCost = ItemStack.with(Items.copper, 200, Items.graphite, 50);
startingItems = ItemStack.list(Items.copper, 400);
conditionWave = 20;
@@ -279,8 +279,8 @@ public class Zones implements ContentList{
stainedMountains = new Zone("stainedMountains", new MapGenerator("stainedMountains", 2)
.dist(2.5f, true)
.decor(new Decoration(Blocks.stainedStone, Blocks.stainedBoulder, 0.01))
.core(Blocks.coreFoundation)){{
.decor(new Decoration(Blocks.stainedStone, Blocks.stainedBoulder, 0.01))){{
loadout = Loadouts.basicFoundation;
baseLaunchCost = ItemStack.with(Items.copper, 100, Items.lead, 200, Items.silicon, 100);
startingItems = ItemStack.list(Items.copper, 400, Items.lead, 100);
conditionWave = 10;
@@ -354,11 +354,11 @@ public class Zones implements ContentList{
}};
impact = new Zone("impact0079", new MapGenerator("impact0079", 2)
.core(Blocks.coreFoundation)
.decor(
new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01),
new Decoration(Blocks.metalFloor, Blocks.metalFloorDamaged, 0.02)
).drops(ItemStack.with(Items.copper, 2000, Items.lead, 1500, Items.silicon, 1000, Items.graphite, 2000, Items.pyratite, 2000, Items.titanium, 2000, Items.metaglass, 1000, Items.coal, 2000))){{
loadout = Loadouts.basicFoundation;
baseLaunchCost = ItemStack.with(Items.copper, 500, Items.lead, 500, Items.silicon, 100);
startingItems = ItemStack.list(Items.copper, 2000, Items.lead, 500, Items.silicon, 200);
itemRequirements = ItemStack.with(Items.silicon, 8000, Items.titanium, 6000, Items.graphite, 4000);
@@ -437,8 +437,8 @@ public class Zones implements ContentList{
}};
}};
desolateRift = new Zone("desolateRift", new MapGenerator("desolateRift")
.core(Blocks.coreNucleus).dist(2f)){{
desolateRift = new Zone("desolateRift", new MapGenerator("desolateRift").dist(2f)){{
loadout = Loadouts.basicNucleus;
baseLaunchCost = ItemStack.with(Items.copper, 500);
startingItems = ItemStack.list(Items.copper, 1500);
itemRequirements = ItemStack.with(Items.copper, 8000, Items.metaglass, 2000, Items.graphite, 3000);
@@ -540,8 +540,8 @@ public class Zones implements ContentList{
*/
nuclearComplex = new Zone("nuclearComplex", new MapGenerator("nuclearProductionComplex", 1)
.drops(ItemStack.with(Items.copper, 2000, Items.lead, 1500, Items.silicon, 1000, Items.graphite, 1000, Items.thorium, 200, Items.titanium, 2000, Items.metaglass, 1000))
.decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01))
.core(Blocks.coreNucleus)){{
.decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01))){{
loadout = Loadouts.basicNucleus;
baseLaunchCost = ItemStack.with(Items.copper, 500, Items.lead, 500, Items.silicon, 200, Items.metaglass, 100);
startingItems = ItemStack.list(Items.copper, 2500, Items.lead, 1500, Items.silicon, 800, Items.metaglass, 400);
itemRequirements = ItemStack.with(Items.copper, 10000, Items.titanium, 8000, Items.metaglass, 6000, Items.plastanium, 2000);

View File

@@ -80,7 +80,8 @@ public class Logic implements ApplicationListener{
public void runWave(){
world.spawner.spawnEnemies();
state.wave++;
state.wavetime = world.isZone() && world.getZone().isBossWave(state.wave) ? state.rules.waveSpacing * bossWaveMultiplier : state.rules.waveSpacing;
state.wavetime = world.isZone() && world.getZone().isBossWave(state.wave) ? state.rules.waveSpacing * bossWaveMultiplier :
world.isZone() && world.getZone().isLaunchWave(state.wave) ? state.rules.waveSpacing * launchWaveMultiplier : state.rules.waveSpacing;
Events.fire(new WaveEvent());
}

View File

@@ -11,6 +11,7 @@ import io.anuke.mindustry.maps.MapTileData;
import io.anuke.mindustry.maps.MapTileData.DataPosition;
import io.anuke.mindustry.maps.MapTileData.TileDataMarker;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.blocks.BlockPart;
import io.anuke.mindustry.world.blocks.Floor;
import static io.anuke.mindustry.Vars.content;
@@ -107,7 +108,7 @@ public enum EditorTool{
dest = floor ? bf : bw;
byte draw = editor.getDrawBlock().id;
if(dest == draw){
if(dest == draw || content.block(bw) instanceof BlockPart || content.block(bw).isMultiblock()){
return;
}

View File

@@ -1,20 +0,0 @@
package io.anuke.mindustry.game;
import io.anuke.mindustry.type.ContentType;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
public abstract class Loadout extends Content{
public final Block core;
Loadout(Block core){
this.core = core;
}
public abstract void setup(Tile tile);
@Override
public ContentType getContentType(){
return ContentType.loadout;
}
}

View File

@@ -33,7 +33,7 @@ public class Stats{
score += (float)((wavesLasted - zone.conditionWave) / zone.launchPeriod + 1) * 1.5f;
}
int capacity = zone.generator.coreBlock.itemCapacity;
int capacity = zone.loadout.core().itemCapacity;
//weigh used fractions of
float frac = 0f;

View File

@@ -1,5 +1,6 @@
package io.anuke.mindustry.maps.generators;
import io.anuke.mindustry.type.Loadout;
import io.anuke.mindustry.world.Tile;
public abstract class Generator{
@@ -12,7 +13,7 @@ public abstract class Generator{
public Generator(){}
public void init(){
public void init(Loadout loadout){
}

View File

@@ -13,6 +13,7 @@ import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.maps.MapTileData;
import io.anuke.mindustry.maps.MapTileData.TileDataMarker;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.Loadout;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Floor;
@@ -27,6 +28,7 @@ public class MapGenerator extends Generator{
private Map map;
private String mapName;
private Array<Decoration> decorations = new Array<>();
private Loadout loadout;
/**How much the landscape is randomly distorted.*/
public float distortion = 3;
/**The amount of final enemy spawns used. -1 to use everything in the map.
@@ -36,7 +38,6 @@ public class MapGenerator extends Generator{
public boolean distortFloor = false;
/**Items randomly added to containers and vaults.*/
public ItemStack[] storageDrops = ItemStack.with(Items.copper, 300, Items.lead, 300, Items.silicon, 200, Items.graphite, 200, Items.blastCompound, 200);
public Block coreBlock = Blocks.coreShard;
public MapGenerator(String mapName){
this.mapName = mapName;
@@ -47,11 +48,6 @@ public class MapGenerator extends Generator{
this.enemySpawns = enemySpawns;
}
public MapGenerator core(Block block){
this.coreBlock = block;
return this;
}
public MapGenerator drops(ItemStack[] drops){
this.storageDrops = drops;
return this;
@@ -74,7 +70,8 @@ public class MapGenerator extends Generator{
}
@Override
public void init(){
public void init(Loadout loadout){
this.loadout = loadout;
map = world.maps.loadInternalMap(mapName);
width = map.meta.width;
height = map.meta.height;
@@ -87,7 +84,6 @@ public class MapGenerator extends Generator{
data.position(0, 0);
TileDataMarker marker = data.newDataMarker();
Array<Point2> players = new Array<>();
Array<Block> coreTypes = new Array<>();
Array<Point2> enemies = new Array<>();
for(int y = 0; y < data.height(); y++){
@@ -96,7 +92,6 @@ public class MapGenerator extends Generator{
if(content.block(marker.wall) instanceof CoreBlock){
players.add(new Point2(x, y));
coreTypes.add(content.block(marker.wall));
marker.wall = 0;
}
@@ -180,7 +175,7 @@ public class MapGenerator extends Generator{
throw new IllegalArgumentException("All zone maps must have a core.");
}
tiles[core.x][core.y].setBlock(coreBlock == null ? coreTypes.get(players.indexOf(core)) : coreBlock, defaultTeam);
loadout.setup(core.x, core.y);
world.prepareTiles(tiles);
world.setMap(map);

View File

@@ -0,0 +1,118 @@
package io.anuke.mindustry.type;
import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.IntMap;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.content.Items;
import io.anuke.mindustry.game.Content;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Pos;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Floor;
import io.anuke.mindustry.world.blocks.OreBlock;
import io.anuke.mindustry.world.blocks.storage.CoreBlock;
import static io.anuke.mindustry.Vars.defaultTeam;
import static io.anuke.mindustry.Vars.world;
public class Loadout extends Content{
private final static Array<Tile> outArray = new Array<>();
private final static IntMap<BlockEntry> entries = new IntMap<BlockEntry>(){{
put('>', new BlockEntry(Blocks.conveyor, 0));
put('^', new BlockEntry(Blocks.conveyor, 1));
put('<', new BlockEntry(Blocks.conveyor, 2));
put('v', new BlockEntry(Blocks.conveyor, 3));
put('1', new BlockEntry(Blocks.coreShard));
put('2', new BlockEntry(Blocks.coreFoundation));
put('3', new BlockEntry(Blocks.coreNucleus));
put('C', new BlockEntry(Blocks.mechanicalDrill, Items.copper));
}};
private final IntMap<BlockEntry> blocks = new IntMap<>();
private Block core;
public Loadout(String... layout){
int coreX = -1, coreY = -1;
outer:
for(int y = 0; y < layout.length; y ++){
for(int x = 0; x < layout[0].length(); x++){
char c = layout[y].charAt(x);
if(entries.get(c) != null && entries.get(c).block instanceof CoreBlock){
core = entries.get(c).block;
coreX = x;
coreY = y;
break outer;
}
}
}
if(coreX == -1) throw new IllegalArgumentException("Schematic does not have a core.");
for(int y = 0; y < layout.length; y ++){
for(int x = 0; x < layout[0].length(); x++){
char c = layout[y].charAt(x);
if(entries.containsKey(c)){
BlockEntry entry = entries.get(c);
blocks.put(Pos.get(x - coreX, layout.length - 1 - (y - coreY)), entry);
}
}
}
}
public Loadout(){
}
public Block core(){
return core;
}
public void setup(int x, int y){
for(IntMap.Entry<BlockEntry> entry : blocks.entries()){
int rx = Pos.x(entry.key);
int ry = Pos.y(entry.key);
Tile tile = world.tile(x + rx, y + ry);
world.setBlock(tile, entry.value.block, defaultTeam);
tile.setRotation((byte)entry.value.rotation);
if(entry.value.ore != null){
for(Tile t : tile.getLinkedTiles(outArray)){
Floor floor = t.floor();
t.setFloor(OreBlock.get(floor, entry.value.ore) == null ? OreBlock.get(Blocks.stone, entry.value.ore) : OreBlock.get(floor, entry.value.ore));
}
}
}
}
@Override
public ContentType getContentType(){
return ContentType.loadout;
}
static class BlockEntry{
final Block block;
final Item ore;
final int rotation;
BlockEntry(Block block, Item ore){
this.block = block;
this.ore = ore;
this.rotation = 0;
}
BlockEntry(Block block, int rotation){
this.block = block;
this.ore = null;
this.rotation = rotation;
}
BlockEntry(Block block){
this.block = block;
this.ore = null;
this.rotation = 0;
}
}
}

View File

@@ -6,13 +6,14 @@ import io.anuke.arc.collection.Array;
import io.anuke.arc.function.Supplier;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.content.Loadouts;
import io.anuke.mindustry.content.StatusEffects;
import io.anuke.mindustry.game.EventType.ZoneCompleteEvent;
import io.anuke.mindustry.game.EventType.ZoneConfigureCompleteEvent;
import io.anuke.mindustry.game.Loadout;
import io.anuke.mindustry.game.Rules;
import io.anuke.mindustry.game.SpawnGroup;
import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.mindustry.maps.generators.Generator;
import io.anuke.mindustry.maps.generators.MapGenerator;
import io.anuke.mindustry.world.Block;
@@ -20,7 +21,7 @@ import static io.anuke.mindustry.Vars.data;
import static io.anuke.mindustry.Vars.state;
public class Zone extends UnlockableContent{
public final MapGenerator generator;
public final Generator generator;
public Block[] blockRequirements = {};
public ItemStack[] itemRequirements = {};
public Zone[] zoneRequirements = {};
@@ -30,7 +31,7 @@ public class Zone extends UnlockableContent{
public int conditionWave = Integer.MAX_VALUE;
public int configureWave = 40;
public int launchPeriod = 10;
public Loadout loadout;
public Loadout loadout = Loadouts.basicShard;
protected ItemStack[] baseLaunchCost = {};
protected Array<ItemStack> startingItems = new Array<>();
@@ -54,6 +55,10 @@ public class Zone extends UnlockableContent{
return wave % configureWave == 0 && wave > 0;
}
public boolean isLaunchWave(int wave){
return metCondition() && wave % launchPeriod == 0;
}
public ItemStack[] getLaunchCost(){
if(launchCost == null){
updateLaunchCost();
@@ -126,7 +131,7 @@ public class Zone extends UnlockableContent{
@Override
public void init(){
generator.init();
generator.init(loadout);
Array<ItemStack> arr = Core.settings.getObject(name + "-starting-items", Array.class, () -> null);
if(arr != null){

View File

@@ -134,7 +134,7 @@ public class ZoneInfoDialog extends FloatingDialog{
rebuildItems.run();
}).size(bsize).pad(2);
load.addButton("+", () -> {
stack.amount = Math.min(stack.amount + step, zone.generator.coreBlock.itemCapacity);
stack.amount = Math.min(stack.amount + step, zone.loadout.core().itemCapacity);
zone.updateLaunchCost();
rebuildItems.run();
}).size(bsize).pad(2);
@@ -193,7 +193,7 @@ public class ZoneInfoDialog extends FloatingDialog{
hide();
world.playZone(zone);
}
}).margin(13f).padTop(5).disabled(b -> zone.locked() ? !canUnlock(zone) : !data.hasItems(zone.getLaunchCost())).get();
}).minWidth(150f).margin(13f).padTop(5).disabled(b -> zone.locked() ? !canUnlock(zone) : !data.hasItems(zone.getLaunchCost())).get();
button.row();
button.add(iteminfo);

View File

@@ -241,7 +241,7 @@ public class HudFragment extends Fragment{
world.getZone().metCondition() &&
!Net.client() &&
state.wave % world.getZone().launchPeriod == 0 &&
state.wavetime < state.rules.waveSpacing - 70);
state.wavetime < state.rules.waveSpacing * launchWaveMultiplier - 70);
button.update(() -> {
if(world.getZone() == null){

View File

@@ -8,7 +8,7 @@ import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
public class OreBlock extends Floor{
private static final ObjectMap<Item, ObjectMap<Block, Block>> oreBlockMap = new ObjectMap<>();
private static final ObjectMap<Item, ObjectMap<Block, Floor>> oreBlockMap = new ObjectMap<>();
public Floor base;
@@ -52,9 +52,8 @@ public class OreBlock extends Floor{
return other != base;
}
public static Block get(Block floor, Item item){
if(!oreBlockMap.containsKey(item)) throw new IllegalArgumentException("Item '" + item + "' is not an ore!");
if(!oreBlockMap.get(item).containsKey(floor)) throw new IllegalArgumentException("Block '" + floor.name + "' does not support ores!");
public static Floor get(Block floor, Item item){
if(!oreBlockMap.containsKey(item) || !oreBlockMap.get(item).containsKey(floor)) return null;
return oreBlockMap.get(item).get(floor);
}
}