Bullet/weapon cleanup
This commit is contained in:
@@ -37,7 +37,7 @@ public class SuicideAI extends GroundAI{
|
|||||||
|
|
||||||
if(!Units.invalidateTarget(target, unit, unit.range()) && unit.hasWeapons()){
|
if(!Units.invalidateTarget(target, unit, unit.range()) && unit.hasWeapons()){
|
||||||
rotate = true;
|
rotate = true;
|
||||||
shoot = unit.within(target, unit.type.weapons.first().bullet.range() +
|
shoot = unit.within(target, unit.type.weapons.first().bullet.range +
|
||||||
(target instanceof Building b ? b.block.size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f));
|
(target instanceof Building b ? b.block.size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f));
|
||||||
|
|
||||||
//do not move toward walls or transport blocks
|
//do not move toward walls or transport blocks
|
||||||
|
|||||||
@@ -3019,24 +3019,24 @@ public class UnitTypes{
|
|||||||
shake = 1f;
|
shake = 1f;
|
||||||
speed = 0f;
|
speed = 0f;
|
||||||
keepVelocity = false;
|
keepVelocity = false;
|
||||||
}};
|
|
||||||
|
|
||||||
unitSpawned = new MissileUnitType("quell-missile"){{
|
spawnUnit = new MissileUnitType("quell-missile"){{
|
||||||
speed = 3.8f;
|
speed = 3.8f;
|
||||||
maxRange = 6f;
|
maxRange = 6f;
|
||||||
lifetime = 60f * 1.2f;
|
lifetime = 60f * 1.2f;
|
||||||
outlineColor = Pal.darkOutline;
|
outlineColor = Pal.darkOutline;
|
||||||
health = 45;
|
health = 45;
|
||||||
|
|
||||||
weapons.add(new Weapon(){{
|
weapons.add(new Weapon(){{
|
||||||
shootCone = 360f;
|
shootCone = 360f;
|
||||||
mirror = false;
|
mirror = false;
|
||||||
reload = 1f;
|
reload = 1f;
|
||||||
shootOnDeath = true;
|
shootOnDeath = true;
|
||||||
bullet = new ExplosionBulletType(100f, 22f){{
|
bullet = new ExplosionBulletType(100f, 22f){{
|
||||||
shootEffect = Fx.massiveExplosion;
|
shootEffect = Fx.massiveExplosion;
|
||||||
}};
|
}};
|
||||||
}});
|
}});
|
||||||
|
}};
|
||||||
}};
|
}};
|
||||||
}});
|
}});
|
||||||
|
|
||||||
@@ -3124,62 +3124,62 @@ public class UnitTypes{
|
|||||||
shake = 1f;
|
shake = 1f;
|
||||||
speed = 0f;
|
speed = 0f;
|
||||||
keepVelocity = false;
|
keepVelocity = false;
|
||||||
}};
|
|
||||||
|
|
||||||
unitSpawned = new MissileUnitType("disrupt-missile"){{
|
spawnUnit = new MissileUnitType("disrupt-missile"){{
|
||||||
speed = 4.5f;
|
speed = 4.5f;
|
||||||
maxRange = 5f;
|
maxRange = 5f;
|
||||||
outlineColor = Pal.darkOutline;
|
outlineColor = Pal.darkOutline;
|
||||||
health = 70;
|
health = 70;
|
||||||
homingDelay = 10f;
|
homingDelay = 10f;
|
||||||
lowAltitude = true;
|
lowAltitude = true;
|
||||||
engineSize = 3f;
|
engineSize = 3f;
|
||||||
deathExplosionEffect = Fx.none;
|
deathExplosionEffect = Fx.none;
|
||||||
|
|
||||||
parts.add(new ShapePart(){{
|
parts.add(new ShapePart(){{
|
||||||
layer = Layer.effect;
|
layer = Layer.effect;
|
||||||
circle = true;
|
circle = true;
|
||||||
y = -0.25f;
|
y = -0.25f;
|
||||||
radius = 1.5f;
|
radius = 1.5f;
|
||||||
color = Pal.suppress;
|
color = Pal.suppress;
|
||||||
colorTo = Color.white;
|
colorTo = Color.white;
|
||||||
progress = PartProgress.life.curve(Interp.pow5In);
|
progress = PartProgress.life.curve(Interp.pow5In);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
parts.add(new RegionPart("-fin"){{
|
parts.add(new RegionPart("-fin"){{
|
||||||
mirror = true;
|
mirror = true;
|
||||||
progress = PartProgress.life.mul(3f).curve(Interp.pow5In);
|
progress = PartProgress.life.mul(3f).curve(Interp.pow5In);
|
||||||
moveRot = 32f;
|
moveRot = 32f;
|
||||||
rotation = -6f;
|
rotation = -6f;
|
||||||
moveY = 1.5f;
|
moveY = 1.5f;
|
||||||
x = 3f / 4f;
|
x = 3f / 4f;
|
||||||
y = -6f / 4f;
|
y = -6f / 4f;
|
||||||
}});
|
}});
|
||||||
|
|
||||||
weapons.add(new Weapon(){{
|
weapons.add(new Weapon(){{
|
||||||
shootCone = 360f;
|
shootCone = 360f;
|
||||||
mirror = false;
|
mirror = false;
|
||||||
reload = 1f;
|
reload = 1f;
|
||||||
shootOnDeath = true;
|
shootOnDeath = true;
|
||||||
bullet = new ExplosionBulletType(120f, 25f){{
|
bullet = new ExplosionBulletType(120f, 25f){{
|
||||||
suppressionRange = 140f;
|
suppressionRange = 140f;
|
||||||
shootEffect = new ExplosionEffect(){{
|
shootEffect = new ExplosionEffect(){{
|
||||||
lifetime = 50f;
|
lifetime = 50f;
|
||||||
waveStroke = 5f;
|
waveStroke = 5f;
|
||||||
waveLife = 8f;
|
waveLife = 8f;
|
||||||
waveColor = Color.white;
|
waveColor = Color.white;
|
||||||
sparkColor = smokeColor = Pal.suppress;
|
sparkColor = smokeColor = Pal.suppress;
|
||||||
waveRad = 40f;
|
waveRad = 40f;
|
||||||
smokeSize = 4f;
|
smokeSize = 4f;
|
||||||
smokes = 7;
|
smokes = 7;
|
||||||
smokeSizeBase = 0f;
|
smokeSizeBase = 0f;
|
||||||
sparks = 10;
|
sparks = 10;
|
||||||
sparkRad = 40f;
|
sparkRad = 40f;
|
||||||
sparkLen = 6f;
|
sparkLen = 6f;
|
||||||
sparkStroke = 2f;
|
sparkStroke = 2f;
|
||||||
|
}};
|
||||||
}};
|
}};
|
||||||
}};
|
}});
|
||||||
}});
|
}};
|
||||||
}};
|
}};
|
||||||
}});
|
}});
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import arc.math.geom.*;
|
|||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
|
import mindustry.ai.types.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
@@ -122,6 +123,8 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
public float rangeOverride = -1f;
|
public float rangeOverride = -1f;
|
||||||
/** When used in a turret with multiple ammo types, this can be set to a non-zero value to influence range. */
|
/** When used in a turret with multiple ammo types, this can be set to a non-zero value to influence range. */
|
||||||
public float rangeChange = 0f;
|
public float rangeChange = 0f;
|
||||||
|
/** Range initialized in init(). */
|
||||||
|
public float range = 0f;
|
||||||
/** % of block health healed **/
|
/** % of block health healed **/
|
||||||
public float healPercent = 0f;
|
public float healPercent = 0f;
|
||||||
/** flat amount of block health healed */
|
/** flat amount of block health healed */
|
||||||
@@ -148,6 +151,8 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
public Effect healEffect = Fx.healBlockFull;
|
public Effect healEffect = Fx.healBlockFull;
|
||||||
/** Bullets spawned when this bullet is created. Rarely necessary, used for visuals. */
|
/** Bullets spawned when this bullet is created. Rarely necessary, used for visuals. */
|
||||||
public Seq<BulletType> spawnBullets = new Seq<>();
|
public Seq<BulletType> spawnBullets = new Seq<>();
|
||||||
|
/** Unit spawned _instead of_ this bullet. Useful for missiles. */
|
||||||
|
public @Nullable UnitType spawnUnit;
|
||||||
|
|
||||||
public Color trailColor = Pal.missileYellowBack;
|
public Color trailColor = Pal.missileYellowBack;
|
||||||
public float trailChance = -0.0001f;
|
public float trailChance = -0.0001f;
|
||||||
@@ -228,9 +233,10 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns maximum distance the bullet this bullet type has can travel. */
|
/** @return maximum distance the bullet this bullet type has can travel. */
|
||||||
public float range(){
|
protected float calculateRange(){
|
||||||
if(rangeOverride > 0) return rangeOverride;
|
if(rangeOverride > 0) return rangeOverride;
|
||||||
|
if(spawnUnit != null) return spawnUnit.lifetime * spawnUnit.speed;
|
||||||
return Math.max(Mathf.zero(drag) ? speed * lifetime : speed * (1f - Mathf.pow(1f - drag, lifetime)) / drag, maxRange);
|
return Math.max(Mathf.zero(drag) ? speed * lifetime : speed * (1f - Mathf.pow(1f - drag, lifetime)) / drag, maxRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,6 +477,7 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawSize = Math.max(drawSize, trailLength * speed * 2f);
|
drawSize = Math.max(drawSize, trailLength * speed * 2f);
|
||||||
|
range = calculateRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -478,35 +485,54 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
return ContentType.bullet;
|
return ContentType.bullet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bullet create(Teamc owner, float x, float y, float angle){
|
public @Nullable Bullet create(Teamc owner, float x, float y, float angle){
|
||||||
return create(owner, owner.team(), x, y, angle);
|
return create(owner, owner.team(), x, y, angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bullet create(Entityc owner, Team team, float x, float y, float angle){
|
public @Nullable Bullet create(Entityc owner, Team team, float x, float y, float angle){
|
||||||
return create(owner, team, x, y, angle, 1f);
|
return create(owner, team, x, y, angle, 1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bullet create(Entityc owner, Team team, float x, float y, float angle, float velocityScl){
|
public @Nullable Bullet create(Entityc owner, Team team, float x, float y, float angle, float velocityScl){
|
||||||
return create(owner, team, x, y, angle, -1, velocityScl, 1f, null);
|
return create(owner, team, x, y, angle, -1, velocityScl, 1f, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bullet create(Entityc owner, Team team, float x, float y, float angle, float velocityScl, float lifetimeScl){
|
public @Nullable Bullet create(Entityc owner, Team team, float x, float y, float angle, float velocityScl, float lifetimeScl){
|
||||||
return create(owner, team, x, y, angle, -1, velocityScl, lifetimeScl, null);
|
return create(owner, team, x, y, angle, -1, velocityScl, lifetimeScl, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bullet create(Bullet parent, float x, float y, float angle){
|
public @Nullable Bullet create(Bullet parent, float x, float y, float angle){
|
||||||
return create(parent.owner, parent.team, x, y, angle);
|
return create(parent.owner, parent.team, x, y, angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bullet create(Bullet parent, float x, float y, float angle, float velocityScl, float lifeScale){
|
public @Nullable Bullet create(Bullet parent, float x, float y, float angle, float velocityScl, float lifeScale){
|
||||||
return create(parent.owner, parent.team, x, y, angle, velocityScl, lifeScale);
|
return create(parent.owner, parent.team, x, y, angle, velocityScl, lifeScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bullet create(Bullet parent, float x, float y, float angle, float velocityScl){
|
public @Nullable Bullet create(Bullet parent, float x, float y, float angle, float velocityScl){
|
||||||
return create(parent.owner(), parent.team, x, y, angle, velocityScl);
|
return create(parent.owner(), parent.team, x, y, angle, velocityScl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bullet create(@Nullable Entityc owner, Team team, float x, float y, float angle, float damage, float velocityScl, float lifetimeScl, Object data){
|
public @Nullable Bullet create(@Nullable Entityc owner, Team team, float x, float y, float angle, float damage, float velocityScl, float lifetimeScl, Object data){
|
||||||
|
if(spawnUnit != null){
|
||||||
|
//don't spawn units clientside!
|
||||||
|
if(!net.client()){
|
||||||
|
Unit spawned = spawnUnit.create(team);
|
||||||
|
spawned.set(x, y);
|
||||||
|
spawned.rotation = angle;
|
||||||
|
//immediately spawn at top speed, since it was launched
|
||||||
|
spawned.vel.trns(angle, spawnUnit.speed);
|
||||||
|
//assign unit owner
|
||||||
|
if(spawned.controller() instanceof MissileAI ai && owner instanceof Unit unit){
|
||||||
|
ai.shooter = unit;
|
||||||
|
}
|
||||||
|
spawned.add();
|
||||||
|
}
|
||||||
|
|
||||||
|
//no bullet returned
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Bullet bullet = Bullet.create();
|
Bullet bullet = Bullet.create();
|
||||||
bullet.type = this;
|
bullet.type = this;
|
||||||
bullet.owner = owner;
|
bullet.owner = owner;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class ContinuousBulletType extends BulletType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float range(){
|
protected float calculateRange(){
|
||||||
return Math.max(length, maxRange);
|
return Math.max(length, maxRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public class LaserBulletType extends BulletType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float range(){
|
protected float calculateRange(){
|
||||||
return Math.max(length, maxRange);
|
return Math.max(length, maxRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class LightningBulletType extends BulletType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float range(){
|
protected float calculateRange(){
|
||||||
return (lightningLength + lightningLengthRand/2f) * 6f;
|
return (lightningLength + lightningLengthRand/2f) * 6f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class RailBulletType extends BulletType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float range(){
|
protected float calculateRange(){
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class SapBulletType extends BulletType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float range(){
|
protected float calculateRange(){
|
||||||
return Math.max(length, maxRange);
|
return Math.max(length, maxRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class ShrapnelBulletType extends BulletType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float range(){
|
protected float calculateRange(){
|
||||||
return Math.max(length, maxRange);
|
return Math.max(length, maxRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import arc.math.geom.*;
|
|||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.ai.types.*;
|
|
||||||
import mindustry.audio.*;
|
import mindustry.audio.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
@@ -28,8 +27,6 @@ public class Weapon implements Cloneable{
|
|||||||
public String name;
|
public String name;
|
||||||
/** bullet shot */
|
/** bullet shot */
|
||||||
public BulletType bullet = Bullets.standardCopper;
|
public BulletType bullet = Bullets.standardCopper;
|
||||||
/** unit, to spawn at bullet, e.g. missile. TODO prevent bullet creation */
|
|
||||||
public @Nullable UnitType unitSpawned;
|
|
||||||
/** shell ejection effect */
|
/** shell ejection effect */
|
||||||
public Effect ejectEffect = Fx.none;
|
public Effect ejectEffect = Fx.none;
|
||||||
/** whether to consume ammo when ammo is enabled in rules */
|
/** whether to consume ammo when ammo is enabled in rules */
|
||||||
@@ -238,7 +235,7 @@ public class Weapon implements Cloneable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public float range(){
|
public float range(){
|
||||||
return unitSpawned != null ? unitSpawned.lifetime * unitSpawned.speed : bullet.range();
|
return bullet.range;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(Unit unit, WeaponMount mount){
|
public void update(Unit unit, WeaponMount mount){
|
||||||
@@ -278,18 +275,18 @@ public class Weapon implements Cloneable{
|
|||||||
//find a new target
|
//find a new target
|
||||||
if(!controllable && autoTarget){
|
if(!controllable && autoTarget){
|
||||||
if((mount.retarget -= Time.delta) <= 0f){
|
if((mount.retarget -= Time.delta) <= 0f){
|
||||||
mount.target = findTarget(unit, mountX, mountY, bullet.range(), bullet.collidesAir, bullet.collidesGround);
|
mount.target = findTarget(unit, mountX, mountY, bullet.range, bullet.collidesAir, bullet.collidesGround);
|
||||||
mount.retarget = mount.target == null ? targetInterval : targetSwitchInterval;
|
mount.retarget = mount.target == null ? targetInterval : targetSwitchInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mount.target != null && checkTarget(unit, mount.target, mountX, mountY, bullet.range())){
|
if(mount.target != null && checkTarget(unit, mount.target, mountX, mountY, bullet.range)){
|
||||||
mount.target = null;
|
mount.target = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean shoot = false;
|
boolean shoot = false;
|
||||||
|
|
||||||
if(mount.target != null){
|
if(mount.target != null){
|
||||||
shoot = mount.target.within(mountX, mountY, bullet.range() + Math.abs(shootY) + (mount.target instanceof Sized s ? s.hitSize()/2f : 0f)) && can;
|
shoot = mount.target.within(mountX, mountY, bullet.range + Math.abs(shootY) + (mount.target instanceof Sized s ? s.hitSize()/2f : 0f)) && can;
|
||||||
|
|
||||||
if(predictTarget){
|
if(predictTarget){
|
||||||
Vec2 to = Predict.intercept(unit, mount.target, bullet.speed);
|
Vec2 to = Predict.intercept(unit, mount.target, bullet.speed);
|
||||||
@@ -348,7 +345,7 @@ public class Weapon implements Cloneable{
|
|||||||
mount.reload <= 0.0001f && //reload has to be 0
|
mount.reload <= 0.0001f && //reload has to be 0
|
||||||
Angles.within(rotate ? mount.rotation : unit.rotation, mount.targetRotation, shootCone) //has to be within the cone
|
Angles.within(rotate ? mount.rotation : unit.rotation, mount.targetRotation, shootCone) //has to be within the cone
|
||||||
){
|
){
|
||||||
shoot(unit, mount, bulletX, bulletY, mount.aimX, mount.aimY, mountX, mountY, shootAngle, Mathf.sign(x));
|
shoot(unit, mount, bulletX, bulletY, shootAngle);
|
||||||
|
|
||||||
mount.reload = reload;
|
mount.reload = reload;
|
||||||
|
|
||||||
@@ -371,45 +368,46 @@ public class Weapon implements Cloneable{
|
|||||||
return rotate ? unit.rotation + mount.rotation : Angles.angle(bulletX, bulletY, mount.aimX, mount.aimY) + (unit.rotation - unit.angleTo(mount.aimX, mount.aimY));
|
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){
|
protected void shoot(Unit unit, WeaponMount mount, float shootX, float shootY, float 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;
|
|
||||||
Unit parent = bullet.keepVelocity || parentizeEffects ? unit : null;
|
Unit parent = bullet.keepVelocity || parentizeEffects ? unit : null;
|
||||||
|
|
||||||
//TODO merge with Turret behavior if possible
|
if(firstShotDelay > 0){
|
||||||
|
|
||||||
if(delay){
|
|
||||||
chargeSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax));
|
chargeSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax));
|
||||||
bullet.chargeEffect.at(shootX, shootY, rotation, parent);
|
bullet.chargeEffect.at(shootX, shootY, rotation, parent);
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < shots; i++){
|
//shot patterns should be able to customize:
|
||||||
float angleOffset = i * spacing - (shots - 1) * spacing / 2f;
|
//- the position of a specific bullet index
|
||||||
|
//- the delay of a specific bullet index
|
||||||
|
|
||||||
Time.run(i * shotDelay + firstShotDelay, () -> {
|
//TODO merge with Turret behavior if possible
|
||||||
//everything needs to be re-calculated again
|
for(int i = 0; i < shots; i++){
|
||||||
float
|
float angleOffset = i * spacing - (shots - 1) * spacing / 2f;
|
||||||
rweaponRotation = unit.rotation - 90 + (rotate ? mount.rotation : 0),
|
if(delay){
|
||||||
rmountX = unit.x + Angles.trnsx(unit.rotation - 90, x, y),
|
Time.run(i * shotDelay + firstShotDelay, () -> shoot(unit, mount, angleOffset));
|
||||||
rmountY = unit.y + Angles.trnsy(unit.rotation - 90, x, y),
|
}else{
|
||||||
rbulletX = rmountX + Angles.trnsx(rweaponRotation, this.shootX, this.shootY),
|
shoot(unit, mount, angleOffset);
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unit.apply(shootStatus, shootStatusDuration);
|
unit.apply(shootStatus, shootStatusDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected @Nullable Bullet bullet(WeaponMount mount, Unit unit, float shootX, float shootY, float angle, float lifescl, int side, float mountRotation, float mountX, float mountY){
|
protected void shoot(Unit unit, WeaponMount mount, float angleOffset){
|
||||||
|
float
|
||||||
|
weaponRotation = unit.rotation - 90 + (rotate ? mount.rotation : 0),
|
||||||
|
mountX = unit.x + Angles.trnsx(unit.rotation - 90, x, y),
|
||||||
|
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 = bulletRotation(unit, mount, bulletX, bulletY),
|
||||||
|
lifeScl = bullet.scaleVelocity ? Mathf.clamp(Mathf.dst(shootX, shootY, mount.aimX, mount.aimY) / bullet.range) : 1f;
|
||||||
|
|
||||||
|
mount.bullet = bullet(mount, unit, shootX, shootY, angleOffset + shootAngle + Mathf.range(inaccuracy), lifeScl, shootAngle, mountX, mountY);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected @Nullable Bullet bullet(WeaponMount mount, Unit unit, float shootX, float shootY, float angle, float lifescl, float mountRotation, float mountX, float mountY){
|
||||||
if(!unit.isAdded()) return null;
|
if(!unit.isAdded()) return null;
|
||||||
|
|
||||||
float
|
float
|
||||||
@@ -417,30 +415,13 @@ public class Weapon implements Cloneable{
|
|||||||
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;
|
Bullet result = bullet.create(unit, unit.team, x, y, angle, (1f - velocityRnd) + Mathf.random(velocityRnd), lifescl);
|
||||||
|
|
||||||
if(unitSpawned == null){
|
|
||||||
result = bullet.create(unit, unit.team, x, y, angle, (1f - velocityRnd) + Mathf.random(velocityRnd), lifescl);
|
|
||||||
}else{
|
|
||||||
//don't spawn units clientside!
|
|
||||||
if(!net.client()){
|
|
||||||
Unit spawned = unitSpawned.create(unit.team);
|
|
||||||
spawned.set(x, y);
|
|
||||||
spawned.rotation = angle;
|
|
||||||
//immediately spawn at top speed, since it was launched
|
|
||||||
spawned.vel.trns(angle, unitSpawned.speed);
|
|
||||||
if(spawned.controller() instanceof MissileAI ai){
|
|
||||||
ai.shooter = unit;
|
|
||||||
}
|
|
||||||
spawned.add();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!continuous){
|
if(!continuous){
|
||||||
shootSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax));
|
shootSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax));
|
||||||
}
|
}
|
||||||
|
|
||||||
ejectEffect.at(mountX, mountY, angle * side);
|
ejectEffect.at(mountX, mountY, angle * Mathf.sign(this.x));
|
||||||
bullet.shootEffect.at(shootX, shootY, angle, bullet.hitColor, unit);
|
bullet.shootEffect.at(shootX, shootY, angle, bullet.hitColor, unit);
|
||||||
bullet.smokeEffect.at(shootX, shootY, angle, bullet.hitColor, unit);
|
bullet.smokeEffect.at(shootX, shootY, angle, bullet.hitColor, unit);
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package mindustry.world.blocks.defense.turrets;
|
|||||||
|
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
|
import arc.util.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.entities.bullet.*;
|
import mindustry.entities.bullet.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
@@ -31,7 +32,7 @@ public class ContinuousTurret extends Turret{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class ContinuousTurretBuild extends TurretBuild{
|
public class ContinuousTurretBuild extends TurretBuild{
|
||||||
public Bullet bullet;
|
public @Nullable Bullet bullet;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateCooling(){
|
protected void updateCooling(){
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class LaserTurret extends PowerTurret{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class LaserTurretBuild extends PowerTurretBuild{
|
public class LaserTurretBuild extends PowerTurretBuild{
|
||||||
public Bullet bullet;
|
public @Nullable Bullet bullet;
|
||||||
public float bulletLife;
|
public float bulletLife;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -512,7 +512,6 @@ public class Turret extends ReloadTurret{
|
|||||||
recoil = recoilAmount;
|
recoil = recoilAmount;
|
||||||
heat = 1f;
|
heat = 1f;
|
||||||
bullet(type, rotation + Mathf.range(inaccuracy + type.inaccuracy));
|
bullet(type, rotation + Mathf.range(inaccuracy + type.inaccuracy));
|
||||||
effects();
|
|
||||||
charging = false;
|
charging = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -525,7 +524,6 @@ public class Turret extends ReloadTurret{
|
|||||||
|
|
||||||
bulletOffset.trns(rotation, shootLength, Mathf.range(xRand));
|
bulletOffset.trns(rotation, shootLength, Mathf.range(xRand));
|
||||||
bullet(peekAmmo(), rotation + Mathf.range(inaccuracy + peekAmmo().inaccuracy) + (ii - (int)(shots / 2f)) * spread);
|
bullet(peekAmmo(), rotation + Mathf.range(inaccuracy + peekAmmo().inaccuracy) + (ii - (int)(shots / 2f)) * spread);
|
||||||
effects();
|
|
||||||
useAmmo();
|
useAmmo();
|
||||||
recoil = recoilAmount;
|
recoil = recoilAmount;
|
||||||
heat = 1f;
|
heat = 1f;
|
||||||
@@ -544,7 +542,6 @@ public class Turret extends ReloadTurret{
|
|||||||
bulletOffset.trns(rotation - 90, (spread) * i + Mathf.range(xRand), shootLength);
|
bulletOffset.trns(rotation - 90, (spread) * i + Mathf.range(xRand), shootLength);
|
||||||
bullet(type, rotation + Mathf.range(inaccuracy + type.inaccuracy));
|
bullet(type, rotation + Mathf.range(inaccuracy + type.inaccuracy));
|
||||||
shotCounter ++;
|
shotCounter ++;
|
||||||
effects();
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
bulletOffset.trns(rotation, shootLength, Mathf.range(xRand));
|
bulletOffset.trns(rotation, shootLength, Mathf.range(xRand));
|
||||||
@@ -553,7 +550,6 @@ public class Turret extends ReloadTurret{
|
|||||||
bullet(type, rotation + Mathf.range(inaccuracy + type.inaccuracy) + (i - (int)(shots / 2f)) * spread);
|
bullet(type, rotation + Mathf.range(inaccuracy + type.inaccuracy) + (i - (int)(shots / 2f)) * spread);
|
||||||
shotCounter ++;
|
shotCounter ++;
|
||||||
}
|
}
|
||||||
effects();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
recoil = recoilAmount;
|
recoil = recoilAmount;
|
||||||
@@ -563,9 +559,10 @@ public class Turret extends ReloadTurret{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void bullet(BulletType type, float angle){
|
protected void bullet(BulletType type, float angle){
|
||||||
float lifeScl = type.scaleVelocity ? Mathf.clamp(Mathf.dst(x + bulletOffset.x, y + bulletOffset.y, targetPos.x, targetPos.y) / type.range(), minRange / type.range(), range() / type.range()) : 1f;
|
float lifeScl = type.scaleVelocity ? Mathf.clamp(Mathf.dst(x + bulletOffset.x, y + bulletOffset.y, targetPos.x, targetPos.y) / type.range, minRange / type.range, range() / type.range) : 1f;
|
||||||
|
|
||||||
type.create(this, team, x + bulletOffset.x, y + bulletOffset.y, angle, 1f + Mathf.range(velocityInaccuracy), lifeScl);
|
type.create(this, team, x + bulletOffset.x, y + bulletOffset.y, angle, 1f + Mathf.range(velocityInaccuracy), lifeScl);
|
||||||
|
effects();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void effects(){
|
protected void effects(){
|
||||||
|
|||||||
Reference in New Issue
Block a user