Implemented puddles of liquid
This commit is contained in:
@@ -11,12 +11,14 @@ public class Liquids {
|
||||
water = new Liquid("water", Color.valueOf("486acd")) {
|
||||
{
|
||||
heatCapacity = 0.4f;
|
||||
effect = StatusEffects.wet;
|
||||
}
|
||||
},
|
||||
lava = new Liquid("lava", Color.valueOf("e37341")) {
|
||||
{
|
||||
temperature = 0.7f;
|
||||
temperature = 0.8f;
|
||||
viscosity = 0.8f;
|
||||
effect = StatusEffects.melting;
|
||||
}
|
||||
},
|
||||
oil = new Liquid("oil", Color.valueOf("313131")) {
|
||||
@@ -24,12 +26,14 @@ public class Liquids {
|
||||
viscosity = 0.7f;
|
||||
flammability = 0.6f;
|
||||
explosiveness = 0.6f;
|
||||
effect = StatusEffects.oiled;
|
||||
}
|
||||
},
|
||||
cryofluid = new Liquid("cryofluid", Color.SKY) {
|
||||
{
|
||||
heatCapacity = 0.75f;
|
||||
temperature = 0.5f;
|
||||
effect = StatusEffects.freezing;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.anuke.mindustry.content.bullets;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import io.anuke.mindustry.content.Liquids;
|
||||
import io.anuke.mindustry.content.StatusEffects;
|
||||
import io.anuke.mindustry.content.fx.BulletFx;
|
||||
@@ -8,7 +9,9 @@ import io.anuke.mindustry.content.fx.Fx;
|
||||
import io.anuke.mindustry.entities.Bullet;
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.effect.DamageArea;
|
||||
import io.anuke.mindustry.entities.effect.Fire;
|
||||
import io.anuke.mindustry.entities.effect.Lightning;
|
||||
import io.anuke.mindustry.entities.effect.Puddle;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.resource.Liquid;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
@@ -16,8 +19,12 @@ import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Fill;
|
||||
import io.anuke.ucore.graphics.Lines;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.tilesize;
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public class TurretBullets {
|
||||
|
||||
public static final BulletType
|
||||
@@ -220,6 +227,15 @@ public class TurretBullets {
|
||||
@Override
|
||||
public void hit(Bullet b, float hitx, float hity) {
|
||||
Effects.effect(hiteffect, liquid.color, hitx, hity);
|
||||
Puddle.deposit(world.tileWorld(hitx, hity), liquid, 5f);
|
||||
|
||||
if(liquid.temperature <= 0.5f && liquid.flammability < 0.3f){
|
||||
float intensity = 400f;
|
||||
Fire.extinguish(world.tileWorld(hitx, hity), intensity);
|
||||
for(GridPoint2 p : Geometry.d4){
|
||||
Fire.extinguish(world.tileWorld(hitx + p.x*tilesize, hity + p.y*tilesize), intensity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,16 @@ public class EnvironmentFx {
|
||||
Draw.color();
|
||||
}),
|
||||
|
||||
steam = new Effect(35f, e -> {
|
||||
Draw.color(Color.LIGHT_GRAY);
|
||||
|
||||
Angles.randLenVectors(e.id, 2, 2f + e.fin()*7f, (x, y) -> {
|
||||
Fill.circle(e.x + x, e.y + y, 0.2f + e.fslope() * 1.5f);
|
||||
});
|
||||
|
||||
Draw.color();
|
||||
}),
|
||||
|
||||
fireballsmoke = new Effect(25f, e -> {
|
||||
Draw.color(Color.GRAY);
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ public class Fire extends TimedEntity {
|
||||
private static GridMap<Fire> map = new GridMap<>();
|
||||
|
||||
private Tile tile;
|
||||
private float flammability = -1;
|
||||
private float baseFlammability = -1, puddleFlammability;
|
||||
|
||||
public static void create(Tile tile){
|
||||
if(!map.containsKey(tile.x, tile.y)){
|
||||
@@ -26,6 +26,12 @@ public class Fire extends TimedEntity {
|
||||
}
|
||||
}
|
||||
|
||||
public static void extinguish(Tile tile, float intensity){
|
||||
if(map.containsKey(tile.x, tile.y)){
|
||||
map.get(tile.x, tile.y).time += intensity * Timers.delta();
|
||||
}
|
||||
}
|
||||
|
||||
private Fire(Tile tile){
|
||||
this.tile = tile;
|
||||
lifetime = 1000f;
|
||||
@@ -38,12 +44,14 @@ public class Fire extends TimedEntity {
|
||||
TileEntity entity = tile.target().entity;
|
||||
boolean damage = entity != null;
|
||||
|
||||
float flammability = baseFlammability + puddleFlammability;
|
||||
|
||||
if(!damage && flammability <= 0){
|
||||
time += Timers.delta()*8;
|
||||
}
|
||||
|
||||
if (flammability < 0){
|
||||
flammability = tile.block().getFlammability(tile);
|
||||
if (baseFlammability < 0){
|
||||
baseFlammability = tile.block().getFlammability(tile);
|
||||
}
|
||||
|
||||
if(damage) {
|
||||
@@ -59,6 +67,13 @@ public class Fire extends TimedEntity {
|
||||
if(Mathf.chance(0.1 * Timers.delta())){
|
||||
Effects.effect(EnvironmentFx.fire, tile.worldx() + Mathf.range(4f), tile.worldy() + Mathf.range(4f));
|
||||
|
||||
Puddle p = Puddle.getPuddle(tile);
|
||||
if(p != null){
|
||||
puddleFlammability = p.getFlammability()/3f;
|
||||
}else{
|
||||
puddleFlammability = 0;
|
||||
}
|
||||
|
||||
if(damage){
|
||||
entity.damage(0.4f);
|
||||
}
|
||||
|
||||
163
core/src/io/anuke/mindustry/entities/effect/Puddle.java
Normal file
163
core/src/io/anuke/mindustry/entities/effect/Puddle.java
Normal file
@@ -0,0 +1,163 @@
|
||||
package io.anuke.mindustry.entities.effect;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.content.blocks.Blocks;
|
||||
import io.anuke.mindustry.content.fx.BlockFx;
|
||||
import io.anuke.mindustry.content.fx.EnvironmentFx;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
import io.anuke.mindustry.resource.Liquid;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Fill;
|
||||
import io.anuke.ucore.graphics.Hue;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
import io.anuke.ucore.util.GridMap;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public class Puddle extends Entity {
|
||||
private static final GridMap<Puddle> map = new GridMap<>();
|
||||
private static final float maxLiquid = 70f;
|
||||
private static final int maxGeneration = 2;
|
||||
private static final Color tmp = new Color();
|
||||
private static final Rectangle rect = new Rectangle();
|
||||
|
||||
private Tile tile;
|
||||
private Liquid liquid;
|
||||
private float amount;
|
||||
private int generation;
|
||||
private float accepting;
|
||||
|
||||
public static void deposit(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
deposit(tile, source, liquid, amount, 0);
|
||||
}
|
||||
|
||||
public static void deposit(Tile tile, Liquid liquid, float amount){
|
||||
deposit(tile, tile, liquid, amount, 0);
|
||||
}
|
||||
|
||||
public static Puddle getPuddle(Tile tile){
|
||||
return map.get(tile.x, tile.y);
|
||||
}
|
||||
|
||||
private static void deposit(Tile tile, Tile source, Liquid liquid, float amount, int generation){
|
||||
Puddle p = map.get(tile.x, tile.y);
|
||||
if(p == null){
|
||||
Puddle puddle = new Puddle(tile, source, liquid, amount, generation).add();
|
||||
map.put(tile.x, tile.y, puddle);
|
||||
}else if(p.liquid == liquid){
|
||||
p.accepting = Math.max(amount, p.accepting);
|
||||
|
||||
if(generation == 0 && Timers.get(p, "ripple", 50) && p.amount >= maxLiquid/2f){
|
||||
Effects.effect(BlockFx.ripple, p.liquid.color, (tile.worldx() + source.worldx())/2f, (tile.worldy() + source.worldy())/2f);
|
||||
}
|
||||
}else{
|
||||
reactPuddle(p, liquid, amount);
|
||||
}
|
||||
}
|
||||
|
||||
private static void reactPuddle(Puddle p, Liquid liquid, float amount){
|
||||
if((p.liquid.flammability > 0.3f && liquid.temperature > 0.7f) ||
|
||||
liquid.flammability > 0.3f && p.liquid.temperature > 0.7f){ //flammable liquid + hot liquid
|
||||
Fire.create(p.tile);
|
||||
if(Mathf.chance(0.006 * amount)){
|
||||
new Fireball(p.x, p.y, p.liquid.flameColor, Mathf.random(360f)).add();
|
||||
}
|
||||
}else if(p.liquid.temperature > 0.7f && liquid.temperature < 0.55f){ //cold liquid poured onto hot puddle
|
||||
if(Mathf.chance(0.5f * amount)){
|
||||
Effects.effect(EnvironmentFx.steam, p.x, p.y);
|
||||
}
|
||||
p.amount -= 0.1f * amount;
|
||||
}else if(liquid.temperature > 0.7f && p.liquid.temperature < 0.55f){ //hot liquid poured onto cold puddle
|
||||
if(Mathf.chance(0.8f * amount)){
|
||||
Effects.effect(EnvironmentFx.steam, p.x, p.y);
|
||||
}
|
||||
p.amount -= 0.4f * amount;
|
||||
}
|
||||
}
|
||||
|
||||
private Puddle(Tile tile, Tile source, Liquid liquid, float amount, int generation) {
|
||||
this.tile = tile;
|
||||
this.liquid = liquid;
|
||||
this.amount = amount;
|
||||
this.generation = generation;
|
||||
set((tile.worldx() + source.worldx())/2f, (tile.worldy() + source.worldy())/2f);
|
||||
}
|
||||
|
||||
public float getFlammability(){
|
||||
return liquid.flammability * amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
float addSpeed = accepting > 0 ? 3f : 0f;
|
||||
|
||||
amount -= Timers.delta() * (1f - liquid.viscosity) /(5f+addSpeed);
|
||||
|
||||
amount += accepting;
|
||||
accepting = 0f;
|
||||
|
||||
if(amount >= maxLiquid/1.5f && generation < maxGeneration){
|
||||
float deposited = Math.min((amount - maxLiquid/1.5f)/4f, 0.3f) * Timers.delta();
|
||||
for(GridPoint2 point : Geometry.d4){
|
||||
Tile other = world.tile(tile.x + point.x, tile.y + point.y);
|
||||
if(other.block() == Blocks.air){
|
||||
deposit(other, tile, liquid, deposited, generation + 1);
|
||||
amount -= deposited/4f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(amount >= maxLiquid/2f && Timers.get(this, "update", 20)){
|
||||
Units.getNearby(rect.setSize(Mathf.clamp(amount/(maxLiquid/1.5f))*10f).setCenter(tile.worldx(), tile.worldy()), unit -> {
|
||||
Rectangle o = unit.hitbox.getRect(unit.x, unit.y);
|
||||
if(!rect.overlaps(o)) return;
|
||||
|
||||
unit.applyEffect(liquid.effect, 0.5f);
|
||||
if(unit.velocity.len() > 0.4) {
|
||||
Effects.effect(BlockFx.ripple, liquid.color, unit.x, unit.y);
|
||||
}
|
||||
});
|
||||
|
||||
if(liquid.temperature > 0.7f && tile.entity != null && Mathf.chance(0.3 * Timers.delta())){
|
||||
Fire.create(tile);
|
||||
}
|
||||
}
|
||||
|
||||
amount = Mathf.clamp(amount, 0, maxLiquid);
|
||||
|
||||
if(amount <= 0f){
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
float f = Mathf.clamp(amount/(maxLiquid/1.5f));
|
||||
|
||||
Draw.color(Hue.shift(tmp.set(liquid.color), 2, -0.05f));
|
||||
Fill.circle(x, y, f * 8f);
|
||||
Angles.randLenVectors(id, 3, f * 6f, (ex, ey) -> {
|
||||
Fill.circle(x + ex, y + ey, f * 5f);
|
||||
});
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed() {
|
||||
map.remove(tile.x, tile.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Puddle add() {
|
||||
return add(Vars.groundEffectGroup);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package io.anuke.mindustry.resource;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.content.StatusEffects;
|
||||
import io.anuke.mindustry.entities.StatusEffect;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
|
||||
public class Liquid {
|
||||
@@ -24,6 +26,8 @@ public class Liquid {
|
||||
public float explosiveness;
|
||||
/**the burning color of this liquid*/
|
||||
public Color flameColor = Color.valueOf("ffb763");
|
||||
/**The associated status effect.*/
|
||||
public StatusEffect effect = StatusEffects.none;
|
||||
|
||||
public Liquid(String name, Color color) {
|
||||
this.name = name;
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.anuke.mindustry.world;
|
||||
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.entities.effect.Puddle;
|
||||
import io.anuke.mindustry.resource.Item;
|
||||
import io.anuke.mindustry.resource.Liquid;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
@@ -108,7 +109,7 @@ public abstract class BaseBlock {
|
||||
}
|
||||
}
|
||||
|
||||
public float tryMoveLiquid(Tile tile, Tile next){
|
||||
public float tryMoveLiquid(Tile tile, Tile next, boolean leak){
|
||||
if(next == null) return 0;
|
||||
|
||||
next = next.target();
|
||||
@@ -132,6 +133,10 @@ public abstract class BaseBlock {
|
||||
tile.entity.liquid.amount -= amount;
|
||||
return flow;
|
||||
}
|
||||
}else if(leak && !next.block().solid && !next.block().hasLiquids){
|
||||
float leakAmount = Math.min(tile.entity.liquid.amount, tile.entity.liquid.amount/1.5f);
|
||||
Puddle.deposit(next, tile, tile.entity.liquid.liquid, leakAmount);
|
||||
tile.entity.liquid.amount -= leakAmount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class Conduit extends LiquidBlock {
|
||||
entity.smoothLiquid = Mathf.lerpDelta(entity.smoothLiquid, entity.liquid.amount/liquidCapacity, 0.05f);
|
||||
|
||||
if(tile.entity.liquid.amount > 0.001f && tile.entity.timer.get(timerFlow, 1)){
|
||||
tryMoveLiquid(tile, tile.getNearby(tile.getRotation()));
|
||||
tryMoveLiquid(tile, tile.getNearby(tile.getRotation()), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class LiquidBridge extends ItemBridge {
|
||||
|
||||
if(entity.uptime >= 0.5f){
|
||||
|
||||
if(tryMoveLiquid(tile, other) > 0.1f){
|
||||
if(tryMoveLiquid(tile, other, false) > 0.1f){
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 4f, 0.05f);
|
||||
}else{
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 1f, 0.01f);
|
||||
|
||||
@@ -37,7 +37,7 @@ public class LiquidExtendingBridge extends ExtendingItemBridge {
|
||||
|
||||
if(entity.uptime >= 0.5f){
|
||||
|
||||
if(tryMoveLiquid(tile, other) > 0.1f){
|
||||
if(tryMoveLiquid(tile, other, false) > 0.1f){
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 4f, 0.05f);
|
||||
}else{
|
||||
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 1f, 0.01f);
|
||||
|
||||
Reference in New Issue
Block a user