Merge branch 'master' into patch-2

This commit is contained in:
Anuken
2020-09-23 18:25:12 -04:00
committed by GitHub
146 changed files with 10504 additions and 8946 deletions

View File

@@ -99,7 +99,7 @@ android{
keyAlias RELEASE_KEY_ALIAS keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD keyPassword RELEASE_KEY_PASSWORD
}else{ }else{
println("No keystore info property found!") println("No keystore property found. Releases will be unsigned.")
} }
} }
} }

View File

@@ -38,6 +38,8 @@ public class EntityIO{
this.serializer = serializer; this.serializer = serializer;
this.name = name; this.name = name;
json.setIgnoreUnknownFields(true);
directory.mkdirs(); directory.mkdirs();
//load old revisions //load old revisions
@@ -45,6 +47,8 @@ public class EntityIO{
revisions.add(json.fromJson(Revision.class, fi)); revisions.add(json.fromJson(Revision.class, fi));
} }
revisions.sort(r -> r.version);
//next revision to be used //next revision to be used
int nextRevision = revisions.isEmpty() ? 0 : revisions.max(r -> r.version).version + 1; int nextRevision = revisions.isEmpty() ? 0 : revisions.max(r -> r.version).version + 1;
@@ -61,11 +65,13 @@ public class EntityIO{
//keep track of fields present in the entity //keep track of fields present in the entity
presentFields.addAll(fields.map(f -> f.name)); presentFields.addAll(fields.map(f -> f.name));
Revision previous = revisions.isEmpty() ? null : revisions.peek();
//add new revision if it doesn't match or there are no revisions //add new revision if it doesn't match or there are no revisions
if(revisions.isEmpty() || !revisions.peek().equal(fields)){ if(revisions.isEmpty() || !revisions.peek().equal(fields)){
revisions.add(new Revision(nextRevision, revisions.add(new Revision(nextRevision,
fields.map(f -> new RevisionField(f.name, f.type.toString(), fields.map(f -> new RevisionField(f.name, f.type.toString()))));
f.type.isPrimitive() ? BaseProcessor.typeSize(f.type.toString()) : -1)))); Log.warn("Adding new revision @ for @.\nPre = @\nNew = @\n", nextRevision, name, previous == null ? null : previous.fields.toString(", ", f -> f.name + ":" + f.type), fields.toString(", ", f -> f.name + ":" + f.type.toString()));
//write revision //write revision
directory.child(nextRevision + ".json").writeString(json.toJson(revisions.peek())); directory.child(nextRevision + ".json").writeString(json.toJson(revisions.peek()));
} }
@@ -322,8 +328,7 @@ public class EntityIO{
for(int i = 0; i < fields.size; i++){ for(int i = 0; i < fields.size; i++){
RevisionField field = fields.get(i); RevisionField field = fields.get(i);
FieldSpec spec = specs.get(i); FieldSpec spec = specs.get(i);
//TODO when making fields, their primitive size may be overwritten by an annotation; check for that if(!field.type.replace("mindustry.gen.", "").equals(spec.type.toString().replace("mindustry.gen.", ""))){
if(!(field.type.equals(spec.type.toString()) && (!spec.type.isPrimitive() || BaseProcessor.typeSize(spec.type.toString()) == field.size))){
return false; return false;
} }
} }
@@ -333,11 +338,9 @@ public class EntityIO{
public static class RevisionField{ public static class RevisionField{
String name, type; String name, type;
int size; //in bytes
RevisionField(String name, String type, int size){ RevisionField(String name, String type){
this.name = name; this.name = name;
this.size = size;
this.type = type; this.type = type;
} }

View File

@@ -3,6 +3,7 @@
alpha=0 alpha=0
atrax=1 atrax=1
block=2 block=2
corvus=24
flare=3 flare=3
mace=4 mace=4
mega=5 mega=5
@@ -21,5 +22,7 @@ mono=16
nova=17 nova=17
poly=18 poly=18
pulsar=19 pulsar=19
quad=23
risso=20 risso=20
spiroct=21 spiroct=21
vela=25

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:payloads,type:arc.struct.Seq<mindustry.world.blocks.payloads.Payload>,size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:payloads,type:arc.struct.Seq<mindustry.world.blocks.payloads.Payload>,size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:payloads,type:arc.struct.Seq<mindustry.world.blocks.payloads.Payload>,size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:deactivated,type:boolean,size:1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{version:1,fields:[{name:ammo,type:float,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -489,6 +489,7 @@ loadout = Loadout
resources = Resources resources = Resources
bannedblocks = Banned Blocks bannedblocks = Banned Blocks
addall = Add All addall = Add All
launch.destination = Destination: {0}
configure.invalid = Amount must be a number between 0 and {0}. configure.invalid = Amount must be a number between 0 and {0}.
zone.unlocked = [lightgray]{0} unlocked. zone.unlocked = [lightgray]{0} unlocked.
zone.requirement.complete = Requirement for {0} completed:[lightgray]\n{1} zone.requirement.complete = Requirement for {0} completed:[lightgray]\n{1}
@@ -521,6 +522,8 @@ sectors.production = Production:
sectors.stored = Stored: sectors.stored = Stored:
sectors.resume = Resume sectors.resume = Resume
sectors.launch = Launch sectors.launch = Launch
sectors.select = Select
sectors.nonelaunch = [lightgray]none (sun)
#NOTE TO TRANSLATORS: don't bother editing these, they'll be removed and/or rewritten anyway #NOTE TO TRANSLATORS: don't bother editing these, they'll be removed and/or rewritten anyway
sector.groundZero.name = Ground Zero sector.groundZero.name = Ground Zero
@@ -920,6 +923,8 @@ unit.eclipse.name = Eclipse
unit.mono.name = Mono unit.mono.name = Mono
unit.poly.name = Poly unit.poly.name = Poly
unit.mega.name = Mega unit.mega.name = Mega
unit.quad.name = Quad
unit.oct.name = Oct
unit.risso.name = Risso unit.risso.name = Risso
unit.minke.name = Minke unit.minke.name = Minke
unit.bryde.name = Bryde unit.bryde.name = Bryde
@@ -930,6 +935,8 @@ unit.beta.name = Beta
unit.gamma.name = Gamma unit.gamma.name = Gamma
unit.scepter.name = Scepter unit.scepter.name = Scepter
unit.reign.name = Reign unit.reign.name = Reign
unit.vela.name = Vela
unit.corvus.name = Corvus
block.resupply-point.name = Resupply Point block.resupply-point.name = Resupply Point
block.parallax.name = Parallax block.parallax.name = Parallax

View File

@@ -20,6 +20,8 @@ gameover = Konec hry
gameover.pvp = Vyhrál tým [accent]{0}[]! gameover.pvp = Vyhrál tým [accent]{0}[]!
highscore = [accent]Nový rekord! highscore = [accent]Nový rekord!
copied = Zkopírováno. copied = Zkopírováno.
indevpopup = Verze [accent]6[] hry je aktuálně v režimu [accent]alfa vývoje[].\n[lightgray]To znamená:[]\n[scarlet][]- Kampaň je zcela nedokončena[]\n- Obsah může chybět\n - Většina [scarlet]umělé inteligence jednotek[] nefunguje správně\n- Hodně jednotek je nedokončeno\n- Vše, co vidíš, se může změnit nebo i být odstraněno.\n\nChyby a pády prosím hlašte na [accent]Github[].[]
indev.notready = Tato část hry ještě není připravena
load.sound = Zvuky load.sound = Zvuky
load.map = Mapy load.map = Mapy
@@ -113,6 +115,7 @@ mod.disable = Zakázat
mod.content = Obsah: mod.content = Obsah:
mod.delete.error = Nebylo možnost smazat modifikaci. Soubor může být používán. mod.delete.error = Nebylo možnost smazat modifikaci. Soubor může být používán.
mod.requiresversion = [scarlet]Minimální požadovaná verze hry: [accent]{0}[] mod.requiresversion = [scarlet]Minimální požadovaná verze hry: [accent]{0}[]
mod.outdated = [scarlet]Nekompatibilní s V6 (chybí minGameVersion: 105)
mod.missingdependencies = [scarlet]Chybějící závislosti: {0}[] mod.missingdependencies = [scarlet]Chybějící závislosti: {0}[]
mod.erroredcontent = [scarlet]V obsahu jsou chyby[] mod.erroredcontent = [scarlet]V obsahu jsou chyby[]
mod.errors = Při načítání obsahu hry se vyskytly problémy. mod.errors = Při načítání obsahu hry se vyskytly problémy.
@@ -136,6 +139,8 @@ mod.scripts.disable = Tvoje zařízení nepodporuje skripty. Musíš zakázat ty
about.button = O hře about.button = O hře
name = Jméno: name = Jméno:
noname = Nejdřív si vyber [accent]jméno ve hře[]. noname = Nejdřív si vyber [accent]jméno ve hře[].
planetmap = Planetární mapa
launchcore = Vyslat jádro
filename = Název souboru: filename = Název souboru:
unlocked = Byl odemmknut nový blok! unlocked = Byl odemmknut nový blok!
completed = [accent]Dokončeno[] completed = [accent]Dokončeno[]
@@ -505,6 +510,18 @@ error.io = Vstupně/výstupní (I/O) chyba sítě.
error.any = Ueznámá chyba sítě. error.any = Ueznámá chyba sítě.
error.bloom = Chyba inicializace filtru Bloom.\nTvé zařízení ho nejspíš nepodporuje. error.bloom = Chyba inicializace filtru Bloom.\nTvé zařízení ho nejspíš nepodporuje.
weather.rain.name = Déšť
weather.snow.name = Sníh
weather.sandstorm.name = Písečná ouře
weather.sporestorm.name = Spórová bouře
sectors.unexplored = [lightgray]Neprozkoumáno
sectors.resources = Zdroje:
sectors.production = Výroba:
sectors.stored = Uskladněno:
sectors.resume = Pokračovat
sectors.launch = Vyslat
#NOTE TO TRANSLATORS: don't bother editing these, they'll be removed and/or rewritten anyway #NOTE TO TRANSLATORS: don't bother editing these, they'll be removed and/or rewritten anyway
sector.groundZero.name = Základní tábor sector.groundZero.name = Základní tábor
sector.craters.name = Krátery sector.craters.name = Krátery
@@ -573,8 +590,11 @@ blocks.itemsmoved = Rychlost pohybu
blocks.launchtime = Čas mezi vysláním blocks.launchtime = Čas mezi vysláním
blocks.shootrange = Dostřel blocks.shootrange = Dostřel
blocks.size = Velikost blocks.size = Velikost
blocks.displaysize = Velikost zobrazovače
blocks.liquidcapacity = Kapacita kapalin blocks.liquidcapacity = Kapacita kapalin
blocks.powerrange = Rozsah energie blocks.powerrange = Rozsah energie
blocks.linkrange = Dosah napojení
blocks.instructions = Instrukce
blocks.powerconnections = Nejvyšší počet spojení blocks.powerconnections = Nejvyšší počet spojení
blocks.poweruse = Spotřeba energie blocks.poweruse = Spotřeba energie
blocks.powerdamage = Energie na jednotku poškození blocks.powerdamage = Energie na jednotku poškození
@@ -596,6 +616,8 @@ blocks.inaccuracy = Nepřesnost
blocks.shots = Střely blocks.shots = Střely
blocks.reload = Střel za 1s blocks.reload = Střel za 1s
blocks.ammo = Střelivo blocks.ammo = Střelivo
blocks.shieldhealth = Zdraví štítu
blocks.cooldowntime = Čas na zchladnutí
bar.drilltierreq = Je vyžadován lepší vrt bar.drilltierreq = Je vyžadován lepší vrt
bar.noresources = Chybějí zdroje bar.noresources = Chybějí zdroje
@@ -638,9 +660,12 @@ unit.liquidunits = jednotek kapalin
unit.powerunits = jednotek energie unit.powerunits = jednotek energie
unit.degrees = úhly unit.degrees = úhly
unit.seconds = sekundy unit.seconds = sekundy
unit.minutes = minuty
unit.persecond = /s unit.persecond = /s
unit.perminute = /min
unit.timesspeed = x větší rychlost unit.timesspeed = x větší rychlost
unit.percent = % unit.percent = %
unit.shieldhealth = zdraví štítu
unit.items = předměty unit.items = předměty
unit.thousands = tis unit.thousands = tis
unit.millions = mio unit.millions = mio
@@ -727,6 +752,7 @@ category.blocks.name = Výběr bloků
command.attack = Útok command.attack = Útok
command.rally = Shromáždění command.rally = Shromáždění
command.retreat = Ústup command.retreat = Ústup
command.idle = Nečinný
placement.blockselectkeys = \n[lightgray]Klávesa:[] [{0}, placement.blockselectkeys = \n[lightgray]Klávesa:[] [{0},
keybind.respawn.name = Znovuzrození keybind.respawn.name = Znovuzrození
keybind.control.name = Ovládací jednotka keybind.control.name = Ovládací jednotka
@@ -739,7 +765,8 @@ keybind.toggle_block_status.name = Toggle Block Statuses
keybind.move_x.name = Pohyb vodorovně keybind.move_x.name = Pohyb vodorovně
keybind.move_y.name = Pohyb svisle keybind.move_y.name = Pohyb svisle
keybind.mouse_move.name = Následovat myš keybind.mouse_move.name = Následovat myš
keybind.boost.name = Boost keybind.pan.name = Následovat kameru
keybind.boost.name = Posílení
keybind.schematic_select.name = Vybrat oblast keybind.schematic_select.name = Vybrat oblast
keybind.schematic_menu.name = Nabídka šablon keybind.schematic_menu.name = Nabídka šablon
keybind.schematic_flip_x.name = Překlopit šablona podle svislé osy keybind.schematic_flip_x.name = Překlopit šablona podle svislé osy
@@ -766,6 +793,9 @@ keybind.diagonal_placement.name = Umisťovat úhlopříčně
keybind.pick.name = Vybrat blok keybind.pick.name = Vybrat blok
keybind.break_block.name = Rozbít blok keybind.break_block.name = Rozbít blok
keybind.deselect.name = Odznačit keybind.deselect.name = Odznačit
keybind.pickupCargo.name = Vyzvednout náklad
keybind.dropCargo.name = Položit náklad
keybind.command.name = Velet
keybind.shoot.name = Střílet keybind.shoot.name = Střílet
keybind.zoom.name = Přiblížení keybind.zoom.name = Přiblížení
keybind.menu.name = Hlavní nabídka keybind.menu.name = Hlavní nabídka
@@ -800,6 +830,7 @@ rules.reactorexplosions = Výbuch reaktoru
rules.wavetimer = Časovač vln rules.wavetimer = Časovač vln
rules.waves = Vlny rules.waves = Vlny
rules.attack = Režim útoku rules.attack = Režim útoku
rules.buildai = Umělá inteligence staví
rules.enemyCheat = Neomezeně surovin pro umělou inteligenci rules.enemyCheat = Neomezeně surovin pro umělou inteligenci
rules.blockhealthmultiplier = Násobek zdraví bloků rules.blockhealthmultiplier = Násobek zdraví bloků
rules.blockdamagemultiplier = Násobek poškození bloků rules.blockdamagemultiplier = Násobek poškození bloků
@@ -821,8 +852,12 @@ rules.title.unit = Jednotky
rules.title.experimental = Experimentální rules.title.experimental = Experimentální
rules.title.environment = Environmentální rules.title.environment = Environmentální
rules.lighting = Světlo rules.lighting = Světlo
rules.fire = Výstřel
rules.explosions = Výbušné poškození bloku/jednotky
rules.ambientlight = Světlo prostředí rules.ambientlight = Světlo prostředí
rules.solarpowermultiplier = Násobek sluneční energie rules.weather = Počasí
rules.weather.frequency = Četnost:
rules.weather.duration = Trvání:
content.item.name = Předměty content.item.name = Předměty
content.liquid.name = Kapaliny content.liquid.name = Kapaliny
@@ -848,9 +883,11 @@ liquid.water.name = Voda
liquid.slag.name = Roztavený kov liquid.slag.name = Roztavený kov
liquid.oil.name = Nafta liquid.oil.name = Nafta
liquid.cryofluid.name = Chladící kapalina liquid.cryofluid.name = Chladící kapalina
item.explosiveness = [lightgray]Výbušnost: {0}%[] item.explosiveness = [lightgray]Výbušnost: {0}%[]
item.flammability = [lightgray]Zápalnost: {0}%[] item.flammability = [lightgray]Zápalnost: {0}%[]
item.radioactivity = [lightgray]Radioaktivita: {0}%[] item.radioactivity = [lightgray]Radioaktivita: {0}%[]
unit.health = [lightgray]Životy: {0}[] unit.health = [lightgray]Životy: {0}[]
unit.speed = [lightgray]Rychlost: {0}[] unit.speed = [lightgray]Rychlost: {0}[]
unit.weapon = [lightgray]Zbraň: {0} unit.weapon = [lightgray]Zbraň: {0}
@@ -872,8 +909,9 @@ unit.pulsar.name = Pulzar
unit.quasar.name = Kvasar unit.quasar.name = Kvasar
unit.crawler.name = Slídil unit.crawler.name = Slídil
unit.atrax.name = Atrax unit.atrax.name = Atrax
unit.spiroct.name = Spiroct unit.spiroct.name = Spirokt
unit.arkyid.name = Arkyid unit.arkyid.name = Arkyid
unit.toxopid.name = Toxopid
unit.flare.name = Záře unit.flare.name = Záře
unit.horizon.name = Horizont unit.horizon.name = Horizont
unit.zenith.name = Zenit unit.zenith.name = Zenit
@@ -885,31 +923,36 @@ unit.mega.name = Mega
unit.risso.name = Risso unit.risso.name = Risso
unit.minke.name = Minke unit.minke.name = Minke
unit.bryde.name = Bryde unit.bryde.name = Bryde
unit.sei.name = Sei
unit.omura.name = Omura
unit.alpha.name = Alfa unit.alpha.name = Alfa
unit.beta.name = Beta unit.beta.name = Beta
unit.gamma.name = Gama unit.gamma.name = Gama
unit.scepter.name = Žezlo
unit.reign.name = Panovník
block.resupply-point.name = Zásobovací místo
block.parallax.name = Paralaxa block.parallax.name = Paralaxa
block.cliff.name = Útes block.cliff.name = Útes
block.sand-boulder.name = Pískovec block.sand-boulder.name = Pískovec
block.grass.name = Tráva block.grass.name = Tráva
block.slag.name = Slag block.slag.name = Slag
block.salt.name = Sůl block.salt.name = Sůl
block.saltrocks.name = Solný kámen block.salt-wall.name = Solné skály
block.pebbles.name = Oblázky block.pebbles.name = Oblázky
block.tendrils.name = Úponky block.tendrils.name = Úponky
block.sandrocks.name = Písečný kámen block.sand-wall.name = Písečné skály
block.spore-pine.name = Spórová borovice block.spore-pine.name = Spórová borovice
block.sporerocks.name = Spórové kamení block.spore-wall.name = Spórové skály
block.rock.name = Kámen block.boulder.name = Kámen
block.snowrock.name = Sněhový kámen block.snow-boulder.name = Sněhový kámen
block.snow-pine.name = Sněžná borovice block.snow-pine.name = Sněžná borovice
block.shale.name = Břidlice block.shale.name = Břidlice
block.shale-boulder.name = Břidličný balvan block.shale-boulder.name = Břidličný balvan
block.moss.name = Mech block.moss.name = Mech
block.shrubs.name = Křoví block.shrubs.name = Křoví
block.spore-moss.name = Spórový mech block.spore-moss.name = Spórový mech
block.shalerocks.name = Břidlicové kamení block.shale-wall.name = Břidlicové skály
block.scrap-wall.name = Rozpadlá zeď block.scrap-wall.name = Rozpadlá zeď
block.scrap-wall-large.name = Velká rozpadlá zeď block.scrap-wall-large.name = Velká rozpadlá zeď
block.scrap-wall-huge.name = Obří rozpadlá zeď block.scrap-wall-huge.name = Obří rozpadlá zeď
@@ -936,14 +979,18 @@ block.snow.name = Sníh
block.craters.name = Krátery block.craters.name = Krátery
block.sand-water.name = Voda s pískem block.sand-water.name = Voda s pískem
block.darksand-water.name = Voda s černým pískem block.darksand-water.name = Voda s černým pískem
block.char.name = Char block.char.name = Dřevěné uhlí
block.holostone.name = Blok kamene block.dacite.name = Dacit
block.dacite-wall.name = Stěna dacitu
block.ice-snow.name = Zasněžený led block.ice-snow.name = Zasněžený led
block.rocks.name = Skály block.stone wall.name = Skály
block.icerocks.name = Ledové skály block.ice-wall.name = Ledové skály
block.snowrocks.name = Sněhové skály block.snow-wall.name = Sněhové skály
block.dunerocks.name = Písečné duny block.dune-wall.name = Písečné duny
block.pine.name = Borovice block.pine.name = Borovice
block.dirt.name = Hlína
block.dirt-wall.name = Kopec hlíny
block.mud.name = Bláto
block.white-tree-dead.name = Bílá souška block.white-tree-dead.name = Bílá souška
block.white-tree.name = Bílý strom block.white-tree.name = Bílý strom
block.spore-cluster.name = Shluk spór block.spore-cluster.name = Shluk spór
@@ -959,10 +1006,9 @@ block.dark-panel-4.name = Tmavá deska 4
block.dark-panel-5.name = Tmavá deska 5 block.dark-panel-5.name = Tmavá deska 5
block.dark-panel-6.name = Tmavá deska 6 block.dark-panel-6.name = Tmavá deska 6
block.dark-metal.name = Tmavý kov block.dark-metal.name = Tmavý kov
block.ignarock.name = Třaskavec block.basalt.name = Čedič
block.hotrock.name = Horký kámen block.hotrock.name = Horký kámen
block.magmarock.name = Magmatický kámen block.magmarock.name = Magmatický kámen
block.cliffs.name = Útesy
block.copper-wall.name = Měděná zeď block.copper-wall.name = Měděná zeď
block.copper-wall-large.name = Velká měděná zeď block.copper-wall-large.name = Velká měděná zeď
block.titanium-wall.name = Titanová zeď block.titanium-wall.name = Titanová zeď
@@ -1073,6 +1119,7 @@ block.container.name = Kontejnér
block.launch-pad.name = Vysílací plošina block.launch-pad.name = Vysílací plošina
block.launch-pad-large.name = Velká vysílací plošina block.launch-pad-large.name = Velká vysílací plošina
block.segment.name = Úsek block.segment.name = Úsek
block.command-center.name = Velín
block.ground-factory.name = Pozemní továrna block.ground-factory.name = Pozemní továrna
block.air-factory.name = Letecká továrna block.air-factory.name = Letecká továrna
block.naval-factory.name = Námořní továrna block.naval-factory.name = Námořní továrna
@@ -1089,7 +1136,9 @@ block.overdrive-dome.name = Velká urychlující kupole
block.switch.name = Přepínač block.switch.name = Přepínač
block.micro-processor.name = Mikroprocesor block.micro-processor.name = Mikroprocesor
block.logic-processor.name = Logický procesor block.logic-processor.name = Logický procesor
block.hyper-processor.name = Hyperprocesor
block.logic-display.name = Zobrazovač logiky block.logic-display.name = Zobrazovač logiky
block.large-logic-display.name = Velký zobrazovač logiky
block.memory-cell.name = Paměťová buňka block.memory-cell.name = Paměťová buňka
team.blue.name = modrý team.blue.name = modrý

View File

@@ -92,3 +92,4 @@ SnakkiZXZ
sk7725 sk7725
ThePlayerA ThePlayerA
YellOw139 YellOw139
PetrGasparik

View File

@@ -314,3 +314,7 @@
63430=omura|unit-omura-medium 63430=omura|unit-omura-medium
63429=mud|block-mud-medium 63429=mud|block-mud-medium
63428=sei|unit-sei-medium 63428=sei|unit-sei-medium
63427=quad|unit-quad-medium
63426=oct|unit-oct-medium
63425=vela|unit-vela-medium
63424=corvus|unit-corvus-medium

View File

@@ -74,6 +74,7 @@ importPackage(Packages.mindustry.gen)
importPackage(Packages.mindustry.graphics) importPackage(Packages.mindustry.graphics)
importPackage(Packages.mindustry.graphics.g3d) importPackage(Packages.mindustry.graphics.g3d)
importPackage(Packages.mindustry.input) importPackage(Packages.mindustry.input)
importPackage(Packages.mindustry.io)
importPackage(Packages.mindustry.logic) importPackage(Packages.mindustry.logic)
importPackage(Packages.mindustry.maps) importPackage(Packages.mindustry.maps)
importPackage(Packages.mindustry.maps.filters) importPackage(Packages.mindustry.maps.filters)

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 KiB

After

Width:  |  Height:  |  Size: 553 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 735 KiB

After

Width:  |  Height:  |  Size: 662 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1020 KiB

After

Width:  |  Height:  |  Size: 950 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 503 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 KiB

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 KiB

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 420 KiB

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -72,6 +72,8 @@ 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 */
@@ -87,15 +89,17 @@ public class Vars implements Loadable{
/** turns needed to destroy a sector completely */ /** turns needed to destroy a sector completely */
public static final float sectorDestructionTurns = 3f; public static final float sectorDestructionTurns = 3f;
/** min armor fraction damage; e.g. 0.05 = at least 5% damage */ /** min armor fraction damage; e.g. 0.05 = at least 5% damage */
public static final float minArmorDamage = 0.05f; public static final float minArmorDamage = 0.1f;
/** launch animation duration */ /** launch animation duration */
public static final float launchDuration = 140f; public static final float launchDuration = 140f;
/** size of tiles in units */
public static final int tilesize = 8;
/** size of one tile payload (^2) */
public static final float tilePayload = tilesize * tilesize;
/** tile used in certain situations, instead of null */ /** tile used in certain situations, instead of null */
public static Tile emptyTile; public static Tile emptyTile;
/** for map generator dialog */ /** for map generator dialog */
public static boolean updateEditorOnChange = false; public static boolean updateEditorOnChange = false;
/** size of tiles in units */
public static final int tilesize = 8;
/** all choosable player colors in join/host dialog */ /** all choosable player colors in join/host dialog */
public static final Color[] playerColors = { public static final Color[] playerColors = {
Color.valueOf("82759a"), Color.valueOf("82759a"),

View File

@@ -43,7 +43,8 @@ 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) ? 70 : 0) +
(PathTile.damages(tile) ? 30 : 0),
//legs //legs
(team, tile) -> PathTile.legSolid(tile) ? impassable : 1 + (team, tile) -> PathTile.legSolid(tile) ? impassable : 1 +
@@ -52,7 +53,8 @@ public class Pathfinder implements Runnable{
//water //water
(team, tile) -> PathTile.solid(tile) || !PathTile.liquid(tile) ? 200 : 2 + //TODO cannot go through blocks - pathfinding isn't great (team, tile) -> PathTile.solid(tile) || !PathTile.liquid(tile) ? 200 : 2 + //TODO cannot go through blocks - pathfinding isn't great
(PathTile.nearGround(tile) || PathTile.nearSolid(tile) ? 14 : 0) + (PathTile.nearGround(tile) || PathTile.nearSolid(tile) ? 14 : 0) +
(PathTile.deep(tile) ? -1 : 0) (PathTile.deep(tile) ? -1 : 0) +
(PathTile.damages(tile) ? 35 : 0)
); );
//maps team, cost, type to flow field //maps team, cost, type to flow field
@@ -122,7 +124,8 @@ public class Pathfinder implements Runnable{
nearLiquid, nearLiquid,
nearGround, nearGround,
nearSolid, nearSolid,
tile.floor().isDeep() tile.floor().isDeep(),
tile.floor().damageTaken > 0.00001f
); );
} }
@@ -514,5 +517,7 @@ public class Pathfinder implements Runnable{
boolean nearSolid; boolean nearSolid;
//whether this block is deep / drownable //whether this block is deep / drownable
boolean deep; boolean deep;
//whether the floor damages
boolean damages;
} }
} }

View File

@@ -12,7 +12,7 @@ import mindustry.world.blocks.ConstructBlock.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class BuilderAI extends AIController{ public class BuilderAI extends AIController{
float buildRadius = 700; float buildRadius = 1500;
boolean found = false; boolean found = false;
@Nullable Builderc following; @Nullable Builderc following;

View File

@@ -25,8 +25,7 @@ public class FlyingAI extends AIController{
} }
if(command() == UnitCommand.rally){ if(command() == UnitCommand.rally){
target = targetFlag(unit.x, unit.y, BlockFlag.rally, false); moveTo(targetFlag(unit.x, unit.y, BlockFlag.rally, false), 60f);
moveTo(target, 60f);
} }
} }

View File

@@ -1,5 +1,6 @@
package mindustry.ai.types; package mindustry.ai.types;
import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.util.ArcAnnotate.*; import arc.util.ArcAnnotate.*;
import mindustry.ai.formations.*; import mindustry.ai.formations.*;
@@ -32,6 +33,10 @@ public class FormationAI extends AIController implements FormationMember{
return; return;
} }
if(unit.type().canBoost && unit.canPassOn()){
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f);
}
unit.controlWeapons(true, leader.isShooting); unit.controlWeapons(true, leader.isShooting);
// unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed)); // unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed));

