Better launch / Better spawns / Tweaks

This commit is contained in:
Anuken
2019-01-27 18:09:59 -05:00
parent da9278ad8d
commit db2e6b6973
27 changed files with 1636 additions and 1479 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -247,8 +247,10 @@ locked = Locked
complete = [LIGHT_GRAY]Complete:
resume = Resume Zone:\n[LIGHT_GRAY]{0}
bestwave = [LIGHT_GRAY]Best: {0}
launch = Launch
launch = < LAUNCH >
launch.title = Launch Successful
launch.next = [LIGHT_GRAY]next opportunity at wave {0}
launch.unable = [scarlet]Unable to LAUNCH.[] Enemies.
zone.unlocked = [LIGHT_GRAY]{0} unlocked.
connectfail = [crimson]Failed to connect to server:\n\n[accent]{0}

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 1020 KiB

View File

@ -2,13 +2,24 @@ package io.anuke.mindustry.ai;
import io.anuke.arc.Events;
import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.IntArray;
import io.anuke.arc.entities.Effects;
import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Time;
import io.anuke.arc.util.Tmp;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.entities.Damage;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.entities.units.Squad;
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
import io.anuke.mindustry.game.SpawnGroup;
import io.anuke.mindustry.world.Pos;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
@ -16,11 +27,31 @@ public class WaveSpawner{
private Array<SpawnGroup> groups;
private Array<FlyerSpawn> flySpawns = new Array<>();
private Array<GroundSpawn> groundSpawns = new Array<>();
private IntArray loadedSpawns = new IntArray();
public WaveSpawner(){
Events.on(WorldLoadEvent.class, e -> reset());
}
public void write(DataOutput stream) throws IOException{
stream.writeInt(groundSpawns.size);
for(GroundSpawn spawn : groundSpawns){
stream.writeInt(Pos.get(spawn.x, spawn.y));
}
}
public void read(DataInput stream) throws IOException{
flySpawns.clear();
groundSpawns.clear();
loadedSpawns.clear();
int amount = stream.readInt();
for(int i = 0; i < amount; i++){
loadedSpawns.add(stream.readInt());
}
}
public void spawnEnemies(){
for(SpawnGroup group : groups){
@ -51,15 +82,23 @@ public class WaveSpawner{
Squad squad = new Squad();
spawnX = spawn.x * tilesize;
spawnY = spawn.y * tilesize;
spread = tilesize;
spread = tilesize*3;
for(int i = 0; i < spawned; i++){
Tmp.v1.rnd(spread);
BaseUnit unit = group.createUnit(waveTeam);
unit.setWave();
unit.setSquad(squad);
unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
unit.add();
unit.set(spawnX + Tmp.v1.x, spawnY + Tmp.v1.y);
Time.run(i*5, () -> {
shockwave(unit);
});
}
Time.run(20f, () -> Effects.effect(Fx.spawnShockwave, spawn.x * tilesize, spawn.y * tilesize));
//would be interesting to see player structures survive this without hacks
Time.run(40f, () -> Damage.damage(waveTeam, spawn.x * tilesize, spawn.y * tilesize, 350f + Mathf.random(80f), 99999999f));
}
}
}
@ -73,17 +112,39 @@ public class WaveSpawner{
for(int x = 0; x < world.width(); x++){
for(int y = 0; y < world.height(); y++){
if(world.tile(x, y).block() == Blocks.spawn){
GroundSpawn spawn = new GroundSpawn();
spawn.x = x;
spawn.y = y;
groundSpawns.add(spawn);
addSpawns(x, y);
FlyerSpawn fspawn = new FlyerSpawn();
fspawn.angle = Angles.angle(world.width()/2f, world.height()/2f, x, y);
flySpawns.add(fspawn);
//hide spawnpoints, they have served their purpose
world.tile(x, y).setBlock(Blocks.air);
}
}
}
for(int i = 0; i < loadedSpawns.size; i++){
int pos = loadedSpawns.get(i);
addSpawns(Pos.x(pos), Pos.y(pos));
}
loadedSpawns.clear();
}
private void addSpawns(int x, int y){
GroundSpawn spawn = new GroundSpawn();
spawn.x = x;
spawn.y = y;
groundSpawns.add(spawn);
FlyerSpawn fspawn = new FlyerSpawn();
fspawn.angle = Angles.angle(world.width()/2f, world.height()/2f, x, y);
flySpawns.add(fspawn);
}
private void shockwave(BaseUnit unit){
Effects.effect(Fx.unitSpawn, unit.x, unit.y, 0f, unit);
Time.run(30f, () -> {
unit.add();
Effects.effect(Fx.spawn, unit);
});
}
private class FlyerSpawn{

View File

@ -33,7 +33,7 @@ public class Blocks implements ContentList{
//environment
air, part, spawn, space, metalfloor, deepwater, water, tar, stone, craters, charr, blackstone, dirt, sand, ice, snow,
grass, shrub, rock, icerock, blackrock, rocks, cliffs, pine,
grass, shrub, rock, icerock, blackrock, rocks, cliffs, pine, whiteTree,
//crafting
siliconSmelter, graphitePress, plastaniumCompressor, multiPress, phaseWeaver, surgeSmelter, pyratiteMixer, blastMixer, cryofluidMixer,
@ -223,6 +223,9 @@ public class Blocks implements ContentList{
variants = 0;
}};
whiteTree = new TreeBlock("white-tree-dead"){{
}};
//endregion
//region crafting
@ -860,9 +863,6 @@ public class Blocks implements ContentList{
health = 1100;
itemCapacity = 1000;
launchThreshold = 500;
launchTime = 60f * 10;
launchChunkSize = 100;
}};
vault = new Vault("vault"){{

View File

@ -10,6 +10,7 @@ import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Tmp;
import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.ContentList;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Shapes;
@ -32,13 +33,27 @@ public class Fx implements ContentList{
bigShockwave, nuclearShockwave, explosion, blockExplosion, blockExplosionSmoke, shootSmall, shootHeal, shootSmallSmoke, shootBig, shootBig2, shootBigSmoke,
shootBigSmoke2, shootSmallFlame, shootLiquid, shellEjectSmall, shellEjectMedium,
shellEjectBig, lancerLaserShoot, lancerLaserShootSmoke, lancerLaserCharge, lancerLaserChargeBegin, lightningCharge, lightningShoot,
launchFull;
launchFull, unitSpawn, spawnShockwave;
@Override
public void load(){
none = new Effect(0, 0f, e -> {});
unitSpawn = new Effect(30f, e -> {
if(!(e.data instanceof BaseUnit)) return;
Draw.alpha(e.fin());
float scl = 1f + e.fout()*2f;
BaseUnit unit = (BaseUnit)e.data;
Draw.rect(unit.getIconRegion(), e.x, e.y,
unit.getIconRegion().getWidth() * Draw.scl * scl, unit.getIconRegion().getWidth() * Draw.scl * scl, 180f);
Draw.reset();
});
placeBlock = new Effect(16, e -> {
Draw.color(Palette.accent);
Lines.stroke(3f - e.fin() * 2f);
@ -78,10 +93,10 @@ public class Fx implements ContentList{
Draw.reset();
});
spawn = new Effect(23, e -> {
spawn = new Effect(30, e -> {
Lines.stroke(2f * e.fout());
Draw.color(Palette.accent);
Lines.poly(e.x, e.y, 4, 3f + e.fin() * 8f);
Lines.poly(e.x, e.y, 4, 5f + e.fin() * 12f);
Draw.reset();
});
@ -545,6 +560,13 @@ public class Fx implements ContentList{
Draw.reset();
});
spawnShockwave = new Effect(20f, 400f, e -> {
Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin());
Lines.stroke(e.fout() * 3f + 0.5f);
Lines.poly(e.x, e.y, 60, e.fin() * 450f);
Draw.reset();
});
explosion = new Effect(30, e -> {
e.scaled(7, i -> {
Lines.stroke(3f * i.fout());

View File

@ -59,8 +59,6 @@ public class Zones implements ContentList{
}};
craters = new Zone("craters", new MapGenerator("craters", 1){{ distortion = 0; }}){{
alwaysUnlocked = true;
deployCost = ItemStack.with(Items.copper, 300);
startingItems = ItemStack.with(Items.copper, 200);
conditionWave = 15;
@ -108,7 +106,8 @@ public class Zones implements ContentList{
}};
}};
frozenForest = new Zone("frozenForest", new MapGenerator("groundZero", 1)){{ //TODO implement
frozenForest = new Zone("frozenForest", new MapGenerator("frozenForest")){{ //TODO implement
alwaysUnlocked = true;
deployCost = ItemStack.with(Items.copper, 300);
startingItems = ItemStack.with(Items.copper, 200);
conditionWave = 15;

View File

@ -112,10 +112,10 @@ public class BlockRenderer{
Draw.flush();
shadows.begin();
Core.graphics.clear(Color.CLEAR);
Draw.color(shadowColor);
floor.beginDraw();
floor.drawLayer(CacheLayer.walls);
floor.endDraw();
drawBlocks(Layer.shadow);
EntityDraw.drawWith(playerGroup, player -> !player.isDead(), Unit::draw);
@ -164,11 +164,12 @@ public class BlockRenderer{
if(block != Blocks.air && block.cacheLayer == CacheLayer.normal){
if(!expanded){
addRequest(tile, Layer.shadow);
addRequest(tile, Layer.block);
}
if(block.expanded || !expanded){
addRequest(tile, Layer.shadow);
if(block.layer != null && block.isLayer(tile)){
addRequest(tile, block.layer);
}
@ -205,7 +206,9 @@ public class BlockRenderer{
Block block = req.tile.block();
if(req.layer == Layer.shadow){
Draw.color(0f, 0f, 0f, 0.45f);
block.drawShadow(req.tile);
Draw.color();
}else if(req.layer == Layer.block){
block.draw(req.tile);
if(block.synthetic() && req.tile.getTeam() != players[0].getTeam()){

View File

@ -43,6 +43,7 @@ public class Save16 extends SaveFileVersion{
state.wave = wave;
state.wavetime = wavetime;
state.stats = Serialization.readStats(stream);
world.spawner.read(stream);
content.setTemporaryMapper(readContentHeader(stream));
@ -66,6 +67,7 @@ public class Save16 extends SaveFileVersion{
stream.writeFloat(state.wavetime); //wave countdown
Serialization.writeStats(stream, state.stats);
world.spawner.write(stream);
writeContentHeader(stream);

View File

@ -83,11 +83,11 @@ public class MapGenerator extends Generator{
}
}
if(enemySpawns > enemies.size){
throw new IllegalArgumentException("Enemy spawn pool greater than map spawn number.");
}
if(enemySpawns != -1){
if(enemySpawns > enemies.size){
throw new IllegalArgumentException("Enemy spawn pool greater than map spawn number.");
}
enemies.shuffle();
for(int i = 0; i < enemySpawns; i++){
Point2 point = enemies.get(i);

View File

@ -22,6 +22,7 @@ public class Zone extends UnlockableContent{
public Supplier<Rules> rules = Rules::new;
public boolean alwaysUnlocked;
public int conditionWave = Integer.MAX_VALUE;
public int launchPeriod = 10;
public Zone(String name, Generator generator){
this.name = name;

View File

@ -52,9 +52,8 @@ public class TechTreeDialog extends FloatingDialog{
recipes.sort(Structs.comparing(r -> r.buildCost));
if(recipes.size > 0){
Log.info("Recipe tree coverage: {0}%", (int)((float)nodes.size / content.blocks().select(Block::isVisible).size * 100));
Log.info("Missing items: ");
recipes.forEach(r -> Log.info(" {0}", r));
Log.info("Missing recipe tree items! ");
recipes.forEach(r -> Log.info("> {0}", r));
}
}

View File

@ -16,9 +16,11 @@ import io.anuke.arc.scene.ui.TextButton;
import io.anuke.arc.scene.ui.layout.Stack;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.utils.Elements;
import io.anuke.arc.util.Align;
import io.anuke.arc.util.Scaling;
import io.anuke.arc.util.Time;
import io.anuke.arc.util.Tmp;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.EventType.StateChangeEvent;
import io.anuke.mindustry.game.Team;
@ -196,8 +198,40 @@ public class HudFragment extends Fragment{
.update(label -> label.getColor().set(Color.ORANGE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 2f, 1f))));
});
parent.fill(t -> t.top().right().addRowImageTextButton("$launch", "icon-arrow-up", 8*3, Call::launchZone)
.size(94f, 70f).visible(() -> world.isZone() && world.getZone().metCondition() && !Net.client()));
parent.fill(t -> {
t.top().right();
TextButton button = Elements.newButton("$launch", Call::launchZone);
button.getStyle().disabledFontColor = Color.WHITE;
button.visible(() ->
world.isZone() &&
world.getZone().metCondition() &&
!Net.client() &&
state.wave % world.getZone().launchPeriod == 0);
button.update(() -> {
if(world.getZone() == null){
button.setText("");
return;
}
button.setText(Core.bundle.get(state.enemies() > 0 ? "launch.unable" : "launch") + "\n" +
Core.bundle.format("launch.next", state.wave + world.getZone().launchPeriod));
button.getLabel().setColor(Tmp.c1.set(Color.WHITE).lerp(state.enemies() > 0 ? Color.WHITE : Palette.accent,
Mathf.absin(Time.time(), 7f, 1f)));
});
button.setDisabled(() -> state.enemies() > 0);
button.getLabelCell().left().get().setAlignment(Align.left, Align.left);
t.add(button).size(350f, 80f);
//.addRowImageTextButton("$launch", "icon-arrow-up", 8*3, Call::launchZone)
//.size(94f, 70f).visible(() -> world.isZone() && world.getZone().metCondition() && !Net.client());
});
//'saving' indicator
parent.fill(t -> {

View File

@ -6,15 +6,19 @@ import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
public class TreeBlock extends Block{
static final float shadowOffset = 5f;
public TreeBlock(String name){
super(name);
solid = true;
layer = Layer.power;
expanded = true;
}
@Override
public void draw(Tile tile){}
public void drawShadow(Tile tile){
Draw.rect(region, tile.drawx() - shadowOffset, tile.drawy() - shadowOffset);
}
@Override
public void drawLayer(Tile tile){

View File

@ -25,10 +25,8 @@ import io.anuke.mindustry.world.meta.BlockFlag;
import static io.anuke.mindustry.Vars.*;
public class CoreBlock extends LaunchPad{
public class CoreBlock extends StorageBlock{
protected TextureRegion topRegion;
protected int launchThreshold;
protected int launchChunkSize;
public CoreBlock(String name){
super(name);
@ -148,16 +146,6 @@ public class CoreBlock extends LaunchPad{
public void update(Tile tile){
CoreEntity entity = tile.entity();
for(Item item : Vars.content.items()){
if(entity.items.get(item) >= launchThreshold + launchChunkSize && entity.timer.get(timerLaunch, launchTime)){
//TODO play animation of some sort
Effects.effect(Fx.dooropenlarge, tile);
//items sent are split evenly across every player in the game
data.addItem(item, launchChunkSize / Math.max(playerGroup.size(), 1));
entity.items.remove(item, launchChunkSize);
}
}
if(entity.currentUnit != null){
if(!entity.currentUnit.isDead()){
entity.currentUnit = null;