diff --git a/core/assets-raw/sprites/units/vela-weapon-heat.png b/core/assets-raw/sprites/units/weapons/vela-weapon-heat.png similarity index 100% rename from core/assets-raw/sprites/units/vela-weapon-heat.png rename to core/assets-raw/sprites/units/weapons/vela-weapon-heat.png diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 0d4739fa28..3310644e23 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -3354,14 +3354,14 @@ public class Blocks{ targetAir = false; shootShake = 4f; recoilAmount = 1f; - reloadTime = 60f * 2f; + reloadTime = 60f * 2.3f; shootLength = 7f; rotateSpeed = 1.4f; minWarmup = 0.85f; shootWarmupSpeed = 0.07f; coolant = consume(new ConsumeLiquid(Liquids.water, 30f / 60f)); - coolantMultiplier = 2.5f; + coolantMultiplier = 1.5f; draw = new DrawTurret("reinforced-"){{ parts.addAll( diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 55807a4a69..e38dd16de1 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -1515,7 +1515,7 @@ public class Fx{ color(Color.white, e.color, e.fin()); rand.setSeed(e.id); - for(int i = 0; i < 10; i++){ + for(int i = 0; i < 8; i++){ float rot = e.rotation + rand.range(22f); v.trns(rot, rand.random(e.finpow() * 24f)); Fill.poly(e.x + v.x, e.y + v.y, 4, e.fout() * 3.8f + 0.2f, rand.random(360f)); diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 1c81142600..426f4ba18a 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -479,7 +479,7 @@ public class UnitTypes{ despawnEffect = Fx.smokeCloud; smokeEffect = Fx.none; - shootEffect = Fx.greenLaserChargeSmall; + chargeEffect = Fx.greenLaserChargeSmall; incendChance = 0.1f; incendSpread = 5f; @@ -566,7 +566,7 @@ public class UnitTypes{ largeHit = true; lightColor = lightningColor = Pal.heal; - shootEffect = Fx.greenLaserCharge; + chargeEffect = Fx.greenLaserCharge; healPercent = 25f; collidesTeam = true; @@ -1209,7 +1209,7 @@ public class UnitTypes{ shadow = 7f; rotate = true; recoil = 0.5f; - + shootY = 7.25f; bullet = fragBullet; }}, new Weapon("large-artillery"){{ @@ -1222,6 +1222,7 @@ public class UnitTypes{ shootSound = Sounds.shoot; rotate = true; shadow = 12f; + shootY = 7.25f; bullet = fragBullet; }}); }}; @@ -2481,6 +2482,8 @@ public class UnitTypes{ heatColor = Color.valueOf("f9350f"); cooldownTime = 30f; + shots = 2; + bullet = new BasicBulletType(5f, 50){{ sprite = "missile-large"; smokeEffect = Fx.shootBigSmoke; @@ -2887,11 +2890,11 @@ public class UnitTypes{ x = 43 / 4f; y = -20f / 4f; - shootY = 39 / 4f; + shootY = 37 / 4f; shootX = -5f / 4f; recoil = 3f; reload = 30f; - shake = 3f; + shake = 2f; cooldownTime = 20f; layerOffset = 0.02f; diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index 375a534647..3b48d926c8 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -53,8 +53,8 @@ public class BulletType extends Content implements Cloneable{ public Effect despawnEffect = Fx.hitBulletSmall; /** Effect created when shooting. */ public Effect shootEffect = Fx.shootSmall; - /** Effect created when charging completes; only usable in single-shot weapons with a firstShotDelay / shotDelay. */ - public Effect chargeShootEffect = Fx.none; + /** Effect created when charging starts; only usable in single-shot weapons with a firstShotDelay / shotDelay. */ + public Effect chargeEffect = Fx.none; /** Extra smoke effect created when shooting. */ public Effect smokeEffect = Fx.shootSmallSmoke; /** Sound made when hitting something or getting removed.*/ diff --git a/core/src/mindustry/type/Weapon.java b/core/src/mindustry/type/Weapon.java index 89fe318b0d..96230d4ae5 100644 --- a/core/src/mindustry/type/Weapon.java +++ b/core/src/mindustry/type/Weapon.java @@ -24,9 +24,6 @@ import mindustry.world.meta.*; import static mindustry.Vars.*; public class Weapon implements Cloneable{ - /** temporary weapon sequence number */ - static int sequenceNum = 0; - /** displayed weapon region */ public String name; /** bullet shot */ @@ -276,7 +273,7 @@ public class Weapon implements Cloneable{ mountY = unit.y + Angles.trnsy(unit.rotation - 90, x, y), bulletX = mountX + Angles.trnsx(weaponRotation, this.shootX, this.shootY), bulletY = mountY + Angles.trnsy(weaponRotation, this.shootX, this.shootY), - shootAngle = rotate ? unit.rotation + mount.rotation : Angles.angle(bulletX, bulletY, mount.aimX, mount.aimY) + (unit.rotation - unit.angleTo(mount.aimX, mount.aimY)); + shootAngle = bulletRotation(unit, mount, bulletX, bulletY); //find a new target if(!controllable && autoTarget){ @@ -370,86 +367,62 @@ public class Weapon implements Cloneable{ return Units.invalidateTarget(target, unit.team, x, y, range + Math.abs(shootY)); } - protected Vec2 getShootPos(Unit unit, WeaponMount mount, Vec2 out){ - float weaponRot = unit.rotation - 90 + (rotate ? mount.rotation : 0); - return out.set(unit.x, unit.y) - .add(Angles.trnsx(unit.rotation - 90, x, y), Angles.trnsy(unit.rotation - 90, x, y)) - .add(Angles.trnsx(weaponRot, this.shootX, this.shootY), Angles.trnsx(weaponRot, this.shootX, this.shootY)); + protected float bulletRotation(Unit unit, WeaponMount mount, float bulletX, float bulletY){ + return rotate ? unit.rotation + mount.rotation : Angles.angle(bulletX, bulletY, mount.aimX, mount.aimY) + (unit.rotation - unit.angleTo(mount.aimX, mount.aimY)); } protected void shoot(Unit unit, WeaponMount mount, float shootX, float shootY, float aimX, float aimY, float mountX, float mountY, float rotation, int side){ - Vec2 offset = getShootPos(unit, mount, Tmp.v1); - float baseX = offset.x, baseY = offset.y, baseRot = unit.rotation + mount.rotation; boolean delay = firstShotDelay + shotDelay > 0f; float lifeScl = bullet.scaleVelocity ? Mathf.clamp(Mathf.dst(shootX, shootY, aimX, aimY) / bullet.range()) : 1f; Unit parent = bullet.keepVelocity || parentizeEffects ? unit : null; - //TODO far too complicated and similar to Turret + //TODO merge with Turret behavior + + //UnitTypes.eclipse.weapons.get(2).shotDelay = 4 - sequenceNum = 0; if(delay){ - Angles.shotgun(shots, spacing, rotation, f -> { - Time.run(sequenceNum * shotDelay + firstShotDelay, () -> { - if(!unit.isAdded()) return; + chargeSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax)); + bullet.chargeEffect.at(shootX, shootY, rotation, parent); - //TODO this is a flawed system, recalculate everything instead. - getShootPos(unit, mount, offset).sub(baseX, baseY); + for(int i = 0; i < shots; i++){ + float angleOffset = i * spacing - (shots - 1) * spacing / 2f; - float rotOffset = unit.rotation + mount.rotation - baseRot; - mount.bullet = bullet(unit, shootX + offset.x, shootY + offset.y, f + Mathf.range(inaccuracy) + rotOffset, lifeScl); - if(!continuous){ - shootSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax)); - } + Time.run(i * shotDelay + firstShotDelay, () -> { + //everything needs to be re-calculated again + float + rweaponRotation = unit.rotation - 90 + (rotate ? mount.rotation : 0), + rmountX = unit.x + Angles.trnsx(unit.rotation - 90, x, y), + rmountY = unit.y + Angles.trnsy(unit.rotation - 90, x, y), + rbulletX = rmountX + Angles.trnsx(rweaponRotation, this.shootX, this.shootY), + rbulletY = rmountY + Angles.trnsy(rweaponRotation, this.shootX, this.shootY), + shootAngle = bulletRotation(unit, mount, rbulletX, rbulletY); + + mount.bullet = bullet(mount, unit, rbulletX, rbulletY, angleOffset + Mathf.range(inaccuracy) + shootAngle, lifeScl, side, rotation, rmountX, rmountY); }); - sequenceNum++; - }); + } }else{ - Angles.shotgun(shots, spacing, rotation, f -> mount.bullet = bullet(unit, shootX, shootY, f + Mathf.range(inaccuracy), lifeScl)); + for(int i = 0; i < shots; i++){ + float angleOffset = i * spacing - (shots - 1) * spacing / 2f; + mount.bullet = bullet(mount, unit, shootX, shootY, angleOffset + rotation + Mathf.range(inaccuracy), lifeScl, side, rotation, mountX, mountY); + } } - if(delay){ - Time.run(firstShotDelay, () -> { - if(!unit.isAdded()) return; - - unit.vel.add(Tmp.v1.trns(rotation + 180f, bullet.recoil)); - Effect.shake(shake, shake, shootX, shootY); - mount.recoil = recoil; - mount.heat = 1f; - if(!continuous){ - shootSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax)); - } - - getShootPos(unit, mount, offset).sub(baseX, baseY); - - bullet.chargeShootEffect.at(shootX + offset.x, shootY + offset.y, rotation, parent); - }); - }else{ - unit.vel.add(Tmp.v1.trns(rotation + 180f, bullet.recoil)); - Effect.shake(shake, shake, shootX, shootY); - mount.recoil = recoil; - mount.heat = 1f; - } - - (delay ? chargeSound : continuous ? Sounds.none : shootSound).at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax)); - effects(parent, mountX, mountY, shootX, shootY, rotation, side); unit.apply(shootStatus, shootStatusDuration); } - protected void effects(Unit parent, float mountX, float mountY, float shootX, float shootY, float rotation, int side){ - ejectEffect.at(mountX, mountY, rotation * side); - bullet.shootEffect.at(shootX, shootY, rotation, bullet.hitColor, parent); - bullet.smokeEffect.at(shootX, shootY, rotation, bullet.hitColor, parent); - } + protected @Nullable Bullet bullet(WeaponMount mount, Unit unit, float shootX, float shootY, float angle, float lifescl, int side, float mountRotation, float mountX, float mountY){ + if(!unit.isAdded()) return null; - protected @Nullable Bullet bullet(Unit unit, float shootX, float shootY, float angle, float lifescl){ float xr = Mathf.range(xRand), x = shootX + Angles.trnsx(angle, 0, xr), y = shootY + Angles.trnsy(angle, 0, xr); + Bullet result = null; + if(unitSpawned == null){ - return bullet.create(unit, unit.team, x, y, angle, (1f - velocityRnd) + Mathf.random(velocityRnd), lifescl); + result = bullet.create(unit, unit.team, x, y, angle, (1f - velocityRnd) + Mathf.random(velocityRnd), lifescl); }else{ //don't spawn units clientside! if(!net.client()){ @@ -463,9 +436,23 @@ public class Weapon implements Cloneable{ } spawned.add(); } - //TODO assign AI target here? - return null; } + + if(!continuous){ + shootSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax)); + } + + //TODO mount pos is wrong + ejectEffect.at(mountX, mountY, angle * side); + bullet.shootEffect.at(shootX, shootY, angle, bullet.hitColor, unit); + bullet.smokeEffect.at(shootX, shootY, angle, bullet.hitColor, unit); + + unit.vel.add(Tmp.v1.trns(mountRotation + 180f, bullet.recoil)); + Effect.shake(shake, shake, shootX, shootY); + mount.recoil = recoil; + mount.heat = 1f; + + return result; } public Weapon copy(){ diff --git a/gradle.properties b/gradle.properties index 22738fc189..92b97e3f8b 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=6fb037d33e +archash=801bc93181