T4/5 support mechs

This commit is contained in:
Anuken
2020-09-21 23:32:30 -04:00
parent 1d8f837fb1
commit 87032c82b1
43 changed files with 5652 additions and 4913 deletions

View File

@@ -77,8 +77,7 @@ public class Damage{
}
}
/** Collides a bullet with blocks in a laser, taking into account absorption blocks. Resulting length is stored in the bullet's fdata. */
public static float collideLaser(Bullet b, float length){
public static float findLaserLength(Bullet b, float length){
Tmp.v1.trns(b.rotation(), length);
furthest = null;
@@ -86,9 +85,15 @@ public class Damage{
world.raycast(b.tileX(), b.tileY(), world.toTile(b.x + Tmp.v1.x), world.toTile(b.y + Tmp.v1.y),
(x, y) -> (furthest = world.tile(x, y)) != null && furthest.team() != b.team && furthest.block().absorbLasers);
float resultLength = furthest != null ? Math.max(6f, b.dst(furthest.worldx(), furthest.worldy())) : length;
return furthest != null ? Math.max(6f, b.dst(furthest.worldx(), furthest.worldy())) : length;
}
/** Collides a bullet with blocks in a laser, taking into account absorption blocks. Resulting length is stored in the bullet's fdata. */
public static float collideLaser(Bullet b, float length, boolean large){
float resultLength = findLaserLength(b, length);
collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), resultLength, large);
Damage.collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), resultLength);
b.fdata = furthest != null ? resultLength : length;
return resultLength;
@@ -103,6 +108,8 @@ public class Damage{
* Only enemies of the specified team are damaged.
*/
public static void collideLine(Bullet hitter, Team team, Effect effect, float x, float y, float angle, float length, boolean large){
length = findLaserLength(hitter, length);
collidedBlocks.clear();
tr.trns(angle, length);
Intc2 collider = (cx, cy) -> {

View File

@@ -96,7 +96,7 @@ public abstract class BulletType extends Content{
public Color lightningColor = Pal.surge;
public int lightning;
public int lightningLength = 5;
public int lightningLength = 5, lightningLengthRand = 0;
/** Use a negative value to use default bullet damage. */
public float lightningDamage = -1;
@@ -179,7 +179,7 @@ public abstract class BulletType extends Content{
}
for(int i = 0; i < lightning; i++){
Lightning.create(b, lightningColor, lightningDamage < 0 ? damage : lightningDamage, b.x, b.y, Mathf.random(360f), lightningLength);
Lightning.create(b, lightningColor, lightningDamage < 0 ? damage : lightningDamage, b.x, b.y, Mathf.random(360f), lightningLength + Mathf.random(lightningLengthRand));
}
}

View File

@@ -12,10 +12,13 @@ import mindustry.graphics.*;
public class ContinuousLaserBulletType extends BulletType{
public float length = 220f;
public float shake = 1f;
public float fadeTime = 16f;
public Color[] colors = {Color.valueOf("ec745855"), Color.valueOf("ec7458aa"), Color.valueOf("ff9c5a"), Color.white};
public float[] tscales = {1f, 0.7f, 0.5f, 0.2f};
public float[] strokes = {2f, 1.5f, 1f, 0.3f};
public float[] lenscales = {1f, 1.12f, 1.15f, 1.17f};
public float width = 9f, oscScl = 0.8f, oscMag = 1.5f;
public boolean largeHit = true;
public ContinuousLaserBulletType(float damage){
super(0.001f, damage);
@@ -25,6 +28,7 @@ public class ContinuousLaserBulletType extends BulletType{
hitSize = 4;
drawSize = 420f;
lifetime = 16f;
keepVelocity = false;
pierce = true;
hittable = false;
hitColor = colors[2];
@@ -32,6 +36,7 @@ public class ContinuousLaserBulletType extends BulletType{
incendAmount = 1;
incendSpread = 5;
incendChance = 0.4f;
lightColor = Color.orange;
}
protected ContinuousLaserBulletType(){
@@ -43,13 +48,20 @@ public class ContinuousLaserBulletType extends BulletType{
return length;
}
@Override
public void init(){
super.init();
drawSize = Math.max(drawSize, length*2f);
}
@Override
public void update(Bullet b){
//TODO possible laser absorption from blocks
//damage every 5 ticks
if(b.timer(1, 5f)){
Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), length, true);
Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), length, largeHit);
}
if(shake > 0){
@@ -59,21 +71,23 @@ public class ContinuousLaserBulletType extends BulletType{
@Override
public void draw(Bullet b){
float baseLen = length * b.fout();
float realLength = Damage.findLaserLength(b, length);
float fout = Mathf.clamp(b.time > b.lifetime - fadeTime ? 1f - (b.time - (lifetime - fadeTime)) / fadeTime : 1f);
float baseLen = realLength * fout;
Lines.lineAngle(b.x, b.y, b.rotation(), baseLen);
for(int s = 0; s < colors.length; s++){
Draw.color(Tmp.c1.set(colors[s]).mul(1f + Mathf.absin(Time.time(), 1f, 0.1f)));
for(int i = 0; i < tscales.length; i++){
Tmp.v1.trns(b.rotation() + 180f, (lenscales[i] - 1f) * 35f);
Lines.stroke((9f + Mathf.absin(Time.time(), 0.8f, 1.5f)) * b.fout() * strokes[s] * tscales[i]);
Lines.stroke((width + Mathf.absin(Time.time(), oscScl, oscMag)) * fout * strokes[s] * tscales[i]);
Lines.lineAngle(b.x + Tmp.v1.x, b.y + Tmp.v1.y, b.rotation(), baseLen * lenscales[i], false);
}
}
Tmp.v1.trns(b.rotation(), baseLen * 1.1f);
Drawf.light(b.team, b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, 40, Color.orange, 0.7f);
Drawf.light(b.team, b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, 40, lightColor, 0.7f);
Draw.reset();
}

View File

@@ -8,18 +8,17 @@ import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.world.*;
public class LaserBulletType extends BulletType{
protected static Tile furthest;
protected Color[] colors = {Pal.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Pal.lancerLaser, Color.white};
protected Effect laserEffect = Fx.lancerLaserShootSmoke;
protected float length = 160f;
protected float width = 15f;
protected float lengthFalloff = 0.5f;
protected float sideLength = 29f, sideWidth = 0.7f;
protected float sideAngle = 90f;
public Color[] colors = {Pal.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Pal.lancerLaser, Color.white};
public Effect laserEffect = Fx.lancerLaserShootSmoke;
public float length = 160f;
public float width = 15f;
public float lengthFalloff = 0.5f;
public float sideLength = 29f, sideWidth = 0.7f;
public float sideAngle = 90f;
public float lightningSpacing = -1, lightningDelay = 0.1f, lightningAngleRand;
public boolean largeHit = false;
public LaserBulletType(float damage){
super(0.01f, damage);
@@ -40,6 +39,13 @@ public class LaserBulletType extends BulletType{
this(1f);
}
@Override
public void init(){
super.init();
drawSize = Math.max(drawSize, length*2f);
}
@Override
public float range(){
return length;
@@ -47,8 +53,28 @@ public class LaserBulletType extends BulletType{
@Override
public void init(Bullet b){
float resultLength = Damage.collideLaser(b, length);
laserEffect.at(b.x, b.y, b.rotation(), resultLength * 0.75f);
float resultLength = Damage.collideLaser(b, length, largeHit), rot = b.rotation();
laserEffect.at(b.x, b.y, rot, resultLength * 0.75f);
if(lightningSpacing > 0){
int idx = 0;
for(float i = 0; i <= resultLength; i += lightningSpacing){
float cx = b.x + Angles.trnsx(rot, i),
cy = b.y + Angles.trnsy(rot, i);
int f = idx++;
for(int s : Mathf.signs){
Time.run(f * lightningDelay, () ->
Lightning.create(b, lightningColor,
lightningDamage < 0 ? damage : lightningDamage,
cx, cy, rot + 90*s + Mathf.range(lightningAngleRand),
lightningLength + Mathf.random(lightningLengthRand))
);
}
}
}
}
@Override

View File

@@ -13,6 +13,7 @@ public class ShrapnelBulletType extends BulletType{
public float length = 100f;
public float width = 20f;
public Color fromColor = Color.white, toColor = Pal.lancerLaser;
public boolean hitLarge = false;
public int serrations = 7;
public float serrationLenScl = 10f, serrationWidth = 4f, serrationSpacing = 8f, serrationSpaceOffset = 80f, serrationFadeOffset = 0.5f;
@@ -30,7 +31,14 @@ public class ShrapnelBulletType extends BulletType{
@Override
public void init(Bullet b){
Damage.collideLaser(b, length);
Damage.collideLaser(b, length, hitLarge);
}
@Override
public void init(){
super.init();
drawSize = Math.max(drawSize, length*2f);
}
@Override

View File

@@ -150,7 +150,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
}
public void lookAt(float angle){
rotation = Angles.moveToward(rotation, angle, type.rotateSpeed * Time.delta);
rotation = Angles.moveToward(rotation, angle, type.rotateSpeed * Time.delta * speedMultiplier());
}
public void lookAt(Position pos){

View File

@@ -13,7 +13,7 @@ import mindustry.type.*;
import static mindustry.Vars.*;
@Component
abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc, Statusc{
@Import float x, y, rotation, reloadMultiplier;
@Import Vec2 vel;
@Import UnitType type;
@@ -93,7 +93,27 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
for(WeaponMount mount : mounts){
Weapon weapon = mount.weapon;
mount.reload = Math.max(mount.reload - Time.delta * reloadMultiplier, 0);
mount.heat = Math.max(mount.heat - Time.delta * reloadMultiplier / mount.weapon.cooldownTime, 0);
float weaponRotation = this.rotation - 90 + (weapon.rotate ? mount.rotation : 0);
float mountX = this.x + Angles.trnsx(this.rotation - 90, weapon.x, weapon.y),
mountY = this.y + Angles.trnsy(this.rotation - 90, weapon.x, weapon.y);
float shootX = mountX + Angles.trnsx(weaponRotation, weapon.shootX, weapon.shootY),
shootY = mountY + Angles.trnsy(weaponRotation, weapon.shootX, weapon.shootY);
float shootAngle = weapon.rotate ? weaponRotation + 90 : Angles.angle(shootX, shootY, mount.aimX, mount.aimY) + (this.rotation - angleTo(mount.aimX, mount.aimY));
//update continuous state
if(weapon.continuous && mount.bullet != null){
if(!mount.bullet.isAdded() || mount.bullet.time >= mount.bullet.lifetime){
mount.bullet = null;
}else{
mount.bullet.rotation(shootAngle);
mount.bullet.set(shootX, shootY);
vel.add(Tmp.v1.trns(rotation + 180f, mount.bullet.type.recoil));
}
}else{
//heat decreases when not firing
mount.heat = Math.max(mount.heat - Time.delta * reloadMultiplier / mount.weapon.cooldownTime, 0);
}
//flip weapon shoot side for alternating weapons at half reload
if(weapon.otherSide != -1 && weapon.alternate && mount.side == weapon.flipSprite &&
@@ -104,10 +124,10 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
//rotate if applicable
if(weapon.rotate && (mount.rotate || mount.shoot) && can){
float axisX = this.x + Angles.trnsx(rotation - 90, weapon.x, weapon.y),
axisY = this.y + Angles.trnsy(rotation - 90, weapon.x, weapon.y);
float axisX = this.x + Angles.trnsx(this.rotation - 90, weapon.x, weapon.y),
axisY = this.y + Angles.trnsy(this.rotation - 90, weapon.x, weapon.y);
mount.targetRotation = Angles.angle(axisX, axisY, mount.aimX, mount.aimY) - rotation;
mount.targetRotation = Angles.angle(axisX, axisY, mount.aimX, mount.aimY) - this.rotation;
mount.rotation = Angles.moveToward(mount.rotation, mount.targetRotation, weapon.rotateSpeed * Time.delta);
}else if(!weapon.rotate){
mount.rotation = 0;
@@ -124,21 +144,9 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
mount.reload <= 0.0001f && //reload has to be 0
Angles.within(weapon.rotate ? mount.rotation : this.rotation, mount.targetRotation, mount.weapon.shootCone) //has to be within the cone
){
float rotation = this.rotation - 90;
float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0);
float mountX = this.x + Angles.trnsx(rotation, weapon.x, weapon.y),
mountY = this.y + Angles.trnsy(rotation, weapon.x, weapon.y);
float shootX = mountX + Angles.trnsx(weaponRotation, weapon.shootX, weapon.shootY),
shootY = mountY + Angles.trnsy(weaponRotation, weapon.shootX, weapon.shootY);
float shootAngle = weapon.rotate ? weaponRotation + 90 : Angles.angle(shootX, shootY, mount.aimX, mount.aimY) + (this.rotation - angleTo(mount.aimX, mount.aimY));
shoot(weapon, shootX, shootY, mount.aimX, mount.aimY, shootAngle, Mathf.sign(weapon.x));
shoot(mount, shootX, shootY, mount.aimX, mount.aimY, shootAngle, Mathf.sign(weapon.x));
mount.reload = weapon.reload;
mount.heat = 1f;
ammo--;
if(ammo < 0) ammo = 0;
@@ -146,7 +154,8 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
}
}
private void shoot(Weapon weapon, float x, float y, float aimX, float aimY, float rotation, int side){
private void shoot(WeaponMount mount, float x, float y, float aimX, float aimY, float rotation, int side){
Weapon weapon = mount.weapon;
float baseX = this.x, baseY = this.y;
@@ -156,29 +165,39 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
float lifeScl = ammo.scaleVelocity ? Mathf.clamp(Mathf.dst(x, y, aimX, aimY) / ammo.range()) : 1f;
sequenceNum = 0;
if(weapon.shotDelay > 0.01f){
if(weapon.shotDelay + weapon.firstShotDelay > 0.01f){
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> {
Time.run(sequenceNum * weapon.shotDelay, () -> bullet(weapon, x + this.x - baseX, y + this.y - baseY, f + Mathf.range(weapon.inaccuracy), lifeScl));
Time.run(sequenceNum * weapon.shotDelay + weapon.firstShotDelay, () -> mount.bullet = bullet(weapon, x + this.x - baseX, y + this.y - baseY, f + Mathf.range(weapon.inaccuracy), lifeScl));
sequenceNum++;
});
}else{
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> bullet(weapon, x, y, f + Mathf.range(weapon.inaccuracy), lifeScl));
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> mount.bullet = bullet(weapon, x, y, f + Mathf.range(weapon.inaccuracy), lifeScl));
}
vel().add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
boolean parentize = ammo.keepVelocity;
Effect.shake(weapon.shake, weapon.shake, x, y);
if(weapon.firstShotDelay > 0){
Time.run(weapon.firstShotDelay, () -> {
vel.add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
Effect.shake(weapon.shake, weapon.shake, x, y);
mount.heat = 1f;
});
}else{
vel.add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
Effect.shake(weapon.shake, weapon.shake, x, y);
mount.heat = 1f;
}
weapon.ejectEffect.at(x, y, rotation * side);
ammo.shootEffect.at(x, y, rotation, parentize ? this : null);
ammo.smokeEffect.at(x, y, rotation, parentize ? this : null);
apply(weapon.shootStatus, weapon.shootStatusDuration);
}
private void bullet(Weapon weapon, float x, float y, float angle, float lifescl){
private Bullet bullet(Weapon weapon, float x, float y, float angle, float lifescl){
float xr = Mathf.range(weapon.xRand);
weapon.bullet.create(this, team(),
return weapon.bullet.create(this, team(),
x + Angles.trnsx(angle, 0, xr),
y + Angles.trnsy(angle, 0, xr),
angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd), lifescl);

View File

@@ -1,5 +1,7 @@
package mindustry.entities.units;
import arc.util.ArcAnnotate.*;
import mindustry.gen.*;
import mindustry.type.*;
public class WeaponMount{
@@ -21,6 +23,8 @@ public class WeaponMount{
public boolean rotate = false;
/** extra state for alternating weapons */
public boolean side;
/** current bullet for continuous weapons */
public @Nullable Bullet bullet;
public WeaponMount(Weapon weapon){
this.weapon = weapon;