diff --git a/core/assets/planets/TODO.dat b/core/assets/planets/TODO.dat index e8220fa481..eb42302979 100644 Binary files a/core/assets/planets/TODO.dat and b/core/assets/planets/TODO.dat differ diff --git a/core/src/mindustry/content/Weathers.java b/core/src/mindustry/content/Weathers.java index 9c3a16ea44..d5b7699076 100644 --- a/core/src/mindustry/content/Weathers.java +++ b/core/src/mindustry/content/Weathers.java @@ -11,6 +11,7 @@ import mindustry.ctype.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; +import mindustry.world.meta.*; import static mindustry.Vars.*; @@ -18,7 +19,8 @@ public class Weathers implements ContentList{ public static Weather rain, snow, - sandstorm; + sandstorm, + sporestorm; @Override public void load(){ @@ -26,6 +28,10 @@ public class Weathers implements ContentList{ TextureRegion region; float yspeed = 2f, xspeed = 0.25f, padding = 16f, size = 12f, density = 1200f; + { + attrs.set(Attribute.light, -0.15f); + } + @Override public void load(){ super.load(); @@ -69,6 +75,11 @@ public class Weathers implements ContentList{ float yspeed = 5f, xspeed = 1.5f, padding = 16f, size = 40f, density = 1200f; TextureRegion[] splashes = new TextureRegion[12]; + { + attrs.set(Attribute.light, -0.2f); + attrs.set(Attribute.water, 0.2f); + } + @Override public void load(){ super.load(); @@ -164,6 +175,10 @@ public class Weathers implements ContentList{ Color color = Color.valueOf("f7cba4"); Texture noise; + { + attrs.set(Attribute.light, -0.1f); + } + @Override public void load(){ region = Core.atlas.find("circle-shadow"); @@ -229,5 +244,76 @@ public class Weathers implements ContentList{ } } }; + + sporestorm = new Weather("sporestorm"){ + TextureRegion region; + float yspeed = 1f, xspeed = 4f, size = 5f, padding = size, invDensity = 2000f; + Color color = Color.valueOf("7457ce"); + Texture noise; + + { + attrs.set(Attribute.spores, 0.5f); + attrs.set(Attribute.light, -0.1f); + } + + @Override + public void load(){ + region = Core.atlas.find("circle-shadow"); + noise = new Texture("sprites/noiseAlpha.png"); + noise.setWrap(TextureWrap.repeat); + noise.setFilter(TextureFilter.linear); + } + + @Override + public void dispose(){ + noise.dispose(); + } + + @Override + public void drawOver(WeatherState state){ + Draw.alpha(state.opacity * 0.8f); + Draw.tint(color); + + float scale = 1f / 2000f; + float scroll = Time.time() * scale; + Tmp.tr1.setTexture(noise); + Core.camera.bounds(Tmp.r1); + Tmp.tr1.set(Tmp.r1.x*scale, Tmp.r1.y*scale, (Tmp.r1.x + Tmp.r1.width)*scale, (Tmp.r1.y + Tmp.r1.height)*scale); + Tmp.tr1.scroll(-xspeed * scroll, -yspeed * scroll); + Draw.rect(Tmp.tr1, Core.camera.position.x, Core.camera.position.y, Core.camera.width, -Core.camera.height); + + rand.setSeed(0); + Tmp.r1.setCentered(Core.camera.position.x, Core.camera.position.y, Core.graphics.getWidth() / renderer.minScale(), Core.graphics.getHeight() / renderer.minScale()); + Tmp.r1.grow(padding); + Core.camera.bounds(Tmp.r2); + int total = (int)(Tmp.r1.area() / invDensity * state.intensity()); + Draw.tint(color); + float baseAlpha = state.opacity; + Draw.alpha(baseAlpha); + + for(int i = 0; i < total; i++){ + float scl = rand.random(0.5f, 1f); + float scl2 = rand.random(0.5f, 1f); + float sscl = rand.random(0.5f, 1f); + float x = (rand.random(0f, world.unitWidth()) + Time.time() * xspeed * scl2); + float y = (rand.random(0f, world.unitHeight()) - Time.time() * yspeed * scl); + float alpha = rand.random(0.1f, 0.8f); + + x += Mathf.sin(y, rand.random(30f, 80f), rand.random(1f, 7f)); + + x -= Tmp.r1.x; + y -= Tmp.r1.y; + x = Mathf.mod(x, Tmp.r1.width); + y = Mathf.mod(y, Tmp.r1.height); + x += Tmp.r1.x; + y += Tmp.r1.y; + + if(Tmp.r3.setCentered(x, y, size * sscl).overlaps(Tmp.r2)){ + Draw.alpha(alpha * baseAlpha); + Fill.circle(x, y, size * sscl / 2f); + } + } + } + }; } } diff --git a/core/src/mindustry/core/GameState.java b/core/src/mindustry/core/GameState.java index b006aae76f..b3f5e49213 100644 --- a/core/src/mindustry/core/GameState.java +++ b/core/src/mindustry/core/GameState.java @@ -7,6 +7,7 @@ import mindustry.game.*; import mindustry.gen.*; import mindustry.maps.*; import mindustry.type.*; +import mindustry.world.blocks.*; import static mindustry.Vars.*; @@ -23,6 +24,8 @@ public class GameState{ public Rules rules = new Rules(); /** Statistics for this save/game. Displayed after game over. */ public Stats stats = new Stats(); + /** Global attributes of the environment, calculated by weather. */ + public Attributes envAttrs = new Attributes(); /** Sector information. Only valid in the campaign. */ public SectorInfo secinfo = new SectorInfo(); /** Team data. Gets reset every new game. */ diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index 74f36a3c5a..d8d8f4871a 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -352,6 +352,10 @@ public class Logic implements ApplicationListener{ runWave(); } + //apply weather attributes + state.envAttrs.clear(); + Groups.weather.each(w -> state.envAttrs.add(w.weather.attrs, w.opacity)); + Groups.update(); } diff --git a/core/src/mindustry/editor/WaveGraph.java b/core/src/mindustry/editor/WaveGraph.java index eb2ac64359..c6e7a9cac6 100644 --- a/core/src/mindustry/editor/WaveGraph.java +++ b/core/src/mindustry/editor/WaveGraph.java @@ -139,7 +139,7 @@ public class WaveGraph extends Table{ for(Mode m : Mode.all){ t.button("$wavemode." + m.name(), Styles.fullTogglet, () -> { mode = m; - }).group(group).height(32f).update(b -> b.setChecked(m == mode)).width(100f); + }).group(group).height(32f).update(b -> b.setChecked(m == mode)).width(130f); } }).growX(); } @@ -201,6 +201,7 @@ public class WaveGraph extends Table{ enum Mode{ counts, totals, health; + static Mode[] all = values(); } } diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index b9f557fd28..621bad7959 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -703,7 +703,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } public float getProgressIncrease(float baseTime){ - return 1f / baseTime * delta() * efficiency(); + return 1f / baseTime * edelta(); + } + + public float getDisplayEfficiency(){ + return getProgressIncrease(1f) / edelta(); } /** @return whether this block should play its active sound.*/ diff --git a/core/src/mindustry/type/Sector.java b/core/src/mindustry/type/Sector.java index d6aab89708..d42560ba9a 100644 --- a/core/src/mindustry/type/Sector.java +++ b/core/src/mindustry/type/Sector.java @@ -390,6 +390,8 @@ public class Sector{ /** Has sandstorms. */ desert, /** Has an enemy base. */ - base + base, + /** Has spore weather. */ + spores } } diff --git a/core/src/mindustry/type/Weather.java b/core/src/mindustry/type/Weather.java index a1d23a0a76..21f3863dcc 100644 --- a/core/src/mindustry/type/Weather.java +++ b/core/src/mindustry/type/Weather.java @@ -8,12 +8,14 @@ import mindustry.annotations.Annotations.*; import mindustry.ctype.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.world.blocks.*; import static mindustry.Vars.renderer; public abstract class Weather extends MappableContent{ /** Default duration of this weather event in ticks. */ public float duration = 15f * Time.toMinutes; + public Attributes attrs = new Attributes(); //internals public Rand rand = new Rand(); diff --git a/core/src/mindustry/world/blocks/Attributes.java b/core/src/mindustry/world/blocks/Attributes.java index 487b093314..50c907e218 100644 --- a/core/src/mindustry/world/blocks/Attributes.java +++ b/core/src/mindustry/world/blocks/Attributes.java @@ -1,15 +1,51 @@ package mindustry.world.blocks; +import arc.util.serialization.*; +import arc.util.serialization.Json.*; import mindustry.world.meta.Attribute; -public class Attributes{ - private float[] array = new float[Attribute.values().length]; +import java.util.*; + +public class Attributes implements Serializable{ + private final float[] arr = new float[Attribute.all.length]; + + public void clear(){ + Arrays.fill(arr, 0); + } public float get(Attribute attr){ - return array[attr.ordinal()]; + return arr[attr.ordinal()]; } public void set(Attribute attr, float value){ - array[attr.ordinal()] = value; + arr[attr.ordinal()] = value; + } + + public void add(Attributes other){ + for(int i = 0; i < arr.length; i++){ + arr[i] += other.arr[i]; + } + } + + public void add(Attributes other, float scl){ + for(int i = 0; i < arr.length; i++){ + arr[i] += other.arr[i] * scl; + } + } + + @Override + public void write(Json json){ + for(Attribute at : Attribute.all){ + if(arr[at.ordinal()] != 0){ + json.writeValue(at.name(), arr[at.ordinal()]); + } + } + } + + @Override + public void read(Json json, JsonValue data){ + for(Attribute at : Attribute.all){ + arr[at.ordinal()] = data.getFloat(at.name(), 0); + } } } diff --git a/core/src/mindustry/world/blocks/power/SolarGenerator.java b/core/src/mindustry/world/blocks/power/SolarGenerator.java index 2c79557e5d..2ca0030e1e 100644 --- a/core/src/mindustry/world/blocks/power/SolarGenerator.java +++ b/core/src/mindustry/world/blocks/power/SolarGenerator.java @@ -1,5 +1,6 @@ package mindustry.world.blocks.power; +import arc.math.*; import arc.struct.*; import mindustry.world.meta.*; @@ -23,7 +24,10 @@ public class SolarGenerator extends PowerGenerator{ public class SolarGeneratorEntity extends GeneratorEntity{ @Override public void updateTile(){ - productionEfficiency = state.rules.solarPowerMultiplier < 0 ? (state.rules.lighting ? 1f - state.rules.ambientLight.a : 1f) : state.rules.solarPowerMultiplier; + productionEfficiency = + Mathf.maxZero(Attribute.light.env() + state.rules.solarPowerMultiplier < 0 ? + (state.rules.lighting ? 1f - state.rules.ambientLight.a : 1f) : + state.rules.solarPowerMultiplier); } } } diff --git a/core/src/mindustry/world/blocks/power/ThermalGenerator.java b/core/src/mindustry/world/blocks/power/ThermalGenerator.java index 83d2212eb5..8dd5555690 100644 --- a/core/src/mindustry/world/blocks/power/ThermalGenerator.java +++ b/core/src/mindustry/world/blocks/power/ThermalGenerator.java @@ -37,8 +37,12 @@ public class ThermalGenerator extends PowerGenerator{ } public class ThermalGeneratorEntity extends GeneratorEntity{ + public float sum; + @Override public void updateTile(){ + productionEfficiency = sum + attribute.env(); + if(productionEfficiency > 0.1f && Mathf.chance(0.05 * delta())){ generateEffect.at(x + Mathf.range(3f), y + Mathf.range(3f)); } @@ -53,14 +57,7 @@ public class ThermalGenerator extends PowerGenerator{ public void onProximityAdded(){ super.onProximityAdded(); - productionEfficiency = sumAttribute(attribute, tile.x, tile.y); - } - - @Override - public float getPowerProduction(){ - //in this case, productionEfficiency means 'total heat' - //thus, it may be greater than 1.0 - return powerProduction * productionEfficiency; + sum = sumAttribute(attribute, tile.x, tile.y); } } } diff --git a/core/src/mindustry/world/blocks/production/Cultivator.java b/core/src/mindustry/world/blocks/production/Cultivator.java index f4587a4a82..cc9efdd8f2 100644 --- a/core/src/mindustry/world/blocks/production/Cultivator.java +++ b/core/src/mindustry/world/blocks/production/Cultivator.java @@ -33,7 +33,7 @@ public class Cultivator extends GenericCrafter{ super.setBars(); bars.add("multiplier", (CultivatorEntity entity) -> new Bar(() -> Core.bundle.formatFloat("bar.efficiency", - ((entity.boost + 1f) * entity.warmup) * 100f, 1), + ((entity.boost + 1f + attribute.env()) * entity.warmup) * 100f, 1), () -> Pal.ammo, () -> entity.warmup)); } @@ -101,7 +101,7 @@ public class Cultivator extends GenericCrafter{ @Override public float getProgressIncrease(float baseTime){ - return super.getProgressIncrease(baseTime) * (1f + boost); + return super.getProgressIncrease(baseTime) * (1f + boost + attribute.env()); } @Override diff --git a/core/src/mindustry/world/blocks/production/SolidPump.java b/core/src/mindustry/world/blocks/production/SolidPump.java index 422557ff8d..abf531ba2a 100644 --- a/core/src/mindustry/world/blocks/production/SolidPump.java +++ b/core/src/mindustry/world/blocks/production/SolidPump.java @@ -120,7 +120,7 @@ public class SolidPump extends Pump{ if(canPump(tile)) fraction = 1f; } - fraction += boost; + fraction += boost + (attribute == null ? 0 : attribute.env()); fraction = Math.max(fraction, 0); if(cons.valid() && typeLiquid() < liquidCapacity - 0.001f){ diff --git a/core/src/mindustry/world/meta/Attribute.java b/core/src/mindustry/world/meta/Attribute.java index 815f471c9d..07699ba6b3 100644 --- a/core/src/mindustry/world/meta/Attribute.java +++ b/core/src/mindustry/world/meta/Attribute.java @@ -1,5 +1,7 @@ package mindustry.world.meta; +import mindustry.*; + public enum Attribute{ /** Heat of this block. Used for calculating output of thermal generators. */ heat, @@ -8,5 +10,15 @@ public enum Attribute{ /** Water content of this block. Used for increasing water extractor yield. */ water, /** Oil content of this block. Used for increasing oil extractor yield. */ - oil + oil, + /** Light coverage. Negative values decrease solar panel efficiency. */ + light; + + public static final Attribute[] all = values(); + + /** @return the envrionmental value for this attribute. */ + public float env(){ + if(Vars.state == null) return 0; + return Vars.state.envAttrs.get(this); + } } diff --git a/tools/src/mindustry/tools/SectorDataGenerator.java b/tools/src/mindustry/tools/SectorDataGenerator.java index e0c4828280..deb9b7343b 100644 --- a/tools/src/mindustry/tools/SectorDataGenerator.java +++ b/tools/src/mindustry/tools/SectorDataGenerator.java @@ -124,6 +124,7 @@ public class SectorDataGenerator{ boolean hasSnow = data.floors[0].name.contains("ice") || data.floors[0].name.contains("snow"); boolean hasRain = !hasSnow && data.floors[0].name.contains("water"); boolean hasDesert = !hasSnow && !hasRain && data.floors[0].name.contains("sand"); + boolean hasSpores = data.floors[0].name.contains("spore") || data.floors[0].name.contains("moss") || data.floors[0].name.contains("tainted"); if(hasSnow){ data.attributes |= (1 << SectorAttribute.snowy.ordinal()); @@ -137,6 +138,10 @@ public class SectorDataGenerator{ data.attributes |= (1 << SectorAttribute.desert.ordinal()); } + if(hasSpores){ + data.attributes |= (1 << SectorAttribute.spores.ordinal()); + } + data.resources = content.asArray().sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id))).toArray(UnlockableContent.class); //50% water -> naval attribute