Basic schematic based generation
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -42,6 +42,7 @@ packr-out/
|
|||||||
config/
|
config/
|
||||||
*.gif
|
*.gif
|
||||||
|
|
||||||
|
/core/assets/basepartnames
|
||||||
version.properties
|
version.properties
|
||||||
|
|
||||||
.attach_*
|
.attach_*
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ allprojects{
|
|||||||
output += other.name.substring("bundle".length() + 1, other.name.lastIndexOf('.')) + "\n"
|
output += other.name.substring("bundle".length() + 1, other.name.lastIndexOf('.')) + "\n"
|
||||||
}
|
}
|
||||||
new File(project(':core').projectDir, 'assets/locales').text = output
|
new File(project(':core').projectDir, 'assets/locales').text = output
|
||||||
|
new File(project(':core').projectDir, 'assets/basepartnames').text = new File(project(':core').projectDir, 'assets/baseparts/').list().join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
writeVersion = {
|
writeVersion = {
|
||||||
|
|||||||
BIN
core/assets/baseparts/core1.msch
Normal file
BIN
core/assets/baseparts/core1.msch
Normal file
Binary file not shown.
BIN
core/assets/baseparts/turret1.msch
Normal file
BIN
core/assets/baseparts/turret1.msch
Normal file
Binary file not shown.
@@ -178,6 +178,7 @@ public class Vars implements Loadable{
|
|||||||
public static BeControl becontrol;
|
public static BeControl becontrol;
|
||||||
public static AsyncCore asyncCore;
|
public static AsyncCore asyncCore;
|
||||||
public static TeamIndexProcess teamIndex;
|
public static TeamIndexProcess teamIndex;
|
||||||
|
public static BaseRegistry bases;
|
||||||
|
|
||||||
public static Universe universe;
|
public static Universe universe;
|
||||||
public static World world;
|
public static World world;
|
||||||
@@ -250,6 +251,7 @@ public class Vars implements Loadable{
|
|||||||
spawner = new WaveSpawner();
|
spawner = new WaveSpawner();
|
||||||
indexer = new BlockIndexer();
|
indexer = new BlockIndexer();
|
||||||
pathfinder = new Pathfinder();
|
pathfinder = new Pathfinder();
|
||||||
|
bases = new BaseRegistry();
|
||||||
|
|
||||||
state = new GameState();
|
state = new GameState();
|
||||||
data = new GlobalData();
|
data = new GlobalData();
|
||||||
|
|||||||
100
core/src/mindustry/ai/BaseRegistry.java
Normal file
100
core/src/mindustry/ai/BaseRegistry.java
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package mindustry.ai;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.game.*;
|
||||||
|
import mindustry.game.Schematic.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.blocks.sandbox.*;
|
||||||
|
import mindustry.world.blocks.storage.*;
|
||||||
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class BaseRegistry{
|
||||||
|
public Array<BasePart> cores = new Array<>();
|
||||||
|
public Array<BasePart> parts = new Array<>();
|
||||||
|
public ObjectMap<Item, Array<BasePart>> itemParts = new ObjectMap<>();
|
||||||
|
|
||||||
|
public Array<BasePart> forItem(Item item){
|
||||||
|
return itemParts.get(item, Array::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(){
|
||||||
|
cores.clear();
|
||||||
|
parts.clear();
|
||||||
|
itemParts.clear();
|
||||||
|
|
||||||
|
String[] names = Core.files.internal("basepartnames").readString().split("\n");
|
||||||
|
|
||||||
|
for(String name : names){
|
||||||
|
try{
|
||||||
|
Schematic schem = Schematics.read(Core.files.internal("baseparts/" + name));
|
||||||
|
|
||||||
|
BasePart part = new BasePart(schem);
|
||||||
|
|
||||||
|
for(Stile tile : schem.tiles){
|
||||||
|
//make note of occupied positions
|
||||||
|
tile.block.iterateTaken(tile.x, tile.y, part.occupied::set);
|
||||||
|
|
||||||
|
//keep track of core type
|
||||||
|
if(tile.block instanceof CoreBlock){
|
||||||
|
part.core = tile.block;
|
||||||
|
}
|
||||||
|
|
||||||
|
//save the required resource based on item source - multiple sources are not allowed
|
||||||
|
if(tile.block instanceof ItemSource){
|
||||||
|
Item config = (Item)tile.config;
|
||||||
|
if(config != null) part.requiredItem = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
//same for liquids - this is not used yet
|
||||||
|
if(tile.block instanceof LiquidSource){
|
||||||
|
Liquid config = (Liquid)tile.config;
|
||||||
|
if(config != null) part.requiredLiquid = config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
schem.tiles.removeAll(s -> s.block.buildVisibility == BuildVisibility.sandboxOnly);
|
||||||
|
|
||||||
|
part.tier = schem.tiles.sumf(s -> s.block.buildCost / s.block.buildCostMultiplier);
|
||||||
|
|
||||||
|
(part.core != null ? cores : parts).add(part);
|
||||||
|
|
||||||
|
if(part.requiredItem != null){
|
||||||
|
itemParts.get(part.requiredItem, Array::new).add(part);
|
||||||
|
}
|
||||||
|
}catch(IOException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cores.sort(Structs.comps(Structs.comparingFloat(b -> b.core.health), Structs.comparingFloat(b -> b.tier)));
|
||||||
|
parts.sort();
|
||||||
|
itemParts.each((key, arr) -> arr.sort());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BasePart implements Comparable<BasePart>{
|
||||||
|
public final Schematic schematic;
|
||||||
|
public final GridBits occupied;
|
||||||
|
|
||||||
|
public @Nullable Liquid requiredLiquid;
|
||||||
|
public @Nullable Item requiredItem;
|
||||||
|
public @Nullable Block core;
|
||||||
|
|
||||||
|
//total build cost
|
||||||
|
public float tier;
|
||||||
|
|
||||||
|
public BasePart(Schematic schematic){
|
||||||
|
this.schematic = schematic;
|
||||||
|
this.occupied = new GridBits(schematic.width, schematic.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(BasePart other){
|
||||||
|
return Float.compare(tier, other.tier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -689,7 +689,7 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
consumes.power(4f);
|
consumes.power(4f);
|
||||||
consumes.item(Items.scrap);
|
consumes.item(Items.scrap);
|
||||||
consumes.liquid(Liquids.slag, 0.1f);
|
consumes.liquid(Liquids.slag, 0.12f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
sporePress = new GenericCrafter("spore-press"){{
|
sporePress = new GenericCrafter("spore-press"){{
|
||||||
@@ -917,11 +917,11 @@ public class Blocks implements ContentList{
|
|||||||
requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 130, Items.silicon, 130, Items.plastanium, 80, Items.surgealloy, 120));
|
requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 130, Items.silicon, 130, Items.plastanium, 80, Items.surgealloy, 120));
|
||||||
consumes.power(10f);
|
consumes.power(10f);
|
||||||
size = 3;
|
size = 3;
|
||||||
range = 180f;
|
range = 200f;
|
||||||
speedBoost = 1.5f;
|
speedBoost = 2.5f;
|
||||||
speedBoostPhase = 1f;
|
|
||||||
useTime = 250f;
|
useTime = 250f;
|
||||||
consumes.item(Items.phasefabric).boost();
|
hasBoost = false;
|
||||||
|
consumes.item(Items.phasefabric);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
forceProjector = new ForceProjector("force-projector"){{
|
forceProjector = new ForceProjector("force-projector"){{
|
||||||
|
|||||||
@@ -191,10 +191,10 @@ public class Bullets implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
flakSurge = new FlakBulletType(4.5f, 13){{
|
flakSurge = new FlakBulletType(4.5f, 13){{
|
||||||
splashDamage = 40f;
|
splashDamage = 45f;
|
||||||
splashDamageRadius = 40f;
|
splashDamageRadius = 40f;
|
||||||
lightning = 2;
|
lightning = 2;
|
||||||
lightningLength = 12;
|
lightningLength = 7;
|
||||||
shootEffect = Fx.shootBig;
|
shootEffect = Fx.shootBig;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,9 @@ public class Schematics implements Loadable{
|
|||||||
if(shadowBuffer == null){
|
if(shadowBuffer == null){
|
||||||
Core.app.post(() -> shadowBuffer = new FrameBuffer(maxSchematicSize + padding + 8, maxSchematicSize + padding + 8));
|
Core.app.post(() -> shadowBuffer = new FrameBuffer(maxSchematicSize + padding + 8, maxSchematicSize + padding + 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//load base schematics
|
||||||
|
bases.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void overwrite(Schematic target, Schematic newSchematic){
|
public void overwrite(Schematic target, Schematic newSchematic){
|
||||||
@@ -372,14 +375,18 @@ public class Schematics implements Loadable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void placeLoadout(Schematic schem, int x, int y){
|
public static void placeLoadout(Schematic schem, int x, int y){
|
||||||
|
placeLoadout(schem, x, y, state.rules.defaultTeam, Blocks.oreCopper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void placeLoadout(Schematic schem, int x, int y, Team team, Block resource){
|
||||||
Stile coreTile = schem.tiles.find(s -> s.block instanceof CoreBlock);
|
Stile coreTile = schem.tiles.find(s -> s.block instanceof CoreBlock);
|
||||||
if(coreTile == null) throw new IllegalArgumentException("Schematic has no core tile. Exiting.");
|
if(coreTile == null) throw new IllegalArgumentException("Loadout schematic has no core tile!");
|
||||||
int ox = x - coreTile.x, oy = y - coreTile.y;
|
int ox = x - coreTile.x, oy = y - coreTile.y;
|
||||||
schem.tiles.each(st -> {
|
schem.tiles.each(st -> {
|
||||||
Tile tile = world.tile(st.x + ox, st.y + oy);
|
Tile tile = world.tile(st.x + ox, st.y + oy);
|
||||||
if(tile == null) return;
|
if(tile == null) return;
|
||||||
|
|
||||||
tile.setBlock(st.block, state.rules.defaultTeam, 0);
|
tile.setBlock(st.block, team, 0);
|
||||||
tile.rotation(st.rotation);
|
tile.rotation(st.rotation);
|
||||||
|
|
||||||
Object config = st.config;
|
Object config = st.config;
|
||||||
@@ -388,7 +395,7 @@ public class Schematics implements Loadable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(st.block instanceof Drill){
|
if(st.block instanceof Drill){
|
||||||
tile.getLinkedTiles(t -> t.setOverlay(Blocks.oreCopper));
|
tile.getLinkedTiles(t -> t.setOverlay(resource));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,12 +94,12 @@ public abstract class SaveFileReader{
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void skipRegion(DataInput input) throws IOException{
|
public void skipChunk(DataInput input) throws IOException{
|
||||||
skipRegion(input, false);
|
skipChunk(input, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Skip a region completely. */
|
/** Skip a chunk completely, discarding the bytes. */
|
||||||
public void skipRegion(DataInput input, boolean isByte) throws IOException{
|
public void skipChunk(DataInput input, boolean isByte) throws IOException{
|
||||||
int length = readChunk(input, isByte, t -> {});
|
int length = readChunk(input, isByte, t -> {});
|
||||||
int skipped = input.skipBytes(length);
|
int skipped = input.skipBytes(length);
|
||||||
if(length != skipped){
|
if(length != skipped){
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
|||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
//skip the entity region, as the entity and its IO code are now gone
|
//skip the entity region, as the entity and its IO code are now gone
|
||||||
skipRegion(stream, true);
|
skipChunk(stream, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public abstract class LegacySaveVersion extends SaveVersion{
|
|||||||
int amount = stream.readInt();
|
int amount = stream.readInt();
|
||||||
for(int j = 0; j < amount; j++){
|
for(int j = 0; j < amount; j++){
|
||||||
//simply skip all the entities
|
//simply skip all the entities
|
||||||
skipRegion(stream, true);
|
skipChunk(stream, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,78 +1,143 @@
|
|||||||
package mindustry.maps.generators;
|
package mindustry.maps.generators;
|
||||||
|
|
||||||
import arc.*;
|
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import mindustry.ai.BaseRegistry.*;
|
||||||
import mindustry.*;
|
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
|
import mindustry.game.Schematic.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.defense.turrets.*;
|
import mindustry.world.blocks.defense.*;
|
||||||
import mindustry.world.blocks.defense.turrets.ItemTurret.*;
|
|
||||||
import mindustry.world.blocks.environment.*;
|
import mindustry.world.blocks.environment.*;
|
||||||
|
import mindustry.world.blocks.production.*;
|
||||||
|
|
||||||
import java.io.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class BaseGenerator{
|
public class BaseGenerator{
|
||||||
static Array<Schematic> schematics = new Array<>();
|
private Tiles tiles;
|
||||||
|
private Team team;
|
||||||
|
private ObjectMap<Item, OreBlock> ores = new ObjectMap<>();
|
||||||
|
|
||||||
public void generate(Tiles tiles, Array<Tile> cores, Tile spawn, Team team, Sector sector){
|
public void generate(Tiles tiles, Array<Tile> cores, Tile spawn, Team team, Sector sector){
|
||||||
|
this.tiles = tiles;
|
||||||
|
this.team = team;
|
||||||
|
|
||||||
|
for(Block block : content.blocks()){
|
||||||
|
if(block instanceof OreBlock && block.asFloor().itemDrop != null){
|
||||||
|
ores.put(block.asFloor().itemDrop, (OreBlock)block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<Block> wallsSmall = content.blocks().select(b -> b instanceof Wall && b.size == 1);
|
||||||
|
Array<Block> wallsLarge = content.blocks().select(b -> b instanceof Wall && b.size == 2);
|
||||||
|
|
||||||
|
float bracket = 0.1f;
|
||||||
|
int range = 200;
|
||||||
|
int wallAngle = 180;
|
||||||
|
BasePart coreschem = bases.cores.getFrac(bracket);
|
||||||
|
|
||||||
|
Block wall = wallsSmall.getFrac(bracket), wallLarge = wallsLarge.getFrac(bracket);
|
||||||
|
|
||||||
|
//TODO random flipping and rotation
|
||||||
|
|
||||||
for(Tile tile : cores){
|
for(Tile tile : cores){
|
||||||
tile.clearOverlay();
|
tile.clearOverlay();
|
||||||
tile.setBlock(Blocks.coreShard, team);
|
Schematics.placeLoadout(coreschem.schematic, tile.x, tile.y, team, coreschem.requiredItem == null ? Blocks.oreCopper : ores.get(coreschem.requiredItem));
|
||||||
|
|
||||||
|
//fill core with every type of item (even non-material)
|
||||||
|
Tilec entity = tile.entity;
|
||||||
|
for(Item item : content.items()){
|
||||||
|
entity.items().add(item, entity.block().itemCapacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO remove this, it's just a test
|
//first pass: random schematics
|
||||||
if(!Core.files.external("SCHEMATICOUTPUT").exists()){
|
for(Tile core : cores){
|
||||||
Log.err("no schematics");
|
core.circle(range, (x, y) -> {
|
||||||
return;
|
Tile tile = tiles.getn(x, y);
|
||||||
|
if(tile.overlay().itemDrop != null){
|
||||||
|
Array<BasePart> parts = bases.forItem(tile.overlay().itemDrop);
|
||||||
|
if(!parts.isEmpty()){
|
||||||
|
tryPlace(parts.random(), x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(schematics.isEmpty()){
|
//second pass: small walls
|
||||||
schematics.addAll(Array.with(Core.files.external("SCHEMATICOUTPUT").list()).map(s -> {
|
for(Tile core : cores){
|
||||||
try{
|
core.circle(range, (x, y) -> {
|
||||||
return Schematics.read(s);
|
Tile tile = tiles.getn(x, y);
|
||||||
}catch(IOException e){
|
if(tile.block().alwaysReplace){
|
||||||
throw new RuntimeException();
|
boolean any = false;
|
||||||
}
|
|
||||||
}));
|
for(Point2 p : Geometry.d8){
|
||||||
|
if(Angles.angleDist(Angles.angle(p.x, p.y), spawn.angleTo(core)) > wallAngle){
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vars.state.rules.enemyCheat = true;
|
Tile o = tiles.get(tile.x + p.x, tile.y + p.y);
|
||||||
|
if(o != null && o.team() == team && !(o.block() instanceof Wall)){
|
||||||
|
any = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int range = 180;
|
if(any){
|
||||||
int attempts = 3000;
|
tile.setBlock(wall, team);
|
||||||
int cx = cores.first().x, cy = cores.first().y;
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
outer:
|
//third pass: large walls
|
||||||
for(int i = 0; i < attempts; i++){
|
for(Tile core : cores){
|
||||||
Tmp.v1.rnd(Mathf.random(range));
|
core.circle(range, (x, y) -> {
|
||||||
int x = (int)(cx + Tmp.v1.x), y = (int)(cy + Tmp.v1.y);
|
int walls = 0;
|
||||||
|
for(int cx = 0; cx < 2; cx++){
|
||||||
|
for(int cy = 0; cy < 2; cy++){
|
||||||
|
Tile tile = tiles.get(x + cx, y + cy);
|
||||||
|
if(tile == null || tile.block().size != 1 || (tile.block() != wall && !tile.block().alwaysReplace)) return;
|
||||||
|
|
||||||
Schematic res = schematics.random();
|
if(tile.block() == wall){
|
||||||
int ex = x - res.width/2, ey = y - res.height/2;
|
walls ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(int rx = ex; rx <= ex + res.width; rx++){
|
if(walls >= 3){
|
||||||
for(int ry = ey; ry <= ey + res.height; ry++){
|
tiles.getn(x, y).setBlock(wallLarge, team);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean tryPlace(BasePart part, int x, int y){
|
||||||
|
int cx = x - part.schematic.width/2, cy = y - part.schematic.height/2;
|
||||||
|
for(int rx = cx; rx <= cx + part.schematic.width; rx++){
|
||||||
|
for(int ry = cy; ry <= cy + part.schematic.height; ry++){
|
||||||
Tile tile = tiles.get(rx, ry);
|
Tile tile = tiles.get(rx, ry);
|
||||||
if(tile == null || Vars.world.getDarkness(rx, ry) > 0 || tile.floor().isDeep() || (!tile.block().isAir() && !(tile.block() instanceof Rock && tile.block().destructible))) continue outer;
|
if(tile == null || ((!tile.block().alwaysReplace || world.getDarkness(rx, ry) > 0) && part.occupied.get(rx - cx, ry - cy))){
|
||||||
}
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
Schematics.place(res, x, y, team);
|
|
||||||
|
|
||||||
//add ammo
|
|
||||||
for(int rx = ex; rx <= ex + res.width; rx++){
|
|
||||||
for(int ry = ey; ry <= ey + res.height; ry++){
|
|
||||||
Tile tile = tiles.get(rx, ry);
|
|
||||||
if(tile != null && tile.entity instanceof ItemTurretEntity){
|
|
||||||
tile.entity.handleItem(tile.entity, ((ItemTurret)tile.block()).ammoTypes.keys().toArray().first());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(part.requiredItem != null){
|
||||||
|
for(Stile tile : part.schematic.tiles){
|
||||||
|
if(tile.block instanceof Drill){
|
||||||
|
tile.block.iterateTaken(tile.x + cx, tile.y + cy, (ex, ey) -> {
|
||||||
|
tiles.getn(ex, ey).setOverlay(ores.get(part.requiredItem));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Schematics.place(part.schematic, x, y, team);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -405,6 +405,23 @@ public class Block extends UnlockableContent{
|
|||||||
return (hasItems && itemCapacity > 0);
|
return (hasItems && itemCapacity > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Iterate through ever grid position taken up by this block. */
|
||||||
|
public void iterateTaken(int x, int y, Intc2 placer){
|
||||||
|
if(isMultiblock()){
|
||||||
|
int offsetx = -(size - 1) / 2;
|
||||||
|
int offsety = -(size - 1) / 2;
|
||||||
|
|
||||||
|
for(int dx = 0; dx < size; dx++){
|
||||||
|
for(int dy = 0; dy < size; dy++){
|
||||||
|
placer.get(dx + offsetx + x, dy + offsety + y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
placer.get(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Never use outside of the editor! */
|
/** Never use outside of the editor! */
|
||||||
public TextureRegion editorIcon(){
|
public TextureRegion editorIcon(){
|
||||||
if(editorIcon == null) editorIcon = Core.atlas.find(name + "-icon-editor");
|
if(editorIcon == null) editorIcon = Core.atlas.find(name + "-icon-editor");
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public class OverdriveProjector extends Block{
|
|||||||
public float speedBoostPhase = 0.75f;
|
public float speedBoostPhase = 0.75f;
|
||||||
public float useTime = 400f;
|
public float useTime = 400f;
|
||||||
public float phaseRangeBoost = 20f;
|
public float phaseRangeBoost = 20f;
|
||||||
|
public boolean hasBoost = true;
|
||||||
public Color baseColor = Color.valueOf("feb380");
|
public Color baseColor = Color.valueOf("feb380");
|
||||||
public Color phaseColor = Color.valueOf("ffd59e");
|
public Color phaseColor = Color.valueOf("ffd59e");
|
||||||
|
|
||||||
@@ -51,10 +52,13 @@ public class OverdriveProjector extends Block{
|
|||||||
|
|
||||||
stats.add(BlockStat.speedIncrease, (int)(100f * speedBoost), StatUnit.percent);
|
stats.add(BlockStat.speedIncrease, (int)(100f * speedBoost), StatUnit.percent);
|
||||||
stats.add(BlockStat.range, range / tilesize, StatUnit.blocks);
|
stats.add(BlockStat.range, range / tilesize, StatUnit.blocks);
|
||||||
|
stats.add(BlockStat.productionTime, useTime / 60f, StatUnit.seconds);
|
||||||
|
|
||||||
|
if(hasBoost){
|
||||||
stats.add(BlockStat.boostEffect, phaseRangeBoost / tilesize, StatUnit.blocks);
|
stats.add(BlockStat.boostEffect, phaseRangeBoost / tilesize, StatUnit.blocks);
|
||||||
stats.add(BlockStat.boostEffect, (int)((speedBoost + speedBoostPhase) * 100f), StatUnit.percent);
|
stats.add(BlockStat.boostEffect, (int)((speedBoost + speedBoostPhase) * 100f), StatUnit.percent);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class OverdriveEntity extends TileEntity{
|
public class OverdriveEntity extends TileEntity{
|
||||||
float heat;
|
float heat;
|
||||||
@@ -71,7 +75,9 @@ public class OverdriveProjector extends Block{
|
|||||||
heat = Mathf.lerpDelta(heat, consValid() ? 1f : 0f, 0.08f);
|
heat = Mathf.lerpDelta(heat, consValid() ? 1f : 0f, 0.08f);
|
||||||
charge += heat * Time.delta();
|
charge += heat * Time.delta();
|
||||||
|
|
||||||
|
if(hasBoost){
|
||||||
phaseHeat = Mathf.lerpDelta(phaseHeat, Mathf.num(cons().optionalValid()), 0.1f);
|
phaseHeat = Mathf.lerpDelta(phaseHeat, Mathf.num(cons().optionalValid()), 0.1f);
|
||||||
|
}
|
||||||
|
|
||||||
if(timer(timerUse, useTime) && efficiency() > 0){
|
if(timer(timerUse, useTime) && efficiency() > 0){
|
||||||
consume();
|
consume();
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ public class ServerLauncher implements ApplicationListener{
|
|||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bases.load();
|
||||||
|
|
||||||
Core.app.addListener(new ApplicationListener(){public void update(){ asyncCore.begin(); }});
|
Core.app.addListener(new ApplicationListener(){public void update(){ asyncCore.begin(); }});
|
||||||
Core.app.addListener(logic = new Logic());
|
Core.app.addListener(logic = new Logic());
|
||||||
Core.app.addListener(netServer = new NetServer());
|
Core.app.addListener(netServer = new NetServer());
|
||||||
|
|||||||
Reference in New Issue
Block a user