From 5fbfe52d0aea3e5f13abfee512cd272e55373f9b Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 8 Dec 2021 14:28:27 -0500 Subject: [PATCH] Misc bugfixes --- .../blocks/defense/regen-projector.png | Bin 1946 -> 2052 bytes core/assets/shaders/shield.frag | 12 +- core/src/mindustry/content/Blocks.java | 3 +- core/src/mindustry/content/Fx.java | 8 + core/src/mindustry/entities/Units.java | 9 + .../src/mindustry/entities/comp/UnitComp.java | 2 +- core/src/mindustry/logic/LParser.java | 3 +- .../defense/DirectionalForceProjector.java | 196 +++++++++++++++--- .../world/blocks/defense/ForceProjector.java | 13 +- .../world/blocks/payloads/PayloadSource.java | 2 +- .../world/blocks/units/Reconstructor.java | 2 +- gradle.properties | 2 +- 12 files changed, 206 insertions(+), 46 deletions(-) diff --git a/core/assets-raw/sprites/blocks/defense/regen-projector.png b/core/assets-raw/sprites/blocks/defense/regen-projector.png index 7c54117503587722ba2926bf6c09971c55c60b4e..46230dd1687f9b7a7d857d2bb8dfd1d99c48f2c5 100644 GIT binary patch delta 2025 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 0.9){ + gl_FragColor = vec4(maxed.rgb, maxed.a * 100.0); }else{ diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 409235fd28..d729f1e272 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1513,7 +1513,8 @@ public class Blocks{ //TODO requirements(Category.effect, with(Items.surgeAlloy, 100, Items.silicon, 125)); size = 3; - radius = 50f; + width = 50f; + length = 36; shieldHealth = 2000f; cooldownNormal = 3f; cooldownBrokenBase = 0.35f; diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index e9dbada86d..3dc5ee97e1 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -78,6 +78,14 @@ public class Fx{ Draw.rect(Icon.warning.getRegion(), e.x, e.y, size, size); }), + unitEnvKill = new Effect(80f, e -> { + color(Color.scarlet); + alpha(e.fout(Interp.pow4Out)); + + float size = 10f + e.fout(Interp.pow10In) * 25f; + Draw.rect(Icon.cancel.getRegion(), e.x, e.y, size, size); + }), + unitControl = new Effect(30f, e -> { if(!(e.data instanceof Unit select)) return; diff --git a/core/src/mindustry/entities/Units.java b/core/src/mindustry/entities/Units.java index a4b94ae570..2c5797067d 100644 --- a/core/src/mindustry/entities/Units.java +++ b/core/src/mindustry/entities/Units.java @@ -33,6 +33,15 @@ public class Units{ } } + @Remote(called = Loc.server) + public static void unitEnvDeath(Unit unit){ + if(unit != null){ + unit.dead = true; + Fx.unitEnvKill.at(unit); + Core.app.post(() -> Call.unitDestroy(unit.id)); + } + } + @Remote(called = Loc.server) public static void unitDeath(int uid){ Unit unit = Groups.unit.getByID(uid); diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java index 7df354bf40..3f8f9f7d50 100644 --- a/core/src/mindustry/entities/comp/UnitComp.java +++ b/core/src/mindustry/entities/comp/UnitComp.java @@ -378,7 +378,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I //check if environment is unsupported if(!type.supportsEnv(state.rules.environment) && !dead){ - Call.unitCapDeath(self()); + Call.unitEnvDeath(self()); team.data().updateCount(type, -1); } diff --git a/core/src/mindustry/logic/LParser.java b/core/src/mindustry/logic/LParser.java index d6e8b40e62..f8d3d37bfa 100644 --- a/core/src/mindustry/logic/LParser.java +++ b/core/src/mindustry/logic/LParser.java @@ -138,8 +138,7 @@ public class LParser{ try{ st = LogicIO.read(tokens, tok); }catch(Exception e){ - //log invalid statements - Log.err(e); + //replace invalid statements st = new InvalidStatement(); } diff --git a/core/src/mindustry/world/blocks/defense/DirectionalForceProjector.java b/core/src/mindustry/world/blocks/defense/DirectionalForceProjector.java index 4525c9102c..6ca4b35ab6 100644 --- a/core/src/mindustry/world/blocks/defense/DirectionalForceProjector.java +++ b/core/src/mindustry/world/blocks/defense/DirectionalForceProjector.java @@ -6,19 +6,32 @@ import arc.graphics.g2d.*; import arc.math.*; import arc.math.geom.*; import arc.util.*; +import mindustry.annotations.Annotations.*; +import mindustry.content.*; +import mindustry.entities.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.ui.*; +import mindustry.world.*; +import mindustry.world.consumers.*; +import mindustry.world.meta.*; import static mindustry.Vars.*; -public class DirectionalForceProjector extends ForceProjector{ +//TODO use completely different layer +//TODO consume heat +public class DirectionalForceProjector extends Block{ protected static final Vec2 intersectOut = new Vec2(), p1 = new Vec2(), p2 = new Vec2(); + protected static DirectionalForceProjectorBuild paramEntity; + protected static Effect paramEffect; protected static final Cons dirShieldConsumer = b -> { if(b.team != paramEntity.team && b.type.absorbable){ //just in case float deltaAdd = 1.1f; - if(Intersector.intersectSegments(b.x, b.y, b.x + b.vel.x * (Time.delta + deltaAdd), b.y + b.vel.y * (Time.delta + deltaAdd), p1.x, p1.y, p2.x, p2.y, intersectOut)){ + if(Intersector.intersectSegments(b.x, b.y, + b.x + b.vel.x * (Time.delta + deltaAdd), + b.y + b.vel.y * (Time.delta + deltaAdd), p1.x, p1.y, p2.x, p2.y, intersectOut)){ b.set(intersectOut); b.absorb(); paramEffect.at(b); @@ -28,48 +41,141 @@ public class DirectionalForceProjector extends ForceProjector{ } }; - //TODO proper length? + public float width = 30f; + public float shieldHealth = 3000f; + public float cooldownNormal = 1.75f; + public float cooldownLiquid = 1.5f; + public float cooldownBrokenBase = 0.35f; + + public Effect absorbEffect = Fx.absorb; + public Effect shieldBreakEffect = Fx.shieldBreak; + public @Load("@-top") TextureRegion topRegion; + public float length = 40f; public float padSize = 40f; public DirectionalForceProjector(String name){ super(name); - radius = 30f; - consumeCoolant = false; rotate = true; rotateDraw = false; + + update = true; + solid = true; + group = BlockGroup.projectors; + envEnabled |= Env.space; + ambientSound = Sounds.shield; + ambientSoundVolume = 0.08f; } @Override public void init(){ + clipSize = Math.max(clipSize, (width + 3f) * 2f); + super.init(); + if(length < 0){ length = size * tilesize/2f; } } + @Override + public void setBars(){ + super.setBars(); + bars.add("shield", (DirectionalForceProjectorBuild entity) -> new Bar("stat.shieldhealth", Pal.accent, () -> entity.broken ? 0f : 1f - entity.buildup / (shieldHealth)).blink(Color.white)); + } + + @Override + public boolean outputsItems(){ + return false; + } + + @Override + public void setStats(){ + super.setStats(); + stats.add(Stat.shieldHealth, shieldHealth, StatUnit.none); + stats.add(Stat.cooldownTime, (int) (shieldHealth / cooldownBrokenBase / 60f), StatUnit.seconds); + } + @Override public void drawPlace(int x, int y, int rotation, boolean valid){ drawPotentialLinks(x, y); - //TODO + x *= tilesize; + y *= tilesize; + + Tmp.v1.set(length - size/2f, (width + size/2f)).rotate(rotation * 90).add(x, y); + Tmp.v2.set(length - size/2f, -(width + size/2f)).rotate(rotation * 90).add(x, y); + + Drawf.dashLine(Color.lightGray, x, y, Tmp.v1.x, Tmp.v1.y); + Drawf.dashLine(Color.lightGray, x, y, Tmp.v2.x, Tmp.v2.y); + Drawf.dashLine(Pal.accent, Tmp.v1.x, Tmp.v1.y, Tmp.v2.x, Tmp.v2.y); } - public class DirectionalForceProjectorBuild extends ForceBuild{ + public class DirectionalForceProjectorBuild extends Building{ + public boolean broken = true; + public float buildup, hit, warmup, shieldRadius; @Override - public void deflectBullets(){ - float realRadius = realRadius(); + public boolean shouldAmbientSound(){ + return !broken && shieldRadius > 1f; + } - if(realRadius > 0 && !broken){ + @Override + public void pickedUp(){ + super.pickedUp(); + shieldRadius = warmup = 0f; + } + + @Override + public void updateTile(){ + shieldRadius = Mathf.lerpDelta(shieldRadius, broken ? 0f : warmup * width, 0.05f); + + //TODO ????????????????? + if(Mathf.chanceDelta(buildup / shieldHealth * 0.1f)){ + Fx.reactorsmoke.at(x + Mathf.range(tilesize / 2f), y + Mathf.range(tilesize / 2f)); + } + + warmup = Mathf.lerpDelta(warmup, efficiency(), 0.1f); + + if(buildup > 0 && consumes.has(ConsumeType.liquid)){ + float scale = !broken ? cooldownNormal : cooldownBrokenBase; + Consume cons = consumes.get(ConsumeType.liquid); + if(cons.valid(this)){ + cons.update(this); + scale *= (cooldownLiquid * (1f + (liquids.current().heatCapacity - 0.4f) * 0.9f)); + } + + buildup -= delta() * scale; + } + + if(broken && buildup <= 0){ + broken = false; + } + + if(buildup >= shieldHealth && !broken){ + broken = true; + buildup = shieldHealth; + shieldBreakEffect.at(x, y, shieldRadius, team.color); + } + + if(hit > 0f){ + hit -= 1f / 5f * Time.delta; + } + + deflectBullets(); + } + + public void deflectBullets(){ + + if(shieldRadius > 0 && !broken){ paramEntity = this; paramEffect = absorbEffect; //top - p1.set(length, realRadius).rotate(rotdeg()); + p1.set(length, shieldRadius).rotate(rotdeg()); //bot - p2.set(length, -realRadius).rotate(rotdeg()); + p2.set(length, -shieldRadius).rotate(rotdeg()); //"check" radius is grown to catch bullets moving at high velocity Tmp.r1.set(p2.x, p2.y, p1.x - p2.x, p1.y - p2.y).normalize().grow(padSize); @@ -82,13 +188,30 @@ public class DirectionalForceProjector extends ForceProjector{ } @Override - public void drawShield(){ - if(!broken && realRadius() > 0){ - float realRadius = realRadius(), rot = rotdeg(); + public void draw(){ + super.draw(); - p1.set(length, realRadius).rotate(rot).add(this); - p2.set(length, -realRadius).rotate(rot).add(this); - float size = 3f; + //TODO wrong + if(buildup > 0f){ + Draw.alpha(buildup / shieldHealth * 0.75f); + Draw.z(Layer.blockAdditive); + Draw.blend(Blending.additive); + Draw.rect(topRegion, x, y); + Draw.blend(); + Draw.z(Layer.block); + Draw.reset(); + } + + drawShield(); + } + + public void drawShield(){ + if(!broken && shieldRadius > 0){ + float rot = rotdeg(); + + p1.set(length, shieldRadius).rotate(rot).add(this); + p2.set(length, -shieldRadius).rotate(rot).add(this); + float size = 4f; Tmp.r1.set(p2.x, p2.y, p1.x - p2.x, p1.y - p2.y).normalize().grow(size); Draw.z(Layer.shields); @@ -98,15 +221,20 @@ public class DirectionalForceProjector extends ForceProjector{ if(renderer.animateShields){ Fill.rect(Tmp.r1); - Tmp.v1.set(length - size/2f - size * 2, (realRadius + size/2f)).rotate(rot).add(this); - Tmp.v2.set(length - size/2f - size * 2, -(realRadius + size/2f)).rotate(rot).add(this); + Tmp.v1.set(length - size/2f, (shieldRadius + size/2f)).rotate(rot).add(this); + Tmp.v2.set(length - size/2f, -(shieldRadius + size/2f)).rotate(rot).add(this); - Fill.tri(x, y, Tmp.v1.x, Tmp.v1.y, Tmp.v2.x, Tmp.v2.y); + //Fill.tri(x, y, Tmp.v1.x, Tmp.v1.y, Tmp.v2.x, Tmp.v2.y); + Lines.stroke(3f); + Lines.line(x, y, Tmp.v1.x, Tmp.v1.y); + Lines.line(x, y, Tmp.v2.x, Tmp.v2.y); + + Draw.z(Layer.shields); for(int i : Mathf.signs){ - Tmp.v1.set(length - size/2f, (realRadius + size/2f) * i).rotate(rot).add(this); - Tmp.v3.set(length + size/2f, (realRadius + size/2f) * i).rotate(rot).add(this); - Tmp.v2.set(length, (realRadius + size) * i).rotate(rot).add(this); + Tmp.v1.set(length - size/2f, (shieldRadius + size/2f) * i).rotate(rot).add(this); + Tmp.v3.set(length + size/2f, (shieldRadius + size/2f) * i).rotate(rot).add(this); + Tmp.v2.set(length, (shieldRadius + size) * i).rotate(rot).add(this); Fill.tri(Tmp.v1.x, Tmp.v1.y, Tmp.v2.x, Tmp.v2.y, Tmp.v3.x, Tmp.v3.y); } }else{ @@ -121,5 +249,25 @@ public class DirectionalForceProjector extends ForceProjector{ Draw.reset(); } } + + //TODO + /* + @Override + public void write(Writes write){ + super.write(write); + write.bool(broken); + write.f(buildup); + write.f(radscl); + write.f(warmup); + } + + @Override + public void read(Reads read, byte revision){ + super.read(read, revision); + broken = read.bool(); + buildup = read.f(); + radscl = read.f(); + warmup = read.f(); + }*/ } } diff --git a/core/src/mindustry/world/blocks/defense/ForceProjector.java b/core/src/mindustry/world/blocks/defense/ForceProjector.java index 488d366cc3..1356619b19 100644 --- a/core/src/mindustry/world/blocks/defense/ForceProjector.java +++ b/core/src/mindustry/world/blocks/defense/ForceProjector.java @@ -155,12 +155,15 @@ public class ForceProjector extends Block{ warmup = Mathf.lerpDelta(warmup, efficiency(), 0.1f); - if(buildup > 0 && consumes.has(ConsumeType.liquid)){ + if(buildup > 0){ float scale = !broken ? cooldownNormal : cooldownBrokenBase; - Consume cons = consumes.get(ConsumeType.liquid); - if(cons.valid(this)){ - cons.update(this); - scale *= (cooldownLiquid * (1f + (liquids.current().heatCapacity - 0.4f) * 0.9f)); + + if(consumes.has(ConsumeType.liquid)){ + Consume cons = consumes.get(ConsumeType.liquid); + if(cons.valid(this)){ + cons.update(this); + scale *= (cooldownLiquid * (1f + (liquids.current().heatCapacity - 0.4f) * 0.9f)); + } } buildup -= delta() * scale; diff --git a/core/src/mindustry/world/blocks/payloads/PayloadSource.java b/core/src/mindustry/world/blocks/payloads/PayloadSource.java index d2146d5a48..a02e3bd29a 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadSource.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadSource.java @@ -75,7 +75,7 @@ public class PayloadSource extends PayloadBlock{ } public boolean canProduce(UnitType t){ - return !t.isHidden() && !t.isBanned(); + return !t.isHidden() && !t.isBanned() && t.supportsEnv(state.rules.environment); } public class PayloadSourceBuild extends PayloadBlockBuild{ diff --git a/core/src/mindustry/world/blocks/units/Reconstructor.java b/core/src/mindustry/world/blocks/units/Reconstructor.java index c6e03236a8..6e4770f919 100644 --- a/core/src/mindustry/world/blocks/units/Reconstructor.java +++ b/core/src/mindustry/world/blocks/units/Reconstructor.java @@ -111,7 +111,7 @@ public class Reconstructor extends UnitBlock{ @Override public boolean acceptUnitPayload(Unit unit){ - return hasUpgrade(unit.type); + return hasUpgrade(unit.type) && !upgrade(unit.type).isBanned(); } @Override diff --git a/gradle.properties b/gradle.properties index ddb9285998..208c2f90ba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,4 +24,4 @@ android.useAndroidX=true #used for slow jitpack builds; TODO see if this actually works org.gradle.internal.http.socketTimeout=100000 org.gradle.internal.http.connectionTimeout=100000 -archash=997803e989 +archash=3dc6a7fac5