Merge branch 'master' into cleanup-2

This commit is contained in:
Skat
2020-11-09 20:21:01 +04:00
committed by GitHub
106 changed files with 328 additions and 249 deletions

View File

@@ -79,7 +79,7 @@ public class BuilderAI extends AIController{
float dist = Math.min(cons.dst(unit) - buildingRange, 0);
//make sure you can reach the request in time
if(dist / unit.type.speed < cons.buildCost * 0.9f){
if(dist / unit.speed() < cons.buildCost * 0.9f){
following = b;
found = true;
}

View File

@@ -55,7 +55,7 @@ public class FlyingAI extends AIController{
vec.setAngle(Mathf.slerpDelta(unit.vel().angle(), vec.angle(), 0.6f));
}
vec.setLength(unit.type.speed);
vec.setLength(unit.speed());
unit.moveAt(vec);
}

View File

@@ -2,17 +2,13 @@ package mindustry.ai.types;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.ai.formations.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.storage.CoreBlock.*;
public class FormationAI extends AIController implements FormationMember{
private static Seq<Tile> tiles = new Seq<>();
public Unit leader;
private Vec3 target = new Vec3();
@@ -30,9 +26,8 @@ public class FormationAI extends AIController implements FormationMember{
@Override
public void updateUnit(){
UnitType type = unit.type;
if(leader.dead){
if(leader == null || leader.dead){
unit.resetController();
return;
}

View File

@@ -104,9 +104,7 @@ public class LogicAI extends AIController{
//look where moving if there's nothing to aim at
if(!shoot){
if(unit.moving()){
unit.lookAt(unit.vel().angle());
}
unit.lookAt(unit.prefRotation());
}else if(unit.hasWeapons()){ //if there is, look at the object
unit.lookAt(unit.mounts[0].aimX, unit.mounts[0].aimY);
}

View File

@@ -65,7 +65,7 @@ public class SuicideAI extends GroundAI{
if(!blocked){
moveToTarget = true;
//move towards target directly
unit.moveAt(vec.set(target).sub(unit).limit(unit.type.speed));
unit.moveAt(vec.set(target).sub(unit).limit(unit.speed()));
}
}
}

View File

@@ -31,12 +31,12 @@ public class LoopControl{
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){
if(data.soundID <= 0 || !sound.isPlaying(data.soundID)){
if(play){
data.soundID = sound.loop(data.curVolume, 1f, pan);
}
}else{
if(data.curVolume <= 0.01f){
if(data.curVolume <= 0.001f){
sound.stop();
data.soundID = -1;
return;

View File

@@ -2,6 +2,7 @@ package mindustry.audio;
import arc.*;
import arc.audio.*;
import arc.audio.SoloudAudio.*;
import arc.math.*;
import arc.struct.*;
import arc.util.*;
@@ -25,6 +26,11 @@ public class MusicControl{
protected float fade;
protected boolean silenced;
protected boolean wasPaused;
protected AudioFilter filter = new BiquadFilter(){{
set(0, 500, 1);
}};
public MusicControl(){
Events.on(ClientLoadEvent.class, e -> reload());
@@ -54,6 +60,13 @@ public class MusicControl{
/** Update and play the right music track.*/
public void update(){
boolean paused = state.isGame() && Core.scene.hasDialog();
if(paused != wasPaused){
Core.audio.setFilter(0, paused ? filter : null);
wasPaused = paused;
}
if(state.isMenu()){
silenced = false;
if(ui.planet.isShown()){

View File

@@ -18,7 +18,7 @@ public class SoundLoop{
}
public void update(float x, float y, boolean play){
if(baseVolume < 0) return;
if(baseVolume <= 0) return;
if(id < 0){
if(play){
@@ -36,6 +36,7 @@ public class SoundLoop{
return;
}
}
sound.setPan(id, sound.calcPan(x, y), sound.calcVolume(x, y) * volume * baseVolume);
}
}

View File

@@ -288,6 +288,10 @@ public class Blocks implements ContentList{
attributes.set(Attribute.water, 1f);
cacheLayer = CacheLayer.mud;
albedo = 0.35f;
walkSound = Sounds.mud;
walkSoundVolume = 0.08f;
walkSoundPitchMin = 0.4f;
walkSoundPitchMax = 0.5f;
}};
((ShallowLiquid)darksandTaintedWater).set(Blocks.taintedWater, Blocks.darksand);
@@ -592,6 +596,9 @@ public class Blocks implements ContentList{
hasPower = true;
drawer = new DrawWeave();
ambientSound = Sounds.techloop;
ambientSoundVolume = 0.02f;
consumes.items(with(Items.thorium, 4, Items.sand, 10));
consumes.power(5f);
itemCapacity = 20;
@@ -720,6 +727,8 @@ public class Blocks implements ContentList{
updateEffect = Fx.pulverizeSmall;
hasItems = hasPower = true;
drawer = new DrawRotator();
ambientSound = Sounds.grinding;
ambientSoundVolume = 0.02f;
consumes.item(Items.scrap, 1);
consumes.power(0.50f);
@@ -1158,6 +1167,9 @@ public class Blocks implements ContentList{
requirements(Category.power, with(Items.copper, 25, Items.lead, 15));
powerProduction = 1f;
itemDuration = 120f;
ambientSound = Sounds.smelter;
ambientSoundVolume = 0.03f;
}};
thermalGenerator = new ThermalGenerator("thermal-generator"){{
@@ -1166,6 +1178,8 @@ public class Blocks implements ContentList{
generateEffect = Fx.redgeneratespark;
size = 2;
floating = true;
ambientSound = Sounds.hum;
ambientSoundVolume = 0.04f;
}};
steamGenerator = new BurnerGenerator("steam-generator"){{
@@ -1175,6 +1189,9 @@ public class Blocks implements ContentList{
consumes.liquid(Liquids.water, 0.1f);
hasLiquids = true;
size = 2;
ambientSound = Sounds.smelter;
ambientSoundVolume = 0.05f;
}};
differentialGenerator = new SingleTypeGenerator("differential-generator"){{
@@ -1184,6 +1201,8 @@ public class Blocks implements ContentList{
hasLiquids = true;
hasItems = true;
size = 3;
ambientSound = Sounds.steam;
ambientSoundVolume = 0.03f;
consumes.item(Items.pyratite).optional(true, false);
consumes.liquid(Liquids.cryofluid, 0.1f);
@@ -1209,6 +1228,8 @@ 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;
size = 3;
health = 700;
itemDuration = 360f;
@@ -1224,6 +1245,9 @@ public class Blocks implements ContentList{
health = 900;
powerProduction = 130f;
itemDuration = 140f;
ambientSound = Sounds.pulse;
ambientSoundVolume = 0.2f;
consumes.power(25f);
consumes.item(Items.blastCompound);
consumes.liquid(Liquids.cryofluid, 0.25f);
@@ -1464,7 +1488,7 @@ public class Blocks implements ContentList{
inaccuracy = 1f;
shootCone = 10f;
health = 260;
shootSound = Sounds.artillery;
shootSound = Sounds.bang;
}};
wave = new LiquidTurret("wave"){{
@@ -1484,7 +1508,6 @@ public class Blocks implements ContentList{
shootEffect = Fx.shootLiquid;
range = 110f;
health = 250 * size * size;
shootSound = Sounds.splash;
}};
lancer = new ChargeTurret("lancer"){{
@@ -1632,7 +1655,6 @@ public class Blocks implements ContentList{
shootEffect = Fx.shootLiquid;
range = 190f;
health = 250 * size * size;
shootSound = Sounds.splash;
}};
fuse = new ItemTurret("fuse"){{
@@ -1752,13 +1774,13 @@ public class Blocks implements ContentList{
shots = 1;
size = 4;
shootCone = 2f;
shootSound = Sounds.shootBig;
shootSound = Sounds.railgun;
unitSort = (u, x, y) -> -u.maxHealth;
coolantMultiplier = 0.09f;
coolantMultiplier = 0.11f;
health = 150 * size * size;
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 2f)).update(false).optional(true, true);
coolantUsage = 1f;
consumes.powerCond(10f, TurretBuild::isActive);
}};
@@ -1786,7 +1808,7 @@ public class Blocks implements ContentList{
shootSound = Sounds.shootBig;
health = 160 * size * size;
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 2f)).update(false).optional(true, true);
coolantUsage = 1f;
}};
meltdown = new LaserTurret("meltdown"){{
@@ -1802,8 +1824,8 @@ public class Blocks implements ContentList{
shootDuration = 220f;
powerUse = 17f;
shootSound = Sounds.laserbig;
activeSound = Sounds.beam;
activeSoundVolume = 2f;
loopSound = Sounds.beam;
loopSoundVolume = 2f;
shootType = new ContinuousLaserBulletType(70){{
length = 200f;

View File

@@ -21,7 +21,7 @@ public class UnitTypes implements ContentList{
public static @EntityDef({Unitc.class, Mechc.class}) UnitType mace, dagger, crawler, fortress, scepter, reign;
//mech + builder + miner
public static @EntityDef({Unitc.class, Mechc.class, Builderc.class, Minerc.class}) UnitType nova, pulsar, quasar;
public static @EntityDef({Unitc.class, Mechc.class, Builderc.class}) UnitType nova, pulsar, quasar;
//mech
public static @EntityDef({Unitc.class, Mechc.class}) UnitType vela;
@@ -35,23 +35,23 @@ public class UnitTypes implements ContentList{
//air (no special traits)
public static @EntityDef({Unitc.class}) UnitType flare, eclipse, horizon, zenith, antumbra;
//air + mining
public static @EntityDef({Unitc.class, Minerc.class}) UnitType mono;
//air, legacy mining
public static @EntityDef(value = {Unitc.class}, legacy = true) UnitType mono;
//air + building + mining
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType poly;
public static @EntityDef({Unitc.class, Builderc.class}) UnitType poly;
//air + building + mining + payload
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class, Payloadc.class}) UnitType mega;
public static @EntityDef({Unitc.class, Builderc.class, Payloadc.class}) UnitType mega;
//air + building + payload
public static @EntityDef({Unitc.class, Builderc.class, Payloadc.class}) UnitType quad;
public static @EntityDef(value = {Unitc.class, Builderc.class, Payloadc.class}, legacy = true) UnitType quad;
//air + building + payload
public static @EntityDef({Unitc.class, Builderc.class, Payloadc.class, AmmoDistributec.class}) UnitType oct;
//air + building + mining
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType alpha, beta, gamma;
public static @EntityDef({Unitc.class, Builderc.class}) UnitType alpha, beta, gamma;
//water
public static @EntityDef({Unitc.class, WaterMovec.class}) UnitType risso, minke, bryde, sei, omura;
@@ -166,7 +166,7 @@ public class UnitTypes implements ContentList{
recoil = 5f;
shake = 2f;
ejectEffect = Fx.casing3;
shootSound = Sounds.artillery;
shootSound = Sounds.bang;
shots = 3;
inaccuracy = 3f;
shotDelay = 4f;
@@ -226,7 +226,7 @@ public class UnitTypes implements ContentList{
recoil = 5f;
shake = 2f;
ejectEffect = Fx.casing4;
shootSound = Sounds.artillery;
shootSound = Sounds.bang;
bullet = new BasicBulletType(13f, 60){{
pierce = true;
@@ -287,6 +287,8 @@ public class UnitTypes implements ContentList{
alternate = false;
ejectEffect = Fx.none;
recoil = 2f;
shootSound = Sounds.lasershoot;
bullet = new LaserBoltBulletType(5.2f, 14){{
healPercent = 5f;
collidesTeam = true;
@@ -328,7 +330,7 @@ public class UnitTypes implements ContentList{
spacing = 0f;
ejectEffect = Fx.none;
recoil = 2.5f;
shootSound = Sounds.pew;
shootSound = Sounds.spark;
bullet = new LightningBulletType(){{
lightningColor = hitColor = Pal.heal;
@@ -430,7 +432,8 @@ public class UnitTypes implements ContentList{
reload = 320f;
recoil = 0f;
shootSound = Sounds.laser;
chargeSound = Sounds.lasercharge2;
shootSound = Sounds.beam;
continuous = true;
cooldownTime = 200f;
@@ -491,6 +494,9 @@ public class UnitTypes implements ContentList{
drawShields = false;
weapons.add(new Weapon("corvus-weapon"){{
shootSound = Sounds.laserblast;
chargeSound = Sounds.lasercharge;
soundPitchMin = 1f;
top = false;
mirror = false;
shake = 14f;
@@ -498,7 +504,6 @@ public class UnitTypes implements ContentList{
x = y = 0;
reload = 350f;
recoil = 0f;
shootSound = Sounds.laser;
cooldownTime = 350f;
@@ -634,7 +639,7 @@ public class UnitTypes implements ContentList{
ejectEffect = Fx.none;
recoil = 2f;
rotate = true;
shootSound = Sounds.flame;
shootSound = Sounds.sap;
x = 8.5f;
y = -1.5f;
@@ -657,6 +662,7 @@ public class UnitTypes implements ContentList{
rotate = true;
x = 4f;
y = 3f;
shootSound = Sounds.sap;
bullet = new SapBulletType(){{
sapStrength = 0.8f;
@@ -721,6 +727,7 @@ public class UnitTypes implements ContentList{
y = 8f;
rotate = true;
bullet = sapper;
shootSound = Sounds.sap;
}},
new Weapon("spiroct-weapon"){{
reload = 15f;
@@ -728,6 +735,7 @@ public class UnitTypes implements ContentList{
y = 6f;
rotate = true;
bullet = sapper;
shootSound = Sounds.sap;
}},
new Weapon("spiroct-weapon"){{
reload = 23f;
@@ -735,6 +743,7 @@ public class UnitTypes implements ContentList{
y = 0f;
rotate = true;
bullet = sapper;
shootSound = Sounds.sap;
}},
new Weapon("large-purple-mount"){{
y = -7f;
@@ -744,7 +753,7 @@ public class UnitTypes implements ContentList{
shake = 3f;
rotateSpeed = 2f;
ejectEffect = Fx.casing1;
shootSound = Sounds.shootBig;
shootSound = Sounds.artillery;
rotate = true;
occlusion = 8f;
recoil = 3f;
@@ -842,7 +851,7 @@ public class UnitTypes implements ContentList{
recoil = 10f;
rotateSpeed = 1f;
ejectEffect = Fx.casing3;
shootSound = Sounds.shootBig;
shootSound = Sounds.artillery;
rotate = true;
occlusion = 30f;
@@ -1205,7 +1214,7 @@ public class UnitTypes implements ContentList{
reload = 30f;
ejectEffect = Fx.none;
recoil = 2f;
shootSound = Sounds.pew;
shootSound = Sounds.missile;
shots = 1;
velocityRnd = 0.5f;
inaccuracy = 15f;
@@ -1221,6 +1230,7 @@ public class UnitTypes implements ContentList{
smokeEffect = Fx.hitLaser;
hitEffect = despawnEffect = Fx.hitLaser;
frontColor = Color.white;
hitSound = Sounds.none;
healPercent = 5.5f;
collidesTeam = true;
@@ -1252,6 +1262,7 @@ public class UnitTypes implements ContentList{
weapons.add(
new Weapon("heal-weapon-mount"){{
shootSound = Sounds.lasershoot;
reload = 25f;
x = 8f;
y = -6f;
@@ -1259,6 +1270,7 @@ public class UnitTypes implements ContentList{
bullet = Bullets.healBulletBig;
}},
new Weapon("heal-weapon-mount"){{
shootSound = Sounds.lasershoot;
reload = 15f;
x = 4f;
y = 5f;
@@ -1578,7 +1590,7 @@ public class UnitTypes implements ContentList{
inaccuracy = 7f;
ejectEffect = Fx.none;
shake = 3f;
shootSound = Sounds.shootBig;
shootSound = Sounds.missile;
xRand = 8f;
shotDelay = 1f;
@@ -1659,6 +1671,7 @@ public class UnitTypes implements ContentList{
shake = 6f;
recoil = 10.5f;
occlusion = 50f;
shootSound = Sounds.railgun;
shots = 1;
ejectEffect = Fx.none;

View File

@@ -3,6 +3,7 @@ package mindustry.content;
import arc.graphics.*;
import arc.util.*;
import mindustry.ctype.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.type.weather.*;
import mindustry.world.meta.*;
@@ -23,12 +24,20 @@ public class Weathers implements ContentList{
sizeMin = 2.6f;
density = 1200f;
attrs.set(Attribute.light, -0.15f);
sound = Sounds.windhowl;
soundVol = 0f;
soundVolOscMag = 1.5f;
soundVolOscScl = 1100f;
soundVolMin = 0.02f;
}};
rain = new RainWeather("rain"){{
attrs.set(Attribute.light, -0.2f);
attrs.set(Attribute.water, 0.2f);
status = StatusEffects.wet;
sound = Sounds.rain;
soundVol = 0.25f;
}};
sandstorm = new ParticleWeather("sandstorm"){{
@@ -46,6 +55,8 @@ public class Weathers implements ContentList{
attrs.set(Attribute.water, -0.1f);
opacityMultiplier = 0.8f;
force = 0.1f;
sound = Sounds.wind;
soundVol = 0.3f;
}};
sporestorm = new ParticleWeather("sporestorm"){{
@@ -65,6 +76,8 @@ public class Weathers implements ContentList{
status = StatusEffects.sporeSlowed;
opacityMultiplier = 0.85f;
force = 0.1f;
sound = Sounds.wind;
soundVol = 0.3f;
}};
fog = new ParticleWeather("fog"){{

View File

@@ -477,10 +477,6 @@ public class Control implements ApplicationListener, Loadable{
dialog.show();
}));
}
if(android){
Sounds.empty.loop(0f, 1f, 0f);
}
}
@Override

View File

@@ -640,7 +640,7 @@ public class NetServer implements ApplicationListener{
Unit unit = player.unit();
long elapsed = Time.timeSinceMillis(con.lastReceivedClientTime);
float maxSpeed = ((player.unit().type.canBoost && player.unit().isFlying()) ? player.unit().type.boostMultiplier : 1f) * player.unit().type.speed;
float maxSpeed = ((player.unit().type.canBoost && player.unit().isFlying()) ? player.unit().type.boostMultiplier : 1f) * player.unit().speed();
if(unit.isGrounded()){
maxSpeed *= unit.floorSpeedMultiplier();
}

View File

@@ -126,7 +126,7 @@ public abstract class UnlockableContent extends MappableContent{
}
public boolean unlocked(){
if(net != null && net.client()) return state.rules.researched.contains(name);
if(net != null && net.client()) return alwaysUnlocked || state.rules.researched.contains(name);
return unlocked || alwaysUnlocked;
}

View File

@@ -207,7 +207,7 @@ public abstract class BulletType extends Content{
Damage.createIncend(x, y, incendSpread, incendAmount);
}
if(splashDamageRadius > 0){
if(splashDamageRadius > 0 && !b.absorbed){
Damage.damage(b.team, x, y, splashDamageRadius, splashDamage * b.damageMultiplier(), collidesAir, collidesGround);
if(status != StatusEffects.none){

View File

@@ -27,7 +27,7 @@ abstract class BuilderComp implements Unitc{
@Import float x, y, rotation;
@SyncLocal Queue<BuildPlan> plans = new Queue<>();
@SyncLocal Queue<BuildPlan> plans = new Queue<>(1);
@SyncLocal transient boolean updateBuilding = true;
@Override
@@ -35,7 +35,6 @@ abstract class BuilderComp implements Unitc{
if(!updateBuilding) return;
float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange;
boolean infinite = state.rules.infiniteResources || team().rules().infiniteResources;
Iterator<BuildPlan> it = plans.iterator();
@@ -69,10 +68,6 @@ abstract class BuilderComp implements Unitc{
Tile tile = world.tile(current.x, current.y);
if(within(tile, finalPlaceDst)){
lookAt(angleTo(tile));
}
if(!(tile.block() instanceof ConstructBlock)){
if(!current.initialized && !current.breaking && Build.validPlace(current.block, team(), current.x, current.y, current.rotation)){
boolean hasAll = infinite || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item));
@@ -188,6 +183,10 @@ abstract class BuilderComp implements Unitc{
}
boolean activelyBuilding(){
//not actively building when not near the build plan
if(isBuilding() && !within(buildPlan(), state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange)){
return false;
}
return isBuilding() && updateBuilding;
}

View File

@@ -29,6 +29,7 @@ import mindustry.logic.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.blocks.*;
import mindustry.world.blocks.ConstructBlock.*;
import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.payloads.*;
@@ -106,8 +107,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
this.block = block;
this.team = team;
if(block.activeSound != Sounds.none){
sound = new SoundLoop(block.activeSound, block.activeSoundVolume);
if(block.loopSound != Sounds.none){
sound = new SoundLoop(block.loopSound, block.loopSoundVolume);
}
health = block.health;
@@ -780,7 +781,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
/** @return whether this block should play its idle sound.*/
public boolean shouldIdleSound(){
public boolean shouldAmbientSound(){
return shouldConsume();
}
@@ -1225,6 +1226,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
/** @return ambient sound volume scale. */
public float ambientVolume(){
return efficiency();
}
//endregion
//region overrides
@@ -1285,6 +1291,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
case powerNetStored -> power == null ? 0 : power.graph.getLastPowerStored();
case powerNetCapacity -> power == null ? 0 : power.graph.getLastCapacity();
case enabled -> enabled ? 1 : 0;
case controlled -> this instanceof ControlBlock c ? c.isControlled() ? 1 : 0 : 0;
case payloadCount -> getPayload() != null ? 1 : 0;
default -> 0;
};
@@ -1365,8 +1372,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
sound.update(x, y, shouldActiveSound());
}
if(block.idleSound != Sounds.none && shouldIdleSound()){
loops.play(block.idleSound, self(), block.idleSoundVolume);
if(block.ambientSound != Sounds.none && shouldAmbientSound()){
loops.play(block.ambientSound, self(), block.ambientSoundVolume * ambientVolume());
}
if(enabled || !block.noUpdateDisabled){

View File

@@ -30,6 +30,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
Object data;
BulletType type;
float fdata;
transient boolean absorbed;
@Override
public void getCollisions(Cons<QuadTree> consumer){
@@ -67,6 +68,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
@Override
public void absorb(){
absorbed = true;
remove();
}

View File

@@ -75,10 +75,14 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
wasFlying = isFlying();
}
if(!hovering && isGrounded() && floor.isLiquid){
if(!hovering && isGrounded()){
if((splashTimer += Mathf.dst(deltaX(), deltaY())) >= (7f + hitSize()/8f)){
floor.walkEffect.at(x, y, hitSize() / 8f, floor.mapColor);
splashTimer = 0f;
if(!(this instanceof WaterMovec)){
floor.walkSound.at(x, y, Mathf.random(floor.walkSoundPitchMin, floor.walkSoundPitchMax), floor.walkSoundVolume);
}
}
}

View File

@@ -112,6 +112,7 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
Floor floor = Vars.world.floorWorld(l.base.x, l.base.y);
if(floor.isLiquid){
floor.walkEffect.at(l.base.x, l.base.y, type.rippleScale, floor.mapColor);
floor.walkSound.at(x, y, 1f, floor.walkSoundVolume);
}else{
Fx.unitLandSmall.at(l.base.x, l.base.y, type.rippleScale, floor.mapColor);
}

View File

@@ -16,8 +16,8 @@ import mindustry.world.*;
import static mindustry.Vars.*;
@Component
abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
@Import float x, y, rotation;
abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{
@Import float x, y, rotation, hitSize;
@Import UnitType type;
transient float mineTimer;
@@ -28,7 +28,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
}
public boolean offloadImmediately(){
return isPlayer();
return this.<Unit>self().isPlayer();
}
boolean mining(){
@@ -63,7 +63,6 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
mineTimer = 0f;
}else if(mining()){
Item item = mineTile.drop();
lookAt(angleTo(mineTile.worldx(), mineTile.worldy()));
mineTimer += Time.delta *type.mineSpeed;
if(Mathf.chance(0.06 * Time.delta)){
@@ -88,13 +87,17 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
mineTimer = 0f;
}
}
if(!headless){
loops.play(type.mineSound, this, type.mineSoundVolume);
}
}
}
@Override
public void draw(){
if(!mining()) return;
float focusLen = hitSize() / 2f + Mathf.absin(Time.time(), 1.1f, 0.5f);
float focusLen = hitSize / 2f + Mathf.absin(Time.time(), 1.1f, 0.5f);
float swingScl = 12f, swingMag = tilesize / 8f;
float flashScl = 0.3f;

View File

@@ -9,6 +9,7 @@ import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import mindustry.ai.*;
import mindustry.ai.types.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.core.*;
@@ -30,10 +31,10 @@ import mindustry.world.blocks.payloads.*;
import static mindustry.Vars.*;
@Component(base = true)
abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Commanderc, Displayable, Senseable, Ranged{
abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Commanderc, Displayable, Senseable, Ranged, Minerc{
@Import boolean hovering, dead;
@Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health, ammo;
@Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health, ammo, minFormationSpeed;
@Import Team team;
@Import int id;
@@ -67,9 +68,14 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
return type.hasWeapons();
}
public float speed(){
//limit speed to minimum formation speed to preserve formation
return isCommanding() ? minFormationSpeed * 0.98f : type.speed;
}
/** @return speed with boost multipliers factored in. */
public float realSpeed(){
return Mathf.lerp(1f, type.canBoost ? type.boostMultiplier : 1f, elevation) * type.speed;
return Mathf.lerp(1f, type.canBoost ? type.boostMultiplier : 1f, elevation) * speed();
}
/** Iterates through this unit and everything it is controlling. */
@@ -78,6 +84,18 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
controlling().each(cons);
}
/** @return where the unit wants to look at. */
public float prefRotation(){
if(this instanceof Builderc builder && builder.activelyBuilding()){
return angleTo(builder.buildPlan());
}else if(mineTile() != null){
return angleTo(mineTile());
}else if(moving()){
return vel().angle();
}
return rotation;
}
@Override
public float range(){
return type.range;
@@ -105,6 +123,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
case shootX -> World.conv(aimX());
case shootY -> World.conv(aimY());
case flag -> flag;
case controlled -> controller instanceof LogicAI || controller instanceof Player ? 1 : 0;
case payloadCount -> self() instanceof Payloadc pay ? pay.payloads().size : 0;
default -> 0;
};

View File

@@ -4,6 +4,7 @@ import arc.math.*;
import arc.math.geom.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.audio.*;
import mindustry.entities.*;
import mindustry.entities.bullet.*;
import mindustry.entities.units.*;
@@ -117,10 +118,18 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc, Statusc{
mount.bullet.rotation(weaponRotation + 90);
mount.bullet.set(shootX, shootY);
vel.add(Tmp.v1.trns(rotation + 180f, mount.bullet.type.recoil));
if(weapon.shootSound != Sounds.none && !headless){
if(mount.sound == null) mount.sound = new SoundLoop(weapon.shootSound, 1f);
mount.sound.update(x, y, true);
}
}
}else{
//heat decreases when not firing
mount.heat = Math.max(mount.heat - Time.delta * reloadMultiplier / mount.weapon.cooldownTime, 0);
if(mount.sound != null){
mount.sound.update(x, y, false);
}
}
//flip weapon shoot side for alternating weapons at half reload
@@ -168,7 +177,7 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc, Statusc{
float baseX = this.x, baseY = this.y;
boolean delay = weapon.firstShotDelay + weapon.shotDelay > 0f;
(delay ? weapon.chargeSound : weapon.shootSound).at(x, y, Mathf.random(0.8f, 1.0f));
(delay ? weapon.chargeSound : weapon.continuous ? Sounds.none : weapon.shootSound).at(x, y, Mathf.random(weapon.soundPitchMin, weapon.soundPitchMax));
BulletType ammo = weapon.bullet;
float lifeScl = ammo.scaleVelocity ? Mathf.clamp(Mathf.dst(x, y, aimX, aimY) / ammo.range()) : 1f;
@@ -195,7 +204,9 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc, Statusc{
vel.add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
Effect.shake(weapon.shake, weapon.shake, x, y);
mount.heat = 1f;
weapon.shootSound.at(x, y, Mathf.random(0.8f, 1.0f));
if(!weapon.continuous){
weapon.shootSound.at(x, y, Mathf.random(weapon.soundPitchMin, weapon.soundPitchMax));
}
});
}else{
vel.add(Tmp.v1.trns(rotation + 180f, ammo.recoil));

View File

@@ -64,9 +64,7 @@ public class AIController implements UnitController{
if(unit.isFlying()){
unit.wobble();
if(unit.moving()){
unit.lookAt(unit.vel.angle());
}
unit.lookAt(unit.prefRotation());
}
}
@@ -94,7 +92,7 @@ public class AIController implements UnitController{
if(tile == targetTile || (costType == Pathfinder.costWater && !targetTile.floor().isLiquid)) return;
unit.moveAt(vec.trns(unit.angleTo(targetTile), unit.type.speed));
unit.moveAt(vec.trns(unit.angleTo(targetTile), unit.speed()));
}
protected void updateWeapons(){
@@ -175,7 +173,7 @@ public class AIController implements UnitController{
}
protected void circle(Position target, float circleLength){
circle(target, circleLength, unit.type.speed);
circle(target, circleLength, unit.speed());
}
protected void circle(Position target, float circleLength, float speed){

View File

@@ -9,7 +9,7 @@ import mindustry.world.*;
import static mindustry.Vars.*;
/** Class for storing build requests. Can be either a place or remove request. */
public class BuildPlan{
public class BuildPlan implements Position{
/** Position and rotation of this request. */
public int x, y, rotation;
/** Block being placed. If null, this is a breaking request.*/
@@ -127,11 +127,11 @@ public class BuildPlan{
}
public float drawx(){
return x*tilesize + block.offset;
return x*tilesize + (block == null ? 0 : block.offset);
}
public float drawy(){
return y*tilesize + block.offset;
return y*tilesize + (block == null ? 0 : block.offset);
}
public @Nullable Tile tile(){
@@ -142,6 +142,16 @@ public class BuildPlan{
return world.build(x, y);
}
@Override
public float getX(){
return drawx();
}
@Override
public float getY(){
return drawy();
}
@Override
public String toString(){
return "BuildRequest{" +

View File

@@ -1,6 +1,7 @@
package mindustry.entities.units;
import arc.util.*;
import mindustry.audio.*;
import mindustry.gen.*;
import mindustry.type.*;
@@ -25,6 +26,8 @@ public class WeaponMount{
public boolean side;
/** current bullet for continuous weapons */
public @Nullable Bullet bullet;
/** sound loop for continuous weapons */
public @Nullable SoundLoop sound;
public WeaponMount(Weapon weapon){
this.weapon = weapon;

View File

@@ -481,8 +481,8 @@ public class DesktopInput extends InputHandler{
deleting = true;
}else if(selected != null){
//only begin shooting if there's no cursor event
if(!tileTapped(selected.build) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && (player.builder().plans().size == 0 || !player.builder().updateBuilding()) && !droppingItem &&
!tryBeginMine(selected) && player.miner().mineTile() == null && !Core.scene.hasKeyboard()){
if(!tileTapped(selected.build) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && !player.builder().activelyBuilding() && !droppingItem &&
!tryBeginMine(selected) && player.miner().mineTile() == null && !Core.scene.hasKeyboard()){
player.shooting = shouldShoot;
}
}else if(!Core.scene.hasKeyboard()){ //if it's out of bounds, shooting is just fine
@@ -603,13 +603,6 @@ public class DesktopInput extends InputHandler{
boolean ground = unit.isGrounded();
float strafePenalty = ground ? 1f : Mathf.lerp(1f, unit.type.strafePenalty, Angles.angleDist(unit.vel().angle(), unit.rotation()) / 180f);
float baseSpeed = unit.type.speed;
//limit speed to minimum formation speed to preserve formation
if(unit.isCommanding()){
//add a tiny multiplier to let units catch up just in case
baseSpeed = unit.minFormationSpeed * 0.95f;
}
float speed = unit.realSpeed() * strafePenalty;
float xa = Core.input.axis(Binding.move_x);
@@ -627,9 +620,7 @@ public class DesktopInput extends InputHandler{
if(aimCursor){
unit.lookAt(mouseAngle);
}else{
if(!movement.isZero()){
unit.lookAt(unit.vel.isZero() ? movement.angle() : unit.vel.angle());
}
unit.lookAt(unit.prefRotation());
}
if(omni){

View File

@@ -933,11 +933,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
boolean canMine(Tile tile){
return !Core.scene.hasMouse()
&& tile.drop() != null
&& player.miner().validMine(tile)
&& !(tile.floor().playerUnmineable && tile.overlay().itemDrop == null)
&& player.unit().acceptsItem(tile.drop())
&& tile.block() == Blocks.air;
&& tile.drop() != null
&& player.miner().validMine(tile)
&& !(tile.floor().playerUnmineable && tile.overlay().itemDrop == null)
&& player.unit().acceptsItem(tile.drop())
&& tile.block() == Blocks.air;
}
/** Returns the tile at the specified MOUSE coordinates. */
@@ -1044,7 +1044,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
public boolean canShoot(){
return block == null && !onConfigurable() && !isDroppingItem() && !(player.builder().updateBuilding() && player.builder().isBuilding()) &&
return block == null && !onConfigurable() && !isDroppingItem() && !player.builder().activelyBuilding() &&
!(player.unit() instanceof Mechc && player.unit().isFlying());
}

View File

@@ -856,14 +856,6 @@ public class MobileInput extends InputHandler implements GestureListener{
float attractDst = 15f;
float strafePenalty = legs ? 1f : Mathf.lerp(1f, type.strafePenalty, Angles.angleDist(unit.vel.angle(), unit.rotation) / 180f);
float baseSpeed = unit.type.speed;
//limit speed to minimum formation speed to preserve formation
if(unit.isCommanding()){
//add a tiny multiplier to let units catch up just in case
baseSpeed = unit.minFormationSpeed * 0.98f;
}
float speed = unit.realSpeed() * strafePenalty;
float range = unit.hasWeapons() ? unit.range() : 0f;
float bulletSpeed = unit.hasWeapons() ? type.weapons.first().bullet.speed : 0f;
@@ -873,9 +865,7 @@ public class MobileInput extends InputHandler implements GestureListener{
if(aimCursor){
unit.lookAt(mouseAngle);
}else{
if(unit.moving()){
unit.lookAt(unit.vel.angle());
}
unit.lookAt(unit.prefRotation());
}
if(payloadTarget != null && unit instanceof Payloadc pay){
@@ -905,7 +895,7 @@ public class MobileInput extends InputHandler implements GestureListener{
if(player.within(targetPos, attractDst)){
movement.setZero();
unit.vel.approachDelta(Vec2.ZERO, type.speed * type.accel / 2f);
unit.vel.approachDelta(Vec2.ZERO, unit.speed() * type.accel / 2f);
}
float expansion = 3f;

View File

@@ -30,6 +30,7 @@ public enum LAccess{
team,
type,
flag,
controlled,
name,
config,
payloadCount,

View File

@@ -96,11 +96,13 @@ public class LAssembler{
if(data == null || data.isEmpty()) return new Seq<>();
Seq<LStatement> statements = new Seq<>();
String[] lines = data.split("[;\n]+");
String[] lines = data.split("\n");
int index = 0;
for(String line : lines){
//comments
if(line.startsWith("#")) continue;
//remove trailing semicolons in case someone adds them in for no reason
if(line.endsWith(";")) line = line.substring(0, line.length() - 1);
if(index++ > max) break;

View File

@@ -469,7 +469,7 @@ public class LExecutor{
Building build = exec.building(p1);
int dropped = Math.min(unit.stack.amount, exec.numi(p2));
if(build != null && dropped > 0 && unit.within(build, logicItemTransferRange + build.block.size * tilesize/2f)){
if(build != null && build.isValid() && dropped > 0 && unit.within(build, logicItemTransferRange + build.block.size * tilesize/2f)){
int accepted = build.acceptStack(unit.item(), dropped, unit);
if(accepted > 0){
Call.transferItemTo(unit, unit.item(), accepted, unit.x, unit.y, build);
@@ -483,7 +483,7 @@ public class LExecutor{
Building build = exec.building(p1);
int amount = exec.numi(p3);
if(build != null && build.items != null && exec.obj(p2) instanceof Item item && unit.within(build, logicItemTransferRange + build.block.size * tilesize/2f)){
if(build != null && build.isValid() && build.items != null && exec.obj(p2) instanceof Item item && unit.within(build, logicItemTransferRange + build.block.size * tilesize/2f)){
int taken = Math.min(build.items.get(item), Math.min(amount, unit.maxAccepted(item)));
if(taken > 0){

View File

@@ -12,8 +12,6 @@ import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.*;
import java.io.*;
import static mindustry.Vars.*;
import static mindustry.game.EventType.*;
@@ -449,111 +447,11 @@ public class Administration{
@SuppressWarnings("unchecked")
private void load(){
if(!loadLegacy()){
//load default data
playerInfo = Core.settings.getJson("player-data", ObjectMap.class, ObjectMap::new);
bannedIPs = Core.settings.getJson("ip-bans", Seq.class, Seq::new);
whitelist = Core.settings.getJson("whitelist-ids", Seq.class, Seq::new);
subnetBans = Core.settings.getJson("banned-subnets", Seq.class, Seq::new);
}else{
//save over loaded legacy data
save();
Log.info("Loaded legacy (5.0) server data.");
}
}
private boolean loadLegacy(){
try{
byte[] info = Core.settings.getBytes("player-info");
byte[] ips = Core.settings.getBytes("banned-ips");
byte[] whitelist = Core.settings.getBytes("whitelisted");
byte[] subnet = Core.settings.getBytes("subnet-bans");
if(info != null){
DataInputStream d = new DataInputStream(new ByteArrayInputStream(info));
int size = d.readInt();
if(size != 0){
d.readUTF();
d.readUTF();
for(int i = 0; i < size; i++){
String mapKey = d.readUTF();
PlayerInfo data = new PlayerInfo();
data.id = d.readUTF();
data.lastName = d.readUTF();
data.lastIP = d.readUTF();
int ipsize = d.readInt();
if(ipsize != 0){
d.readUTF();
for(int j = 0; j < ipsize; j++){
data.ips.add(d.readUTF());
}
}
int namesize = d.readInt();
if(namesize != 0){
d.readUTF();
for(int j = 0; j < ipsize; j++){
data.names.add(d.readUTF());
}
}
//ips, names...
data.adminUsid = d.readUTF();
data.timesKicked = d.readInt();
data.timesJoined = d.readInt();
data.banned = d.readBoolean();
data.admin = d.readBoolean();
data.lastKicked = d.readLong();
playerInfo.put(mapKey, data);
}
}
Core.settings.remove("player-info");
}
if(ips != null){
DataInputStream d = new DataInputStream(new ByteArrayInputStream(ips));
int size = d.readInt();
if(size != 0){
d.readUTF();
for(int i = 0; i < size; i++){
bannedIPs.add(d.readUTF());
}
}
Core.settings.remove("banned-ips");
}
if(whitelist != null){
DataInputStream d = new DataInputStream(new ByteArrayInputStream(whitelist));
int size = d.readInt();
if(size != 0){
d.readUTF();
for(int i = 0; i < size; i++){
this.whitelist.add(d.readUTF());
}
}
Core.settings.remove("whitelisted");
}
if(subnet != null){
DataInputStream d = new DataInputStream(new ByteArrayInputStream(subnet));
int size = d.readInt();
if(size != 0){
d.readUTF();
for(int i = 0; i < size; i++){
subnetBans.add(d.readUTF());
}
}
Core.settings.remove("subnet-bans");
}
return info != null || ips != null || whitelist != null || subnet != null;
}catch(Throwable t){
Log.err(t);
}
return false;
//load default data
playerInfo = Core.settings.getJson("player-data", ObjectMap.class, ObjectMap::new);
bannedIPs = Core.settings.getJson("ip-bans", Seq.class, Seq::new);
whitelist = Core.settings.getJson("whitelist-ids", Seq.class, Seq::new);
subnetBans = Core.settings.getJson("banned-subnets", Seq.class, Seq::new);
}
/** Server configuration definition. Each config value can be a string, boolean or number. */
@@ -584,8 +482,7 @@ public class Administration{
autosaveAmount("The maximum amount of autosaves. Older ones get replaced.", 10),
autosaveSpacing("Spacing between autosaves in seconds.", 60 * 5),
debug("Enable debug logging", false, () -> {
LogLevel level = debug() ? LogLevel.debug : LogLevel.info;
Log.level = level;
Log.level = debug() ? LogLevel.debug : LogLevel.info;
});
public static final Config[] all = values();

View File

@@ -0,0 +1,6 @@
package mindustry.net;
public class ServerGroup{
public String[] addresses;
public String name;
}

View File

@@ -55,6 +55,12 @@ public class ItemSeq implements Iterable<ItemStack>, Serializable{
return out;
}
public void min(int number){
for(Item item : Vars.content.items()){
set(item, Math.min(get(item), number));
}
}
public boolean has(Item item){
return values[item.id] > 0;
}

View File

@@ -81,6 +81,8 @@ public class UnitType extends UnlockableContent{
public AmmoType ammoType = AmmoTypes.copper;
public int mineTier = -1;
public float buildSpeed = 1f, mineSpeed = 1f;
public Sound mineSound = Sounds.minebeam;
public float mineSoundVolume = 0.6f;
/** This is a VERY ROUGH estimate of unit DPS. */
public float dpsEstimate = -1;

View File

@@ -62,6 +62,8 @@ public class Weapon{
public float shootCone = 5f;
/** ticks to cool down the heat region */
public float cooldownTime = 20f;
/** random sound pitch range */
public float soundPitchMin = 0.8f, soundPitchMax = 1f;
/** whether shooter rotation is ignored when shooting. */
public boolean ignoreRotation = false;
/** min velocity required for this weapon to shoot */

View File

@@ -1,12 +1,14 @@
package mindustry.type;
import arc.*;
import arc.audio.*;
import arc.func.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
import arc.util.*;
import arc.util.noise.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.ctype.*;
@@ -22,6 +24,9 @@ public abstract class Weather extends UnlockableContent{
public float duration = 9f * Time.toMinutes;
public float opacityMultiplier = 1f;
public Attributes attrs = new Attributes();
public Sound sound = Sounds.none;
public float soundVol = 0.1f, soundVolMin = 0f;
public float soundVolOscMag = 0f, soundVolOscScl = 20f;
//internals
public Rand rand = new Rand();
@@ -83,6 +88,11 @@ public abstract class Weather extends UnlockableContent{
state.effectTimer -= Time.delta;
}
}
if(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));
}
}
public void drawOver(WeatherState state){

View File

@@ -42,6 +42,13 @@ public class LaunchLoadoutDialog extends BaseDialog{
//updates sum requirements
Runnable update = () -> {
int cap = selected.findCore().itemCapacity;
//cap resources based on core type
ItemSeq resources = universe.getLaunchResources();
resources.min(cap);
universe.updateLaunchResources(resources);
total.clear();
selected.requirements().each(total::add);
universe.getLaunchResources().each(total::add);
@@ -79,7 +86,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
ItemSeq stacks = universe.getLaunchResources();
Seq<ItemStack> out = stacks.toSeq();
loadout.show(core.itemCapacity, out, UnlockableContent::unlocked, out::clear, () -> {}, () -> {
loadout.show(selected.findCore().itemCapacity, out, UnlockableContent::unlocked, out::clear, () -> {}, () -> {
universe.updateLaunchResources(new ItemSeq(out));
update.run();
rebuildItems.run();

View File

@@ -174,14 +174,14 @@ public class Block extends UnlockableContent{
public float lightRadius = 60f;
/** The sound that this block makes while active. One sound loop. Do not overuse.*/
public Sound activeSound = Sounds.none;
public Sound loopSound = Sounds.none;
/** Active sound base volume. */
public float activeSoundVolume = 0.5f;
public float loopSoundVolume = 0.5f;
/** The sound that this block makes while idle. Uses one sound loop for all blocks.*/
public Sound idleSound = Sounds.none;
public Sound ambientSound = Sounds.none;
/** Idle sound base volume. */
public float idleSoundVolume = 0.5f;
public float ambientSoundVolume = 0.05f;
/** Cost of constructing this block. */
public ItemStack[] requirements = {};

View File

@@ -51,6 +51,8 @@ public class ForceProjector extends Block{
hasPower = true;
hasLiquids = true;
hasItems = true;
ambientSound = Sounds.shield;
ambientSoundVolume = 0.08f;
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.1f)).boost().update(false);
}
@@ -107,6 +109,11 @@ public class ForceProjector extends Block{
drawer.add();
}
@Override
public boolean shouldAmbientSound(){
return !broken && realRadius() > 1f;
}
@Override
public void onRemoved(){
super.onRemoved();

View File

@@ -25,7 +25,7 @@ public class LiquidTurret extends Turret{
super(name);
acceptCoolant = false;
hasLiquids = true;
activeSound = Sounds.spray;
loopSound = Sounds.spray;
}
/** Initializes accepted ammo map. Format: [liquid1, bullet1, liquid2, bullet2...] */

View File

@@ -1,5 +1,6 @@
package mindustry.world.blocks.defense.turrets;
import arc.audio.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
@@ -24,6 +25,8 @@ public class PointDefenseTurret extends ReloadTurret{
public Effect hitEffect = Fx.pointHit;
public Effect shootEffect = Fx.sparkShoot;
public Sound shootSound = Sounds.lasershoot;
public float shootCone = 5f;
public float bulletDamage = 10f;
public float shootLength = 3f;
@@ -90,6 +93,7 @@ public class PointDefenseTurret extends ReloadTurret{
beamEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, color, new Vec2().set(target));
shootEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, color);
hitEffect.at(target.x, target.y, color);
shootSound.at(x + Tmp.v1.x, y + Tmp.v1.y, Mathf.random(0.9f, 1.1f));
reload = 0;
}
}else{

View File

@@ -1,5 +1,6 @@
package mindustry.world.blocks.defense.turrets;
import arc.audio.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
@@ -34,6 +35,9 @@ public class TractorBeamTurret extends BaseTurret{
public StatusEffect status = StatusEffects.none;
public float statusDuration = 300;
public Sound shootSound = Sounds.tractorbeam;
public float shootSoundVolume = 0.9f;
public TractorBeamTurret(String name){
super(name);
@@ -91,6 +95,8 @@ 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);
any = true;
float dest = angleTo(target);
rotation = Angles.moveToward(rotation, dest, rotateSpeed * edelta());

View File

@@ -50,6 +50,7 @@ public abstract class Turret extends ReloadTurret{
public float recoilAmount = 1f;
public float restitution = 0.02f;
public float cooldown = 0.02f;
public float coolantUsage = 0.2f;
public float shootCone = 8f;
public float shootShake = 0f;
public float xRand = 0f;
@@ -109,7 +110,7 @@ public abstract class Turret extends ReloadTurret{
public void init(){
if(acceptCoolant && !consumes.has(ConsumeType.liquid)){
hasLiquids = true;
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.2f)).update(false).boost();
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, coolantUsage)).update(false).boost();
}
super.init();

View File

@@ -41,8 +41,8 @@ public class Conveyor extends Block implements Autotiler{
itemCapacity = 4;
conveyorPlacement = true;
idleSound = Sounds.conveyor;
idleSoundVolume = 0.004f;
ambientSound = Sounds.conveyor;
ambientSoundVolume = 0.0015f;
unloadable = false;
noUpdateDisabled = false;
}
@@ -161,7 +161,7 @@ public class Conveyor extends Block implements Autotiler{
}
@Override
public boolean shouldIdleSound(){
public boolean shouldAmbientSound(){
return clogHeat <= 0.5f;
}

View File

@@ -44,8 +44,8 @@ public class StackConveyor extends Block implements Autotiler{
itemCapacity = 10;
conveyorPlacement = true;
idleSound = Sounds.conveyor;
idleSoundVolume = 0.004f;
ambientSound = Sounds.conveyor;
ambientSoundVolume = 0.004f;
unloadable = false;
}
@@ -231,7 +231,7 @@ public class StackConveyor extends Block implements Autotiler{
}
@Override
public boolean shouldIdleSound(){
public boolean shouldAmbientSound(){
return false; // has no moving parts;
}

View File

@@ -1,6 +1,7 @@
package mindustry.world.blocks.environment;
import arc.*;
import arc.audio.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.graphics.g2d.TextureAtlas.*;
@@ -10,6 +11,7 @@ import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.graphics.MultiPacker.*;
import mindustry.type.*;
@@ -33,7 +35,11 @@ public class Floor extends Block{
/** How many ticks it takes to drown on this. */
public float drownTime = 0f;
/** Effect when walking on this floor. */
public Effect walkEffect = Fx.ripple;
public Effect walkEffect = Fx.none;
/** Sound made when walking. */
public Sound walkSound = Sounds.none;
/** Volume of sound made when walking. */
public float walkSoundVolume = 0.1f, walkSoundPitchMin = 0.8f, walkSoundPitchMax = 1.2f;
/** Effect displayed when drowning on this floor. */
public Effect drownUpdateEffect = Fx.bubble;
/** Status effect applied when walking on. */
@@ -115,6 +121,14 @@ public class Floor extends Block{
if(decoration == Blocks.air){
decoration = content.blocks().min(b -> b instanceof Boulder && b.breakable ? mapColor.diff(b.mapColor) : Float.POSITIVE_INFINITY);
}
if(isLiquid && walkEffect == Fx.none){
walkEffect = Fx.ripple;
}
if(isLiquid && walkSound == Sounds.none){
walkSound = Sounds.splash;
}
}
@Override

View File

@@ -91,6 +91,11 @@ public class ImpactReactor extends PowerGenerator{
productionEfficiency = Mathf.pow(warmup, 5f);
}
@Override
public float ambientVolume(){
return warmup;
}
@Override
public void draw(){
Draw.rect(bottomRegion, x, y);

View File

@@ -66,8 +66,8 @@ public class Drill extends Block{
hasLiquids = true;
liquidCapacity = 5f;
hasItems = true;
idleSound = Sounds.drill;
idleSoundVolume = 0.003f;
ambientSound = Sounds.drill;
ambientSoundVolume = 0.016f;
}
@Override
@@ -205,8 +205,8 @@ public class Drill extends Block{
}
@Override
public boolean shouldIdleSound(){
return efficiency() > 0.01f;
public boolean shouldAmbientSound(){
return efficiency() > 0.01f && items.total() < itemCapacity;
}
@Override

View File

@@ -9,7 +9,6 @@ import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.consumers.*;
import mindustry.world.draw.*;
import mindustry.world.meta.*;
@@ -29,9 +28,9 @@ public class GenericCrafter extends Block{
update = true;
solid = true;
hasItems = true;
idleSound = Sounds.machine;
ambientSound = Sounds.machine;
sync = true;
idleSoundVolume = 0.03f;
ambientSoundVolume = 0.03f;
flags = EnumSet.of(BlockFlag.factory);
}
@@ -137,7 +136,7 @@ public class GenericCrafter extends Block{
}
@Override
public boolean shouldIdleSound(){
public boolean shouldAmbientSound(){
return cons.valid();
}

View File

@@ -5,6 +5,7 @@ import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.gen.*;
import mindustry.graphics.*;
/** A GenericCrafter with a new glowing region drawn on top. */
@@ -14,6 +15,8 @@ public class GenericSmelter extends GenericCrafter{
public GenericSmelter(String name){
super(name);
ambientSound = Sounds.smelter;
ambientSoundVolume = 0.06f;
}
public class SmelterBuild extends GenericCrafterBuild{

View File

@@ -52,7 +52,7 @@ public class Separator extends Block{
public float warmup;
@Override
public boolean shouldIdleSound(){
public boolean shouldAmbientSound(){
return cons.valid();
}

View File

@@ -50,8 +50,8 @@ public class CoreBlock extends StorageBlock{
priority = TargetPriority.core;
flags = EnumSet.of(BlockFlag.core, BlockFlag.unitModifier);
unitCapModifier = 10;
activeSound = Sounds.respawning;
activeSoundVolume = 1f;
loopSound = Sounds.respawning;
loopSoundVolume = 1f;
group = BlockGroup.none;
}