diff --git a/core/src/mindustry/entities/bullet/ContinuousBulletType.java b/core/src/mindustry/entities/bullet/ContinuousBulletType.java index df7b63c68d..0f95881285 100644 --- a/core/src/mindustry/entities/bullet/ContinuousBulletType.java +++ b/core/src/mindustry/entities/bullet/ContinuousBulletType.java @@ -74,6 +74,8 @@ public class ContinuousBulletType extends BulletType{ if(shake > 0){ Effect.shake(shake, shake, b); } + + updateBulletInterval(b); } public void applyDamage(Bullet b){ diff --git a/core/src/mindustry/entities/bullet/PointLaserBulletType.java b/core/src/mindustry/entities/bullet/PointLaserBulletType.java index e78b91d2d8..8e96579a5b 100644 --- a/core/src/mindustry/entities/bullet/PointLaserBulletType.java +++ b/core/src/mindustry/entities/bullet/PointLaserBulletType.java @@ -75,7 +75,9 @@ public class PointLaserBulletType extends BulletType{ @Override public void update(Bullet b){ - super.update(b); + updateTrail(b); + updateTrailEffects(b); + updateBulletInterval(b); if(b.timer.get(0, damageInterval)){ Damage.collidePoint(b, b.team, hitEffect, b.aimX, b.aimY); @@ -115,4 +117,13 @@ public class PointLaserBulletType extends BulletType{ b.trail.update(b.aimX, b.aimY, b.fslope() * (1f - (trailSinMag > 0 ? Mathf.absin(Time.time, trailSinScl, trailSinMag) : 0f))); } } + + public void updateBulletInterval(Bullet b){ + if(intervalBullet != null && b.time >= intervalDelay && b.timer.get(2, bulletInterval)){ + float ang = b.rotation(); + for(int i = 0; i < intervalBullets; i++){ + intervalBullet.create(b, b.aimX, b.aimY, ang + Mathf.range(intervalRandomSpread) + intervalAngle + ((i - (intervalBullets - 1f)/2f) * intervalSpread)); + } + } + } } diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index d39825f455..8fd98c0c1e 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -190,32 +190,33 @@ public class ContentParser{ data.has("operation") ? data.get("operation") : data.has("op") ? data.get("op") : null; - //no operations I guess (why would you do this?) + //no singular operation, check for multi-operation if(opval == null){ + JsonValue opsVal = + data.has("operations") ? data.get("operations") : + data.has("ops") ? data.get("ops") : null; + + if(opsVal != null){ + if(!opsVal.isArray()) throw new RuntimeException("Chained PartProgress operations must be an array."); + int i = 0; + while(true){ + JsonValue val = opsVal.get(i); + if(val == null) break; + JsonValue op = val.has("operation") ? val.get("operation") : + val.has("op") ? val.get("op") : null; + + base = parseProgressOp(base, op.asString(), val); + i++; + } + } + return base; } //this is the name of the method to call String op = opval.asString(); - //I have to hard-code this, no easy way of getting parameter names, unfortunately - return switch(op){ - case "inv" -> base.inv(); - case "slope" -> base.slope(); - case "clamp" -> base.clamp(); - case "delay" -> base.delay(data.getFloat("amount")); - case "sustain" -> base.sustain(data.getFloat("offset", 0f), data.getFloat("grow", 0f), data.getFloat("sustain")); - case "shorten" -> base.shorten(data.getFloat("amount")); - case "compress" -> base.compress(data.getFloat("start"), data.getFloat("end")); - case "add" -> data.has("amount") ? base.add(data.getFloat("amount")) : base.add(parser.readValue(PartProgress.class, data.get("other"))); - case "blend" -> base.blend(parser.readValue(PartProgress.class, data.get("other")), data.getFloat("amount")); - case "mul" -> data.has("amount") ? base.mul(data.getFloat("amount")) : base.mul(parser.readValue(PartProgress.class, data.get("other"))); - case "min" -> base.min(parser.readValue(PartProgress.class, data.get("other"))); - case "sin" -> base.sin(data.has("offset") ? data.getFloat("offset") : 0f, data.getFloat("scl"), data.getFloat("mag")); - case "absin" -> base.absin(data.getFloat("scl"), data.getFloat("mag")); - case "curve" -> data.has("interp") ? base.curve(parser.readValue(Interp.class, data.get("interp"))) : base.curve(data.getFloat("offset"), data.getFloat("duration")); - default -> throw new RuntimeException("Unknown operation '" + op + "', check PartProgress class for a list of methods."); - }; + return parseProgressOp(base, op, data); }); put(PlanetGenerator.class, (type, data) -> { var result = new AsteroidGenerator(); //only one type for now @@ -875,6 +876,27 @@ public class ContentParser{ }; } + private PartProgress parseProgressOp(PartProgress base, String op, JsonValue data){ + //I have to hard-code this, no easy way of getting parameter names, unfortunately + return switch(op){ + case "inv" -> base.inv(); + case "slope" -> base.slope(); + case "clamp" -> base.clamp(); + case "delay" -> base.delay(data.getFloat("amount")); + case "sustain" -> base.sustain(data.getFloat("offset", 0f), data.getFloat("grow", 0f), data.getFloat("sustain")); + case "shorten" -> base.shorten(data.getFloat("amount")); + case "compress" -> base.compress(data.getFloat("start"), data.getFloat("end")); + case "add" -> data.has("amount") ? base.add(data.getFloat("amount")) : base.add(parser.readValue(PartProgress.class, data.get("other"))); + case "blend" -> base.blend(parser.readValue(PartProgress.class, data.get("other")), data.getFloat("amount")); + case "mul" -> data.has("amount") ? base.mul(data.getFloat("amount")) : base.mul(parser.readValue(PartProgress.class, data.get("other"))); + case "min" -> base.min(parser.readValue(PartProgress.class, data.get("other"))); + case "sin" -> base.sin(data.has("offset") ? data.getFloat("offset") : 0f, data.getFloat("scl"), data.getFloat("mag")); + case "absin" -> base.absin(data.getFloat("scl"), data.getFloat("mag")); + case "curve" -> data.has("interp") ? base.curve(parser.readValue(Interp.class, data.get("interp"))) : base.curve(data.getFloat("offset"), data.getFloat("duration")); + default -> throw new RuntimeException("Unknown operation '" + op + "', check PartProgress class for a list of methods."); + }; + } + T make(Class type){ try{ Constructor cons = type.getDeclaredConstructor();