diff --git a/core/assets-raw/sprites/blocks/storage/core-foundation-thruster1.png b/core/assets-raw/sprites/blocks/storage/core-foundation-thruster1.png new file mode 100644 index 0000000000..f40a7eb905 Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-foundation-thruster1.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-foundation-thruster2.png b/core/assets-raw/sprites/blocks/storage/core-foundation-thruster2.png new file mode 100644 index 0000000000..21bb44abc9 Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-foundation-thruster2.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster1.png b/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster1.png new file mode 100644 index 0000000000..112429f26a Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster1.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster2.png b/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster2.png new file mode 100644 index 0000000000..83897e87d7 Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster2.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-shard-thruster1.png b/core/assets-raw/sprites/blocks/storage/core-shard-thruster1.png new file mode 100644 index 0000000000..7d6fd61604 Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-shard-thruster1.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-shard-thruster2.png b/core/assets-raw/sprites/blocks/storage/core-shard-thruster2.png new file mode 100644 index 0000000000..2a15417fbe Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-shard-thruster2.png differ diff --git a/core/assets-raw/sprites/effects/landheat.png b/core/assets-raw/sprites/effects/landheat.png new file mode 100644 index 0000000000..762e7735e7 Binary files /dev/null and b/core/assets-raw/sprites/effects/landheat.png differ diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index 069518fd38..51373139a6 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -352,3 +352,4 @@ 63354=payload-launch-pad|block-payload-launch-pad-ui 63353=silicon-arc-furnace|block-silicon-arc-furnace-ui 63352=metal-floor-4|block-metal-floor-4-ui +63351=invincible|status-invincible-ui diff --git a/core/assets/logicids.dat b/core/assets/logicids.dat index c34c5571b7..07a91ab487 100644 Binary files a/core/assets/logicids.dat and b/core/assets/logicids.dat differ diff --git a/core/assets/sprites/clouds.png b/core/assets/sprites/clouds.png index 93a8684689..adcf7a97db 100644 Binary files a/core/assets/sprites/clouds.png and b/core/assets/sprites/clouds.png differ diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index a167606c00..8a9f850a61 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -105,6 +105,8 @@ public class Vars implements Loadable{ public static final float minArmorDamage = 0.1f; /** launch animation duration */ public static final float launchDuration = 140f; + /** land animation duration */ + public static final float coreLandDuration = 150f; /** size of tiles in units */ public static final int tilesize = 8; /** size of one tile payload (^2) */ @@ -144,6 +146,8 @@ public class Vars implements Loadable{ public static int maxTextureSize = 2048; /** Whether to show the core landing animation. */ public static boolean showLandAnimation = true; + /** Whether to show sector info upon landing. */ + public static boolean showSectorLandInfo = true; /** Whether to check for memory use before taking screenshots. */ public static boolean checkScreenshotMemory = true; /** Whether to prompt the user to confirm exiting. */ diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 151d134752..9a1c16842e 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1377,6 +1377,7 @@ public class Blocks implements ContentList{ health = 3500; itemCapacity = 9000; size = 4; + thrusterLength = 34/4f; unitCapModifier = 16; researchCostMultiplier = 0.07f; @@ -1389,6 +1390,7 @@ public class Blocks implements ContentList{ health = 6000; itemCapacity = 13000; size = 5; + thrusterLength = 40/4f; unitCapModifier = 24; researchCostMultiplier = 0.11f; diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 509167dd6b..dc11b79f36 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -1862,6 +1862,13 @@ public class Fx{ Lines.poly(e.x, e.y, 6, e.rotation + e.fin()); }), + coreLandDust = new Effect(100f, e -> { + color(e.color, e.fout(0.1f)); + rand.setSeed(e.id); + Tmp.v1.trns(e.rotation, e.finpow() * 90f * rand.random(0.2f, 1f)); + Fill.circle(e.x + Tmp.v1.x, e.y + Tmp.v1.y, 8f * rand.random(0.6f, 1f) * e.fout(0.2f)); + }).layer(Layer.block + 1f), + unitShieldBreak = new Effect(35, e -> { if(!(e.data instanceof Unitc)) return; @@ -1955,8 +1962,5 @@ public class Fx{ } Lines.endLine(); - }).followParent(false), - - coreLand = new Effect(120f, e -> { - }); + }).followParent(false); } diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java index 7134a6ef28..6e81501d15 100644 --- a/core/src/mindustry/content/Planets.java +++ b/core/src/mindustry/content/Planets.java @@ -2,6 +2,7 @@ package mindustry.content; import arc.graphics.*; import mindustry.ctype.*; +import mindustry.graphics.*; import mindustry.graphics.g3d.*; import mindustry.maps.planet.*; import mindustry.type.*; @@ -38,6 +39,7 @@ public class Planets implements ContentList{ atmosphereRadOut = 0.3f; startSector = 15; alwaysUnlocked = true; + landCloudColor = Pal.spore.cpy().a(0.5f); }}; } } diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 19498a5086..cf0593afc6 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -421,14 +421,14 @@ public class UnitTypes implements ContentList{ mechStepShake = 0.15f; ammoType = AmmoTypes.powerHigh; - speed = 0.39f; + speed = 0.4f; boostMultiplier = 2.2f; engineOffset = 12f; engineSize = 6f; lowAltitude = true; riseSpeed = 0.02f; - health = 7500f; + health = 8000f; armor = 9f; canBoost = true; landShake = 4f; @@ -453,8 +453,8 @@ public class UnitTypes implements ContentList{ cooldownTime = 200f; bullet = new ContinuousLaserBulletType(){{ - damage = 30f; - length = 175f; + damage = 32f; + length = 180f; hitEffect = Fx.hitMeltHeal; drawSize = 420f; lifetime = 160f; diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index a416b5d2fd..d5f6343190 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -36,7 +36,6 @@ import java.text.*; import java.util.*; import static arc.Core.*; -import static mindustry.Vars.net; import static mindustry.Vars.*; /** @@ -195,7 +194,7 @@ public class Control implements ApplicationListener, Loadable{ }); Events.run(Trigger.newGame, () -> { - Building core = player.bestCore(); + var core = player.bestCore(); if(core == null) return; @@ -203,6 +202,8 @@ public class Control implements ApplicationListener, Loadable{ player.set(core); if(showLandAnimation){ + //delay player respawn so animation can play. + player.deathTimer = -70f; //TODO this sounds pretty bad due to conflict if(settings.getInt("musicvol") > 0){ Musics.land.stop(); @@ -211,14 +212,14 @@ public class Control implements ApplicationListener, Loadable{ } app.post(() -> ui.hudfrag.showLand()); - renderer.zoomIn(Fx.coreLand.lifetime); - app.post(() -> Fx.coreLand.at(core.getX(), core.getY(), 0, core.block)); + renderer.showLaunch(); - Time.run(Fx.coreLand.lifetime, () -> { + Time.run(coreLandDuration, () -> { Fx.launch.at(core); Effect.shake(5f, 5f, core); + core.thrusterTime = 1f; - if(state.isCampaign()){ + if(state.isCampaign() && Vars.showSectorLandInfo){ ui.announce("[accent]" + state.rules.sector.name() + "\n" + (state.rules.sector.info.resources.any() ? "[lightgray]" + bundle.get("sectors.resources") + "[white] " + state.rules.sector.info.resources.toString(" ", u -> u.emoji()) : ""), 5); @@ -328,6 +329,7 @@ public class Control implements ApplicationListener, Loadable{ slot.load(); slot.setAutosave(true); state.rules.sector = sector; + state.rules.cloudColor = sector.planet.landCloudColor; //if there is no base, simulate a new game and place the right loadout at the spawn position if(state.rules.defaultTeam.cores().isEmpty() || hadNoCore){ diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index 5183069725..efe7c3af48 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -18,6 +18,7 @@ import mindustry.game.EventType.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.graphics.g3d.*; +import mindustry.world.blocks.storage.*; import mindustry.world.blocks.storage.CoreBlock.*; import static arc.Core.*; @@ -27,6 +28,12 @@ public class Renderer implements ApplicationListener{ /** These are global variables, for headless access. Cached. */ public static float laserOpacity = 0.5f, bridgeOpacity = 0.75f; + private static final float cloudScaling = 1700f, cfinScl = -2f, cfinOffset = 0.3f, calphaFinOffset = 0.25f; + private static final float[] cloudAlphas = {0, 0.5f, 1f, 0.1f, 0, 0f}; + private static final float cloudAlpha = 0.81f; + private static final float[] thrusterSize = {0f, 0f, 0f, 0f, 0.3f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 0f}; + private static final Interp landInterp = Interp.pow3; + public final BlockRenderer blocks = new BlockRenderer(); public final MinimapRenderer minimap = new MinimapRenderer(); public final OverlayRenderer overlays = new OverlayRenderer(); @@ -44,7 +51,8 @@ public class Renderer implements ApplicationListener{ private @Nullable CoreBuild landCore; private Color clearColor = new Color(0f, 0f, 0f, 1f); - private float targetscale = Scl.scl(4), camerascale = targetscale, landscale, landTime, weatherAlpha, minZoomScl = Scl.scl(0.01f); + private float cloudSeed = 0f; + private float targetscale = Scl.scl(4), camerascale = targetscale, landscale, landTime, landPTimer, weatherAlpha, minZoomScl = Scl.scl(0.01f); private float shakeIntensity, shaketime; private Vec2 camShakeOffset = new Vec2(); @@ -97,10 +105,14 @@ public class Renderer implements ApplicationListener{ drawStatus = Core.settings.getBool("blockstatus"); if(landTime > 0){ + if(!state.isPaused()){ + updateLandParticles(); + } + if(!state.isPaused()){ landTime -= Time.delta; } - landscale = Interp.pow5In.apply(minZoomScl, Scl.scl(4f), 1f - landTime / Fx.coreLand.lifetime); + landscale = landInterp.apply(minZoomScl, Scl.scl(4f), 1f - landTime / coreLandDuration); camerascale = landscale; weatherAlpha = 0f; }else{ @@ -281,45 +293,134 @@ public class Renderer implements ApplicationListener{ } - private void drawLanding(){ - CoreBuild entity = landCore == null ? player.bestCore() : landCore; - //var clouds = assets.get("sprites/clouds.png", Texture.class); - if(landTime > 0 && entity != null){ - float fout = landTime / Fx.coreLand.lifetime; + void updateLandParticles(){ + float tsize = Mathf.sample(thrusterSize, (landTime + 35f) / coreLandDuration); - //TODO clouds - /* - float scaling = 10000f; - float sscl = 1f + fout*1.5f; - float offset = -0.38f; + landPTimer += tsize * Time.delta; + if(landCore != null && landPTimer >= 1f){ + landCore.tile.getLinkedTiles(t -> { + if(Mathf.chance(0.4f)){ + Fx.coreLandDust.at(t.worldx(), t.worldy(), landCore.angleTo(t) + Mathf.range(30f), Tmp.c1.set(t.floor().mapColor).mul(1.5f + Mathf.range(0.15f))); + } + }); - Tmp.tr1.set(clouds); - Tmp.tr1.set((camera.position.x - camera.width/2f * sscl) / scaling, (camera.position.y - camera.height/2f * sscl) / scaling, (camera.position.x + camera.width/2f * sscl) / scaling, (camera.position.y + camera.height/2f * sscl) / scaling); - Draw.alpha(Mathf.slope(Mathf.clamp(((1f - fout) + offset)/(1f + offset)))); - Draw.mixcol(Pal.spore, 0.5f); - Draw.rect(Tmp.tr1, camera.position.x, camera.position.y, camera.width, camera.height); - Draw.reset();*/ + landPTimer = 0f; + } + } - TextureRegion reg = entity.block.fullIcon; + void drawLanding(){ + CoreBuild build = landCore == null ? player.bestCore() : landCore; + var clouds = assets.get("sprites/clouds.png", Texture.class); + if(landTime > 0 && build != null){ + float fout = landTime / coreLandDuration; + float fin = 1f - fout; + + //core + var block = (CoreBlock)build.block; + TextureRegion reg = block.fullIcon; float scl = Scl.scl(4f) / camerascale; - float s = reg.width * Draw.scl * scl * 4f * fout; + float shake = 0f; + float s = reg.width * Draw.scl * scl * 3.6f * Interp.pow2Out.apply(fout); + float rotation = Interp.pow2In.apply(fout) * 135f, x = build.x + Mathf.range(shake), y = build.y + Mathf.range(shake); + float thrustOpen = 0.25f; + float frame = fin >= thrustOpen ? 1f : fin / thrustOpen; Draw.color(Pal.lightTrail); - Draw.rect("circle-shadow", entity.x, entity.y, s, s); + //TODO spikier heat + Draw.rect("circle-shadow", x, y, s, s); - Angles.randLenVectors(1, (1f- fout), 100, 1000f * scl * (1f-fout), (x, y, ffin, ffout) -> { - Lines.stroke(scl * ffin); - Lines.lineAngle(entity.x + x, entity.y + y, Mathf.angle(x, y), (ffin * 20 + 1f) * scl); + Draw.color(Pal.lightTrail); + + float pfin = Interp.pow3Out.apply(fin), pf = Interp.pow2In.apply(fout); + + //particles + Angles.randLenVectors(1, pfin, 100, 800f * scl * pfin, (ax, ay, ffin, ffout) -> { + Lines.stroke(scl * ffin * pf * 3f); + Lines.lineAngle(build.x + ax, build.y + ay, Mathf.angle(ax, ay), (ffin * 20 + 1f) * scl); }); Draw.color(); - Draw.mixcol(Color.white, fout); - Draw.rect(reg, entity.x, entity.y, reg.width * Draw.scl * scl, reg.height * Draw.scl * scl, fout * 135f); + Draw.mixcol(Color.white, Interp.pow2In.apply(fout)); + Draw.scl(scl); + + Draw.alpha(1f); + + //thruster flame + float strength = (1f + (block.size - 3)/2.5f) * scl * Mathf.sample(thrusterSize, fin) * (0.95f + Mathf.absin(2f, 0.1f)); + float offset = (block.size - 3) * 3f * scl; + + for(int i = 0; i < 4; i++){ + Tmp.v1.trns(i * 90 + rotation, 1f); + + Tmp.v1.setLength((block.size * tilesize/2f + 1f)*scl + strength*2f + offset); + Draw.color(build.team.color); + Fill.circle(Tmp.v1.x + x, Tmp.v1.y + y, 6f * strength); + + Tmp.v1.setLength((block.size * tilesize/2f + 1f)*scl + strength*0.5f + offset); + Draw.color(Color.white); + Fill.circle(Tmp.v1.x + x, Tmp.v1.y + y, 3f * strength); + } + + drawThrusters(block, x, y, rotation, frame); + + Drawf.spinSprite(block.region, x, y, rotation); + + Draw.alpha(Interp.pow4In.apply(frame)); + drawThrusters(block, x, y, rotation, frame); + Draw.alpha(1f); + + Drawf.spinSprite(block.teamRegions[build.team.id], x, y, rotation); + + Draw.scl(); Draw.reset(); + + //clouds + float scaling = cloudScaling; + float sscl = Math.max(1f + Mathf.clamp(fin + cfinOffset)* cfinScl, 0f) * landscale; + + Tmp.tr1.set(clouds); + Tmp.tr1.set( + (camera.position.x - camera.width/2f * sscl) / scaling, + (camera.position.y - camera.height/2f * sscl) / scaling, + (camera.position.x + camera.width/2f * sscl) / scaling, + (camera.position.y + camera.height/2f * sscl) / scaling); + + Tmp.tr1.scroll(10f * cloudSeed, 10f * cloudSeed); + + Draw.alpha(Mathf.sample(cloudAlphas, fin + calphaFinOffset) * cloudAlpha); + Draw.mixcol(state.rules.cloudColor, state.rules.cloudColor.a); + Draw.rect(Tmp.tr1, camera.position.x, camera.position.y, camera.width, camera.height); + Draw.reset(); } } + void drawThrusters(CoreBlock block, float x, float y, float rotation, float frame){ + float length = block.thrusterLength * (frame - 1f) - 1f/4f; + float alpha = Draw.getColor().a; + + //two passes for consistent lighting + for(int j = 0; j < 2; j++){ + for(int i = 0; i < 4; i++){ + var reg = i >= 2 ? block.thruster2 : block.thruster1; + float rot = (i * 90) + rotation % 90f; + Tmp.v1.trns(rot, length * Draw.xscl); + + //second pass applies extra layer of shading + if(j == 1){ + Tmp.v1.rotate(-90f); + Draw.alpha((rotation % 90f) / 90f * alpha); + rot -= 90f; + Draw.rect(reg, x + Tmp.v1.x, y + Tmp.v1.y, rot); + }else{ + Draw.alpha(alpha); + Draw.rect(reg, x + Tmp.v1.x, y + Tmp.v1.y, rot); + } + } + } + Draw.alpha(1f); + } + public void scaleCamera(float amount){ targetscale *= (amount / 4) + 1; clampScale(); @@ -350,9 +451,10 @@ public class Renderer implements ApplicationListener{ clampScale(); } - public void zoomIn(float duration){ + public void showLaunch(){ landscale = minZoomScl; - landTime = duration; + landTime = coreLandDuration; + cloudSeed = Mathf.random(1f); } public void takeMapScreenshot(){ diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java index e1363a281f..453ccb1c71 100644 --- a/core/src/mindustry/core/World.java +++ b/core/src/mindustry/core/World.java @@ -287,6 +287,7 @@ public class World{ if(liquid != null) content.add(liquid); } + state.rules.cloudColor = sector.planet.landCloudColor; sector.info.resources = content.asArray(); sector.info.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id))); sector.saveInfo(); diff --git a/core/src/mindustry/entities/units/AIController.java b/core/src/mindustry/entities/units/AIController.java index c1764052da..0af7565424 100644 --- a/core/src/mindustry/entities/units/AIController.java +++ b/core/src/mindustry/entities/units/AIController.java @@ -6,6 +6,7 @@ import arc.util.*; import mindustry.*; import mindustry.ai.*; import mindustry.entities.*; +import mindustry.game.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; @@ -154,6 +155,7 @@ public class AIController implements UnitController{ } protected Teamc targetFlag(float x, float y, BlockFlag flag, boolean enemy){ + if(unit.team == Team.derelict) return null; Tile target = Geometry.findClosest(x, y, enemy ? indexer.getEnemy(unit.team, flag) : indexer.getAllied(unit.team, flag)); return target == null ? null : target.build; } diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index f66dd658ea..385d7671e9 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -109,6 +109,8 @@ public class Rules{ public Team defaultTeam = Team.sharded; /** team of the enemy in waves/sectors. */ public Team waveTeam = Team.crux; + /** color of clouds that is displayed when the player is landing */ + public Color cloudColor = new Color(0f, 0f, 0f, 0f); /** name of the custom mode that this ruleset describes, or null. */ public @Nullable String modeName; /** Whether cores incinerate items when full, just like in the campaign. */ diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index 0c52d3a701..06499d9ca0 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -55,6 +55,8 @@ public class Planet extends UnlockableContent{ public boolean bloom = false; /** Whether this planet is displayed. */ public boolean visible = true; + /** Tint of clouds displayed when landing. */ + public Color landCloudColor = new Color(1f, 1f, 1f, 0.5f); /** For suns, this is the color that shines on other planets. Does nothing for children. */ public Color lightColor = Color.white.cpy(); /** Atmosphere tint for landable planets. */ diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 8aa18cf014..8963e1fcd1 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -29,6 +29,10 @@ public class CoreBlock extends StorageBlock{ //hacky way to pass item modules between methods private static ItemModule nextItems; + public @Load("@-thruster1") TextureRegion thruster1; //top right + public @Load("@-thruster2") TextureRegion thruster2; //bot left + public float thrusterLength = 14f/4f; + public UnitType unitType = UnitTypes.alpha; public float captureInvicibility = 60f * 15f; @@ -176,6 +180,35 @@ public class CoreBlock extends StorageBlock{ public boolean noEffect = false; public Team lastDamage = Team.derelict; public float iframes = -1f; + public float thrusterTime = 0f; + + @Override + public void draw(){ + //draw thrusters when just landed + if(thrusterTime > 0){ + float frame = thrusterTime; + + Draw.alpha(1f); + drawThrusters(frame); + Draw.rect(block.region, x, y); + Draw.alpha(Interp.pow4In.apply(frame)); + drawThrusters(frame); + Draw.reset(); + + drawTeamTop(); + }else{ + super.draw(); + } + } + + public void drawThrusters(float frame){ + float length = thrusterLength * (frame - 1f) - 1f/4f; + for(int i = 0; i < 4; i++){ + var reg = i >= 2 ? thruster2 : thruster1; + float dx = Geometry.d4x[i] * length, dy = Geometry.d4y[i] * length; + Draw.rect(reg, x + dx, y + dy, i * 90); + } + } @Override public void damage(@Nullable Team source, float damage){ @@ -234,6 +267,7 @@ public class CoreBlock extends StorageBlock{ @Override public void updateTile(){ iframes -= Time.delta; + thrusterTime -= Time.delta/90f; } @Override diff --git a/gradle.properties b/gradle.properties index 6df565d95f..1366866c20 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=d7b814ff69853e3bc8fa0703d3b2829cbff65e9e +archash=6e9fd338866c05cd42ec20f26ec7fa7c3a25d6d5