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
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

+7
View File
@@ -489,6 +489,7 @@ loadout = Loadout
resources = Resources
bannedblocks = Banned Blocks
addall = Add All
launch.destination = Destination: {0}
configure.invalid = Amount must be a number between 0 and {0}.
zone.unlocked = [lightgray]{0} unlocked.
zone.requirement.complete = Requirement for {0} completed:[lightgray]\n{1}
@@ -521,6 +522,8 @@ sectors.production = Production:
sectors.stored = Stored:
sectors.resume = Resume
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
sector.groundZero.name = Ground Zero
@@ -920,6 +923,8 @@ unit.eclipse.name = Eclipse
unit.mono.name = Mono
unit.poly.name = Poly
unit.mega.name = Mega
unit.quad.name = Quad
unit.oct.name = Oct
unit.risso.name = Risso
unit.minke.name = Minke
unit.bryde.name = Bryde
@@ -930,6 +935,8 @@ unit.beta.name = Beta
unit.gamma.name = Gamma
unit.scepter.name = Scepter
unit.reign.name = Reign
unit.vela.name = Vela
unit.corvus.name = Corvus
block.resupply-point.name = Resupply Point
block.parallax.name = Parallax
+66 -17
View File
@@ -20,6 +20,8 @@ gameover = Konec hry
gameover.pvp = Vyhrál tým [accent]{0}[]!
highscore = [accent]Nový rekord!
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.map = Mapy
@@ -113,6 +115,7 @@ mod.disable = Zakázat
mod.content = Obsah:
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.outdated = [scarlet]Nekompatibilní s V6 (chybí minGameVersion: 105)
mod.missingdependencies = [scarlet]Chybějící závislosti: {0}[]
mod.erroredcontent = [scarlet]V obsahu jsou chyby[]
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
name = Jméno:
noname = Nejdřív si vyber [accent]jméno ve hře[].
planetmap = Planetární mapa
launchcore = Vyslat jádro
filename = Název souboru:
unlocked = Byl odemmknut nový blok!
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.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
sector.groundZero.name = Základní tábor
sector.craters.name = Krátery
@@ -573,8 +590,11 @@ blocks.itemsmoved = Rychlost pohybu
blocks.launchtime = Čas mezi vysláním
blocks.shootrange = Dostřel
blocks.size = Velikost
blocks.displaysize = Velikost zobrazovače
blocks.liquidcapacity = Kapacita kapalin
blocks.powerrange = Rozsah energie
blocks.linkrange = Dosah napojení
blocks.instructions = Instrukce
blocks.powerconnections = Nejvyšší počet spojení
blocks.poweruse = Spotřeba energie
blocks.powerdamage = Energie na jednotku poškození
@@ -596,6 +616,8 @@ blocks.inaccuracy = Nepřesnost
blocks.shots = Střely
blocks.reload = Střel za 1s
blocks.ammo = Střelivo
blocks.shieldhealth = Zdraví štítu
blocks.cooldowntime = Čas na zchladnutí
bar.drilltierreq = Je vyžadován lepší vrt
bar.noresources = Chybějí zdroje
@@ -638,9 +660,12 @@ unit.liquidunits = jednotek kapalin
unit.powerunits = jednotek energie
unit.degrees = úhly
unit.seconds = sekundy
unit.minutes = minuty
unit.persecond = /s
unit.perminute = /min
unit.timesspeed = x větší rychlost
unit.percent = %
unit.shieldhealth = zdraví štítu
unit.items = předměty
unit.thousands = tis
unit.millions = mio
@@ -727,6 +752,7 @@ category.blocks.name = Výběr bloků
command.attack = Útok
command.rally = Shromáždění
command.retreat = Ústup
command.idle = Nečinný
placement.blockselectkeys = \n[lightgray]Klávesa:[] [{0},
keybind.respawn.name = Znovuzrození
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_y.name = Pohyb svisle
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_menu.name = Nabídka šablon
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.break_block.name = Rozbít blok
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.zoom.name = Přiblížení
keybind.menu.name = Hlavní nabídka
@@ -800,6 +830,7 @@ rules.reactorexplosions = Výbuch reaktoru
rules.wavetimer = Časovač vln
rules.waves = Vlny
rules.attack = Režim útoku
rules.buildai = Umělá inteligence staví
rules.enemyCheat = Neomezeně surovin pro umělou inteligenci
rules.blockhealthmultiplier = Násobek zdraví bloků
rules.blockdamagemultiplier = Násobek poškození bloků
@@ -821,8 +852,12 @@ rules.title.unit = Jednotky
rules.title.experimental = Experimentální
rules.title.environment = Environmentální
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.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.liquid.name = Kapaliny
@@ -848,9 +883,11 @@ liquid.water.name = Voda
liquid.slag.name = Roztavený kov
liquid.oil.name = Nafta
liquid.cryofluid.name = Chladící kapalina
item.explosiveness = [lightgray]Výbušnost: {0}%[]
item.flammability = [lightgray]Zápalnost: {0}%[]
item.radioactivity = [lightgray]Radioaktivita: {0}%[]
unit.health = [lightgray]Životy: {0}[]
unit.speed = [lightgray]Rychlost: {0}[]
unit.weapon = [lightgray]Zbraň: {0}
@@ -872,8 +909,9 @@ unit.pulsar.name = Pulzar
unit.quasar.name = Kvasar
unit.crawler.name = Slídil
unit.atrax.name = Atrax
unit.spiroct.name = Spiroct
unit.spiroct.name = Spirokt
unit.arkyid.name = Arkyid
unit.toxopid.name = Toxopid
unit.flare.name = Záře
unit.horizon.name = Horizont
unit.zenith.name = Zenit
@@ -885,31 +923,36 @@ unit.mega.name = Mega
unit.risso.name = Risso
unit.minke.name = Minke
unit.bryde.name = Bryde
unit.sei.name = Sei
unit.omura.name = Omura
unit.alpha.name = Alfa
unit.beta.name = Beta
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.cliff.name = Útes
block.sand-boulder.name = Pískovec
block.grass.name = Tráva
block.slag.name = Slag
block.salt.name = Sůl
block.saltrocks.name = Solný kámen
block.salt-wall.name = Solné skály
block.pebbles.name = Oblázky
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.sporerocks.name = Spórové kamení
block.rock.name = Kámen
block.snowrock.name = Sněhový kámen
block.spore-wall.name = Spórové skály
block.boulder.name = Kámen
block.snow-boulder.name = Sněhový kámen
block.snow-pine.name = Sněžná borovice
block.shale.name = Břidlice
block.shale-boulder.name = Břidličný balvan
block.moss.name = Mech
block.shrubs.name = Křoví
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-large.name = Velká 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.sand-water.name = Voda s pískem
block.darksand-water.name = Voda s černým pískem
block.char.name = Char
block.holostone.name = Blok kamene
block.char.name = Dřevěné uhlí
block.dacite.name = Dacit
block.dacite-wall.name = Stěna dacitu
block.ice-snow.name = Zasněžený led
block.rocks.name = Skály
block.icerocks.name = Ledové skály
block.snowrocks.name = Sněhové skály
block.dunerocks.name = Písečné duny
block.stone wall.name = Skály
block.ice-wall.name = Ledové skály
block.snow-wall.name = Sněhové skály
block.dune-wall.name = Písečné duny
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.name = Bílý strom
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-6.name = Tmavá deska 6
block.dark-metal.name = Tmavý kov
block.ignarock.name = Třaskavec
block.basalt.name = Čedič
block.hotrock.name = Horký kámen
block.magmarock.name = Magmatický kámen
block.cliffs.name = Útesy
block.copper-wall.name = Měděná zeď
block.copper-wall-large.name = Velká měděná 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-large.name = Velká vysílací plošina
block.segment.name = Úsek
block.command-center.name = Velín
block.ground-factory.name = Pozemní továrna
block.air-factory.name = Letecká 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.micro-processor.name = Mikroprocesor
block.logic-processor.name = Logický procesor
block.hyper-processor.name = Hyperprocesor
block.logic-display.name = Zobrazovač logiky
block.large-logic-display.name = Velký zobrazovač logiky
block.memory-cell.name = Paměťová buňka
team.blue.name = modrý
+1
View File
@@ -92,3 +92,4 @@ SnakkiZXZ
sk7725
ThePlayerA
YellOw139
PetrGasparik
+4
View File
@@ -314,3 +314,7 @@
63430=omura|unit-omura-medium
63429=mud|block-mud-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
+1
View File
@@ -74,6 +74,7 @@ importPackage(Packages.mindustry.gen)
importPackage(Packages.mindustry.graphics)
importPackage(Packages.mindustry.graphics.g3d)
importPackage(Packages.mindustry.input)
importPackage(Packages.mindustry.io)
importPackage(Packages.mindustry.logic)
importPackage(Packages.mindustry.maps)
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

+7 -3
View File
@@ -72,6 +72,8 @@ public class Vars implements Loadable{
public static final int maxTextLength = 150;
/** max player name length in bytes */
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. */
public static final float itemSize = 5f;
/** units outside of this bound will die instantly */
@@ -87,15 +89,17 @@ public class Vars implements Loadable{
/** turns needed to destroy a sector completely */
public static final float sectorDestructionTurns = 3f;
/** 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 */
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 */
public static Tile emptyTile;
/** for map generator dialog */
public static boolean updateEditorOnChange = false;
/** size of tiles in units */
public static final int tilesize = 8;
/** all choosable player colors in join/host dialog */
public static final Color[] playerColors = {
Color.valueOf("82759a"),
+8 -3
View File
@@ -43,7 +43,8 @@ public class Pathfinder implements Runnable{
PathTile.health(tile) * 5 +
(PathTile.nearSolid(tile) ? 2 : 0) +
(PathTile.nearLiquid(tile) ? 6 : 0) +
(PathTile.deep(tile) ? 70 : 0),
(PathTile.deep(tile) ? 70 : 0) +
(PathTile.damages(tile) ? 30 : 0),
//legs
(team, tile) -> PathTile.legSolid(tile) ? impassable : 1 +
@@ -52,7 +53,8 @@ public class Pathfinder implements Runnable{
//water
(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.deep(tile) ? -1 : 0)
(PathTile.deep(tile) ? -1 : 0) +
(PathTile.damages(tile) ? 35 : 0)
);
//maps team, cost, type to flow field
@@ -122,7 +124,8 @@ public class Pathfinder implements Runnable{
nearLiquid,
nearGround,
nearSolid,
tile.floor().isDeep()
tile.floor().isDeep(),
tile.floor().damageTaken > 0.00001f
);
}
@@ -514,5 +517,7 @@ public class Pathfinder implements Runnable{
boolean nearSolid;
//whether this block is deep / drownable
boolean deep;
//whether the floor damages
boolean damages;
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ import mindustry.world.blocks.ConstructBlock.*;
import static mindustry.Vars.*;
public class BuilderAI extends AIController{
float buildRadius = 700;
float buildRadius = 1500;
boolean found = false;
@Nullable Builderc following;
+1 -2
View File
@@ -25,8 +25,7 @@ public class FlyingAI extends AIController{
}
if(command() == UnitCommand.rally){
target = targetFlag(unit.x, unit.y, BlockFlag.rally, false);
moveTo(target, 60f);
moveTo(targetFlag(unit.x, unit.y, BlockFlag.rally, false), 60f);
}
}
@@ -1,5 +1,6 @@
package mindustry.ai.types;
import arc.math.*;
import arc.math.geom.*;
import arc.util.ArcAnnotate.*;
import mindustry.ai.formations.*;
@@ -32,6 +33,10 @@ public class FormationAI extends AIController implements FormationMember{
return;
}
if(unit.type().canBoost && unit.canPassOn()){
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f);
}
unit.controlWeapons(true, leader.isShooting);
// unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed));
+4 -7
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);
}
@@ -74,15 +74,12 @@ public class GroundAI extends AIController{
}*/
}
protected void moveTo(int pathType){
int costType =
unit instanceof Legsc ? Pathfinder.costLegs :
unit instanceof WaterMovec ? Pathfinder.costWater :
Pathfinder.costGround;
protected void moveTo(int pathTarget){
int costType = unit.pathType();
Tile tile = unit.tileOn();
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;
+1 -1
View File
@@ -44,7 +44,7 @@ public class MinerAI extends AIController{
}
if(ore != null){
moveTo(ore, unit.type().range / 1.5f);
moveTo(ore, unit.type().range / 2f);
if(unit.within(ore, unit.type().range)){
miner.mineTile(ore);
+3 -1
View File
@@ -14,7 +14,9 @@ public class RepairAI extends AIController{
if(target != null){
if(!target.within(unit, unit.type().range * 0.8f)){
moveTo(target, unit.type().range * 0.8f);
}else{
}
if(target.within(unit, unit.type().range)){
unit.aim(target);
shoot = true;
}
@@ -14,7 +14,6 @@ public class TeamIndexProcess implements AsyncProcess{
private QuadTree<Unit>[] trees = new QuadTree[Team.all.length];
private int[] counts = new int[Team.all.length];
private int[][] typeCounts = new int[Team.all.length][0];
private int[][] activeCounts = new int[Team.all.length][0];
public QuadTree<Unit> tree(Team team){
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];
}
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){
counts[team.id] += amount;
if(typeCounts[team.id].length <= type.id){
@@ -42,16 +37,8 @@ public class TeamIndexProcess implements AsyncProcess{
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){
updateCount(unit.team, unit.type(), 1);
if(!unit.deactivated) updateActiveCount(unit.team, unit.type(), 1);
if(unit instanceof Payloadc){
((Payloadc)unit).payloads().each(p -> {
@@ -77,7 +64,6 @@ public class TeamIndexProcess implements AsyncProcess{
}
Arrays.fill(typeCounts[team.id], 0);
Arrays.fill(activeCounts[team.id], 0);
}
Arrays.fill(counts, 0);
+15 -9
View File
@@ -1267,7 +1267,7 @@ public class Blocks implements ContentList{
rotateSpeed = 1.4f;
attribute = Attribute.water;
consumes.power(1f);
consumes.power(1.25f);
}};
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));
unitType = UnitTypes.beta;
health = 2000;
health = 3500;
itemCapacity = 9000;
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));
unitType = UnitTypes.gamma;
health = 4000;
health = 6000;
itemCapacity = 13000;
size = 5;
@@ -1377,7 +1377,7 @@ public class Blocks implements ContentList{
ammoUseEffect = Fx.shellEjectSmall;
health = 250;
inaccuracy = 2f;
rotatespeed = 10f;
rotateSpeed = 10f;
}};
scatter = new ItemTurret("scatter"){{
@@ -1395,7 +1395,7 @@ public class Blocks implements ContentList{
targetGround = false;
recoilAmount = 2f;
rotatespeed = 15f;
rotateSpeed = 15f;
inaccuracy = 17f;
shootCone = 35f;
@@ -1498,7 +1498,7 @@ public class Blocks implements ContentList{
}};
reloadTime = 35f;
shootCone = 40f;
rotatespeed = 8f;
rotateSpeed = 8f;
powerUse = 4f;
targetAir = false;
range = 90f;
@@ -1597,8 +1597,10 @@ public class Blocks implements ContentList{
health = 220 * size * size;
shootSound = Sounds.shotgun;
float brange = range + 10f;
ammo(Items.thorium, new ShrapnelBulletType(){{
length = range + 10f;
length = brange;
damage = 105f;
ammoMultiplier = 6f;
}});
@@ -1647,7 +1649,7 @@ public class Blocks implements ContentList{
range = 200f;
size = 3;
recoilAmount = 3f;
rotatespeed = 10f;
rotateSpeed = 10f;
inaccuracy = 10f;
shootCone = 30f;
shootSound = Sounds.shootSnap;
@@ -1805,6 +1807,8 @@ public class Blocks implements ContentList{
{UnitTypes.spiroct, UnitTypes.arkyid},
{UnitTypes.fortress, UnitTypes.scepter},
{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.arkyid, UnitTypes.toxopid},
{UnitTypes.scepter, UnitTypes.reign},
{UnitTypes.sei, UnitTypes.omura}
{UnitTypes.sei, UnitTypes.omura},
{UnitTypes.quad, UnitTypes.oct},
{UnitTypes.vela, UnitTypes.corvus}
};
}};
+64 -1
View File
@@ -145,7 +145,7 @@ public class Fx{
int i = 0;
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);
}),
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 -> {
color(Pal.heal);
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 -> {
color(Color.white, Pal.heal, e.fin());
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);
});
}),
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 -> {
randLenVectors(e.id, 6, 4f + e.fin() * 5f, (x, y) -> {
@@ -9,7 +9,7 @@ import mindustry.type.StatusEffect;
import static mindustry.Vars.*;
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
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"){{
color = Color.royal;
speedMultiplier = 0.94f;
+6 -2
View File
@@ -263,7 +263,7 @@ public class TechTree implements ContentList{
node(steamGenerator, () -> {
node(thermalGenerator, () -> {
node(differentialGenerator, () -> {
node(thoriumReactor, () -> {
node(thoriumReactor, Seq.with(new Research(Liquids.cryofluid)), () -> {
node(impactReactor, () -> {
});
@@ -409,7 +409,11 @@ public class TechTree implements ContentList{
node(mono, () -> {
node(poly, () -> {
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){
TechNode node = new TechNode(content, empty, children);
TechNode node = new TechNode(content, content.researchRequirements(), children);
node.objectives = objectives;
return node;
}
+235 -21
View File
@@ -11,15 +11,23 @@ import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import static mindustry.Vars.*;
public class UnitTypes implements ContentList{
//region definitions
//ground
//mech
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;
//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
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;
//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
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType alpha, beta, gamma;
@@ -257,7 +265,7 @@ public class UnitTypes implements ContentList{
itemCapacity = 60;
canBoost = true;
boostMultiplier = 1.5f;
speed = 0.52f;
speed = 0.55f;
hitsize = 8f;
health = 110f;
buildSpeed = 0.8f;
@@ -283,7 +291,7 @@ public class UnitTypes implements ContentList{
itemCapacity = 60;
canBoost = true;
boostMultiplier = 1.5f;
speed = 0.62f;
speed = 0.65f;
hitsize = 10f;
health = 320f;
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
//region ground legs
@@ -405,6 +543,7 @@ public class UnitTypes implements ContentList{
targetAir = false;
health = 600;
immunities = ObjectSet.with(StatusEffects.burning, StatusEffects.melting);
legCount = 4;
legLength = 9f;
legTrns = 0.6f;
@@ -603,8 +742,8 @@ public class UnitTypes implements ContentList{
drag = 0.1f;
speed = 0.5f;
hitsize = 21f;
health = 23000;
armor = 14f;
health = 22000;
armor = 13f;
rotateSpeed = 1.9f;
@@ -729,7 +868,6 @@ public class UnitTypes implements ContentList{
faceTarget = false;
engineOffset = 5.5f;
range = 140f;
crashDamageMultiplier = 4f;
weapons.add(new Weapon(){{
y = 0f;
@@ -1047,6 +1185,8 @@ public class UnitTypes implements ContentList{
mineTier = 2;
health = 500;
armor = 2f;
armor = 5f;
speed = 1.8f;
accel = 0.06f;
drag = 0.017f;
@@ -1056,7 +1196,7 @@ public class UnitTypes implements ContentList{
rotateShooting = false;
hitsize = 15f;
engineSize = 3f;
payloadCapacity = 4 * (8 * 8);
payloadCapacity = (2 * 2) * tilePayload;
buildSpeed = 2.5f;
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
//region naval attack
@@ -1086,7 +1306,6 @@ public class UnitTypes implements ContentList{
health = 280;
accel = 0.4f;
rotateSpeed = 3.3f;
immunities = ObjectSet.with(StatusEffects.wet);
trailLength = 20;
rotateShooting = false;
@@ -1138,14 +1357,12 @@ public class UnitTypes implements ContentList{
armor = 4f;
accel = 0.3f;
rotateSpeed = 2.6f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
trailLength = 20;
trailX = 5.5f;
trailY = -4f;
trailScl = 1.9f;
rotateShooting = false;
abilities.add(new StatusFieldAbility(StatusEffects.overclock, 60f * 6, 60f * 6f, 60f));
@@ -1180,8 +1397,7 @@ public class UnitTypes implements ContentList{
rotateSpeed = 1.8f;
drag = 0.17f;
hitsize = 16f;
armor = 6f;
immunities = ObjectSet.with(StatusEffects.wet);
armor = 7f;
rotateShooting = false;
trailLength = 22;
@@ -1189,7 +1405,7 @@ public class UnitTypes implements ContentList{
trailY = -9f;
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"){{
reload = 65f;
@@ -1276,7 +1492,6 @@ public class UnitTypes implements ContentList{
hitsize = 39f;
accel = 0.2f;
rotateSpeed = 1.3f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
trailLength = 50;
@@ -1361,10 +1576,9 @@ public class UnitTypes implements ContentList{
armor = 16f;
accel = 0.19f;
rotateSpeed = 0.9f;
immunities = ObjectSet.with(StatusEffects.wet);
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));
@@ -1415,7 +1629,7 @@ public class UnitTypes implements ContentList{
mineTier = 1;
buildSpeed = 0.5f;
drag = 0.05f;
speed = 2.6f;
speed = 2.8f;
rotateSpeed = 15f;
accel = 0.1f;
itemCapacity = 30;
@@ -1449,7 +1663,7 @@ public class UnitTypes implements ContentList{
mineTier = 1;
buildSpeed = 0.75f;
drag = 0.05f;
speed = 2.9f;
speed = 3f;
rotateSpeed = 17f;
accel = 0.1f;
itemCapacity = 50;
@@ -1489,7 +1703,7 @@ public class UnitTypes implements ContentList{
mineTier = 2;
buildSpeed = 1f;
drag = 0.05f;
speed = 3.4f;
speed = 3.5f;
rotateSpeed = 19f;
accel = 0.11f;
itemCapacity = 70;
+8
View File
@@ -45,4 +45,12 @@ public class Version{
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);
}
}
@@ -31,7 +31,7 @@ public abstract class UnlockableContent extends MappableContent{
this.localizedName = Core.bundle.get(getContentType() + "." + this.name + ".name", this.name);
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(){
+14 -12
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 collideLaser(Bullet b, float length){
public static float findLaserLength(Bullet b, float length){
Tmp.v1.trns(b.rotation(), length);
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);
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);
b.fdata = furthest != null ? resultLength : length;
/** 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 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;
}
@@ -103,6 +108,8 @@ public class Damage{
* 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){
length = findLaserLength(hitter, length);
collidedBlocks.clear();
tr.trns(angle, length);
Intc2 collider = (cx, cy) -> {
@@ -150,13 +157,8 @@ public class Damage{
if(!e.checkTarget(hitter.type.collidesAir, hitter.type.collidesGround)) return;
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){
effect.at(vec.x, vec.y);
+1 -1
View File
@@ -40,7 +40,7 @@ public class Effect{
}
public Effect(float life, Cons<EffectContainer> renderer){
this(life, 32f, renderer);
this(life,50f, renderer);
}
public Effect ground(){
+16 -1
View File
@@ -24,7 +24,7 @@ public class Units{
if(unit != null){
unit.dead = true;
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)
public static void unitDespawn(Unit unit){
Fx.unitDespawn.at(unit.x, unit.y, 0, unit);
@@ -21,8 +21,8 @@ public class ForceFieldAbility extends Ability{
/** Cooldown after the shield is broken, in ticks. */
public float cooldown = 60f * 5;
/** State: radius scaling. */
protected float radiusScale;
/** State. */
protected float radiusScale, alpha;
private static float realRad;
private static Unit paramUnit;
@@ -40,7 +40,7 @@ public class ForceFieldAbility extends Ability{
}
paramUnit.shield -= trait.damage();
paramUnit.shieldAlpha = 1f;
paramField.alpha = 1f;
}
};
@@ -59,6 +59,8 @@ public class ForceFieldAbility extends Ability{
unit.shield += Time.delta * regen;
}
alpha = Math.max(alpha - Time.delta/10f, 0f);
if(unit.shield > 0){
radiusScale = Mathf.lerpDelta(radiusScale, 1f, 0.06f);
paramUnit = unit;
@@ -78,7 +80,7 @@ public class ForceFieldAbility extends Ability{
if(unit.shield > 0){
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")){
Fill.poly(unit.x, unit.y, 6, realRad);
@@ -8,7 +8,7 @@ import mindustry.gen.*;
public class HealFieldAbility extends Ability{
public float amount = 1, reload = 100, range = 60;
public Effect healEffect = Fx.heal;
public Effect activeEffect = Fx.healWave;
public Effect activeEffect = Fx.healWaveDynamic;
protected float timer;
protected boolean wasHealed = false;
@@ -37,7 +37,7 @@ public class HealFieldAbility extends Ability{
});
if(wasHealed){
activeEffect.at(unit);
activeEffect.at(unit, range);
}
timer = 0f;
@@ -1,16 +1,17 @@
package mindustry.entities.bullet;
import arc.Core;
import arc.graphics.Color;
import arc.graphics.g2d.Draw;
import arc.graphics.g2d.TextureRegion;
import arc.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
import mindustry.gen.*;
import mindustry.graphics.Pal;
import mindustry.graphics.*;
/** An extended BulletType for most ammo-based bullets shot from turrets and units. */
public class BasicBulletType extends BulletType{
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 shrinkX = 0f, shrinkY = 0.5f;
public float spin = 0;
@@ -45,10 +46,15 @@ public class BasicBulletType extends BulletType{
float width = this.width * ((1f - shrinkX) + shrinkX * b.fout());
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.rect(backRegion, b.x, b.y, width, height, b.rotation() + offset);
Draw.color(frontColor);
Draw.rect(frontRegion, b.x, b.y, width, height, b.rotation() + offset);
Draw.color();
Draw.reset();
}
}
@@ -71,6 +71,8 @@ public abstract class BulletType extends Content{
public boolean hittable = true;
/** Whether this bullet can be reflected. */
public boolean reflectable = true;
/** Bullet range override. */
public float range = -1f;
//additional effects
@@ -96,13 +98,13 @@ public abstract class BulletType extends Content{
public Color lightningColor = Pal.surge;
public int lightning;
public int lightningLength = 5;
public int lightningLength = 5, lightningLengthRand = 0;
/** Use a negative value to use default bullet damage. */
public float lightningDamage = -1;
public float weaveScale = 1f;
public float weaveMag = -1f;
public float hitShake = 0f;
public float hitShake = 0f, despawnShake = 0f;
public int puddles;
public float puddleRange;
@@ -126,7 +128,7 @@ public abstract class BulletType extends Content{
/** Returns maximum distance the bullet this bullet type has can travel. */
public float range(){
return speed * lifetime * (1f - drag);
return Math.max(speed * lifetime * (1f - drag), range);
}
public boolean collides(Bullet bullet, Building tile){
@@ -179,7 +181,7 @@ public abstract class BulletType extends Content{
}
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);
hitSound.at(b);
Effect.shake(despawnShake, despawnShake, b);
if(fragBullet != null || splashDamageRadius > 0 || lightning > 0){
hit(b);
}
@@ -275,9 +279,8 @@ public abstract class BulletType extends Content{
bullet.damage = damage < 0 ? this.damage : damage;
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;
}
public void createNet(Team team, float x, float y, float angle, float damage, float velocityScl, float lifetimeScl){
@@ -12,10 +12,13 @@ import mindustry.graphics.*;
public class ContinuousLaserBulletType extends BulletType{
public float length = 220f;
public float shake = 1f;
public float fadeTime = 16f;
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[] strokes = {2f, 1.5f, 1f, 0.3f};
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){
super(0.001f, damage);
@@ -25,6 +28,7 @@ public class ContinuousLaserBulletType extends BulletType{
hitSize = 4;
drawSize = 420f;
lifetime = 16f;
keepVelocity = false;
pierce = true;
hittable = false;
hitColor = colors[2];
@@ -32,6 +36,7 @@ public class ContinuousLaserBulletType extends BulletType{
incendAmount = 1;
incendSpread = 5;
incendChance = 0.4f;
lightColor = Color.orange;
}
protected ContinuousLaserBulletType(){
@@ -43,13 +48,20 @@ public class ContinuousLaserBulletType extends BulletType{
return length;
}
@Override
public void init(){
super.init();
drawSize = Math.max(drawSize, length*2f);
}
@Override
public void update(Bullet b){
//TODO possible laser absorption from blocks
//damage every 5 ticks
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){
@@ -59,21 +71,23 @@ public class ContinuousLaserBulletType extends BulletType{
@Override
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);
for(int s = 0; s < colors.length; s++){
Draw.color(Tmp.c1.set(colors[s]).mul(1f + Mathf.absin(Time.time(), 1f, 0.1f)));
for(int i = 0; i < tscales.length; i++){
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);
}
}
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();
}
@@ -8,18 +8,17 @@ import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.world.*;
public class LaserBulletType extends BulletType{
protected static Tile furthest;
protected Color[] colors = {Pal.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Pal.lancerLaser, Color.white};
protected Effect laserEffect = Fx.lancerLaserShootSmoke;
protected float length = 160f;
protected float width = 15f;
protected float lengthFalloff = 0.5f;
protected float sideLength = 29f, sideWidth = 0.7f;
protected float sideAngle = 90f;
public Color[] colors = {Pal.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Pal.lancerLaser, Color.white};
public Effect laserEffect = Fx.lancerLaserShootSmoke;
public float length = 160f;
public float width = 15f;
public float lengthFalloff = 0.5f;
public float sideLength = 29f, sideWidth = 0.7f;
public float sideAngle = 90f;
public float lightningSpacing = -1, lightningDelay = 0.1f, lightningAngleRand;
public boolean largeHit = false;
public LaserBulletType(float damage){
super(0.01f, damage);
@@ -40,6 +39,13 @@ public class LaserBulletType extends BulletType{
this(1f);
}
@Override
public void init(){
super.init();
drawSize = Math.max(drawSize, length*2f);
}
@Override
public float range(){
return length;
@@ -47,8 +53,30 @@ public class LaserBulletType extends BulletType{
@Override
public void init(Bullet b){
float resultLength = Damage.collideLaser(b, length);
laserEffect.at(b.x, b.y, b.rotation(), resultLength * 0.75f);
float resultLength = Damage.collideLaser(b, length, largeHit), rot = b.rotation();
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
@@ -4,6 +4,12 @@ import mindustry.content.*;
import mindustry.entities.*;
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 Effect pierceEffect = Fx.hitBulletSmall, updateEffect = Fx.none;
/** Multiplier of damage decreased per health pierced. */
@@ -37,7 +43,9 @@ public class RailBulletType extends BulletType{
@Override
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
@@ -13,6 +13,7 @@ public class ShrapnelBulletType extends BulletType{
public float length = 100f;
public float width = 20f;
public Color fromColor = Color.white, toColor = Pal.lancerLaser;
public boolean hitLarge = false;
public int serrations = 7;
public float serrationLenScl = 10f, serrationWidth = 4f, serrationSpacing = 8f, serrationSpaceOffset = 80f, serrationFadeOffset = 0.5f;
@@ -30,7 +31,14 @@ public class ShrapnelBulletType extends BulletType{
@Override
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
@@ -1,23 +1,18 @@
package mindustry.entities.comp;
import mindustry.annotations.Annotations.*;
import mindustry.entities.*;
import mindustry.entities.EntityCollisions.*;
import mindustry.gen.*;
import static mindustry.Vars.*;
@Component
abstract class ElevationMoveComp implements Velc, Posc, Flyingc, Hitboxc{
@Import float x, y;
@Replace
@Override
public void move(float cx, float cy){
if(isFlying()){
x += cx;
y += cy;
}else{
collisions.move(this, cx, cy);
}
public SolidPred solidity(){
return isFlying() ? null : EntityCollisions::solid;
}
}
+10 -4
View File
@@ -4,16 +4,16 @@ import arc.math.*;
import arc.math.geom.*;
import arc.util.*;
import mindustry.*;
import mindustry.ai.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.entities.EntityCollisions.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.blocks.environment.*;
import static mindustry.Vars.*;
@Component
abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
@Import float x, y;
@@ -26,8 +26,14 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
@Replace
@Override
public void move(float cx, float cy){
collisions.moveCheck(this, cx, cy, !type.allowLegStep ? EntityCollisions::solid : EntityCollisions::legsSolid);
public SolidPred solidity(){
return !type.allowLegStep ? EntityCollisions::solid : EntityCollisions::legsSolid;
}
@Override
@Replace
public int pathType(){
return Pathfinder.costLegs;
}
@Override
+17 -3
View File
@@ -1,6 +1,7 @@
package mindustry.entities.comp;
import arc.math.*;
import arc.math.geom.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.gen.*;
@@ -9,11 +10,24 @@ import mindustry.gen.*;
abstract class MechComp implements Posc, Flyingc, Hitboxc, Unitc, Mechc, ElevationMovec{
@SyncField(false) @SyncLocal float baseRotation;
transient float walkTime, walkExtension;
transient private boolean walked;
@Override
public void update(){
float len = deltaLen();
baseRotation = Angles.moveToward(baseRotation, deltaAngle(), type().baseRotateSpeed * Mathf.clamp(len / type().speed / Time.delta) * Time.delta);
walkTime += len;
//trigger animation only when walking manually
if(walked){
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;
}
}
}
@@ -25,15 +25,15 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
}
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){
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){
return payloadUsed() + pay.size()*pay.size() <= type.payloadCapacity;
return payloadUsed() + pay.size()*pay.size() <= type.payloadCapacity + 0.001f;
}
boolean hasPayload(){
@@ -98,7 +98,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
Unit u = payload.unit;
//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;
}
+34 -36
View File
@@ -8,6 +8,7 @@ import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import mindustry.ai.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.ctype.*;
@@ -37,7 +38,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
private UnitController controller;
private UnitType type;
boolean spawnedByCore, deactivated; //TODO remove deactivation boolean
boolean spawnedByCore;
transient Seq<Ability> abilities = new Seq<>(0);
@@ -69,7 +70,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Replace
public float clipSize(){
return type.region.width * 2f;
return Math.max(type.region.width * 2f, type.clipSize);
}
@Override
@@ -103,7 +104,14 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override
@Replace
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
@@ -149,8 +157,13 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
return type;
}
/** @return pathfinder path type for calculating costs */
public int pathType(){
return Pathfinder.costGround;
}
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){
@@ -206,12 +219,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
public void add(){
//check if over unit cap
if(count() > cap() && !spawnedByCore){
deactivated = true;
if(!dead){
Call.unitCapDeath(self());
}
if(count() > cap() && !spawnedByCore && !dead){
Call.unitCapDeath(self());
teamIndex.updateCount(team, type, -1);
}
}
@@ -232,22 +242,13 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override
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){
for(Ability a : abilities){
a.update(self());
}
if(abilities.size > 0){
for(Ability a : abilities){
a.update(self());
}
}else if(!dead){
Call.unitCapDeath(self());
}
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){
damageContinuous(floor.damageTaken);
}
}
if(tile.solid()){
if(type.canBoost){
elevation = 1f;
}else if(!net.client()){
kill();
}
//kill entities on tiles that are solid to them
if(tile != null && !canPassOn()){
//boost if possible
if(type.canBoost){
elevation = 1f;
}else if(!net.client()){
kill();
}
}
//AI only updates on the server
if(!net.client() && !dead && !deactivated){
if(!net.client() && !dead){
controller.updateUnit();
}
@@ -325,11 +328,6 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
resetController();
}
//do not control anything when deactivated
if(deactivated){
controlWeapons(false, false);
}
//remove units spawned by the core
if(spawnedByCore && !isPlayer()){
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(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){
+29 -2
View File
@@ -3,9 +3,13 @@ package mindustry.entities.comp;
import arc.math.*;
import arc.math.geom.*;
import arc.util.*;
import arc.util.ArcAnnotate.*;
import mindustry.annotations.Annotations.*;
import mindustry.entities.EntityCollisions.*;
import mindustry.gen.*;
import static mindustry.Vars.*;
@Component
abstract class VelComp implements Posc{
@Import float x, y;
@@ -22,12 +26,35 @@ abstract class VelComp implements Posc{
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(){
return !vel.isZero(0.01f);
}
void move(float cx, float cy){
x += cx;
y += cy;
SolidPred check = solidity();
if(check != null){
collisions.move(self(), cx, cy, check);
}else{
x += cx;
y += cy;
}
}
}
@@ -4,17 +4,17 @@ import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
import mindustry.ai.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.entities.EntityCollisions.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.environment.*;
import static mindustry.Vars.*;
//just a proof of concept
@Component
abstract class WaterMoveComp implements Posc, Velc, Hitboxc, Flyingc, Unitc{
@@ -38,16 +38,8 @@ abstract class WaterMoveComp implements Posc, Velc, Hitboxc, Flyingc, Unitc{
@Override
@Replace
public void lookAt(float angle){
if(onLiquid()){
rotation = Angles.moveToward(rotation, angle, type.rotateSpeed * Time.delta);
}
}
@Override
@Replace
public boolean canShoot(){
return onLiquid();
public int pathType(){
return Pathfinder.costWater;
}
@Override
@@ -74,13 +66,8 @@ abstract class WaterMoveComp implements Posc, Velc, Hitboxc, Flyingc, Unitc{
@Replace
@Override
public void move(float cx, float cy){
if(isGrounded()){
collisions.moveCheck(this, cx, cy, EntityCollisions::waterSolid);
}else{
x += cx;
y += cy;
}
public SolidPred solidity(){
return isFlying() ? null : EntityCollisions::waterSolid;
}
@Replace
@@ -13,7 +13,7 @@ import mindustry.type.*;
import static mindustry.Vars.*;
@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 Vec2 vel;
@Import UnitType type;
@@ -85,6 +85,16 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
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. */
@Override
public void update(){
@@ -93,7 +103,27 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
for(WeaponMount mount : mounts){
Weapon weapon = mount.weapon;
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
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
if(weapon.rotate && (mount.rotate || mount.shoot) && can){
float axisX = this.x + Angles.trnsx(rotation - 90, weapon.x, weapon.y),
axisY = this.y + Angles.trnsy(rotation - 90, weapon.x, weapon.y);
float axisX = this.x + Angles.trnsx(this.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);
}else if(!weapon.rotate){
mount.rotation = 0;
@@ -124,21 +154,9 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
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
){
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));
shoot(mount, shootX, shootY, mount.aimX, mount.aimY, shootAngle, Mathf.sign(weapon.x));
mount.reload = weapon.reload;
mount.heat = 1f;
ammo--;
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;
@@ -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;
sequenceNum = 0;
if(weapon.shotDelay > 0.01f){
if(weapon.shotDelay + weapon.firstShotDelay > 0.01f){
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++;
});
}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;
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);
ammo.shootEffect.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);
weapon.bullet.create(this, team(),
return weapon.bullet.create(this, team(),
x + Angles.trnsx(angle, 0, xr),
y + Angles.trnsy(angle, 0, xr),
angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd), lifescl);
@@ -1,5 +1,7 @@
package mindustry.entities.units;
import arc.util.ArcAnnotate.*;
import mindustry.gen.*;
import mindustry.type.*;
public class WeaponMount{
@@ -21,6 +23,8 @@ public class WeaponMount{
public boolean rotate = false;
/** extra state for alternating weapons */
public boolean side;
/** current bullet for continuous weapons */
public @Nullable Bullet bullet;
public WeaponMount(Weapon weapon){
this.weapon = weapon;
+10 -9
View File
@@ -61,6 +61,9 @@ public class Saves{
//automatically assign sector save slots
for(SaveSlot slot : saves){
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;
}
}
@@ -75,7 +78,6 @@ public class Saves{
}
public void update(){
SaveSlot current = this.current;
if(current != null && state.isGame()
&& !(state.isPaused() && Core.scene.hasDialog())){
@@ -90,14 +92,13 @@ public class Saves{
if(time > Core.settings.getInt("saveinterval") * 60){
saving = true;
Time.runTask(2f, () -> {
try{
current.save();
}catch(Throwable e){
e.printStackTrace();
}
saving = false;
});
try{
current.save();
}catch(Throwable e){
e.printStackTrace();
}
Time.runTask(3f, () -> saving = false);
time = 0;
}
+5 -11
View File
@@ -2,9 +2,7 @@ package mindustry.game;
import arc.files.*;
import arc.struct.*;
import arc.struct.IntIntMap.*;
import arc.util.ArcAnnotate.*;
import mindustry.*;
import mindustry.content.*;
import mindustry.mod.Mods.*;
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);
}
public Seq<ItemStack> requirements(){
IntIntMap amounts = new IntIntMap();
public ItemSeq requirements(){
ItemSeq requirements = new ItemSeq();
tiles.each(t -> {
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()){
stacks.add(new ItemStack(Vars.content.item(ent.key), ent.value));
}
stacks.sort();
return stacks;
return requirements;
}
public boolean hasCore(){
+8
View File
@@ -33,6 +33,8 @@ public class SectorInfo{
public boolean hasCore = true;
/** Sector that was launched from. */
public @Nullable Sector origin;
/** Launch destination. */
public @Nullable Sector destination;
/** Resources known to occur at this sector. */
public Seq<UnlockableContent> resources = new Seq<>();
/** Time spent at this sector. Do not use unless you know what you're doing. */
@@ -43,6 +45,12 @@ public class SectorInfo{
/** Core item storage to prevent spoofing. */
private transient int[] lastCoreItems;
/** @return the real location items go when launched on this sector */
public Sector getRealDestination(){
//on multiplayer the destination is, by default, the first captured sector (basically random)
return !net.client() || destination != null ? destination : state.rules.sector.planet.sectors.find(Sector::hasBase);
}
/** Updates export statistics. */
public void handleItemExport(ItemStack stack){
handleItemExport(stack.item, stack.amount);
+18 -5
View File
@@ -20,7 +20,7 @@ public class Universe{
private int turn;
private Schematic lastLoadout;
private Seq<ItemStack> lastLaunchResources = new Seq<>();
private ItemSeq lastLaunchResources = new ItemSeq();
public Universe(){
load();
@@ -104,14 +104,14 @@ public class Universe{
}
}
public Seq<ItemStack> getLaunchResources(){
lastLaunchResources = Core.settings.getJson("launch-resources", Seq.class, ItemStack.class, Seq::new);
public ItemSeq getLaunchResources(){
lastLaunchResources = Core.settings.getJson("launch-resources-seq", ItemSeq.class, ItemSeq::new);
return lastLaunchResources;
}
public void updateLaunchResources(Seq<ItemStack> stacks){
public void updateLaunchResources(ItemSeq stacks){
this.lastLaunchResources = stacks;
Core.settings.putJson("launch-resources", ItemStack.class, lastLaunchResources);
Core.settings.putJson("launch-resources-seq", lastLaunchResources);
}
/** Updates selected loadout for future deployment. */
@@ -165,10 +165,23 @@ public class Universe{
//if so, just delete the save for now. it's lost.
//TODO don't delete it later maybe
sector.save.delete();
//clear recieved
sector.setExtraItems(new ItemSeq());
sector.save = null;
}
}
//export to another sector
if(sector.save.meta.secinfo.destination != null){
Sector to = sector.save.meta.secinfo.destination;
if(to.save != null){
ItemSeq items = to.getExtraItems();
//calculated exported items to this sector
sector.save.meta.secinfo.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed)));
to.setExtraItems(items);
}
}
//reset time spent to 0
sector.setTimeSpent(0f);
}
+1 -1
View File
@@ -3,7 +3,7 @@ package mindustry.graphics;
import arc.graphics.Color;
public class Pal{
public static final Color
public static Color
items = Color.valueOf("2ea756"),
command = Color.valueOf("eab678"),
+3 -3
View File
@@ -200,7 +200,7 @@ public class DesktopInput extends InputHandler{
}
panning = false;
Core.camera.position.add(Tmp.v1.setZero().add(Core.input.axis(Binding.move_x), Core.input.axis(Binding.move_y)).nor().scl(Time.delta * camSpeed));
Core.camera.position.add(Tmp.v1.setZero().add(Core.input.axis(Binding.move_x), Core.input.axis(Binding.move_y)).nor().scl(camSpeed));
}else if(!player.dead() && !panning){
Core.camera.position.lerpDelta(player, Core.settings.getBool("smoothcamera") ? 0.08f : 1f);
}
@@ -354,7 +354,7 @@ public class DesktopInput extends InputHandler{
}).visible(() -> state.isCampaign()).tooltip("@planetmap");
table.button(Icon.up, Styles.clearPartiali, () -> {
ui.planet.show(state.getSector(), player.team().core());
ui.planet.showLaunch(state.getSector(), player.team().core());
}).visible(() -> state.isCampaign()).tooltip("@launchcore").disabled(b -> player.team().core() == null);
}
@@ -596,7 +596,7 @@ public class DesktopInput extends InputHandler{
}
protected void updateMovement(Unit unit){
boolean omni = !(unit instanceof WaterMovec);
boolean omni = unit.type().omniMovement;
boolean ground = unit.isGrounded();
float strafePenalty = ground ? 1f : Mathf.lerp(1f, unit.type().strafePenalty, Angles.angleDist(unit.vel().angle(), unit.rotation()) / 180f);
+4 -4
View File
@@ -292,7 +292,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}else if(unit == null){ //just clear the unit (is this used?)
player.clearUnit();
//make sure it's AI controlled, so players can't overwrite each other
}else if(unit.isAI() && unit.team == player.team() && !unit.deactivated() && !unit.dead){
}else if(unit.isAI() && unit.team == player.team() && !unit.dead){
if(!net.client()){
player.unit(unit);
}
@@ -365,7 +365,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
if(controlledType != null && player.dead()){
Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType && !u.deactivated() && !u.dead);
Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType && !u.dead);
if(unit != null){
Call.unitControl(player, unit);
@@ -375,7 +375,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public void checkUnit(){
if(controlledType != null){
Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType && !u.deactivated() && !u.dead);
Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType && !u.dead);
if(unit == null && controlledType == UnitTypes.block){
unit = world.buildWorld(player.x, player.y) instanceof ControlBlock ? ((ControlBlock)world.buildWorld(player.x, player.y)).unit() : null;
}
@@ -931,7 +931,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
public @Nullable Unit selectedUnit(){
Unit unit = Units.closest(player.team(), Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, u -> u.isAI() && !u.deactivated());
Unit unit = Units.closest(player.team(), Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, u -> u.isAI());
if(unit != null){
unit.hitbox(Tmp.r1);
Tmp.r1.grow(6f);
+1 -1
View File
@@ -804,7 +804,7 @@ public class MobileInput extends InputHandler implements GestureListener{
if(type == null) return;
boolean flying = type.flying;
boolean omni = !(unit instanceof WaterMovec);
boolean omni = unit.type().omniMovement;
boolean legs = unit.isGrounded();
boolean allowHealing = type.canHeal;
boolean validHealTarget = allowHealing && target instanceof Building && ((Building)target).isValid() && target.team() == unit.team &&
+4
View File
@@ -126,6 +126,10 @@ public class SaveIO{
}
}
public static void load(String saveName) throws SaveException{
load(saveDirectory.child(saveName + ".msav"));
}
public static void load(Fi file) throws SaveException{
load(file, world.context);
}
@@ -295,16 +295,6 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
//TODO better waves
state.rules.spawns = defaultWaves.get();
float waveScaling = 1f + difficulty*2;
//scale up the spawning base on difficulty (this is just for testing)
for(SpawnGroup group : state.rules.spawns){
group.unitAmount *= waveScaling;
if(group.unitScaling != SpawnGroup.never){
group.unitScaling /= waveScaling;
}
}
}
@Override
+1 -1
View File
@@ -22,7 +22,7 @@ public class Scripts implements Disposable{
private final Seq<String> blacklist = Seq.with(".net.", "java.net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk",
"runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system",
".awt", "socket", "classloader", "oracle", "invoke", "java.util.function", "java.util.stream", "org.");
private final Seq<String> whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "mindustry.gen.", "mindustry.logic.", "mindustry.async.");
private final Seq<String> whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "mindustry.gen.", "mindustry.logic.", "mindustry.async.", "saveio");
private final Context context;
private final Scriptable scope;
private boolean errored;
+3 -13
View File
@@ -61,7 +61,7 @@ public class ArcNetProvider implements NetProvider{
try{
net.handleClientReceived(object);
}catch(Throwable e){
handleException(e);
net.handleException(e);
}
});
@@ -144,14 +144,14 @@ public class ArcNetProvider implements NetProvider{
try{
client.run();
}catch(Exception e){
if(!(e instanceof ClosedSelectorException)) handleException(e);
if(!(e instanceof ClosedSelectorException)) net.handleException(e);
}
});
client.connect(5000, ip, port, port);
success.run();
}catch(Exception e){
handleException(e);
net.handleException(e);
}
});
}
@@ -269,16 +269,6 @@ public class ArcNetProvider implements NetProvider{
return null;
}
void handleException(Throwable e){
if(e instanceof ArcNetException){
Core.app.post(() -> net.showError(new IOException("mismatch")));
}else if(e instanceof ClosedChannelException){
Core.app.post(() -> net.showError(new IOException("alreadyconnected")));
}else{
Core.app.post(() -> net.showError(e));
}
}
class ArcConnection extends NetConnection{
public final Connection connection;
+19 -5
View File
@@ -19,19 +19,33 @@ import java.text.*;
import java.util.*;
import static arc.Core.*;
import static mindustry.Vars.mods;
import static mindustry.Vars.net;
public class CrashSender{
public static String createReport(String error){
String report = "Oh no, Mindustry crashed!\n";
if(mods.list().size == 0){
report += "Please report this at https://github.com/Anuken/Mindustry/issues/new?labels=bug&template=bug_report.md\n\n";
}
return report + "Version: " + Version.combined() + (Vars.headless ? " (Server)" : "") + "\n"
+ "OS: " + System.getProperty("os.name") + " x" + (OS.is64Bit ? "64" : "32") + "\n"
+ "Java Version: " + System.getProperty("java.version") + "\n"
+ "Java Architecture: " + System.getProperty("sun.arch.data.model") + "\n"
+ mods.list().size + " Mods: " + mods.list().toString(", ", mod -> mod.name + ":" + mod.meta.version)
+ "\n\n" + error;
}
public static void log(Throwable exception){
try{
Core.settings.getDataDirectory().child("crashes").child("crash_" + System.currentTimeMillis() + ".txt").writeString(Strings.neatError(exception));
Core.settings.getDataDirectory().child("crashes").child("crash_" + System.currentTimeMillis() + ".txt")
.writeString(createReport(Strings.neatError(exception)));
}catch(Throwable ignored){
}
}
public static void send(Throwable exception, Cons<File> writeListener){
try{
exception.printStackTrace();
@@ -70,7 +84,7 @@ public class CrashSender{
try{
File file = new File(OS.getAppDataDirectoryString(Vars.appName), "crashes/crash-report-" + new SimpleDateFormat("MM_dd_yyyy_HH_mm_ss").format(new Date()) + ".txt");
new Fi(OS.getAppDataDirectoryString(Vars.appName)).child("crashes").mkdirs();
new Fi(file).writeString(parseException(exception));
new Fi(file).writeString(createReport(parseException(exception)));
writeListener.get(file);
}catch(Throwable e){
Log.err("Failed to save local crash report.", e);
@@ -130,7 +144,7 @@ public class CrashSender{
boolean[] sent = {false};
Log.info("Sending crash report.");
//post to crash report URL
//post to crash report URL, exit code indicates send success
httpPost(Vars.crashReportURL, value.toJson(OutputType.json), r -> {
Log.info("Crash sent successfully.");
sent[0] = true;
@@ -138,7 +152,7 @@ public class CrashSender{
}, t -> {
t.printStackTrace();
sent[0] = true;
System.exit(1);
System.exit(-1);
});
//sleep until report is sent
+14 -2
View File
@@ -1,10 +1,11 @@
package mindustry.net;
import arc.*;
import arc.struct.*;
import arc.func.*;
import arc.util.*;
import arc.net.*;
import arc.struct.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import arc.util.pooling.*;
import mindustry.gen.*;
import mindustry.net.Packets.*;
@@ -13,6 +14,7 @@ import net.jpountz.lz4.*;
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import static mindustry.Vars.*;
@@ -36,6 +38,16 @@ public class Net{
this.provider = provider;
}
public void handleException(Throwable e){
if(e instanceof ArcNetException){
Core.app.post(() -> showError(new IOException("mismatch")));
}else if(e instanceof ClosedChannelException){
Core.app.post(() -> showError(new IOException("alreadyconnected")));
}else{
Core.app.post(() -> showError(e));
}
}
/** Display a network error. Call on the graphics thread. */
public void showError(Throwable e){
+10 -2
View File
@@ -11,11 +11,14 @@ import mindustry.world.modules.ItemModule.*;
import java.util.*;
public class ItemSeq implements Iterable<ItemStack>, Serializable{
protected final int[] values;
protected final int[] values = new int[Vars.content.items().size];
public int total;
public ItemSeq(){
values = new int[Vars.content.items().size];
}
public ItemSeq(Seq<ItemStack> stacks){
stacks.each(this::add);
}
public void each(ItemConsumer cons){
@@ -26,6 +29,11 @@ public class ItemSeq implements Iterable<ItemStack>, Serializable{
}
}
public void clear(){
total = 0;
Arrays.fill(values, 0);
}
public Seq<ItemStack> toSeq(){
Seq<ItemStack> out = new Seq<>();
for(int i = 0; i < values.length; i++){
+4
View File
@@ -275,6 +275,10 @@ public class Sector{
Core.settings.put(key(key), value);
}
public String toString(){
return planet.name + "#" + id;
}
/** Projects this sector onto a 4-corner square for use in map gen.
* Allocates a new object. Do not call in the main loop. */
private SectorRect makeRect(){
+24 -34
View File
@@ -44,7 +44,7 @@ public class UnitType extends UnlockableContent{
public float speed = 1.1f, boostMultiplier = 1f, rotateSpeed = 5f, baseRotateSpeed = 5f;
public float drag = 0.3f, accel = 0.5f, landShake = 0f, rippleScale = 1f, fallSpeed = 0.018f;
public float health = 200f, range = -1, armor = 0f;
public float crashDamageMultiplier = 3f;
public float crashDamageMultiplier = 1f;
public boolean targetAir = true, targetGround = true;
public boolean faceTarget = true, rotateShooting = true, isCounted = true, lowAltitude = false;
public boolean canBoost = false;
@@ -55,6 +55,7 @@ public class UnitType extends UnlockableContent{
public float visualElevation = -1f;
public boolean allowLegStep = false;
public boolean hovering = false;
public boolean omniMovement = true;
public Effect fallEffect = Fx.fallSmoke;
public Effect fallThrusterEffect = Fx.fallSmoke;
public Seq<Ability> abilities = new Seq<>();
@@ -75,6 +76,7 @@ public class UnitType extends UnlockableContent{
public int mineTier = -1;
public float buildSpeed = 1f, mineSpeed = 1f;
public float clipSize = -1;
public boolean canDrown = true;
public float engineOffset = 5f, engineSize = 2.5f;
public float strafePenalty = 0.5f;
@@ -134,7 +136,7 @@ public class UnitType extends UnlockableContent{
public void update(Unit unit){
if(unit instanceof Mechc){
if(unit instanceof Mechc && !unit.isFlying()){
updateMechEffects(unit);
}
}
@@ -194,13 +196,6 @@ public class UnitType extends UnlockableContent{
}).growX();
table.row();
if(unit.deactivated){
table.table(d -> {
d.left();
d.label(() -> Core.bundle.format("bar.limitreached", unit.count(), unit.cap(), Fonts.getUnicodeStr(name)));
}).left().visible(() -> unit.deactivated);
}
}
@Override
@@ -230,6 +225,15 @@ public class UnitType extends UnlockableContent{
public void init(){
if(constructor == null) throw new IllegalArgumentException("no constructor set up for unit '" + name + "'");
Unit example = constructor.get();
//water preset
if(example instanceof WaterMovec){
canDrown = false;
omniMovement = false;
immunities.add(StatusEffects.wet);
}
singleTarget = weapons.size <= 1;
if(itemCapacity < 0){
@@ -396,10 +400,6 @@ public class UnitType extends UnlockableContent{
unit.trns(-legOffset.x, -legOffset.y);
}
if(unit.deactivated){
drawDeactive(unit);
}
if(unit.abilities.size > 0){
for(Ability a : unit.abilities){
Draw.reset();
@@ -410,16 +410,6 @@ public class UnitType extends UnlockableContent{
}
}
public void drawDeactive(Unit unit){
Draw.color(Color.scarlet);
Draw.alpha(0.8f);
float size = 8f;
Draw.rect(Icon.warning.getRegion(), unit.x, unit.y, size, size);
Draw.reset();
}
public <T extends Unit & Payloadc> void drawPayload(T unit){
if(unit.hasPayload()){
Payload pay = unit.payloads().first();
@@ -525,7 +515,6 @@ public class UnitType extends UnlockableContent{
float rotation = unit.rotation - 90;
float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0);
float width = weapon.region.width;
float recoil = -((mount.reload) / weapon.reload * weapon.recoil);
float wx = unit.x + Angles.trnsx(rotation, weapon.x, weapon.y) + Angles.trnsx(weaponRotation, 0, recoil),
wy = unit.y + Angles.trnsy(rotation, weapon.x, weapon.y) + Angles.trnsy(weaponRotation, 0, recoil);
@@ -540,17 +529,16 @@ public class UnitType extends UnlockableContent{
Draw.rect(weapon.outlineRegion,
wx, wy,
width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.outlineRegion.width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.region.height * Draw.scl,
weaponRotation);
Draw.z(z);
}
Draw.rect(weapon.region,
wx, wy,
width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.region.width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.region.height * Draw.scl,
weaponRotation);
@@ -559,8 +547,8 @@ public class UnitType extends UnlockableContent{
Draw.blend(Blending.additive);
Draw.rect(weapon.heatRegion,
wx, wy,
width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.region.height * Draw.scl,
weapon.heatRegion.width * Draw.scl * -Mathf.sign(weapon.flipSprite),
weapon.heatRegion.height * Draw.scl,
weaponRotation);
Draw.blend();
Draw.color();
@@ -571,6 +559,8 @@ public class UnitType extends UnlockableContent{
}
public void drawOutline(Unit unit){
Draw.reset();
if(Core.atlas.isFound(outlineRegion)){
Draw.rect(outlineRegion, unit.x, unit.y, unit.rotation - 90);
}
@@ -614,11 +604,6 @@ public class UnitType extends UnlockableContent{
Drawf.shadow(leg.base.x, leg.base.y, ssize);
}
//TODO should be below/above legs
if(baseRegion.found()){
Draw.rect(baseRegion, unit.x, unit.y, rotation);
}
//legs are drawn front first
for(int j = legs.length - 1; j >= 0; j--){
int i = (j % 2 == 0 ? j/2 : legs.length - 1 - j/2);
@@ -656,6 +641,11 @@ public class UnitType extends UnlockableContent{
}
}
//TODO should be below/above legs
if(baseRegion.found()){
Draw.rect(baseRegion, unit.x, unit.y, rotation - 90);
}
Draw.reset();
}
+8
View File
@@ -29,6 +29,8 @@ public class Weapon{
public boolean rotate = false;
/** whether to draw the outline on top. */
public boolean top = true;
/** whether to hold the bullet in place while firing */
public boolean continuous;
/** rotation speed of weapon when rotation is enabled, in degrees/t*/
public float rotateSpeed = 20f;
/** weapon reload in frames */
@@ -54,6 +56,8 @@ public class Weapon{
/** fraction of velocity that is random */
public float velocityRnd = 0f;
/** delay in ticks between shots */
public float firstShotDelay = 0;
/** delay in ticks between shots */
public float shotDelay = 0;
/** The half-radius of the cone in which shooting will start. */
public float shootCone = 5f;
@@ -77,6 +81,10 @@ public class Weapon{
public TextureRegion outlineRegion;
/** heat region tint */
public Color heatColor = Pal.turretHeat;
/** status effect applied when shooting */
public StatusEffect shootStatus = StatusEffects.none;
/** status effect duration when shot */
public float shootStatusDuration = 60f * 5f;
public Weapon(String name){
this.name = name;
+1 -1
View File
@@ -14,7 +14,7 @@ public class ItemDisplay extends Table{
}
public ItemDisplay(Item item, int amount, boolean showName){
add(new ItemImage(new ItemStack(item, amount))).size(8 * 4).padRight(amount > 99 ? 12 : 0);
add(new ItemImage(new ItemStack(item, amount)));
if(showName) add(item.localizedName).padLeft(4 + amount > 99 ? 4 : 0);
this.item = item;
+16 -8
View File
@@ -8,15 +8,17 @@ import mindustry.type.*;
public class ItemImage extends Stack{
public ItemImage(TextureRegion region, int amount){
Table t = new Table().left().bottom();
t.add(amount + "").name("item-label");
t.pack();
add(new Table(o -> {
o.left();
o.add(new Image(region)).size(32f);
}));
add(t);
add(new Table(t -> {
t.left().bottom();
t.add(amount + "");
t.pack();
}));
}
public ItemImage(TextureRegion region){
@@ -27,12 +29,18 @@ public class ItemImage extends Stack{
}
public ItemImage(ItemStack stack){
add(new Image(stack.item.icon(Cicon.medium)));
add(new Table(o -> {
o.left();
o.add(new Image(stack.item.icon(Cicon.medium))).size(32f);
}));
if(stack.amount != 0){
Table t = new Table().left().bottom();
t.add(stack.amount + "").name("item-label").style(Styles.outlineLabel);
add(t);
add(new Table(t -> {
t.left().bottom();
t.add(stack.amount + "").style(Styles.outlineLabel);
t.pack();
}));
}
}
}
@@ -56,7 +56,7 @@ public class DatabaseDialog extends BaseDialog{
for(int i = 0; i < array.size; i++){
UnlockableContent unlock = (UnlockableContent)array.get(i);
Image image = unlocked(unlock) ? new Image(unlock.icon(Cicon.medium)) : new Image(Icon.lock, Pal.gray);
Image image = unlocked(unlock) ? new Image(unlock.icon(Cicon.medium)).setScaling(Scaling.fit) : new Image(Icon.lock, Pal.gray);
list.add(image).size(8*4).pad(3);
ClickListener listener = new ClickListener();
image.addListener(listener);

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