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

@ -3,6 +3,7 @@
alpha=0
atrax=1
block=2
corvus=24
flare=3
mace=4
mega=5
@ -23,4 +24,5 @@ poly=18
pulsar=19
quad=23
risso=20
spiroct=21
spiroct=21
vela=25

View File

@ -0,0 +1 @@
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@ -0,0 +1 @@
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -316,3 +316,5 @@
63428=sei|unit-sei-medium
63427=quad|unit-quad-medium
63426=oct|unit-oct-medium
63425=vela|unit-vela-medium
63424=corvus|unit-corvus-medium

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 557 KiB

After

Width:  |  Height:  |  Size: 554 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 661 KiB

After

Width:  |  Height:  |  Size: 664 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 942 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 322 KiB

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@ -1806,6 +1806,7 @@ public class Blocks implements ContentList{
{UnitTypes.fortress, UnitTypes.scepter},
{UnitTypes.bryde, UnitTypes.sei},
{UnitTypes.mega, UnitTypes.quad},
{UnitTypes.quasar, UnitTypes.vela},
};
}};
@ -1825,7 +1826,8 @@ public class Blocks implements ContentList{
{UnitTypes.arkyid, UnitTypes.toxopid},
{UnitTypes.scepter, UnitTypes.reign},
{UnitTypes.sei, UnitTypes.omura},
{UnitTypes.quad, UnitTypes.oct}
{UnitTypes.quad, UnitTypes.oct},
{UnitTypes.vela, UnitTypes.corvus}
};
}};

View File

