Merge branch 'master' of https://github.com/Anuken/Mindustry into refactor-paths
Conflicts: core/src/mindustry/ai/types/GroundAI.java
8
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -13,11 +13,13 @@ assignees: ''
|
|||||||
|
|
||||||
**Issue**: *Explain your issue in detail.*
|
**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.*
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
6
.gitignore
vendored
@@ -79,9 +79,11 @@ com_crashlytics_export_strings.xml
|
|||||||
/android/bin/
|
/android/bin/
|
||||||
/core/bin/
|
/core/bin/
|
||||||
/desktop/bin/
|
/desktop/bin/
|
||||||
/html/bin/
|
|
||||||
/ios/bin/
|
/ios/bin/
|
||||||
/ios-moe/bin/
|
/annotations/bin/
|
||||||
|
/server/bin/
|
||||||
|
/tests/bin/
|
||||||
|
/tools/bin/
|
||||||
*.tmp
|
*.tmp
|
||||||
*.bak
|
*.bak
|
||||||
*.swp
|
*.swp
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
jdk:
|
jdk:
|
||||||
- openjdk8
|
- openjdk14
|
||||||
dist: xenial
|
dist: xenial
|
||||||
android:
|
android:
|
||||||
components:
|
components:
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ See [CONTRIBUTING](CONTRIBUTING.md).
|
|||||||
|
|
||||||
### Building
|
### 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.
|
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:
|
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
|
#### 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.
|
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`.
|
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.
|
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(\" \")");
|
||||||
writer.addStatement("out.append((($T)obj).$L$L)", c.mirror(), field.name(),
|
writer.addStatement("out.append((($T)obj).$L$L)", c.mirror(), field.name(),
|
||||||
field.mirror().toString().equals("java.lang.String") ?
|
Seq.with(typeu.directSupertypes(field.mirror())).contains(t -> t.toString().contains("java.lang.Enum")) ? ".name()" :
|
||||||
".replace(\"\\n\", \"\\\\n\")" :
|
"");
|
||||||
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
|
//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,
|
index + 1,
|
||||||
field.name(),
|
field.name(),
|
||||||
field.mirror().toString().equals("java.lang.String") ?
|
field.mirror().toString().equals("java.lang.String") ?
|
||||||
"" : (field.tname().isPrimitive() ? field.tname().box().toString() :
|
"" : (field.tname().isPrimitive() ? field.tname().box().toString() :
|
||||||
field.mirror().toString()) + ".valueOf", //if it's not a string, it must have a valueOf method
|
field.mirror().toString()) + ".valueOf", //if it's not a string, it must have a valueOf method
|
||||||
index + 1,
|
index + 1
|
||||||
field.mirror().toString().equals("java.lang.String") ?
|
|
||||||
".replace(\"\\\\n\", \"\\n\")" :
|
|
||||||
""
|
|
||||||
);
|
);
|
||||||
|
|
||||||
index ++;
|
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}]}
|
|
||||||
1
annotations/src/main/resources/revisions/Fire/1.json
Normal file
@@ -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}]}
|
||||||
@@ -187,6 +187,10 @@ configure(subprojects - project(":annotations")){
|
|||||||
options.compilerArgs.addAll(['--release', '8'])
|
options.compilerArgs.addAll(['--release', '8'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType(Javadoc){
|
||||||
|
options.addStringOption('Xdoclint:none', '-quiet')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
project(":desktop"){
|
project(":desktop"){
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
BIN
core/assets-raw/sprites/blocks/logic/hyper-processor.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 517 B After Width: | Height: | Size: 783 B |
|
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 553 B After Width: | Height: | Size: 613 B |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.7 KiB |
BIN
core/assets-raw/sprites/units/toxopid-cannon.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
core/assets-raw/sprites/units/toxopid-cell.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
core/assets-raw/sprites/units/toxopid-foot.png
Normal file
|
After Width: | Height: | Size: 989 B |
BIN
core/assets-raw/sprites/units/toxopid-joint-base.png
Normal file
|
After Width: | Height: | Size: 617 B |
BIN
core/assets-raw/sprites/units/toxopid-leg-base.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
core/assets-raw/sprites/units/toxopid-leg.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
core/assets-raw/sprites/units/toxopid.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 639 B |
BIN
core/assets-raw/sprites/units/weapons/large-purple-mount.png
Normal file
|
After Width: | Height: | Size: 938 B |
@@ -136,6 +136,8 @@ mod.scripts.disable = Your device does not support mods with scripts. You must d
|
|||||||
about.button = About
|
about.button = About
|
||||||
name = Name:
|
name = Name:
|
||||||
noname = Pick a[accent] player name[] first.
|
noname = Pick a[accent] player name[] first.
|
||||||
|
planetmap = Planet Map
|
||||||
|
launchcore = Launch Core
|
||||||
filename = File Name:
|
filename = File Name:
|
||||||
unlocked = New content unlocked!
|
unlocked = New content unlocked!
|
||||||
completed = [accent]Completed
|
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.
|
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
|
hostserver = Host Multiplayer Game
|
||||||
invitefriends = Invite Friends
|
invitefriends = Invite Friends
|
||||||
hostserver.mobile = Host\nGame
|
hostserver.mobile = Host Game
|
||||||
host = Host
|
host = Host
|
||||||
hosting = [accent]Opening server...
|
hosting = [accent]Opening server...
|
||||||
hosts.refresh = Refresh
|
hosts.refresh = Refresh
|
||||||
@@ -575,6 +577,8 @@ blocks.shootrange = Range
|
|||||||
blocks.size = Size
|
blocks.size = Size
|
||||||
blocks.liquidcapacity = Liquid Capacity
|
blocks.liquidcapacity = Liquid Capacity
|
||||||
blocks.powerrange = Power Range
|
blocks.powerrange = Power Range
|
||||||
|
blocks.linkrange = Link Range
|
||||||
|
blocks.instructions = Instructions
|
||||||
blocks.powerconnections = Max Connections
|
blocks.powerconnections = Max Connections
|
||||||
blocks.poweruse = Power Use
|
blocks.poweruse = Power Use
|
||||||
blocks.powerdamage = Power/Damage
|
blocks.powerdamage = Power/Damage
|
||||||
@@ -727,6 +731,7 @@ category.blocks.name = Block Select
|
|||||||
command.attack = Attack
|
command.attack = Attack
|
||||||
command.rally = Rally
|
command.rally = Rally
|
||||||
command.retreat = Retreat
|
command.retreat = Retreat
|
||||||
|
command.idle = Idle
|
||||||
placement.blockselectkeys = \n[lightgray]Key: [{0},
|
placement.blockselectkeys = \n[lightgray]Key: [{0},
|
||||||
keybind.respawn.name = Respawn
|
keybind.respawn.name = Respawn
|
||||||
keybind.control.name = Control Unit
|
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_x.name = Move X
|
||||||
keybind.move_y.name = Move Y
|
keybind.move_y.name = Move Y
|
||||||
keybind.mouse_move.name = Follow Mouse
|
keybind.mouse_move.name = Follow Mouse
|
||||||
|
keybind.pan.name = Pan View
|
||||||
keybind.boost.name = Boost
|
keybind.boost.name = Boost
|
||||||
keybind.schematic_select.name = Select Region
|
keybind.schematic_select.name = Select Region
|
||||||
keybind.schematic_menu.name = Schematic Menu
|
keybind.schematic_menu.name = Schematic Menu
|
||||||
@@ -874,6 +880,7 @@ unit.crawler.name = Crawler
|
|||||||
unit.atrax.name = Atrax
|
unit.atrax.name = Atrax
|
||||||
unit.spiroct.name = Spiroct
|
unit.spiroct.name = Spiroct
|
||||||
unit.arkyid.name = Arkyid
|
unit.arkyid.name = Arkyid
|
||||||
|
unit.toxopid.name = Toxopid
|
||||||
unit.flare.name = Flare
|
unit.flare.name = Flare
|
||||||
unit.horizon.name = Horizon
|
unit.horizon.name = Horizon
|
||||||
unit.zenith.name = Zenith
|
unit.zenith.name = Zenith
|
||||||
@@ -1073,6 +1080,7 @@ block.container.name = Container
|
|||||||
block.launch-pad.name = Launch Pad
|
block.launch-pad.name = Launch Pad
|
||||||
block.launch-pad-large.name = Large Launch Pad
|
block.launch-pad-large.name = Large Launch Pad
|
||||||
block.segment.name = Segment
|
block.segment.name = Segment
|
||||||
|
block.command-center.name = Command Center
|
||||||
block.ground-factory.name = Ground Factory
|
block.ground-factory.name = Ground Factory
|
||||||
block.air-factory.name = Air Factory
|
block.air-factory.name = Air Factory
|
||||||
block.naval-factory.name = Naval Factory
|
block.naval-factory.name = Naval Factory
|
||||||
@@ -1089,6 +1097,7 @@ block.overdrive-dome.name = Overdrive Dome
|
|||||||
block.switch.name = Switch
|
block.switch.name = Switch
|
||||||
block.micro-processor.name = Micro Processor
|
block.micro-processor.name = Micro Processor
|
||||||
block.logic-processor.name = Logic Processor
|
block.logic-processor.name = Logic Processor
|
||||||
|
block.hyper-processor.name = Hyper Processor
|
||||||
block.logic-display.name = Logic Display
|
block.logic-display.name = Logic Display
|
||||||
block.memory-cell.name = Memory Cell
|
block.memory-cell.name = Memory Cell
|
||||||
|
|
||||||
|
|||||||
@@ -286,3 +286,5 @@
|
|||||||
63458=switch|block-switch-medium
|
63458=switch|block-switch-medium
|
||||||
63457=memory-cell|block-memory-cell-medium
|
63457=memory-cell|block-memory-cell-medium
|
||||||
63456=payload-conveyor|block-payload-conveyor-medium
|
63456=payload-conveyor|block-payload-conveyor-medium
|
||||||
|
63455=hyper-processor|block-hyper-processor-medium
|
||||||
|
63454=toxopid|unit-toxopid-medium
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ const log = function(context, obj){
|
|||||||
}
|
}
|
||||||
|
|
||||||
const readString = path => Vars.mods.getScripts().readString(path)
|
const readString = path => Vars.mods.getScripts().readString(path)
|
||||||
|
|
||||||
const readBytes = path => Vars.mods.getScripts().readBytes(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 scriptName = "base.js"
|
||||||
var modName = "none"
|
var modName = "none"
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ const log = function(context, obj){
|
|||||||
}
|
}
|
||||||
|
|
||||||
const readString = path => Vars.mods.getScripts().readString(path)
|
const readString = path => Vars.mods.getScripts().readString(path)
|
||||||
|
|
||||||
const readBytes = path => Vars.mods.getScripts().readBytes(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 scriptName = "base.js"
|
||||||
var modName = "none"
|
var modName = "none"
|
||||||
@@ -40,6 +41,7 @@ importPackage(Packages.arc)
|
|||||||
importPackage(Packages.arc.func)
|
importPackage(Packages.arc.func)
|
||||||
importPackage(Packages.arc.graphics)
|
importPackage(Packages.arc.graphics)
|
||||||
importPackage(Packages.arc.graphics.g2d)
|
importPackage(Packages.arc.graphics.g2d)
|
||||||
|
importPackage(Packages.arc.graphics.gl)
|
||||||
importPackage(Packages.arc.math)
|
importPackage(Packages.arc.math)
|
||||||
importPackage(Packages.arc.math.geom)
|
importPackage(Packages.arc.math.geom)
|
||||||
importPackage(Packages.arc.scene)
|
importPackage(Packages.arc.scene)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 788 B After Width: | Height: | Size: 794 B |
|
Before Width: | Height: | Size: 644 KiB After Width: | Height: | Size: 650 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 994 KiB |
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 264 KiB |
|
Before Width: | Height: | Size: 187 KiB After Width: | Height: | Size: 183 KiB |
|
Before Width: | Height: | Size: 407 KiB After Width: | Height: | Size: 406 KiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 2.1 MiB |
|
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 184 KiB |
|
Before Width: | Height: | Size: 402 KiB After Width: | Height: | Size: 416 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
@@ -199,8 +199,7 @@ public class Vars implements Loadable{
|
|||||||
public static NetServer netServer;
|
public static NetServer netServer;
|
||||||
public static NetClient netClient;
|
public static NetClient netClient;
|
||||||
|
|
||||||
public static
|
public static Player player;
|
||||||
Player player;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadAsync(){
|
public void loadAsync(){
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ public class BaseAI{
|
|||||||
int range = 150;
|
int range = 150;
|
||||||
|
|
||||||
Position pos = randomPosition();
|
Position pos = randomPosition();
|
||||||
|
|
||||||
//when there are no random positions, do nothing.
|
//when there are no random positions, do nothing.
|
||||||
if(pos == null) return;
|
if(pos == null) return;
|
||||||
|
|
||||||
@@ -159,7 +160,10 @@ public class BaseAI{
|
|||||||
|
|
||||||
private void tryWalls(){
|
private void tryWalls(){
|
||||||
Block wall = Blocks.copperWall;
|
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 wx = lastX; wx <= lastX + lastW; wx++){
|
||||||
for(int wy = lastY; wy <= lastY + lastH; wy++){
|
for(int wy = lastY; wy <= lastY + lastH; wy++){
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ public class BlockIndexer{
|
|||||||
|
|
||||||
if(other == null) continue;
|
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);
|
cons.get(other);
|
||||||
any = true;
|
any = true;
|
||||||
}
|
}
|
||||||
@@ -212,11 +212,11 @@ public class BlockIndexer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void notifyTileDamaged(Building entity){
|
public void notifyTileDamaged(Building entity){
|
||||||
if(damagedTiles[entity.team().id] == null){
|
if(damagedTiles[entity.team.id] == null){
|
||||||
damagedTiles[entity.team().id] = new BuildingArray();
|
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){
|
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 == null) continue;
|
||||||
|
|
||||||
if(e.team() != team || !pred.get(e) || !e.block().targetable)
|
if(e.team != team || !pred.get(e) || !e.block().targetable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
float ndst = e.dst2(x, y);
|
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++){
|
for(int y = quadrantY * quadrantSize; y < world.height() && y < (quadrantY + 1) * quadrantSize; y++){
|
||||||
Building result = world.build(x, y);
|
Building result = world.build(x, y);
|
||||||
//when a targetable block is found, mark this quadrant as occupied and stop searching
|
//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);
|
bits.set(quadrantX, quadrantY);
|
||||||
break outer;
|
break outer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public class WaveSpawner{
|
|||||||
|
|
||||||
private void eachFlyerSpawn(Floatc2 cons){
|
private void eachFlyerSpawn(Floatc2 cons){
|
||||||
for(Tile tile : spawns){
|
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 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);
|
float spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(angle, trns), -margin, world.width() * tilesize + margin);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import mindustry.entities.units.*;
|
|||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.world.meta.*;
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class FlyingAI extends AIController{
|
public class FlyingAI extends AIController{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -18,7 +20,7 @@ public class FlyingAI extends AIController{
|
|||||||
unit.wobble();
|
unit.wobble();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(target != null && unit.hasWeapons()){
|
if(target != null && unit.hasWeapons() && command() == UnitCommand.attack){
|
||||||
if(unit.type().weapons.first().rotate){
|
if(unit.type().weapons.first().rotate){
|
||||||
moveTo(target, unit.range() * 0.8f);
|
moveTo(target, unit.range() * 0.8f);
|
||||||
unit.lookAt(target);
|
unit.lookAt(target);
|
||||||
@@ -26,6 +28,15 @@ public class FlyingAI extends AIController{
|
|||||||
attack(80f);
|
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
|
@Override
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import mindustry.entities.*;
|
|||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -17,16 +20,34 @@ public class GroundAI extends AIController{
|
|||||||
|
|
||||||
Building core = unit.closestEnemyCore();
|
Building core = unit.closestEnemyCore();
|
||||||
|
|
||||||
if(core != null){
|
if(core != null && unit.within(core, unit.range() / 1.1f + core.block.size * tilesize / 2f)){
|
||||||
if(unit.within(core,unit.range() / 1.1f)){
|
target = core;
|
||||||
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)){
|
if(move) moveToCore(FlagTarget.enemyCores);
|
||||||
moveTo(Pathfinder.fieldCore);
|
}
|
||||||
|
|
||||||
|
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(!Units.invalidateTarget(target, unit, unit.range())){
|
||||||
if(unit.type().hasWeapons()){
|
if(unit.type().hasWeapons()){
|
||||||
unit.aimLook(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
|
unit.aimLook(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public class SuicideAI extends GroundAI{
|
|||||||
boolean blocked = Vars.world.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> {
|
boolean blocked = Vars.world.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> {
|
||||||
Tile tile = Vars.world.tile(x, y);
|
Tile tile = Vars.world.tile(x, y);
|
||||||
if(tile != null && tile.build == target) return false;
|
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;
|
blockedByBlock = true;
|
||||||
return true;
|
return true;
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public class MusicControl{
|
|||||||
public Seq<Music> ambientMusic = Seq.with();
|
public Seq<Music> ambientMusic = Seq.with();
|
||||||
/** darker music, used in times of conflict */
|
/** darker music, used in times of conflict */
|
||||||
public Seq<Music> darkMusic = Seq.with();
|
public Seq<Music> darkMusic = Seq.with();
|
||||||
|
|
||||||
protected Music lastRandomPlayed;
|
protected Music lastRandomPlayed;
|
||||||
protected Interval timer = new Interval();
|
protected Interval timer = new Interval();
|
||||||
protected @Nullable Music current;
|
protected @Nullable Music current;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import mindustry.world.blocks.experimental.*;
|
|||||||
import mindustry.world.blocks.legacy.*;
|
import mindustry.world.blocks.legacy.*;
|
||||||
import mindustry.world.blocks.liquid.*;
|
import mindustry.world.blocks.liquid.*;
|
||||||
import mindustry.world.blocks.logic.*;
|
import mindustry.world.blocks.logic.*;
|
||||||
import mindustry.world.blocks.logic.MessageBlock;
|
|
||||||
import mindustry.world.blocks.power.*;
|
import mindustry.world.blocks.power.*;
|
||||||
import mindustry.world.blocks.production.*;
|
import mindustry.world.blocks.production.*;
|
||||||
import mindustry.world.blocks.sandbox.*;
|
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,
|
duo, scatter, scorch, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, segment, parallax,
|
||||||
|
|
||||||
//units
|
//units
|
||||||
|
commandCenter,
|
||||||
groundFactory, airFactory, navalFactory,
|
groundFactory, airFactory, navalFactory,
|
||||||
additiveReconstructor, multiplicativeReconstructor, exponentialReconstructor, tetrativeReconstructor,
|
additiveReconstructor, multiplicativeReconstructor, exponentialReconstructor, tetrativeReconstructor,
|
||||||
repairPoint, resupplyPoint,
|
repairPoint, resupplyPoint,
|
||||||
|
|
||||||
//logic
|
//logic
|
||||||
message, switchBlock, microProcessor, logicProcessor, logicDisplay, memoryCell,
|
message, switchBlock, microProcessor, logicProcessor, hyperProcessor, logicDisplay, memoryCell,
|
||||||
|
|
||||||
//campaign
|
//campaign
|
||||||
launchPad, launchPadLarge,
|
launchPad, launchPadLarge,
|
||||||
@@ -998,10 +998,12 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
payloadConveyor = new PayloadConveyor("payload-conveyor"){{
|
payloadConveyor = new PayloadConveyor("payload-conveyor"){{
|
||||||
requirements(Category.distribution, with(Items.graphite, 10, Items.copper, 20));
|
requirements(Category.distribution, with(Items.graphite, 10, Items.copper, 20));
|
||||||
|
canOverdrive = false;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
payloadRouter = new PayloadRouter("payload-router"){{
|
payloadRouter = new PayloadRouter("payload-router"){{
|
||||||
requirements(Category.distribution, with(Items.graphite, 15, Items.copper, 20));
|
requirements(Category.distribution, with(Items.graphite, 15, Items.copper, 20));
|
||||||
|
canOverdrive = false;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -1339,7 +1341,7 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
unloader = new Unloader("unloader"){{
|
unloader = new Unloader("unloader"){{
|
||||||
requirements(Category.effect, with(Items.titanium, 25, Items.silicon, 30));
|
requirements(Category.effect, with(Items.titanium, 25, Items.silicon, 30));
|
||||||
speed = 7f;
|
speed = 6f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -1486,7 +1488,7 @@ public class Blocks implements ContentList{
|
|||||||
reloadTime = 35f;
|
reloadTime = 35f;
|
||||||
shootCone = 40f;
|
shootCone = 40f;
|
||||||
rotatespeed = 8f;
|
rotatespeed = 8f;
|
||||||
powerUse = 5f;
|
powerUse = 4f;
|
||||||
targetAir = false;
|
targetAir = false;
|
||||||
range = 90f;
|
range = 90f;
|
||||||
shootEffect = Fx.lightningShoot;
|
shootEffect = Fx.lightningShoot;
|
||||||
@@ -1502,12 +1504,13 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
size = 2;
|
size = 2;
|
||||||
force = 3f;
|
force = 4f;
|
||||||
scaledForce = 5.5f;
|
scaledForce = 5.5f;
|
||||||
range = 170f;
|
range = 170f;
|
||||||
damage = 0.08f;
|
damage = 0.1f;
|
||||||
health = 160 * size * size;
|
health = 160 * size * size;
|
||||||
rotateSpeed = 10;
|
rotateSpeed = 10;
|
||||||
|
range = 85f;
|
||||||
|
|
||||||
consumes.powerCond(3f, (TractorBeamEntity e) -> e.target != null);
|
consumes.powerCond(3f, (TractorBeamEntity e) -> e.target != null);
|
||||||
}};
|
}};
|
||||||
@@ -1556,14 +1559,15 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
segment = new PointDefenseTurret("segment"){{
|
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;
|
hasPower = true;
|
||||||
consumes.power(3f);
|
consumes.power(3f);
|
||||||
size = 2;
|
size = 2;
|
||||||
shootLength = 5f;
|
shootLength = 5f;
|
||||||
bulletDamage = 12f;
|
bulletDamage = 16f;
|
||||||
reloadTime = 25f;
|
reloadTime = 15f;
|
||||||
health = 190 * size * size;
|
health = 190 * size * size;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -1699,6 +1703,12 @@ public class Blocks implements ContentList{
|
|||||||
//endregion
|
//endregion
|
||||||
//region units
|
//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"){{
|
groundFactory = new UnitFactory("ground-factory"){{
|
||||||
requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 80));
|
requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 80));
|
||||||
plans = new UnitPlan[]{
|
plans = new UnitPlan[]{
|
||||||
@@ -1769,11 +1779,11 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
exponentialReconstructor = new Reconstructor("exponential-reconstructor"){{
|
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;
|
size = 7;
|
||||||
consumes.power(12f);
|
consumes.power(13f);
|
||||||
consumes.items(with(Items.silicon, 250, Items.titanium, 500, Items.plastanium, 400));
|
consumes.items(with(Items.silicon, 450, Items.titanium, 550, Items.plastanium, 550));
|
||||||
consumes.liquid(Liquids.cryofluid, 1f);
|
consumes.liquid(Liquids.cryofluid, 1f);
|
||||||
|
|
||||||
constructTime = 60f * 60f * 1.5f;
|
constructTime = 60f * 60f * 1.5f;
|
||||||
@@ -1781,15 +1791,16 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
upgrades = new UnitType[][]{
|
upgrades = new UnitType[][]{
|
||||||
{UnitTypes.zenith, UnitTypes.antumbra},
|
{UnitTypes.zenith, UnitTypes.antumbra},
|
||||||
|
{UnitTypes.spiroct, UnitTypes.arkyid},
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
tetrativeReconstructor = new Reconstructor("tetrative-reconstructor"){{
|
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;
|
size = 9;
|
||||||
consumes.power(25f);
|
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);
|
consumes.liquid(Liquids.cryofluid, 3f);
|
||||||
|
|
||||||
constructTime = 60f * 60f * 4;
|
constructTime = 60f * 60f * 4;
|
||||||
@@ -1797,6 +1808,7 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
upgrades = new UnitType[][]{
|
upgrades = new UnitType[][]{
|
||||||
{UnitTypes.antumbra, UnitTypes.eclipse},
|
{UnitTypes.antumbra, UnitTypes.eclipse},
|
||||||
|
{UnitTypes.arkyid, UnitTypes.toxopid},
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -1862,7 +1874,6 @@ public class Blocks implements ContentList{
|
|||||||
//looked up by name, no ref needed
|
//looked up by name, no ref needed
|
||||||
new LegacyMechPad("legacy-mech-pad");
|
new LegacyMechPad("legacy-mech-pad");
|
||||||
new LegacyUnitFactory("legacy-unit-factory");
|
new LegacyUnitFactory("legacy-unit-factory");
|
||||||
new LegacyCommandCenter("legacy-command-center");
|
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
//region campaign
|
//region campaign
|
||||||
@@ -1898,7 +1909,7 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
microProcessor = new LogicBlock("micro-processor"){{
|
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;
|
instructionsPerTick = 2;
|
||||||
|
|
||||||
@@ -1906,15 +1917,28 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
logicProcessor = new LogicBlock("logic-processor"){{
|
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;
|
instructionsPerTick = 5;
|
||||||
|
|
||||||
range = 16 * 10;
|
range = 8 * 20;
|
||||||
|
|
||||||
size = 2;
|
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"){{
|
logicDisplay = new LogicDisplay("logic-display"){{
|
||||||
requirements(Category.logic, with(Items.copper, 200, Items.lead, 120, Items.silicon, 100, Items.metaglass, 50));
|
requirements(Category.logic, with(Items.copper, 200, Items.lead, 120, Items.silicon, 100, Items.metaglass, 50));
|
||||||
|
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ public class Bullets implements ContentList{
|
|||||||
width = 6f;
|
width = 6f;
|
||||||
height = 8f;
|
height = 8f;
|
||||||
hitEffect = Fx.flakExplosion;
|
hitEffect = Fx.flakExplosion;
|
||||||
splashDamage = 20f;
|
splashDamage = 22f;
|
||||||
splashDamageRadius = 20f;
|
splashDamageRadius = 20f;
|
||||||
fragBullet = flakGlassFrag;
|
fragBullet = flakGlassFrag;
|
||||||
fragBullets = 5;
|
fragBullets = 5;
|
||||||
@@ -240,7 +240,7 @@ public class Bullets implements ContentList{
|
|||||||
explodeRange = 20f;
|
explodeRange = 20f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
missileExplosive = new MissileBulletType(3f, 10){{
|
missileExplosive = new MissileBulletType(3.7f, 10){{
|
||||||
width = 8f;
|
width = 8f;
|
||||||
height = 8f;
|
height = 8f;
|
||||||
shrinkY = 0f;
|
shrinkY = 0f;
|
||||||
@@ -255,7 +255,7 @@ public class Bullets implements ContentList{
|
|||||||
statusDuration = 60f;
|
statusDuration = 60f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
missileIncendiary = new MissileBulletType(3f, 12){{
|
missileIncendiary = new MissileBulletType(3.7f, 12){{
|
||||||
frontColor = Pal.lightishOrange;
|
frontColor = Pal.lightishOrange;
|
||||||
backColor = Pal.lightOrange;
|
backColor = Pal.lightOrange;
|
||||||
width = 7f;
|
width = 7f;
|
||||||
@@ -269,17 +269,17 @@ public class Bullets implements ContentList{
|
|||||||
status = StatusEffects.burning;
|
status = StatusEffects.burning;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
missileSurge = new MissileBulletType(3f, 20){{
|
missileSurge = new MissileBulletType(3.7f, 20){{
|
||||||
width = 8f;
|
width = 8f;
|
||||||
height = 8f;
|
height = 8f;
|
||||||
shrinkY = 0f;
|
shrinkY = 0f;
|
||||||
drag = -0.01f;
|
drag = -0.01f;
|
||||||
splashDamageRadius = 28f;
|
splashDamageRadius = 28f;
|
||||||
splashDamage = 40f;
|
splashDamage = 35f;
|
||||||
hitEffect = Fx.blastExplosion;
|
hitEffect = Fx.blastExplosion;
|
||||||
despawnEffect = Fx.blastExplosion;
|
despawnEffect = Fx.blastExplosion;
|
||||||
lightning = 2;
|
lightning = 2;
|
||||||
lightningLength = 14;
|
lightningLength = 10;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
standardCopper = new BasicBulletType(2.5f, 9){{
|
standardCopper = new BasicBulletType(2.5f, 9){{
|
||||||
|
|||||||
@@ -52,10 +52,11 @@ public class Fx{
|
|||||||
if(!(e.data instanceof Unit)) return;
|
if(!(e.data instanceof Unit)) return;
|
||||||
|
|
||||||
Unit select = e.data();
|
Unit select = e.data();
|
||||||
|
boolean block = select instanceof BlockUnitc;
|
||||||
|
|
||||||
mixcol(Pal.accent, 1f);
|
mixcol(Pal.accent, 1f);
|
||||||
alpha(e.fout());
|
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);
|
alpha(1f);
|
||||||
Lines.stroke(e.fslope() * 1f);
|
Lines.stroke(e.fslope() * 1f);
|
||||||
Lines.square(select.x, select.y, e.fout() * select.hitSize * 2f, 45);
|
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 -> {
|
massiveExplosion = new Effect(30, e -> {
|
||||||
|
|
||||||
color(Pal.missileYellow);
|
color(Pal.missileYellow);
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ public class TechTree implements ContentList{
|
|||||||
node(distributor);
|
node(distributor);
|
||||||
node(sorter, () -> {
|
node(sorter, () -> {
|
||||||
node(invertedSorter);
|
node(invertedSorter);
|
||||||
node(message);
|
|
||||||
node(overflowGate, () -> {
|
node(overflowGate, () -> {
|
||||||
node(underflowGate);
|
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(groundFactory, () -> {
|
||||||
|
node(commandCenter, () -> {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
node(dagger, () -> {
|
node(dagger, () -> {
|
||||||
node(mace, () -> {
|
node(mace, () -> {
|
||||||
node(fortress, () -> {
|
node(fortress, () -> {
|
||||||
@@ -406,8 +429,6 @@ public class TechTree implements ContentList{
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
//TODO research sectors
|
|
||||||
|
|
||||||
node(groundZero, () -> {
|
node(groundZero, () -> {
|
||||||
node(frozenForest, Seq.with(
|
node(frozenForest, Seq.with(
|
||||||
new SectorComplete(groundZero),
|
new SectorComplete(groundZero),
|
||||||
@@ -556,25 +577,20 @@ public class TechTree implements ContentList{
|
|||||||
public ItemStack[] requirements;
|
public ItemStack[] requirements;
|
||||||
/** Requirements that have been fulfilled. Always the same length as the requirement array. */
|
/** Requirements that have been fulfilled. Always the same length as the requirement array. */
|
||||||
public final ItemStack[] finishedRequirements;
|
public final ItemStack[] finishedRequirements;
|
||||||
/** Extra objectives needed to research this. TODO implement */
|
/** Extra objectives needed to research this. */
|
||||||
public Seq<Objective> objectives = new Seq<>();
|
public Seq<Objective> objectives = new Seq<>();
|
||||||
/** Time required to research this content, in seconds. */
|
/** Time required to research this content, in seconds. */
|
||||||
public float time;
|
public float time;
|
||||||
/** Nodes that depend on this node. */
|
/** Nodes that depend on this node. */
|
||||||
public final Seq<TechNode> children = new Seq<>();
|
public final Seq<TechNode> children = new Seq<>();
|
||||||
/** Research progress, in seconds. */
|
|
||||||
public float progress;
|
|
||||||
|
|
||||||
TechNode(@Nullable TechNode ccontext, UnlockableContent content, ItemStack[] requirements, Runnable children){
|
TechNode(@Nullable TechNode ccontext, UnlockableContent content, ItemStack[] requirements, Runnable children){
|
||||||
if(ccontext != null){
|
if(ccontext != null) ccontext.children.add(this);
|
||||||
ccontext.children.add(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.parent = ccontext;
|
this.parent = ccontext;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.requirements = requirements;
|
this.requirements = requirements;
|
||||||
this.depth = parent == null ? 0 : parent.depth + 1;
|
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.time = Seq.with(requirements).mapFloat(i -> i.item.cost * i.amount).sum() * 10;
|
||||||
this.finishedRequirements = new ItemStack[requirements.length];
|
this.finishedRequirements = new ItemStack[requirements.length];
|
||||||
|
|
||||||
@@ -599,7 +615,6 @@ public class TechTree implements ContentList{
|
|||||||
|
|
||||||
/** Flushes research progress to settings. */
|
/** Flushes research progress to settings. */
|
||||||
public void save(){
|
public void save(){
|
||||||
Core.settings.put("research-" + content.name, progress);
|
|
||||||
|
|
||||||
//save finished requirements by item type
|
//save finished requirements by item type
|
||||||
for(ItemStack stack : finishedRequirements){
|
for(ItemStack stack : finishedRequirements){
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class UnitTypes implements ContentList{
|
|||||||
public static @EntityDef({Unitc.class, Legsc.class}) UnitType atrax;
|
public static @EntityDef({Unitc.class, Legsc.class}) UnitType atrax;
|
||||||
|
|
||||||
//legs + building
|
//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)
|
//air (no special traits)
|
||||||
public static @EntityDef({Unitc.class}) UnitType flare, eclipse, horizon, zenith, antumbra;
|
public static @EntityDef({Unitc.class}) UnitType flare, eclipse, horizon, zenith, antumbra;
|
||||||
@@ -72,7 +72,6 @@ public class UnitTypes implements ContentList{
|
|||||||
mace = new UnitType("mace"){{
|
mace = new UnitType("mace"){{
|
||||||
speed = 0.4f;
|
speed = 0.4f;
|
||||||
hitsize = 9f;
|
hitsize = 9f;
|
||||||
range = 10f;
|
|
||||||
health = 500;
|
health = 500;
|
||||||
armor = 4f;
|
armor = 4f;
|
||||||
|
|
||||||
@@ -84,12 +83,11 @@ public class UnitTypes implements ContentList{
|
|||||||
reload = 14f;
|
reload = 14f;
|
||||||
recoil = 1f;
|
recoil = 1f;
|
||||||
ejectEffect = Fx.none;
|
ejectEffect = Fx.none;
|
||||||
bullet = new BulletType(3f, 30f){{
|
bullet = new BulletType(3.9f, 30f){{
|
||||||
ammoMultiplier = 3f;
|
ammoMultiplier = 3f;
|
||||||
hitSize = 7f;
|
hitSize = 7f;
|
||||||
lifetime = 42f;
|
lifetime = 12f;
|
||||||
pierce = true;
|
pierce = true;
|
||||||
drag = 0.05f;
|
|
||||||
statusDuration = 60f * 4;
|
statusDuration = 60f * 4;
|
||||||
shootEffect = Fx.shootSmallFlame;
|
shootEffect = Fx.shootSmallFlame;
|
||||||
hitEffect = Fx.hitFlameSmall;
|
hitEffect = Fx.hitFlameSmall;
|
||||||
@@ -376,52 +374,218 @@ public class UnitTypes implements ContentList{
|
|||||||
}});
|
}});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//TODO implement
|
|
||||||
arkyid = new UnitType("arkyid"){{
|
arkyid = new UnitType("arkyid"){{
|
||||||
drag = 0.1f;
|
drag = 0.1f;
|
||||||
speed = 0.5f;
|
speed = 0.5f;
|
||||||
hitsize = 9f;
|
hitsize = 21f;
|
||||||
health = 140;
|
health = 8000;
|
||||||
|
armor = 6f;
|
||||||
|
|
||||||
|
rotateSpeed = 2.7f;
|
||||||
|
|
||||||
legCount = 6;
|
legCount = 6;
|
||||||
legMoveSpace = 1f;
|
legMoveSpace = 1f;
|
||||||
legPairOffset = 3;
|
legPairOffset = 3;
|
||||||
legLength = 34f;
|
legLength = 30f;
|
||||||
rotateShooting = false;
|
|
||||||
legExtension = -15;
|
legExtension = -15;
|
||||||
legBaseOffset = 10f;
|
legBaseOffset = 10f;
|
||||||
landShake = 2f;
|
landShake = 1f;
|
||||||
legSpeed = 0.1f;
|
legSpeed = 0.1f;
|
||||||
legLengthScl = 1f;
|
legLengthScl = 0.96f;
|
||||||
rippleScale = 2f;
|
rippleScale = 2f;
|
||||||
legSpeed = 0.2f;
|
legSpeed = 0.2f;
|
||||||
|
|
||||||
legSplashDamage = 32;
|
legSplashDamage = 32;
|
||||||
legSplashRange = 30;
|
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(
|
weapons.add(
|
||||||
new Weapon("missiles-mount"){{
|
new Weapon("spiroct-weapon"){{
|
||||||
reload = 20f;
|
reload = 9f;
|
||||||
x = 4f;
|
x = 4f;
|
||||||
|
y = 8f;
|
||||||
rotate = true;
|
rotate = true;
|
||||||
shake = 1f;
|
bullet = sapper;
|
||||||
bullet = new MissileBulletType(2.7f, 12, "missile"){{
|
}},
|
||||||
width = 8f;
|
new Weapon("spiroct-weapon"){{
|
||||||
height = 8f;
|
reload = 15f;
|
||||||
shrinkY = 0f;
|
x = 9f;
|
||||||
drag = -0.003f;
|
y = 6f;
|
||||||
homingRange = 60f;
|
rotate = true;
|
||||||
keepVelocity = false;
|
bullet = sapper;
|
||||||
splashDamageRadius = 25f;
|
}},
|
||||||
splashDamage = 10f;
|
new Weapon("spiroct-weapon"){{
|
||||||
lifetime = 120f;
|
reload = 23f;
|
||||||
trailColor = Color.gray;
|
x = 14f;
|
||||||
backColor = Pal.bulletYellowBack;
|
y = 0f;
|
||||||
frontColor = Pal.bulletYellow;
|
rotate = true;
|
||||||
hitEffect = Fx.blastExplosion;
|
bullet = sapper;
|
||||||
despawnEffect = Fx.blastExplosion;
|
}},
|
||||||
weaveScale = 8f;
|
new Weapon("large-purple-mount"){{
|
||||||
weaveMag = 2f;
|
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;
|
faceTarget = false;
|
||||||
engineOffset = 5.5f;
|
engineOffset = 5.5f;
|
||||||
range = 140f;
|
range = 140f;
|
||||||
|
crashDamageMultiplier = 4f;
|
||||||
|
|
||||||
weapons.add(new Weapon(){{
|
weapons.add(new Weapon(){{
|
||||||
y = 0f;
|
y = 0f;
|
||||||
x = 2f;
|
x = 2f;
|
||||||
@@ -449,7 +615,7 @@ public class UnitTypes implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
horizon = new UnitType("horizon"){{
|
horizon = new UnitType("horizon"){{
|
||||||
health = 300;
|
health = 350;
|
||||||
speed = 2f;
|
speed = 2f;
|
||||||
accel = 0.08f;
|
accel = 0.08f;
|
||||||
drag = 0.016f;
|
drag = 0.016f;
|
||||||
@@ -458,19 +624,19 @@ public class UnitTypes implements ContentList{
|
|||||||
engineOffset = 7.8f;
|
engineOffset = 7.8f;
|
||||||
range = 140f;
|
range = 140f;
|
||||||
faceTarget = false;
|
faceTarget = false;
|
||||||
armor = 2f;
|
armor = 4f;
|
||||||
|
|
||||||
weapons.add(new Weapon(){{
|
weapons.add(new Weapon(){{
|
||||||
minShootVelocity = 0.75f;
|
minShootVelocity = 0.75f;
|
||||||
x = 3f;
|
x = 3f;
|
||||||
shootY = 0f;
|
shootY = 0f;
|
||||||
reload = 12f;
|
reload = 11f;
|
||||||
shootCone = 180f;
|
shootCone = 180f;
|
||||||
ejectEffect = Fx.none;
|
ejectEffect = Fx.none;
|
||||||
inaccuracy = 15f;
|
inaccuracy = 15f;
|
||||||
ignoreRotation = true;
|
ignoreRotation = true;
|
||||||
shootSound = Sounds.none;
|
shootSound = Sounds.none;
|
||||||
bullet = new BombBulletType(23f, 25f){{
|
bullet = new BombBulletType(28f, 25f){{
|
||||||
width = 10f;
|
width = 10f;
|
||||||
height = 14f;
|
height = 14f;
|
||||||
hitEffect = Fx.flakExplosion;
|
hitEffect = Fx.flakExplosion;
|
||||||
@@ -484,21 +650,21 @@ public class UnitTypes implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
zenith = new UnitType("zenith"){{
|
zenith = new UnitType("zenith"){{
|
||||||
health = 1000;
|
health = 700;
|
||||||
speed = 1.9f;
|
speed = 1.7f;
|
||||||
accel = 0.04f;
|
accel = 0.04f;
|
||||||
drag = 0.016f;
|
drag = 0.016f;
|
||||||
flying = true;
|
flying = true;
|
||||||
range = 140f;
|
range = 140f;
|
||||||
hitsize = 18f;
|
hitsize = 18f;
|
||||||
lowAltitude = true;
|
lowAltitude = true;
|
||||||
armor = 6f;
|
armor = 5f;
|
||||||
|
|
||||||
engineOffset = 12f;
|
engineOffset = 12f;
|
||||||
engineSize = 3f;
|
engineSize = 3f;
|
||||||
|
|
||||||
weapons.add(new Weapon("zenith-missiles"){{
|
weapons.add(new Weapon("zenith-missiles"){{
|
||||||
reload = 32f;
|
reload = 40f;
|
||||||
x = 7f;
|
x = 7f;
|
||||||
rotate = true;
|
rotate = true;
|
||||||
shake = 1f;
|
shake = 1f;
|
||||||
@@ -534,21 +700,21 @@ public class UnitTypes implements ContentList{
|
|||||||
rotateSpeed = 1.9f;
|
rotateSpeed = 1.9f;
|
||||||
flying = true;
|
flying = true;
|
||||||
lowAltitude = true;
|
lowAltitude = true;
|
||||||
health = 9000;
|
health = 7000;
|
||||||
armor = 9f;
|
armor = 9f;
|
||||||
engineOffset = 21;
|
engineOffset = 21;
|
||||||
engineSize = 5.3f;
|
engineSize = 5.3f;
|
||||||
hitsize = 58f;
|
hitsize = 56f;
|
||||||
|
|
||||||
BulletType missiles = new MissileBulletType(2.7f, 10){{
|
BulletType missiles = new MissileBulletType(2.7f, 10){{
|
||||||
width = 8f;
|
width = 8f;
|
||||||
height = 8f;
|
height = 8f;
|
||||||
shrinkY = 0f;
|
shrinkY = 0f;
|
||||||
drag = -0.01f;
|
drag = -0.01f;
|
||||||
splashDamageRadius = 40f;
|
splashDamageRadius = 20f;
|
||||||
splashDamage = 40f;
|
splashDamage = 30f;
|
||||||
ammoMultiplier = 4f;
|
ammoMultiplier = 4f;
|
||||||
lifetime = 80f;
|
lifetime = 50f;
|
||||||
hitEffect = Fx.blastExplosion;
|
hitEffect = Fx.blastExplosion;
|
||||||
despawnEffect = Fx.blastExplosion;
|
despawnEffect = Fx.blastExplosion;
|
||||||
|
|
||||||
@@ -582,18 +748,18 @@ public class UnitTypes implements ContentList{
|
|||||||
new Weapon("large-bullet-mount"){{
|
new Weapon("large-bullet-mount"){{
|
||||||
y = 2f;
|
y = 2f;
|
||||||
x = 10f;
|
x = 10f;
|
||||||
shootY = 12f;
|
shootY = 10f;
|
||||||
reload = 10;
|
reload = 12;
|
||||||
shake = 1f;
|
shake = 1f;
|
||||||
rotateSpeed = 2f;
|
rotateSpeed = 2f;
|
||||||
ejectEffect = Fx.shellEjectSmall;
|
ejectEffect = Fx.shellEjectSmall;
|
||||||
shootSound = Sounds.shootBig;
|
shootSound = Sounds.shootBig;
|
||||||
rotate = true;
|
rotate = true;
|
||||||
occlusion = 8f;
|
occlusion = 8f;
|
||||||
bullet = new BasicBulletType(7f, 60){{
|
bullet = new BasicBulletType(7f, 50){{
|
||||||
width = 12f;
|
width = 12f;
|
||||||
height = 18f;
|
height = 18f;
|
||||||
lifetime = 30f;
|
lifetime = 25f;
|
||||||
shootEffect = Fx.shootBig;
|
shootEffect = Fx.shootBig;
|
||||||
}};
|
}};
|
||||||
}}
|
}}
|
||||||
@@ -607,13 +773,25 @@ public class UnitTypes implements ContentList{
|
|||||||
rotateSpeed = 1f;
|
rotateSpeed = 1f;
|
||||||
flying = true;
|
flying = true;
|
||||||
lowAltitude = true;
|
lowAltitude = true;
|
||||||
health = 18000;
|
health = 20000;
|
||||||
engineOffset = 38;
|
engineOffset = 38;
|
||||||
engineSize = 7.3f;
|
engineSize = 7.3f;
|
||||||
hitsize = 58f;
|
hitsize = 58f;
|
||||||
destructibleWreck = false;
|
destructibleWreck = false;
|
||||||
armor = 13f;
|
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(
|
weapons.add(
|
||||||
new Weapon("large-laser-mount"){{
|
new Weapon("large-laser-mount"){{
|
||||||
shake = 4f;
|
shake = 4f;
|
||||||
@@ -621,14 +799,14 @@ public class UnitTypes implements ContentList{
|
|||||||
x = 18f;
|
x = 18f;
|
||||||
y = 5f;
|
y = 5f;
|
||||||
rotateSpeed = 2f;
|
rotateSpeed = 2f;
|
||||||
reload = 50f;
|
reload = 45f;
|
||||||
recoil = 4f;
|
recoil = 4f;
|
||||||
shootSound = Sounds.laser;
|
shootSound = Sounds.laser;
|
||||||
occlusion = 20f;
|
occlusion = 20f;
|
||||||
rotate = true;
|
rotate = true;
|
||||||
|
|
||||||
bullet = new LaserBulletType(){{
|
bullet = new LaserBulletType(){{
|
||||||
damage = 75f;
|
damage = 90f;
|
||||||
sideAngle = 20f;
|
sideAngle = 20f;
|
||||||
sideWidth = 1.5f;
|
sideWidth = 1.5f;
|
||||||
sideLength = 80f;
|
sideLength = 80f;
|
||||||
@@ -638,50 +816,29 @@ public class UnitTypes implements ContentList{
|
|||||||
colors = new Color[]{Color.valueOf("ec7458aa"), Color.valueOf("ff9c5a"), Color.white};
|
colors = new Color[]{Color.valueOf("ec7458aa"), Color.valueOf("ff9c5a"), Color.white};
|
||||||
}};
|
}};
|
||||||
}},
|
}},
|
||||||
new Weapon("missiles-mount"){{
|
new Weapon("large-artillery"){{
|
||||||
x = 11f;
|
x = 11f;
|
||||||
y = 27f;
|
y = 27f;
|
||||||
rotateSpeed = 2f;
|
rotateSpeed = 2f;
|
||||||
reload = 4f;
|
reload = 9f;
|
||||||
shootSound = Sounds.flame;
|
shootSound = Sounds.flame;
|
||||||
occlusion = 7f;
|
occlusion = 7f;
|
||||||
rotate = true;
|
rotate = true;
|
||||||
recoil = 0.5f;
|
recoil = 0.5f;
|
||||||
|
|
||||||
bullet = Bullets.pyraFlame;
|
bullet = fragBullet;
|
||||||
}},
|
}},
|
||||||
new Weapon("large-artillery"){{
|
new Weapon("large-artillery"){{
|
||||||
y = -13f;
|
y = -13f;
|
||||||
x = 20f;
|
x = 20f;
|
||||||
reload = 18f;
|
reload = 12f;
|
||||||
ejectEffect = Fx.shellEjectSmall;
|
ejectEffect = Fx.shellEjectSmall;
|
||||||
rotateSpeed = 7f;
|
rotateSpeed = 7f;
|
||||||
shake = 1f;
|
shake = 1f;
|
||||||
shootSound = Sounds.shoot;
|
shootSound = Sounds.shoot;
|
||||||
rotate = true;
|
rotate = true;
|
||||||
occlusion = 12f;
|
occlusion = 12f;
|
||||||
bullet = new ArtilleryBulletType(3.2f, 12){{
|
bullet = fragBullet;
|
||||||
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;
|
|
||||||
}};
|
|
||||||
}});
|
}});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -700,6 +857,7 @@ public class UnitTypes implements ContentList{
|
|||||||
engineOffset = 5.7f;
|
engineOffset = 5.7f;
|
||||||
itemCapacity = 30;
|
itemCapacity = 30;
|
||||||
range = 50f;
|
range = 50f;
|
||||||
|
isCounted = false;
|
||||||
|
|
||||||
mineTier = 1;
|
mineTier = 1;
|
||||||
mineSpeed = 2.5f;
|
mineSpeed = 2.5f;
|
||||||
@@ -720,6 +878,7 @@ public class UnitTypes implements ContentList{
|
|||||||
engineOffset = 6.5f;
|
engineOffset = 6.5f;
|
||||||
hitsize = 8f;
|
hitsize = 8f;
|
||||||
lowAltitude = true;
|
lowAltitude = true;
|
||||||
|
isCounted = false;
|
||||||
|
|
||||||
mineTier = 2;
|
mineTier = 2;
|
||||||
mineSpeed = 3.5f;
|
mineSpeed = 3.5f;
|
||||||
@@ -1094,6 +1253,7 @@ public class UnitTypes implements ContentList{
|
|||||||
hitsize = 0f;
|
hitsize = 0f;
|
||||||
health = 1;
|
health = 1;
|
||||||
rotateSpeed = 360f;
|
rotateSpeed = 360f;
|
||||||
|
itemCapacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -325,6 +325,10 @@ public class Logic implements ApplicationListener{
|
|||||||
Events.fire(Trigger.update);
|
Events.fire(Trigger.update);
|
||||||
universe.updateGlobal();
|
universe.updateGlobal();
|
||||||
|
|
||||||
|
if(Core.settings.modified() && !state.isPlaying()){
|
||||||
|
Core.settings.forceSave();
|
||||||
|
}
|
||||||
|
|
||||||
if(state.isGame()){
|
if(state.isGame()){
|
||||||
if(!net.client()){
|
if(!net.client()){
|
||||||
state.enemies = Groups.unit.count(u -> u.team() == state.rules.waveTeam && u.type().isCounted);
|
state.enemies = Groups.unit.count(u -> u.team() == state.rules.waveTeam && u.type().isCounted);
|
||||||
|
|||||||
@@ -366,6 +366,9 @@ public class NetClient implements ApplicationListener{
|
|||||||
|
|
||||||
@Remote
|
@Remote
|
||||||
public static void playerDisconnect(int playerid){
|
public static void playerDisconnect(int playerid){
|
||||||
|
if(netClient != null){
|
||||||
|
netClient.addRemovedEntity(playerid);
|
||||||
|
}
|
||||||
Groups.player.removeByID(playerid);
|
Groups.player.removeByID(playerid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,6 +562,22 @@ public class NetClient implements ApplicationListener{
|
|||||||
//limit to 10 to prevent buffer overflows
|
//limit to 10 to prevent buffer overflows
|
||||||
int usedRequests = Math.min(player.builder().plans().size, 10);
|
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];
|
requests = new BuildPlan[usedRequests];
|
||||||
for(int i = 0; i < usedRequests; i++){
|
for(int i = 0; i < usedRequests; i++){
|
||||||
requests[i] = player.builder().plans().get(i);
|
requests[i] = player.builder().plans().get(i);
|
||||||
|
|||||||
@@ -371,6 +371,11 @@ public class NetServer implements ApplicationListener{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(currentlyKicking[0] != null){
|
||||||
|
player.sendMessage("[scarlet]A vote is already in progress.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(args.length == 0){
|
if(args.length == 0){
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("[orange]Players to kick: \n");
|
builder.append("[orange]Players to kick: \n");
|
||||||
@@ -385,9 +390,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
int id = Strings.parseInt(args[0].substring(1));
|
int id = Strings.parseInt(args[0].substring(1));
|
||||||
found = Groups.player.find(p -> p.id() == id);
|
found = Groups.player.find(p -> p.id() == id);
|
||||||
}else{
|
}else{
|
||||||
found = Groups.player.find(p -> {
|
found = Groups.player.find(p -> p.name.equalsIgnoreCase(args[0]));
|
||||||
return p.name.equalsIgnoreCase(args[0]);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(found != null){
|
if(found != null){
|
||||||
@@ -527,6 +530,10 @@ public class NetServer implements ApplicationListener{
|
|||||||
public static void serverPacketUnreliable(Player player, String type, String contents){
|
public static void serverPacketUnreliable(Player player, String type, String contents){
|
||||||
serverPacketReliable(player, type, contents);
|
serverPacketReliable(player, type, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean invalid(float f){
|
||||||
|
return Float.isInfinite(f) || Float.isNaN(f);
|
||||||
|
}
|
||||||
|
|
||||||
@Remote(targets = Loc.client, unreliable = true)
|
@Remote(targets = Loc.client, unreliable = true)
|
||||||
public static void clientSnapshot(
|
public static void clientSnapshot(
|
||||||
@@ -545,6 +552,16 @@ public class NetServer implements ApplicationListener{
|
|||||||
NetConnection con = player.con;
|
NetConnection con = player.con;
|
||||||
if(con == null || snapshotID < con.lastReceivedClientSnapshot) return;
|
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;
|
boolean verifyPosition = !player.dead() && netServer.admins.getStrict() && headless;
|
||||||
|
|
||||||
if(con.lastReceivedClientTime == 0) con.lastReceivedClientTime = Time.millis() - 16;
|
if(con.lastReceivedClientTime == 0) con.lastReceivedClientTime = Time.millis() - 16;
|
||||||
@@ -614,7 +631,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
Unit unit = player.unit();
|
Unit unit = player.unit();
|
||||||
|
|
||||||
long elapsed = Time.timeSinceMillis(con.lastReceivedClientTime);
|
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()){
|
if(unit.isGrounded()){
|
||||||
maxSpeed *= unit.floorSpeedMultiplier();
|
maxSpeed *= unit.floorSpeedMultiplier();
|
||||||
}
|
}
|
||||||
@@ -682,8 +699,8 @@ public class NetServer implements ApplicationListener{
|
|||||||
public static void adminRequest(Player player, Player other, AdminAction action){
|
public static void adminRequest(Player player, Player other, AdminAction action){
|
||||||
|
|
||||||
if(!player.admin){
|
if(!player.admin){
|
||||||
Log.warn("ACCESS DENIED: Player @ / @ attempted to perform admin action without proper security access.",
|
Log.warn("ACCESS DENIED: Player @ / @ attempted to perform admin action '@' on '@' without proper security access.",
|
||||||
player.name, player.con.address);
|
player.name, player.con.address, action.name(), other == null ? null : other.name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -762,6 +779,10 @@ public class NetServer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(state.isGame() && net.server()){
|
if(state.isGame() && net.server()){
|
||||||
|
if(state.rules.pvp){
|
||||||
|
state.serverPaused = isWaitingForPlayers();
|
||||||
|
}
|
||||||
|
|
||||||
sync();
|
sync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,6 +185,8 @@ public class Renderer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void draw(){
|
public void draw(){
|
||||||
|
Events.fire(Trigger.preDraw);
|
||||||
|
|
||||||
camera.update();
|
camera.update();
|
||||||
|
|
||||||
if(Float.isNaN(camera.position.x) || Float.isNaN(camera.position.y)){
|
if(Float.isNaN(camera.position.x) || Float.isNaN(camera.position.y)){
|
||||||
@@ -205,6 +207,8 @@ public class Renderer implements ApplicationListener{
|
|||||||
|
|
||||||
Draw.sort(true);
|
Draw.sort(true);
|
||||||
|
|
||||||
|
Events.fire(Trigger.draw);
|
||||||
|
|
||||||
if(pixelator.enabled()){
|
if(pixelator.enabled()){
|
||||||
pixelator.register();
|
pixelator.register();
|
||||||
}
|
}
|
||||||
@@ -254,6 +258,8 @@ public class Renderer implements ApplicationListener{
|
|||||||
Draw.reset();
|
Draw.reset();
|
||||||
Draw.flush();
|
Draw.flush();
|
||||||
Draw.sort(false);
|
Draw.sort(false);
|
||||||
|
|
||||||
|
Events.fire(Trigger.postDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawBackground(){
|
private void drawBackground(){
|
||||||
|
|||||||
@@ -128,6 +128,8 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
public void update(){
|
public void update(){
|
||||||
if(disableUI || Core.scene == null) return;
|
if(disableUI || Core.scene == null) return;
|
||||||
|
|
||||||
|
Events.fire(Trigger.uiDrawBegin);
|
||||||
|
|
||||||
Core.scene.act();
|
Core.scene.act();
|
||||||
Core.scene.draw();
|
Core.scene.draw();
|
||||||
|
|
||||||
@@ -143,6 +145,8 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
control.tutorial.draw();
|
control.tutorial.draw();
|
||||||
Draw.flush();
|
Draw.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Events.fire(Trigger.uiDrawEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -221,12 +225,15 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TextureRegionDrawable getIcon(String name){
|
public TextureRegionDrawable getIcon(String name){
|
||||||
if(Icon.icons.containsKey(name)){
|
if(Icon.icons.containsKey(name)) return Icon.icons.get(name);
|
||||||
return Icon.icons.get(name);
|
|
||||||
}
|
|
||||||
return Core.atlas.getDrawable("error");
|
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){
|
public void loadAnd(Runnable call){
|
||||||
loadAnd("@loading", call);
|
loadAnd("@loading", call);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public class MapEditor{
|
|||||||
x = Mathf.clamp(x, (drawBlock.size - 1) / 2, width() - drawBlock.size / 2 - 1);
|
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);
|
y = Mathf.clamp(y, (drawBlock.size - 1) / 2, height() - drawBlock.size / 2 - 1);
|
||||||
if(!hasOverlap(x, y)){
|
if(!hasOverlap(x, y)){
|
||||||
tile(x, y).setBlock(drawBlock, drawTeam, 0);
|
tile(x, y).setBlock(drawBlock, drawTeam, rotation);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
boolean isFloor = drawBlock.isFloor() && drawBlock != Blocks.air;
|
boolean isFloor = drawBlock.isFloor() && drawBlock != Blocks.air;
|
||||||
|
|||||||
@@ -110,18 +110,13 @@ public class MapRenderer implements Disposable{
|
|||||||
if(wall != Blocks.air && wall.synthetic()){
|
if(wall != Blocks.air && wall.synthetic()){
|
||||||
region = !Core.atlas.isFound(wall.editorIcon()) || !center ? Core.atlas.find("clear-editor") : wall.editorIcon();
|
region = !Core.atlas.isFound(wall.editorIcon()) || !center ? Core.atlas.find("clear-editor") : wall.editorIcon();
|
||||||
|
|
||||||
if(wall.rotate){
|
float width = region.getWidth() * Draw.scl, height = region.getHeight() * Draw.scl;
|
||||||
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;
|
|
||||||
|
|
||||||
mesh.draw(idxWall, region,
|
mesh.draw(idxWall, region,
|
||||||
wx * tilesize + wall.offset + (tilesize - width) / 2f,
|
wx * tilesize + wall.offset + (tilesize - width) / 2f,
|
||||||
wy * tilesize + wall.offset + (tilesize - height) / 2f,
|
wy * tilesize + wall.offset + (tilesize - height) / 2f,
|
||||||
width, height);
|
width, height,
|
||||||
}
|
tile.build == null || !wall.rotate ? 0 : tile.build.rotdeg() - 90);
|
||||||
}else{
|
}else{
|
||||||
region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length - 1)];
|
region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length - 1)];
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
/** Utility class for damaging in an area. */
|
/** Utility class for damaging in an area. */
|
||||||
public class Damage{
|
public class Damage{
|
||||||
|
private static Tile furthest;
|
||||||
private static Rect rect = new Rect();
|
private static Rect rect = new Rect();
|
||||||
private static Rect hitrect = new Rect();
|
private static Rect hitrect = new Rect();
|
||||||
private static Vec2 tr = new Vec2();
|
private static Vec2 tr = new Vec2();
|
||||||
@@ -30,24 +31,26 @@ public class Damage{
|
|||||||
private static Unit tmpUnit;
|
private static Unit tmpUnit;
|
||||||
|
|
||||||
/** Creates a dynamic explosion based on specified parameters. */
|
/** 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){
|
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color, boolean damage){
|
||||||
for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){
|
if(damage){
|
||||||
int branches = 5 + Mathf.clamp((int)(power / 30), 1, 20);
|
for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){
|
||||||
Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.derelict, Pal.power, 3, x, y, Mathf.random(360f), branches + Mathf.range(2)));
|
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++){
|
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));
|
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++){
|
for(int i = 0; i < waves; i++){
|
||||||
int f = i;
|
int f = i;
|
||||||
Time.run(i * 2f, () -> {
|
Time.run(i * 2f, () -> {
|
||||||
Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 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));
|
Fx.blockExplosionSmoke.at(x + Mathf.range(radius), y + Mathf.range(radius));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(explosiveness > 15f){
|
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){
|
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);
|
collideLine(hitter, team, effect, x, y, angle, length, false);
|
||||||
}
|
}
|
||||||
@@ -87,7 +107,7 @@ public class Damage{
|
|||||||
tr.trns(angle, length);
|
tr.trns(angle, length);
|
||||||
Intc2 collider = (cx, cy) -> {
|
Intc2 collider = (cx, cy) -> {
|
||||||
Building tile = world.build(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);
|
tile.collision(hitter);
|
||||||
collidedBlocks.add(tile.pos());
|
collidedBlocks.add(tile.pos());
|
||||||
hitter.type.hit(hitter, tile.x, tile.y);
|
hitter.type.hit(hitter, tile.x, tile.y);
|
||||||
|
|||||||
@@ -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 + "!");
|
if(map == null) throw new RuntimeException("Mapping is not enabled for group " + id + "!");
|
||||||
T t = map.get(id);
|
T t = map.get(id);
|
||||||
if(t != null){ //remove if present in map already
|
if(t != null){ //remove if present in map already
|
||||||
remove(t);
|
t.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class Fires{
|
|||||||
|
|
||||||
/** Start a fire on the tile. If there already is a file there, refreshes its lifetime. */
|
/** Start a fire on the tile. If there already is a file there, refreshes its lifetime. */
|
||||||
public static void create(Tile tile){
|
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());
|
Fire fire = map.get(tile.pos());
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,17 @@ public class Units{
|
|||||||
private static boolean boolResult;
|
private static boolean boolResult;
|
||||||
|
|
||||||
@Remote(called = Loc.server)
|
@Remote(called = Loc.server)
|
||||||
public static void unitDeath(Unit unit){
|
public static void unitDeath(int uid){
|
||||||
unit.killed();
|
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)
|
@Remote(called = Loc.server)
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ public class ForceFieldAbility implements Ability{
|
|||||||
|
|
||||||
private float realRad;
|
private float realRad;
|
||||||
private Unit paramUnit;
|
private Unit paramUnit;
|
||||||
private boolean hadShield;
|
|
||||||
private final Cons<Shielderc> shieldConsumer = trait -> {
|
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){
|
if(trait.team() != paramUnit.team && Intersector.isInsideHexagon(paramUnit.x, paramUnit.y, realRad * 2f, trait.x(), trait.y()) && paramUnit.shield > 0){
|
||||||
trait.absorb();
|
trait.absorb();
|
||||||
@@ -32,6 +31,8 @@ public class ForceFieldAbility implements Ability{
|
|||||||
//break shield
|
//break shield
|
||||||
if(paramUnit.shield <= trait.damage()){
|
if(paramUnit.shield <= trait.damage()){
|
||||||
paramUnit.shield -= cooldown * regen;
|
paramUnit.shield -= cooldown * regen;
|
||||||
|
|
||||||
|
Fx.shieldBreak.at(paramUnit.x, paramUnit.y, radius, paramUnit.team.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
paramUnit.shield -= trait.damage();
|
paramUnit.shield -= trait.damage();
|
||||||
@@ -54,13 +55,6 @@ public class ForceFieldAbility implements Ability{
|
|||||||
unit.shield += Time.delta * regen;
|
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){
|
if(unit.shield > 0){
|
||||||
unit.timer2 = Mathf.lerpDelta(unit.timer2, 1f, 0.06f);
|
unit.timer2 = Mathf.lerpDelta(unit.timer2, 1f, 0.06f);
|
||||||
paramUnit = unit;
|
paramUnit = unit;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public abstract class BulletType extends Content{
|
|||||||
|
|
||||||
public float fragCone = 360f;
|
public float fragCone = 360f;
|
||||||
public int fragBullets = 9;
|
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 BulletType fragBullet = null;
|
||||||
public Color hitColor = Color.white;
|
public Color hitColor = Color.white;
|
||||||
|
|
||||||
@@ -92,6 +92,7 @@ public abstract class BulletType extends Content{
|
|||||||
public float homingPower = 0f;
|
public float homingPower = 0f;
|
||||||
public float homingRange = 50f;
|
public float homingRange = 50f;
|
||||||
|
|
||||||
|
public Color lightningColor = Pal.surge;
|
||||||
public int lightning;
|
public int lightning;
|
||||||
public int lightningLength = 5;
|
public int lightningLength = 5;
|
||||||
/** Use a negative value to use default bullet damage. */
|
/** 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++){
|
for(int i = 0; i < fragBullets; i++){
|
||||||
float len = Mathf.random(1f, 7f);
|
float len = Mathf.random(1f, 7f);
|
||||||
float a = b.rotation() + Mathf.range(fragCone/2);
|
float a = b.rotation() + Mathf.range(fragCone/2);
|
||||||
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++){
|
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);
|
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){
|
public Bullet create(Bullet parent, float x, float y, float angle, float velocityScl){
|
||||||
return create(parent.owner(), parent.team, x, y, angle, velocityScl);
|
return create(parent.owner(), parent.team, x, y, angle, velocityScl);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class HealBulletType extends BulletType{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean collides(Bullet b, Building tile){
|
public boolean collides(Bullet b, Building tile){
|
||||||
return tile.team() != b.team || tile.healthf() < 1f;
|
return tile.team != b.team || tile.healthf() < 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,7 +46,7 @@ public class HealBulletType extends BulletType{
|
|||||||
public void hitTile(Bullet b, Building tile){
|
public void hitTile(Bullet b, Building tile){
|
||||||
super.hit(b);
|
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);
|
Fx.healBlockFull.at(tile.x, tile.y, tile.block().size, Pal.heal);
|
||||||
tile.heal(healPercent / 100f * tile.maxHealth());
|
tile.heal(healPercent / 100f * tile.maxHealth());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ import mindustry.gen.*;
|
|||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
|
||||||
import static mindustry.Vars.world;
|
|
||||||
|
|
||||||
public class LaserBulletType extends BulletType{
|
public class LaserBulletType extends BulletType{
|
||||||
protected static Tile furthest;
|
protected static Tile furthest;
|
||||||
|
|
||||||
@@ -49,24 +47,13 @@ public class LaserBulletType extends BulletType{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Bullet b){
|
public void init(Bullet b){
|
||||||
Tmp.v1.trns(b.rotation(), length);
|
float resultLength = Damage.collideLaser(b, 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);
|
|
||||||
|
|
||||||
laserEffect.at(b.x, b.y, b.rotation(), resultLength * 0.75f);
|
laserEffect.at(b.x, b.y, b.rotation(), resultLength * 0.75f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Bullet b){
|
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 f = Mathf.curve(b.fin(), 0f, 0.2f);
|
||||||
float baseLen = realLength * f;
|
float baseLen = realLength * f;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class ShrapnelBulletType extends BulletType{
|
|||||||
public Color fromColor = Color.white, toColor = Pal.lancerLaser;
|
public Color fromColor = Color.white, toColor = Pal.lancerLaser;
|
||||||
|
|
||||||
public int serrations = 7;
|
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(){
|
public ShrapnelBulletType(){
|
||||||
speed = 0.01f;
|
speed = 0.01f;
|
||||||
@@ -24,23 +24,26 @@ public class ShrapnelBulletType extends BulletType{
|
|||||||
lifetime = 10f;
|
lifetime = 10f;
|
||||||
despawnEffect = Fx.none;
|
despawnEffect = Fx.none;
|
||||||
pierce = true;
|
pierce = true;
|
||||||
|
keepVelocity = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Bullet b){
|
public void init(Bullet b){
|
||||||
Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), length);
|
Damage.collideLaser(b, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Bullet b){
|
public void draw(Bullet b){
|
||||||
|
float realLength = b.fdata;
|
||||||
|
|
||||||
Draw.color(fromColor, toColor, b.fin());
|
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);
|
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 + 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);
|
Drawf.tri(b.x, b.y, width * b.fout(), 10f, b.rotation() + 180f);
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ abstract class BlockUnitComp implements Unitc{
|
|||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
if(tile != null){
|
if(tile != null){
|
||||||
team = tile.team();
|
team = tile.team;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ abstract class BlockUnitComp implements Unitc{
|
|||||||
public void team(Team team){
|
public void team(Team team){
|
||||||
if(tile != null && this.team != team){
|
if(tile != null && this.team != team){
|
||||||
this.team = team;
|
this.team = team;
|
||||||
if(tile.team() != team){
|
if(tile.team != team){
|
||||||
tile.team(team);
|
tile.team(team);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,7 +144,6 @@ abstract class BuilderComp implements Unitc{
|
|||||||
boolean shouldSkip(BuildPlan request, @Nullable Building core){
|
boolean shouldSkip(BuildPlan request, @Nullable Building core){
|
||||||
//requests that you have at least *started* are considered
|
//requests that you have at least *started* are considered
|
||||||
if(state.rules.infiniteResources || team().rules().infiniteResources || request.breaking || core == null) return false;
|
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);
|
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){
|
public final void writeBase(Writes write){
|
||||||
write.f(health);
|
write.f(health);
|
||||||
write.b(rotation);
|
write.b(rotation | 0b10000000);
|
||||||
write.b(team.id);
|
write.b(team.id);
|
||||||
|
write.b(0); //extra padding for later use
|
||||||
if(items != null) items.write(write);
|
if(items != null) items.write(write);
|
||||||
if(power != null) power.write(write);
|
if(power != null) power.write(write);
|
||||||
if(liquids != null) liquids.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){
|
public final void readBase(Reads read){
|
||||||
health = read.f();
|
health = read.f();
|
||||||
rotation = read.b();
|
byte rot = read.b();
|
||||||
team = Team.get(read.b());
|
team = Team.get(read.b());
|
||||||
if(items != null) items.read(read);
|
|
||||||
if(power != null) power.read(read);
|
rotation = rot & 0b01111111;
|
||||||
if(liquids != null) liquids.read(read);
|
boolean legacy = true;
|
||||||
if(cons != null) cons.read(read);
|
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){
|
public void writeAll(Writes write){
|
||||||
@@ -410,7 +419,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
int trns = block.size/2 + 1;
|
int trns = block.size/2 + 1;
|
||||||
Tile next = tile.getNearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns);
|
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);
|
next.build.handlePayload(base(), todump);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -431,7 +440,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
for(int i = 0; i < proximity.size; i++){
|
for(int i = 0; i < proximity.size; i++){
|
||||||
Building other = proximity.get((i + dump) % proximity.size);
|
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);
|
other.handlePayload(base(), todump);
|
||||||
incrementDump(proximity.size);
|
incrementDump(proximity.size);
|
||||||
return true;
|
return true;
|
||||||
@@ -510,34 +519,31 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
|
|
||||||
next = next.getLiquidDestination(base(), liquid);
|
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)){
|
if(flow > 0f && ofract <= fract && next.acceptLiquid(base(), liquid, flow)){
|
||||||
float ofract = next.liquids().get(liquid) / next.block.liquidCapacity;
|
next.handleLiquid(base(), liquid, flow);
|
||||||
float fract = liquids.get(liquid) / block.liquidCapacity * block.liquidPressure;
|
liquids.remove(liquid, flow);
|
||||||
float flow = Math.min(Mathf.clamp((fract - ofract) * (1f)) * (block.liquidCapacity), liquids.get(liquid));
|
return flow;
|
||||||
flow = Math.min(flow, next.block.liquidCapacity - next.liquids().get(liquid) - 0.001f);
|
}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)){
|
Liquid other = next.liquids.current();
|
||||||
next.handleLiquid(base(), liquid, flow);
|
if((other.flammability > 0.3f && liquid.temperature > 0.7f) || (liquid.flammability > 0.3f && other.temperature > 0.7f)){
|
||||||
liquids.remove(liquid, flow);
|
damage(1 * Time.delta);
|
||||||
return flow;
|
next.damage(1 * Time.delta);
|
||||||
}else if(ofract > 0.1f && fract > 0.1f){
|
if(Mathf.chance(0.1 * Time.delta)){
|
||||||
//TODO these are incorrect effect positions
|
Fx.fire.at(fx, fy);
|
||||||
float fx = (x + next.x) / 2f, fy = (y + next.y) / 2f;
|
}
|
||||||
|
}else if((liquid.temperature > 0.7f && other.temperature < 0.55f) || (other.temperature > 0.7f && liquid.temperature < 0.55f)){
|
||||||
Liquid other = next.liquids().current();
|
liquids.remove(liquid, Math.min(liquids.get(liquid), 0.7f * Time.delta));
|
||||||
if((other.flammability > 0.3f && liquid.temperature > 0.7f) || (liquid.flammability > 0.3f && other.temperature > 0.7f)){
|
if(Mathf.chance(0.2f * Time.delta)){
|
||||||
damage(1 * Time.delta);
|
Fx.steam.at(fx, fy);
|
||||||
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++){
|
for(int i = 0; i < proximity.size; i++){
|
||||||
incrementDump(proximity.size);
|
incrementDump(proximity.size);
|
||||||
Building other = proximity.get((i + dump) % 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);
|
other.handleItem(base(), item);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -586,7 +592,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
for(int i = 0; i < proximity.size; i++){
|
for(int i = 0; i < proximity.size; i++){
|
||||||
incrementDump(proximity.size);
|
incrementDump(proximity.size);
|
||||||
Building other = proximity.get((i + dump) % 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);
|
other.handleItem(base(), item);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -619,7 +625,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
for(int ii = 0; ii < content.items().size; ii++){
|
for(int ii = 0; ii < content.items().size; ii++){
|
||||||
Item item = content.item(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);
|
other.handleItem(base(), item);
|
||||||
items.remove(item, 1);
|
items.remove(item, 1);
|
||||||
incrementDump(proximity.size);
|
incrementDump(proximity.size);
|
||||||
@@ -627,7 +633,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}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);
|
other.handleItem(base(), todump);
|
||||||
items.remove(todump, 1);
|
items.remove(todump, 1);
|
||||||
incrementDump(proximity.size);
|
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. */
|
/** Try offloading an item to a nearby container in its facing direction. Returns true if success. */
|
||||||
public boolean moveForward(Item item){
|
public boolean moveForward(Item item){
|
||||||
Building other = front();
|
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);
|
other.handleItem(base(), item);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -887,7 +893,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
power += this.power.status * block.consumes.getPower().capacity;
|
power += this.power.status * block.consumes.getPower().capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(block.hasLiquids){
|
if(block.hasLiquids && state.rules.damageExplosions){
|
||||||
|
|
||||||
liquids.each((liquid, amount) -> {
|
liquids.each((liquid, amount) -> {
|
||||||
float splash = Mathf.clamp(amount / 4f, 0f, 10f);
|
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){
|
if(!floor().solid && !floor().isLiquid){
|
||||||
Effect.rubble(x, y, block.size);
|
Effect.rubble(x, y, block.size);
|
||||||
}
|
}
|
||||||
@@ -960,7 +967,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
table.row();
|
table.row();
|
||||||
table.table(this::displayConsumption).growX();
|
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){
|
if(displayFlow){
|
||||||
String ps = " " + StatUnit.perSecond.localized();
|
String ps = " " + StatUnit.perSecond.localized();
|
||||||
@@ -998,9 +1005,21 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
if(liquids != null){
|
if(liquids != null){
|
||||||
table.row();
|
table.row();
|
||||||
table.table(l -> {
|
table.table(l -> {
|
||||||
l.left();
|
boolean[] had = {false};
|
||||||
l.image(() -> liquids.current().icon(Cicon.small)).padRight(3f);
|
|
||||||
l.label(() -> liquids.getFlowRate() < 0 ? "..." : Strings.fixed(liquids.getFlowRate(), 2) + ps).color(Color.lightGray);
|
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();
|
}).left();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
|
|||||||
Object data;
|
Object data;
|
||||||
BulletType type;
|
BulletType type;
|
||||||
float damage;
|
float damage;
|
||||||
|
float fdata;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getCollisions(Cons<QuadTree> consumer){
|
public void getCollisions(Cons<QuadTree> consumer){
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
@EntityDef(value = {Firec.class}, pooled = true)
|
@EntityDef(value = {Firec.class}, pooled = true)
|
||||||
@Component(base = 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;
|
private static final float spreadChance = 0.05f, fireballChance = 0.07f;
|
||||||
|
|
||||||
@Import float time, lifetime, x, y;
|
@Import float time, lifetime, x, y;
|
||||||
|
|
||||||
Tile tile;
|
Tile tile;
|
||||||
private Block block;
|
private transient Block block;
|
||||||
private float baseFlammability = -1, puddleFlammability;
|
private transient float baseFlammability = -1, puddleFlammability;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
@@ -99,4 +99,9 @@ abstract class FireComp implements Timedc, Posc, Firec{
|
|||||||
public void afterRead(){
|
public void afterRead(){
|
||||||
Fires.register(base());
|
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{
|
abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
|
||||||
private static final Vec2 tmp1 = new Vec2(), tmp2 = new Vec2();
|
private static final Vec2 tmp1 = new Vec2(), tmp2 = new Vec2();
|
||||||
|
|
||||||
@Import float x, y;
|
@Import float x, y, speedMultiplier;
|
||||||
@Import Vec2 vel;
|
@Import Vec2 vel;
|
||||||
|
|
||||||
@SyncLocal float elevation;
|
@SyncLocal float elevation;
|
||||||
@@ -56,7 +56,7 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
|
|||||||
|
|
||||||
float floorSpeedMultiplier(){
|
float floorSpeedMultiplier(){
|
||||||
Floor on = isFlying() || hovering ? Blocks.air.asFloor() : floorOn();
|
Floor on = isFlying() || hovering ? Blocks.air.asFloor() : floorOn();
|
||||||
return on.speedMultiplier;
|
return on.speedMultiplier * speedMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
|
|||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
if(Mathf.dst(deltaX(), deltaY()) > 0.001f){
|
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;
|
float rot = baseRotation;
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc{
|
|||||||
Building tile = payload.entity;
|
Building tile = payload.entity;
|
||||||
int tx = Vars.world.toTile(x - tile.block().offset), ty = Vars.world.toTile(y - tile.block().offset);
|
int tx = Vars.world.toTile(x - tile.block().offset), ty = Vars.world.toTile(y - tile.block().offset);
|
||||||
Tile on = Vars.world.tile(tx, ty);
|
Tile on = Vars.world.tile(tx, ty);
|
||||||
if(on != null && Build.validPlace(tile.block(), tile.team(), tx, ty, tile.rotation)){
|
if(on != null && Build.validPlace(tile.block(), tile.team, tx, ty, tile.rotation)){
|
||||||
int rot = (int)((rotation + 45f) / 90f) % 4;
|
int rot = (int)((rotation + 45f) / 90f) % 4;
|
||||||
payload.place(on, rot);
|
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();
|
return tile == null || tile.block() != Blocks.air ? (Floor)Blocks.air : tile.floor();
|
||||||
}
|
}
|
||||||
|
|
||||||
Block blockOn(){
|
Block blockOn(){
|
||||||
Tile tile = tileOn();
|
Tile tile = tileOn();
|
||||||
return tile == null ? Blocks.air : tile.block();
|
return tile == null ? Blocks.air : tile.block();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean onSolid(){
|
||||||
|
Tile tile = tileOn();
|
||||||
|
return tile != null && tile.solid();
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable Tile tileOn(){
|
@Nullable Tile tileOn(){
|
||||||
return world.tileWorld(x, y);
|
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 float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health;
|
||||||
@Import boolean dead;
|
@Import boolean dead;
|
||||||
@Import Team team;
|
@Import Team team;
|
||||||
|
@Import int id;
|
||||||
|
|
||||||
private UnitController controller;
|
private UnitController controller;
|
||||||
private UnitType type;
|
private UnitType type;
|
||||||
@@ -223,7 +224,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
|
|
||||||
//apply knockback based on spawns
|
//apply knockback based on spawns
|
||||||
if(team != state.rules.waveTeam){
|
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()){
|
for(Tile spawn : spawner.getSpawns()){
|
||||||
if(within(spawn.worldx(), spawn.worldy(), relativeSize)){
|
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));
|
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);
|
damageContinuous(floor.damageTaken);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!net.client() && tile.solid()){
|
if(tile.solid()){
|
||||||
if(type.canBoost){
|
if(type.canBoost){
|
||||||
elevation = 1f;
|
elevation = 1f;
|
||||||
}else{
|
}else if(!net.client()){
|
||||||
kill();
|
kill();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -314,7 +315,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
public void destroy(){
|
public void destroy(){
|
||||||
float explosiveness = 2f + item().explosiveness * stack().amount;
|
float explosiveness = 2f + item().explosiveness * stack().amount;
|
||||||
float flammability = item().flammability * 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;
|
float shake = hitSize / 3f;
|
||||||
|
|
||||||
@@ -389,6 +390,6 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
if(dead || net.client()) return;
|
if(dead || net.client()) return;
|
||||||
|
|
||||||
//deaths are synced; this calls killed()
|
//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.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import mindustry.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
@@ -33,6 +35,10 @@ public class AIController implements UnitController{
|
|||||||
updateMovement();
|
updateMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected UnitCommand command(){
|
||||||
|
return unit.team.data().command;
|
||||||
|
}
|
||||||
|
|
||||||
protected void updateMovement(){
|
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){
|
protected void circle(Position target, float circleLength){
|
||||||
circle(target, circleLength, unit.type().speed);
|
circle(target, circleLength, unit.type().speed);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package mindustry.entities.units;
|
|||||||
import arc.*;
|
import arc.*;
|
||||||
|
|
||||||
public enum UnitCommand{
|
public enum UnitCommand{
|
||||||
attack, retreat, rally, idle;
|
attack, rally, idle;
|
||||||
|
|
||||||
private final String localized;
|
private final String localized;
|
||||||
public static final UnitCommand[] all = values();
|
public static final UnitCommand[] all = values();
|
||||||
|
|||||||
@@ -30,7 +30,12 @@ public class EventType{
|
|||||||
openWiki,
|
openWiki,
|
||||||
teamCoreDamage,
|
teamCoreDamage,
|
||||||
socketConfigChanged,
|
socketConfigChanged,
|
||||||
update
|
update,
|
||||||
|
draw,
|
||||||
|
preDraw,
|
||||||
|
postDraw,
|
||||||
|
uiDrawBegin,
|
||||||
|
uiDrawEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class WinEvent{}
|
public static class WinEvent{}
|
||||||
@@ -77,7 +82,6 @@ public class EventType{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class CommandIssueEvent{
|
public static class CommandIssueEvent{
|
||||||
public final Building tile;
|
public final Building tile;
|
||||||
public final UnitCommand command;
|
public final UnitCommand command;
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ public class Rules{
|
|||||||
public boolean canGameOver = true;
|
public boolean canGameOver = true;
|
||||||
/** Whether reactors can explode and damage other blocks. */
|
/** Whether reactors can explode and damage other blocks. */
|
||||||
public boolean reactorExplosions = true;
|
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. */
|
/** Whether units use and require ammo. */
|
||||||
public boolean unitAmmo = false;
|
public boolean unitAmmo = false;
|
||||||
/** How fast unit pads build units. */
|
/** How fast unit pads build units. */
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ public class Teams{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void registerCore(CoreBuild core){
|
public void registerCore(CoreBuild core){
|
||||||
TeamData data = get(core.team());
|
TeamData data = get(core.team);
|
||||||
//add core if not present
|
//add core if not present
|
||||||
if(!data.cores.contains(core)){
|
if(!data.cores.contains(core)){
|
||||||
data.cores.add(core);
|
data.cores.add(core);
|
||||||
@@ -117,7 +117,7 @@ public class Teams{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void unregisterCore(CoreBuild entity){
|
public void unregisterCore(CoreBuild entity){
|
||||||
TeamData data = get(entity.team());
|
TeamData data = get(entity.team);
|
||||||
//remove core
|
//remove core
|
||||||
data.cores.remove(entity);
|
data.cores.remove(entity);
|
||||||
//unregister in active list
|
//unregister in active list
|
||||||
@@ -181,7 +181,7 @@ public class Teams{
|
|||||||
|
|
||||||
/** @return whether this team is controlled by the AI and builds bases. */
|
/** @return whether this team is controlled by the AI and builds bases. */
|
||||||
public boolean hasAI(){
|
public boolean hasAI(){
|
||||||
return state.rules.attackMode && team.rules().ai;
|
return team.rules().ai;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ public class Universe{
|
|||||||
sector.setSecondsPassed(sector.getSecondsPassed() + actuallyPassed);
|
sector.setSecondsPassed(sector.getSecondsPassed() + actuallyPassed);
|
||||||
|
|
||||||
//check if the sector has been attacked too many times...
|
//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
|
//fire event for losing the sector
|
||||||
Events.fire(new SectorLoseEvent(sector));
|
Events.fire(new SectorLoseEvent(sector));
|
||||||
|
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ public class BlockRenderer implements Disposable{
|
|||||||
Draw.z(Layer.block);
|
Draw.z(Layer.block);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(entity.team() != player.team()){
|
if(entity.team != player.team()){
|
||||||
entity.drawTeam();
|
entity.drawTeam();
|
||||||
Draw.z(Layer.block);
|
Draw.z(Layer.block);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ public class Layer{
|
|||||||
|
|
||||||
public static final float
|
public static final float
|
||||||
|
|
||||||
|
//min layer
|
||||||
|
min = -11,
|
||||||
|
|
||||||
//background, which may be planets or an image or nothing at all
|
//background, which may be planets or an image or nothing at all
|
||||||
background = -10,
|
background = -10,
|
||||||
|
|
||||||
@@ -81,7 +84,10 @@ public class Layer{
|
|||||||
end = 200,
|
end = 200,
|
||||||
|
|
||||||
//things after pixelation - used for text
|
//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){
|
if(dst < state.rules.enemyCoreBuildRadius * 2.2f){
|
||||||
Draw.color(Color.darkGray);
|
Draw.color(Color.darkGray);
|
||||||
Lines.circle(core.x, core.y - 2, state.rules.enemyCoreBuildRadius);
|
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);
|
Lines.circle(core.x, core.y, state.rules.enemyCoreBuildRadius);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -132,23 +132,25 @@ public class OverlayRenderer{
|
|||||||
//draw selected block
|
//draw selected block
|
||||||
if(input.block == null && !Core.scene.hasMouse()){
|
if(input.block == null && !Core.scene.hasMouse()){
|
||||||
Vec2 vec = Core.input.mouseWorld(input.getMouseX(), input.getMouseY());
|
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()){
|
if(build != null && build.team == player.team()){
|
||||||
tile.drawSelect();
|
build.drawSelect();
|
||||||
if(!tile.enabled && tile.block.drawDisabled){
|
if(!build.enabled && build.block.drawDisabled){
|
||||||
tile.drawDisabled();
|
build.drawDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Core.input.keyDown(Binding.rotateplaced) && tile.block().rotate && tile.interactable(player.team())){
|
if(Core.input.keyDown(Binding.rotateplaced) && build.block().rotate && build.interactable(player.team())){
|
||||||
control.input.drawArrow(tile.block(), tile.tileX(), tile.tileY(), tile.rotation, true);
|
control.input.drawArrow(build.block(), build.tileX(), build.tileY(), build.rotation, true);
|
||||||
Draw.color(Pal.accent, 0.3f + Mathf.absin(4f, 0.2f));
|
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();
|
Draw.color();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.drawOverSelect();
|
||||||
|
|
||||||
//draw selection overlay when dropping item
|
//draw selection overlay when dropping item
|
||||||
if(input.isDroppingItem()){
|
if(input.isDroppingItem()){
|
||||||
Vec2 v = Core.input.mouseWorld(input.getMouseX(), input.getMouseY());
|
Vec2 v = Core.input.mouseWorld(input.getMouseX(), input.getMouseY());
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ public class Pal{
|
|||||||
command = Color.valueOf("eab678"),
|
command = Color.valueOf("eab678"),
|
||||||
|
|
||||||
sap = Color.valueOf("665c9f"),
|
sap = Color.valueOf("665c9f"),
|
||||||
|
sapBullet = Color.valueOf("bf92f9"),
|
||||||
|
sapBulletBack = Color.valueOf("6d56bf"),
|
||||||
|
|
||||||
spore = Color.valueOf("7457ce"),
|
spore = Color.valueOf("7457ce"),
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import arc.input.*;
|
|||||||
public enum Binding implements KeyBind{
|
public enum Binding implements KeyBind{
|
||||||
move_x(new Axis(KeyCode.a, KeyCode.d), "general"),
|
move_x(new Axis(KeyCode.a, KeyCode.d), "general"),
|
||||||
move_y(new Axis(KeyCode.s, KeyCode.w)),
|
move_y(new Axis(KeyCode.s, KeyCode.w)),
|
||||||
mouse_move(KeyCode.mouseForward),
|
mouse_move(KeyCode.mouseBack),
|
||||||
|
pan(KeyCode.mouseForward),
|
||||||
|
|
||||||
boost(KeyCode.shiftLeft),
|
boost(KeyCode.shiftLeft),
|
||||||
control(KeyCode.controlLeft),
|
control(KeyCode.controlLeft),
|
||||||
|
|||||||
@@ -27,24 +27,35 @@ import static mindustry.Vars.*;
|
|||||||
import static mindustry.input.PlaceMode.*;
|
import static mindustry.input.PlaceMode.*;
|
||||||
|
|
||||||
public class DesktopInput extends InputHandler{
|
public class DesktopInput extends InputHandler{
|
||||||
private Vec2 movement = new Vec2();
|
public Vec2 movement = new Vec2();
|
||||||
/** Current cursor type. */
|
/** Current cursor type. */
|
||||||
private Cursor cursorType = SystemCursor.arrow;
|
public Cursor cursorType = SystemCursor.arrow;
|
||||||
/** Position where the player started dragging a line. */
|
/** Position where the player started dragging a line. */
|
||||||
private int selectX, selectY, schemX, schemY;
|
public int selectX, selectY, schemX, schemY;
|
||||||
/** Last known line positions.*/
|
/** Last known line positions.*/
|
||||||
private int lastLineX, lastLineY, schematicX, schematicY;
|
public int lastLineX, lastLineY, schematicX, schematicY;
|
||||||
/** Whether selecting mode is active. */
|
/** Whether selecting mode is active. */
|
||||||
private PlaceMode mode;
|
public PlaceMode mode;
|
||||||
/** Animation scale for line. */
|
/** Animation scale for line. */
|
||||||
private float selectScale;
|
public float selectScale;
|
||||||
/** Selected build request for movement. */
|
/** Selected build request for movement. */
|
||||||
private @Nullable BuildPlan sreq;
|
public @Nullable BuildPlan sreq;
|
||||||
/** Whether player is currently deleting removal requests. */
|
/** 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
|
@Override
|
||||||
public void buildUI(Group group){
|
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 -> {
|
group.fill(t -> {
|
||||||
t.bottom();
|
t.bottom();
|
||||||
t.visible(() -> {
|
t.visible(() -> {
|
||||||
@@ -77,15 +88,6 @@ public class DesktopInput extends InputHandler{
|
|||||||
});
|
});
|
||||||
}).margin(6f);
|
}).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
|
@Override
|
||||||
@@ -132,14 +134,12 @@ public class DesktopInput extends InputHandler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//draw schematic requests
|
//draw schematic requests
|
||||||
for(BuildPlan request : selectRequests){
|
selectRequests.each(req -> {
|
||||||
request.animScale = 1f;
|
req.animScale = 1f;
|
||||||
drawRequest(request);
|
drawRequest(req);
|
||||||
}
|
});
|
||||||
|
|
||||||
for(BuildPlan request : selectRequests){
|
selectRequests.each(this::drawOverRequest);
|
||||||
drawOverRequest(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(player.isBuilder()){
|
if(player.isBuilder()){
|
||||||
//draw things that may be placed soon
|
//draw things that may be placed soon
|
||||||
@@ -180,22 +180,35 @@ public class DesktopInput extends InputHandler{
|
|||||||
ui.listfrag.toggle();
|
ui.listfrag.toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO awful UI state checking code
|
boolean panCam = false;
|
||||||
if((player.dead() || state.isPaused()) && !ui.chatfrag.shown()){
|
float camSpeed = !Core.input.keyDown(Binding.boost) ? panSpeed : panBoostSpeed;
|
||||||
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));
|
|
||||||
|
|
||||||
if(Core.input.keyDown(Binding.mouse_move)){
|
if(input.keyDown(Binding.pan)){
|
||||||
Core.camera.position.x += Mathf.clamp((Core.input.mouseX() - Core.graphics.getWidth() / 2f) * 0.005f, -1, 1) * camSpeed;
|
panCam = true;
|
||||||
Core.camera.position.y += Mathf.clamp((Core.input.mouseY() - Core.graphics.getHeight() / 2f) * 0.005f, -1, 1) * camSpeed;
|
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);
|
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();
|
shouldShoot = !scene.hasMouse();
|
||||||
|
|
||||||
if(!scene.hasMouse()){
|
if(!scene.hasMouse()){
|
||||||
@@ -327,22 +340,24 @@ public class DesktopInput extends InputHandler{
|
|||||||
table.row();
|
table.row();
|
||||||
table.left().margin(0f).defaults().size(48f).left();
|
table.left().margin(0f).defaults().size(48f).left();
|
||||||
|
|
||||||
|
//TODO localize these
|
||||||
|
|
||||||
table.button(Icon.paste, Styles.clearPartiali, () -> {
|
table.button(Icon.paste, Styles.clearPartiali, () -> {
|
||||||
ui.schematics.show();
|
ui.schematics.show();
|
||||||
}).tooltip("Schematics");
|
}).tooltip("@schematics");
|
||||||
|
|
||||||
table.button(Icon.tree, Styles.clearPartiali, () -> {
|
table.button(Icon.tree, Styles.clearPartiali, () -> {
|
||||||
ui.research.show();
|
ui.research.show();
|
||||||
}).visible(() -> state.isCampaign()).tooltip("Research");
|
}).visible(() -> state.isCampaign()).tooltip("@research");
|
||||||
|
|
||||||
table.button(Icon.map, Styles.clearPartiali, () -> {
|
table.button(Icon.map, Styles.clearPartiali, () -> {
|
||||||
ui.planet.show();
|
ui.planet.show();
|
||||||
}).visible(() -> state.isCampaign()).tooltip("Planet Map");
|
}).visible(() -> state.isCampaign()).tooltip("@planetmap");
|
||||||
|
|
||||||
table.button(Icon.up, Styles.clearPartiali, () -> {
|
table.button(Icon.up, Styles.clearPartiali, () -> {
|
||||||
ui.planet.show(state.getSector(), player.team().core());
|
ui.planet.show(state.getSector(), player.team().core());
|
||||||
}).visible(() -> state.isCampaign())
|
}).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(){
|
void pollInput(){
|
||||||
@@ -555,6 +570,8 @@ public class DesktopInput extends InputHandler{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateState(){
|
public void updateState(){
|
||||||
|
super.updateState();
|
||||||
|
|
||||||
if(state.isMenu()){
|
if(state.isMenu()){
|
||||||
droppingItem = false;
|
droppingItem = false;
|
||||||
mode = none;
|
mode = none;
|
||||||
@@ -574,7 +591,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
//limit speed to minimum formation speed to preserve formation
|
//limit speed to minimum formation speed to preserve formation
|
||||||
if(unit instanceof Commanderc && ((Commanderc)unit).isCommanding()){
|
if(unit instanceof Commanderc && ((Commanderc)unit).isCommanding()){
|
||||||
//add a tiny multiplier to let units catch up just in case
|
//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;
|
float speed = baseSpeed * Mathf.lerp(1f, unit.type().canBoost ? unit.type().boostMultiplier : 1f, unit.elevation) * strafePenalty;
|
||||||
|
|||||||
@@ -62,13 +62,13 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
public boolean isBuilding = true, buildWasAutoPaused = false;
|
public boolean isBuilding = true, buildWasAutoPaused = false;
|
||||||
public @Nullable UnitType controlledType;
|
public @Nullable UnitType controlledType;
|
||||||
|
|
||||||
protected @Nullable Schematic lastSchematic;
|
public @Nullable Schematic lastSchematic;
|
||||||
protected GestureDetector detector;
|
public GestureDetector detector;
|
||||||
protected PlaceLine line = new PlaceLine();
|
public PlaceLine line = new PlaceLine();
|
||||||
protected BuildPlan resultreq;
|
public BuildPlan resultreq;
|
||||||
protected BuildPlan brequest = new BuildPlan();
|
public BuildPlan brequest = new BuildPlan();
|
||||||
protected Seq<BuildPlan> lineRequests = new Seq<>();
|
public Seq<BuildPlan> lineRequests = new Seq<>();
|
||||||
protected Seq<BuildPlan> selectRequests = new Seq<>();
|
public Seq<BuildPlan> selectRequests = new Seq<>();
|
||||||
|
|
||||||
//methods to override
|
//methods to override
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
Unit unit = player.unit();
|
Unit unit = player.unit();
|
||||||
Payloadc pay = (Payloadc)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)){
|
&& unit.within(tile, tilesize * tile.block.size * 1.2f)){
|
||||||
//pick up block directly
|
//pick up block directly
|
||||||
if(tile.block().buildVisibility != BuildVisibility.hidden && tile.block().size <= 2 && tile.canPickup()){
|
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.clearUnit();
|
||||||
player.deathTimer = 61f;
|
player.deathTimer = 61f;
|
||||||
|
((CoreBuild)((BlockUnitc)unit).tile()).requestSpawn(player);
|
||||||
|
|
||||||
}else if(unit == null){ //just clear the unit (is this used?)
|
}else if(unit == null){ //just clear the unit (is this used?)
|
||||||
player.clearUnit();
|
player.clearUnit();
|
||||||
//make sure it's AI controlled, so players can't overwrite each other
|
//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(){
|
public void updateState(){
|
||||||
|
if(state.isMenu()){
|
||||||
|
controlledType = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawBottom(){
|
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){
|
public void drawSelected(int x, int y, Block block, Color color){
|
||||||
Drawf.selected(x, y, block, color);
|
Drawf.selected(x, y, block, color);
|
||||||
}
|
}
|
||||||
@@ -538,11 +546,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
if(test.get(req)) return req;
|
if(test.get(req)) return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(BuildPlan req : selectRequests){
|
return selectRequests.find(test);
|
||||||
if(test.get(req)) return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void drawBreakSelection(int x1, int y1, int x2, int y2){
|
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);
|
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();
|
return ((ControlBlock)tile).unit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||