Merge branch 'master' of https://github.com/Anuken/Mindustry into new-pathfinding
This commit is contained in:
@@ -293,7 +293,6 @@ public class Damage{
|
||||
collided.each(c -> {
|
||||
if(hitter.damage > 0 && (pierceCap <= 0 || collideCount[0] < pierceCap)){
|
||||
if(c.target instanceof Unit u){
|
||||
effect.at(c.x, c.y);
|
||||
u.collision(hitter, c.x, c.y);
|
||||
hitter.collision(u, c.x, c.y);
|
||||
collideCount[0]++;
|
||||
@@ -344,7 +343,6 @@ public class Damage{
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package mindustry.entities;
|
||||
|
||||
import arc.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.game.EventType.*;
|
||||
@@ -14,13 +12,12 @@ import static mindustry.Vars.*;
|
||||
|
||||
public class Fires{
|
||||
private static final float baseLifetime = 1000f;
|
||||
private static final IntMap<Fire> map = new IntMap<>();
|
||||
|
||||
/** Start a fire on the tile. If there already is a fire there, refreshes its lifetime. */
|
||||
public static void create(Tile tile){
|
||||
if(net.client() || tile == null || !state.rules.fire || !state.rules.hasEnv(Env.oxygen)) return; //not clientside.
|
||||
|
||||
Fire fire = map.get(tile.pos());
|
||||
Fire fire = get(tile);
|
||||
|
||||
if(fire == null){
|
||||
fire = Fire.create();
|
||||
@@ -28,48 +25,58 @@ public class Fires{
|
||||
fire.lifetime = baseLifetime;
|
||||
fire.set(tile.worldx(), tile.worldy());
|
||||
fire.add();
|
||||
map.put(tile.pos(), fire);
|
||||
set(tile, fire);
|
||||
}else{
|
||||
fire.lifetime = baseLifetime;
|
||||
fire.time = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public static Fire get(int x, int y){
|
||||
return map.get(Point2.pack(x, y));
|
||||
public static @Nullable Fire get(Tile tile){
|
||||
return tile == null ? null : world.tiles.getFire(tile.array());
|
||||
}
|
||||
|
||||
public static @Nullable Fire get(int x, int y){
|
||||
return Structs.inBounds(x, y, world.width(), world.height()) ? world.tiles.getFire(world.packArray(x, y)) : null;
|
||||
}
|
||||
|
||||
private static void set(Tile tile, Fire fire){
|
||||
world.tiles.setFire(tile.array(), fire);
|
||||
}
|
||||
|
||||
public static boolean has(int x, int y){
|
||||
if(!Structs.inBounds(x, y, world.width(), world.height()) || !map.containsKey(Point2.pack(x, y))){
|
||||
if(!Structs.inBounds(x, y, world.width(), world.height())){
|
||||
return false;
|
||||
}
|
||||
Fire fire = map.get(Point2.pack(x, y));
|
||||
return fire.isAdded() && fire.fin() < 1f && fire.tile() != null && fire.tile().x == x && fire.tile().y == y;
|
||||
Fire fire = get(x, y);
|
||||
return fire != null && fire.isAdded() && fire.fin() < 1f && fire.tile != null && fire.tile.x == x && fire.tile.y == y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to extinguish a fire by shortening its life. If there is no fire here, does nothing.
|
||||
*/
|
||||
public static void extinguish(Tile tile, float intensity){
|
||||
if(tile != null && map.containsKey(tile.pos())){
|
||||
Fire fire = map.get(tile.pos());
|
||||
fire.time(fire.time + intensity * Time.delta);
|
||||
Fx.steam.at(fire);
|
||||
if(fire.time >= fire.lifetime){
|
||||
Events.fire(Trigger.fireExtinguish);
|
||||
if(tile != null){
|
||||
Fire fire = get(tile);
|
||||
if(fire != null){
|
||||
fire.time(fire.time + intensity * Time.delta);
|
||||
Fx.steam.at(fire);
|
||||
if(fire.time >= fire.lifetime){
|
||||
Events.fire(Trigger.fireExtinguish);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void remove(Tile tile){
|
||||
if(tile != null){
|
||||
map.remove(tile.pos());
|
||||
set(tile, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static void register(Fire fire){
|
||||
if(fire.tile != null){
|
||||
map.put(fire.tile.pos(), fire);
|
||||
set(fire.tile, fire);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ public class Puddles{
|
||||
}
|
||||
|
||||
/** Returns the Puddle on the specified tile. May return null. */
|
||||
public static Puddle get(Tile tile){
|
||||
return world.tiles.puddle(tile.array());
|
||||
public static @Nullable Puddle get(Tile tile){
|
||||
return tile == null ? null : world.tiles.getPuddle(tile.array());
|
||||
}
|
||||
|
||||
public static void deposit(Tile tile, Tile source, Liquid liquid, float amount, boolean initial){
|
||||
@@ -74,7 +74,7 @@ public class Puddles{
|
||||
Puddle puddle = Puddle.create();
|
||||
puddle.tile = tile;
|
||||
puddle.liquid = liquid;
|
||||
puddle.amount = amount;
|
||||
puddle.amount = Math.min(amount, maxLiquid);
|
||||
puddle.set(ax, ay);
|
||||
register(puddle);
|
||||
puddle.add();
|
||||
|
||||
@@ -192,8 +192,18 @@ public class Units{
|
||||
|
||||
/** Returns the nearest enemy tile in a range. */
|
||||
public static Building findEnemyTile(Team team, float x, float y, float range, Boolf<Building> pred){
|
||||
return findEnemyTile(team, x, y, range, false, pred);
|
||||
}
|
||||
|
||||
/** Returns the nearest enemy tile in a range. */
|
||||
public static Building findEnemyTile(Team team, float x, float y, float range, boolean checkUnder, Boolf<Building> pred){
|
||||
if(team == Team.derelict) return null;
|
||||
|
||||
if(checkUnder){
|
||||
Building target = indexer.findEnemyTile(team, x, y, range, build -> !build.block.underBullets && pred.get(build));
|
||||
if(target != null) return target;
|
||||
}
|
||||
|
||||
return indexer.findEnemyTile(team, x, y, range, pred);
|
||||
}
|
||||
|
||||
@@ -214,7 +224,10 @@ public class Units{
|
||||
}
|
||||
});
|
||||
|
||||
return buildResult;
|
||||
var result = buildResult;
|
||||
buildResult = null;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Iterates through all buildings in a range. */
|
||||
@@ -240,7 +253,7 @@ public class Units{
|
||||
if(unit != null){
|
||||
return unit;
|
||||
}else{
|
||||
return findEnemyTile(team, x, y, range, tilePred);
|
||||
return findEnemyTile(team, x, y, range, true, tilePred);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +265,7 @@ public class Units{
|
||||
if(unit != null){
|
||||
return unit;
|
||||
}else{
|
||||
return findEnemyTile(team, x, y, range, tilePred);
|
||||
return findEnemyTile(team, x, y, range, true, tilePred);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
public abstract class Ability implements Cloneable{
|
||||
protected static final float descriptionWidth = 350f;
|
||||
/** If false, this ability does not show in unit stats. */
|
||||
public boolean display = true;
|
||||
//the one and only data variable that is synced.
|
||||
@@ -16,7 +17,16 @@ public abstract class Ability implements Cloneable{
|
||||
public void death(Unit unit){}
|
||||
public void init(UnitType type){}
|
||||
public void displayBars(Unit unit, Table bars){}
|
||||
public void addStats(Table t){}
|
||||
public void addStats(Table t){
|
||||
if(Core.bundle.has(getBundle() + ".description")){
|
||||
t.add(Core.bundle.get(getBundle() + ".description")).wrap().width(descriptionWidth);
|
||||
t.row();
|
||||
}
|
||||
}
|
||||
|
||||
public String abilityStat(String stat, Object... values){
|
||||
return Core.bundle.format("ability.stat." + stat, values);
|
||||
}
|
||||
|
||||
public Ability copy(){
|
||||
try{
|
||||
@@ -29,7 +39,11 @@ public abstract class Ability implements Cloneable{
|
||||
|
||||
/** @return localized ability name; mods should override this. */
|
||||
public String localized(){
|
||||
return Core.bundle.get(getBundle());
|
||||
}
|
||||
|
||||
public String getBundle(){
|
||||
var type = getClass();
|
||||
return Core.bundle.get("ability." + (type.isAnonymousClass() ? type.getSuperclass() : type).getSimpleName().replace("Ability", "").toLowerCase());
|
||||
return "ability." + (type.isAnonymousClass() ? type.getSuperclass() : type).getSimpleName().replace("Ability", "").toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,27 @@ import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.ui.layout.Table;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class ArmorPlateAbility extends Ability{
|
||||
public TextureRegion plateRegion;
|
||||
public Color color = Color.valueOf("d1efff");
|
||||
public TextureRegion shineRegion;
|
||||
public String plateSuffix = "-armor";
|
||||
public String shineSuffix = "-shine";
|
||||
/** Color of the shine. If null, uses team color. */
|
||||
public @Nullable Color color = null;
|
||||
public float shineSpeed = 1f;
|
||||
public float z = -1;
|
||||
|
||||
/** Whether to draw the plate region. */
|
||||
public boolean drawPlate = true;
|
||||
/** Whether to draw the shine over the plate region. */
|
||||
public boolean drawShine = true;
|
||||
|
||||
public float healthMultiplier = 0.2f;
|
||||
public float z = Layer.effect;
|
||||
|
||||
protected float warmup;
|
||||
|
||||
@@ -29,29 +38,45 @@ public class ArmorPlateAbility extends Ability{
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
t.add("[lightgray]" + Stat.healthMultiplier.localized() + ": [white]" + Math.round(healthMultiplier * 100f) + 100 + "%");
|
||||
super.addStats(t);
|
||||
t.add(abilityStat("damagereduction", Strings.autoFixed(-healthMultiplier * 100f, 1)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Unit unit){
|
||||
if(!drawPlate && !drawShine) return;
|
||||
|
||||
if(warmup > 0.001f){
|
||||
if(plateRegion == null){
|
||||
plateRegion = Core.atlas.find(unit.type.name + "-armor", unit.type.region);
|
||||
plateRegion = Core.atlas.find(unit.type.name + plateSuffix, unit.type.region);
|
||||
shineRegion = Core.atlas.find(unit.type.name + shineSuffix, plateRegion);
|
||||
}
|
||||
|
||||
Draw.draw(z <= 0 ? Draw.z() : z, () -> {
|
||||
Shaders.armor.region = plateRegion;
|
||||
Shaders.armor.progress = warmup;
|
||||
Shaders.armor.time = -Time.time / 20f;
|
||||
float pz = Draw.z();
|
||||
if(z > 0) Draw.z(z);
|
||||
|
||||
Draw.rect(Shaders.armor.region, unit.x, unit.y, unit.rotation - 90f);
|
||||
Draw.color(color);
|
||||
Draw.shader(Shaders.armor);
|
||||
Draw.rect(Shaders.armor.region, unit.x, unit.y, unit.rotation - 90f);
|
||||
Draw.shader();
|
||||
if(drawPlate){
|
||||
Draw.alpha(warmup);
|
||||
Draw.rect(plateRegion, unit.x, unit.y, unit.rotation - 90f);
|
||||
Draw.alpha(1f);
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
});
|
||||
if(drawShine){
|
||||
Draw.draw(Draw.z(), () -> {
|
||||
Shaders.armor.region = shineRegion;
|
||||
Shaders.armor.progress = warmup;
|
||||
Shaders.armor.time = -Time.time / 20f * shineSpeed;
|
||||
|
||||
Draw.color(color == null ? unit.team.color : color);
|
||||
Draw.shader(Shaders.armor);
|
||||
Draw.rect(shineRegion, unit.x, unit.y, unit.rotation - 90f);
|
||||
Draw.shader();
|
||||
|
||||
Draw.reset();
|
||||
});
|
||||
}
|
||||
|
||||
Draw.z(pz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@@ -53,23 +52,29 @@ public class EnergyFieldAbility extends Ability{
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
t.add(Core.bundle.format("bullet.damage", damage));
|
||||
if(displayHeal){
|
||||
t.add(Core.bundle.get(getBundle() + ".healdescription")).wrap().width(descriptionWidth);
|
||||
}else{
|
||||
t.add(Core.bundle.get(getBundle() + ".description")).wrap().width(descriptionWidth);
|
||||
}
|
||||
t.row();
|
||||
t.add("[lightgray]" + Stat.reload.localized() + ": [white]" + Strings.autoFixed(60f / reload, 2) + " " + StatUnit.perSecond.localized());
|
||||
t.row();
|
||||
t.add("[lightgray]" + Stat.shootRange.localized() + ": [white]" + Strings.autoFixed(range / tilesize, 2) + " " + StatUnit.blocks.localized());
|
||||
t.row();
|
||||
t.add(Core.bundle.format("ability.energyfield.maxtargets", maxTargets));
|
||||
|
||||
t.add(Core.bundle.format("bullet.range", Strings.autoFixed(range / tilesize, 2)));
|
||||
t.row();
|
||||
t.add(abilityStat("firingrate", Strings.autoFixed(60f / reload, 2)));
|
||||
t.row();
|
||||
t.add(abilityStat("maxtargets", maxTargets));
|
||||
t.row();
|
||||
t.add(Core.bundle.format("bullet.damage", damage));
|
||||
if(status != StatusEffects.none){
|
||||
t.row();
|
||||
t.add((status.hasEmoji() ? status.emoji() : "") + "[stat]" + status.localizedName);
|
||||
}
|
||||
if(displayHeal){
|
||||
t.row();
|
||||
t.add(Core.bundle.format("bullet.healpercent", Strings.autoFixed(healPercent, 2)));
|
||||
t.row();
|
||||
t.add(Core.bundle.format("ability.energyfield.sametypehealmultiplier", Math.round(sameTypeHealMult * 100f)));
|
||||
}
|
||||
if(status != StatusEffects.none){
|
||||
t.row();
|
||||
t.add(status.emoji() + " " + status.localizedName);
|
||||
t.add(abilityStat("sametypehealmultiplier", (sameTypeHealMult < 1f ? "[negstat]" : "") + Strings.autoFixed(sameTypeHealMult * 100f, 2)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.entities.abilities;
|
||||
|
||||
import arc.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
@@ -12,7 +13,6 @@ import mindustry.content.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@@ -73,14 +73,14 @@ public class ForceFieldAbility extends Ability{
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
t.add("[lightgray]" + Stat.health.localized() + ": [white]" + Math.round(max));
|
||||
super.addStats(t);
|
||||
t.add(Core.bundle.format("bullet.range", Strings.autoFixed(radius / tilesize, 2)));
|
||||
t.row();
|
||||
t.add("[lightgray]" + Stat.shootRange.localized() + ": [white]" + Strings.autoFixed(radius / tilesize, 2) + " " + StatUnit.blocks.localized());
|
||||
t.add(abilityStat("shield", Strings.autoFixed(max, 2)));
|
||||
t.row();
|
||||
t.add("[lightgray]" + Stat.repairSpeed.localized() + ": [white]" + Strings.autoFixed(regen * 60f, 2) + StatUnit.perSecond.localized());
|
||||
t.row();
|
||||
t.add("[lightgray]" + Stat.cooldownTime.localized() + ": [white]" + Strings.autoFixed(cooldown / 60f, 2) + " " + StatUnit.seconds.localized());
|
||||
t.add(abilityStat("repairspeed", Strings.autoFixed(regen * 60f, 2)));
|
||||
t.row();
|
||||
t.add(abilityStat("cooldown", Strings.autoFixed(cooldown / 60f, 2)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.entities.abilities;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.noise.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
@@ -16,6 +17,12 @@ public class LiquidExplodeAbility extends Ability{
|
||||
public float radAmountScale = 5f, radScale = 1f;
|
||||
public float noiseMag = 6.5f, noiseScl = 5f;
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
super.addStats(t);
|
||||
t.add((liquid.hasEmoji() ? liquid.emoji() : "") + "[stat]" + liquid.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void death(Unit unit){
|
||||
//TODO what if noise is radial, so it looks like a splat?
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.entities.abilities;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
@@ -17,6 +18,14 @@ public class LiquidRegenAbility extends Ability{
|
||||
public float slurpEffectChance = 0.4f;
|
||||
public Effect slurpEffect = Fx.heal;
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
super.addStats(t);
|
||||
t.add((liquid.hasEmoji() ? liquid.emoji() : "") + "[stat]" + liquid.localizedName);
|
||||
t.row();
|
||||
t.add(abilityStat("slurpheal", Strings.autoFixed(regenPerSlurp, 2)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Unit unit){
|
||||
//TODO timer?
|
||||
|
||||
@@ -5,12 +5,15 @@ import arc.audio.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class MoveLightningAbility extends Ability{
|
||||
/** Lightning damage */
|
||||
public float damage = 35f;
|
||||
@@ -63,7 +66,15 @@ public class MoveLightningAbility extends Ability{
|
||||
this.maxSpeed = maxSpeed;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
super.addStats(t);
|
||||
t.add(abilityStat("minspeed", Strings.autoFixed(minSpeed * 60f / tilesize, 2)));
|
||||
t.row();
|
||||
t.add(Core.bundle.format("bullet.damage", damage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Unit unit){
|
||||
float scl = Mathf.clamp((unit.vel().len() - minSpeed) / (maxSpeed - minSpeed));
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package mindustry.entities.abilities;
|
||||
|
||||
import arc.Core;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class RegenAbility extends Ability{
|
||||
/** Amount healed as percent per tick. */
|
||||
@@ -14,13 +12,16 @@ public class RegenAbility extends Ability{
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
if(amount > 0.01f){
|
||||
t.add("[lightgray]" + Stat.repairSpeed.localized() + ": [white]" + Strings.autoFixed(amount * 60f, 2) + StatUnit.perSecond.localized());
|
||||
t.row();
|
||||
}
|
||||
super.addStats(t);
|
||||
|
||||
if(percentAmount > 0.01f){
|
||||
t.add(Core.bundle.format("bullet.healpercent", Strings.autoFixed(percentAmount * 60f, 2)) + StatUnit.perSecond.localized()); //stupid but works
|
||||
boolean flat = amount >= 0.001f;
|
||||
boolean percent = percentAmount >= 0.001f;
|
||||
|
||||
if(flat || percent){
|
||||
t.add(abilityStat("regen",
|
||||
(flat ? Strings.autoFixed(amount * 60f, 2) + (percent ? " [lightgray]+[stat] " : "") : "")
|
||||
+ (percent ? Strings.autoFixed(percentAmount * 60f, 2) + "%" : "")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package mindustry.entities.abilities;
|
||||
|
||||
import arc.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class RepairFieldAbility extends Ability{
|
||||
public float amount = 1, reload = 100, range = 60;
|
||||
@@ -28,9 +28,10 @@ public class RepairFieldAbility extends Ability{
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
t.add("[lightgray]" + Stat.repairSpeed.localized() + ": [white]" + Strings.autoFixed(amount * 60f / reload, 2) + StatUnit.perSecond.localized());
|
||||
super.addStats(t);
|
||||
t.add(Core.bundle.format("bullet.range", Strings.autoFixed(range / tilesize, 2)));
|
||||
t.row();
|
||||
t.add("[lightgray]" + Stat.shootRange.localized() + ": [white]" + Strings.autoFixed(range / tilesize, 2) + " " + StatUnit.blocks.localized());
|
||||
t.add(abilityStat("repairspeed", Strings.autoFixed(amount * 60f / reload, 2)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,7 +13,6 @@ import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class ShieldArcAbility extends Ability{
|
||||
private static Unit paramUnit;
|
||||
@@ -69,12 +68,12 @@ public class ShieldArcAbility extends Ability{
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
t.add("[lightgray]" + Stat.health.localized() + ": [white]" + Math.round(max));
|
||||
super.addStats(t);
|
||||
t.add(abilityStat("shield", Strings.autoFixed(max, 2)));
|
||||
t.row();
|
||||
t.add("[lightgray]" + Stat.repairSpeed.localized() + ": [white]" + Strings.autoFixed(regen * 60f, 2) + StatUnit.perSecond.localized());
|
||||
t.row();
|
||||
t.add("[lightgray]" + Stat.cooldownTime.localized() + ": [white]" + Strings.autoFixed(cooldown / 60f, 2) + " " + StatUnit.seconds.localized());
|
||||
t.add(abilityStat("repairspeed", Strings.autoFixed(regen * 60f, 2)));
|
||||
t.row();
|
||||
t.add(abilityStat("cooldown", Strings.autoFixed(cooldown / 60f, 2)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package mindustry.entities.abilities;
|
||||
|
||||
import arc.Core;
|
||||
import arc.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class ShieldRegenFieldAbility extends Ability{
|
||||
public float amount = 1, max = 100f, reload = 100, range = 60;
|
||||
@@ -30,12 +29,12 @@ public class ShieldRegenFieldAbility extends Ability{
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
t.add("[lightgray]" + Core.bundle.get("waves.shields") + ": [white]" + Math.round(max)); //extremely stupid usage
|
||||
super.addStats(t);
|
||||
t.add(Core.bundle.format("bullet.range", Strings.autoFixed(range / tilesize, 2)));
|
||||
t.row();
|
||||
t.add("[lightgray]" + Stat.shootRange.localized() + ": [white]" + Strings.autoFixed(range / tilesize, 2) + " " + StatUnit.blocks.localized());
|
||||
t.row();
|
||||
t.add("[lightgray]" + Stat.reload.localized() + ": [white]" + Strings.autoFixed(60f / reload, 2) + " " + StatUnit.perSecond.localized());
|
||||
t.add(abilityStat("firingrate", Strings.autoFixed(60f / reload, 2)));
|
||||
t.row();
|
||||
t.add(abilityStat("shield", Strings.autoFixed(max, 2)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,7 +27,8 @@ public class SpawnDeathAbility extends Ability{
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
t.add((randAmount > 0 ? amount + "-" + (amount + randAmount) : amount) + " " + unit.emoji() + " " + unit.localizedName);
|
||||
super.addStats(t);
|
||||
t.add("[stat]" + (randAmount > 0 ? amount + "x-" + (amount + randAmount) : amount) + "x[] " + (unit.hasEmoji() ? unit.emoji() : "") + "[stat]" + unit.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package mindustry.entities.abilities;
|
||||
|
||||
import arc.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.ui.layout.Table;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class StatusFieldAbility extends Ability{
|
||||
public StatusEffect effect;
|
||||
@@ -33,11 +33,12 @@ public class StatusFieldAbility extends Ability{
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
t.add("[lightgray]" + Stat.reload.localized() + ": [white]" + Strings.autoFixed(60f / reload, 2) + " " + StatUnit.perSecond.localized());
|
||||
super.addStats(t);
|
||||
t.add(Core.bundle.format("bullet.range", Strings.autoFixed(range / tilesize, 2)));
|
||||
t.row();
|
||||
t.add("[lightgray]" + Stat.shootRange.localized() + ": [white]" + Strings.autoFixed(range / tilesize, 2) + " " + StatUnit.blocks.localized());
|
||||
t.add(abilityStat("firingrate", Strings.autoFixed(60f / reload, 2)));
|
||||
t.row();
|
||||
t.add(effect.emoji() + " " + effect.localizedName);
|
||||
t.add((effect.hasEmoji() ? effect.emoji() : "") + "[stat]" + effect.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
package mindustry.entities.abilities;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class SuppressionFieldAbility extends Ability{
|
||||
protected static Rand rand = new Rand();
|
||||
@@ -33,6 +38,19 @@ public class SuppressionFieldAbility extends Ability{
|
||||
|
||||
protected float timer;
|
||||
|
||||
@Override
|
||||
public void init(UnitType type){
|
||||
if(!active) display = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
super.addStats(t);
|
||||
t.add(Core.bundle.format("bullet.range", Strings.autoFixed(range / tilesize, 2)));
|
||||
t.row();
|
||||
t.add(abilityStat("duration", Strings.autoFixed(reload / 60f, 2)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Unit unit){
|
||||
if(!active) return;
|
||||
|
||||
@@ -12,7 +12,6 @@ import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@@ -36,9 +35,10 @@ public class UnitSpawnAbility extends Ability{
|
||||
|
||||
@Override
|
||||
public void addStats(Table t){
|
||||
t.add("[lightgray]" + Stat.buildTime.localized() + ": [white]" + Strings.autoFixed(spawnTime / 60f, 2) + " " + StatUnit.seconds.localized());
|
||||
super.addStats(t);
|
||||
t.add(abilityStat("buildtime", Strings.autoFixed(spawnTime / 60f, 2)));
|
||||
t.row();
|
||||
t.add(unit.emoji() + " " + unit.localizedName);
|
||||
t.add((unit.hasEmoji() ? unit.emoji() : "") + "[stat]" + unit.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -174,6 +174,10 @@ public class BulletType extends Content implements Cloneable{
|
||||
public float fragVelocityMin = 0.2f, fragVelocityMax = 1f;
|
||||
/** Random range of frag lifetime as a multiplier. */
|
||||
public float fragLifeMin = 1f, fragLifeMax = 1f;
|
||||
/** Random offset of frag bullets from the parent bullet. */
|
||||
public float fragOffsetMin = 1f, fragOffsetMax = 7f;
|
||||
/** How many times this bullet can release frag bullets, if pierce = true. */
|
||||
public int pierceFragCap = -1;
|
||||
|
||||
/** Bullet that is created at a fixed interval. */
|
||||
public @Nullable BulletType intervalBullet;
|
||||
@@ -387,14 +391,14 @@ public class BulletType extends Content implements Cloneable{
|
||||
|
||||
if(entity instanceof Healthc h){
|
||||
float damage = b.damage;
|
||||
float shield = entity instanceof Shieldc s ? Math.max(s.shield(), 0f) : 0f;
|
||||
if(maxDamageFraction > 0){
|
||||
float cap = h.maxHealth() * maxDamageFraction;
|
||||
if(entity instanceof Shieldc s){
|
||||
cap += Math.max(s.shield(), 0f);
|
||||
}
|
||||
float cap = h.maxHealth() * maxDamageFraction + shield;
|
||||
damage = Math.min(damage, cap);
|
||||
//cap health to effective health for handlePierce to handle it properly
|
||||
health = Math.min(health, cap);
|
||||
}else{
|
||||
health += shield;
|
||||
}
|
||||
if(pierceArmor){
|
||||
h.damagePierce(damage);
|
||||
@@ -507,12 +511,13 @@ public class BulletType extends Content implements Cloneable{
|
||||
}
|
||||
|
||||
public void createFrags(Bullet b, float x, float y){
|
||||
if(fragBullet != null && (fragOnAbsorb || !b.absorbed)){
|
||||
if(fragBullet != null && (fragOnAbsorb || !b.absorbed) && !(b.frags >= pierceFragCap && pierceFragCap > 0)){
|
||||
for(int i = 0; i < fragBullets; i++){
|
||||
float len = Mathf.random(1f, 7f);
|
||||
float len = Mathf.random(fragOffsetMin, fragOffsetMax);
|
||||
float a = b.rotation() + Mathf.range(fragRandomSpread / 2) + fragAngle + ((i - fragBullets/2) * fragSpread);
|
||||
fragBullet.create(b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax), Mathf.random(fragLifeMin, fragLifeMax));
|
||||
}
|
||||
b.frags++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ public class ContinuousFlameBulletType extends ContinuousBulletType{
|
||||
lifetime = 16f;
|
||||
hitColor = colors[1].cpy().a(1f);
|
||||
lightColor = hitColor;
|
||||
lightOpacity = 0.7f;
|
||||
laserAbsorb = false;
|
||||
ammoMultiplier = 1f;
|
||||
pierceArmor = true;
|
||||
@@ -87,7 +88,7 @@ public class ContinuousFlameBulletType extends ContinuousBulletType{
|
||||
}
|
||||
|
||||
Tmp.v1.trns(b.rotation(), realLength * 1.1f);
|
||||
Drawf.light(b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, lightStroke, lightColor, 0.7f);
|
||||
Drawf.light(b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, lightStroke, lightColor, lightOpacity);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,6 @@ public class RailBulletType extends BulletType{
|
||||
|
||||
if(b.damage > 0){
|
||||
pierceEffect.at(x, y, b.rotation());
|
||||
|
||||
hitEffect.at(x, y);
|
||||
}
|
||||
|
||||
//subtract health from each consecutive pierce
|
||||
|
||||
@@ -86,9 +86,9 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{
|
||||
buildAlpha = Mathf.lerpDelta(buildAlpha, activelyBuilding() ? 1f : 0f, 0.15f);
|
||||
}
|
||||
|
||||
//validate regardless of whether building is enabled.
|
||||
validatePlans();
|
||||
|
||||
if(!updateBuilding || !canBuild()){
|
||||
validatePlans();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -99,19 +99,18 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{
|
||||
if(Float.isNaN(buildCounter) || Float.isInfinite(buildCounter)) buildCounter = 0f;
|
||||
buildCounter = Math.min(buildCounter, 10f);
|
||||
|
||||
boolean instant = state.rules.instantBuild && state.rules.infiniteResources;
|
||||
|
||||
//random attempt to fix a freeze that only occurs on Android
|
||||
int maxPerFrame = 10, count = 0;
|
||||
int maxPerFrame = instant ? plans.size : 10, count = 0;
|
||||
|
||||
while(buildCounter >= 1 && count++ < maxPerFrame){
|
||||
var core = core();
|
||||
|
||||
if((core == null && !infinite)) return;
|
||||
|
||||
while((buildCounter >= 1 || instant) && count++ < maxPerFrame && plans.size > 0){
|
||||
buildCounter -= 1f;
|
||||
|
||||
validatePlans();
|
||||
|
||||
var core = core();
|
||||
|
||||
//nothing to build.
|
||||
if(buildPlan() == null) return;
|
||||
|
||||
//find the next build plan
|
||||
if(plans.size > 1){
|
||||
int total = 0;
|
||||
@@ -163,7 +162,7 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{
|
||||
}
|
||||
|
||||
//if there is no core to build with or no build entity, stop building!
|
||||
if((core == null && !infinite) || !(tile.build instanceof ConstructBuild entity)){
|
||||
if(!(tile.build instanceof ConstructBuild entity)){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -1310,7 +1310,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
if(value instanceof UnitType) type = UnitType.class;
|
||||
|
||||
if(builder != null && builder.isPlayer()){
|
||||
lastAccessed = builder.getPlayer().coloredName();
|
||||
updateLastAccess(builder.getPlayer());
|
||||
}
|
||||
|
||||
if(block.configurations.containsKey(type)){
|
||||
@@ -1324,6 +1324,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLastAccess(Player player){
|
||||
lastAccessed = player.coloredName();
|
||||
}
|
||||
|
||||
/** Called when the block is tapped by the local player. */
|
||||
public void tapped(){
|
||||
|
||||
@@ -1344,6 +1348,15 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
return block.itemCapacity;
|
||||
}
|
||||
|
||||
/** Called when a block begins (not finishes!) deconstruction. The building is still present at this point. */
|
||||
public void onDeconstructed(@Nullable Unit builder){
|
||||
//deposit non-incinerable liquid on ground
|
||||
if(liquids != null && liquids.currentAmount() > 0 && (!liquids.current().incinerable || block.deconstructDropAllLiquid)){
|
||||
float perCell = liquids.currentAmount() / (block.size * block.size) * 2f;
|
||||
tile.getLinkedTiles(other -> Puddles.deposit(other, liquids.current(), perCell));
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the block is destroyed. The tile is still intact at this stage. */
|
||||
public void onDestroyed(){
|
||||
float explosiveness = block.baseExplosiveness;
|
||||
|
||||
@@ -45,6 +45,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
|
||||
transient @Nullable Mover mover;
|
||||
transient boolean absorbed, hit;
|
||||
transient @Nullable Trail trail;
|
||||
transient int frags;
|
||||
|
||||
@Override
|
||||
public void getCollisions(Cons<QuadTree> consumer){
|
||||
|
||||
@@ -4,6 +4,7 @@ import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.blocks.*;
|
||||
|
||||
@Component
|
||||
abstract class ChildComp implements Posc, Rotc{
|
||||
@@ -18,9 +19,14 @@ abstract class ChildComp implements Posc, Rotc{
|
||||
if(parent != null){
|
||||
offsetX = x - parent.getX();
|
||||
offsetY = y - parent.getY();
|
||||
if(rotWithParent && parent instanceof Rotc r){
|
||||
offsetPos = -r.rotation();
|
||||
offsetRot = rotation - r.rotation();
|
||||
if(rotWithParent){
|
||||
if(parent instanceof Rotc r){
|
||||
offsetPos = -r.rotation();
|
||||
offsetRot = rotation - r.rotation();
|
||||
}else if(parent instanceof RotBlock rot){
|
||||
offsetPos = -rot.buildRotation();
|
||||
offsetRot = rotation - rot.buildRotation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,10 +34,16 @@ abstract class ChildComp implements Posc, Rotc{
|
||||
@Override
|
||||
public void update(){
|
||||
if(parent != null){
|
||||
if(rotWithParent && parent instanceof Rotc r){
|
||||
x = parent.getX() + Angles.trnsx(r.rotation() + offsetPos, offsetX, offsetY);
|
||||
y = parent.getY() + Angles.trnsy(r.rotation() + offsetPos, offsetX, offsetY);
|
||||
rotation = r.rotation() + offsetRot;
|
||||
if(rotWithParent){
|
||||
if(parent instanceof Rotc r){
|
||||
x = parent.getX() + Angles.trnsx(r.rotation() + offsetPos, offsetX, offsetY);
|
||||
y = parent.getY() + Angles.trnsy(r.rotation() + offsetPos, offsetX, offsetY);
|
||||
rotation = r.rotation() + offsetRot;
|
||||
}else if(parent instanceof RotBlock rot){
|
||||
x = parent.getX() + Angles.trnsx(rot.buildRotation() + offsetPos, offsetX, offsetY);
|
||||
y = parent.getY() + Angles.trnsy(rot.buildRotation() + offsetPos, offsetX, offsetY);
|
||||
rotation = rot.buildRotation() + offsetRot;
|
||||
}
|
||||
}else{
|
||||
x = parent.getX() + offsetX;
|
||||
y = parent.getY() + offsetY;
|
||||
|
||||
@@ -66,4 +66,9 @@ abstract class EntityComp{
|
||||
void afterRead(){
|
||||
|
||||
}
|
||||
|
||||
/** Called after *all* entities are read. */
|
||||
void afterAllRead(){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,11 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(){
|
||||
if(Vars.state.rules.unitPayloadsExplode) payloads.each(Payload::destroyed);
|
||||
}
|
||||
|
||||
float payloadUsed(){
|
||||
return payloads.sumf(p -> p.size() * p.size());
|
||||
}
|
||||
|
||||
@@ -183,6 +183,9 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
||||
if(!unit.isNull()){
|
||||
clearUnit();
|
||||
}
|
||||
|
||||
lastReadUnit = Nulls.unit;
|
||||
justSwitchTo = justSwitchFrom = null;
|
||||
}
|
||||
|
||||
public void team(Team team){
|
||||
|
||||
@@ -59,6 +59,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc, Syncc{
|
||||
|
||||
amount -= Time.delta * (1f - liquid.viscosity) / (5f + addSpeed);
|
||||
amount += accepting;
|
||||
amount = Math.min(amount, maxLiquid);
|
||||
accepting = 0f;
|
||||
|
||||
if(amount >= maxLiquid / 1.5f){
|
||||
|
||||
@@ -127,10 +127,10 @@ abstract class StatusComp implements Posc, Flyingc{
|
||||
return entry;
|
||||
}
|
||||
|
||||
/** Uses a dynamic status effect to override speed. */
|
||||
/** Uses a dynamic status effect to override speed (in tiles/second). */
|
||||
public void statusSpeed(float speed){
|
||||
//type.speed should never be 0
|
||||
applyDynamicStatus().speedMultiplier = speed / type.speed;
|
||||
applyDynamicStatus().speedMultiplier = speed / (type.speed * 60f / tilesize);
|
||||
}
|
||||
|
||||
/** Uses a dynamic status effect to change damage. */
|
||||
|
||||
@@ -92,7 +92,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
moveAt(Tmp.v2.trns(rotation, vec.len()));
|
||||
|
||||
if(!vec.isZero()){
|
||||
rotation = Angles.moveToward(rotation, vec.angle(), type.rotateSpeed * Time.delta);
|
||||
rotation = Angles.moveToward(rotation, vec.angle(), type.rotateSpeed * Time.delta * speedMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,6 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
return !type.flying && world.tiles.in(tileX, tileY) && type.pathCost.getCost(team.id, pathfinder.get(tileX, tileY)) == -1;
|
||||
}
|
||||
|
||||
|
||||
/** @return approx. square size of the physical hitbox for physics */
|
||||
public float physicSize(){
|
||||
return hitSize * 0.7f;
|
||||
@@ -490,6 +489,11 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterAllRead(){
|
||||
controller.afterRead(self());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(){
|
||||
team.data().updateCount(type, 1);
|
||||
@@ -730,7 +734,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
/** @return name of direct or indirect player controller. */
|
||||
@Override
|
||||
public @Nullable String getControllerName(){
|
||||
if(isPlayer()) return getPlayer().name;
|
||||
if(isPlayer()) return getPlayer().coloredName();
|
||||
if(controller instanceof LogicAI ai && ai.controller != null) return ai.controller.lastAccessed;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -21,18 +21,32 @@ public class SoundEffect extends Effect{
|
||||
public Effect effect;
|
||||
|
||||
public SoundEffect(){
|
||||
startDelay = -1;
|
||||
}
|
||||
|
||||
public SoundEffect(Sound sound, Effect effect){
|
||||
this();
|
||||
this.sound = sound;
|
||||
this.effect = effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
if(startDelay < 0){
|
||||
startDelay = effect.startDelay;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(float x, float y, float rotation, Color color, Object data){
|
||||
if(!shouldCreate()) return;
|
||||
|
||||
sound.at(x, y, Mathf.random(minPitch, maxPitch), Mathf.random(minVolume, maxVolume));
|
||||
if(startDelay > 0){
|
||||
Time.run(startDelay, () -> sound.at(x, y, Mathf.random(minPitch, maxPitch), Mathf.random(minVolume, maxVolume)));
|
||||
}else{
|
||||
sound.at(x, y, Mathf.random(minPitch, maxPitch), Mathf.random(minVolume, maxVolume));
|
||||
}
|
||||
|
||||
effect.create(x, y, rotation, color, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,8 +85,10 @@ public abstract class DrawPart{
|
||||
/** Weapon heat, 1 when just fired, 0, when it has cooled down (duration depends on weapon) */
|
||||
heat = p -> p.heat,
|
||||
/** Lifetime fraction, 0 to 1. Only for missiles. */
|
||||
life = p -> p.life;
|
||||
|
||||
life = p -> p.life,
|
||||
/** Current unscaled value of Time.time. */
|
||||
time = p -> Time.time;
|
||||
|
||||
float get(PartParams p);
|
||||
|
||||
static PartProgress constant(float value){
|
||||
@@ -167,6 +169,14 @@ public abstract class DrawPart{
|
||||
default PartProgress absin(float scl, float mag){
|
||||
return p -> get(p) + Mathf.absin(scl, mag);
|
||||
}
|
||||
|
||||
default PartProgress mod(float amount){
|
||||
return p -> Mathf.mod(get(p), amount);
|
||||
}
|
||||
|
||||
default PartProgress loop(float time){
|
||||
return p -> Mathf.mod(get(p)/time, 1);
|
||||
}
|
||||
|
||||
default PartProgress apply(PartProgress other, PartFunc func){
|
||||
return p -> func.get(get(p), other.get(p));
|
||||
|
||||
@@ -55,6 +55,11 @@ public class AIController implements UnitController{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRead(Unit unit){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLogicControllable(){
|
||||
return true;
|
||||
@@ -222,7 +227,7 @@ public class AIController implements UnitController{
|
||||
}
|
||||
|
||||
public Teamc target(float x, float y, float range, boolean air, boolean ground){
|
||||
return Units.closestTarget(unit.team, x, y, range, u -> u.checkTarget(air, ground), t -> ground);
|
||||
return Units.closestTarget(unit.team, x, y, range, u -> u.checkTarget(air, ground), t -> ground && (unit.type.targetUnderBlocks || !t.block.underBullets));
|
||||
}
|
||||
|
||||
public boolean retarget(){
|
||||
@@ -272,7 +277,7 @@ public class AIController implements UnitController{
|
||||
|
||||
vec.setLength(prefSpeed());
|
||||
|
||||
unit.moveAt(vec);
|
||||
unit.movePref(vec);
|
||||
}
|
||||
|
||||
public void circle(Position target, float circleLength){
|
||||
@@ -290,7 +295,7 @@ public class AIController implements UnitController{
|
||||
|
||||
vec.setLength(speed);
|
||||
|
||||
unit.moveAt(vec);
|
||||
unit.movePref(vec);
|
||||
}
|
||||
|
||||
public void moveTo(Position target, float circleLength){
|
||||
|
||||
@@ -27,6 +27,10 @@ public interface UnitController{
|
||||
|
||||
}
|
||||
|
||||
default void afterRead(Unit unit){
|
||||
|
||||
}
|
||||
|
||||
default boolean isBeingControlled(Unit player){
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ public class WeaponMount{
|
||||
public int totalShots;
|
||||
/** counter for which barrel bullets have been fired from; used for alternating patterns */
|
||||
public int barrelCounter;
|
||||
/** Last aim length of weapon. Only used for point lasers. */
|
||||
public float lastLength;
|
||||
/** current bullet for continuous weapons */
|
||||
public @Nullable Bullet bullet;
|
||||
/** sound loop for continuous weapons */
|
||||
|
||||
Reference in New Issue
Block a user