WIP point laser turret
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 629 B After Width: | Height: | Size: 629 B |
Before Width: | Height: | Size: 639 B After Width: | Height: | Size: 639 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 783 B After Width: | Height: | Size: 783 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
@ -380,9 +380,10 @@ editor.mapinfo = Map Info
|
||||
editor.author = Author:
|
||||
editor.description = Description:
|
||||
editor.nodescription = A map must have a description of at least 4 characters before being published.
|
||||
editor.waves = Waves:
|
||||
editor.rules = Rules:
|
||||
editor.generation = Generation:
|
||||
editor.waves = Waves
|
||||
editor.rules = Rules
|
||||
editor.generation = Generation
|
||||
editor.objectives = Objectives
|
||||
editor.ingame = Edit In-Game
|
||||
editor.playtest = Playtest
|
||||
editor.publish.workshop = Publish On Workshop
|
||||
@ -395,6 +396,8 @@ editor.filters.type = Map Type:
|
||||
editor.filters.search = Search In:
|
||||
editor.filters.author = Author
|
||||
editor.filters.description = Description
|
||||
editor.shiftx = Shift X
|
||||
editor.shifty = Shift Y
|
||||
workshop = Workshop
|
||||
waves.title = Waves
|
||||
waves.remove = Remove
|
||||
@ -2067,7 +2070,3 @@ unit.merui.name = Merui
|
||||
unit.anthicus.name = Anthicus
|
||||
unit.elude.name = Elude
|
||||
unit.obviate.name = Obviate
|
||||
sector.two.name = Two
|
||||
sector.three.name = Three
|
||||
sector.four.name = Four
|
||||
sector.five.name = Five
|
||||
|
@ -568,3 +568,4 @@
|
||||
63116=shielded-wall|block-shielded-wall-ui
|
||||
63115=fracture|block-fracture-ui
|
||||
63114=renale|unit-renale-ui
|
||||
63113=lustre|block-lustre-ui
|
||||
|
@ -8,6 +8,7 @@ import mindustry.entities.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.entities.effect.*;
|
||||
import mindustry.entities.part.*;
|
||||
import mindustry.entities.part.DrawPart.*;
|
||||
import mindustry.entities.pattern.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
@ -23,8 +24,6 @@ import mindustry.world.blocks.heat.*;
|
||||
import mindustry.world.blocks.legacy.*;
|
||||
import mindustry.world.blocks.liquid.*;
|
||||
import mindustry.world.blocks.logic.*;
|
||||
import mindustry.world.blocks.payloads.PayloadConveyor;
|
||||
import mindustry.world.blocks.payloads.PayloadRouter;
|
||||
import mindustry.world.blocks.payloads.*;
|
||||
import mindustry.world.blocks.power.*;
|
||||
import mindustry.world.blocks.production.*;
|
||||
@ -135,7 +134,7 @@ public class Blocks{
|
||||
duo, scatter, scorch, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, foreshadow, spectre, meltdown, segment, parallax, tsunami,
|
||||
|
||||
//turrets - erekir
|
||||
breach, diffuse, sublimate, titan, disperse, afflict, fracture,
|
||||
breach, diffuse, sublimate, titan, disperse, afflict, lustre,
|
||||
|
||||
//units
|
||||
groundFactory, airFactory, navalFactory,
|
||||
@ -4081,7 +4080,6 @@ public class Blocks{
|
||||
limitRange(-5f);
|
||||
}};
|
||||
|
||||
//TODO WIP
|
||||
afflict = new PowerTurret("afflict"){{
|
||||
requirements(Category.turret, with(Items.surgeAlloy, 100, Items.silicon, 200, Items.graphite, 250, Items.oxide, 40));
|
||||
|
||||
@ -4197,61 +4195,33 @@ public class Blocks{
|
||||
limitRange(9f);
|
||||
}};
|
||||
|
||||
if(false)
|
||||
fracture = new ItemTurret("fracture"){{
|
||||
lustre = new ContinuousTurret("lustre"){{
|
||||
requirements(Category.turret, with(Items.beryllium, 150, Items.silicon, 200, Items.graphite, 200, Items.carbide, 50));
|
||||
|
||||
ammo(
|
||||
Items.tungsten, new BasicBulletType(8f, 41){{
|
||||
knockback = 4f;
|
||||
width = 25f;
|
||||
hitSize = 7f;
|
||||
height = 20f;
|
||||
shootEffect = Fx.shootBigColor;
|
||||
smokeEffect = Fx.shootSmokeSquareSparse;
|
||||
ammoMultiplier = 1;
|
||||
hitColor = backColor = trailColor = Color.valueOf("ea8878");
|
||||
frontColor = Color.valueOf("feb380");
|
||||
trailWidth = 6f;
|
||||
trailLength = 3;
|
||||
hitEffect = despawnEffect = Fx.hitSquaresColor;
|
||||
buildingDamageMultiplier = 0.2f;
|
||||
range = 100f;
|
||||
|
||||
if(false)
|
||||
spawnBullets.add(new BulletType(){{
|
||||
instantDisappear = true;
|
||||
lightning = 6;
|
||||
lightningLength = 10;
|
||||
lightningLengthRand = 10;
|
||||
lightningColor = Color.valueOf("ff6214");
|
||||
lightningCone = 20f;
|
||||
damage = 30;
|
||||
despawnEffect = hitEffect = Fx.none;
|
||||
}});
|
||||
}}
|
||||
);
|
||||
|
||||
coolantMultiplier = 6f;
|
||||
shake = 1f;
|
||||
|
||||
//shoot = new ShootAlternate(){{
|
||||
// shots = 3;
|
||||
// barrels = 3;
|
||||
//}};
|
||||
shootType = new PointLaserBulletType(){{
|
||||
damage = 150f;
|
||||
buildingDamageMultiplier = 0.3f;
|
||||
hitColor = Color.valueOf("fd9e81");
|
||||
}};
|
||||
|
||||
drawer = new DrawTurret("reinforced-"){{
|
||||
var heatp = PartProgress.warmup.blend(p -> Mathf.absin(2f, 1f) * p.warmup, 0.2f);
|
||||
|
||||
parts.add(new RegionPart("-blade"){{
|
||||
progress = PartProgress.warmup;
|
||||
heatProgress = PartProgress.warmup.blend(PartProgress.recoil, 0.2f);
|
||||
heatProgress = PartProgress.warmup;
|
||||
heatColor = Color.valueOf("ff6214");
|
||||
mirror = true;
|
||||
under = true;
|
||||
moveX = 2f;
|
||||
moveRot = -7f;
|
||||
moves.add(new PartMove(PartProgress.recoil, 0f, -2f, 3f));
|
||||
moves.add(new PartMove(PartProgress.warmup, 0f, -2f, 3f));
|
||||
}},
|
||||
new RegionPart("-inner"){{
|
||||
progress = PartProgress.recoil;
|
||||
heatProgress = heatp;
|
||||
progress = PartProgress.warmup;
|
||||
heatColor = Color.valueOf("ff6214");
|
||||
mirror = true;
|
||||
under = false;
|
||||
@ -4259,26 +4229,32 @@ public class Blocks{
|
||||
moveY = -8f;
|
||||
}},
|
||||
new RegionPart("-mid"){{
|
||||
heatProgress = PartProgress.warmup.blend(PartProgress.recoil, 0.2f);
|
||||
heatProgress = heatp;
|
||||
progress = PartProgress.warmup;
|
||||
heatColor = Color.valueOf("ff6214");
|
||||
moveY = -8f;
|
||||
progress = PartProgress.recoil;
|
||||
mirror = false;
|
||||
under = true;
|
||||
}});
|
||||
}};
|
||||
|
||||
shootY = 11f;
|
||||
shootWarmupSpeed = 0.08f;
|
||||
shootCone = 360f;
|
||||
|
||||
aimChangeSpeed = 0.9f;
|
||||
rotateSpeed = 0.9f;
|
||||
|
||||
shootY = 0.5f;
|
||||
outlineColor = Pal.darkOutline;
|
||||
size = 4;
|
||||
envEnabled |= Env.space;
|
||||
reload = 30f;
|
||||
recoil = 2f;
|
||||
range = 125;
|
||||
range = 250f;
|
||||
scaledHealth = 210;
|
||||
rotateSpeed = 3f;
|
||||
|
||||
coolant = consume(new ConsumeLiquid(Liquids.water, 15f / 60f));
|
||||
//TODO is this a good idea to begin with?
|
||||
unitSort = UnitSorts.strongest;
|
||||
|
||||
consumeLiquid(Liquids.nitrogen, 5f / 60f);
|
||||
}};
|
||||
|
||||
//TODO 3 more turrets.
|
||||
|
@ -1003,6 +1003,11 @@ public class Fx{
|
||||
Fill.circle(e.x, e.y, e.rotation * e.fout());
|
||||
}).layer(Layer.bullet - 0.001f),
|
||||
|
||||
colorTrail = new Effect(50, e -> {
|
||||
color(e.color);
|
||||
Fill.circle(e.x, e.y, e.rotation * e.fout());
|
||||
}),
|
||||
|
||||
absorb = new Effect(12, e -> {
|
||||
color(Pal.accent);
|
||||
stroke(2f * e.fout());
|
||||
|
@ -298,6 +298,39 @@ public class Damage{
|
||||
units.each(cons);
|
||||
}
|
||||
|
||||
/**
|
||||
* Damages entities on a point.
|
||||
* Only enemies of the specified team are damaged.
|
||||
*/
|
||||
public static void collidePoint(Bullet hitter, Team team, Effect effect, float x, float y){
|
||||
|
||||
if(hitter.type.collidesGround){
|
||||
Building build = world.build(World.toTile(x), World.toTile(y));
|
||||
|
||||
if(build != null && hitter.damage > 0){
|
||||
float health = build.health;
|
||||
|
||||
if(build.team != team && build.collide(hitter)){
|
||||
build.collision(hitter);
|
||||
hitter.type.hit(hitter, x, y);
|
||||
}
|
||||
|
||||
//try to heal the tile
|
||||
if(hitter.type.testCollision(hitter, build)){
|
||||
hitter.type.hitTile(hitter, build, x, y, health, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Units.nearbyEnemies(team, rect.setCentered(x, y, 1f), u -> {
|
||||
if(u.checkTarget(hitter.type.collidesAir, hitter.type.collidesGround) && u.hittable()){
|
||||
effect.at(x, y);
|
||||
u.collision(hitter, x, y);
|
||||
hitter.collision(u, x, y);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts forward in a line.
|
||||
* @return the first encountered object.
|
||||
|
@ -4,7 +4,7 @@ import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
/** Basic continuous bullet type that does not draw itself. Essentially abstract. */
|
||||
/** Basic continuous (line) bullet type that does not draw itself. Essentially abstract. */
|
||||
public class ContinuousBulletType extends BulletType{
|
||||
public float length = 220f;
|
||||
public float shake = 0f;
|
||||
|
85
core/src/mindustry/entities/bullet/PointLaserBulletType.java
Normal file
@ -0,0 +1,85 @@
|
||||
package mindustry.entities.bullet;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
|
||||
/** A continuous bullet type that only damages in a point. */
|
||||
public class PointLaserBulletType extends BulletType{
|
||||
public String sprite = "drill-laser";
|
||||
public TextureRegion laser, laserEnd;
|
||||
|
||||
public Color color = Color.white;
|
||||
|
||||
public Effect beamEffect = Fx.colorTrail;
|
||||
public float beamEffectInterval = 3f, beamEffectSize = 3.5f;
|
||||
|
||||
public float oscScl = 2f, oscMag = 0.3f;
|
||||
public float damageInterval = 5f;
|
||||
|
||||
public float shake = 0f;
|
||||
|
||||
public PointLaserBulletType(){
|
||||
removeAfterPierce = false;
|
||||
speed = 0f;
|
||||
despawnEffect = Fx.none;
|
||||
shootEffect = Fx.none;
|
||||
lifetime = 20f;
|
||||
impact = true;
|
||||
keepVelocity = false;
|
||||
collides = false;
|
||||
pierce = true;
|
||||
hittable = false;
|
||||
absorbable = false;
|
||||
optimalLifeFract = 0.5f;
|
||||
|
||||
//just make it massive, users of this bullet can adjust as necessary
|
||||
drawSize = 1000f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float estimateDPS(){
|
||||
return damage * 100f / damageInterval * 3f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
super.load();
|
||||
|
||||
laser = Core.atlas.find(sprite);
|
||||
laserEnd = Core.atlas.find(sprite + "-end");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Bullet b){
|
||||
super.draw(b);
|
||||
|
||||
Draw.color(color);
|
||||
Drawf.laser(laser, laserEnd, b.x, b.y, b.aimX, b.aimY, b.fslope() * (1f - oscMag + Mathf.absin(Time.time, oscScl, oscMag)));
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Bullet b){
|
||||
super.update(b);
|
||||
|
||||
if(b.timer.get(0, damageInterval)){
|
||||
Damage.collidePoint(b, b.team, hitEffect, b.aimX, b.aimY);
|
||||
}
|
||||
|
||||
if(b.timer.get(1, beamEffectInterval)){
|
||||
beamEffect.at(b.aimX, b.aimY, beamEffectSize * b.fslope(), hitColor);
|
||||
}
|
||||
|
||||
if(shake > 0){
|
||||
Effect.shake(shake, shake, b);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package mindustry.world.blocks.defense.turrets;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.gen.*;
|
||||
@ -12,6 +13,8 @@ import mindustry.world.meta.*;
|
||||
/** A turret that fires a continuous beam bullet with no reload or coolant necessary. The bullet only disappears when the turret stops shooting. */
|
||||
public class ContinuousTurret extends Turret{
|
||||
public BulletType shootType = Bullets.placeholder;
|
||||
/** Speed at which the turret can change its bullet "aim" distance. This is only used for point laser bullets. */
|
||||
public float aimChangeSpeed = Float.POSITIVE_INFINITY;
|
||||
|
||||
public ContinuousTurret(String name){
|
||||
super(name);
|
||||
@ -33,6 +36,7 @@ public class ContinuousTurret extends Turret{
|
||||
//TODO LaserTurret shared code
|
||||
public class ContinuousTurretBuild extends TurretBuild{
|
||||
public Seq<BulletEntry> bullets = new Seq<>();
|
||||
public float lastLength = size * 4f;
|
||||
|
||||
@Override
|
||||
protected void updateCooling(){
|
||||
@ -85,6 +89,18 @@ public class ContinuousTurret extends Turret{
|
||||
entry.bullet.rotation(angle);
|
||||
entry.bullet.set(bulletX, bulletY);
|
||||
|
||||
//target length of laser
|
||||
float shootLength = Math.min(dst(targetPos), range);
|
||||
//current length of laser
|
||||
float curLength = dst(entry.bullet.aimX, entry.bullet.aimY);
|
||||
//resulting length of the bullet (smoothed)
|
||||
float resultLength = Mathf.approachDelta(curLength, shootLength, aimChangeSpeed);
|
||||
//actual aim end point based on length
|
||||
Tmp.v1.trns(rotation, lastLength = resultLength).add(x, y);
|
||||
|
||||
entry.bullet.aimX = Tmp.v1.x;
|
||||
entry.bullet.aimY = Tmp.v1.y;
|
||||
|
||||
if(isShooting() && hasAmmo()){
|
||||
entry.bullet.time = entry.bullet.lifetime * entry.bullet.type.optimalLifeFract * shootWarmup;
|
||||
entry.bullet.keepAlive = true;
|
||||
@ -122,6 +138,11 @@ public class ContinuousTurret extends Turret{
|
||||
protected void handleBullet(@Nullable Bullet bullet, float offsetX, float offsetY, float angleOffset){
|
||||
if(bullet != null){
|
||||
bullets.add(new BulletEntry(bullet, offsetX, offsetY, angleOffset, 0f));
|
||||
|
||||
//make sure the length updates to the last set value
|
||||
Tmp.v1.trns(rotation, shootY + lastLength).add(x, y);
|
||||
bullet.aimX = Tmp.v1.x;
|
||||
bullet.aimY = Tmp.v1.y;
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,5 +150,26 @@ public class ContinuousTurret extends Turret{
|
||||
public boolean shouldActiveSound(){
|
||||
return bullets.any();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte version(){
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
|
||||
write.f(lastLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
|
||||
if(revision >= 3){
|
||||
lastLength = read.f();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|