New system for Serpulo sector loss (WIP)
This commit is contained in:
@@ -20,6 +20,7 @@ import mindustry.game.*;
|
|||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.game.Objectives.*;
|
import mindustry.game.Objectives.*;
|
||||||
import mindustry.game.Saves.*;
|
import mindustry.game.Saves.*;
|
||||||
|
import mindustry.game.Teams.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.input.*;
|
import mindustry.input.*;
|
||||||
import mindustry.io.*;
|
import mindustry.io.*;
|
||||||
@@ -419,7 +420,7 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
ui.planet.hide();
|
ui.planet.hide();
|
||||||
SaveSlot slot = sector.save;
|
SaveSlot slot = sector.save;
|
||||||
sector.planet.setLastSector(sector);
|
sector.planet.setLastSector(sector);
|
||||||
if(slot != null && !clearSectors && (!(sector.planet.clearSectorOnLose || sector.info.hasWorldProcessor) || sector.info.hasCore)){
|
if(slot != null && !clearSectors && (!sector.planet.clearSectorOnLose || sector.info.hasCore)){
|
||||||
|
|
||||||
try{
|
try{
|
||||||
boolean hadNoCore = !sector.info.hasCore;
|
boolean hadNoCore = !sector.info.hasCore;
|
||||||
@@ -433,7 +434,7 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
//if there is no base, simulate a new game and place the right loadout at the spawn position
|
//if there is no base, simulate a new game and place the right loadout at the spawn position
|
||||||
if(state.rules.defaultTeam.cores().isEmpty() || hadNoCore){
|
if(state.rules.defaultTeam.cores().isEmpty() || hadNoCore){
|
||||||
|
|
||||||
if(sector.planet.clearSectorOnLose || sector.info.hasWorldProcessor){
|
if(sector.planet.clearSectorOnLose){
|
||||||
playNewSector(origin, sector, reloader);
|
playNewSector(origin, sector, reloader);
|
||||||
}else{
|
}else{
|
||||||
//no spawn set -> delete the sector save
|
//no spawn set -> delete the sector save
|
||||||
@@ -446,61 +447,63 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int spawnPos = sector.info.spawnPosition;
|
||||||
|
|
||||||
//set spawn for sector damage to use
|
//set spawn for sector damage to use
|
||||||
Tile spawn = world.tile(sector.info.spawnPosition);
|
Tile spawn = world.tile(spawnPos);
|
||||||
spawn.setBlock(sector.planet.defaultCore, state.rules.defaultTeam);
|
spawn.setBlock(sector.planet.defaultCore, state.rules.defaultTeam);
|
||||||
|
|
||||||
//add extra damage.
|
//apply damage to simulate the sector being lost
|
||||||
SectorDamage.apply(1f);
|
SectorDamage.apply(1f);
|
||||||
|
|
||||||
//reset wave so things are more fair
|
//save the plans and buildings from the previous save; they will be used to re-populate the sector
|
||||||
state.wave = 1;
|
var previousPlans = state.rules.defaultTeam.data().plans.toArray(BlockPlan.class);
|
||||||
//set up default wave time
|
var previousBuildings = state.rules.defaultTeam.data().buildings.<Building>toArray(Building.class);
|
||||||
state.wavetime = state.rules.initialWaveSpacing <= 0f ? (state.rules.waveSpacing * (sector.preset == null ? 2f : sector.preset.startWaveTimeMultiplier)) : state.rules.initialWaveSpacing;
|
var previousDerelicts = Team.derelict.data().buildings.<Building>toArray(Building.class);
|
||||||
state.wavetime *= sector.planet.campaignRules.difficulty.waveTimeMultiplier;
|
|
||||||
//reset captured state
|
|
||||||
sector.info.wasCaptured = false;
|
|
||||||
|
|
||||||
if(state.rules.sector.planet.allowWaves){
|
logic.reset();
|
||||||
//re-enable waves
|
|
||||||
state.rules.waves = true;
|
|
||||||
//reset win wave??
|
|
||||||
state.rules.winWave = state.rules.attackMode ? -1 : sector.preset != null && sector.preset.captureWave > 0 ? sector.preset.captureWave : state.rules.winWave > state.wave ? state.rules.winWave : 30;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if there's still an enemy base left, fix it
|
//now, load a fresh save; the old one was only used to grab previous building data
|
||||||
if(state.rules.attackMode){
|
playNewSector(origin, sector, reloader, new WorldParams(){{
|
||||||
//replace all broken blocks
|
corePositionOverride = spawnPos;
|
||||||
for(var plan : state.rules.waveTeam.data().plans){
|
}}, () -> {
|
||||||
Tile tile = world.tile(plan.x, plan.y);
|
var teamData = state.rules.defaultTeam.data();
|
||||||
if(tile != null){
|
|
||||||
tile.setBlock(plan.block, state.rules.waveTeam, plan.rotation);
|
//all the old derelicts have to be removed.
|
||||||
if(plan.config != null && tile.build != null){
|
for(var generatedDerelict : Team.derelict.data().buildings.<Building>toArray(Building.class)){
|
||||||
tile.build.configureAny(plan.config);
|
generatedDerelict.tile.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//retain old derelicts from the previous save.
|
||||||
|
for(var build : previousDerelicts){
|
||||||
|
Tile tile = world.tile(build.tileX(), build.tileY());
|
||||||
|
if(tile != null && tile.build == null && Build.validPlace(build.block, Team.derelict, build.tileX(), build.tileY(), build.rotation, false, false)){
|
||||||
|
tile.setBlock(build.block, Team.derelict, build.rotation, () -> build);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.rules.waveTeam.data().plans.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
//kill all units, since they should be dead anyway
|
//copy over all buildings from the previous save, retaining config and health, and making them derelict. contents are not saved (derelict repair clears them anyway)
|
||||||
Groups.unit.clear();
|
for(var build : previousBuildings){
|
||||||
Groups.fire.clear();
|
Tile tile = world.tile(build.tileX(), build.tileY());
|
||||||
Groups.puddle.clear();
|
if(tile != null && tile.build == null && Build.validPlace(build.block, state.rules.defaultTeam, build.tileX(), build.tileY(), build.rotation, false, false)){
|
||||||
|
tile.setBlock(build.block, state.rules.defaultTeam, build.rotation, () -> build);
|
||||||
|
build.changeTeam(Team.derelict);
|
||||||
|
build.dropped(); //TODO: call pickedUp too? this may screw up power networks in a major way as they refer to potentially deleted entities
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//reset to 0, so replaced cores don't count
|
for(var build : previousBuildings){
|
||||||
state.rules.defaultTeam.data().unitCap = 0;
|
build.updateProximity();
|
||||||
Schematics.placeLaunchLoadout(spawn.x, spawn.y);
|
}
|
||||||
|
|
||||||
//set up camera/player locations
|
//carry over all previous plans that don't already have the corresponding block at their position
|
||||||
player.set(spawn.x * tilesize, spawn.y * tilesize);
|
for(var plan : previousPlans){
|
||||||
camera.position.set(player);
|
var build = world.build(plan.x, plan.y);
|
||||||
|
if(!(build != null && build.block == plan.block && build.tileX() == plan.x && build.tileY() == plan.y && build.team != state.rules.waveTeam)){
|
||||||
Events.fire(new SectorLaunchEvent(sector));
|
teamData.plans.add(plan);
|
||||||
Events.fire(Trigger.newGame);
|
}
|
||||||
|
}
|
||||||
state.set(State.playing);
|
});
|
||||||
reloader.end();
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
state.set(State.playing);
|
state.set(State.playing);
|
||||||
@@ -522,12 +525,20 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void playNewSector(@Nullable Sector origin, Sector sector, WorldReloader reloader){
|
public void playNewSector(@Nullable Sector origin, Sector sector, WorldReloader reloader){
|
||||||
|
playNewSector(origin, sector, reloader, new WorldParams(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void playNewSector(@Nullable Sector origin, Sector sector, WorldReloader reloader, WorldParams params, @Nullable Runnable beforePlay){
|
||||||
reloader.begin();
|
reloader.begin();
|
||||||
world.loadSector(sector);
|
world.loadSector(sector, params);
|
||||||
state.rules.sector = sector;
|
state.rules.sector = sector;
|
||||||
//assign origin when launching
|
|
||||||
sector.info.origin = origin;
|
sector.info.origin = origin;
|
||||||
sector.info.destination = origin;
|
sector.info.destination = origin;
|
||||||
|
|
||||||
|
if(beforePlay != null){
|
||||||
|
beforePlay.run();
|
||||||
|
}
|
||||||
|
|
||||||
logic.play();
|
logic.play();
|
||||||
control.saves.saveSector(sector);
|
control.saves.saveSector(sector);
|
||||||
Events.fire(new SectorLaunchEvent(sector));
|
Events.fire(new SectorLaunchEvent(sector));
|
||||||
|
|||||||
@@ -259,19 +259,19 @@ public class World{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadSector(Sector sector){
|
public void loadSector(Sector sector){
|
||||||
loadSector(sector, 0, true);
|
loadSector(sector, new WorldParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadSector(Sector sector, int seedOffset, boolean saveInfo){
|
public void loadSector(Sector sector, WorldParams params){
|
||||||
setSectorRules(sector, saveInfo);
|
setSectorRules(sector, params.saveInfo);
|
||||||
|
|
||||||
int size = sector.getSize();
|
int size = sector.getSize();
|
||||||
loadGenerator(size, size, tiles -> {
|
loadGenerator(size, size, tiles -> {
|
||||||
if(sector.preset != null){
|
if(sector.preset != null){
|
||||||
sector.preset.generator.generate(tiles);
|
sector.preset.generator.generate(tiles, params);
|
||||||
sector.preset.rules.get(state.rules); //apply extra rules
|
sector.preset.rules.get(state.rules); //apply extra rules
|
||||||
}else if(sector.planet.generator != null){
|
}else if(sector.planet.generator != null){
|
||||||
sector.planet.generator.generate(tiles, sector, seedOffset);
|
sector.planet.generator.generate(tiles, sector, params);
|
||||||
}else{
|
}else{
|
||||||
throw new RuntimeException("Sector " + sector.id + " on planet " + sector.planet.name + " has no generator or preset defined. Provide a planet generator or preset map.");
|
throw new RuntimeException("Sector " + sector.id + " on planet " + sector.planet.name + " has no generator or preset defined. Provide a planet generator or preset map.");
|
||||||
}
|
}
|
||||||
@@ -279,7 +279,7 @@ public class World{
|
|||||||
state.rules.sector = sector;
|
state.rules.sector = sector;
|
||||||
});
|
});
|
||||||
|
|
||||||
if(saveInfo && state.rules.waves){
|
if(params.saveInfo && state.rules.waves){
|
||||||
sector.info.waves = state.rules.waves;
|
sector.info.waves = state.rules.waves;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +289,7 @@ public class World{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//reset rules
|
//reset rules
|
||||||
setSectorRules(sector, saveInfo);
|
setSectorRules(sector, params.saveInfo);
|
||||||
|
|
||||||
if(state.rules.defaultTeam.core() != null){
|
if(state.rules.defaultTeam.core() != null){
|
||||||
sector.info.spawnPosition = state.rules.defaultTeam.core().pos();
|
sector.info.spawnPosition = state.rules.defaultTeam.core().pos();
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ public class MapProcessorsDialog extends BaseDialog{
|
|||||||
|
|
||||||
processors.clear();
|
processors.clear();
|
||||||
|
|
||||||
//scan the entire world for processor (Groups.build can be empty, indexer is probably inaccurate)
|
//scan the entire world for processors (Groups.build can be empty, indexer is probably inaccurate)
|
||||||
Vars.world.tiles.eachTile(t -> {
|
Vars.world.tiles.eachTile(t -> {
|
||||||
if(t.isCenter() && t.block() == Blocks.worldProcessor){
|
if(t.isCenter() && t.block() == Blocks.worldProcessor){
|
||||||
processors.add(t.build);
|
processors.add(t.build);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import mindustry.graphics.*;
|
|||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
import mindustry.ui.dialogs.*;
|
import mindustry.ui.dialogs.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -94,7 +95,10 @@ public class SectorGenerateDialog extends BaseDialog{
|
|||||||
sectorobj.preset = null;
|
sectorobj.preset = null;
|
||||||
|
|
||||||
logic.reset(); //TODO: is this a good idea? all rules and map state are cleared, but it fixes inconsistent gen
|
logic.reset(); //TODO: is this a good idea? all rules and map state are cleared, but it fixes inconsistent gen
|
||||||
world.loadSector(sectorobj, seed, false);
|
var params = new WorldParams();
|
||||||
|
params.seedOffset = seed;
|
||||||
|
params.saveInfo = false;
|
||||||
|
world.loadSector(sectorobj, params);
|
||||||
|
|
||||||
sectorobj.preset = preset;
|
sectorobj.preset = preset;
|
||||||
|
|
||||||
|
|||||||
@@ -114,12 +114,35 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{
|
|||||||
if(plans.size > 1){
|
if(plans.size > 1){
|
||||||
int total = 0;
|
int total = 0;
|
||||||
int size = plans.size;
|
int size = plans.size;
|
||||||
BuildPlan plan;
|
float bestDst = Float.MAX_VALUE;
|
||||||
while((!within((plan = buildPlan()).tile(), finalPlaceDst) || shouldSkip(plan, core)) && total < size){
|
boolean foundAny = false;
|
||||||
|
int bestIndex = -1;
|
||||||
|
while(total < size){
|
||||||
|
var plan = buildPlan();
|
||||||
|
|
||||||
|
float dst = plan.dst2(this);
|
||||||
|
boolean within = dst <= finalPlaceDst*finalPlaceDst;
|
||||||
|
//if it's a valid plan within range, break out of the loop
|
||||||
|
if(within && !shouldSkip(plan, core)){
|
||||||
|
foundAny = true;
|
||||||
|
break;
|
||||||
|
}else if(within && dst < bestDst){ //it's still bad, but at least it's within build radius
|
||||||
|
bestIndex = total;
|
||||||
|
bestDst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
plans.removeFirst();
|
plans.removeFirst();
|
||||||
plans.addLast(plan);
|
plans.addLast(plan);
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//all the plans were useless, and the current one can't be reached. skip to the closest one, if applicable
|
||||||
|
if(!foundAny && bestIndex > 0 && !within(buildPlan(), finalPlaceDst)){
|
||||||
|
//this is slow, but should be rare in practice
|
||||||
|
for(int i = 0; i < bestIndex; i++){
|
||||||
|
plans.addLast(plans.removeFirst());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildPlan current = buildPlan();
|
BuildPlan current = buildPlan();
|
||||||
@@ -236,10 +259,10 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{
|
|||||||
|
|
||||||
/** @return whether this plan should be skipped, in favor of the next one. */
|
/** @return whether this plan should be skipped, in favor of the next one. */
|
||||||
boolean shouldSkip(BuildPlan plan, @Nullable Building core){
|
boolean shouldSkip(BuildPlan plan, @Nullable Building core){
|
||||||
//plans that you have at least *started* are considered
|
if(state.rules.infiniteResources || team.rules().infiniteResources || plan.breaking || core == null || plan.isRotation(team) || plan.isDerelictRepair()) return false;
|
||||||
if(state.rules.infiniteResources || team.rules().infiniteResources || plan.breaking || core == null || plan.isRotation(team) || (isBuilding() && !within(plans.last(), type.buildRange))) return false;
|
|
||||||
|
|
||||||
return (plan.stuck && !core.items.has(plan.block.requirements)) || (Structs.contains(plan.block.requirements, i -> !core.items.has(i.item, Math.min(i.amount, 15)) && Mathf.round(i.amount * state.rules.buildCostMultiplier) > 0) && !plan.initialized);
|
return (plan.stuck && !core.items.has(plan.block.requirements)) ||
|
||||||
|
(Structs.contains(plan.block.requirements, i -> !core.items.has(i.item, Math.min(i.amount, 15)) && Mathf.round(i.amount * state.rules.buildCostMultiplier) > 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeBuild(int x, int y, boolean breaking){
|
void removeBuild(int x, int y, boolean breaking){
|
||||||
|
|||||||
@@ -1333,6 +1333,12 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Called when this block is derelict repaired. */
|
||||||
|
@CallSuper
|
||||||
|
public void onRepaired(){
|
||||||
|
placed();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isCommandable(){
|
public boolean isCommandable(){
|
||||||
return block.commandable;
|
return block.commandable;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,12 @@ public class BuildPlan implements Position, QuadTreeObject{
|
|||||||
return tile != null && tile.team() == team && tile.block() == block && tile.build != null && tile.build.rotation != rotation;
|
return tile != null && tile.team() == team && tile.block() == block && tile.build != null && tile.build.rotation != rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDerelictRepair(){
|
||||||
|
if(breaking || !state.rules.derelictRepair) return false;
|
||||||
|
Tile tile = tile();
|
||||||
|
return tile != null && tile.team() == Team.derelict && tile.block() == block && tile.build != null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean samePos(BuildPlan other){
|
public boolean samePos(BuildPlan other){
|
||||||
return x == other.x && y == other.y;
|
return x == other.x && y == other.y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ public class SectorInfo{
|
|||||||
public int storageCapacity = 0;
|
public int storageCapacity = 0;
|
||||||
/** Whether a core is available here. */
|
/** Whether a core is available here. */
|
||||||
public boolean hasCore = true;
|
public boolean hasCore = true;
|
||||||
/** Whether a world processor is on this map - implies that the map will get cleared. */
|
|
||||||
public boolean hasWorldProcessor;
|
|
||||||
/** Whether this sector was ever fully captured. */
|
/** Whether this sector was ever fully captured. */
|
||||||
public boolean wasCaptured = false;
|
public boolean wasCaptured = false;
|
||||||
/** Sector that was launched from. */
|
/** Sector that was launched from. */
|
||||||
@@ -213,7 +211,6 @@ public class SectorInfo{
|
|||||||
spawnPosition = entity.pos();
|
spawnPosition = entity.pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
hasWorldProcessor = state.teams.present.contains(t -> t.getBuildings(Blocks.worldProcessor).any());
|
|
||||||
waveSpacing = state.rules.waveSpacing;
|
waveSpacing = state.rules.waveSpacing;
|
||||||
wave = state.wave;
|
wave = state.wave;
|
||||||
winWave = state.rules.winWave;
|
winWave = state.rules.winWave;
|
||||||
|
|||||||
@@ -483,8 +483,8 @@ public class SectorDamage{
|
|||||||
Tile other = tiles.getn(cx, cy);
|
Tile other = tiles.getn(cx, cy);
|
||||||
float resultDamage = currDamage;
|
float resultDamage = currDamage;
|
||||||
|
|
||||||
//damage the tile if it's not friendly
|
//damage the tile if it's the player team (derelict blocks get ignored)
|
||||||
if(other.build != null && other.team() != state.rules.waveTeam){
|
if(other.build != null && other.team() == state.rules.defaultTeam){
|
||||||
resultDamage -= other.build.health();
|
resultDamage -= other.build.health();
|
||||||
|
|
||||||
other.build.health -= currDamage;
|
other.build.health -= currDamage;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public abstract class BasicGenerator implements WorldGenerator{
|
|||||||
public Schematic defaultLoadout = Loadouts.basicShard;
|
public Schematic defaultLoadout = Loadouts.basicShard;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(Tiles tiles){
|
public void generate(Tiles tiles, WorldParams params){
|
||||||
this.tiles = tiles;
|
this.tiles = tiles;
|
||||||
this.width = tiles.width;
|
this.width = tiles.width;
|
||||||
this.height = tiles.height;
|
this.height = tiles.height;
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ public class BlankPlanetGenerator extends PlanetGenerator{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(Tiles tiles, Sector sec, int seed){
|
public void generate(Tiles tiles, Sector sec, WorldParams params){
|
||||||
this.tiles = tiles;
|
this.tiles = tiles;
|
||||||
this.sector = sec;
|
this.sector = sec;
|
||||||
this.rand.setSeed(sec.id + seed + baseSeed);
|
this.rand.setSeed(sec.id + params.seedOffset + baseSeed);
|
||||||
|
|
||||||
tiles.fill();
|
tiles.fill();
|
||||||
|
|
||||||
generate(tiles);
|
generate(tiles, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import mindustry.maps.*;
|
|||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.storage.*;
|
import mindustry.world.blocks.storage.*;
|
||||||
|
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ public class FileMapGenerator implements WorldGenerator{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(Tiles tiles){
|
public void generate(Tiles tiles, WorldParams params){
|
||||||
if(map == null) throw new RuntimeException("Generator has null map, cannot be used.");
|
if(map == null) throw new RuntimeException("Generator has null map, cannot be used.");
|
||||||
|
|
||||||
Sector sector = state.rules.sector;
|
Sector sector = state.rules.sector;
|
||||||
@@ -72,6 +73,9 @@ public class FileMapGenerator implements WorldGenerator{
|
|||||||
|
|
||||||
boolean anyCores = false;
|
boolean anyCores = false;
|
||||||
|
|
||||||
|
//TODO: unsure if indexer even works at this stage
|
||||||
|
Block coreTypeToUse = state.rules.defaultTeam.cores().isEmpty() ? sector.planet.defaultCore : state.rules.defaultTeam.core().block;
|
||||||
|
|
||||||
for(Tile tile : tiles){
|
for(Tile tile : tiles){
|
||||||
|
|
||||||
if(tile.overlay() == Blocks.spawn){
|
if(tile.overlay() == Blocks.spawn){
|
||||||
@@ -83,8 +87,26 @@ public class FileMapGenerator implements WorldGenerator{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tile.isCenter() && tile.block() instanceof CoreBlock && tile.team() == state.rules.defaultTeam && !anyCores){
|
if(params.corePositionOverride != 0 && sector != null){
|
||||||
if(state.rules.sector != null && state.rules.sector.allowLaunchLoadout()){
|
if(tile.pos() == params.corePositionOverride){
|
||||||
|
if(sector.allowLaunchLoadout()){
|
||||||
|
Schematics.placeLaunchLoadout(tile.x, tile.y);
|
||||||
|
}else{
|
||||||
|
//if there's an override and no loadout schematic is allowed, try to place a fitting core instead.
|
||||||
|
tile.setBlock(coreTypeToUse, state.rules.defaultTeam, 0);
|
||||||
|
}
|
||||||
|
anyCores = true;
|
||||||
|
|
||||||
|
if(preset.addStartingItems || !preset.planet.allowLaunchLoadout){
|
||||||
|
tile.build.items.clear();
|
||||||
|
tile.build.items.add(state.rules.loadout);
|
||||||
|
}
|
||||||
|
}else if(tile.build instanceof CoreBuild && tile.build.pos() != params.corePositionOverride){
|
||||||
|
//other cores placed must be cleared; they have been overridden
|
||||||
|
tile.remove();
|
||||||
|
}
|
||||||
|
}else if(tile.isCenter() && tile.block() instanceof CoreBlock && tile.team() == state.rules.defaultTeam && !anyCores){
|
||||||
|
if(sector != null && sector.allowLaunchLoadout()){
|
||||||
Schematics.placeLaunchLoadout(tile.x, tile.y);
|
Schematics.placeLaunchLoadout(tile.x, tile.y);
|
||||||
}
|
}
|
||||||
anyCores = true;
|
anyCores = true;
|
||||||
|
|||||||
@@ -178,13 +178,13 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe
|
|||||||
return res % 2 == 0 ? res : res + 1;
|
return res % 2 == 0 ? res : res + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generate(Tiles tiles, Sector sec, int seed){
|
public void generate(Tiles tiles, Sector sec, WorldParams params){
|
||||||
this.tiles = tiles;
|
this.tiles = tiles;
|
||||||
this.seed = seed + baseSeed;
|
this.seed = params.seedOffset + baseSeed;
|
||||||
this.sector = sec;
|
this.sector = sec;
|
||||||
this.width = tiles.width;
|
this.width = tiles.width;
|
||||||
this.height = tiles.height;
|
this.height = tiles.height;
|
||||||
this.rand.setSeed(sec.id + seed + baseSeed);
|
this.rand.setSeed(sec.id + params.seedOffset + baseSeed);
|
||||||
|
|
||||||
TileGen gen = new TileGen();
|
TileGen gen = new TileGen();
|
||||||
for(int y = 0; y < height; y++){
|
for(int y = 0; y < height; y++){
|
||||||
@@ -197,6 +197,6 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generate(tiles);
|
generate(tiles, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package mindustry.maps.generators;
|
|||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
|
||||||
public interface WorldGenerator{
|
public interface WorldGenerator{
|
||||||
void generate(Tiles tiles);
|
void generate(Tiles tiles, WorldParams params);
|
||||||
|
|
||||||
/** Do not modify tiles here. This is only for specialized configuration. */
|
/** Do not modify tiles here. This is only for specialized configuration. */
|
||||||
default void postGenerate(Tiles tiles){}
|
default void postGenerate(Tiles tiles){}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
public class IconSelectDialog extends Dialog{
|
public class IconSelectDialog extends Dialog{
|
||||||
private Intc consumer = i -> Log.info("you have mere seconds");
|
private Intc consumer = i -> Log.info("you have mere seconds");
|
||||||
private boolean allowLocked;
|
|
||||||
|
|
||||||
public IconSelectDialog(){
|
public IconSelectDialog(){
|
||||||
this(true);
|
this(true);
|
||||||
|
|||||||
@@ -1122,10 +1122,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
if(sector.save != null){
|
sector.info.hasCore = false;
|
||||||
sector.save.delete();
|
sector.saveInfo();
|
||||||
}
|
|
||||||
sector.save = null;
|
|
||||||
}
|
}
|
||||||
updateSelected();
|
updateSelected();
|
||||||
rebuildList();
|
rebuildList();
|
||||||
|
|||||||
@@ -92,26 +92,21 @@ public class Build{
|
|||||||
|
|
||||||
//repair derelict tile
|
//repair derelict tile
|
||||||
if(tile.team() == Team.derelict && team != Team.derelict && tile.block == result && tile.build != null && tile.block.allowDerelictRepair && state.rules.derelictRepair){
|
if(tile.team() == Team.derelict && team != Team.derelict && tile.block == result && tile.build != null && tile.block.allowDerelictRepair && state.rules.derelictRepair){
|
||||||
float healthf = tile.build.healthf();
|
tile.build.rotation = rotation;
|
||||||
var config = tile.build.config();
|
tile.build.changeTeam(team);
|
||||||
|
tile.build.enabled = true;
|
||||||
tile.setBlock(result, team, rotation);
|
tile.build.checkAllowUpdate();
|
||||||
|
tile.build.onRepaired();
|
||||||
|
|
||||||
if(unit != null && unit.getControllerName() != null) tile.build.lastAccessed = unit.getControllerName();
|
if(unit != null && unit.getControllerName() != null) tile.build.lastAccessed = unit.getControllerName();
|
||||||
|
|
||||||
if(config != null){
|
|
||||||
tile.build.configured(unit, config);
|
|
||||||
}
|
|
||||||
//keep health
|
|
||||||
tile.build.health = result.health * healthf;
|
|
||||||
|
|
||||||
if(fogControl.isVisibleTile(team, tile.x, tile.y)){
|
if(fogControl.isVisibleTile(team, tile.x, tile.y)){
|
||||||
result.placeEffect.at(tile.drawx(), tile.drawy(), result.size);
|
result.placeEffect.at(tile.drawx(), tile.drawy(), result.size);
|
||||||
Fx.rotateBlock.at(tile.build.x, tile.build.y, tile.build.block.size);
|
Fx.rotateBlock.at(tile.build.x, tile.build.y, tile.build.block.size);
|
||||||
//doesn't play a sound
|
//doesn't play a sound
|
||||||
}
|
}
|
||||||
|
|
||||||
Events.fire(new BlockBuildEndEvent(tile, unit, team, false, config));
|
Events.fire(new BlockBuildEndEvent(tile, unit, team, false, tile.build.config()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,8 +163,8 @@ public class Build{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return whether a tile can be placed at this location by this team. */
|
/** @return whether a tile can be placed at this location by this team. */
|
||||||
public static boolean validPlace(Block type, Team team, int x, int y, int rotation, boolean checkVisible, boolean ignoreCoreRadius){
|
public static boolean validPlace(Block type, Team team, int x, int y, int rotation, boolean checkVisible, boolean checkCoreRadius){
|
||||||
return validPlaceIgnoreUnits(type, team, x, y, rotation, checkVisible, ignoreCoreRadius) && checkNoUnitOverlap(type, x, y);
|
return validPlaceIgnoreUnits(type, team, x, y, rotation, checkVisible, checkCoreRadius) && checkNoUnitOverlap(type, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return whether a tile can be placed at this location by this team. */
|
/** @return whether a tile can be placed at this location by this team. */
|
||||||
|
|||||||
11
core/src/mindustry/world/WorldParams.java
Normal file
11
core/src/mindustry/world/WorldParams.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package mindustry.world;
|
||||||
|
|
||||||
|
/** Parameters for loading or generating a world. */
|
||||||
|
public class WorldParams{
|
||||||
|
/** For sectors: World generator seed offset. */
|
||||||
|
public int seedOffset;
|
||||||
|
/** For sectors: Whether to save the info once the map is generated. A value of 'false' is used for editor generation. */
|
||||||
|
public boolean saveInfo = true;
|
||||||
|
/** Position in packed x/y format - not array format. Overrides the core position when generating with a FileMapGenerator. 0 to disable. */
|
||||||
|
public int corePositionOverride;
|
||||||
|
}
|
||||||
@@ -283,6 +283,12 @@ public class Turret extends ReloadTurret{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//overridden so that the rotation isn't affected during repairs (standard placed() code isn't called)
|
||||||
|
@Override
|
||||||
|
public void onRepaired(){
|
||||||
|
super.placed();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(){
|
public void remove(){
|
||||||
super.remove();
|
super.remove();
|
||||||
@@ -519,7 +525,7 @@ public class Turret extends ReloadTurret{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(validateTarget()){
|
if(validateTarget()){
|
||||||
boolean canShoot = true;
|
boolean canShoot;
|
||||||
|
|
||||||
if(isControlled()){ //player behavior
|
if(isControlled()){ //player behavior
|
||||||
targetPos.set(unit.aimX(), unit.aimY());
|
targetPos.set(unit.aimX(), unit.aimY());
|
||||||
|
|||||||
@@ -892,7 +892,7 @@ public class ApplicationTests{
|
|||||||
|
|
||||||
logic.reset();
|
logic.reset();
|
||||||
state.rules.sector = zone.sector;
|
state.rules.sector = zone.sector;
|
||||||
world.loadGenerator(zone.generator.map.width, zone.generator.map.height, zone.generator::generate);
|
world.loadGenerator(zone.generator.map.width, zone.generator.map.height, tiles -> zone.generator.generate(tiles, new WorldParams()));
|
||||||
zone.rules.get(state.rules);
|
zone.rules.get(state.rules);
|
||||||
ObjectSet<Item> resources = new ObjectSet<>();
|
ObjectSet<Item> resources = new ObjectSet<>();
|
||||||
boolean hasSpawnPoint = false;
|
boolean hasSpawnPoint = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user