Added tractor beam turret
BIN
core/assets-raw/sprites/blocks/defense/parallax.png
Normal file
|
After Width: | Height: | Size: 758 B |
BIN
core/assets-raw/sprites/effects/parallax-laser-end.png
Normal file
|
After Width: | Height: | Size: 415 B |
BIN
core/assets-raw/sprites/effects/parallax-laser.png
Normal file
|
After Width: | Height: | Size: 111 B |
@@ -708,6 +708,7 @@ keybinds.mobile = [scarlet]Most keybinds here are not functional on mobile. Only
|
|||||||
category.general.name = General
|
category.general.name = General
|
||||||
category.view.name = View
|
category.view.name = View
|
||||||
category.multiplayer.name = Multiplayer
|
category.multiplayer.name = Multiplayer
|
||||||
|
category.blocks.name = Block Select
|
||||||
command.attack = Attack
|
command.attack = Attack
|
||||||
command.rally = Rally
|
command.rally = Rally
|
||||||
command.retreat = Retreat
|
command.retreat = Retreat
|
||||||
|
|||||||
@@ -252,3 +252,4 @@
|
|||||||
63492=exponential-reconstructor|block-exponential-reconstructor-medium
|
63492=exponential-reconstructor|block-exponential-reconstructor-medium
|
||||||
63491=tetrative-reconstructor|block-tetrative-reconstructor-medium
|
63491=tetrative-reconstructor|block-tetrative-reconstructor-medium
|
||||||
63490=resupply-point|block-resupply-point-medium
|
63490=resupply-point|block-resupply-point-medium
|
||||||
|
63489=parallax|block-parallax-medium
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 777 B After Width: | Height: | Size: 780 B |
|
Before Width: | Height: | Size: 852 KiB After Width: | Height: | Size: 849 KiB |
|
Before Width: | Height: | Size: 184 KiB After Width: | Height: | Size: 185 KiB |
|
Before Width: | Height: | Size: 375 KiB After Width: | Height: | Size: 376 KiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 378 KiB After Width: | Height: | Size: 380 KiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.1 MiB |
@@ -88,7 +88,7 @@ public class WaveSpawner{
|
|||||||
Building firstCore = state.teams.playerCores().first();
|
Building firstCore = state.teams.playerCores().first();
|
||||||
for(Building core : state.rules.waveTeam.cores()){
|
for(Building core : state.rules.waveTeam.cores()){
|
||||||
Tmp.v1.set(firstCore).sub(core).limit(coreMargin + core.block().size * tilesize);
|
Tmp.v1.set(firstCore).sub(core).limit(coreMargin + core.block().size * tilesize);
|
||||||
cons.accept(core.x() + Tmp.v1.x, core.y() + Tmp.v1.y, false);
|
cons.accept(core.x + Tmp.v1.x, core.y + Tmp.v1.y, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ public class WaveSpawner{
|
|||||||
|
|
||||||
if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam)){
|
if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam)){
|
||||||
for(Building core : state.teams.get(state.rules.waveTeam).cores){
|
for(Building core : state.teams.get(state.rules.waveTeam).cores){
|
||||||
cons.get(core.x(), core.y());
|
cons.get(core.x, core.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class Blocks implements ContentList{
|
|||||||
coreShard, coreFoundation, coreNucleus, vault, container, unloader,
|
coreShard, coreFoundation, coreNucleus, vault, container, unloader,
|
||||||
|
|
||||||
//turrets
|
//turrets
|
||||||
duo, scatter, scorch, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, segment,
|
duo, scatter, scorch, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, segment, parallax,
|
||||||
|
|
||||||
//units
|
//units
|
||||||
groundFactory, airFactory, navalFactory,
|
groundFactory, airFactory, navalFactory,
|
||||||
@@ -1339,7 +1339,7 @@ public class Blocks implements ContentList{
|
|||||||
Items.metaglass, Bullets.flakGlass
|
Items.metaglass, Bullets.flakGlass
|
||||||
);
|
);
|
||||||
reloadTime = 18f;
|
reloadTime = 18f;
|
||||||
range = 170f;
|
range = 160f;
|
||||||
size = 2;
|
size = 2;
|
||||||
burstSpacing = 5f;
|
burstSpacing = 5f;
|
||||||
shots = 2;
|
shots = 2;
|
||||||
@@ -1655,6 +1655,20 @@ public class Blocks implements ContentList{
|
|||||||
health = 190 * size * size;
|
health = 190 * size * size;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
parallax = new TractorBeamTurret("parallax"){{
|
||||||
|
requirements(Category.turret, with(Items.silicon, 120, Items.titanium, 90));
|
||||||
|
|
||||||
|
hasPower = true;
|
||||||
|
size = 2;
|
||||||
|
force = 3f;
|
||||||
|
range = 170f;
|
||||||
|
damage = 0.08f;
|
||||||
|
health = 160 * size * size;
|
||||||
|
rotateSpeed = 10;
|
||||||
|
|
||||||
|
consumes.power(3f);
|
||||||
|
}};
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
//region units
|
//region units
|
||||||
|
|
||||||
|
|||||||
@@ -657,8 +657,8 @@ public class NetServer implements ApplicationListener{
|
|||||||
//read sync data so it can be used for interpolation for the server
|
//read sync data so it can be used for interpolation for the server
|
||||||
unit.readSyncManual(fbuffer);
|
unit.readSyncManual(fbuffer);
|
||||||
}else{
|
}else{
|
||||||
player.x(x);
|
player.x = x;
|
||||||
player.y(y);
|
player.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.lastRecievedClientSnapshot = snapshotID;
|
connection.lastRecievedClientSnapshot = snapshotID;
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public class Damage{
|
|||||||
if(tile != null && !collidedBlocks.contains(tile.pos()) && tile.team() != team && tile.collide(hitter)){
|
if(tile != null && !collidedBlocks.contains(tile.pos()) && tile.team() != team && tile.collide(hitter)){
|
||||||
tile.collision(hitter);
|
tile.collision(hitter);
|
||||||
collidedBlocks.add(tile.pos());
|
collidedBlocks.add(tile.pos());
|
||||||
hitter.type().hit(hitter, tile.x(), tile.y());
|
hitter.type().hit(hitter, tile.x, tile.y);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class HealBulletType extends BulletType{
|
|||||||
super.hit(b);
|
super.hit(b);
|
||||||
|
|
||||||
if(tile.team() == b.team() && !(tile.block() instanceof BuildBlock)){
|
if(tile.team() == b.team() && !(tile.block() instanceof BuildBlock)){
|
||||||
Fx.healBlockFull.at(tile.x(), tile.y(), tile.block().size, Pal.heal);
|
Fx.healBlockFull.at(tile.x, tile.y, tile.block().size, Pal.heal);
|
||||||
tile.heal(healPercent / 100f * tile.maxHealth());
|
tile.heal(healPercent / 100f * tile.maxHealth());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class MassDriverBolt extends BulletType{
|
|||||||
if(Angles.near(angleTo, baseAngle, 2f)){
|
if(Angles.near(angleTo, baseAngle, 2f)){
|
||||||
intersect = true;
|
intersect = true;
|
||||||
//snap bullet position back; this is used for low-FPS situations
|
//snap bullet position back; this is used for low-FPS situations
|
||||||
b.set(data.to.x() + Angles.trnsx(baseAngle, hitDst), data.to.y() + Angles.trnsy(baseAngle, hitDst));
|
b.set(data.to.x + Angles.trnsx(baseAngle, hitDst), data.to.y + Angles.trnsy(baseAngle, hitDst));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -514,7 +514,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
return flow;
|
return flow;
|
||||||
}else if(ofract > 0.1f && fract > 0.1f){
|
}else if(ofract > 0.1f && fract > 0.1f){
|
||||||
//TODO these are incorrect effect positions
|
//TODO these are incorrect effect positions
|
||||||
float fx = (x + next.x()) / 2f, fy = (y + next.y()) / 2f;
|
float fx = (x + next.x) / 2f, fy = (y + next.y) / 2f;
|
||||||
|
|
||||||
Liquid other = next.liquids().current();
|
Liquid other = next.liquids().current();
|
||||||
if((other.flammability > 0.3f && liquid.temperature > 0.7f) || (liquid.flammability > 0.3f && other.temperature > 0.7f)){
|
if((other.flammability > 0.3f && liquid.temperature > 0.7f) || (liquid.flammability > 0.3f && other.temperature > 0.7f)){
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
|
|||||||
transient float drownTime;
|
transient float drownTime;
|
||||||
transient float splashTimer;
|
transient float splashTimer;
|
||||||
|
|
||||||
|
boolean checkTarget(boolean targetAir, boolean targetGround){
|
||||||
|
return (isGrounded() && targetGround) || (isFlying() && targetAir);
|
||||||
|
}
|
||||||
|
|
||||||
boolean isGrounded(){
|
boolean isGrounded(){
|
||||||
return elevation < 0.001f;
|
return elevation < 0.001f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ abstract class HealthComp implements Entityc{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void damageContinuous(float amount){
|
void damageContinuous(float amount){
|
||||||
damage(amount * Time.delta(), hitTime <= -20 + hitDuration);
|
damage(amount * Time.delta(), hitTime <= -10 + hitDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void damageContinuousPierce(float amount){
|
void damageContinuousPierce(float amount){
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package mindustry.entities.comp;
|
package mindustry.entities.comp;
|
||||||
|
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.async.PhysicsProcess.*;
|
import mindustry.async.PhysicsProcess.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
@@ -11,6 +12,7 @@ import mindustry.gen.*;
|
|||||||
@Component
|
@Component
|
||||||
abstract class PhysicsComp implements Velc, Hitboxc, Flyingc{
|
abstract class PhysicsComp implements Velc, Hitboxc, Flyingc{
|
||||||
@Import float hitSize;
|
@Import float hitSize;
|
||||||
|
@Import Vec2 vel;
|
||||||
|
|
||||||
transient PhysicRef physref;
|
transient PhysicRef physref;
|
||||||
|
|
||||||
@@ -21,6 +23,10 @@ abstract class PhysicsComp implements Velc, Hitboxc, Flyingc{
|
|||||||
|
|
||||||
void impulse(float x, float y){
|
void impulse(float x, float y){
|
||||||
float mass = mass();
|
float mass = mass();
|
||||||
vel().add(x / mass, y / mass);
|
vel.add(x / mass, y / mass);
|
||||||
|
}
|
||||||
|
|
||||||
|
void impulse(Vec2 v){
|
||||||
|
impulse(v.x, v.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,13 +177,13 @@ public class Drawf{
|
|||||||
Shaders.build.time = -time / 20f;
|
Shaders.build.time = -time / 20f;
|
||||||
|
|
||||||
Draw.shader(Shaders.build);
|
Draw.shader(Shaders.build);
|
||||||
Draw.rect(region, t.x(), t.y(), rotation);
|
Draw.rect(region, t.x, t.y, rotation);
|
||||||
Draw.shader();
|
Draw.shader();
|
||||||
|
|
||||||
Draw.color(Pal.accent);
|
Draw.color(Pal.accent);
|
||||||
Draw.alpha(speed);
|
Draw.alpha(speed);
|
||||||
|
|
||||||
Lines.lineAngleCenter(t.x() + Mathf.sin(time, 20f, Vars.tilesize / 2f * t.block().size - 2f), t.y(), 90, t.block().size * Vars.tilesize - 4f);
|
Lines.lineAngleCenter(t.x + Mathf.sin(time, 20f, Vars.tilesize / 2f * t.block().size - 2f), t.y, 90, t.block().size * Vars.tilesize - 4f);
|
||||||
|
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,9 +107,9 @@ public class OverlayRenderer{
|
|||||||
float dst = core.dst(player);
|
float dst = core.dst(player);
|
||||||
if(dst < state.rules.enemyCoreBuildRadius * 2.2f){
|
if(dst < state.rules.enemyCoreBuildRadius * 2.2f){
|
||||||
Draw.color(Color.darkGray);
|
Draw.color(Color.darkGray);
|
||||||
Lines.circle(core.x(), core.y() - 2, state.rules.enemyCoreBuildRadius);
|
Lines.circle(core.x, core.y - 2, state.rules.enemyCoreBuildRadius);
|
||||||
Draw.color(Pal.accent, core.team().color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f));
|
Draw.color(Pal.accent, core.team().color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f));
|
||||||
Lines.circle(core.x(), core.y(), state.rules.enemyCoreBuildRadius);
|
Lines.circle(core.x, core.y, state.rules.enemyCoreBuildRadius);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ public class OverlayRenderer{
|
|||||||
if(Core.input.keyDown(Binding.rotateplaced) && tile.block().rotate && tile.interactable(player.team())){
|
if(Core.input.keyDown(Binding.rotateplaced) && tile.block().rotate && tile.interactable(player.team())){
|
||||||
control.input.drawArrow(tile.block(), tile.tileX(), tile.tileY(), tile.rotation(), true);
|
control.input.drawArrow(tile.block(), tile.tileX(), tile.tileY(), tile.rotation(), true);
|
||||||
Draw.color(Pal.accent, 0.3f + Mathf.absin(4f, 0.2f));
|
Draw.color(Pal.accent, 0.3f + Mathf.absin(4f, 0.2f));
|
||||||
Fill.square(tile.x(), tile.y(), tile.block().size * tilesize/2f);
|
Fill.square(tile.x, tile.y, tile.block().size * tilesize/2f);
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,9 +155,9 @@ public class OverlayRenderer{
|
|||||||
Building tile = world.entWorld(v.x, v.y);
|
Building tile = world.entWorld(v.x, v.y);
|
||||||
if(tile != null && tile.interactable(player.team()) && tile.acceptStack(player.unit().item(), player.unit().stack.amount, player.unit()) > 0){
|
if(tile != null && tile.interactable(player.team()) && tile.acceptStack(player.unit().item(), player.unit().stack.amount, player.unit()) > 0){
|
||||||
Lines.stroke(3f, Pal.gray);
|
Lines.stroke(3f, Pal.gray);
|
||||||
Lines.square(tile.x(), tile.y(), tile.block().size * tilesize / 2f + 3 + Mathf.absin(Time.time(), 5f, 1f));
|
Lines.square(tile.x, tile.y, tile.block().size * tilesize / 2f + 3 + Mathf.absin(Time.time(), 5f, 1f));
|
||||||
Lines.stroke(1f, Pal.place);
|
Lines.stroke(1f, Pal.place);
|
||||||
Lines.square(tile.x(), tile.y(), tile.block().size * tilesize / 2f + 2 + Mathf.absin(Time.time(), 5f, 1f));
|
Lines.square(tile.x, tile.y, tile.block().size * tilesize / 2f + 2 + Mathf.absin(Time.time(), 5f, 1f));
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public enum Binding implements KeyBind{
|
|||||||
schematic_flip_y(KeyCode.x),
|
schematic_flip_y(KeyCode.x),
|
||||||
schematic_menu(KeyCode.t),
|
schematic_menu(KeyCode.t),
|
||||||
|
|
||||||
category_prev(KeyCode.comma),
|
category_prev(KeyCode.comma, "blocks"),
|
||||||
category_next(KeyCode.period),
|
category_next(KeyCode.period),
|
||||||
|
|
||||||
block_select_left(KeyCode.left),
|
block_select_left(KeyCode.left),
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
item,
|
item,
|
||||||
amount,
|
amount,
|
||||||
player.x + Angles.trnsx(player.unit().rotation + 180f, backTrns), player.y + Angles.trnsy(player.unit().rotation + 180f, backTrns),
|
player.x + Angles.trnsx(player.unit().rotation + 180f, backTrns), player.y + Angles.trnsy(player.unit().rotation + 180f, backTrns),
|
||||||
new Vec2(tile.x() + stackTrns.x, tile.y() + stackTrns.y),
|
new Vec2(tile.x + stackTrns.x, tile.y + stackTrns.y),
|
||||||
() -> tile.handleStack(item, accepted, player.unit())
|
() -> tile.handleStack(item, accepted, player.unit())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class BlockInventoryFragment extends Fragment{
|
|||||||
player.unit().addItem(item, removed);
|
player.unit().addItem(item, removed);
|
||||||
Events.fire(new WithdrawEvent(tile, player, item, amount));
|
Events.fire(new WithdrawEvent(tile, player, item, amount));
|
||||||
for(int j = 0; j < Mathf.clamp(removed / 3, 1, 8); j++){
|
for(int j = 0; j < Mathf.clamp(removed / 3, 1, 8); j++){
|
||||||
Time.run(j * 3f, () -> Call.transferItemEffect(item, tile.x(), tile.y(), player.unit()));
|
Time.run(j * 3f, () -> Call.transferItemEffect(item, tile.x, tile.y, player.unit()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +231,7 @@ public class BlockInventoryFragment extends Fragment{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateTablePosition(){
|
private void updateTablePosition(){
|
||||||
Vec2 v = Core.input.mouseScreen(tile.x() + tile.block().size * tilesize / 2f, tile.y() + tile.block().size * tilesize / 2f);
|
Vec2 v = Core.input.mouseScreen(tile.x + tile.block().size * tilesize / 2f, tile.y + tile.block().size * tilesize / 2f);
|
||||||
table.pack();
|
table.pack();
|
||||||
table.setPosition(v.x, v.y, Align.topLeft);
|
table.setPosition(v.x, v.y, Align.topLeft);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class Build{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.teams.eachEnemyCore(team, core -> Mathf.dst(x * tilesize + type.offset(), y * tilesize + type.offset(), core.x(), core.y()) < state.rules.enemyCoreBuildRadius + type.size * tilesize / 2f)){
|
if(state.teams.eachEnemyCore(team, core -> Mathf.dst(x * tilesize + type.offset(), y * tilesize + type.offset(), core.x, core.y) < state.rules.enemyCoreBuildRadius + type.size * tilesize / 2f)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class ForceProjector extends Block{
|
|||||||
|
|
||||||
private static ForceProjectorEntity paramEntity;
|
private static ForceProjectorEntity paramEntity;
|
||||||
private static Cons<Shielderc> shieldConsumer = trait -> {
|
private static Cons<Shielderc> shieldConsumer = trait -> {
|
||||||
if(trait.team() != paramEntity.team() && Intersector.isInsideHexagon(paramEntity.x(), paramEntity.y(), paramEntity.realRadius() * 2f, trait.x(), trait.y())){
|
if(trait.team() != paramEntity.team() && Intersector.isInsideHexagon(paramEntity.x, paramEntity.y, paramEntity.realRadius() * 2f, trait.x(), trait.y())){
|
||||||
trait.absorb();
|
trait.absorb();
|
||||||
Fx.absorb.at(trait);
|
Fx.absorb.at(trait);
|
||||||
paramEntity.hit = 1f;
|
paramEntity.hit = 1f;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class MendProjector extends Block{
|
|||||||
|
|
||||||
indexer.eachBlock(this, realRange, other -> other.damaged(), other -> {
|
indexer.eachBlock(this, realRange, other -> other.damaged(), other -> {
|
||||||
other.heal(other.maxHealth() * (healPercent + phaseHeat * phaseBoost) / 100f * efficiency());
|
other.heal(other.maxHealth() * (healPercent + phaseHeat * phaseBoost) / 100f * efficiency());
|
||||||
Fx.healBlockFull.at(other.x(), other.y(), other.block().size, Tmp.c1.set(baseColor).lerp(phaseColor, phaseHeat));
|
Fx.healBlockFull.at(other.x, other.y, other.block().size, Tmp.c1.set(baseColor).lerp(phaseColor, phaseHeat));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import mindustry.entities.*;
|
|||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -51,6 +52,14 @@ public class PointDefenseTurret extends Block{
|
|||||||
return new TextureRegion[]{baseRegion, region};
|
return new TextureRegion[]{baseRegion, region};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStats(){
|
||||||
|
super.setStats();
|
||||||
|
|
||||||
|
stats.add(BlockStat.shootRange, range / tilesize, StatUnit.blocks);
|
||||||
|
stats.add(BlockStat.reload, 60f / reloadTime, StatUnit.none);
|
||||||
|
}
|
||||||
|
|
||||||
public class PointDefenseEntity extends Building{
|
public class PointDefenseEntity extends Building{
|
||||||
public float rotation = 90, reload;
|
public float rotation = 90, reload;
|
||||||
public @Nullable Bullet target;
|
public @Nullable Bullet target;
|
||||||
@@ -66,7 +75,7 @@ public class PointDefenseTurret extends Block{
|
|||||||
//look at target
|
//look at target
|
||||||
if(target != null && target.within(this, range) && target.team() != team && target.type().hittable){
|
if(target != null && target.within(this, range) && target.team() != team && target.type().hittable){
|
||||||
float dest = angleTo(target);
|
float dest = angleTo(target);
|
||||||
rotation = Angles.moveToward(rotation,dest, rotateSpeed * edelta());
|
rotation = Angles.moveToward(rotation, dest, rotateSpeed * edelta());
|
||||||
reload -= edelta();
|
reload -= edelta();
|
||||||
|
|
||||||
//shoot when possible
|
//shoot when possible
|
||||||
|
|||||||
139
core/src/mindustry/world/blocks/defense/TractorBeamTurret.java
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
package mindustry.world.blocks.defense;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.io.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.entities.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
public class TractorBeamTurret extends Block{
|
||||||
|
public final int timerTarget = timers++;
|
||||||
|
public float retargetTime = 5f;
|
||||||
|
|
||||||
|
public @Load("block-$size") TextureRegion baseRegion;
|
||||||
|
public @Load("@-laser") TextureRegion laser;
|
||||||
|
public @Load("@-laser-end") TextureRegion laserEnd;
|
||||||
|
|
||||||
|
public float range = 80f;
|
||||||
|
public float rotateSpeed = 10;
|
||||||
|
public float shootCone = 6f;
|
||||||
|
public float laserWidth = 0.6f;
|
||||||
|
public float force = 0.3f;
|
||||||
|
public float damage = 0f;
|
||||||
|
public boolean targetAir = true, targetGround = false;
|
||||||
|
|
||||||
|
public TractorBeamTurret(String name){
|
||||||
|
super(name);
|
||||||
|
|
||||||
|
update = true;
|
||||||
|
solid = true;
|
||||||
|
outlineIcon = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||||
|
Drawf.dashCircle(x * tilesize + offset(), y * tilesize + offset(), range, Pal.accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TextureRegion[] icons(){
|
||||||
|
return new TextureRegion[]{baseRegion, region};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStats(){
|
||||||
|
super.setStats();
|
||||||
|
|
||||||
|
stats.add(BlockStat.shootRange, range / tilesize, StatUnit.blocks);
|
||||||
|
stats.add(BlockStat.targetsAir, targetAir);
|
||||||
|
stats.add(BlockStat.targetsGround, targetGround);
|
||||||
|
stats.add(BlockStat.damage, damage * 60f, StatUnit.perSecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TractorBeamEntity extends Building{
|
||||||
|
public float rotation = 90;
|
||||||
|
public @Nullable Unit target;
|
||||||
|
public float lastX, lastY, strength;
|
||||||
|
public boolean any;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateTile(){
|
||||||
|
|
||||||
|
//retarget
|
||||||
|
if(timer(timerTarget, retargetTime)){
|
||||||
|
target = Units.closestEnemy(team, x, y, range, u -> u.checkTarget(targetAir, targetGround));
|
||||||
|
}
|
||||||
|
|
||||||
|
//look at target
|
||||||
|
if(target != null && target.within(this, range) && target.team() != team && target.type().flying){
|
||||||
|
any = true;
|
||||||
|
float dest = angleTo(target);
|
||||||
|
rotation = Angles.moveToward(rotation,dest, rotateSpeed * edelta());
|
||||||
|
lastX = target.x;
|
||||||
|
lastY = target.y;
|
||||||
|
strength = Mathf.lerpDelta(strength, 1f, 0.1f);
|
||||||
|
|
||||||
|
if(damage > 0){
|
||||||
|
target.damageContinuous(damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
//shoot when possible
|
||||||
|
if(Angles.within(rotation, dest, shootCone)){
|
||||||
|
target.impulse(Tmp.v1.set(this).sub(target).limit(force * efficiency() * timeScale));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
target = null;
|
||||||
|
strength = Mathf.lerpDelta(strength, 0, 0.1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawSelect(){
|
||||||
|
Drawf.dashCircle(x, y, range, Pal.accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(){
|
||||||
|
Draw.rect(baseRegion, x, y);
|
||||||
|
Draw.rect(region, x, y, rotation - 90);
|
||||||
|
|
||||||
|
//draw laser if applicable
|
||||||
|
if(any){
|
||||||
|
Draw.z(Layer.bullet);
|
||||||
|
float ang = angleTo(lastX, lastY);
|
||||||
|
float len = 5f;
|
||||||
|
|
||||||
|
Draw.mixcol(Color.white, Mathf.absin(4f, 0.6f));
|
||||||
|
|
||||||
|
Drawf.laser(team, laser, laserEnd,
|
||||||
|
x + Angles.trnsx(ang, len), y + Angles.trnsy(ang, len),
|
||||||
|
lastX, lastY, strength * efficiency() * laserWidth);
|
||||||
|
|
||||||
|
Draw.mixcol();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Writes write){
|
||||||
|
super.write(write);
|
||||||
|
|
||||||
|
write.f(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Reads read, byte revision){
|
||||||
|
super.read(read, revision);
|
||||||
|
|
||||||
|
rotation = read.f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,12 +70,12 @@ public abstract class Turret extends Block{
|
|||||||
public @Load("block-$size") TextureRegion baseRegion;
|
public @Load("block-$size") TextureRegion baseRegion;
|
||||||
public @Load("@-heat") TextureRegion heatRegion;
|
public @Load("@-heat") TextureRegion heatRegion;
|
||||||
|
|
||||||
public Cons<TurretEntity> drawer = tile -> Draw.rect(region, tile.x() + tr2.x, tile.y() + tr2.y, tile.rotation - 90);
|
public Cons<TurretEntity> drawer = tile -> Draw.rect(region, tile.x + tr2.x, tile.y + tr2.y, tile.rotation - 90);
|
||||||
public Cons<TurretEntity> heatDrawer = tile -> {
|
public Cons<TurretEntity> heatDrawer = tile -> {
|
||||||
if(tile.heat <= 0.00001f) return;
|
if(tile.heat <= 0.00001f) return;
|
||||||
Draw.color(heatColor, tile.heat);
|
Draw.color(heatColor, tile.heat);
|
||||||
Draw.blend(Blending.additive);
|
Draw.blend(Blending.additive);
|
||||||
Draw.rect(heatRegion, tile.x() + tr2.x, tile.y() + tr2.y, tile.rotation - 90);
|
Draw.rect(heatRegion, tile.x + tr2.x, tile.y + tr2.y, tile.rotation - 90);
|
||||||
Draw.blend();
|
Draw.blend();
|
||||||
Draw.color();
|
Draw.color();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ public class MassDriver extends Block{
|
|||||||
|
|
||||||
//if so, draw a dotted line towards it while it is in range
|
//if so, draw a dotted line towards it while it is in range
|
||||||
float sin = Mathf.absin(Time.time(), 6f, 1f);
|
float sin = Mathf.absin(Time.time(), 6f, 1f);
|
||||||
Tmp.v1.set(x * tilesize + offset(), y * tilesize + offset()).sub(selected.x(), selected.y()).limit((size / 2f + 1) * tilesize + sin + 0.5f);
|
Tmp.v1.set(x * tilesize + offset(), y * tilesize + offset()).sub(selected.x, selected.y).limit((size / 2f + 1) * tilesize + sin + 0.5f);
|
||||||
float x2 = x * tilesize - Tmp.v1.x, y2 = y * tilesize - Tmp.v1.y,
|
float x2 = x * tilesize - Tmp.v1.x, y2 = y * tilesize - Tmp.v1.y,
|
||||||
x1 = selected.x() + Tmp.v1.x, y1 = selected.y() + Tmp.v1.y;
|
x1 = selected.x + Tmp.v1.x, y1 = selected.y + Tmp.v1.y;
|
||||||
int segs = (int)(selected.dst(x * tilesize, y * tilesize) / tilesize);
|
int segs = (int)(selected.dst(x * tilesize, y * tilesize) / tilesize);
|
||||||
|
|
||||||
Lines.stroke(4f, Pal.gray);
|
Lines.stroke(4f, Pal.gray);
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ public class PayloadConveyor extends Block{
|
|||||||
//differing sizes
|
//differing sizes
|
||||||
(accept.block().size > size &&
|
(accept.block().size > size &&
|
||||||
(rotation() % 2 == 0 ? //check orientation
|
(rotation() % 2 == 0 ? //check orientation
|
||||||
Math.abs(accept.y() - y) <= (accept.block().size * tilesize - size * tilesize)/2f : //check Y alignment
|
Math.abs(accept.y - y) <= (accept.block().size * tilesize - size * tilesize)/2f : //check Y alignment
|
||||||
Math.abs(accept.x() - x) <= (accept.block().size * tilesize - size * tilesize)/2f //check X alignment
|
Math.abs(accept.x - x) <= (accept.block().size * tilesize - size * tilesize)/2f //check X alignment
|
||||||
)))){
|
)))){
|
||||||
next = accept;
|
next = accept;
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class BlockPayload implements Payload{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
Drawf.shadow(entity.x(), entity.y(), entity.block().size * tilesize * 2f);
|
Drawf.shadow(entity.x, entity.y, entity.block().size * tilesize * 2f);
|
||||||
Draw.rect(entity.block().icon(Cicon.full), entity.x(), entity.y());
|
Draw.rect(entity.block().icon(Cicon.full), entity.x, entity.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,10 +122,10 @@ public class PowerNode extends PowerBlock{
|
|||||||
Drawf.circles(x * tilesize + offset(), y * tilesize + offset(), laserRange * tilesize);
|
Drawf.circles(x * tilesize + offset(), y * tilesize + offset(), laserRange * tilesize);
|
||||||
|
|
||||||
getPotentialLinks(tile, other -> {
|
getPotentialLinks(tile, other -> {
|
||||||
Drawf.square(other.x(), other.y(), other.block().size * tilesize / 2f + 2f, Pal.place);
|
Drawf.square(other.x, other.y, other.block().size * tilesize / 2f + 2f, Pal.place);
|
||||||
|
|
||||||
insulators(tile.x, tile.y, other.tileX(), other.tileY(), cause -> {
|
insulators(tile.x, tile.y, other.tileX(), other.tileY(), cause -> {
|
||||||
Drawf.square(cause.x(), cause.y(), cause.block().size * tilesize / 2f + 2f, Pal.plastanium);
|
Drawf.square(cause.x, cause.y, cause.block().size * tilesize / 2f + 2f, Pal.plastanium);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ public class PowerNode extends PowerBlock{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean overlaps(Building src, Building other, float range){
|
protected boolean overlaps(Building src, Building other, float range){
|
||||||
return overlaps(src.x(), src.y(), other.tile(), range);
|
return overlaps(src.x, src.y, other.tile(), range);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean overlaps(Tile src, Tile other, float range){
|
protected boolean overlaps(Tile src, Tile other, float range){
|
||||||
@@ -352,7 +352,7 @@ public class PowerNode extends PowerBlock{
|
|||||||
boolean linked = linked(link);
|
boolean linked = linked(link);
|
||||||
|
|
||||||
if(linked){
|
if(linked){
|
||||||
Drawf.square(link.x(), link.y(), link.block().size * tilesize / 2f + 1f, Pal.place);
|
Drawf.square(link.x, link.y, link.block().size * tilesize / 2f + 1f, Pal.place);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,7 +387,7 @@ public class PowerNode extends PowerBlock{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void drawLaserTo(Building target){
|
protected void drawLaserTo(Building target){
|
||||||
drawLaser(team, x, y, target.x(), target.y(), power.graph.getSatisfaction(), size, target.block().size);
|
drawLaser(team, x, y, target.x, target.y, power.graph.getSatisfaction(), size, target.block().size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ public class PayloadAcceptor extends Block{
|
|||||||
//if the other block is smaller, check alignment
|
//if the other block is smaller, check alignment
|
||||||
(accept.block().size < size &&
|
(accept.block().size < size &&
|
||||||
(accept.rotation() % 2 == 0 ? //check orientation; make sure it's aligned properly with this block.
|
(accept.rotation() % 2 == 0 ? //check orientation; make sure it's aligned properly with this block.
|
||||||
Math.abs(accept.y() - tile.y()) <= (size * tilesize - accept.block().size * tilesize)/2f : //check Y alignment
|
Math.abs(accept.y - tile.y) <= (size * tilesize - accept.block().size * tilesize)/2f : //check Y alignment
|
||||||
Math.abs(accept.x() - tile.x()) <= (size * tilesize - accept.block().size * tilesize)/2f //check X alignment
|
Math.abs(accept.x - tile.x) <= (size * tilesize - accept.block().size * tilesize)/2f //check X alignment
|
||||||
)) && (!accept.block().rotate || accept.front() == tile || !accept.block().outputFacing) //make sure it's facing this block
|
)) && (!accept.block().rotate || accept.front() == tile || !accept.block().outputFacing) //make sure it's facing this block
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ public class CoreBlock extends StorageBlock{
|
|||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
Point2 p = Geometry.d8edge[i];
|
Point2 p = Geometry.d8edge[i];
|
||||||
float offset = -Math.max(t.block().size - 1, 0) / 2f * tilesize;
|
float offset = -Math.max(t.block().size - 1, 0) / 2f * tilesize;
|
||||||
Draw.rect("block-select", t.x() + offset * p.x, t.y() + offset * p.y, i * 90);
|
Draw.rect("block-select", t.x + offset * p.x, t.y + offset * p.y, i * 90);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if(proximity.contains(e -> isContainer(e) && e.items == items)){
|
if(proximity.contains(e -> isContainer(e) && e.items == items)){
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ public class RepairPoint extends Block{
|
|||||||
public @Load("laser") TextureRegion laser;
|
public @Load("laser") TextureRegion laser;
|
||||||
public @Load("laser-end") TextureRegion laserEnd;
|
public @Load("laser-end") TextureRegion laserEnd;
|
||||||
|
|
||||||
|
public Color laserColor = Color.valueOf("e8ffd7");
|
||||||
|
|
||||||
public RepairPoint(String name){
|
public RepairPoint(String name){
|
||||||
super(name);
|
super(name);
|
||||||
update = true;
|
update = true;
|
||||||
@@ -60,7 +62,7 @@ public class RepairPoint extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class RepairPointEntity extends Building{
|
public class RepairPointEntity extends Building{
|
||||||
public Unitc target;
|
public Unit target;
|
||||||
public float strength, rotation = 90;
|
public float strength, rotation = 90;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -75,7 +77,7 @@ public class RepairPoint extends Block{
|
|||||||
float ang = angleTo(target);
|
float ang = angleTo(target);
|
||||||
float len = 5f;
|
float len = 5f;
|
||||||
|
|
||||||
Draw.color(Color.valueOf("e8ffd7"));
|
Draw.color(laserColor);
|
||||||
Drawf.laser(team, laser, laserEnd,
|
Drawf.laser(team, laser, laserEnd,
|
||||||
x + Angles.trnsx(ang, len), y + Angles.trnsy(ang, len),
|
x + Angles.trnsx(ang, len), y + Angles.trnsy(ang, len),
|
||||||
target.x(), target.y(), strength);
|
target.x(), target.y(), strength);
|
||||||
|
|||||||
@@ -13,15 +13,15 @@ public class DrawWeave extends DrawBlock{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(GenericCrafterEntity entity){
|
public void draw(GenericCrafterEntity entity){
|
||||||
Draw.rect(bottom, entity.x(), entity.y());
|
Draw.rect(bottom, entity.x, entity.y);
|
||||||
Draw.rect(weave, entity.x(), entity.y(), entity.totalProgress);
|
Draw.rect(weave, entity.x, entity.y, entity.totalProgress);
|
||||||
|
|
||||||
Draw.color(Pal.accent);
|
Draw.color(Pal.accent);
|
||||||
Draw.alpha(entity.warmup);
|
Draw.alpha(entity.warmup);
|
||||||
|
|
||||||
Lines.lineAngleCenter(
|
Lines.lineAngleCenter(
|
||||||
entity.x() + Mathf.sin(entity.totalProgress, 6f, Vars.tilesize / 3f * entity.block.size),
|
entity.x + Mathf.sin(entity.totalProgress, 6f, Vars.tilesize / 3f * entity.block.size),
|
||||||
entity.y(),
|
entity.y,
|
||||||
90,
|
90,
|
||||||
entity.block.size * Vars.tilesize / 2f);
|
entity.block.size * Vars.tilesize / 2f);
|
||||||
|
|
||||||
|
|||||||