@ -145,7 +145,7 @@ public class Fx{
int i = 0;
for(Vec2 p : lines){
Fill.square(p.x, p.y, (5f - (float)i++ / lines.size * 2f) * e.fout(), 45);
Fill.circle(p.x, p.y, Lines.getStroke() / 2f);
}
}),
@ -290,7 +290,7 @@ public class Fx{
Lines.spikes(e.x, e.y, 1f + e.fin() * 6f, e.fout() * 4f, 6);
}),
healBomb = new Effect(40f, 100f, e -> {
greenBomb = new Effect(40f, 100f, e -> {
color(Pal.heal);
stroke(e.fout() * 2f);
Lines.circle(e.x, e.y, 4f + e.finpow() * 65f);
@ -306,6 +306,28 @@ public class Fx{
}
}),
greenLaserCharge = new Effect(80f, 100f, e -> {
color(Pal.heal);
stroke(e.fin() * 2f);
Lines.circle(e.x, e.y, 4f + e.fout() * 100f);
Fill.circle(e.x, e.y, e.fin() * 20);
randLenVectors(e.id, 20, 40f * e.fout(), (x, y) -> {
Fill.circle(e.x + x, e.y + y, e.fin() * 5f);
});
color();
Fill.circle(e.x, e.y, e.fin() * 10);
}),
greenLaserChargeSmall = new Effect(40f, 100f, e -> {
color(Pal.heal);
stroke(e.fin() * 2f);
Lines.circle(e.x, e.y, e.fout() * 50f);
}),
healWaveDynamic = new Effect(22, e -> {
color(Pal.heal);
stroke(e.fout() * 2f);
@ -422,6 +444,17 @@ public class Fx{
}),
hitMeltHeal = new Effect(12, e -> {
color(Pal.heal);
stroke(e.fout() * 2f);
randLenVectors(e.id, 6, e.finpow() * 18f, e.rotation, 360f, (x, y) -> {
float ang = Mathf.angle(x, y);
lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1f);
});
}),
hitLaser = new Effect(8, e -> {
color(Color.white, Pal.heal, e.fin());
stroke(0.5f + e.fout());
@ -1251,6 +1284,14 @@ public class Fx{
Fill.square(e.x + x, e.y + y, 1f + e.fout() * 3f, 45);
});
}),
smokeCloud = new Effect(70, e -> {
randLenVectors(e.id, e.fin(), 30, 30f, (x, y, fin, fout) -> {
color(Color.gray);
alpha((0.5f - Math.abs(fin - 0.5f)) * 2f);
Fill.circle(e.x + x, e.y + y, 0.5f + fout * 4f);
});
}),
smeltsmoke = new Effect(15, e -> {
randLenVectors(e.id, 6, 4f + e.fin() * 5f, (x, y) -> {

View File

@ -9,7 +9,7 @@ import mindustry.type.StatusEffect;
import static mindustry.Vars.*;
public class StatusEffects implements ContentList{
public static StatusEffect none, burning, freezing, wet, muddy, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, corroded, boss, sporeSlowed;
public static StatusEffect none, burning, freezing, unmoving, slow, wet, muddy, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, corroded, boss, sporeSlowed;
@Override
public void load(){
@ -45,6 +45,14 @@ public class StatusEffects implements ContentList{
});
}};
unmoving = new StatusEffect("unmoving"){{
speedMultiplier = 0.001f;
}};
slow = new StatusEffect("slow"){{
speedMultiplier = 0.4f;
}};
wet = new StatusEffect("wet"){{
color = Color.royal;
speedMultiplier = 0.94f;

View File

@ -14,12 +14,18 @@ import mindustry.type.*;
public class UnitTypes implements ContentList{
//region definitions
//ground
//mech
public static @EntityDef({Unitc.class, Mechc.class}) UnitType mace, dagger, crawler, fortress, scepter, reign;
//ground + builder + miner + commander
//mech + builder + miner + commander
public static @EntityDef({Unitc.class, Mechc.class, Builderc.class, Minerc.class, Commanderc.class}) UnitType nova, pulsar, quasar;
//mech + commander
public static @EntityDef({Unitc.class, Mechc.class, Commanderc.class}) UnitType vela;
//legs + commander
public static @EntityDef({Unitc.class, Legsc.class, Commanderc.class}) UnitType corvus;
//legs
public static @EntityDef({Unitc.class, Legsc.class}) UnitType atrax;
@ -365,6 +371,134 @@ public class UnitTypes implements ContentList{
}});
}};
vela = new UnitType("vela"){{
hitsize = 23f;
rotateSpeed = 1.6f;
canDrown = false;
mechFrontSway = 1f;
mechStepParticles = true;
mechStepShake = 0.15f;
speed = 0.35f;
boostMultiplier = 1.5f;
engineOffset = 12f;
engineSize = 6f;
health = 6000f;
armor = 7f;
canBoost = true;
landShake = 4f;
commandLimit = 32;
weapons.add(new Weapon("vela-weapon"){{
mirror = false;
top = false;
shake = 4f;
shootY = 13f;
x = y = 0f;
firstShotDelay = Fx.greenLaserChargeSmall.lifetime - 1f;
reload = 320f;
recoil = 0f;
shootSound = Sounds.laser;
continuous = true;
cooldownTime = 200f;
bullet = new ContinuousLaserBulletType(16){{
length = 150f;
hitEffect = Fx.hitMeltHeal;
drawSize = 420f;
lifetime = 160f;
shake = 1f;
despawnEffect = Fx.smokeCloud;
smokeEffect = Fx.none;
shootEffect = Fx.greenLaserChargeSmall;
incendChance = 0.02f;
incendSpread = 5f;
incendAmount = 1;
colors = new Color[]{Pal.heal.cpy().a(.2f), Pal.heal.cpy().a(.5f), Pal.heal.cpy().mul(1.2f), Color.white};
}};
shootStatus = StatusEffects.slow;
shootStatusDuration = bullet.lifetime + firstShotDelay;
}});
}};
corvus = new UnitType("corvus"){{
mineTier = 1;
hitsize = 29f;
itemCapacity = 80;
health = 19000f;
buildSpeed = 1.7f;
armor = 9f;
landShake = 1.5f;
commandLimit = 24;
legCount = 4;
legLength = 14f;
legBaseOffset = 10f;
legMoveSpace = 1.5f;
legTrns = 0.58f;
hovering = true;
visualElevation = 0.2f;
allowLegStep = true;
speed = 0.3f;
mineTier = 2;
mineSpeed = 7f;
drawShields = false;
weapons.add(new Weapon("corvus-weapon"){{
top = false;
mirror = false;
shake = 14f;
shootY = 5f;
x = y = 0;
reload = 350f;
recoil = 0f;
shootSound = Sounds.laser;
cooldownTime = 350f;
shootStatusDuration = 60f * 2f;
shootStatus = StatusEffects.unmoving;
firstShotDelay = Fx.greenLaserCharge.lifetime;
bullet = new LaserBulletType(){{
length = 500f;
damage = 520f;
width = 75f;
lifetime = 65f;
lightningSpacing = 35f;
lightningLength = 5;
lightningDelay = 1.1f;
lightningLengthRand = 15;
lightningDamage = 50;
lightningAngleRand = 40f;
largeHit = true;
lightColor = lightningColor = Pal.heal;
shootEffect = Fx.greenLaserCharge;
sideAngle = 15f;
sideWidth = 0f;
sideLength = 0f;
colors = new Color[]{Pal.heal.cpy().a(0.4f), Pal.heal, Color.white};
}};
}});
}};
//endregion
//region ground legs
@ -405,6 +539,7 @@ public class UnitTypes implements ContentList{
targetAir = false;
health = 600;
immunities = ObjectSet.with(StatusEffects.burning, StatusEffects.melting);
legCount = 4;
legLength = 9f;
legTrns = 0.6f;
@ -603,8 +738,8 @@ public class UnitTypes implements ContentList{
drag = 0.1f;
speed = 0.5f;
hitsize = 21f;
health = 23000;
armor = 14f;
health = 22000;
armor = 13f;
rotateSpeed = 1.9f;
@ -1121,7 +1256,7 @@ public class UnitTypes implements ContentList{
lifetime = 70f;
despawnEffect = Fx.healBomb;
despawnEffect = Fx.greenBomb;
hitEffect = Fx.massiveExplosion;
keepVelocity = false;
spin = 2f;
@ -1139,7 +1274,7 @@ public class UnitTypes implements ContentList{
oct = new UnitType("oct"){{
armor = 16f;
health = 23000;
health = 24000;
speed = 0.6f;
rotateSpeed = 1f;
accel = 0.04f;
@ -1149,10 +1284,11 @@ public class UnitTypes implements ContentList{
engineSize = 7.8f;
rotateShooting = false;
hitsize = 60f;
payloadCapacity = (4.5f * 4.5f) * (8 * 8);
buildSpeed = 3.5f;
payloadCapacity = (5.2f * 5.2f) * (8 * 8);
buildSpeed = 4f;
drawShields = false;
abilities.add(new ForceFieldAbility(140f, 4f, 6000f, 60f * 8), new HealFieldAbility(130f, 60f * 2, 140f));
abilities.add(new ForceFieldAbility(140f, 4f, 7000f, 60f * 8), new HealFieldAbility(130f, 60f * 2, 140f));
}};
//endregion

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;

View File

@ -135,7 +135,7 @@ public class UnitType extends UnlockableContent{
public void update(Unit unit){
if(unit instanceof Mechc){
if(unit instanceof Mechc && !unit.isFlying()){
updateMechEffects(unit);
}
}
@ -526,7 +526,6 @@ public class UnitType extends UnlockableContent{
float rotation = unit.rotation - 90;
float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0);
float width = weapon.region.width;
float recoil = -((mount.reload) / weapon.reload * weapon.recoil);
float wx = unit.x + Angles.trnsx(rotation, weapon.x, weapon.y) + Angles.trnsx(weaponRotation, 0, recoil),
wy = unit.y + Angles.trnsy(rotation, weapon.x, weapon.y) + Angles.trnsy(weaponRotation, 0, recoil);
@ -541,17 +540,16 @@ public class UnitType extends UnlockableContent{
Draw.rect(weapon.outlineRegion,
wx, wy,
width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.outlineRegion.width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.region.height * Draw.scl,
weaponRotation);
Draw.z(z);
}
Draw.rect(weapon.region,
wx, wy,
width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.region.width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.region.height * Draw.scl,
weaponRotation);
@ -560,8 +558,8 @@ public class UnitType extends UnlockableContent{
Draw.blend(Blending.additive);
Draw.rect(weapon.heatRegion,
wx, wy,
width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.region.height * Draw.scl,
weapon.heatRegion.width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.heatRegion.height * Draw.scl,
weaponRotation);
Draw.blend();
Draw.color();

View File

@ -29,6 +29,8 @@ public class Weapon{
public boolean rotate = false;
/** whether to draw the outline on top. */
public boolean top = true;
/** whether to hold the bullet in place while firing */
public boolean continuous;
/** rotation speed of weapon when rotation is enabled, in degrees/t*/
public float rotateSpeed = 20f;
/** weapon reload in frames */
@ -54,6 +56,8 @@ public class Weapon{
/** fraction of velocity that is random */
public float velocityRnd = 0f;
/** delay in ticks between shots */
public float firstShotDelay = 0;
/** delay in ticks between shots */
public float shotDelay = 0;
/** The half-radius of the cone in which shooting will start. */
public float shootCone = 5f;
@ -77,6 +81,10 @@ public class Weapon{
public TextureRegion outlineRegion;
/** heat region tint */
public Color heatColor = Pal.turretHeat;
/** status effect applied when shooting */
public StatusEffect shootStatus = StatusEffects.none;
/** status effect duration when shot */
public float shootStatusDuration = 60f * 5f;
public Weapon(String name){
this.name = name;

View File

@ -56,7 +56,7 @@ public class DatabaseDialog extends BaseDialog{
for(int i = 0; i < array.size; i++){
UnlockableContent unlock = (UnlockableContent)array.get(i);
Image image = unlocked(unlock) ? new Image(unlock.icon(Cicon.medium)).setScaling(Scaling.bounded) : new Image(Icon.lock, Pal.gray);
Image image = unlocked(unlock) ? new Image(unlock.icon(Cicon.medium)).setScaling(Scaling.fit) : new Image(Icon.lock, Pal.gray);
list.add(image).size(8*4).pad(3);
ClickListener listener = new ClickListener();
image.addListener(listener);