Merge branch 'master' of https://github.com/Anuken/Mindustry into tsunami
Conflicts: core/assets/sprites/block_colors.png core/assets/sprites/fallback/sprites.atlas core/assets/sprites/fallback/sprites.png core/assets/sprites/fallback/sprites2.png core/assets/sprites/fallback/sprites3.png core/assets/sprites/fallback/sprites4.png core/assets/sprites/fallback/sprites5.png core/assets/sprites/fallback/sprites7.png core/assets/sprites/fallback/sprites8.png core/assets/sprites/sprites.atlas core/assets/sprites/sprites.png core/assets/sprites/sprites2.png core/assets/sprites/sprites4.png core/assets/sprites/sprites5.png
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -19,7 +19,7 @@ assignees: ''
|
|||||||
|
|
||||||
**Link(s) to mod(s) used**: *The mod repositories or zip files that are related to the issue, if applicable.*
|
**Link(s) to mod(s) used**: *The mod repositories or zip files that are related to the issue, if applicable.*
|
||||||
|
|
||||||
**Save file**: *The save file you were playing on when the bug happened, if applicable.*
|
**Save file**: *The save file you were playing on when the bug happened. REQUIRED for any issue that happens in-game.*
|
||||||
|
|
||||||
**Crash report**: *The contents of relevant crash report files. REQUIRED if you are reporting a crash.*
|
**Crash report**: *The contents of relevant crash report files. REQUIRED if you are reporting a crash.*
|
||||||
|
|
||||||
|
|||||||
@@ -70,3 +70,7 @@ Post feature requests and feedback [here](https://github.com/Anuken/Mindustry-Su
|
|||||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
||||||
alt="Get it on F-Droid"
|
alt="Get it on F-Droid"
|
||||||
height="80">](https://f-droid.org/packages/io.anuke.mindustry/)
|
height="80">](https://f-droid.org/packages/io.anuke.mindustry/)
|
||||||
|
|
||||||
|
[<img src="https://flathub.org/assets/badges/flathub-badge-en.svg"
|
||||||
|
alt="Download On Flathub"
|
||||||
|
height="60">](https://flathub.org/apps/details/com.github.Anuken.Mindustry)
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import android.content.pm.*;
|
|||||||
import android.net.*;
|
import android.net.*;
|
||||||
import android.os.Build.*;
|
import android.os.Build.*;
|
||||||
import android.os.*;
|
import android.os.*;
|
||||||
import android.provider.Settings.*;
|
|
||||||
import android.telephony.*;
|
import android.telephony.*;
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.backend.android.*;
|
import arc.backend.android.*;
|
||||||
@@ -15,7 +14,7 @@ import arc.files.*;
|
|||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import arc.util.serialization.*;
|
import dalvik.system.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.game.Saves.*;
|
import mindustry.game.Saves.*;
|
||||||
import mindustry.io.*;
|
import mindustry.io.*;
|
||||||
@@ -23,7 +22,6 @@ import mindustry.net.*;
|
|||||||
import mindustry.ui.dialogs.*;
|
import mindustry.ui.dialogs.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.System;
|
|
||||||
import java.lang.Thread.*;
|
import java.lang.Thread.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -73,12 +71,25 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
public void shareFile(Fi file){
|
public void shareFile(Fi file){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> loadJar(Fi jar, String mainClass) throws Exception{
|
||||||
|
DexClassLoader loader = new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, getClassLoader());
|
||||||
|
return Class.forName(mainClass, true, loader);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showFileChooser(boolean open, String extension, Cons<Fi> cons){
|
public void showFileChooser(boolean open, String extension, Cons<Fi> cons){
|
||||||
|
showFileChooser(open, cons, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showFileChooser(boolean open, Cons<Fi> cons, String... extensions){
|
||||||
|
String extension = extensions[0];
|
||||||
|
|
||||||
if(VERSION.SDK_INT >= VERSION_CODES.Q){
|
if(VERSION.SDK_INT >= VERSION_CODES.Q){
|
||||||
Intent intent = new Intent(open ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_CREATE_DOCUMENT);
|
Intent intent = new Intent(open ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_CREATE_DOCUMENT);
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
intent.setType(extension.equals("zip") && !open ? "application/zip" : "*/*");
|
intent.setType(extension.equals("zip") && !open && extensions.length == 1 ? "application/zip" : "*/*");
|
||||||
|
|
||||||
addResultListener(i -> startActivityForResult(intent, i), (code, in) -> {
|
addResultListener(i -> startActivityForResult(intent, i), (code, in) -> {
|
||||||
if(code == Activity.RESULT_OK && in != null && in.getData() != null){
|
if(code == Activity.RESULT_OK && in != null && in.getData() != null){
|
||||||
Uri uri = in.getData();
|
Uri uri = in.getData();
|
||||||
@@ -108,7 +119,7 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
});
|
});
|
||||||
}else if(VERSION.SDK_INT >= VERSION_CODES.M && !(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
|
}else if(VERSION.SDK_INT >= VERSION_CODES.M && !(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
|
||||||
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
|
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
|
||||||
chooser = new FileChooser(open ? "@open" : "@save", file -> file.extension().equalsIgnoreCase(extension), open, file -> {
|
chooser = new FileChooser(open ? "@open" : "@save", file -> Structs.contains(extensions, file.extension().toLowerCase()), open, file -> {
|
||||||
if(!open){
|
if(!open){
|
||||||
cons.get(file.parent().child(file.nameWithoutExtension() + "." + extension));
|
cons.get(file.parent().child(file.nameWithoutExtension() + "." + extension));
|
||||||
}else{
|
}else{
|
||||||
@@ -124,10 +135,19 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
perms.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
perms.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||||
}
|
}
|
||||||
requestPermissions(perms.toArray(new String[0]), PERMISSION_REQUEST_CODE);
|
requestPermissions(perms.toArray(new String[0]), PERMISSION_REQUEST_CODE);
|
||||||
|
}else{
|
||||||
|
if(open){
|
||||||
|
new FileChooser("@open", file -> Structs.contains(extensions, file.extension().toLowerCase()), true, cons).show();
|
||||||
}else{
|
}else{
|
||||||
super.showFileChooser(open, extension, cons);
|
super.showFileChooser(open, extension, cons);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showMultiFileChooser(Cons<Fi> cons, String... extensions){
|
||||||
|
showFileChooser(true, cons, extensions);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginForceLandscape(){
|
public void beginForceLandscape(){
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class LogicStatementProcessor extends BaseProcessor{
|
|||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
for(Svar field : fields){
|
for(Svar field : fields){
|
||||||
if(field.is(Modifier.TRANSIENT)) continue;
|
if(field.isAny(Modifier.TRANSIENT, Modifier.STATIC)) continue;
|
||||||
|
|
||||||
writer.addStatement("out.append(\" \")");
|
writer.addStatement("out.append(\" \")");
|
||||||
writer.addStatement("out.append((($T)obj).$L$L)", c.mirror(), field.name(),
|
writer.addStatement("out.append((($T)obj).$L$L)", c.mirror(), field.name(),
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 230 B After Width: | Height: | Size: 277 B |
|
Before Width: | Height: | Size: 229 B After Width: | Height: | Size: 277 B |
|
Before Width: | Height: | Size: 231 B After Width: | Height: | Size: 283 B |
|
Before Width: | Height: | Size: 226 B After Width: | Height: | Size: 278 B |
|
Before Width: | Height: | Size: 298 B After Width: | Height: | Size: 491 B |
|
Before Width: | Height: | Size: 309 B After Width: | Height: | Size: 499 B |
|
Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 522 B |
|
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 515 B |
|
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 300 B |
|
Before Width: | Height: | Size: 252 B After Width: | Height: | Size: 292 B |
|
Before Width: | Height: | Size: 250 B After Width: | Height: | Size: 294 B |
|
Before Width: | Height: | Size: 261 B After Width: | Height: | Size: 299 B |
|
Before Width: | Height: | Size: 247 B After Width: | Height: | Size: 296 B |
|
Before Width: | Height: | Size: 243 B After Width: | Height: | Size: 290 B |
|
Before Width: | Height: | Size: 234 B After Width: | Height: | Size: 289 B |
|
Before Width: | Height: | Size: 237 B After Width: | Height: | Size: 292 B |
|
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 375 B |
|
Before Width: | Height: | Size: 247 B After Width: | Height: | Size: 408 B |
|
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 419 B |
|
Before Width: | Height: | Size: 245 B After Width: | Height: | Size: 409 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 640 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 636 B |
|
Before Width: | Height: | Size: 245 B After Width: | Height: | Size: 410 B |
|
Before Width: | Height: | Size: 265 B After Width: | Height: | Size: 441 B |
|
Before Width: | Height: | Size: 280 B After Width: | Height: | Size: 454 B |
|
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 448 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 330 B After Width: | Height: | Size: 376 B |
|
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 490 B |
|
Before Width: | Height: | Size: 189 B After Width: | Height: | Size: 304 B |
|
Before Width: | Height: | Size: 763 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 812 B After Width: | Height: | Size: 1.1 KiB |
BIN
core/assets-raw/sprites/blocks/turrets/wave-top.png
Normal file
|
After Width: | Height: | Size: 285 B |
|
Before Width: | Height: | Size: 427 B After Width: | Height: | Size: 660 B |
|
Before Width: | Height: | Size: 546 B After Width: | Height: | Size: 843 B |
|
Before Width: | Height: | Size: 244 B After Width: | Height: | Size: 323 B |
|
Before Width: | Height: | Size: 602 B After Width: | Height: | Size: 796 B |
|
Before Width: | Height: | Size: 226 B After Width: | Height: | Size: 323 B |
|
Before Width: | Height: | Size: 428 B After Width: | Height: | Size: 655 B |
|
Before Width: | Height: | Size: 890 B After Width: | Height: | Size: 908 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 589 B After Width: | Height: | Size: 586 B |
|
Before Width: | Height: | Size: 815 B After Width: | Height: | Size: 812 B |
|
Before Width: | Height: | Size: 527 KiB After Width: | Height: | Size: 563 KiB |
|
Before Width: | Height: | Size: 640 KiB After Width: | Height: | Size: 668 KiB |
|
Before Width: | Height: | Size: 908 KiB After Width: | Height: | Size: 968 KiB |
|
Before Width: | Height: | Size: 461 KiB After Width: | Height: | Size: 506 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 409 KiB After Width: | Height: | Size: 419 KiB |
|
Before Width: | Height: | Size: 319 KiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 2.9 MiB |
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 190 KiB |
|
Before Width: | Height: | Size: 407 KiB After Width: | Height: | Size: 419 KiB |
|
Before Width: | Height: | Size: 307 KiB After Width: | Height: | Size: 1.4 MiB |
@@ -63,7 +63,7 @@ public class Vars implements Loadable{
|
|||||||
/** URL to the JSON file containing all the BE servers. Only queried in the V6 alpha (will be removed once it's out). */
|
/** URL to the JSON file containing all the BE servers. Only queried in the V6 alpha (will be removed once it's out). */
|
||||||
public static final String serverJsonV6URL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_v6.json";
|
public static final String serverJsonV6URL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_v6.json";
|
||||||
/** URL of the github issue report template.*/
|
/** URL of the github issue report template.*/
|
||||||
public static final String reportIssueURL = "https://github.com/Anuken/Mindustry/issues/new?template=bug_report.md";
|
public static final String reportIssueURL = "https://github.com/Anuken/Mindustry/issues/new?labels=bug&template=bug_report.md";
|
||||||
/** list of built-in servers.*/
|
/** list of built-in servers.*/
|
||||||
public static final Seq<String> defaultServers = Seq.with();
|
public static final Seq<String> defaultServers = Seq.with();
|
||||||
/** maximum distance between mine and core that supports automatic transferring */
|
/** maximum distance between mine and core that supports automatic transferring */
|
||||||
@@ -72,8 +72,6 @@ public class Vars implements Loadable{
|
|||||||
public static final int maxTextLength = 150;
|
public static final int maxTextLength = 150;
|
||||||
/** max player name length in bytes */
|
/** max player name length in bytes */
|
||||||
public static final int maxNameLength = 40;
|
public static final int maxNameLength = 40;
|
||||||
/** shadow color for turrets */
|
|
||||||
public static final float turretShadowColor = Color.toFloatBits(0, 0, 0, 0.22f);
|
|
||||||
/** displayed item size when ingame. */
|
/** displayed item size when ingame. */
|
||||||
public static final float itemSize = 5f;
|
public static final float itemSize = 5f;
|
||||||
/** units outside of this bound will die instantly */
|
/** units outside of this bound will die instantly */
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class Pathfinder implements Runnable{
|
|||||||
PathTile.health(tile) * 5 +
|
PathTile.health(tile) * 5 +
|
||||||
(PathTile.nearSolid(tile) ? 2 : 0) +
|
(PathTile.nearSolid(tile) ? 2 : 0) +
|
||||||
(PathTile.nearLiquid(tile) ? 6 : 0) +
|
(PathTile.nearLiquid(tile) ? 6 : 0) +
|
||||||
(PathTile.deep(tile) ? 70 : 0) +
|
(PathTile.deep(tile) ? 6000 : 0) +
|
||||||
(PathTile.damages(tile) ? 30 : 0),
|
(PathTile.damages(tile) ? 30 : 0),
|
||||||
|
|
||||||
//legs
|
//legs
|
||||||
@@ -116,7 +116,7 @@ public class Pathfinder implements Runnable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return PathTile.get(
|
return PathTile.get(
|
||||||
tile.build == null ? 0 : Math.min((int)(tile.build.health / 40), 127),
|
tile.build == null ? 0 : Math.min((int)(tile.build.health / 40), 80),
|
||||||
tile.getTeamID(),
|
tile.getTeamID(),
|
||||||
tile.solid(),
|
tile.solid(),
|
||||||
tile.floor().isLiquid,
|
tile.floor().isLiquid,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class FlyingAI extends AIController{
|
|||||||
moveTo(target, unit.range() * 0.8f);
|
moveTo(target, unit.range() * 0.8f);
|
||||||
unit.lookAt(target);
|
unit.lookAt(target);
|
||||||
}else{
|
}else{
|
||||||
attack(80f);
|
attack(100f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class GroundAI extends AIController{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(unit.type().canBoost && unit.canPassOn()){
|
if(unit.type().canBoost && unit.tileOn() != null && !unit.tileOn().solid()){
|
||||||
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f);
|
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -208,6 +208,11 @@ public class Blocks implements ContentList{
|
|||||||
liquidDrop = Liquids.slag;
|
liquidDrop = Liquids.slag;
|
||||||
isLiquid = true;
|
isLiquid = true;
|
||||||
cacheLayer = CacheLayer.slag;
|
cacheLayer = CacheLayer.slag;
|
||||||
|
attributes.set(Attribute.heat, 0.85f);
|
||||||
|
|
||||||
|
emitLight = true;
|
||||||
|
lightRadius = 40f;
|
||||||
|
lightColor = Color.orange.cpy().a(0.38f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
stone = new Floor("stone");
|
stone = new Floor("stone");
|
||||||
@@ -242,7 +247,7 @@ public class Blocks implements ContentList{
|
|||||||
blendGroup = basalt;
|
blendGroup = basalt;
|
||||||
|
|
||||||
emitLight = true;
|
emitLight = true;
|
||||||
lightRadius = 60f;
|
lightRadius = 50f;
|
||||||
lightColor = Color.orange.cpy().a(0.3f);
|
lightColor = Color.orange.cpy().a(0.3f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -865,7 +870,8 @@ public class Blocks implements ContentList{
|
|||||||
size = 2;
|
size = 2;
|
||||||
reload = 250f;
|
reload = 250f;
|
||||||
range = 85f;
|
range = 85f;
|
||||||
healPercent = 14f;
|
healPercent = 11f;
|
||||||
|
phaseBoost = 15f;
|
||||||
health = 80 * size * size;
|
health = 80 * size * size;
|
||||||
consumes.item(Items.phasefabric).boost();
|
consumes.item(Items.phasefabric).boost();
|
||||||
}};
|
}};
|
||||||
@@ -1142,6 +1148,7 @@ public class Blocks implements ContentList{
|
|||||||
powerProduction = 1.8f;
|
powerProduction = 1.8f;
|
||||||
generateEffect = Fx.redgeneratespark;
|
generateEffect = Fx.redgeneratespark;
|
||||||
size = 2;
|
size = 2;
|
||||||
|
floating = true;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
steamGenerator = new BurnerGenerator("steam-generator"){{
|
steamGenerator = new BurnerGenerator("steam-generator"){{
|
||||||
@@ -1771,6 +1778,7 @@ public class Blocks implements ContentList{
|
|||||||
};
|
};
|
||||||
size = 3;
|
size = 3;
|
||||||
consumes.power(1.2f);
|
consumes.power(1.2f);
|
||||||
|
floating = true;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
additiveReconstructor = new Reconstructor("additive-reconstructor"){{
|
additiveReconstructor = new Reconstructor("additive-reconstructor"){{
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ public class UnitTypes implements ContentList{
|
|||||||
continuous = true;
|
continuous = true;
|
||||||
cooldownTime = 200f;
|
cooldownTime = 200f;
|
||||||
|
|
||||||
bullet = new ContinuousLaserBulletType(17){{
|
bullet = new ContinuousLaserBulletType(20){{
|
||||||
length = 150f;
|
length = 150f;
|
||||||
hitEffect = Fx.hitMeltHeal;
|
hitEffect = Fx.hitMeltHeal;
|
||||||
drawSize = 420f;
|
drawSize = 420f;
|
||||||
@@ -430,7 +430,7 @@ public class UnitTypes implements ContentList{
|
|||||||
|
|
||||||
shootEffect = Fx.greenLaserChargeSmall;
|
shootEffect = Fx.greenLaserChargeSmall;
|
||||||
|
|
||||||
incendChance = 0.02f;
|
incendChance = 0.05f;
|
||||||
incendSpread = 5f;
|
incendSpread = 5f;
|
||||||
incendAmount = 1;
|
incendAmount = 1;
|
||||||
|
|
||||||
@@ -489,7 +489,7 @@ public class UnitTypes implements ContentList{
|
|||||||
|
|
||||||
bullet = new LaserBulletType(){{
|
bullet = new LaserBulletType(){{
|
||||||
length = 500f;
|
length = 500f;
|
||||||
damage = 520f;
|
damage = 550f;
|
||||||
width = 75f;
|
width = 75f;
|
||||||
|
|
||||||
lifetime = 65f;
|
lifetime = 65f;
|
||||||
@@ -885,7 +885,7 @@ public class UnitTypes implements ContentList{
|
|||||||
weapons.add(new Weapon(){{
|
weapons.add(new Weapon(){{
|
||||||
y = 0f;
|
y = 0f;
|
||||||
x = 2f;
|
x = 2f;
|
||||||
reload = 15f;
|
reload = 13f;
|
||||||
ejectEffect = Fx.shellEjectSmall;
|
ejectEffect = Fx.shellEjectSmall;
|
||||||
bullet = Bullets.standardCopper;
|
bullet = Bullets.standardCopper;
|
||||||
shootSound = Sounds.shoot;
|
shootSound = Sounds.shoot;
|
||||||
@@ -935,7 +935,7 @@ public class UnitTypes implements ContentList{
|
|||||||
drag = 0.016f;
|
drag = 0.016f;
|
||||||
flying = true;
|
flying = true;
|
||||||
range = 140f;
|
range = 140f;
|
||||||
hitSize = 18f;
|
hitSize = 20f;
|
||||||
lowAltitude = true;
|
lowAltitude = true;
|
||||||
armor = 5f;
|
armor = 5f;
|
||||||
|
|
||||||
|
|||||||
@@ -170,12 +170,13 @@ public class Weathers implements ContentList{
|
|||||||
sandstorm = new Weather("sandstorm"){
|
sandstorm = new Weather("sandstorm"){
|
||||||
TextureRegion region;
|
TextureRegion region;
|
||||||
float size = 140f, padding = size, invDensity = 1500f, baseSpeed = 6.1f;
|
float size = 140f, padding = size, invDensity = 1500f, baseSpeed = 6.1f;
|
||||||
float force = 0.45f;
|
float force = 0.4f * 0;
|
||||||
Color color = Color.valueOf("f7cba4");
|
Color color = Color.valueOf("f7cba4");
|
||||||
Texture noise;
|
Texture noise;
|
||||||
|
|
||||||
{
|
{
|
||||||
attrs.set(Attribute.light, -0.1f);
|
attrs.set(Attribute.light, -0.1f);
|
||||||
|
opacityMultiplier = 0.8f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -250,7 +251,7 @@ public class Weathers implements ContentList{
|
|||||||
|
|
||||||
sporestorm = new Weather("sporestorm"){
|
sporestorm = new Weather("sporestorm"){
|
||||||
TextureRegion region;
|
TextureRegion region;
|
||||||
float size = 5f, padding = size, invDensity = 2000f, baseSpeed = 4.3f, force = 0.28f;
|
float size = 5f, padding = size, invDensity = 2000f, baseSpeed = 4.3f, force = 0.28f * 0;
|
||||||
Color color = Color.valueOf("7457ce");
|
Color color = Color.valueOf("7457ce");
|
||||||
Texture noise;
|
Texture noise;
|
||||||
|
|
||||||
@@ -259,6 +260,7 @@ public class Weathers implements ContentList{
|
|||||||
attrs.set(Attribute.light, -0.15f);
|
attrs.set(Attribute.light, -0.15f);
|
||||||
status = StatusEffects.sporeSlowed;
|
status = StatusEffects.sporeSlowed;
|
||||||
statusGround = false;
|
statusGround = false;
|
||||||
|
opacityMultiplier = 0.85f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class GameState{
|
|||||||
|
|
||||||
/** @return whether the player is in a campaign and they are out of sector time */
|
/** @return whether the player is in a campaign and they are out of sector time */
|
||||||
public boolean isOutOfTime(){
|
public boolean isOutOfTime(){
|
||||||
return isCampaign() && isGame() && getSector().getTimeSpent() >= turnDuration;
|
return isCampaign() && isGame() && getSector().getTimeSpent() >= turnDuration && !net.active();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasSector(){
|
public boolean hasSector(){
|
||||||
|
|||||||
@@ -14,10 +14,18 @@ import mindustry.type.*;
|
|||||||
import mindustry.ui.dialogs.*;
|
import mindustry.ui.dialogs.*;
|
||||||
import rhino.*;
|
import rhino.*;
|
||||||
|
|
||||||
|
import java.net.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public interface Platform{
|
public interface Platform{
|
||||||
|
|
||||||
|
/** Dynamically loads a jar file. */
|
||||||
|
default Class<?> loadJar(Fi jar, String mainClass) throws Exception{
|
||||||
|
URLClassLoader classLoader = new URLClassLoader(new URL[]{jar.file().toURI().toURL()}, ClassLoader.getSystemClassLoader());
|
||||||
|
return classLoader.loadClass(mainClass);
|
||||||
|
}
|
||||||
|
|
||||||
/** Steam: Update lobby visibility.*/
|
/** Steam: Update lobby visibility.*/
|
||||||
default void updateLobby(){}
|
default void updateLobby(){}
|
||||||
|
|
||||||
@@ -121,7 +129,7 @@ public interface Platform{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a file chooser for multiple file types. Only supported on desktop.
|
* Show a file chooser for multiple file types.
|
||||||
* @param cons Selection listener
|
* @param cons Selection listener
|
||||||
* @param extensions File extensions to filter
|
* @param extensions File extensions to filter
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ public class EditorTile extends Tile{
|
|||||||
|
|
||||||
Block block = block();
|
Block block = block();
|
||||||
|
|
||||||
if(block.hasEntity()){
|
if(block.hasBuilding()){
|
||||||
build = entityprov.get().init(this, team, false, rotation);
|
build = entityprov.get().init(this, team, false, rotation);
|
||||||
build.cons = new ConsumeModule(build);
|
build.cons = new ConsumeModule(build);
|
||||||
if(block.hasItems) build.items = new ItemModule();
|
if(block.hasItems) build.items = new ItemModule();
|
||||||
|
|||||||
@@ -257,6 +257,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
player.set(world.width() * tilesize/2f, world.height() * tilesize/2f);
|
player.set(world.width() * tilesize/2f, world.height() * tilesize/2f);
|
||||||
player.clearUnit();
|
player.clearUnit();
|
||||||
Groups.unit.clear();
|
Groups.unit.clear();
|
||||||
|
Groups.build.clear();
|
||||||
logic.play();
|
logic.play();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ public abstract class BulletType extends Content{
|
|||||||
//additional effects
|
//additional effects
|
||||||
|
|
||||||
public float fragCone = 360f;
|
public float fragCone = 360f;
|
||||||
|
public float fragAngle = 0f;
|
||||||
public int fragBullets = 9;
|
public int fragBullets = 9;
|
||||||
public float fragVelocityMin = 0.2f, fragVelocityMax = 1f, fragLifeMin = 1f, fragLifeMax = 1f;
|
public float fragVelocityMin = 0.2f, fragVelocityMax = 1f, fragLifeMin = 1f, fragLifeMax = 1f;
|
||||||
public BulletType fragBullet = null;
|
public BulletType fragBullet = null;
|
||||||
@@ -101,6 +102,8 @@ public abstract class BulletType extends Content{
|
|||||||
public int lightningLength = 5, lightningLengthRand = 0;
|
public int lightningLength = 5, lightningLengthRand = 0;
|
||||||
/** Use a negative value to use default bullet damage. */
|
/** Use a negative value to use default bullet damage. */
|
||||||
public float lightningDamage = -1;
|
public float lightningDamage = -1;
|
||||||
|
public float lightningCone = 360f;
|
||||||
|
public float lightningAngle = 0f;
|
||||||
|
|
||||||
public float weaveScale = 1f;
|
public float weaveScale = 1f;
|
||||||
public float weaveMag = -1f;
|
public float weaveMag = -1f;
|
||||||
@@ -156,7 +159,7 @@ public abstract class BulletType extends Content{
|
|||||||
if(fragBullet != null){
|
if(fragBullet != null){
|
||||||
for(int i = 0; i < fragBullets; i++){
|
for(int i = 0; i < fragBullets; i++){
|
||||||
float len = Mathf.random(1f, 7f);
|
float len = Mathf.random(1f, 7f);
|
||||||
float a = b.rotation() + Mathf.range(fragCone/2);
|
float a = b.rotation() + Mathf.range(fragCone/2) + fragAngle;
|
||||||
fragBullet.create(b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax), Mathf.random(fragLifeMin, fragLifeMax));
|
fragBullet.create(b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax), Mathf.random(fragLifeMin, fragLifeMax));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,7 +184,7 @@ public abstract class BulletType extends Content{
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < lightning; i++){
|
for(int i = 0; i < lightning; i++){
|
||||||
Lightning.create(b, lightningColor, lightningDamage < 0 ? damage : lightningDamage, b.x, b.y, Mathf.random(360f), lightningLength + Mathf.random(lightningLengthRand));
|
Lightning.create(b, lightningColor, lightningDamage < 0 ? damage : lightningDamage, b.x, b.y, b.rotation() + Mathf.range(lightningCone/2) + lightningAngle, lightningLength + Mathf.random(lightningLengthRand));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package mindustry.entities.comp;
|
package mindustry.entities.comp;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.world.blocks.environment.*;
|
import mindustry.world.blocks.environment.*;
|
||||||
|
|
||||||
@@ -90,7 +92,7 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
|
|||||||
//TODO is the netClient check necessary?
|
//TODO is the netClient check necessary?
|
||||||
if(drownTime >= 0.999f && !net.client()){
|
if(drownTime >= 0.999f && !net.client()){
|
||||||
kill();
|
kill();
|
||||||
//TODO drown event!
|
Events.fire(new UnitDrownEvent(self()));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
drownTime = Mathf.lerpDelta(drownTime, 0f, 0.03f);
|
drownTime = Mathf.lerpDelta(drownTime, 0f, 0.03f);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ abstract class MechComp implements Posc, Flyingc, Hitboxc, Unitc, Mechc, Elevati
|
|||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
//trigger animation only when walking manually
|
//trigger animation only when walking manually
|
||||||
if(walked){
|
if(walked || net.client()){
|
||||||
float len = deltaLen();
|
float len = deltaLen();
|
||||||
baseRotation = Angles.moveToward(baseRotation, deltaAngle(), type().baseRotateSpeed * Mathf.clamp(len / type().speed / Time.delta) * Time.delta);
|
baseRotation = Angles.moveToward(baseRotation, deltaAngle(), type().baseRotateSpeed * Mathf.clamp(len / type().speed / Time.delta) * Time.delta);
|
||||||
walkTime += len;
|
walkTime += len;
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
|
|||||||
Building tile = payload.entity;
|
Building tile = payload.entity;
|
||||||
int tx = Vars.world.toTile(x - tile.block.offset), ty = Vars.world.toTile(y - tile.block.offset);
|
int tx = Vars.world.toTile(x - tile.block.offset), ty = Vars.world.toTile(y - tile.block.offset);
|
||||||
Tile on = Vars.world.tile(tx, ty);
|
Tile on = Vars.world.tile(tx, ty);
|
||||||
if(on != null && Build.validPlace(tile.block, tile.team, tx, ty, tile.rotation)){
|
if(on != null && Build.validPlace(tile.block, tile.team, tx, ty, tile.rotation, false)){
|
||||||
int rot = (int)((rotation + 45f) / 90f) % 4;
|
int rot = (int)((rotation + 45f) / 90f) % 4;
|
||||||
payload.place(on, rot);
|
payload.place(on, rot);
|
||||||
|
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
dead = true;
|
dead = true;
|
||||||
|
|
||||||
//don't waste time when the unit is already on the ground, just destroy it
|
//don't waste time when the unit is already on the ground, just destroy it
|
||||||
if(isGrounded()){
|
if(!type.flying){
|
||||||
destroy();
|
destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc, Statusc{
|
|||||||
@Import Vec2 vel;
|
@Import Vec2 vel;
|
||||||
@Import UnitType type;
|
@Import UnitType type;
|
||||||
|
|
||||||
/** minimum cursor distance from unit, fixes 'cross-eyed' shooting */
|
|
||||||
static final float minAimDst = 18f;
|
|
||||||
/** temporary weapon sequence number */
|
/** temporary weapon sequence number */
|
||||||
static int sequenceNum = 0;
|
static int sequenceNum = 0;
|
||||||
|
|
||||||
@@ -67,7 +65,7 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc, Statusc{
|
|||||||
/** Aim at something. This will make all mounts point at it. */
|
/** Aim at something. This will make all mounts point at it. */
|
||||||
void aim(float x, float y){
|
void aim(float x, float y){
|
||||||
Tmp.v1.set(x, y).sub(this.x, this.y);
|
Tmp.v1.set(x, y).sub(this.x, this.y);
|
||||||
if(Tmp.v1.len() < minAimDst) Tmp.v1.setLength(minAimDst);
|
if(Tmp.v1.len() < type.aimDst) Tmp.v1.setLength(type.aimDst);
|
||||||
|
|
||||||
x = Tmp.v1.x + this.x;
|
x = Tmp.v1.x + this.x;
|
||||||
y = Tmp.v1.y + this.y;
|
y = Tmp.v1.y + this.y;
|
||||||
|
|||||||
@@ -1,47 +1,51 @@
|
|||||||
package mindustry.game;
|
package mindustry.game;
|
||||||
|
|
||||||
import arc.struct.Seq;
|
import arc.math.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.type.ItemStack;
|
import mindustry.type.*;
|
||||||
|
|
||||||
|
import static mindustry.content.UnitTypes.*;
|
||||||
|
|
||||||
public class DefaultWaves{
|
public class DefaultWaves{
|
||||||
private Seq<SpawnGroup> spawns;
|
private Seq<SpawnGroup> spawns;
|
||||||
|
|
||||||
public Seq<SpawnGroup> get(){
|
public Seq<SpawnGroup> get(){
|
||||||
if(spawns == null && UnitTypes.dagger != null){
|
if(spawns == null && dagger != null){
|
||||||
spawns = Seq.with(
|
spawns = Seq.with(
|
||||||
new SpawnGroup(UnitTypes.dagger){{
|
new SpawnGroup(dagger){{
|
||||||
end = 10;
|
end = 10;
|
||||||
unitScaling = 2f;
|
unitScaling = 2f;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.crawler){{
|
new SpawnGroup(crawler){{
|
||||||
begin = 4;
|
begin = 4;
|
||||||
end = 13;
|
end = 13;
|
||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
unitScaling = 1.5f;
|
unitScaling = 1.5f;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.flare){{
|
new SpawnGroup(flare){{
|
||||||
begin = 12;
|
begin = 12;
|
||||||
end = 16;
|
end = 16;
|
||||||
unitScaling = 1f;
|
unitScaling = 1f;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.dagger){{
|
new SpawnGroup(dagger){{
|
||||||
begin = 11;
|
begin = 11;
|
||||||
unitScaling = 1.7f;
|
unitScaling = 1.7f;
|
||||||
spacing = 2;
|
spacing = 2;
|
||||||
max = 4;
|
max = 4;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.pulsar){{
|
new SpawnGroup(pulsar){{
|
||||||
begin = 13;
|
begin = 13;
|
||||||
spacing = 3;
|
spacing = 3;
|
||||||
unitScaling = 0.5f;
|
unitScaling = 0.5f;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.mace){{
|
new SpawnGroup(mace){{
|
||||||
begin = 7;
|
begin = 7;
|
||||||
spacing = 3;
|
spacing = 3;
|
||||||
unitScaling = 2;
|
unitScaling = 2;
|
||||||
@@ -49,28 +53,28 @@ public class DefaultWaves{
|
|||||||
end = 30;
|
end = 30;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.dagger){{
|
new SpawnGroup(dagger){{
|
||||||
begin = 8;
|
begin = 8;
|
||||||
unitScaling = 1;
|
unitScaling = 1;
|
||||||
unitAmount = 4;
|
unitAmount = 4;
|
||||||
spacing = 2;
|
spacing = 2;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.mace){{
|
new SpawnGroup(mace){{
|
||||||
begin = 28;
|
begin = 28;
|
||||||
spacing = 3;
|
spacing = 3;
|
||||||
unitScaling = 1;
|
unitScaling = 1;
|
||||||
end = 40;
|
end = 40;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.mace){{
|
new SpawnGroup(mace){{
|
||||||
begin = 45;
|
begin = 45;
|
||||||
spacing = 3;
|
spacing = 3;
|
||||||
unitScaling = 2;
|
unitScaling = 2;
|
||||||
effect = StatusEffects.overdrive;
|
effect = StatusEffects.overdrive;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.mace){{
|
new SpawnGroup(mace){{
|
||||||
begin = 120;
|
begin = 120;
|
||||||
spacing = 2;
|
spacing = 2;
|
||||||
unitScaling = 3;
|
unitScaling = 3;
|
||||||
@@ -78,13 +82,13 @@ public class DefaultWaves{
|
|||||||
effect = StatusEffects.overdrive;
|
effect = StatusEffects.overdrive;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.flare){{
|
new SpawnGroup(flare){{
|
||||||
begin = 16;
|
begin = 16;
|
||||||
unitScaling = 1;
|
unitScaling = 1;
|
||||||
spacing = 2;
|
spacing = 2;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.dagger){{
|
new SpawnGroup(dagger){{
|
||||||
begin = 82;
|
begin = 82;
|
||||||
spacing = 3;
|
spacing = 3;
|
||||||
unitAmount = 4;
|
unitAmount = 4;
|
||||||
@@ -92,7 +96,7 @@ public class DefaultWaves{
|
|||||||
effect = StatusEffects.overdrive;
|
effect = StatusEffects.overdrive;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.dagger){{
|
new SpawnGroup(dagger){{
|
||||||
begin = 41;
|
begin = 41;
|
||||||
spacing = 5;
|
spacing = 5;
|
||||||
unitAmount = 1;
|
unitAmount = 1;
|
||||||
@@ -100,7 +104,7 @@ public class DefaultWaves{
|
|||||||
effect = StatusEffects.shielded;
|
effect = StatusEffects.shielded;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.fortress){{
|
new SpawnGroup(fortress){{
|
||||||
begin = 40;
|
begin = 40;
|
||||||
spacing = 5;
|
spacing = 5;
|
||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
@@ -108,7 +112,7 @@ public class DefaultWaves{
|
|||||||
max = 20;
|
max = 20;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.dagger){{
|
new SpawnGroup(dagger){{
|
||||||
begin = 35;
|
begin = 35;
|
||||||
spacing = 3;
|
spacing = 3;
|
||||||
unitAmount = 4;
|
unitAmount = 4;
|
||||||
@@ -117,7 +121,7 @@ public class DefaultWaves{
|
|||||||
end = 60;
|
end = 60;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.dagger){{
|
new SpawnGroup(dagger){{
|
||||||
begin = 42;
|
begin = 42;
|
||||||
spacing = 3;
|
spacing = 3;
|
||||||
unitAmount = 4;
|
unitAmount = 4;
|
||||||
@@ -126,14 +130,14 @@ public class DefaultWaves{
|
|||||||
end = 130;
|
end = 130;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.horizon){{
|
new SpawnGroup(horizon){{
|
||||||
begin = 40;
|
begin = 40;
|
||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
spacing = 2;
|
spacing = 2;
|
||||||
unitScaling = 2;
|
unitScaling = 2;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.flare){{
|
new SpawnGroup(flare){{
|
||||||
begin = 50;
|
begin = 50;
|
||||||
unitAmount = 4;
|
unitAmount = 4;
|
||||||
unitScaling = 3;
|
unitScaling = 3;
|
||||||
@@ -141,7 +145,7 @@ public class DefaultWaves{
|
|||||||
effect = StatusEffects.overdrive;
|
effect = StatusEffects.overdrive;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.zenith){{
|
new SpawnGroup(zenith){{
|
||||||
begin = 50;
|
begin = 50;
|
||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
unitScaling = 3;
|
unitScaling = 3;
|
||||||
@@ -149,42 +153,42 @@ public class DefaultWaves{
|
|||||||
max = 16;
|
max = 16;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.horizon){{
|
new SpawnGroup(horizon){{
|
||||||
begin = 53;
|
begin = 53;
|
||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
unitScaling = 3;
|
unitScaling = 3;
|
||||||
spacing = 4;
|
spacing = 4;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.atrax){{
|
new SpawnGroup(atrax){{
|
||||||
begin = 31;
|
begin = 31;
|
||||||
unitAmount = 4;
|
unitAmount = 4;
|
||||||
unitScaling = 1;
|
unitScaling = 1;
|
||||||
spacing = 3;
|
spacing = 3;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.scepter){{
|
new SpawnGroup(scepter){{
|
||||||
begin = 41;
|
begin = 41;
|
||||||
unitAmount = 1;
|
unitAmount = 1;
|
||||||
unitScaling = 1;
|
unitScaling = 1;
|
||||||
spacing = 30;
|
spacing = 30;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.reign){{
|
new SpawnGroup(reign){{
|
||||||
begin = 81;
|
begin = 81;
|
||||||
unitAmount = 1;
|
unitAmount = 1;
|
||||||
unitScaling = 1;
|
unitScaling = 1;
|
||||||
spacing = 40;
|
spacing = 40;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.antumbra){{
|
new SpawnGroup(antumbra){{
|
||||||
begin = 131;
|
begin = 131;
|
||||||
unitAmount = 1;
|
unitAmount = 1;
|
||||||
unitScaling = 1;
|
unitScaling = 1;
|
||||||
spacing = 40;
|
spacing = 40;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.horizon){{
|
new SpawnGroup(horizon){{
|
||||||
begin = 90;
|
begin = 90;
|
||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
unitScaling = 3;
|
unitScaling = 3;
|
||||||
@@ -194,4 +198,76 @@ public class DefaultWaves{
|
|||||||
}
|
}
|
||||||
return spawns == null ? new Seq<>() : spawns;
|
return spawns == null ? new Seq<>() : spawns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO move elsewhere
|
||||||
|
public static Seq<SpawnGroup> generate(){
|
||||||
|
UnitType[][] species = {
|
||||||
|
{dagger, mace, fortress, scepter, reign},
|
||||||
|
{nova, pulsar, quasar, vela, corvus},
|
||||||
|
{crawler, atrax, spiroct, arkyid, toxopid},
|
||||||
|
//{risso, minke, bryde, sei, omura}, //questionable choices
|
||||||
|
//{mono, poly, mega, quad, oct}, //do not attack
|
||||||
|
{flare, horizon, zenith, antumbra, eclipse}
|
||||||
|
};
|
||||||
|
|
||||||
|
//required progression:
|
||||||
|
//- extra periodic patterns
|
||||||
|
|
||||||
|
Seq<SpawnGroup> out = new Seq<>();
|
||||||
|
|
||||||
|
//max reasonable wave, after which everything gets boring
|
||||||
|
int cap = 400;
|
||||||
|
|
||||||
|
//main sequence
|
||||||
|
float shieldStart = 30, shieldsPerWave = 12;
|
||||||
|
UnitType[] curSpecies = Structs.random(species);
|
||||||
|
int curTier = 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < cap;){
|
||||||
|
int f = i;
|
||||||
|
int next = Mathf.random(15, 25);
|
||||||
|
|
||||||
|
float shieldAmount = Math.max((i - shieldStart) * shieldsPerWave, 0);
|
||||||
|
|
||||||
|
//main progression
|
||||||
|
out.add(new SpawnGroup(curSpecies[Math.min(curTier, curSpecies.length - 1)]){{
|
||||||
|
unitAmount = f == 0 ? 1 : 10;
|
||||||
|
begin = f;
|
||||||
|
end = f + next >= cap ? never : f + next;
|
||||||
|
max = 16;
|
||||||
|
unitScaling = Mathf.random(1f, 2f);
|
||||||
|
shields = shieldAmount;
|
||||||
|
shieldScaling = shieldsPerWave;
|
||||||
|
}});
|
||||||
|
|
||||||
|
//extra progression that tails out, blends in
|
||||||
|
out.add(new SpawnGroup(curSpecies[Math.min(curTier, curSpecies.length - 1)]){{
|
||||||
|
unitAmount = 6;
|
||||||
|
begin = f + next;
|
||||||
|
end = f + next + Mathf.random(8, 12);
|
||||||
|
max = 10;
|
||||||
|
unitScaling = Mathf.random(2f);
|
||||||
|
spacing = Mathf.random(2, 3);
|
||||||
|
shields = shieldAmount;
|
||||||
|
shieldScaling = shieldsPerWave;
|
||||||
|
}});
|
||||||
|
|
||||||
|
i += next;
|
||||||
|
if(curTier < 3 || Mathf.chance(0.2)){
|
||||||
|
curTier ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//do not spawn bosses
|
||||||
|
curTier = Math.min(curTier, 3);
|
||||||
|
|
||||||
|
//small chance to switch species
|
||||||
|
if(Mathf.chance(0.2)){
|
||||||
|
curSpecies = Structs.random(species);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,6 +270,14 @@ public class EventType{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class UnitDrownEvent{
|
||||||
|
public final Unit unit;
|
||||||
|
|
||||||
|
public UnitDrownEvent(Unit unit){
|
||||||
|
this.unit = unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class UnitCreateEvent{
|
public static class UnitCreateEvent{
|
||||||
public final Unit unit;
|
public final Unit unit;
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class BlockRenderer implements Disposable{
|
|||||||
private FrameBuffer dark = new FrameBuffer();
|
private FrameBuffer dark = new FrameBuffer();
|
||||||
private Seq<Building> outArray2 = new Seq<>();
|
private Seq<Building> outArray2 = new Seq<>();
|
||||||
private Seq<Tile> shadowEvents = new Seq<>();
|
private Seq<Tile> shadowEvents = new Seq<>();
|
||||||
private IntSet processedEntities = new IntSet();
|
private IntSet processedEntities = new IntSet(), processedLinks = new IntSet();
|
||||||
private boolean displayStatus = false;
|
private boolean displayStatus = false;
|
||||||
|
|
||||||
public BlockRenderer(){
|
public BlockRenderer(){
|
||||||
@@ -180,6 +180,7 @@ public class BlockRenderer implements Disposable{
|
|||||||
tileview.clear();
|
tileview.clear();
|
||||||
lightview.clear();
|
lightview.clear();
|
||||||
processedEntities.clear();
|
processedEntities.clear();
|
||||||
|
processedLinks.clear();
|
||||||
|
|
||||||
int minx = Math.max(avgx - rangex - expandr, 0);
|
int minx = Math.max(avgx - rangex - expandr, 0);
|
||||||
int miny = Math.max(avgy - rangey - expandr, 0);
|
int miny = Math.max(avgy - rangey - expandr, 0);
|
||||||
@@ -196,10 +197,15 @@ public class BlockRenderer implements Disposable{
|
|||||||
tile = tile.build.tile;
|
tile = tile.build.tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(block != Blocks.air && block.cacheLayer == CacheLayer.normal && (tile.build == null || !processedEntities.contains(tile.build.id()))){
|
if(block != Blocks.air && block.cacheLayer == CacheLayer.normal && (tile.build == null || !processedEntities.contains(tile.build.id))){
|
||||||
if(block.expanded || !expanded){
|
if(block.expanded || !expanded){
|
||||||
|
if(tile.build == null || processedLinks.add(tile.build.id)){
|
||||||
tileview.add(tile);
|
tileview.add(tile);
|
||||||
if(tile.build != null) processedEntities.add(tile.build.id());
|
if(tile.build != null){
|
||||||
|
processedEntities.add(tile.build.id);
|
||||||
|
processedLinks.add(tile.build.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//lights are drawn even in the expanded range
|
//lights are drawn even in the expanded range
|
||||||
@@ -209,7 +215,7 @@ public class BlockRenderer implements Disposable{
|
|||||||
|
|
||||||
if(tile.build != null && tile.build.power != null && tile.build.power.links.size > 0){
|
if(tile.build != null && tile.build.power != null && tile.build.power.links.size > 0){
|
||||||
for(Building other : tile.build.getPowerConnections(outArray2)){
|
for(Building other : tile.build.getPowerConnections(outArray2)){
|
||||||
if(other.block instanceof PowerNode){ //TODO need a generic way to render connections!
|
if(other.block instanceof PowerNode && processedLinks.add(other.id)){ //TODO need a generic way to render connections!
|
||||||
tileview.add(other.tile);
|
tileview.add(other.tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,18 @@ public class Drawf{
|
|||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void shadow(TextureRegion region, float x, float y, float rotation){
|
||||||
|
Draw.color(Pal.shadow);
|
||||||
|
Draw.rect(region, x, y, rotation);
|
||||||
|
Draw.color();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void shadow(TextureRegion region, float x, float y){
|
||||||
|
Draw.color(Pal.shadow);
|
||||||
|
Draw.rect(region, x, y);
|
||||||
|
Draw.color();
|
||||||
|
}
|
||||||
|
|
||||||
public static void dashCircle(float x, float y, float rad, Color color){
|
public static void dashCircle(float x, float y, float rad, Color color){
|
||||||
Lines.stroke(3f, Pal.gray);
|
Lines.stroke(3f, Pal.gray);
|
||||||
Lines.dashCircle(x, y, rad);
|
Lines.dashCircle(x, y, rad);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class FloorRenderer implements Disposable{
|
|||||||
//TODO find out number with best performance
|
//TODO find out number with best performance
|
||||||
private static final int chunksize = mobile ? 16 : 32;
|
private static final int chunksize = mobile ? 16 : 32;
|
||||||
|
|
||||||
private Chunk[][] cache;
|
private int[][][] cache;
|
||||||
private MultiCacheBatch cbatch;
|
private MultiCacheBatch cbatch;
|
||||||
private IntSet drawnLayerSet = new IntSet();
|
private IntSet drawnLayerSet = new IntSet();
|
||||||
private IntSet recacheSet = new IntSet();
|
private IntSet recacheSet = new IntSet();
|
||||||
@@ -63,11 +63,11 @@ public class FloorRenderer implements Disposable{
|
|||||||
if(!Structs.inBounds(worldx, worldy, cache))
|
if(!Structs.inBounds(worldx, worldy, cache))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Chunk chunk = cache[worldx][worldy];
|
int[] chunk = cache[worldx][worldy];
|
||||||
|
|
||||||
//loop through all layers, and add layer index if it exists
|
//loop through all layers, and add layer index if it exists
|
||||||
for(int i = 0; i < layers; i++){
|
for(int i = 0; i < layers; i++){
|
||||||
if(chunk.caches[i] != -1 && i != CacheLayer.walls.ordinal()){
|
if(chunk[i] != -1 && i != CacheLayer.walls.ordinal()){
|
||||||
drawnLayerSet.add(i);
|
drawnLayerSet.add(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,9 +154,9 @@ public class FloorRenderer implements Disposable{
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk chunk = cache[worldx][worldy];
|
int[] chunk = cache[worldx][worldy];
|
||||||
if(chunk.caches[layer.ordinal()] == -1) continue;
|
if(chunk[layer.ordinal()] == -1) continue;
|
||||||
cbatch.drawCache(chunk.caches[layer.ordinal()]);
|
cbatch.drawCache(chunk[layer.ordinal()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ public class FloorRenderer implements Disposable{
|
|||||||
|
|
||||||
private void cacheChunk(int cx, int cy){
|
private void cacheChunk(int cx, int cy){
|
||||||
used.clear();
|
used.clear();
|
||||||
Chunk chunk = cache[cx][cy];
|
int[] chunk = cache[cx][cy];
|
||||||
|
|
||||||
for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize && tilex < world.width(); tilex++){
|
for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize && tilex < world.width(); tilex++){
|
||||||
for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize && tiley < world.height(); tiley++){
|
for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize && tiley < world.height(); tiley++){
|
||||||
@@ -184,15 +184,15 @@ public class FloorRenderer implements Disposable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cacheChunkLayer(int cx, int cy, Chunk chunk, CacheLayer layer){
|
private void cacheChunkLayer(int cx, int cy, int[] chunk, CacheLayer layer){
|
||||||
Batch current = Core.batch;
|
Batch current = Core.batch;
|
||||||
Core.batch = cbatch;
|
Core.batch = cbatch;
|
||||||
|
|
||||||
//begin a new cache
|
//begin a new cache
|
||||||
if(chunk.caches[layer.ordinal()] == -1){
|
if(chunk[layer.ordinal()] == -1){
|
||||||
cbatch.beginCache();
|
cbatch.beginCache();
|
||||||
}else{
|
}else{
|
||||||
cbatch.beginCache(chunk.caches[layer.ordinal()]);
|
cbatch.beginCache(chunk[layer.ordinal()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize; tilex++){
|
for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize; tilex++){
|
||||||
@@ -218,7 +218,7 @@ public class FloorRenderer implements Disposable{
|
|||||||
|
|
||||||
Core.batch = current;
|
Core.batch = current;
|
||||||
cbatch.reserve(layer.capacity * chunksize * chunksize);
|
cbatch.reserve(layer.capacity * chunksize * chunksize);
|
||||||
chunk.caches[layer.ordinal()] = cbatch.endCache();
|
chunk[layer.ordinal()] = cbatch.endCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearTiles(){
|
public void clearTiles(){
|
||||||
@@ -227,15 +227,14 @@ public class FloorRenderer implements Disposable{
|
|||||||
recacheSet.clear();
|
recacheSet.clear();
|
||||||
int chunksx = Mathf.ceil((float)(world.width()) / chunksize),
|
int chunksx = Mathf.ceil((float)(world.width()) / chunksize),
|
||||||
chunksy = Mathf.ceil((float)(world.height()) / chunksize);
|
chunksy = Mathf.ceil((float)(world.height()) / chunksize);
|
||||||
cache = new Chunk[chunksx][chunksy];
|
cache = new int[chunksx][chunksy][CacheLayer.all.length];
|
||||||
cbatch = new MultiCacheBatch(chunksize * chunksize * 8);
|
cbatch = new MultiCacheBatch(chunksize * chunksize * 9);
|
||||||
|
|
||||||
Time.mark();
|
Time.mark();
|
||||||
|
|
||||||
for(int x = 0; x < chunksx; x++){
|
for(int x = 0; x < chunksx; x++){
|
||||||
for(int y = 0; y < chunksy; y++){
|
for(int y = 0; y < chunksy; y++){
|
||||||
cache[x][y] = new Chunk();
|
Arrays.fill(cache[x][y], -1);
|
||||||
Arrays.fill(cache[x][y].caches, -1);
|
|
||||||
|
|
||||||
cacheChunk(x, y);
|
cacheChunk(x, y);
|
||||||
}
|
}
|
||||||
@@ -251,13 +250,4 @@ public class FloorRenderer implements Disposable{
|
|||||||
cbatch = null;
|
cbatch = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Chunk{
|
|
||||||
/** Maps cache layer ID to cache ID in the batch.
|
|
||||||
* -1 means that this cache is unoccupied. */
|
|
||||||
int[] caches = new int[CacheLayer.all.length];
|
|
||||||
|
|
||||||
Chunk(){
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public class Pal{
|
|||||||
darkishGray = new Color(0.3f, 0.3f, 0.3f, 1f),
|
darkishGray = new Color(0.3f, 0.3f, 0.3f, 1f),
|
||||||
darkerGray = new Color(0.2f, 0.2f, 0.2f, 1f),
|
darkerGray = new Color(0.2f, 0.2f, 0.2f, 1f),
|
||||||
darkestGray = new Color(0.1f, 0.1f, 0.1f, 1f),
|
darkestGray = new Color(0.1f, 0.1f, 0.1f, 1f),
|
||||||
|
shadow = new Color(0, 0, 0, 0.22f),
|
||||||
ammo = Color.valueOf("ff8947"),
|
ammo = Color.valueOf("ff8947"),
|
||||||
rubble = Color.valueOf("1c1817"),
|
rubble = Color.valueOf("1c1817"),
|
||||||
|
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
|||||||
|
|
||||||
if(hadEntity){
|
if(hadEntity){
|
||||||
if(isCenter){ //only read entity for center blocks
|
if(isCenter){ //only read entity for center blocks
|
||||||
if(block.hasEntity()){
|
if(block.hasBuilding()){
|
||||||
try{
|
try{
|
||||||
readChunk(stream, true, in -> {
|
readChunk(stream, true, in -> {
|
||||||
byte revision = in.readByte();
|
byte revision = in.readByte();
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public abstract class LegacySaveVersion extends SaveVersion{
|
|||||||
tile.setBlock(block);
|
tile.setBlock(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(block.hasEntity()){
|
if(block.hasBuilding()){
|
||||||
try{
|
try{
|
||||||
readChunk(stream, true, in -> {
|
readChunk(stream, true, in -> {
|
||||||
byte version = in.readByte();
|
byte version = in.readByte();
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ public enum ConditionOp{
|
|||||||
lessThan("<", (a, b) -> a < b),
|
lessThan("<", (a, b) -> a < b),
|
||||||
lessThanEq("<=", (a, b) -> a <= b),
|
lessThanEq("<=", (a, b) -> a <= b),
|
||||||
greaterThan(">", (a, b) -> a > b),
|
greaterThan(">", (a, b) -> a > b),
|
||||||
greaterThanEq(">=", (a, b) -> a >= b);
|
greaterThanEq(">=", (a, b) -> a >= b),
|
||||||
|
always("always", (a, b) -> true);
|
||||||
|
|
||||||
public static final ConditionOp[] all = values();
|
public static final ConditionOp[] all = values();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package mindustry.logic;
|
package mindustry.logic;
|
||||||
|
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
|
import arc.graphics.*;
|
||||||
import arc.scene.style.*;
|
import arc.scene.style.*;
|
||||||
import arc.scene.ui.*;
|
import arc.scene.ui.*;
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
@@ -633,6 +634,8 @@ public class LStatements{
|
|||||||
|
|
||||||
@RegisterStatement("jump")
|
@RegisterStatement("jump")
|
||||||
public static class JumpStatement extends LStatement{
|
public static class JumpStatement extends LStatement{
|
||||||
|
private static Color last = new Color();
|
||||||
|
|
||||||
public transient StatementElem dest;
|
public transient StatementElem dest;
|
||||||
|
|
||||||
public int destIndex;
|
public int destIndex;
|
||||||
@@ -644,19 +647,30 @@ public class LStatements{
|
|||||||
public void build(Table table){
|
public void build(Table table){
|
||||||
table.add("if ").padLeft(4);
|
table.add("if ").padLeft(4);
|
||||||
|
|
||||||
field(table, value, str -> value = str);
|
last = table.color;
|
||||||
|
table.table(this::rebuild);
|
||||||
table.button(b -> {
|
|
||||||
b.label(() -> op.symbol);
|
|
||||||
b.clicked(() -> showSelect(b, ConditionOp.all, op, o -> op = o));
|
|
||||||
}, Styles.logict, () -> {}).size(48f, 40f).pad(4f).color(table.color);
|
|
||||||
|
|
||||||
field(table, compare, str -> compare = str);
|
|
||||||
|
|
||||||
table.add().growX();
|
table.add().growX();
|
||||||
table.add(new JumpButton(() -> dest, s -> dest = s)).size(30).right().padLeft(-8);
|
table.add(new JumpButton(() -> dest, s -> dest = s)).size(30).right().padLeft(-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rebuild(Table table){
|
||||||
|
table.clearChildren();
|
||||||
|
table.setColor(last);
|
||||||
|
|
||||||
|
if(op != ConditionOp.always) field(table, value, str -> value = str);
|
||||||
|
|
||||||
|
table.button(b -> {
|
||||||
|
b.label(() -> op.symbol);
|
||||||
|
b.clicked(() -> showSelect(b, ConditionOp.all, op, o -> {
|
||||||
|
op = o;
|
||||||
|
rebuild(table);
|
||||||
|
}));
|
||||||
|
}, Styles.logict, () -> {}).size(op == ConditionOp.always ? 80f : 48f, 40f).pad(4f).color(table.color);
|
||||||
|
|
||||||
|
if(op != ConditionOp.always) field(table, compare, str -> compare = str);
|
||||||
|
}
|
||||||
|
|
||||||
//elements need separate conversion logic
|
//elements need separate conversion logic
|
||||||
@Override
|
@Override
|
||||||
public void setupUI(){
|
public void setupUI(){
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import mindustry.gen.*;
|
|||||||
public enum RadarSort{
|
public enum RadarSort{
|
||||||
distance((pos, other) -> -pos.dst2(other)),
|
distance((pos, other) -> -pos.dst2(other)),
|
||||||
health((pos, other) -> other.health()),
|
health((pos, other) -> other.health()),
|
||||||
|
shield((pos, other) -> other.shield()),
|
||||||
|
armor((pos, other) -> other.armor()),
|
||||||
maxHealth((pos, other) -> other.maxHealth());
|
maxHealth((pos, other) -> other.maxHealth());
|
||||||
|
|
||||||
public final RadarSortFunc func;
|
public final RadarSortFunc func;
|
||||||
@@ -17,6 +19,6 @@ public enum RadarSort{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface RadarSortFunc{
|
public interface RadarSortFunc{
|
||||||
float get(Position pos, Healthc other);
|
float get(Position pos, Unit other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public enum RadarTarget{
|
|||||||
enemy((team, other) -> team != other.team),
|
enemy((team, other) -> team != other.team),
|
||||||
ally((team, other) -> team == other.team),
|
ally((team, other) -> team == other.team),
|
||||||
player((team, other) -> other.isPlayer()),
|
player((team, other) -> other.isPlayer()),
|
||||||
|
attacker((pos, other) -> other.canShoot()),
|
||||||
flying((team, other) -> other.isFlying()),
|
flying((team, other) -> other.isFlying()),
|
||||||
boss((team, other) -> other.isBoss()),
|
boss((team, other) -> other.isBoss()),
|
||||||
ground((team, other) -> other.isGrounded());
|
ground((team, other) -> other.isGrounded());
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import mindustry.type.*;
|
|||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -634,12 +633,11 @@ public class Mods implements Loadable{
|
|||||||
//make sure the main class exists before loading it; if it doesn't just don't put it there
|
//make sure the main class exists before loading it; if it doesn't just don't put it there
|
||||||
if(mainFile.exists()){
|
if(mainFile.exists()){
|
||||||
//mobile versions don't support class mods
|
//mobile versions don't support class mods
|
||||||
if(mobile){
|
if(ios){
|
||||||
throw new IllegalArgumentException("Java class mods are not supported on mobile.");
|
throw new IllegalArgumentException("Java class mods are not supported on iOS.");
|
||||||
}
|
}
|
||||||
|
|
||||||
URLClassLoader classLoader = new URLClassLoader(new URL[]{sourceFile.file().toURI().toURL()}, ClassLoader.getSystemClassLoader());
|
Class<?> main = platform.loadJar(sourceFile, mainClass);
|
||||||
Class<?> main = classLoader.loadClass(mainClass);
|
|
||||||
metas.put(main, meta);
|
metas.put(main, meta);
|
||||||
mainMod = (Mod)main.getDeclaredConstructor().newInstance();
|
mainMod = (Mod)main.getDeclaredConstructor().newInstance();
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -25,15 +25,15 @@ import static mindustry.Vars.net;
|
|||||||
public class CrashSender{
|
public class CrashSender{
|
||||||
|
|
||||||
public static String createReport(String error){
|
public static String createReport(String error){
|
||||||
String report = "Oh no, Mindustry crashed!\n";
|
String report = "Mindustry has crashed. How unforunate.\n";
|
||||||
if(mods.list().size == 0){
|
if(mods.list().size == 0 && Version.build != -1){
|
||||||
report += "Please report this at https://github.com/Anuken/Mindustry/issues/new?labels=bug&template=bug_report.md\n\n";
|
report += "Report this at " + Vars.reportIssueURL + "\n\n";
|
||||||
}
|
}
|
||||||
return report + "Version: " + Version.combined() + (Vars.headless ? " (Server)" : "") + "\n"
|
return report + "Version: " + Version.combined() + (Vars.headless ? " (Server)" : "") + "\n"
|
||||||
+ "OS: " + System.getProperty("os.name") + " x" + (OS.is64Bit ? "64" : "32") + "\n"
|
+ "OS: " + System.getProperty("os.name") + " x" + (OS.is64Bit ? "64" : "32") + "\n"
|
||||||
+ "Java Version: " + System.getProperty("java.version") + "\n"
|
+ "Java Version: " + System.getProperty("java.version") + "\n"
|
||||||
+ "Java Architecture: " + System.getProperty("sun.arch.data.model") + "\n"
|
+ "Java Architecture: " + System.getProperty("sun.arch.data.model") + "\n"
|
||||||
+ mods.list().size + " Mods: " + mods.list().toString(", ", mod -> mod.name + ":" + mod.meta.version)
|
+ mods.list().size + " Mods" + (mods.list().isEmpty() ? "" : ": " + mods.list().toString(", ", mod -> mod.name + ":" + mod.meta.version))
|
||||||
+ "\n\n" + error;
|
+ "\n\n" + error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import mindustry.world.consumers.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class UnitType extends UnlockableContent{
|
public class UnitType extends UnlockableContent{
|
||||||
public static final float shadowTX = -12, shadowTY = -13, shadowColor = Color.toFloatBits(0, 0, 0, 0.22f), outlineSpace = 0.01f;
|
public static final float shadowTX = -12, shadowTY = -13, outlineSpace = 0.01f;
|
||||||
private static final Vec2 legOffset = new Vec2();
|
private static final Vec2 legOffset = new Vec2();
|
||||||
|
|
||||||
/** If true, the unit is always at elevation 1. */
|
/** If true, the unit is always at elevation 1. */
|
||||||
@@ -51,6 +51,7 @@ public class UnitType extends UnlockableContent{
|
|||||||
public boolean destructibleWreck = true;
|
public boolean destructibleWreck = true;
|
||||||
public float groundLayer = Layer.groundUnit;
|
public float groundLayer = Layer.groundUnit;
|
||||||
public float payloadCapacity = 8;
|
public float payloadCapacity = 8;
|
||||||
|
public float aimDst = -1f;
|
||||||
public int commandLimit = 24;
|
public int commandLimit = 24;
|
||||||
public float visualElevation = -1f;
|
public float visualElevation = -1f;
|
||||||
public boolean allowLegStep = false;
|
public boolean allowLegStep = false;
|
||||||
@@ -218,6 +219,10 @@ public class UnitType extends UnlockableContent{
|
|||||||
mechStride = 4f + (hitSize -8f)/2.1f;
|
mechStride = 4f + (hitSize -8f)/2.1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(aimDst < 0){
|
||||||
|
aimDst = weapons.contains(w -> !w.rotate) ? hitSize * 2f : hitSize / 2f;
|
||||||
|
}
|
||||||
|
|
||||||
if(mechStepShake < 0){
|
if(mechStepShake < 0){
|
||||||
mechStepShake = Mathf.round((hitSize - 11f) / 9f);
|
mechStepShake = Mathf.round((hitSize - 11f) / 9f);
|
||||||
mechStepParticles = hitSize > 15f;
|
mechStepParticles = hitSize > 15f;
|
||||||
@@ -409,7 +414,7 @@ public class UnitType extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void drawShadow(Unit unit){
|
public void drawShadow(Unit unit){
|
||||||
Draw.color(shadowColor);
|
Draw.color(Pal.shadow);
|
||||||
float e = Math.max(unit.elevation, visualElevation);
|
float e = Math.max(unit.elevation, visualElevation);
|
||||||
Draw.rect(shadowRegion, unit.x + shadowTX * e, unit.y + shadowTY * e, unit.rotation - 90);
|
Draw.rect(shadowRegion, unit.x + shadowTX * e, unit.y + shadowTY * e, unit.rotation - 90);
|
||||||
Draw.color();
|
Draw.color();
|
||||||
@@ -594,7 +599,7 @@ public class UnitType extends UnlockableContent{
|
|||||||
if(leg.moving && visualElevation > 0){
|
if(leg.moving && visualElevation > 0){
|
||||||
float scl = visualElevation;
|
float scl = visualElevation;
|
||||||
float elev = Mathf.slope(1f - leg.stage) * scl;
|
float elev = Mathf.slope(1f - leg.stage) * scl;
|
||||||
Draw.color(shadowColor);
|
Draw.color(Pal.shadow);
|
||||||
Draw.rect(footRegion, leg.base.x + shadowTX * elev, leg.base.y + shadowTY * elev, position.angleTo(leg.base));
|
Draw.rect(footRegion, leg.base.x + shadowTX * elev, leg.base.y + shadowTY * elev, position.angleTo(leg.base));
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
public abstract class Weather extends UnlockableContent{
|
public abstract class Weather extends UnlockableContent{
|
||||||
/** Default duration of this weather event in ticks. */
|
/** Default duration of this weather event in ticks. */
|
||||||
public float duration = 9f * Time.toMinutes;
|
public float duration = 8f * Time.toMinutes;
|
||||||
|
public float opacityMultiplier = 1f;
|
||||||
public Attributes attrs = new Attributes();
|
public Attributes attrs = new Attributes();
|
||||||
|
|
||||||
//internals
|
//internals
|
||||||
@@ -122,7 +123,7 @@ public abstract class Weather extends UnlockableContent{
|
|||||||
|
|
||||||
/** Creates a weather entry with some approximate weather values. */
|
/** Creates a weather entry with some approximate weather values. */
|
||||||
public WeatherEntry(Weather weather){
|
public WeatherEntry(Weather weather){
|
||||||
this(weather, weather.duration * 1f, weather.duration * 3f, weather.duration / 2f, weather.duration * 1.5f);
|
this(weather, weather.duration * 3f, weather.duration * 6f, weather.duration / 2f, weather.duration * 1.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WeatherEntry(Weather weather, float minFrequency, float maxFrequency, float minDuration, float maxDuration){
|
public WeatherEntry(Weather weather, float minFrequency, float maxFrequency, float minDuration, float maxDuration){
|
||||||
@@ -177,14 +178,14 @@ public abstract class Weather extends UnlockableContent{
|
|||||||
if(renderer.weatherAlpha() > 0.0001f){
|
if(renderer.weatherAlpha() > 0.0001f){
|
||||||
Draw.draw(Layer.weather, () -> {
|
Draw.draw(Layer.weather, () -> {
|
||||||
weather.rand.setSeed(0);
|
weather.rand.setSeed(0);
|
||||||
Draw.alpha(renderer.weatherAlpha() * opacity);
|
Draw.alpha(renderer.weatherAlpha() * opacity * weather.opacityMultiplier);
|
||||||
weather.drawOver(self());
|
weather.drawOver(self());
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
Draw.draw(Layer.debris, () -> {
|
Draw.draw(Layer.debris, () -> {
|
||||||
weather.rand.setSeed(0);
|
weather.rand.setSeed(0);
|
||||||
Draw.alpha(renderer.weatherAlpha() * opacity);
|
Draw.alpha(renderer.weatherAlpha() * opacity * weather.opacityMultiplier);
|
||||||
weather.drawUnder(self());
|
weather.drawUnder(self());
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ public class Block extends UnlockableContent{
|
|||||||
public @Load("@-team") TextureRegion teamRegion;
|
public @Load("@-team") TextureRegion teamRegion;
|
||||||
public TextureRegion[] teamRegions;
|
public TextureRegion[] teamRegions;
|
||||||
|
|
||||||
|
//TODO make this not static
|
||||||
public static TextureRegion[][] cracks;
|
public static TextureRegion[][] cracks;
|
||||||
protected static final Seq<Tile> tempTiles = new Seq<>();
|
protected static final Seq<Tile> tempTiles = new Seq<>();
|
||||||
protected static final Seq<Building> tempTileEnts = new Seq<>();
|
protected static final Seq<Building> tempTileEnts = new Seq<>();
|
||||||
@@ -369,6 +370,7 @@ public class Block extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean canReplace(Block other){
|
public boolean canReplace(Block other){
|
||||||
|
if(other.alwaysReplace) return true;
|
||||||
return (other != this || rotate) && this.group != BlockGroup.none && other.group == this.group && size == other.size;
|
return (other != this || rotate) && this.group != BlockGroup.none && other.group == this.group && size == other.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,7 +500,7 @@ public class Block extends UnlockableContent{
|
|||||||
return variantRegions;
|
return variantRegions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasEntity(){
|
public boolean hasBuilding(){
|
||||||
return destructible || update;
|
return destructible || update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,8 +68,13 @@ public class Build{
|
|||||||
|
|
||||||
/** Returns whether a tile can be placed at this location by this team. */
|
/** Returns whether a tile can be placed at this location by this team. */
|
||||||
public static boolean validPlace(Block type, Team team, int x, int y, int rotation){
|
public static boolean validPlace(Block type, Team team, int x, int y, int rotation){
|
||||||
|
return validPlace(type, team, x, y, rotation, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns whether a tile can be placed at this location by this team. */
|
||||||
|
public static boolean validPlace(Block type, Team team, int x, int y, int rotation, boolean checkVisible){
|
||||||
//the wave team can build whatever they want as long as it's visible - banned blocks are not applicable
|
//the wave team can build whatever they want as long as it's visible - banned blocks are not applicable
|
||||||
if(type == null || (!type.isPlaceable() && !(state.rules.waves && team == state.rules.waveTeam && type.isVisible()))){
|
if(type == null || (checkVisible && (!type.isPlaceable() && !(state.rules.waves && team == state.rules.waveTeam && type.isVisible())))){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,30 +95,6 @@ public class Build{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type.isMultiblock()){
|
|
||||||
if(((type.canReplace(tile.block()) || tile.block.alwaysReplace) || (tile.block instanceof ConstructBlock && tile.<ConstructBuild>bc().cblock == type)) &&
|
|
||||||
type.canPlaceOn(tile, team) && tile.interactable(team)){
|
|
||||||
|
|
||||||
//if the block can be replaced but the sizes differ, check all the spaces around the block to make sure it can fit
|
|
||||||
if(type.size != tile.block().size){
|
|
||||||
int offsetx = -(type.size - 1) / 2;
|
|
||||||
int offsety = -(type.size - 1) / 2;
|
|
||||||
|
|
||||||
//this does not check *all* the conditions for placeability yet
|
|
||||||
for(int dx = 0; dx < type.size; dx++){
|
|
||||||
for(int dy = 0; dy < type.size; dy++){
|
|
||||||
int wx = dx + offsetx + x, wy = dy + offsety + y;
|
|
||||||
|
|
||||||
Tile check = world.tile(wx, wy);
|
|
||||||
if(check == null || !check.interactable(team) || (!check.block.alwaysReplace && check.block != tile.block && !(check.block.size == 1 && type.canReplace(check.block)))) return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//make sure that the new block can fit the old one
|
|
||||||
return type.bounds(x, y, Tmp.r1).grow(0.01f).contains(tile.block.bounds(tile.centerX(), tile.centerY(), Tmp.r2));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!type.requiresWater && !contactsShallows(tile.x, tile.y, type) && !type.placeableLiquid){
|
if(!type.requiresWater && !contactsShallows(tile.x, tile.y, type) && !type.placeableLiquid){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -124,31 +105,27 @@ public class Build{
|
|||||||
|
|
||||||
int offsetx = -(type.size - 1) / 2;
|
int offsetx = -(type.size - 1) / 2;
|
||||||
int offsety = -(type.size - 1) / 2;
|
int offsety = -(type.size - 1) / 2;
|
||||||
|
|
||||||
for(int dx = 0; dx < type.size; dx++){
|
for(int dx = 0; dx < type.size; dx++){
|
||||||
for(int dy = 0; dy < type.size; dy++){
|
for(int dy = 0; dy < type.size; dy++){
|
||||||
Tile other = world.tile(x + dx + offsetx, y + dy + offsety);
|
int wx = dx + offsetx + tile.x, wy = dy + offsety + tile.y;
|
||||||
|
|
||||||
|
Tile check = world.tile(wx, wy);
|
||||||
if(
|
if(
|
||||||
other == null ||
|
check == null || //nothing there
|
||||||
!other.block().alwaysReplace ||
|
(check.floor().isDeep() && !type.floating && !type.requiresWater && !type.placeableLiquid) || //deep water
|
||||||
!other.floor().placeableOn ||
|
(type == check.block() && check.build != null && rotation == check.build.rotation && type.rotate) || //same block, same rotation
|
||||||
(other.floor().isDeep() && !type.floating && !type.requiresWater && !type.placeableLiquid) ||
|
!check.interactable(team) || //cannot interact
|
||||||
(type.requiresWater && tile.floor().liquidDrop != Liquids.water)
|
!check.floor().placeableOn || //solid wall
|
||||||
){
|
!((type.canReplace(check.block()) || //can replace type
|
||||||
return false;
|
(check.block instanceof ConstructBlock && check.<ConstructBuild>bc().cblock == type && check.centerX() == tile.x && check.centerY() == tile.y)) && //same type in construction
|
||||||
}
|
type.bounds(tile.x, tile.y, Tmp.r1).grow(0.01f).contains(check.block.bounds(check.centerX(), check.centerY(), Tmp.r2))) || //no replacement
|
||||||
|
(type.requiresWater && check.floor().liquidDrop != Liquids.water) //requires water but none found
|
||||||
|
) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}else{
|
|
||||||
return tile.interactable(team)
|
|
||||||
&& (contactsShallows(tile.x, tile.y, type) || type.requiresWater || type.placeableLiquid)
|
|
||||||
&& (!tile.floor().isDeep() || type.floating || type.requiresWater || type.placeableLiquid)
|
|
||||||
&& tile.floor().placeableOn
|
|
||||||
&& (!type.requiresWater || tile.floor().liquidDrop == Liquids.water)
|
|
||||||
&& (((type.canReplace(tile.block()) || (tile.block instanceof ConstructBlock && tile.<ConstructBuild>bc().cblock == type))
|
|
||||||
&& !(type == tile.block() && (tile.build != null && rotation == tile.build.rotation) && type.rotate)) || tile.block().alwaysReplace || tile.block() == Blocks.air)
|
|
||||||
&& tile.block().isMultiblock() == type.isMultiblock() && type.canPlaceOn(tile, team);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean contactsGround(int x, int y, Block block){
|
public static boolean contactsGround(int x, int y, Block block){
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class CachedTile extends Tile{
|
|||||||
|
|
||||||
Block block = block();
|
Block block = block();
|
||||||
|
|
||||||
if(block.hasEntity()){
|
if(block.hasBuilding()){
|
||||||
Building n = entityprov.get();
|
Building n = entityprov.get();
|
||||||
n.cons(new ConsumeModule(build));
|
n.cons(new ConsumeModule(build));
|
||||||
n.tile(this);
|
n.tile(this);
|
||||||
|
|||||||
@@ -508,7 +508,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(block.hasEntity()){
|
if(block.hasBuilding()){
|
||||||
build = entityprov.get().init(this, team, block.update && !state.isEditor(), rotation);
|
build = entityprov.get().init(this, team, block.update && !state.isEditor(), rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,6 +129,11 @@ public class LaunchPad extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void buildConfiguration(Table table){
|
public void buildConfiguration(Table table){
|
||||||
|
if(!state.isCampaign()){
|
||||||
|
deselect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
table.button(Icon.upOpen, Styles.clearTransi, () -> {
|
table.button(Icon.upOpen, Styles.clearTransi, () -> {
|
||||||
ui.planet.showSelect(state.rules.sector, other -> state.secinfo.destination = other);
|
ui.planet.showSelect(state.rules.sector, other -> state.secinfo.destination = other);
|
||||||
deselect();
|
deselect();
|
||||||
|
|||||||
@@ -112,9 +112,7 @@ public class PointDefenseTurret extends Block{
|
|||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
Draw.rect(baseRegion, x, y);
|
Draw.rect(baseRegion, x, y);
|
||||||
Draw.color(Vars.turretShadowColor);
|
Drawf.shadow(region, x - (size / 2f), y - (size / 2f), rotation - 90);
|
||||||
Draw.rect(region, x - (size / 2f), y - (size / 2f), rotation - 90);
|
|
||||||
Draw.color();
|
|
||||||
Draw.rect(region, x, y, rotation - 90);
|
Draw.rect(region, x, y, rotation - 90);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,9 +107,7 @@ public class TractorBeamTurret extends Block{
|
|||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
Draw.rect(baseRegion, x, y);
|
Draw.rect(baseRegion, x, y);
|
||||||
Draw.color(Vars.turretShadowColor);
|
Drawf.shadow(region, x - (size / 2f), y - (size / 2f), rotation - 90);
|
||||||
Draw.rect(region, x - (size / 2f), y - (size / 2f), rotation - 90);
|
|
||||||
Draw.color();
|
|
||||||
Draw.rect(region, x, y, rotation - 90);
|
Draw.rect(region, x, y, rotation - 90);
|
||||||
|
|
||||||
//draw laser if applicable
|
//draw laser if applicable
|
||||||
|
|||||||