Merge branch 'master' into files

This commit is contained in:
DeltaNedas
2020-11-13 07:10:39 +00:00
committed by GitHub
220 changed files with 1104 additions and 931 deletions

View File

@@ -10,11 +10,10 @@ import arc.util.*;
import arc.util.Log.*;
import mindustry.ai.*;
import mindustry.async.*;
import mindustry.audio.*;
import mindustry.core.*;
import mindustry.entities.*;
import mindustry.game.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.input.*;
import mindustry.io.*;
@@ -188,7 +187,6 @@ public class Vars implements Loadable{
public static GameState state;
public static EntityCollisions collisions;
public static Waves waves;
public static LoopControl loops;
public static Platform platform = new Platform(){};
public static Mods mods;
public static Schematics schematics;
@@ -255,7 +253,6 @@ public class Vars implements Loadable{
if(mods == null) mods = new Mods();
content = new ContentLoader();
loops = new LoopControl();
waves = new Waves();
collisions = new EntityCollisions();
world = new World();

View File

@@ -1,61 +0,0 @@
package mindustry.audio;
import arc.*;
import arc.audio.*;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import mindustry.*;
public class LoopControl{
private ObjectMap<Sound, SoundData> sounds = new ObjectMap<>();
public void play(Sound sound, Position pos, float volume){
if(Vars.headless) return;
float baseVol = sound.calcFalloff(pos.getX(), pos.getY());
float vol = baseVol * volume;
SoundData data = sounds.get(sound, SoundData::new);
data.volume += vol;
data.volume = Mathf.clamp(data.volume, 0f, 1f);
data.total += baseVol;
data.sum.add(pos.getX() * baseVol, pos.getY() * baseVol);
}
public void update(){
float avol = Core.settings.getInt("ambientvol", 100) / 100f;
sounds.each((sound, data) -> {
data.curVolume = Mathf.lerpDelta(data.curVolume, data.volume * avol, 0.2f);
boolean play = data.curVolume > 0.01f;
float pan = Mathf.zero(data.total, 0.0001f) ? 0f : sound.calcPan(data.sum.x / data.total, data.sum.y / data.total);
if(data.soundID <= 0 || !sound.isPlaying(data.soundID)){
if(play){
data.soundID = sound.loop(data.curVolume, 1f, pan);
}
}else{
if(data.curVolume <= 0.001f){
sound.stop();
data.soundID = -1;
return;
}
sound.set(data.soundID, pan, data.curVolume);
}
data.volume = 0f;
data.total = 0f;
data.sum.setZero();
});
}
private static class SoundData{
float volume;
float total;
Vec2 sum = new Vec2();
int soundID;
float curVolume;
}
}

View File

@@ -2,18 +2,21 @@ package mindustry.audio;
import arc.*;
import arc.audio.*;
import arc.audio.SoloudAudio.*;
import arc.audio.Filters.*;
import arc.files.*;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.content.*;
import mindustry.game.EventType.*;
import mindustry.gen.*;
import static mindustry.Vars.*;
/** Controls playback of multiple music tracks.*/
public class MusicControl{
/** Controls playback of multiple audio tracks.*/
public class SoundControl{
protected static final float finTime = 120f, foutTime = 120f, musicInterval = 60 * 60 * 3f, musicChance = 0.6f, musicWaveChance = 0.46f;
/** normal, ambient music, plays at any time */
@@ -29,12 +32,15 @@ public class MusicControl{
protected float fade;
protected boolean silenced;
protected boolean wasPaused;
protected AudioBus uiBus = new AudioBus();
protected boolean wasPaused, wasPlaying;
protected AudioFilter filter = new BiquadFilter(){{
set(0, 500, 1);
}};
public MusicControl(){
protected ObjectMap<Sound, SoundData> sounds = new ObjectMap<>();
public SoundControl(){
Events.on(ClientLoadEvent.class, e -> reload());
//only run music 10 seconds after a wave spawns
@@ -47,6 +53,13 @@ public class MusicControl{
playRandom();
}
}));
setupFilters();
}
protected void setupFilters(){
Core.audio.soundBus.setFilter(0, filter);
Core.audio.soundBus.setFilterParam(0, Filters.paramWet, 0f);
}
protected void reload(){
@@ -55,6 +68,33 @@ public class MusicControl{
ambientMusic = Seq.with(Musics.game1, Musics.game3, Musics.game6, Musics.game8, Musics.game9);
darkMusic = Seq.with(Musics.game2, Musics.game5, Musics.game7, Musics.game4);
bossMusic = Seq.with(Musics.boss1, Musics.boss2, Musics.game2, Musics.game5);
//setup UI bus for all sounds that are in the UI folder
for(var sound : Core.assets.getAll(Sound.class, new Seq<>())){
var file = Fi.get(Core.assets.getAssetFileName(sound));
if(file.parent().name().equals("ui")){
sound.setBus(uiBus);
}
}
}
public void loop(Sound sound, float volume){
if(Vars.headless) return;
loop(sound, Core.camera.position, volume);
}
public void loop(Sound sound, Position pos, float volume){
if(Vars.headless) return;
float baseVol = sound.calcFalloff(pos.getX(), pos.getY());
float vol = baseVol * volume;
SoundData data = sounds.get(sound, SoundData::new);
data.volume += vol;
data.volume = Mathf.clamp(data.volume, 0f, 1f);
data.total += baseVol;
data.sum.add(pos.getX() * baseVol, pos.getY() * baseVol);
}
public void stop(){
@@ -69,10 +109,30 @@ public class MusicControl{
/** Update and play the right music track.*/
public void update(){
boolean paused = state.isGame() && Core.scene.hasDialog();
boolean playing = state.isGame();
//check if current track is finished
if(current != null && !current.isPlaying()){
current = null;
fade = 0f;
}
//fade the lowpass filter in/out
if(paused != wasPaused){
Core.audio.setFilter(0, paused ? filter : null);
wasPaused = paused;
Core.audio.soundBus.fadeFilterParam(0, Filters.paramWet, paused ? 1f : 0f, 0.4f);
}
//play/stop ordinary effects
if(playing != wasPlaying){
wasPlaying = playing;
if(playing){
Core.audio.soundBus.play();
setupFilters();
}else{
Core.audio.soundBus.stop();
}
}
if(state.isMenu()){
@@ -99,10 +159,46 @@ public class MusicControl{
}
}
}
updateLoops();
}
protected void updateLoops(){
//clear loops when in menu
if(!state.isGame()){
sounds.clear();
return;
}
float avol = Core.settings.getInt("ambientvol", 100) / 100f;
sounds.each((sound, data) -> {
data.curVolume = Mathf.lerpDelta(data.curVolume, data.volume * avol, 0.2f);
boolean play = data.curVolume > 0.01f;
float pan = Mathf.zero(data.total, 0.0001f) ? 0f : sound.calcPan(data.sum.x / data.total, data.sum.y / data.total);
if(data.soundID <= 0 || !Core.audio.isPlaying(data.soundID)){
if(play){
data.soundID = sound.loop(data.curVolume, 1f, pan);
Core.audio.protect(data.soundID, true);
}
}else{
if(data.curVolume <= 0.001f){
sound.stop();
data.soundID = -1;
return;
}
Core.audio.set(data.soundID, pan, data.curVolume);
}
data.volume = 0f;
data.total = 0f;
data.sum.setZero();
});
}
/** Plays a random track.*/
protected void playRandom(){
public void playRandom(){
if(isDark()){
playOnce(darkMusic.random(lastRandomPlayed));
}else{
@@ -191,12 +287,6 @@ public class MusicControl{
current = music;
current.setVolume(1f);
current.setLooping(false);
current.setCompletionListener(m -> {
if(current == m){
current = null;
fade = 0f;
}
});
current.play();
}
@@ -208,4 +298,13 @@ public class MusicControl{
protected void silence(){
play(null);
}
protected static class SoundData{
float volume;
float total;
Vec2 sum = new Vec2();
int soundID;
float curVolume;
}
}

View File

@@ -1,5 +1,6 @@
package mindustry.audio;
import arc.*;
import arc.audio.*;
import arc.math.*;
import arc.util.*;
@@ -31,19 +32,19 @@ public class SoundLoop{
}else{
volume = Mathf.clamp(volume - fadeSpeed * Time.delta);
if(volume <= 0.001f){
sound.stop(id);
Core.audio.stop(id);
id = -1;
return;
}
}
sound.set(id, sound.calcPan(x, y), sound.calcVolume(x, y) * volume * baseVolume);
Core.audio.set(id, sound.calcPan(x, y), sound.calcVolume(x, y) * volume * baseVolume);
}
}
public void stop(){
if(id != -1){
sound.stop(id);
Core.audio.stop(id);
id = -1;
volume = baseVolume = -1;
}

View File

@@ -728,7 +728,7 @@ public class Blocks implements ContentList{
hasItems = hasPower = true;
drawer = new DrawRotator();
ambientSound = Sounds.grinding;
ambientSoundVolume = 0.02f;
ambientSoundVolume = 0.025f;
consumes.item(Items.scrap, 1);
consumes.power(0.50f);
@@ -1229,7 +1229,7 @@ public class Blocks implements ContentList{
thoriumReactor = new NuclearReactor("thorium-reactor"){{
requirements(Category.power, with(Items.lead, 300, Items.silicon, 200, Items.graphite, 150, Items.thorium, 150, Items.metaglass, 50));
ambientSound = Sounds.hum;
ambientSoundVolume = 0.2f;
ambientSoundVolume = 0.24f;
size = 3;
health = 700;
itemDuration = 360f;
@@ -1246,7 +1246,7 @@ public class Blocks implements ContentList{
powerProduction = 130f;
itemDuration = 140f;
ambientSound = Sounds.pulse;
ambientSoundVolume = 0.2f;
ambientSoundVolume = 0.07f;
consumes.power(25f);
consumes.item(Items.blastCompound);

View File

@@ -10,7 +10,7 @@ public class SectorPresets implements ContentList{
groundZero,
craters, frozenForest, ruinousShores, stainedMountains, tarFields, fungalPass,
saltFlats, overgrowth,
desolateRift, nuclearComplex;
impact0078, desolateRift, nuclearComplex;
@Override
public void load(){
@@ -55,17 +55,22 @@ public class SectorPresets implements ContentList{
}};
tarFields = new SectorPreset("tarFields", serpulo, 23){{
captureWave = 50;
captureWave = 40;
difficulty = 5;
}};
impact0078 = new SectorPreset("impact0078", serpulo, 227){{
captureWave = 45;
difficulty = 7;
}};
desolateRift = new SectorPreset("desolateRift", serpulo, 123){{
captureWave = 40;
captureWave = 30;
difficulty = 8;
}};
nuclearComplex = new SectorPreset("nuclearComplex", serpulo, 130){{
captureWave = 60;
captureWave = 50;
difficulty = 7;
}};
}

View File

@@ -151,7 +151,7 @@ public class StatusEffects implements ContentList{
boss = new StatusEffect("boss"){{
color = Pal.health;
permanent = true;
damageMultiplier = 1.5f;
damageMultiplier = 1.3f;
healthMultiplier = 1.5f;
}};

View File

@@ -479,19 +479,25 @@ public class TechTree implements ContentList{
new Research(kiln),
new Research(mechanicalPump)
), () -> {
node(tarFields, Seq.with(
new SectorComplete(ruinousShores),
new Research(coalCentrifuge),
new Research(conduit),
new Research(wave)
), () -> {
node(desolateRift, Seq.with(
//TODO change positions?
node(impact0078, Seq.with(
new SectorComplete(tarFields),
new Research(thermalGenerator),
new Research(thoriumReactor)
new Research(Items.thorium),
new Research(overdriveProjector)
), () -> {
node(desolateRift, Seq.with(
new SectorComplete(impact0078),
new Research(thermalGenerator),
new Research(thoriumReactor)
), () -> {
});
});
});

View File

@@ -295,7 +295,6 @@ public class UnitTypes implements ContentList{
backColor = Pal.heal;
frontColor = Color.white;
}};
shootSound = Sounds.pew;
}});
}};
@@ -1307,6 +1306,9 @@ public class UnitTypes implements ContentList{
reload = 55f;
minShootVelocity = 0.01f;
soundPitchMin = 1f;
shootSound = Sounds.plasmadrop;
bullet = new BasicBulletType(){{
sprite = "large-bomb";
width = height = 120/4f;
@@ -1318,9 +1320,10 @@ public class UnitTypes implements ContentList{
frontColor = Color.white;
mixColorTo = Color.white;
hitSound = Sounds.plasmaboom;
shootCone = 180f;
ejectEffect = Fx.none;
shootSound = Sounds.none;
despawnShake = 4f;
collidesAir = false;

View File

@@ -12,7 +12,6 @@ import arc.util.*;
import mindustry.audio.*;
import mindustry.content.*;
import mindustry.core.GameState.*;
import mindustry.ctype.*;
import mindustry.entities.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
@@ -42,7 +41,7 @@ import static mindustry.Vars.*;
*/
public class Control implements ApplicationListener, Loadable{
public Saves saves;
public MusicControl music;
public SoundControl sound;
public Tutorial tutorial;
public InputHandler input;
@@ -53,14 +52,11 @@ public class Control implements ApplicationListener, Loadable{
public Control(){
saves = new Saves();
tutorial = new Tutorial();
music = new MusicControl();
sound = new SoundControl();
Events.on(StateChangeEvent.class, event -> {
if((event.from == State.playing && event.to == State.menu) || (event.from == State.menu && event.to != State.menu)){
Time.runTask(5f, platform::updateRPC);
for(Sound sound : assets.getAll(Sound.class, new Seq<>())){
sound.stop();
}
}
});
@@ -406,6 +402,10 @@ public class Control implements ApplicationListener, Loadable{
}
}
for(Music music : assets.getAll(Music.class, new Seq<>())){
music.stop();
}
content.dispose();
net.dispose();
Musics.dispose();
@@ -494,8 +494,7 @@ public class Control implements ApplicationListener, Loadable{
input.updateState();
music.update();
loops.update();
sound.update();
if(Core.input.keyTap(Binding.fullscreen)){
boolean full = settings.getBool("fullscreen");

View File

@@ -365,6 +365,7 @@ public class NetClient implements ApplicationListener{
@Remote(variants = Variant.one)
public static void setPosition(float x, float y){
player.unit().set(x, y);
player.set(x, y);
}

View File

@@ -8,7 +8,7 @@ import arc.util.*;
import mindustry.ui.dialogs.*;
public class MapResizeDialog extends BaseDialog{
private static final int minSize = 50, maxSize = 500, increment = 50;
public static int minSize = 50, maxSize = 500, increment = 50;
int width, height;
public MapResizeDialog(MapEditor editor, Intc2 cons){

View File

@@ -1368,12 +1368,14 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
}
if(sound != null){
sound.update(x, y, shouldActiveSound());
}
if(!headless){
if(sound != null){
sound.update(x, y, shouldActiveSound());
}
if(block.ambientSound != Sounds.none && shouldAmbientSound()){
loops.play(block.ambientSound, self(), block.ambientSoundVolume * ambientVolume());
if(block.ambientSound != Sounds.none && shouldAmbientSound()){
control.sound.loop(block.ambientSound, self(), block.ambientSoundVolume * ambientVolume());
}
}
if(enabled || !block.noUpdateDisabled){

View File

@@ -34,8 +34,8 @@ abstract class FireComp implements Timedc, Posc, Firec, Syncc{
Fx.fireSmoke.at(x + Mathf.range(4f), y + Mathf.range(4f));
}
if(Mathf.chance(0.001 * Time.delta)){
Sounds.fire.at(this);
if(!headless){
control.sound.loop(Sounds.fire, this, 0.07f);
}
time = Mathf.clamp(time + Time.delta, 0, lifetime());

View File

@@ -89,7 +89,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{
}
if(!headless){
loops.play(type.mineSound, this, type.mineSoundVolume);
control.sound.loop(type.mineSound, this, type.mineSoundVolume);
}
}
}

View File

@@ -69,8 +69,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
}
public float speed(){
float strafePenalty = isGrounded() || !isPlayer() ? 1f : Mathf.lerp(1f, type.strafePenalty, Angles.angleDist(vel().angle(), rotation) / 180f);
//limit speed to minimum formation speed to preserve formation
return isCommanding() ? minFormationSpeed * 0.98f : type.speed;
return (isCommanding() ? minFormationSpeed * 0.98f : type.speed) * strafePenalty;
}
/** @return speed with boost multipliers factored in. */

View File

@@ -334,6 +334,9 @@ public class Saves{
}
public void delete(){
if(SaveIO.backupFileFor(file).exists()){
SaveIO.backupFileFor(file).delete();
}
file.delete();
saves.remove(this, true);
if(this == current){

View File

@@ -133,6 +133,7 @@ public class Schematics implements Loadable{
try{
write(newSchematic, target.file);
}catch(Exception e){
Log.err("Failed to overwrite schematic '@' (@)", newSchematic.name(), target.file);
Log.err(e);
ui.showException(e);
}
@@ -153,6 +154,7 @@ public class Schematics implements Loadable{
return s;
}catch(Throwable e){
Log.err("Failed to read schematic from file '@'", file);
Log.err(e);
}
return null;
@@ -188,6 +190,7 @@ public class Schematics implements Loadable{
try{
return getBuffer(schematic).getTexture();
}catch(Throwable t){
Log.err("Failed to get preview for schematic '@' (@)", schematic.name(), schematic.file);
Log.err(t);
errored.add(schematic);
return errorTexture;

View File

@@ -150,8 +150,11 @@ public class Universe{
//increment seconds passed for this sector by the time that just passed with this turn
if(!sector.isBeingPlayed()){
//increment time
sector.info.secondsPassed += turnDuration/60f;
//increment time if attacked
if(sector.isAttacked()){
sector.info.secondsPassed += turnDuration/60f;
}
int wavesPassed = (int)(sector.info.secondsPassed*60f / sector.info.waveSpacing);
boolean attacked = sector.info.waves;
@@ -206,7 +209,7 @@ public class Universe{
if(!sector.isAttacked() && turn > invasionGracePeriod){
//invasion chance depends on # of nearby bases
if(Mathf.chance(baseInvasionChance * sector.near().count(Sector::hasEnemyBase))){
int waveMax = Math.max(sector.info.winWave, state.wave) + Mathf.random(2, 5) * 5;
int waveMax = Math.max(sector.info.winWave, sector.isBeingPlayed() ? state.wave : sector.info.wave + sector.info.wavesPassed) + Mathf.random(2, 5) * 5;
//assign invasion-related things
if(sector.isBeingPlayed()){

View File

@@ -316,7 +316,7 @@ public class Waves{
}});
i += next + 1;
if(curTier < 3 || rand.chance(0.05)){
if(curTier < 3 || (rand.chance(0.05) && difficulty > 0.8)){
curTier ++;
}

View File

@@ -51,7 +51,7 @@ public class Drawf{
}
private static boolean allowLight(Team team){
return team == Team.derelict || team == Vars.player.team() || state.rules.enemyLights;
return renderer != null && (team == Team.derelict || team == Vars.player.team() || state.rules.enemyLights);
}
public static void selected(Building tile, Color color){

View File

@@ -98,5 +98,11 @@ public class Pal{
plasticSmoke = Color.valueOf("f1e479"),
adminChat = Color.valueOf("ff4000");
adminChat = Color.valueOf("ff4000"),
logicBlocks = Color.valueOf("d4816b"),
logicControl = Color.valueOf("6bb2b2"),
logicOperations = Color.valueOf("877bad"),
logicIo = Color.valueOf("a08a8a"),
logicUnits = Color.valueOf("c7b59d");
}

View File

@@ -99,7 +99,7 @@ public class PlanetRenderer implements Disposable{
Gl.enable(Gl.blend);
irenderer.renderProjections();
irenderer.renderProjections(planet);
Gl.disable(Gl.cullFace);
Gl.disable(Gl.depthTest);
@@ -177,17 +177,23 @@ public class PlanetRenderer implements Disposable{
}
public void drawArc(Planet planet, Vec3 a, Vec3 b){
drawArc(planet, a, b, Pal.accent, Color.clear, 1f);
}
public void drawArc(Planet planet, Vec3 a, Vec3 b, Color from, Color to, float length){
drawArc(planet, a, b, from, to, length, 80f, 25);
}
public void drawArc(Planet planet, Vec3 a, Vec3 b, Color from, Color to, float length, float timeScale, int pointCount){
Vec3 avg = Tmp.v31.set(b).add(a).scl(0.5f);
avg.setLength(planet.radius*2f);
avg.setLength(planet.radius*(1f+length));
points.clear();
points.addAll(Tmp.v33.set(b).setLength(outlineRad), Tmp.v31, Tmp.v34.set(a).setLength(outlineRad));
Tmp.bz3.set(points);
float points = 25;
for(int i = 0; i < points + 1; i++){
float f = i / points;
Tmp.c1.set(Pal.accent).lerp(Color.clear, (f+Time.globalTime()/80f)%1f);
for(int i = 0; i < pointCount + 1; i++){
float f = i / (float)pointCount;
Tmp.c1.set(from).lerp(to, (f+Time.globalTime()/timeScale)%1f);
batch.color(Tmp.c1);
batch.vertex(Tmp.bz3.valueAt(Tmp.v32, f));
@@ -312,6 +318,6 @@ public class PlanetRenderer implements Disposable{
public interface PlanetInterfaceRenderer{
void renderSectors(Planet planet);
void renderProjections();
void renderProjections(Planet planet);
}
}

View File

@@ -183,7 +183,7 @@ public class DesktopInput extends InputHandler{
boolean panCam = false;
float camSpeed = (!Core.input.keyDown(Binding.boost) ? panSpeed : panBoostSpeed) * Time.delta;
if(input.keyDown(Binding.pan)){
if(input.keyDown(Binding.pan) && !scene.hasField() && !scene.hasDialog()){
panCam = true;
panning = true;
}
@@ -193,7 +193,7 @@ public class DesktopInput extends InputHandler{
}
//TODO awful UI state checking code
if(((player.dead() || state.isPaused()) && !ui.chatfrag.shown()) && (!scene.hasField() && !scene.hasDialog())){
if(((player.dead() || state.isPaused()) && !ui.chatfrag.shown()) && !scene.hasField() && !scene.hasDialog()){
if(input.keyDown(Binding.mouse_move)){
panCam = true;
}
@@ -602,9 +602,7 @@ public class DesktopInput extends InputHandler{
boolean omni = unit.type.omniMovement;
boolean ground = unit.isGrounded();
float strafePenalty = ground ? 1f : Mathf.lerp(1f, unit.type.strafePenalty, Angles.angleDist(unit.vel().angle(), unit.rotation()) / 180f);
float speed = unit.realSpeed() * strafePenalty;
float speed = unit.realSpeed();
float xa = Core.input.axis(Binding.move_x);
float ya = Core.input.axis(Binding.move_y);
boolean boosted = (unit instanceof Mechc && unit.isFlying());

View File

@@ -854,9 +854,8 @@ public class MobileInput extends InputHandler implements GestureListener{
targetPos.set(Core.camera.position);
float attractDst = 15f;
float strafePenalty = legs ? 1f : Mathf.lerp(1f, type.strafePenalty, Angles.angleDist(unit.vel.angle(), unit.rotation) / 180f);
float speed = unit.realSpeed() * strafePenalty;
float speed = unit.realSpeed();
float range = unit.hasWeapons() ? unit.range() : 0f;
float bulletSpeed = unit.hasWeapons() ? type.weapons.first().bullet.speed : 0f;
float mouseAngle = unit.angleTo(unit.aimX(), unit.aimY());

View File

@@ -100,7 +100,7 @@ public class LAssembler{
int index = 0;
for(String line : lines){
//comments
if(line.startsWith("#")) continue;
if(line.startsWith("#") || line.isEmpty()) continue;
//remove trailing semicolons in case someone adds them in for no reason
if(line.endsWith(";")) line = line.substring(0, line.length() - 1);

View File

@@ -268,7 +268,7 @@ public class LCanvas extends Table{
st.elem = this;
background(Tex.whitePane);
setColor(st.category().color);
setColor(st.color());
margin(0f);
touchable = Touchable.enabled;

View File

@@ -1,17 +0,0 @@
package mindustry.logic;
import arc.graphics.*;
public enum LCategory{
blocks(Color.valueOf("d4816b")),
control(Color.valueOf("6bb2b2")),
operations(Color.valueOf("877bad")),
io(Color.valueOf("a08a8a")),
units(Color.valueOf("c7b59d"));
public final Color color;
LCategory(Color color){
this.color = color;
}
}

View File

@@ -199,11 +199,14 @@ public class LExecutor{
//bind to the next unit
exec.setconst(varUnit, seq.get(index));
}
index ++;
index++;
}else{
//no units of this type found
exec.setconst(varUnit, null);
}
}else if(exec.obj(type) instanceof Unit u && u.team == exec.team){
//bind to specific unit object
exec.setconst(varUnit, u);
}else{
exec.setconst(varUnit, null);
}

View File

@@ -2,6 +2,7 @@ package mindustry.logic;
import arc.*;
import arc.func.*;
import arc.graphics.*;
import arc.math.*;
import arc.scene.*;
import arc.scene.actions.*;
@@ -21,7 +22,7 @@ public abstract class LStatement{
public transient @Nullable StatementElem elem;
public abstract void build(Table table);
public abstract LCategory category();
public abstract Color color();
public abstract LInstruction build(LAssembler builder);
public LStatement copy(){

View File

@@ -8,6 +8,7 @@ import arc.scene.ui.layout.*;
import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.logic.LCanvas.*;
import mindustry.logic.LExecutor.*;
import mindustry.type.*;
@@ -29,8 +30,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.control;
public Color color(){
return Pal.logicControl;
}
@Override
@@ -47,8 +48,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.operations;
public Color color(){
return Pal.logicOperations;
}
@Override
@@ -79,8 +80,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.io;
public Color color(){
return Pal.logicIo;
}
@Override
@@ -111,8 +112,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.io;
public Color color(){
return Pal.logicIo;
}
@Override
@@ -233,8 +234,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.io;
public Color color(){
return Pal.logicIo;
}
@Override
@@ -258,8 +259,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.io;
public Color color(){
return Pal.logicIo;
}
}
@@ -274,8 +275,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.blocks;
public Color color(){
return Pal.logicBlocks;
}
@Override
@@ -295,8 +296,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.blocks;
public Color color(){
return Pal.logicBlocks;
}
@Override
@@ -319,8 +320,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.blocks;
public Color color(){
return Pal.logicBlocks;
}
@Override
@@ -372,8 +373,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.blocks;
public Color color(){
return Pal.logicBlocks;
}
@Override
@@ -443,8 +444,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.blocks;
public Color color(){
return Pal.logicBlocks;
}
@Override
@@ -546,8 +547,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.blocks;
public Color color(){
return Pal.logicBlocks;
}
@Override
@@ -571,8 +572,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.operations;
public Color color(){
return Pal.logicOperations;
}
@Override
@@ -629,8 +630,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.operations;
public Color color(){
return Pal.logicOperations;
}
}
@@ -647,8 +648,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.control;
public Color color(){
return Pal.logicControl;
}
}
@@ -712,8 +713,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.control;
public Color color(){
return Pal.logicControl;
}
}
@@ -750,8 +751,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.units;
public Color color(){
return Pal.logicUnits;
}
@Override
@@ -803,8 +804,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.units;
public Color color(){
return Pal.logicUnits;
}
@Override
@@ -823,8 +824,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.units;
public Color color(){
return Pal.logicUnits;
}
@Override
@@ -932,8 +933,8 @@ public class LStatements{
}
@Override
public LCategory category(){
return LCategory.units;
public Color color(){
return Pal.logicUnits;
}
@Override

View File

@@ -65,7 +65,7 @@ public class LogicDialog extends BaseDialog{
if(example instanceof InvalidStatement || example.hidden()) continue;
TextButtonStyle style = new TextButtonStyle(Styles.cleart);
style.fontColor = example.category().color;
style.fontColor = example.color();
style.font = Fonts.outline;
t.button(example.name(), style, () -> {

View File

@@ -10,25 +10,28 @@ public enum LogicOp{
div("/", (a, b) -> a / b),
idiv("//", (a, b) -> Math.floor(a / b)),
mod("%", (a, b) -> a % b),
pow("^", Math::pow),
equal("==", (a, b) -> Math.abs(a - b) < 0.000001 ? 1 : 0, (a, b) -> Structs.eq(a, b) ? 1 : 0),
notEqual("not", (a, b) -> Math.abs(a - b) < 0.000001 ? 0 : 1, (a, b) -> !Structs.eq(a, b) ? 1 : 0),
land("and", (a, b) -> a != 0 && b != 0 ? 1 : 0),
lessThan("<", (a, b) -> a < b ? 1 : 0),
lessThanEq("<=", (a, b) -> a <= b ? 1 : 0),
greaterThan(">", (a, b) -> a > b ? 1 : 0),
greaterThanEq(">=", (a, b) -> a >= b ? 1 : 0),
pow("^", Math::pow),
shl("<<", (a, b) -> (long)a << (long)b),
shr(">>", (a, b) -> (long)a >> (long)b),
or("or", (a, b) -> (long)a | (long)b),
and("and", (a, b) -> (long)a & (long)b),
and("b-and", (a, b) -> (long)a & (long)b),
xor("xor", (a, b) -> (long)a ^ (long)b),
not("flip", a -> ~(long)(a)),
max("max", Math::max),
min("min", Math::min),
atan2("atan2", (x, y) -> Mathf.atan2((float)x, (float)y) * Mathf.radDeg),
dst("dst", (x, y) -> Mathf.dst((float)x, (float)y)),
noise("noise", LExecutor.noise::rawNoise2D),
not("not", a -> ~(long)(a)),
abs("abs", a -> Math.abs(a)),
log("log", Math::log),
log10("log10", Math::log10),

View File

@@ -2,6 +2,8 @@ package mindustry.mod;
import arc.*;
import arc.assets.*;
import arc.assets.loaders.*;
import arc.assets.loaders.SoundLoader.*;
import arc.audio.*;
import arc.files.*;
import arc.func.*;
@@ -89,15 +91,14 @@ public class ContentParser{
});
put(Sound.class, (type, data) -> {
if(fieldOpt(Sounds.class, data) != null) return fieldOpt(Sounds.class, data);
if(Vars.headless) return new MockSound();
if(Vars.headless) return new Sound();
String name = "sounds/" + data.asString();
String path = Vars.tree.get(name + ".ogg").exists() && !Vars.ios ? name + ".ogg" : name + ".mp3";
String path = Vars.tree.get(name + ".ogg").exists() ? name + ".ogg" : name + ".mp3";
if(Core.assets.contains(path, Sound.class)) return Core.assets.get(path, Sound.class);
ModLoadingSound sound = new ModLoadingSound();
AssetDescriptor<?> desc = Core.assets.load(path, Sound.class);
desc.loaded = result -> sound.sound = (Sound)result;
var sound = new Sound();
AssetDescriptor<?> desc = Core.assets.load(path, Sound.class, new SoundParameter(sound));
desc.errored = Throwable::printStackTrace;
return sound;
});

View File

@@ -1,78 +0,0 @@
package mindustry.mod;
import arc.audio.*;
import arc.mock.*;
public class ModLoadingMusic implements Music{
public Music music = new MockMusic();
@Override
public void play(){
music.play();
}
@Override
public void pause(){
music.pause();
}
@Override
public void stop(){
music.stop();
}
@Override
public boolean isPlaying(){
return music.isPlaying();
}
@Override
public boolean isLooping(){
return music.isLooping();
}
@Override
public void setLooping(boolean isLooping){
music.setLooping(isLooping);
}
@Override
public float getVolume(){
return music.getVolume();
}
@Override
public void setVolume(float volume){
music.setVolume(volume);
}
@Override
public void setPan(float pan, float volume){
music.setPan(pan, volume);
}
@Override
public float getPosition(){
return music.getPosition();
}
@Override
public void setPosition(float position){
music.setPosition(position);
}
@Override
public void dispose(){
music.dispose();
}
@Override
public void setCompletionListener(OnCompletionListener listener){
music.setCompletionListener(listener);
}
@Override
public boolean isDisposed(){
return music.isDisposed();
}
}

View File

@@ -1,134 +0,0 @@
package mindustry.mod;
import arc.audio.*;
import arc.math.geom.*;
import arc.mock.*;
public class ModLoadingSound implements Sound{
public Sound sound = new MockSound();
@Override
public float calcPan(float x, float y){
return sound.calcPan(x, y);
}
@Override
public float calcVolume(float x, float y){
return sound.calcVolume(x, y);
}
@Override
public float calcFalloff(float x, float y){
return sound.calcFalloff(x, y);
}
@Override
public int at(float x, float y, float pitch){
return sound.at(x, y, pitch);
}
@Override
public int at(float x, float y){
return sound.at(x, y);
}
@Override
public int at(Position pos){
return sound.at(pos);
}
@Override
public int at(Position pos, float pitch){
return sound.at(pos, pitch);
}
@Override
public int play(){
return sound.play();
}
@Override
public int play(float volume){
return sound.play(volume);
}
@Override
public int play(float volume, float pitch, float pan){
return sound.play(volume, pitch, pan);
}
@Override
public int loop(){
return sound.loop();
}
@Override
public int loop(float volume){
return sound.loop(volume);
}
@Override
public int loop(float volume, float pitch, float pan){
return sound.loop(volume, pitch, pan);
}
@Override
public void stop(){
sound.stop();
}
@Override
public void pause(){
sound.pause();
}
@Override
public void resume(){
sound.resume();
}
@Override
public void dispose(){
sound.dispose();
}
@Override
public void stop(int soundId){
sound.stop(soundId);
}
@Override
public void pause(int soundId){
sound.pause(soundId);
}
@Override
public void resume(int soundId){
sound.resume(soundId);
}
@Override
public void setLooping(int soundId, boolean looping){
sound.setLooping(soundId, looping);
}
@Override
public void setPitch(int soundId, float pitch){
sound.setPitch(soundId, pitch);
}
@Override
public void setVolume(int soundId, float volume){
sound.setVolume(soundId, volume);
}
@Override
public void set(int soundId, float pan, float volume){
sound.set(soundId, pan, volume);
}
@Override
public boolean isDisposed(){
return sound.isDisposed();
}
}

View File

@@ -2,11 +2,11 @@ package mindustry.mod;
import arc.*;
import arc.assets.*;
import arc.assets.loaders.MusicLoader.*;
import arc.assets.loaders.SoundLoader.*;
import arc.audio.*;
import arc.files.*;
import arc.func.*;
import arc.mock.*;
import arc.scene.ui.*;
import arc.struct.*;
import arc.util.*;
import arc.util.Log.*;
@@ -89,33 +89,31 @@ public class Scripts implements Disposable{
}
public Sound loadSound(String soundName){
if(Vars.headless) return new MockSound();
if(Vars.headless) return new Sound();
String name = "sounds/" + soundName;
String path = Vars.tree.get(name + ".ogg").exists() && !Vars.ios ? name + ".ogg" : name + ".mp3";
String path = Vars.tree.get(name + ".ogg").exists() ? name + ".ogg" : name + ".mp3";
if(Core.assets.contains(path, Sound.class)) return Core.assets.get(path, Sound.class);
ModLoadingSound sound = new ModLoadingSound();
AssetDescriptor<?> desc = Core.assets.load(path, Sound.class);
desc.loaded = result -> sound.sound = (Sound)result;
var sound = new Sound();
AssetDescriptor<?> desc = Core.assets.load(path, Sound.class, new SoundParameter(sound));
desc.errored = Throwable::printStackTrace;
return sound;
}
public Music loadMusic(String soundName){
if(Vars.headless) return new MockMusic();
if(Vars.headless) return new Music();
String name = "music/" + soundName;
String path = Vars.tree.get(name + ".ogg").exists() && !Vars.ios ? name + ".ogg" : name + ".mp3";
String path = Vars.tree.get(name + ".ogg").exists() ? name + ".ogg" : name + ".mp3";
if(Core.assets.contains(path, Music.class)) return Core.assets.get(path, Music.class);
ModLoadingMusic sound = new ModLoadingMusic();
AssetDescriptor<?> desc = Core.assets.load(path, Music.class);
desc.loaded = result -> sound.music = (Music)result;
var music = new Music();
AssetDescriptor<?> desc = Core.assets.load(path, Music.class, new MusicParameter(music));
desc.errored = Throwable::printStackTrace;
return sound;
return music;
}
/** Ask the user to select a file to read for a certain purpose like "Please upload a sprite" */

View File

@@ -45,7 +45,7 @@ public class BeControl{
}, updateInterval, updateInterval);
}
if(System.getProperties().contains("becopy")){
if(System.getProperties().containsKey("becopy")){
try{
Fi dest = Fi.get(System.getProperty("becopy"));
Fi self = Fi.get(BeControl.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());

View File

@@ -356,12 +356,12 @@ public class UnitType extends UnlockableContent{
ItemStack[] stacks = null;
//calculate costs based on reconstructors or factories found
Block rec = content.blocks().find(b -> b instanceof Reconstructor && ((Reconstructor)b).upgrades.contains(u -> u[1] == this));
Block rec = content.blocks().find(b -> b instanceof Reconstructor re && re.upgrades.contains(u -> u[1] == this));
if(rec != null && rec.consumes.has(ConsumeType.item) && rec.consumes.get(ConsumeType.item) instanceof ConsumeItems){
stacks = ((ConsumeItems)rec.consumes.get(ConsumeType.item)).items;
if(rec != null && rec.consumes.has(ConsumeType.item) && rec.consumes.get(ConsumeType.item) instanceof ConsumeItems ci){
stacks = ci.items;
}else{
UnitFactory factory = (UnitFactory)content.blocks().find(u -> u instanceof UnitFactory && ((UnitFactory)u).plans.contains(p -> p.unit == this));
UnitFactory factory = (UnitFactory)content.blocks().find(u -> u instanceof UnitFactory uf && uf.plans.contains(p -> p.unit == this));
if(factory != null){
stacks = factory.plans.find(p -> p.unit == this).requirements;
}
@@ -370,7 +370,7 @@ public class UnitType extends UnlockableContent{
if(stacks != null){
ItemStack[] out = new ItemStack[stacks.length];
for(int i = 0; i < out.length; i++){
out[i] = new ItemStack(stacks[i].item, UI.roundAmount((int)(Math.pow(stacks[i].amount, 1) * 50)));
out[i] = new ItemStack(stacks[i].item, UI.roundAmount((int)(Math.pow(stacks[i].amount, 1.1) * 50)));
}
return out;

View File

@@ -89,9 +89,9 @@ public abstract class Weather extends UnlockableContent{
}
}
if(sound != Sounds.none){
if(!headless && sound != Sounds.none){
float noise = soundVolOscMag > 0 ? (float)Math.abs(Noise.rawNoise(Time.time() / soundVolOscScl)) * soundVolOscMag : 0;
loops.play(sound, Core.camera.position, Math.max((soundVol + noise) * state.opacity, soundVolMin));
control.sound.loop(sound, Math.max((soundVol + noise) * state.opacity, soundVolMin));
}
}

View File

@@ -136,7 +136,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
if(to.near().contains(launchSector)) return launchSector;
Sector launchFrom = launchSector;
if(launchFrom == null){
if(launchFrom == null || (to.preset == null && !to.near().contains(launchSector))){
//TODO pick one with the most resources
launchFrom = to.near().find(Sector::hasBase);
if(launchFrom == null && to.preset != null){
@@ -153,24 +153,21 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
public void renderSectors(Planet planet){
//draw all sector stuff
if(!debugSelect){
if(!debugSelect && selectAlpha > 0.01f){
for(Sector sec : planet.sectors){
if(canSelect(sec) || sec.unlocked()){
if(selectAlpha > 0.01f){
if(canSelect(sec) || sec.unlocked()){
Color color =
sec.hasBase() ? Tmp.c2.set(Team.sharded.color).lerp(Team.crux.color, sec.hasEnemyBase() ? 0.5f : 0f) :
sec.preset != null ? Team.derelict.color :
sec.hasEnemyBase() ? Team.crux.color :
null;
Color color =
sec.hasBase() ? Team.sharded.color :
sec.preset != null ? Team.derelict.color :
sec.hasEnemyBase() ? Team.crux.color :
null;
if(color != null){
planets.drawSelection(sec, Tmp.c1.set(color).mul(0.8f).a(selectAlpha), 0.026f, -0.001f);
}
}else{
planets.fill(sec, Tmp.c1.set(shadowColor).mul(1, 1, 1, selectAlpha), -0.001f);
if(color != null){
planets.drawSelection(sec, Tmp.c1.set(color).mul(0.8f).a(selectAlpha), 0.026f, -0.001f);
}
}else{
planets.fill(sec, Tmp.c1.set(shadowColor).mul(1, 1, 1, selectAlpha), -0.001f);
}
}
}
@@ -202,20 +199,39 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
}
}
/*
//TODO render arcs
if(selected != null && selected.preset != null){
for(Objective o : selected.preset.requirements){
if(o instanceof SectorObjective){
SectorPreset preset = ((SectorObjective)o).preset;
planets.drawArc(planet, selected.tile.v, preset.sector.tile.v);
if(selectAlpha > 0.001f){
for(Sector sec : planet.sectors){
if(sec.hasBase()){
for(Sector enemy : sec.near()){
if(enemy.hasEnemyBase()){
planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.crux.color.write(Tmp.c2).a(selectAlpha), Color.clear, 0.24f, 110f, 25);
}
}
}
}
}*/
}
}
@Override
public void renderProjections(){
public void renderProjections(Planet planet){
for(Sector sec : planet.sectors){
if(sec != hovered){
var icon = (sec.isAttacked() ? Icon.warning : !sec.hasBase() && sec.preset != null && sec.preset.unlocked() ? Icon.terrain : null);
var color = sec.preset != null && !sec.hasBase() ? Team.derelict.color : Team.sharded.color;
if(icon != null){
planets.drawPlane(sec, () -> {
Draw.color(color, selectAlpha);
Draw.rect(icon.getRegion(), 0, 0);
});
}
}
}
Draw.reset();
if(hovered != null){
planets.drawPlane(hovered, () -> {
Draw.color(hovered.isAttacked() ? Pal.remove : Color.white, Pal.accent, Mathf.absin(5f, 1f));
@@ -229,6 +245,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
Draw.reset();
});
}
Draw.reset();
}
void setup(){
@@ -391,6 +409,12 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
(plus ? "+" : "") + (toCapture < 0 ? "" : "/" + toCapture) + " waves");
stable.row();
}
}else if(sector.hasBase() && sector.near().contains(Sector::hasEnemyBase)){
stable.add("[scarlet]Vulnerable");
stable.row();
}else if(!sector.hasBase() && sector.hasEnemyBase()){
stable.add("[scarlet]Enemy Base");
stable.row();
}
if(sector.save != null && sector.info.resources.any()){
@@ -441,7 +465,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
int i = 0;
for(ItemStack stack : items){
res.image(stack.item.icon(Cicon.small)).padRight(3);
res.add(UI.formatAmount(stack.amount)).color(Color.lightGray);
res.add(UI.formatAmount(Math.max(stack.amount, 0))).color(Color.lightGray);
if(++i % 2 == 0){
res.row();
}

View File

@@ -146,6 +146,12 @@ public class SettingsMenuDialog extends SettingsDialog{
}
}
}
for(var slot : control.saves.getSaveSlots().copy()){
if(slot.isSector()){
slot.delete();
}
}
});
}).marginLeft(4);

View File

@@ -617,7 +617,7 @@ public class Block extends UnlockableContent{
public ItemStack[] researchRequirements(){
ItemStack[] out = new ItemStack[requirements.length];
for(int i = 0; i < out.length; i++){
int quantity = 60 + Mathf.round(Mathf.pow(requirements[i].amount, 1.09f) * 20 * researchCostMultiplier, 10);
int quantity = 60 + Mathf.round(Mathf.pow(requirements[i].amount, 1.11f) * 20 * researchCostMultiplier, 10);
out[i] = new ItemStack(requirements[i].item, UI.roundAmount(quantity));
}

View File

@@ -177,7 +177,7 @@ public class ItemTurret extends Turret{
totalAmmo += a;
//only add ammo if this is a valid ammo type
if(ammoTypes.containsKey(item)){
if(item != null && ammoTypes.containsKey(item)){
ammo.add(new ItemEntry(item, a));
}
}

View File

@@ -26,6 +26,7 @@ public class LiquidTurret extends Turret{
acceptCoolant = false;
hasLiquids = true;
loopSound = Sounds.spray;
shootSound = Sounds.none;
}
/** Initializes accepted ammo map. Format: [liquid1, bullet1, liquid2, bullet2...] */
@@ -75,7 +76,7 @@ public class LiquidTurret extends Turret{
@Override
public boolean shouldActiveSound(){
return target != null && hasAmmo();
return wasShooting;
}
@Override

View File

@@ -95,7 +95,9 @@ public class TractorBeamTurret extends BaseTurret{
//look at target
if(target != null && target.within(this, range) && target.team() != team && target.type.flying && efficiency() > 0.01f){
loops.play(shootSound, this, shootSoundVolume);
if(!headless){
control.sound.loop(shootSound, this, shootSoundVolume);
}
any = true;
float dest = angleTo(target);

View File

@@ -136,6 +136,7 @@ public abstract class Turret extends ReloadTurret{
public @Nullable Posc target;
public Vec2 targetPos = new Vec2();
public BlockUnitc unit = Nulls.blockUnit;
public boolean wasShooting;
@Override
public void created(){
@@ -176,11 +177,15 @@ public abstract class Turret extends ReloadTurret{
case rotation -> rotation;
case shootX -> World.conv(targetPos.x);
case shootY -> World.conv(targetPos.y);
case shooting -> (isControlled() ? unit.isShooting() : logicControlled() ? logicShooting : validateTarget()) ? 1 : 0;
case shooting -> isShooting() ? 1 : 0;
default -> super.sense(sensor);
};
}
public boolean isShooting(){
return (isControlled() ? unit.isShooting() : logicControlled() ? logicShooting : target != null);
}
@Override
public Unit unit(){
return (Unit)unit;
@@ -228,6 +233,8 @@ public abstract class Turret extends ReloadTurret{
public void updateTile(){
if(!validateTarget()) target = null;
wasShooting = false;
recoil = Mathf.lerpDelta(recoil, 0f, restitution);
heat = Mathf.lerpDelta(heat, 0f, cooldown);
@@ -269,6 +276,7 @@ public abstract class Turret extends ReloadTurret{
}
if(Angles.angleDist(rotation, targetRot) < shootCone && canShoot){
wasShooting = true;
updateShooting();
}
}

View File

@@ -42,7 +42,7 @@ public class Conveyor extends Block implements Autotiler{
conveyorPlacement = true;
ambientSound = Sounds.conveyor;
ambientSoundVolume = 0.0015f;
ambientSoundVolume = 0.0022f;
unloadable = false;
noUpdateDisabled = false;
}

View File

@@ -153,7 +153,7 @@ public class PowerNode extends PowerBlock{
float fract = 1f - satisfaction;
Draw.color(laserColor1, laserColor2, fract * 0.86f + Mathf.absin(3f, 0.1f));
Draw.alpha(renderer.laserOpacity);
Draw.alpha(renderer == null ? 0.5f : renderer.laserOpacity);
}
protected void drawLaser(Team team, float x1, float y1, float x2, float y2, int size1, int size2){
@@ -226,7 +226,7 @@ public class PowerNode extends PowerBlock{
if(otherReq == null || otherReq.block == null) return;
drawLaser(player.team(), req.drawx(), req.drawy(), otherReq.drawx(), otherReq.drawy(), size, otherReq.block.size);
drawLaser(player == null ? Team.sharded : player.team(), req.drawx(), req.drawy(), otherReq.drawx(), otherReq.drawy(), size, otherReq.block.size);
}
Draw.color();
}

View File

@@ -67,7 +67,7 @@ public class Drill extends Block{
liquidCapacity = 5f;
hasItems = true;
ambientSound = Sounds.drill;
ambientSoundVolume = 0.016f;
ambientSoundVolume = 0.018f;
}
@Override
@@ -209,6 +209,11 @@ public class Drill extends Block{
return efficiency() > 0.01f && items.total() < itemCapacity;
}
@Override
public float ambientVolume(){
return efficiency() * (size * size) / 4f;
}
@Override
public void drawSelect(){
if(dominantItem != null){

View File

@@ -2,6 +2,7 @@ package mindustry.world.blocks.production;
import arc.graphics.g2d.*;
import mindustry.annotations.Annotations.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.world.meta.*;
@@ -15,6 +16,8 @@ public class Fracker extends SolidPump{
public Fracker(String name){
super(name);
hasItems = true;
ambientSound = Sounds.drill;
ambientSoundVolume = 0.03f;
}
@Override

View File

@@ -15,7 +15,7 @@ import static mindustry.Vars.*;
public class Pump extends LiquidBlock{
/** Pump amount per tile. */
protected float pumpAmount = 0.2f;
public float pumpAmount = 0.2f;
public Pump(String name){
super(name);

View File

@@ -210,7 +210,7 @@ public class CoreBlock extends StorageBlock{
super.onDestroyed();
//add a spawn to the map for future reference - waves should be disabled, so it shouldn't matter
if(state.isCampaign() && team == state.rules.waveTeam){
if(state.isCampaign() && team == state.rules.waveTeam && team.cores().size <= 1){
//do not recache
tile.setOverlayQuiet(Blocks.spawn);

View File

@@ -71,6 +71,8 @@ public class Unloader extends Block{
other.items.remove(item, 1);
}
other.itemTaken(item);
}else if(sortItem == null){
other.items.failTake();
}
}
}

View File

@@ -41,10 +41,13 @@ public class AmmoListValue<T extends UnlockableContent> implements StatValue{
sep(bt, Core.bundle.format("bullet.splashdamage", (int)type.splashDamage, Strings.fixed(type.splashDamageRadius / tilesize, 1)));
}
if(!Mathf.equal(type.ammoMultiplier, 1f))
if(!Mathf.equal(type.ammoMultiplier, 1f) && !(type instanceof LiquidBulletType)){
sep(bt, Core.bundle.format("bullet.multiplier", (int)type.ammoMultiplier));
if(!Mathf.equal(type.reloadMultiplier, 1f))
}
if(!Mathf.equal(type.reloadMultiplier, 1f)){
sep(bt, Core.bundle.format("bullet.reload", Strings.fixed(type.reloadMultiplier, 1)));
}
if(type.knockback > 0){
sep(bt, Core.bundle.format("bullet.knockback", Strings.fixed(type.knockback, 1)));

View File

@@ -224,6 +224,18 @@ public class ItemModule extends BlockModule{
takeRotation = item.id + 1;
}
public void failTake(){
for(int i = 1; i < items.length; i++){
int index = (i + takeRotation);
if(index >= items.length) index -= items.length;
if(items[index] > 0){
takeRotation += i;
takeRotation %= items.length;
return;
}
}
}
public int get(int id){
return items[id];
}