New WIP achievement definitions
This commit is contained in:
@@ -45,6 +45,9 @@ public class StatusEffects{
|
||||
|
||||
affinity(blasted, (unit, result, time) -> {
|
||||
unit.damagePierce(transitionDamage);
|
||||
if(unit.team == state.rules.waveTeam){
|
||||
Events.fire(Trigger.blastFreeze);
|
||||
}
|
||||
});
|
||||
});
|
||||
}};
|
||||
|
||||
@@ -39,6 +39,11 @@ public abstract class Content implements Comparable<Content>{
|
||||
return minfo.error != null;
|
||||
}
|
||||
|
||||
/** @return whether this is content from the base game. */
|
||||
public boolean isVanilla(){
|
||||
return minfo.mod == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Content c){
|
||||
return Integer.compare(id, c.id);
|
||||
|
||||
@@ -19,6 +19,7 @@ import static mindustry.Vars.*;
|
||||
|
||||
/** Utility class for damaging in an area. */
|
||||
public class Damage{
|
||||
private static final UnitDamageEvent bulletDamageEvent = new UnitDamageEvent();
|
||||
private static final Rect rect = new Rect();
|
||||
private static final Rect hitrect = new Rect();
|
||||
private static final Vec2 vec = new Vec2(), seg1 = new Vec2(), seg2 = new Vec2();
|
||||
@@ -467,21 +468,29 @@ public class Damage{
|
||||
|
||||
/** Damages all entities and blocks in a radius that are enemies of the team. */
|
||||
public static void damage(Team team, float x, float y, float radius, float damage, boolean complete, boolean air, boolean ground, boolean scaled, @Nullable Bullet source){
|
||||
Cons<Unit> cons = entity -> {
|
||||
if(entity.team == team || !entity.checkTarget(air, ground) || !entity.hittable() || !entity.within(x, y, radius + (scaled ? entity.hitSize / 2f : 0f))){
|
||||
Cons<Unit> cons = unit -> {
|
||||
if(unit.team == team || !unit.checkTarget(air, ground) || !unit.hittable() || !unit.within(x, y, radius + (scaled ? unit.hitSize / 2f : 0f))){
|
||||
return;
|
||||
}
|
||||
|
||||
float amount = calculateDamage(scaled ? Math.max(0, entity.dst(x, y) - entity.type.hitSize/2) : entity.dst(x, y), radius, damage);
|
||||
entity.damage(amount);
|
||||
boolean dead = unit.dead;
|
||||
|
||||
float amount = calculateDamage(scaled ? Math.max(0, unit.dst(x, y) - unit.type.hitSize/2) : unit.dst(x, y), radius, damage);
|
||||
unit.damage(amount);
|
||||
|
||||
if(source != null){
|
||||
entity.controller().hit(source);
|
||||
Events.fire(bulletDamageEvent.set(unit, source));
|
||||
unit.controller().hit(source);
|
||||
|
||||
if(!dead && unit.dead){
|
||||
Events.fire(new UnitBulletDestroyEvent(unit, source));
|
||||
}
|
||||
}
|
||||
//TODO better velocity displacement
|
||||
float dst = vec.set(entity.x - x, entity.y - y).len();
|
||||
entity.vel.add(vec.setLength((1f - dst / radius) * 2f / entity.mass()));
|
||||
float dst = vec.set(unit.x - x, unit.y - y).len();
|
||||
unit.vel.add(vec.setLength((1f - dst / radius) * 2f / unit.mass()));
|
||||
|
||||
if(complete && damage >= 9999999f && entity.isPlayer()){
|
||||
if(complete && damage >= 9999999f && unit.isPlayer()){
|
||||
Events.fire(Trigger.exclusionDeath);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -15,4 +15,5 @@ class GroupDefs<G>{
|
||||
@GroupDef(value = Puddlec.class) G puddle;
|
||||
@GroupDef(value = WeatherStatec.class) G weather;
|
||||
@GroupDef(value = WorldLabelc.class, mapping = true) G label;
|
||||
@GroupDef(value = PowerGraphUpdaterc.class) G powerGraph;
|
||||
}
|
||||
|
||||
@@ -22,11 +22,12 @@ import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.defense.Wall.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class BulletType extends Content implements Cloneable{
|
||||
static final UnitDamageEvent bulletDamageEvent = new UnitDamageEvent();
|
||||
|
||||
/** Lifetime in ticks. */
|
||||
public float lifetime = 40f;
|
||||
/** Speed in units/tick. */
|
||||
@@ -354,6 +355,8 @@ public class BulletType extends Content implements Cloneable{
|
||||
}
|
||||
|
||||
public void hitEntity(Bullet b, Hitboxc entity, float health){
|
||||
boolean wasDead = entity instanceof Unit u && u.dead;
|
||||
|
||||
if(entity instanceof Healthc h){
|
||||
if(pierceArmor){
|
||||
h.damagePierce(b.damage);
|
||||
@@ -367,11 +370,12 @@ public class BulletType extends Content implements Cloneable{
|
||||
if(impact) Tmp.v3.setAngle(b.rotation() + (knockback < 0 ? 180f : 0f));
|
||||
unit.impulse(Tmp.v3);
|
||||
unit.apply(status, statusDuration);
|
||||
|
||||
Events.fire(bulletDamageEvent.set(unit, b));
|
||||
}
|
||||
|
||||
//for achievements
|
||||
if(b.owner instanceof WallBuild && player != null && b.team == player.team() && entity instanceof Unit unit && unit.dead){
|
||||
Events.fire(Trigger.phaseDeflectHit);
|
||||
if(!wasDead && entity instanceof Unit unit && unit.dead){
|
||||
Events.fire(new UnitBulletDestroyEvent(unit, b));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1570,9 +1570,15 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
/** Handle a bullet collision.
|
||||
* @return whether the bullet should be removed. */
|
||||
public boolean collision(Bullet other){
|
||||
boolean wasDead = dead();
|
||||
|
||||
damage(other.team, other.damage() * other.type().buildingDamageMultiplier);
|
||||
Events.fire(bulletDamageEvent.set(self(), other));
|
||||
|
||||
if(dead() && !wasDead){
|
||||
Events.fire(new BuildingBulletDestroyEvent(self(), other));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,13 @@ public class EventType{
|
||||
//events that occur very often
|
||||
public enum Trigger{
|
||||
shock,
|
||||
phaseDeflectHit,
|
||||
blastFreeze,
|
||||
impactPower,
|
||||
blastGenerator,
|
||||
shockwaveTowerUse,
|
||||
forceProjectorBreak,
|
||||
thoriumReactorOverheat,
|
||||
neoplasmReact,
|
||||
fireExtinguish,
|
||||
acceleratorUse,
|
||||
newGame,
|
||||
@@ -33,6 +37,7 @@ public class EventType{
|
||||
socketConfigChanged,
|
||||
update,
|
||||
unitCommandChange,
|
||||
importMod,
|
||||
draw,
|
||||
drawOver,
|
||||
preDraw,
|
||||
@@ -127,6 +132,17 @@ public class EventType{
|
||||
}
|
||||
}
|
||||
|
||||
public static class SectorLaunchLoadoutEvent{
|
||||
public final Sector sector, from;
|
||||
public final Schematic loadout;
|
||||
|
||||
public SectorLaunchLoadoutEvent(Sector sector, Sector from, Schematic loadout){
|
||||
this.sector = sector;
|
||||
this.from = from;
|
||||
this.loadout = loadout;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SchematicCreateEvent{
|
||||
public final Schematic schematic;
|
||||
|
||||
@@ -448,6 +464,29 @@ public class EventType{
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when a neoplasia (or other pressure-based block, from mods) reactor explodes due to pressure.*/
|
||||
public static class GeneratorPressureExplodeEvent{
|
||||
public final Building build;
|
||||
|
||||
public GeneratorPressureExplodeEvent(Building build){
|
||||
this.build = build;
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when a building is directly killed by a bullet. May not fire in all circumstances. */
|
||||
public static class BuildingBulletDestroyEvent{
|
||||
public Building build;
|
||||
public Bullet bullet;
|
||||
|
||||
public BuildingBulletDestroyEvent(Building build, Bullet bullet){
|
||||
this.build = build;
|
||||
this.bullet = bullet;
|
||||
}
|
||||
|
||||
public BuildingBulletDestroyEvent(){
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnitDestroyEvent{
|
||||
public final Unit unit;
|
||||
|
||||
@@ -456,6 +495,35 @@ public class EventType{
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when a unit is directly killed by a bullet. May not fire in all circumstances. */
|
||||
public static class UnitBulletDestroyEvent{
|
||||
public Unit unit;
|
||||
public Bullet bullet;
|
||||
|
||||
public UnitBulletDestroyEvent(Unit unit, Bullet bullet){
|
||||
this.unit = unit;
|
||||
this.bullet = bullet;
|
||||
}
|
||||
|
||||
public UnitBulletDestroyEvent(){
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a unit is hit by a bullet.
|
||||
* This event is REUSED, do not nest invocations of it (e.g. damage units in its event handler)
|
||||
* */
|
||||
public static class UnitDamageEvent{
|
||||
public Unit unit;
|
||||
public Bullet bullet;
|
||||
|
||||
public UnitDamageEvent set(Unit unit, Bullet bullet){
|
||||
this.unit = unit;
|
||||
this.bullet = bullet;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnitDrownEvent{
|
||||
public final Unit unit;
|
||||
|
||||
|
||||
@@ -292,6 +292,10 @@ public class Schematics implements Loadable{
|
||||
return defaultLoadouts.get(block);
|
||||
}
|
||||
|
||||
public boolean isDefaultLoadout(Schematic schem){
|
||||
return defaultLoadouts.containsValue(schem, true);
|
||||
}
|
||||
|
||||
/** Checks a schematic for deployment validity and adds it to the cache. */
|
||||
private void checkLoadout(Schematic s, boolean customSchem){
|
||||
Stile core = s.tiles.find(t -> t.block instanceof CoreBlock);
|
||||
|
||||
@@ -286,6 +286,11 @@ public class Teams{
|
||||
return buildingTypes.get(block, () -> new Seq<>(false));
|
||||
}
|
||||
|
||||
public int getCount(Block block){
|
||||
var res = buildingTypes.get(block);
|
||||
return res == null ? 0 : res.size;
|
||||
}
|
||||
|
||||
/** Destroys this team's presence on the map, killing part of its buildings and converting everything to 'derelict'. */
|
||||
public void destroyToDerelict(){
|
||||
|
||||
@@ -355,6 +360,12 @@ public class Teams{
|
||||
}
|
||||
}
|
||||
|
||||
//this is just an alias for consistency
|
||||
@Nullable
|
||||
public Seq<Unit> getUnits(UnitType type){
|
||||
return unitCache(type);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Seq<Unit> unitCache(UnitType type){
|
||||
if(unitsByType == null || unitsByType.length <= type.id || unitsByType[type.id] == null) return null;
|
||||
|
||||
@@ -110,6 +110,9 @@ public class Mods implements Loadable{
|
||||
sortMods();
|
||||
//try to load the mod's icon so it displays on import
|
||||
Core.app.post(() -> loadIcon(loaded));
|
||||
|
||||
Events.fire(Trigger.importMod);
|
||||
|
||||
return loaded;
|
||||
}catch(IOException e){
|
||||
dest.delete();
|
||||
|
||||
@@ -15,7 +15,7 @@ public enum Achievement{
|
||||
launch30Times(SStat.timesLaunched, 30),
|
||||
captureBackground,
|
||||
survive100Waves(SStat.maxWavesSurvived, 100),
|
||||
researchAll,
|
||||
researchAll, //TODO - remake/change?
|
||||
shockWetEnemy,
|
||||
killEnemyPhaseWall,
|
||||
researchRouter,
|
||||
@@ -51,6 +51,7 @@ public enum Achievement{
|
||||
circleConveyor,
|
||||
becomeRouter,
|
||||
create20Schematics(SStat.schematicsCreated, 20),
|
||||
create500Schematics(SStat.schematicsCreated, 50), //TODO - Steam
|
||||
survive10WavesNoBlocks,
|
||||
captureNoBlocksBroken,
|
||||
useFlameAmmo,
|
||||
@@ -60,6 +61,61 @@ public enum Achievement{
|
||||
useAccelerator,
|
||||
unlockAllZones,
|
||||
|
||||
//TODO new ones
|
||||
|
||||
allTransportOneMap, //TODO - Steam
|
||||
buildOverdrive, //TODO - Steam
|
||||
buildMendProjector, //TODO - Steam
|
||||
buildWexWater, //TODO - Steam
|
||||
|
||||
have10mItems(SStat.totalCampaignItems, 10_000_000), //TODO - Steam
|
||||
killEclipseDuo, //TODO - Steam
|
||||
|
||||
allPresetsErekir, //TODO - Steam
|
||||
|
||||
launchCoreSchematic, //TODO - Steam
|
||||
nucleusGroundZero, //TODO - Steam
|
||||
|
||||
neoplasmWater, //TODO - Steam
|
||||
blastFrozenUnit, //TODO - Steam
|
||||
|
||||
allBlocksSerpulo, //TODO - Steam
|
||||
allBlocksErekir, //TODO - Steam
|
||||
|
||||
//TODO are these necessary?
|
||||
//allTurretsSerpulo, //TODO
|
||||
//allTurretsErekir, //TODO
|
||||
//allTechSerpulo, //TODO
|
||||
//allTechErekir, //TODO
|
||||
|
||||
breakForceProjector, //TODO - Steam
|
||||
researchLogic, //TODO - Steam
|
||||
|
||||
negative10kPower, //TODO - Steam
|
||||
positive100kPower, //TODO - Steam
|
||||
store1milPower, //TODO - Steam
|
||||
|
||||
blastGenerator, //TODO - Steam
|
||||
neoplasiaExplosion, //TODO - Steam
|
||||
|
||||
installMod, //TODO - Steam
|
||||
routerLanguage, //TODO - Steam
|
||||
joinCommunityServer, //TODO - Steam
|
||||
openConsole, //TODO - Steam
|
||||
|
||||
controlTurret, //TODO - Steam
|
||||
dropUnitsCoreZone, //TODO - Steam
|
||||
destroyScatterFlare, //TODO - Steam
|
||||
boostUnit, //TODO - Steam
|
||||
boostBuildingFloor, //TODO - Steam
|
||||
|
||||
hoverUnitLiquid, //TODO - Steam
|
||||
|
||||
break100Boulders(SStat.bouldersDeconstructed, 100), //TODO - Steam
|
||||
break10000Boulders(SStat.bouldersDeconstructed, 10_000), //TODO - Steam
|
||||
|
||||
shockwaveTowerUse, //TODO - Steam
|
||||
|
||||
;
|
||||
|
||||
private final SStat stat;
|
||||
|
||||
@@ -11,7 +11,13 @@ import mindustry.game.SectorInfo.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.defense.*;
|
||||
import mindustry.world.blocks.defense.Wall.*;
|
||||
import mindustry.world.blocks.defense.turrets.Turret.*;
|
||||
import mindustry.world.blocks.distribution.*;
|
||||
import mindustry.world.blocks.production.AttributeCrafter.*;
|
||||
import mindustry.world.blocks.production.SolidPump.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.service.Achievement.*;
|
||||
@@ -21,16 +27,17 @@ import static mindustry.service.Achievement.*;
|
||||
*
|
||||
* This includes:
|
||||
* - Desktop (Steam)
|
||||
* - iOS (Game Center)
|
||||
* - Android (Google Play Games)
|
||||
*
|
||||
* The default implementation does nothing.
|
||||
* */
|
||||
public class GameService{
|
||||
private Seq<Tile> tmpTiles = new Seq<>();
|
||||
private ObjectSet<String> blocksBuilt = new ObjectSet<>(), unitsBuilt = new ObjectSet<>();
|
||||
private ObjectSet<UnitType> t5s = new ObjectSet<>();
|
||||
private IntSet checked = new IntSet();
|
||||
|
||||
private Block[] allTransportSerpulo, allTransportErekir, allErekirBlocks, allSerpuloBlocks;
|
||||
|
||||
/** Begin listening for new achievement events, once the game service is activated. This can be called at any time, but only once. */
|
||||
public void init(){
|
||||
if(clientLoaded){
|
||||
@@ -64,11 +71,26 @@ public class GameService{
|
||||
|
||||
}
|
||||
|
||||
private void checkAllBlocks(Achievement ach, Block[] blocks){
|
||||
if(!Structs.contains(blocks, t -> !blocksBuilt.contains(t.name))){
|
||||
ach.complete();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerEvents(){
|
||||
allTransportSerpulo = content.blocks().select(b -> b.category == Category.distribution && b.isVisibleOn(Planets.serpulo) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
|
||||
allTransportErekir = content.blocks().select(b -> b.category == Category.distribution && b.isVisibleOn(Planets.erekir) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
|
||||
|
||||
allSerpuloBlocks = content.blocks().select(b -> b.synthetic() && b.isVisibleOn(Planets.serpulo) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
|
||||
allErekirBlocks = content.blocks().select(b -> b.synthetic() && b.isVisibleOn(Planets.erekir) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
|
||||
|
||||
unitsBuilt = Core.settings.getJson("units-built" , ObjectSet.class, String.class, ObjectSet::new);
|
||||
blocksBuilt = Core.settings.getJson("blocks-built" , ObjectSet.class, String.class, ObjectSet::new);
|
||||
t5s = ObjectSet.with(UnitTypes.omura, UnitTypes.reign, UnitTypes.toxopid, UnitTypes.eclipse, UnitTypes.oct, UnitTypes.corvus);
|
||||
|
||||
checkAllBlocks(allBlocksErekir, allErekirBlocks);
|
||||
checkAllBlocks(allBlocksSerpulo, allSerpuloBlocks);
|
||||
|
||||
//periodically check for various conditions
|
||||
float updateInterval = 2f;
|
||||
Timer.schedule(this::checkUpdate, updateInterval, updateInterval);
|
||||
@@ -79,6 +101,14 @@ public class GameService{
|
||||
unlockAllZones.complete();
|
||||
}
|
||||
|
||||
if(mods.list().size > 0){
|
||||
installMod.complete();
|
||||
}
|
||||
|
||||
if(Core.bundle.get("yes").equals("router")){
|
||||
routerLanguage.complete();
|
||||
}
|
||||
|
||||
Events.on(UnitDestroyEvent.class, e -> {
|
||||
if(campaign()){
|
||||
if(e.unit.team != Vars.player.team()){
|
||||
@@ -106,12 +136,43 @@ public class GameService{
|
||||
SStat.maxProduction.max(Math.round(total));
|
||||
});
|
||||
|
||||
Events.run(Trigger.update, () -> {
|
||||
//extremely lazy timer, I just don't care
|
||||
if(campaign() && !hoverUnitLiquid.isAchieved() && Core.graphics.getFrameId() % 20 == 0){
|
||||
var units = state.rules.defaultTeam.data().getUnits(UnitTypes.elude);
|
||||
if(units != null){
|
||||
for(var unit : units){
|
||||
if(unit.floorOn().isLiquid){
|
||||
hoverUnitLiquid.complete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(campaign() && player.unit().type.canBoost && player.unit().elevation >= 0.25f){
|
||||
boostUnit.complete();
|
||||
}
|
||||
});
|
||||
|
||||
Events.run(Trigger.newGame, () -> Core.app.post(() -> {
|
||||
if(campaign() && player.core() != null && player.core().items.total() >= 10 * 1000){
|
||||
drop10kitems.complete();
|
||||
}
|
||||
}));
|
||||
|
||||
Events.on(BuildingBulletDestroyEvent.class, e -> {
|
||||
if(campaign() && e.build.block == Blocks.scatter && e.build.team == state.rules.waveTeam && e.bullet.owner instanceof Unit u && u.type == UnitTypes.flare && u.team == player.team()){
|
||||
destroyScatterFlare.complete();
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(BlockBuildBeginEvent.class, e -> {
|
||||
if(campaign() && state.rules.sector == SectorPresets.groundZero.sector && e.tile.block() == Blocks.coreNucleus){
|
||||
nucleusGroundZero.complete();
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(BlockBuildEndEvent.class, e -> {
|
||||
if(campaign() && e.unit != null && e.unit.isLocal() && !e.breaking){
|
||||
SStat.blocksBuilt.add();
|
||||
@@ -124,7 +185,40 @@ public class GameService{
|
||||
buildGroundFactory.complete();
|
||||
}
|
||||
|
||||
if((e.tile.build instanceof AttributeCrafterBuild a && a.attrsum > 0) || (e.tile.build instanceof SolidPumpBuild sp && sp.boost > 0)){
|
||||
boostBuildingFloor.complete();
|
||||
}
|
||||
|
||||
if(!allTransportOneMap.isAchieved()){
|
||||
Block[] allTransports = state.rules.sector.planet == Planets.erekir ? allTransportErekir : allTransportSerpulo;
|
||||
boolean all = true;
|
||||
for(var block : allTransports){
|
||||
if(state.rules.defaultTeam.data().getCount(block) == 0){
|
||||
all = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(all){
|
||||
allTransportOneMap.complete();
|
||||
}
|
||||
}
|
||||
|
||||
if(e.tile.block() instanceof MendProjector || e.tile.block() instanceof RegenProjector) buildMendProjector.complete();
|
||||
if(e.tile.block() instanceof OverdriveProjector) buildOverdrive.complete();
|
||||
|
||||
if(e.tile.block() == Blocks.waterExtractor){
|
||||
if(e.tile.getLinkedTiles(tmpTiles).contains(t -> t.floor().liquidDrop == Liquids.water)){
|
||||
buildWexWater.complete();
|
||||
}
|
||||
}
|
||||
|
||||
if(blocksBuilt.add(e.tile.block().name)){
|
||||
if(state.rules.sector.planet == Planets.erekir){
|
||||
checkAllBlocks(allBlocksErekir, allErekirBlocks);
|
||||
}else{
|
||||
checkAllBlocks(allBlocksSerpulo, allSerpuloBlocks);
|
||||
}
|
||||
|
||||
if(blocksBuilt.contains("meltdown") && blocksBuilt.contains("spectre") && blocksBuilt.contains("foreshadow")){
|
||||
buildMeltdownSpectre.complete();
|
||||
}
|
||||
@@ -153,6 +247,32 @@ public class GameService{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(campaign() && e.unit != null && e.unit.isLocal() && e.breaking){
|
||||
//hacky way of testing for boulders without string contains/endsWith
|
||||
if(e.tile.block().breakSound == Sounds.rockBreak){
|
||||
SStat.bouldersDeconstructed.add();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(TurnEvent.class, e -> {
|
||||
int total = 0;
|
||||
for(var planet : content.planets()){
|
||||
for(var sector : planet.sectors){
|
||||
if(sector.hasBase()){
|
||||
total += sector.items().total;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SStat.totalCampaignItems.max(total);
|
||||
});
|
||||
|
||||
Events.on(SectorLaunchLoadoutEvent.class, e -> {
|
||||
if(!schematics.isDefaultLoadout(e.loadout)){
|
||||
launchCoreSchematic.complete();
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(UnitCreateEvent.class, e -> {
|
||||
@@ -172,6 +292,10 @@ public class GameService{
|
||||
if(e.unit instanceof BlockUnitc unit && unit.tile().block == Blocks.router){
|
||||
becomeRouter.complete();
|
||||
}
|
||||
|
||||
if(e.unit instanceof BlockUnitc unit && unit.tile() instanceof TurretBuild){
|
||||
controlTurret.complete();
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(SchematicCreateEvent.class, e -> {
|
||||
@@ -198,6 +322,8 @@ public class GameService{
|
||||
|
||||
Events.run(Trigger.openWiki, openWiki::complete);
|
||||
|
||||
Events.run(Trigger.importMod, installMod::complete);
|
||||
|
||||
Events.run(Trigger.exclusionDeath, dieExclusion::complete);
|
||||
|
||||
Events.on(UnitDrownEvent.class, e -> {
|
||||
@@ -216,6 +342,14 @@ public class GameService{
|
||||
|
||||
trigger(Trigger.suicideBomb, suicideBomb);
|
||||
|
||||
trigger(Trigger.blastGenerator, blastGenerator);
|
||||
|
||||
trigger(Trigger.forceProjectorBreak, breakForceProjector);
|
||||
|
||||
trigger(Trigger.neoplasmReact, neoplasmWater);
|
||||
|
||||
trigger(Trigger.shockwaveTowerUse, shockwaveTowerUse);
|
||||
|
||||
Events.run(Trigger.enablePixelation, enablePixelation::complete);
|
||||
|
||||
Events.run(Trigger.thoriumReactorOverheat, () -> {
|
||||
@@ -224,9 +358,28 @@ public class GameService{
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(GeneratorPressureExplodeEvent.class, e -> {
|
||||
if(campaign() && e.build.block == Blocks.neoplasiaReactor){
|
||||
neoplasiaExplosion.complete();
|
||||
}
|
||||
});
|
||||
|
||||
trigger(Trigger.shock, shockWetEnemy);
|
||||
|
||||
trigger(Trigger.phaseDeflectHit, killEnemyPhaseWall);
|
||||
trigger(Trigger.blastFreeze, blastFrozenUnit);
|
||||
|
||||
Events.on(UnitBulletDestroyEvent.class, e -> {
|
||||
if(state.isCampaign() && player != null && player.team() == e.bullet.team){
|
||||
|
||||
if(e.bullet.owner instanceof WallBuild){
|
||||
killEnemyPhaseWall.complete();
|
||||
}
|
||||
|
||||
if(e.unit.type == UnitTypes.eclipse && e.bullet.owner instanceof TurretBuild turret && turret.block == Blocks.duo){
|
||||
killEclipseDuo.complete();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(LaunchItemEvent.class, e -> {
|
||||
if(campaign()){
|
||||
@@ -276,6 +429,8 @@ public class GameService{
|
||||
if(!TechTree.all.contains(t -> t.content.locked())){
|
||||
researchAll.complete();
|
||||
}
|
||||
|
||||
if(Blocks.logicProcessor.unlocked()) researchLogic.complete();
|
||||
};
|
||||
|
||||
//check unlocked stuff on load as well
|
||||
@@ -289,6 +444,12 @@ public class GameService{
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(ClientPreConnectEvent.class, e -> {
|
||||
if(e.host != null && !e.host.address.startsWith("steam:") && !e.host.address.startsWith("192.")){
|
||||
joinCommunityServer.complete();
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(SectorCaptureEvent.class, e -> {
|
||||
if(e.sector.isBeingPlayed() || net.client()){
|
||||
if(Vars.state.wave <= 5 && state.rules.attackMode){
|
||||
@@ -312,8 +473,18 @@ public class GameService{
|
||||
captureAllSectors.complete();
|
||||
}
|
||||
|
||||
if(!e.sector.planet.sectors.contains(s -> s.preset != null && !s.hasBase())){
|
||||
allPresetsErekir.complete();
|
||||
}
|
||||
|
||||
SStat.sectorsControlled.set(e.sector.planet.sectors.count(Sector::hasBase));
|
||||
});
|
||||
|
||||
Events.on(PayloadDropEvent.class, e -> {
|
||||
if(e.unit != null && e.carrier.team == state.rules.defaultTeam && state.rules.waveTeam.cores().contains(c -> c.within(e.unit, state.rules.enemyCoreBuildRadius))){
|
||||
dropUnitsCoreZone.complete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void checkUpdate(){
|
||||
@@ -330,6 +501,20 @@ public class GameService{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(var up : Groups.powerGraph){
|
||||
var graph = up.graph();
|
||||
if(graph.all.size > 0 && graph.all.first().team == player.team()){
|
||||
float balance = graph.getPowerBalance();
|
||||
if(balance < 10_000) negative10kPower.complete();
|
||||
if(balance > 100_000) positive100kPower.complete();
|
||||
if(graph.getBatteryStored() > 1_000_000) store1milPower.complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ui.consolefrag.shown()){
|
||||
openConsole.complete();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ public enum SStat{
|
||||
maxProduction,
|
||||
sectorsControlled,
|
||||
schematicsCreated,
|
||||
bouldersDeconstructed, //TODO
|
||||
totalCampaignItems, //TODO
|
||||
;
|
||||
|
||||
public int get(){
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package mindustry.type;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
@@ -35,6 +38,7 @@ public class CellLiquid extends Liquid{
|
||||
|
||||
if(spreadTarget != null){
|
||||
float scaling = Mathf.pow(Mathf.clamp(puddle.amount / maxLiquid), 2f);
|
||||
boolean reacted = false;
|
||||
|
||||
for(var point : Geometry.d4c){
|
||||
Tile tile = puddle.tile.nearby(point);
|
||||
@@ -42,11 +46,13 @@ public class CellLiquid extends Liquid{
|
||||
float amount = Math.min(tile.build.liquids.get(spreadTarget), maxSpread * Time.delta * scaling);
|
||||
tile.build.liquids.remove(spreadTarget, amount * removeScaling);
|
||||
Puddles.deposit(tile, this, amount * spreadConversion);
|
||||
reacted = true;
|
||||
}
|
||||
}
|
||||
|
||||
//damage thing it is on
|
||||
if(spreadDamage > 0 && puddle.tile.build != null && puddle.tile.build.liquids != null && puddle.tile.build.liquids.get(spreadTarget) > 0.0001f){
|
||||
reacted = true;
|
||||
|
||||
//spread in 4 adjacent directions around thing it is on
|
||||
float amountSpread = Math.min(puddle.tile.build.liquids.get(spreadTarget) * spreadConversion, maxSpread * Time.delta) / 2f;
|
||||
@@ -70,6 +76,7 @@ public class CellLiquid extends Liquid{
|
||||
float amount = Math.min(other.amount, Math.max(maxSpread * Time.delta * scaling, other.amount * 0.25f * scaling));
|
||||
other.amount -= amount;
|
||||
puddle.amount += amount;
|
||||
reacted = true;
|
||||
if(other.amount <= maxLiquid / 3f){
|
||||
other.remove();
|
||||
Puddles.deposit(tile, puddle.tile, this, Math.max(amount, maxLiquid / 3f));
|
||||
@@ -77,6 +84,10 @@ public class CellLiquid extends Liquid{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(reacted && this == Liquids.neoplasm){
|
||||
Events.fire(Trigger.neoplasmReact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import mindustry.content.*;
|
||||
import mindustry.content.TechTree.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.Objectives.*;
|
||||
import mindustry.game.SectorInfo.*;
|
||||
import mindustry.game.*;
|
||||
@@ -1215,10 +1216,13 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
CoreBlock block = sector.allowLaunchSchematics() ? (from.info.bestCoreType instanceof CoreBlock b ? b : (CoreBlock)from.planet.defaultCore) : (CoreBlock)from.planet.defaultCore;
|
||||
|
||||
loadouts.show(block, from, sector, () -> {
|
||||
var schemCore = universe.getLastLoadout().findCore();
|
||||
from.removeItems(universe.getLastLoadout().requirements());
|
||||
var loadout = universe.getLastLoadout();
|
||||
var schemCore = loadout.findCore();
|
||||
from.removeItems(loadout.requirements());
|
||||
from.removeItems(universe.getLaunchResources());
|
||||
|
||||
Events.fire(new SectorLaunchLoadoutEvent(sector, from, loadout));
|
||||
|
||||
if(settings.getBool("skipcoreanimation")){
|
||||
//just... go there
|
||||
control.playSector(from, sector);
|
||||
|
||||
@@ -856,6 +856,10 @@ public class Block extends UnlockableContent implements Senseable{
|
||||
return !isHidden() && (state.rules.editor || (!state.rules.hideBannedBlocks || !state.rules.isBanned(this)));
|
||||
}
|
||||
|
||||
public boolean isVisibleOn(Planet planet){
|
||||
return !Structs.contains(requirements, i -> planet.hiddenItems.contains(i.item));
|
||||
}
|
||||
|
||||
public boolean isPlaceable(){
|
||||
return isVisible() && (!state.rules.isBanned(this) || state.rules.editor) && supportsEnv(state.rules.env);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.world.blocks.defense;
|
||||
|
||||
import arc.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
@@ -10,6 +11,7 @@ import arc.util.io.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
@@ -186,6 +188,9 @@ public class ForceProjector extends Block{
|
||||
broken = true;
|
||||
buildup = shieldHealth;
|
||||
shieldBreakEffect.at(x, y, realRadius(), team.color);
|
||||
if(team != state.rules.defaultTeam){
|
||||
Events.fire(Trigger.forceProjectorBreak);
|
||||
}
|
||||
}
|
||||
|
||||
if(hit > 0f){
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package mindustry.world.blocks.defense;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import arc.struct.*;
|
||||
import arc.*;
|
||||
import arc.audio.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.audio.*;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.meta.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.annotations.Annotations.Load;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@@ -89,6 +91,10 @@ public class ShockwaveTower extends Block{
|
||||
target.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if(team == state.rules.defaultTeam){
|
||||
Events.fire(Trigger.shockwaveTowerUse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package mindustry.world.blocks.power;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.consumers.*;
|
||||
@@ -115,6 +117,7 @@ public class ConsumeGenerator extends PowerGenerator{
|
||||
|
||||
if(explodeOnFull && liquids.get(outputLiquid.liquid) >= liquidCapacity - 0.0001f){
|
||||
kill();
|
||||
Events.fire(new GeneratorPressureExplodeEvent(this));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package mindustry.world.consumers;
|
||||
|
||||
import arc.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
@@ -34,6 +36,7 @@ public class ConsumeItemExplode extends ConsumeItemFilter{
|
||||
if(Vars.state.rules.reactorExplosions && Mathf.chance(build.delta() * baseChance * Mathf.clamp(item.explosiveness - threshold))){
|
||||
build.damage(damage);
|
||||
explodeEffect.at(build.x + Mathf.range(build.block.size * tilesize / 2f), build.y + Mathf.range(build.block.size * tilesize / 2f));
|
||||
Events.fire(Trigger.blastGenerator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user