Merge branch 'master' of https://github.com/Anuken/Mindustry into v105

This commit is contained in:
Petr Gašparík
2020-09-21 10:05:24 +02:00
174 changed files with 16037 additions and 12418 deletions
@@ -77,7 +77,11 @@ public class EntityProcess extends BaseProcessor{
for(Smethod elem : component.methods()){
if(elem.is(Modifier.ABSTRACT) || elem.is(Modifier.NATIVE)) continue;
//get all statements in the method, store them
methodBlocks.put(elem.descString(), elem.tree().getBody().toString());
methodBlocks.put(elem.descString(), elem.tree().getBody().toString()
//replace all self() invocations with this
.replaceAll("this\\.<(.*)>self\\(\\)", "this")
.replaceAll("self\\(\\)", "this")
);
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 B

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 904 B

After

Width:  |  Height:  |  Size: 671 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 984 B

After

Width:  |  Height:  |  Size: 893 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

-1
View File
@@ -4,6 +4,5 @@
flattenPaths: true,
maxWidth: 4096,
maxHeight: 4096,
minHeight: 2048,
fast: true
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+13 -2
View File
@@ -20,7 +20,8 @@ gameover = Game Over
gameover.pvp = The[accent] {0}[] team is victorious!
highscore = [accent]New highscore!
copied = Copied.
indevpopup = [accent]v6[] is currently in [accent]alpha[].\n[lightgray]This means:[]\n[scarlet]- The campaign is completely unfinished[]\n- Content is missing\n - Most [scarlet]Unit AI[] does not work properly\n- Many units are unfinished\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[].
indev.popup = [accent]v6[] is currently in [accent]alpha[].\n[lightgray]This means:[]\n[scarlet]- The campaign is completely unfinished[]\n- Content is missing\n - Most [scarlet]Unit AI[] does not work properly\n- Many units are unfinished\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[].
indev.notready = This part of the game isn't ready yet
load.sound = Sounds
load.map = Maps
@@ -615,6 +616,8 @@ blocks.inaccuracy = Inaccuracy
blocks.shots = Shots
blocks.reload = Shots/Second
blocks.ammo = Ammo
blocks.shieldhealth = Shield Health
blocks.cooldowntime = Cooldown Time
bar.drilltierreq = Better Drill Required
bar.noresources = Missing Resources
@@ -662,6 +665,7 @@ unit.persecond = /sec
unit.perminute = /min
unit.timesspeed = x speed
unit.percent = %
unit.shieldhealth = shield health
unit.items = items
unit.thousands = k
unit.millions = mil
@@ -789,6 +793,9 @@ keybind.diagonal_placement.name = Diagonal Placement
keybind.pick.name = Pick Block
keybind.break_block.name = Break Block
keybind.deselect.name = Deselect
keybind.pickupCargo.name = Pickup Cargo
keybind.dropCargo.name = Drop Cargo
keybind.command.name = Command
keybind.shoot.name = Shoot
keybind.zoom.name = Zoom
keybind.menu.name = Menu
@@ -876,9 +883,11 @@ liquid.water.name = Water
liquid.slag.name = Slag
liquid.oil.name = Oil
liquid.cryofluid.name = Cryofluid
item.explosiveness = [lightgray]Explosiveness: {0}%
item.flammability = [lightgray]Flammability: {0}%
item.radioactivity = [lightgray]Radioactivity: {0}%
unit.health = [lightgray]Health: {0}
unit.speed = [lightgray]Speed: {0}
unit.weapon = [lightgray]Weapon: {0}
@@ -914,6 +923,8 @@ unit.mega.name = Mega
unit.risso.name = Risso
unit.minke.name = Minke
unit.bryde.name = Bryde
unit.sei.name = Sei
unit.omura.name = Omura
unit.alpha.name = Alpha
unit.beta.name = Beta
unit.gamma.name = Gamma
@@ -979,6 +990,7 @@ block.dune-wall.name = Dune Wall
block.pine.name = Pine
block.dirt.name = Dirt
block.dirt-wall.name = Dirt Wall
block.mud.name = Mud
block.white-tree-dead.name = White Tree Dead
block.white-tree.name = White Tree
block.spore-cluster.name = Spore Cluster
@@ -997,7 +1009,6 @@ block.dark-metal.name = Dark Metal
block.basalt.name = Basalt
block.hotrock.name = Hot Rock
block.magmarock.name = Magma Rock
block.cliffs.name = Cliffs
block.copper-wall.name = Copper Wall
block.copper-wall-large.name = Large Copper Wall
block.titanium-wall.name = Titanium Wall
+34 -27
View File
@@ -803,7 +803,7 @@ rules.title.unit = 유닛
rules.title.experimental = 실험적인 기능
rules.title.environment = 환경
rules.lighting = 조명
rules.ambientlight = 주변 조명
rules.ambientlight = 자연 조명
rules.solarpowermultiplier = 태양광 발전 배수
content.item.name = 자원
@@ -856,17 +856,20 @@ unit.crawler.name = 크롤러
unit.atrax.name = 아트락스
unit.spiroct.name = 스피록트
unit.arkyid.name = 아키드
unit.flare.name = 화염
unit.horizon.name = 수평선
unit.zenith.name = 천정
unit.antumbra.name = 그림자
unit.eclipse.name = 일식
unit.toxipod.name = 독소포드
unit.flare.name = 플레어
unit.horizon.name = 호라이즌
unit.zenith.name = 제니스
unit.antumbra.name = 안텀브라
unit.eclipse.name = 이클립스
unit.mono.name = 모노
unit.poly.name = 폴리
unit.mega.name = 메가
unit.risso.name = 리소
unit.minke.name = 민케
unit.bryde.name = 브리드
unit.sei.name = 세이
unit.omura.name = 오무라
unit.alpha.name = 알파
unit.beta.name = 베타
unit.gamma.name = 감마
@@ -877,21 +880,21 @@ block.sand-boulder.name = 사암
block.grass.name = 잔디
block.slag.name = 광재
block.salt.name = 소금
block.saltrocks.name = 소금 바위
block.salt-wall.name = 소금
block.pebbles.name = 조약돌
block.tendrils.name = 덩굴
block.sandrocks.name = 모래 바위
block.sand-wall.name = 모래
block.spore-pine.name = 포자 덮인 소나무
block.sporerocks.name = 포자 바위
block.rock.name =
block.snowrock.name = 눈덩이
block.spore-wall.name = 포자
block.boulder.name =
block.snow-boulder.name = 눈덩이
block.snow-pine.name = 눈 덮인 소나무
block.shale.name = 이판암
block.shale-boulder.name = 둥근 이판암
block.moss.name = 이끼
block.shrubs.name = 관목
block.spore-moss.name = 포자 이끼
block.shalerocks.name = 이판암 바위
block.shale-wall.name = 이판암
block.scrap-wall.name = 조각벽
block.scrap-wall-large.name = 대형 조각벽
block.scrap-wall-huge.name = 거대한 조각 벽
@@ -910,6 +913,7 @@ block.water.name = 물
block.tainted-water.name = 오염된 물
block.darksand-tainted-water.name = 오염된 젖은 검은 모래
block.tar.name = 석유
block.mud.name = 진흙
block.stone.name = 바위
block.sand.name = 모래
block.darksand.name = 검은 모래
@@ -919,13 +923,16 @@ block.craters.name = 구덩이
block.sand-water.name = 젖은 모래
block.darksand-water.name = 젖은 검은 모래
block.char.name =
block.holostone.name = 홀로스톤
block.dacite.name = 데이사이트
block.dacite-wall.name = 데이사이트 벽
block.ice-snow.name = 얼음눈
block.rocks.name =
block.icerocks.name = 얼음바위
block.snowrocks.name = 바위
block.dunerocks.name = 모래
block.stone-wall.name =
block.ice-wall.name = 얼음
block.snow-wall.name =
block.dune-wall.name = 모래
block.pine.name = 소나무
block.dirt.name =
block.dirt-wall.name = 흙 벽
block.white-tree-dead.name = 죽은 하얀나무
block.white-tree.name = 하얀 나무
block.spore-cluster.name = 포자낭
@@ -941,7 +948,7 @@ block.dark-panel-4.name = 어두운 패널 4
block.dark-panel-5.name = 어두운 패널 5
block.dark-panel-6.name = 어두운 패널 6
block.dark-metal.name = 어두운 금속제
block.ignarock.name = 얼은 바위
block.basalt.name = 현무암
block.hotrock.name = 뜨거운 바위
block.magmarock.name = 용암 바위
block.cliffs.name = 절벽
@@ -1011,7 +1018,7 @@ block.power-void.name = 방전장치
block.power-source.name = 전력 공급기
block.unloader.name = 언로더
block.vault.name = 창고
block.wave.name = 웨이브
block.wave.name = 파도
block.swarmer.name = 스워머
block.salvo.name = 살보
block.ripple.name = 립플
@@ -1019,7 +1026,7 @@ block.phase-conveyor.name = 메타 컨베이어
block.bridge-conveyor.name = 다리 컨베이어
block.plastanium-compressor.name = 플라스터늄 압축기
block.pyratite-mixer.name = 파이라타이트 혼합기
block.blast-mixer.name = 화합물 혼합기
block.blast-mixer.name = 폭발물 혼합기
block.solar-panel.name = 태양 전지판
block.solar-panel-large.name = 대형 태양 전지판
block.oil-extractor.name = 석유 추출기
@@ -1062,11 +1069,11 @@ block.additive-reconstructor.name = 첨가물 재구성기
block.multiplicative-reconstructor.name = 다중 재구성기
block.exponential-reconstructor.name = 지수 재구성기
block.tetrative-reconstructor.name = 정서 재구성기
block.payload-conveyor.name = 매스 컨베이어
block.payload-conveyor.name = 화물 컨베이어
block.payload-router.name = 화물 분배기
block.disassembler.name = 분해기
block.disassembler.name = 가속 분해기
block.silicon-crucible.name = 실리콘 도가니
block.large-overdrive-projector.name = 대형 과부하 프로젝터
block.overdrive-dome.name = 대형 과부하 프로젝터
team.blue.name = 파랑색 팀
team.crux.name = 빨강색 팀
team.sharded.name = 주황색 팀
@@ -1099,7 +1106,7 @@ tutorial.launch = 특정 웨이브에 도달하면 [accent]코어로 출격[]
item.copper.description = 가장 기본적인 건설 재료. 모든 유형의 블록에서 광범위하게 사용됩니다.
item.lead.description = 기본 초반 재료. 전자 및 액체 수송 블록에서 광범위하게 사용되는 자원입니다.
item.metaglass.description = 초강력 유리 화합물. 액체 분배 및 저장에 광범위하게 사용됩니다.
item.metaglass.description = 초강력 방탄 유리. 액체 분배 및 저장에 광범위하게 사용됩니다.
item.graphite.description = 탄약 및 전기 부품에 사용되는 무기질 탄소.
item.sand.description = 제련에서 합금 또는 플럭스에서 광범위하게 사용되는 일반적인 재료.
item.coal.description = 화석화된 식물 물질. 씨앗이 나오기 훨씬 전에 형성되었습니다. 연료 및 자원 생산에 광범위하게 사용됩니다.
@@ -1127,7 +1134,7 @@ block.plastanium-compressor.description = 석유와 티타늄으로 플라스터
block.phase-weaver.description = 방사성 토륨과 모래에서 메타를 합성합니다. 작동하려면 엄청난 양의 전력이 필요합니다.
block.alloy-smelter.description = 티타늄, 납, 실리콘, 구리를 결합하여 설금을 생산합니다.
block.cryofluidmixer.description = 물과 미세 티타늄 분말을 냉각수로 혼합합니다. 토륨 원자로 사용에 필수적입니다.
block.blast-mixer.description = 포자 클러스터를 파이라타이트와 분쇄하고 혼합하여 화합물을 만듭니다.
block.blast-mixer.description = 포자 클러스터를 파이라타이트와 분쇄하고 혼합하여 폭발물을 만듭니다.
block.pyratite-mixer.description = 석탄, 납, 모래를 가연성이 높은 파이라타이트로 만듭니다.
block.melter.description = 웨이브 포탑에서 추가 처리 또는 사용을 위해 고철을 광재로 녹입니다.
block.separator.description = 광재를 미네랄 성분으로 분리합니다. 그리고 냉각된 결과를 출력합니다.
@@ -1194,7 +1201,7 @@ block.combustion-generator.description = 석탄과 같은 가연성 물질을
block.thermal-generator.description = 열이 있는 곳에 설치하면 전력이 생성됩니다.
block.steam-generator.description = 고급 연소 발전기. 더 효율적이지만 증기를 생성하기 위해 물이 필요합니다.
block.differential-generator.description = 많은 양의 전력을 생성합니다. 냉각수와 불타는 파이라타이트의 온도 차이를 이용합니다.
block.rtg-generator.description = 간단하고 안정적인 발전기. 붕괴하는 방사성 화합물의 열을 이용하여 느린 속도로 전력을 생성합니다.
block.rtg-generator.description = 간단하고 안정적인 발전기. 붕괴하는 방사성 물의 열을 이용하여 느린 속도로 전력을 생성합니다.
block.solar-panel.description = 태양으로부터 소량의 전력을 생성합니다.
block.solar-panel-large.description = 표준 태양 전지판보다 훨씬 더 효율적인 버전.
block.thorium-reactor.description = 토륨으로부터 상당한 양의 전력을 생산합니다. 지속적인 냉각이 필요하며, 충분한 양의 냉각수가 공급되지 않으면 크게 폭발합니다. 전력 출력은 토륨의 양에 따라 달라집니다.
@@ -1228,5 +1235,5 @@ block.ripple.description = 매우 강력한 포병 포탑. 원거리에 있는
block.cyclone.description = 대공 및 대지 포탑. 근처 유닛에게 폭발성 덩어리를 발사합니다.
block.spectre.description = 거대한 이중 배럴 대포. 공중 및 지상 목표물에 큰 관통 철갑탄을 발사합니다.
block.meltdown.description = 거대한 레이저 대포. 근처의 적에게 지속적인 레이버 빔을 충전하여 발사합니다. 냉각수가 있어야 작동합니다.
block.repair-point.description = 주변에서 가장 가까운 유닛을 지속적으로 치료합니다.
block.repair-point.description = 주변에서 가장 가까운 유닛을 지속적으로 치료합니다.
block.segment.description = 날아오는 발사체를 요격합니다. 레이저는 목표 대상이 아닙니다.
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -20,7 +20,8 @@ gameover = Игра окончена
gameover.pvp = [accent]{0}[] команда победила!
highscore = [accent]Новый рекорд!
copied = Скопировано.
indevpopup = [accent]v6[] находится на стадии [accent]alpha[].\n[lightgray]Это означает следующее:[]\n- Отсутствие контента.\n- Большинство [scarlet]ИИ единиц[] не работает.\n- Множество единиц не готово.\n- Кампания не завершена.\n- Всё, что вы видите, может быть изменено или удалено.\n\nСообщайте о багах и вылетах на [accent]Github[].
indev.popup = [accent]v6[] находится на стадии [accent]alpha[].\n[lightgray]Это означает следующее:[]\n- Отсутствие контента.\n- Большинство [scarlet]ИИ единиц[] не работает.\n- Множество единиц не готово.\n- Кампания не завершена.\n- Всё, что вы видите, может быть изменено или удалено.\n\nСообщайте о багах и вылетах на [accent]Github[].
indev.notready = Эта часть игры ещё не готова
load.sound = Звуки
load.map = Карты
+2 -1
View File
@@ -20,7 +20,8 @@ gameover = Гра завершена
gameover.pvp = [accent]{0}[] команда перемогла!
highscore = [accent]Новий рекорд!
copied = Скопійовано.
indevpopup = Наразі [accent]6.0[] знаходиться у стадії [accent]альфа[].\n[lightgray]Це означає наступне:[]\n- Не вистачає наповнення гри;\n- Більшість [scarlet]ШІ бойових одиниць[] не працює належним чином;\n- Багато одиниць [scarlet]відсутні[] або незавершені;\n- Кампанія повністю не є завершеною;\n- Усе, що ви бачите, може змінитися або видалитися.\n\nПовідомляйте про вади або збої на [accent]Github[], а про помилки в перекладі в Discord.
indev.popup = Наразі [accent]6.0[] знаходиться у стадії [accent]альфа[].\n[lightgray]Це означає наступне:[]\n- Не вистачає наповнення гри;\n- Більшість [scarlet]ШІ бойових одиниць[] не працює належним чином;\n- Багато одиниць [scarlet]відсутні[] або незавершені;\n- Кампанія повністю не є завершеною;\n- Усе, що ви бачите, може змінитися або видалитися.\n\nПовідомляйте про вади або збої на [accent]Github[], а про помилки в перекладі в Discord.
indev.notready = Ця частина гри ще не готова
load.sound = Звуки
load.map = Мапи
+1
View File
@@ -90,3 +90,4 @@ DeltaNedas
GioIacca9
SnakkiZXZ
sk7725
ThePlayerA
+4
View File
@@ -311,3 +311,7 @@
63433=dacite-wall|block-dacite-wall-medium
63432=dacite-boulder|block-dacite-boulder-medium
63431=large-logic-display|block-large-logic-display-medium
63430=omura|unit-omura-medium
63429=mud|block-mud-medium
63428=sei|unit-sei-medium
63427=quad|unit-quad-medium
Binary file not shown.
+1
View File
@@ -74,6 +74,7 @@ importPackage(Packages.mindustry.gen)
importPackage(Packages.mindustry.graphics)
importPackage(Packages.mindustry.graphics.g3d)
importPackage(Packages.mindustry.input)
importPackage(Packages.mindustry.io)
importPackage(Packages.mindustry.logic)
importPackage(Packages.mindustry.maps)
importPackage(Packages.mindustry.maps.filters)
+29
View File
@@ -0,0 +1,29 @@
#define HIGHP
#define NSCALE 180.0 / 2.0
uniform sampler2D u_texture;
uniform sampler2D u_noise;
uniform vec2 u_campos;
uniform vec2 u_resolution;
uniform float u_time;
varying vec2 v_texCoords;
void main(){
vec2 c = v_texCoords.xy;
vec2 coords = vec2(c.x * u_resolution.x + u_campos.x, c.y * u_resolution.y + u_campos.y);
float btime = u_time / 70000.0;
float noise = sin((texture2D(u_noise, (coords) / NSCALE + vec2(btime) * vec2(-0.9, 0.8)).r + texture2D(u_noise, (coords) / NSCALE + vec2(abs(sin(btime)) * 1.1) * vec2(-0.8, -1.0)).r) / 2.0);
vec4 color = texture2D(u_texture, c);
if(noise > 0.54 && noise < 0.68){
color.rgb *= 1.4;
}else if(!(noise > 0.40 && noise < 0.54)){
color.rgb *= 1.2;
}
gl_FragColor = color;
}
+4 -6
View File
@@ -22,12 +22,10 @@ void main(){
float noise = (texture2D(u_noise, (coords) / NSCALE + vec2(btime) * vec2(-0.9, 0.8)).r + texture2D(u_noise, (coords) / NSCALE + vec2(btime * 1.1) * vec2(0.8, -1.0)).r) / 2.0;
vec4 color = texture2D(u_texture, c);
if(color.a > 0.1){
if(noise > 0.6){
color.rgb = S2;
}else if (noise > 0.54){
color.rgb = S1;
}
if(noise > 0.6){
color.rgb = S2;
}else if (noise > 0.54){
color.rgb = S1;
}
gl_FragColor = color;
+1 -1
View File
@@ -20,7 +20,7 @@ void main(){
vec4 color = texture2D(u_texture, c);
if(!(noise > 0.54 && noise < 0.58)){
color.rgb *= 0.6;
color.rgb *= vec3(0.6, 0.6, 0.7);
}
gl_FragColor = color;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 811 B

After

Width:  |  Height:  |  Size: 810 B

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

Before

Width:  |  Height:  |  Size: 647 KiB

After

Width:  |  Height:  |  Size: 639 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 958 KiB

After

Width:  |  Height:  |  Size: 760 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 KiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 KiB

After

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

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

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 KiB

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 KiB

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

+7 -38
View File
@@ -33,7 +33,7 @@ public class BlockIndexer{
/** Maps each team ID to a quarant. A quadrant is a grid of bits, where each bit is set if and only if there is a block of that team in that quadrant. */
private GridBits[] structQuadrants;
/** Stores all damaged tile entities by team. */
private BuildingArray[] damagedTiles = new BuildingArray[Team.all.length];
private ObjectSet<Building>[] damagedTiles = new ObjectSet[Team.all.length];
/** All ores available on this map. */
private ObjectSet<Item> allOres = new ObjectSet<>();
/** Stores teams that are present here as tiles. */
@@ -70,7 +70,7 @@ public class BlockIndexer{
Events.on(WorldLoadEvent.class, event -> {
scanOres.clear();
scanOres.addAll(Item.getAllOres());
damagedTiles = new BuildingArray[Team.all.length];
damagedTiles = new ObjectSet[Team.all.length];
flagMap = new TileArray[Team.all.length][BlockFlag.all.length];
unitCaps = new int[Team.all.length];
activeTeams = new Seq<>(Team.class);
@@ -139,14 +139,14 @@ public class BlockIndexer{
}
/** Returns all damaged tiles by team. */
public BuildingArray getDamaged(Team team){
returnArray.clear();
public ObjectSet<Building> getDamaged(Team team){
breturnArray.clear();
if(damagedTiles[team.id] == null){
damagedTiles[team.id] = new BuildingArray();
damagedTiles[team.id] = new ObjectSet<>();
}
BuildingArray set = damagedTiles[team.id];
ObjectSet<Building> set = damagedTiles[team.id];
for(Building build : set){
if((!build.isValid() || build.team != team || !build.damaged()) || build.block instanceof ConstructBlock){
breturnArray.add(build);
@@ -214,7 +214,7 @@ public class BlockIndexer{
public void notifyTileDamaged(Building entity){
if(damagedTiles[entity.team.id] == null){
damagedTiles[entity.team.id] = new BuildingArray();
damagedTiles[entity.team.id] = new ObjectSet<Building>();
}
damagedTiles[entity.team.id].add(entity);
@@ -476,35 +476,4 @@ public class BlockIndexer{
return tiles.iterator();
}
}
//TODO copy-pasted code, generics would be nice here
public static class BuildingArray implements Iterable<Building>{
private Seq<Building> tiles = new Seq<>(false, 16);
private IntSet contained = new IntSet();
public void add(Building tile){
if(contained.add(tile.pos())){
tiles.add(tile);
}
}
public void remove(Building tile){
if(contained.remove(tile.pos())){
tiles.remove(tile);
}
}
public int size(){
return tiles.size;
}
public Building first(){
return tiles.first();
}
@Override
public Iterator<Building> iterator(){
return tiles.iterator();
}
}
}
+1 -1
View File
@@ -59,7 +59,7 @@ public class Pathfinder implements Runnable{
Flowfield[][][] cache;
/** tile data, see PathTileStruct */
int[][] tiles;
int[][] tiles = new int[0][0];
/** unordered array of path data for iteration only. DO NOT iterate or access this in the main thread. */
Seq<Flowfield> threadList = new Seq<>(), mainList = new Seq<>();
/** handles task scheduling on the update thread. */
@@ -5,20 +5,14 @@ import arc.math.geom.*;
import mindustry.ai.formations.*;
public class CircleFormation extends FormationPattern{
/** The radius of one member. This is needed to determine how close we can pack a given number of members around circle. */
public float memberRadius;
/** Angle offset. */
public float angleOffset = 0;
public CircleFormation(float memberRadius){
this.memberRadius = memberRadius;
}
@Override
public Vec3 calculateSlotLocation(Vec3 outLocation, int slotNumber){
if(slots > 1){
float angle = (360f * slotNumber) / slots;
float radius = memberRadius / (float)Math.sin(180f / slots * Mathf.degRad);
float radius = spacing / (float)Math.sin(180f / slots * Mathf.degRad);
outLocation.set(Angles.trnsx(angle, radius), Angles.trnsy(angle, radius), angle);
}else{
outLocation.set(0, 0, 360f * slotNumber);
+1 -2
View File
@@ -1,7 +1,6 @@
package mindustry.ai.types;
import arc.math.*;
import arc.util.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.world.meta.*;
@@ -59,7 +58,7 @@ public class FlyingAI extends AIController{
vec.setAngle(Mathf.slerpDelta(unit.vel().angle(), vec.angle(), 0.6f));
}
vec.setLength(unit.type().speed * Time.delta);
vec.setLength(unit.type().speed);
unit.moveAt(vec);
}
+19 -18
View File
@@ -2,10 +2,10 @@ package mindustry.ai.types;
import arc.math.geom.*;
import arc.util.ArcAnnotate.*;
import mindustry.*;
import mindustry.ai.formations.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.type.*;
public class FormationAI extends AIController implements FormationMember{
public Unit leader;
@@ -25,39 +25,40 @@ public class FormationAI extends AIController implements FormationMember{
@Override
public void updateUnit(){
UnitType type = unit.type();
if(leader.dead){
unit.resetController();
return;
}
unit.controlWeapons(leader.isRotate(), leader.isShooting);
unit.controlWeapons(true, leader.isShooting);
// unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed));
if(leader.isShooting){
unit.aimLook(leader.aimX(), leader.aimY());
}else{
if(!leader.moving() || !unit.type().rotateShooting){
if(unit.moving()){
unit.lookAt(unit.vel.angle());
}
}else{
unit.lookAt(leader.rotation);
}
unit.aim(leader.aimX(), leader.aimY());
if(unit.type().rotateShooting){
unit.lookAt(leader.aimX(), leader.aimY());
}else if(unit.moving()){
unit.lookAt(unit.vel.angle());
}
Vec2 realtarget = vec.set(target);
if(unit.isGrounded() && Vars.world.raycast(unit.tileX(), unit.tileY(), leader.tileX(), leader.tileY(), Vars.world::solid)){
//TODO pathfind
//realtarget.set(Vars.pathfinder.getTargetTile(unit.tileOn(), unit.team, leader));
}
float margin = 3f;
unit.moveAt(realtarget.sub(unit).limit(unit.type().speed));
if(unit.dst(realtarget) <= margin){
unit.vel.approachDelta(Vec2.ZERO, type.speed * type.accel / 2f);
}else{
unit.moveAt(realtarget.sub(unit).limit(type.speed));
}
}
@Override
public void removed(Unit unit){
if(formation != null){
formation.removeMember(this);
unit.resetController();
}
}
@@ -67,7 +68,7 @@ public class FormationAI extends AIController implements FormationMember{
//TODO return formation size
//eturn ((Commanderc)unit).formation().
}
return unit.hitSize * 1.7f;
return unit.hitSize * 1f;
}
@Override
+2 -2
View File
@@ -49,10 +49,10 @@ public class GroundAI extends AIController{
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f);
}
if(!Units.invalidateTarget(target, unit, unit.range())){
if(!Units.invalidateTarget(target, unit, unit.range()) && unit.type().rotateShooting){
if(unit.type().hasWeapons()){
//TODO certain units should not look at the target, e.g. ships
unit.aimLook(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
unit.lookAt(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
}
}else if(unit.moving()){
unit.lookAt(unit.vel().angle());
+1 -1
View File
@@ -44,7 +44,7 @@ public class MinerAI extends AIController{
}
if(ore != null){
moveTo(ore, unit.type().range / 1.5f);
moveTo(ore, unit.type().range / 2f);
if(unit.within(ore, unit.type().range)){
miner.mineTile(ore);
+2 -2
View File
@@ -12,8 +12,8 @@ public class RepairAI extends AIController{
boolean shoot = false;
if(target != null){
if(!target.within(unit, unit.type().range)){
moveTo(target, unit.type().range * 0.9f);
if(!target.within(unit, unit.type().range * 0.8f)){
moveTo(target, unit.type().range * 0.8f);
}else{
unit.aim(target);
shoot = true;
@@ -35,6 +35,7 @@ public class PhysicsProcess implements AsyncProcess{
refs.removeAll(ref -> {
if(!ref.entity.isAdded()){
physics.destroyBody(ref.body);
ref.entity.physref(null);
return true;
}
return false;
+15 -2
View File
@@ -5,6 +5,7 @@ import mindustry.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.blocks.payloads.*;
import java.util.*;
@@ -48,6 +49,19 @@ public class TeamIndexProcess implements AsyncProcess{
activeCounts[team.id][type.id] += amount;
}
private void count(Unit unit){
updateCount(unit.team, unit.type(), 1);
if(!unit.deactivated) updateActiveCount(unit.team, unit.type(), 1);
if(unit instanceof Payloadc){
((Payloadc)unit).payloads().each(p -> {
if(p instanceof UnitPayload){
count(((UnitPayload)p).unit);
}
});
}
}
@Override
public void reset(){
counts = new int[Team.all.length];
@@ -71,8 +85,7 @@ public class TeamIndexProcess implements AsyncProcess{
for(Unit unit : Groups.unit){
tree(unit.team).insert(unit);
updateCount(unit.team, unit.type(), 1);
if(!unit.deactivated) updateActiveCount(unit.team, unit.type(), 1);
count(unit);
}
}
+21 -8
View File
@@ -34,7 +34,7 @@ public class Blocks implements ContentList{
public static Block
//environment
air, spawn, cliff, deepwater, water, taintedWater, tar, slag, stone, craters, charr, sand, darksand, dirt, ice, snow, darksandTaintedWater,
air, spawn, cliff, deepwater, water, taintedWater, tar, slag, stone, craters, charr, sand, darksand, dirt, mud, ice, snow, darksandTaintedWater,
dacite, stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster,
iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, shaleBoulder, sandBoulder, daciteBoulder, grass, salt,
metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, basalt, magmarock, hotrock, snowWall, boulder, snowBoulder, saltWall,
@@ -260,6 +260,16 @@ public class Blocks implements ContentList{
dirt = new Floor("dirt");
mud = new Floor("mud"){{
speedMultiplier = 0.6f;
variants = 3;
status = StatusEffects.muddy;
statusDuration = 30f;
attributes.set(Attribute.water, 2f);
cacheLayer = CacheLayer.mud;
albedo = 0.35f;
}};
((ShallowLiquid)darksandTaintedWater).set(Blocks.taintedWater, Blocks.darksand);
((ShallowLiquid)sandWater).set(Blocks.water, Blocks.sand);
((ShallowLiquid)darksandWater).set(Blocks.water, Blocks.darksand);
@@ -327,11 +337,12 @@ public class Blocks implements ContentList{
duneWall = new StaticWall("dune-wall"){{
variants = 2;
basalt.asFloor().wall = this;
basalt.asFloor().wall = darksandWater.asFloor().wall = darksandTaintedWater.asFloor().wall = this;
}};
sandWall = new StaticWall("sand-wall"){{
variants = 2;
sandWater.asFloor().wall = this;
}};
saltWall = new StaticWall("salt-wall");
@@ -791,7 +802,7 @@ public class Blocks implements ContentList{
}};
door = new Door("door"){{
requirements(Category.defense, with(Items.graphite, 6, Items.silicon, 4));
requirements(Category.defense, with(Items.titanium, 6, Items.silicon, 4));
health = 100 * wallHealthMultiplier;
}};
@@ -1011,7 +1022,7 @@ public class Blocks implements ContentList{
mechanicalPump = new Pump("mechanical-pump"){{
requirements(Category.liquid, with(Items.copper, 15, Items.metaglass, 10));
pumpAmount = 0.1f;
pumpAmount = 0.11f;
}};
rotaryPump = new Pump("rotary-pump"){{
@@ -1136,7 +1147,7 @@ public class Blocks implements ContentList{
requirements(Category.power, with(Items.copper, 35, Items.graphite, 25, Items.lead, 40, Items.silicon, 30));
powerProduction = 5.5f;
itemDuration = 90f;
consumes.liquid(Liquids.water, 0.06f);
consumes.liquid(Liquids.water, 0.07f);
hasLiquids = true;
size = 2;
}};
@@ -1269,7 +1280,7 @@ public class Blocks implements ContentList{
hasItems = true;
consumes.power(0.80f);
consumes.liquid(Liquids.water, 0.18f);
consumes.liquid(Liquids.water, 0.2f);
}};
oilExtractor = new Fracker("oil-extractor"){{
@@ -1645,7 +1656,7 @@ public class Blocks implements ContentList{
}};
spectre = new ItemTurret("spectre"){{
requirements(Category.turret, with(Items.copper, 350, Items.graphite, 300, Items.surgealloy, 250, Items.plastanium, 175, Items.thorium, 250));
requirements(Category.turret, with(Items.copper, 900, Items.graphite, 300, Items.surgealloy, 250, Items.plastanium, 175, Items.thorium, 250));
ammo(
Items.graphite, Bullets.standardDenseBig,
Items.pyratite, Bullets.standardIncendiaryBig,
@@ -1671,7 +1682,7 @@ public class Blocks implements ContentList{
}};
meltdown = new LaserTurret("meltdown"){{
requirements(Category.turret, with(Items.copper, 250, Items.lead, 350, Items.graphite, 300, Items.surgealloy, 325, Items.silicon, 325));
requirements(Category.turret, with(Items.copper, 1200, Items.lead, 350, Items.graphite, 300, Items.surgealloy, 325, Items.silicon, 325));
shootEffect = Fx.shootBigSmoke2;
shootCone = 40f;
recoilAmount = 4f;
@@ -1793,6 +1804,7 @@ public class Blocks implements ContentList{
{UnitTypes.zenith, UnitTypes.antumbra},
{UnitTypes.spiroct, UnitTypes.arkyid},
{UnitTypes.fortress, UnitTypes.scepter},
{UnitTypes.bryde, UnitTypes.sei},
};
}};
@@ -1811,6 +1823,7 @@ public class Blocks implements ContentList{
{UnitTypes.antumbra, UnitTypes.eclipse},
{UnitTypes.arkyid, UnitTypes.toxopid},
{UnitTypes.scepter, UnitTypes.reign},
{UnitTypes.sei, UnitTypes.omura}
};
}};
+3 -3
View File
@@ -269,13 +269,13 @@ public class Bullets implements ContentList{
status = StatusEffects.burning;
}};
missileSurge = new MissileBulletType(3.7f, 20){{
missileSurge = new MissileBulletType(3.7f, 18){{
width = 8f;
height = 8f;
shrinkY = 0f;
drag = -0.01f;
splashDamageRadius = 28f;
splashDamage = 35f;
splashDamageRadius = 25f;
splashDamage = 25f;
hitEffect = Fx.blastExplosion;
despawnEffect = Fx.blastExplosion;
lightning = 2;
+83 -3
View File
@@ -290,6 +290,22 @@ public class Fx{
Lines.spikes(e.x, e.y, 1f + e.fin() * 6f, e.fout() * 4f, 6);
}),
healBomb = new Effect(40f, 100f, e -> {
color(Pal.heal);
stroke(e.fout() * 2f);
Lines.circle(e.x, e.y, 4f + e.finpow() * 65f);
color(Pal.heal);
for(int i = 0; i < 4; i++){
Drawf.tri(e.x, e.y, 6f, 100f * e.fout(), i*90);
}
color();
for(int i = 0; i < 4; i++){
Drawf.tri(e.x, e.y, 3f, 35f * e.fout(), i*90);
}
}),
healWave = new Effect(22, e -> {
color(Pal.heal);
stroke(e.fout() * 2f);
@@ -686,6 +702,13 @@ public class Fx{
Fill.circle(e.x, e.y, e.fout() * 1f);
}),
muddy = new Effect(80f, e -> {
color(Color.valueOf("432722"));
alpha(Mathf.clamp(e.fin() * 2f));
Fill.circle(e.x, e.y, e.fout() * 1f);
}),
sapped = new Effect(40f, e -> {
color(Pal.sap);
@@ -989,6 +1012,53 @@ public class Fx{
}).ground(400f),
railShoot = new Effect(24f, e -> {
e.scaled(10f, b -> {
color(Color.white, Color.lightGray, b.fin());
stroke(b.fout() * 3f + 0.2f);
Lines.circle(b.x, b.y, b.fin() * 50f);
});
color(Pal.orangeSpark);
for(int i : Mathf.signs){
Drawf.tri(e.x, e.y, 13f * e.fout(), 85f, e.rotation + 90f * i);
}
}),
railTrail = new Effect(16f, e -> {
color(Pal.orangeSpark);
for(int i : Mathf.signs){
Drawf.tri(e.x, e.y, 10f * e.fout(), 24f, e.rotation + 90 + 90f * i);
}
}),
railHit = new Effect(18f, 200f, e -> {
if(true){
color(Pal.orangeSpark);
for(int i : Mathf.signs){
Drawf.tri(e.x, e.y, 10f * e.fout(), 60f, e.rotation + 140f * i);
}
}else{
e.scaled(7f, b -> {
color(Color.white, Color.lightGray, b.fin());
stroke(b.fout() * 2f + 0.2f);
Lines.circle(b.x, b.y, b.fin() * 28f);
});
color(Pal.orangeSpark);
float rot = e.rotation + Mathf.randomSeedRange(e.id, 20f);
float w = 9f * e.fout();
Drawf.tri(e.x, e.y, w, 100f, rot);
Drawf.tri(e.x, e.y, w, 10f, rot + 180f);
}
}),
lancerLaserShoot = new Effect(21f, e -> {
color(Pal.lancerLaser);
@@ -1000,7 +1070,7 @@ public class Fx{
lancerLaserShootSmoke = new Effect(26f, e -> {
color(Color.white);
float length = e.data == null ? 70f : (Float)e.data;
float length = e.data == null || !(e.data instanceof Float) ? 70f : (Float)e.data;
randLenVectors(e.id, 7, length, e.rotation, 0f, (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fout() * 9f);
@@ -1070,6 +1140,15 @@ public class Fx{
});
}),
cloudsmoke = new Effect(70, e -> {
randLenVectors(e.id, 12, 15f + e.fin() * 45f, (x, y) -> {
float size = e.fslope() * 2f;
color(Color.gray);
alpha(e.fslope());
Fill.circle(e.x + x, e.y + y, size);
});
}),
nuclearcloud = new Effect(90, 200f, e -> {
randLenVectors(e.id, 10, e.finpow() * 90f, (x, y) -> {
float size = e.fout() * 14f;
@@ -1295,10 +1374,11 @@ public class Fx{
}),
//TODO fix false in constructor
ripple = new Effect(30, e -> {
e.lifetime = 30f*e.rotation;
color(Tmp.c1.set(e.color).mul(1.5f));
stroke(e.fout() + 0.4f);
stroke(e.fout() * 1.4f);
Lines.circle(e.x, e.y, (2f + e.fin() * 4f) * e.rotation);
}).ground(),
@@ -9,7 +9,7 @@ import mindustry.type.StatusEffect;
import static mindustry.Vars.*;
public class StatusEffects implements ContentList{
public static StatusEffect none, burning, freezing, wet, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, corroded, boss, sporeSlowed;
public static StatusEffect none, burning, freezing, wet, muddy, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, corroded, boss, sporeSlowed;
@Override
public void load(){
@@ -62,6 +62,13 @@ public class StatusEffects implements ContentList{
opposite(burning);
});
}};
muddy = new StatusEffect("muddy"){{
color = Color.valueOf("46382a");
speedMultiplier = 0.94f;
effect = Fx.muddy;
effectChance = 0.09f;
}};
melting = new StatusEffect("melting"){{
speedMultiplier = 0.8f;
+11 -25
View File
@@ -1,18 +1,15 @@
package mindustry.content;
import arc.*;
import arc.math.*;
import arc.struct.*;
import arc.util.ArcAnnotate.*;
import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.game.Objectives.*;
import mindustry.type.*;
import mindustry.world.*;
import static mindustry.content.Blocks.*;
import static mindustry.content.SectorPresets.*;
import static mindustry.content.SectorPresets.craters;
import static mindustry.content.SectorPresets.*;
import static mindustry.content.UnitTypes.*;
import static mindustry.type.ItemStack.*;
@@ -422,7 +419,11 @@ public class TechTree implements ContentList{
node(risso, () -> {
node(minke, () -> {
node(bryde, () -> {
node(sei, () -> {
node(omura, () -> {
});
});
});
});
});
@@ -522,42 +523,27 @@ public class TechTree implements ContentList{
});
}
private static void setup(){
public static void setup(){
TechNode.context = null;
map = new ObjectMap<>();
all = new Seq<>();
}
private static TechNode node(UnlockableContent content, Runnable children){
ItemStack[] requirements;
if(content instanceof Block){
Block block = (Block)content;
requirements = new ItemStack[block.requirements.length];
for(int i = 0; i < requirements.length; i++){
int quantity = 40 + Mathf.round(Mathf.pow(block.requirements[i].amount, 1.25f) * 20, 10);
requirements[i] = new ItemStack(block.requirements[i].item, UI.roundAmount(quantity));
}
}else{
requirements = ItemStack.empty;
}
return node(content, requirements, children);
public static TechNode node(UnlockableContent content, Runnable children){
return node(content, content.researchRequirements(), children);
}
private static TechNode node(UnlockableContent content, ItemStack[] requirements, Runnable children){
public static TechNode node(UnlockableContent content, ItemStack[] requirements, Runnable children){
return new TechNode(content, requirements, children);
}
private static TechNode node(UnlockableContent content, Seq<Objective> objectives, Runnable children){
public static TechNode node(UnlockableContent content, Seq<Objective> objectives, Runnable children){
TechNode node = new TechNode(content, empty, children);
node.objectives = objectives;
return node;
}
private static TechNode node(UnlockableContent block){
public static TechNode node(UnlockableContent block){
return node(block, () -> {});
}
+223 -8
View File
@@ -38,11 +38,14 @@ public class UnitTypes implements ContentList{
//air + building + mining + payload
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class, Payloadc.class}) UnitType mega;
//air + building + payload TODO implement
public static @EntityDef({Unitc.class, Builderc.class, Payloadc.class}) UnitType quad, oct;
//air + building + mining
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType alpha, beta, gamma;
//water
public static @EntityDef({Unitc.class, WaterMovec.class, Commanderc.class}) UnitType risso, minke, bryde;
//water + commander
public static @EntityDef({Unitc.class, WaterMovec.class, Commanderc.class}) UnitType risso, minke, bryde, sei, omura;
//special block unit type
public static @EntityDef({Unitc.class, BlockUnitc.class}) UnitType block;
@@ -61,6 +64,7 @@ public class UnitTypes implements ContentList{
reload = 14f;
x = 4f;
y = 2f;
top = false;
ejectEffect = Fx.shellEjectSmall;
bullet = Bullets.standardCopper;
}});
@@ -75,6 +79,7 @@ public class UnitTypes implements ContentList{
immunities.add(StatusEffects.burning);
weapons.add(new Weapon("flamethrower"){{
top = false;
shootSound = Sounds.flame;
shootY = 2f;
reload = 14f;
@@ -106,6 +111,7 @@ public class UnitTypes implements ContentList{
mechFrontSway = 0.55f;
weapons.add(new Weapon("artillery"){{
top = false;
y = 1f;
x = 9f;
reload = 60f;
@@ -142,6 +148,7 @@ public class UnitTypes implements ContentList{
weapons.add(
new Weapon("scepter-weapon"){{
top = false;
y = 1f;
x = 16f;
shootY = 8f;
@@ -201,6 +208,7 @@ public class UnitTypes implements ContentList{
weapons.add(
new Weapon("reign-weapon"){{
top = false;
y = 1f;
x = 21.5f;
shootY = 11f;
@@ -259,6 +267,7 @@ public class UnitTypes implements ContentList{
abilities.add(new HealFieldAbility(10f, 60f * 4, 60f));
weapons.add(new Weapon("heal-weapon"){{
top = false;
shootY = 2f;
reload = 24f;
x = 4.5f;
@@ -274,7 +283,7 @@ public class UnitTypes implements ContentList{
itemCapacity = 60;
canBoost = true;
boostMultiplier = 1.5f;
speed = 0.48f;
speed = 0.62f;
hitsize = 10f;
health = 320f;
buildSpeed = 0.9f;
@@ -287,6 +296,7 @@ public class UnitTypes implements ContentList{
abilities.add(new ShieldFieldAbility(20f, 40f, 60f * 5, 60f));
weapons.add(new Weapon("heal-shotgun-weapon"){{
top = false;
x = 5f;
shake = 2.2f;
y = 0.5f;
@@ -336,6 +346,7 @@ public class UnitTypes implements ContentList{
abilities.add(new ForceFieldAbility(60f, 0.3f, 400f, 60f * 6));
weapons.add(new Weapon("beam-weapon"){{
top = false;
shake = 2f;
shootY = 4f;
x = 6.5f;
@@ -406,6 +417,7 @@ public class UnitTypes implements ContentList{
groundLayer = Layer.legUnit - 1f;
weapons.add(new Weapon("eruption"){{
top = false;
shootY = 3f;
reload = 10f;
ejectEffect = Fx.none;
@@ -668,8 +680,8 @@ public class UnitTypes implements ContentList{
width = height = 25f;
collidesTiles = collides = true;
ammoMultiplier = 4f;
splashDamageRadius = 95f;
splashDamage = 90f;
splashDamageRadius = 90f;
splashDamage = 75f;
backColor = Pal.sapBulletBack;
frontColor = lightningColor = Pal.sapBullet;
lightning = 5;
@@ -690,7 +702,7 @@ public class UnitTypes implements ContentList{
width = height = 20f;
collidesTiles = false;
splashDamageRadius = 80f;
splashDamage = 45f;
splashDamage = 40f;
backColor = Pal.sapBulletBack;
frontColor = lightningColor = Pal.sapBullet;
lightning = 2;
@@ -735,6 +747,7 @@ public class UnitTypes implements ContentList{
accel = 0.08f;
drag = 0.016f;
flying = true;
hitsize = 9f;
targetAir = false;
engineOffset = 7.8f;
range = 140f;
@@ -1001,6 +1014,7 @@ public class UnitTypes implements ContentList{
abilities.add(new HealFieldAbility(5f, 60f * 5, 50f));
weapons.add(new Weapon("heal-weapon-mount"){{
top = false;
y = -2.5f;
x = 3.5f;
reload = 30f;
@@ -1033,6 +1047,8 @@ public class UnitTypes implements ContentList{
mineTier = 2;
health = 500;
armor = 2f;
armor = 5f;
speed = 1.8f;
accel = 0.06f;
drag = 0.017f;
@@ -1062,6 +1078,65 @@ public class UnitTypes implements ContentList{
}});
}};
quad = new UnitType("quad"){{
mineTier = 2;
armor = 4f;
health = 7000;
speed = 1.2f;
rotateSpeed = 2f;
accel = 0.05f;
drag = 0.017f;
lowAltitude = false;
flying = true;
engineOffset = 12f;
engineSize = 6f;
rotateShooting = false;
hitsize = 32f;
payloadCapacity = (3 * 3) * (8 * 8);
buildSpeed = 2.5f;
range = 140f;
weapons.add(
new Weapon(){{
x = y = 0f;
mirror = false;
reload = 60f;
minShootVelocity = 0.01f;
bullet = new BasicBulletType(){{
sprite = "large-bomb";
width = height = 120/4f;
backColor = Pal.heal;
frontColor = Color.white;
mixColorTo = Color.white;
shootCone = 180f;
ejectEffect = Fx.none;
ignoreRotation = true;
shootSound = Sounds.none;
despawnShake = 4f;
collidesAir = false;
lifetime = 70f;
despawnEffect = Fx.healBomb;
hitEffect = Fx.massiveExplosion;
keepVelocity = false;
spin = 2f;
shrinkX = shrinkY = 0.7f;
speed = 0.001f;
collides = false;
splashDamage = 230f;
splashDamageRadius = 90f;
}};
}});
}};
//endregion
//region naval attack
@@ -1125,6 +1200,7 @@ public class UnitTypes implements ContentList{
accel = 0.3f;
rotateSpeed = 2.6f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
trailLength = 20;
trailX = 5.5f;
@@ -1164,7 +1240,7 @@ public class UnitTypes implements ContentList{
accel = 0.2f;
rotateSpeed = 1.8f;
drag = 0.17f;
hitsize = 14f;
hitsize = 16f;
armor = 6f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
@@ -1186,7 +1262,7 @@ public class UnitTypes implements ContentList{
shootY = 7f;
shake = 5f;
recoil = 4f;
occlusion = 17f;
occlusion = 12f;
shots = 1;
inaccuracy = 3f;
@@ -1252,6 +1328,142 @@ public class UnitTypes implements ContentList{
}});
}};
sei = new UnitType("sei"){{
health = 10000;
armor = 12f;
speed = 0.73f;
drag = 0.17f;
hitsize = 39f;
accel = 0.2f;
rotateSpeed = 1.3f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
trailLength = 50;
trailX = 18f;
trailY = -21f;
trailScl = 3f;
weapons.add(new Weapon("sei-launcher"){{
x = 0f;
y = 0f;
rotate = true;
rotateSpeed = 4f;
mirror = false;
occlusion = 20f;
shootY = 2f;
recoil = 4f;
reload = 45f;
shots = 6;
spacing = 10f;
velocityRnd = 0.4f;
inaccuracy = 7f;
ejectEffect = Fx.none;
shake = 3f;
shootSound = Sounds.shootBig;
xRand = 8f;
shotDelay = 1f;
bullet = new MissileBulletType(4.2f, 25){{
homingPower = 0.12f;
width = 8f;
height = 8f;
shrinkX = shrinkY = 0f;
drag = -0.003f;
homingRange = 80f;
keepVelocity = false;
splashDamageRadius = 25f;
splashDamage = 25f;
lifetime = 56f;
trailColor = Pal.bulletYellowBack;
backColor = Pal.bulletYellowBack;
frontColor = Pal.bulletYellow;
hitEffect = Fx.blastExplosion;
despawnEffect = Fx.blastExplosion;
weaveScale = 8f;
weaveMag = 2f;
}};
}});
weapons.add(new Weapon("large-bullet-mount"){{
reload = 80f;
cooldownTime = 90f;
x = 70f/4f;
y = -66f/4f;
rotateSpeed = 4f;
rotate = true;
shootY = 7f;
shake = 2f;
recoil = 3f;
occlusion = 12f;
ejectEffect = Fx.shellEjectBig;
shots = 3;
shotDelay = 4f;
inaccuracy = 1f;
bullet = new BasicBulletType(7f, 50){{
width = 13f;
height = 19f;
shootEffect = Fx.shootBig;
lifetime = 30f;
}};
}});
}};
omura = new UnitType("omura"){{
health = 22000;
speed = 0.62f;
drag = 0.18f;
hitsize = 50f;
armor = 16f;
accel = 0.19f;
rotateSpeed = 0.9f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
float spawnTime = 60f * 25f;
abilities.add(new UnitSpawnAbility(flare, spawnTime, 19.25f, -31.75f), new UnitSpawnAbility(flare, spawnTime, -19.25f, -31.75f));
trailLength = 70;
trailX = 23f;
trailY = -32f;
trailScl = 3.5f;
weapons.add(new Weapon("omura-cannon"){{
reload = 110f;
cooldownTime = 90f;
mirror = false;
x = 0f;
y = -3.5f;
rotateSpeed = 1.4f;
rotate = true;
shootY = 23f;
shake = 6f;
recoil = 10.5f;
occlusion = 50f;
shots = 1;
ejectEffect = Fx.none;
bullet = new RailBulletType(){{
shootEffect = Fx.railShoot;
speed = 67f;
lifetime = 8f;
pierceEffect = Fx.railHit;
updateEffect = Fx.railTrail;
hitEffect = Fx.massiveExplosion;
smokeEffect = Fx.shootBig2;
damage = 1250;
pierceDamageFactor = 0.5f;
}};
}});
}};
//endregion
//region core
@@ -1276,6 +1488,7 @@ public class UnitTypes implements ContentList{
reload = 17f;
x = 2.75f;
y = 1f;
top = false;
bullet = new BasicBulletType(2.5f, 9){{
width = 7f;
@@ -1308,6 +1521,7 @@ public class UnitTypes implements ContentList{
lowAltitude = true;
weapons.add(new Weapon("small-mount-weapon"){{
top = false;
reload = 20f;
x = 3f;
y = 0.5f;
@@ -1345,6 +1559,7 @@ public class UnitTypes implements ContentList{
hitsize = 10f;
weapons.add(new Weapon("small-mount-weapon"){{
top = false;
reload = 15f;
x = 1f;
y = 2f;
+7 -2
View File
@@ -191,6 +191,10 @@ public class Control implements ApplicationListener, Loadable{
}
void resetCamera(){
}
@Override
public void loadAsync(){
Draw.scl = 1f / Core.atlas.find("scale_marker").width;
@@ -280,6 +284,7 @@ public class Control implements ApplicationListener, Loadable{
try{
net.reset();
slot.load();
slot.setAutosave(true);
state.rules.sector = sector;
//if there is no base, simulate a new game and place the right loadout at the spawn position
@@ -329,7 +334,7 @@ public class Control implements ApplicationListener, Loadable{
}
public void playTutorial(){
ui.showInfo("There is no tutorial yet.");
ui.showInfo("@indev.notready");
//TODO implement
//ui.showInfo("death");
/*
@@ -429,7 +434,7 @@ public class Control implements ApplicationListener, Loadable{
//just a regular reminder
if(!OS.prop("user.name").equals("anuke") && !OS.hasEnv("iknowwhatimdoing")){
app.post(() -> app.post(() -> {
ui.showStartupInfo("@indevpopup");
ui.showStartupInfo("@indev.popup");
}));
}
+1 -1
View File
@@ -17,7 +17,7 @@ public class GameState{
/** Wave countdown in ticks. */
public float wavetime;
/** Whether the game is in game over state. */
public boolean gameOver = false, launched = false, serverPaused = false;
public boolean gameOver = false, launched = false, serverPaused = false, wasTimeout;
/** Map that is currently being played on. */
public @NonNull Map map = emptyMap;
/** The current game rules. */
+8 -1
View File
@@ -337,7 +337,14 @@ public class Logic implements ApplicationListener{
//force pausing when the player is out of sector time
if(state.isOutOfTime()){
state.set(State.paused);
if(!state.wasTimeout){
universe.displayTimeEnd();
state.wasTimeout = true;
}
//if no turn was run.
if(state.isOutOfTime()){
state.set(State.paused);
}
}
if(!state.isPaused()){
+7 -3
View File
@@ -338,8 +338,6 @@ public class NetClient implements ApplicationListener{
@Remote(variants = Variant.both)
public static void setRules(Rules rules){
state.rules = rules;
//campaign is not valid in multiplayer
state.rules.sector = null;
}
@Remote(variants = Variant.both)
@@ -442,7 +440,7 @@ public class NetClient implements ApplicationListener{
}
@Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true)
public static void stateSnapshot(float waveTime, int wave, int enemies, boolean paused, boolean gameOver, short coreDataLen, byte[] coreData){
public static void stateSnapshot(float waveTime, int wave, int enemies, boolean paused, boolean gameOver, int timeData, short coreDataLen, byte[] coreData){
try{
if(wave > state.wave){
state.wave = wave;
@@ -455,6 +453,8 @@ public class NetClient implements ApplicationListener{
state.enemies = enemies;
state.serverPaused = paused;
universe.updateNetSeconds(timeData);
netClient.byteStream.setBytes(net.decompressSnapshot(coreData, coreDataLen));
DataInputStream input = netClient.dataStream;
@@ -549,6 +549,10 @@ public class NetClient implements ApplicationListener{
quiet = true;
}
public void clearRemovedEntity(int id){
removed.remove(id);
}
public void addRemovedEntity(int id){
removed.add(id);
}
+27 -27
View File
@@ -593,38 +593,38 @@ public class NetServer implements ApplicationListener{
if(player.isBuilder()){
player.builder().clearBuilding();
player.builder().updateBuilding(building);
if(requests != null){
for(BuildPlan req : requests){
if(req == null) continue;
Tile tile = world.tile(req.x, req.y);
if(tile == null || (!req.breaking && req.block == null)) continue;
//auto-skip done requests
if(req.breaking && tile.block() == Blocks.air){
continue;
}else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || (tile.build != null && tile.build.rotation == req.rotation))){
continue;
}else if(con.rejectedRequests.contains(r -> r.breaking == req.breaking && r.x == req.x && r.y == req.y)){ //check if request was recently rejected, and skip it if so
continue;
}else if(!netServer.admins.allowAction(player, req.breaking ? ActionType.breakBlock : ActionType.placeBlock, tile, action -> { //make sure request is allowed by the server
action.block = req.block;
action.rotation = req.rotation;
action.config = req.config;
})){
//force the player to remove this request if that's not the case
Call.removeQueueBlock(player.con, req.x, req.y, req.breaking);
con.rejectedRequests.add(req);
continue;
}
player.builder().plans().addLast(req);
}
}
}
if(player.isMiner()){
player.miner().mineTile(mining);
}
if(requests != null){
for(BuildPlan req : requests){
if(req == null) continue;
Tile tile = world.tile(req.x, req.y);
if(tile == null || (!req.breaking && req.block == null)) continue;
//auto-skip done requests
if(req.breaking && tile.block() == Blocks.air){
continue;
}else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || (tile.build != null && tile.build.rotation == req.rotation))){
continue;
}else if(con.rejectedRequests.contains(r -> r.breaking == req.breaking && r.x == req.x && r.y == req.y)){ //check if request was recently rejected, and skip it if so
continue;
}else if(!netServer.admins.allowAction(player, req.breaking ? ActionType.breakBlock : ActionType.placeBlock, tile, action -> { //make sure request is allowed by the server
action.block = req.block;
action.rotation = req.rotation;
action.config = req.config;
})){
//force the player to remove this request if that's not the case
Call.removeQueueBlock(player.con, req.x, req.y, req.breaking);
con.rejectedRequests.add(req);
continue;
}
player.builder().plans().addLast(req);
}
}
con.rejectedRequests.clear();
if(!player.dead()){
@@ -846,7 +846,7 @@ public class NetServer implements ApplicationListener{
byte[] stateBytes = syncStream.toByteArray();
//write basic state data.
Call.stateSnapshot(player.con, state.wavetime, state.wave, state.enemies, state.serverPaused, state.gameOver, (short)stateBytes.length, net.compressSnapshot(stateBytes));
Call.stateSnapshot(player.con, state.wavetime, state.wave, state.enemies, state.serverPaused, state.gameOver, universe.seconds(), (short)stateBytes.length, net.compressSnapshot(stateBytes));
viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY);
+80 -5
View File
@@ -5,11 +5,13 @@ import arc.func.*;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.struct.ObjectIntMap.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import arc.util.noise.*;
import mindustry.content.*;
import mindustry.core.GameState.*;
import mindustry.ctype.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.game.Teams.*;
@@ -19,7 +21,6 @@ import mindustry.maps.*;
import mindustry.maps.filters.*;
import mindustry.maps.filters.GenerateFilter.*;
import mindustry.type.*;
import mindustry.type.Sector.*;
import mindustry.type.Weather.*;
import mindustry.world.*;
import mindustry.world.blocks.environment.*;
@@ -33,11 +34,17 @@ public class World{
public @NonNull Tiles tiles = new Tiles(0, 0);
private boolean generating, invalidMap;
private ObjectMap<Map, Runnable> customMapLoaders = new ObjectMap<>();
public World(){
}
/** Adds a custom handler function for loading a custom map - usually a generated one. */
public void addMapLoader(Map map, Runnable loader){
customMapLoaders.put(map, loader);
}
public boolean isInvalidMap(){
return invalidMap;
}
@@ -255,9 +262,71 @@ public class World{
state.rules.weather.clear();
if(sector.is(SectorAttribute.rainy)) state.rules.weather.add(new WeatherEntry(Weathers.rain));
if(sector.is(SectorAttribute.snowy)) state.rules.weather.add(new WeatherEntry(Weathers.snow));
if(sector.is(SectorAttribute.desert)) state.rules.weather.add(new WeatherEntry(Weathers.sandstorm));
//apply weather based on terrain
ObjectIntMap<Block> floorc = new ObjectIntMap<>();
ObjectSet<UnlockableContent> content = new ObjectSet<>();
float waterFloors = 0, totalFloors = 0;
for(Tile tile : world.tiles){
if(world.getDarkness(tile.x, tile.y) >= 3){
continue;
}
Liquid liquid = tile.floor().liquidDrop;
if(tile.floor().itemDrop != null) content.add(tile.floor().itemDrop);
if(tile.overlay().itemDrop != null) content.add(tile.overlay().itemDrop);
if(liquid != null) content.add(liquid);
if(!tile.block().isStatic()){
totalFloors ++;
if(liquid == Liquids.water){
waterFloors += tile.floor().isDeep() ? 1f : 0.7f;
}
floorc.increment(tile.floor());
if(tile.overlay() != Blocks.air){
floorc.increment(tile.overlay());
}
}
}
//sort counts in descending order
Seq<Entry<Block>> entries = floorc.entries().toArray();
entries.sort(e -> -e.value);
//remove all blocks occuring < 30 times - unimportant
entries.removeAll(e -> e.value < 30);
Block[] floors = new Block[entries.size];
int[] floorCounts = new int[entries.size];
for(int i = 0; i < entries.size; i++){
floorCounts[i] = entries.get(i).value;
floors[i] = entries.get(i).key;
}
//TODO bad code
boolean hasSnow = floors[0].name.contains("ice") || floors[0].name.contains("snow");
boolean hasRain = !hasSnow && floors[0].name.contains("water");
boolean hasDesert = !hasSnow && !hasRain && floors[0].name.contains("sand");
boolean hasSpores = floors[0].name.contains("spore") || floors[0].name.contains("moss") || floors[0].name.contains("tainted");
if(hasSnow){
state.rules.weather.add(new WeatherEntry(Weathers.snow));
}
if(hasRain){
state.rules.weather.add(new WeatherEntry(Weathers.rain));
}
if(hasDesert){
state.rules.weather.add(new WeatherEntry(Weathers.sandstorm));
}
if(hasSpores){
state.rules.weather.add(new WeatherEntry(Weathers.sporestorm));
}
state.secinfo.resources = content.asArray();
state.secinfo.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id)));
}
@@ -270,6 +339,12 @@ public class World{
}
public void loadMap(Map map, Rules checkRules){
//load using custom loader if possible
if(customMapLoaders.containsKey(map)){
customMapLoaders.get(map).run();
return;
}
try{
SaveIO.load(map.file, new FilterContext(map));
}catch(Throwable e){
@@ -444,7 +519,7 @@ public class World{
dark = Math.max((edgeBlend - edgeDst) * (4f / edgeBlend), dark);
}
if(state.hasSector()){
if(state.hasSector() && state.getSector().preset == null){
int circleBlend = 14;
//quantized angle
float offset = state.getSector().rect.rotation + 90;
@@ -8,6 +8,7 @@ import arc.util.ArcAnnotate.*;
import mindustry.annotations.Annotations.*;
import mindustry.game.EventType.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
import static mindustry.Vars.*;
@@ -30,7 +31,7 @@ public abstract class UnlockableContent extends MappableContent{
this.localizedName = Core.bundle.get(getContentType() + "." + this.name + ".name", this.name);
this.description = Core.bundle.getOrNull(getContentType() + "." + this.name + ".description");
this.unlocked = Core.settings != null && Core.settings.getBool(name + "-unlocked", false);
this.unlocked = Core.settings != null && Core.settings.getBool(this.name + "-unlocked", false);
}
public String displayDescription(){
@@ -43,6 +44,11 @@ public abstract class UnlockableContent extends MappableContent{
}
/** @return items needed to research this content */
public ItemStack[] researchRequirements(){
return ItemStack.empty;
}
public String emoji(){
return Fonts.getUnicodeStr(name);
}
+5 -1
View File
@@ -64,8 +64,12 @@ public class DrawOperation{
if(type == OpType.floor.ordinal()){
tile.setFloor((Floor)content.block(to));
}else if(type == OpType.block.ordinal()){
tile.getLinkedTiles(t -> editor.renderer.updatePoint(t.x, t.y));
Block block = content.block(to);
tile.setBlock(block, tile.team(), tile.build == null ? 0 : tile.build.rotation);
tile.getLinkedTiles(t -> editor.renderer.updatePoint(t.x, t.y));
}else if(type == OpType.rotation.ordinal()){
if(tile.build != null) tile.build.rotation = to;
}else if(type == OpType.team.ordinal()){
@@ -74,7 +78,7 @@ public class DrawOperation{
tile.setOverlayID(to);
}
});
editor.renderer().updatePoint(tile.x, tile.y);
editor.renderer.updatePoint(tile.x, tile.y);
}
@Struct
+22 -9
View File
@@ -20,7 +20,7 @@ public class EditorTile extends Tile{
@Override
public void setFloor(@NonNull Floor type){
if(state.isGame()){
if(skip()){
super.setFloor(type);
return;
}
@@ -41,20 +41,25 @@ public class EditorTile extends Tile{
@Override
public void setBlock(Block type, Team team, int rotation){
if(state.isGame()){
if(skip()){
super.setBlock(type, team, rotation);
return;
}
if(this.block == type && (build == null || build.rotation == rotation)){
update();
return;
}
op(OpType.block, block.id);
if(rotation != 0) op(OpType.rotation, (byte)rotation);
if(team() != Team.derelict) op(OpType.team, (byte)team().id);
if(team != Team.derelict) op(OpType.team, (byte)team.id);
super.setBlock(type, team, rotation);
}
@Override
public void setTeam(Team team){
if(state.isGame()){
if(skip()){
super.setTeam(team);
return;
}
@@ -66,7 +71,7 @@ public class EditorTile extends Tile{
@Override
public void setOverlay(Block overlay){
if(state.isGame()){
if(skip()){
super.setOverlay(overlay);
return;
}
@@ -79,23 +84,23 @@ public class EditorTile extends Tile{
@Override
protected void fireChanged(){
if(state.isGame()){
if(skip()){
super.fireChanged();
}else{
ui.editor.editor.renderer().updatePoint(x, y);
update();
}
}
@Override
public void recache(){
if(state.isGame()){
if(skip()){
super.recache();
}
}
@Override
protected void changeEntity(Team team, Prov<Building> entityprov, int rotation){
if(state.isGame()){
if(skip()){
super.changeEntity(team, entityprov, rotation);
return;
}
@@ -116,6 +121,14 @@ public class EditorTile extends Tile{
}
}
private void update(){
ui.editor.editor.renderer.updatePoint(x, y);
}
private boolean skip(){
return state.isGame() || ui.editor.editor.isLoading();
}
private void op(OpType type, short value){
ui.editor.editor.addTileOp(TileOp.get(x, y, (byte)type.ordinal(), value));
}
+1 -1
View File
@@ -17,7 +17,7 @@ public enum EditorTool{
if(!Structs.inBounds(x, y, editor.width(), editor.height())) return;
Tile tile = editor.tile(x, y);
editor.drawBlock = tile.block() == Blocks.air ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block();
editor.drawBlock = tile.block() == Blocks.air || !tile.block().inEditor ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block();
}
},
line(KeyCode.l, "replace", "orthogonal"){
+14 -12
View File
@@ -18,10 +18,10 @@ import static mindustry.Vars.*;
public class MapEditor{
public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15, 20};
private final Context context = new Context();
private StringMap tags = new StringMap();
private MapRenderer renderer = new MapRenderer(this);
public StringMap tags = new StringMap();
public MapRenderer renderer = new MapRenderer(this);
private final Context context = new Context();
private OperationStack stack = new OperationStack();
private DrawOperation currentOp;
private boolean loading;
@@ -31,8 +31,8 @@ public class MapEditor{
public Block drawBlock = Blocks.stone;
public Team drawTeam = Team.sharded;
public StringMap getTags(){
return tags;
public boolean isLoading(){
return loading;
}
public void beginEdit(int width, int height){
@@ -52,7 +52,7 @@ public class MapEditor{
if(map.file.parent().parent().name().equals("1127400") && steam){
tags.put("steamid", map.file.parent().name());
}
MapIO.loadMap(map, context);
load(() -> MapIO.loadMap(map, context));
renderer.resize(width(), height());
loading = false;
}
@@ -210,10 +210,6 @@ public class MapEditor{
}
}
public MapRenderer renderer(){
return renderer;
}
public void resize(int width, int height){
clearOp();
@@ -227,8 +223,14 @@ public class MapEditor{
int px = offsetX + x, py = offsetY + y;
if(previous.in(px, py)){
tiles.set(x, y, previous.getn(px, py));
tiles.getn(x, y).x = (short)x;
tiles.getn(x, y).y = (short)y;
Tile tile = tiles.getn(x, y);
tile.x = (short)x;
tile.y = (short)y;
if(tile.build != null && tile.isCenter()){
tile.build.x = x * tilesize + tile.block().offset;
tile.build.y = y * tilesize + tile.block().offset;
}
}else{
tiles.set(x, y, new EditorTile(x, y, Blocks.stone.id, (short)0, (short)0));
}
+16 -16
View File
@@ -116,9 +116,9 @@ public class MapEditorDialog extends Dialog implements Disposable{
t.button("@editor.export", Icon.upload, () -> createDialog("@editor.export",
"@editor.exportfile", "@editor.exportfile.description", Icon.file,
(Runnable)() -> platform.export(editor.getTags().get("name", "unknown"), mapExtension, file -> MapIO.writeMap(file, editor.createMap(file))),
(Runnable)() -> platform.export(editor.tags.get("name", "unknown"), mapExtension, file -> MapIO.writeMap(file, editor.createMap(file))),
"@editor.exportimage", "@editor.exportimage.description", Icon.fileImage,
(Runnable)() -> platform.export(editor.getTags().get("name", "unknown"), "png", file -> {
(Runnable)() -> platform.export(editor.tags.get("name", "unknown"), "png", file -> {
Pixmap out = MapIO.writeImage(editor.tiles());
file.writePNG(out);
out.dispose();
@@ -129,16 +129,16 @@ public class MapEditorDialog extends Dialog implements Disposable{
if(steam){
menu.cont.button("@editor.publish.workshop", Icon.link, () -> {
Map builtin = maps.all().find(m -> m.name().equals(editor.getTags().get("name", "").trim()));
Map builtin = maps.all().find(m -> m.name().equals(editor.tags.get("name", "").trim()));
if(editor.getTags().containsKey("steamid") && builtin != null && !builtin.custom){
platform.viewListingID(editor.getTags().get("steamid"));
if(editor.tags.containsKey("steamid") && builtin != null && !builtin.custom){
platform.viewListingID(editor.tags.get("steamid"));
return;
}
Map map = save();
if(editor.getTags().containsKey("steamid") && map != null){
if(editor.tags.containsKey("steamid") && map != null){
platform.viewListing(map);
return;
}
@@ -156,7 +156,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
}
platform.publish(map);
}).padTop(-3).size(swidth * 2f + 10, 60f).update(b -> b.setText(editor.getTags().containsKey("steamid") ? editor.getTags().get("author").equals(player.name) ? "@workshop.listing" : "@view.workshop" : "@editor.publish.workshop"));
}).padTop(-3).size(swidth * 2f + 10, 60f).update(b -> b.setText(editor.tags.containsKey("steamid") ? editor.tags.get("author").equals(player.name) ? "@workshop.listing" : "@view.workshop" : "@editor.publish.workshop"));
menu.cont.row();
}
@@ -235,7 +235,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
state.rules = (lastSavedRules == null ? new Rules() : lastSavedRules);
lastSavedRules = null;
saved = false;
editor.renderer().updateAll();
editor.renderer.updateAll();
}
private void playtest(){
@@ -264,10 +264,10 @@ public class MapEditorDialog extends Dialog implements Disposable{
public @Nullable Map save(){
boolean isEditor = state.rules.editor;
state.rules.editor = false;
String name = editor.getTags().get("name", "").trim();
editor.getTags().put("rules", JsonIO.write(state.rules));
editor.getTags().remove("width");
editor.getTags().remove("height");
String name = editor.tags.get("name", "").trim();
editor.tags.put("rules", JsonIO.write(state.rules));
editor.tags.remove("width");
editor.tags.remove("height");
player.clearUnit();
@@ -281,7 +281,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
if(map != null && !map.custom){
handleSaveBuiltin(map);
}else{
returned = maps.saveMap(editor.getTags());
returned = maps.saveMap(editor.tags);
ui.showInfoFade("@editor.saved");
}
}
@@ -352,7 +352,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
@Override
public void dispose(){
editor.renderer().dispose();
editor.renderer.dispose();
}
public void beginEditMap(Fi file){
@@ -614,12 +614,12 @@ public class MapEditorDialog extends Dialog implements Disposable{
Tile tile = editor.tile(x, y);
if(tile.block().breakable && tile.block() instanceof Boulder){
tile.setBlock(Blocks.air);
editor.renderer().updatePoint(x, y);
editor.renderer.updatePoint(x, y);
}
if(tile.overlay() != Blocks.air && tile.overlay() != Blocks.spawn){
tile.setOverlay(Blocks.air);
editor.renderer().updatePoint(x, y);
editor.renderer.updatePoint(x, y);
}
}
}
@@ -144,7 +144,7 @@ public class MapGenerateDialog extends BaseDialog{
}
//reset undo stack as generation... messes things up
editor.renderer().updateAll();
editor.renderer.updateAll();
editor.clearOp();
}
+3 -3
View File
@@ -29,7 +29,7 @@ public class MapInfoDialog extends BaseDialog{
private void setup(){
cont.clear();
ObjectMap<String, String> tags = editor.getTags();
ObjectMap<String, String> tags = editor.tags;
cont.pane(t -> {
t.add("@editor.mapname").padRight(8).left();
@@ -73,8 +73,8 @@ public class MapInfoDialog extends BaseDialog{
t.row();
t.add("@editor.generation").padRight(8).left();
t.button("@edit", () -> {
generate.show(Vars.maps.readFilters(editor.getTags().get("genfilters", "")),
filters -> editor.getTags().put("genfilters", JsonIO.write(filters)));
generate.show(Vars.maps.readFilters(editor.tags.get("genfilters", "")),
filters -> editor.tags.put("genfilters", JsonIO.write(filters)));
hide();
}).left().width(200f);
+1 -1
View File
@@ -116,7 +116,7 @@ public class MapRenderer implements Disposable{
wx * tilesize + wall.offset + (tilesize - width) / 2f,
wy * tilesize + wall.offset + (tilesize - height) / 2f,
width, height,
tile.build == null || !wall.rotate ? 0 : tile.build.rotdeg() - 90);
tile.build == null || !wall.rotate ? 0 : tile.build.rotdeg());
}else{
region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length - 1)];
+1 -1
View File
@@ -248,7 +248,7 @@ public class MapView extends Element implements GestureListener{
Draw.color(Pal.remove);
Lines.stroke(2f);
Lines.rect(centerx - sclwidth / 2 - 1, centery - sclheight / 2 - 1, sclwidth + 2, sclheight + 2);
editor.renderer().draw(centerx - sclwidth / 2, centery - sclheight / 2, sclwidth, sclheight);
editor.renderer.draw(centerx - sclwidth / 2, centery - sclheight / 2, sclwidth, sclheight);
Draw.reset();
if(grid){
+10 -8
View File
@@ -40,7 +40,7 @@ public class Effect{
}
public Effect(float life, Cons<EffectContainer> renderer){
this(life, 32f, renderer);
this(life,50f, renderer);
}
public Effect ground(){
@@ -86,12 +86,14 @@ public class Effect{
create(this, x, y, rotation, Color.white, data);
}
public void render(int id, Color color, float life, float rotation, float x, float y, Object data){
public float render(int id, Color color, float life, float lifetime, float rotation, float x, float y, Object data){
container.set(id, color, life, lifetime, rotation, x, y, data);
Draw.z(ground ? Layer.debris : Layer.effect);
Draw.reset();
renderer.get(container);
Draw.reset();
return container.lifetime;
}
public static @Nullable Effect get(int id){
@@ -125,13 +127,13 @@ public class Effect{
if(view.overlaps(pos)){
EffectState entity = EffectState.create();
entity.effect(effect);
entity.rotation(rotation);
entity.data(data);
entity.lifetime(effect.lifetime);
entity.effect = effect;
entity.rotation = rotation;
entity.data = (data);
entity.lifetime = (effect.lifetime);
entity.set(x, y);
entity.color().set(color);
if(data instanceof Posc) entity.parent((Posc)data);
entity.color.set(color);
if(data instanceof Posc) entity.parent = ((Posc)data);
entity.add();
}
}
+10
View File
@@ -1,5 +1,6 @@
package mindustry.entities;
import arc.*;
import arc.func.*;
import arc.math.geom.*;
import mindustry.annotations.Annotations.*;
@@ -18,6 +19,15 @@ public class Units{
private static float cdist;
private static boolean boolResult;
@Remote(called = Loc.server)
public static void unitCapDeath(Unit unit){
if(unit != null){
unit.dead = true;
Fx.unitCapKill.at(unit);
Core.app.post(() -> Call.unitDeath(unit.id));
}
}
@Remote(called = Loc.server)
public static void unitDeath(int uid){
Unit unit = Groups.unit.getByID(uid);
@@ -2,7 +2,16 @@ package mindustry.entities.abilities;
import mindustry.gen.*;
public interface Ability{
default void update(Unit unit){}
default void draw(Unit unit){}
public abstract class Ability implements Cloneable{
public void update(Unit unit){}
public void draw(Unit unit){}
public Ability copy(){
try{
return (Ability)clone();
}catch(CloneNotSupportedException e){
//I am disgusted
throw new RuntimeException("java sucks", e);
}
}
}
@@ -11,7 +11,7 @@ import mindustry.content.*;
import mindustry.gen.*;
import mindustry.graphics.*;
public class ForceFieldAbility implements Ability{
public class ForceFieldAbility extends Ability{
/** Shield radius. */
public float radius = 60f;
/** Shield regen speed in damage/tick. */
@@ -21,18 +21,22 @@ public class ForceFieldAbility implements Ability{
/** Cooldown after the shield is broken, in ticks. */
public float cooldown = 60f * 5;
private float realRad;
private Unit paramUnit;
private final Cons<Shielderc> shieldConsumer = trait -> {
/** State: radius scaling. */
protected float radiusScale;
private static float realRad;
private static Unit paramUnit;
private static ForceFieldAbility paramField;
private static final Cons<Shielderc> shieldConsumer = trait -> {
if(trait.team() != paramUnit.team && Intersector.isInsideHexagon(paramUnit.x, paramUnit.y, realRad * 2f, trait.x(), trait.y()) && paramUnit.shield > 0){
trait.absorb();
Fx.absorb.at(trait);
//break shield
if(paramUnit.shield <= trait.damage()){
paramUnit.shield -= cooldown * regen;
paramUnit.shield -= paramField.cooldown * paramField.regen;
Fx.shieldBreak.at(paramUnit.x, paramUnit.y, radius, paramUnit.team.color);
Fx.shieldBreak.at(paramUnit.x, paramUnit.y, paramField.radius, paramUnit.team.color);
}
paramUnit.shield -= trait.damage();
@@ -56,13 +60,14 @@ public class ForceFieldAbility implements Ability{
}
if(unit.shield > 0){
unit.timer2 = Mathf.lerpDelta(unit.timer2, 1f, 0.06f);
radiusScale = Mathf.lerpDelta(radiusScale, 1f, 0.06f);
paramUnit = unit;
paramField = this;
checkRadius(unit);
Groups.bullet.intersect(unit.x - realRad, unit.y - realRad, realRad * 2f, realRad * 2f, shieldConsumer);
}else{
unit.timer2 = 0f;
radiusScale = 0f;
}
}
@@ -89,6 +94,6 @@ public class ForceFieldAbility implements Ability{
private void checkRadius(Unit unit){
//timer2 is used to store radius scale as an effect
realRad = unit.timer2 * radius;
realRad = radiusScale * radius;
}
}
@@ -5,12 +5,13 @@ import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
public class HealFieldAbility implements Ability{
public class HealFieldAbility extends Ability{
public float amount = 1, reload = 100, range = 60;
public Effect healEffect = Fx.heal;
public Effect activeEffect = Fx.healWave;
private boolean wasHealed = false;
protected float timer;
protected boolean wasHealed = false;
HealFieldAbility(){}
@@ -22,9 +23,9 @@ public class HealFieldAbility implements Ability{
@Override
public void update(Unit unit){
unit.timer1 += Time.delta;
timer += Time.delta;
if(unit.timer1 >= reload){
if(timer >= reload){
wasHealed = false;
Units.nearby(unit.team, unit.x, unit.y, range, other -> {
@@ -39,7 +40,7 @@ public class HealFieldAbility implements Ability{
activeEffect.at(unit);
}
unit.timer1 = 0f;
timer = 0f;
}
}
}
@@ -5,12 +5,13 @@ import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
public class ShieldFieldAbility implements Ability{
public class ShieldFieldAbility extends Ability{
public float amount = 1, max = 100f, reload = 100, range = 60;
public Effect applyEffect = Fx.shieldApply;
public Effect activeEffect = Fx.shieldWave;
private boolean applied = false;
protected float timer;
protected boolean applied = false;
ShieldFieldAbility(){}
@@ -23,9 +24,9 @@ public class ShieldFieldAbility implements Ability{
@Override
public void update(Unit unit){
unit.timer1 += Time.delta;
timer += Time.delta;
if(unit.timer1 >= reload){
if(timer >= reload){
applied = false;
Units.nearby(unit.team, unit.x, unit.y, range, other -> {
@@ -41,7 +42,7 @@ public class ShieldFieldAbility implements Ability{
activeEffect.at(unit);
}
unit.timer1 = 0f;
timer = 0f;
}
}
}
@@ -7,12 +7,14 @@ import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.type.*;
public class StatusFieldAbility implements Ability{
public class StatusFieldAbility extends Ability{
public @NonNull StatusEffect effect;
public float duration = 60, reload = 100, range = 20;
public Effect applyEffect = Fx.heal;
public Effect activeEffect = Fx.overdriveWave;
protected float timer;
StatusFieldAbility(){}
public StatusFieldAbility(@NonNull StatusEffect effect, float duration, float reload, float range){
@@ -24,9 +26,9 @@ public class StatusFieldAbility implements Ability{
@Override
public void update(Unit unit){
unit.timer2 += Time.delta;
timer += Time.delta;
if(unit.timer2 >= reload){
if(timer >= reload){
Units.nearby(unit.team, unit.x, unit.y, range, other -> {
other.apply(effect, duration);
@@ -34,7 +36,7 @@ public class StatusFieldAbility implements Ability{
activeEffect.at(unit);
unit.timer2 = 0f;
timer = 0f;
}
}
}
@@ -0,0 +1,60 @@
package mindustry.entities.abilities;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import mindustry.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
public class UnitSpawnAbility extends Ability{
public @NonNull UnitType type;
public float spawnTime = 60f, spawnX, spawnY;
public Effect spawnEffect = Fx.spawn;
protected float timer;
public UnitSpawnAbility(@NonNull UnitType type, float spawnTime, float spawnX, float spawnY){
this.type = type;
this.spawnTime = spawnTime;
this.spawnX = spawnX;
this.spawnY = spawnY;
}
public UnitSpawnAbility(){
}
@Override
public void update(Unit unit){
timer += Time.delta;
if(timer >= spawnTime && Units.canCreate(unit.team, type)){
float x = unit.x + Angles.trnsx(unit.rotation, spawnY, spawnX), y = unit.y + Angles.trnsy(unit.rotation, spawnY, spawnX);
spawnEffect.at(x, y);
Unit u = type.create(unit.team);
u.set(x, y);
u.rotation = unit.rotation;
if(!Vars.net.client()){
u.add();
}
timer = 0f;
}
}
@Override
public void draw(Unit unit){
if(Units.canCreate(unit.team, type)){
Draw.draw(Draw.z(), () -> {
float x = unit.x + Angles.trnsx(unit.rotation, spawnY, spawnX), y = unit.y + Angles.trnsy(unit.rotation, spawnY, spawnX);
Drawf.construct(x, y, type.icon(Cicon.full), unit.rotation - 90, timer / spawnTime, 1f, timer);
});
}
}
}
@@ -1,16 +1,17 @@
package mindustry.entities.bullet;
import arc.Core;
import arc.graphics.Color;
import arc.graphics.g2d.Draw;
import arc.graphics.g2d.TextureRegion;
import arc.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
import mindustry.gen.*;
import mindustry.graphics.Pal;
import mindustry.graphics.*;
/** An extended BulletType for most ammo-based bullets shot from turrets and units. */
public class BasicBulletType extends BulletType{
public Color backColor = Pal.bulletYellowBack, frontColor = Pal.bulletYellow;
public Color mixColorFrom = new Color(1f, 1f, 1f, 0f), mixColorTo = new Color(1f, 1f, 1f, 0f);
public float width = 5f, height = 7f;
public float shrinkX = 0f, shrinkY = 0.5f;
public float spin = 0;
@@ -45,10 +46,15 @@ public class BasicBulletType extends BulletType{
float width = this.width * ((1f - shrinkX) + shrinkX * b.fout());
float offset = -90 + (spin != 0 ? Mathf.randomSeed(b.id, 360f) + b.time * spin : 0f);
Color mix = Tmp.c1.set(mixColorFrom).lerp(mixColorTo, b.fin());
Draw.mixcol(mix, mix.a);
Draw.color(backColor);
Draw.rect(backRegion, b.x, b.y, width, height, b.rotation() + offset);
Draw.color(frontColor);
Draw.rect(frontRegion, b.x, b.y, width, height, b.rotation() + offset);
Draw.color();
Draw.reset();
}
}
@@ -24,7 +24,7 @@ public abstract class BulletType extends Content{
public float hitSize = 4;
public float drawSize = 40f;
public float drag = 0f;
public boolean pierce;
public boolean pierce, pierceBuilding;
public Effect hitEffect, despawnEffect;
/** Effect created when shooting. */
@@ -69,6 +69,8 @@ public abstract class BulletType extends Content{
public boolean scaleVelocity;
/** Whether this bullet can be hit by point defense. */
public boolean hittable = true;
/** Whether this bullet can be reflected. */
public boolean reflectable = true;
//additional effects
@@ -100,7 +102,7 @@ public abstract class BulletType extends Content{
public float weaveScale = 1f;
public float weaveMag = -1f;
public float hitShake = 0f;
public float hitShake = 0f, despawnShake = 0f;
public int puddles;
public float puddleRange;
@@ -131,10 +133,14 @@ public abstract class BulletType extends Content{
return true;
}
public void hitTile(Bullet b, Building tile){
public void hitTile(Bullet b, Building tile, float initialHealth){
hit(b);
}
public void hitEntity(Bullet b, Hitboxc other, float initialHealth){
}
public void hit(Bullet b){
hit(b, b.x, b.y);
}
@@ -181,6 +187,8 @@ public abstract class BulletType extends Content{
despawnEffect.at(b.x, b.y, b.rotation(), hitColor);
hitSound.at(b);
Effect.shake(despawnShake, despawnShake, b);
if(fragBullet != null || splashDamageRadius > 0 || lightning > 0){
hit(b);
}
@@ -43,7 +43,7 @@ public class HealBulletType extends BulletType{
}
@Override
public void hitTile(Bullet b, Building tile){
public void hitTile(Bullet b, Building tile, float initialHealth){
super.hit(b);
if(tile.team == b.team && !(tile.block instanceof ConstructBlock)){
@@ -0,0 +1,52 @@
package mindustry.entities.bullet;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
public class RailBulletType extends BulletType{
public Effect pierceEffect = Fx.hitBulletSmall, updateEffect = Fx.none;
/** Multiplier of damage decreased per health pierced. */
public float pierceDamageFactor = 1f;
public RailBulletType(){
pierceBuilding = true;
pierce = true;
reflectable = false;
hitEffect = Fx.none;
despawnEffect = Fx.none;
}
void handle(Bullet b, Posc pos, float initialHealth){
float sub = initialHealth*pierceDamageFactor;
if(sub >= b.damage){
//cause a despawn
b.remove();
}
//subtract health from each consecutive pierce
b.damage -= Math.min(b.damage, sub);
if(b.damage > 0){
pierceEffect.at(pos.getX(), pos.getY(), b.rotation());
}
hitEffect.at(pos.getX(), pos.getY());
}
@Override
public void update(Bullet b){
updateEffect.at(b.x, b.y, b.rotation());
}
@Override
public void hitEntity(Bullet b, Hitboxc entity, float initialHealth){
handle(b, entity, initialHealth);
}
@Override
public void hitTile(Bullet b, Building tile, float initialHealth){
handle(b, tile, initialHealth);
}
}
@@ -39,10 +39,15 @@ public class SapBulletType extends BulletType{
Draw.reset();
Drawf.light(b.team, b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, 15f * b.fout(), lightColor, 0.6f);
Drawf.light(b.team, b.x, b.y, Tmp.v1.x, Tmp.v1.y, 15f * b.fout(), lightColor, 0.6f);
}
}
@Override
public void drawLight(Bullet b){
}
@Override
public float range(){
return length;
@@ -108,9 +108,9 @@ abstract class BuilderComp implements Unitc{
ConstructBuild entity = tile.bc();
if(current.breaking){
entity.deconstruct(base(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier);
entity.deconstruct(self(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier);
}else{
entity.construct(base(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier, current.config);
entity.construct(self(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier, current.config);
}
current.stuck = Mathf.equal(current.progress, entity.progress);
@@ -80,7 +80,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
if(block.hasPower){
//reinit power graph
power.graph = new PowerGraph();
power.graph.add(base());
power.graph.add(self());
}
}
this.rotation = rotation;
@@ -94,7 +94,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
created();
return base();
return self();
}
/** Sets up all the necessary variables, but does not add this entity anywhere. */
@@ -111,17 +111,17 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
maxHealth(block.health);
timer(new Interval(block.timers));
cons = new ConsumeModule(base());
cons = new ConsumeModule(self());
if(block.hasItems) items = new ItemModule();
if(block.hasLiquids) liquids = new LiquidModule();
if(block.hasPower){
power = new PowerModule();
power.graph.add(base());
power.graph.add(self());
}
initialized = true;
return base();
return self();
}
@Override
@@ -195,17 +195,17 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public void configure(Object value){
//save last used config
block.lastConfig = value;
Call.tileConfig(player, base(), value);
Call.tileConfig(player, self(), value);
}
/** Configure from a server. */
public void configureAny(Object value){
Call.tileConfig(null, base(), value);
Call.tileConfig(null, self(), value);
}
/** Deselect this tile from configuration. */
public void deselect(){
if(!headless && control.input.frag.config.getSelectedTile() == base()){
if(!headless && control.input.frag.config.getSelectedTile() == self()){
control.input.frag.config.hideConfig();
}
}
@@ -372,7 +372,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Returns the amount of items this block can accept. */
public int acceptStack(Item item, int amount, Teamc source){
if(acceptItem(base(), item) && block.hasItems && (source == null || source.team() == team)){
if(acceptItem(self(), item) && block.hasItems && (source == null || source.team() == team)){
return Math.min(getMaximumAccepted(item) - items.get(item), amount);
}else{
return 0;
@@ -425,8 +425,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
int trns = block.size/2 + 1;
Tile next = tile.getNearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns);
if(next != null && next.build != null && next.build.team == team && next.build.acceptPayload(base(), todump)){
next.build.handlePayload(base(), todump);
if(next != null && next.build != null && next.build.team == team && next.build.acceptPayload(self(), todump)){
next.build.handlePayload(self(), todump);
return true;
}
@@ -446,8 +446,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){
Building other = proximity.get((i + dump) % proximity.size);
if(other.team == team && other.acceptPayload(base(), todump)){
other.handlePayload(base(), todump);
if(other.team == team && other.acceptPayload(self(), todump)){
other.handlePayload(self(), todump);
incrementDump(proximity.size);
return true;
}
@@ -480,7 +480,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size);
Building other = proximity.get((i + dump) % proximity.size);
other = other.getLiquidDestination(base(), liquid);
other = other.getLiquidDestination(self(), liquid);
if(other != null && other.team == team && other.block.hasLiquids && canDumpLiquid(other, liquid) && other.liquids != null){
float ofract = other.liquids.get(liquid) / other.block.liquidCapacity;
@@ -499,8 +499,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public void transferLiquid(Building next, float amount, Liquid liquid){
float flow = Math.min(next.block.liquidCapacity - next.liquids.get(liquid) - 0.001f, amount);
if(next.acceptLiquid(base(), liquid, flow)){
next.handleLiquid(base(), liquid, flow);
if(next.acceptLiquid(self(), liquid, flow)){
next.handleLiquid(self(), liquid, flow);
liquids.remove(liquid, flow);
}
}
@@ -523,7 +523,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public float moveLiquid(Building next, Liquid liquid){
if(next == null) return 0;
next = next.getLiquidDestination(base(), liquid);
next = next.getLiquidDestination(self(), liquid);
if(next.team == team && next.block.hasLiquids && liquids.get(liquid) > 0f){
float ofract = next.liquids.get(liquid) / next.block.liquidCapacity;
@@ -531,8 +531,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
float flow = Math.min(Mathf.clamp((fract - ofract) * (1f)) * (block.liquidCapacity), liquids.get(liquid));
flow = Math.min(flow, next.block.liquidCapacity - next.liquids.get(liquid) - 0.001f);
if(flow > 0f && ofract <= fract && next.acceptLiquid(base(), liquid, flow)){
next.handleLiquid(base(), liquid, flow);
if(flow > 0f && ofract <= fract && next.acceptLiquid(self(), liquid, flow)){
next.handleLiquid(self(), liquid, flow);
liquids.remove(liquid, flow);
return flow;
}else if(next.liquids.currentAmount() / next.block.liquidCapacity > 0.1f && fract > 0.1f){
@@ -558,7 +558,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
public Building getLiquidDestination(Building from, Liquid liquid){
return base();
return self();
}
public @Nullable Payload getPayload(){
@@ -580,13 +580,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size);
Building other = proximity.get((i + dump) % proximity.size);
if(other.team == team && other.acceptItem(base(), item) && canDump(other, item)){
other.handleItem(base(), item);
if(other.team == team && other.acceptItem(self(), item) && canDump(other, item)){
other.handleItem(self(), item);
return;
}
}
handleItem(base(), item);
handleItem(self(), item);
}
/**
@@ -598,8 +598,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size);
Building other = proximity.get((i + dump) % proximity.size);
if(other.team == team && other.acceptItem(base(), item) && canDump(other, item)){
other.handleItem(base(), item);
if(other.team == team && other.acceptItem(self(), item) && canDump(other, item)){
other.handleItem(self(), item);
return true;
}
}
@@ -631,16 +631,16 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int ii = 0; ii < content.items().size; ii++){
Item item = content.item(ii);
if(other.team == team && items.has(item) && other.acceptItem(base(), item) && canDump(other, item)){
other.handleItem(base(), item);
if(other.team == team && items.has(item) && other.acceptItem(self(), item) && canDump(other, item)){
other.handleItem(self(), item);
items.remove(item, 1);
incrementDump(proximity.size);
return true;
}
}
}else{
if(other.team == team && other.acceptItem(base(), todump) && canDump(other, todump)){
other.handleItem(base(), todump);
if(other.team == team && other.acceptItem(self(), todump) && canDump(other, todump)){
other.handleItem(self(), todump);
items.remove(todump, 1);
incrementDump(proximity.size);
return true;
@@ -665,8 +665,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Try offloading an item to a nearby container in its facing direction. Returns true if success. */
public boolean moveForward(Item item){
Building other = front();
if(other != null && other.team == team && other.acceptItem(base(), item)){
other.handleItem(base(), item);
if(other != null && other.team == team && other.acceptItem(self(), item)){
other.handleItem(self(), item);
return true;
}
return false;
@@ -696,7 +696,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
return;
}
power.graph.remove(base());
power.graph.remove(self());
for(int i = 0; i < power.links.size; i++){
Tile other = world.tile(power.links.get(i));
if(other != null && other.build != null && other.build.power != null){
@@ -833,8 +833,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
tempTiles.clear();
Geometry.circle(tileX(), tileY(), range, (x, y) -> {
Building other = world.build(x, y);
if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, base()) && !PowerNode.insulated(other, base())
&& !other.proximity().contains(this.<Building>base()) &&
if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, self()) && !PowerNode.insulated(other, self())
&& !other.proximity().contains(this.<Building>self()) &&
!(block.outputsPower && proximity.contains(p -> p.power != null && p.power.graph == other.power.graph))){
tempTiles.add(other.tile);
}
@@ -1037,13 +1037,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
table.left();
for(Consume cons : block.consumes.all()){
if(cons.isOptional() && cons.isBoost()) continue;
cons.build(base(), table);
cons.build(self(), table);
}
}
public void displayBars(Table table){
for(Func<Building, Bar> bar : block.bars.list()){
table.add(bar.get(base())).growX();
table.add(bar.get(self())).growX();
table.row();
}
}
@@ -1069,7 +1069,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
* @return whether or not this block should be deselected.
*/
public boolean onConfigureTileTapped(Building other){
return base() != other;
return self() != other;
}
/** Returns whether this config menu should show when the specified player taps it. */
@@ -1128,7 +1128,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
for(Building other : tmpTiles){
other.proximity.remove(base(), true);
other.proximity.remove(self(), true);
other.onProximityUpdate();
}
}
@@ -1144,8 +1144,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
if(other == null || !(other.tile.interactable(team))) continue;
//add this tile to proximity of nearby tiles
if(!other.proximity.contains(base(), true)){
other.proximity.add(base());
if(!other.proximity.contains(self(), true)){
other.proximity.add(self());
}
tmpTiles.add(other);
@@ -1184,13 +1184,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
@Replace
@Override
public boolean isValid(){
return tile.build == base() && !dead();
return tile.build == self() && !dead();
}
@Replace
@Override
public void kill(){
Call.tileDestroyed(base());
Call.tileDestroyed(self());
}
@Replace
@@ -1204,10 +1204,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
damage /= state.rules.blockHealthMultiplier;
}
Call.tileDamage(base(), health - handleDamage(damage));
Call.tileDamage(self(), health - handleDamage(damage));
if(health <= 0){
Call.tileDestroyed(base());
Call.tileDestroyed(self());
}
}
@@ -1292,7 +1292,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
if(block.idleSound != Sounds.none && shouldIdleSound()){
loops.play(block.idleSound, base(), block.idleSoundVolume);
loops.play(block.idleSound, self(), block.idleSoundVolume);
}
if(enabled || !block.noUpdateDisabled){
@@ -44,17 +44,17 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
@Override
public void drawBullets(){
type.draw(base());
type.draw(self());
}
@Override
public void add(){
type.init(base());
type.init(self());
}
@Override
public void remove(){
type.despawned(base());
type.despawned(self());
collided.clear();
}
@@ -92,10 +92,12 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
@MethodPriority(100)
@Override
public void collision(Hitboxc other, float x, float y){
type.hit(base(), x, y);
type.hit(self(), x, y);
float health = 0f;
if(other instanceof Healthc){
Healthc h = (Healthc)other;
health = h.health();
h.damage(damage);
}
@@ -111,30 +113,40 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
}else{
collided.add(other.id());
}
type.hitEntity(self(), other, health);
}
@Override
public void update(){
type.update(base());
type.update(self());
if(type.collidesTiles && type.collides && type.collidesGround){
world.raycastEach(world.toTile(lastX()), world.toTile(lastY()), tileX(), tileY(), (x, y) -> {
Building tile = world.build(x, y);
if(tile == null) return false;
if(tile == null || !isAdded()) return false;
if(tile.collide(base()) && type.collides(base(), tile) && !tile.dead() && (type.collidesTeam || tile.team != team)){
if(tile.collide(self()) && type.collides(self(), tile) && !tile.dead() && (type.collidesTeam || tile.team != team) && !(type.pierceBuilding && collided.contains(tile.id))){
boolean remove = false;
float health = tile.health;
if(tile.team != team){
remove = tile.collision(base());
remove = tile.collision(self());
}
if(remove || type.collidesTeam){
type.hitTile(base(), tile);
remove();
if(!type.pierceBuilding){
remove();
}else{
collided.add(tile.id);
}
}
return true;
type.hitTile(self(), tile, health);
return !type.pierceBuilding;
}
return false;
@@ -146,8 +158,8 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
public void draw(){
Draw.z(Layer.bullet);
type.draw(base());
type.drawLight(base());
type.draw(self());
type.drawLight(self());
}
/** Sets the bullet's rotation in degrees. */

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