WIP Disrupt missiles
This commit is contained in:
Binary file not shown.
BIN
core/assets-raw/sprites/units/weapons/disrupt-missile.png
Normal file
BIN
core/assets-raw/sprites/units/weapons/disrupt-missile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 502 B |
BIN
core/assets-raw/sprites/units/weapons/disrupt-weapon-blade.png
Normal file
BIN
core/assets-raw/sprites/units/weapons/disrupt-weapon-blade.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 886 B |
BIN
core/assets-raw/sprites/units/weapons/disrupt-weapon.png
Normal file
BIN
core/assets-raw/sprites/units/weapons/disrupt-weapon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 815 B |
Binary file not shown.
|
Before Width: | Height: | Size: 839 B After Width: | Height: | Size: 844 B |
@@ -520,3 +520,4 @@
|
|||||||
63183=conquer|unit-conquer-ui
|
63183=conquer|unit-conquer-ui
|
||||||
63182=disrupt|unit-disrupt-ui
|
63182=disrupt|unit-disrupt-ui
|
||||||
63181=krepost|unit-krepost-ui
|
63181=krepost|unit-krepost-ui
|
||||||
|
63180=disrupt-missile|unit-disrupt-missile-ui
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
package mindustry.ai.types;
|
package mindustry.ai.types;
|
||||||
|
|
||||||
|
import arc.util.*;
|
||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
public class MissileAI extends AIController{
|
public class MissileAI extends AIController{
|
||||||
//TODO store 'main' target and use that as a fallback
|
public @Nullable Unit shooter;
|
||||||
|
|
||||||
//TODO UNPREDICTABLE TARGETING
|
|
||||||
@Override
|
@Override
|
||||||
public void updateMovement(){
|
public void updateMovement(){
|
||||||
unloadPayloads();
|
unloadPayloads();
|
||||||
|
|
||||||
if(target != null){
|
float time = unit instanceof TimedKillc t ? t.time() : 1000000f;
|
||||||
unit.lookAt(target);
|
|
||||||
|
if(time >= unit.type.homingDelay && shooter != null){
|
||||||
|
unit.lookAt(shooter.aimX, shooter.aimY);
|
||||||
}
|
}
|
||||||
|
|
||||||
//move forward forever
|
//move forward forever
|
||||||
@@ -26,8 +29,7 @@ public class MissileAI extends AIController{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean retarget(){
|
public void updateTargeting(){
|
||||||
//more frequent retarget. TODO won't this lag?
|
//no
|
||||||
return timer.get(timerTarget, 10f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2529,7 +2529,7 @@ public class Blocks{
|
|||||||
thrusterLength = 40/4f;
|
thrusterLength = 40/4f;
|
||||||
armor = 10f;
|
armor = 10f;
|
||||||
|
|
||||||
unitCapModifier = 12;
|
unitCapModifier = 10;
|
||||||
researchCostMultiplier = 0.11f;
|
researchCostMultiplier = 0.11f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -2544,7 +2544,7 @@ public class Blocks{
|
|||||||
thrusterLength = 48/4f;
|
thrusterLength = 48/4f;
|
||||||
armor = 15f;
|
armor = 15f;
|
||||||
|
|
||||||
unitCapModifier = 16;
|
unitCapModifier = 14;
|
||||||
researchCostMultiplier = 0.11f;
|
researchCostMultiplier = 0.11f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import mindustry.entities.abilities.*;
|
|||||||
import mindustry.entities.bullet.*;
|
import mindustry.entities.bullet.*;
|
||||||
import mindustry.entities.effect.*;
|
import mindustry.entities.effect.*;
|
||||||
import mindustry.entities.part.*;
|
import mindustry.entities.part.*;
|
||||||
import mindustry.entities.units.*;
|
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
@@ -2503,7 +2502,7 @@ public class UnitTypes{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
conquer = new TankUnitType("conquer"){{
|
conquer = new TankUnitType("conquer"){{
|
||||||
hitSize = 44f;
|
hitSize = 46f;
|
||||||
treadPullOffset = 1;
|
treadPullOffset = 1;
|
||||||
speed = 0.48f;
|
speed = 0.48f;
|
||||||
health = 20000;
|
health = 20000;
|
||||||
@@ -2664,7 +2663,12 @@ public class UnitTypes{
|
|||||||
}};
|
}};
|
||||||
}});
|
}});
|
||||||
|
|
||||||
decals.add(new UnitDecal("conquer-glow", Color.red, Blending.additive, -1f));
|
parts.add(new RegionPart("-glow"){{
|
||||||
|
color = Color.red;
|
||||||
|
blending = Blending.additive;
|
||||||
|
layer = -1f;
|
||||||
|
outline = false;
|
||||||
|
}});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -2919,13 +2923,8 @@ public class UnitTypes{
|
|||||||
mirror = false;
|
mirror = false;
|
||||||
reload = 1f;
|
reload = 1f;
|
||||||
shootOnDeath = true;
|
shootOnDeath = true;
|
||||||
bullet = new BulletType(){{
|
bullet = new ExplosionBulletType(120f, 30f){{
|
||||||
rangeOverride = 20f;
|
|
||||||
shootEffect = Fx.massiveExplosion;
|
shootEffect = Fx.massiveExplosion;
|
||||||
killShooter = true;
|
|
||||||
//TODO status?
|
|
||||||
splashDamageRadius = 30f;
|
|
||||||
splashDamage = 120f;
|
|
||||||
}};
|
}};
|
||||||
}});
|
}});
|
||||||
}};
|
}};
|
||||||
@@ -2946,7 +2945,7 @@ public class UnitTypes{
|
|||||||
flying = true;
|
flying = true;
|
||||||
drag = 0.07f;
|
drag = 0.07f;
|
||||||
speed = 1f;
|
speed = 1f;
|
||||||
rotateSpeed = 2.5f;
|
rotateSpeed = 2f;
|
||||||
accel = 0.1f;
|
accel = 0.1f;
|
||||||
health = 10000f;
|
health = 10000f;
|
||||||
armor = 7f;
|
armor = 7f;
|
||||||
@@ -2979,16 +2978,36 @@ public class UnitTypes{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO needs weapons! cool missiles or something
|
//TODO needs weapons! cool missiles or something
|
||||||
if(false)
|
weapons.add(new Weapon("disrupt-weapon"){{
|
||||||
weapons.add(new Weapon("quell-weapon"){{
|
x = 78f / 4f;
|
||||||
x = 51 / 4f;
|
y = -10f / 4f;
|
||||||
y = 5 / 4f;
|
mirror = true;
|
||||||
rotate = true;
|
rotate = true;
|
||||||
rotateSpeed = 2f;
|
rotateSpeed = 0.4f;
|
||||||
reload = 70f;
|
reload = 60f;
|
||||||
layerOffset = -0.001f;
|
layerOffset = -20f;
|
||||||
recoil = 1f;
|
recoil = 1f;
|
||||||
rotationLimit = 60f;
|
rotationLimit = 22f;
|
||||||
|
minWarmup = 0.95f;
|
||||||
|
shootWarmupSpeed = 0.1f;
|
||||||
|
shootY = 2f;
|
||||||
|
shootCone = 40f;
|
||||||
|
shots = 3;
|
||||||
|
shotDelay = 5f;
|
||||||
|
inaccuracy = 28f;
|
||||||
|
|
||||||
|
parts.add(new RegionPart("-blade"){{
|
||||||
|
heatProgress = PartProgress.warmup;
|
||||||
|
progress = PartProgress.warmup.blend(PartProgress.reload, 0.15f);
|
||||||
|
heatColor = Color.valueOf("9c50ff");
|
||||||
|
x = 5 / 4f;
|
||||||
|
y = 0f;
|
||||||
|
rotMove = -33f;
|
||||||
|
moveY = -1f;
|
||||||
|
moveX = -1f;
|
||||||
|
under = true;
|
||||||
|
mirror = true;
|
||||||
|
}});
|
||||||
|
|
||||||
bullet = new BulletType(){{
|
bullet = new BulletType(){{
|
||||||
shootEffect = Fx.shootBig;
|
shootEffect = Fx.shootBig;
|
||||||
@@ -2998,24 +3017,20 @@ public class UnitTypes{
|
|||||||
keepVelocity = false;
|
keepVelocity = false;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
unitSpawned = new MissileUnitType("quell-missile"){{
|
unitSpawned = new MissileUnitType("disrupt-missile"){{
|
||||||
speed = 3.8f;
|
speed = 4.5f;
|
||||||
maxRange = 80f;
|
maxRange = 80f;
|
||||||
outlineColor = Pal.darkOutline;
|
outlineColor = Pal.darkOutline;
|
||||||
health = 45;
|
health = 45;
|
||||||
|
homingDelay = 10f;
|
||||||
|
|
||||||
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 BulletType(){{
|
bullet = new ExplosionBulletType(120f, 30f){{
|
||||||
rangeOverride = 20f;
|
|
||||||
shootEffect = Fx.massiveExplosion;
|
shootEffect = Fx.massiveExplosion;
|
||||||
killShooter = true;
|
|
||||||
//TODO status?
|
|
||||||
splashDamageRadius = 30f;
|
|
||||||
splashDamage = 120f;
|
|
||||||
}};
|
}};
|
||||||
}});
|
}});
|
||||||
}};
|
}};
|
||||||
@@ -3107,7 +3122,8 @@ public class UnitTypes{
|
|||||||
shootEffect = Fx.colorSpark;
|
shootEffect = Fx.colorSpark;
|
||||||
hitEffect = smokeEffect = despawnEffect = Fx.hitLaserColor;
|
hitEffect = smokeEffect = despawnEffect = Fx.hitLaserColor;
|
||||||
|
|
||||||
damage = 1;
|
//TODO 0, or 1?
|
||||||
|
damage = 0;
|
||||||
}};
|
}};
|
||||||
}});
|
}});
|
||||||
}};
|
}};
|
||||||
|
|||||||
@@ -387,11 +387,17 @@ public class Damage{
|
|||||||
|
|
||||||
/** Damages all entities and blocks in a radius that are enemies of the team. */
|
/** Damages all entities and blocks in a radius that are enemies of the team. */
|
||||||
public static void damage(Team team, float x, float y, float radius, float damage, boolean complete, boolean air, boolean ground){
|
public static void damage(Team team, float x, float y, float radius, float damage, boolean complete, boolean air, boolean ground){
|
||||||
|
damage(team, x, y, radius, damage, complete, air, ground, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Damages all entities and blocks in a radius that are enemies of the team. */
|
||||||
|
public static void damage(Team team, float x, float y, float radius, float damage, boolean complete, boolean air, boolean ground, boolean scaled){
|
||||||
Cons<Unit> cons = entity -> {
|
Cons<Unit> cons = entity -> {
|
||||||
if(entity.team == team || !entity.within(x, y, radius) || (entity.isFlying() && !air) || (entity.isGrounded() && !ground)){
|
if(entity.team == team || !entity.within(x, y, radius + (scaled ? entity.hitSize / 2f : 0f)) || (entity.isFlying() && !air) || (entity.isGrounded() && !ground)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float amount = calculateDamage(x, y, entity.getX(), entity.getY(), radius, damage);
|
|
||||||
|
float amount = calculateDamage(scaled ? Math.max(0, entity.dst(x, y) - entity.type.hitSize/2) : entity.dst(x, y), radius, damage);
|
||||||
entity.damage(amount);
|
entity.damage(amount);
|
||||||
//TODO better velocity displacement
|
//TODO better velocity displacement
|
||||||
float dst = tr.set(entity.getX() - x, entity.getY() - y).len();
|
float dst = tr.set(entity.getX() - x, entity.getY() - y).len();
|
||||||
@@ -504,8 +510,7 @@ public class Damage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float calculateDamage(float x, float y, float tx, float ty, float radius, float damage){
|
private static float calculateDamage(float dist, float radius, float damage){
|
||||||
float dist = Mathf.dst(x, y, tx, ty);
|
|
||||||
float falloff = 0.4f;
|
float falloff = 0.4f;
|
||||||
float scaled = Mathf.lerp(1f - dist / radius, 1f, falloff);
|
float scaled = Mathf.lerp(1f - dist / radius, 1f, falloff);
|
||||||
return damage * scaled;
|
return damage * scaled;
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
public boolean instantDisappear;
|
public boolean instantDisappear;
|
||||||
/** Damage dealt in splash. 0 to disable.*/
|
/** Damage dealt in splash. 0 to disable.*/
|
||||||
public float splashDamage = 0f;
|
public float splashDamage = 0f;
|
||||||
|
/** If true, splash damage is "correctly" affected by unit hitbox size. Used for projectiles that do not collide / have splash as their main source of damage. */
|
||||||
|
public boolean scaledSplashDamage = false;
|
||||||
/** Knockback in velocity. */
|
/** Knockback in velocity. */
|
||||||
public float knockback;
|
public float knockback;
|
||||||
/** Should knockback follow the bullet's direction */
|
/** Should knockback follow the bullet's direction */
|
||||||
@@ -142,6 +144,7 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
public @Nullable BulletType fragBullet = null;
|
public @Nullable BulletType fragBullet = null;
|
||||||
public Color hitColor = Color.white;
|
public Color hitColor = Color.white;
|
||||||
public Color healColor = Pal.heal;
|
public Color healColor = Pal.heal;
|
||||||
|
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<>();
|
||||||
|
|
||||||
@@ -249,7 +252,7 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(heals()&& build.team == b.team && !(build.block instanceof ConstructBlock)){
|
if(heals()&& build.team == b.team && !(build.block instanceof ConstructBlock)){
|
||||||
Fx.healBlockFull.at(build.x, build.y, build.block.size, healColor);
|
healEffect.at(build.x, build.y, build.block.size, healColor);
|
||||||
build.heal(healPercent / 100f * build.maxHealth + healAmount);
|
build.heal(healPercent / 100f * build.maxHealth + healAmount);
|
||||||
}else if(build.team != b.team && direct){
|
}else if(build.team != b.team && direct){
|
||||||
hit(b);
|
hit(b);
|
||||||
@@ -308,7 +311,7 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(splashDamageRadius > 0 && !b.absorbed){
|
if(splashDamageRadius > 0 && !b.absorbed){
|
||||||
Damage.damage(b.team, x, y, splashDamageRadius, splashDamage * b.damageMultiplier(), collidesAir, collidesGround);
|
Damage.damage(b.team, x, y, splashDamageRadius, splashDamage * b.damageMultiplier(), false, collidesAir, collidesGround, scaledSplashDamage);
|
||||||
|
|
||||||
if(status != StatusEffects.none){
|
if(status != StatusEffects.none){
|
||||||
Damage.status(b.team, x, y, splashDamageRadius, status, statusDuration, collidesAir, collidesGround);
|
Damage.status(b.team, x, y, splashDamageRadius, status, statusDuration, collidesAir, collidesGround);
|
||||||
@@ -316,7 +319,7 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
|
|
||||||
if(heals()){
|
if(heals()){
|
||||||
indexer.eachBlock(b.team, x, y, splashDamageRadius, Building::damaged, other -> {
|
indexer.eachBlock(b.team, x, y, splashDamageRadius, Building::damaged, other -> {
|
||||||
Fx.healBlockFull.at(other.x, other.y, other.block.size, healColor);
|
healEffect.at(other.x, other.y, other.block.size, healColor);
|
||||||
other.heal(healPercent / 100f * other.maxHealth() + healAmount);
|
other.heal(healPercent / 100f * other.maxHealth() + healAmount);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -375,7 +378,7 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(instantDisappear){
|
if(instantDisappear){
|
||||||
b.time = lifetime;
|
b.time = lifetime + 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(spawnBullets.size > 0){
|
if(spawnBullets.size > 0){
|
||||||
|
|||||||
28
core/src/mindustry/entities/bullet/ExplosionBulletType.java
Normal file
28
core/src/mindustry/entities/bullet/ExplosionBulletType.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package mindustry.entities.bullet;
|
||||||
|
|
||||||
|
import mindustry.content.*;
|
||||||
|
|
||||||
|
public class ExplosionBulletType extends BulletType{
|
||||||
|
|
||||||
|
public ExplosionBulletType(float splashDamage, float splashDamageRadius){
|
||||||
|
this.splashDamage = splashDamage;
|
||||||
|
this.splashDamageRadius = splashDamageRadius;
|
||||||
|
rangeOverride = Math.max(rangeOverride, splashDamageRadius * 2f / 3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExplosionBulletType(){
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
hittable = false;
|
||||||
|
lifetime = 1f;
|
||||||
|
speed = 0f;
|
||||||
|
rangeOverride = 20f;
|
||||||
|
shootEffect = Fx.massiveExplosion;
|
||||||
|
instantDisappear = true;
|
||||||
|
scaledSplashDamage = true;
|
||||||
|
killShooter = true;
|
||||||
|
collides = false;
|
||||||
|
keepVelocity = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -513,7 +513,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
|
|
||||||
float shake = hitSize / 3f;
|
float shake = hitSize / 3f;
|
||||||
|
|
||||||
Effect.scorch(x, y, (int)(hitSize / 5));
|
if(type.createScorch){
|
||||||
|
Effect.scorch(x, y, (int)(hitSize / 5));
|
||||||
|
}
|
||||||
Effect.shake(shake, shake, this);
|
Effect.shake(shake, shake, this);
|
||||||
type.deathSound.at(this);
|
type.deathSound.at(this);
|
||||||
|
|
||||||
@@ -536,7 +538,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
Damage.damage(team, x, y, Mathf.pow(hitSize, 0.94f) * 1.25f, Mathf.pow(hitSize, 0.75f) * type.crashDamageMultiplier * 5f, true, false, true);
|
Damage.damage(team, x, y, Mathf.pow(hitSize, 0.94f) * 1.25f, Mathf.pow(hitSize, 0.75f) * type.crashDamageMultiplier * 5f, true, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!headless){
|
if(!headless && type.createScorch){
|
||||||
for(int i = 0; i < type.wreckRegions.length; i++){
|
for(int i = 0; i < type.wreckRegions.length; i++){
|
||||||
if(type.wreckRegions[i].found()){
|
if(type.wreckRegions[i].found()){
|
||||||
float range = type.hitSize /4f;
|
float range = type.hitSize /4f;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import arc.graphics.g2d.*;
|
|||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
|
|
||||||
public abstract class WeaponPart{
|
public abstract class DrawPart{
|
||||||
public static final PartParams params = new PartParams();
|
public static final PartParams params = new PartParams();
|
||||||
|
|
||||||
/** If true, turret shading is used. Don't touch this, it is set up in unit/block init()! */
|
/** If true, turret shading is used. Don't touch this, it is set up in unit/block init()! */
|
||||||
@@ -37,11 +37,14 @@ public abstract class WeaponPart{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface PartProgress{
|
public interface PartProgress{
|
||||||
|
/** Reload of the weapon - 1 right after shooting, 0 when ready to fire*/
|
||||||
PartProgress
|
PartProgress
|
||||||
|
|
||||||
reload = p -> p.reload,
|
reload = p -> p.reload,
|
||||||
|
/** Reload, but smoothed out, so there is no sudden jump between 0-1. */
|
||||||
smoothReload = p -> p.smoothReload,
|
smoothReload = p -> p.smoothReload,
|
||||||
|
/** Weapon warmup, 0 when not firing, 1 when actively shooting. Not equivalent to heat. */
|
||||||
warmup = p -> p.warmup,
|
warmup = p -> p.warmup,
|
||||||
|
/** Weapon heat, 1 when just fired, 0, when it has cooled down (duration depends on weapon) */
|
||||||
heat = p -> p.heat;
|
heat = p -> p.heat;
|
||||||
|
|
||||||
float get(PartParams p);
|
float get(PartParams p);
|
||||||
@@ -74,6 +77,10 @@ public abstract class WeaponPart{
|
|||||||
return p -> get(p) * other.get(p);
|
return p -> get(p) * other.get(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default PartProgress mul(float amount){
|
||||||
|
return p -> get(p) * amount;
|
||||||
|
}
|
||||||
|
|
||||||
default PartProgress min(PartProgress other){
|
default PartProgress min(PartProgress other){
|
||||||
return p -> Math.min(get(p), other.get(p));
|
return p -> Math.min(get(p), other.get(p));
|
||||||
}
|
}
|
||||||
@@ -8,10 +8,13 @@ import arc.struct.*;
|
|||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
|
|
||||||
public class RegionPart extends WeaponPart{
|
public class RegionPart extends DrawPart{
|
||||||
protected PartParams childParam = new PartParams();
|
protected PartParams childParam = new PartParams();
|
||||||
|
|
||||||
|
/** Appended to unit/weapon/block name and drawn. */
|
||||||
public String suffix = "";
|
public String suffix = "";
|
||||||
|
/** Overrides suffix if set. */
|
||||||
|
public @Nullable String name;
|
||||||
public TextureRegion heat;
|
public TextureRegion heat;
|
||||||
public TextureRegion[] regions = {};
|
public TextureRegion[] regions = {};
|
||||||
public TextureRegion[] outlines = {};
|
public TextureRegion[] outlines = {};
|
||||||
@@ -34,12 +37,19 @@ public class RegionPart extends WeaponPart{
|
|||||||
public float x, y, moveX, moveY;
|
public float x, y, moveX, moveY;
|
||||||
public @Nullable Color color, colorTo;
|
public @Nullable Color color, colorTo;
|
||||||
public Color heatColor = Pal.turretHeat.cpy();
|
public Color heatColor = Pal.turretHeat.cpy();
|
||||||
public Seq<WeaponPart> children = new Seq<>();
|
public Seq<DrawPart> children = new Seq<>();
|
||||||
|
|
||||||
public RegionPart(String region){
|
public RegionPart(String region){
|
||||||
this.suffix = region;
|
this.suffix = region;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RegionPart(String region, Blending blending, Color color){
|
||||||
|
this.suffix = region;
|
||||||
|
this.blending = blending;
|
||||||
|
this.color = color;
|
||||||
|
outline = false;
|
||||||
|
}
|
||||||
|
|
||||||
public RegionPart(){
|
public RegionPart(){
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,25 +129,27 @@ public class RegionPart extends WeaponPart{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(String name){
|
public void load(String name){
|
||||||
|
String realName = this.name == null ? name + suffix : this.name;
|
||||||
|
|
||||||
if(drawRegion){
|
if(drawRegion){
|
||||||
//TODO l/r
|
//TODO l/r
|
||||||
if(mirror && turretShading){
|
if(mirror && turretShading){
|
||||||
regions = new TextureRegion[]{
|
regions = new TextureRegion[]{
|
||||||
Core.atlas.find(name + suffix + "1"),
|
Core.atlas.find(realName + "1"),
|
||||||
Core.atlas.find(name + suffix + "2")
|
Core.atlas.find(realName + "2")
|
||||||
};
|
};
|
||||||
|
|
||||||
outlines = new TextureRegion[]{
|
outlines = new TextureRegion[]{
|
||||||
Core.atlas.find(name + suffix + "1-outline"),
|
Core.atlas.find(realName + "1-outline"),
|
||||||
Core.atlas.find(name + suffix + "2-outline")
|
Core.atlas.find(realName + "2-outline")
|
||||||
};
|
};
|
||||||
}else{
|
}else{
|
||||||
regions = new TextureRegion[]{Core.atlas.find(name + suffix)};
|
regions = new TextureRegion[]{Core.atlas.find(realName)};
|
||||||
outlines = new TextureRegion[]{Core.atlas.find(name + suffix + "-outline")};
|
outlines = new TextureRegion[]{Core.atlas.find(realName + "-outline")};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
heat = Core.atlas.find(name + suffix + "-heat");
|
heat = Core.atlas.find(realName + "-heat");
|
||||||
for(var child : children){
|
for(var child : children){
|
||||||
child.load(name);
|
child.load(name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
package mindustry.entities.units;
|
|
||||||
|
|
||||||
import arc.graphics.*;
|
|
||||||
import arc.graphics.g2d.*;
|
|
||||||
import mindustry.graphics.*;
|
|
||||||
|
|
||||||
/** A sprite drawn in addition to the base unit sprites. */
|
|
||||||
public class UnitDecal{
|
|
||||||
public String region = "error";
|
|
||||||
public float x, y, rotation;
|
|
||||||
public float layer = Layer.flyingUnit + 1f;
|
|
||||||
public float xScale = 1f, yScale = 1f;
|
|
||||||
public Blending blending = Blending.normal;
|
|
||||||
public Color color = Color.white;
|
|
||||||
|
|
||||||
public TextureRegion loadedRegion;
|
|
||||||
|
|
||||||
public UnitDecal(String region, float x, float y, float rotation, float layer, Color color){
|
|
||||||
this.region = region;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.rotation = rotation;
|
|
||||||
this.layer = layer;
|
|
||||||
this.color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnitDecal(String region, Color color, Blending blending, float layer){
|
|
||||||
this.region = region;
|
|
||||||
this.color = color;
|
|
||||||
this.layer = layer;
|
|
||||||
this.blending = blending;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnitDecal(){
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -25,7 +25,7 @@ import mindustry.entities.abilities.*;
|
|||||||
import mindustry.entities.bullet.*;
|
import mindustry.entities.bullet.*;
|
||||||
import mindustry.entities.effect.*;
|
import mindustry.entities.effect.*;
|
||||||
import mindustry.entities.part.*;
|
import mindustry.entities.part.*;
|
||||||
import mindustry.entities.part.WeaponPart.*;
|
import mindustry.entities.part.DrawPart.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.game.Objectives.*;
|
import mindustry.game.Objectives.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
@@ -130,13 +130,14 @@ public class ContentParser{
|
|||||||
readFields(result, data);
|
readFields(result, data);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
put(WeaponPart.class, (type, data) -> {
|
put(DrawPart.class, (type, data) -> {
|
||||||
var bc = resolve(data.getString("type", ""), RegionPart.class);
|
var bc = resolve(data.getString("type", ""), RegionPart.class);
|
||||||
data.remove("type");
|
data.remove("type");
|
||||||
var result = make(bc);
|
var result = make(bc);
|
||||||
readFields(result, data);
|
readFields(result, data);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
//TODO this is untested
|
||||||
put(PartProgress.class, (type, data) -> {
|
put(PartProgress.class, (type, data) -> {
|
||||||
//simple case: it's a string or number constant
|
//simple case: it's a string or number constant
|
||||||
if(data.isString()) return field(PartProgress.class, data.asString());
|
if(data.isString()) return field(PartProgress.class, data.asString());
|
||||||
@@ -166,7 +167,7 @@ public class ContentParser{
|
|||||||
case "mul" -> base.mul(parser.readValue(PartProgress.class, data.get("other")));
|
case "mul" -> base.mul(parser.readValue(PartProgress.class, data.get("other")));
|
||||||
case "min" -> base.min(parser.readValue(PartProgress.class, data.get("other")));
|
case "min" -> base.min(parser.readValue(PartProgress.class, data.get("other")));
|
||||||
case "sin" -> base.sin(data.getFloat("scl"), data.getFloat("mag"));
|
case "sin" -> base.sin(data.getFloat("scl"), data.getFloat("mag"));
|
||||||
case "absin" -> base.sin(data.getFloat("scl"), data.getFloat("mag"));
|
case "absin" -> base.absin(data.getFloat("scl"), data.getFloat("mag"));
|
||||||
case "curve" -> base.curve(parser.readValue(Interp.class, data.get("interp")));
|
case "curve" -> base.curve(parser.readValue(Interp.class, data.get("interp")));
|
||||||
default -> throw new RuntimeException("Unknown operation '" + op + "', check PartProgress class for a list of methods.");
|
default -> throw new RuntimeException("Unknown operation '" + op + "', check PartProgress class for a list of methods.");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import mindustry.core.*;
|
|||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.entities.abilities.*;
|
import mindustry.entities.abilities.*;
|
||||||
|
import mindustry.entities.part.*;
|
||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
@@ -59,7 +60,6 @@ public class UnitType extends UnlockableContent{
|
|||||||
public float speed = 1.1f, boostMultiplier = 1f, rotateSpeed = 5f, baseRotateSpeed = 5f;
|
public float speed = 1.1f, boostMultiplier = 1f, rotateSpeed = 5f, baseRotateSpeed = 5f;
|
||||||
public float drag = 0.3f, accel = 0.5f, landShake = 0f, rippleScale = 1f, riseSpeed = 0.08f, fallSpeed = 0.018f;
|
public float drag = 0.3f, accel = 0.5f, landShake = 0f, rippleScale = 1f, riseSpeed = 0.08f, fallSpeed = 0.018f;
|
||||||
public float health = 200f, range = -1, miningRange = 70f, armor = 0f, maxRange = -1f, buildRange = Vars.buildingRange;
|
public float health = 200f, range = -1, miningRange = 70f, armor = 0f, maxRange = -1f, buildRange = Vars.buildingRange;
|
||||||
public float lifetime = 60f * 5f; //for missiles only
|
|
||||||
public float crashDamageMultiplier = 1f;
|
public float crashDamageMultiplier = 1f;
|
||||||
public boolean targetAir = true, targetGround = true;
|
public boolean targetAir = true, targetGround = true;
|
||||||
public boolean faceTarget = true, rotateShooting = true, isCounted = true, lowAltitude = false, circleTarget = false;
|
public boolean faceTarget = true, rotateShooting = true, isCounted = true, lowAltitude = false, circleTarget = false;
|
||||||
@@ -68,6 +68,7 @@ public class UnitType extends UnlockableContent{
|
|||||||
public boolean playerControllable = true;
|
public boolean playerControllable = true;
|
||||||
public boolean allowedInPayloads = true;
|
public boolean allowedInPayloads = true;
|
||||||
public boolean createWreck = true;
|
public boolean createWreck = true;
|
||||||
|
public boolean createScorch = true;
|
||||||
public boolean useUnitCap = true;
|
public boolean useUnitCap = true;
|
||||||
public boolean destructibleWreck = true;
|
public boolean destructibleWreck = true;
|
||||||
/** If true, this modded unit always has a -outline region generated for its base. Normally, outlines are ignored if there are no top = false weapons. */
|
/** If true, this modded unit always has a -outline region generated for its base. Normally, outlines are ignored if there are no top = false weapons. */
|
||||||
@@ -94,8 +95,8 @@ public class UnitType extends UnlockableContent{
|
|||||||
public Effect fallThrusterEffect = Fx.fallSmoke;
|
public Effect fallThrusterEffect = Fx.fallSmoke;
|
||||||
public Effect deathExplosionEffect = Fx.dynamicExplosion;
|
public Effect deathExplosionEffect = Fx.dynamicExplosion;
|
||||||
public @Nullable Effect treadEffect;
|
public @Nullable Effect treadEffect;
|
||||||
/** Additional sprites that are drawn with the unit. */
|
/** Extra (usually animated) parts */
|
||||||
public Seq<UnitDecal> decals = new Seq<>();
|
public Seq<DrawPart> parts = new Seq<>(DrawPart.class);
|
||||||
public Seq<Ability> abilities = new Seq<>();
|
public Seq<Ability> abilities = new Seq<>();
|
||||||
/** Flags to target based on priority. Null indicates that the closest target should be found. The closest enemy core is used as a fallback. */
|
/** Flags to target based on priority. Null indicates that the closest target should be found. The closest enemy core is used as a fallback. */
|
||||||
public BlockFlag[] targetFlags = {null};
|
public BlockFlag[] targetFlags = {null};
|
||||||
@@ -138,6 +139,10 @@ public class UnitType extends UnlockableContent{
|
|||||||
public Sound mineSound = Sounds.minebeam;
|
public Sound mineSound = Sounds.minebeam;
|
||||||
public float mineSoundVolume = 0.6f;
|
public float mineSoundVolume = 0.6f;
|
||||||
|
|
||||||
|
//missiles only!
|
||||||
|
public float lifetime = 60f * 5f;
|
||||||
|
public float homingDelay = 10f;
|
||||||
|
|
||||||
/** This is a VERY ROUGH estimate of unit DPS. */
|
/** This is a VERY ROUGH estimate of unit DPS. */
|
||||||
public float dpsEstimate = -1;
|
public float dpsEstimate = -1;
|
||||||
public float clipSize = -1;
|
public float clipSize = -1;
|
||||||
@@ -522,6 +527,9 @@ public class UnitType extends UnlockableContent{
|
|||||||
public void load(){
|
public void load(){
|
||||||
super.load();
|
super.load();
|
||||||
|
|
||||||
|
for(var part : parts){
|
||||||
|
part.load(name);
|
||||||
|
}
|
||||||
weapons.each(Weapon::load);
|
weapons.each(Weapon::load);
|
||||||
region = Core.atlas.find(name);
|
region = Core.atlas.find(name);
|
||||||
legRegion = Core.atlas.find(name + "-leg");
|
legRegion = Core.atlas.find(name + "-leg");
|
||||||
@@ -562,10 +570,6 @@ public class UnitType extends UnlockableContent{
|
|||||||
segmentOutlineRegions[i] = Core.atlas.find(name + "-segment-outline" + i);
|
segmentOutlineRegions[i] = Core.atlas.find(name + "-segment-outline" + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var decal : decals){
|
|
||||||
decal.loadedRegion = Core.atlas.find(decal.region);
|
|
||||||
}
|
|
||||||
|
|
||||||
clipSize = Math.max(region.width * 2f, clipSize);
|
clipSize = Math.max(region.width * 2f, clipSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,18 +802,19 @@ public class UnitType extends UnlockableContent{
|
|||||||
unit.trns(-legOffset.x, -legOffset.y);
|
unit.trns(-legOffset.x, -legOffset.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(decals.size > 0){
|
//TODO how/where do I draw under?
|
||||||
float base = unit.rotation - 90;
|
if(parts.size > 0){
|
||||||
for(var d : decals){
|
//TODO does it need an outline?
|
||||||
Draw.blend(d.blending);
|
WeaponMount first = unit.mounts.length > 0 ? unit.mounts[0] : null;
|
||||||
Draw.z(d.layer <= 0f ? z : d.layer);
|
if(unit.mounts.length > 0){
|
||||||
Draw.scl(d.xScale, d.yScale);
|
DrawPart.params.set(first.warmup, first.reload / weapons.first().reload, first.smoothReload, first.heat, unit.x, unit.y, unit.rotation);
|
||||||
Draw.color(d.color);
|
}else{
|
||||||
Draw.rect(d.loadedRegion, unit.x + Angles.trnsx(base, d.x, d.y), unit.y + Angles.trnsy(base, d.x, d.y), base + d.rotation);
|
DrawPart.params.set(0f, 0f, 0f, 0f, unit.x, unit.y, unit.rotation);
|
||||||
Draw.blend();
|
}
|
||||||
|
for(int i = 0; i < parts.size; i++){
|
||||||
|
var part = parts.items[i];
|
||||||
|
part.draw(DrawPart.params);
|
||||||
}
|
}
|
||||||
Draw.reset();
|
|
||||||
Draw.z(z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Ability a : unit.abilities){
|
for(Ability a : unit.abilities){
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ 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.*;
|
||||||
@@ -131,7 +132,7 @@ public class Weapon implements Cloneable{
|
|||||||
/** whether this weapon should fire when its owner dies */
|
/** whether this weapon should fire when its owner dies */
|
||||||
public boolean shootOnDeath = false;
|
public boolean shootOnDeath = false;
|
||||||
/** extra animated parts */
|
/** extra animated parts */
|
||||||
public Seq<WeaponPart> parts = new Seq<>(WeaponPart.class);
|
public Seq<DrawPart> parts = new Seq<>(DrawPart.class);
|
||||||
|
|
||||||
public Weapon(String name){
|
public Weapon(String name){
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -195,12 +196,12 @@ public class Weapon implements Cloneable{
|
|||||||
Draw.xscl = -Mathf.sign(flipSprite);
|
Draw.xscl = -Mathf.sign(flipSprite);
|
||||||
|
|
||||||
if(parts.size > 0){
|
if(parts.size > 0){
|
||||||
WeaponPart.params.set(mount.warmup, mount.reload / reload, mount.smoothReload, mount.heat, wx, wy, weaponRotation + 90);
|
DrawPart.params.set(mount.warmup, mount.reload / reload, mount.smoothReload, mount.heat, wx, wy, weaponRotation + 90);
|
||||||
|
|
||||||
for(int i = 0; i < parts.size; i++){
|
for(int i = 0; i < parts.size; i++){
|
||||||
var part = parts.items[i];
|
var part = parts.items[i];
|
||||||
if(part.under){
|
if(part.under){
|
||||||
part.draw(WeaponPart.params);
|
part.draw(DrawPart.params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,18 +218,10 @@ public class Weapon implements Cloneable{
|
|||||||
|
|
||||||
if(parts.size > 0){
|
if(parts.size > 0){
|
||||||
//TODO does it need an outline?
|
//TODO does it need an outline?
|
||||||
/*
|
|
||||||
if(outline.found()){
|
|
||||||
//draw outline under everything when parts are involved
|
|
||||||
Draw.z(Layer.turret - 0.01f);
|
|
||||||
Draw.rect(outline, build.x + tb.recoilOffset.x, build.y + tb.recoilOffset.y, tb.drawrot());
|
|
||||||
Draw.z(Layer.turret);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
for(int i = 0; i < parts.size; i++){
|
for(int i = 0; i < parts.size; i++){
|
||||||
var part = parts.items[i];
|
var part = parts.items[i];
|
||||||
if(!part.under){
|
if(!part.under){
|
||||||
part.draw(WeaponPart.params);
|
part.draw(DrawPart.params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -380,10 +373,8 @@ public class Weapon implements Cloneable{
|
|||||||
float baseX = offset.x, baseY = offset.y, baseRot = unit.rotation + mount.rotation;
|
float baseX = offset.x, baseY = offset.y, baseRot = unit.rotation + mount.rotation;
|
||||||
boolean delay = firstShotDelay + shotDelay > 0f;
|
boolean delay = firstShotDelay + shotDelay > 0f;
|
||||||
|
|
||||||
(delay ? chargeSound : continuous ? Sounds.none : shootSound).at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax));
|
float lifeScl = bullet.scaleVelocity ? Mathf.clamp(Mathf.dst(shootX, shootY, aimX, aimY) / bullet.range()) : 1f;
|
||||||
|
Unit parent = bullet.keepVelocity || parentizeEffects ? unit : null;
|
||||||
BulletType ammo = bullet;
|
|
||||||
float lifeScl = ammo.scaleVelocity ? Mathf.clamp(Mathf.dst(shootX, shootY, aimX, aimY) / ammo.range()) : 1f;
|
|
||||||
|
|
||||||
//TODO far too complicated and similar to Turret
|
//TODO far too complicated and similar to Turret
|
||||||
|
|
||||||
@@ -393,6 +384,7 @@ public class Weapon implements Cloneable{
|
|||||||
Time.run(sequenceNum * shotDelay + firstShotDelay, () -> {
|
Time.run(sequenceNum * shotDelay + firstShotDelay, () -> {
|
||||||
if(!unit.isAdded()) return;
|
if(!unit.isAdded()) return;
|
||||||
|
|
||||||
|
//TODO this is a flawed system, recalculate everything instead.
|
||||||
getShootPos(unit, mount, offset).sub(baseX, baseY);
|
getShootPos(unit, mount, offset).sub(baseX, baseY);
|
||||||
|
|
||||||
float rotOffset = unit.rotation + mount.rotation - baseRot;
|
float rotOffset = unit.rotation + mount.rotation - baseRot;
|
||||||
@@ -407,13 +399,11 @@ public class Weapon implements Cloneable{
|
|||||||
Angles.shotgun(shots, spacing, rotation, f -> mount.bullet = bullet(unit, shootX, shootY, f + Mathf.range(inaccuracy), lifeScl));
|
Angles.shotgun(shots, spacing, rotation, f -> mount.bullet = bullet(unit, shootX, shootY, f + Mathf.range(inaccuracy), lifeScl));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean parentize = ammo.keepVelocity || parentizeEffects;
|
|
||||||
|
|
||||||
if(delay){
|
if(delay){
|
||||||
Time.run(firstShotDelay, () -> {
|
Time.run(firstShotDelay, () -> {
|
||||||
if(!unit.isAdded()) return;
|
if(!unit.isAdded()) return;
|
||||||
|
|
||||||
unit.vel.add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
|
unit.vel.add(Tmp.v1.trns(rotation + 180f, bullet.recoil));
|
||||||
Effect.shake(shake, shake, shootX, shootY);
|
Effect.shake(shake, shake, shootX, shootY);
|
||||||
mount.recoil = recoil;
|
mount.recoil = recoil;
|
||||||
mount.heat = 1f;
|
mount.heat = 1f;
|
||||||
@@ -423,21 +413,26 @@ public class Weapon implements Cloneable{
|
|||||||
|
|
||||||
getShootPos(unit, mount, offset).sub(baseX, baseY);
|
getShootPos(unit, mount, offset).sub(baseX, baseY);
|
||||||
|
|
||||||
ammo.chargeShootEffect.at(shootX + offset.x, shootY + offset.y, rotation, parentize ? unit : null);
|
bullet.chargeShootEffect.at(shootX + offset.x, shootY + offset.y, rotation, parent);
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
unit.vel.add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
|
unit.vel.add(Tmp.v1.trns(rotation + 180f, bullet.recoil));
|
||||||
Effect.shake(shake, shake, shootX, shootY);
|
Effect.shake(shake, shake, shootX, shootY);
|
||||||
mount.recoil = recoil;
|
mount.recoil = recoil;
|
||||||
mount.heat = 1f;
|
mount.heat = 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
ejectEffect.at(mountX, mountY, rotation * side);
|
(delay ? chargeSound : continuous ? Sounds.none : shootSound).at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax));
|
||||||
ammo.shootEffect.at(shootX, shootY, rotation, ammo.hitColor, parentize ? unit : null);
|
effects(parent, mountX, mountY, shootX, shootY, rotation, side);
|
||||||
ammo.smokeEffect.at(shootX, shootY, rotation, ammo.hitColor, parentize ? unit : null);
|
|
||||||
unit.apply(shootStatus, shootStatusDuration);
|
unit.apply(shootStatus, shootStatusDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void effects(Unit parent, float mountX, float mountY, float shootX, float shootY, float rotation, int side){
|
||||||
|
ejectEffect.at(mountX, mountY, rotation * side);
|
||||||
|
bullet.shootEffect.at(shootX, shootY, rotation, bullet.hitColor, parent);
|
||||||
|
bullet.smokeEffect.at(shootX, shootY, rotation, bullet.hitColor, parent);
|
||||||
|
}
|
||||||
|
|
||||||
protected @Nullable Bullet bullet(Unit unit, float shootX, float shootY, float angle, float lifescl){
|
protected @Nullable Bullet bullet(Unit unit, float shootX, float shootY, float angle, float lifescl){
|
||||||
float
|
float
|
||||||
xr = Mathf.range(xRand),
|
xr = Mathf.range(xRand),
|
||||||
@@ -452,6 +447,9 @@ public class Weapon implements Cloneable{
|
|||||||
spawned.rotation = angle;
|
spawned.rotation = angle;
|
||||||
//immediately spawn at top speed, since it was launched
|
//immediately spawn at top speed, since it was launched
|
||||||
spawned.vel.trns(angle, unitSpawned.speed);
|
spawned.vel.trns(angle, unitSpawned.speed);
|
||||||
|
if(spawned.controller() instanceof MissileAI ai){
|
||||||
|
ai.shooter = unit;
|
||||||
|
}
|
||||||
spawned.add();
|
spawned.add();
|
||||||
//TODO assign AI target here?
|
//TODO assign AI target here?
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public class MissileUnitType extends UnitType{
|
|||||||
|
|
||||||
playerControllable = false;
|
playerControllable = false;
|
||||||
createWreck = false;
|
createWreck = false;
|
||||||
|
createScorch = false;
|
||||||
logicControllable = false;
|
logicControllable = false;
|
||||||
isCounted = false;
|
isCounted = false;
|
||||||
useUnitCap = false;
|
useUnitCap = false;
|
||||||
@@ -26,8 +27,8 @@ public class MissileUnitType extends UnitType{
|
|||||||
trailLength = 7;
|
trailLength = 7;
|
||||||
hidden = true;
|
hidden = true;
|
||||||
speed = 4f;
|
speed = 4f;
|
||||||
lifetime = 60f * 3f;
|
lifetime = 60f * 1.6f;
|
||||||
rotateSpeed = 3f;
|
rotateSpeed = 2.5f;
|
||||||
range = 30f;
|
range = 30f;
|
||||||
//TODO weapons, etc
|
//TODO weapons, etc
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1077,7 +1077,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
//make sure there are no under-attack sectors (other than this one)
|
//make sure there are no under-attack sectors (other than this one)
|
||||||
//TODO abandon button?
|
//TODO abandon button?
|
||||||
for(Planet planet : content.planets()){
|
for(Planet planet : content.planets()){
|
||||||
if(!planet.allowWaveSimulation){
|
if(!planet.allowWaveSimulation && !debugSelect){
|
||||||
int attackedCount = planet.sectors.count(s -> s.isAttacked() && s != sector);
|
int attackedCount = planet.sectors.count(s -> s.isAttacked() && s != sector);
|
||||||
|
|
||||||
//if there are two or more attacked sectors... something went wrong, don't show the dialog to prevent softlock
|
//if there are two or more attacked sectors... something went wrong, don't show the dialog to prevent softlock
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import mindustry.world.blocks.defense.turrets.Turret.*;
|
|||||||
public class DrawTurret extends DrawBlock{
|
public class DrawTurret extends DrawBlock{
|
||||||
protected static final Rand rand = new Rand();
|
protected static final Rand rand = new Rand();
|
||||||
|
|
||||||
public Seq<WeaponPart> parts = new Seq<>();
|
public Seq<DrawPart> parts = new Seq<>();
|
||||||
public String basePrefix = "";
|
public String basePrefix = "";
|
||||||
/** Overrides the liquid to draw in the liquid region. */
|
/** Overrides the liquid to draw in the liquid region. */
|
||||||
public @Nullable Liquid liquidDraw;
|
public @Nullable Liquid liquidDraw;
|
||||||
@@ -66,7 +66,7 @@ public class DrawTurret extends DrawBlock{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO no smooth reload
|
//TODO no smooth reload
|
||||||
var params = WeaponPart.params.set(build.warmup(), 1f - tb.progress(), 1f - tb.progress(), tb.heat, tb.x + tb.recoilOffset.x, tb.y + tb.recoilOffset.y, tb.rotation);
|
var params = DrawPart.params.set(build.warmup(), 1f - tb.progress(), 1f - tb.progress(), tb.heat, tb.x + tb.recoilOffset.x, tb.y + tb.recoilOffset.y, tb.rotation);
|
||||||
|
|
||||||
for(var part : parts){
|
for(var part : parts){
|
||||||
part.draw(params);
|
part.draw(params);
|
||||||
|
|||||||
Reference in New Issue
Block a user