diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 068068ff94..a5303bc3d6 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -23,7 +23,7 @@ gameover.waiting = [accent]Waiting for next map... highscore = [accent]New highscore! copied = Copied. indev.notready = This part of the game isn't ready yet -indev.campaign = [accent]You've reached the end of the campaign![]\n\nThis is as far as the content goes. Interplanetary travel will be added in future updates. +indev.campaign = [accent]Congratulations! You've reached the end of the campaign![]\n\nThis is as far as the content goes right now. Interplanetary travel will be added in future updates. load.sound = Sounds load.map = Maps @@ -149,6 +149,9 @@ unlocked = New content unlocked! available = New research available! completed = [accent]Completed techtree = Tech Tree +research.legacy = [accent]5.0[] research data found.\nDo you want to [accent]load this data[], or [accent]discard it[] and restart research in the new campaign (recommended)? +research.load = Load +research.discard = Discard research.list = [lightgray]Research: research = Research researched = [lightgray]{0} researched. diff --git a/core/assets/maps/extractionOutpost.msav b/core/assets/maps/extractionOutpost.msav index 5728a4b217..7ce6a6904e 100644 Binary files a/core/assets/maps/extractionOutpost.msav and b/core/assets/maps/extractionOutpost.msav differ diff --git a/core/assets/maps/fungalPass.msav b/core/assets/maps/fungalPass.msav index f0edb0987b..40b5ff376e 100644 Binary files a/core/assets/maps/fungalPass.msav and b/core/assets/maps/fungalPass.msav differ diff --git a/core/assets/maps/impact0078.msav b/core/assets/maps/impact0078.msav index 56f5570bfb..44279fec16 100644 Binary files a/core/assets/maps/impact0078.msav and b/core/assets/maps/impact0078.msav differ diff --git a/core/assets/maps/nuclearComplex.msav b/core/assets/maps/nuclearComplex.msav index aa9424850b..b56ea9a866 100644 Binary files a/core/assets/maps/nuclearComplex.msav and b/core/assets/maps/nuclearComplex.msav differ diff --git a/core/assets/maps/overgrowth.msav b/core/assets/maps/overgrowth.msav index 0fd4902d1d..a51978cb0f 100644 Binary files a/core/assets/maps/overgrowth.msav and b/core/assets/maps/overgrowth.msav differ diff --git a/core/assets/maps/tarFields.msav b/core/assets/maps/tarFields.msav index 006be2fb0f..1ec074997c 100644 Binary files a/core/assets/maps/tarFields.msav and b/core/assets/maps/tarFields.msav differ diff --git a/core/assets/maps/windsweptIslands.msav b/core/assets/maps/windsweptIslands.msav index 2c8547f6f9..690a924716 100644 Binary files a/core/assets/maps/windsweptIslands.msav and b/core/assets/maps/windsweptIslands.msav differ diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index 21a8b3fb45..12819feff6 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -88,7 +88,7 @@ public class Vars implements Loadable{ /** duration of time between turns in ticks */ public static final float turnDuration = 2 * Time.toMinutes; /** chance of an invasion per turn, 1 = 100% */ - public static final float baseInvasionChance = 1f / 75f; + public static final float baseInvasionChance = 1f / 85f; /** how many turns have to pass before invasions start */ public static final int invasionGracePeriod = 20; /** min armor fraction damage; e.g. 0.05 = at least 5% damage */ diff --git a/core/src/mindustry/ai/types/FormationAI.java b/core/src/mindustry/ai/types/FormationAI.java index 2379b28e07..bb4182c254 100644 --- a/core/src/mindustry/ai/types/FormationAI.java +++ b/core/src/mindustry/ai/types/FormationAI.java @@ -67,7 +67,7 @@ public class FormationAI extends AIController implements FormationMember{ if(core != null && leader.mineTile.drop() != null && unit.within(core, unit.type.range) && !unit.acceptsItem(leader.mineTile.drop())){ if(core.acceptStack(unit.stack.item, unit.stack.amount, unit) > 0){ - Call.transferItemTo(unit.stack.item, unit.stack.amount, unit.x, unit.y, core); + Call.transferItemTo(unit, unit.stack.item, unit.stack.amount, unit.x, unit.y, core); unit.clearItem(); } diff --git a/core/src/mindustry/ai/types/MinerAI.java b/core/src/mindustry/ai/types/MinerAI.java index 97d8198bb2..28306deb84 100644 --- a/core/src/mindustry/ai/types/MinerAI.java +++ b/core/src/mindustry/ai/types/MinerAI.java @@ -65,7 +65,7 @@ public class MinerAI extends AIController{ if(unit.within(core, unit.type.range)){ if(core.acceptStack(unit.stack.item, unit.stack.amount, unit) > 0){ - Call.transferItemTo(unit.stack.item, unit.stack.amount, unit.x, unit.y, core); + Call.transferItemTo(unit, unit.stack.item, unit.stack.amount, unit.x, unit.y, core); } unit.clearItem(); diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 363256dc83..b324b24190 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1388,7 +1388,7 @@ public class Blocks implements ContentList{ size = 5; unitCapModifier = 24; - researchCostMultiplier = 0.05f; + researchCostMultiplier = 0.06f; }}; vault = new StorageBlock("vault"){{ diff --git a/core/src/mindustry/content/Bullets.java b/core/src/mindustry/content/Bullets.java index c7fa47a62b..04a04ffbb1 100644 --- a/core/src/mindustry/content/Bullets.java +++ b/core/src/mindustry/content/Bullets.java @@ -37,7 +37,7 @@ public class Bullets implements ContentList{ waterShot, cryoShot, slagShot, oilShot, heavyWaterShot, heavyCryoShot, heavySlagShot, heavyOilShot, //environment, misc. - damageLightning, damageLightningGround, fireball, basicFlame, pyraFlame, driverBolt, healBullet, healBulletBig; + damageLightning, damageLightningGround, fireball, basicFlame, pyraFlame, driverBolt; @Override public void load(){ @@ -374,20 +374,6 @@ public class Bullets implements ContentList{ knockback = 0.7f; }}; - healBullet = new LaserBoltBulletType(5.2f, 13){{ - healPercent = 3f; - collidesTeam = true; - backColor = Pal.heal; - frontColor = Color.white; - }}; - - healBulletBig = new LaserBoltBulletType(5.2f, 15){{ - healPercent = 5.5f; - collidesTeam = true; - backColor = Pal.heal; - frontColor = Color.white; - }}; - fireball = new BulletType(1f, 4){ { pierce = true; diff --git a/core/src/mindustry/content/TechTree.java b/core/src/mindustry/content/TechTree.java index 98ff7fd6e8..6d82895b97 100644 --- a/core/src/mindustry/content/TechTree.java +++ b/core/src/mindustry/content/TechTree.java @@ -98,11 +98,11 @@ public class TechTree implements ContentList{ node(platedConduit, () -> { }); - }); - node(rotaryPump, () -> { - node(thermalPump, () -> { + node(rotaryPump, () -> { + node(thermalPump, () -> { + }); }); }); }); @@ -422,7 +422,7 @@ public class TechTree implements ContentList{ node(additiveReconstructor, Seq.with(new SectorComplete(biomassFacility)), () -> { node(multiplicativeReconstructor, () -> { - node(exponentialReconstructor, () -> { + node(exponentialReconstructor, Seq.with(new SectorComplete(overgrowth)), () -> { node(tetrativeReconstructor, () -> { }); diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 023eeb5631..3dd1d1f20f 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -292,6 +292,7 @@ public class UnitTypes implements ContentList{ shootSound = Sounds.lasershoot; bullet = new LaserBoltBulletType(5.2f, 14){{ + lifetime = 37f; healPercent = 5f; collidesTeam = true; backColor = Pal.heal; @@ -311,7 +312,7 @@ public class UnitTypes implements ContentList{ mineTier = 2; mineSpeed = 5f; - commandLimit = 8; + commandLimit = 9; abilities.add(new ShieldRegenFieldAbility(20f, 40f, 60f * 5, 60f)); ammoType = AmmoTypes.power; @@ -975,7 +976,7 @@ public class UnitTypes implements ContentList{ zenith = new UnitType("zenith"){{ health = 700; - speed = 1.7f; + speed = 1.8f; accel = 0.04f; drag = 0.016f; flying = true; @@ -997,7 +998,7 @@ public class UnitTypes implements ContentList{ velocityRnd = 0.2f; shootSound = Sounds.missile; - bullet = new MissileBulletType(3f, 12){{ + bullet = new MissileBulletType(3f, 14){{ width = 8f; height = 8f; shrinkY = 0f; @@ -1005,7 +1006,7 @@ public class UnitTypes implements ContentList{ homingRange = 60f; keepVelocity = false; splashDamageRadius = 25f; - splashDamage = 10f; + splashDamage = 14f; lifetime = 60f; trailColor = Pal.unitBack; backColor = Pal.unitBack; @@ -1264,6 +1265,7 @@ public class UnitTypes implements ContentList{ engineSize = 3f; payloadCapacity = (2 * 2) * tilePayload; buildSpeed = 2.6f; + isCounted = false; ammoType = AmmoTypes.power; @@ -1274,7 +1276,13 @@ public class UnitTypes implements ContentList{ x = 8f; y = -6f; rotate = true; - bullet = Bullets.healBulletBig; + bullet = new LaserBoltBulletType(5.2f, 10){{ + lifetime = 35f; + healPercent = 5.5f; + collidesTeam = true; + backColor = Pal.heal; + frontColor = Color.white; + }}; }}, new Weapon("heal-weapon-mount"){{ shootSound = Sounds.lasershoot; @@ -1282,7 +1290,13 @@ public class UnitTypes implements ContentList{ x = 4f; y = 5f; rotate = true; - bullet = Bullets.healBullet; + bullet = new LaserBoltBulletType(5.2f, 8){{ + lifetime = 35f; + healPercent = 3f; + collidesTeam = true; + backColor = Pal.heal; + frontColor = Color.white; + }}; }}); }}; @@ -1349,7 +1363,7 @@ public class UnitTypes implements ContentList{ collides = false; healPercent = 15f; - splashDamage = 240f; + splashDamage = 230f; splashDamageRadius = 120f; }}; }}); diff --git a/core/src/mindustry/content/Weathers.java b/core/src/mindustry/content/Weathers.java index 86dac06f7b..0d5c47e56a 100644 --- a/core/src/mindustry/content/Weathers.java +++ b/core/src/mindustry/content/Weathers.java @@ -53,10 +53,11 @@ public class Weathers implements ContentList{ baseSpeed = 5.4f; attrs.set(Attribute.light, -0.1f); attrs.set(Attribute.water, -0.1f); - opacityMultiplier = 0.5f; + opacityMultiplier = 0.4f; force = 0.1f; sound = Sounds.wind; - soundVol = 0.3f; + soundVol = 0.8f; + duration = 7f * Time.toMinutes; }}; sporestorm = new ParticleWeather("sporestorm"){{ @@ -77,7 +78,8 @@ public class Weathers implements ContentList{ opacityMultiplier = 0.75f; force = 0.1f; sound = Sounds.wind; - soundVol = 0.3f; + soundVol = 0.7f; + duration = 7f * Time.toMinutes; }}; fog = new ParticleWeather("fog"){{ diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index bc5acc066f..2a1c79f107 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -334,10 +334,27 @@ public class Control implements ApplicationListener, Loadable{ state.wave = 1; //set up default wave time state.wavetime = state.rules.waveSpacing * 2f; + //reset captured state + sector.info.wasCaptured = false; //reset win wave?? state.rules.winWave = state.rules.attackMode ? -1 : sector.preset != null ? sector.preset.captureWave : 40; + //if there's still an enemy base left, fix it + if(state.rules.attackMode){ + //replace all broken blocks + for(var plan : state.rules.waveTeam.data().blocks){ + Tile tile = world.tile(plan.x, plan.y); + if(tile != null){ + tile.setBlock(content.block(plan.block), state.rules.waveTeam, plan.rotation); + if(plan.config != null && tile.build != null){ + tile.build.configure(plan.config); + } + } + } + state.rules.waveTeam.data().blocks.clear(); + } + //kill all units, since they should be dead anyway Groups.unit.clear(); Groups.fire.clear(); diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index 02222bd327..abcdfc85a0 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -109,6 +109,13 @@ public class Logic implements ApplicationListener{ } state.rules.waveTeam.rules().aiTier = state.getSector().threat * 0.8f; state.rules.waveTeam.rules().infiniteResources = true; + + //fill enemy cores by default. + for(var core : state.rules.waveTeam.cores()){ + for(Item item : content.items()){ + core.items.set(item, core.block.itemCapacity); + } + } } //save settings @@ -260,6 +267,8 @@ public class Logic implements ApplicationListener{ if(state.rules.sector == null) return; + state.rules.sector.info.wasCaptured = true; + //fire capture event Events.fire(new SectorCaptureEvent(state.rules.sector)); diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java index c0a35c625b..5f7dfd100b 100644 --- a/core/src/mindustry/core/NetServer.java +++ b/core/src/mindustry/core/NetServer.java @@ -447,6 +447,11 @@ public class NetServer implements ApplicationListener{ return; } + if(currentlyKicking[0].target.team() != player.team()){ + player.sendMessage("[scarlet]You can't vote for other teams."); + return; + } + if(!arg[0].toLowerCase().equals("y") && !arg[0].toLowerCase().equals("n")){ player.sendMessage("[scarlet]Vote either 'y' (yes) or 'n' (no)."); return; diff --git a/core/src/mindustry/entities/Damage.java b/core/src/mindustry/entities/Damage.java index a3dd3913f1..64c08f318c 100644 --- a/core/src/mindustry/entities/Damage.java +++ b/core/src/mindustry/entities/Damage.java @@ -2,7 +2,6 @@ package mindustry.entities; import arc.*; import arc.func.*; -import arc.graphics.*; import arc.math.*; import arc.math.geom.*; import arc.struct.*; @@ -33,15 +32,22 @@ public class Damage{ private static Unit tmpUnit; /** Creates a dynamic explosion based on specified parameters. */ - public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color, boolean damage){ + public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, boolean damage){ + dynamicExplosion(x, y, flammability, explosiveness, power, radius, damage, true, null); + } + + /** Creates a dynamic explosion based on specified parameters. */ + public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, boolean damage, boolean fire, @Nullable Team ignoreTeam){ if(damage){ for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){ int branches = 5 + Mathf.clamp((int)(power / 30), 1, 20); Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.derelict, Pal.power, 3, x, y, Mathf.random(360f), branches + Mathf.range(2))); } - for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i++){ - Time.run(i / 2f, () -> Call.createBullet(Bullets.fireball, Team.derelict, x, y, Mathf.random(360f), Bullets.fireball.damage, 1, 1)); + if(fire){ + for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i++){ + Time.run(i / 2f, () -> Call.createBullet(Bullets.fireball, Team.derelict, x, y, Mathf.random(360f), Bullets.fireball.damage, 1, 1)); + } } int waves = Mathf.clamp((int)(explosiveness / 4), 0, 30); @@ -49,7 +55,7 @@ public class Damage{ for(int i = 0; i < waves; i++){ int f = i; Time.run(i * 2f, () -> { - Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f); + Damage.damage(ignoreTeam, x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f, false); Fx.blockExplosionSmoke.at(x + Mathf.range(radius), y + Mathf.range(radius)); }); } diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index fca91f0417..7499fcd9c2 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -435,7 +435,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } /** Handle a stack input. */ - public void handleStack(Item item, int amount, Teamc source){ + public void handleStack(Item item, int amount, @Nullable Teamc source){ noSleep(); items.add(item, amount); } @@ -519,6 +519,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, public void dumpLiquid(Liquid liquid){ int dump = this.cdump; + if(liquids.get(liquid) <= 0.0001f) return; + if(!net.client() && state.isCampaign() && team == state.rules.defaultTeam) liquid.unlock(); for(int i = 0; i < proximity.size; i++){ @@ -970,34 +972,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, }); } - Damage.dynamicExplosion(x, y, flammability, explosiveness * 3.5f, power, tilesize * block.size / 2f, Pal.darkFlame, state.rules.damageExplosions); + Damage.dynamicExplosion(x, y, flammability, explosiveness * 3.5f, power, tilesize * block.size / 2f, state.rules.damageExplosions); if(!floor().solid && !floor().isLiquid){ Effect.rubble(x, y, block.size); } } - /** - * Returns the flammability of the Used for fire calculations. - * Takes flammability of floor liquid into account. - */ - public float getFlammability(){ - if(!block.hasItems){ - if(floor().isLiquid && !block.solid){ - return floor().liquidDrop.flammability; - } - return 0; - }else{ - float result = items.sum((item, amount) -> item.flammability * amount); - - if(block.hasLiquids){ - result += liquids.sum((liquid, amount) -> liquid.flammability * amount / 3f); - } - - return result; - } - } - public String getDisplayName(){ return block.localizedName; } diff --git a/core/src/mindustry/entities/comp/FireComp.java b/core/src/mindustry/entities/comp/FireComp.java index 43fc3cdae9..7981e061b6 100644 --- a/core/src/mindustry/entities/comp/FireComp.java +++ b/core/src/mindustry/entities/comp/FireComp.java @@ -26,7 +26,7 @@ abstract class FireComp implements Timedc, Posc, Firec, Syncc{ @Override public void update(){ - if(Mathf.chance(0.1 * Time.delta)){ + if(Mathf.chance(0.09 * Time.delta)){ Fx.fire.at(x + Mathf.range(4f), y + Mathf.range(4f)); } @@ -59,7 +59,7 @@ abstract class FireComp implements Timedc, Posc, Firec, Syncc{ } if(baseFlammability < 0 || block != tile.block()){ - baseFlammability = tile.build == null ? 0 : tile.build.getFlammability(); + baseFlammability = tile.build == null ? 0 : tile.getFlammability(); block = tile.block(); } @@ -77,12 +77,12 @@ abstract class FireComp implements Timedc, Posc, Firec, Syncc{ } } - if(Mathf.chance(0.1 * Time.delta)){ + if(Mathf.chance(0.025 * Time.delta)){ Puddlec p = Puddles.get(tile); puddleFlammability = p != null ? p.getFlammability() / 3f : 0; if(damage){ - entity.damage(0.4f); + entity.damage(1.6f); } Damage.damageUnits(null, tile.worldx(), tile.worldy(), tilesize, 3f, unit -> !unit.isFlying() && !unit.isImmune(StatusEffects.burning), diff --git a/core/src/mindustry/entities/comp/FlyingComp.java b/core/src/mindustry/entities/comp/FlyingComp.java index be7b003baa..d37a6da899 100644 --- a/core/src/mindustry/entities/comp/FlyingComp.java +++ b/core/src/mindustry/entities/comp/FlyingComp.java @@ -46,8 +46,8 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{ } void wobble(){ - x += Mathf.sin(Time.time() + id() * 99, 25f, 0.05f) * Time.delta * elevation; - y += Mathf.cos(Time.time() + id() * 99, 25f, 0.05f) * Time.delta * elevation; + x += Mathf.sin(Time.time() + (id() % 10) * 12, 25f, 0.05f) * Time.delta * elevation; + y += Mathf.cos(Time.time() + (id() % 10) * 12, 25f, 0.05f) * Time.delta * elevation; } void moveAt(Vec2 vector, float acceleration){ diff --git a/core/src/mindustry/entities/comp/MinerComp.java b/core/src/mindustry/entities/comp/MinerComp.java index 9368918d8c..f10a217105 100644 --- a/core/src/mindustry/entities/comp/MinerComp.java +++ b/core/src/mindustry/entities/comp/MinerComp.java @@ -55,7 +55,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{ if(core != null && mineTile != null && mineTile.drop() != null && !acceptsItem(mineTile.drop()) && within(core, mineTransferRange) && !offloadImmediately()){ int accepted = core.acceptStack(item(), stack().amount, this); if(accepted > 0){ - Call.transferItemTo(item(), accepted, + Call.transferItemTo(self(), item(), accepted, mineTile.worldx() + Mathf.range(tilesize / 2f), mineTile.worldy() + Mathf.range(tilesize / 2f), core); clearItem(); @@ -77,7 +77,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{ mineTimer = 0; if(core != null && within(core, mineTransferRange) && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){ - Call.transferItemTo(item, 1, + Call.transferItemTo(self(), item, 1, mineTile.worldx() + Mathf.range(tilesize / 2f), mineTile.worldy() + Mathf.range(tilesize / 2f), core); }else if(acceptsItem(item)){ diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java index b90afcae56..3854876873 100644 --- a/core/src/mindustry/entities/comp/UnitComp.java +++ b/core/src/mindustry/entities/comp/UnitComp.java @@ -397,9 +397,12 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I /** Actually destroys the unit, removing it and creating explosions. **/ public void destroy(){ - float explosiveness = 2f + item().explosiveness * stack().amount / 2.4f; - float flammability = item().flammability * stack().amount / 2.4f; - Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, Pal.darkFlame, state.rules.damageExplosions); + float explosiveness = 2f + item().explosiveness * stack().amount * 1.53f; + float flammability = item().flammability * stack().amount / 1.9f; + + if(!spawnedByCore){ + Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, state.rules.damageExplosions, item().flammability > 1, team); + } float shake = hitSize / 3f; @@ -415,7 +418,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I } //if this unit crash landed (was flying), damage stuff in a radius - if(type.flying){ + if(type.flying && !spawnedByCore){ Damage.damage(team,x, y, Mathf.pow(hitSize, 0.94f) * 1.25f, Mathf.pow(hitSize, 0.75f) * type.crashDamageMultiplier * 5f, true, false, true); } diff --git a/core/src/mindustry/game/Objectives.java b/core/src/mindustry/game/Objectives.java index bf306cb957..31fc92e1b3 100644 --- a/core/src/mindustry/game/Objectives.java +++ b/core/src/mindustry/game/Objectives.java @@ -59,7 +59,7 @@ public class Objectives{ @Override public boolean complete(){ - return preset.sector.save != null && !preset.sector.isAttacked() && preset.sector.hasBase(); + return preset.sector.save != null && (!preset.sector.isAttacked() || preset.sector.info.wasCaptured) && preset.sector.hasBase(); } @Override diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index e8aa42262b..50425ec4af 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -33,6 +33,8 @@ public class SectorInfo{ public int storageCapacity = 0; /** Whether a core is available here. */ public boolean hasCore = true; + /** Whether this sector was ever fully captured. */ + public boolean wasCaptured = false; /** Sector that was launched from. */ public @Nullable Sector origin; /** Launch destination. */ diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java index b19fcee6da..9c3a614350 100644 --- a/core/src/mindustry/game/Universe.java +++ b/core/src/mindustry/game/Universe.java @@ -6,7 +6,6 @@ import arc.struct.*; import arc.util.*; import mindustry.content.*; import mindustry.game.EventType.*; -import mindustry.io.legacy.*; import mindustry.maps.*; import mindustry.type.*; import mindustry.world.blocks.storage.*; @@ -27,13 +26,6 @@ public class Universe{ public Universe(){ load(); - //load legacy research - Events.on(ClientLoadEvent.class, e -> { - if(Core.settings.has("unlocks")){ - LegacyIO.readResearch(); - } - }); - //update base coverage on capture Events.on(SectorCaptureEvent.class, e -> { if(!net.client() && state.isCampaign()){ @@ -188,6 +180,7 @@ public class Universe{ }else if(attacked && wavesPassed > 0 && sector.info.winWave > 1 && sector.info.wave + wavesPassed >= sector.info.winWave && !sector.hasEnemyBase()){ //autocapture the sector sector.info.waves = false; + sector.info.wasCaptured = true; //fire the event Events.fire(new SectorCaptureEvent(sector)); diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 2df91588b6..551fd5e82d 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -96,18 +96,17 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } @Remote(called = Loc.server, unreliable = true) - public static void transferItemTo(Item item, int amount, float x, float y, Building build){ + public static void setItem(Building build, Item item, int amount){ if(build == null || build.items == null) return; - for(int i = 0; i < Mathf.clamp(amount / 5, 1, 8); i++){ - Time.run(i * 3, () -> createItemTransfer(item, amount, x, y, build, () -> {})); - } - build.items.add(item, amount); + build.items.set(item, amount); } @Remote(called = Loc.server, unreliable = true) - public static void transferItemTo(Unit unit, Item item, int amount, float x, float y, Building build){ + public static void transferItemTo(@Nullable Unit unit, Item item, int amount, float x, float y, Building build){ if(build == null || build.items == null) return; - unit.stack.amount = Math.max(unit.stack.amount - amount, 0); + + if(unit != null) unit.stack.amount = Math.max(unit.stack.amount - amount, 0); + for(int i = 0; i < Mathf.clamp(amount / 3, 1, 8); i++){ Time.run(i * 3, () -> createItemTransfer(item, amount, x, y, build, () -> {})); } diff --git a/core/src/mindustry/maps/SectorDamage.java b/core/src/mindustry/maps/SectorDamage.java index 187778e470..128ec3fcd2 100644 --- a/core/src/mindustry/maps/SectorDamage.java +++ b/core/src/mindustry/maps/SectorDamage.java @@ -338,9 +338,9 @@ public class SectorDamage{ info.waveDpsSlope = reg.slope; //enemy units like to aim for a lot of non-essential things, so increase resulting health slightly - info.sumHealth = sumHealth * 1.2f; + info.sumHealth = sumHealth * 1.05f; //players tend to have longer range units/turrets, so assume DPS is higher - info.sumDps = sumDps * 1.2f; + info.sumDps = sumDps * 1.05f; info.sumRps = sumRps; info.wavesSurvived = getWavesSurvived(info); diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index 5f2bbdb637..4cd9d704f5 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -225,7 +225,7 @@ public class ContentParser{ currentContent = block; read(() -> { - if(value.has("consumes")){ + if(value.has("consumes") && value.get("consumes").isObject()){ for(JsonValue child : value.get("consumes")){ if(child.name.equals("item")){ block.consumes.item(find(ContentType.item, child.asString())); diff --git a/core/src/mindustry/type/Weather.java b/core/src/mindustry/type/Weather.java index 9daaf11087..a9741b5241 100644 --- a/core/src/mindustry/type/Weather.java +++ b/core/src/mindustry/type/Weather.java @@ -21,7 +21,7 @@ import static mindustry.Vars.*; public abstract class Weather extends UnlockableContent{ /** Default duration of this weather event in ticks. */ - public float duration = 9f * Time.toMinutes; + public float duration = 10f * Time.toMinutes; public float opacityMultiplier = 1f; public Attributes attrs = new Attributes(); public Sound sound = Sounds.none; diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index b3dc7aa135..121fb41d57 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -23,6 +23,7 @@ import mindustry.gen.*; import mindustry.graphics.*; import mindustry.graphics.g3d.*; import mindustry.input.*; +import mindustry.io.legacy.*; import mindustry.maps.*; import mindustry.type.*; import mindustry.ui.*; @@ -140,6 +141,13 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ return this; } + //load legacy research + if(Core.settings.has("unlocks") && !Core.settings.has("junction-unlocked")){ + Core.app.post(() -> { + ui.showCustomConfirm("@research", "@research.legacy", "@research.load", "@research.discard", LegacyIO::readResearch, () -> Core.settings.remove("unlocks")); + }); + } + rebuildButtons(); mode = look; selected = hovered = launchSector = null; @@ -554,7 +562,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ if(t.getChildren().any()){ c.add(name).left().row(); - c.add(t).padLeft(10f).row(); + c.add(t).padLeft(10f).left().row(); } }; diff --git a/core/src/mindustry/world/Tile.java b/core/src/mindustry/world/Tile.java index e8a27b7c05..b91b26d699 100644 --- a/core/src/mindustry/world/Tile.java +++ b/core/src/mindustry/world/Tile.java @@ -103,6 +103,28 @@ public class Tile implements Position, QuadTreeObject, Displayable{ return -1; } + /** + * Returns the flammability of the Used for fire calculations. + * Takes flammability of floor liquid into account. + */ + public float getFlammability(){ + if(!block.hasItems){ + if(floor.liquidDrop != null && !block.solid){ + return floor.liquidDrop.flammability; + } + return 0; + }else if(build != null){ + float result = build.items.sum((item, amount) -> item.flammability * amount); + + if(block.hasLiquids){ + result += build.liquids.sum((liquid, amount) -> liquid.flammability * amount / 3f); + } + + return result; + } + return 0; + } + /** Convenience method that returns the building of this tile with a cast. * Method name is shortened to prevent conflict. */ @SuppressWarnings("unchecked") diff --git a/core/src/mindustry/world/blocks/campaign/LaunchPad.java b/core/src/mindustry/world/blocks/campaign/LaunchPad.java index d72c1f133a..ef60f9a482 100644 --- a/core/src/mindustry/world/blocks/campaign/LaunchPad.java +++ b/core/src/mindustry/world/blocks/campaign/LaunchPad.java @@ -56,6 +56,11 @@ public class LaunchPad extends Block{ bars.add("items", entity -> new Bar(() -> Core.bundle.format("bar.items", entity.items.total()), () -> Pal.items, () -> (float)entity.items.total() / itemCapacity)); } + @Override + public boolean outputsItems(){ + return false; + } + public class LaunchPadBuild extends Building{ @Override diff --git a/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java b/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java index 3aefcdd33c..fd971e55d7 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java @@ -54,6 +54,7 @@ public class LaserTurret extends PowerTurret{ super.updateTile(); if(bulletLife > 0 && bullet != null){ + wasShooting = true; tr.trns(rotation, size * tilesize / 2f, 0f); bullet.rotation(rotation); bullet.set(x + tr.x, y + tr.y); @@ -65,6 +66,7 @@ public class LaserTurret extends PowerTurret{ bullet = null; } }else if(reload > 0){ + wasShooting = true; Liquid liquid = liquids.current(); float maxUsed = consumes.get(ConsumeType.liquid).amount; @@ -76,7 +78,6 @@ public class LaserTurret extends PowerTurret{ coolEffect.at(x + Mathf.range(size * tilesize / 2f), y + Mathf.range(size * tilesize / 2f)); } } - } @Override diff --git a/core/src/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/mindustry/world/blocks/defense/turrets/Turret.java index 9e41023c01..4572852eb2 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/Turret.java @@ -205,7 +205,7 @@ public abstract class Turret extends ReloadTurret{ } public boolean isActive(){ - return target != null || (logicControlled() && logicShooting) || (isControlled() && unit.isShooting()); + return target != null || wasShooting; } public void targetPosition(Posc pos){ diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 995834c977..e53bd84eff 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -229,12 +229,12 @@ public class CoreBlock extends StorageBlock{ @Override public boolean acceptItem(Building source, Item item){ - return items.get(item) < getMaximumAccepted(item) || incinerate(); + return items.get(item) < getMaximumAccepted(item); } @Override public int getMaximumAccepted(Item item){ - return storageCapacity; + return incinerate() ? storageCapacity * 2 : storageCapacity; } @Override @@ -270,10 +270,15 @@ public class CoreBlock extends StorageBlock{ @Override public void handleStack(Item item, int amount, Teamc source){ - super.handleStack(item, amount, source); + int realAmount = Math.min(amount, storageCapacity - items.get(item)); + super.handleStack(item, realAmount, source); if(team == state.rules.defaultTeam && state.isCampaign()){ state.rules.sector.info.handleCoreItem(item, amount); + + if(realAmount == 0){ + Fx.coreBurn.at(x, y); + } } } @@ -377,7 +382,7 @@ public class CoreBlock extends StorageBlock{ state.rules.sector.info.handleCoreItem(item, 1); } - if(items.get(item) >= getMaximumAccepted(item)){ + if(items.get(item) >= storageCapacity){ //create item incineration effect at random intervals if(!noEffect){ incinerateEffect(this, source);