diff --git a/plugin.json b/plugin.json index 4ca86eb..bd39c29 100644 --- a/plugin.json +++ b/plugin.json @@ -1,5 +1,5 @@ { - "name": "Agzam's plugin v1.8.1", + "name": "Agzam's plugin v1.8.3", "author": "Agzam4", "main": "example.ExamplePlugin", "description": "New command, events, core protection from thorium reactors and more", diff --git a/src/example/DataCollecter.java b/src/example/DataCollecter.java index bc3fa4e..9793f4f 100644 --- a/src/example/DataCollecter.java +++ b/src/example/DataCollecter.java @@ -1,5 +1,6 @@ package example; +import java.io.File; import java.io.Writer; import java.nio.file.Paths; import java.util.ArrayList; @@ -8,7 +9,12 @@ import arc.Core; import arc.Files; +import arc.Files.FileType; import arc.files.Fi; +import arc.func.Intc2; +import arc.math.geom.Geometry; +import arc.math.geom.Vec2; +import arc.struct.Seq; import arc.util.Log; import arc.util.serialization.Json; import arc.util.serialization.JsonWriter; @@ -21,10 +27,12 @@ import mindustry.gen.Player; import mindustry.io.JsonIO; import mindustry.net.Administration.Config; +import mindustry.net.Administration.PlayerInfo; public class DataCollecter { public static final String FILENAME = "agzam_s_plugin_statistics.json"; + public static final String FILENAME_ADMINS = "agzam_s_plugin_admins.json"; private transient long sleepTime = 5 * 60_000 / 60 / 5; // FIXME: 5 minutes @@ -119,9 +127,26 @@ public void save() { json.append('}'); - Fi fi = new Fi(getPathToFile()); + Fi fi = new Fi(getPathToFile(FILENAME)); fi.writeString(json.toString()); -// Files.writeString(json);//(Vars.saveDirectory, json); + + + StringBuilder adminsList = new StringBuilder("Admins list (IP/ID/NAME):"); + + if(Vars.netServer != null) { + Seq admins = Vars.netServer.admins.getAdmins(); + if(admins != null) { + if(admins.size == 0){ + }else{ + for (int i = 0; i < admins.size; i++) { + PlayerInfo info = admins.get(i); + adminsList.append("\n" + info.lastIP + " " + info.id + " " + info.plainLastName()); + } + } + } + } + Fi fia = new Fi(getPathToFile(FILENAME_ADMINS)); + fia.writeString(adminsList.toString()); } private void createJsonValue(StringBuilder json, String name, String[][] values) { @@ -171,8 +196,8 @@ private void createJsonValue(StringBuilder json, String name, int value) { json.append(",\n"); } - public static String getPathToFile() { - return Vars.saveDirectory + "/" + FILENAME; + public static String getPathToFile(String name) { + return Vars.saveDirectory + "/" + name; } public long getSleepTime() { diff --git a/src/example/Emoji.java b/src/example/Emoji.java new file mode 100644 index 0000000..a3adb7d --- /dev/null +++ b/src/example/Emoji.java @@ -0,0 +1,50 @@ +package example; + +import static example.Emoji.emojiCryofluid; +import static example.Emoji.emojiOil; +import static example.Emoji.emojiSlag; +import static example.Emoji.emojiWater; + +public class Emoji { + + public static final char emojiCopper = '\uf838'; + public static final char emojiLead = '\uf837'; + public static final char emojiMetaglass = '\uf836'; + public static final char emojiGraphite = '\uf835'; + public static final char emojiSand = '\uf834'; + public static final char emojiCoal = '\uf833'; + public static final char emojiTitanium = '\uf832'; + public static final char emojiThorium = '\uf831'; + public static final char emojiScrap = '\uf830'; + public static final char emojiSilicon = '\uf82f'; + public static final char emojiPlastanium = '\uf82e'; + public static final char emojiPhaseFabric = '\uf82d'; + public static final char emojiSurgeAlloy = '\uf82c'; + public static final char emojiSporePod = '\uf82b'; + public static final char emojiBlastCompound = '\uf82a'; + public static final char emojiPyratite = '\uf829'; + + public static final char emojiWater = '\uf828'; + public static final char emojiSlag = '\uf827'; + public static final char emojiOil = '\uf826'; + public static final char emojiCryofluid = '\uf825'; + + public static final char emojiAlert = '\u26a0'; + + public static final char[] oreBlocksEmoji = new char[] { + emojiCopper, + emojiLead, + emojiScrap, + emojiSand, + emojiCoal, + emojiTitanium, + emojiThorium + }; + + public static final char[] liquidsEmoji = new char[] { + emojiWater, + emojiOil, + emojiSlag, + emojiCryofluid + }; +} diff --git a/src/example/ExamplePlugin.java b/src/example/ExamplePlugin.java index b5eb32b..302b55f 100644 --- a/src/example/ExamplePlugin.java +++ b/src/example/ExamplePlugin.java @@ -1,15 +1,18 @@ package example; +import java.awt.Point; import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Arrays; import java.util.Iterator; -import javax.swing.plaf.nimbus.State; - import arc.*; +import arc.freetype.FreeType.Size; +import arc.func.Intc2; import arc.graphics.Color; +import arc.graphics.g2d.Draw; import arc.math.Mathf; +import arc.math.geom.Point2; +import arc.math.geom.Vec2; import arc.struct.ObjectSet; import arc.struct.Seq; import arc.util.*; @@ -20,109 +23,77 @@ import mindustry.content.*; import mindustry.core.GameState; import mindustry.core.World; -import mindustry.game.Team; +import mindustry.ctype.Content; +import mindustry.ctype.ContentType; +import mindustry.entities.Effect; +import mindustry.entities.units.BuildPlan; import mindustry.gen.Call; import mindustry.gen.Groups; import mindustry.gen.Player; import mindustry.gen.Unit; -import mindustry.game.EventType; import mindustry.game.EventType.*; -import mindustry.game.GameStats; import mindustry.game.Gamemode; +import mindustry.game.Team; import mindustry.mod.*; import mindustry.net.Administration; import mindustry.net.Administration.*; import mindustry.type.Item; import mindustry.type.Liquid; import mindustry.type.UnitType; +import mindustry.world.Block; +import mindustry.world.Tile; +import mindustry.world.blocks.environment.Floor; +import mindustry.world.blocks.environment.OverlayFloor; import mindustry.world.blocks.storage.CoreBlock.CoreBuild; import mindustry.maps.Map; import mindustry.maps.*; import static mindustry.Vars.*; +import static example.Emoji.*; public class ExamplePlugin extends Plugin{ - private @Nullable Map nextMapOverride; - private boolean inGameOverWait; - private Gamemode lastMode; - private GameState e; + private static final String PLUGIN_NAME = "agzams-plugin"; + + private @Nullable Map nextMapOverride; private Maps maps; private Administration admins = new Administration(); - private float lastThoriumReactorAlertX, lastThoriumReactorAlertY; - - private World world; private String worldinfo = ""; - private boolean chatFilter; private DataCollecter dataCollect; - - - private static final char emojiCopper = '\uf838'; - private static final char emojiLead = '\uf837'; - private static final char emojiMetaglass = '\uf836'; - private static final char emojiGraphite = '\uf835'; - private static final char emojiSand = '\uf834'; - private static final char emojiCoal = '\uf833'; - private static final char emojiTitanium = '\uf832'; - private static final char emojiThorium = '\uf831'; - private static final char emojiScrap = '\uf830'; - private static final char emojiSilicon = '\uf82f'; - private static final char emojiPlastanium = '\uf82e'; - private static final char emojiPhaseFabric = '\uf82d'; - private static final char emojiSurgeAlloy = '\uf82c'; - private static final char emojiSporePod = '\uf82b'; - private static final char emojiBlastCompound = '\uf82a'; - private static final char emojiPyratite = '\uf829'; - - private static final char emojiWater = '\uf828'; - private static final char emojiSlag = '\uf827'; - private static final char emojiOil = '\uf826'; - private static final char emojiCryofluid = '\uf825'; - - private static final char emojiAlert = '\u26a0'; -// private static final char emojiWater = '\uf826'; - - - private static final char[] oreblocksemoji = new char[] { - emojiCopper, - emojiLead, - emojiScrap, - emojiSand, - emojiCoal, - emojiTitanium, - emojiThorium - }; - - private static final char[] liquidsemoji = new char[] { - emojiWater, - emojiOil, - emojiSlag, - emojiCryofluid - }; + private static int doorsCup = 100; + private static ArrayList doorsCoordinates; private ServerEventsManager eventsManager; private Team admin; - - + + private boolean chatFilter; private int ignoreUnitId = -1; -// private - private int updateId = 0; - + + private Block brushBlock; + private Floor brushFloor; + private OverlayFloor brushOverlay; SkipmapVoteSession[] currentlyMapSkipping = {null}; -// - - MyMenu menu; - // TODO: bans command - //called when game initializes + private ArrayList extraStarsUIDD; + @Override public void init() { + Vars.netServer.admins.getBannedIPs(); + + doorsCup = Core.settings.getInt(PLUGIN_NAME + "-doors-cup", Integer.MAX_VALUE); + discordLink = Core.settings.getString(PLUGIN_NAME + "-discord-link", null); + chatFilter = Core.settings.getBool(PLUGIN_NAME + "-chat-filter", false); + + doorsCoordinates = new ArrayList<>(); + + + extraStarsUIDD = new ArrayList<>(); menu = new MyMenu(); eventsManager = new ServerEventsManager(); @@ -131,11 +102,6 @@ public void init() { admin = Team.all[10]; admin.name = "admin"; -// admin.rules(). -// eventsManager.isEventsOn[0] = true; -// eventsManager.startEventsLoop(); -// eventsManager.startEventsLoop(); - maps = new Maps(); maps.load(); @@ -157,11 +123,32 @@ public void init() { adminCommands.add("m"); adminCommands.add("js"); adminCommands.add("link"); + adminCommands.add("pardon"); + adminCommands.add("doorscup"); + adminCommands.add("brush"); + adminCommands.add("etrigger"); + adminCommands.add("extrastar"); Events.run(Trigger.update, () -> { menu.update(); eventsManager.update(); }); + + Events.on(PlayerBanEvent.class, e -> { + if(extraStarsUIDD.contains(e.uuid)) { + netServer.admins.unbanPlayerID(e.uuid); + } + }); + Events.on(PlayerIpBanEvent.class, e -> { + Seq admins = Vars.netServer.admins.getAdmins(); + + for (int i = 0; i < admins.size; i++) { + if(admins.get(i).ips.contains(e.ip)) { + netServer.admins.unbanPlayerIP(e.ip); + return; + } + } + }); Events.on(GameOverEvent.class, e -> { StringBuilder result = new StringBuilder(state.map.name()); @@ -181,6 +168,7 @@ public void init() { Events.on(WorldLoadEndEvent.class, e -> { currentlyMapSkipping[0] = null; eventsManager.worldLoadEnd(e); + doorsCoordinates.clear(); }); Events.on(PlayerJoin.class, e -> { @@ -195,50 +183,76 @@ public void init() { int startCount = (int) Math.ceil(rate*5); StringBuilder stars = new StringBuilder(); Color color = Color.HSVtoRGB(rate*120, 100, 100); + int index = extraStarsUIDD.indexOf(e.player.uuid()); + if(index != -1) { + color = Color.magenta; + } stars.append("[#"); stars.append(color.toString()); stars.append("]"); + int count = 5; for (int j = 0; j < startCount; j++) { stars.append('\ue809'); + count--; } Color color2 = Color.HSVtoRGB(rate*120, 100, 33); stars.append("[#"); stars.append(color2.toString()); stars.append("]"); - for (float j = startCount+1; j < 5; j++) { + for (float j = 0; j < count; j++) { stars.append('\ue809'); } + + if(index != -1) { + stars.append("[magenta]\ue813"); + } + Call.sendMessage("Игрок " + e.player.name() + "[white] имеет рейтинг " + stars.toString()); } else { Call.sendMessage("Игрок " + e.player.name() + "[white] в первый раз на этом сервере!"); } }); -// Blocks. -// Events.on(GameOverEvent.class, event -> { -// if(inGameOverWait) return; -// Map map = nextMapOverride != null ? nextMapOverride : maps.getNextMap(); -// nextMapOverride = null; -// }); -// Events.on(ServerLoadEvent.class, event -> { -// }); -// -// Events.on(PlayerJoin.class, event -> { -// }); -// Events.on(Event.class, event -> { -// }); - -// Events.on(BlockDestroyEvent.class, event -> { -// event.tile. -// }); + Events.on(BlockDestroyEvent.class, event -> { + /** + * Destroy (by explosion, or enemy and etc.) + */ + if(event.tile == null) return; + if(event.tile.block() == null) return; + Block block = event.tile.block(); + + if(block == Blocks.door || block == Blocks.doorLarge || block == Blocks.blastDoor) { + updateDoors(event.tile); + } + }); - /** - * killing builder, that building thoriumReactor near core - */ Events.on(BuildSelectEvent.class, event -> { Unit builder = event.builder; - if(!event.breaking && builder != null && builder.buildPlan() != null && builder.buildPlan().block == Blocks.thoriumReactor && builder.isPlayer()){ - + if(builder == null) return; + BuildPlan buildPlan = builder.buildPlan(); + if(buildPlan == null) return; + Block block = buildPlan.block; + + if(block == Blocks.door || block == Blocks.doorLarge || block == Blocks.blastDoor) { + + Tile door = event.tile; + if(door == null) return; + int center = Point2.pack(door.centerX(), door.centerY()); + for (int i = 0; i < doorsCoordinates.size(); i++) { + int pos = doorsCoordinates.get(i); + if(center == pos) { + doorsCoordinates.remove(i); + break; + } + } + if(!event.breaking) { + doorsCoordinates.add(Point2.pack(event.tile.centerX(), event.tile.centerY())); + } + if(event.tile != null) + updateDoors(event.tile); + } + + if(!event.breaking && builder.buildPlan().block == Blocks.thoriumReactor && builder.isPlayer()){ Player player = builder.getPlayer(); Team team = player.team(); @@ -261,8 +275,30 @@ public void init() { */ Events.on(BlockBuildBeginEvent.class, event -> { Unit builder = event.unit; + if(builder == null) return; + BuildPlan buildPlan = builder.buildPlan(); + if(buildPlan == null) return; + Block block = buildPlan.block; + + if(!event.breaking) { + if(block == Blocks.door || block == Blocks.doorLarge || block == Blocks.blastDoor) { + if(doorsCoordinates.size() >= doorsCup) { + event.tile.setNet(Blocks.air); + Player player = builder.getPlayer(); + if(player != null) { + builder.clearBuilding(); + if(builder.plans != null) builder.plans.clear(); + player.clearUnit(); + Log.info(player.plainName() + " exceeded the limit of doors"); + player.sendMessage("[red]Достигнут максимальный лимит дверей!"); + return; + } + return; + } + } + } - if(!event.breaking && builder != null && builder.buildPlan() != null && builder.buildPlan().block == Blocks.thoriumReactor && builder.isPlayer()){ + if(!event.breaking && builder.buildPlan().block == Blocks.thoriumReactor && builder.isPlayer()) { Player player = builder.getPlayer(); Team team = player.team(); @@ -303,45 +339,31 @@ public void init() { } }); - // add a chat filter that changes the contents of all messages - Vars.netServer.admins.addChatFilter((player, text) -> { + Events.on(TapEvent.class, event -> { + Player player = event.player; + if(player == null) return; + + if(player.admin()) { + if(event.tile == null) return; + if(brushBlock != null || brushFloor != null || brushOverlay != null) { + Tile tile = event.tile; + if(brushBlock != null) { + tile.setNet(brushBlock, player.team(), 0); + } + if(brushFloor != null) { + if(brushOverlay != null) { + tile.setFloorNet(brushFloor, brushOverlay); + } else { + tile.setFloorNet(brushFloor); + } + } + } + } + }); + -// char[] msg = text.toCharArray(); -// -// String searchName = ""; -// int searchNameStart = -1; -// boolean needSearchName = false; -// -// for (int i = 0; i < msg.length; i++) { -// if(msg[i] == '@') { -// searchName = ""; -// searchNameStart = i; -// needSearchName = true; -// } -// -// if(needSearchName) { -// if(msg[i] == ' ') { -// ObjectSet infos = netServer.admins.searchNames(arg[0]); -// -// if(infos.size > 0) { -// info("Players found: @", infos.size); -// -// int i = 0; -// for(PlayerInfo info : infos){ -// info("- [@] '@' / @", i++, info.plainLastName(), info.id); -// } -// } -// -// searchName = ""; -// needSearchName = false; -// searchNameStart = -1; -// -// } else { -// searchName += msg[i]; -// } -// } -// } - + // add a chat filter that changes the contents + Vars.netServer.admins.addChatFilter((player, text) -> { if(chatFilter) { text = "[white]" + text + "[white]"; char[] msg = text.toCharArray(); @@ -400,7 +422,30 @@ public void init() { // }); } - @Override + private void updateDoors(Tile tile) { + for (int i = 0; i < doorsCoordinates.size(); i++) { + int pos = doorsCoordinates.get(i); + Tile door = world.tile(pos); + if(door == tile) continue; + if((door.block() != Blocks.door && door.block() != Blocks.doorLarge && door.block() != Blocks.blastDoor) || door == null) { + Log.info("Not door"); + doorsCoordinates.remove(i); + i--; + if(i < 0) i = 0; + } else { + int center = Point2.pack(door.centerX(), door.centerY()); + if(center != pos) { + Log.info("Not center"); + doorsCoordinates.remove(i); + i--; + if(i < 0) i = 0; + } + } + } + Log.info("Doors count: " + doorsCoordinates.size() + "/" + doorsCup); + } + + @Override public void registerServerCommands(CommandHandler handler){ handler.register("reactors", "List all thorium reactors in the map.", args -> { for(int x = 0; x < Vars.world.width(); x++){ @@ -413,7 +458,7 @@ public void registerServerCommands(CommandHandler handler){ }); handler.register("cdata", "cdata", args -> { - Log.info("Statistics file: " + DataCollecter.getPathToFile()); + Log.info("Statistics files dir: " + DataCollecter.getPathToFile("")); Log.info("User dir: " + System.getProperty("user.dir")); Log.info("Sleep time: " + dataCollect.getSleepTime()); }); @@ -501,6 +546,7 @@ public void registerClientCommands(CommandHandler handler){ } }); + /** * Plugin developer command (to find) emoji codes */ @@ -526,7 +572,6 @@ public void registerClientCommands(CommandHandler handler){ * Map recourses statistic */ handler.register("mapinfo", "", "Показывает статистику ресурсов карты", (arg, player) -> { - world = Vars.world; final Item itemDrops[] = new Item[] { Items.copper, @@ -581,15 +626,15 @@ public void registerClientCommands(CommandHandler handler){ if(summaryCounter == 0) return; worldInfo.append("Информация о карте:\n"); - worldInfo.append("Название: " + Vars.state.map.name() + "\n"); - worldInfo.append("Рекорд: " + Vars.state.map.getHightScore()); + worldInfo.append("[gold]Название: [lightgray]" + Vars.state.map.name() + "\n"); + worldInfo.append("[gold]Рекорд: [lightgray]" + Vars.state.map.getHightScore() + "\n"); worldInfo.append("Ресурсы:\n"); for (int i = 0; i < counter.length; i++) { float cv = ((float)counter[i])*typesCounter/summaryCounter/3f; if(cv > 1/3f) cv = 1/3f; int percent = (int) Math.ceil(counter[i]*100d/summaryCounter); java.awt.Color c = new java.awt.Color(java.awt.Color.HSBtoRGB(cv, 1, 1)); - worldInfo.append(oreblocksemoji[i]); + worldInfo.append(oreBlocksEmoji[i]); worldInfo.append('['); worldInfo.append(String.format("#%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue())); worldInfo.append("]: "); @@ -609,7 +654,7 @@ public void registerClientCommands(CommandHandler handler){ for (int i = 0; i < lcounter.length; i++) { if(lcounter[i] > 0) { worldInfo.append("\n[white]"); - worldInfo.append(liquidsemoji[i]); + worldInfo.append(liquidsEmoji[i]); worldInfo.append("[lightgray]: "); worldInfo.append(counter[i]); isLFound = true; @@ -778,7 +823,7 @@ public void registerClientCommands(CommandHandler handler){ handler.register("plugininfo", "info about pluging", (arg, player) -> { player.sendMessage("" - + "[green] Agzam's plugin v1.8.2\n" + + "[green] Agzam's plugin v1.8.3\n" + "[gray]========================================================\n" + "[white] Added [royal]skip map[white] commands\n" + "[white] Added protection from [violet]thorium reactors[white]\n" @@ -786,15 +831,13 @@ public void registerClientCommands(CommandHandler handler){ + "[white] Added fill items by type to core command\n" + "[white] Added Map recourses statistic command\n" + "[white] and more other\n" - + "[gray] Download: github.com/Agzam4/Mindustry-plugin"); + + "[gray] Download: github.com/Agzam4/Mindustry-plugin"); }); handler.register("fillitems", "[item] [count]", "Заполните ядро предметами", (arg, player) -> { if(player.admin()) { try { - - final Item serpuloItems[] = { Items.scrap, Items.copper, Items.lead, Items.graphite, Items.coal, Items.titanium, Items.thorium, Items.silicon, Items.plastanium, Items.phaseFabric, Items.surgeAlloy, Items.sporePod, Items.sand, Items.blastCompound, Items.pyratite, Items.metaglass @@ -904,7 +947,9 @@ public void registerClientCommands(CommandHandler handler){ for(CoreBuild core : team.cores()){ core.items.add(item, count); } - player.sendMessage("Added " + "[gold]x" + count + " [orange]" + item.name); + player.sendMessage("Добавлено " + "[gold]x" + count + " [orange]" + item.name); + } else { + player.sendMessage("Предмет не найден"); } } catch (Exception e) { player.sendMessage(e.getMessage()); @@ -964,9 +1009,11 @@ public void registerClientCommands(CommandHandler handler){ } if(arg[0].equals("on")) { chatFilter = true; + Core.settings.put(PLUGIN_NAME + "-chat-filter", chatFilter); player.sendMessage("[green]Чат фильтр включен"); }else if(arg[0].equals("off")) { chatFilter = false; + Core.settings.put(PLUGIN_NAME + "-chat-filter", chatFilter); player.sendMessage("[red]Чат фильтр выключен"); }else { player.sendMessage("Неверный аргумент, используйте [gold]on/off"); @@ -1077,23 +1124,6 @@ public void registerClientCommands(CommandHandler handler){ } } -// for (int i = 0; i < ServerEventsManager.EVENTS_ID.length; i++) { -// if(arg[0].equals(ServerEventsManager.EVENTS_ID[i])) { -// eventsManager.isEventsOn[i] = isOn; -// -// if(isOn) { -// eventsManager.startEventsLoop(); -// player.sendMessage("Событие [gold]" + ServerEventsManager.EVENTS_ID[i] + " [green]запущено!"); -// if(isFast) { -// eventsManager.fastStart(); -// } -// }else { -// player.sendMessage("Событие [gold]" + ServerEventsManager.EVENTS_ID[i] + " [red]выключено!"); -// } -// -// return; -// } -// } player.sendMessage("[red]Событие не найдено, [gold]/event [red] для списка событий"); return; } @@ -1450,12 +1480,192 @@ public void registerClientCommands(CommandHandler handler){ if(player.admin()) { if(arg.length == 1) { discordLink = arg[0]; + Core.settings.put(PLUGIN_NAME + "-discord-link", discordLink); player.sendMessage("[gold]\ue80d Готово!"); } } else { player.sendMessage("[red]Команда только для администраторов"); } }); + + handler.register("pardon", "", "Прощает выбор игрока по ID и позволяет ему присоединиться снова.", (arg, player) -> { + if(player.admin()) { + PlayerInfo info = netServer.admins.getInfoOptional(arg[0]); + + if(info != null){ + info.lastKicked = 0; + netServer.admins.kickedIPs.remove(info.lastIP); + player.sendMessage("Pardoned player: " + info.plainLastName()); + }else{ + player.sendMessage("[red]That ID can't be found"); + } + } else { + player.sendMessage("[red]Команда только для администраторов"); + } + }); + + handler.register("doorscup", "[count]", "Устанавливает лимит дверей", (arg, player) -> { + if(player.admin()) { + if(arg.length == 1) { + try { + int lastDoorsCup = doorsCup; + doorsCup = Integer.parseInt(arg[0]); + Core.settings.put(PLUGIN_NAME + "-doors-cup", doorsCup); + player.sendMessage("[gold]Лимит дверей изменен с " + lastDoorsCup + " на " + doorsCup); + } catch (Exception e) { + player.sendMessage(e.getMessage()); + } + } else if(arg.length == 0) { + player.sendMessage("[gold]Сейчас дверей: " + doorsCoordinates.size() + "/" + doorsCup); + } + } else { + player.sendMessage("[red]Команда только для администраторов"); + } + }); + + handler.register("brush", "[none/block/floor/overlay] [block/none]", "Устанваливает кисточку", (arg, player) -> { + if(player.admin()) { + if(arg.length == 1) { + if(arg[0].equalsIgnoreCase("none")) { + brushBlock = null; + brushFloor = null; + brushOverlay = null; + player.sendMessage("[gold]Кисть отчищена"); + } else if(arg[0].equalsIgnoreCase("block")) { + if(brushBlock == null) player.sendMessage("[gold]К кисти не привязан блок"); + else player.sendMessage("[gold]К кисти привязан блок: [lightgray]" + brushBlock.name); + } else if(arg[0].equalsIgnoreCase("floor")) { + if(brushBlock == null) player.sendMessage("[gold]К кисти не привязана поверхность"); + else player.sendMessage("[gold]К кисти привязана поверхность: [lightgray]" + brushFloor.name); + } else if(arg[0].equalsIgnoreCase("overlay")) { + if(brushBlock == null) player.sendMessage("[gold]К кисти не привязано покрытие"); + else player.sendMessage("[gold]К кисти привязан блок: [lightgray]" + brushOverlay.name); + } else { + player.sendMessage("[red]На первом месте только аргумены [lightgray]none/block/floor/overlay"); + } + } else if(arg.length == 2) { + String blockname = arg[1]; + if(arg[0].equalsIgnoreCase("block")) { + if(arg[1].equals("none")) { + brushBlock = null; + player.sendMessage("[gold]Блок отвязан"); + return; + } + try { + Field field = Blocks.class.getField(blockname); + Block block = (Block) field.get(null); + brushBlock = block; + player.sendMessage("[gold]Блок привязан!"); + } catch (NoSuchFieldException | SecurityException e) { + player.sendMessage("[red]Блок не найден"); + } catch (ClassCastException e2) { + player.sendMessage("[red]Это не блок"); + } catch (IllegalArgumentException | IllegalAccessException e) { + player.sendMessage("[red]Доступ к блоку заблокирован"); + } + } else if(arg[0].equalsIgnoreCase("floor")) { + if(arg[1].equals("none")) { + brushFloor = null; + player.sendMessage("[gold]Поверхность отвязана"); + return; + } + try { + Field field = Blocks.class.getField(blockname); + Floor floor = (Floor) field.get(null); + brushFloor = floor; + player.sendMessage("[gold]Поверхность привязана!"); + } catch (NoSuchFieldException | SecurityException e) { + player.sendMessage("[red]Поверхность не найдена"); + } catch (ClassCastException e2) { + player.sendMessage("[red]Это не поверхность"); + } catch (IllegalArgumentException | IllegalAccessException e) { + player.sendMessage("[red]Доступ к поверхности заблокирован"); + } + } else if(arg[0].equalsIgnoreCase("overlay")) { + if(arg[1].equals("none")) { + brushOverlay = null; + player.sendMessage("[gold]Покрытие отвязано"); + return; + } + try { + Field field = Blocks.class.getField(blockname); + OverlayFloor overlay = (OverlayFloor) field.get(null); + brushOverlay = overlay; + player.sendMessage("[gold]Покрытие привязано!"); + } catch (NoSuchFieldException | SecurityException e) { + player.sendMessage("[red]Покрытие не найдено"); + } catch (ClassCastException e2) { + player.sendMessage("[red]Это не покрытие"); + } catch (IllegalArgumentException | IllegalAccessException e) { + player.sendMessage("[red]Доступ к покрытию заблокирован"); + } + } + } + } else { + player.sendMessage("[red]Команда только для администраторов"); + } + }); + + handler.register("etrigger", "[trigger] [args...]", "Устанваливает кисточку", (args, player) -> { + if(player.admin()) { + eventsManager.trigger(player, args); + } else { + player.sendMessage("[red]Команда только для администраторов"); + } + }); + + handler.register("extrastar", "[add/remove] [uidd/name]", "", (args, player) -> { + if(player.admin()) { + if(args.length == 0) { + if(extraStarsUIDD.isEmpty()) { + player.sendMessage("[gold]Нет игроков"); + } else { + StringBuilder sb = new StringBuilder("[gold]Игроки с дополнительными звездами:[white]"); + for (int i = 0; i < extraStarsUIDD.size(); i++) { + String uidd = extraStarsUIDD.get(i); + String name = netServer.admins.getInfo(uidd).lastName; + sb.append("\n" + uidd + " (" + name + ")"); + } + player.sendMessage(sb.toString()); + } + } else if(args.length == 2) { + Player playert = Groups.player.find(p -> Strings.stripColors(p.name()).equalsIgnoreCase(Strings.stripColors(args[1]))); + if(playert != null) args[1] = playert.uuid(); + + if(args[0].equalsIgnoreCase("add")) { + if(!extraStarsUIDD.contains(args[1])) { + PlayerInfo info = netServer.admins.getInfo(args[1]); + if(info == null) { + player.sendMessage("[red]Игрок не найден"); + } else { + extraStarsUIDD.add(args[1]); + player.sendMessage("[gold]Игрок []" + info.lastName + " [gold]добавлен"); + } + } else { + player.sendMessage("[red]Игрок уже есть"); + } + } else if(args[0].equalsIgnoreCase("remove")) { + if(extraStarsUIDD.contains(args[1])) { + PlayerInfo info = netServer.admins.getInfo(args[1]); + if(info == null) { + player.sendMessage("[red]Игрок не найден"); + } else { + extraStarsUIDD.remove(args[1]); + player.sendMessage("[gold]Игрок []" + info.lastName + " [gold]убран"); + } + } else { + player.sendMessage("[red]UIDD не найден"); + } + } else { + player.sendMessage("[red]Только add/remove"); + } + } else { + player.sendMessage("[red]Неверные аргументы"); + } + } else { + player.sendMessage("[red]Команда только для администраторов"); + } + }); } String discordLink = ""; @@ -1467,6 +1677,10 @@ private String getColoredLocalizedItemName(Item item) { private void fillitemsCheck() { } + + + + class GrieferVoteSession { @@ -1566,5 +1780,4 @@ public int votesRequiredSkipmap(){ return (int) Math.ceil(Groups.player.size()*2d/3d); } - } diff --git a/src/example/MyMenu.java b/src/example/MyMenu.java index fa7c61b..951b548 100644 --- a/src/example/MyMenu.java +++ b/src/example/MyMenu.java @@ -105,7 +105,7 @@ public void onButtonPressed(Menu menu, int optionID, int clickedId) { if(playerName == null) return; String[] teams = new String[Team.baseTeams.length]; - MenuOption[] menuOptions = new MenuOption[Team.baseTeams.length+2]; + MenuOption[] menuOptions = new MenuOption[Team.baseTeams.length+5]; for (int i = 0; i < teams.length; i++) { char ch = ' '; @@ -125,12 +125,10 @@ public void onButtonPressed(Menu menu, int optionID, int clickedId) { for (int i = 0; i < menuOptions.length; i++) { menuOptions[i] = MenuOption.AdminPlayerConfigAction; } - - - menu(menu.player, "Управление игроком", playerName, new String[][] {teams, {"[green]\ue80f Вылечить", "[royal]\ue86b Неуязвимость"}}, menuOptions).payload = playerName; + menu(menu.player, "Управление игроком", playerName, new String[][] {teams, {"[green]\ue80f Вылечить", "[royal]\ue86b Неуязвимость"}, {"[gold]\ue86d Сброс юнита", "[red]\uue815 Уничтожить"}, {"[lightgray]\ue88e Режим наблюдателя"}}, menuOptions).payload = playerName; } if(optionID == MenuOption.AdminPlayerConfigAction.ordinal()) { - Log.info(menu.payload); + Log.info(menu.payload + " " + clickedId); if(menu.payload == null) return; Player targetPlayer = Groups.player.find(p -> Strings.stripColors(p.name()).equalsIgnoreCase(Strings.stripColors(menu.payload))); if(targetPlayer == null) return; @@ -147,9 +145,26 @@ public void onButtonPressed(Menu menu, int optionID, int clickedId) { if(clickedId == teamsCount+1) { targetPlayer.unit().apply(StatusEffects.invincible, Float.MAX_VALUE); } + if(clickedId == teamsCount+2) { + targetPlayer.clearUnit(); + } + if(clickedId == teamsCount+3) { + targetPlayer.unit().kill(); + } + if(clickedId == teamsCount+4) { + targetPlayer.team(Team.derelict); + targetPlayer.unit().kill(); + } + +// if(clickedId != -1) { +// adminPlayerConfig(menu, MenuOption.AdminPlayerConfig.ordinal(), clickedId); +// } } } + + + public void registerCommand(CommandHandler handler) { handler.register("m", "", "Открыть меню", (args, player) -> { if(player.admin()) { diff --git a/src/example/Work.java b/src/example/Work.java new file mode 100644 index 0000000..c8444f9 --- /dev/null +++ b/src/example/Work.java @@ -0,0 +1,12 @@ +package example; + +import mindustry.content.UnitTypes; +import mindustry.type.UnitType; + +public class Work { + + public static boolean isPlayerUnit(UnitType unit) { + return unit == UnitTypes.alpha || unit == UnitTypes.beta || unit == UnitTypes.gamma + || unit == UnitTypes.evoke || unit == UnitTypes.incite || unit == UnitTypes.emanate; + } +} diff --git a/src/example/events/ServerEvent.java b/src/example/events/ServerEvent.java index 838e858..f542bca 100644 --- a/src/example/events/ServerEvent.java +++ b/src/example/events/ServerEvent.java @@ -6,6 +6,7 @@ import mindustry.game.EventType.TapEvent; import mindustry.game.EventType.UnitDestroyEvent; import mindustry.game.EventType.WithdrawEvent; +import mindustry.gen.Player; import mindustry.game.GameStats; public abstract class ServerEvent { @@ -92,4 +93,8 @@ public void withdraw(WithdrawEvent e) { public void playerJoin(PlayerJoin e) { // for @Override } + + public void trigger(Player player, String... args) { + // for @Override + } } diff --git a/src/example/events/ServerEventsManager.java b/src/example/events/ServerEventsManager.java index c2b57e6..a28eb24 100644 --- a/src/example/events/ServerEventsManager.java +++ b/src/example/events/ServerEventsManager.java @@ -509,5 +509,9 @@ private ServerEvent getEventByCommandName(String commandName) { return null; } - + public void trigger(Player player, String... args) { + for (int i = 0; i < activeEvents.size(); i++) { + activeEvents.get(i).trigger(player, args); + } + } } diff --git a/src/example/events/SpaceDangerEvent.java b/src/example/events/SpaceDangerEvent.java index b623b0e..b92183d 100644 --- a/src/example/events/SpaceDangerEvent.java +++ b/src/example/events/SpaceDangerEvent.java @@ -1,11 +1,15 @@ package example.events; +import mindustry.Vars; import mindustry.content.Blocks; import mindustry.content.Fx; import mindustry.content.Items; import mindustry.content.Liquids; import mindustry.content.UnitTypes; +import mindustry.content.Weathers; +import mindustry.core.UI; import mindustry.core.World; +import mindustry.entities.Effect; import mindustry.entities.abilities.Ability; import mindustry.entities.abilities.RegenAbility; import mindustry.game.EventType.BlockBuildEndEvent; @@ -19,12 +23,17 @@ import mindustry.game.Team; import mindustry.gen.Building; import mindustry.gen.Call; +import mindustry.gen.Entityc; import mindustry.gen.Groups; import mindustry.gen.Player; import mindustry.gen.Unit; +import mindustry.gen.WeatherState; +import mindustry.gen.WeatherStatec; +import mindustry.graphics.Drawf; import mindustry.type.Item; import mindustry.type.Liquid; import mindustry.type.UnitType; +import mindustry.type.Weather; import mindustry.world.Block; import mindustry.world.Tile; import mindustry.world.blocks.defense.turrets.LiquidTurret; @@ -40,15 +49,25 @@ import static mindustry.Vars.*; import java.awt.Point; +import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.Iterator; import arc.Events; +import arc.graphics.Color; +import arc.math.Mat; +import arc.math.Mathf; +import arc.math.Rand; import arc.math.geom.Point2; +import arc.math.geom.Position; +import arc.math.geom.Vec2; +import arc.util.Log; +import arc.util.io.Reads; +import arc.util.io.Writes; public class SpaceDangerEvent extends ServerEvent { - + public SpaceDangerEvent() { super("Space danger"); color = "magenta"; @@ -56,7 +75,7 @@ public SpaceDangerEvent() { @Override public void init() { - + }///event space_danger faston @Override @@ -66,22 +85,65 @@ public void announce() { } boolean isLablePlaced = false; - + ArrayList targets = new ArrayList<>(); - + int meteorits = 0; - + @Override public void playerJoin(PlayerJoin e) { if(e.player == null) return; e.player.sendMessage(info); - + } - + private static final String info = "[magenta]Постойте [gold]электоромагнитную катапульту[magenta]\\nОкружите ее четырмя [gold]цунами[magenta] запитанными шлаком (Не забудьте подготовить защиту)"; - + + private int updates = 0; + + int dFissileMatterTimer = 0; + int fissileMatterCounter = 0; + int targetFissileMatterCounter = 0; + int hudLerpT = 0; + @Override public void update() { + + updates++; + if(updates % 10 == 0) { + if(fissileMatterCounter < targetFissileMatterCounter) { + int d = (targetFissileMatterCounter - dFissileMatterTimer)/2; + if(d < 1) d = 1; + fissileMatterCounter+=d; + dFissileMatterTimer = 61; + hudLerpT = 0; + + // /event space_danger faston + // /sandbox on + // /sync + // /etrigger fall + } + + for (int i = 0; i < targets.size(); i++) { + targets.get(i).effect(updates); + } + } + if(updates%5 == 0 && hudLerpT < 20) { + hudLerpT += 5; + if(hudLerpT > 20) hudLerpT = 20; + Call.setHudText("Получено [#" + new Color(0xffd700ff).lerp(Color.lightGray, hudLerpT/20f).toString() + "] x" + fissileMatterCounter + " [#5e988dff]нестабильная материя [white](\uf747)"); + } + // Получено [lightgray]x1\uf747 [#5e988dff]нестабильная материя + if(dFissileMatterTimer > 0) { + dFissileMatterTimer--; + if(dFissileMatterTimer == 0) { + targetFissileMatterCounter = 0; + fissileMatterCounter = 0; + dFissileMatterTimer = 0; + Call.hideHudText(); + } + } + if(!isLablePlaced) { for (int i = 0; i < Groups.player .size(); i++) { Player player = Groups.player.index(i); @@ -91,7 +153,7 @@ public void update() { int x = core.tileX(); int y = core.tileY(); - + for (int yy = 0; yy <= 5; yy++) { for (int xx = 0; xx <= 5; xx++) { Tile tile = world.tile(x-xx, y-yy); @@ -105,7 +167,7 @@ public void update() { } } } - + for (int i = 0; i < targets.size(); i++) { targets.get(i).update(); } @@ -117,7 +179,7 @@ public void update() { } } } - + // /event space_danger faston @Override @@ -126,6 +188,12 @@ public void generateWorld() { targets.clear(); dormantCystDropUnits.clear(); Call.sendMessage(info); + + + dFissileMatterTimer = 0; + fissileMatterCounter = 0; + targetFissileMatterCounter = 0; + hudLerpT = 0; } @Override @@ -133,7 +201,7 @@ protected void blockBuildEnd(BlockBuildEndEvent e) { if(e.tile.block().name.equals(Blocks.massDriver.name)) { int x = e.tile.centerX(); int y = e.tile.centerY(); - + if(hasTarget(x, y)) { targets.add(new Target(x, y)); } @@ -152,7 +220,7 @@ protected void blockBuildEnd(BlockBuildEndEvent e) { targets.add(new Target(x-3, y)); } } - + if(hasMassDriver(x, y+3)) { if(hasTarget(x, y+3)) { targets.add(new Target(x, y+3)); @@ -165,23 +233,57 @@ protected void blockBuildEnd(BlockBuildEndEvent e) { } } } + + static final UnitType[] pull = new UnitType[] { + UnitTypes.renale, // 0. score 1 HP: 500 + UnitTypes.risso, // 1. score 1 HP: 280 + UnitTypes.retusa, // 2. score 1 HP: 270 + + UnitTypes.minke, // 3. score 5 HP: 600 + UnitTypes.oxynoe, // 4. score 6 HP: 560 + + UnitTypes.bryde, // 5. score 10 HP: 900 + UnitTypes.cyerce, // 6. score 11 HP: 870 + + UnitTypes.sei, // 7. score 25 HP: 11 000 + UnitTypes.aegires, // 8. score 30 HP: 12 000 + + UnitTypes.omura, // 9. score 45 HP: 22 000 + UnitTypes.navanax, // 10. score 45 HP: 20 000 + + UnitTypes.latum, // 11. score 50 HP: 20 000 + (500 x 5) = 22500 (x45 renale) + }; - ArrayList dormantCystDropUnits = new ArrayList<>(); + static final int[] pullValue = new int[] { + 1, 1, 1, + 5, 5, + 10, 11, + 25, 30, + 45, 45, + 50 + }; + ArrayList dormantCystDropUnits = new ArrayList<>(); + @Override public void unitDestroy(UnitDestroyEvent e) { if(dormantCystDropUnits.contains(e.unit)) { if(Groups.player.size() > 0) { if(Groups.player.index(0).core() != null) { + + int count = 0; - int count = 1; - - if(e.unit.type() == UnitTypes.latum) { - count = 5; + for (int i = 0; i < pull.length; i++) { + if(e.unit.type() == pull[i]) { + count = pullValue[i]; + } } - Groups.player.index(0).core().items.add(Items.fissileMatter, count); - Call.sendMessage("Получено [lightgray] x" + count + "[gold] нестабильная материя"); + if(count != 0) { + Groups.player.index(0).core().items.add(Items.fissileMatter, count); + targetFissileMatterCounter += count; + } + // Call.sendMessage(); } } dormantCystDropUnits.remove(e.unit); @@ -189,18 +291,18 @@ public void unitDestroy(UnitDestroyEvent e) { } // /event space_danger faston - + private boolean hasTarget(int xx, int yy) { if(isOut(xx, yy)) return false; if(world.tile(xx, yy).block().name.equals(Blocks.massDriver.name)) { int x = world.tile(xx, yy).build.tile.centerX(); int y = world.tile(xx, yy).build.tile.centerY(); return hasTsunami(x+3, y) && hasTsunami(x-3, y) - && hasTsunami(x, y+3) && hasTsunami(x, y-3); + && hasTsunami(x, y+3) && hasTsunami(x, y-3); } return false; } - + private boolean hasTsunami(int x, int y) { if(isOut(x, y)) return false; if(world.tile(x, y).block().name.equals(Blocks.tsunami.name)) { @@ -208,16 +310,16 @@ private boolean hasTsunami(int x, int y) { } return false; } - + private boolean hasMassDriver(int x, int y) { if(isOut(x, y)) return false; - + if(world.tile(x, y).block().name.equals(Blocks.massDriver.name)) { return true; } return false; } - + private boolean isOut(int x, int y) { if(x < 0) return true; if(y < 0) return true; @@ -225,17 +327,15 @@ private boolean isOut(int x, int y) { if(y >= world.height()) return true; return false; } - + private class Target { - + private int x, y; private boolean needRemove = false; - private int shootTime = 0; - private boolean isActivated = false; private boolean isEnded = false; private int fallTime; - + public Target(int x, int y) { for (int i = 0; i < targets.size(); i++) { if(targets.get(i).x == x && targets.get(i).y == y) { @@ -243,170 +343,222 @@ public Target(int x, int y) { break; } } - + this.x = x; this.y = y; - - if(world.tile(x, y).block().name.equals(Blocks.massDriver.name)) { + + if(world.tile(x, y) == null) return; + if(world.tile(x, y).block() == null) return; + if(world.tile(x, y).block() == Blocks.massDriver) { world.tile(x, y).setTeam(Team.crux); + x = world.tile(x, y).centerX(); + y = world.tile(x, y).centerY(); } + + fallTime = (int) (Math.random()*60+60)*60; + } + + public void effect(int i) { + double angle = i%120/60d*Math.PI; + final double r = 5; + float dx = (float) (r*Math.sin(angle)); + float dy = (float) (r*Math.cos(angle)); + Call.effect(Fx.chainLightning, x*tilesize, y*tilesize, 1, Color.red, new Vec2((x+dx)*tilesize, (y+dy)*tilesize)); + Call.effect(Fx.chainLightning, x*tilesize, y*tilesize, 1, Color.blue, new Vec2((x-dx)*tilesize, (y+dy)*tilesize)); } - + private void update() { if(isEnded) return; - if(isActivated) { + + if((fallTime%(30*60) == 0 || fallTime == 15*60) && fallTime > 0) { + int sec = fallTime/60; + int min = sec/60; + sec -= min*60; + Call.warningToast(0, "Метероит упадет через " + (min > 0 ? "[gold]" + min + ":" : "[red]") + (sec == 0 ? "00" : sec)); + } + if(fallTime < 0) { + fall(); + return; + } + + if(hasTarget(x, y) + && getTsunamiPower(x+3, y) > .5 && getTsunamiPower(x-3, y) > .5 + && getTsunamiPower(x, y+3) > .5 && getTsunamiPower(x, y-3) > .5) { + if(fallTime == 0) { + Call.warningToast(0, "[red]Метеорит приближается!"); + } fallTime--; - if(fallTime < 0) { - int radius = 15 + ((meteorits%5 == 0 && meteorits > 0) ? 15 : 0); - for (int dy = -radius; dy <= radius; dy++) { - for (int dx = -radius; dx <= radius; dx++) { - int x = this.x + dx; - int y = this.y + dy; - if(isOut(x, y)) continue; - double hypot = Math.hypot(dx, dy); - if(hypot > radius) continue; - - boolean ferricStone = false; - boolean ferricCraters = false; - boolean ferricBoulder = false; - boolean ferricWall = false; - - boolean slag = false; - boolean magmarock = false; - boolean hotrock = false; - boolean basalt = false; - - boolean ore = false; - - double k = hypot/radius; - - ferricStone = Math.random() > (hypot-5)/radius; - - if(ferricStone) { - if(Math.random() < .2) { - ferricStone = false; - ferricCraters = true; - } - } - if(Math.random() < .3) { - ore = true; - } - if(Math.random() < .15) { - ferricBoulder = true; - } - if(Math.random() < .025) { - ferricWall = true; - ferricStone = true; - } + } else if(!isEnded) { + Call.warningToast(0, "[red]Метеорит пролетел мимо!"); + needRemove = true; + } + } - if(ferricStone) { - if(Math.random() < .4) { - basalt = true; - } - if(Math.random() < .2) { - magmarock = true; - } - if(Math.random() < .1) { - magmarock = true; - } - if(Math.random() < .05) { - slag = true; - } - } - - Block floor = null; - if(ferricStone) floor = Blocks.ferricStone; - if(ferricCraters) floor = Blocks.ferricCraters; - if(slag) floor = Blocks.slag; - if(magmarock) floor = Blocks.magmarock; - if(hotrock) floor = Blocks.hotrock; - if(basalt) floor = Blocks.basalt; - - Tile tile = world.tile(x, y); - tile.clearOverlay(); - if(floor != null) { - tile.setFloorNet(floor, ore ? Blocks.oreScrap : tile.overlay()); - } - if(tile.block() == Blocks.air && ferricBoulder) { - tile.setNet(Blocks.ferricBoulder); - }else if(ferricWall) { - if(tile.block() == Blocks.air) { - tile.setNet(Blocks.ferricStoneWall); - } else { - if(Math.random() < k) tile.setNet(Blocks.ferricStoneWall); - else tile.setNet(Blocks.air); - } - } + private void fall() { + int score = meteorits*2 + 5; + int maxUnitLevel = 0; + + ArrayList ids = new ArrayList<>(); + + while (true) { + int maxIndex = 0; + if(score <= 0) break; + if(score >= 1) maxIndex = 2; + if(score >= 5) maxIndex = 3; + if(score >= 6) maxIndex = 4; + if(score >= 10) maxIndex = 5; + if(score >= 11) maxIndex = 6; + if(score >= 25) maxIndex = 7; + if(score >= 30) maxIndex = 8; + if(score >= 45) maxIndex = 10; + if(score >= 50) maxIndex = 11; + + int index = Mathf.random(maxIndex); + + ids.add(index); + + maxUnitLevel = Math.max(maxUnitLevel, pullValue[index]); + score -= pullValue[index]; + } + + int radius = 15 + (maxUnitLevel*15/50); + for (int dy = -radius; dy <= radius; dy++) { + for (int dx = -radius; dx <= radius; dx++) { + int x = this.x + dx; + int y = this.y + dy; + if(isOut(x, y)) continue; + double hypot = Math.hypot(dx, dy); + if(hypot > radius) continue; + + boolean ferricStone = false; + boolean ferricCraters = false; + boolean ferricBoulder = false; + boolean ferricWall = false; + + boolean slag = false; + boolean magmarock = false; + boolean hotrock = false; + boolean basalt = false; + + boolean ore = false; + + double rand = hypot/radius; // 0 is near center + double irand = 1d - hypot/radius; // 0 is near bounds + ferricStone = Math.random() > (hypot-5)/radius; + + if(ferricStone) { + if(Math.random() < .2) { + ferricStone = false; + ferricCraters = true; } } - Call.logicExplosion(Team.neoplastic, x*tilesize, y*tilesize, radius*2, 25_000, true, true, false); - Call.logicExplosion(Team.neoplastic, x*tilesize, y*tilesize, radius*2 + 10, 10_000, true, true, true); - Call.sendMessage("[red]Метерорит упал!"); - - for (int i = 0; i < 5 + meteorits; i++) { - if(Groups.player.size() == 0) break; - if(Groups.player.index(0).unit() == null) break; - - Unit u = UnitTypes.renale.create(Team.crux); - u.set(x*tilesize, y*tilesize); - dormantCystDropUnits.add(u); - if(!net.client()){ - u.add(); - } + if(Math.random() < .3) { + ore = true; } - - if(meteorits%5 == 0 && meteorits > 0) { - for (int j = 0; j < meteorits; j+=5) { - boolean canHeal = UnitTypes.latum.canHeal; - - Ability regen = null; - for (int i = 0; i < UnitTypes.latum.abilities.size; i++) { - if(UnitTypes.latum.abilities.get(i).getClass().getName().equals(RegenAbility.class.getName())) { - regen = UnitTypes.latum.abilities.get(i); - UnitTypes.latum.abilities.remove(i); - break; - } - } - - UnitTypes.latum.setStats(); - Unit u = UnitTypes.latum.create(Team.crux); - u.set(x*tilesize, y*tilesize); - dormantCystDropUnits.add(u); - u.add(); - if(regen != null) - UnitTypes.latum.abilities.add(regen); - UnitTypes.latum.setStats(); + if(Math.random() < .15) { + ferricBoulder = true; + } + if(Math.random() < .05*irand) { + ferricWall = true; + ferricStone = true; + } + + if(ferricStone) { + if(Math.random() < .4) { + basalt = true; + } + if(Math.random() < .2) { + magmarock = true; + } + if(Math.random() < .1) { + magmarock = true; + } + if(Math.random() < .05) { + slag = true; } } - - meteorits++; - isEnded = true; - } - } else { - if(hasTarget(x, y)) { - if(getTsunamiPower(x+3, y) > .5 && getTsunamiPower(x-3, y) > .5 - && getTsunamiPower(x, y+3) > .5 && getTsunamiPower(x, y-3) > .5) { - if(shootTime%60 == 0) { - Fx.spawnShockwave.at(x, y, World.conv(15)); + + Block floor = null; + if(ferricStone) floor = Blocks.ferricStone; + if(ferricCraters) floor = Blocks.ferricCraters; + if(slag) floor = Blocks.slag; + if(magmarock) floor = Blocks.magmarock; + if(hotrock) floor = Blocks.hotrock; + if(basalt) floor = Blocks.basalt; + + Tile tile = world.tile(x, y); + if(tile.overlay() != Blocks.spawn) { + tile.clearOverlay(); + if(floor != null) { + tile.setFloorNet(floor, ore ? Blocks.oreScrap : tile.overlay()); } - if(shootTime == 0) { - Call.sendMessage("[red]Метерорит приближается!"); + if(floor != null && tile.block() != Blocks.air) { + if(Math.random() > rand*rand/1.5d) tile.setNet(Blocks.air); } - shootTime++; - if(shootTime > 60*30) { - fallTime = (int) (Math.random() * 60*60); - isActivated = true; + if(tile.block() == Blocks.air && ferricBoulder) { + tile.setNet(Blocks.ferricBoulder); + }else if(ferricWall) { + tile.setNet(Blocks.ferricStoneWall); } - } else { - shootTime = 0; } - + } + } + Call.effect(Fx.teleportActivate, x*tilesize, y*tilesize, radius*tilesize, Color.coral); + + Call.logicExplosion(Team.neoplastic, x*tilesize, y*tilesize, radius*tilesize, 10_000, true, true, false); + Call.logicExplosion(Team.neoplastic, x*tilesize, y*tilesize, radius*tilesize + 5*8, 5_000, true, true, true); + Call.sendMessage("[red]Метеорит упал!"); + + for (int i = 0; i < ids.size(); i++) { + int id = ids.get(i); + UnitType type = pull[id]; + Unit unit = null; + if(type == UnitTypes.latum || type == UnitTypes.renale) { + unit = type.create(Team.crux); } else { - Call.sendMessage("[red]Метерорит пролетел мимо!"); - needRemove = true; + type.flying = true; + unit = type.create(Team.crux); + type.flying = false; + } + if(unit != null) { + float angle = Mathf.random(360); + float dist = Mathf.random(radius/2f); + unit.set(x*tilesize + dist*Mathf.cosDeg(angle), y*tilesize + dist*Mathf.sinDeg(angle)); + dormantCystDropUnits.add(unit); + if(!net.client()){ + unit.add(); + } } } + +// if(meteorits%5 == 0 && meteorits > 0) { +// for (int j = 0; j < meteorits; j+=5) { +// boolean canHeal = UnitTypes.latum.canHeal; +// +// Ability regen = null; +// for (int i = 0; i < UnitTypes.latum.abilities.size; i++) { +// if(UnitTypes.latum.abilities.get(i).getClass().getName().equals(RegenAbility.class.getName())) { +// regen = UnitTypes.latum.abilities.get(i); +// UnitTypes.latum.abilities.remove(i); +// break; +// } +// } +// +// UnitTypes.latum.setStats(); +// Unit u = UnitTypes.latum.create(Team.crux); +// u.set(x*tilesize, y*tilesize); +// dormantCystDropUnits.add(u); +// u.add(); +// if(regen != null) +// UnitTypes.latum.abilities.add(regen); +// UnitTypes.latum.setStats(); +// } +// } + + meteorits++; + isEnded = true; } + private LiquidTurret getTsunami(int x, int y) { if(isOut(x, y)) return null; if(world.tile(x, y).block().name.equals(Blocks.tsunami.name)) { @@ -414,9 +566,10 @@ private LiquidTurret getTsunami(int x, int y) { } return null; } + private float getTsunamiPower(int x, int y) { if(isOut(x, y)) return 0; - + if(world.tile(x, y).block().name.equals(Blocks.tsunami.name)) { Building build = world.tile(x, y).build; if(build == null) return 0; @@ -427,8 +580,8 @@ private float getTsunamiPower(int x, int y) { return 0; } } - - + + private static final UnitType[][] replaseBase = { // 1 {UnitTypes.dagger, UnitTypes.stell}, @@ -449,14 +602,16 @@ private float getTsunamiPower(int x, int y) { {UnitTypes.antumbra, UnitTypes.quell}, {UnitTypes.eclipse, UnitTypes.disrupt}, }; + + // /event space_danger faston - + @Override public void withdraw(WithdrawEvent e) { if(e.player == null) return; Unit unit = e.player.unit(); if(unit == null) return; - + if(e.item == Items.fissileMatter) { UnitType unitType = unit.type(); if(unitType == UnitTypes.alpha || unitType == UnitTypes.beta || unitType == UnitTypes.gamma) { @@ -466,8 +621,8 @@ public void withdraw(WithdrawEvent e) { return; } for (int i = 0; i < replaseBase.length; i++) { - int cost1 = (i%5 + 1)*5; - int cost2 = (i%5 + 1); + int cost1 = (i%5 + 1)*10; + int cost2 = -(i%5 + 1)*10 + 1; if(unitType == replaseBase[i][0]) { if(e.amount >= cost1) { replaseBase[i][1].spawn(unit.team(), unit.x(), unit.y()); @@ -485,19 +640,13 @@ public void withdraw(WithdrawEvent e) { return; } if(unitType == replaseBase[i][1]) { - if(e.amount >= cost2) { - replaseBase[i][0].spawn(unit.team(), unit.x(), unit.y()); - unit.x(0); - unit.y(0); - unit.kill(); - addDormantCystToCore(e.amount-cost2); - unit.clearItem(); - Call.sendMessage("[gold]Игрок " + e.player.coloredName() + " [gold] потратил [lightgray]" + cost2 + " [gold]дремлющих оболочек"); - } else { - e.player.sendMessage("[gold]Недостаточно предметов, требуется " + cost2); - addDormantCystToCore(e.amount); - unit.clearItem(); - } + replaseBase[i][0].spawn(unit.team(), unit.x(), unit.y()); + unit.x(0); + unit.y(0); + unit.kill(); + addDormantCystToCore(e.amount-cost2); + unit.clearItem(); + Call.sendMessage("[gold]Игрок " + e.player.coloredName() + " [gold] вернул [lightgray]" + -cost2 + " [gold]дремлющих оболочек"); return; } } @@ -506,7 +655,20 @@ public void withdraw(WithdrawEvent e) { unit.clearItem(); } } - + + @Override + public void trigger(Player player, String... args) { + String name = args[0]; + if(name.equalsIgnoreCase("fall")) { + int x = (int) (player.mouseX()/8); + int y = (int) (player.mouseY()/8); + + Target target = new Target(x, y); + target.fallTime = -1; + target.update(); + } + } + private boolean addDormantCystToCore(int count) { if(Groups.player.size() > 0) { if(Groups.player.index(0).core() != null) {