Merge branch 'master' of https://github.com/Anuken/Mindustry into 7.0-features
Conflicts: gradle.properties
This commit is contained in:
@@ -149,7 +149,16 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
|
||||
}
|
||||
mods.eachClass(Mod::init);
|
||||
finished = true;
|
||||
Events.fire(new ClientLoadEvent());
|
||||
var event = new ClientLoadEvent();
|
||||
//a temporary measure for compatibility with certain mods
|
||||
Events.fireWrap(event.getClass(), event, listener -> {
|
||||
try{
|
||||
listener.get(event);
|
||||
}catch(NoSuchFieldError | NoSuchMethodError | NoClassDefFoundError error){
|
||||
Log.err(error);
|
||||
}
|
||||
|
||||
});
|
||||
clientLoaded = true;
|
||||
super.resize(graphics.getWidth(), graphics.getHeight());
|
||||
app.post(() -> app.post(() -> app.post(() -> app.post(() -> {
|
||||
|
||||
@@ -73,8 +73,8 @@ public class Vars implements Loadable{
|
||||
/** URL to the JSON file containing all the BE servers. Only queried in BE. */
|
||||
public static final String serverJsonBeURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_be.json";
|
||||
/** URL to the JSON file containing all the stable servers. */
|
||||
//TODO this uses BE servers until full v7 release, there's no point in displaying v6 at all
|
||||
public static final String serverJsonURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_be.json";
|
||||
//TODO merge with v6 list upon release
|
||||
public static final String serverJsonURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_v7.json";
|
||||
/** URL of the github issue report template.*/
|
||||
public static final String reportIssueURL = "https://github.com/Anuken/Mindustry/issues/new?labels=bug&template=bug_report.md";
|
||||
/** list of built-in servers.*/
|
||||
@@ -148,6 +148,8 @@ public class Vars implements Loadable{
|
||||
public static int maxTextureSize = 2048;
|
||||
/** Whether to show the core landing animation. */
|
||||
public static boolean showLandAnimation = true;
|
||||
/** Whether to check for memory use before taking screenshots. */
|
||||
public static boolean checkScreenshotMemory = true;
|
||||
/** Whether to prompt the user to confirm exiting. */
|
||||
public static boolean confirmExit = true;
|
||||
/** if true, UI is not drawn */
|
||||
|
||||
@@ -31,7 +31,7 @@ public class MinerAI extends AIController{
|
||||
//core full of the target item, do nothing
|
||||
if(targetItem != null && core.acceptStack(targetItem, 1, unit) == 0){
|
||||
unit.clearItem();
|
||||
unit.mineTile =null;
|
||||
unit.mineTile = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public class MinerAI extends AIController{
|
||||
if(unit.stack.amount >= unit.type.itemCapacity || (targetItem != null && !unit.acceptsItem(targetItem))){
|
||||
mining = false;
|
||||
}else{
|
||||
if(timer.get(timerTarget, 60) && targetItem != null){
|
||||
if(timer.get(timerTarget3, 60) && targetItem != null){
|
||||
ore = indexer.findClosestOre(unit, targetItem);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ public class PhysicsProcess implements AsyncProcess{
|
||||
@Override
|
||||
public void begin(){
|
||||
if(physics == null) return;
|
||||
boolean local = !Vars.net.client();
|
||||
|
||||
//remove stale entities
|
||||
refs.removeAll(ref -> {
|
||||
@@ -60,8 +61,9 @@ public class PhysicsProcess implements AsyncProcess{
|
||||
ref.body.layer =
|
||||
entity.type.allowLegStep ? layerLegs :
|
||||
entity.isGrounded() ? layerGround : layerFlying;
|
||||
ref.x = entity.x();
|
||||
ref.y = entity.y();
|
||||
ref.x = entity.x;
|
||||
ref.y = entity.y;
|
||||
ref.body.local = local || entity.isLocal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,6 +158,10 @@ public class PhysicsProcess implements AsyncProcess{
|
||||
|
||||
for(int i = 0; i < bodies.size; i++){
|
||||
PhysicsBody body = bodies.items[i];
|
||||
|
||||
//for clients, the only body that collides is the local one; all other physics simulations are handled by the server.
|
||||
if(!body.local) continue;
|
||||
|
||||
body.hitbox(rect);
|
||||
|
||||
seq.size = 0;
|
||||
@@ -174,10 +180,14 @@ public class PhysicsProcess implements AsyncProcess{
|
||||
float ms = body.mass + other.mass;
|
||||
float m1 = other.mass / ms, m2 = body.mass / ms;
|
||||
|
||||
//first body is always local due to guard check above
|
||||
body.x += vec.x * m1 / scl;
|
||||
body.y += vec.y * m1 / scl;
|
||||
other.x -= vec.x * m2 / scl;
|
||||
other.y -= vec.y * m2 / scl;
|
||||
|
||||
if(other.local){
|
||||
other.x -= vec.x * m2 / scl;
|
||||
other.y -= vec.y * m2 / scl;
|
||||
}
|
||||
}
|
||||
}
|
||||
body.collided = true;
|
||||
@@ -187,7 +197,7 @@ public class PhysicsProcess implements AsyncProcess{
|
||||
public static class PhysicsBody implements QuadTreeObject{
|
||||
public float x, y, radius, mass;
|
||||
public int layer = 0;
|
||||
public boolean collided = false;
|
||||
public boolean collided = false, local = true;
|
||||
|
||||
@Override
|
||||
public void hitbox(Rect out){
|
||||
|
||||
@@ -60,7 +60,7 @@ public class Blocks implements ContentList{
|
||||
cellSynthesisChamber,
|
||||
|
||||
//sandbox
|
||||
powerSource, powerVoid, itemSource, itemVoid, liquidSource, liquidVoid, payloadVoid, payloadSource, illuminator,
|
||||
powerSource, powerVoid, itemSource, itemVoid, liquidSource, liquidVoid, payloadSource, payloadVoid, illuminator,
|
||||
|
||||
//defense
|
||||
copperWall, copperWallLarge, titaniumWall, titaniumWallLarge, plastaniumWall, plastaniumWallLarge, thoriumWall, thoriumWallLarge, door, doorLarge,
|
||||
@@ -1178,17 +1178,17 @@ public class Blocks implements ContentList{
|
||||
//special transport blocks
|
||||
|
||||
duct = new Duct("duct"){{
|
||||
requirements(Category.distribution, with(Items.graphite, 5, Items.metaglass, 2));
|
||||
requirements(Category.distribution, BuildVisibility.debugOnly, with(Items.graphite, 5, Items.metaglass, 2));
|
||||
speed = 4f;
|
||||
}};
|
||||
|
||||
ductRouter = new DuctRouter("duct-router"){{
|
||||
requirements(Category.distribution, with(Items.graphite, 10, Items.metaglass, 4));
|
||||
requirements(Category.distribution, BuildVisibility.debugOnly, with(Items.graphite, 10, Items.metaglass, 4));
|
||||
speed = 4f;
|
||||
}};
|
||||
|
||||
ductBridge = new DuctBridge("duct-bridge"){{
|
||||
requirements(Category.distribution, with(Items.graphite, 20, Items.metaglass, 8));
|
||||
requirements(Category.distribution, BuildVisibility.debugOnly, with(Items.graphite, 20, Items.metaglass, 8));
|
||||
speed = 4f;
|
||||
}};
|
||||
|
||||
@@ -1757,13 +1757,13 @@ public class Blocks implements ContentList{
|
||||
shots = 4;
|
||||
burstSpacing = 5;
|
||||
inaccuracy = 10f;
|
||||
range = 210f;
|
||||
range = 215f;
|
||||
xRand = 6f;
|
||||
size = 2;
|
||||
health = 300 * size * size;
|
||||
shootSound = Sounds.missile;
|
||||
|
||||
limitRange(2f);
|
||||
limitRange(5f);
|
||||
}};
|
||||
|
||||
salvo = new ItemTurret("salvo"){{
|
||||
@@ -1778,7 +1778,7 @@ public class Blocks implements ContentList{
|
||||
|
||||
size = 2;
|
||||
range = 190f;
|
||||
reloadTime = 34f;
|
||||
reloadTime = 31f;
|
||||
restitution = 0.03f;
|
||||
ammoEjectBack = 3f;
|
||||
cooldown = 0.03f;
|
||||
@@ -2147,7 +2147,7 @@ public class Blocks implements ContentList{
|
||||
}};
|
||||
|
||||
repairPoint = new RepairPoint("repair-point"){{
|
||||
requirements(Category.units, with(Items.lead, 20, Items.copper, 20, Items.silicon, 15));
|
||||
requirements(Category.units, with(Items.lead, 25, Items.copper, 25, Items.silicon, 20));
|
||||
repairSpeed = 0.5f;
|
||||
repairRadius = 65f;
|
||||
beamWidth = 0.73f;
|
||||
@@ -2156,16 +2156,16 @@ public class Blocks implements ContentList{
|
||||
}};
|
||||
|
||||
repairTurret = new RepairPoint("repair-turret"){{
|
||||
requirements(Category.units, with(Items.silicon, 70, Items.thorium, 60, Items.plastanium, 60));
|
||||
requirements(Category.units, with(Items.silicon, 90, Items.thorium, 80, Items.plastanium, 80));
|
||||
size = 2;
|
||||
length = 6f;
|
||||
repairSpeed = 4f;
|
||||
repairSpeed = 3.25f;
|
||||
repairRadius = 140f;
|
||||
powerUse = 5f;
|
||||
beamWidth = 1.1f;
|
||||
pulseRadius = 6.1f;
|
||||
coolantUse = 0.15f;
|
||||
coolantMultiplier = 1.7f;
|
||||
coolantUse = 0.16f;
|
||||
coolantMultiplier = 1.5f;
|
||||
acceptCoolant = true;
|
||||
}};
|
||||
|
||||
@@ -2266,12 +2266,12 @@ public class Blocks implements ContentList{
|
||||
alwaysUnlocked = true;
|
||||
}};
|
||||
|
||||
payloadVoid = new PayloadVoid("payload-void"){{
|
||||
payloadSource = new PayloadSource("payload-source"){{
|
||||
requirements(Category.units, BuildVisibility.sandboxOnly, with());
|
||||
size = 5;
|
||||
}};
|
||||
|
||||
payloadSource = new PayloadSource("payload-source"){{
|
||||
payloadVoid = new PayloadVoid("payload-void"){{
|
||||
requirements(Category.units, BuildVisibility.sandboxOnly, with());
|
||||
size = 5;
|
||||
}};
|
||||
|
||||
@@ -257,7 +257,6 @@ public class Bullets implements ContentList{
|
||||
width = 8f;
|
||||
height = 8f;
|
||||
shrinkY = 0f;
|
||||
drag = -0.01f;
|
||||
splashDamageRadius = 30f;
|
||||
splashDamage = 30f * 1.5f;
|
||||
ammoMultiplier = 5f;
|
||||
@@ -274,7 +273,6 @@ public class Bullets implements ContentList{
|
||||
width = 7f;
|
||||
height = 8f;
|
||||
shrinkY = 0f;
|
||||
drag = -0.01f;
|
||||
homingPower = 0.08f;
|
||||
splashDamageRadius = 20f;
|
||||
splashDamage = 20f * 1.5f;
|
||||
@@ -288,7 +286,6 @@ public class Bullets implements ContentList{
|
||||
width = 8f;
|
||||
height = 8f;
|
||||
shrinkY = 0f;
|
||||
drag = -0.01f;
|
||||
splashDamageRadius = 25f;
|
||||
splashDamage = 25f * 1.4f;
|
||||
hitEffect = Fx.blastExplosion;
|
||||
|
||||
@@ -854,7 +854,7 @@ public class Fx{
|
||||
fireRemove = new Effect(70f, e -> {
|
||||
if(Fire.regions[0] == null) return;
|
||||
alpha(e.fout());
|
||||
rect(Fire.regions[((int)(e.rotation + e.fin() * Fire.frames)) % Fire.frames], e.x, e.y);
|
||||
rect(Fire.regions[((int)(e.rotation + e.fin() * Fire.frames)) % Fire.frames], e.x + Mathf.randomSeedRange((int)e.y, 2), e.y + Mathf.randomSeedRange((int)e.x, 2));
|
||||
Drawf.light(e.x, e.y, 50f + Mathf.absin(5f, 5f), Pal.lightFlame, 0.6f * e.fout());
|
||||
}),
|
||||
|
||||
|
||||
@@ -572,7 +572,7 @@ public class UnitTypes implements ContentList{
|
||||
speed = 1f;
|
||||
splashDamageRadius = 60f;
|
||||
instantDisappear = true;
|
||||
splashDamage = 88f;
|
||||
splashDamage = 90f;
|
||||
killShooter = true;
|
||||
hittable = false;
|
||||
collidesAir = true;
|
||||
@@ -581,7 +581,7 @@ public class UnitTypes implements ContentList{
|
||||
}};
|
||||
|
||||
atrax = new UnitType("atrax"){{
|
||||
speed = 0.5f;
|
||||
speed = 0.54f;
|
||||
drag = 0.4f;
|
||||
hitSize = 13f;
|
||||
rotateSpeed = 3f;
|
||||
@@ -621,7 +621,7 @@ public class UnitTypes implements ContentList{
|
||||
}};
|
||||
|
||||
spiroct = new UnitType("spiroct"){{
|
||||
speed = 0.45f;
|
||||
speed = 0.48f;
|
||||
drag = 0.4f;
|
||||
hitSize = 15f;
|
||||
rotateSpeed = 3f;
|
||||
@@ -2113,7 +2113,7 @@ public class UnitTypes implements ContentList{
|
||||
|
||||
bullet = new ContinuousLaserBulletType(){{
|
||||
maxRange = 90f;
|
||||
damage = 26f;
|
||||
damage = 27f;
|
||||
length = 95f;
|
||||
hitEffect = Fx.hitMeltHeal;
|
||||
drawSize = 200f;
|
||||
@@ -2144,7 +2144,7 @@ public class UnitTypes implements ContentList{
|
||||
x = 70f/4f;
|
||||
y = -26f/4f;
|
||||
|
||||
reload = 70f;
|
||||
reload = 65f;
|
||||
shake = 3f;
|
||||
rotateSpeed = 2f;
|
||||
shadow = 30f;
|
||||
@@ -2161,7 +2161,7 @@ public class UnitTypes implements ContentList{
|
||||
timeIncrease = 3f;
|
||||
timeDuration = 60f * 20f;
|
||||
powerDamageScl = 3f;
|
||||
damage = 50;
|
||||
damage = 60;
|
||||
hitColor = lightColor = Pal.heal;
|
||||
lightRadius = 70f;
|
||||
clipSize = 250f;
|
||||
@@ -2177,7 +2177,7 @@ public class UnitTypes implements ContentList{
|
||||
trailWidth = 6f;
|
||||
trailColor = Pal.heal;
|
||||
trailInterval = 3f;
|
||||
splashDamage = 60f;
|
||||
splashDamage = 70f;
|
||||
splashDamageRadius = rad;
|
||||
hitShake = 4f;
|
||||
trailRotation = true;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class NetServer implements ApplicationListener{
|
||||
if(state.rules.pvp){
|
||||
//find team with minimum amount of players and auto-assign player to that.
|
||||
TeamData re = state.teams.getActive().min(data -> {
|
||||
if((state.rules.waveTeam == data.team && state.rules.waves) || !data.team.active()) return Integer.MAX_VALUE;
|
||||
if((state.rules.waveTeam == data.team && state.rules.waves) || !data.team.active() || data.team == Team.derelict) return Integer.MAX_VALUE;
|
||||
|
||||
int count = 0;
|
||||
for(Player other : players){
|
||||
@@ -472,6 +472,10 @@ public class NetServer implements ApplicationListener{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!player.dead() && player.unit().isCommanding()){
|
||||
player.unit().clearCommand();
|
||||
}
|
||||
|
||||
player.getInfo().lastSyncTime = Time.millis();
|
||||
Call.worldDataBegin(player.con);
|
||||
netServer.sendWorldData(player);
|
||||
|
||||
@@ -11,6 +11,7 @@ import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.async.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
@@ -355,7 +356,7 @@ public class Renderer implements ApplicationListener{
|
||||
int w = world.width() * tilesize, h = world.height() * tilesize;
|
||||
int memory = w * h * 4 / 1024 / 1024;
|
||||
|
||||
if(memory >= (mobile ? 65 : 120)){
|
||||
if(Vars.checkScreenshotMemory && memory >= (mobile ? 65 : 120)){
|
||||
ui.showInfo("@screenshot.invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,10 @@ public abstract class UnlockableContent extends MappableContent{
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean logicVisible(){
|
||||
return !isHidden();
|
||||
}
|
||||
|
||||
/** Makes this piece of content unlocked; if it already unlocked, nothing happens. */
|
||||
public void unlock(){
|
||||
if(!unlocked && !alwaysUnlocked){
|
||||
|
||||
@@ -52,22 +52,22 @@ public class Puddles{
|
||||
Puddle p = map.get(tile.pos());
|
||||
if(p == null){
|
||||
Puddle puddle = Puddle.create();
|
||||
puddle.tile(tile);
|
||||
puddle.liquid(liquid);
|
||||
puddle.amount(amount);
|
||||
puddle.generation(generation);
|
||||
puddle.tile = tile;
|
||||
puddle.liquid = liquid;
|
||||
puddle.amount = amount;
|
||||
puddle.generation = generation;
|
||||
puddle.set((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
|
||||
puddle.add();
|
||||
map.put(tile.pos(), puddle);
|
||||
}else if(p.liquid() == liquid){
|
||||
p.accepting(Math.max(amount, p.accepting()));
|
||||
}else if(p.liquid == liquid){
|
||||
p.accepting = Math.max(amount, p.accepting);
|
||||
|
||||
if(generation == 0 && p.lastRipple <= Time.time - 40f && p.amount() >= maxLiquid / 2f){
|
||||
Fx.ripple.at((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f, 1f, p.liquid().color);
|
||||
if(generation == 0 && p.lastRipple <= Time.time - 40f && p.amount >= maxLiquid / 2f){
|
||||
Fx.ripple.at((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f, 1f, p.liquid.color);
|
||||
p.lastRipple = Time.time;
|
||||
}
|
||||
}else{
|
||||
p.amount(p.amount() + reactPuddle(p.liquid(), liquid, amount, p.tile(), (p.x() + source.worldx())/2f, (p.y() + source.worldy())/2f));
|
||||
p.amount += reactPuddle(p.liquid, liquid, amount, p.tile, (p.x + source.worldx())/2f, (p.y + source.worldy())/2f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -297,7 +297,7 @@ public class BulletType extends Content implements Cloneable{
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the bullet reaches the end of its lifetime of is destroyed by something external. */
|
||||
/** Called when the bullet reaches the end of its lifetime or is destroyed by something external. */
|
||||
public void despawned(Bullet b){
|
||||
if(despawnHit){
|
||||
hit(b);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.entities.comp;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
@@ -24,7 +25,7 @@ abstract class BoundedComp implements Velc, Posc, Healthc, Flyingc{
|
||||
if(x > world.unitWidth()) dx -= (x - world.unitWidth())/warpDst;
|
||||
if(y > world.unitHeight()) dy -= (y - world.unitHeight())/warpDst;
|
||||
|
||||
velAddNet(dx, dy);
|
||||
velAddNet(dx * Time.delta, dy * Time.delta);
|
||||
}
|
||||
|
||||
//clamp position if not flying
|
||||
|
||||
@@ -28,6 +28,7 @@ abstract class FireComp implements Timedc, Posc, Syncc, Drawc{
|
||||
public static final TextureRegion[] regions = new TextureRegion[frames];
|
||||
|
||||
@Import float time, lifetime, x, y;
|
||||
@Import int id;
|
||||
|
||||
Tile tile;
|
||||
private transient Block block;
|
||||
@@ -116,7 +117,7 @@ abstract class FireComp implements Timedc, Posc, Syncc, Drawc{
|
||||
|
||||
Draw.alpha(Mathf.clamp(warmup / warmupDuration));
|
||||
Draw.z(Layer.effect);
|
||||
Draw.rect(regions[Math.min((int)animation, regions.length - 1)], x, y);
|
||||
Draw.rect(regions[Math.min((int)animation, regions.length - 1)], x + Mathf.randomSeedRange((int)y, 2), y + Mathf.randomSeedRange((int)x, 2));
|
||||
Draw.reset();
|
||||
|
||||
Drawf.light(x, y, 50f + Mathf.absin(5f, 5f), Pal.lightFlame, 0.6f * Mathf.clamp(warmup / warmupDuration));
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package mindustry.entities.comp;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.gen.*;
|
||||
@@ -34,7 +33,7 @@ abstract class HealthComp implements Entityc, Posc{
|
||||
void kill(){
|
||||
if(dead) return;
|
||||
|
||||
health = 0;
|
||||
health = Math.min(health, 0);
|
||||
dead = true;
|
||||
killed();
|
||||
remove();
|
||||
@@ -86,7 +85,7 @@ abstract class HealthComp implements Entityc, Posc{
|
||||
}
|
||||
|
||||
void clampHealth(){
|
||||
health = Mathf.clamp(health, 0, maxHealth);
|
||||
health = Math.min(health, maxHealth);
|
||||
}
|
||||
|
||||
/** Heals by a flat amount. */
|
||||
|
||||
@@ -397,7 +397,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
//move down
|
||||
elevation -= type.fallSpeed * Time.delta;
|
||||
|
||||
if(isGrounded()){
|
||||
if(isGrounded() || health <= -maxHealth){
|
||||
Call.unitDestroy(id);
|
||||
}
|
||||
}
|
||||
@@ -528,7 +528,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
@Override
|
||||
public void killed(){
|
||||
wasPlayer = isLocal();
|
||||
health = 0;
|
||||
health = Math.min(health, 0);
|
||||
dead = true;
|
||||
|
||||
//don't waste time when the unit is already on the ground, just destroy it
|
||||
|
||||
@@ -38,7 +38,6 @@ public enum Gamemode{
|
||||
rules.infiniteResources = true;
|
||||
rules.editor = true;
|
||||
rules.waves = false;
|
||||
rules.enemyCoreBuildRadius = 0f;
|
||||
rules.waveTimer = false;
|
||||
});
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ public class BlockRenderer{
|
||||
|
||||
darkEvents.each(pos -> {
|
||||
var tile = world.tile(pos);
|
||||
if(tile == null) return;
|
||||
float darkness = world.getDarkness(tile.x, tile.y);
|
||||
//then draw the shadow
|
||||
Draw.colorl(darkness <= 0f ? 1f : 1f - Math.min((darkness + 0.5f) / 4f, 1f));
|
||||
|
||||
@@ -270,6 +270,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
b.button(Icon.save, style, this::showSchematicSave).disabled(f -> lastSchematic == null || lastSchematic.file != null);
|
||||
b.button(Icon.cancel, style, () -> {
|
||||
selectRequests.clear();
|
||||
lastSchematic = null;
|
||||
});
|
||||
b.row();
|
||||
b.button(Icon.flipX, style, () -> flipRequests(selectRequests, true));
|
||||
|
||||
@@ -70,8 +70,6 @@ public class JsonIO{
|
||||
json.setElementType(Rules.class, "spawns", SpawnGroup.class);
|
||||
json.setElementType(Rules.class, "loadout", ItemStack.class);
|
||||
|
||||
//TODO this is terrible
|
||||
|
||||
json.setSerializer(Sector.class, new Serializer<>(){
|
||||
@Override
|
||||
public void write(Json json, Sector object, Class knownType){
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
package mindustry.logic;
|
||||
|
||||
import arc.*;
|
||||
import arc.files.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.logic.LExecutor.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/** Stores global constants for logic processors. */
|
||||
public class GlobalConstants{
|
||||
public static final int ctrlProcessor = 1, ctrlPlayer = 2, ctrlFormation = 3;
|
||||
public static final ContentType[] lookableContent = {ContentType.block, ContentType.unit, ContentType.item, ContentType.liquid};
|
||||
|
||||
private ObjectIntMap<String> namesToIds = new ObjectIntMap<>();
|
||||
private Seq<Var> vars = new Seq<>(Var.class);
|
||||
private UnlockableContent[][] logicIdToContent;
|
||||
private int[][] contentIdToLogicId;
|
||||
|
||||
public void init(){
|
||||
put("the end", null);
|
||||
@@ -61,6 +69,49 @@ public class GlobalConstants{
|
||||
for(UnitCommand cmd : UnitCommand.all){
|
||||
put("@command" + Strings.capitalize(cmd.name()), cmd);
|
||||
}
|
||||
|
||||
logicIdToContent = new UnlockableContent[ContentType.all.length][];
|
||||
contentIdToLogicId = new int[ContentType.all.length][];
|
||||
|
||||
Fi ids = Core.files.internal("logicids.dat");
|
||||
if(ids.exists()){
|
||||
//read logic ID mapping data (generated in ImagePacker)
|
||||
try(DataInputStream in = new DataInputStream(ids.readByteStream())){
|
||||
for(ContentType ctype : lookableContent){
|
||||
short amount = in.readShort();
|
||||
logicIdToContent[ctype.ordinal()] = new UnlockableContent[amount];
|
||||
contentIdToLogicId[ctype.ordinal()] = new int[Vars.content.getBy(ctype).size];
|
||||
|
||||
//store count constants
|
||||
put("@" + ctype.name() + "Count", amount);
|
||||
|
||||
for(int i = 0; i < amount; i++){
|
||||
String name = in.readUTF();
|
||||
UnlockableContent fetched = Vars.content.getByName(ctype, name);
|
||||
|
||||
if(fetched != null){
|
||||
logicIdToContent[ctype.ordinal()][i] = fetched;
|
||||
contentIdToLogicId[ctype.ordinal()][fetched.id] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(IOException e){
|
||||
//don't crash?
|
||||
Log.err("Error reading logic ID mapping", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @return a piece of content based on its logic ID. This is not equivalent to content ID. */
|
||||
public @Nullable Content lookupContent(ContentType type, int id){
|
||||
var arr = logicIdToContent[type.ordinal()];
|
||||
return arr != null && id >= 0 && id < arr.length ? arr[id] : null;
|
||||
}
|
||||
|
||||
/** @return the integer logic ID of content, or -1 if invalid. */
|
||||
public int lookupLogicId(UnlockableContent content){
|
||||
var arr = contentIdToLogicId[content.getContentType().ordinal()];
|
||||
return arr != null && content.id >= 0 && content.id < arr.length ? arr[content.id] : -1;
|
||||
}
|
||||
|
||||
/** @return a constant ID > 0 if there is a constant with this name, otherwise -1. */
|
||||
|
||||
@@ -537,7 +537,7 @@ public class LExecutor{
|
||||
public void run(LExecutor exec){
|
||||
Object obj = exec.obj(target);
|
||||
if(obj instanceof Building b && b.team == exec.team && exec.linkIds.contains(b.id)){
|
||||
if(type.isObj && exec.var(p1).isobj){ //TODO may break logic?
|
||||
if(type.isObj && exec.var(p1).isobj){
|
||||
b.control(type, exec.obj(p1), exec.num(p2), exec.num(p3), exec.num(p4));
|
||||
}else{
|
||||
b.control(type, exec.num(p1), exec.num(p2), exec.num(p3), exec.num(p4));
|
||||
@@ -764,7 +764,6 @@ public class LExecutor{
|
||||
Var v = exec.var(to);
|
||||
Var f = exec.var(from);
|
||||
|
||||
//TODO error out when the from-value is a constant
|
||||
if(!v.constant){
|
||||
if(f.isobj){
|
||||
v.objval = f.objval;
|
||||
@@ -1024,6 +1023,26 @@ public class LExecutor{
|
||||
}
|
||||
}
|
||||
|
||||
public static class LookupI implements LInstruction{
|
||||
public int dest;
|
||||
public int from;
|
||||
public ContentType type;
|
||||
|
||||
public LookupI(int dest, int from, ContentType type){
|
||||
this.dest = dest;
|
||||
this.from = from;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public LookupI(){
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(LExecutor exec){
|
||||
exec.setobj(dest, constants.lookupContent(type, exec.numi(from)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//endregion
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.logic.LCanvas.*;
|
||||
@@ -662,8 +663,7 @@ public class LStatements{
|
||||
}
|
||||
}
|
||||
|
||||
//TODO untested
|
||||
//@RegisterStatement("wait")
|
||||
@RegisterStatement("wait")
|
||||
public static class WaitStatement extends LStatement{
|
||||
public String value = "0.5";
|
||||
|
||||
@@ -684,6 +684,42 @@ public class LStatements{
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("lookup")
|
||||
public static class LookupStatement extends LStatement{
|
||||
public ContentType type = ContentType.item;
|
||||
public String result = "result", id = "0";
|
||||
|
||||
@Override
|
||||
public void build(Table table){
|
||||
fields(table, result, str -> result = str);
|
||||
|
||||
table.add(" = lookup ");
|
||||
|
||||
row(table);
|
||||
|
||||
table.button(b -> {
|
||||
b.label(() -> type.name());
|
||||
b.clicked(() -> showSelect(b, GlobalConstants.lookableContent, type, o -> {
|
||||
type = o;
|
||||
}));
|
||||
}, Styles.logict, () -> {}).size(64f, 40f).pad(4f).color(table.color);
|
||||
|
||||
table.add(" # ");
|
||||
|
||||
fields(table, id, str -> id = str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color color(){
|
||||
return Pal.logicOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LInstruction build(LAssembler builder){
|
||||
return new LookupI(builder.var(result), builder.var(id), type);
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("end")
|
||||
public static class EndStatement extends LStatement{
|
||||
@Override
|
||||
|
||||
@@ -11,6 +11,10 @@ public class ModClassLoader extends ClassLoader{
|
||||
}
|
||||
};
|
||||
|
||||
public ModClassLoader(ClassLoader parent){
|
||||
super(parent);
|
||||
}
|
||||
|
||||
public void addChild(ClassLoader child){
|
||||
children.add(child);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public class Mods implements Loadable{
|
||||
|
||||
private int totalSprites;
|
||||
private MultiPacker packer;
|
||||
private ModClassLoader mainLoader = new ModClassLoader();
|
||||
private ModClassLoader mainLoader = new ModClassLoader(getClass().getClassLoader());
|
||||
|
||||
Seq<LoadedMod> mods = new Seq<>();
|
||||
private ObjectMap<Class<?>, ModMeta> metas = new ObjectMap<>();
|
||||
|
||||
@@ -61,7 +61,6 @@ public class Administration{
|
||||
});
|
||||
|
||||
//block interaction rate limit
|
||||
//TODO when someone disconnects, a different player is mistakenly kicked for spamming actions
|
||||
addActionFilter(action -> {
|
||||
if(action.type != ActionType.breakBlock &&
|
||||
action.type != ActionType.placeBlock &&
|
||||
|
||||
@@ -391,7 +391,15 @@ public class ArcNetProvider implements NetProvider{
|
||||
//no compression, copy over buffer
|
||||
if(compression == 0){
|
||||
buffer.position(0).limit(length);
|
||||
buffer.put(byteBuffer.array(), byteBuffer.position(), length);
|
||||
if(byteBuffer.hasArray()){
|
||||
buffer.put(byteBuffer.array(), byteBuffer.position(), length);
|
||||
}else{
|
||||
byte[] readcopy = new byte[length];
|
||||
int pos = byteBuffer.position();
|
||||
byteBuffer.get(readcopy);
|
||||
byteBuffer.position(pos);
|
||||
buffer.put(readcopy);
|
||||
}
|
||||
buffer.position(0);
|
||||
packet.read(reads.get(), length);
|
||||
//move read packets forward
|
||||
|
||||
@@ -97,7 +97,7 @@ public class Net{
|
||||
|
||||
if(e instanceof BufferUnderflowException || e instanceof BufferOverflowException){
|
||||
error = Core.bundle.get("error.io");
|
||||
}else if(error.equals("mismatch")){
|
||||
}else if(error.equals("mismatch") || (e instanceof IndexOutOfBoundsException && e.getStackTrace()[0].getClassName().contains("java.nio"))){
|
||||
error = Core.bundle.get("error.mismatch");
|
||||
}else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address")) || Strings.neatError(e).contains("address associated")){
|
||||
error = Core.bundle.get("error.invalidaddress");
|
||||
|
||||
@@ -664,7 +664,7 @@ public class UnitType extends UnlockableContent{
|
||||
if(unit.item() != null && unit.itemTime > 0.01f){
|
||||
float size = (itemSize + Mathf.absin(Time.time, 5f, 1f)) * unit.itemTime;
|
||||
|
||||
Draw.mixcol(Pal.accent, Mathf.absin(Time.time, 5f, 0.5f));
|
||||
Draw.mixcol(Pal.accent, Mathf.absin(Time.time, 5f, 0.1f));
|
||||
Draw.rect(unit.item().fullIcon,
|
||||
unit.x + Angles.trnsx(unit.rotation + 180f, itemOffsetY),
|
||||
unit.y + Angles.trnsy(unit.rotation + 180f, itemOffsetY),
|
||||
|
||||
@@ -33,7 +33,6 @@ public class ParticleWeather extends Weather{
|
||||
region = Core.atlas.find(particleRegion);
|
||||
|
||||
//load noise texture
|
||||
//TODO mod support
|
||||
if(drawNoise && Core.assets != null){
|
||||
Core.assets.load("sprites/" + noisePath + ".png", Texture.class);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import arc.graphics.*;
|
||||
import arc.input.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.TextButton.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
@@ -34,6 +35,7 @@ public class JoinDialog extends BaseDialog{
|
||||
int totalHosts;
|
||||
int refreshes;
|
||||
boolean showHidden;
|
||||
TextButtonStyle style;
|
||||
|
||||
String lastIp;
|
||||
int lastPort;
|
||||
@@ -42,6 +44,15 @@ public class JoinDialog extends BaseDialog{
|
||||
public JoinDialog(){
|
||||
super("@joingame");
|
||||
|
||||
style = new TextButtonStyle(){{
|
||||
over = Styles.flatOver;
|
||||
font = Fonts.def;
|
||||
fontColor = Color.white;
|
||||
disabledFontColor = Color.gray;
|
||||
down = Styles.flatOver;
|
||||
up = Styles.black5;
|
||||
}};
|
||||
|
||||
loadServers();
|
||||
|
||||
if(!steam) buttons.add().width(60f);
|
||||
@@ -119,7 +130,7 @@ public class JoinDialog extends BaseDialog{
|
||||
//why are java lambdas this bad
|
||||
TextButton[] buttons = {null};
|
||||
|
||||
TextButton button = buttons[0] = remote.button("[accent]" + server.displayIP(), Styles.cleart, () -> {
|
||||
TextButton button = buttons[0] = remote.button("[accent]" + server.displayIP(), style, () -> {
|
||||
if(!buttons[0].childrenPressed()){
|
||||
if(server.lastHost != null){
|
||||
Events.fire(new ClientPreConnectEvent(server.lastHost));
|
||||
@@ -405,7 +416,7 @@ public class JoinDialog extends BaseDialog{
|
||||
float w = targetWidth();
|
||||
|
||||
//TODO looks bad
|
||||
container.button(b -> buildServer(host, b), Styles.cleart, () -> {
|
||||
container.button(b -> buildServer(host, b), style, () -> {
|
||||
Events.fire(new ClientPreConnectEvent(host));
|
||||
if(!Core.settings.getBool("server-disclaimer", false)){
|
||||
ui.showCustomConfirm("@warning", "@servers.disclaimer", "@ok", "@back", () -> {
|
||||
@@ -442,7 +453,7 @@ public class JoinDialog extends BaseDialog{
|
||||
|
||||
local.row();
|
||||
|
||||
local.button(b -> buildServer(host, b), Styles.cleart, () -> {
|
||||
local.button(b -> buildServer(host, b), style, () -> {
|
||||
Events.fire(new ClientPreConnectEvent(host));
|
||||
safeConnect(host.address, host.port, host.version);
|
||||
}).width(w);
|
||||
|
||||
@@ -72,7 +72,6 @@ public class KeybindDialog extends Dialog{
|
||||
}
|
||||
|
||||
if(sections.length != 1){
|
||||
//TODO toggle style
|
||||
TextButton button = new TextButton(bundle.get("section." + section.name + ".name", Strings.capitalize(section.name))/*, "toggle"*/);
|
||||
if(section.equals(this.section))
|
||||
button.toggle();
|
||||
|
||||
@@ -324,7 +324,6 @@ public class ModsDialog extends BaseDialog{
|
||||
if(showImport) dialog.buttons.button("@mods.browser.reinstall", Icon.download, () -> githubImportMod(mod.getRepo(), mod.isJava()));
|
||||
}
|
||||
|
||||
//TODO improve this menu later
|
||||
dialog.cont.pane(desc -> {
|
||||
desc.center();
|
||||
desc.defaults().padTop(10).left();
|
||||
|
||||
@@ -241,7 +241,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
dialog.add("@sectors.captured");
|
||||
}
|
||||
|
||||
//TODO
|
||||
//TODO unimplemented, cutscene needed
|
||||
public void showPlanetLaunch(Sector sector, Cons<Sector> listener){
|
||||
selected = null;
|
||||
hovered = null;
|
||||
|
||||
@@ -423,12 +423,17 @@ public class SettingsMenuDialog extends Dialog{
|
||||
}
|
||||
});
|
||||
|
||||
graphics.checkPref("linear", !mobile, b -> {
|
||||
for(Texture tex : Core.atlas.getTextures()){
|
||||
TextureFilter filter = b ? TextureFilter.linear : TextureFilter.nearest;
|
||||
tex.setFilter(filter, filter);
|
||||
}
|
||||
});
|
||||
//iOS (and possibly Android) devices do not support linear filtering well, so disable it
|
||||
if(!ios){
|
||||
graphics.checkPref("linear", !mobile, b -> {
|
||||
for(Texture tex : Core.atlas.getTextures()){
|
||||
TextureFilter filter = b ? TextureFilter.linear : TextureFilter.nearest;
|
||||
tex.setFilter(filter, filter);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
settings.put("linear", false);
|
||||
}
|
||||
|
||||
if(Core.settings.getBool("linear")){
|
||||
for(Texture tex : Core.atlas.getTextures()){
|
||||
|
||||
@@ -267,6 +267,7 @@ public class HudFragment extends Fragment{
|
||||
//core info
|
||||
parent.fill(t -> {
|
||||
t.top();
|
||||
t.visible(() -> shown);
|
||||
|
||||
t.name = "coreinfo";
|
||||
|
||||
|
||||
@@ -774,6 +774,11 @@ public class Block extends UnlockableContent{
|
||||
return ContentType.block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean logicVisible(){
|
||||
return buildVisibility != BuildVisibility.hidden;
|
||||
}
|
||||
|
||||
/** Called after all blocks are created. */
|
||||
@Override
|
||||
@CallSuper
|
||||
@@ -838,7 +843,7 @@ public class Block extends UnlockableContent{
|
||||
//load specific team regions
|
||||
teamRegions = new TextureRegion[Team.all.length];
|
||||
for(Team team : Team.all){
|
||||
teamRegions[team.id] = teamRegion.found() ? Core.atlas.find(name + "-team-" + team.name, teamRegion) : teamRegion;
|
||||
teamRegions[team.id] = teamRegion.found() && team.hasPalette ? Core.atlas.find(name + "-team-" + team.name, teamRegion) : teamRegion;
|
||||
}
|
||||
|
||||
if(variants != 0){
|
||||
|
||||
@@ -134,24 +134,26 @@ public class Build{
|
||||
return false;
|
||||
}
|
||||
|
||||
//find closest core, if it doesn't match the team, placing is not legal
|
||||
if(state.rules.polygonCoreProtection){
|
||||
float mindst = Float.MAX_VALUE;
|
||||
CoreBuild closest = null;
|
||||
for(TeamData data : state.teams.active){
|
||||
for(CoreBuild tile : data.cores){
|
||||
float dst = tile.dst2(x * tilesize + type.offset, y * tilesize + type.offset);
|
||||
if(dst < mindst){
|
||||
closest = tile;
|
||||
mindst = dst;
|
||||
if(!state.rules.editor){
|
||||
//find closest core, if it doesn't match the team, placing is not legal
|
||||
if(state.rules.polygonCoreProtection){
|
||||
float mindst = Float.MAX_VALUE;
|
||||
CoreBuild closest = null;
|
||||
for(TeamData data : state.teams.active){
|
||||
for(CoreBuild tile : data.cores){
|
||||
float dst = tile.dst2(x * tilesize + type.offset, y * tilesize + type.offset);
|
||||
if(dst < mindst){
|
||||
closest = tile;
|
||||
mindst = dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(closest != null && closest.team != team){
|
||||
if(closest != null && closest.team != team){
|
||||
return false;
|
||||
}
|
||||
}else 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;
|
||||
}
|
||||
}else 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;
|
||||
}
|
||||
|
||||
Tile tile = world.tile(x, y);
|
||||
|
||||
@@ -109,10 +109,15 @@ public class Accelerator extends Block{
|
||||
|
||||
if(!state.isCampaign() || !consValid()) return;
|
||||
|
||||
ui.planet.showPlanetLaunch(state.rules.sector, sector -> {
|
||||
//TODO cutscene, etc...
|
||||
consume();
|
||||
});
|
||||
//TODO implement
|
||||
if(true){
|
||||
ui.showInfo("@indev.campaign");
|
||||
}else{
|
||||
ui.planet.showPlanetLaunch(state.rules.sector, sector -> {
|
||||
//TODO cutscene, etc...
|
||||
consume();
|
||||
});
|
||||
}
|
||||
Events.fire(Trigger.acceleratorUse);
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ public class LaunchPad extends Block{
|
||||
public void display(Table table){
|
||||
super.display(table);
|
||||
|
||||
if(!state.isCampaign()) return;
|
||||
if(!state.isCampaign() || net.client()) return;
|
||||
|
||||
table.row();
|
||||
table.label(() -> {
|
||||
|
||||
@@ -3,8 +3,10 @@ package mindustry.world.blocks.defense;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
@@ -18,6 +20,9 @@ public class ShockMine extends Block{
|
||||
public int length = 10;
|
||||
public int tendrils = 6;
|
||||
public Color lightningColor = Pal.lancerLaser;
|
||||
public int shots = 6;
|
||||
public float inaccuracy = 0f;
|
||||
public @Nullable BulletType bullet;
|
||||
public float teamAlpha = 0.3f;
|
||||
public @Load("@-team-top") TextureRegion teamRegion;
|
||||
|
||||
@@ -46,17 +51,26 @@ public class ShockMine extends Block{
|
||||
|
||||
@Override
|
||||
public void drawCracks(){
|
||||
|
||||
//no
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitOn(Unit unit){
|
||||
if(enabled && unit.team != team && timer(timerDamage, cooldown)){
|
||||
for(int i = 0; i < tendrils; i++){
|
||||
Lightning.create(team, lightningColor, damage, x, y, Mathf.random(360f), length);
|
||||
}
|
||||
triggered();
|
||||
damage(tileDamage);
|
||||
}
|
||||
}
|
||||
|
||||
public void triggered(){
|
||||
for(int i = 0; i < tendrils; i++){
|
||||
Lightning.create(team, lightningColor, damage, x, y, Mathf.random(360f), length);
|
||||
}
|
||||
if(bullet != null){
|
||||
for(int i = 0; i < shots; i++){
|
||||
bullet.create(this, x, y, (360f / shots) * i + Mathf.random(inaccuracy));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +136,7 @@ public class ItemTurret extends Turret{
|
||||
}
|
||||
|
||||
BulletType type = ammoTypes.get(item);
|
||||
if(type == null) return;
|
||||
totalAmmo += type.ammoMultiplier;
|
||||
|
||||
//find ammo entry by type
|
||||
|
||||
@@ -100,17 +100,27 @@ public class LiquidTurret extends Turret{
|
||||
@Override
|
||||
protected void findTarget(){
|
||||
if(extinguish && liquids.current().canExtinguish()){
|
||||
Fire result = null;
|
||||
float mindst = 0f;
|
||||
int tr = (int)(range / tilesize);
|
||||
for(int x = -tr; x <= tr; x++){
|
||||
for(int y = -tr; y <= tr; y++){
|
||||
Tile other = world.tileWorld(x + tile.x, y + tile.y);
|
||||
Tile other = world.tile(x + tile.x, y + tile.y);
|
||||
var fire = Fires.get(x + tile.x, y + tile.y);
|
||||
float dst = fire == null ? 0 : dst2(fire);
|
||||
//do not extinguish fires on other team blocks
|
||||
if(other != null && Fires.has(x + tile.x, y + tile.y) && (other.build == null || other.team() == team)){
|
||||
target = Fires.get(x + tile.x, y + tile.y);
|
||||
return;
|
||||
if(other != null && fire != null && Fires.has(other.x, other.y) && dst <= range * range && (result == null || dst < mindst) && (other.build == null || other.team() == team)){
|
||||
result = fire;
|
||||
mindst = dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(result != null){
|
||||
target = result;
|
||||
//don't run standard targeting
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
super.findTarget();
|
||||
|
||||
@@ -43,6 +43,10 @@ public class PayloadRouter extends PayloadConveyor{
|
||||
do{
|
||||
rotation = (rotation + 1) % 4;
|
||||
onProximityUpdate();
|
||||
//force update to transfer if necessary
|
||||
if(next instanceof PayloadConveyorBuild && !(next instanceof PayloadRouterBuild)){
|
||||
next.updateTile();
|
||||
}
|
||||
//this condition intentionally uses "accept from itself" conditions, because payload conveyors only accept during the start
|
||||
//"accept from self" conditions are for dropped payloads and are less restrictive
|
||||
}while((blocked || next == null || !next.acceptPayload(next, item)) && ++rotations < 4);
|
||||
|
||||
@@ -12,6 +12,7 @@ import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.storage.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@@ -69,7 +70,7 @@ public class PayloadSource extends PayloadBlock{
|
||||
}
|
||||
|
||||
public boolean canProduce(Block b){
|
||||
return b.isVisible() && b.size < size;
|
||||
return b.isVisible() && b.size < size && !(b instanceof CoreBlock);
|
||||
}
|
||||
|
||||
public boolean canProduce(UnitType t){
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.world.blocks.production;
|
||||
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
@@ -67,6 +68,8 @@ public class Fracker extends SolidPump{
|
||||
super.updateTile();
|
||||
accumulator += delta() * efficiency();
|
||||
}else{
|
||||
warmup = Mathf.lerpDelta(warmup, 0f, 0.02f);
|
||||
lastPump = 0f;
|
||||
dumpLiquid(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import arc.util.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.production.GenericCrafter.*;
|
||||
|
||||
//TODO
|
||||
public class DrawArcSmelter extends DrawBlock{
|
||||
public TextureRegion top, bottom;
|
||||
public Color flameColor = Color.valueOf("f58349"), midColor = Color.valueOf("f2d585");
|
||||
|
||||
@@ -38,6 +38,6 @@ public class DrawWeave extends DrawBlock{
|
||||
|
||||
@Override
|
||||
public TextureRegion[] icons(Block block){
|
||||
return new TextureRegion[]{bottom, block.region, weave};
|
||||
return new TextureRegion[]{bottom, weave, block.region};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user