View File

@@ -45,7 +45,7 @@ public class GroundAI extends AIController{
} }
} }
if(unit.type().canBoost && !unit.onSolid()){ if(unit.type().canBoost && unit.canPassOn()){
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f); unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f);
} }
@@ -74,15 +74,12 @@ public class GroundAI extends AIController{
}*/ }*/
} }
protected void moveTo(int pathType){ protected void moveTo(int pathTarget){
int costType = int costType = unit.pathType();
unit instanceof Legsc ? Pathfinder.costLegs :
unit instanceof WaterMovec ? Pathfinder.costWater :
Pathfinder.costGround;
Tile tile = unit.tileOn(); Tile tile = unit.tileOn();
if(tile == null) return; if(tile == null) return;
Tile targetTile = pathfinder.getTargetTile(tile, pathfinder.getField(unit.team, costType, pathType)); Tile targetTile = pathfinder.getTargetTile(tile, pathfinder.getField(unit.team, costType, pathTarget));
if(tile == targetTile || (costType == Pathfinder.costWater && !targetTile.floor().isLiquid)) return; if(tile == targetTile || (costType == Pathfinder.costWater && !targetTile.floor().isLiquid)) return;

View File

@@ -44,7 +44,7 @@ public class MinerAI extends AIController{
} }
if(ore != null){ if(ore != null){
moveTo(ore, unit.type().range / 1.5f); moveTo(ore, unit.type().range / 2f);
if(unit.within(ore, unit.type().range)){ if(unit.within(ore, unit.type().range)){
miner.mineTile(ore); miner.mineTile(ore);

View File

@@ -14,7 +14,9 @@ public class RepairAI extends AIController{
if(target != null){ if(target != null){
if(!target.within(unit, unit.type().range * 0.8f)){ if(!target.within(unit, unit.type().range * 0.8f)){
moveTo(target, unit.type().range * 0.8f); moveTo(target, unit.type().range * 0.8f);
}else{ }
if(target.within(unit, unit.type().range)){
unit.aim(target); unit.aim(target);
shoot = true; shoot = true;
} }

View File

@@ -14,7 +14,6 @@ public class TeamIndexProcess implements AsyncProcess{
private QuadTree<Unit>[] trees = new QuadTree[Team.all.length]; private QuadTree<Unit>[] trees = new QuadTree[Team.all.length];
private int[] counts = new int[Team.all.length]; private int[] counts = new int[Team.all.length];
private int[][] typeCounts = new int[Team.all.length][0]; private int[][] typeCounts = new int[Team.all.length][0];
private int[][] activeCounts = new int[Team.all.length][0];
public QuadTree<Unit> tree(Team team){ public QuadTree<Unit> tree(Team team){
if(trees[team.id] == null) trees[team.id] = new QuadTree<>(Vars.world.getQuadBounds(new Rect())); if(trees[team.id] == null) trees[team.id] = new QuadTree<>(Vars.world.getQuadBounds(new Rect()));
@@ -30,10 +29,6 @@ public class TeamIndexProcess implements AsyncProcess{
return typeCounts[team.id].length <= type.id ? 0 : typeCounts[team.id][type.id]; return typeCounts[team.id].length <= type.id ? 0 : typeCounts[team.id][type.id];
} }
public int countActive(Team team, UnitType type){
return activeCounts[team.id].length <= type.id ? 0 : activeCounts[team.id][type.id];
}
public void updateCount(Team team, UnitType type, int amount){ public void updateCount(Team team, UnitType type, int amount){
counts[team.id] += amount; counts[team.id] += amount;
if(typeCounts[team.id].length <= type.id){ if(typeCounts[team.id].length <= type.id){
@@ -42,16 +37,8 @@ public class TeamIndexProcess implements AsyncProcess{
typeCounts[team.id][type.id] += amount; typeCounts[team.id][type.id] += amount;
} }
public void updateActiveCount(Team team, UnitType type, int amount){
if(activeCounts[team.id].length <= type.id){
activeCounts[team.id] = new int[Vars.content.units().size];
}
activeCounts[team.id][type.id] += amount;
}
private void count(Unit unit){ private void count(Unit unit){
updateCount(unit.team, unit.type(), 1); updateCount(unit.team, unit.type(), 1);
if(!unit.deactivated) updateActiveCount(unit.team, unit.type(), 1);
if(unit instanceof Payloadc){ if(unit instanceof Payloadc){
((Payloadc)unit).payloads().each(p -> { ((Payloadc)unit).payloads().each(p -> {
@@ -77,7 +64,6 @@ public class TeamIndexProcess implements AsyncProcess{
} }
Arrays.fill(typeCounts[team.id], 0); Arrays.fill(typeCounts[team.id], 0);
Arrays.fill(activeCounts[team.id], 0);
} }
Arrays.fill(counts, 0); Arrays.fill(counts, 0);

View File

@@ -1267,7 +1267,7 @@ public class Blocks implements ContentList{
rotateSpeed = 1.4f; rotateSpeed = 1.4f;
attribute = Attribute.water; attribute = Attribute.water;
consumes.power(1f); consumes.power(1.25f);
}}; }};
cultivator = new Cultivator("cultivator"){{ cultivator = new Cultivator("cultivator"){{
@@ -1320,7 +1320,7 @@ public class Blocks implements ContentList{
requirements(Category.effect, with(Items.copper, 3000, Items.lead, 3000, Items.silicon, 2000)); requirements(Category.effect, with(Items.copper, 3000, Items.lead, 3000, Items.silicon, 2000));
unitType = UnitTypes.beta; unitType = UnitTypes.beta;
health = 2000; health = 3500;
itemCapacity = 9000; itemCapacity = 9000;
size = 4; size = 4;
@@ -1331,7 +1331,7 @@ public class Blocks implements ContentList{
requirements(Category.effect, with(Items.copper, 8000, Items.lead, 8000, Items.silicon, 5000, Items.thorium, 4000)); requirements(Category.effect, with(Items.copper, 8000, Items.lead, 8000, Items.silicon, 5000, Items.thorium, 4000));
unitType = UnitTypes.gamma; unitType = UnitTypes.gamma;
health = 4000; health = 6000;
itemCapacity = 13000; itemCapacity = 13000;
size = 5; size = 5;
@@ -1377,7 +1377,7 @@ public class Blocks implements ContentList{
ammoUseEffect = Fx.shellEjectSmall; ammoUseEffect = Fx.shellEjectSmall;
health = 250; health = 250;
inaccuracy = 2f; inaccuracy = 2f;
rotatespeed = 10f; rotateSpeed = 10f;
}}; }};
scatter = new ItemTurret("scatter"){{ scatter = new ItemTurret("scatter"){{
@@ -1395,7 +1395,7 @@ public class Blocks implements ContentList{
targetGround = false; targetGround = false;
recoilAmount = 2f; recoilAmount = 2f;
rotatespeed = 15f; rotateSpeed = 15f;
inaccuracy = 17f; inaccuracy = 17f;
shootCone = 35f; shootCone = 35f;
@@ -1498,7 +1498,7 @@ public class Blocks implements ContentList{
}}; }};
reloadTime = 35f; reloadTime = 35f;
shootCone = 40f; shootCone = 40f;
rotatespeed = 8f; rotateSpeed = 8f;
powerUse = 4f; powerUse = 4f;
targetAir = false; targetAir = false;
range = 90f; range = 90f;
@@ -1597,8 +1597,10 @@ public class Blocks implements ContentList{
health = 220 * size * size; health = 220 * size * size;
shootSound = Sounds.shotgun; shootSound = Sounds.shotgun;
float brange = range + 10f;
ammo(Items.thorium, new ShrapnelBulletType(){{ ammo(Items.thorium, new ShrapnelBulletType(){{
length = range + 10f; length = brange;
damage = 105f; damage = 105f;
ammoMultiplier = 6f; ammoMultiplier = 6f;
}}); }});
@@ -1647,7 +1649,7 @@ public class Blocks implements ContentList{
range = 200f; range = 200f;
size = 3; size = 3;
recoilAmount = 3f; recoilAmount = 3f;
rotatespeed = 10f; rotateSpeed = 10f;
inaccuracy = 10f; inaccuracy = 10f;
shootCone = 30f; shootCone = 30f;
shootSound = Sounds.shootSnap; shootSound = Sounds.shootSnap;
@@ -1805,6 +1807,8 @@ public class Blocks implements ContentList{
{UnitTypes.spiroct, UnitTypes.arkyid}, {UnitTypes.spiroct, UnitTypes.arkyid},
{UnitTypes.fortress, UnitTypes.scepter}, {UnitTypes.fortress, UnitTypes.scepter},
{UnitTypes.bryde, UnitTypes.sei}, {UnitTypes.bryde, UnitTypes.sei},
{UnitTypes.mega, UnitTypes.quad},
{UnitTypes.quasar, UnitTypes.vela},
}; };
}}; }};
@@ -1823,7 +1827,9 @@ public class Blocks implements ContentList{
{UnitTypes.antumbra, UnitTypes.eclipse}, {UnitTypes.antumbra, UnitTypes.eclipse},
{UnitTypes.arkyid, UnitTypes.toxopid}, {UnitTypes.arkyid, UnitTypes.toxopid},
{UnitTypes.scepter, UnitTypes.reign}, {UnitTypes.scepter, UnitTypes.reign},
{UnitTypes.sei, UnitTypes.omura} {UnitTypes.sei, UnitTypes.omura},
{UnitTypes.quad, UnitTypes.oct},
{UnitTypes.vela, UnitTypes.corvus}
}; };
}}; }};

View File

@@ -145,7 +145,7 @@ public class Fx{
int i = 0; int i = 0;
for(Vec2 p : lines){ for(Vec2 p : lines){
Fill.square(p.x, p.y, (5f - (float)i++ / lines.size * 2f) * e.fout(), 45); Fill.circle(p.x, p.y, Lines.getStroke() / 2f);
} }
}), }),
@@ -290,6 +290,50 @@ public class Fx{
Lines.spikes(e.x, e.y, 1f + e.fin() * 6f, e.fout() * 4f, 6); Lines.spikes(e.x, e.y, 1f + e.fin() * 6f, e.fout() * 4f, 6);
}), }),
greenBomb = new Effect(40f, 100f, e -> {
color(Pal.heal);
stroke(e.fout() * 2f);
Lines.circle(e.x, e.y, 4f + e.finpow() * 65f);
color(Pal.heal);
for(int i = 0; i < 4; i++){
Drawf.tri(e.x, e.y, 6f, 100f * e.fout(), i*90);
}
color();
for(int i = 0; i < 4; i++){
Drawf.tri(e.x, e.y, 3f, 35f * e.fout(), i*90);
}
}),
greenLaserCharge = new Effect(80f, 100f, e -> {
color(Pal.heal);
stroke(e.fin() * 2f);
Lines.circle(e.x, e.y, 4f + e.fout() * 100f);
Fill.circle(e.x, e.y, e.fin() * 20);
randLenVectors(e.id, 20, 40f * e.fout(), (x, y) -> {
Fill.circle(e.x + x, e.y + y, e.fin() * 5f);
});
color();
Fill.circle(e.x, e.y, e.fin() * 10);
}),
greenLaserChargeSmall = new Effect(40f, 100f, e -> {
color(Pal.heal);
stroke(e.fin() * 2f);
Lines.circle(e.x, e.y, e.fout() * 50f);
}),
healWaveDynamic = new Effect(22, e -> {
color(Pal.heal);
stroke(e.fout() * 2f);
Lines.circle(e.x, e.y, 4f + e.finpow() * e.rotation);
}),
healWave = new Effect(22, e -> { healWave = new Effect(22, e -> {
color(Pal.heal); color(Pal.heal);
stroke(e.fout() * 2f); stroke(e.fout() * 2f);
@@ -400,6 +444,17 @@ public class Fx{
}), }),
hitMeltHeal = new Effect(12, e -> {
color(Pal.heal);
stroke(e.fout() * 2f);
randLenVectors(e.id, 6, e.finpow() * 18f, e.rotation, 360f, (x, y) -> {
float ang = Mathf.angle(x, y);
lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1f);
});
}),
hitLaser = new Effect(8, e -> { hitLaser = new Effect(8, e -> {
color(Color.white, Pal.heal, e.fin()); color(Color.white, Pal.heal, e.fin());
stroke(0.5f + e.fout()); stroke(0.5f + e.fout());
@@ -1229,6 +1284,14 @@ public class Fx{
Fill.square(e.x + x, e.y + y, 1f + e.fout() * 3f, 45); Fill.square(e.x + x, e.y + y, 1f + e.fout() * 3f, 45);
}); });
}), }),
smokeCloud = new Effect(70, e -> {
randLenVectors(e.id, e.fin(), 30, 30f, (x, y, fin, fout) -> {
color(Color.gray);
alpha((0.5f - Math.abs(fin - 0.5f)) * 2f);
Fill.circle(e.x + x, e.y + y, 0.5f + fout * 4f);
});
}),
smeltsmoke = new Effect(15, e -> { smeltsmoke = new Effect(15, e -> {
randLenVectors(e.id, 6, 4f + e.fin() * 5f, (x, y) -> { randLenVectors(e.id, 6, 4f + e.fin() * 5f, (x, y) -> {

View File

@@ -9,7 +9,7 @@ import mindustry.type.StatusEffect;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class StatusEffects implements ContentList{ public class StatusEffects implements ContentList{
public static StatusEffect none, burning, freezing, wet, muddy, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, corroded, boss, sporeSlowed; public static StatusEffect none, burning, freezing, unmoving, slow, wet, muddy, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, corroded, boss, sporeSlowed;
@Override @Override
public void load(){ public void load(){
@@ -45,6 +45,14 @@ public class StatusEffects implements ContentList{
}); });
}}; }};
unmoving = new StatusEffect("unmoving"){{
speedMultiplier = 0.001f;
}};
slow = new StatusEffect("slow"){{
speedMultiplier = 0.4f;
}};
wet = new StatusEffect("wet"){{ wet = new StatusEffect("wet"){{
color = Color.royal; color = Color.royal;
speedMultiplier = 0.94f; speedMultiplier = 0.94f;

View File

@@ -263,7 +263,7 @@ public class TechTree implements ContentList{
node(steamGenerator, () -> { node(steamGenerator, () -> {
node(thermalGenerator, () -> { node(thermalGenerator, () -> {
node(differentialGenerator, () -> { node(differentialGenerator, () -> {
node(thoriumReactor, () -> { node(thoriumReactor, Seq.with(new Research(Liquids.cryofluid)), () -> {
node(impactReactor, () -> { node(impactReactor, () -> {
}); });
@@ -409,7 +409,11 @@ public class TechTree implements ContentList{
node(mono, () -> { node(mono, () -> {
node(poly, () -> { node(poly, () -> {
node(mega, () -> { node(mega, () -> {
node(quad, () -> {
node(oct, () -> {
});
});
}); });
}); });
}); });
@@ -538,7 +542,7 @@ public class TechTree implements ContentList{
} }
public static TechNode node(UnlockableContent content, Seq<Objective> objectives, Runnable children){ public static TechNode node(UnlockableContent content, Seq<Objective> objectives, Runnable children){
TechNode node = new TechNode(content, empty, children); TechNode node = new TechNode(content, content.researchRequirements(), children);
node.objectives = objectives; node.objectives = objectives;
return node; return node;
} }

View File

@@ -11,15 +11,23 @@ import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.type.*; import mindustry.type.*;
import static mindustry.Vars.*;
public class UnitTypes implements ContentList{ public class UnitTypes implements ContentList{
//region definitions //region definitions
//ground //mech
public static @EntityDef({Unitc.class, Mechc.class}) UnitType mace, dagger, crawler, fortress, scepter, reign; public static @EntityDef({Unitc.class, Mechc.class}) UnitType mace, dagger, crawler, fortress, scepter, reign;
//ground + builder + miner + commander //mech + builder + miner + commander
public static @EntityDef({Unitc.class, Mechc.class, Builderc.class, Minerc.class, Commanderc.class}) UnitType nova, pulsar, quasar; public static @EntityDef({Unitc.class, Mechc.class, Builderc.class, Minerc.class, Commanderc.class}) UnitType nova, pulsar, quasar;
//mech + commander
public static @EntityDef({Unitc.class, Mechc.class, Commanderc.class}) UnitType vela;
//legs + commander
public static @EntityDef({Unitc.class, Legsc.class, Commanderc.class}) UnitType corvus;
//legs //legs
public static @EntityDef({Unitc.class, Legsc.class}) UnitType atrax; public static @EntityDef({Unitc.class, Legsc.class}) UnitType atrax;
@@ -39,7 +47,7 @@ public class UnitTypes implements ContentList{
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class, Payloadc.class}) UnitType mega; public static @EntityDef({Unitc.class, Builderc.class, Minerc.class, Payloadc.class}) UnitType mega;
//air + building + payload TODO implement //air + building + payload TODO implement
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class, Payloadc.class}) UnitType quad, oct; public static @EntityDef({Unitc.class, Builderc.class, Payloadc.class}) UnitType quad, oct;
//air + building + mining //air + building + mining
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType alpha, beta, gamma; public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType alpha, beta, gamma;
@@ -257,7 +265,7 @@ public class UnitTypes implements ContentList{
itemCapacity = 60; itemCapacity = 60;
canBoost = true; canBoost = true;
boostMultiplier = 1.5f; boostMultiplier = 1.5f;
speed = 0.52f; speed = 0.55f;
hitsize = 8f; hitsize = 8f;
health = 110f; health = 110f;
buildSpeed = 0.8f; buildSpeed = 0.8f;
@@ -283,7 +291,7 @@ public class UnitTypes implements ContentList{
itemCapacity = 60; itemCapacity = 60;
canBoost = true; canBoost = true;
boostMultiplier = 1.5f; boostMultiplier = 1.5f;
speed = 0.62f; speed = 0.65f;
hitsize = 10f; hitsize = 10f;
health = 320f; health = 320f;
buildSpeed = 0.9f; buildSpeed = 0.9f;
@@ -365,6 +373,136 @@ public class UnitTypes implements ContentList{
}}); }});
}}; }};
vela = new UnitType("vela"){{
hitsize = 23f;
rotateSpeed = 1.6f;
canDrown = false;
mechFrontSway = 1f;
mechStepParticles = true;
mechStepShake = 0.15f;
speed = 0.35f;
boostMultiplier = 2.1f;
engineOffset = 12f;
engineSize = 6f;
lowAltitude = true;
health = 6000f;
armor = 7f;
canBoost = true;
landShake = 4f;
commandLimit = 32;
weapons.add(new Weapon("vela-weapon"){{
mirror = false;
top = false;
shake = 4f;
shootY = 13f;
x = y = 0f;
firstShotDelay = Fx.greenLaserChargeSmall.lifetime - 1f;
reload = 320f;
recoil = 0f;
shootSound = Sounds.laser;
continuous = true;
cooldownTime = 200f;
bullet = new ContinuousLaserBulletType(16){{
length = 150f;
hitEffect = Fx.hitMeltHeal;
drawSize = 420f;
lifetime = 160f;
shake = 1f;
despawnEffect = Fx.smokeCloud;
smokeEffect = Fx.none;
shootEffect = Fx.greenLaserChargeSmall;
incendChance = 0.02f;
incendSpread = 5f;
incendAmount = 1;
colors = new Color[]{Pal.heal.cpy().a(.2f), Pal.heal.cpy().a(.5f), Pal.heal.cpy().mul(1.2f), Color.white};
}};
shootStatus = StatusEffects.slow;
shootStatusDuration = bullet.lifetime + firstShotDelay;
}});
}};
corvus = new UnitType("corvus"){{
mineTier = 1;
hitsize = 29f;
itemCapacity = 80;
health = 19000f;
buildSpeed = 1.7f;
armor = 9f;
landShake = 1.5f;
rotateSpeed = 1.5f;
commandLimit = 24;
legCount = 4;
legLength = 14f;
legBaseOffset = 11f;
legMoveSpace = 1.5f;
legTrns = 0.58f;
hovering = true;
visualElevation = 0.2f;
allowLegStep = true;
speed = 0.3f;
mineTier = 2;
mineSpeed = 7f;
drawShields = false;
weapons.add(new Weapon("corvus-weapon"){{
top = false;
mirror = false;
shake = 14f;
shootY = 5f;
x = y = 0;
reload = 350f;
recoil = 0f;
shootSound = Sounds.laser;
cooldownTime = 350f;
shootStatusDuration = 60f * 2f;
shootStatus = StatusEffects.unmoving;
firstShotDelay = Fx.greenLaserCharge.lifetime;
bullet = new LaserBulletType(){{
length = 500f;
damage = 520f;
width = 75f;
lifetime = 65f;
lightningSpacing = 35f;
lightningLength = 5;
lightningDelay = 1.1f;
lightningLengthRand = 15;
lightningDamage = 50;
lightningAngleRand = 40f;
largeHit = true;
lightColor = lightningColor = Pal.heal;
shootEffect = Fx.greenLaserCharge;
sideAngle = 15f;
sideWidth = 0f;
sideLength = 0f;
colors = new Color[]{Pal.heal.cpy().a(0.4f), Pal.heal, Color.white};
}};
}});
}};
//endregion //endregion
//region ground legs //region ground legs
@@ -405,6 +543,7 @@ public class UnitTypes implements ContentList{
targetAir = false; targetAir = false;
health = 600; health = 600;
immunities = ObjectSet.with(StatusEffects.burning, StatusEffects.melting); immunities = ObjectSet.with(StatusEffects.burning, StatusEffects.melting);
legCount = 4; legCount = 4;
legLength = 9f; legLength = 9f;
legTrns = 0.6f; legTrns = 0.6f;
@@ -603,8 +742,8 @@ public class UnitTypes implements ContentList{
drag = 0.1f; drag = 0.1f;
speed = 0.5f; speed = 0.5f;
hitsize = 21f; hitsize = 21f;
health = 23000; health = 22000;
armor = 14f; armor = 13f;
rotateSpeed = 1.9f; rotateSpeed = 1.9f;
@@ -729,7 +868,6 @@ public class UnitTypes implements ContentList{
faceTarget = false; faceTarget = false;
engineOffset = 5.5f; engineOffset = 5.5f;
range = 140f; range = 140f;
crashDamageMultiplier = 4f;
weapons.add(new Weapon(){{ weapons.add(new Weapon(){{
y = 0f; y = 0f;
@@ -1047,6 +1185,8 @@ public class UnitTypes implements ContentList{
mineTier = 2; mineTier = 2;
health = 500; health = 500;
armor = 2f;
armor = 5f;
speed = 1.8f; speed = 1.8f;
accel = 0.06f; accel = 0.06f;
drag = 0.017f; drag = 0.017f;
@@ -1056,7 +1196,7 @@ public class UnitTypes implements ContentList{
rotateShooting = false; rotateShooting = false;
hitsize = 15f; hitsize = 15f;
engineSize = 3f; engineSize = 3f;
payloadCapacity = 4 * (8 * 8); payloadCapacity = (2 * 2) * tilePayload;
buildSpeed = 2.5f; buildSpeed = 2.5f;
weapons.add( weapons.add(
@@ -1076,6 +1216,86 @@ public class UnitTypes implements ContentList{
}}); }});
}}; }};
quad = new UnitType("quad"){{
armor = 4f;
health = 6000;
speed = 1.2f;
rotateSpeed = 2f;
accel = 0.05f;
drag = 0.017f;
lowAltitude = false;
flying = true;
engineOffset = 12f;
engineSize = 6f;
rotateShooting = false;
hitsize = 32f;
payloadCapacity = (3 * 3) * tilePayload;
buildSpeed = 2.5f;
range = 140f;
targetAir = false;
weapons.add(
new Weapon(){{
x = y = 0f;
mirror = false;
reload = 60f;
minShootVelocity = 0.01f;
bullet = new BasicBulletType(){{
sprite = "large-bomb";
width = height = 120/4f;
range = 30f;
ignoreRotation = true;
backColor = Pal.heal;
frontColor = Color.white;
mixColorTo = Color.white;
shootCone = 180f;
ejectEffect = Fx.none;
shootSound = Sounds.none;
despawnShake = 4f;
collidesAir = false;
lifetime = 70f;
despawnEffect = Fx.greenBomb;
hitEffect = Fx.massiveExplosion;
keepVelocity = false;
spin = 2f;
shrinkX = shrinkY = 0.7f;
speed = 0.001f;
collides = false;
splashDamage = 240f;
splashDamageRadius = 115f;
}};
}});
}};
oct = new UnitType("oct"){{
armor = 16f;
health = 24000;
speed = 0.6f;
rotateSpeed = 1f;
accel = 0.04f;
drag = 0.018f;
flying = true;
engineOffset = 46f;
engineSize = 7.8f;
rotateShooting = false;
hitsize = 60f;
payloadCapacity = (5.3f * 5.3f) * tilePayload;
buildSpeed = 4f;
drawShields = false;
abilities.add(new ForceFieldAbility(140f, 4f, 7000f, 60f * 8), new HealFieldAbility(130f, 60f * 2, 140f));
}};
//endregion //endregion
//region naval attack //region naval attack
@@ -1086,7 +1306,6 @@ public class UnitTypes implements ContentList{
health = 280; health = 280;
accel = 0.4f; accel = 0.4f;
rotateSpeed = 3.3f; rotateSpeed = 3.3f;
immunities = ObjectSet.with(StatusEffects.wet);
trailLength = 20; trailLength = 20;
rotateShooting = false; rotateShooting = false;
@@ -1138,14 +1357,12 @@ public class UnitTypes implements ContentList{
armor = 4f; armor = 4f;
accel = 0.3f; accel = 0.3f;
rotateSpeed = 2.6f; rotateSpeed = 2.6f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false; rotateShooting = false;
trailLength = 20; trailLength = 20;
trailX = 5.5f; trailX = 5.5f;
trailY = -4f; trailY = -4f;
trailScl = 1.9f; trailScl = 1.9f;
rotateShooting = false;
abilities.add(new StatusFieldAbility(StatusEffects.overclock, 60f * 6, 60f * 6f, 60f)); abilities.add(new StatusFieldAbility(StatusEffects.overclock, 60f * 6, 60f * 6f, 60f));
@@ -1180,8 +1397,7 @@ public class UnitTypes implements ContentList{
rotateSpeed = 1.8f; rotateSpeed = 1.8f;
drag = 0.17f; drag = 0.17f;
hitsize = 16f; hitsize = 16f;
armor = 6f; armor = 7f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false; rotateShooting = false;
trailLength = 22; trailLength = 22;
@@ -1189,7 +1405,7 @@ public class UnitTypes implements ContentList{
trailY = -9f; trailY = -9f;
trailScl = 1.5f; trailScl = 1.5f;
abilities.add(new HealFieldAbility(22f, 60f * 4, 70f), new ShieldFieldAbility(20f, 40f, 60f * 4, 60f)); abilities.add(new ShieldFieldAbility(20f, 40f, 60f * 4, 60f));
weapons.add(new Weapon("large-artillery"){{ weapons.add(new Weapon("large-artillery"){{
reload = 65f; reload = 65f;
@@ -1276,7 +1492,6 @@ public class UnitTypes implements ContentList{
hitsize = 39f; hitsize = 39f;
accel = 0.2f; accel = 0.2f;
rotateSpeed = 1.3f; rotateSpeed = 1.3f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false; rotateShooting = false;
trailLength = 50; trailLength = 50;
@@ -1361,10 +1576,9 @@ public class UnitTypes implements ContentList{
armor = 16f; armor = 16f;
accel = 0.19f; accel = 0.19f;
rotateSpeed = 0.9f; rotateSpeed = 0.9f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false; rotateShooting = false;
float spawnTime = 60f * 25f; float spawnTime = 60f * 15f;
abilities.add(new UnitSpawnAbility(flare, spawnTime, 19.25f, -31.75f), new UnitSpawnAbility(flare, spawnTime, -19.25f, -31.75f)); abilities.add(new UnitSpawnAbility(flare, spawnTime, 19.25f, -31.75f), new UnitSpawnAbility(flare, spawnTime, -19.25f, -31.75f));
@@ -1415,7 +1629,7 @@ public class UnitTypes implements ContentList{
mineTier = 1; mineTier = 1;
buildSpeed = 0.5f; buildSpeed = 0.5f;
drag = 0.05f; drag = 0.05f;
speed = 2.6f; speed = 2.8f;
rotateSpeed = 15f; rotateSpeed = 15f;
accel = 0.1f; accel = 0.1f;
itemCapacity = 30; itemCapacity = 30;
@@ -1449,7 +1663,7 @@ public class UnitTypes implements ContentList{
mineTier = 1; mineTier = 1;
buildSpeed = 0.75f; buildSpeed = 0.75f;
drag = 0.05f; drag = 0.05f;
speed = 2.9f; speed = 3f;
rotateSpeed = 17f; rotateSpeed = 17f;
accel = 0.1f; accel = 0.1f;
itemCapacity = 50; itemCapacity = 50;
@@ -1489,7 +1703,7 @@ public class UnitTypes implements ContentList{
mineTier = 2; mineTier = 2;
buildSpeed = 1f; buildSpeed = 1f;
drag = 0.05f; drag = 0.05f;
speed = 3.4f; speed = 3.5f;
rotateSpeed = 19f; rotateSpeed = 19f;
accel = 0.11f; accel = 0.11f;
itemCapacity = 70; itemCapacity = 70;

View File

@@ -45,4 +45,12 @@ public class Version{
build = Strings.canParseInt(map.get("build")) ? Integer.parseInt(map.get("build")) : -1; build = Strings.canParseInt(map.get("build")) ? Integer.parseInt(map.get("build")) : -1;
} }
} }
/** get menu version without colors */
public static String combined(){
if(build == -1){
return "custom build";
}
return (type.equals("official") ? modifier : type) + " build " + build + (revision == 0 ? "" : "." + revision);
}
} }

View File

@@ -31,7 +31,7 @@ public abstract class UnlockableContent extends MappableContent{
this.localizedName = Core.bundle.get(getContentType() + "." + this.name + ".name", this.name); this.localizedName = Core.bundle.get(getContentType() + "." + this.name + ".name", this.name);
this.description = Core.bundle.getOrNull(getContentType() + "." + this.name + ".description"); this.description = Core.bundle.getOrNull(getContentType() + "." + this.name + ".description");
this.unlocked = Core.settings != null && Core.settings.getBool(name + "-unlocked", false); this.unlocked = Core.settings != null && Core.settings.getBool(this.name + "-unlocked", false);
} }
public String displayDescription(){ public String displayDescription(){

View File

@@ -77,19 +77,24 @@ public class Damage{
} }
} }
/** Collides a bullet with blocks in a laser, taking into account absorption blocks. Resulting length is stored in the bullet's fdata. */ public static float findLaserLength(Bullet b, float length){
public static float collideLaser(Bullet b, float length){
Tmp.v1.trns(b.rotation(), length); Tmp.v1.trns(b.rotation(), length);
furthest = null; furthest = null;
world.raycast(b.tileX(), b.tileY(), world.toTile(b.x + Tmp.v1.x), world.toTile(b.y + Tmp.v1.y), boolean found = world.raycast(b.tileX(), b.tileY(), world.toTile(b.x + Tmp.v1.x), world.toTile(b.y + Tmp.v1.y),
(x, y) -> (furthest = world.tile(x, y)) != null && furthest.team() != b.team && furthest.block().absorbLasers); (x, y) -> (furthest = world.tile(x, y)) != null && furthest.team() != b.team && furthest.block().absorbLasers);
float resultLength = furthest != null ? Math.max(6f, b.dst(furthest.worldx(), furthest.worldy())) : length; return found && furthest != null ? Math.max(6f, b.dst(furthest.worldx(), furthest.worldy())) : length;
}
Damage.collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), resultLength); /** Collides a bullet with blocks in a laser, taking into account absorption blocks. Resulting length is stored in the bullet's fdata. */
b.fdata = furthest != null ? resultLength : length; public static float collideLaser(Bullet b, float length, boolean large){
float resultLength = findLaserLength(b, length);
collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), resultLength, large);
b.fdata = resultLength;
return resultLength; return resultLength;
} }
@@ -103,6 +108,8 @@ public class Damage{
* Only enemies of the specified team are damaged. * Only enemies of the specified team are damaged.
*/ */
public static void collideLine(Bullet hitter, Team team, Effect effect, float x, float y, float angle, float length, boolean large){ public static void collideLine(Bullet hitter, Team team, Effect effect, float x, float y, float angle, float length, boolean large){
length = findLaserLength(hitter, length);
collidedBlocks.clear(); collidedBlocks.clear();
tr.trns(angle, length); tr.trns(angle, length);
Intc2 collider = (cx, cy) -> { Intc2 collider = (cx, cy) -> {
@@ -150,13 +157,8 @@ public class Damage{
if(!e.checkTarget(hitter.type.collidesAir, hitter.type.collidesGround)) return; if(!e.checkTarget(hitter.type.collidesAir, hitter.type.collidesGround)) return;
e.hitbox(hitrect); e.hitbox(hitrect);
Rect other = hitrect;
other.y -= expand;
other.x -= expand;
other.width += expand * 2;
other.height += expand * 2;
Vec2 vec = Geometry.raycastRect(x, y, x2, y2, other); Vec2 vec = Geometry.raycastRect(x, y, x2, y2, hitrect.grow(expand * 2));
if(vec != null){ if(vec != null){
effect.at(vec.x, vec.y); effect.at(vec.x, vec.y);

View File

@@ -40,7 +40,7 @@ public class Effect{
} }
public Effect(float life, Cons<EffectContainer> renderer){ public Effect(float life, Cons<EffectContainer> renderer){
this(life, 32f, renderer); this(life,50f, renderer);
} }
public Effect ground(){ public Effect ground(){

View File

@@ -24,7 +24,7 @@ public class Units{
if(unit != null){ if(unit != null){
unit.dead = true; unit.dead = true;
Fx.unitCapKill.at(unit); Fx.unitCapKill.at(unit);
Core.app.post(() -> Call.unitDeath(unit.id)); Core.app.post(() -> Call.unitDestroy(unit.id));
} }
} }
@@ -42,6 +42,21 @@ public class Units{
} }
} }
//destroys immediately
@Remote(called = Loc.server)
public static void unitDestroy(int uid){
Unit unit = Groups.unit.getByID(uid);
//if there's no unit don't add it later and get it stuck as a ghost
if(netClient != null){
netClient.addRemovedEntity(uid);
}
if(unit != null){
unit.destroy();
}
}
@Remote(called = Loc.server) @Remote(called = Loc.server)
public static void unitDespawn(Unit unit){ public static void unitDespawn(Unit unit){
Fx.unitDespawn.at(unit.x, unit.y, 0, unit); Fx.unitDespawn.at(unit.x, unit.y, 0, unit);

View File

@@ -21,8 +21,8 @@ public class ForceFieldAbility extends Ability{
/** Cooldown after the shield is broken, in ticks. */ /** Cooldown after the shield is broken, in ticks. */
public float cooldown = 60f * 5; public float cooldown = 60f * 5;
/** State: radius scaling. */ /** State. */
protected float radiusScale; protected float radiusScale, alpha;
private static float realRad; private static float realRad;
private static Unit paramUnit; private static Unit paramUnit;
@@ -40,7 +40,7 @@ public class ForceFieldAbility extends Ability{
} }
paramUnit.shield -= trait.damage(); paramUnit.shield -= trait.damage();
paramUnit.shieldAlpha = 1f; paramField.alpha = 1f;
} }
}; };
@@ -59,6 +59,8 @@ public class ForceFieldAbility extends Ability{
unit.shield += Time.delta * regen; unit.shield += Time.delta * regen;
} }
alpha = Math.max(alpha - Time.delta/10f, 0f);
if(unit.shield > 0){ if(unit.shield > 0){
radiusScale = Mathf.lerpDelta(radiusScale, 1f, 0.06f); radiusScale = Mathf.lerpDelta(radiusScale, 1f, 0.06f);
paramUnit = unit; paramUnit = unit;
@@ -78,7 +80,7 @@ public class ForceFieldAbility extends Ability{
if(unit.shield > 0){ if(unit.shield > 0){
Draw.z(Layer.shields); Draw.z(Layer.shields);
Draw.color(unit.team.color, Color.white, Mathf.clamp(unit.shieldAlpha)); Draw.color(unit.team.color, Color.white, Mathf.clamp(alpha));
if(Core.settings.getBool("animatedshields")){ if(Core.settings.getBool("animatedshields")){
Fill.poly(unit.x, unit.y, 6, realRad); Fill.poly(unit.x, unit.y, 6, realRad);

View File

@@ -8,7 +8,7 @@ import mindustry.gen.*;
public class HealFieldAbility extends Ability{ public class HealFieldAbility extends Ability{
public float amount = 1, reload = 100, range = 60; public float amount = 1, reload = 100, range = 60;
public Effect healEffect = Fx.heal; public Effect healEffect = Fx.heal;
public Effect activeEffect = Fx.healWave; public Effect activeEffect = Fx.healWaveDynamic;
protected float timer; protected float timer;
protected boolean wasHealed = false; protected boolean wasHealed = false;
@@ -37,7 +37,7 @@ public class HealFieldAbility extends Ability{
}); });
if(wasHealed){ if(wasHealed){
activeEffect.at(unit); activeEffect.at(unit, range);
} }
timer = 0f; timer = 0f;

View File

@@ -1,16 +1,17 @@
package mindustry.entities.bullet; package mindustry.entities.bullet;
import arc.Core; import arc.*;
import arc.graphics.Color; import arc.graphics.*;
import arc.graphics.g2d.Draw; import arc.graphics.g2d.*;
import arc.graphics.g2d.TextureRegion;
import arc.math.*; import arc.math.*;
import arc.util.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.Pal; import mindustry.graphics.*;
/** An extended BulletType for most ammo-based bullets shot from turrets and units. */ /** An extended BulletType for most ammo-based bullets shot from turrets and units. */
public class BasicBulletType extends BulletType{ public class BasicBulletType extends BulletType{
public Color backColor = Pal.bulletYellowBack, frontColor = Pal.bulletYellow; public Color backColor = Pal.bulletYellowBack, frontColor = Pal.bulletYellow;
public Color mixColorFrom = new Color(1f, 1f, 1f, 0f), mixColorTo = new Color(1f, 1f, 1f, 0f);
public float width = 5f, height = 7f; public float width = 5f, height = 7f;
public float shrinkX = 0f, shrinkY = 0.5f; public float shrinkX = 0f, shrinkY = 0.5f;
public float spin = 0; public float spin = 0;
@@ -45,10 +46,15 @@ public class BasicBulletType extends BulletType{
float width = this.width * ((1f - shrinkX) + shrinkX * b.fout()); float width = this.width * ((1f - shrinkX) + shrinkX * b.fout());
float offset = -90 + (spin != 0 ? Mathf.randomSeed(b.id, 360f) + b.time * spin : 0f); float offset = -90 + (spin != 0 ? Mathf.randomSeed(b.id, 360f) + b.time * spin : 0f);
Color mix = Tmp.c1.set(mixColorFrom).lerp(mixColorTo, b.fin());
Draw.mixcol(mix, mix.a);
Draw.color(backColor); Draw.color(backColor);
Draw.rect(backRegion, b.x, b.y, width, height, b.rotation() + offset); Draw.rect(backRegion, b.x, b.y, width, height, b.rotation() + offset);
Draw.color(frontColor); Draw.color(frontColor);
Draw.rect(frontRegion, b.x, b.y, width, height, b.rotation() + offset); Draw.rect(frontRegion, b.x, b.y, width, height, b.rotation() + offset);
Draw.color();
Draw.reset();
} }
} }

View File

@@ -71,6 +71,8 @@ public abstract class BulletType extends Content{
public boolean hittable = true; public boolean hittable = true;
/** Whether this bullet can be reflected. */ /** Whether this bullet can be reflected. */
public boolean reflectable = true; public boolean reflectable = true;
/** Bullet range override. */
public float range = -1f;
//additional effects //additional effects
@@ -96,13 +98,13 @@ public abstract class BulletType extends Content{
public Color lightningColor = Pal.surge; public Color lightningColor = Pal.surge;
public int lightning; public int lightning;
public int lightningLength = 5; 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 weaveScale = 1f; public float weaveScale = 1f;
public float weaveMag = -1f; public float weaveMag = -1f;
public float hitShake = 0f; public float hitShake = 0f, despawnShake = 0f;
public int puddles; public int puddles;
public float puddleRange; public float puddleRange;
@@ -126,7 +128,7 @@ public abstract class BulletType extends Content{
/** Returns maximum distance the bullet this bullet type has can travel. */ /** Returns maximum distance the bullet this bullet type has can travel. */
public float range(){ public float range(){
return speed * lifetime * (1f - drag); return Math.max(speed * lifetime * (1f - drag), range);
} }
public boolean collides(Bullet bullet, Building tile){ public boolean collides(Bullet bullet, Building tile){
@@ -179,7 +181,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); Lightning.create(b, lightningColor, lightningDamage < 0 ? damage : lightningDamage, b.x, b.y, Mathf.random(360f), lightningLength + Mathf.random(lightningLengthRand));
} }
} }
@@ -187,6 +189,8 @@ public abstract class BulletType extends Content{
despawnEffect.at(b.x, b.y, b.rotation(), hitColor); despawnEffect.at(b.x, b.y, b.rotation(), hitColor);
hitSound.at(b); hitSound.at(b);
Effect.shake(despawnShake, despawnShake, b);
if(fragBullet != null || splashDamageRadius > 0 || lightning > 0){ if(fragBullet != null || splashDamageRadius > 0 || lightning > 0){
hit(b); hit(b);
} }
@@ -275,9 +279,8 @@ public abstract class BulletType extends Content{
bullet.damage = damage < 0 ? this.damage : damage; bullet.damage = damage < 0 ? this.damage : damage;
bullet.add(); bullet.add();
if(keepVelocity && owner instanceof Hitboxc) bullet.vel.add(((Hitboxc)owner).deltaX() / Time.delta, ((Hitboxc)owner).deltaY() / Time.delta); if(keepVelocity && owner instanceof Velc) bullet.vel.add(((Velc)owner).vel().x, ((Velc)owner).vel().y);
return bullet; return bullet;
} }
public void createNet(Team team, float x, float y, float angle, float damage, float velocityScl, float lifetimeScl){ public void createNet(Team team, float x, float y, float angle, float damage, float velocityScl, float lifetimeScl){

View File

@@ -12,10 +12,13 @@ import mindustry.graphics.*;
public class ContinuousLaserBulletType extends BulletType{ public class ContinuousLaserBulletType extends BulletType{
public float length = 220f; public float length = 220f;
public float shake = 1f; public float shake = 1f;
public float fadeTime = 16f;
public Color[] colors = {Color.valueOf("ec745855"), Color.valueOf("ec7458aa"), Color.valueOf("ff9c5a"), Color.white}; public Color[] colors = {Color.valueOf("ec745855"), Color.valueOf("ec7458aa"), Color.valueOf("ff9c5a"), Color.white};
public float[] tscales = {1f, 0.7f, 0.5f, 0.2f}; public float[] tscales = {1f, 0.7f, 0.5f, 0.2f};
public float[] strokes = {2f, 1.5f, 1f, 0.3f}; public float[] strokes = {2f, 1.5f, 1f, 0.3f};
public float[] lenscales = {1f, 1.12f, 1.15f, 1.17f}; public float[] lenscales = {1f, 1.12f, 1.15f, 1.17f};
public float width = 9f, oscScl = 0.8f, oscMag = 1.5f;
public boolean largeHit = true;
public ContinuousLaserBulletType(float damage){ public ContinuousLaserBulletType(float damage){
super(0.001f, damage); super(0.001f, damage);
@@ -25,6 +28,7 @@ public class ContinuousLaserBulletType extends BulletType{
hitSize = 4; hitSize = 4;
drawSize = 420f; drawSize = 420f;
lifetime = 16f; lifetime = 16f;
keepVelocity = false;
pierce = true; pierce = true;
hittable = false; hittable = false;
hitColor = colors[2]; hitColor = colors[2];
@@ -32,6 +36,7 @@ public class ContinuousLaserBulletType extends BulletType{
incendAmount = 1; incendAmount = 1;
incendSpread = 5; incendSpread = 5;
incendChance = 0.4f; incendChance = 0.4f;
lightColor = Color.orange;
} }
protected ContinuousLaserBulletType(){ protected ContinuousLaserBulletType(){
@@ -43,13 +48,20 @@ public class ContinuousLaserBulletType extends BulletType{
return length; return length;
} }
@Override
public void init(){
super.init();
drawSize = Math.max(drawSize, length*2f);
}
@Override @Override
public void update(Bullet b){ public void update(Bullet b){
//TODO possible laser absorption from blocks //TODO possible laser absorption from blocks
//damage every 5 ticks //damage every 5 ticks
if(b.timer(1, 5f)){ if(b.timer(1, 5f)){
Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), length, true); Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), length, largeHit);
} }
if(shake > 0){ if(shake > 0){
@@ -59,21 +71,23 @@ public class ContinuousLaserBulletType extends BulletType{
@Override @Override
public void draw(Bullet b){ public void draw(Bullet b){
float baseLen = length * b.fout(); float realLength = Damage.findLaserLength(b, length);
float fout = Mathf.clamp(b.time > b.lifetime - fadeTime ? 1f - (b.time - (lifetime - fadeTime)) / fadeTime : 1f);
float baseLen = realLength * fout;
Lines.lineAngle(b.x, b.y, b.rotation(), baseLen); Lines.lineAngle(b.x, b.y, b.rotation(), baseLen);
for(int s = 0; s < colors.length; s++){ for(int s = 0; s < colors.length; s++){
Draw.color(Tmp.c1.set(colors[s]).mul(1f + Mathf.absin(Time.time(), 1f, 0.1f))); Draw.color(Tmp.c1.set(colors[s]).mul(1f + Mathf.absin(Time.time(), 1f, 0.1f)));
for(int i = 0; i < tscales.length; i++){ for(int i = 0; i < tscales.length; i++){
Tmp.v1.trns(b.rotation() + 180f, (lenscales[i] - 1f) * 35f); Tmp.v1.trns(b.rotation() + 180f, (lenscales[i] - 1f) * 35f);
Lines.stroke((9f + Mathf.absin(Time.time(), 0.8f, 1.5f)) * b.fout() * strokes[s] * tscales[i]); Lines.stroke((width + Mathf.absin(Time.time(), oscScl, oscMag)) * fout * strokes[s] * tscales[i]);
Lines.lineAngle(b.x + Tmp.v1.x, b.y + Tmp.v1.y, b.rotation(), baseLen * lenscales[i], false); Lines.lineAngle(b.x + Tmp.v1.x, b.y + Tmp.v1.y, b.rotation(), baseLen * lenscales[i], false);
} }
} }
Tmp.v1.trns(b.rotation(), baseLen * 1.1f); Tmp.v1.trns(b.rotation(), baseLen * 1.1f);
Drawf.light(b.team, b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, 40, Color.orange, 0.7f); Drawf.light(b.team, b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, 40, lightColor, 0.7f);
Draw.reset(); Draw.reset();
} }

View File

@@ -8,18 +8,17 @@ import mindustry.content.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.world.*;
public class LaserBulletType extends BulletType{ public class LaserBulletType extends BulletType{
protected static Tile furthest; public Color[] colors = {Pal.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Pal.lancerLaser, Color.white};
public Effect laserEffect = Fx.lancerLaserShootSmoke;
protected Color[] colors = {Pal.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Pal.lancerLaser, Color.white}; public float length = 160f;
protected Effect laserEffect = Fx.lancerLaserShootSmoke; public float width = 15f;
protected float length = 160f; public float lengthFalloff = 0.5f;
protected float width = 15f; public float sideLength = 29f, sideWidth = 0.7f;
protected float lengthFalloff = 0.5f; public float sideAngle = 90f;
protected float sideLength = 29f, sideWidth = 0.7f; public float lightningSpacing = -1, lightningDelay = 0.1f, lightningAngleRand;
protected float sideAngle = 90f; public boolean largeHit = false;
public LaserBulletType(float damage){ public LaserBulletType(float damage){
super(0.01f, damage); super(0.01f, damage);
@@ -40,6 +39,13 @@ public class LaserBulletType extends BulletType{
this(1f); this(1f);
} }
@Override
public void init(){
super.init();
drawSize = Math.max(drawSize, length*2f);
}
@Override @Override
public float range(){ public float range(){
return length; return length;
@@ -47,8 +53,30 @@ public class LaserBulletType extends BulletType{
@Override @Override
public void init(Bullet b){ public void init(Bullet b){
float resultLength = Damage.collideLaser(b, length); float resultLength = Damage.collideLaser(b, length, largeHit), rot = b.rotation();
laserEffect.at(b.x, b.y, b.rotation(), resultLength * 0.75f);
laserEffect.at(b.x, b.y, rot, resultLength * 0.75f);
if(lightningSpacing > 0){
int idx = 0;
for(float i = 0; i <= resultLength; i += lightningSpacing){
float cx = b.x + Angles.trnsx(rot, i),
cy = b.y + Angles.trnsy(rot, i);
int f = idx++;
for(int s : Mathf.signs){
Time.run(f * lightningDelay, () -> {
if(b.isAdded() && b.type == this){
Lightning.create(b, lightningColor,
lightningDamage < 0 ? damage : lightningDamage,
cx, cy, rot + 90*s + Mathf.range(lightningAngleRand),
lightningLength + Mathf.random(lightningLengthRand));
}
});
}
}
}
} }
@Override @Override

View File

@@ -4,6 +4,12 @@ import mindustry.content.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.gen.*; import mindustry.gen.*;
//TODO this class is bad for multiple reasons, remove/replace it.
//- effects unreliable
//- not really hitscan but works like it
//- buggy trails
//- looks bad
//- generally unreliable
public class RailBulletType extends BulletType{ public class RailBulletType extends BulletType{
public Effect pierceEffect = Fx.hitBulletSmall, updateEffect = Fx.none; public Effect pierceEffect = Fx.hitBulletSmall, updateEffect = Fx.none;
/** Multiplier of damage decreased per health pierced. */ /** Multiplier of damage decreased per health pierced. */
@@ -37,7 +43,9 @@ public class RailBulletType extends BulletType{
@Override @Override
public void update(Bullet b){ public void update(Bullet b){
updateEffect.at(b.x, b.y, b.rotation()); if(b.timer(1, 0.9f)){
updateEffect.at(b.x, b.y, b.rotation());
}
} }
@Override @Override

View File

@@ -13,6 +13,7 @@ public class ShrapnelBulletType extends BulletType{
public float length = 100f; public float length = 100f;
public float width = 20f; public float width = 20f;
public Color fromColor = Color.white, toColor = Pal.lancerLaser; public Color fromColor = Color.white, toColor = Pal.lancerLaser;
public boolean hitLarge = false;
public int serrations = 7; public int serrations = 7;
public float serrationLenScl = 10f, serrationWidth = 4f, serrationSpacing = 8f, serrationSpaceOffset = 80f, serrationFadeOffset = 0.5f; public float serrationLenScl = 10f, serrationWidth = 4f, serrationSpacing = 8f, serrationSpaceOffset = 80f, serrationFadeOffset = 0.5f;
@@ -30,7 +31,14 @@ public class ShrapnelBulletType extends BulletType{
@Override @Override
public void init(Bullet b){ public void init(Bullet b){
Damage.collideLaser(b, length); Damage.collideLaser(b, length, hitLarge);
}
@Override
public void init(){
super.init();
drawSize = Math.max(drawSize, length*2f);
} }
@Override @Override

View File

@@ -1,23 +1,18 @@
package mindustry.entities.comp; package mindustry.entities.comp;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.entities.*;
import mindustry.entities.EntityCollisions.*;
import mindustry.gen.*; import mindustry.gen.*;
import static mindustry.Vars.*;
@Component @Component
abstract class ElevationMoveComp implements Velc, Posc, Flyingc, Hitboxc{ abstract class ElevationMoveComp implements Velc, Posc, Flyingc, Hitboxc{
@Import float x, y; @Import float x, y;
@Replace @Replace
@Override @Override
public void move(float cx, float cy){ public SolidPred solidity(){
if(isFlying()){ return isFlying() ? null : EntityCollisions::solid;
x += cx;
y += cy;
}else{
collisions.move(this, cx, cy);
}
} }
} }

View File

@@ -4,16 +4,16 @@ import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.util.*; import arc.util.*;
import mindustry.*; import mindustry.*;
import mindustry.ai.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.entities.EntityCollisions.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.blocks.environment.*; import mindustry.world.blocks.environment.*;
import static mindustry.Vars.*;
@Component @Component
abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
@Import float x, y; @Import float x, y;
@@ -26,8 +26,14 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
@Replace @Replace
@Override @Override
public void move(float cx, float cy){ public SolidPred solidity(){
collisions.moveCheck(this, cx, cy, !type.allowLegStep ? EntityCollisions::solid : EntityCollisions::legsSolid); return !type.allowLegStep ? EntityCollisions::solid : EntityCollisions::legsSolid;
}
@Override
@Replace
public int pathType(){
return Pathfinder.costLegs;
} }
@Override @Override

View File

@@ -1,6 +1,7 @@
package mindustry.entities.comp; package mindustry.entities.comp;
import arc.math.*; import arc.math.*;
import arc.math.geom.*;
import arc.util.*; import arc.util.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.gen.*; import mindustry.gen.*;
@@ -9,11 +10,24 @@ import mindustry.gen.*;
abstract class MechComp implements Posc, Flyingc, Hitboxc, Unitc, Mechc, ElevationMovec{ abstract class MechComp implements Posc, Flyingc, Hitboxc, Unitc, Mechc, ElevationMovec{
@SyncField(false) @SyncLocal float baseRotation; @SyncField(false) @SyncLocal float baseRotation;
transient float walkTime, walkExtension; transient float walkTime, walkExtension;
transient private boolean walked;
@Override @Override
public void update(){ public void update(){
float len = deltaLen(); //trigger animation only when walking manually
baseRotation = Angles.moveToward(baseRotation, deltaAngle(), type().baseRotateSpeed * Mathf.clamp(len / type().speed / Time.delta) * Time.delta); if(walked){
walkTime += len; float len = deltaLen();
baseRotation = Angles.moveToward(baseRotation, deltaAngle(), type().baseRotateSpeed * Mathf.clamp(len / type().speed / Time.delta) * Time.delta);
walkTime += len;
walked = false;
}
}
@Override
public void moveAt(Vec2 vector, float acceleration){
if(!vector.isZero()){
//mark walking state when moving in a controlled manner
walked = true;
}
} }
} }

View File

@@ -25,15 +25,15 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
} }
boolean canPickup(Unit unit){ boolean canPickup(Unit unit){
return payloadUsed() + unit.hitSize * unit.hitSize <= type.payloadCapacity; return payloadUsed() + unit.hitSize * unit.hitSize <= type.payloadCapacity + 0.001f;
} }
boolean canPickup(Building build){ boolean canPickup(Building build){
return payloadUsed() + build.block.size * build.block.size * Vars.tilesize * Vars.tilesize <= type.payloadCapacity; return payloadUsed() + build.block.size * build.block.size * Vars.tilesize * Vars.tilesize <= type.payloadCapacity + 0.001f;
} }
boolean canPickupPayload(Payload pay){ boolean canPickupPayload(Payload pay){
return payloadUsed() + pay.size()*pay.size() <= type.payloadCapacity; return payloadUsed() + pay.size()*pay.size() <= type.payloadCapacity + 0.001f;
} }
boolean hasPayload(){ boolean hasPayload(){
@@ -98,7 +98,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
Unit u = payload.unit; Unit u = payload.unit;
//can't drop ground units //can't drop ground units
if(((tileOn() == null || tileOn().solid()) && u.elevation < 0.1f) || (!floorOn().isLiquid && u instanceof WaterMovec)){ if(!u.canPass(tileX(), tileY())){
return false; return false;
} }

View File

@@ -8,6 +8,7 @@ import arc.scene.ui.layout.*;
import arc.struct.*; import arc.struct.*;
import arc.util.ArcAnnotate.*; import arc.util.ArcAnnotate.*;
import arc.util.*; import arc.util.*;
import mindustry.ai.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.ctype.*; import mindustry.ctype.*;
@@ -37,7 +38,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
private UnitController controller; private UnitController controller;
private UnitType type; private UnitType type;
boolean spawnedByCore, deactivated; //TODO remove deactivation boolean boolean spawnedByCore;
transient Seq<Ability> abilities = new Seq<>(0); transient Seq<Ability> abilities = new Seq<>(0);
@@ -69,7 +70,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Replace @Replace
public float clipSize(){ public float clipSize(){
return type.region.width * 2f; return Math.max(type.region.width * 2f, type.clipSize);
} }
@Override @Override
@@ -103,7 +104,14 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override @Override
@Replace @Replace
public boolean canDrown(){ public boolean canDrown(){
return isGrounded() && !hovering && type.canDrown && !(this instanceof WaterMovec); return isGrounded() && !hovering && type.canDrown;
}
@Override
@Replace
public boolean canShoot(){
//cannot shoot while boosting
return !(type.canBoost && isFlying());
} }
@Override @Override
@@ -149,8 +157,13 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
return type; return type;
} }
/** @return pathfinder path type for calculating costs */
public int pathType(){
return Pathfinder.costGround;
}
public void lookAt(float angle){ public void lookAt(float angle){
rotation = Angles.moveToward(rotation, angle, type.rotateSpeed * Time.delta); rotation = Angles.moveToward(rotation, angle, type.rotateSpeed * Time.delta * speedMultiplier());
} }
public void lookAt(Position pos){ public void lookAt(Position pos){
@@ -206,12 +219,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
public void add(){ public void add(){
//check if over unit cap //check if over unit cap
if(count() > cap() && !spawnedByCore){ if(count() > cap() && !spawnedByCore && !dead){
deactivated = true; Call.unitCapDeath(self());
teamIndex.updateCount(team, type, -1);
if(!dead){
Call.unitCapDeath(self());
}
} }
} }
@@ -232,22 +242,13 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override @Override
public void update(){ public void update(){
//activate the unit when possible
if(!net.client() && deactivated && teamIndex.countActive(team, type) < Units.getCap(team)){
teamIndex.updateActiveCount(team, type, 1);
deactivated = false;
}
if(!deactivated){ type.update(self());
type.update(self());
if(abilities.size > 0){ if(abilities.size > 0){
for(Ability a : abilities){ for(Ability a : abilities){
a.update(self()); a.update(self());
}
} }
}else if(!dead){
Call.unitCapDeath(self());
} }
drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f); drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f);
@@ -305,18 +306,20 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
if(floor.damageTaken > 0f){ if(floor.damageTaken > 0f){
damageContinuous(floor.damageTaken); damageContinuous(floor.damageTaken);
} }
}
if(tile.solid()){ //kill entities on tiles that are solid to them
if(type.canBoost){ if(tile != null && !canPassOn()){
elevation = 1f; //boost if possible
}else if(!net.client()){ if(type.canBoost){
kill(); elevation = 1f;
} }else if(!net.client()){
kill();
} }
} }
//AI only updates on the server //AI only updates on the server
if(!net.client() && !dead && !deactivated){ if(!net.client() && !dead){
controller.updateUnit(); controller.updateUnit();
} }
@@ -325,11 +328,6 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
resetController(); resetController();
} }
//do not control anything when deactivated
if(deactivated){
controlWeapons(false, false);
}
//remove units spawned by the core //remove units spawned by the core
if(spawnedByCore && !isPlayer()){ if(spawnedByCore && !isPlayer()){
Call.unitDespawn(self()); Call.unitDespawn(self());
@@ -362,7 +360,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
//if this unit crash landed (was flying), damage stuff in a radius //if this unit crash landed (was flying), damage stuff in a radius
if(type.flying){ if(type.flying){
Damage.damage(team,x, y, hitSize * 1.1f, hitSize * type.crashDamageMultiplier, true, false, true); Damage.damage(team,x, y, Mathf.pow(hitSize, 0.94f) * 1.25f, Mathf.pow(hitSize, 0.75f) * type.crashDamageMultiplier * 5f, true, false, true);
} }
if(!headless){ if(!headless){

View File

@@ -3,9 +3,13 @@ package mindustry.entities.comp;
import arc.math.*; import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.util.*; import arc.util.*;
import arc.util.ArcAnnotate.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.entities.EntityCollisions.*;
import mindustry.gen.*; import mindustry.gen.*;
import static mindustry.Vars.*;
@Component @Component
abstract class VelComp implements Posc{ abstract class VelComp implements Posc{
@Import float x, y; @Import float x, y;
@@ -22,12 +26,35 @@ abstract class VelComp implements Posc{
vel.scl(Mathf.clamp(1f - drag * Time.delta)); vel.scl(Mathf.clamp(1f - drag * Time.delta));
} }
/** @return function to use for check solid state. if null, no checking is done. */
@Nullable
SolidPred solidity(){
return null;
}
/** @return whether this entity can move through a location*/
boolean canPass(int tileX, int tileY){
SolidPred s = solidity();
return s == null || !s.solid(tileX, tileY);
}
/** @return whether this entity can exist on its current location*/
boolean canPassOn(){
return canPass(tileX(), tileY());
}
boolean moving(){ boolean moving(){
return !vel.isZero(0.01f); return !vel.isZero(0.01f);
} }
void move(float cx, float cy){ void move(float cx, float cy){
x += cx; SolidPred check = solidity();
y += cy;
if(check != null){
collisions.move(self(), cx, cy, check);
}else{
x += cx;
y += cy;
}
} }
} }

View File

@@ -4,17 +4,17 @@ import arc.graphics.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.math.*; import arc.math.*;
import arc.util.*; import arc.util.*;
import mindustry.ai.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.entities.EntityCollisions.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.environment.*; import mindustry.world.blocks.environment.*;
import static mindustry.Vars.*;
//just a proof of concept //just a proof of concept
@Component @Component
abstract class WaterMoveComp implements Posc, Velc, Hitboxc, Flyingc, Unitc{ abstract class WaterMoveComp implements Posc, Velc, Hitboxc, Flyingc, Unitc{
@@ -38,16 +38,8 @@ abstract class WaterMoveComp implements Posc, Velc, Hitboxc, Flyingc, Unitc{
@Override @Override
@Replace @Replace
public void lookAt(float angle){ public int pathType(){
if(onLiquid()){ return Pathfinder.costWater;
rotation = Angles.moveToward(rotation, angle, type.rotateSpeed * Time.delta);
}
}
@Override
@Replace
public boolean canShoot(){
return onLiquid();
} }
@Override @Override
@@ -74,13 +66,8 @@ abstract class WaterMoveComp implements Posc, Velc, Hitboxc, Flyingc, Unitc{
@Replace @Replace
@Override @Override
public void move(float cx, float cy){ public SolidPred solidity(){
if(isGrounded()){ return isFlying() ? null : EntityCollisions::waterSolid;
collisions.moveCheck(this, cx, cy, EntityCollisions::waterSolid);
}else{
x += cx;
y += cy;
}
} }
@Replace @Replace

View File

@@ -13,7 +13,7 @@ import mindustry.type.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
@Component @Component
abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc, Statusc{
@Import float x, y, rotation, reloadMultiplier; @Import float x, y, rotation, reloadMultiplier;
@Import Vec2 vel; @Import Vec2 vel;
@Import UnitType type; @Import UnitType type;
@@ -85,6 +85,16 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
return true; return true;
} }
@Override
public void remove(){
for(WeaponMount mount : mounts){
if(mount.bullet != null){
mount.bullet.time = mount.bullet.lifetime - 10f;
mount.bullet = null;
}
}
}
/** Update shooting and rotation for this unit. */ /** Update shooting and rotation for this unit. */
@Override @Override
public void update(){ public void update(){
@@ -93,7 +103,27 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
for(WeaponMount mount : mounts){ for(WeaponMount mount : mounts){
Weapon weapon = mount.weapon; Weapon weapon = mount.weapon;
mount.reload = Math.max(mount.reload - Time.delta * reloadMultiplier, 0); mount.reload = Math.max(mount.reload - Time.delta * reloadMultiplier, 0);
mount.heat = Math.max(mount.heat - Time.delta * reloadMultiplier / mount.weapon.cooldownTime, 0);
float weaponRotation = this.rotation - 90 + (weapon.rotate ? mount.rotation : 0);
float mountX = this.x + Angles.trnsx(this.rotation - 90, weapon.x, weapon.y),
mountY = this.y + Angles.trnsy(this.rotation - 90, weapon.x, weapon.y);
float shootX = mountX + Angles.trnsx(weaponRotation, weapon.shootX, weapon.shootY),
shootY = mountY + Angles.trnsy(weaponRotation, weapon.shootX, weapon.shootY);
float shootAngle = weapon.rotate ? weaponRotation + 90 : Angles.angle(shootX, shootY, mount.aimX, mount.aimY) + (this.rotation - angleTo(mount.aimX, mount.aimY));
//update continuous state
if(weapon.continuous && mount.bullet != null){
if(!mount.bullet.isAdded() || mount.bullet.time >= mount.bullet.lifetime){
mount.bullet = null;
}else{
mount.bullet.rotation(weaponRotation + 90);
mount.bullet.set(shootX, shootY);
vel.add(Tmp.v1.trns(rotation + 180f, mount.bullet.type.recoil));
}
}else{
//heat decreases when not firing
mount.heat = Math.max(mount.heat - Time.delta * reloadMultiplier / mount.weapon.cooldownTime, 0);
}
//flip weapon shoot side for alternating weapons at half reload //flip weapon shoot side for alternating weapons at half reload
if(weapon.otherSide != -1 && weapon.alternate && mount.side == weapon.flipSprite && if(weapon.otherSide != -1 && weapon.alternate && mount.side == weapon.flipSprite &&
@@ -104,10 +134,10 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
//rotate if applicable //rotate if applicable
if(weapon.rotate && (mount.rotate || mount.shoot) && can){ if(weapon.rotate && (mount.rotate || mount.shoot) && can){
float axisX = this.x + Angles.trnsx(rotation - 90, weapon.x, weapon.y), float axisX = this.x + Angles.trnsx(this.rotation - 90, weapon.x, weapon.y),
axisY = this.y + Angles.trnsy(rotation - 90, weapon.x, weapon.y); axisY = this.y + Angles.trnsy(this.rotation - 90, weapon.x, weapon.y);
mount.targetRotation = Angles.angle(axisX, axisY, mount.aimX, mount.aimY) - rotation; mount.targetRotation = Angles.angle(axisX, axisY, mount.aimX, mount.aimY) - this.rotation;
mount.rotation = Angles.moveToward(mount.rotation, mount.targetRotation, weapon.rotateSpeed * Time.delta); mount.rotation = Angles.moveToward(mount.rotation, mount.targetRotation, weapon.rotateSpeed * Time.delta);
}else if(!weapon.rotate){ }else if(!weapon.rotate){
mount.rotation = 0; mount.rotation = 0;
@@ -124,21 +154,9 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
mount.reload <= 0.0001f && //reload has to be 0 mount.reload <= 0.0001f && //reload has to be 0
Angles.within(weapon.rotate ? mount.rotation : this.rotation, mount.targetRotation, mount.weapon.shootCone) //has to be within the cone Angles.within(weapon.rotate ? mount.rotation : this.rotation, mount.targetRotation, mount.weapon.shootCone) //has to be within the cone
){ ){
shoot(mount, shootX, shootY, mount.aimX, mount.aimY, shootAngle, Mathf.sign(weapon.x));
float rotation = this.rotation - 90;
float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0);
float mountX = this.x + Angles.trnsx(rotation, weapon.x, weapon.y),
mountY = this.y + Angles.trnsy(rotation, weapon.x, weapon.y);
float shootX = mountX + Angles.trnsx(weaponRotation, weapon.shootX, weapon.shootY),
shootY = mountY + Angles.trnsy(weaponRotation, weapon.shootX, weapon.shootY);
float shootAngle = weapon.rotate ? weaponRotation + 90 : Angles.angle(shootX, shootY, mount.aimX, mount.aimY) + (this.rotation - angleTo(mount.aimX, mount.aimY));
shoot(weapon, shootX, shootY, mount.aimX, mount.aimY, shootAngle, Mathf.sign(weapon.x));
mount.reload = weapon.reload; mount.reload = weapon.reload;
mount.heat = 1f;
ammo--; ammo--;
if(ammo < 0) ammo = 0; if(ammo < 0) ammo = 0;
@@ -146,7 +164,8 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
} }
} }
private void shoot(Weapon weapon, float x, float y, float aimX, float aimY, float rotation, int side){ private void shoot(WeaponMount mount, float x, float y, float aimX, float aimY, float rotation, int side){
Weapon weapon = mount.weapon;
float baseX = this.x, baseY = this.y; float baseX = this.x, baseY = this.y;
@@ -156,29 +175,44 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
float lifeScl = ammo.scaleVelocity ? Mathf.clamp(Mathf.dst(x, y, aimX, aimY) / ammo.range()) : 1f; float lifeScl = ammo.scaleVelocity ? Mathf.clamp(Mathf.dst(x, y, aimX, aimY) / ammo.range()) : 1f;
sequenceNum = 0; sequenceNum = 0;
if(weapon.shotDelay > 0.01f){ if(weapon.shotDelay + weapon.firstShotDelay > 0.01f){
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> { Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> {
Time.run(sequenceNum * weapon.shotDelay, () -> bullet(weapon, x + this.x - baseX, y + this.y - baseY, f + Mathf.range(weapon.inaccuracy), lifeScl)); Time.run(sequenceNum * weapon.shotDelay + weapon.firstShotDelay, () -> {
if(!isAdded()) return;
mount.bullet = bullet(weapon, x + this.x - baseX, y + this.y - baseY, f + Mathf.range(weapon.inaccuracy), lifeScl);
});
sequenceNum++; sequenceNum++;
}); });
}else{ }else{
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> bullet(weapon, x, y, f + Mathf.range(weapon.inaccuracy), lifeScl)); Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> mount.bullet = bullet(weapon, x, y, f + Mathf.range(weapon.inaccuracy), lifeScl));
} }
vel().add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
boolean parentize = ammo.keepVelocity; boolean parentize = ammo.keepVelocity;
Effect.shake(weapon.shake, weapon.shake, x, y); if(weapon.firstShotDelay > 0){
Time.run(weapon.firstShotDelay, () -> {
if(!isAdded()) return;
vel.add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
Effect.shake(weapon.shake, weapon.shake, x, y);
mount.heat = 1f;
});
}else{
vel.add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
Effect.shake(weapon.shake, weapon.shake, x, y);
mount.heat = 1f;
}
weapon.ejectEffect.at(x, y, rotation * side); weapon.ejectEffect.at(x, y, rotation * side);
ammo.shootEffect.at(x, y, rotation, parentize ? this : null); ammo.shootEffect.at(x, y, rotation, parentize ? this : null);
ammo.smokeEffect.at(x, y, rotation, parentize ? this : null); ammo.smokeEffect.at(x, y, rotation, parentize ? this : null);
apply(weapon.shootStatus, weapon.shootStatusDuration);
} }
private void bullet(Weapon weapon, float x, float y, float angle, float lifescl){ private Bullet bullet(Weapon weapon, float x, float y, float angle, float lifescl){
float xr = Mathf.range(weapon.xRand); float xr = Mathf.range(weapon.xRand);
weapon.bullet.create(this, team(), return weapon.bullet.create(this, team(),
x + Angles.trnsx(angle, 0, xr), x + Angles.trnsx(angle, 0, xr),
y + Angles.trnsy(angle, 0, xr), y + Angles.trnsy(angle, 0, xr),
angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd), lifescl); angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd), lifescl);

View File

@@ -1,5 +1,7 @@
package mindustry.entities.units; package mindustry.entities.units;
import arc.util.ArcAnnotate.*;
import mindustry.gen.*;
import mindustry.type.*; import mindustry.type.*;
public class WeaponMount{ public class WeaponMount{
@@ -21,6 +23,8 @@ public class WeaponMount{
public boolean rotate = false; public boolean rotate = false;
/** extra state for alternating weapons */ /** extra state for alternating weapons */
public boolean side; public boolean side;
/** current bullet for continuous weapons */
public @Nullable Bullet bullet;
public WeaponMount(Weapon weapon){ public WeaponMount(Weapon weapon){
this.weapon = weapon; this.weapon = weapon;

View File

@@ -61,6 +61,9 @@ public class Saves{
//automatically assign sector save slots //automatically assign sector save slots
for(SaveSlot slot : saves){ for(SaveSlot slot : saves){
if(slot.getSector() != null){ if(slot.getSector() != null){
if(slot.getSector().save != null){
Log.warn("Sector @ has two corresponding saves: @ and @", slot.getSector(), slot.getSector().save.file, slot.file);
}
slot.getSector().save = slot; slot.getSector().save = slot;
} }
} }
@@ -75,7 +78,6 @@ public class Saves{
} }
public void update(){ public void update(){
SaveSlot current = this.current;
if(current != null && state.isGame() if(current != null && state.isGame()
&& !(state.isPaused() && Core.scene.hasDialog())){ && !(state.isPaused() && Core.scene.hasDialog())){
@@ -90,14 +92,13 @@ public class Saves{
if(time > Core.settings.getInt("saveinterval") * 60){ if(time > Core.settings.getInt("saveinterval") * 60){
saving = true; saving = true;
Time.runTask(2f, () -> { try{
try{ current.save();
current.save(); }catch(Throwable e){
}catch(Throwable e){ e.printStackTrace();
e.printStackTrace(); }
}
saving = false; Time.runTask(3f, () -> saving = false);
});
time = 0; time = 0;
} }

View File

@@ -2,9 +2,7 @@ package mindustry.game;
import arc.files.*; import arc.files.*;
import arc.struct.*; import arc.struct.*;
import arc.struct.IntIntMap.*;
import arc.util.ArcAnnotate.*; import arc.util.ArcAnnotate.*;
import mindustry.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.mod.Mods.*; import mindustry.mod.Mods.*;
import mindustry.type.*; import mindustry.type.*;
@@ -38,20 +36,16 @@ public class Schematic implements Publishable, Comparable<Schematic>{
return tiles.sumf(s -> s.block.consumes.has(ConsumeType.power) ? s.block.consumes.getPower().usage : 0f); return tiles.sumf(s -> s.block.consumes.has(ConsumeType.power) ? s.block.consumes.getPower().usage : 0f);
} }
public Seq<ItemStack> requirements(){ public ItemSeq requirements(){
IntIntMap amounts = new IntIntMap(); ItemSeq requirements = new ItemSeq();
tiles.each(t -> { tiles.each(t -> {
for(ItemStack stack : t.block.requirements){ for(ItemStack stack : t.block.requirements){
amounts.increment(stack.item.id, stack.amount); requirements.add(stack.item, stack.amount);
} }
}); });
Seq<ItemStack> stacks = new Seq<>();
for(Entry ent : amounts.entries()){ return requirements;
stacks.add(new ItemStack(Vars.content.item(ent.key), ent.value));
}
stacks.sort();
return stacks;
} }
public boolean hasCore(){ public boolean hasCore(){

Some files were not shown because too many files have changed in this diff Show More