T4/5 support mechs
@ -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
|
@ -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}]}
|
@ -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}]}
|
BIN
core/assets-raw/sprites/units/corvus-cell.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
core/assets-raw/sprites/units/corvus-foot.png
Normal file
After Width: | Height: | Size: 720 B |
BIN
core/assets-raw/sprites/units/corvus-joint-base.png
Normal file
After Width: | Height: | Size: 617 B |
BIN
core/assets-raw/sprites/units/corvus-joint.png
Normal file
After Width: | Height: | Size: 550 B |
BIN
core/assets-raw/sprites/units/corvus-leg-base.png
Normal file
After Width: | Height: | Size: 350 B |
BIN
core/assets-raw/sprites/units/corvus-leg.png
Normal file
After Width: | Height: | Size: 486 B |
BIN
core/assets-raw/sprites/units/corvus-weapon-heat.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
core/assets-raw/sprites/units/corvus.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
core/assets-raw/sprites/units/vela-base.png
Normal file
After Width: | Height: | Size: 600 B |
BIN
core/assets-raw/sprites/units/vela-cell.png
Normal file
After Width: | Height: | Size: 748 B |
BIN
core/assets-raw/sprites/units/vela-leg.png
Normal file
After Width: | Height: | Size: 740 B |
BIN
core/assets-raw/sprites/units/vela-weapon-heat.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
core/assets-raw/sprites/units/vela.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 557 KiB After Width: | Height: | Size: 554 KiB |
Before Width: | Height: | Size: 661 KiB After Width: | Height: | Size: 664 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 942 KiB |
Before Width: | Height: | Size: 322 KiB After Width: | Height: | Size: 506 KiB |
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 185 KiB |
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 2.8 MiB |
Before Width: | Height: | Size: 187 KiB After Width: | Height: | Size: 186 KiB |
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
@ -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}
|
||||
};
|
||||
}};
|
||||
|
||||
|
@ -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) -> {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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) -> {
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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){
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|