Merge branch 'master' of https://github.com/Anuken/Mindustry into refactor-paths

 Conflicts:
	core/src/mindustry/ai/types/GroundAI.java
This commit is contained in:
Anuken
2020-09-03 09:18:06 -04:00
186 changed files with 10171 additions and 8983 deletions
+5 -3
View File
@@ -13,11 +13,13 @@ assignees: ''
**Issue**: *Explain your issue in detail.*
**Steps to reproduce**: *How you happened across the issue, and what you were doing at the time.*
**Steps to reproduce**: *How you happened across the issue, and what exactly you did to make the bug happen.*
**Link to mod(s) used, if applicable**: *The mod repositories or zip files that are related to the issue.*
**Link(s) to mod(s) used**: *The mod repositories or zip files that are related to the issue, if applicable.*
**Crash report, if applicable**: *The contents of relevant crash report files.*
**Save file**: *The save file you were playing on when the bug happened, if applicable.*
**Crash report**: *The contents of relevant crash report files. REQUIRED if you are reporting a crash.*
---
+4 -2
View File
@@ -79,9 +79,11 @@ com_crashlytics_export_strings.xml
/android/bin/
/core/bin/
/desktop/bin/
/html/bin/
/ios/bin/
/ios-moe/bin/
/annotations/bin/
/server/bin/
/tests/bin/
/tools/bin/
*.tmp
*.bak
*.swp
+1 -1
View File
@@ -1,5 +1,5 @@
jdk:
- openjdk8
- openjdk14
dist: xenial
android:
components:
+2 -2
View File
@@ -15,7 +15,7 @@ See [CONTRIBUTING](CONTRIBUTING.md).
### Building
Bleeding-edge live builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases). Old builds might still be on [jenkins](https://jenkins.hellomouse.net/job/mindustry/).
Bleeding-edge builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases). Old builds might still be on [jenkins](https://jenkins.hellomouse.net/job/mindustry/).
If you'd rather compile on your own, follow these instructions.
First, make sure you have [JDK 14](https://adoptopenjdk.net/) installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands:
@@ -39,7 +39,7 @@ Server builds are bundled with each released build (in Releases). If you'd rathe
#### Android
1. Install the Android SDK [here.](https://developer.android.com/studio#downloads) Make sure you're downloading the "Command line tools only", as Android Studio is not required.
2. Create a file named `local.properties` inside the Mindustry directory, with its contents looking like this: `sdk.dir=<Path to Android SDK you just downloaded, without these bracket>`. For example, if you're on Windows and installed the tools to C:\\tools, your local.properties would contain `sdk.dir=C:\\tools` (*note the double backslashes are required instead of single ones!*).
2. Set the `ANDROID_HOME` environment variable to point to your unzipped Android SDK directory.
3. Run `gradlew android:assembleDebug` (or `./gradlew` if on linux/mac). This will create an unsigned APK in `android/build/outputs/apk`.
4. (Optional) To debug the application on a connected phone, do `gradlew android:installDebug android:run`. It is **highly recommended** to use IntelliJ for this instead.
@@ -71,22 +71,17 @@ public class LogicStatementProcessor extends BaseProcessor{
writer.addStatement("out.append(\" \")");
writer.addStatement("out.append((($T)obj).$L$L)", c.mirror(), field.name(),
field.mirror().toString().equals("java.lang.String") ?
".replace(\"\\n\", \"\\\\n\")" :
Seq.with(typeu.directSupertypes(field.mirror())).contains(t -> t.toString().contains("java.lang.Enum")) ? ".name()" :
"");
Seq.with(typeu.directSupertypes(field.mirror())).contains(t -> t.toString().contains("java.lang.Enum")) ? ".name()" :
"");
//reading primitives, strings and enums is supported; nothing else is
reader.addStatement("if(tokens.length > $L) result.$L = $L(tokens[$L])$L",
reader.addStatement("if(tokens.length > $L) result.$L = $L(tokens[$L])",
index + 1,
field.name(),
field.mirror().toString().equals("java.lang.String") ?
"" : (field.tname().isPrimitive() ? field.tname().box().toString() :
field.mirror().toString()) + ".valueOf", //if it's not a string, it must have a valueOf method
index + 1,
field.mirror().toString().equals("java.lang.String") ?
".replace(\"\\\\n\", \"\\n\")" :
""
index + 1
);
index ++;
@@ -1 +1 @@
{fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:mindustry.gen.Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
{fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:fdata,type:float,size:4},{name:lifetime,type:float,size:4},{name:owner,type:mindustry.gen.Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
@@ -1 +0,0 @@
{version:1,fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
@@ -1 +0,0 @@
{version:2,fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:mindustry.gen.Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
@@ -1 +0,0 @@
{version:3,fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
@@ -1 +0,0 @@
{version:4,fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
@@ -1 +0,0 @@
{version:5,fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
@@ -0,0 +1 @@
{version:1,fields:[{name:lifetime,type:float,size:4},{name:tile,type:mindustry.world.Tile,size:-1},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
@@ -0,0 +1 @@
{version:2,fields:[{name:effectTimer,type:float,size:4},{name:intensity,type:float,size:4},{name:life,type:float,size:4},{name:opacity,type:float,size:4},{name:weather,type:mindustry.type.Weather,size:-1},{name:windVector,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
+4
View File
@@ -187,6 +187,10 @@ configure(subprojects - project(":annotations")){
options.compilerArgs.addAll(['--release', '8'])
}
}
tasks.withType(Javadoc){
options.addStringOption('Xdoclint:none', '-quiet')
}
}
project(":desktop"){
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 517 B

After

Width:  |  Height:  |  Size: 783 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 553 B

After

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 989 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 639 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 B

+10 -1
View File
@@ -136,6 +136,8 @@ mod.scripts.disable = Your device does not support mods with scripts. You must d
about.button = About
name = Name:
noname = Pick a[accent] player name[] first.
planetmap = Planet Map
launchcore = Launch Core
filename = File Name:
unlocked = New content unlocked!
completed = [accent]Completed
@@ -170,7 +172,7 @@ host.info = The [accent]host[] button hosts a server on port [scarlet]6567[]. \n
join.info = Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] or [accent]global[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[lightgray]If you want to connect to someone by IP, you would need to ask the host for their IP, which can be found by googling "my ip" from their device.
hostserver = Host Multiplayer Game
invitefriends = Invite Friends
hostserver.mobile = Host\nGame
hostserver.mobile = Host Game
host = Host
hosting = [accent]Opening server...
hosts.refresh = Refresh
@@ -575,6 +577,8 @@ blocks.shootrange = Range
blocks.size = Size
blocks.liquidcapacity = Liquid Capacity
blocks.powerrange = Power Range
blocks.linkrange = Link Range
blocks.instructions = Instructions
blocks.powerconnections = Max Connections
blocks.poweruse = Power Use
blocks.powerdamage = Power/Damage
@@ -727,6 +731,7 @@ category.blocks.name = Block Select
command.attack = Attack
command.rally = Rally
command.retreat = Retreat
command.idle = Idle
placement.blockselectkeys = \n[lightgray]Key: [{0},
keybind.respawn.name = Respawn
keybind.control.name = Control Unit
@@ -739,6 +744,7 @@ keybind.toggle_block_status.name = Toggle Block Statuses
keybind.move_x.name = Move X
keybind.move_y.name = Move Y
keybind.mouse_move.name = Follow Mouse
keybind.pan.name = Pan View
keybind.boost.name = Boost
keybind.schematic_select.name = Select Region
keybind.schematic_menu.name = Schematic Menu
@@ -874,6 +880,7 @@ unit.crawler.name = Crawler
unit.atrax.name = Atrax
unit.spiroct.name = Spiroct
unit.arkyid.name = Arkyid
unit.toxopid.name = Toxopid
unit.flare.name = Flare
unit.horizon.name = Horizon
unit.zenith.name = Zenith
@@ -1073,6 +1080,7 @@ block.container.name = Container
block.launch-pad.name = Launch Pad
block.launch-pad-large.name = Large Launch Pad
block.segment.name = Segment
block.command-center.name = Command Center
block.ground-factory.name = Ground Factory
block.air-factory.name = Air Factory
block.naval-factory.name = Naval Factory
@@ -1089,6 +1097,7 @@ block.overdrive-dome.name = Overdrive Dome
block.switch.name = Switch
block.micro-processor.name = Micro Processor
block.logic-processor.name = Logic Processor
block.hyper-processor.name = Hyper Processor
block.logic-display.name = Logic Display
block.memory-cell.name = Memory Cell
+2
View File
@@ -286,3 +286,5 @@
63458=switch|block-switch-medium
63457=memory-cell|block-memory-cell-medium
63456=payload-conveyor|block-payload-conveyor-medium
63455=hyper-processor|block-hyper-processor-medium
63454=toxopid|unit-toxopid-medium
+2 -1
View File
@@ -5,8 +5,9 @@ const log = function(context, obj){
}
const readString = path => Vars.mods.getScripts().readString(path)
const readBytes = path => Vars.mods.getScripts().readBytes(path)
const loadMusic = path => Vars.mods.getScripts().loadMusic(path)
const loadSound = path => Vars.mods.getScripts().loadSound(path)
var scriptName = "base.js"
var modName = "none"
+3 -1
View File
@@ -7,8 +7,9 @@ const log = function(context, obj){
}
const readString = path => Vars.mods.getScripts().readString(path)
const readBytes = path => Vars.mods.getScripts().readBytes(path)
const loadMusic = path => Vars.mods.getScripts().loadMusic(path)
const loadSound = path => Vars.mods.getScripts().loadSound(path)
var scriptName = "base.js"
var modName = "none"
@@ -40,6 +41,7 @@ importPackage(Packages.arc)
importPackage(Packages.arc.func)
importPackage(Packages.arc.graphics)
importPackage(Packages.arc.graphics.g2d)
importPackage(Packages.arc.graphics.gl)
importPackage(Packages.arc.math)
importPackage(Packages.arc.math.geom)
importPackage(Packages.arc.scene)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 788 B

After

Width:  |  Height:  |  Size: 794 B

File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 644 KiB

After

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 994 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 407 KiB

After

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

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: 1.9 MiB

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

After

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

+1 -2
View File
@@ -199,8 +199,7 @@ public class Vars implements Loadable{
public static NetServer netServer;
public static NetClient netClient;
public static
Player player;
public static Player player;
@Override
public void loadAsync(){
+5 -1
View File
@@ -63,6 +63,7 @@ public class BaseAI{
int range = 150;
Position pos = randomPosition();
//when there are no random positions, do nothing.
if(pos == null) return;
@@ -159,7 +160,10 @@ public class BaseAI{
private void tryWalls(){
Block wall = Blocks.copperWall;
Tile spawn = state.rules.defaultTeam.core() != null ? state.rules.defaultTeam.core().tile : data.team.core().tile;
Building spawnt = state.rules.defaultTeam.core() != null ? state.rules.defaultTeam.core() : data.team.core();
Tile spawn = spawnt == null ? null : spawnt.tile;
if(spawn == null) return;
for(int wx = lastX; wx <= lastX + lastW; wx++){
for(int wy = lastY; wy <= lastY + lastH; wy++){
+6 -6
View File
@@ -185,7 +185,7 @@ public class BlockIndexer{
if(other == null) continue;
if(other.team() == team && pred.get(other) && intSet.add(other.pos())){
if(other.team == team && pred.get(other) && intSet.add(other.pos())){
cons.get(other);
any = true;
}
@@ -212,11 +212,11 @@ public class BlockIndexer{
}
public void notifyTileDamaged(Building entity){
if(damagedTiles[entity.team().id] == null){
damagedTiles[entity.team().id] = new BuildingArray();
if(damagedTiles[entity.team.id] == null){
damagedTiles[entity.team.id] = new BuildingArray();
}
damagedTiles[entity.team().id].add(entity);
damagedTiles[entity.team.id].add(entity);
}
public Building findEnemyTile(Team team, float x, float y, float range, Boolf<Building> pred){
@@ -251,7 +251,7 @@ public class BlockIndexer{
if(e == null) continue;
if(e.team() != team || !pred.get(e) || !e.block().targetable)
if(e.team != team || !pred.get(e) || !e.block().targetable)
continue;
float ndst = e.dst2(x, y);
@@ -390,7 +390,7 @@ public class BlockIndexer{
for(int y = quadrantY * quadrantSize; y < world.height() && y < (quadrantY + 1) * quadrantSize; y++){
Building result = world.build(x, y);
//when a targetable block is found, mark this quadrant as occupied and stop searching
if(result != null && result.team() == team){
if(result != null && result.team == team){
bits.set(quadrantX, quadrantY);
break outer;
}
+1 -1
View File
@@ -99,7 +99,7 @@ public class WaveSpawner{
private void eachFlyerSpawn(Floatc2 cons){
for(Tile tile : spawns){
float angle = Angles.angle(tile.x, tile.y, world.width() / 2, world.height() / 2);
float angle = Angles.angle(world.width() / 2, world.height() / 2, tile.x, tile.y);
float trns = Math.max(world.width(), world.height()) * Mathf.sqrt2 * tilesize;
float spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(angle, trns), -margin, world.width() * tilesize + margin);
+12 -1
View File
@@ -6,6 +6,8 @@ import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
public class FlyingAI extends AIController{
@Override
@@ -18,7 +20,7 @@ public class FlyingAI extends AIController{
unit.wobble();
}
if(target != null && unit.hasWeapons()){
if(target != null && unit.hasWeapons() && command() == UnitCommand.attack){
if(unit.type().weapons.first().rotate){
moveTo(target, unit.range() * 0.8f);
unit.lookAt(target);
@@ -26,6 +28,15 @@ public class FlyingAI extends AIController{
attack(80f);
}
}
if(target == null && command() == UnitCommand.attack && state.rules.waves && unit.team == state.rules.defaultTeam){
moveTo(getClosestSpawner(), state.rules.dropZoneRadius + 120f);
}
if(command() == UnitCommand.rally){
target = targetFlag(unit.x, unit.y, BlockFlag.rally, false);
moveTo(target, 60f);
}
}
@Override
+26 -5
View File
@@ -5,6 +5,9 @@ import mindustry.entities.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.world.*;
import mindustry.world.meta.*;
import java.util.*;
import static mindustry.Vars.*;
@@ -17,16 +20,34 @@ public class GroundAI extends AIController{
Building core = unit.closestEnemyCore();
if(core != null){
if(unit.within(core,unit.range() / 1.1f)){
target = core;
if(core != null && unit.within(core, unit.range() / 1.1f + core.block.size * tilesize / 2f)){
target = core;
Arrays.fill(targets, core);
}
if((core == null || !unit.within(core, unit.range() * 0.5f)) && command() == UnitCommand.attack){
boolean move = true;
if(state.rules.waves && unit.team == state.rules.defaultTeam){
Tile spawner = getClosestSpawner();
if(spawner != null && unit.within(spawner, state.rules.dropZoneRadius + 120f)) move = false;
}
if(!unit.within(core, unit.range() * 0.5f)){
moveTo(Pathfinder.fieldCore);
if(move) moveToCore(FlagTarget.enemyCores);
}
if(command() == UnitCommand.rally){
Teamc target = targetFlag(unit.x, unit.y, BlockFlag.rally, false);
if(target != null && !unit.within(target, 70f)){
moveToCore(FlagTarget.rallyPoints);
}
}
if(unit.type().canBoost && !unit.onSolid()){
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f);
}
if(!Units.invalidateTarget(target, unit, unit.range())){
if(unit.type().hasWeapons()){
unit.aimLook(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
+1 -1
View File
@@ -39,7 +39,7 @@ public class SuicideAI extends GroundAI{
boolean blocked = Vars.world.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> {
Tile tile = Vars.world.tile(x, y);
if(tile != null && tile.build == target) return false;
if(tile != null && tile.build != null && tile.build.team() != unit.team()){
if(tile != null && tile.build != null && tile.build.team != unit.team()){
blockedByBlock = true;
return true;
}else{
@@ -19,6 +19,7 @@ public class MusicControl{
public Seq<Music> ambientMusic = Seq.with();
/** darker music, used in times of conflict */
public Seq<Music> darkMusic = Seq.with();
protected Music lastRandomPlayed;
protected Interval timer = new Interval();
protected @Nullable Music current;
+42 -18
View File
@@ -19,7 +19,6 @@ import mindustry.world.blocks.experimental.*;
import mindustry.world.blocks.legacy.*;
import mindustry.world.blocks.liquid.*;
import mindustry.world.blocks.logic.*;
import mindustry.world.blocks.logic.MessageBlock;
import mindustry.world.blocks.power.*;
import mindustry.world.blocks.production.*;
import mindustry.world.blocks.sandbox.*;
@@ -78,12 +77,13 @@ public class Blocks implements ContentList{
duo, scatter, scorch, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, segment, parallax,
//units
commandCenter,
groundFactory, airFactory, navalFactory,
additiveReconstructor, multiplicativeReconstructor, exponentialReconstructor, tetrativeReconstructor,
repairPoint, resupplyPoint,
//logic
message, switchBlock, microProcessor, logicProcessor, logicDisplay, memoryCell,
message, switchBlock, microProcessor, logicProcessor, hyperProcessor, logicDisplay, memoryCell,
//campaign
launchPad, launchPadLarge,
@@ -998,10 +998,12 @@ public class Blocks implements ContentList{
payloadConveyor = new PayloadConveyor("payload-conveyor"){{
requirements(Category.distribution, with(Items.graphite, 10, Items.copper, 20));
canOverdrive = false;
}};
payloadRouter = new PayloadRouter("payload-router"){{
requirements(Category.distribution, with(Items.graphite, 15, Items.copper, 20));
canOverdrive = false;
}};
//endregion
@@ -1339,7 +1341,7 @@ public class Blocks implements ContentList{
unloader = new Unloader("unloader"){{
requirements(Category.effect, with(Items.titanium, 25, Items.silicon, 30));
speed = 7f;
speed = 6f;
}};
//endregion
@@ -1486,7 +1488,7 @@ public class Blocks implements ContentList{
reloadTime = 35f;
shootCone = 40f;
rotatespeed = 8f;
powerUse = 5f;
powerUse = 4f;
targetAir = false;
range = 90f;
shootEffect = Fx.lightningShoot;
@@ -1502,12 +1504,13 @@ public class Blocks implements ContentList{
hasPower = true;
size = 2;
force = 3f;
force = 4f;
scaledForce = 5.5f;
range = 170f;
damage = 0.08f;
damage = 0.1f;
health = 160 * size * size;
rotateSpeed = 10;
range = 85f;
consumes.powerCond(3f, (TractorBeamEntity e) -> e.target != null);
}};
@@ -1556,14 +1559,15 @@ public class Blocks implements ContentList{
}};
segment = new PointDefenseTurret("segment"){{
requirements(Category.turret, with(Items.silicon, 130, Items.thorium, 80, Items.phasefabric, 50));
requirements(Category.turret, with(Items.silicon, 130, Items.thorium, 80, Items.phasefabric, 25));
range = 100f;
hasPower = true;
consumes.power(3f);
size = 2;
shootLength = 5f;
bulletDamage = 12f;
reloadTime = 25f;
bulletDamage = 16f;
reloadTime = 15f;
health = 190 * size * size;
}};
@@ -1699,6 +1703,12 @@ public class Blocks implements ContentList{
//endregion
//region units
commandCenter = new CommandCenter("command-center"){{
requirements(Category.units, ItemStack.with(Items.copper, 200, Items.lead, 250, Items.silicon, 250, Items.graphite, 100));
size = 2;
health = size * size * 55;
}};
groundFactory = new UnitFactory("ground-factory"){{
requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 80));
plans = new UnitPlan[]{
@@ -1769,11 +1779,11 @@ public class Blocks implements ContentList{
}};
exponentialReconstructor = new Reconstructor("exponential-reconstructor"){{
requirements(Category.units, with(Items.lead, 2000, Items.silicon, 750, Items.titanium, 950, Items.thorium, 450, Items.plastanium, 350, Items.phasefabric, 250));
requirements(Category.units, with(Items.lead, 2000, Items.silicon, 750, Items.titanium, 950, Items.thorium, 450, Items.plastanium, 350, Items.phasefabric, 450));
size = 7;
consumes.power(12f);
consumes.items(with(Items.silicon, 250, Items.titanium, 500, Items.plastanium, 400));
consumes.power(13f);
consumes.items(with(Items.silicon, 450, Items.titanium, 550, Items.plastanium, 550));
consumes.liquid(Liquids.cryofluid, 1f);
constructTime = 60f * 60f * 1.5f;
@@ -1781,15 +1791,16 @@ public class Blocks implements ContentList{
upgrades = new UnitType[][]{
{UnitTypes.zenith, UnitTypes.antumbra},
{UnitTypes.spiroct, UnitTypes.arkyid},
};
}};
tetrativeReconstructor = new Reconstructor("tetrative-reconstructor"){{
requirements(Category.units, with(Items.lead, 4000, Items.silicon, 1500, Items.thorium, 500, Items.plastanium, 50, Items.phasefabric, 600, Items.surgealloy, 500));
requirements(Category.units, with(Items.lead, 4000, Items.silicon, 1500, Items.thorium, 500, Items.plastanium, 450, Items.phasefabric, 600, Items.surgealloy, 500));
size = 9;
consumes.power(25f);
consumes.items(with(Items.silicon, 350, Items.plastanium, 450, Items.surgealloy, 400, Items.phasefabric, 150));
consumes.items(with(Items.silicon, 350, Items.plastanium, 550, Items.surgealloy, 350, Items.phasefabric, 150));
consumes.liquid(Liquids.cryofluid, 3f);
constructTime = 60f * 60f * 4;
@@ -1797,6 +1808,7 @@ public class Blocks implements ContentList{
upgrades = new UnitType[][]{
{UnitTypes.antumbra, UnitTypes.eclipse},
{UnitTypes.arkyid, UnitTypes.toxopid},
};
}};
@@ -1862,7 +1874,6 @@ public class Blocks implements ContentList{
//looked up by name, no ref needed
new LegacyMechPad("legacy-mech-pad");
new LegacyUnitFactory("legacy-unit-factory");
new LegacyCommandCenter("legacy-command-center");
//endregion
//region campaign
@@ -1898,7 +1909,7 @@ public class Blocks implements ContentList{
}};
microProcessor = new LogicBlock("micro-processor"){{
requirements(Category.logic, with(Items.copper, 80, Items.lead, 50, Items.silicon, 60));
requirements(Category.logic, with(Items.copper, 80, Items.lead, 50, Items.silicon, 50));
instructionsPerTick = 2;
@@ -1906,15 +1917,28 @@ public class Blocks implements ContentList{
}};
logicProcessor = new LogicBlock("logic-processor"){{
requirements(Category.logic, with(Items.lead, 320, Items.silicon, 140, Items.graphite, 80, Items.thorium, 70));
requirements(Category.logic, with(Items.lead, 320, Items.silicon, 100, Items.graphite, 60, Items.thorium, 50));
instructionsPerTick = 5;
range = 16 * 10;
range = 8 * 20;
size = 2;
}};
hyperProcessor = new LogicBlock("hyper-processor"){{
requirements(Category.logic, with(Items.lead, 450, Items.silicon, 150, Items.thorium, 75, Items.surgealloy, 50));
consumes.liquid(Liquids.cryofluid, 0.08f);
hasLiquids = true;
instructionsPerTick = 25;
range = 8 * 40;
size = 3;
}};
logicDisplay = new LogicDisplay("logic-display"){{
requirements(Category.logic, with(Items.copper, 200, Items.lead, 120, Items.silicon, 100, Items.metaglass, 50));
+6 -6
View File
@@ -163,7 +163,7 @@ public class Bullets implements ContentList{
width = 6f;
height = 8f;
hitEffect = Fx.flakExplosion;
splashDamage = 20f;
splashDamage = 22f;
splashDamageRadius = 20f;
fragBullet = flakGlassFrag;
fragBullets = 5;
@@ -240,7 +240,7 @@ public class Bullets implements ContentList{
explodeRange = 20f;
}};
missileExplosive = new MissileBulletType(3f, 10){{
missileExplosive = new MissileBulletType(3.7f, 10){{
width = 8f;
height = 8f;
shrinkY = 0f;
@@ -255,7 +255,7 @@ public class Bullets implements ContentList{
statusDuration = 60f;
}};
missileIncendiary = new MissileBulletType(3f, 12){{
missileIncendiary = new MissileBulletType(3.7f, 12){{
frontColor = Pal.lightishOrange;
backColor = Pal.lightOrange;
width = 7f;
@@ -269,17 +269,17 @@ public class Bullets implements ContentList{
status = StatusEffects.burning;
}};
missileSurge = new MissileBulletType(3f, 20){{
missileSurge = new MissileBulletType(3.7f, 20){{
width = 8f;
height = 8f;
shrinkY = 0f;
drag = -0.01f;
splashDamageRadius = 28f;
splashDamage = 40f;
splashDamage = 35f;
hitEffect = Fx.blastExplosion;
despawnEffect = Fx.blastExplosion;
lightning = 2;
lightningLength = 14;
lightningLength = 10;
}};
standardCopper = new BasicBulletType(2.5f, 9){{
+25 -1
View File
@@ -52,10 +52,11 @@ public class Fx{
if(!(e.data instanceof Unit)) return;
Unit select = e.data();
boolean block = select instanceof BlockUnitc;
mixcol(Pal.accent, 1f);
alpha(e.fout());
rect(select.type().icon(Cicon.full), select.x, select.y, select.rotation - 90f);
rect(block ? ((BlockUnitc)select).tile().block.icon(Cicon.full) : select.type().icon(Cicon.full), select.x, select.y, block ? 0f : select.rotation - 90f);
alpha(1f);
Lines.stroke(e.fslope() * 1f);
Lines.square(select.x, select.y, e.fout() * select.hitSize * 2f, 45);
@@ -514,6 +515,29 @@ public class Fx{
}),
sapExplosion = new Effect(25, e -> {
color(Pal.sapBullet);
e.scaled(6, i -> {
stroke(3f * i.fout());
Lines.circle(e.x, e.y, 3f + i.fin() * 80f);
});
color(Color.gray);
randLenVectors(e.id, 9, 2f + 70 * e.finpow(), (x, y) -> {
Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f);
});
color(Pal.sapBulletBack);
stroke(1f * e.fout());
randLenVectors(e.id + 1, 8, 1f + 60f * e.finpow(), (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f);
});
}),
massiveExplosion = new Effect(30, e -> {
color(Pal.missileYellow);
+26 -11
View File
@@ -38,7 +38,6 @@ public class TechTree implements ContentList{
node(distributor);
node(sorter, () -> {
node(invertedSorter);
node(message);
node(overflowGate, () -> {
node(underflowGate);
});
@@ -204,6 +203,26 @@ public class TechTree implements ContentList{
});
});
});
node(microProcessor, () -> {
node(switchBlock, () -> {
node(message, () -> {
node(logicDisplay, () -> {
});
node(memoryCell, () -> {
});
});
node(logicProcessor, () -> {
node(hyperProcessor, () -> {
});
});
});
});
});
});
});
@@ -340,6 +359,10 @@ public class TechTree implements ContentList{
});
node(groundFactory, () -> {
node(commandCenter, () -> {
});
node(dagger, () -> {
node(mace, () -> {
node(fortress, () -> {
@@ -406,8 +429,6 @@ public class TechTree implements ContentList{
});
});
//TODO research sectors
node(groundZero, () -> {
node(frozenForest, Seq.with(
new SectorComplete(groundZero),
@@ -556,25 +577,20 @@ public class TechTree implements ContentList{
public ItemStack[] requirements;
/** Requirements that have been fulfilled. Always the same length as the requirement array. */
public final ItemStack[] finishedRequirements;
/** Extra objectives needed to research this. TODO implement */
/** Extra objectives needed to research this. */
public Seq<Objective> objectives = new Seq<>();
/** Time required to research this content, in seconds. */
public float time;
/** Nodes that depend on this node. */
public final Seq<TechNode> children = new Seq<>();
/** Research progress, in seconds. */
public float progress;
TechNode(@Nullable TechNode ccontext, UnlockableContent content, ItemStack[] requirements, Runnable children){
if(ccontext != null){
ccontext.children.add(this);
}
if(ccontext != null) ccontext.children.add(this);
this.parent = ccontext;
this.content = content;
this.requirements = requirements;
this.depth = parent == null ? 0 : parent.depth + 1;
this.progress = Core.settings == null ? 0 : Core.settings.getFloat("research-" + content.name, 0f);
this.time = Seq.with(requirements).mapFloat(i -> i.item.cost * i.amount).sum() * 10;
this.finishedRequirements = new ItemStack[requirements.length];
@@ -599,7 +615,6 @@ public class TechTree implements ContentList{
/** Flushes research progress to settings. */
public void save(){
Core.settings.put("research-" + content.name, progress);
//save finished requirements by item type
for(ItemStack stack : finishedRequirements){
+238 -78
View File
@@ -27,7 +27,7 @@ public class UnitTypes implements ContentList{
public static @EntityDef({Unitc.class, Legsc.class}) UnitType atrax;
//legs + building
public static @EntityDef({Unitc.class, Legsc.class, Builderc.class}) UnitType spiroct, arkyid;
public static @EntityDef({Unitc.class, Legsc.class, Builderc.class}) UnitType spiroct, arkyid, toxopid;
//air (no special traits)
public static @EntityDef({Unitc.class}) UnitType flare, eclipse, horizon, zenith, antumbra;
@@ -72,7 +72,6 @@ public class UnitTypes implements ContentList{
mace = new UnitType("mace"){{
speed = 0.4f;
hitsize = 9f;
range = 10f;
health = 500;
armor = 4f;
@@ -84,12 +83,11 @@ public class UnitTypes implements ContentList{
reload = 14f;
recoil = 1f;
ejectEffect = Fx.none;
bullet = new BulletType(3f, 30f){{
bullet = new BulletType(3.9f, 30f){{
ammoMultiplier = 3f;
hitSize = 7f;
lifetime = 42f;
lifetime = 12f;
pierce = true;
drag = 0.05f;
statusDuration = 60f * 4;
shootEffect = Fx.shootSmallFlame;
hitEffect = Fx.hitFlameSmall;
@@ -376,52 +374,218 @@ public class UnitTypes implements ContentList{
}});
}};
//TODO implement
arkyid = new UnitType("arkyid"){{
drag = 0.1f;
speed = 0.5f;
hitsize = 9f;
health = 140;
hitsize = 21f;
health = 8000;
armor = 6f;
rotateSpeed = 2.7f;
legCount = 6;
legMoveSpace = 1f;
legPairOffset = 3;
legLength = 34f;
rotateShooting = false;
legLength = 30f;
legExtension = -15;
legBaseOffset = 10f;
landShake = 2f;
landShake = 1f;
legSpeed = 0.1f;
legLengthScl = 1f;
legLengthScl = 0.96f;
rippleScale = 2f;
legSpeed = 0.2f;
legSplashDamage = 32;
legSplashRange = 30;
hovering = true;
allowLegStep = true;
visualElevation = 0.65f;
groundLayer = Layer.legUnit;
BulletType sapper = new SapBulletType(){{
sapStrength = 0.83f;
length = 55f;
damage = 34;
shootEffect = Fx.shootSmall;
hitColor = color = Color.valueOf("bf92f9");
despawnEffect = Fx.none;
width = 0.55f;
lifetime = 30f;
knockback = -1f;
}};
weapons.add(
new Weapon("missiles-mount"){{
reload = 20f;
new Weapon("spiroct-weapon"){{
reload = 9f;
x = 4f;
y = 8f;
rotate = true;
shake = 1f;
bullet = new MissileBulletType(2.7f, 12, "missile"){{
width = 8f;
height = 8f;
shrinkY = 0f;
drag = -0.003f;
homingRange = 60f;
keepVelocity = false;
splashDamageRadius = 25f;
splashDamage = 10f;
lifetime = 120f;
trailColor = Color.gray;
backColor = Pal.bulletYellowBack;
frontColor = Pal.bulletYellow;
hitEffect = Fx.blastExplosion;
despawnEffect = Fx.blastExplosion;
weaveScale = 8f;
weaveMag = 2f;
bullet = sapper;
}},
new Weapon("spiroct-weapon"){{
reload = 15f;
x = 9f;
y = 6f;
rotate = true;
bullet = sapper;
}},
new Weapon("spiroct-weapon"){{
reload = 23f;
x = 14f;
y = 0f;
rotate = true;
bullet = sapper;
}},
new Weapon("large-purple-mount"){{
y = -7f;
x = 9f;
shootY = 7f;
reload = 45;
shake = 3f;
rotateSpeed = 2f;
ejectEffect = Fx.shellEjectSmall;
shootSound = Sounds.shootBig;
rotate = true;
occlusion = 8f;
recoil = 3f;
bullet = new ArtilleryBulletType(2f, 12){{
hitEffect = Fx.sapExplosion;
knockback = 0.8f;
lifetime = 70f;
width = height = 19f;
collidesTiles = true;
ammoMultiplier = 4f;
splashDamageRadius = 95f;
splashDamage = 65f;
backColor = Pal.sapBulletBack;
frontColor = lightningColor = Pal.sapBullet;
lightning = 3;
lightningLength = 10;
smokeEffect = Fx.shootBigSmoke2;
shake = 5f;
status = StatusEffects.sapped;
statusDuration = 60f * 10;
}};
}});
}};
toxopid = new UnitType("toxopid"){{
drag = 0.1f;
speed = 0.5f;
hitsize = 21f;
health = 23000;
armor = 14f;
rotateSpeed = 1.9f;
legCount = 8;
legMoveSpace = 0.8f;
legPairOffset = 3;
legLength = 75f;
legExtension = -20;
legBaseOffset = 8f;
landShake = 1f;
legSpeed = 0.1f;
legLengthScl = 0.93f;
rippleScale = 3f;
legSpeed = 0.19f;
legSplashDamage = 80;
legSplashRange = 60;
hovering = true;
allowLegStep = true;
visualElevation = 0.95f;
groundLayer = Layer.legUnit;
weapons.add(
new Weapon("large-purple-mount"){{
y = -5f;
x = 11f;
shootY = 7f;
reload = 30;
shake = 4f;
rotateSpeed = 2f;
ejectEffect = Fx.shellEjectSmall;
shootSound = Sounds.shootBig;
rotate = true;
occlusion = 12f;
recoil = 3f;
shots = 2;
spacing = 17f;
bullet = new ShrapnelBulletType(){{
length = 90f;
damage = 110f;
width = 25f;
serrationLenScl = 7f;
serrationSpaceOffset = 60f;
serrationFadeOffset = 0f;
serrations = 10;
serrationWidth = 6f;
fromColor = Pal.sapBullet;
toColor = Pal.sapBulletBack;
shootEffect = smokeEffect = Fx.sparkShoot;
}};
}});
weapons.add(new Weapon("toxopid-cannon"){{
y = -14f;
x = 0f;
shootY = 22f;
mirror = false;
reload = 180;
shake = 10f;
recoil = 10f;
rotateSpeed = 1f;
ejectEffect = Fx.shellEjectBig;
shootSound = Sounds.shootBig;
rotate = true;
occlusion = 30f;
bullet = new ArtilleryBulletType(3f, 70){{
hitEffect = Fx.sapExplosion;
knockback = 0.8f;
lifetime = 80f;
width = height = 25f;
collidesTiles = collides = true;
ammoMultiplier = 4f;
splashDamageRadius = 95f;
splashDamage = 90f;
backColor = Pal.sapBulletBack;
frontColor = lightningColor = Pal.sapBullet;
lightning = 5;
lightningLength = 20;
smokeEffect = Fx.shootBigSmoke2;
hitShake = 10f;
status = StatusEffects.sapped;
statusDuration = 60f * 10;
fragLifeMin = 0.3f;
fragBullets = 12;
fragBullet = new ArtilleryBulletType(2.3f, 30){{
hitEffect = Fx.sapExplosion;
knockback = 0.8f;
lifetime = 90f;
width = height = 20f;
collidesTiles = false;
splashDamageRadius = 90f;
splashDamage = 55f;
backColor = Pal.sapBulletBack;
frontColor = lightningColor = Pal.sapBullet;
lightning = 2;
lightningLength = 5;
smokeEffect = Fx.shootBigSmoke2;
hitShake = 5f;
status = StatusEffects.sapped;
statusDuration = 60f * 10;
}};
}};
}});
}};
@@ -438,6 +602,8 @@ public class UnitTypes implements ContentList{
faceTarget = false;
engineOffset = 5.5f;
range = 140f;
crashDamageMultiplier = 4f;
weapons.add(new Weapon(){{
y = 0f;
x = 2f;
@@ -449,7 +615,7 @@ public class UnitTypes implements ContentList{
}};
horizon = new UnitType("horizon"){{
health = 300;
health = 350;
speed = 2f;
accel = 0.08f;
drag = 0.016f;
@@ -458,19 +624,19 @@ public class UnitTypes implements ContentList{
engineOffset = 7.8f;
range = 140f;
faceTarget = false;
armor = 2f;
armor = 4f;
weapons.add(new Weapon(){{
minShootVelocity = 0.75f;
x = 3f;
shootY = 0f;
reload = 12f;
reload = 11f;
shootCone = 180f;
ejectEffect = Fx.none;
inaccuracy = 15f;
ignoreRotation = true;
shootSound = Sounds.none;
bullet = new BombBulletType(23f, 25f){{
bullet = new BombBulletType(28f, 25f){{
width = 10f;
height = 14f;
hitEffect = Fx.flakExplosion;
@@ -484,21 +650,21 @@ public class UnitTypes implements ContentList{
}};
zenith = new UnitType("zenith"){{
health = 1000;
speed = 1.9f;
health = 700;
speed = 1.7f;
accel = 0.04f;
drag = 0.016f;
flying = true;
range = 140f;
hitsize = 18f;
lowAltitude = true;
armor = 6f;
armor = 5f;
engineOffset = 12f;
engineSize = 3f;
weapons.add(new Weapon("zenith-missiles"){{
reload = 32f;
reload = 40f;
x = 7f;
rotate = true;
shake = 1f;
@@ -534,21 +700,21 @@ public class UnitTypes implements ContentList{
rotateSpeed = 1.9f;
flying = true;
lowAltitude = true;
health = 9000;
health = 7000;
armor = 9f;
engineOffset = 21;
engineSize = 5.3f;
hitsize = 58f;
hitsize = 56f;
BulletType missiles = new MissileBulletType(2.7f, 10){{
width = 8f;
height = 8f;
shrinkY = 0f;
drag = -0.01f;
splashDamageRadius = 40f;
splashDamage = 40f;
splashDamageRadius = 20f;
splashDamage = 30f;
ammoMultiplier = 4f;
lifetime = 80f;
lifetime = 50f;
hitEffect = Fx.blastExplosion;
despawnEffect = Fx.blastExplosion;
@@ -582,18 +748,18 @@ public class UnitTypes implements ContentList{
new Weapon("large-bullet-mount"){{
y = 2f;
x = 10f;
shootY = 12f;
reload = 10;
shootY = 10f;
reload = 12;
shake = 1f;
rotateSpeed = 2f;
ejectEffect = Fx.shellEjectSmall;
shootSound = Sounds.shootBig;
rotate = true;
occlusion = 8f;
bullet = new BasicBulletType(7f, 60){{
bullet = new BasicBulletType(7f, 50){{
width = 12f;
height = 18f;
lifetime = 30f;
lifetime = 25f;
shootEffect = Fx.shootBig;
}};
}}
@@ -607,13 +773,25 @@ public class UnitTypes implements ContentList{
rotateSpeed = 1f;
flying = true;
lowAltitude = true;
health = 18000;
health = 20000;
engineOffset = 38;
engineSize = 7.3f;
hitsize = 58f;
destructibleWreck = false;
armor = 13f;
BulletType fragBullet = new FlakBulletType(4f, 5){{
shootEffect = Fx.shootBig;
ammoMultiplier = 4f;
splashDamage = 42f;
splashDamageRadius = 25f;
collidesGround = true;
lifetime = 38f;
status = StatusEffects.blasted;
statusDuration = 60f;
}};
weapons.add(
new Weapon("large-laser-mount"){{
shake = 4f;
@@ -621,14 +799,14 @@ public class UnitTypes implements ContentList{
x = 18f;
y = 5f;
rotateSpeed = 2f;
reload = 50f;
reload = 45f;
recoil = 4f;
shootSound = Sounds.laser;
occlusion = 20f;
rotate = true;
bullet = new LaserBulletType(){{
damage = 75f;
damage = 90f;
sideAngle = 20f;
sideWidth = 1.5f;
sideLength = 80f;
@@ -638,50 +816,29 @@ public class UnitTypes implements ContentList{
colors = new Color[]{Color.valueOf("ec7458aa"), Color.valueOf("ff9c5a"), Color.white};
}};
}},
new Weapon("missiles-mount"){{
new Weapon("large-artillery"){{
x = 11f;
y = 27f;
rotateSpeed = 2f;
reload = 4f;
reload = 9f;
shootSound = Sounds.flame;
occlusion = 7f;
rotate = true;
recoil = 0.5f;
bullet = Bullets.pyraFlame;
bullet = fragBullet;
}},
new Weapon("large-artillery"){{
y = -13f;
x = 20f;
reload = 18f;
reload = 12f;
ejectEffect = Fx.shellEjectSmall;
rotateSpeed = 7f;
shake = 1f;
shootSound = Sounds.shoot;
rotate = true;
occlusion = 12f;
bullet = new ArtilleryBulletType(3.2f, 12){{
trailMult = 0.8f;
hitEffect = Fx.massiveExplosion;
knockback = 1.5f;
lifetime = 140f;
height = 12f;
width = 12f;
collidesTiles = false;
ammoMultiplier = 4f;
splashDamageRadius = 60f;
splashDamage = 60f;
backColor = Pal.missileYellowBack;
frontColor = Pal.missileYellow;
trailEffect = Fx.artilleryTrail;
trailSize = 6f;
hitShake = 4f;
shootEffect = Fx.shootBig2;
status = StatusEffects.blasted;
statusDuration = 60f;
}};
bullet = fragBullet;
}});
}};
@@ -700,6 +857,7 @@ public class UnitTypes implements ContentList{
engineOffset = 5.7f;
itemCapacity = 30;
range = 50f;
isCounted = false;
mineTier = 1;
mineSpeed = 2.5f;
@@ -720,6 +878,7 @@ public class UnitTypes implements ContentList{
engineOffset = 6.5f;
hitsize = 8f;
lowAltitude = true;
isCounted = false;
mineTier = 2;
mineSpeed = 3.5f;
@@ -1094,6 +1253,7 @@ public class UnitTypes implements ContentList{
hitsize = 0f;
health = 1;
rotateSpeed = 360f;
itemCapacity = 0;
}
@Override
+4
View File
@@ -325,6 +325,10 @@ public class Logic implements ApplicationListener{
Events.fire(Trigger.update);
universe.updateGlobal();
if(Core.settings.modified() && !state.isPlaying()){
Core.settings.forceSave();
}
if(state.isGame()){
if(!net.client()){
state.enemies = Groups.unit.count(u -> u.team() == state.rules.waveTeam && u.type().isCounted);
+19
View File
@@ -366,6 +366,9 @@ public class NetClient implements ApplicationListener{
@Remote
public static void playerDisconnect(int playerid){
if(netClient != null){
netClient.addRemovedEntity(playerid);
}
Groups.player.removeByID(playerid);
}
@@ -559,6 +562,22 @@ public class NetClient implements ApplicationListener{
//limit to 10 to prevent buffer overflows
int usedRequests = Math.min(player.builder().plans().size, 10);
int totalLength = 0;
//prevent buffer overflow by checking config length
for(int i = 0; i < usedRequests; i++){
BuildPlan plan = player.builder().plans().get(i);
if(plan.config instanceof byte[]){
int length = ((byte[])plan.config).length;
totalLength += length;
}
if(totalLength > 2048){
usedRequests = i + 1;
break;
}
}
requests = new BuildPlan[usedRequests];
for(int i = 0; i < usedRequests; i++){
requests[i] = player.builder().plans().get(i);
+27 -6
View File
@@ -371,6 +371,11 @@ public class NetServer implements ApplicationListener{
return;
}
if(currentlyKicking[0] != null){
player.sendMessage("[scarlet]A vote is already in progress.");
return;
}
if(args.length == 0){
StringBuilder builder = new StringBuilder();
builder.append("[orange]Players to kick: \n");
@@ -385,9 +390,7 @@ public class NetServer implements ApplicationListener{
int id = Strings.parseInt(args[0].substring(1));
found = Groups.player.find(p -> p.id() == id);
}else{
found = Groups.player.find(p -> {
return p.name.equalsIgnoreCase(args[0]);
});
found = Groups.player.find(p -> p.name.equalsIgnoreCase(args[0]));
}
if(found != null){
@@ -527,6 +530,10 @@ public class NetServer implements ApplicationListener{
public static void serverPacketUnreliable(Player player, String type, String contents){
serverPacketReliable(player, type, contents);
}
private static boolean invalid(float f){
return Float.isInfinite(f) || Float.isNaN(f);
}
@Remote(targets = Loc.client, unreliable = true)
public static void clientSnapshot(
@@ -545,6 +552,16 @@ public class NetServer implements ApplicationListener{
NetConnection con = player.con;
if(con == null || snapshotID < con.lastReceivedClientSnapshot) return;
//validate coordinates just in case
if(invalid(x)) x = 0f;
if(invalid(y)) y = 0f;
if(invalid(xVelocity)) xVelocity = 0f;
if(invalid(yVelocity)) yVelocity = 0f;
if(invalid(pointerX)) pointerX = 0f;
if(invalid(pointerY)) pointerY = 0f;
if(invalid(rotation)) rotation = 0f;
if(invalid(baseRotation)) baseRotation = 0f;
boolean verifyPosition = !player.dead() && netServer.admins.getStrict() && headless;
if(con.lastReceivedClientTime == 0) con.lastReceivedClientTime = Time.millis() - 16;
@@ -614,7 +631,7 @@ public class NetServer implements ApplicationListener{
Unit unit = player.unit();
long elapsed = Time.timeSinceMillis(con.lastReceivedClientTime);
float maxSpeed = (boosting ? player.unit().type().boostMultiplier : 1f) * player.unit().type().speed;
float maxSpeed = ((player.unit().type().canBoost && player.unit().isFlying()) ? player.unit().type().boostMultiplier : 1f) * player.unit().type().speed;
if(unit.isGrounded()){
maxSpeed *= unit.floorSpeedMultiplier();
}
@@ -682,8 +699,8 @@ public class NetServer implements ApplicationListener{
public static void adminRequest(Player player, Player other, AdminAction action){
if(!player.admin){
Log.warn("ACCESS DENIED: Player @ / @ attempted to perform admin action without proper security access.",
player.name, player.con.address);
Log.warn("ACCESS DENIED: Player @ / @ attempted to perform admin action '@' on '@' without proper security access.",
player.name, player.con.address, action.name(), other == null ? null : other.name);
return;
}
@@ -762,6 +779,10 @@ public class NetServer implements ApplicationListener{
}
if(state.isGame() && net.server()){
if(state.rules.pvp){
state.serverPaused = isWaitingForPlayers();
}
sync();
}
}
+6
View File
@@ -185,6 +185,8 @@ public class Renderer implements ApplicationListener{
}
public void draw(){
Events.fire(Trigger.preDraw);
camera.update();
if(Float.isNaN(camera.position.x) || Float.isNaN(camera.position.y)){
@@ -205,6 +207,8 @@ public class Renderer implements ApplicationListener{
Draw.sort(true);
Events.fire(Trigger.draw);
if(pixelator.enabled()){
pixelator.register();
}
@@ -254,6 +258,8 @@ public class Renderer implements ApplicationListener{
Draw.reset();
Draw.flush();
Draw.sort(false);
Events.fire(Trigger.postDraw);
}
private void drawBackground(){
+10 -3
View File
@@ -128,6 +128,8 @@ public class UI implements ApplicationListener, Loadable{
public void update(){
if(disableUI || Core.scene == null) return;
Events.fire(Trigger.uiDrawBegin);
Core.scene.act();
Core.scene.draw();
@@ -143,6 +145,8 @@ public class UI implements ApplicationListener, Loadable{
control.tutorial.draw();
Draw.flush();
}
Events.fire(Trigger.uiDrawEnd);
}
@Override
@@ -221,12 +225,15 @@ public class UI implements ApplicationListener, Loadable{
}
public TextureRegionDrawable getIcon(String name){
if(Icon.icons.containsKey(name)){
return Icon.icons.get(name);
}
if(Icon.icons.containsKey(name)) return Icon.icons.get(name);
return Core.atlas.getDrawable("error");
}
public TextureRegionDrawable getIcon(String name, String def){
if(Icon.icons.containsKey(name)) return Icon.icons.get(name);
return getIcon(def);
}
public void loadAnd(Runnable call){
loadAnd("@loading", call);
}
+1 -1
View File
@@ -126,7 +126,7 @@ public class MapEditor{
x = Mathf.clamp(x, (drawBlock.size - 1) / 2, width() - drawBlock.size / 2 - 1);
y = Mathf.clamp(y, (drawBlock.size - 1) / 2, height() - drawBlock.size / 2 - 1);
if(!hasOverlap(x, y)){
tile(x, y).setBlock(drawBlock, drawTeam, 0);
tile(x, y).setBlock(drawBlock, drawTeam, rotation);
}
}else{
boolean isFloor = drawBlock.isFloor() && drawBlock != Blocks.air;
+6 -11
View File
@@ -110,18 +110,13 @@ public class MapRenderer implements Disposable{
if(wall != Blocks.air && wall.synthetic()){
region = !Core.atlas.isFound(wall.editorIcon()) || !center ? Core.atlas.find("clear-editor") : wall.editorIcon();
if(wall.rotate){
mesh.draw(idxWall, region,
wx * tilesize + wall.offset, wy * tilesize + wall.offset,
region.getWidth() * Draw.scl, region.getHeight() * Draw.scl, tile.build == null ? 0 : tile.build.rotdeg() - 90);
}else{
float width = region.getWidth() * Draw.scl, height = region.getHeight() * Draw.scl;
float width = region.getWidth() * Draw.scl, height = region.getHeight() * Draw.scl;
mesh.draw(idxWall, region,
wx * tilesize + wall.offset + (tilesize - width) / 2f,
wy * tilesize + wall.offset + (tilesize - height) / 2f,
width, height);
}
mesh.draw(idxWall, region,
wx * tilesize + wall.offset + (tilesize - width) / 2f,
wy * tilesize + wall.offset + (tilesize - height) / 2f,
width, height,
tile.build == null || !wall.rotate ? 0 : tile.build.rotdeg() - 90);
}else{
region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length - 1)];
+36 -16
View File
@@ -20,6 +20,7 @@ import static mindustry.Vars.*;
/** Utility class for damaging in an area. */
public class Damage{
private static Tile furthest;
private static Rect rect = new Rect();
private static Rect hitrect = new Rect();
private static Vec2 tr = new Vec2();
@@ -30,24 +31,26 @@ public class Damage{
private static Unit tmpUnit;
/** Creates a dynamic explosion based on specified parameters. */
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color){
for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){
int branches = 5 + Mathf.clamp((int)(power / 30), 1, 20);
Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.derelict, Pal.power, 3, x, y, Mathf.random(360f), branches + Mathf.range(2)));
}
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color, boolean damage){
if(damage){
for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){
int branches = 5 + Mathf.clamp((int)(power / 30), 1, 20);
Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.derelict, Pal.power, 3, x, y, Mathf.random(360f), branches + Mathf.range(2)));
}
for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i++){
Time.run(i / 2f, () -> Call.createBullet(Bullets.fireball, Team.derelict, x, y, Mathf.random(360f), Bullets.fireball.damage, 1, 1));
}
for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i++){
Time.run(i / 2f, () -> Call.createBullet(Bullets.fireball, Team.derelict, x, y, Mathf.random(360f), Bullets.fireball.damage, 1, 1));
}
int waves = Mathf.clamp((int)(explosiveness / 4), 0, 30);
int waves = Mathf.clamp((int)(explosiveness / 4), 0, 30);
for(int i = 0; i < waves; i++){
int f = i;
Time.run(i * 2f, () -> {
Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f);
Fx.blockExplosionSmoke.at(x + Mathf.range(radius), y + Mathf.range(radius));
});
for(int i = 0; i < waves; i++){
int f = i;
Time.run(i * 2f, () -> {
Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f);
Fx.blockExplosionSmoke.at(x + Mathf.range(radius), y + Mathf.range(radius));
});
}
}
if(explosiveness > 15f){
@@ -74,6 +77,23 @@ 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){
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),
(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;
Damage.collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), resultLength);
b.fdata = furthest != null ? resultLength : length;
return resultLength;
}
public static void collideLine(Bullet hitter, Team team, Effect effect, float x, float y, float angle, float length){
collideLine(hitter, team, effect, x, y, angle, length, false);
}
@@ -87,7 +107,7 @@ public class Damage{
tr.trns(angle, length);
Intc2 collider = (cx, cy) -> {
Building tile = world.build(cx, cy);
if(tile != null && !collidedBlocks.contains(tile.pos()) && tile.team() != team && tile.collide(hitter)){
if(tile != null && !collidedBlocks.contains(tile.pos()) && tile.team != team && tile.collide(hitter)){
tile.collision(hitter);
collidedBlocks.add(tile.pos());
hitter.type.hit(hitter, tile.x, tile.y);
+1 -1
View File
@@ -101,7 +101,7 @@ public class EntityGroup<T extends Entityc> implements Iterable<T>{
if(map == null) throw new RuntimeException("Mapping is not enabled for group " + id + "!");
T t = map.get(id);
if(t != null){ //remove if present in map already
remove(t);
t.remove();
}
}
+1 -1
View File
@@ -17,7 +17,7 @@ public class Fires{
/** Start a fire on the tile. If there already is a file there, refreshes its lifetime. */
public static void create(Tile tile){
if(net.client() || tile == null) return; //not clientside.
if(net.client() || tile == null || !state.rules.fire) return; //not clientside.
Fire fire = map.get(tile.pos());
+11 -2
View File
@@ -19,8 +19,17 @@ public class Units{
private static boolean boolResult;
@Remote(called = Loc.server)
public static void unitDeath(Unit unit){
unit.killed();
public static void unitDeath(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.killed();
}
}
@Remote(called = Loc.server)
@@ -23,7 +23,6 @@ public class ForceFieldAbility implements Ability{
private float realRad;
private Unit paramUnit;
private boolean hadShield;
private final Cons<Shielderc> shieldConsumer = trait -> {
if(trait.team() != paramUnit.team && Intersector.isInsideHexagon(paramUnit.x, paramUnit.y, realRad * 2f, trait.x(), trait.y()) && paramUnit.shield > 0){
trait.absorb();
@@ -32,6 +31,8 @@ public class ForceFieldAbility implements Ability{
//break shield
if(paramUnit.shield <= trait.damage()){
paramUnit.shield -= cooldown * regen;
Fx.shieldBreak.at(paramUnit.x, paramUnit.y, radius, paramUnit.team.color);
}
paramUnit.shield -= trait.damage();
@@ -54,13 +55,6 @@ public class ForceFieldAbility implements Ability{
unit.shield += Time.delta * regen;
}
//break effect
if(hadShield && unit.shield <= 0){
Fx.shieldBreak.at(paramUnit.x, paramUnit.y, radius, paramUnit.team.color);
}
hadShield = unit.shield > 0;
if(unit.shield > 0){
unit.timer2 = Mathf.lerpDelta(unit.timer2, 1f, 0.06f);
paramUnit = unit;
@@ -74,7 +74,7 @@ public abstract class BulletType extends Content{
public float fragCone = 360f;
public int fragBullets = 9;
public float fragVelocityMin = 0.2f, fragVelocityMax = 1f;
public float fragVelocityMin = 0.2f, fragVelocityMax = 1f, fragLifeMin = 1f, fragLifeMax = 1f;
public BulletType fragBullet = null;
public Color hitColor = Color.white;
@@ -92,6 +92,7 @@ public abstract class BulletType extends Content{
public float homingPower = 0f;
public float homingRange = 50f;
public Color lightningColor = Pal.surge;
public int lightning;
public int lightningLength = 5;
/** Use a negative value to use default bullet damage. */
@@ -148,7 +149,7 @@ public abstract class BulletType extends Content{
for(int i = 0; i < fragBullets; i++){
float len = Mathf.random(1f, 7f);
float a = b.rotation() + Mathf.range(fragCone/2);
fragBullet.create(b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax));
fragBullet.create(b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax), Mathf.random(fragLifeMin, fragLifeMax));
}
}
@@ -172,7 +173,7 @@ public abstract class BulletType extends Content{
}
for(int i = 0; i < lightning; i++){
Lightning.create(b, Pal.surge, 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);
}
}
@@ -246,6 +247,10 @@ public abstract class BulletType extends Content{
return create(parent.owner(), parent.team, x, y, angle);
}
public Bullet create(Bullet parent, float x, float y, float angle, float velocityScl, float lifeScale){
return create(parent.owner(), parent.team, x, y, angle, velocityScl, lifeScale);
}
public Bullet create(Bullet parent, float x, float y, float angle, float velocityScl){
return create(parent.owner(), parent.team, x, y, angle, velocityScl);
}
@@ -29,7 +29,7 @@ public class HealBulletType extends BulletType{
@Override
public boolean collides(Bullet b, Building tile){
return tile.team() != b.team || tile.healthf() < 1f;
return tile.team != b.team || tile.healthf() < 1f;
}
@Override
@@ -46,7 +46,7 @@ public class HealBulletType extends BulletType{
public void hitTile(Bullet b, Building tile){
super.hit(b);
if(tile.team() == b.team && !(tile.block() instanceof BuildBlock)){
if(tile.team == b.team && !(tile.block() instanceof BuildBlock)){
Fx.healBlockFull.at(tile.x, tile.y, tile.block().size, Pal.heal);
tile.heal(healPercent / 100f * tile.maxHealth());
}
@@ -10,8 +10,6 @@ import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.world.*;
import static mindustry.Vars.world;
public class LaserBulletType extends BulletType{
protected static Tile furthest;
@@ -49,24 +47,13 @@ public class LaserBulletType extends BulletType{
@Override
public void init(Bullet b){
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),
(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;
Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), resultLength);
if(furthest != null) b.data(resultLength);
float resultLength = Damage.collideLaser(b, length);
laserEffect.at(b.x, b.y, b.rotation(), resultLength * 0.75f);
}
@Override
public void draw(Bullet b){
float realLength = b.data() == null ? length : (Float)b.data();
float realLength = b.fdata;
float f = Mathf.curve(b.fin(), 0f, 0.2f);
float baseLen = realLength * f;
@@ -15,7 +15,7 @@ public class ShrapnelBulletType extends BulletType{
public Color fromColor = Color.white, toColor = Pal.lancerLaser;
public int serrations = 7;
public float serrationLenScl = 10f, serrationWidth = 4f, serrationSpacing = 8f, serrationSpaceOffset = 80f;
public float serrationLenScl = 10f, serrationWidth = 4f, serrationSpacing = 8f, serrationSpaceOffset = 80f, serrationFadeOffset = 0.5f;
public ShrapnelBulletType(){
speed = 0.01f;
@@ -24,23 +24,26 @@ public class ShrapnelBulletType extends BulletType{
lifetime = 10f;
despawnEffect = Fx.none;
pierce = true;
keepVelocity = false;
}
@Override
public void init(Bullet b){
Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), length);
Damage.collideLaser(b, length);
}
@Override
public void draw(Bullet b){
float realLength = b.fdata;
Draw.color(fromColor, toColor, b.fin());
for(int i = 0; i < serrations; i++){
for(int i = 0; i < (int)(serrations * realLength / length); i++){
Tmp.v1.trns(b.rotation(), i * serrationSpacing);
float sl = Mathf.clamp(b.fout() - 0.5f) * (serrationSpaceOffset - i * serrationLenScl);
float sl = Mathf.clamp(b.fout() - serrationFadeOffset) * (serrationSpaceOffset - i * serrationLenScl);
Drawf.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, serrationWidth, sl, b.rotation() + 90);
Drawf.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, serrationWidth, sl, b.rotation() - 90);
}
Drawf.tri(b.x, b.y, width * b.fout(), (length + 50), b.rotation());
Drawf.tri(b.x, b.y, width * b.fout(), (realLength + 50), b.rotation());
Drawf.tri(b.x, b.y, width * b.fout(), 10f, b.rotation() + 180f);
Draw.reset();
}
@@ -27,7 +27,7 @@ abstract class BlockUnitComp implements Unitc{
@Override
public void update(){
if(tile != null){
team = tile.team();
team = tile.team;
}
}
@@ -61,7 +61,7 @@ abstract class BlockUnitComp implements Unitc{
public void team(Team team){
if(tile != null && this.team != team){
this.team = team;
if(tile.team() != team){
if(tile.team != team){
tile.team(team);
}
}
@@ -144,7 +144,6 @@ abstract class BuilderComp implements Unitc{
boolean shouldSkip(BuildPlan request, @Nullable Building core){
//requests that you have at least *started* are considered
if(state.rules.infiniteResources || team().rules().infiniteResources || request.breaking || core == null) return false;
//TODO these are bad criteria
return (request.stuck && !core.items.has(request.block.requirements)) || (Structs.contains(request.block.requirements, i -> !core.items.has(i.item)) && !request.initialized);
}
@@ -135,8 +135,9 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public final void writeBase(Writes write){
write.f(health);
write.b(rotation);
write.b(rotation | 0b10000000);
write.b(team.id);
write.b(0); //extra padding for later use
if(items != null) items.write(write);
if(power != null) power.write(write);
if(liquids != null) liquids.write(write);
@@ -145,12 +146,20 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public final void readBase(Reads read){
health = read.f();
rotation = read.b();
byte rot = read.b();
team = Team.get(read.b());
if(items != null) items.read(read);
if(power != null) power.read(read);
if(liquids != null) liquids.read(read);
if(cons != null) cons.read(read);
rotation = rot & 0b01111111;
boolean legacy = true;
if((rot & 0b10000000) != 0){
read.b(); //padding
legacy = false;
}
if(items != null) items.read(read, legacy);
if(power != null) power.read(read, legacy);
if(liquids != null) liquids.read(read, legacy);
if(cons != null) cons.read(read, legacy);
}
public void writeAll(Writes write){
@@ -410,7 +419,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
int trns = block.size/2 + 1;
Tile next = tile.getNearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns);
if(next != null && next.build != null && next.build.team() == team && next.build.acceptPayload(base(), todump)){
if(next != null && next.build != null && next.build.team == team && next.build.acceptPayload(base(), todump)){
next.build.handlePayload(base(), todump);
return true;
}
@@ -431,7 +440,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){
Building other = proximity.get((i + dump) % proximity.size);
if(other.team() == team && other.acceptPayload(base(), todump)){
if(other.team == team && other.acceptPayload(base(), todump)){
other.handlePayload(base(), todump);
incrementDump(proximity.size);
return true;
@@ -510,34 +519,31 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
next = next.getLiquidDestination(base(), liquid);
if(next.team() == team && next.block.hasLiquids && liquids.get(liquid) > 0f){
if(next.team == team && next.block.hasLiquids && liquids.get(liquid) > 0f){
float ofract = next.liquids.get(liquid) / next.block.liquidCapacity;
float fract = liquids.get(liquid) / block.liquidCapacity * block.liquidPressure;
float flow = Math.min(Mathf.clamp((fract - ofract) * (1f)) * (block.liquidCapacity), liquids.get(liquid));
flow = Math.min(flow, next.block.liquidCapacity - next.liquids.get(liquid) - 0.001f);
if(next.acceptLiquid(base(), liquid, 0f)){
float ofract = next.liquids().get(liquid) / next.block.liquidCapacity;
float fract = liquids.get(liquid) / block.liquidCapacity * block.liquidPressure;
float flow = Math.min(Mathf.clamp((fract - ofract) * (1f)) * (block.liquidCapacity), liquids.get(liquid));
flow = Math.min(flow, next.block.liquidCapacity - next.liquids().get(liquid) - 0.001f);
if(flow > 0f && ofract <= fract && next.acceptLiquid(base(), liquid, flow)){
next.handleLiquid(base(), liquid, flow);
liquids.remove(liquid, flow);
return flow;
}else if(next.liquids.currentAmount() / next.block.liquidCapacity > 0.1f && fract > 0.1f){
//TODO these are incorrect effect positions
float fx = (x + next.x) / 2f, fy = (y + next.y) / 2f;
if(flow > 0f && ofract <= fract && next.acceptLiquid(base(), liquid, flow)){
next.handleLiquid(base(), liquid, flow);
liquids.remove(liquid, flow);
return flow;
}else if(ofract > 0.1f && fract > 0.1f){
//TODO these are incorrect effect positions
float fx = (x + next.x) / 2f, fy = (y + next.y) / 2f;
Liquid other = next.liquids().current();
if((other.flammability > 0.3f && liquid.temperature > 0.7f) || (liquid.flammability > 0.3f && other.temperature > 0.7f)){
damage(1 * Time.delta);
next.damage(1 * Time.delta);
if(Mathf.chance(0.1 * Time.delta)){
Fx.fire.at(fx, fy);
}
}else if((liquid.temperature > 0.7f && other.temperature < 0.55f) || (other.temperature > 0.7f && liquid.temperature < 0.55f)){
liquids.remove(liquid, Math.min(liquids.get(liquid), 0.7f * Time.delta));
if(Mathf.chance(0.2f * Time.delta)){
Fx.steam.at(fx, fy);
}
Liquid other = next.liquids.current();
if((other.flammability > 0.3f && liquid.temperature > 0.7f) || (liquid.flammability > 0.3f && other.temperature > 0.7f)){
damage(1 * Time.delta);
next.damage(1 * Time.delta);
if(Mathf.chance(0.1 * Time.delta)){
Fx.fire.at(fx, fy);
}
}else if((liquid.temperature > 0.7f && other.temperature < 0.55f) || (other.temperature > 0.7f && liquid.temperature < 0.55f)){
liquids.remove(liquid, Math.min(liquids.get(liquid), 0.7f * Time.delta));
if(Mathf.chance(0.2f * Time.delta)){
Fx.steam.at(fx, fy);
}
}
}
@@ -568,7 +574,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size);
Building other = proximity.get((i + dump) % proximity.size);
if(other.team() == team && other.acceptItem(base(), item) && canDump(other, item)){
if(other.team == team && other.acceptItem(base(), item) && canDump(other, item)){
other.handleItem(base(), item);
return;
}
@@ -586,7 +592,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size);
Building other = proximity.get((i + dump) % proximity.size);
if(other.team() == team && other.acceptItem(base(), item) && canDump(other, item)){
if(other.team == team && other.acceptItem(base(), item) && canDump(other, item)){
other.handleItem(base(), item);
return true;
}
@@ -619,7 +625,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int ii = 0; ii < content.items().size; ii++){
Item item = content.item(ii);
if(other.team() == team && items.has(item) && other.acceptItem(base(), item) && canDump(other, item)){
if(other.team == team && items.has(item) && other.acceptItem(base(), item) && canDump(other, item)){
other.handleItem(base(), item);
items.remove(item, 1);
incrementDump(proximity.size);
@@ -627,7 +633,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
}
}else{
if(other.team() == team && other.acceptItem(base(), todump) && canDump(other, todump)){
if(other.team == team && other.acceptItem(base(), todump) && canDump(other, todump)){
other.handleItem(base(), todump);
items.remove(todump, 1);
incrementDump(proximity.size);
@@ -653,7 +659,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Try offloading an item to a nearby container in its facing direction. Returns true if success. */
public boolean moveForward(Item item){
Building other = front();
if(other != null && other.team() == team && other.acceptItem(base(), item)){
if(other != null && other.team == team && other.acceptItem(base(), item)){
other.handleItem(base(), item);
return true;
}
@@ -887,7 +893,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
power += this.power.status * block.consumes.getPower().capacity;
}
if(block.hasLiquids){
if(block.hasLiquids && state.rules.damageExplosions){
liquids.each((liquid, amount) -> {
float splash = Mathf.clamp(amount / 4f, 0f, 10f);
@@ -903,7 +909,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
});
}
Damage.dynamicExplosion(x, y, flammability, explosiveness * 3.5f, power, tilesize * block.size / 2f, Pal.darkFlame);
Damage.dynamicExplosion(x, y, flammability, explosiveness * 3.5f, power, tilesize * block.size / 2f, Pal.darkFlame, state.rules.damageExplosions);
if(!floor().solid && !floor().isLiquid){
Effect.rubble(x, y, block.size);
}
@@ -960,7 +967,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
table.row();
table.table(this::displayConsumption).growX();
boolean displayFlow = (block.category == Category.distribution || block.category == Category.liquid) && Core.settings.getBool("flow");
boolean displayFlow = (block.category == Category.distribution || block.category == Category.liquid) && Core.settings.getBool("flow") && block.displayFlow;
if(displayFlow){
String ps = " " + StatUnit.perSecond.localized();
@@ -998,9 +1005,21 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
if(liquids != null){
table.row();
table.table(l -> {
l.left();
l.image(() -> liquids.current().icon(Cicon.small)).padRight(3f);
l.label(() -> liquids.getFlowRate() < 0 ? "..." : Strings.fixed(liquids.getFlowRate(), 2) + ps).color(Color.lightGray);
boolean[] had = {false};
Runnable rebuild = () -> {
l.clearChildren();
l.left();
l.image(() -> liquids.current().icon(Cicon.small)).padRight(3f);
l.label(() -> liquids.getFlowRate() < 0 ? "..." : Strings.fixed(liquids.getFlowRate(), 2) + ps).color(Color.lightGray);
};
l.update(() -> {
if(!had[0] && liquids.hadFlow()){
had[0] = true;
rebuild.run();
}
});
}).left();
}
}
@@ -25,6 +25,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
Object data;
BulletType type;
float damage;
float fdata;
@Override
public void getCollisions(Cons<QuadTree> consumer){
@@ -15,14 +15,14 @@ import static mindustry.Vars.*;
@EntityDef(value = {Firec.class}, pooled = true)
@Component(base = true)
abstract class FireComp implements Timedc, Posc, Firec{
abstract class FireComp implements Timedc, Posc, Firec, Syncc{
private static final float spreadChance = 0.05f, fireballChance = 0.07f;
@Import float time, lifetime, x, y;
Tile tile;
private Block block;
private float baseFlammability = -1, puddleFlammability;
private transient Block block;
private transient float baseFlammability = -1, puddleFlammability;
@Override
public void update(){
@@ -99,4 +99,9 @@ abstract class FireComp implements Timedc, Posc, Firec{
public void afterRead(){
Fires.register(base());
}
@Override
public void afterSync(){
Fires.register(base());
}
}
@@ -14,7 +14,7 @@ import static mindustry.Vars.net;
abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
private static final Vec2 tmp1 = new Vec2(), tmp2 = new Vec2();
@Import float x, y;
@Import float x, y, speedMultiplier;
@Import Vec2 vel;
@SyncLocal float elevation;
@@ -56,7 +56,7 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
float floorSpeedMultiplier(){
Floor on = isFlying() || hovering ? Blocks.air.asFloor() : floorOn();
return on.speedMultiplier;
return on.speedMultiplier * speedMultiplier;
}
@Override
@@ -33,7 +33,7 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
@Override
public void update(){
if(Mathf.dst(deltaX(), deltaY()) > 0.001f){
baseRotation = Mathf.slerpDelta(baseRotation, Mathf.angle(deltaX(), deltaY()), 0.1f);
baseRotation = Angles.moveToward(baseRotation, Mathf.angle(deltaX(), deltaY()), type.rotateSpeed);
}
float rot = baseRotation;
@@ -95,7 +95,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc{
Building tile = payload.entity;
int tx = Vars.world.toTile(x - tile.block().offset), ty = Vars.world.toTile(y - tile.block().offset);
Tile on = Vars.world.tile(tx, ty);
if(on != null && Build.validPlace(tile.block(), tile.team(), tx, ty, tile.rotation)){
if(on != null && Build.validPlace(tile.block(), tile.team, tx, ty, tile.rotation)){
int rot = (int)((rotation + 45f) / 90f) % 4;
payload.place(on, rot);
@@ -45,11 +45,16 @@ abstract class PosComp implements Position{
return tile == null || tile.block() != Blocks.air ? (Floor)Blocks.air : tile.floor();
}
Block blockOn(){
Block blockOn(){
Tile tile = tileOn();
return tile == null ? Blocks.air : tile.block();
}
boolean onSolid(){
Tile tile = tileOn();
return tile != null && tile.solid();
}
@Nullable Tile tileOn(){
return world.tileWorld(x, y);
}
@@ -31,6 +31,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health;
@Import boolean dead;
@Import Team team;
@Import int id;
private UnitController controller;
private UnitType type;
@@ -223,7 +224,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
//apply knockback based on spawns
if(team != state.rules.waveTeam){
float relativeSize = state.rules.dropZoneRadius + bounds()/2f + 1f;
float relativeSize = state.rules.dropZoneRadius + hitSize/2f + 1f;
for(Tile spawn : spawner.getSpawns()){
if(within(spawn.worldx(), spawn.worldy(), relativeSize)){
vel().add(Tmp.v1.set(this).sub(spawn.worldx(), spawn.worldy()).setLength(0.1f + 1f - dst(spawn) / relativeSize).scl(0.45f * Time.delta));
@@ -275,10 +276,10 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
damageContinuous(floor.damageTaken);
}
if(!net.client() && tile.solid()){
if(tile.solid()){
if(type.canBoost){
elevation = 1f;
}else{
}else if(!net.client()){
kill();
}
}
@@ -314,7 +315,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
public void destroy(){
float explosiveness = 2f + item().explosiveness * stack().amount;
float flammability = item().flammability * stack().amount;
Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, Pal.darkFlame);
Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, Pal.darkFlame, state.rules.damageExplosions);
float shake = hitSize / 3f;
@@ -389,6 +390,6 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
if(dead || net.client()) return;
//deaths are synced; this calls killed()
Call.unitDeath(base());
Call.unitDeath(id);
}
}
@@ -2,7 +2,9 @@ package mindustry.entities.units;
import arc.math.*;
import arc.math.geom.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import mindustry.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.type.*;
@@ -33,6 +35,10 @@ public class AIController implements UnitController{
updateMovement();
}
protected UnitCommand command(){
return unit.team.data().command;
}
protected void updateMovement(){
}
@@ -115,6 +121,10 @@ public class AIController implements UnitController{
}
protected @Nullable Tile getClosestSpawner(){
return Geometry.findClosest(unit.x, unit.y, Vars.spawner.getSpawns());
}
protected void circle(Position target, float circleLength){
circle(target, circleLength, unit.type().speed);
}
@@ -3,7 +3,7 @@ package mindustry.entities.units;
import arc.*;
public enum UnitCommand{
attack, retreat, rally, idle;
attack, rally, idle;
private final String localized;
public static final UnitCommand[] all = values();
+6 -2
View File
@@ -30,7 +30,12 @@ public class EventType{
openWiki,
teamCoreDamage,
socketConfigChanged,
update
update,
draw,
preDraw,
postDraw,
uiDrawBegin,
uiDrawEnd
}
public static class WinEvent{}
@@ -77,7 +82,6 @@ public class EventType{
}
}
public static class CommandIssueEvent{
public final Building tile;
public final UnitCommand command;
+4
View File
@@ -38,6 +38,10 @@ public class Rules{
public boolean canGameOver = true;
/** Whether reactors can explode and damage other blocks. */
public boolean reactorExplosions = true;
/** Whether friendly explosions can occur and set fire/damage other blocks. */
public boolean damageExplosions = true;
/** Whether fire is enabled. */
public boolean fire = true;
/** Whether units use and require ammo. */
public boolean unitAmmo = false;
/** How fast unit pads build units. */
+3 -3
View File
@@ -102,7 +102,7 @@ public class Teams{
}
public void registerCore(CoreBuild core){
TeamData data = get(core.team());
TeamData data = get(core.team);
//add core if not present
if(!data.cores.contains(core)){
data.cores.add(core);
@@ -117,7 +117,7 @@ public class Teams{
}
public void unregisterCore(CoreBuild entity){
TeamData data = get(entity.team());
TeamData data = get(entity.team);
//remove core
data.cores.remove(entity);
//unregister in active list
@@ -181,7 +181,7 @@ public class Teams{
/** @return whether this team is controlled by the AI and builds bases. */
public boolean hasAI(){
return state.rules.attackMode && team.rules().ai;
return team.rules().ai;
}
@Override
+1 -1
View File
@@ -140,7 +140,7 @@ public class Universe{
sector.setSecondsPassed(sector.getSecondsPassed() + actuallyPassed);
//check if the sector has been attacked too many times...
if(sector.hasBase() && sector.getSecondsPassed() * 60f > turnDuration * sectorDestructionTurns){
if(sector.hasBase() && sector.hasWaves() && sector.getSecondsPassed() * 60f > turnDuration * sectorDestructionTurns){
//fire event for losing the sector
Events.fire(new SectorLoseEvent(sector));
@@ -249,7 +249,7 @@ public class BlockRenderer implements Disposable{
Draw.z(Layer.block);
}
if(entity.team() != player.team()){
if(entity.team != player.team()){
entity.drawTeam();
Draw.z(Layer.block);
}
+7 -1
View File
@@ -5,6 +5,9 @@ public class Layer{
public static final float
//min layer
min = -11,
//background, which may be planets or an image or nothing at all
background = -10,
@@ -81,7 +84,10 @@ public class Layer{
end = 200,
//things after pixelation - used for text
endPixeled = 210
endPixeled = 210,
//max layer
max = 220
;
}
@@ -111,7 +111,7 @@ public class OverlayRenderer{
if(dst < state.rules.enemyCoreBuildRadius * 2.2f){
Draw.color(Color.darkGray);
Lines.circle(core.x, core.y - 2, state.rules.enemyCoreBuildRadius);
Draw.color(Pal.accent, core.team().color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f));
Draw.color(Pal.accent, core.team.color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f));
Lines.circle(core.x, core.y, state.rules.enemyCoreBuildRadius);
}
});
@@ -132,23 +132,25 @@ public class OverlayRenderer{
//draw selected block
if(input.block == null && !Core.scene.hasMouse()){
Vec2 vec = Core.input.mouseWorld(input.getMouseX(), input.getMouseY());
Building tile = world.buildWorld(vec.x, vec.y);
Building build = world.buildWorld(vec.x, vec.y);
if(tile != null && tile.team() == player.team()){
tile.drawSelect();
if(!tile.enabled && tile.block.drawDisabled){
tile.drawDisabled();
if(build != null && build.team == player.team()){
build.drawSelect();
if(!build.enabled && build.block.drawDisabled){
build.drawDisabled();
}
if(Core.input.keyDown(Binding.rotateplaced) && tile.block().rotate && tile.interactable(player.team())){
control.input.drawArrow(tile.block(), tile.tileX(), tile.tileY(), tile.rotation, true);
if(Core.input.keyDown(Binding.rotateplaced) && build.block().rotate && build.interactable(player.team())){
control.input.drawArrow(build.block(), build.tileX(), build.tileY(), build.rotation, true);
Draw.color(Pal.accent, 0.3f + Mathf.absin(4f, 0.2f));
Fill.square(tile.x, tile.y, tile.block().size * tilesize/2f);
Fill.square(build.x, build.y, build.block().size * tilesize/2f);
Draw.color();
}
}
}
input.drawOverSelect();
//draw selection overlay when dropping item
if(input.isDroppingItem()){
Vec2 v = Core.input.mouseWorld(input.getMouseX(), input.getMouseY());
+2
View File
@@ -9,6 +9,8 @@ public class Pal{
command = Color.valueOf("eab678"),
sap = Color.valueOf("665c9f"),
sapBullet = Color.valueOf("bf92f9"),
sapBulletBack = Color.valueOf("6d56bf"),
spore = Color.valueOf("7457ce"),
+2 -1
View File
@@ -8,7 +8,8 @@ import arc.input.*;
public enum Binding implements KeyBind{
move_x(new Axis(KeyCode.a, KeyCode.d), "general"),
move_y(new Axis(KeyCode.s, KeyCode.w)),
mouse_move(KeyCode.mouseForward),
mouse_move(KeyCode.mouseBack),
pan(KeyCode.mouseForward),
boost(KeyCode.shiftLeft),
control(KeyCode.controlLeft),
+57 -40
View File
@@ -27,24 +27,35 @@ import static mindustry.Vars.*;
import static mindustry.input.PlaceMode.*;
public class DesktopInput extends InputHandler{
private Vec2 movement = new Vec2();
public Vec2 movement = new Vec2();
/** Current cursor type. */
private Cursor cursorType = SystemCursor.arrow;
public Cursor cursorType = SystemCursor.arrow;
/** Position where the player started dragging a line. */
private int selectX, selectY, schemX, schemY;
public int selectX, selectY, schemX, schemY;
/** Last known line positions.*/
private int lastLineX, lastLineY, schematicX, schematicY;
public int lastLineX, lastLineY, schematicX, schematicY;
/** Whether selecting mode is active. */
private PlaceMode mode;
public PlaceMode mode;
/** Animation scale for line. */
private float selectScale;
public float selectScale;
/** Selected build request for movement. */
private @Nullable BuildPlan sreq;
public @Nullable BuildPlan sreq;
/** Whether player is currently deleting removal requests. */
private boolean deleting = false, shouldShoot = false;
public boolean deleting = false, shouldShoot = false, panning = false;
/** Mouse pan speed. */
public float panScale = 0.005f, panSpeed = 4.5f, panBoostSpeed = 9f;
@Override
public void buildUI(Group group){
group.fill(t -> {
t.visible(() -> Core.settings.getBool("hints") && !player.dead() && !player.unit().spawnedByCore() && !(Core.settings.getBool("hints") && lastSchematic != null && !selectRequests.isEmpty()));
t.bottom();
t.table(Styles.black6, b -> {
b.defaults().left();
b.label(() -> Core.bundle.format("respawn", Core.keybinds.get(Binding.respawn).key.toString())).style(Styles.outlineLabel);
}).margin(6f);
});
group.fill(t -> {
t.bottom();
t.visible(() -> {
@@ -77,15 +88,6 @@ public class DesktopInput extends InputHandler{
});
}).margin(6f);
});
group.fill(t -> {
t.visible(() -> Core.settings.getBool("hints") && !player.dead() && !player.unit().spawnedByCore());
t.bottom();
t.table(Styles.black6, b -> {
b.defaults().left();
b.label(() -> Core.bundle.format("respawn", Core.keybinds.get(Binding.respawn).key.toString())).style(Styles.outlineLabel);
}).margin(6f);
});
}
@Override
@@ -132,14 +134,12 @@ public class DesktopInput extends InputHandler{
}
//draw schematic requests
for(BuildPlan request : selectRequests){
request.animScale = 1f;
drawRequest(request);
}
selectRequests.each(req -> {
req.animScale = 1f;
drawRequest(req);
});
for(BuildPlan request : selectRequests){
drawOverRequest(request);
}
selectRequests.each(this::drawOverRequest);
if(player.isBuilder()){
//draw things that may be placed soon
@@ -180,22 +180,35 @@ public class DesktopInput extends InputHandler{
ui.listfrag.toggle();
}
//TODO awful UI state checking code
if((player.dead() || state.isPaused()) && !ui.chatfrag.shown()){
if(!(scene.getKeyboardFocus() instanceof TextField) && !scene.hasDialog()){
//move camera around
float camSpeed = !Core.input.keyDown(Binding.boost) ? 3f : 8f;
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));
boolean panCam = false;
float camSpeed = !Core.input.keyDown(Binding.boost) ? panSpeed : panBoostSpeed;
if(Core.input.keyDown(Binding.mouse_move)){
Core.camera.position.x += Mathf.clamp((Core.input.mouseX() - Core.graphics.getWidth() / 2f) * 0.005f, -1, 1) * camSpeed;
Core.camera.position.y += Mathf.clamp((Core.input.mouseY() - Core.graphics.getHeight() / 2f) * 0.005f, -1, 1) * camSpeed;
}
if(input.keyDown(Binding.pan)){
panCam = true;
panning = true;
}
if((Math.abs(Core.input.axis(Binding.move_x)) > 0 || Math.abs(Core.input.axis(Binding.move_y)) > 0 || input.keyDown(Binding.mouse_move)) && (!scene.hasField())){
panning = false;
}
//TODO awful UI state checking code
if(((player.dead() || state.isPaused()) && !ui.chatfrag.shown()) && (!scene.hasField() && !scene.hasDialog())){
if(input.keyDown(Binding.mouse_move)){
panCam = true;
}
}else if(!player.dead()){
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));
}else if(!player.dead() && !panning){
Core.camera.position.lerpDelta(player, Core.settings.getBool("smoothcamera") ? 0.08f : 1f);
}
if(panCam){
Core.camera.position.x += Mathf.clamp((Core.input.mouseX() - Core.graphics.getWidth() / 2f) * panScale, -1, 1) * camSpeed;
Core.camera.position.y += Mathf.clamp((Core.input.mouseY() - Core.graphics.getHeight() / 2f) * panScale, -1, 1) * camSpeed;
}
shouldShoot = !scene.hasMouse();
if(!scene.hasMouse()){
@@ -327,22 +340,24 @@ public class DesktopInput extends InputHandler{
table.row();
table.left().margin(0f).defaults().size(48f).left();
//TODO localize these
table.button(Icon.paste, Styles.clearPartiali, () -> {
ui.schematics.show();
}).tooltip("Schematics");
}).tooltip("@schematics");
table.button(Icon.tree, Styles.clearPartiali, () -> {
ui.research.show();
}).visible(() -> state.isCampaign()).tooltip("Research");
}).visible(() -> state.isCampaign()).tooltip("@research");
table.button(Icon.map, Styles.clearPartiali, () -> {
ui.planet.show();
}).visible(() -> state.isCampaign()).tooltip("Planet Map");
}).visible(() -> state.isCampaign()).tooltip("@planetmap");
table.button(Icon.up, Styles.clearPartiali, () -> {
ui.planet.show(state.getSector(), player.team().core());
}).visible(() -> state.isCampaign())
.disabled(b -> player.team().core() == null || !player.team().core().items.has(player.team().core().block.requirements)).tooltip("Launch Core");
.disabled(b -> player.team().core() == null || !player.team().core().items.has(player.team().core().block.requirements)).tooltip("@launchcore");
}
void pollInput(){
@@ -555,6 +570,8 @@ public class DesktopInput extends InputHandler{
@Override
public void updateState(){
super.updateState();
if(state.isMenu()){
droppingItem = false;
mode = none;
@@ -574,7 +591,7 @@ public class DesktopInput extends InputHandler{
//limit speed to minimum formation speed to preserve formation
if(unit instanceof Commanderc && ((Commanderc)unit).isCommanding()){
//add a tiny multiplier to let units catch up just in case
baseSpeed = ((Commanderc)unit).minFormationSpeed() * 0.98f;
baseSpeed = ((Commanderc)unit).minFormationSpeed() * 0.95f;
}
float speed = baseSpeed * Mathf.lerp(1f, unit.type().canBoost ? unit.type().boostMultiplier : 1f, unit.elevation) * strafePenalty;
+19 -15
View File
@@ -62,13 +62,13 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public boolean isBuilding = true, buildWasAutoPaused = false;
public @Nullable UnitType controlledType;
protected @Nullable Schematic lastSchematic;
protected GestureDetector detector;
protected PlaceLine line = new PlaceLine();
protected BuildPlan resultreq;
protected BuildPlan brequest = new BuildPlan();
protected Seq<BuildPlan> lineRequests = new Seq<>();
protected Seq<BuildPlan> selectRequests = new Seq<>();
public @Nullable Schematic lastSchematic;
public GestureDetector detector;
public PlaceLine line = new PlaceLine();
public BuildPlan resultreq;
public BuildPlan brequest = new BuildPlan();
public Seq<BuildPlan> lineRequests = new Seq<>();
public Seq<BuildPlan> selectRequests = new Seq<>();
//methods to override
@@ -126,7 +126,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
Unit unit = player.unit();
Payloadc pay = (Payloadc)unit;
if(tile != null && tile.team() == unit.team && pay.payloads().size < unit.type().payloadCapacity
if(tile != null && tile.team == unit.team && pay.payloads().size < unit.type().payloadCapacity
&& unit.within(tile, tilesize * tile.block.size * 1.2f)){
//pick up block directly
if(tile.block().buildVisibility != BuildVisibility.hidden && tile.block().size <= 2 && tile.canPickup()){
@@ -236,6 +236,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
player.clearUnit();
player.deathTimer = 61f;
((CoreBuild)((BlockUnitc)unit).tile()).requestSpawn(player);
}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
@@ -372,7 +374,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
public void updateState(){
if(state.isMenu()){
controlledType = null;
}
}
public void drawBottom(){
@@ -383,6 +387,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
public void drawOverSelect(){
}
public void drawSelected(int x, int y, Block block, Color color){
Drawf.selected(x, y, block, color);
}
@@ -538,11 +546,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
if(test.get(req)) return req;
}
for(BuildPlan req : selectRequests){
if(test.get(req)) return req;
}
return null;
return selectRequests.find(test);
}
protected void drawBreakSelection(int x1, int y1, int x2, int y2){
@@ -873,7 +877,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
Building tile = world.buildWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
if(tile instanceof ControlBlock && tile.team() == player.team()){
if(tile instanceof ControlBlock && tile.team == player.team()){
return ((ControlBlock)tile).unit();
}

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