More vent variants
BIN
core/assets-raw/sprites/blocks/environment/arkyic-vent1.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
core/assets-raw/sprites/blocks/environment/arkyic-vent2.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
core/assets-raw/sprites/blocks/environment/carbon-vent1.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
core/assets-raw/sprites/blocks/environment/carbon-vent2.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
core/assets-raw/sprites/blocks/environment/red-stone-vent1.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
core/assets-raw/sprites/blocks/environment/red-stone-vent2.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.6 KiB |
BIN
core/assets-raw/sprites/units/weapons/disrupt-weapon-preview.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
@ -521,3 +521,8 @@
|
||||
63182=disrupt|unit-disrupt-ui
|
||||
63181=krepost|unit-krepost-ui
|
||||
63180=disrupt-missile|unit-disrupt-missile-ui
|
||||
63179=rhyolite-vent|block-rhyolite-vent-ui
|
||||
63178=arkyic-vent|block-arkyic-vent-ui
|
||||
63177=yellow-stone-vent|block-yellow-stone-vent-ui
|
||||
63176=red-stone-vent|block-red-stone-vent-ui
|
||||
63175=carbon-vent|block-carbon-vent-ui
|
||||
|
@ -46,7 +46,9 @@ public class Blocks{
|
||||
redmat, bluemat,
|
||||
stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster,
|
||||
redweed, purbush, yellowCoral,
|
||||
regolithWall, yellowStoneWall, rhyoliteWall, steamVent, carbonWall, redIceWall, ferricStoneWall, beryllicStoneWall, arkyicWall, crystallineStoneWall, redStoneWall, redDiamondWall,
|
||||
//TODO rename steamvent to rhyolite vent, maybe add red vent or crystal vent
|
||||
rhyoliteVent, carbonVent, arkyicVent, yellowStoneVent, redStoneVent,
|
||||
regolithWall, yellowStoneWall, rhyoliteWall, carbonWall, redIceWall, ferricStoneWall, beryllicStoneWall, arkyicWall, crystallineStoneWall, redStoneWall, redDiamondWall,
|
||||
ferricStone, ferricCraters, carbonStone, beryllicStone, crystallineStone, crystalFloor, yellowStonePlates,
|
||||
iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, grass, salt,
|
||||
//boulders
|
||||
@ -382,11 +384,6 @@ public class Blocks{
|
||||
variants = 3;
|
||||
}};
|
||||
|
||||
steamVent = new SteamVent("steam-vent"){{
|
||||
parent = blendGroup = rhyolite;
|
||||
attributes.set(Attribute.vent, 1f);
|
||||
}};
|
||||
|
||||
regolith = new Floor("regolith"){{
|
||||
attributes.set(Attribute.water, -1f);
|
||||
}};
|
||||
@ -457,10 +454,38 @@ public class Blocks{
|
||||
albedo = 0.9f;
|
||||
}};
|
||||
|
||||
arkyicStone = new Floor("arkyic-stone"){{
|
||||
arkyicStone = new Floor("arkyic-stone"){{
|
||||
variants = 3;
|
||||
}};
|
||||
|
||||
//TODO different vent colors
|
||||
rhyoliteVent = new SteamVent("rhyolite-vent"){{
|
||||
parent = blendGroup = rhyolite;
|
||||
attributes.set(Attribute.steam, 1f);
|
||||
}};
|
||||
|
||||
carbonVent = new SteamVent("carbon-vent"){{
|
||||
parent = blendGroup = carbonStone;
|
||||
attributes.set(Attribute.steam, 1f);
|
||||
}};
|
||||
|
||||
arkyicVent = new SteamVent("arkyic-vent"){{
|
||||
parent = blendGroup = arkyicStone;
|
||||
attributes.set(Attribute.steam, 1f);
|
||||
}};
|
||||
|
||||
yellowStoneVent = new SteamVent("yellow-stone-vent"){{
|
||||
//TODO ...or regolith
|
||||
parent = blendGroup = yellowStone;
|
||||
attributes.set(Attribute.steam, 1f);
|
||||
}};
|
||||
|
||||
redStoneVent = new SteamVent("red-stone-vent"){{
|
||||
//TODO ...or regolith
|
||||
parent = blendGroup = denseRedStone;
|
||||
attributes.set(Attribute.steam, 1f);
|
||||
}};
|
||||
|
||||
redmat = new Floor("redmat");
|
||||
bluemat = new Floor("bluemat");
|
||||
|
||||
@ -879,10 +904,10 @@ public class Blocks{
|
||||
}};
|
||||
|
||||
siliconArcFurnace = new GenericCrafter("silicon-arc-furnace"){{
|
||||
requirements(Category.crafting, with(Items.beryllium, 60, Items.graphite, 80));
|
||||
requirements(Category.crafting, with(Items.beryllium, 70, Items.graphite, 80));
|
||||
craftEffect = Fx.none;
|
||||
outputItem = new ItemStack(Items.silicon, 5);
|
||||
craftTime = 40f;
|
||||
outputItem = new ItemStack(Items.silicon, 4);
|
||||
craftTime = 50f;
|
||||
size = 3;
|
||||
hasPower = true;
|
||||
hasLiquids = false;
|
||||
@ -1138,6 +1163,7 @@ public class Blocks{
|
||||
);
|
||||
|
||||
drawer.iconOverride = new String[]{"-bottom", ""};
|
||||
regionRotated1 = 3;
|
||||
continuousLiquidOutput = true;
|
||||
outputLiquids = LiquidStack.with(Liquids.ozone, 4f / 60, Liquids.hydrogen, 6f / 60);
|
||||
liquidOutputDirections = new int[]{1, 3};
|
||||
@ -1184,6 +1210,7 @@ public class Blocks{
|
||||
drawer = new DrawMulti(new DrawRegion("-bottom"), new DrawLiquidRegion(), new DrawBlock(), new DrawHeatOutput());
|
||||
drawer.iconOverride = new String[]{"-bottom", "", "-top1"};
|
||||
|
||||
regionRotated1 = 2;
|
||||
craftTime = 60f * 3f;
|
||||
liquidCapacity = 30f;
|
||||
heatOutput = 5f;
|
||||
@ -2185,7 +2212,7 @@ public class Blocks{
|
||||
|
||||
turbineCondenser = new ThermalGenerator("turbine-condenser"){{
|
||||
requirements(Category.power, with(Items.graphite, 40, Items.beryllium, 40));
|
||||
attribute = Attribute.vent;
|
||||
attribute = Attribute.steam;
|
||||
displayEfficiencyScale = 1f / 9f;
|
||||
minEfficiency = 9f - 0.0001f;
|
||||
powerProduction = 3f / 9f;
|
||||
@ -2369,7 +2396,7 @@ public class Blocks{
|
||||
//TODO output heat?
|
||||
ventCondenser = new AttributeCrafter("vent-condenser"){{
|
||||
requirements(Category.production, with(Items.graphite, 20, Items.beryllium, 60));
|
||||
attribute = Attribute.vent;
|
||||
attribute = Attribute.steam;
|
||||
minEfficiency = 9f - 0.0001f;
|
||||
baseEfficiency = 0f;
|
||||
displayEfficiency = false;
|
||||
|
@ -119,7 +119,7 @@ public class SectorPresets{
|
||||
}};
|
||||
|
||||
aware = new SectorPreset("aware", erekir, 88){{
|
||||
captureWave = 6;
|
||||
captureWave = 5;
|
||||
difficulty = 3;
|
||||
}};
|
||||
|
||||
|
@ -328,6 +328,7 @@ public class Renderer implements ApplicationListener{
|
||||
Draw.draw(Layer.plans, overlays::drawBottom);
|
||||
|
||||
if(animateShields && Shaders.shield != null){
|
||||
//TODO would be nice if there were a way to detect if any shields or build beams actually *exist* before beginning/ending buffers, otherwise you're just blitting and swapping shaders for nothing
|
||||
Draw.drawRange(Layer.shields, 1f, () -> effectBuffer.begin(Color.clear), () -> {
|
||||
effectBuffer.end();
|
||||
effectBuffer.blit(Shaders.shield);
|
||||
|
@ -1036,6 +1036,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
int id = pos();
|
||||
TextureRegion region = renderer.blocks.cracks[block.size - 1][Mathf.clamp((int)((1f - healthf()) * BlockRenderer.crackRegions), 0, BlockRenderer.crackRegions-1)];
|
||||
Draw.colorl(0.2f, 0.1f + (1f - healthf())* 0.6f);
|
||||
//TODO could be random, flipped, pseudorandom, etc
|
||||
Draw.rect(region, x, y, (id%4)*90);
|
||||
Draw.color();
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public class Rules{
|
||||
/** Whether this is the editor gamemode. */
|
||||
public boolean editor = false;
|
||||
/** Whether a gameover can happen at all. Set this to false to implement custom gameover conditions. */
|
||||
public boolean canGameOver = true;
|
||||
public boolean canGameOver = false;
|
||||
/** Whether cores change teams when they are destroyed. */
|
||||
public boolean coreCapture = false;
|
||||
/** Whether reactors can explode and damage other blocks. */
|
||||
|
@ -359,7 +359,7 @@ public class BlockRenderer{
|
||||
for(int i = 0; i < tileview.size; i++){
|
||||
Tile tile = tileview.items[i];
|
||||
Block block = tile.block();
|
||||
Building entity = tile.build;
|
||||
Building build = tile.build;
|
||||
|
||||
Draw.z(Layer.block);
|
||||
|
||||
@ -374,20 +374,21 @@ public class BlockRenderer{
|
||||
Draw.z(Layer.block);
|
||||
}
|
||||
|
||||
if(entity != null){
|
||||
if(build != null){
|
||||
|
||||
if(entity.damaged()){
|
||||
entity.drawCracks();
|
||||
if(build.damaged()){
|
||||
Draw.z(Layer.blockCracks);
|
||||
build.drawCracks();
|
||||
Draw.z(Layer.block);
|
||||
}
|
||||
|
||||
if(entity.team != player.team()){
|
||||
entity.drawTeam();
|
||||
if(build.team != player.team()){
|
||||
build.drawTeam();
|
||||
Draw.z(Layer.block);
|
||||
}
|
||||
|
||||
if(entity.team == player.team() && renderer.drawStatus && block.consumes.any()){
|
||||
entity.drawStatus();
|
||||
if(build.team == player.team() && renderer.drawStatus && block.consumes.any()){
|
||||
build.drawStatus();
|
||||
}
|
||||
}
|
||||
Draw.reset();
|
||||
|
@ -26,6 +26,12 @@ public class Layer{
|
||||
//base block layer - most blocks go here
|
||||
block = 30,
|
||||
|
||||
//layer for cracks over blocks, batched to prevent excessive texture swaps
|
||||
blockCracks = 30f + 0.1f,
|
||||
|
||||
//some blocks need to draw stuff after cracks
|
||||
blockAfterCracks = 30f + 0.2f,
|
||||
|
||||
//informal layer used for additive blending overlay, grouped together to reduce draw calls
|
||||
blockAdditive = 31,
|
||||
|
||||
|
@ -61,7 +61,8 @@ public abstract class SaveFileReader{
|
||||
"block-unloader", "payload-unloader",
|
||||
"block-loader", "payload-loader",
|
||||
"thermal-pump", "impulse-pump",
|
||||
"alloy-smelter", "surge-smelter"
|
||||
"alloy-smelter", "surge-smelter",
|
||||
"steam-vent", "rhyolite-vent"
|
||||
);
|
||||
|
||||
public static final ObjectMap<String, String> modContentNameMap = ObjectMap.of(
|
||||
|
@ -324,10 +324,9 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
|
||||
|
||||
trimDark();
|
||||
|
||||
int minVents = rand.random(5, 8);
|
||||
int minVents = rand.random(6, 8);
|
||||
int ventCount = 0;
|
||||
|
||||
//TODO vents everywhere! rhyolite patches
|
||||
//vents
|
||||
outer:
|
||||
for(Tile tile : tiles){
|
||||
@ -346,7 +345,7 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
|
||||
ventCount ++;
|
||||
for(var pos : SteamVent.offsets){
|
||||
Tile other = tiles.get(pos.x + tile.x + 1, pos.y + tile.y + 1);
|
||||
other.setFloor(Blocks.steamVent.asFloor());
|
||||
other.setFloor(Blocks.rhyoliteVent.asFloor());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -358,22 +357,52 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
|
||||
while(ventCount < minVents && iterations++ < maxIterations){
|
||||
outer:
|
||||
for(Tile tile : tiles){
|
||||
if(rand.chance(0.00018)){
|
||||
if(rand.chance(0.00018 * (1 + iterations))){
|
||||
//skip crystals, but only when directly on them
|
||||
if(tile.floor() == Blocks.crystallineStone || tile.floor() == Blocks.crystalFloor){
|
||||
continue;
|
||||
}
|
||||
|
||||
int radius = 1;
|
||||
for(int x = -radius; x <= radius; x++){
|
||||
for(int y = -radius; y <= radius; y++){
|
||||
Tile other = tiles.get(x + tile.x, y + tile.y);
|
||||
//skip solids / other vents / arkycite / slag
|
||||
if(other == null || other.block().solid || other.floor() == Blocks.steamVent || other.floor() == Blocks.slag || other.floor() == Blocks.arkyciteFloor){
|
||||
if(other == null || other.block().solid || other.floor().attributes.get(Attribute.steam) != 0 || other.floor() == Blocks.slag || other.floor() == Blocks.arkyciteFloor){
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Block
|
||||
floor = Blocks.rhyolite,
|
||||
secondFloor = Blocks.rhyoliteCrater,
|
||||
vent = Blocks.rhyoliteVent;
|
||||
|
||||
int xDir = 1;
|
||||
//set target material depending on what's encountered
|
||||
if(tile.floor() == Blocks.beryllicStone || tile.floor() == Blocks.arkyicStone){
|
||||
floor = secondFloor = Blocks.arkyicStone;
|
||||
vent = Blocks.arkyicVent;
|
||||
}else if(tile.floor() == Blocks.yellowStone || tile.floor() == Blocks.yellowStonePlates || tile.floor() == Blocks.regolith){
|
||||
floor = Blocks.yellowStone;
|
||||
secondFloor = Blocks.yellowStonePlates;
|
||||
vent = Blocks.yellowStoneVent;
|
||||
}else if(tile.floor() == Blocks.redStone || tile.floor() == Blocks.denseRedStone){
|
||||
floor = Blocks.denseRedStone;
|
||||
secondFloor = Blocks.redStone;
|
||||
vent = Blocks.redStoneVent;
|
||||
xDir = -1;
|
||||
}else if(tile.floor() == Blocks.carbonStone){
|
||||
floor = secondFloor = Blocks.carbonStone;
|
||||
vent = Blocks.carbonVent;
|
||||
}
|
||||
|
||||
|
||||
ventCount ++;
|
||||
for(var pos : SteamVent.offsets){
|
||||
Tile other = tiles.get(pos.x + tile.x + 1, pos.y + tile.y + 1);
|
||||
other.setFloor(Blocks.steamVent.asFloor());
|
||||
other.setFloor(vent.asFloor());
|
||||
}
|
||||
|
||||
//"circle" for blending
|
||||
@ -384,12 +413,14 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
|
||||
int rx = cx + tile.x, ry = cy + tile.y;
|
||||
//skew circle Y
|
||||
float rcy = cy + cx*0.9f;
|
||||
if(cx*cx + rcy*rcy <= crad2 - noise(rx, ry + rx*2f, 2, 0.7f, 8f, crad2 * 1.1f)){
|
||||
if(cx*cx + rcy*rcy <= crad2 - noise(rx, ry + rx * 2f * xDir, 2, 0.7f, 8f, crad2 * 1.1f)){
|
||||
Tile dest = tiles.get(rx, ry);
|
||||
if(dest != null && dest.floor() != Blocks.steamVent && dest.floor() != Blocks.roughRhyolite && dest.floor() != Blocks.arkyciteFloor && dest.floor() != Blocks.slag){
|
||||
dest.setFloor(rand.chance(0.08) ? Blocks.rhyoliteCrater.asFloor() : Blocks.rhyolite.asFloor());
|
||||
if(dest != null && dest.floor().attributes.get(Attribute.steam) == 0 && dest.floor() != Blocks.roughRhyolite && dest.floor() != Blocks.arkyciteFloor && dest.floor() != Blocks.slag){
|
||||
|
||||
dest.setFloor(rand.chance(0.08) ? secondFloor.asFloor() : floor.asFloor());
|
||||
|
||||
if(dest.block().isStatic()){
|
||||
dest.setBlock(Blocks.rhyoliteWall);
|
||||
dest.setBlock(floor.asFloor().wall);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -149,13 +149,17 @@ public class ContentParser{
|
||||
|
||||
PartProgress base = (PartProgress)field(PartProgress.class, data.getString("type"));
|
||||
|
||||
JsonValue opval =
|
||||
data.has("operation") ? data.get("operation") :
|
||||
data.has("op") ? data.get("op") : null;
|
||||
|
||||
//no operations I guess (why would you do this?)
|
||||
if(!data.has("operation")){
|
||||
if(opval == null){
|
||||
return base;
|
||||
}
|
||||
|
||||
//this is the name of the method to call
|
||||
String op = data.getString("operation");
|
||||
String op = opval.asString();
|
||||
|
||||
//I have to hard-code this, no easy way of getting parameter names, unfortunately
|
||||
return switch(op){
|
||||
|
@ -171,6 +171,8 @@ public class UnitType extends UnlockableContent{
|
||||
public boolean forceMultiTarget = false;
|
||||
public boolean hidden = false;
|
||||
public boolean internal = false;
|
||||
/** A sample of the unit that this type creates. Do not modify! */
|
||||
public Unit sample;
|
||||
|
||||
//for crawlers
|
||||
public int segments = 0;
|
||||
@ -522,6 +524,9 @@ public class UnitType extends UnlockableContent{
|
||||
dpsEstimate /= 25f;
|
||||
}
|
||||
}
|
||||
|
||||
//only do this after everything else was initialized
|
||||
sample = constructor.get();
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
|
107
core/src/mindustry/world/blocks/defense/BaseShield.java
Normal file
@ -0,0 +1,107 @@
|
||||
package mindustry.world.blocks.defense;
|
||||
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class BaseShield extends Block{
|
||||
//TODO game rule? or field? should vary by base.
|
||||
//public float radius = 400f;
|
||||
|
||||
protected static BaseShieldBuild paramBuild;
|
||||
//protected static Effect paramEffect;
|
||||
protected static final Cons<Bullet> bulletConsumer = bullet -> {
|
||||
if(bullet.team != paramBuild.team && bullet.type.absorbable && bullet.within(paramBuild, paramBuild.radius())){
|
||||
bullet.absorb();
|
||||
//paramEffect.at(bullet);
|
||||
|
||||
//TODO effect, shield health go down?
|
||||
//paramBuild.hit = 1f;
|
||||
//paramBuild.buildup += bullet.damage;
|
||||
}
|
||||
};
|
||||
|
||||
protected static final Cons<Unit> unitConsumer = unit -> {
|
||||
//if this is positive, repel the unit; if it exceeds the unit radius * 2, it's inside the forcefield and must be killed
|
||||
float overlapDst = (unit.hitSize/2f + paramBuild.radius()) - unit.dst(paramBuild);
|
||||
|
||||
if(overlapDst > 0){
|
||||
if(overlapDst > unit.hitSize){
|
||||
//instakill units that are stuck inside the shield (TODO or maybe damage them instead?)
|
||||
unit.kill();
|
||||
}else{
|
||||
unit.move(Tmp.v1.set(unit).sub(paramBuild).setLength(overlapDst));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public BaseShield(String name){
|
||||
super(name);
|
||||
|
||||
hasPower = true;
|
||||
}
|
||||
|
||||
public class BaseShieldBuild extends Building{
|
||||
public boolean broken = false; //TODO
|
||||
public float hit = 0f;
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
//TODO smooth radius
|
||||
float radius = radius();
|
||||
|
||||
if(radius > 0 && !broken){
|
||||
paramBuild = this;
|
||||
//paramEffect = absorbEffect;
|
||||
Groups.bullet.intersect(x - radius, y - radius, radius * 2f, radius * 2f, bulletConsumer);
|
||||
Units.nearbyEnemies(team,x ,y, radius, unitConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
public float radius(){
|
||||
//TODO bad rule?
|
||||
return Vars.state.rules.enemyCoreBuildRadius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
super.draw();
|
||||
|
||||
drawShield();
|
||||
}
|
||||
|
||||
public void drawShield(){
|
||||
if(!broken){
|
||||
float radius = radius();
|
||||
|
||||
Draw.z(Layer.shields);
|
||||
|
||||
Draw.color(team.color, Color.white, Mathf.clamp(hit));
|
||||
|
||||
if(renderer.animateShields){
|
||||
Fill.circle(x, y, radius);
|
||||
}else{
|
||||
Lines.stroke(1.5f);
|
||||
Draw.alpha(0.09f + Mathf.clamp(0.08f * hit));
|
||||
Fill.circle(x, y, radius);
|
||||
Draw.alpha(1f);
|
||||
//TODO
|
||||
Lines.poly(x, y, 60, radius);
|
||||
Draw.reset();
|
||||
}
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
}
|
||||
}
|
@ -39,12 +39,12 @@ public class ForceProjector extends Block{
|
||||
|
||||
protected static ForceBuild paramEntity;
|
||||
protected static Effect paramEffect;
|
||||
protected static final Cons<Bullet> shieldConsumer = trait -> {
|
||||
if(trait.team != paramEntity.team && trait.type.absorbable && Intersector.isInsideHexagon(paramEntity.x, paramEntity.y, paramEntity.realRadius() * 2f, trait.x(), trait.y())){
|
||||
trait.absorb();
|
||||
paramEffect.at(trait);
|
||||
protected static final Cons<Bullet> shieldConsumer = bullet -> {
|
||||
if(bullet.team != paramEntity.team && bullet.type.absorbable && Intersector.isInsideHexagon(paramEntity.x, paramEntity.y, paramEntity.realRadius() * 2f, bullet.x, bullet.y)){
|
||||
bullet.absorb();
|
||||
paramEffect.at(bullet);
|
||||
paramEntity.hit = 1f;
|
||||
paramEntity.buildup += trait.damage();
|
||||
paramEntity.buildup += bullet.damage;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -325,8 +325,10 @@ public class Drill extends Block{
|
||||
float ts = 0.6f;
|
||||
|
||||
Draw.rect(region, x, y);
|
||||
Draw.z(Layer.blockCracks);
|
||||
drawDefaultCracks();
|
||||
|
||||
Draw.z(Layer.blockAfterCracks);
|
||||
if(drawRim){
|
||||
Draw.color(heatColor);
|
||||
Draw.alpha(warmup * ts * (1f - s + Mathf.absin(Time.time, 3f, s)));
|
||||
|
@ -103,7 +103,9 @@ public class SolidPump extends Pump{
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect(region, x, y);
|
||||
Draw.z(Layer.blockCracks);
|
||||
super.drawCracks();
|
||||
Draw.z(Layer.blockAfterCracks);
|
||||
|
||||
Drawf.liquid(liquidRegion, x, y, liquids.get(result) / liquidCapacity, result.color);
|
||||
Drawf.spinSprite(rotatorRegion, x, y, pumpTime * rotateSpeed);
|
||||
|
@ -21,7 +21,7 @@ public class Attribute{
|
||||
/** Used for sand extraction. */
|
||||
sand = add("sand"),
|
||||
/** Used for erekir vents only. */
|
||||
vent = add("vent");
|
||||
steam = add("steam");
|
||||
|
||||
public final int id;
|
||||
public final String name;
|
||||
|
@ -765,7 +765,7 @@ public class ApplicationTests{
|
||||
|
||||
@Test
|
||||
void allBlockTest(){
|
||||
Tiles tiles = world.resize(256 * 4 + 20, 10);
|
||||
Tiles tiles = world.resize(80, 80);
|
||||
|
||||
world.beginMapLoad();
|
||||
for(int x = 0; x < tiles.width; x++){
|
||||
@ -773,14 +773,24 @@ public class ApplicationTests{
|
||||
tiles.set(x, y, new Tile(x, y, Blocks.stone, Blocks.air, Blocks.air));
|
||||
}
|
||||
}
|
||||
int i = 0;
|
||||
int maxHeight = 0;
|
||||
state.rules.canGameOver = false;
|
||||
state.rules.borderDarkness = false;
|
||||
|
||||
for(int x = 5; x < tiles.width && i < content.blocks().size; ){
|
||||
Block block = content.block(i++);
|
||||
for(int x = 0, y = 0, i = 0; i < content.blocks().size; i ++){
|
||||
Block block = content.block(i);
|
||||
if(block.canBeBuilt()){
|
||||
int offset = Math.max(block.size % 2 == 0 ? block.size/2 - 1 : block.size/2, 0);
|
||||
|
||||
if(x + block.size + 1 >= world.width()){
|
||||
y += maxHeight;
|
||||
maxHeight = 0;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
tiles.get(x + offset, y + offset).setBlock(block);
|
||||
x += block.size;
|
||||
tiles.get(x, 5).setBlock(block);
|
||||
x += block.size;
|
||||
maxHeight = Math.max(maxHeight, block.size);
|
||||
}
|
||||
}
|
||||
world.endMapLoad();
|
||||
@ -903,14 +913,16 @@ public class ApplicationTests{
|
||||
if(state.rules.attackMode){
|
||||
bossWave = 100;
|
||||
}else{
|
||||
assertNotEquals(0, bossWave, "Sector doesn't have a boss wave.");
|
||||
assertNotEquals(0, bossWave, "Sector doesn't have a boss/end wave.");
|
||||
}
|
||||
|
||||
if(state.rules.winWave > 0) bossWave = state.rules.winWave - 1;
|
||||
|
||||
//TODO check for difficulty?
|
||||
for(int i = 1; i <= bossWave; i++){
|
||||
int total = 0;
|
||||
for(SpawnGroup spawn : spawns){
|
||||
total += spawn.getSpawned(i);
|
||||
total += spawn.getSpawned(i - 1);
|
||||
}
|
||||
|
||||
assertNotEquals(0, total, "Sector " + zone + " has no spawned enemies at wave " + i);
|
||||
|
@ -95,13 +95,7 @@ public class PowerTestFixture{
|
||||
// Simulate the "changed" method. Calling it through reflections would require half the game to be initialized.
|
||||
tile.build = block.newBuilding().init(tile, Team.sharded, false, 0);
|
||||
if(block.hasPower){
|
||||
new PowerGraph(){
|
||||
//assume there's always something consuming power
|
||||
@Override
|
||||
public float getUsageFraction(){
|
||||
return 1f;
|
||||
}
|
||||
}.add(tile.build);
|
||||
new PowerGraph().add(tile.build);
|
||||
}
|
||||
|
||||
// Assign incredibly high health so the block does not get destroyed on e.g. burning Blast Compound
|
||||
|
@ -275,7 +275,7 @@ public class Generators{
|
||||
}
|
||||
}
|
||||
|
||||
Fi.get("cracks-" + size + "-" + i + ".png").writePng(output);
|
||||
Fi.get("../rubble/cracks-" + size + "-" + i + ".png").writePng(output);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -560,6 +560,16 @@ public class Generators{
|
||||
|
||||
Pixmap image = type.segments > 0 ? get(type.segmentRegions[0]) : outline.get(get(type.region));
|
||||
|
||||
Func<Weapon, Pixmap> weaponRegion = weapon -> Core.atlas.has(weapon.name + "-preview") ? get(weapon.name + "-preview") : get(weapon.region);
|
||||
Cons2<Weapon, Pixmap> drawWeapon = (weapon, pixmap) ->
|
||||
image.draw(weapon.flipSprite ? pixmap.flipX() : pixmap,
|
||||
(int)(weapon.x / Draw.scl + image.width / 2f - weapon.region.width / 2f),
|
||||
(int)(-weapon.y / Draw.scl + image.height / 2f - weapon.region.height / 2f),
|
||||
true
|
||||
);
|
||||
|
||||
boolean anyUnder = false;
|
||||
|
||||
//draw each extra segment on top before it is saved as outline
|
||||
if(sample instanceof Crawlc){
|
||||
for(int i = 0; i < type.segments; i++){
|
||||
@ -579,6 +589,17 @@ public class Generators{
|
||||
replace(type.name, image);
|
||||
}
|
||||
|
||||
//draw weapons that are under the base
|
||||
for(Weapon weapon : weapons.select(w -> w.layerOffset < 0)){
|
||||
drawWeapon.get(weapon, outline.get(weaponRegion.get(weapon)));
|
||||
anyUnder = true;
|
||||
}
|
||||
|
||||
//draw over the weapons under the image
|
||||
if(anyUnder){
|
||||
image.draw(outline.get(get(type.region)), true);
|
||||
}
|
||||
|
||||
//draw treads
|
||||
if(sample instanceof Tankc){
|
||||
image.draw(outline.get(get(type.treadRegion)), true);
|
||||
@ -593,14 +614,12 @@ public class Generators{
|
||||
image.draw(get(type.region), true);
|
||||
}
|
||||
|
||||
//TODO draw under for layerOffset < 0
|
||||
//draw weapon outlines on base
|
||||
for(Weapon weapon : weapons){
|
||||
image.draw(weapon.flipSprite ? outline.get(get(weapon.region)).flipX() : outline.get(get(weapon.region)),
|
||||
(int)(weapon.x / Draw.scl + image.width / 2f - weapon.region.width / 2f),
|
||||
(int)(-weapon.y / Draw.scl + image.height / 2f - weapon.region.height / 2f),
|
||||
true
|
||||
);
|
||||
//skip weapons under unit
|
||||
if(weapon.layerOffset < 0) continue;
|
||||
|
||||
drawWeapon.get(weapon, outline.get(weaponRegion.get(weapon)));
|
||||
}
|
||||
|
||||
//draw base region on top to mask weapons
|
||||
@ -610,24 +629,23 @@ public class Generators{
|
||||
Pixmap baseCell = get(type.cellRegion);
|
||||
Pixmap cell = baseCell.copy();
|
||||
|
||||
//replace with 0xffd37fff : 0xdca463ff for sharded colors?
|
||||
cell.replace(in -> in == 0xffffffff ? 0xffa664ff : in == 0xdcc6c6ff || in == 0xdcc5c5ff ? 0xd06b53ff : 0);
|
||||
//replace with 0xffd37fff : 0xdca463ff for sharded colors?
|
||||
cell.replace(in -> in == 0xffffffff ? 0xffa664ff : in == 0xdcc6c6ff || in == 0xdcc5c5ff ? 0xd06b53ff : 0);
|
||||
|
||||
image.draw(cell, image.width / 2 - cell.width / 2, image.height / 2 - cell.height / 2, true);
|
||||
}
|
||||
|
||||
for(Weapon weapon : weapons){
|
||||
Pixmap wepReg = weapon.top ? outline.get(get(weapon.region)) : get(weapon.region);
|
||||
if(weapon.flipSprite){
|
||||
wepReg = wepReg.flipX();
|
||||
}
|
||||
//skip weapons under unit
|
||||
if(weapon.layerOffset < 0) continue;
|
||||
|
||||
image.draw(wepReg,
|
||||
(int)(weapon.x / Draw.scl + image.width / 2f - weapon.region.width / 2f),
|
||||
(int)(-weapon.y / Draw.scl + image.height / 2f - weapon.region.height / 2f),
|
||||
true);
|
||||
Pixmap reg = weaponRegion.get(weapon);
|
||||
Pixmap wepReg = weapon.top ? outline.get(reg) : reg;
|
||||
|
||||
drawWeapon.get(weapon, wepReg);
|
||||
}
|
||||
|
||||
//TODO I can save a LOT of space by not creating a full icon.
|
||||
save(image, "unit-" + type.name + "-full");
|
||||
|
||||
Rand rand = new Rand();
|
||||
|