Merge branch 'master' into files
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}};
|
||||
|
||||
|
||||
@@ -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)
|
||||
), () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()){
|
||||
|
||||
@@ -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 ++;
|
||||
}
|
||||
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(){
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, () -> {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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" */
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -146,6 +146,12 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(var slot : control.saves.getSaveSlots().copy()){
|
||||
if(slot.isSector()){
|
||||
slot.delete();
|
||||
}
|
||||
}
|
||||
});
|
||||
}).marginLeft(4);
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ public class Unloader extends Block{
|
||||
other.items.remove(item, 1);
|
||||
}
|
||||
other.itemTaken(item);
|
||||
}else if(sortItem == null){
|
||||
other.items.failTake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user