Merge branch 'master' into ground-support-heal
This commit is contained in:
@@ -9,6 +9,7 @@ import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
@@ -82,7 +83,7 @@ public class Damage{
|
||||
|
||||
furthest = null;
|
||||
|
||||
boolean found = world.raycast(b.tileX(), b.tileY(), world.toTile(b.x + Tmp.v1.x), world.toTile(b.y + Tmp.v1.y),
|
||||
boolean found = world.raycast(b.tileX(), b.tileY(), World.toTile(b.x + Tmp.v1.x), World.toTile(b.y + Tmp.v1.y),
|
||||
(x, y) -> (furthest = world.tile(x, y)) != null && furthest.team() != b.team && furthest.block().absorbLasers);
|
||||
|
||||
return found && furthest != null ? Math.max(6f, b.dst(furthest.worldx(), furthest.worldy())) : length;
|
||||
|
||||
@@ -27,8 +27,8 @@ public class Effect{
|
||||
/** Clip size. */
|
||||
public float size;
|
||||
|
||||
public boolean ground;
|
||||
public float groundDuration;
|
||||
public float layer = Layer.effect;
|
||||
public float layerDuration;
|
||||
|
||||
public Effect(float life, float clipsize, Cons<EffectContainer> renderer){
|
||||
this.id = all.size;
|
||||
@@ -42,14 +42,14 @@ public class Effect{
|
||||
this(life,50f, renderer);
|
||||
}
|
||||
|
||||
public Effect ground(){
|
||||
ground = true;
|
||||
public Effect layer(float l){
|
||||
layer = l;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Effect ground(float duration){
|
||||
ground = true;
|
||||
this.groundDuration = duration;
|
||||
public Effect layer(float l, float duration){
|
||||
layer = l;
|
||||
this.layerDuration = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class Effect{
|
||||
|
||||
public float render(int id, Color color, float life, float lifetime, float rotation, float x, float y, Object data){
|
||||
container.set(id, color, life, lifetime, rotation, x, y, data);
|
||||
Draw.z(ground ? Layer.debris : Layer.effect);
|
||||
Draw.z(layer);
|
||||
Draw.reset();
|
||||
renderer.get(container);
|
||||
Draw.reset();
|
||||
@@ -209,4 +209,4 @@ public class Effect{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ public class Fires{
|
||||
|
||||
if(fire == null){
|
||||
fire = Fire.create();
|
||||
fire.tile(tile);
|
||||
fire.lifetime(baseLifetime);
|
||||
fire.tile = tile;
|
||||
fire.lifetime = baseLifetime;
|
||||
fire.set(tile.worldx(), tile.worldy());
|
||||
fire.add();
|
||||
map.put(tile.pos(), fire);
|
||||
}else{
|
||||
fire.lifetime(baseLifetime);
|
||||
fire.time(0f);
|
||||
fire.lifetime = baseLifetime;
|
||||
fire.time = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,5 +11,6 @@ class GroupDefs<G>{
|
||||
@GroupDef(value = Buildingc.class) G build;
|
||||
@GroupDef(value = Syncc.class, mapping = true) G sync;
|
||||
@GroupDef(value = Drawc.class) G draw;
|
||||
@GroupDef(value = Firec.class) G fire;
|
||||
@GroupDef(value = WeatherStatec.class) G weather;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
@@ -54,7 +55,7 @@ public class Lightning{
|
||||
bhit = false;
|
||||
Vec2 from = lines.get(lines.size - 2);
|
||||
Vec2 to = lines.get(lines.size - 1);
|
||||
world.raycastEach(world.toTile(from.getX()), world.toTile(from.getY()), world.toTile(to.getX()), world.toTile(to.getY()), (wx, wy) -> {
|
||||
world.raycastEach(World.toTile(from.getX()), World.toTile(from.getY()), World.toTile(to.getX()), World.toTile(to.getY()), (wx, wy) -> {
|
||||
|
||||
Tile tile = world.tile(wx, wy);
|
||||
if(tile != null && tile.block().insulated){
|
||||
|
||||
@@ -53,13 +53,13 @@ public class Predict{
|
||||
|
||||
public static Vec2 intercept(Position src, Position dst, float v){
|
||||
float ddx = 0, ddy = 0;
|
||||
if(dst instanceof Hitboxc){
|
||||
ddx += ((Hitboxc)dst).deltaX();
|
||||
ddy += ((Hitboxc)dst).deltaY();
|
||||
if(dst instanceof Hitboxc h){
|
||||
ddx += h.deltaX();
|
||||
ddy += h.deltaY();
|
||||
}
|
||||
if(src instanceof Hitboxc){
|
||||
ddx -= ((Hitboxc)src).deltaX()/(Time.delta);
|
||||
ddy -= ((Hitboxc)src).deltaY()/(Time.delta);
|
||||
if(src instanceof Hitboxc h){
|
||||
ddx -= h.deltaX()/(Time.delta);
|
||||
ddy -= h.deltaY()/(Time.delta);
|
||||
}
|
||||
return intercept(src.getX(), src.getY(), dst.getX(), dst.getY(), ddx, ddy, v);
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ public class Units{
|
||||
|
||||
nearby(x, y, width, height, unit -> {
|
||||
if(boolResult) return;
|
||||
if((unit.isGrounded() && !unit.type().hovering) == ground){
|
||||
if((unit.isGrounded() && !unit.type.hovering) == ground){
|
||||
unit.hitbox(hitrect);
|
||||
|
||||
if(hitrect.overlaps(x, y, width, height)){
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.entities.abilities;
|
||||
|
||||
import arc.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
public abstract class Ability implements Cloneable{
|
||||
@@ -14,4 +15,9 @@ public abstract class Ability implements Cloneable{
|
||||
throw new RuntimeException("java sucks", e);
|
||||
}
|
||||
}
|
||||
|
||||
/** @return localized ability name; mods should override this. */
|
||||
public String localized(){
|
||||
return Core.bundle.get("ability." + getClass().getSimpleName().replace("Ability", "").toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package mindustry.entities.abilities;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import arc.audio.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
public class MoveLightningAbility extends Ability{
|
||||
//Lightning damage
|
||||
public float damage = 35f;
|
||||
//Chance of firing every tick. Set >= 1 to always fire lightning every tick at max speed.
|
||||
public float chance = 0.15f;
|
||||
//Length of the lightning
|
||||
public int length = 12;
|
||||
//Speeds for when to start lightninging and when to stop getting faster
|
||||
public float minSpeed = 0.8f, maxSpeed = 1.2f;
|
||||
//Lightning color
|
||||
public Color color = Color.valueOf("a9d8ff");
|
||||
|
||||
public Effect shootEffect = Fx.sparkShoot;
|
||||
public Sound shootSound = Sounds.spark;
|
||||
|
||||
MoveLightningAbility(){}
|
||||
|
||||
public MoveLightningAbility(float damage, int length, float chance, float minSpeed, float maxSpeed, Color color){
|
||||
this.damage = damage;
|
||||
this.length = length;
|
||||
this.chance = chance;
|
||||
this.minSpeed = minSpeed;
|
||||
this.maxSpeed = maxSpeed;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Unit unit){
|
||||
float scl = Mathf.clamp((unit.vel().len() - minSpeed) / (maxSpeed - minSpeed));
|
||||
if(Mathf.chance(Time.delta * chance * scl)){
|
||||
shootEffect.at(unit.x, unit.y, unit.rotation, color);
|
||||
Lightning.create(unit.team, color, damage, unit.x + unit.vel.x, unit.y + unit.vel.y, unit.rotation, length);
|
||||
shootSound.at(unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
public class HealFieldAbility extends Ability{
|
||||
public class RepairFieldAbility extends Ability{
|
||||
public float amount = 1, reload = 100, range = 60;
|
||||
public Effect healEffect = Fx.heal;
|
||||
public Effect activeEffect = Fx.healWaveDynamic;
|
||||
@@ -13,9 +13,9 @@ public class HealFieldAbility extends Ability{
|
||||
protected float timer;
|
||||
protected boolean wasHealed = false;
|
||||
|
||||
HealFieldAbility(){}
|
||||
RepairFieldAbility(){}
|
||||
|
||||
public HealFieldAbility(float amount, float reload, float range){
|
||||
public RepairFieldAbility(float amount, float reload, float range){
|
||||
this.amount = amount;
|
||||
this.reload = reload;
|
||||
this.range = range;
|
||||
@@ -5,7 +5,7 @@ import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
public class ShieldFieldAbility extends Ability{
|
||||
public class ShieldRegenFieldAbility extends Ability{
|
||||
public float amount = 1, max = 100f, reload = 100, range = 60;
|
||||
public Effect applyEffect = Fx.shieldApply;
|
||||
public Effect activeEffect = Fx.shieldWave;
|
||||
@@ -13,9 +13,9 @@ public class ShieldFieldAbility extends Ability{
|
||||
protected float timer;
|
||||
protected boolean applied = false;
|
||||
|
||||
ShieldFieldAbility(){}
|
||||
ShieldRegenFieldAbility(){}
|
||||
|
||||
public ShieldFieldAbility(float amount, float max, float reload, float range){
|
||||
public ShieldRegenFieldAbility(float amount, float max, float reload, float range){
|
||||
this.amount = amount;
|
||||
this.max = max;
|
||||
this.reload = reload;
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.entities.abilities;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
@@ -56,4 +57,9 @@ public class UnitSpawnAbility extends Ability{
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String localized(){
|
||||
return Core.bundle.format("ability.unitspawn", type.localizedName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,8 +79,10 @@ public abstract class BulletType extends Content{
|
||||
public boolean backMove = true;
|
||||
/** Bullet range override. */
|
||||
public float range = -1f;
|
||||
/** Heal Bullet Percent **/
|
||||
/** % of block health healed **/
|
||||
public float healPercent = 0f;
|
||||
/** whether to make fire on impact */
|
||||
public boolean makeFire = false;
|
||||
|
||||
//additional effects
|
||||
|
||||
@@ -104,6 +106,8 @@ public abstract class BulletType extends Content{
|
||||
public float incendChance = 1f;
|
||||
public float homingPower = 0f;
|
||||
public float homingRange = 50f;
|
||||
/** Use a negative value to disable homing delay. */
|
||||
public float homingDelay = -1f;
|
||||
|
||||
public Color lightningColor = Pal.surge;
|
||||
public int lightning;
|
||||
@@ -158,7 +162,7 @@ public abstract class BulletType extends Content{
|
||||
}
|
||||
|
||||
public void hitTile(Bullet b, Building tile, float initialHealth){
|
||||
if(status == StatusEffects.burning){
|
||||
if(makeFire){
|
||||
Fires.create(tile.tile);
|
||||
}
|
||||
|
||||
@@ -210,14 +214,14 @@ public abstract class BulletType extends Content{
|
||||
Damage.status(b.team, x, y, splashDamageRadius, status, statusDuration, collidesAir, collidesGround);
|
||||
}
|
||||
|
||||
if(healPercent > 0f) {
|
||||
if(healPercent > 0f){
|
||||
indexer.eachBlock(b.team, x, y, splashDamageRadius, other -> other.damaged(), other -> {
|
||||
Fx.healBlockFull.at(other.x, other.y, other.block.size, Pal.heal);
|
||||
other.heal(healPercent / 100f * other.maxHealth());
|
||||
});
|
||||
}
|
||||
|
||||
if(status == StatusEffects.burning) {
|
||||
if(makeFire){
|
||||
indexer.eachBlock(null, x, y, splashDamageRadius, other -> other.team != b.team, other -> {
|
||||
Fires.create(other.tile);
|
||||
});
|
||||
@@ -248,7 +252,7 @@ public abstract class BulletType extends Content{
|
||||
}
|
||||
|
||||
public void init(Bullet b){
|
||||
if(pierceCap >= 1) {
|
||||
if(pierceCap >= 1){
|
||||
pierce = true;
|
||||
//pierceBuilding is not enabled by default, because a bullet may want to *not* pierce buildings
|
||||
}
|
||||
@@ -263,7 +267,7 @@ public abstract class BulletType extends Content{
|
||||
}
|
||||
|
||||
public void update(Bullet b){
|
||||
if(homingPower > 0.0001f){
|
||||
if(homingPower > 0.0001f && b.time >= homingDelay){
|
||||
Teamc target = Units.closestTarget(b.team, b.x, b.y, homingRange, e -> (e.isGrounded() && collidesGround) || (e.isFlying() && collidesAir), t -> collidesGround);
|
||||
if(target != null){
|
||||
b.vel.setAngle(Mathf.slerpDelta(b.rotation(), b.angleTo(target), homingPower));
|
||||
|
||||
@@ -39,6 +39,11 @@ public class LaserBulletType extends BulletType{
|
||||
this(1f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float estimateDPS(){
|
||||
return super.estimateDPS() * 2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
super.init();
|
||||
|
||||
@@ -22,6 +22,8 @@ public class LiquidBulletType extends BulletType{
|
||||
if(liquid != null){
|
||||
this.liquid = liquid;
|
||||
this.status = liquid.effect;
|
||||
lightColor = liquid.lightColor;
|
||||
lightOpacity = liquid.lightColor.a;
|
||||
}
|
||||
|
||||
ammoMultiplier = 1f;
|
||||
|
||||
@@ -207,7 +207,8 @@ abstract class BuilderComp implements Unitc{
|
||||
BuildPlan plan = buildPlan();
|
||||
Tile tile = world.tile(plan.x, plan.y);
|
||||
|
||||
if((!within(tile, buildingRange) && !state.isEditor()) || tile == null){
|
||||
|
||||
if(tile == null || (!within(tile, buildingRange) && !state.isEditor())){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,16 +17,19 @@ import arc.util.io.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.audio.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.Teams.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.logic.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.ConstructBlock.*;
|
||||
import mindustry.world.blocks.environment.*;
|
||||
import mindustry.world.blocks.payloads.*;
|
||||
import mindustry.world.blocks.power.*;
|
||||
@@ -191,6 +194,36 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
//endregion
|
||||
//region utility methods
|
||||
|
||||
public void addPlan(boolean checkPrevious){
|
||||
if(!block.rebuildable) return;
|
||||
|
||||
if(self() instanceof ConstructBuild entity){
|
||||
//update block to reflect the fact that something was being constructed
|
||||
if(entity.cblock != null && entity.cblock.synthetic()){
|
||||
block = entity.cblock;
|
||||
}else{
|
||||
//otherwise this was a deconstruction that was interrupted, don't want to rebuild that
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TeamData data = state.teams.get(team);
|
||||
|
||||
if(checkPrevious){
|
||||
//remove existing blocks that have been placed here.
|
||||
//painful O(n) iteration + copy
|
||||
for(int i = 0; i < data.blocks.size; i++){
|
||||
BlockPlan b = data.blocks.get(i);
|
||||
if(b.x == tile.x && b.y == tile.y){
|
||||
data.blocks.removeIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data.blocks.addFirst(new BlockPlan(tile.x, tile.y, (short)rotation, block.id, config()));
|
||||
}
|
||||
|
||||
/** Configure with the current, local player. */
|
||||
public void configure(Object value){
|
||||
//save last used config
|
||||
@@ -431,7 +464,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
*/
|
||||
public boolean movePayload(Payload todump){
|
||||
int trns = block.size/2 + 1;
|
||||
Tile next = tile.getNearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns);
|
||||
Tile next = tile.nearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns);
|
||||
|
||||
if(next != null && next.build != null && next.build.team == team && next.build.acceptPayload(self(), todump)){
|
||||
next.build.handlePayload(self(), todump);
|
||||
@@ -514,7 +547,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
}
|
||||
|
||||
public float moveLiquidForward(boolean leaks, Liquid liquid){
|
||||
Tile next = tile.getNearby(rotation);
|
||||
Tile next = tile.nearby(rotation);
|
||||
|
||||
if(next == null) return 0;
|
||||
|
||||
@@ -836,7 +869,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
public void placed(){
|
||||
if(net.client()) return;
|
||||
|
||||
if((block.consumesPower && !block.outputsPower) || (!block.consumesPower && block.outputsPower)){
|
||||
if(block.consumesPower || block.outputsPower){
|
||||
int range = 10;
|
||||
tempTiles.clear();
|
||||
Geometry.circle(tileX(), tileY(), range, (x, y) -> {
|
||||
@@ -878,7 +911,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
/** Called when arbitrary configuration is applied to a tile. */
|
||||
public void configured(@Nullable Unit builder, @Nullable Object value){
|
||||
//null is of type void.class; anonymous classes use their superclass.
|
||||
Class<?> type = value == null ? void.class : value.getClass().isAnonymousClass() ? value.getClass().getSuperclass() : value.getClass();
|
||||
Class<?> type = value == null ? void.class : value.getClass().isAnonymousClass() || value.getClass().getSimpleName().startsWith("adapter") ? value.getClass().getSuperclass() : value.getClass();
|
||||
|
||||
if(builder != null && builder.isPlayer()){
|
||||
lastAccessed = builder.getPlayer().name;
|
||||
@@ -1234,8 +1267,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
@Override
|
||||
public double sense(LAccess sensor){
|
||||
return switch(sensor){
|
||||
case x -> x;
|
||||
case y -> y;
|
||||
case x -> World.conv(x);
|
||||
case y -> World.conv(y);
|
||||
case team -> team.id;
|
||||
case health -> health;
|
||||
case maxHealth -> maxHealth;
|
||||
@@ -1244,8 +1277,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
case totalItems -> items == null ? 0 : items.total();
|
||||
case totalLiquids -> liquids == null ? 0 : liquids.total();
|
||||
case totalPower -> power == null || !block.consumes.hasPower() ? 0 : power.status * (block.consumes.getPower().buffered ? block.consumes.getPower().capacity : 1f);
|
||||
case itemCapacity -> block.itemCapacity;
|
||||
case liquidCapacity -> block.liquidCapacity;
|
||||
case itemCapacity -> block.hasItems ? block.itemCapacity : 0;
|
||||
case liquidCapacity -> block.hasLiquids ? block.liquidCapacity : 0;
|
||||
case powerCapacity -> block.consumes.hasPower() ? block.consumes.getPower().capacity : 0f;
|
||||
case powerNetIn -> power == null ? 0 : power.graph.getLastScaledPowerIn() * 60;
|
||||
case powerNetOut -> power == null ? 0 : power.graph.getLastScaledPowerOut() * 60;
|
||||
@@ -1263,7 +1296,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
case type -> block;
|
||||
case firstItem -> items == null ? null : items.first();
|
||||
case config -> block.configurations.containsKey(Item.class) || block.configurations.containsKey(Liquid.class) ? config() : null;
|
||||
case payloadType -> getPayload() instanceof UnitPayload p1 ? p1.unit.type() : getPayload() instanceof BuildPayload p2 ? p2.block() : null;
|
||||
case payloadType -> getPayload() instanceof UnitPayload p1 ? p1.unit.type : getPayload() instanceof BuildPayload p2 ? p2.block() : null;
|
||||
default -> noSensed;
|
||||
};
|
||||
|
||||
@@ -1286,7 +1319,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
|
||||
@Override
|
||||
public void control(LAccess type, Object p1, double p2, double p3, double p4){
|
||||
|
||||
if(type == LAccess.configure && block.logicConfigurable){
|
||||
//change config only if it's new
|
||||
Object prev = senseObject(LAccess.config);
|
||||
if(prev != p1){
|
||||
configureAny(p1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,6 +7,7 @@ import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.Teams.*;
|
||||
@@ -110,7 +111,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
|
||||
type.update(self());
|
||||
|
||||
if(type.collidesTiles && type.collides && type.collidesGround){
|
||||
world.raycastEach(world.toTile(lastX()), world.toTile(lastY()), tileX(), tileY(), (x, y) -> {
|
||||
world.raycastEach(World.toTile(lastX()), World.toTile(lastY()), tileX(), tileY(), (x, y) -> {
|
||||
|
||||
Building tile = world.build(x, y);
|
||||
if(tile == null || !isAdded()) return false;
|
||||
@@ -141,7 +142,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
|
||||
});
|
||||
}
|
||||
|
||||
if(type.pierceCap != -1 && collided.size >= type.pierceCap) {
|
||||
if(type.pierceCap != -1 && collided.size >= type.pierceCap){
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ abstract class CommanderComp implements Entityc, Posc{
|
||||
|
||||
public void update(){
|
||||
if(formation != null){
|
||||
formation.anchor.set(x, y, /*rotation*/ 0); //TODO rotation set to 0 because rotating is pointless
|
||||
formation.anchor.set(x, y, 0);
|
||||
formation.updateSlots();
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ abstract class CommanderComp implements Entityc, Posc{
|
||||
units.clear();
|
||||
|
||||
Units.nearby(team, x, y, 150f, u -> {
|
||||
if(u.isAI() && include.get(u) && u != self() && u.type().flying == type.flying && u.hitSize <= hitSize * 1.1f){
|
||||
if(u.isAI() && include.get(u) && u != self() && u.type.flying == type.flying && u.hitSize <= hitSize * 1.1f){
|
||||
units.add(u);
|
||||
}
|
||||
});
|
||||
@@ -74,7 +74,7 @@ abstract class CommanderComp implements Entityc, Posc{
|
||||
void command(Formation formation, Seq<Unit> units){
|
||||
clearCommand();
|
||||
|
||||
float spacing = hitSize * 0.65f;
|
||||
float spacing = hitSize * 0.8f;
|
||||
minFormationSpeed = type.speed;
|
||||
|
||||
controlling.addAll(units);
|
||||
@@ -82,7 +82,7 @@ abstract class CommanderComp implements Entityc, Posc{
|
||||
FormationAI ai;
|
||||
unit.controller(ai = new FormationAI(self(), formation));
|
||||
spacing = Math.max(spacing, ai.formationSize());
|
||||
minFormationSpeed = Math.min(minFormationSpeed, unit.type().speed);
|
||||
minFormationSpeed = Math.min(minFormationSpeed, unit.type.speed);
|
||||
}
|
||||
this.formation = formation;
|
||||
|
||||
@@ -106,7 +106,7 @@ abstract class CommanderComp implements Entityc, Posc{
|
||||
//reset controlled units
|
||||
for(Unit unit : controlling){
|
||||
if(unit.controller().isBeingControlled(self())){
|
||||
unit.controller(unit.type().createController());
|
||||
unit.controller(unit.type.createController());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import static mindustry.Vars.*;
|
||||
@EntityDef(value = {Firec.class}, pooled = true)
|
||||
@Component(base = true)
|
||||
abstract class FireComp implements Timedc, Posc, Firec, Syncc{
|
||||
private static final float spreadChance = 0.05f, fireballChance = 0.07f;
|
||||
private static final float spreadChance = 0.04f, fireballChance = 0.06f;
|
||||
|
||||
@Import float time, lifetime, x, y;
|
||||
|
||||
|
||||
@@ -73,4 +73,4 @@ abstract class LaunchCoreComp implements Drawc, Timedc{
|
||||
Fx.rocketSmokeLarge.at(cx() + Mathf.range(r), cy() + Mathf.range(r), fin());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,16 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
|
||||
}
|
||||
|
||||
boolean mining(){
|
||||
return mineTile != null && !(((Object)this) instanceof Builderc && ((Builderc)(Object)this).activelyBuilding());
|
||||
return mineTile != null && !(((Object)this) instanceof Builderc b && b.activelyBuilding());
|
||||
}
|
||||
|
||||
public boolean validMine(Tile tile, boolean checkDst){
|
||||
return !(tile == null || tile.block() != Blocks.air || (!within(tile.worldx(), tile.worldy(), miningRange) && checkDst)
|
||||
|| tile.drop() == null || !canMine(tile.drop()));
|
||||
}
|
||||
|
||||
public boolean validMine(Tile tile){
|
||||
return !(tile == null || tile.block() != Blocks.air || !within(tile.worldx(), tile.worldy(), miningRange)
|
||||
|| tile.drop() == null || !canMine(tile.drop()));
|
||||
return validMine(tile, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,7 +58,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
|
||||
}
|
||||
}
|
||||
|
||||
if(core == null || !validMine(mineTile)){
|
||||
if(!validMine(mineTile)){
|
||||
mineTile = null;
|
||||
mineTimer = 0f;
|
||||
}else if(mining()){
|
||||
@@ -69,7 +73,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
|
||||
if(mineTimer >= 50f + item.hardness*15f){
|
||||
mineTimer = 0;
|
||||
|
||||
if(within(core, mineTransferRange) && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){
|
||||
if(core != null && within(core, mineTransferRange) && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){
|
||||
Call.transferItemTo(item, 1,
|
||||
mineTile.worldx() + Mathf.range(tilesize / 2f),
|
||||
mineTile.worldy() + Mathf.range(tilesize / 2f), core);
|
||||
@@ -84,15 +88,13 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
|
||||
mineTimer = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
if(!mining()) return;
|
||||
float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f);
|
||||
float focusLen = hitSize() / 2f + Mathf.absin(Time.time(), 1.1f, 0.5f);
|
||||
float swingScl = 12f, swingMag = tilesize / 8f;
|
||||
float flashScl = 0.3f;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
@@ -120,7 +121,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
|
||||
/** @return whether the tile has been successfully placed. */
|
||||
boolean dropBlock(BuildPayload payload){
|
||||
Building tile = payload.build;
|
||||
int tx = Vars.world.toTile(x - tile.block.offset), ty = Vars.world.toTile(y - tile.block.offset);
|
||||
int tx = World.toTile(x - tile.block.offset), ty = World.toTile(y - tile.block.offset);
|
||||
Tile on = Vars.world.tile(tx, ty);
|
||||
if(on != null && Build.validPlace(tile.block, tile.team, tx, ty, tile.rotation, false)){
|
||||
int rot = (int)((rotation + 45f) / 90f) % 4;
|
||||
|
||||
@@ -78,8 +78,9 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
||||
team = state.rules.defaultTeam;
|
||||
admin = typing = false;
|
||||
textFadeTime = 0f;
|
||||
x = y = 0f;
|
||||
if(!dead()){
|
||||
unit.controller(unit.type().createController());
|
||||
unit.controller(unit.type.createController());
|
||||
unit = Nulls.unit;
|
||||
}
|
||||
}
|
||||
@@ -91,7 +92,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
||||
|
||||
@Replace
|
||||
public float clipSize(){
|
||||
return unit.isNull() ? 20 : unit.type().hitSize * 2f;
|
||||
return unit.isNull() ? 20 : unit.type.hitSize * 2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -123,7 +124,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
||||
deathTimer = 0;
|
||||
|
||||
//update some basic state to sync things
|
||||
if(unit.type().canBoost){
|
||||
if(unit.type.canBoost){
|
||||
Tile tile = unit.tileOn();
|
||||
unit.elevation = Mathf.approachDelta(unit.elevation, (tile != null && tile.solid()) || boosting ? 1f : 0f, 0.08f);
|
||||
}
|
||||
@@ -177,7 +178,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
||||
|
||||
if(this.unit != Nulls.unit){
|
||||
//un-control the old unit
|
||||
this.unit.controller(this.unit.type().createController());
|
||||
this.unit.controller(this.unit.type.createController());
|
||||
}
|
||||
this.unit = unit;
|
||||
if(unit != Nulls.unit){
|
||||
|
||||
@@ -2,9 +2,9 @@ package mindustry.entities.comp;
|
||||
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.environment.*;
|
||||
|
||||
@@ -32,11 +32,11 @@ abstract class PosComp implements Position{
|
||||
}
|
||||
|
||||
int tileX(){
|
||||
return Vars.world.toTile(x);
|
||||
return World.toTile(x);
|
||||
}
|
||||
|
||||
int tileY(){
|
||||
return Vars.world.toTile(y);
|
||||
return World.toTile(y);
|
||||
}
|
||||
|
||||
/** Returns air if this unit is on a non-air top block. */
|
||||
|
||||
@@ -74,7 +74,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{
|
||||
unit.apply(liquid.effect, 60 * 2);
|
||||
|
||||
if(unit.vel.len() > 0.1){
|
||||
Fx.ripple.at(unit.x, unit.y, unit.type().rippleScale, liquid.color);
|
||||
Fx.ripple.at(unit.x, unit.y, unit.type.rippleScale, liquid.color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{
|
||||
boolean onLiquid = tile.floor().isLiquid;
|
||||
float f = Mathf.clamp(amount / (maxLiquid / 1.5f));
|
||||
float smag = onLiquid ? 0.8f : 0f;
|
||||
float sscl = 20f;
|
||||
float sscl = 25f;
|
||||
|
||||
Draw.color(tmp.set(liquid.color).shiftValue(-0.05f));
|
||||
Fill.circle(x + Mathf.sin(Time.time() + seeds * 532, sscl, smag), y + Mathf.sin(Time.time() + seeds * 53, sscl, smag), f * 8f);
|
||||
|
||||
@@ -22,9 +22,9 @@ abstract class ShieldComp implements Healthc, Posc{
|
||||
@Replace
|
||||
@Override
|
||||
public void damage(float amount){
|
||||
amount /= healthMultiplier;
|
||||
//apply armor
|
||||
amount = Math.max(amount - armor, minArmorDamage * amount);
|
||||
amount /= healthMultiplier;
|
||||
|
||||
hitTime = 1f;
|
||||
|
||||
|
||||
@@ -114,13 +114,14 @@ abstract class StatusComp implements Posc, Flyingc{
|
||||
StatusEntry entry = statuses.get(index++);
|
||||
|
||||
entry.time = Math.max(entry.time - Time.delta, 0);
|
||||
applied.set(entry.effect.id);
|
||||
|
||||
if(entry.time <= 0 && !entry.effect.permanent){
|
||||
if(entry.effect == null || (entry.time <= 0 && !entry.effect.permanent)){
|
||||
Pools.free(entry);
|
||||
index --;
|
||||
statuses.remove(index);
|
||||
}else{
|
||||
applied.set(entry.effect.id);
|
||||
|
||||
speedMultiplier *= entry.effect.speedMultiplier;
|
||||
healthMultiplier *= entry.effect.healthMultiplier;
|
||||
damageMultiplier *= entry.effect.damageMultiplier;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.entities.comp;
|
||||
|
||||
import arc.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
@@ -10,6 +11,7 @@ import arc.util.*;
|
||||
import mindustry.ai.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.abilities.*;
|
||||
@@ -36,7 +38,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
@Import int id;
|
||||
|
||||
private UnitController controller;
|
||||
private UnitType type;
|
||||
UnitType type;
|
||||
boolean spawnedByCore;
|
||||
double flag;
|
||||
|
||||
@@ -70,6 +72,12 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
return Mathf.lerp(1f, type.canBoost ? type.boostMultiplier : 1f, elevation) * type.speed;
|
||||
}
|
||||
|
||||
/** Iterates through this unit and everything it is controlling. */
|
||||
public void eachGroup(Cons<Unit> cons){
|
||||
cons.get(self());
|
||||
controlling().each(cons);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float range(){
|
||||
return type.range;
|
||||
@@ -88,14 +96,14 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
case rotation -> rotation;
|
||||
case health -> health;
|
||||
case maxHealth -> maxHealth;
|
||||
case ammo -> state.rules.unitAmmo ? type.ammoCapacity : ammo;
|
||||
case ammo -> !state.rules.unitAmmo ? type.ammoCapacity : ammo;
|
||||
case ammoCapacity -> type.ammoCapacity;
|
||||
case x -> x;
|
||||
case y -> y;
|
||||
case x -> World.conv(x);
|
||||
case y -> World.conv(y);
|
||||
case team -> team.id;
|
||||
case shooting -> isShooting() ? 1 : 0;
|
||||
case shootX -> aimX();
|
||||
case shootY -> aimY();
|
||||
case shootX -> World.conv(aimX());
|
||||
case shootY -> World.conv(aimY());
|
||||
case flag -> flag;
|
||||
case payloadCount -> self() instanceof Payloadc pay ? pay.payloads().size : 0;
|
||||
default -> 0;
|
||||
@@ -110,7 +118,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
case firstItem -> stack().amount == 0 ? null : item();
|
||||
case payloadType -> self() instanceof Payloadc pay ?
|
||||
(pay.payloads().isEmpty() ? null :
|
||||
pay.payloads().peek() instanceof UnitPayload p1 ? p1.unit.type() :
|
||||
pay.payloads().peek() instanceof UnitPayload p1 ? p1.unit.type :
|
||||
pay.payloads().peek() instanceof BuildPayload p2 ? p2.block() : null) : null;
|
||||
default -> noSensed;
|
||||
};
|
||||
@@ -163,22 +171,12 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
|
||||
@Override
|
||||
public void set(UnitType def, UnitController controller){
|
||||
type(type);
|
||||
if(this.type != def){
|
||||
setType(def);
|
||||
}
|
||||
controller(controller);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void type(UnitType type){
|
||||
if(this.type == type) return;
|
||||
|
||||
setStats(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnitType type(){
|
||||
return type;
|
||||
}
|
||||
|
||||
/** @return pathfinder path type for calculating costs */
|
||||
public int pathType(){
|
||||
return Pathfinder.costGround;
|
||||
@@ -208,7 +206,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
return Units.getCap(team);
|
||||
}
|
||||
|
||||
public void setStats(UnitType type){
|
||||
public void setType(UnitType type){
|
||||
this.type = type;
|
||||
this.maxHealth = type.health;
|
||||
this.drag = type.drag;
|
||||
@@ -226,7 +224,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
@Override
|
||||
public void afterSync(){
|
||||
//set up type info after reading
|
||||
setStats(this.type);
|
||||
setType(this.type);
|
||||
controller.unit(self());
|
||||
}
|
||||
|
||||
@@ -239,12 +237,14 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
|
||||
@Override
|
||||
public void add(){
|
||||
team.data().updateCount(type, 1);
|
||||
|
||||
//check if over unit cap
|
||||
if(count() > cap() && !spawnedByCore && !dead){
|
||||
Call.unitCapDeath(self());
|
||||
team.data().updateCount(type, -1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -286,7 +286,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f);
|
||||
|
||||
//apply knockback based on spawns
|
||||
if(team != state.rules.waveTeam && state.rules.waves){
|
||||
if(team != state.rules.waveTeam && state.hasSpawns()){
|
||||
float relativeSize = state.rules.dropZoneRadius + hitSize/2f + 1f;
|
||||
for(Tile spawn : spawner.getSpawns()){
|
||||
if(within(spawn.worldx(), spawn.worldy(), relativeSize)){
|
||||
|
||||
@@ -95,7 +95,7 @@ public class AIController implements UnitController{
|
||||
|
||||
if(tile == targetTile || (costType == Pathfinder.costWater && !targetTile.floor().isLiquid)) return;
|
||||
|
||||
unit.moveAt(vec.trns(unit.angleTo(targetTile), unit.type().speed));
|
||||
unit.moveAt(vec.trns(unit.angleTo(targetTile), unit.type.speed));
|
||||
}
|
||||
|
||||
protected void updateWeapons(){
|
||||
@@ -105,7 +105,7 @@ public class AIController implements UnitController{
|
||||
boolean ret = retarget();
|
||||
|
||||
if(ret){
|
||||
target = findTarget(unit.x, unit.y, unit.range(), unit.type().targetAir, unit.type().targetGround);
|
||||
target = findTarget(unit.x, unit.y, unit.range(), unit.type.targetAir, unit.type.targetGround);
|
||||
}
|
||||
|
||||
if(invalid(target)){
|
||||
@@ -119,7 +119,7 @@ public class AIController implements UnitController{
|
||||
float mountX = unit.x + Angles.trnsx(rotation, weapon.x, weapon.y),
|
||||
mountY = unit.y + Angles.trnsy(rotation, weapon.x, weapon.y);
|
||||
|
||||
if(unit.type().singleTarget){
|
||||
if(unit.type.singleTarget){
|
||||
targets[i] = target;
|
||||
}else{
|
||||
if(ret){
|
||||
@@ -160,7 +160,7 @@ public class AIController implements UnitController{
|
||||
}
|
||||
|
||||
protected boolean retarget(){
|
||||
return timer.get(timerTarget, 30);
|
||||
return timer.get(timerTarget, 40);
|
||||
}
|
||||
|
||||
protected Teamc findTarget(float x, float y, float range, boolean air, boolean ground){
|
||||
@@ -176,7 +176,7 @@ public class AIController implements UnitController{
|
||||
}
|
||||
|
||||
protected void circle(Position target, float circleLength){
|
||||
circle(target, circleLength, unit.type().speed);
|
||||
circle(target, circleLength, unit.type.speed);
|
||||
}
|
||||
|
||||
protected void circle(Position target, float circleLength, float speed){
|
||||
|
||||
Reference in New Issue
Block a user