New weapon pattern system

This commit is contained in:
Anuken
2022-02-24 20:06:52 -05:00
parent 30787e49ad
commit c3e9a961c5
24 changed files with 219 additions and 126 deletions
+3 -21
View File
@@ -53,33 +53,13 @@ function extend(/*Base, ..., def*/){
const extendContent = extend; const extendContent = extend;
importPackage(Packages.arc) importPackage(Packages.arc)
importPackage(Packages.arc.audio)
importPackage(Packages.arc.func)
importPackage(Packages.arc.graphics) importPackage(Packages.arc.graphics)
importPackage(Packages.arc.graphics.g2d) importPackage(Packages.arc.graphics.g2d)
importPackage(Packages.arc.graphics.gl) importPackage(Packages.arc.graphics.gl)
importPackage(Packages.arc.input)
importPackage(Packages.arc.math) importPackage(Packages.arc.math)
importPackage(Packages.arc.math.geom)
importPackage(Packages.arc.scene)
importPackage(Packages.arc.scene.actions)
importPackage(Packages.arc.scene.event)
importPackage(Packages.arc.scene.style)
importPackage(Packages.arc.scene.ui)
importPackage(Packages.arc.scene.ui.layout)
importPackage(Packages.arc.scene.utils)
importPackage(Packages.arc.struct)
importPackage(Packages.arc.util) importPackage(Packages.arc.util)
importPackage(Packages.arc.util.async)
importPackage(Packages.arc.util.io)
importPackage(Packages.arc.util.noise)
importPackage(Packages.arc.util.pooling)
importPackage(Packages.arc.util.serialization)
importPackage(Packages.arc.util.viewport)
importPackage(Packages.mindustry) importPackage(Packages.mindustry)
importPackage(Packages.mindustry.ai) importPackage(Packages.mindustry.ai)
importPackage(Packages.mindustry.ai.formations)
importPackage(Packages.mindustry.ai.formations.patterns)
importPackage(Packages.mindustry.ai.types) importPackage(Packages.mindustry.ai.types)
importPackage(Packages.mindustry.async) importPackage(Packages.mindustry.async)
importPackage(Packages.mindustry.audio) importPackage(Packages.mindustry.audio)
@@ -91,6 +71,8 @@ importPackage(Packages.mindustry.entities)
importPackage(Packages.mindustry.entities.abilities) importPackage(Packages.mindustry.entities.abilities)
importPackage(Packages.mindustry.entities.bullet) importPackage(Packages.mindustry.entities.bullet)
importPackage(Packages.mindustry.entities.effect) importPackage(Packages.mindustry.entities.effect)
importPackage(Packages.mindustry.entities.part)
importPackage(Packages.mindustry.entities.pattern)
importPackage(Packages.mindustry.entities.units) importPackage(Packages.mindustry.entities.units)
importPackage(Packages.mindustry.game) importPackage(Packages.mindustry.game)
importPackage(Packages.mindustry.gen) importPackage(Packages.mindustry.gen)
@@ -121,7 +103,6 @@ importPackage(Packages.mindustry.world.blocks.defense)
importPackage(Packages.mindustry.world.blocks.defense.turrets) importPackage(Packages.mindustry.world.blocks.defense.turrets)
importPackage(Packages.mindustry.world.blocks.distribution) importPackage(Packages.mindustry.world.blocks.distribution)
importPackage(Packages.mindustry.world.blocks.environment) importPackage(Packages.mindustry.world.blocks.environment)
importPackage(Packages.mindustry.world.blocks.experimental)
importPackage(Packages.mindustry.world.blocks.heat) importPackage(Packages.mindustry.world.blocks.heat)
importPackage(Packages.mindustry.world.blocks.legacy) importPackage(Packages.mindustry.world.blocks.legacy)
importPackage(Packages.mindustry.world.blocks.liquid) importPackage(Packages.mindustry.world.blocks.liquid)
@@ -164,6 +145,7 @@ const CoreChangeEvent = Packages.mindustry.game.EventType.CoreChangeEvent
const BuildTeamChangeEvent = Packages.mindustry.game.EventType.BuildTeamChangeEvent const BuildTeamChangeEvent = Packages.mindustry.game.EventType.BuildTeamChangeEvent
const TileChangeEvent = Packages.mindustry.game.EventType.TileChangeEvent const TileChangeEvent = Packages.mindustry.game.EventType.TileChangeEvent
const TilePreChangeEvent = Packages.mindustry.game.EventType.TilePreChangeEvent const TilePreChangeEvent = Packages.mindustry.game.EventType.TilePreChangeEvent
const BuildDamageEvent = Packages.mindustry.game.EventType.BuildDamageEvent
const GameOverEvent = Packages.mindustry.game.EventType.GameOverEvent const GameOverEvent = Packages.mindustry.game.EventType.GameOverEvent
const UnitControlEvent = Packages.mindustry.game.EventType.UnitControlEvent const UnitControlEvent = Packages.mindustry.game.EventType.UnitControlEvent
const PickupEvent = Packages.mindustry.game.EventType.PickupEvent const PickupEvent = Packages.mindustry.game.EventType.PickupEvent
+52 -38
View File
@@ -12,6 +12,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.pattern.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.type.*; import mindustry.type.*;
@@ -194,9 +195,10 @@ public class UnitTypes{
shake = 2f; shake = 2f;
ejectEffect = Fx.casing3; ejectEffect = Fx.casing3;
shootSound = Sounds.bang; shootSound = Sounds.bang;
shots = 3;
inaccuracy = 3f; inaccuracy = 3f;
shotDelay = 4f;
shoot.shots = 3;
shoot.shotDelay = 4f;
bullet = new BasicBulletType(7f, 50){{ bullet = new BasicBulletType(7f, 50){{
width = 11f; width = 11f;
@@ -350,10 +352,11 @@ public class UnitTypes{
shootY = 2.5f; shootY = 2.5f;
reload = 36f; reload = 36f;
shots = 3;
inaccuracy = 35; inaccuracy = 35;
shotDelay = 0.5f;
spacing = 0f; shoot.shots = 3;
shoot.shotDelay = 0.5f;
ejectEffect = Fx.none; ejectEffect = Fx.none;
recoil = 2.5f; recoil = 2.5f;
shootSound = Sounds.spark; shootSound = Sounds.spark;
@@ -459,7 +462,7 @@ public class UnitTypes{
shootY = 13f; shootY = 13f;
x = y = 0f; x = y = 0f;
firstShotDelay = Fx.greenLaserChargeSmall.lifetime - 1f; shoot.firstShotDelay = Fx.greenLaserChargeSmall.lifetime - 1f;
parentizeEffects = true; parentizeEffects = true;
reload = 155f; reload = 155f;
@@ -493,7 +496,7 @@ public class UnitTypes{
}}; }};
shootStatus = StatusEffects.slow; shootStatus = StatusEffects.slow;
shootStatusDuration = bullet.lifetime + firstShotDelay; shootStatusDuration = bullet.lifetime + shoot.firstShotDelay;
}}); }});
weapons.add(new RepairBeamWeapon("repair-beam-weapon-center-large"){{ weapons.add(new RepairBeamWeapon("repair-beam-weapon-center-large"){{
@@ -547,7 +550,7 @@ public class UnitTypes{
shootStatusDuration = 60f * 2f; shootStatusDuration = 60f * 2f;
shootStatus = StatusEffects.unmoving; shootStatus = StatusEffects.unmoving;
firstShotDelay = Fx.greenLaserCharge.lifetime; shoot.firstShotDelay = Fx.greenLaserCharge.lifetime;
parentizeEffects = true; parentizeEffects = true;
bullet = new LaserBulletType(){{ bullet = new LaserBulletType(){{
@@ -870,8 +873,11 @@ public class UnitTypes{
rotate = true; rotate = true;
shadow = 12f; shadow = 12f;
recoil = 3f; recoil = 3f;
shots = 2;
spacing = 17f; shoot = new SpreadPattern(){{
shots = 2;
spread = 17f;
}};
bullet = new ShrapnelBulletType(){{ bullet = new ShrapnelBulletType(){{
length = 90f; length = 90f;
@@ -998,6 +1004,7 @@ public class UnitTypes{
range = 140f; range = 140f;
faceTarget = false; faceTarget = false;
armor = 3f; armor = 3f;
itemCapacity = 0;
targetFlags = new BlockFlag[]{BlockFlag.factory, null}; targetFlags = new BlockFlag[]{BlockFlag.factory, null};
circleTarget = true; circleTarget = true;
ammoType = new ItemAmmoType(Items.graphite); ammoType = new ItemAmmoType(Items.graphite);
@@ -1036,6 +1043,7 @@ public class UnitTypes{
lowAltitude = true; lowAltitude = true;
forceMultiTarget = true; forceMultiTarget = true;
armor = 5f; armor = 5f;
itemCapacity = 0;
targetFlags = new BlockFlag[]{BlockFlag.launchPad, BlockFlag.storage, BlockFlag.battery, null}; targetFlags = new BlockFlag[]{BlockFlag.launchPad, BlockFlag.storage, BlockFlag.battery, null};
engineOffset = 12f; engineOffset = 12f;
@@ -1047,7 +1055,7 @@ public class UnitTypes{
x = 7f; x = 7f;
rotate = true; rotate = true;
shake = 1f; shake = 1f;
shots = 2; shoot.shots = 2;
inaccuracy = 5f; inaccuracy = 5f;
velocityRnd = 0.2f; velocityRnd = 0.2f;
shootSound = Sounds.missile; shootSound = Sounds.missile;
@@ -1279,7 +1287,6 @@ public class UnitTypes{
ejectEffect = Fx.none; ejectEffect = Fx.none;
recoil = 2f; recoil = 2f;
shootSound = Sounds.missile; shootSound = Sounds.missile;
shots = 1;
velocityRnd = 0.5f; velocityRnd = 0.5f;
inaccuracy = 15f; inaccuracy = 15f;
alternate = true; alternate = true;
@@ -1586,7 +1593,6 @@ public class UnitTypes{
recoil = 4f; recoil = 4f;
shadow = 12f; shadow = 12f;
shots = 1;
inaccuracy = 3f; inaccuracy = 3f;
ejectEffect = Fx.casing3; ejectEffect = Fx.casing3;
shootSound = Sounds.artillery; shootSound = Sounds.artillery;
@@ -1623,8 +1629,9 @@ public class UnitTypes{
rotateSpeed = 4f; rotateSpeed = 4f;
rotate = true; rotate = true;
shots = 2; shoot.shots = 2;
shotDelay = 3f; shoot.shotDelay = 3f;
inaccuracy = 5f; inaccuracy = 5f;
velocityRnd = 0.1f; velocityRnd = 0.1f;
shootSound = Sounds.missile; shootSound = Sounds.missile;
@@ -1679,18 +1686,21 @@ public class UnitTypes{
shadow = 20f; shadow = 20f;
shootY = 2f; shootY = 4.5f;
recoil = 4f; recoil = 4f;
reload = 45f; reload = 45f;
shots = 6;
spacing = 10f;
velocityRnd = 0.4f; velocityRnd = 0.4f;
inaccuracy = 7f; inaccuracy = 7f;
ejectEffect = Fx.none; ejectEffect = Fx.none;
shake = 3f; shake = 1f;
shootSound = Sounds.missile; shootSound = Sounds.missile;
xRand = 8f;
shotDelay = 1f; shoot = new AlternatePattern(){{
shots = 6;
shotDelay = 1.5f;
spread = 4f;
barrels = 3;
}};
bullet = new MissileBulletType(4.2f, 42){{ bullet = new MissileBulletType(4.2f, 42){{
homingPower = 0.12f; homingPower = 0.12f;
@@ -1727,8 +1737,9 @@ public class UnitTypes{
ejectEffect = Fx.casing3; ejectEffect = Fx.casing3;
shootSound = Sounds.shootBig; shootSound = Sounds.shootBig;
shots = 3; shoot.shots = 3;
shotDelay = 4f; shoot.shotDelay = 4f;
inaccuracy = 1f; inaccuracy = 1f;
bullet = new BasicBulletType(7f, 57){{ bullet = new BasicBulletType(7f, 57){{
width = 13f; width = 13f;
@@ -1773,7 +1784,6 @@ public class UnitTypes{
shadow = 50f; shadow = 50f;
shootSound = Sounds.railgun; shootSound = Sounds.railgun;
shots = 1;
ejectEffect = Fx.none; ejectEffect = Fx.none;
bullet = new RailBulletType(){{ bullet = new RailBulletType(){{
@@ -1828,13 +1838,14 @@ public class UnitTypes{
mirror = false; mirror = false;
rotate = true; rotate = true;
reload = 90f; reload = 90f;
shots = 3;
shotDelay = 7f;
x = y = shootX = shootY = 0f; x = y = shootX = shootY = 0f;
shootSound = Sounds.mineDeploy; shootSound = Sounds.mineDeploy;
rotateSpeed = 180f; rotateSpeed = 180f;
targetAir = false; targetAir = false;
shoot.shots = 3;
shoot.shotDelay = 7f;
bullet = new BasicBulletType(){{ bullet = new BasicBulletType(){{
sprite = "mine-bullet"; sprite = "mine-bullet";
width = height = 8f; width = height = 8f;
@@ -2357,9 +2368,8 @@ public class UnitTypes{
x = 3f; x = 3f;
y = 0.5f; y = 0.5f;
rotate = true; rotate = true;
shots = 2; shoot.shots = 2;
shotDelay = 4f; shoot.shotDelay = 4f;
spacing = 0f;
ejectEffect = Fx.casing1; ejectEffect = Fx.casing1;
bullet = new BasicBulletType(3f, 11){{ bullet = new BasicBulletType(3f, 11){{
@@ -2396,10 +2406,13 @@ public class UnitTypes{
reload = 15f; reload = 15f;
x = 1f; x = 1f;
y = 2f; y = 2f;
shots = 2; shoot = new SpreadPattern(){{
spacing = 2f; shots = 2;
shotDelay = 3f;
spread = 2f;
}};
inaccuracy = 3f; inaccuracy = 3f;
shotDelay = 3f;
ejectEffect = Fx.casing1; ejectEffect = Fx.casing1;
bullet = new BasicBulletType(3.5f, 11){{ bullet = new BasicBulletType(3.5f, 11){{
@@ -2482,7 +2495,8 @@ public class UnitTypes{
heatColor = Color.valueOf("f9350f"); heatColor = Color.valueOf("f9350f");
cooldownTime = 30f; cooldownTime = 30f;
shots = 2; //TODO alternating double pattern
shoot.shots = 2;
bullet = new BasicBulletType(5f, 50){{ bullet = new BasicBulletType(5f, 50){{
sprite = "missile-large"; sprite = "missile-large";
@@ -2804,7 +2818,7 @@ public class UnitTypes{
shake = 3f; shake = 3f;
cooldownTime = 40f; cooldownTime = 40f;
shots = 3; shoot.shots = 3;
inaccuracy = 3f; inaccuracy = 3f;
velocityRnd = 0.33f; velocityRnd = 0.33f;
heatColor = Color.red; heatColor = Color.red;
@@ -2898,8 +2912,8 @@ public class UnitTypes{
cooldownTime = 20f; cooldownTime = 20f;
layerOffset = 0.02f; layerOffset = 0.02f;
shots = 3; shoot.shots = 3;
shotDelay = 3f; shoot.shotDelay = 3f;
inaccuracy = 2f; inaccuracy = 2f;
velocityRnd = 0.1f; velocityRnd = 0.1f;
heatColor = Color.red; heatColor = Color.red;
@@ -3100,8 +3114,8 @@ public class UnitTypes{
shootWarmupSpeed = 0.1f; shootWarmupSpeed = 0.1f;
shootY = 2f; shootY = 2f;
shootCone = 40f; shootCone = 40f;
shots = 3; shoot.shots = 3;
shotDelay = 5f; shoot.shotDelay = 5f;
inaccuracy = 28f; inaccuracy = 28f;
parts.add(new RegionPart("-blade"){{ parts.add(new RegionPart("-blade"){{
@@ -0,0 +1,18 @@
package mindustry.entities.pattern;
public class AlternatePattern extends ShotPattern{
/** number of barrels used for shooting. */
public int barrels = 2;
/** spread between barrels, in world units - not degrees. */
public float spread = 5f;
/** offset of barrel to start on */
public int barrelOffset = 0;
@Override
public void shoot(int totalShots, BulletHandler handler){
for(int i = 0; i < shots; i++){
float index = ((totalShots + i + barrelOffset) % barrels) - (barrels-1)/2f;
handler.shoot(index * spread, 0, 0f, firstShotDelay + shotDelay * i);
}
}
}
@@ -0,0 +1,25 @@
package mindustry.entities.pattern;
public class MultiPattern extends ShotPattern{
public ShotPattern source;
public ShotPattern[] dest = {};
public MultiPattern(ShotPattern source, ShotPattern... dest){
this.source = source;
this.dest = dest;
}
public MultiPattern(){
}
@Override
public void shoot(int totalShots, BulletHandler handler){
source.shoot(totalShots, (x, y, rotation, delay) -> {
for(var pattern : dest){
pattern.shoot(totalShots, (x2, y2, rot2, delay2) -> {
handler.shoot(x + x2, y + y2, rotation + rot2, delay + delay2);
});
}
});
}
}
@@ -1,12 +1,28 @@
package mindustry.entities.pattern; package mindustry.entities.pattern;
import arc.func.*; /** Handles different types of bullet patterns for shooting. */
import arc.math.geom.*;
//TODO
public class ShotPattern{ public class ShotPattern{
/** amount of shots per "trigger pull" */
public int shots = 1;
/** delay in ticks before first shot */
public float firstShotDelay = 0;
/** delay in ticks between shots */
public float shotDelay = 0;
public void shoot(float x, float y, Cons<Vec2> positionHandler){ /** Called on a single "trigger pull". This function should call the handler with any bullets that result. */
public void shoot(int totalShots, BulletHandler handler){
for(int i = 0; i < shots; i++){
handler.shoot(0, 0, 0, firstShotDelay + shotDelay * i);
}
}
public interface BulletHandler{
/**
* @param x x offset of bullet, should be transformed by weapon rotation
* @param y y offset of bullet, should be transformed by weapon rotation
* @param rotation rotation offset relative to weapon
* @param delay bullet delay in ticks
* */
void shoot(float x, float y, float rotation, float delay);
} }
} }
@@ -0,0 +1,26 @@
package mindustry.entities.pattern;
import arc.math.*;
public class SinePattern extends ShotPattern{
/** scaling applied to bullet index */
public float scl = 4f;
/** magnitude of sine curve for position displacement */
public float mag = 20f;
public SinePattern(float scl, float mag){
this.scl = scl;
this.mag = mag;
}
public SinePattern(){
}
@Override
public void shoot(int totalShots, BulletHandler handler){
for(int i = 0; i < shots; i++){
float angleOffset = Mathf.sin(i + totalShots, scl, mag);
handler.shoot(0, 0, angleOffset, firstShotDelay + shotDelay * i);
}
}
}
@@ -0,0 +1,14 @@
package mindustry.entities.pattern;
public class SpreadPattern extends ShotPattern{
/** spread between bullets, in degrees. */
public float spread = 5f;
@Override
public void shoot(int totalShots, BulletHandler handler){
for(int i = 0; i < shots; i++){
float angleOffset = i * spread - (shots - 1) * spread / 2f;
handler.shoot(0, 0, angleOffset, firstShotDelay + shotDelay * i);
}
}
}
@@ -30,6 +30,8 @@ public class WeaponMount{
public boolean rotate = false; public boolean rotate = false;
/** extra state for alternating weapons */ /** extra state for alternating weapons */
public boolean side; public boolean side;
/** total bullets fired from this mount; used for alternating patterns */
public int totalShots;
/** current bullet for continuous weapons */ /** current bullet for continuous weapons */
public @Nullable Bullet bullet; public @Nullable Bullet bullet;
/** sound loop for continuous weapons */ /** sound loop for continuous weapons */
+2 -1
View File
@@ -10,7 +10,8 @@ import static mindustry.Vars.*;
public class CacheLayer{ public class CacheLayer{
public static CacheLayer public static CacheLayer
water, mud, cryofluid, tar, slag, arkycite, space, normal, walls; water, mud, cryofluid, tar, slag, arkycite,
space, normal, walls;
public static CacheLayer[] all = {}; public static CacheLayer[] all = {};
@@ -7,8 +7,8 @@ import mindustry.world.*;
import static mindustry.maps.filters.FilterOption.*; import static mindustry.maps.filters.FilterOption.*;
public class BlendFilter extends GenerateFilter{ public class BlendFilter extends GenerateFilter{
float radius = 2f; public float radius = 2f;
Block block = Blocks.sand, floor = Blocks.sandWater, ignore = Blocks.air; public Block block = Blocks.sand, floor = Blocks.sandWater, ignore = Blocks.air;
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
@@ -7,8 +7,8 @@ import mindustry.world.*;
import static mindustry.maps.filters.FilterOption.*; import static mindustry.maps.filters.FilterOption.*;
public class ClearFilter extends GenerateFilter{ public class ClearFilter extends GenerateFilter{
protected Block target = Blocks.stone; public Block target = Blocks.stone;
protected Block replace = Blocks.air; public Block replace = Blocks.air;
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
@@ -9,7 +9,7 @@ import static mindustry.Vars.*;
/** Selects X spawns from the core spawn pool.*/ /** Selects X spawns from the core spawn pool.*/
public class CoreSpawnFilter extends GenerateFilter{ public class CoreSpawnFilter extends GenerateFilter{
int amount = 1; public int amount = 1;
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
@@ -5,7 +5,7 @@ import mindustry.maps.filters.FilterOption.*;
import mindustry.world.*; import mindustry.world.*;
public class DistortFilter extends GenerateFilter{ public class DistortFilter extends GenerateFilter{
float scl = 40, mag = 5; public float scl = 40, mag = 5;
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
@@ -8,7 +8,7 @@ import mindustry.world.*;
/** Selects X spawns from the spawn pool.*/ /** Selects X spawns from the spawn pool.*/
public class EnemySpawnFilter extends GenerateFilter{ public class EnemySpawnFilter extends GenerateFilter{
int amount = 1; public int amount = 1;
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
@@ -11,8 +11,8 @@ import static mindustry.Vars.*;
public class MedianFilter extends GenerateFilter{ public class MedianFilter extends GenerateFilter{
private static final IntSeq blocks = new IntSeq(), floors = new IntSeq(); private static final IntSeq blocks = new IntSeq(), floors = new IntSeq();
float radius = 2; public float radius = 2;
float percentile = 0.5f; public float percentile = 0.5f;
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
@@ -14,8 +14,8 @@ import mindustry.world.*;
public class MirrorFilter extends GenerateFilter{ public class MirrorFilter extends GenerateFilter{
private static final Vec2 v1 = new Vec2(), v2 = new Vec2(), v3 = new Vec2(); private static final Vec2 v1 = new Vec2(), v2 = new Vec2(), v3 = new Vec2();
int angle = 45; public int angle = 45;
boolean rotate = false; public boolean rotate = false;
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
@@ -9,11 +9,11 @@ import mindustry.maps.filters.FilterOption.*;
import mindustry.world.*; import mindustry.world.*;
public class OreMedianFilter extends GenerateFilter{ public class OreMedianFilter extends GenerateFilter{
private static IntSeq blocks = new IntSeq();
public float radius = 2; public float radius = 2;
public float percentile = 0.5f; public float percentile = 0.5f;
private IntSeq blocks = new IntSeq();
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
return new SliderOption[]{ return new SliderOption[]{
@@ -7,8 +7,8 @@ import mindustry.world.*;
import static mindustry.maps.filters.FilterOption.*; import static mindustry.maps.filters.FilterOption.*;
public class RiverNoiseFilter extends GenerateFilter{ public class RiverNoiseFilter extends GenerateFilter{
float scl = 40, threshold = 0f, threshold2 = 0.1f, octaves = 1, falloff = 0.5f; public float scl = 40, threshold = 0f, threshold2 = 0.1f, octaves = 1, falloff = 0.5f;
Block floor = Blocks.water, floor2 = Blocks.deepwater, block = Blocks.sandWall, target = Blocks.air; public Block floor = Blocks.water, floor2 = Blocks.deepwater, block = Blocks.sandWall, target = Blocks.air;
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
@@ -8,8 +8,8 @@ import mindustry.world.*;
import static mindustry.maps.filters.FilterOption.*; import static mindustry.maps.filters.FilterOption.*;
public class TerrainFilter extends GenerateFilter{ public class TerrainFilter extends GenerateFilter{
float scl = 40, threshold = 0.9f, octaves = 3f, falloff = 0.5f, magnitude = 1f, circleScl = 2.1f, tilt = 0f; public float scl = 40, threshold = 0.9f, octaves = 3f, falloff = 0.5f, magnitude = 1f, circleScl = 2.1f, tilt = 0f;
Block floor = Blocks.air, block = Blocks.stoneWall; public Block floor = Blocks.air, block = Blocks.stoneWall;
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
+10 -10
View File
@@ -1,10 +1,6 @@
package mindustry.mod; package mindustry.mod;
import arc.struct.*; import arc.struct.*;
import mindustry.type.*;
import mindustry.world.blocks.legacy.*;
import mindustry.world.consumers.*;
/** Generated class. Maps simple class names to concrete classes. For use in JSON mods. */ /** Generated class. Maps simple class names to concrete classes. For use in JSON mods. */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class ClassMap{ public class ClassMap{
@@ -68,6 +64,12 @@ public class ClassMap{
classes.put("SeqEffect", mindustry.entities.effect.SeqEffect.class); classes.put("SeqEffect", mindustry.entities.effect.SeqEffect.class);
classes.put("WaveEffect", mindustry.entities.effect.WaveEffect.class); classes.put("WaveEffect", mindustry.entities.effect.WaveEffect.class);
classes.put("WrapEffect", mindustry.entities.effect.WrapEffect.class); classes.put("WrapEffect", mindustry.entities.effect.WrapEffect.class);
classes.put("AlternatePattern", mindustry.entities.pattern.AlternatePattern.class);
classes.put("MultiPattern", mindustry.entities.pattern.MultiPattern.class);
classes.put("ShotPattern", mindustry.entities.pattern.ShotPattern.class);
classes.put("BulletHandler", mindustry.entities.pattern.ShotPattern.BulletHandler.class);
classes.put("SinePattern", mindustry.entities.pattern.SinePattern.class);
classes.put("SpreadPattern", mindustry.entities.pattern.SpreadPattern.class);
classes.put("Objectives", mindustry.game.Objectives.class); classes.put("Objectives", mindustry.game.Objectives.class);
classes.put("Objective", mindustry.game.Objectives.Objective.class); classes.put("Objective", mindustry.game.Objectives.Objective.class);
classes.put("OnPlanet", mindustry.game.Objectives.OnPlanet.class); classes.put("OnPlanet", mindustry.game.Objectives.OnPlanet.class);
@@ -76,8 +78,6 @@ public class ClassMap{
classes.put("Research", mindustry.game.Objectives.Research.class); classes.put("Research", mindustry.game.Objectives.Research.class);
classes.put("SectorComplete", mindustry.game.Objectives.SectorComplete.class); classes.put("SectorComplete", mindustry.game.Objectives.SectorComplete.class);
classes.put("AmmoType", mindustry.type.AmmoType.class); classes.put("AmmoType", mindustry.type.AmmoType.class);
classes.put("BlockSeq", PayloadSeq.class);
classes.put("BlockStack", PayloadStack.class);
classes.put("Category", mindustry.type.Category.class); classes.put("Category", mindustry.type.Category.class);
classes.put("CellLiquid", mindustry.type.CellLiquid.class); classes.put("CellLiquid", mindustry.type.CellLiquid.class);
classes.put("ErrorContent", mindustry.type.ErrorContent.class); classes.put("ErrorContent", mindustry.type.ErrorContent.class);
@@ -86,6 +86,8 @@ public class ClassMap{
classes.put("ItemStack", mindustry.type.ItemStack.class); classes.put("ItemStack", mindustry.type.ItemStack.class);
classes.put("Liquid", mindustry.type.Liquid.class); classes.put("Liquid", mindustry.type.Liquid.class);
classes.put("LiquidStack", mindustry.type.LiquidStack.class); classes.put("LiquidStack", mindustry.type.LiquidStack.class);
classes.put("PayloadSeq", mindustry.type.PayloadSeq.class);
classes.put("PayloadStack", mindustry.type.PayloadStack.class);
classes.put("Planet", mindustry.type.Planet.class); classes.put("Planet", mindustry.type.Planet.class);
classes.put("Publishable", mindustry.type.Publishable.class); classes.put("Publishable", mindustry.type.Publishable.class);
classes.put("Satellite", mindustry.type.Satellite.class); classes.put("Satellite", mindustry.type.Satellite.class);
@@ -238,6 +240,8 @@ public class ClassMap{
classes.put("HeatProducer", mindustry.world.blocks.heat.HeatProducer.class); classes.put("HeatProducer", mindustry.world.blocks.heat.HeatProducer.class);
classes.put("HeatProducerBuild", mindustry.world.blocks.heat.HeatProducer.HeatProducerBuild.class); classes.put("HeatProducerBuild", mindustry.world.blocks.heat.HeatProducer.HeatProducerBuild.class);
classes.put("LegacyBlock", mindustry.world.blocks.legacy.LegacyBlock.class); classes.put("LegacyBlock", mindustry.world.blocks.legacy.LegacyBlock.class);
classes.put("LegacyCommandCenter", mindustry.world.blocks.legacy.LegacyCommandCenter.class);
classes.put("CommandBuild", mindustry.world.blocks.legacy.LegacyCommandCenter.CommandBuild.class);
classes.put("LegacyMechPad", mindustry.world.blocks.legacy.LegacyMechPad.class); classes.put("LegacyMechPad", mindustry.world.blocks.legacy.LegacyMechPad.class);
classes.put("LegacyMechPadBuild", mindustry.world.blocks.legacy.LegacyMechPad.LegacyMechPadBuild.class); classes.put("LegacyMechPadBuild", mindustry.world.blocks.legacy.LegacyMechPad.LegacyMechPadBuild.class);
classes.put("LegacyUnitFactory", mindustry.world.blocks.legacy.LegacyUnitFactory.class); classes.put("LegacyUnitFactory", mindustry.world.blocks.legacy.LegacyUnitFactory.class);
@@ -297,10 +301,8 @@ public class ClassMap{
classes.put("BatteryBuild", mindustry.world.blocks.power.Battery.BatteryBuild.class); classes.put("BatteryBuild", mindustry.world.blocks.power.Battery.BatteryBuild.class);
classes.put("BeamNode", mindustry.world.blocks.power.BeamNode.class); classes.put("BeamNode", mindustry.world.blocks.power.BeamNode.class);
classes.put("BeamNodeBuild", mindustry.world.blocks.power.BeamNode.BeamNodeBuild.class); classes.put("BeamNodeBuild", mindustry.world.blocks.power.BeamNode.BeamNodeBuild.class);
classes.put("ConditionalConsumePower", ConsumePowerCondition.class);
classes.put("ConsumeGenerator", mindustry.world.blocks.power.ConsumeGenerator.class); classes.put("ConsumeGenerator", mindustry.world.blocks.power.ConsumeGenerator.class);
classes.put("ConsumeGeneratorBuild", mindustry.world.blocks.power.ConsumeGenerator.ConsumeGeneratorBuild.class); classes.put("ConsumeGeneratorBuild", mindustry.world.blocks.power.ConsumeGenerator.ConsumeGeneratorBuild.class);
classes.put("DynamicConsumePower", ConsumePowerDynamic.class);
classes.put("ImpactReactor", mindustry.world.blocks.power.ImpactReactor.class); classes.put("ImpactReactor", mindustry.world.blocks.power.ImpactReactor.class);
classes.put("ImpactReactorBuild", mindustry.world.blocks.power.ImpactReactor.ImpactReactorBuild.class); classes.put("ImpactReactorBuild", mindustry.world.blocks.power.ImpactReactor.ImpactReactorBuild.class);
classes.put("LightBlock", mindustry.world.blocks.power.LightBlock.class); classes.put("LightBlock", mindustry.world.blocks.power.LightBlock.class);
@@ -368,8 +370,6 @@ public class ClassMap{
classes.put("Unloader", mindustry.world.blocks.storage.Unloader.class); classes.put("Unloader", mindustry.world.blocks.storage.Unloader.class);
classes.put("ContainerStat", mindustry.world.blocks.storage.Unloader.ContainerStat.class); classes.put("ContainerStat", mindustry.world.blocks.storage.Unloader.ContainerStat.class);
classes.put("UnloaderBuild", mindustry.world.blocks.storage.Unloader.UnloaderBuild.class); classes.put("UnloaderBuild", mindustry.world.blocks.storage.Unloader.UnloaderBuild.class);
classes.put("CommandCenter", LegacyCommandCenter.class);
classes.put("CommandBuild", LegacyCommandCenter.CommandBuild.class);
classes.put("ControlCore", mindustry.world.blocks.units.ControlCore.class); classes.put("ControlCore", mindustry.world.blocks.units.ControlCore.class);
classes.put("DroneCenter", mindustry.world.blocks.units.DroneCenter.class); classes.put("DroneCenter", mindustry.world.blocks.units.DroneCenter.class);
classes.put("DroneCenterBuild", mindustry.world.blocks.units.DroneCenter.DroneCenterBuild.class); classes.put("DroneCenterBuild", mindustry.world.blocks.units.DroneCenter.DroneCenterBuild.class);
@@ -27,6 +27,7 @@ import mindustry.entities.bullet.*;
import mindustry.entities.effect.*; import mindustry.entities.effect.*;
import mindustry.entities.part.*; import mindustry.entities.part.*;
import mindustry.entities.part.DrawPart.*; import mindustry.entities.part.DrawPart.*;
import mindustry.entities.pattern.*;
import mindustry.game.*; import mindustry.game.*;
import mindustry.game.Objectives.*; import mindustry.game.Objectives.*;
import mindustry.gen.*; import mindustry.gen.*;
@@ -136,6 +137,13 @@ public class ContentParser{
readFields(result, data); readFields(result, data);
return result; return result;
}); });
put(ShotPattern.class, (type, data) -> {
var bc = resolve(data.getString("type", ""), ShotPattern.class);
data.remove("type");
var result = make(bc);
readFields(result, data);
return result;
});
put(DrawPart.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");
+18 -32
View File
@@ -15,6 +15,7 @@ import mindustry.content.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.entities.bullet.*; import mindustry.entities.bullet.*;
import mindustry.entities.part.*; import mindustry.entities.part.*;
import mindustry.entities.pattern.*;
import mindustry.entities.units.*; import mindustry.entities.units.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
@@ -55,10 +56,7 @@ public class Weapon implements Cloneable{
public float rotateSpeed = 20f; public float rotateSpeed = 20f;
/** weapon reload in frames */ /** weapon reload in frames */
public float reload; public float reload;
/** amount of shots per fire */
public int shots = 1;
/** spacing in degrees between multiple shots, if applicable */
public float spacing = 0;
/** inaccuracy of degrees of each shot */ /** inaccuracy of degrees of each shot */
public float inaccuracy = 0f; public float inaccuracy = 0f;
/** intensity and duration of each shot's screen shake */ /** intensity and duration of each shot's screen shake */
@@ -71,16 +69,12 @@ public class Weapon implements Cloneable{
public float shootX = 0f, shootY = 3f; public float shootX = 0f, shootY = 3f;
/** offsets of weapon position on unit */ /** offsets of weapon position on unit */
public float x = 5f, y = 0f; public float x = 5f, y = 0f;
/** random spread on the X axis */ /** pattern used for bullets */
public float xRand = 0f; public ShotPattern shoot = new ShotPattern();
/** radius of shadow drawn under the weapon; <0 to disable */ /** radius of shadow drawn under the weapon; <0 to disable */
public float shadow = -1f; public float shadow = -1f;
/** fraction of velocity that is random */ /** fraction of velocity that is random */
public float velocityRnd = 0f; 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. */ /** The half-radius of the cone in which shooting will start. */
public float shootCone = 5f; public float shootCone = 5f;
/** Cone in which the weapon can rotate relative to its mount. */ /** Cone in which the weapon can rotate relative to its mount. */
@@ -144,13 +138,13 @@ public class Weapon implements Cloneable{
t.add("[lightgray]" + Stat.inaccuracy.localized() + ": [white]" + (int)inaccuracy + " " + StatUnit.degrees.localized()); t.add("[lightgray]" + Stat.inaccuracy.localized() + ": [white]" + (int)inaccuracy + " " + StatUnit.degrees.localized());
} }
t.row(); t.row();
t.add("[lightgray]" + Stat.reload.localized() + ": " + (mirror ? "2x " : "") + "[white]" + Strings.autoFixed(60f / reload * shots, 2) + " " + StatUnit.perSecond.localized()); t.add("[lightgray]" + Stat.reload.localized() + ": " + (mirror ? "2x " : "") + "[white]" + Strings.autoFixed(60f / reload * shoot.shots, 2) + " " + StatUnit.perSecond.localized());
StatValues.ammo(ObjectMap.of(u, bullet)).display(t); StatValues.ammo(ObjectMap.of(u, bullet)).display(t);
} }
public float dps(){ public float dps(){
return (bullet.estimateDPS() / reload) * shots * 60f; return (bullet.estimateDPS() / reload) * shoot.shots * 60f;
} }
//TODO copy-pasted code //TODO copy-pasted code
@@ -371,34 +365,29 @@ public class Weapon implements Cloneable{
protected void shoot(Unit unit, WeaponMount mount, float shootX, float shootY, float rotation){ protected void shoot(Unit unit, WeaponMount mount, float shootX, float shootY, float rotation){
unit.apply(shootStatus, shootStatusDuration); unit.apply(shootStatus, shootStatusDuration);
if(firstShotDelay > 0){ if(shoot.firstShotDelay > 0){
chargeSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax)); chargeSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax));
bullet.chargeEffect.at(shootX, shootY, rotation, bullet.keepVelocity || parentizeEffects ? unit : null); bullet.chargeEffect.at(shootX, shootY, rotation, bullet.keepVelocity || parentizeEffects ? unit : null);
} }
//shot patterns should be able to customize: shoot.shoot(mount.totalShots, (xOffset, yOffset, angle, delay) -> {
//- the position of a specific bullet index if(delay > 0f){
//- the delay of a specific bullet index Time.run(delay, () -> setupBullet(unit, mount, xOffset, yOffset, angle));
//TODO merge with Turret behavior if possible
for(int i = 0; i < shots; i++){
float angleOffset = i * spacing - (shots - 1) * spacing / 2f;
if(firstShotDelay + shotDelay > 0f){
Time.run(i * shotDelay + firstShotDelay, () -> shoot(unit, mount, angleOffset));
}else{ }else{
shoot(unit, mount, angleOffset); setupBullet(unit, mount, xOffset, yOffset, angle);
} }
} mount.totalShots ++;
});
} }
protected void shoot(Unit unit, WeaponMount mount, float angleOffset){ protected void setupBullet(Unit unit, WeaponMount mount, float xOffset, float yOffset, float angleOffset){
float float
weaponRotation = unit.rotation - 90 + (rotate ? mount.rotation : 0), weaponRotation = unit.rotation - 90 + (rotate ? mount.rotation : 0),
mountX = unit.x + Angles.trnsx(unit.rotation - 90, x, y), mountX = unit.x + Angles.trnsx(unit.rotation - 90, x, y),
mountY = unit.y + Angles.trnsy(unit.rotation - 90, x, y), mountY = unit.y + Angles.trnsy(unit.rotation - 90, x, y),
bulletX = mountX + Angles.trnsx(weaponRotation, this.shootX, this.shootY), bulletX = mountX + Angles.trnsx(weaponRotation, this.shootX, this.shootY) + Angles.trnsx(weaponRotation, xOffset, yOffset),
bulletY = mountY + Angles.trnsy(weaponRotation, this.shootX, this.shootY), bulletY = mountY + Angles.trnsy(weaponRotation, this.shootX, this.shootY) + Angles.trnsy(weaponRotation, xOffset, yOffset),
shootAngle = bulletRotation(unit, mount, bulletX, bulletY), shootAngle = bulletRotation(unit, mount, bulletX, bulletY) + angleOffset,
lifeScl = bullet.scaleVelocity ? Mathf.clamp(Mathf.dst(shootX, shootY, mount.aimX, mount.aimY) / bullet.range) : 1f; lifeScl = bullet.scaleVelocity ? Mathf.clamp(Mathf.dst(shootX, shootY, mount.aimX, mount.aimY) / bullet.range) : 1f;
bullet(mount, unit, bulletX, bulletY, angleOffset + shootAngle + Mathf.range(inaccuracy), lifeScl, shootAngle, mountX, mountY); bullet(mount, unit, bulletX, bulletY, angleOffset + shootAngle + Mathf.range(inaccuracy), lifeScl, shootAngle, mountX, mountY);
@@ -407,10 +396,7 @@ public class Weapon implements Cloneable{
protected void bullet(WeaponMount mount, Unit unit, float shootX, float shootY, float angle, float lifescl, float mountRotation, float mountX, float mountY){ protected void bullet(WeaponMount mount, Unit unit, float shootX, float shootY, float angle, float lifescl, float mountRotation, float mountX, float mountY){
if(!unit.isAdded()) return; if(!unit.isAdded()) return;
//TODO should be part of shoot pattern. mount.bullet = bullet.create(unit, unit.team, shootX, shootY, angle, (1f - velocityRnd) + Mathf.random(velocityRnd), lifescl);
float xr = Mathf.range(xRand), x = shootX + Angles.trnsx(angle, 0, xr), y = shootY + Angles.trnsy(angle, 0, xr);
mount.bullet = bullet.create(unit, unit.team, x, y, angle, (1f - velocityRnd) + Mathf.random(velocityRnd), lifescl);
if(!continuous){ if(!continuous){
shootSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax)); shootSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax));
@@ -538,8 +538,8 @@ public class Turret extends ReloadTurret{
for(int c = 0; c < count; c++){ for(int c = 0; c < count; c++){
float i = (shotCounter % shots) - (shots-1)/2f; float i = (shotCounter % shots) - (shots-1)/2f;
bulletOffset.trns(rotation - 90, (spread) * i + Mathf.range(xRand), shootLength); bulletOffset.trns(rotation - 90, (spread) * i + Mathf.range(xRand), shootLength);
bullet(type, rotation + Mathf.range(inaccuracy + type.inaccuracy)); bullet(type, rotation + Mathf.range(inaccuracy + type.inaccuracy));
shotCounter ++; shotCounter ++;
} }
@@ -84,7 +84,8 @@ public class ScriptMainGenerator{
"mindustry.game.Objectives", "mindustry.game.Objectives",
"mindustry.world.blocks", "mindustry.world.blocks",
"mindustry.world.draw", "mindustry.world.draw",
"mindustry.type" "mindustry.type",
"mindustry.entities.pattern"
); );
String classTemplate = "package mindustry.mod;\n" + String classTemplate = "package mindustry.mod;\n" +