Better weapon shooting implementation

This commit is contained in:
Anuken
2022-02-23 14:29:41 -05:00
parent 08d9ff331a
commit af8268241b
7 changed files with 61 additions and 71 deletions

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -3354,14 +3354,14 @@ public class Blocks{
targetAir = false; targetAir = false;
shootShake = 4f; shootShake = 4f;
recoilAmount = 1f; recoilAmount = 1f;
reloadTime = 60f * 2f; reloadTime = 60f * 2.3f;
shootLength = 7f; shootLength = 7f;
rotateSpeed = 1.4f; rotateSpeed = 1.4f;
minWarmup = 0.85f; minWarmup = 0.85f;
shootWarmupSpeed = 0.07f; shootWarmupSpeed = 0.07f;
coolant = consume(new ConsumeLiquid(Liquids.water, 30f / 60f)); coolant = consume(new ConsumeLiquid(Liquids.water, 30f / 60f));
coolantMultiplier = 2.5f; coolantMultiplier = 1.5f;
draw = new DrawTurret("reinforced-"){{ draw = new DrawTurret("reinforced-"){{
parts.addAll( parts.addAll(

View File

@@ -1515,7 +1515,7 @@ public class Fx{
color(Color.white, e.color, e.fin()); color(Color.white, e.color, e.fin());
rand.setSeed(e.id); 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); float rot = e.rotation + rand.range(22f);
v.trns(rot, rand.random(e.finpow() * 24f)); 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)); Fill.poly(e.x + v.x, e.y + v.y, 4, e.fout() * 3.8f + 0.2f, rand.random(360f));

View File

@@ -479,7 +479,7 @@ public class UnitTypes{
despawnEffect = Fx.smokeCloud; despawnEffect = Fx.smokeCloud;
smokeEffect = Fx.none; smokeEffect = Fx.none;
shootEffect = Fx.greenLaserChargeSmall; chargeEffect = Fx.greenLaserChargeSmall;
incendChance = 0.1f; incendChance = 0.1f;
incendSpread = 5f; incendSpread = 5f;
@@ -566,7 +566,7 @@ public class UnitTypes{
largeHit = true; largeHit = true;
lightColor = lightningColor = Pal.heal; lightColor = lightningColor = Pal.heal;
shootEffect = Fx.greenLaserCharge; chargeEffect = Fx.greenLaserCharge;
healPercent = 25f; healPercent = 25f;
collidesTeam = true; collidesTeam = true;
@@ -1209,7 +1209,7 @@ public class UnitTypes{
shadow = 7f; shadow = 7f;
rotate = true; rotate = true;
recoil = 0.5f; recoil = 0.5f;
shootY = 7.25f;
bullet = fragBullet; bullet = fragBullet;
}}, }},
new Weapon("large-artillery"){{ new Weapon("large-artillery"){{
@@ -1222,6 +1222,7 @@ public class UnitTypes{
shootSound = Sounds.shoot; shootSound = Sounds.shoot;
rotate = true; rotate = true;
shadow = 12f; shadow = 12f;
shootY = 7.25f;
bullet = fragBullet; bullet = fragBullet;
}}); }});
}}; }};
@@ -2481,6 +2482,8 @@ public class UnitTypes{
heatColor = Color.valueOf("f9350f"); heatColor = Color.valueOf("f9350f");
cooldownTime = 30f; cooldownTime = 30f;
shots = 2;
bullet = new BasicBulletType(5f, 50){{ bullet = new BasicBulletType(5f, 50){{
sprite = "missile-large"; sprite = "missile-large";
smokeEffect = Fx.shootBigSmoke; smokeEffect = Fx.shootBigSmoke;
@@ -2887,11 +2890,11 @@ public class UnitTypes{
x = 43 / 4f; x = 43 / 4f;
y = -20f / 4f; y = -20f / 4f;
shootY = 39 / 4f; shootY = 37 / 4f;
shootX = -5f / 4f; shootX = -5f / 4f;
recoil = 3f; recoil = 3f;
reload = 30f; reload = 30f;
shake = 3f; shake = 2f;
cooldownTime = 20f; cooldownTime = 20f;
layerOffset = 0.02f; layerOffset = 0.02f;

View File

@@ -53,8 +53,8 @@ public class BulletType extends Content implements Cloneable{
public Effect despawnEffect = Fx.hitBulletSmall; public Effect despawnEffect = Fx.hitBulletSmall;
/** Effect created when shooting. */ /** Effect created when shooting. */
public Effect shootEffect = Fx.shootSmall; public Effect shootEffect = Fx.shootSmall;
/** Effect created when charging completes; only usable in single-shot weapons with a firstShotDelay / shotDelay. */ /** Effect created when charging starts; only usable in single-shot weapons with a firstShotDelay / shotDelay. */
public Effect chargeShootEffect = Fx.none; public Effect chargeEffect = Fx.none;
/** Extra smoke effect created when shooting. */ /** Extra smoke effect created when shooting. */
public Effect smokeEffect = Fx.shootSmallSmoke; public Effect smokeEffect = Fx.shootSmallSmoke;
/** Sound made when hitting something or getting removed.*/ /** Sound made when hitting something or getting removed.*/

View File

@@ -24,9 +24,6 @@ import mindustry.world.meta.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class Weapon implements Cloneable{ public class Weapon implements Cloneable{
/** temporary weapon sequence number */
static int sequenceNum = 0;
/** displayed weapon region */ /** displayed weapon region */
public String name; public String name;
/** bullet shot */ /** bullet shot */
@@ -276,7 +273,7 @@ public class Weapon implements Cloneable{
mountY = unit.y + Angles.trnsy(unit.rotation - 90, x, y), mountY = unit.y + Angles.trnsy(unit.rotation - 90, x, y),
bulletX = mountX + Angles.trnsx(weaponRotation, this.shootX, this.shootY), bulletX = mountX + Angles.trnsx(weaponRotation, this.shootX, this.shootY),
bulletY = mountY + Angles.trnsy(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 //find a new target
if(!controllable && autoTarget){ if(!controllable && autoTarget){
@@ -370,86 +367,62 @@ public class Weapon implements Cloneable{
return Units.invalidateTarget(target, unit.team, x, y, range + Math.abs(shootY)); return Units.invalidateTarget(target, unit.team, x, y, range + Math.abs(shootY));
} }
protected Vec2 getShootPos(Unit unit, WeaponMount mount, Vec2 out){ protected float bulletRotation(Unit unit, WeaponMount mount, float bulletX, float bulletY){
float weaponRot = unit.rotation - 90 + (rotate ? mount.rotation : 0); return rotate ? unit.rotation + mount.rotation : Angles.angle(bulletX, bulletY, mount.aimX, mount.aimY) + (unit.rotation - unit.angleTo(mount.aimX, mount.aimY));
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 void shoot(Unit unit, WeaponMount mount, float shootX, float shootY, float aimX, float aimY, float mountX, float mountY, float rotation, int side){ 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; boolean delay = firstShotDelay + shotDelay > 0f;
float lifeScl = bullet.scaleVelocity ? Mathf.clamp(Mathf.dst(shootX, shootY, aimX, aimY) / bullet.range()) : 1f; float lifeScl = bullet.scaleVelocity ? Mathf.clamp(Mathf.dst(shootX, shootY, aimX, aimY) / bullet.range()) : 1f;
Unit parent = bullet.keepVelocity || parentizeEffects ? unit : null; 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){ if(delay){
Angles.shotgun(shots, spacing, rotation, f -> { chargeSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax));
Time.run(sequenceNum * shotDelay + firstShotDelay, () -> { bullet.chargeEffect.at(shootX, shootY, rotation, parent);
if(!unit.isAdded()) return;
//TODO this is a flawed system, recalculate everything instead. for(int i = 0; i < shots; i++){
getShootPos(unit, mount, offset).sub(baseX, baseY); float angleOffset = i * spacing - (shots - 1) * spacing / 2f;
float rotOffset = unit.rotation + mount.rotation - baseRot; Time.run(i * shotDelay + firstShotDelay, () -> {
mount.bullet = bullet(unit, shootX + offset.x, shootY + offset.y, f + Mathf.range(inaccuracy) + rotOffset, lifeScl); //everything needs to be re-calculated again
if(!continuous){ float
shootSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax)); 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{ }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); unit.apply(shootStatus, shootStatusDuration);
} }
protected void effects(Unit parent, float mountX, float mountY, float shootX, float shootY, float rotation, int side){ protected @Nullable Bullet bullet(WeaponMount mount, Unit unit, float shootX, float shootY, float angle, float lifescl, int side, float mountRotation, float mountX, float mountY){
ejectEffect.at(mountX, mountY, rotation * side); if(!unit.isAdded()) return null;
bullet.shootEffect.at(shootX, shootY, rotation, bullet.hitColor, parent);
bullet.smokeEffect.at(shootX, shootY, rotation, bullet.hitColor, parent);
}
protected @Nullable Bullet bullet(Unit unit, float shootX, float shootY, float angle, float lifescl){
float float
xr = Mathf.range(xRand), xr = Mathf.range(xRand),
x = shootX + Angles.trnsx(angle, 0, xr), x = shootX + Angles.trnsx(angle, 0, xr),
y = shootY + Angles.trnsy(angle, 0, xr); y = shootY + Angles.trnsy(angle, 0, xr);
Bullet result = null;
if(unitSpawned == 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{ }else{
//don't spawn units clientside! //don't spawn units clientside!
if(!net.client()){ if(!net.client()){
@@ -463,9 +436,23 @@ public class Weapon implements Cloneable{
} }
spawned.add(); 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(){ public Weapon copy(){

View File

@@ -24,4 +24,4 @@ android.useAndroidX=true
#used for slow jitpack builds; TODO see if this actually works #used for slow jitpack builds; TODO see if this actually works
org.gradle.internal.http.socketTimeout=100000 org.gradle.internal.http.socketTimeout=100000
org.gradle.internal.http.connectionTimeout=100000 org.gradle.internal.http.connectionTimeout=100000
archash=6fb037d33e archash=801bc93181