Multi shotgun fix (#8460)

* Multi-barrel shotgun fix

* multi-recoil support

* @Nullable for everything
This commit is contained in:
MEEPofFaith 2023-04-03 13:38:10 -07:00 committed by GitHub
parent 2075a226e1
commit 6d71bcd2eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 73 additions and 20 deletions

View file

@ -14,6 +14,8 @@ public abstract class DrawPart{
public boolean under = false;
/** For units, this is the index of the weapon this part gets its progress for. */
public int weaponIndex = 0;
/** Which recoil counter to use. < 0 to use base recoil. */
public int recoilIndex = -1;
public abstract void draw(PartParams params);
public abstract void load(String name);
@ -41,6 +43,11 @@ public abstract class DrawPart{
this.sideMultiplier = 1;
return this;
}
public PartParams setRecoil(float recoils){
this.recoil = recoils;
return this;
}
}
public static class PartMove{

View file

@ -1,5 +1,7 @@
package mindustry.entities.pattern;
import arc.util.*;
public class ShootAlternate extends ShootPattern{
/** number of barrels used for shooting. */
public int barrels = 2;
@ -16,10 +18,11 @@ public class ShootAlternate extends ShootPattern{
}
@Override
public void shoot(int totalShots, BulletHandler handler){
public void shoot(int totalShots, BulletHandler handler, @Nullable Runnable barrelIncrementer){
for(int i = 0; i < shots; i++){
float index = ((totalShots + i + barrelOffset) % barrels) - (barrels-1)/2f;
handler.shoot(index * spread, 0, 0f, firstShotDelay + shotDelay * i);
if(barrelIncrementer != null) barrelIncrementer.run();
}
}
}

View file

@ -1,5 +1,7 @@
package mindustry.entities.pattern;
import arc.util.*;
public class ShootBarrel extends ShootPattern{
/** barrels [in x, y, rotation] format. */
public float[] barrels = {0f, 0f, 0f};
@ -16,10 +18,11 @@ public class ShootBarrel extends ShootPattern{
}
@Override
public void shoot(int totalShots, BulletHandler handler){
public void shoot(int totalShots, BulletHandler handler, @Nullable Runnable barrelIncrementer){
for(int i = 0; i < shots; i++){
int index = ((i + totalShots + barrelOffset) % (barrels.length / 3)) * 3;
handler.shoot(barrels[index], barrels[index + 1], barrels[index + 2], firstShotDelay + shotDelay * i);
if(barrelIncrementer != null) barrelIncrementer.run();
}
}
}

View file

@ -1,12 +1,13 @@
package mindustry.entities.pattern;
import arc.math.*;
import arc.util.*;
public class ShootHelix extends ShootPattern{
public float scl = 2f, mag = 1.5f, offset = Mathf.PI * 1.25f;
@Override
public void shoot(int totalShots, BulletHandler handler){
public void shoot(int totalShots, BulletHandler handler, @Nullable Runnable barrelIncrementer){
for(int i = 0; i < shots; i++){
for(int sign : Mathf.signs){
handler.shoot(0, 0, 0, firstShotDelay + shotDelay * i,

View file

@ -1,5 +1,7 @@
package mindustry.entities.pattern;
import arc.util.*;
public class ShootMulti extends ShootPattern{
public ShootPattern source;
public ShootPattern[] dest = {};
@ -25,7 +27,7 @@ public class ShootMulti extends ShootPattern{
}
@Override
public void shoot(int totalShots, BulletHandler handler){
public void shoot(int totalShots, BulletHandler handler, @Nullable Runnable barrelIncrementer){
source.shoot(totalShots, (x, y, rotation, delay, move) -> {
for(var pattern : dest){
pattern.shoot(totalShots, (x2, y2, rot2, delay2, mover) -> {
@ -35,6 +37,6 @@ public class ShootMulti extends ShootPattern{
});
});
}
});
}, barrelIncrementer);
}
}

View file

@ -1,5 +1,6 @@
package mindustry.entities.pattern;
import arc.util.*;
import mindustry.entities.*;
/** Handles different types of bullet patterns for shooting. */
@ -12,12 +13,17 @@ public class ShootPattern implements Cloneable{
public float shotDelay = 0;
/** Called on a single "trigger pull". This function should call the handler with any bullets that result. */
public void shoot(int totalShots, BulletHandler handler){
public void shoot(int totalShots, BulletHandler handler, @Nullable Runnable barrelIncrementer){
for(int i = 0; i < shots; i++){
handler.shoot(0, 0, 0, firstShotDelay + shotDelay * i);
}
}
/** Called on a single "trigger pull". This function should call the handler with any bullets that result. */
public void shoot(int totalShots, BulletHandler handler){
shoot(totalShots, handler, null);
}
/** Subclasses should override this to flip its sides. */
public void flip(){

View file

@ -1,6 +1,7 @@
package mindustry.entities.pattern;
import arc.math.*;
import arc.util.*;
public class ShootSine extends ShootPattern{
/** scaling applied to bullet index */
@ -17,7 +18,7 @@ public class ShootSine extends ShootPattern{
}
@Override
public void shoot(int totalShots, BulletHandler handler){
public void shoot(int totalShots, BulletHandler handler, @Nullable Runnable barrelIncrementer){
for(int i = 0; i < shots; i++){
float angleOffset = Mathf.sin(i + totalShots, scl, mag);
handler.shoot(0, 0, angleOffset, firstShotDelay + shotDelay * i);

View file

@ -1,5 +1,7 @@
package mindustry.entities.pattern;
import arc.util.*;
public class ShootSpread extends ShootPattern{
/** spread between bullets, in degrees. */
public float spread = 5f;
@ -13,7 +15,7 @@ public class ShootSpread extends ShootPattern{
}
@Override
public void shoot(int totalShots, BulletHandler handler){
public void shoot(int totalShots, BulletHandler handler, @Nullable Runnable barrelIncrementer){
for(int i = 0; i < shots; i++){
float angleOffset = i * spread - (shots - 1) * spread / 2f;
handler.shoot(0, 0, angleOffset, firstShotDelay + shotDelay * i);

View file

@ -14,9 +14,7 @@ public class ShootSummon extends ShootPattern{
}
@Override
public void shoot(int totalShots, BulletHandler handler){
public void shoot(int totalShots, BulletHandler handler, @Nullable Runnable barrelIncrementer){
for(int i = 0; i < shots; i++){
Tmp.v1.trns(Mathf.random(360f), Mathf.random(radius));

View file

@ -14,6 +14,8 @@ public class WeaponMount{
public float rotation;
/** weapon recoil */
public float recoil;
/** weapon barrel recoil */
public @Nullable float[] recoils;
/** destination rotation; do not modify! */
public float targetRotation;
/** current heat, 0 to 1*/
@ -34,8 +36,10 @@ public class WeaponMount{
public boolean rotate = false;
/** extra state for alternating weapons */
public boolean side;
/** total bullets fired from this mount; used for alternating patterns */
/** total bullets fired from this mount */
public int totalShots;
/** counter for which barrel bullets have been fired from; used for alternating patterns */
public int barrelCounter;
/** current bullet for continuous weapons */
public @Nullable Bullet bullet;
/** sound loop for continuous weapons */

View file

@ -75,6 +75,8 @@ public class Weapon implements Cloneable{
public float shake = 0f;
/** visual weapon knockback. */
public float recoil = 1.5f;
/** Number of additional counters for recoil. */
public int recoils = -1;
/** time taken for weapon to return to starting position in ticks. uses reload time by default */
public float recoilTime = -1f;
/** power curve applied to visual recoil */
@ -219,6 +221,7 @@ public class Weapon implements Cloneable{
for(int i = 0; i < parts.size; i++){
var part = parts.get(i);
DrawPart.params.setRecoil(part.recoilIndex >= 0 ? mount.recoils[part.recoilIndex] : mount.recoil);
if(part.under){
part.draw(DrawPart.params);
}
@ -250,6 +253,7 @@ public class Weapon implements Cloneable{
//TODO does it need an outline?
for(int i = 0; i < parts.size; i++){
var part = parts.get(i);
DrawPart.params.setRecoil(part.recoilIndex >= 0 ? mount.recoils[part.recoilIndex] : mount.recoil);
if(!part.under){
part.draw(DrawPart.params);
}
@ -270,6 +274,12 @@ public class Weapon implements Cloneable{
float lastReload = mount.reload;
mount.reload = Math.max(mount.reload - Time.delta * unit.reloadMultiplier, 0);
mount.recoil = Mathf.approachDelta(mount.recoil, 0, unit.reloadMultiplier / recoilTime);
if(recoils > 0){
if(mount.recoils == null) mount.recoils = new float[recoils];
for(int i = 0; i < recoils; i++){
mount.recoils[i] = Mathf.approachDelta(mount.recoils[i], 0, unit.reloadMultiplier / recoilTime);
}
}
mount.smoothReload = Mathf.lerpDelta(mount.smoothReload, mount.reload / reload, smoothReloadSpeed);
mount.charge = mount.charging && shoot.firstShotDelay > 0 ? Mathf.approachDelta(mount.charge, 1, 1 / shoot.firstShotDelay) : 0;
@ -420,14 +430,13 @@ public class Weapon implements Cloneable{
bullet.chargeEffect.at(shootX, shootY, rotation, bullet.keepVelocity || parentizeEffects ? unit : null);
}
shoot.shoot(mount.totalShots, (xOffset, yOffset, angle, delay, mover) -> {
mount.totalShots++;
shoot.shoot(mount.barrelCounter, (xOffset, yOffset, angle, delay, mover) -> {
if(delay > 0f){
Time.run(delay, () -> bullet(unit, mount, xOffset, yOffset, angle, mover));
}else{
bullet(unit, mount, xOffset, yOffset, angle, mover);
}
});
}, () -> mount.barrelCounter++);
}
protected void bullet(Unit unit, WeaponMount mount, float xOffset, float yOffset, float angleOffset, Mover mover){
@ -459,7 +468,11 @@ public class Weapon implements Cloneable{
unit.vel.add(Tmp.v1.trns(shootAngle + 180f, bullet.recoil));
Effect.shake(shake, shake, bulletX, bulletY);
mount.recoil = 1f;
if(recoils > 0){
mount.recoils[mount.barrelCounter % recoils] = 1f;
}
mount.heat = 1f;
mount.totalShots++;
}
//override to do special things to a bullet after spawning

View file

@ -112,6 +112,8 @@ public class Turret extends ReloadTurret{
public boolean linearWarmup = false;
/** Visual amount by which the turret recoils back per shot. */
public float recoil = 1f;
/** Number of additional counters for recoil. */
public int recoils = -1;
/** ticks taken for turret to return to starting position in ticks. uses reload time by default */
public float recoilTime = -1f;
/** power curve applied to visual recoil */
@ -210,8 +212,9 @@ public class Turret extends ReloadTurret{
public Seq<AmmoEntry> ammo = new Seq<>();
public int totalAmmo;
public float curRecoil, heat, logicControlTime = -1;
public @Nullable float[] curRecoils;
public float shootWarmup, charge, warmupHold = 0f;
public int totalShots;
public int totalShots, barrelCounter;
public boolean logicShooting = false;
public @Nullable Posc target;
public Vec2 targetPos = new Vec2();
@ -365,6 +368,12 @@ public class Turret extends ReloadTurret{
wasShooting = false;
curRecoil = Mathf.approachDelta(curRecoil, 0, 1 / recoilTime);
if(recoils > 0){
if(curRecoils == null) curRecoils = new float[recoils];
for(int i = 0; i < recoils; i++){
curRecoils[i] = Mathf.approachDelta(curRecoils[i], 0, 1 / recoilTime);
}
}
heat = Mathf.approachDelta(heat, 0, 1 / cooldownTime);
charge = charging() ? Mathf.approachDelta(charge, 1, 1 / shoot.firstShotDelay) : 0;
@ -537,15 +546,14 @@ public class Turret extends ReloadTurret{
type.chargeEffect.at(bulletX, bulletY, rotation);
}
shoot.shoot(totalShots, (xOffset, yOffset, angle, delay, mover) -> {
queuedBullets ++;
shoot.shoot(barrelCounter, (xOffset, yOffset, angle, delay, mover) -> {
queuedBullets++;
if(delay > 0f){
Time.run(delay, () -> bullet(type, xOffset, yOffset, angle, mover));
}else{
bullet(type, xOffset, yOffset, angle, mover);
}
totalShots ++;
});
}, () -> barrelCounter++);
if(consumeAmmoOnce){
useAmmo();
@ -583,7 +591,11 @@ public class Turret extends ReloadTurret{
}
curRecoil = 1f;
if(recoils > 0){
curRecoils[barrelCounter % recoils] = 1f;
}
heat = 1f;
totalShots++;
if(!consumeAmmoOnce){
useAmmo();

View file

@ -75,6 +75,7 @@ public class DrawTurret extends DrawBlock{
var params = DrawPart.params.set(build.warmup(), 1f - progress, 1f - progress, tb.heat, tb.curRecoil, tb.charge, tb.x + tb.recoilOffset.x, tb.y + tb.recoilOffset.y, tb.rotation);
for(var part : parts){
params.setRecoil(part.recoilIndex >= 0 ? tb.curRecoils[part.recoilIndex] : tb.curRecoil);
part.draw(params);
}
}