Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5fd66d38bb | ||
|
|
15f33b45c7 | ||
|
|
17e66f1008 | ||
|
|
bcaf5e4c3d | ||
|
|
6fd36d97f0 | ||
|
|
61bec243dc | ||
|
|
7d43856735 | ||
|
|
058b2ddfce | ||
|
|
2282cb89b1 | ||
|
|
06929ee8f3 | ||
|
|
ec19381c4e | ||
|
|
4a52392ce9 | ||
|
|
dcbe06229c | ||
|
|
075be1a862 | ||
|
|
8d91a9b014 | ||
|
|
ecea8eab01 | ||
|
|
3db2fea32b | ||
|
|
335e7489ce |
2
.github/workflows/deployment.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
java-version: 14
|
java-version: 14
|
||||||
- name: Create artifacts
|
- name: Create artifacts
|
||||||
run: |
|
run: |
|
||||||
./gradlew desktop:dist server:dist core:javadoc -Pbuildversion=${GITHUB_REF:1}"
|
./gradlew desktop:dist server:dist core:javadoc -Pbuildversion=${GITHUB_REF:1}
|
||||||
- name: Update docs
|
- name: Update docs
|
||||||
run: |
|
run: |
|
||||||
cd ../
|
cd ../
|
||||||
|
|||||||
BIN
core/assets-raw/sprites/blocks/props/basalt-boulder1.png
Normal file
|
After Width: | Height: | Size: 682 B |
BIN
core/assets-raw/sprites/blocks/props/basalt-boulder2.png
Normal file
|
After Width: | Height: | Size: 683 B |
@@ -22,7 +22,6 @@ gameover.pvp = The[accent] {0}[] team is victorious!
|
|||||||
gameover.waiting = [accent]Waiting for next map...
|
gameover.waiting = [accent]Waiting for next map...
|
||||||
highscore = [accent]New highscore!
|
highscore = [accent]New highscore!
|
||||||
copied = Copied.
|
copied = Copied.
|
||||||
indev.popup = [accent]v6[] is currently in [accent]beta[].\n[lightgray]This means:[]\n[scarlet]- The campaign is 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
|
indev.notready = This part of the game isn't ready yet
|
||||||
indev.campaign = [accent]You've reached the end of the campaign![]\n\nThis is as far as the content goes. Interplanetary travel will be added in future updates.
|
indev.campaign = [accent]You've reached the end of the campaign![]\n\nThis is as far as the content goes. Interplanetary travel will be added in future updates.
|
||||||
|
|
||||||
@@ -147,6 +146,7 @@ planetmap = Planet Map
|
|||||||
launchcore = Launch Core
|
launchcore = Launch Core
|
||||||
filename = File Name:
|
filename = File Name:
|
||||||
unlocked = New content unlocked!
|
unlocked = New content unlocked!
|
||||||
|
available = New research available!
|
||||||
completed = [accent]Completed
|
completed = [accent]Completed
|
||||||
techtree = Tech Tree
|
techtree = Tech Tree
|
||||||
research.list = [lightgray]Research:
|
research.list = [lightgray]Research:
|
||||||
@@ -501,7 +501,6 @@ map.multiplayer = Only the host can view sectors.
|
|||||||
uncover = Uncover
|
uncover = Uncover
|
||||||
configure = Configure Loadout
|
configure = Configure Loadout
|
||||||
|
|
||||||
#TODO
|
|
||||||
loadout = Loadout
|
loadout = Loadout
|
||||||
resources = Resources
|
resources = Resources
|
||||||
bannedblocks = Banned Blocks
|
bannedblocks = Banned Blocks
|
||||||
@@ -509,12 +508,6 @@ addall = Add All
|
|||||||
launch.from = Launching From: [accent]{0}
|
launch.from = Launching From: [accent]{0}
|
||||||
launch.destination = Destination: {0}
|
launch.destination = Destination: {0}
|
||||||
configure.invalid = Amount must be a number between 0 and {0}.
|
configure.invalid = Amount must be a number between 0 and {0}.
|
||||||
zone.unlocked = [lightgray]{0} unlocked.
|
|
||||||
zone.requirement.complete = Requirement for {0} completed:[lightgray]\n{1}
|
|
||||||
zone.resources = [lightgray]Resources Detected:
|
|
||||||
zone.objective = [lightgray]Objective: [accent]{0}
|
|
||||||
zone.objective.survival = Survive
|
|
||||||
zone.objective.attack = Destroy Enemy Core
|
|
||||||
add = Add...
|
add = Add...
|
||||||
boss.health = Guardian Health
|
boss.health = Guardian Health
|
||||||
|
|
||||||
@@ -600,6 +593,11 @@ sector.tarFields.description = The outskirts of an oil production zone, between
|
|||||||
sector.desolateRift.description = An extremely dangerous zone. Plentiful resources, but little space. High risk of destruction. Leave as soon as possible. Do not be fooled by the long spacing between enemy attacks.
|
sector.desolateRift.description = An extremely dangerous zone. Plentiful resources, but little space. High risk of destruction. Leave as soon as possible. Do not be fooled by the long spacing between enemy attacks.
|
||||||
sector.nuclearComplex.description = A former facility for the production and processing of thorium, reduced to ruins.\n[lightgray]Research the thorium and its many uses.\n\nThe enemy is present here in great numbers, constantly scouting for attackers.
|
sector.nuclearComplex.description = A former facility for the production and processing of thorium, reduced to ruins.\n[lightgray]Research the thorium and its many uses.\n\nThe enemy is present here in great numbers, constantly scouting for attackers.
|
||||||
sector.fungalPass.description = A transition area between high mountains and lower, spore-ridden lands. A small enemy reconnaissance base is located here.\nDestroy it.\nUse Dagger and Crawler units. Take out the two cores.
|
sector.fungalPass.description = A transition area between high mountains and lower, spore-ridden lands. A small enemy reconnaissance base is located here.\nDestroy it.\nUse Dagger and Crawler units. Take out the two cores.
|
||||||
|
sector.biomassFacility.description = The origin of spores. This is the facility in which they were researched and initially produced.\nResearch the technology contained within. Cultivate spores for the production of fuel and plastics.\n\n[lightgray]Upon this facility's demise, the spores were released. Nothing in the local ecosystem could compete with such an invasive organism.
|
||||||
|
sector.windsweptIslands.description = Further past the shoreline is this remote chain of islands. Records show they once had [accent]Plastanium[]-producing structures.\n\nFend off the enemy's naval units. Establish a base on the islands. Research these factories.
|
||||||
|
sector.extractionOutpost.description = A remote outpost, constructed by the enemy for the purpose of launching resources to other sectors.\n\nCross-sector transport technology is essential for further conquest. Destroy the base. Research their Launch Pads.
|
||||||
|
sector.impact0078.description = Here lie remnants of the interstellar transport vessel that first entered this system.\n\nSalvage as much as possible from the wreckage. Research any intact technology.
|
||||||
|
sector.planetaryTerminal.description = The final target.\n\nThis coastal base contains a structure capable of launching Cores to local planets. It is extremely well guarded.\n\nProduce naval units. Eliminate the enemy as quickly as possible. Research the launch structure.
|
||||||
|
|
||||||
settings.language = Language
|
settings.language = Language
|
||||||
settings.data = Game Data
|
settings.data = Game Data
|
||||||
@@ -813,7 +811,7 @@ setting.smoothcamera.name = Smooth Camera
|
|||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.pixelate.name = Pixelate
|
setting.pixelate.name = Pixelate
|
||||||
setting.minimap.name = Show Minimap
|
setting.minimap.name = Show Minimap
|
||||||
setting.coreitems.name = Display Core Items (WIP)
|
setting.coreitems.name = Display Core Items
|
||||||
setting.position.name = Show Player Position
|
setting.position.name = Show Player Position
|
||||||
setting.musicvol.name = Music Volume
|
setting.musicvol.name = Music Volume
|
||||||
setting.atmosphere.name = Show Planet Atmosphere
|
setting.atmosphere.name = Show Planet Atmosphere
|
||||||
@@ -894,6 +892,7 @@ keybind.pause.name = Pause
|
|||||||
keybind.pause_building.name = Pause/Resume Building
|
keybind.pause_building.name = Pause/Resume Building
|
||||||
keybind.minimap.name = Minimap
|
keybind.minimap.name = Minimap
|
||||||
keybind.planet_map.name = Planet Map
|
keybind.planet_map.name = Planet Map
|
||||||
|
keybind.research.name = Research
|
||||||
keybind.chat.name = Chat
|
keybind.chat.name = Chat
|
||||||
keybind.player_list.name = Player List
|
keybind.player_list.name = Player List
|
||||||
keybind.console.name = Console
|
keybind.console.name = Console
|
||||||
@@ -1018,6 +1017,7 @@ block.resupply-point.name = Resupply Point
|
|||||||
block.parallax.name = Parallax
|
block.parallax.name = Parallax
|
||||||
block.cliff.name = Cliff
|
block.cliff.name = Cliff
|
||||||
block.sand-boulder.name = Sand Boulder
|
block.sand-boulder.name = Sand Boulder
|
||||||
|
block.basalt-boulder.name = Basalt Boulder
|
||||||
block.grass.name = Grass
|
block.grass.name = Grass
|
||||||
block.slag.name = Slag
|
block.slag.name = Slag
|
||||||
block.space.name = Space
|
block.space.name = Space
|
||||||
@@ -1266,13 +1266,15 @@ hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and
|
|||||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||||
hint.conveyorPathfind.mobile = Enable \ue844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
hint.conveyorPathfind.mobile = Enable \ue844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
||||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||||
hint.command = Press [accent][[G][] to command nearby units into formation.
|
hint.command = Press [accent][[G][] to command nearby units of [accent]similar type[] into formation.\n\nTo command ground units, you must first control another ground unit.
|
||||||
hint.command.mobile = [accent][[Double-tap][] your unit to command nearby units into formation.
|
hint.command.mobile = [accent][[Double-tap][] your unit to command nearby units into formation.
|
||||||
hint.payloadPickup = Press [accent][[[] to pick up small blocks or units.
|
hint.payloadPickup = Press [accent][[[] to pick up small blocks or units.
|
||||||
hint.payloadPickup.mobile = [accent]Tap and hold[] a small block or unit to pick it up.
|
hint.payloadPickup.mobile = [accent]Tap and hold[] a small block or unit to pick it up.
|
||||||
hint.payloadDrop = Press [accent]][] to drop a payload.
|
hint.payloadDrop = Press [accent]][] to drop a payload.
|
||||||
hint.payloadDrop.mobile = [accent]Tap and hold[] an empty location to drop a payload there.
|
hint.payloadDrop.mobile = [accent]Tap and hold[] an empty location to drop a payload there.
|
||||||
hint.waveFire = [accent]Wave[] turrets with water as ammunition will automatically put out nearby fires.
|
hint.waveFire = [accent]Wave[] turrets with water as ammunition will automatically put out nearby fires.
|
||||||
|
hint.generator = \uf879 [accent]Combustion Generators[] burn coal and transmit power to adjacent blocks.\n\nPower transmission range can be extended with \uf87f [accent]Power Nodes[].
|
||||||
|
hint.guardian = [accent]Guardian[] units are armored. Weak ammo such as [accent]Copper[] and [accent]Lead[] is [scarlet]not effective[].\n\nUse higher tier turrets or \uf835 [accent]Graphite[] \uf861Duo/\uf859Salvo ammunition to take Guardians down.
|
||||||
|
|
||||||
item.copper.description = Used in all types of construction and ammunition.
|
item.copper.description = Used in all types of construction and ammunition.
|
||||||
item.copper.details = Copper. Abnormally abundant metal on Serpulo. Structurally weak unless reinforced.
|
item.copper.details = Copper. Abnormally abundant metal on Serpulo. Structurally weak unless reinforced.
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ sectors.rename = Переименовать сектор
|
|||||||
sectors.enemybase = [scarlet]Вражеская база
|
sectors.enemybase = [scarlet]Вражеская база
|
||||||
sectors.vulnerable = [scarlet]Уязвим
|
sectors.vulnerable = [scarlet]Уязвим
|
||||||
sectors.underattack = [scarlet]Атакован! [accent]{0}% повреждений
|
sectors.underattack = [scarlet]Атакован! [accent]{0}% повреждений
|
||||||
sectors.survives = [accent]Продержался {0} волн(ы)
|
sectors.survives = [accent]Продержиться {0} волн(ы)
|
||||||
|
|
||||||
sector.curcapture = Сектор захвачен
|
sector.curcapture = Сектор захвачен
|
||||||
sector.curlost = Сектор потерян
|
sector.curlost = Сектор потерян
|
||||||
|
|||||||
@@ -317,3 +317,4 @@
|
|||||||
63419=legacy-unit-factory-air|block-legacy-unit-factory-air-medium
|
63419=legacy-unit-factory-air|block-legacy-unit-factory-air-medium
|
||||||
63418=legacy-unit-factory-ground|block-legacy-unit-factory-ground-medium
|
63418=legacy-unit-factory-ground|block-legacy-unit-factory-ground-medium
|
||||||
63417=interplanetary-accelerator|block-interplanetary-accelerator-medium
|
63417=interplanetary-accelerator|block-interplanetary-accelerator-medium
|
||||||
|
63416=basalt-boulder|block-basalt-boulder-medium
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 828 B After Width: | Height: | Size: 831 B |
|
Before Width: | Height: | Size: 675 KiB After Width: | Height: | Size: 667 KiB |
|
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 437 KiB After Width: | Height: | Size: 440 KiB |
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 3.0 MiB After Width: | Height: | Size: 3.0 MiB |
|
Before Width: | Height: | Size: 187 KiB After Width: | Height: | Size: 187 KiB |
|
Before Width: | Height: | Size: 438 KiB After Width: | Height: | Size: 438 KiB |
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
@@ -88,7 +88,7 @@ public class Vars implements Loadable{
|
|||||||
/** duration of time between turns in ticks */
|
/** duration of time between turns in ticks */
|
||||||
public static final float turnDuration = 2 * Time.toMinutes;
|
public static final float turnDuration = 2 * Time.toMinutes;
|
||||||
/** chance of an invasion per turn, 1 = 100% */
|
/** chance of an invasion per turn, 1 = 100% */
|
||||||
public static final float baseInvasionChance = 1f / 50f;
|
public static final float baseInvasionChance = 1f / 75f;
|
||||||
/** how many turns have to pass before invasions start */
|
/** how many turns have to pass before invasions start */
|
||||||
public static final int invasionGracePeriod = 20;
|
public static final int invasionGracePeriod = 20;
|
||||||
/** min armor fraction damage; e.g. 0.05 = at least 5% damage */
|
/** min armor fraction damage; e.g. 0.05 = at least 5% damage */
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import mindustry.gen.*;
|
|||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.defense.*;
|
import mindustry.world.blocks.defense.*;
|
||||||
|
import mindustry.world.blocks.distribution.*;
|
||||||
import mindustry.world.blocks.production.*;
|
import mindustry.world.blocks.production.*;
|
||||||
import mindustry.world.blocks.storage.*;
|
import mindustry.world.blocks.storage.*;
|
||||||
import mindustry.world.blocks.storage.CoreBlock.*;
|
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||||
@@ -271,6 +272,10 @@ public class BaseAI{
|
|||||||
}
|
}
|
||||||
|
|
||||||
Tile o = world.tile(tile.x + p.x, tile.y + p.y);
|
Tile o = world.tile(tile.x + p.x, tile.y + p.y);
|
||||||
|
if(o != null && (o.block() instanceof PayloadAcceptor || o.block() instanceof PayloadConveyor)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(o != null && o.team() == data.team && !(o.block() instanceof Wall)){
|
if(o != null && o.team() == data.team && !(o.block() instanceof Wall)){
|
||||||
any = true;
|
any = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package mindustry.ai.types;
|
package mindustry.ai.types;
|
||||||
|
|
||||||
|
import arc.math.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
@@ -45,7 +46,7 @@ public class BuilderAI extends AIController{
|
|||||||
BuildPlan req = unit.buildPlan();
|
BuildPlan req = unit.buildPlan();
|
||||||
|
|
||||||
boolean valid =
|
boolean valid =
|
||||||
(req.tile().build instanceof ConstructBuild && req.tile().<ConstructBuild>bc().cblock == req.block) ||
|
(req.tile() != null && req.tile().build instanceof ConstructBuild && req.tile().<ConstructBuild>bc().cblock == req.block) ||
|
||||||
(req.breaking ?
|
(req.breaking ?
|
||||||
Build.validBreak(unit.team(), req.x, req.y) :
|
Build.validBreak(unit.team(), req.x, req.y) :
|
||||||
Build.validPlace(req.block, unit.team(), req.x, req.y, req.rotation));
|
Build.validPlace(req.block, unit.team(), req.x, req.y, req.rotation));
|
||||||
@@ -83,8 +84,10 @@ public class BuilderAI extends AIController{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float rebuildTime = (unit.team.rules().ai ? Mathf.lerp(15f, 2f, unit.team.rules().aiTier) : 2f) * 60f;
|
||||||
|
|
||||||
//find new request
|
//find new request
|
||||||
if(!unit.team.data().blocks.isEmpty() && following == null && timer.get(timerTarget3, 60 * 2f)){
|
if(!unit.team.data().blocks.isEmpty() && following == null && timer.get(timerTarget3, rebuildTime)){
|
||||||
Queue<BlockPlan> blocks = unit.team.data().blocks;
|
Queue<BlockPlan> blocks = unit.team.data().blocks;
|
||||||
BlockPlan block = blocks.first();
|
BlockPlan block = blocks.first();
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public class Blocks implements ContentList{
|
|||||||
//environment
|
//environment
|
||||||
air, spawn, cliff, deepwater, water, taintedWater, tar, slag, stone, craters, charr, sand, darksand, dirt, mud, ice, snow, darksandTaintedWater, space,
|
air, spawn, cliff, deepwater, water, taintedWater, tar, slag, stone, craters, charr, sand, darksand, dirt, mud, ice, snow, darksandTaintedWater, space,
|
||||||
dacite, stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster,
|
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, boulder, snowBoulder, grass, salt,
|
iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, shaleBoulder, sandBoulder, daciteBoulder, boulder, snowBoulder, basaltBoulder, grass, salt,
|
||||||
metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, basalt, magmarock, hotrock, snowWall, saltWall,
|
metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, basalt, magmarock, hotrock, snowWall, saltWall,
|
||||||
darkPanel1, darkPanel2, darkPanel3, darkPanel4, darkPanel5, darkPanel6, darkMetal,
|
darkPanel1, darkPanel2, darkPanel3, darkPanel4, darkPanel5, darkPanel6, darkMetal,
|
||||||
pebbles, tendrils,
|
pebbles, tendrils,
|
||||||
@@ -363,7 +363,7 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
sandWall = new StaticWall("sand-wall"){{
|
sandWall = new StaticWall("sand-wall"){{
|
||||||
variants = 2;
|
variants = 2;
|
||||||
sandWater.asFloor().wall = this;
|
sandWater.asFloor().wall = water.asFloor().wall = deepwater.asFloor().wall = this;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
saltWall = new StaticWall("salt-wall");
|
saltWall = new StaticWall("salt-wall");
|
||||||
@@ -415,6 +415,10 @@ public class Blocks implements ContentList{
|
|||||||
variants = 2;
|
variants = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
basaltBoulder = new Boulder("basalt-boulder"){{
|
||||||
|
variants = 2;
|
||||||
|
}};
|
||||||
|
|
||||||
moss = new Floor("moss"){{
|
moss = new Floor("moss"){{
|
||||||
variants = 3;
|
variants = 3;
|
||||||
attributes.set(Attribute.spores, 0.15f);
|
attributes.set(Attribute.spores, 0.15f);
|
||||||
@@ -1153,7 +1157,7 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
battery = new Battery("battery"){{
|
battery = new Battery("battery"){{
|
||||||
requirements(Category.power, with(Items.copper, 4, Items.lead, 20));
|
requirements(Category.power, with(Items.copper, 5, Items.lead, 20));
|
||||||
consumes.powerBuffered(4000f);
|
consumes.powerBuffered(4000f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -1191,7 +1195,7 @@ public class Blocks implements ContentList{
|
|||||||
size = 2;
|
size = 2;
|
||||||
|
|
||||||
ambientSound = Sounds.smelter;
|
ambientSound = Sounds.smelter;
|
||||||
ambientSoundVolume = 0.05f;
|
ambientSoundVolume = 0.06f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
differentialGenerator = new SingleTypeGenerator("differential-generator"){{
|
differentialGenerator = new SingleTypeGenerator("differential-generator"){{
|
||||||
@@ -1354,7 +1358,7 @@ public class Blocks implements ContentList{
|
|||||||
//region storage
|
//region storage
|
||||||
|
|
||||||
coreShard = new CoreBlock("core-shard"){{
|
coreShard = new CoreBlock("core-shard"){{
|
||||||
requirements(Category.effect, BuildVisibility.editorOnly, with(Items.copper, 1000, Items.lead, 1000));
|
requirements(Category.effect, BuildVisibility.editorOnly, with(Items.copper, 1000, Items.lead, 800));
|
||||||
alwaysUnlocked = true;
|
alwaysUnlocked = true;
|
||||||
|
|
||||||
unitType = UnitTypes.alpha;
|
unitType = UnitTypes.alpha;
|
||||||
@@ -1373,7 +1377,7 @@ public class Blocks implements ContentList{
|
|||||||
itemCapacity = 9000;
|
itemCapacity = 9000;
|
||||||
size = 4;
|
size = 4;
|
||||||
|
|
||||||
unitCapModifier = 14;
|
unitCapModifier = 16;
|
||||||
researchCostMultiplier = 0.04f;
|
researchCostMultiplier = 0.04f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -1385,7 +1389,7 @@ public class Blocks implements ContentList{
|
|||||||
itemCapacity = 13000;
|
itemCapacity = 13000;
|
||||||
size = 5;
|
size = 5;
|
||||||
|
|
||||||
unitCapModifier = 20;
|
unitCapModifier = 24;
|
||||||
researchCostMultiplier = 0.05f;
|
researchCostMultiplier = 0.05f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -1513,12 +1517,12 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
lancer = new ChargeTurret("lancer"){{
|
lancer = new ChargeTurret("lancer"){{
|
||||||
requirements(Category.turret, with(Items.copper, 25, Items.lead, 50, Items.silicon, 45));
|
requirements(Category.turret, with(Items.copper, 25, Items.lead, 50, Items.silicon, 45));
|
||||||
range = 155f;
|
range = 165f;
|
||||||
chargeTime = 50f;
|
chargeTime = 40f;
|
||||||
chargeMaxDelay = 30f;
|
chargeMaxDelay = 30f;
|
||||||
chargeEffects = 7;
|
chargeEffects = 7;
|
||||||
recoilAmount = 2f;
|
recoilAmount = 2f;
|
||||||
reloadTime = 90f;
|
reloadTime = 80f;
|
||||||
cooldown = 0.03f;
|
cooldown = 0.03f;
|
||||||
powerUse = 6f;
|
powerUse = 6f;
|
||||||
shootShake = 2f;
|
shootShake = 2f;
|
||||||
@@ -1540,6 +1544,7 @@ public class Blocks implements ContentList{
|
|||||||
lifetime = 16f;
|
lifetime = 16f;
|
||||||
drawSize = 400f;
|
drawSize = 400f;
|
||||||
collidesAir = false;
|
collidesAir = false;
|
||||||
|
length = 173f;
|
||||||
}};
|
}};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -1553,7 +1558,7 @@ public class Blocks implements ContentList{
|
|||||||
reloadTime = 35f;
|
reloadTime = 35f;
|
||||||
shootCone = 40f;
|
shootCone = 40f;
|
||||||
rotateSpeed = 8f;
|
rotateSpeed = 8f;
|
||||||
powerUse = 3f;
|
powerUse = 3.3f;
|
||||||
targetAir = false;
|
targetAir = false;
|
||||||
range = 90f;
|
range = 90f;
|
||||||
shootEffect = Fx.lightningShoot;
|
shootEffect = Fx.lightningShoot;
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ public class Items implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
surgeAlloy = new Item("surge-alloy", Color.valueOf("f3e979")){{
|
surgeAlloy = new Item("surge-alloy", Color.valueOf("f3e979")){{
|
||||||
|
cost = 1.2f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
sporePod = new Item("spore-pod", Color.valueOf("7457ce")){{
|
sporePod = new Item("spore-pod", Color.valueOf("7457ce")){{
|
||||||
|
|||||||
@@ -24,10 +24,11 @@ public class SectorPresets implements ContentList{
|
|||||||
|
|
||||||
saltFlats = new SectorPreset("saltFlats", serpulo, 101){{
|
saltFlats = new SectorPreset("saltFlats", serpulo, 101){{
|
||||||
difficulty = 5;
|
difficulty = 5;
|
||||||
|
useAI = false;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
frozenForest = new SectorPreset("frozenForest", serpulo, 86){{
|
frozenForest = new SectorPreset("frozenForest", serpulo, 86){{
|
||||||
captureWave = 20;
|
captureWave = 15;
|
||||||
difficulty = 2;
|
difficulty = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ public class TechTree implements ContentList{
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
node(waterExtractor, () -> {
|
node(waterExtractor, Seq.with(new SectorComplete(saltFlats)), () -> {
|
||||||
node(oilExtractor, () -> {
|
node(oilExtractor, () -> {
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -198,12 +198,12 @@ public class TechTree implements ContentList{
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
node(illuminator, () -> {
|
node(illuminator, () -> {
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
node(combustionGenerator, Seq.with(new Research(Items.coal)), () -> {
|
node(combustionGenerator, Seq.with(new Research(Items.coal)), () -> {
|
||||||
@@ -421,7 +421,7 @@ public class TechTree implements ContentList{
|
|||||||
});
|
});
|
||||||
|
|
||||||
node(additiveReconstructor, Seq.with(new SectorComplete(biomassFacility)), () -> {
|
node(additiveReconstructor, Seq.with(new SectorComplete(biomassFacility)), () -> {
|
||||||
node(multiplicativeReconstructor, Seq.with(new SectorComplete(overgrowth)), () -> {
|
node(multiplicativeReconstructor, () -> {
|
||||||
node(exponentialReconstructor, () -> {
|
node(exponentialReconstructor, () -> {
|
||||||
node(tetrativeReconstructor, () -> {
|
node(tetrativeReconstructor, () -> {
|
||||||
|
|
||||||
@@ -484,6 +484,7 @@ public class TechTree implements ContentList{
|
|||||||
new Research(bryde),
|
new Research(bryde),
|
||||||
new Research(spectre),
|
new Research(spectre),
|
||||||
new Research(launchPad),
|
new Research(launchPad),
|
||||||
|
new Research(massDriver),
|
||||||
new Research(impactReactor),
|
new Research(impactReactor),
|
||||||
new Research(additiveReconstructor),
|
new Research(additiveReconstructor),
|
||||||
new Research(exponentialReconstructor)
|
new Research(exponentialReconstructor)
|
||||||
@@ -507,7 +508,9 @@ public class TechTree implements ContentList{
|
|||||||
|
|
||||||
node(saltFlats, Seq.with(
|
node(saltFlats, Seq.with(
|
||||||
new SectorComplete(windsweptIslands),
|
new SectorComplete(windsweptIslands),
|
||||||
|
new Research(commandCenter),
|
||||||
new Research(groundFactory),
|
new Research(groundFactory),
|
||||||
|
new Research(additiveReconstructor),
|
||||||
new Research(airFactory),
|
new Research(airFactory),
|
||||||
new Research(door),
|
new Research(door),
|
||||||
new Research(waterExtractor)
|
new Research(waterExtractor)
|
||||||
@@ -551,7 +554,9 @@ public class TechTree implements ContentList{
|
|||||||
node(nuclearComplex, Seq.with(
|
node(nuclearComplex, Seq.with(
|
||||||
new SectorComplete(fungalPass),
|
new SectorComplete(fungalPass),
|
||||||
new Research(thermalGenerator),
|
new Research(thermalGenerator),
|
||||||
new Research(laserDrill)
|
new Research(laserDrill),
|
||||||
|
new Research(Items.plastanium),
|
||||||
|
new Research(swarmer)
|
||||||
), () -> {
|
), () -> {
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -613,12 +618,14 @@ public class TechTree implements ContentList{
|
|||||||
});
|
});
|
||||||
|
|
||||||
nodeProduce(Liquids.oil, () -> {
|
nodeProduce(Liquids.oil, () -> {
|
||||||
|
nodeProduce(Items.plastanium, () -> {
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setup(){
|
public static void setup(){
|
||||||
@@ -641,7 +648,7 @@ public class TechTree implements ContentList{
|
|||||||
static TechNode node(UnlockableContent content, ItemStack[] requirements, Seq<Objective> objectives, Runnable children){
|
static TechNode node(UnlockableContent content, ItemStack[] requirements, Seq<Objective> objectives, Runnable children){
|
||||||
TechNode node = new TechNode(context, content, requirements);
|
TechNode node = new TechNode(context, content, requirements);
|
||||||
if(objectives != null){
|
if(objectives != null){
|
||||||
node.objectives = objectives;
|
node.objectives.addAll(objectives);
|
||||||
}
|
}
|
||||||
|
|
||||||
TechNode prev = context;
|
TechNode prev = context;
|
||||||
|
|||||||
@@ -556,7 +556,7 @@ public class UnitTypes implements ContentList{
|
|||||||
range = 40f;
|
range = 40f;
|
||||||
|
|
||||||
weapons.add(new Weapon(){{
|
weapons.add(new Weapon(){{
|
||||||
reload = 12f;
|
reload = 24f;
|
||||||
shootCone = 180f;
|
shootCone = 180f;
|
||||||
ejectEffect = Fx.none;
|
ejectEffect = Fx.none;
|
||||||
shootSound = Sounds.explosion;
|
shootSound = Sounds.explosion;
|
||||||
@@ -1321,7 +1321,7 @@ public class UnitTypes implements ContentList{
|
|||||||
sprite = "large-bomb";
|
sprite = "large-bomb";
|
||||||
width = height = 120/4f;
|
width = height = 120/4f;
|
||||||
|
|
||||||
range = 30f;
|
maxRange = 30f;
|
||||||
ignoreRotation = true;
|
ignoreRotation = true;
|
||||||
|
|
||||||
backColor = Pal.heal;
|
backColor = Pal.heal;
|
||||||
@@ -1413,12 +1413,12 @@ public class UnitTypes implements ContentList{
|
|||||||
ejectEffect = Fx.casing1;
|
ejectEffect = Fx.casing1;
|
||||||
shootSound = Sounds.missile;
|
shootSound = Sounds.missile;
|
||||||
bullet = new MissileBulletType(2.7f, 12, "missile"){{
|
bullet = new MissileBulletType(2.7f, 12, "missile"){{
|
||||||
|
keepVelocity = true;
|
||||||
width = 8f;
|
width = 8f;
|
||||||
height = 8f;
|
height = 8f;
|
||||||
shrinkY = 0f;
|
shrinkY = 0f;
|
||||||
drag = -0.003f;
|
drag = -0.003f;
|
||||||
homingRange = 60f;
|
homingRange = 60f;
|
||||||
keepVelocity = false;
|
|
||||||
splashDamageRadius = 25f;
|
splashDamageRadius = 25f;
|
||||||
splashDamage = 10f;
|
splashDamage = 10f;
|
||||||
lifetime = 80f;
|
lifetime = 80f;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import arc.audio.*;
|
|||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.input.*;
|
import arc.input.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
|
import arc.scene.style.*;
|
||||||
import arc.scene.ui.*;
|
import arc.scene.ui.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
@@ -16,14 +17,17 @@ import mindustry.core.GameState.*;
|
|||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
|
import mindustry.game.Objectives.*;
|
||||||
import mindustry.game.Saves.*;
|
import mindustry.game.Saves.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.input.*;
|
import mindustry.input.*;
|
||||||
import mindustry.io.*;
|
import mindustry.io.*;
|
||||||
import mindustry.io.SaveIO.*;
|
import mindustry.io.SaveIO.*;
|
||||||
|
import mindustry.maps.*;
|
||||||
import mindustry.maps.Map;
|
import mindustry.maps.Map;
|
||||||
import mindustry.net.*;
|
import mindustry.net.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
|
import mindustry.ui.*;
|
||||||
import mindustry.ui.dialogs.*;
|
import mindustry.ui.dialogs.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
|
||||||
@@ -124,10 +128,18 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Events.on(UnlockEvent.class, e -> ui.hudfrag.showUnlock(e.content));
|
|
||||||
|
|
||||||
Events.on(UnlockEvent.class, e -> {
|
Events.on(UnlockEvent.class, e -> {
|
||||||
|
ui.hudfrag.showUnlock(e.content);
|
||||||
|
|
||||||
checkAutoUnlocks();
|
checkAutoUnlocks();
|
||||||
|
|
||||||
|
if(e.content instanceof SectorPreset){
|
||||||
|
for(TechNode node : TechTree.all){
|
||||||
|
if(!node.content.unlocked() && node.objectives.contains(o -> o instanceof SectorComplete sec && sec.preset == e.content) && !node.objectives.contains(o -> !o.complete())){
|
||||||
|
ui.hudfrag.showToast(new TextureRegionDrawable(node.content.icon(Cicon.large)), bundle.get("available"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(SectorCaptureEvent.class, e -> {
|
Events.on(SectorCaptureEvent.class, e -> {
|
||||||
@@ -223,7 +235,7 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
|
|
||||||
for(TechNode node : TechTree.all){
|
for(TechNode node : TechTree.all){
|
||||||
if(!node.content.unlocked() && node.requirements.length == 0 && !node.objectives.contains(o -> !o.complete())){
|
if(!node.content.unlocked() && node.requirements.length == 0 && !node.objectives.contains(o -> !o.complete())){
|
||||||
node.content.unlocked();
|
node.content.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,8 +323,17 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//set spawn for sector damage to use
|
||||||
|
Tile spawn = world.tile(sector.info.spawnPosition);
|
||||||
|
spawn.setBlock(Blocks.coreShard, state.rules.defaultTeam);
|
||||||
|
|
||||||
|
//add extra damage.
|
||||||
|
SectorDamage.apply(1f);
|
||||||
|
|
||||||
//reset wave so things are more fair
|
//reset wave so things are more fair
|
||||||
state.wave = 1;
|
state.wave = 1;
|
||||||
|
//set up default wave time
|
||||||
|
state.wavetime = state.rules.waveSpacing * 2f;
|
||||||
|
|
||||||
//reset win wave??
|
//reset win wave??
|
||||||
state.rules.winWave = state.rules.attackMode ? -1 : sector.preset != null ? sector.preset.captureWave : 40;
|
state.rules.winWave = state.rules.attackMode ? -1 : sector.preset != null ? sector.preset.captureWave : 40;
|
||||||
@@ -320,8 +341,8 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
//kill all units, since they should be dead anyway
|
//kill all units, since they should be dead anyway
|
||||||
Groups.unit.clear();
|
Groups.unit.clear();
|
||||||
Groups.fire.clear();
|
Groups.fire.clear();
|
||||||
|
Groups.puddle.clear();
|
||||||
|
|
||||||
Tile spawn = world.tile(sector.info.spawnPosition);
|
|
||||||
Schematics.placeLaunchLoadout(spawn.x, spawn.y);
|
Schematics.placeLaunchLoadout(spawn.x, spawn.y);
|
||||||
|
|
||||||
//set up camera/player locations
|
//set up camera/player locations
|
||||||
|
|||||||
@@ -33,9 +33,8 @@ public class GameState{
|
|||||||
/** Current game state. */
|
/** Current game state. */
|
||||||
private State state = State.menu;
|
private State state = State.menu;
|
||||||
|
|
||||||
//TODO optimize
|
|
||||||
public Unit boss(){
|
public Unit boss(){
|
||||||
return Groups.unit.find(u -> u.isBoss() && u.team == rules.waveTeam);
|
return teams.boss;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(State astate){
|
public void set(State astate){
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public class Logic implements ApplicationListener{
|
|||||||
if(!(state.getSector().preset != null && !state.getSector().preset.useAI)){
|
if(!(state.getSector().preset != null && !state.getSector().preset.useAI)){
|
||||||
state.rules.waveTeam.rules().ai = true;
|
state.rules.waveTeam.rules().ai = true;
|
||||||
}
|
}
|
||||||
state.rules.waveTeam.rules().aiTier = state.getSector().threat;
|
state.rules.waveTeam.rules().aiTier = state.getSector().threat * 0.8f;
|
||||||
state.rules.waveTeam.rules().infiniteResources = true;
|
state.rules.waveTeam.rules().infiniteResources = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,5 +12,6 @@ class GroupDefs<G>{
|
|||||||
@GroupDef(value = Syncc.class, mapping = true) G sync;
|
@GroupDef(value = Syncc.class, mapping = true) G sync;
|
||||||
@GroupDef(value = Drawc.class) G draw;
|
@GroupDef(value = Drawc.class) G draw;
|
||||||
@GroupDef(value = Firec.class) G fire;
|
@GroupDef(value = Firec.class) G fire;
|
||||||
|
@GroupDef(value = Puddlec.class) G puddle;
|
||||||
@GroupDef(value = WeatherStatec.class) G weather;
|
@GroupDef(value = WeatherStatec.class) G weather;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public abstract class BulletType extends Content{
|
|||||||
* Do not change unless you know what you're doing. */
|
* Do not change unless you know what you're doing. */
|
||||||
public boolean backMove = true;
|
public boolean backMove = true;
|
||||||
/** Bullet range override. */
|
/** Bullet range override. */
|
||||||
public float range = -1f;
|
public float maxRange = -1f;
|
||||||
/** % of block health healed **/
|
/** % of block health healed **/
|
||||||
public float healPercent = 0f;
|
public float healPercent = 0f;
|
||||||
/** whether to make fire on impact */
|
/** whether to make fire on impact */
|
||||||
@@ -154,7 +154,7 @@ public abstract class BulletType extends Content{
|
|||||||
|
|
||||||
/** Returns maximum distance the bullet this bullet type has can travel. */
|
/** Returns maximum distance the bullet this bullet type has can travel. */
|
||||||
public float range(){
|
public float range(){
|
||||||
return Math.max(speed * lifetime * (1f - drag), range);
|
return Math.max(speed * lifetime * (1f - drag), maxRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean collides(Bullet bullet, Building tile){
|
public boolean collides(Bullet bullet, Building tile){
|
||||||
@@ -317,11 +317,11 @@ public abstract class BulletType extends Content{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Bullet create(Bullet parent, float x, float y, float angle){
|
public Bullet create(Bullet parent, float x, float y, float angle){
|
||||||
return create(parent.owner(), parent.team, x, y, angle);
|
return create(parent.owner, parent.team, x, y, angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bullet create(Bullet parent, float x, float y, float angle, float velocityScl, float lifeScale){
|
public Bullet create(Bullet parent, float x, float y, float angle, float velocityScl, float lifeScale){
|
||||||
return create(parent.owner(), parent.team, x, y, angle, velocityScl, lifeScale);
|
return create(parent.owner, parent.team, x, y, angle, velocityScl, lifeScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bullet create(Bullet parent, float x, float y, float angle, float velocityScl){
|
public Bullet create(Bullet parent, float x, float y, float angle, float velocityScl){
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public class SapBulletType extends BulletType{
|
|||||||
b.data = target;
|
b.data = target;
|
||||||
|
|
||||||
if(target != null){
|
if(target != null){
|
||||||
float result = Math.min(target.health(), damage);
|
float result = Math.max(Math.min(target.health(), damage), 0);
|
||||||
|
|
||||||
if(b.owner instanceof Healthc h){
|
if(b.owner instanceof Healthc h){
|
||||||
h.heal(result * sapStrength);
|
h.heal(result * sapStrength);
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
|||||||
boolean shouldSkip(BuildPlan request, @Nullable Building core){
|
boolean shouldSkip(BuildPlan request, @Nullable Building core){
|
||||||
//requests that you have at least *started* are considered
|
//requests that you have at least *started* are considered
|
||||||
if(state.rules.infiniteResources || team().rules().infiniteResources || request.breaking || core == null) return false;
|
if(state.rules.infiniteResources || team().rules().infiniteResources || request.breaking || core == null) return false;
|
||||||
return (request.stuck && !core.items.has(request.block.requirements)) || (Structs.contains(request.block.requirements, i -> !core.items.has(i.item)) && !request.initialized);
|
return (request.stuck && !core.items.has(request.block.requirements)) || (Structs.contains(request.block.requirements, i -> !core.items.has(i.item) && Mathf.round(i.amount * state.rules.buildCostMultiplier) > 0) && !request.initialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeBuild(int x, int y, boolean breaking){
|
void removeBuild(int x, int y, boolean breaking){
|
||||||
|
|||||||
@@ -397,8 +397,8 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
|
|
||||||
/** Actually destroys the unit, removing it and creating explosions. **/
|
/** Actually destroys the unit, removing it and creating explosions. **/
|
||||||
public void destroy(){
|
public void destroy(){
|
||||||
float explosiveness = 2f + item().explosiveness * stack().amount / 2f;
|
float explosiveness = 2f + item().explosiveness * stack().amount / 2.4f;
|
||||||
float flammability = item().flammability * stack().amount / 2f;
|
float flammability = item().flammability * stack().amount / 2.4f;
|
||||||
Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, Pal.darkFlame, state.rules.damageExplosions);
|
Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, Pal.darkFlame, state.rules.damageExplosions);
|
||||||
|
|
||||||
float shake = hitSize / 3f;
|
float shake = hitSize / 3f;
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ public class Objectives{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SectorComplete extends SectorObjective{
|
public static class SectorComplete implements Objective{
|
||||||
|
public SectorPreset preset;
|
||||||
|
|
||||||
public SectorComplete(SectorPreset zone){
|
public SectorComplete(SectorPreset zone){
|
||||||
this.preset = zone;
|
this.preset = zone;
|
||||||
@@ -67,11 +68,6 @@ public class Objectives{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO merge
|
|
||||||
public abstract static class SectorObjective implements Objective{
|
|
||||||
public SectorPreset preset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Defines a specific objective for a game. */
|
/** Defines a specific objective for a game. */
|
||||||
public interface Objective{
|
public interface Objective{
|
||||||
|
|
||||||
@@ -86,9 +82,5 @@ public class Objectives{
|
|||||||
default void build(Table table){
|
default void build(Table table){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default SectorPreset zone(){
|
|
||||||
return this instanceof SectorObjective ? ((SectorObjective)this).preset : null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,6 +127,9 @@ public class Schematics implements Loadable{
|
|||||||
newSchematic.tags.putAll(target.tags);
|
newSchematic.tags.putAll(target.tags);
|
||||||
newSchematic.file = target.file;
|
newSchematic.file = target.file;
|
||||||
|
|
||||||
|
loadouts.each((block, list) -> list.remove(target));
|
||||||
|
checkLoadout(target, true);
|
||||||
|
|
||||||
try{
|
try{
|
||||||
write(newSchematic, target.file);
|
write(newSchematic, target.file);
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
@@ -134,6 +137,8 @@ public class Schematics implements Loadable{
|
|||||||
Log.err(e);
|
Log.err(e);
|
||||||
ui.showException(e);
|
ui.showException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable Schematic loadFile(Fi file){
|
private @Nullable Schematic loadFile(Fi file){
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ public class Teams{
|
|||||||
public Seq<TeamData> active = new Seq<>();
|
public Seq<TeamData> active = new Seq<>();
|
||||||
/** Teams with block or unit presence. */
|
/** Teams with block or unit presence. */
|
||||||
public Seq<TeamData> present = new Seq<>(TeamData.class);
|
public Seq<TeamData> present = new Seq<>(TeamData.class);
|
||||||
|
/** Current boss unit. */
|
||||||
|
public @Nullable Unit boss;
|
||||||
|
|
||||||
public Teams(){
|
public Teams(){
|
||||||
active.add(get(Team.crux));
|
active.add(get(Team.crux));
|
||||||
@@ -144,6 +146,7 @@ public class Teams{
|
|||||||
|
|
||||||
public void updateTeamStats(){
|
public void updateTeamStats(){
|
||||||
present.clear();
|
present.clear();
|
||||||
|
boss = null;
|
||||||
|
|
||||||
for(Team team : Team.all){
|
for(Team team : Team.all){
|
||||||
TeamData data = team.data();
|
TeamData data = team.data();
|
||||||
@@ -178,6 +181,10 @@ public class Teams{
|
|||||||
data.units.add(unit);
|
data.units.add(unit);
|
||||||
data.presentFlag = true;
|
data.presentFlag = true;
|
||||||
|
|
||||||
|
if(unit.team == state.rules.waveTeam && unit.isBoss()){
|
||||||
|
boss = unit;
|
||||||
|
}
|
||||||
|
|
||||||
if(data.unitsByType == null || data.unitsByType.length <= unit.type.id){
|
if(data.unitsByType == null || data.unitsByType.length <= unit.type.id){
|
||||||
data.unitsByType = new Seq[content.units().size];
|
data.unitsByType = new Seq[content.units().size];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,6 +208,8 @@ public class Universe{
|
|||||||
|
|
||||||
//add production, making sure that it's capped
|
//add production, making sure that it's capped
|
||||||
sector.info.production.each((item, stat) -> sector.info.items.add(item, Math.min((int)(stat.mean * newSecondsPassed * scl), sector.info.storageCapacity - sector.info.items.get(item))));
|
sector.info.production.each((item, stat) -> sector.info.items.add(item, Math.min((int)(stat.mean * newSecondsPassed * scl), sector.info.storageCapacity - sector.info.items.get(item))));
|
||||||
|
//prevent negative values with unloaders
|
||||||
|
sector.info.items.checkNegative();
|
||||||
|
|
||||||
sector.saveInfo();
|
sector.saveInfo();
|
||||||
}
|
}
|
||||||
@@ -216,7 +218,7 @@ public class Universe{
|
|||||||
if(!sector.isAttacked() && turn > invasionGracePeriod && sector.info.hasSpawns){
|
if(!sector.isAttacked() && turn > invasionGracePeriod && sector.info.hasSpawns){
|
||||||
//invasion chance depends on # of nearby bases
|
//invasion chance depends on # of nearby bases
|
||||||
if(Mathf.chance(baseInvasionChance * Math.min(sector.near().count(Sector::hasEnemyBase), 1))){
|
if(Mathf.chance(baseInvasionChance * Math.min(sector.near().count(Sector::hasEnemyBase), 1))){
|
||||||
int waveMax = Math.max(sector.info.winWave, sector.isBeingPlayed() ? state.wave : sector.info.wave + sector.info.wavesPassed) + Mathf.random(2, 5) * 5;
|
int waveMax = Math.max(sector.info.winWave, sector.isBeingPlayed() ? state.wave : sector.info.wave + sector.info.wavesPassed) + Mathf.random(2, 4) * 5;
|
||||||
|
|
||||||
//assign invasion-related things
|
//assign invasion-related things
|
||||||
if(sector.isBeingPlayed()){
|
if(sector.isBeingPlayed()){
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import mindustry.type.*;
|
|||||||
import static mindustry.content.UnitTypes.*;
|
import static mindustry.content.UnitTypes.*;
|
||||||
|
|
||||||
public class Waves{
|
public class Waves{
|
||||||
public static final int waveVersion = 3;
|
public static final int waveVersion = 4;
|
||||||
|
|
||||||
private Seq<SpawnGroup> spawns;
|
private Seq<SpawnGroup> spawns;
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ public class Waves{
|
|||||||
int cap = 150;
|
int cap = 150;
|
||||||
|
|
||||||
float shieldStart = 30, shieldsPerWave = 20 + difficulty*30f;
|
float shieldStart = 30, shieldsPerWave = 20 + difficulty*30f;
|
||||||
float[] scaling = {1, 1, 1.5f, 3f, 4f};
|
float[] scaling = {1, 1.5f, 3f, 4f, 5f};
|
||||||
|
|
||||||
Intc createProgression = start -> {
|
Intc createProgression = start -> {
|
||||||
//main sequence
|
//main sequence
|
||||||
@@ -286,7 +286,7 @@ public class Waves{
|
|||||||
|
|
||||||
for(int i = start; i < cap;){
|
for(int i = start; i < cap;){
|
||||||
int f = i;
|
int f = i;
|
||||||
int next = rand.random(8, 16) + (int)Mathf.lerp(4f, 0f, difficulty) + curTier * 4;
|
int next = rand.random(8, 16) + (int)Mathf.lerp(5f, 0f, difficulty) + curTier * 4;
|
||||||
|
|
||||||
float shieldAmount = Math.max((i - shieldStart) * shieldsPerWave, 0);
|
float shieldAmount = Math.max((i - shieldStart) * shieldsPerWave, 0);
|
||||||
int space = start == 0 ? 1 : rand.random(1, 2);
|
int space = start == 0 ? 1 : rand.random(1, 2);
|
||||||
@@ -298,7 +298,7 @@ public class Waves{
|
|||||||
begin = f;
|
begin = f;
|
||||||
end = f + next >= cap ? never : f + next;
|
end = f + next >= cap ? never : f + next;
|
||||||
max = 13;
|
max = 13;
|
||||||
unitScaling = (difficulty < 0.4f ? rand.random(2.5f, 4f) : rand.random(1f, 4f)) * scaling[ctier];
|
unitScaling = (difficulty < 0.4f ? rand.random(2.5f, 5f) : rand.random(1f, 4f)) * scaling[ctier];
|
||||||
shields = shieldAmount;
|
shields = shieldAmount;
|
||||||
shieldScaling = shieldsPerWave;
|
shieldScaling = shieldsPerWave;
|
||||||
spacing = space;
|
spacing = space;
|
||||||
@@ -310,7 +310,7 @@ public class Waves{
|
|||||||
begin = f + next - 1;
|
begin = f + next - 1;
|
||||||
end = f + next + rand.random(6, 10);
|
end = f + next + rand.random(6, 10);
|
||||||
max = 6;
|
max = 6;
|
||||||
unitScaling = rand.random(1f, 2f);
|
unitScaling = rand.random(2f, 4f);
|
||||||
spacing = rand.random(2, 4);
|
spacing = rand.random(2, 4);
|
||||||
shields = shieldAmount/2f;
|
shields = shieldAmount/2f;
|
||||||
shieldScaling = shieldsPerWave;
|
shieldScaling = shieldsPerWave;
|
||||||
@@ -340,10 +340,10 @@ public class Waves{
|
|||||||
step += (int)(rand.random(15, 30) * Mathf.lerp(1f, 0.5f, difficulty));
|
step += (int)(rand.random(15, 30) * Mathf.lerp(1f, 0.5f, difficulty));
|
||||||
}
|
}
|
||||||
|
|
||||||
int bossWave = (int)(rand.random(50, 70) * Mathf.lerp(1f, 0.5f, difficulty));
|
int bossWave = (int)(rand.random(50, 70) * Mathf.lerp(1f, 0.7f, difficulty));
|
||||||
int bossSpacing = (int)(rand.random(25, 40) * Mathf.lerp(1f, 0.6f, difficulty));
|
int bossSpacing = (int)(rand.random(25, 40) * Mathf.lerp(1f, 0.6f, difficulty));
|
||||||
|
|
||||||
int bossTier = difficulty < 0.5 ? 3 : 4;
|
int bossTier = difficulty < 0.6 ? 3 : 4;
|
||||||
|
|
||||||
//main boss progression
|
//main boss progression
|
||||||
out.add(new SpawnGroup(Structs.random(species)[bossTier]){{
|
out.add(new SpawnGroup(Structs.random(species)[bossTier]){{
|
||||||
@@ -411,7 +411,7 @@ public class Waves{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//shift back waves on higher difficulty for a harder start
|
//shift back waves on higher difficulty for a harder start
|
||||||
int shift = Math.max((int)(difficulty * 15 - 5), 0);
|
int shift = Math.max((int)(difficulty * 14 - 5), 0);
|
||||||
|
|
||||||
for(SpawnGroup group : out){
|
for(SpawnGroup group : out){
|
||||||
group.begin -= shift;
|
group.begin -= shift;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public enum Binding implements KeyBind{
|
|||||||
fullscreen(KeyCode.f11),
|
fullscreen(KeyCode.f11),
|
||||||
pause(KeyCode.space),
|
pause(KeyCode.space),
|
||||||
minimap(KeyCode.m),
|
minimap(KeyCode.m),
|
||||||
|
research(KeyCode.b),
|
||||||
planet_map(KeyCode.n),
|
planet_map(KeyCode.n),
|
||||||
toggle_menus(KeyCode.c),
|
toggle_menus(KeyCode.c),
|
||||||
screenshot(KeyCode.p),
|
screenshot(KeyCode.p),
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
if(state.isGame() && !scene.hasDialog() && !(scene.getKeyboardFocus() instanceof TextField)){
|
if(state.isGame() && !scene.hasDialog() && !(scene.getKeyboardFocus() instanceof TextField)){
|
||||||
if(Core.input.keyTap(Binding.minimap)) ui.minimapfrag.toggle();
|
if(Core.input.keyTap(Binding.minimap)) ui.minimapfrag.toggle();
|
||||||
if(Core.input.keyTap(Binding.planet_map) && state.isCampaign()) ui.planet.toggle();
|
if(Core.input.keyTap(Binding.planet_map) && state.isCampaign()) ui.planet.toggle();
|
||||||
|
if(Core.input.keyTap(Binding.research) && state.isCampaign()) ui.research.toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.isMenu() || Core.scene.hasDialog()) return;
|
if(state.isMenu() || Core.scene.hasDialog()) return;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
/** Maximum line length. */
|
/** Maximum line length. */
|
||||||
final static int maxLength = 100;
|
final static int maxLength = 100;
|
||||||
final static Rect r1 = new Rect(), r2 = new Rect();
|
final static Rect r1 = new Rect(), r2 = new Rect();
|
||||||
|
final static Seq<Point2> tmpPoints = new Seq<>(), tmpPoints2 = new Seq<>();
|
||||||
|
|
||||||
public final OverlayFragment frag = new OverlayFragment();
|
public final OverlayFragment frag = new OverlayFragment();
|
||||||
|
|
||||||
@@ -1164,27 +1165,39 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
points = Placement.normalizeLine(startX, startY, endX, endY);
|
points = Placement.normalizeLine(startX, startY, endX, endY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(block instanceof PowerNode){
|
if(block instanceof PowerNode node){
|
||||||
Seq<Point2> skip = new Seq<>();
|
var base = tmpPoints2;
|
||||||
|
var result = tmpPoints.clear();
|
||||||
|
|
||||||
for(int i = 1; i < points.size; i++){
|
base.selectFrom(points, p -> p == points.first() || p == points.peek() || Build.validPlace(block, player.team(), p.x, p.y, rotation, false));
|
||||||
int overlaps = 0;
|
boolean addedLast = false;
|
||||||
Point2 point = points.get(i);
|
|
||||||
|
|
||||||
//check with how many powernodes the *next* tile will overlap
|
outer:
|
||||||
for(int j = 0; j < i; j++){
|
for(int i = 0; i < base.size;){
|
||||||
if(!skip.contains(points.get(j)) && ((PowerNode)block).overlaps(world.tile(point.x, point.y), world.tile(points.get(j).x, points.get(j).y))){
|
var point = base.get(i);
|
||||||
overlaps++;
|
result.add(point);
|
||||||
|
if(i == base.size - 1) addedLast = true;
|
||||||
|
|
||||||
|
//find the furthest node that overlaps this one
|
||||||
|
for(int j = base.size - 1; j > i; j--){
|
||||||
|
var other = base.get(j);
|
||||||
|
boolean over = node.overlaps(world.tile(point.x, point.y), world.tile(other.x, other.y));
|
||||||
|
|
||||||
|
if(over){
|
||||||
|
//add node to list and start searching for node that overlaps the next one
|
||||||
|
i = j;
|
||||||
|
continue outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if it's more than one, it can bridge the gap
|
//if it got here, that means nothing was found. try to proceed to the next node anyway
|
||||||
if(overlaps > 1){
|
i ++;
|
||||||
skip.add(points.get(i-1));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
//remove skipped points
|
if(!addedLast) result.add(base.peek());
|
||||||
points.removeAll(skip);
|
|
||||||
|
points.clear();
|
||||||
|
points.addAll(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
float angle = Angles.angle(startX, startY, endX, endY);
|
float angle = Angles.angle(startX, startY, endX, endY);
|
||||||
|
|||||||
@@ -241,35 +241,10 @@ public class Placement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class NormalizeDrawResult{
|
public static class NormalizeDrawResult{
|
||||||
float x, y, x2, y2;
|
public float x, y, x2, y2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class NormalizeResult{
|
public static class NormalizeResult{
|
||||||
public int x, y, x2, y2, rotation;
|
public int x, y, x2, y2, rotation;
|
||||||
|
|
||||||
boolean isX(){
|
|
||||||
return Math.abs(x2 - x) > Math.abs(y2 - y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns length of greater edge of the selection.
|
|
||||||
*/
|
|
||||||
int getLength(){
|
|
||||||
return Math.max(x2 - x, y2 - y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the X position of a specific index along this area as a line.
|
|
||||||
*/
|
|
||||||
int getScaledX(int i){
|
|
||||||
return x + (x2 - x > y2 - y ? i : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the Y position of a specific index along this area as a line.
|
|
||||||
*/
|
|
||||||
int getScaledY(int i){
|
|
||||||
return y + (x2 - x > y2 - y ? 0 : i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
|||||||
|
|
||||||
public void writeEntities(DataOutput stream) throws IOException{
|
public void writeEntities(DataOutput stream) throws IOException{
|
||||||
//write team data with entities.
|
//write team data with entities.
|
||||||
Seq<TeamData> data = state.teams.getActive();
|
Seq<TeamData> data = state.teams.getActive().and(Team.sharded.data());
|
||||||
stream.writeInt(data.size);
|
stream.writeInt(data.size);
|
||||||
for(TeamData team : data){
|
for(TeamData team : data){
|
||||||
stream.writeInt(team.team.id);
|
stream.writeInt(team.team.id);
|
||||||
|
|||||||
@@ -302,6 +302,14 @@ public class Maps{
|
|||||||
flooronto = Blocks.sand;
|
flooronto = Blocks.sand;
|
||||||
block = Blocks.sandBoulder;
|
block = Blocks.sandBoulder;
|
||||||
}},
|
}},
|
||||||
|
new ScatterFilter(){{
|
||||||
|
flooronto = Blocks.darksand;
|
||||||
|
block = Blocks.basaltBoulder;
|
||||||
|
}},
|
||||||
|
new ScatterFilter(){{
|
||||||
|
flooronto = Blocks.basalt;
|
||||||
|
block = Blocks.basaltBoulder;
|
||||||
|
}},
|
||||||
new ScatterFilter(){{
|
new ScatterFilter(){{
|
||||||
flooronto = Blocks.dacite;
|
flooronto = Blocks.dacite;
|
||||||
block = Blocks.daciteBoulder;
|
block = Blocks.daciteBoulder;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import mindustry.world.blocks.storage.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class SectorDamage{
|
public class SectorDamage{
|
||||||
public static final int maxRetWave = 30, maxWavesSimulated = 50;
|
public static final int maxRetWave = 40, maxWavesSimulated = 50;
|
||||||
|
|
||||||
//direct damage is for testing only
|
//direct damage is for testing only
|
||||||
private static final boolean direct = false, rubble = true;
|
private static final boolean direct = false, rubble = true;
|
||||||
@@ -111,23 +111,26 @@ public class SectorDamage{
|
|||||||
float damage = getDamage(state.rules.sector.info);
|
float damage = getDamage(state.rules.sector.info);
|
||||||
|
|
||||||
//scaled damage has a power component to make it seem a little more realistic (as systems fail, enemy capturing gets easier and easier)
|
//scaled damage has a power component to make it seem a little more realistic (as systems fail, enemy capturing gets easier and easier)
|
||||||
float scaled = Mathf.pow(damage, 1.6f);
|
float scaled = Mathf.pow(damage, 1.2f);
|
||||||
|
|
||||||
//apply damage to units
|
|
||||||
float unitDamage = damage * state.rules.sector.info.sumHealth;
|
|
||||||
Tile spawn = spawner.getFirstSpawn();
|
Tile spawn = spawner.getFirstSpawn();
|
||||||
|
|
||||||
//damage only units near the spawn point
|
//damage only units near the spawn point
|
||||||
if(spawn != null){
|
if(spawn != null){
|
||||||
Seq<Unit> allies = new Seq<>();
|
Seq<Unit> allies = new Seq<>();
|
||||||
|
float sumUnitHealth = 0f;
|
||||||
for(Unit ally : Groups.unit){
|
for(Unit ally : Groups.unit){
|
||||||
if(ally.team == state.rules.defaultTeam && ally.within(spawn, state.rules.dropZoneRadius * 2.5f)){
|
if(ally.team == state.rules.defaultTeam && ally.within(spawn, state.rules.dropZoneRadius * 2.5f)){
|
||||||
allies.add(ally);
|
allies.add(ally);
|
||||||
|
sumUnitHealth += ally.health;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allies.sort(u -> u.dst2(spawn));
|
allies.sort(u -> u.dst2(spawn));
|
||||||
|
|
||||||
|
//apply damage to units
|
||||||
|
float unitDamage = damage * sumUnitHealth;
|
||||||
|
|
||||||
//damage units one by one, not uniformly
|
//damage units one by one, not uniformly
|
||||||
for(var u : allies){
|
for(var u : allies){
|
||||||
if(u.health < unitDamage){
|
if(u.health < unitDamage){
|
||||||
@@ -335,9 +338,9 @@ public class SectorDamage{
|
|||||||
info.waveDpsSlope = reg.slope;
|
info.waveDpsSlope = reg.slope;
|
||||||
|
|
||||||
//enemy units like to aim for a lot of non-essential things, so increase resulting health slightly
|
//enemy units like to aim for a lot of non-essential things, so increase resulting health slightly
|
||||||
info.sumHealth = sumHealth * 1.3f;
|
info.sumHealth = sumHealth * 1.2f;
|
||||||
//players tend to have longer range units/turrets, so assume DPS is higher
|
//players tend to have longer range units/turrets, so assume DPS is higher
|
||||||
info.sumDps = sumDps * 1.3f;
|
info.sumDps = sumDps * 1.2f;
|
||||||
info.sumRps = sumRps;
|
info.sumRps = sumRps;
|
||||||
|
|
||||||
info.wavesSurvived = getWavesSurvived(info);
|
info.wavesSurvived = getWavesSurvived(info);
|
||||||
@@ -348,13 +351,12 @@ public class SectorDamage{
|
|||||||
|
|
||||||
Queue<Tile> frontier = new Queue<>();
|
Queue<Tile> frontier = new Queue<>();
|
||||||
float[][] values = new float[tiles.width][tiles.height];
|
float[][] values = new float[tiles.width][tiles.height];
|
||||||
float damage = fraction*80; //arbitrary damage value
|
|
||||||
|
|
||||||
//phase one: find all spawnpoints
|
//phase one: find all spawnpoints
|
||||||
for(Tile tile : tiles){
|
for(Tile tile : tiles){
|
||||||
if((tile.block() instanceof CoreBlock && tile.team() == state.rules.waveTeam) || tile.overlay() == Blocks.spawn){
|
if((tile.block() instanceof CoreBlock && tile.team() == state.rules.waveTeam) || tile.overlay() == Blocks.spawn){
|
||||||
frontier.add(tile);
|
frontier.add(tile);
|
||||||
values[tile.x][tile.y] = damage;
|
values[tile.x][tile.y] = fraction * 26;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,24 +370,26 @@ public class SectorDamage{
|
|||||||
int radius = 3;
|
int radius = 3;
|
||||||
|
|
||||||
//only penetrate a certain % by health, not by distance
|
//only penetrate a certain % by health, not by distance
|
||||||
float totalHealth = damage >= 1f ? 1f : path.sumf(t -> {
|
float totalHealth = fraction >= 1f ? 1f : path.sumf(t -> {
|
||||||
float s = 0;
|
float s = 0;
|
||||||
for(int dx = -radius; dx <= radius; dx++){
|
for(int dx = -radius; dx <= radius; dx++){
|
||||||
for(int dy = -radius; dy <= radius; dy++){
|
for(int dy = -radius; dy <= radius; dy++){
|
||||||
int wx = dx + t.x, wy = dy + t.y;
|
int wx = dx + t.x, wy = dy + t.y;
|
||||||
if(wx >= 0 && wy >= 0 && wx < world.width() && wy < world.height() && Mathf.within(dx, dy, radius)){
|
if(wx >= 0 && wy >= 0 && wx < world.width() && wy < world.height() && Mathf.within(dx, dy, radius)){
|
||||||
Tile other = world.rawTile(wx, wy);
|
Tile other = world.rawTile(wx, wy);
|
||||||
|
if(!(other.block() instanceof CoreBlock)){
|
||||||
s += other.team() == state.rules.defaultTeam ? other.build.health / other.block().size : 0f;
|
s += other.team() == state.rules.defaultTeam ? other.build.health / other.block().size : 0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
float targetHealth = totalHealth * fraction;
|
float targetHealth = totalHealth * fraction;
|
||||||
float healthCount = 0;
|
float healthCount = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
for(int i = 0; i < path.size && (healthCount < targetHealth || damage >= 1f); i++){
|
for(int i = 0; i < path.size && (healthCount < targetHealth || fraction >= 1f); i++){
|
||||||
Tile t = path.get(i);
|
Tile t = path.get(i);
|
||||||
|
|
||||||
for(int dx = -radius; dx <= radius; dx++){
|
for(int dx = -radius; dx <= radius; dx++){
|
||||||
@@ -405,7 +409,7 @@ public class SectorDamage{
|
|||||||
|
|
||||||
removal.add(other.build);
|
removal.add(other.build);
|
||||||
|
|
||||||
if(healthCount >= targetHealth && damage < 0.999f){
|
if(healthCount >= targetHealth && fraction < 0.999f){
|
||||||
break out;
|
break out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,10 +434,10 @@ public class SectorDamage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float falloff = (damage) / (Math.max(tiles.width, tiles.height) * Mathf.sqrt2);
|
float falloff = (fraction) / (Math.max(tiles.width, tiles.height) * Mathf.sqrt2);
|
||||||
int peak = 0;
|
int peak = 0;
|
||||||
|
|
||||||
if(damage > 0.1f){
|
if(fraction > 0.15f){
|
||||||
//phase two: propagate the damage
|
//phase two: propagate the damage
|
||||||
while(!frontier.isEmpty()){
|
while(!frontier.isEmpty()){
|
||||||
peak = Math.max(peak, frontier.size);
|
peak = Math.max(peak, frontier.size);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import mindustry.world.*;
|
|||||||
import static mindustry.maps.filters.FilterOption.*;
|
import static mindustry.maps.filters.FilterOption.*;
|
||||||
|
|
||||||
public class ScatterFilter extends GenerateFilter{
|
public class ScatterFilter extends GenerateFilter{
|
||||||
protected float chance = 0.014f;
|
protected float chance = 0.013f;
|
||||||
protected Block flooronto = Blocks.air, floor = Blocks.air, block = Blocks.air;
|
protected Block flooronto = Blocks.air, floor = Blocks.air, block = Blocks.air;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class BaseGenerator{
|
|||||||
BasePart coreschem = bases.cores.getFrac(difficulty);
|
BasePart coreschem = bases.cores.getFrac(difficulty);
|
||||||
int passes = difficulty < 0.4 ? 1 : difficulty < 0.8 ? 2 : 3;
|
int passes = difficulty < 0.4 ? 1 : difficulty < 0.8 ? 2 : 3;
|
||||||
|
|
||||||
Block wall = wallsSmall.getFrac(difficulty), wallLarge = wallsLarge.getFrac(difficulty);
|
Block wall = wallsSmall.getFrac(difficulty * 0.91f), wallLarge = wallsLarge.getFrac(difficulty * 0.91f);
|
||||||
|
|
||||||
for(Tile tile : cores){
|
for(Tile tile : cores){
|
||||||
tile.clearOverlay();
|
tile.clearOverlay();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package mindustry.type;
|
package mindustry.type;
|
||||||
|
|
||||||
|
import arc.math.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
|
|
||||||
@@ -35,10 +36,10 @@ public class ItemStack implements Comparable<ItemStack>{
|
|||||||
return other != null && other.item == item && other.amount == amount;
|
return other != null && other.item == item && other.amount == amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack[] mult(ItemStack[] stacks, int amount){
|
public static ItemStack[] mult(ItemStack[] stacks, float amount){
|
||||||
ItemStack[] copy = new ItemStack[stacks.length];
|
ItemStack[] copy = new ItemStack[stacks.length];
|
||||||
for(int i = 0; i < copy.length; i++){
|
for(int i = 0; i < copy.length; i++){
|
||||||
copy[i] = new ItemStack(stacks[i].item, stacks[i].amount * amount);
|
copy[i] = new ItemStack(stacks[i].item, Mathf.round(stacks[i].amount * amount));
|
||||||
}
|
}
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,15 +182,15 @@ public class Planet extends UnlockableContent{
|
|||||||
float sum = 1f;
|
float sum = 1f;
|
||||||
for(Sector other : sector.near()){
|
for(Sector other : sector.near()){
|
||||||
if(other.generateEnemyBase){
|
if(other.generateEnemyBase){
|
||||||
sum += 1f;
|
sum += 0.9f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sector.hasEnemyBase()){
|
if(sector.hasEnemyBase()){
|
||||||
sum += 2.5f;
|
sum += 0.88f;
|
||||||
}
|
}
|
||||||
|
|
||||||
sector.threat = sector.preset == null ? Math.min(sum / 5f, 1.5f) : Mathf.clamp(sector.preset.difficulty / 10f);
|
sector.threat = sector.preset == null ? Math.min(sum / 5f, 1.2f) : Mathf.clamp(sector.preset.difficulty / 10f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ public class Sector{
|
|||||||
|
|
||||||
public boolean isBeingPlayed(){
|
public boolean isBeingPlayed(){
|
||||||
//after the launch dialog, a sector is no longer considered being played
|
//after the launch dialog, a sector is no longer considered being played
|
||||||
return Vars.state.isGame() && Vars.state.rules.sector == this && !Vars.state.gameOver;
|
return Vars.state.isGame() && Vars.state.rules.sector == this && !Vars.state.gameOver && !net.client();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String name(){
|
public String name(){
|
||||||
@@ -169,6 +169,8 @@ public class Sector{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addItems(ItemSeq items){
|
public void addItems(ItemSeq items){
|
||||||
|
if(net.client()) return;
|
||||||
|
|
||||||
if(isBeingPlayed()){
|
if(isBeingPlayed()){
|
||||||
if(state.rules.defaultTeam.core() != null){
|
if(state.rules.defaultTeam.core() != null){
|
||||||
ItemModule storage = state.rules.defaultTeam.items();
|
ItemModule storage = state.rules.defaultTeam.items();
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ public class UnitType extends UnlockableContent{
|
|||||||
//suicide enemy
|
//suicide enemy
|
||||||
if(weapons.contains(w -> w.bullet.killShooter)){
|
if(weapons.contains(w -> w.bullet.killShooter)){
|
||||||
//scale down DPS to be insignificant
|
//scale down DPS to be insignificant
|
||||||
dpsEstimate /= 20f;
|
dpsEstimate /= 25f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import mindustry.game.*;
|
|||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.graphics.g3d.*;
|
import mindustry.graphics.g3d.*;
|
||||||
|
import mindustry.input.*;
|
||||||
import mindustry.maps.*;
|
import mindustry.maps.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
@@ -60,7 +61,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
shouldPause = true;
|
shouldPause = true;
|
||||||
|
|
||||||
keyDown(key -> {
|
keyDown(key -> {
|
||||||
if(key == KeyCode.escape || key == KeyCode.back){
|
if(key == KeyCode.escape || key == KeyCode.back || key == Core.keybinds.get(Binding.planet_map).key){
|
||||||
if(showing() && newPresets.size > 1){
|
if(showing() && newPresets.size > 1){
|
||||||
//clear all except first, which is the last sector.
|
//clear all except first, which is the last sector.
|
||||||
newPresets.truncate(1);
|
newPresets.truncate(1);
|
||||||
@@ -166,6 +167,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
newPresets.reverse();
|
newPresets.reverse();
|
||||||
|
updateSelected();
|
||||||
|
|
||||||
if(planets.planet.getLastSector() != null){
|
if(planets.planet.getLastSector() != null){
|
||||||
lookAt(planets.planet.getLastSector());
|
lookAt(planets.planet.getLastSector());
|
||||||
@@ -684,7 +686,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
if(sector.info.wavesSurvived >= 0 && sector.info.wavesSurvived - sector.info.wavesPassed >= 0 && !sector.isBeingPlayed()){
|
if(sector.info.wavesSurvived >= 0 && sector.info.wavesSurvived - sector.info.wavesPassed >= 0 && !sector.isBeingPlayed()){
|
||||||
int toCapture = sector.info.attack || sector.info.winWave <= 1 ? -1 : sector.info.winWave - (sector.info.wave + sector.info.wavesPassed);
|
int toCapture = sector.info.attack || sector.info.winWave <= 1 ? -1 : sector.info.winWave - (sector.info.wave + sector.info.wavesPassed);
|
||||||
boolean plus = (sector.info.wavesSurvived - sector.info.wavesPassed) >= SectorDamage.maxRetWave - 1;
|
boolean plus = (sector.info.wavesSurvived - sector.info.wavesPassed) >= SectorDamage.maxRetWave - 1;
|
||||||
stable.add(Core.bundle.format("sectors.survives", Math.min(sector.info.wavesSurvived - sector.info.wavesPassed, toCapture <= 0 ? 200 : 0) +
|
stable.add(Core.bundle.format("sectors.survives", Math.min(sector.info.wavesSurvived - sector.info.wavesPassed, toCapture <= 0 ? 200 : toCapture) +
|
||||||
(plus ? "+" : "") + (toCapture < 0 ? "" : "/" + toCapture)));
|
(plus ? "+" : "") + (toCapture < 0 ? "" : "/" + toCapture)));
|
||||||
stable.row();
|
stable.row();
|
||||||
}
|
}
|
||||||
@@ -699,11 +701,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
if(sector.save != null && sector.info.resources.any()){
|
if(sector.save != null && sector.info.resources.any()){
|
||||||
stable.table(t -> {
|
stable.table(t -> {
|
||||||
t.add("@sectors.resources").padRight(4);
|
t.add("@sectors.resources").padRight(4);
|
||||||
int idx = 0;
|
|
||||||
int max = 5;
|
|
||||||
for(UnlockableContent c : sector.info.resources){
|
for(UnlockableContent c : sector.info.resources){
|
||||||
t.image(c.icon(Cicon.small)).padRight(3).size(Cicon.small.size);
|
t.image(c.icon(Cicon.small)).padRight(3).size(Cicon.small.size);
|
||||||
//if(++idx % max == 0) t.row();
|
|
||||||
}
|
}
|
||||||
}).padLeft(10f).fillX().row();
|
}).padLeft(10f).fillX().row();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import mindustry.game.EventType.*;
|
|||||||
import mindustry.game.Objectives.*;
|
import mindustry.game.Objectives.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.input.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
import mindustry.ui.layout.*;
|
import mindustry.ui.layout.*;
|
||||||
@@ -63,8 +64,8 @@ public class ResearchDialog extends BaseDialog{
|
|||||||
ItemSeq cached = sector.items();
|
ItemSeq cached = sector.items();
|
||||||
cache.put(sector, cached);
|
cache.put(sector, cached);
|
||||||
cached.each((item, amount) -> {
|
cached.each((item, amount) -> {
|
||||||
values[item.id] += amount;
|
values[item.id] += Math.max(amount, 0);
|
||||||
total += amount;
|
total += Math.max(amount, 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,6 +115,12 @@ public class ResearchDialog extends BaseDialog{
|
|||||||
|
|
||||||
addCloseButton();
|
addCloseButton();
|
||||||
|
|
||||||
|
keyDown(key -> {
|
||||||
|
if(key == Core.keybinds.get(Binding.research).key){
|
||||||
|
Core.app.post(this::hide);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
buttons.button("@database", Icon.book, () -> {
|
buttons.button("@database", Icon.book, () -> {
|
||||||
hide();
|
hide();
|
||||||
ui.database.show();
|
ui.database.show();
|
||||||
|
|||||||
@@ -396,7 +396,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
|||||||
graphics.checkPref("blockstatus", false);
|
graphics.checkPref("blockstatus", false);
|
||||||
graphics.checkPref("playerchat", true);
|
graphics.checkPref("playerchat", true);
|
||||||
if(!mobile){
|
if(!mobile){
|
||||||
graphics.checkPref("coreitems", false);
|
graphics.checkPref("coreitems", true);
|
||||||
}
|
}
|
||||||
graphics.checkPref("minimap", !mobile);
|
graphics.checkPref("minimap", !mobile);
|
||||||
graphics.checkPref("smoothcamera", true);
|
graphics.checkPref("smoothcamera", true);
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ public class HintsFragment extends Fragment{
|
|||||||
}else if(hints.size > 0){
|
}else if(hints.size > 0){
|
||||||
//check one hint each frame to see if it should be shown.
|
//check one hint each frame to see if it should be shown.
|
||||||
Hint hint = hints.find(Hint::show);
|
Hint hint = hints.find(Hint::show);
|
||||||
if(hint != null && !hint.finished() & !hint.complete()){
|
if(hint != null && hint.complete()){
|
||||||
|
hints.remove(hint);
|
||||||
|
}else if(hint != null){
|
||||||
display(hint);
|
display(hint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +81,7 @@ public class HintsFragment extends Fragment{
|
|||||||
void checkNext(){
|
void checkNext(){
|
||||||
if(current != null) return;
|
if(current != null) return;
|
||||||
|
|
||||||
hints.removeAll(h -> h == current || !h.valid() || h.finished() || (h.show() && h.complete()));
|
hints.removeAll(h -> !h.valid() || h.finished() || (h.show() && h.complete()));
|
||||||
hints.sort(Hint::order);
|
hints.sort(Hint::order);
|
||||||
|
|
||||||
Hint first = hints.find(Hint::show);
|
Hint first = hints.find(Hint::show);
|
||||||
@@ -148,7 +150,7 @@ public class HintsFragment extends Fragment{
|
|||||||
depositItems(() -> player.unit().hasItem(), () -> !player.unit().hasItem()),
|
depositItems(() -> player.unit().hasItem(), () -> !player.unit().hasItem()),
|
||||||
desktopPause(visibleDesktop, () -> isTutorial.get() && !Vars.net.active(), () -> Core.input.keyTap(Binding.pause)),
|
desktopPause(visibleDesktop, () -> isTutorial.get() && !Vars.net.active(), () -> Core.input.keyTap(Binding.pause)),
|
||||||
research(isTutorial, () -> ui.research.isShown()),
|
research(isTutorial, () -> ui.research.isShown()),
|
||||||
unitControl(() -> state.rules.defaultTeam.data().units.size > 1 && !net.active(), () -> !player.dead() && !player.unit().spawnedByCore),
|
unitControl(() -> state.rules.defaultTeam.data().units.size > 2 && !net.active() && !player.dead(), () -> !player.dead() && !player.unit().spawnedByCore),
|
||||||
respawn(visibleMobile, () -> !player.dead() && !player.unit().spawnedByCore, () -> !player.dead() && player.unit().spawnedByCore),
|
respawn(visibleMobile, () -> !player.dead() && !player.unit().spawnedByCore, () -> !player.dead() && player.unit().spawnedByCore),
|
||||||
launch(() -> isTutorial.get() && state.rules.sector.isCaptured(), () -> ui.planet.isShown()),
|
launch(() -> isTutorial.get() && state.rules.sector.isCaptured(), () -> ui.planet.isShown()),
|
||||||
schematicSelect(visibleDesktop, () -> ui.hints.placedBlocks.contains(Blocks.router), () -> Core.input.keyRelease(Binding.schematic_select) || Core.input.keyTap(Binding.pick)),
|
schematicSelect(visibleDesktop, () -> ui.hints.placedBlocks.contains(Blocks.router), () -> Core.input.keyRelease(Binding.schematic_select) || Core.input.keyTap(Binding.pick)),
|
||||||
@@ -158,6 +160,8 @@ public class HintsFragment extends Fragment{
|
|||||||
payloadPickup(() -> !player.unit().dead && player.unit() instanceof Payloadc p && p.payloads().isEmpty(), () -> player.unit() instanceof Payloadc p && p.payloads().any()),
|
payloadPickup(() -> !player.unit().dead && player.unit() instanceof Payloadc p && p.payloads().isEmpty(), () -> player.unit() instanceof Payloadc p && p.payloads().any()),
|
||||||
payloadDrop(() -> !player.unit().dead && player.unit() instanceof Payloadc p && p.payloads().any(), () -> player.unit() instanceof Payloadc p && p.payloads().isEmpty()),
|
payloadDrop(() -> !player.unit().dead && player.unit() instanceof Payloadc p && p.payloads().any(), () -> player.unit() instanceof Payloadc p && p.payloads().isEmpty()),
|
||||||
waveFire(() -> Groups.fire.size() > 0 && Blocks.wave.unlockedNow(), () -> indexer.getAllied(state.rules.defaultTeam, BlockFlag.extinguisher).size() > 0),
|
waveFire(() -> Groups.fire.size() > 0 && Blocks.wave.unlockedNow(), () -> indexer.getAllied(state.rules.defaultTeam, BlockFlag.extinguisher).size() > 0),
|
||||||
|
generator(() -> control.input.block == Blocks.combustionGenerator, () -> ui.hints.placedBlocks.contains(Blocks.combustionGenerator)),
|
||||||
|
guardian(() -> state.boss() != null && state.boss().armor >= 4, () -> state.boss() == null),
|
||||||
;
|
;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import mindustry.graphics.*;
|
|||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.consumers.*;
|
||||||
import mindustry.world.meta.*;
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
@@ -38,6 +39,7 @@ public class LaunchPad extends Block{
|
|||||||
solid = true;
|
solid = true;
|
||||||
update = true;
|
update = true;
|
||||||
configurable = true;
|
configurable = true;
|
||||||
|
drawDisabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -58,7 +60,13 @@ public class LaunchPad extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Cursor getCursor(){
|
public Cursor getCursor(){
|
||||||
return !state.isCampaign() ? SystemCursor.arrow : super.getCursor();
|
return !state.isCampaign() || net.client() ? SystemCursor.arrow : super.getCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
//cannot be disabled
|
||||||
|
@Override
|
||||||
|
public float efficiency(){
|
||||||
|
return power != null && (block.consumes.has(ConsumeType.power) && !block.consumes.getPower().buffered) ? power.status : 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -136,7 +144,7 @@ public class LaunchPad extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void buildConfiguration(Table table){
|
public void buildConfiguration(Table table){
|
||||||
if(!state.isCampaign()){
|
if(!state.isCampaign() || net.client()){
|
||||||
deselect();
|
deselect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -234,9 +242,11 @@ public class LaunchPad extends Block{
|
|||||||
Events.fire(new LaunchItemEvent(stack));
|
Events.fire(new LaunchItemEvent(stack));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!net.client()){
|
||||||
destsec.addItems(dest);
|
destsec.addItems(dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ public class MendProjector extends Block{
|
|||||||
float heat;
|
float heat;
|
||||||
float charge = Mathf.random(reload);
|
float charge = Mathf.random(reload);
|
||||||
float phaseHeat;
|
float phaseHeat;
|
||||||
|
float smoothEfficiency;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float range(){
|
public float range(){
|
||||||
@@ -68,6 +69,7 @@ public class MendProjector extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTile(){
|
public void updateTile(){
|
||||||
|
smoothEfficiency = Mathf.lerpDelta(smoothEfficiency, efficiency(), 0.08f);
|
||||||
heat = Mathf.lerpDelta(heat, consValid() || cheating() ? 1f : 0f, 0.08f);
|
heat = Mathf.lerpDelta(heat, consValid() || cheating() ? 1f : 0f, 0.08f);
|
||||||
charge += heat * delta();
|
charge += heat * delta();
|
||||||
|
|
||||||
@@ -115,7 +117,7 @@ public class MendProjector extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawLight(){
|
public void drawLight(){
|
||||||
Drawf.light(team, x, y, 50f * efficiency(), baseColor, 0.7f * efficiency());
|
Drawf.light(team, x, y, 50f * smoothEfficiency, baseColor, 0.7f * smoothEfficiency);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ public class OverdriveProjector extends Block{
|
|||||||
float heat;
|
float heat;
|
||||||
float charge = Mathf.random(reload);
|
float charge = Mathf.random(reload);
|
||||||
float phaseHeat;
|
float phaseHeat;
|
||||||
|
float smoothEfficiency;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float range(){
|
public float range(){
|
||||||
@@ -73,11 +74,12 @@ public class OverdriveProjector extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawLight(){
|
public void drawLight(){
|
||||||
Drawf.light(team, x, y, 50f * efficiency(), baseColor, 0.7f * efficiency());
|
Drawf.light(team, x, y, 50f * smoothEfficiency, baseColor, 0.7f * smoothEfficiency);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTile(){
|
public void updateTile(){
|
||||||
|
smoothEfficiency = Mathf.lerpDelta(smoothEfficiency, efficiency(), 0.08f);
|
||||||
heat = Mathf.lerpDelta(heat, consValid() ? 1f : 0f, 0.08f);
|
heat = Mathf.lerpDelta(heat, consValid() ? 1f : 0f, 0.08f);
|
||||||
charge += heat * Time.delta;
|
charge += heat * Time.delta;
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class Junction extends Block{
|
|||||||
Building dest = nearby(i);
|
Building dest = nearby(i);
|
||||||
|
|
||||||
//skip blocks that don't want the item, keep waiting until they do
|
//skip blocks that don't want the item, keep waiting until they do
|
||||||
if(dest == null || !dest.acceptItem(this, item) || dest.team != team){
|
if(item == null || dest == null || !dest.acceptItem(this, item) || dest.team != team){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,11 @@ public class ItemLiquidGenerator extends PowerGenerator{
|
|||||||
return generateTime > 0;
|
return generateTime > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float ambientVolume(){
|
||||||
|
return Mathf.clamp(productionEfficiency);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTile(){
|
public void updateTile(){
|
||||||
//Note: Do not use this delta when calculating the amount of power or the power efficiency, but use it for resource consumption if necessary.
|
//Note: Do not use this delta when calculating the amount of power or the power efficiency, but use it for resource consumption if necessary.
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ public class CoreBlock extends StorageBlock{
|
|||||||
//right before placing, create a "destination" item array which is all the previous items minus core requirements
|
//right before placing, create a "destination" item array which is all the previous items minus core requirements
|
||||||
ItemModule items = tile.build.items.copy();
|
ItemModule items = tile.build.items.copy();
|
||||||
if(!state.rules.infiniteResources){
|
if(!state.rules.infiniteResources){
|
||||||
items.remove(requirements);
|
items.remove(ItemStack.mult(requirements, state.rules.buildCostMultiplier));
|
||||||
}
|
}
|
||||||
|
|
||||||
nextItems = items;
|
nextItems = items;
|
||||||
@@ -157,7 +157,7 @@ public class CoreBlock extends StorageBlock{
|
|||||||
|
|
||||||
if(!canPlaceOn(world.tile(x, y), player.team())){
|
if(!canPlaceOn(world.tile(x, y), player.team())){
|
||||||
|
|
||||||
drawPlaceText(Core.bundle.get((player.team().core() != null && player.team().core().items.has(requirements)) || state.rules.infiniteResources ?
|
drawPlaceText(Core.bundle.get((player.team().core() != null && player.team().core().items.has(requirements, state.rules.buildCostMultiplier)) || state.rules.infiniteResources ?
|
||||||
"bar.corereq" :
|
"bar.corereq" :
|
||||||
"bar.noresources"
|
"bar.noresources"
|
||||||
), x, y, valid);
|
), x, y, valid);
|
||||||
@@ -268,6 +268,26 @@ public class CoreBlock extends StorageBlock{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleStack(Item item, int amount, Teamc source){
|
||||||
|
super.handleStack(item, amount, source);
|
||||||
|
|
||||||
|
if(team == state.rules.defaultTeam && state.isCampaign()){
|
||||||
|
state.rules.sector.info.handleCoreItem(item, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int removeStack(Item item, int amount){
|
||||||
|
int result = super.removeStack(item, amount);
|
||||||
|
|
||||||
|
if(team == state.rules.defaultTeam && state.isCampaign()){
|
||||||
|
state.rules.sector.info.handleCoreItem(item, -result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawSelect(){
|
public void drawSelect(){
|
||||||
Lines.stroke(1f, Pal.accent);
|
Lines.stroke(1f, Pal.accent);
|
||||||
|
|||||||
@@ -53,15 +53,12 @@ public class UnitFactory extends UnitBlock{
|
|||||||
@Override
|
@Override
|
||||||
public void init(){
|
public void init(){
|
||||||
capacities = new int[Vars.content.items().size];
|
capacities = new int[Vars.content.items().size];
|
||||||
itemCapacity = 0;
|
|
||||||
for(UnitPlan plan : plans){
|
for(UnitPlan plan : plans){
|
||||||
for(ItemStack stack : plan.requirements){
|
for(ItemStack stack : plan.requirements){
|
||||||
capacities[stack.item.id] = Math.max(capacities[stack.item.id], stack.amount * 2);
|
capacities[stack.item.id] = Math.max(capacities[stack.item.id], stack.amount * 2);
|
||||||
|
itemCapacity = Math.max(itemCapacity, stack.amount * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(int i : capacities){
|
|
||||||
itemCapacity += i;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.init();
|
super.init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ public class SStats implements SteamUserStatsCallback{
|
|||||||
SStat.attacksWon.add();
|
SStat.attacksWon.add();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!e.sector.isBeingPlayed()){
|
if(!e.sector.isBeingPlayed() && !net.client()){
|
||||||
captureBackground.complete();
|
captureBackground.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
fastlane/metadata/android/en-US/changelogs/29719.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
- Added tutorial hints (Can be disabled in settings)
|
||||||
|
- Fixed game crashing on systems without audio devices
|
||||||
|
- Removed game startup dialog
|
||||||
|
- Campaign: Balancing of certain preset sectors
|
||||||
|
- Campaign: Made attacks less frequent
|
||||||
|
- Campaign: Shifted AI bases toward poles
|
||||||
|
- Campaign: Increased resource quantities near poles
|
||||||
|
- Campaign: Fixed sectors being accessible after defeat
|
||||||
|
- Campaign: Fixed AI builders sometimes blocking ground unit paths
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
||||||
archash=bfac70a18ab9158efefcd36f3ff43738c96733a0
|
archash=a61861127c9fea900f10b84a35be2369437be8f1
|
||||||
|
|||||||
@@ -1008,6 +1008,10 @@ public class ServerControl implements ApplicationListener{
|
|||||||
currentLogFile = null;
|
currentLogFile = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(String value : values){
|
||||||
|
text = text.replace(value, "");
|
||||||
|
}
|
||||||
|
|
||||||
if(currentLogFile == null){
|
if(currentLogFile == null){
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(logFolder.child("log-" + i + ".txt").length() >= maxLogLength){
|
while(logFolder.child("log-" + i + ".txt").length() >= maxLogLength){
|
||||||
|
|||||||