Gaikotsu 620 Опубликовано 8 июня, 2018 7 часов назад, pvpgate сказал: интересно получается при логировании. getId() не подходит, т.к. дает Id рефлекта а не инстанс зоны. int izId = reflection.getInstancedZoneId(); 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
pvpgate 11 Опубликовано 9 июня, 2018 В 08.06.2018 в 06:30, Gaikotsu сказал: int izId = reflection.getInstancedZoneId(); Привет, это снова я, и опять же, чтобы не создавать новую тему, есть вопрос по инстансам. Как можно обрабатывать покидание инстанс зоны? Например по выходу из инстанс зоны (СОЕ, "в город" после смерти и т.д.) При входе я пробую причислить игроков к одной из 2 команд, а сразу при выходе хочу удалять игрока из списка команды. И второй вопрос, сложнее, можно ли имея списки игроков для 1 и 2 команды настроить, скажем, чтобы все игроки второй команды были варами для игрока первой команды. Или что-то типа такого, но не используя уродские RED и BLUE которые во всех ивентах и дуелях используются. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Demoncool 1110 Опубликовано 9 июня, 2018 19 минут назад, pvpgate сказал: Привет, это снова я, и опять же, чтобы не создавать новую тему, есть вопрос по инстансам. Как можно обрабатывать покидание инстанс зоны? Например по выходу из инстанс зоны (СОЕ, "в город" после смерти и т.д.) При входе я пробую причислить игроков к одной из 2 команд, а сразу при выходе хочу удалять игрока из списка команды. И второй вопрос, сложнее, можно ли имея списки игроков для 1 и 2 команды настроить, скажем, чтобы все игроки второй команды были варами для игрока первой команды. Или что-то типа такого, но не используя уродские RED и BLUE которые во всех ивентах и дуелях используются. добавляете метод onLeave листинг при выходе и туда все условия нужные Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
pvpgate 11 Опубликовано 9 июня, 2018 (изменено) 30 минут назад, Demoncool сказал: добавляете метод onLeave листинг при выходе и туда все условия нужные Извини, не понимаю. Я инстанс зону начал пробовать делать всего пару дней назад. а джаву и ооп вцелом начал осваивать незадолго до этого. В каком классе этот метод onLeave? Я так понимаю это в нем по умолчанию описано что у персонаж еще минуту после выхода будет принадлежать покинутой инстанс зоне? //upd кажется понял, это минуту живет зона. Если бы она жила час после вхыхода, то час игрок к ней бы и принадлежал... но все же, как удалить игрока из списка, в который он добавлен при входе в зону? Изменено 9 июня, 2018 пользователем pvpgate Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 9 июня, 2018 объявить для своего инстанса наследный класс от Reflection и делать в нем что хочется - там есть методы onPlayerEnter и onPlayerExit, вызывающиеся при входе и выходе игрока в инстанс. пример инстанса, имеющего свой особый класс - в нем при входе игроку показывают сценку на дивжке игры package instances; import l2p.gameserver.enums.Scene; import l2p.gameserver.model.Player; import l2p.gameserver.model.entity.Reflection; /** * @author Gaikotsu */ public class AdventOfDelusion extends Reflection { @Override public void onPlayerEnter(Player player) { super.onPlayerEnter(player); player.showScene(Scene.BLOODVEIN_OPENING); } } ну и естественно создавать и входить в инстанс с этим самым наследным классом, а не с базовым Reflection, т.е. так к примеру ReflectionUtils.simpleEnterInstancedZone(player, new AdventOfDelusion(), izId); ну а для того, чтобы сразу же при выходе из инстанса убрать игрока из списка посетивших его - надо его удалить из списка _visitors в этом самом методе onPlayerExit _visitors.remove(player.getObjectId()); 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 9 июня, 2018 а по причислению игроков к разным отрядам без стандартного setTeam - это можно, но только с модифицированием ядра сервера, если хочется чтобы полноценно обрабатывались все ситуации, связанные с взаимодействием игроков в одной и в разных командах. надо просто во всех местах, где проверяются стандартная принадлежность командам, добавить и проверку своей реализации причисления к командам. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
pvpgate 11 Опубликовано 9 июня, 2018 42 минуты назад, Gaikotsu сказал: ReflectionUtils.simpleEnterInstancedZone(player, new AdventOfDelusion(), izId); Слушай, а я же не смогу вызывать эту функцию прямо в классе своей инстанс зоны? Просто с одной стороны я в классе инстанс зоны должен удалять игроков из списка. А с другой стороны я в другом классе проверяю есть ли инстанс зона с таким названием, и если нет - создаю ее, а если да - телепортирую в существующую. И именно в этом месте, в байпасе, я должен решать в какую команду записывать игрока. Как я могу делать это в 2 классах? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 10 июня, 2018 дык запоминай в классе непися, через которого входишь - созданный инстанс и сверяйся с ним - есть он еще или нет и действуй по обстоятельствам Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
pvpgate 11 Опубликовано 10 июня, 2018 (изменено) 3 часа назад, Gaikotsu сказал: дык запоминай в классе непися, через которого входишь - созданный инстанс и сверяйся с ним - есть он еще или нет и действуй по обстоятельствам да, так и делаю, но ведь onPlayerEnter() я буду в классе инстанса допиливать и в нем нужно удалять из списка игроков Что-то типа public class L2Arena extends Reflection { ArrayList<Player> arenaTeam1 = new ArrayList<Player>(); ArrayList<Player> arenaTeam2 = new ArrayList<Player>(); @Override public void onPlayerExit(Player player) { super.onPlayerExit(player); player.sendMessage("Leave instance"); _visitors.remove(player.getObjectId()); arenaTeam1.remove(player); arenaTeam2.remove(player); } А добавлять в ту или иную команду мне нужно в классе НПЦ Я попробовал сделать костыль, и распределять по командам после входа на арену, а потом телепортировать в нужную точку арены: public class L2Arena extends Reflection { ArrayList<Player> arenaTeam1 = new ArrayList<Player>(); ArrayList<Player> arenaTeam2 = new ArrayList<Player>(); @Override public void onPlayerEnter(Player player) { super.onPlayerEnter(player); player.sendMessage("Enter instance"); if(arenaTeam1.size()>arenaTeam2.size()) { player.teleToLocation(84696, -16824, -1824, player.getActiveReflection()); arenaTeam2.add(player); player.sendMessage("add to team 2"); } else { player.teleToLocation(83304, -16024, -1888, player.getActiveReflection()); arenaTeam1.add(player); player.sendMessage("add to team 1"); } } добавил логирование, все происходит нормально, только вот улетаю я всегда на точку телепорта в xml инстанса и больше никуда не лечу, т.е. доп. телоепорты в IF-е ну срабатывают Изменено 10 июня, 2018 пользователем pvpgate Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 10 июня, 2018 (изменено) это происходит из-за того, что onPlayerEnter вызывается как раз в процессе телепорта в инстанс и само собой в то же время еще раз телепортироваться нельзя. можешь раскидывать по командам и перемещать на требуемые координаты с определенной задержкой, запуская задачу с этим в onPlayerEnter к примеру так - действия через 5 секунд после входа ThreadPoolManager.getInstance().schedule(new RunnableImpl() { @Override public void runImpl() throws Exception { // здесь назначаем команду и делаем телепорт } }, 5000); но вобще по уму надо сделать так как я выше писал - для телепортирующего в инстанс непися объявить свой инстанс и в нем обрабатывая байпас на вход перед самим входом обрабатывать игроков - давать им нужный отряд и задавать куда их телепортировать, в какие координаты. Изменено 10 июня, 2018 пользователем Gaikotsu 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
pvpgate 11 Опубликовано 10 июня, 2018 47 минут назад, Gaikotsu сказал: но вобще по уму надо сделать так как я выше писал - для телепортирующего в инстанс непися объявить свой инстанс и в нем обрабатывая байпас на вход перед самим входом обрабатывать игроков - давать им нужный отряд и задавать куда их телепортировать, в какие координаты. Спасибо. А нет случайно примера где объявляется инстанса классе НПС? Я не совсем понимаю что это значит. Класс НПЦ должен наследовать класс моей инсты? Или просто надо импортировать класс моей инсты? и Как объявлять новый экземпляр класса моей инсты в классе нпс? Сори за глупые вопросы, только начинаю разбираться с java и ооп вообще. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 10 июня, 2018 в датапаке, в scripts/npc/model/ есть целая куча персональных классов-инстансов для определенных неписей, так что примеров тебе там целую кучу найти можно 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
pvpgate 11 Опубликовано 11 июня, 2018 В 10.06.2018 в 14:23, Gaikotsu сказал: в датапаке, в scripts/npc/model/ есть целая куча персональных классов-инстансов для определенных неписей, так что примеров тебе там целую кучу найти можно спасибо. Еще один вопрос есть, можно ли точку респауна задавать динамически? Т.е. по сути я делаю некоторую модификацию ТВТ ивента, хочу чтобы при нажатии "в город" игроки ресались на своей стороне арены. Или же появлялась дополнительная кнопка, по аналогии "к флагу" на осаде, не важно, что можно что проще.. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 12 июня, 2018 (изменено) добавить свою обработку воскрешения и перемещения в пакет RequestRestartPoint ну или сделать проще - если игрок в режиме участия в пвп-эвенте, то вобще игнорировать от него запросы на воскрешение, а просто ресать самому с определенной задержкой. вот к примеру у меня в эвенте Team DeathMatch так сделано @Override public void onKill(Creature actor, Creature victim) { if (actor == null || victim == null || getStatus() != EventStatus.BATTLE || actor.getPlayer() == null || !victim.isPlayer()) return; EventMember killer = getMember(actor.getPlayer()); EventMember killed = getMember(victim.getPlayer()); if (killer == null || killed == null || killer == killed || killer.getPlayer() == null || killed.getPlayer() == null || killer.getTeam() == killed.getTeam()) return; if (killer.getTeam() == TeamType.RED) { incScore(TeamType.RED, getConfig().getPointsGive()); decScore(TeamType.BLUE, getConfig().getPointsLose()); } else { incScore(TeamType.BLUE, getConfig().getPointsGive()); decScore(TeamType.RED, getConfig().getPointsLose()); } addRewards(killer.getPlayer(), ActionType.KILL); ThreadPoolManager.getInstance().schedule(new PvPEventTasks.ActionTask(this, killed.getPlayer(), ActionTaskType.REVIVE_AND_BUFF), getConfig().getTimeToRevive() * 1000L); showMessage(killed.getPlayer(), "Вас убили. Через несколько секунд вы будете возрождены."); if (getConfig().getPointsCount() > 0 && (getScore(TeamType.RED) >= getConfig().getPointsCount() || getScore(TeamType.BLUE) >= getConfig().getPointsCount())) endBattle(); } вот эта строчка ThreadPoolManager.getInstance().schedule(new PvPEventTasks.ActionTask(this, killed.getPlayer(), ActionTaskType.REVIVE_AND_BUFF), getConfig().getTimeToRevive() * 1000L); указывает что надо через определенное время после смерти воскресить (с перемещением в заданную точку) и бафнуть З.Ы. onKill - это из листенера OnKillListener, так что само собой надо этот листенер объявлять и регистрировать у участников в начале боя, а в конце убирать обратно. Изменено 12 июня, 2018 пользователем Gaikotsu 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
pvpgate 11 Опубликовано 13 июня, 2018 (изменено) В 12.06.2018 в 09:27, Gaikotsu сказал: добавить свою обработку воскрешения и перемещения в пакет RequestRestartPoint Добавил в RequestRestartPoint условия default: if(activeChar.isInL2ArenaMode()==true) { if(activeChar.getL2ArenaSide()==1) { activeChar.setPendingRevive(true); activeChar.teleToLocation(81992, -16040, -1888, activeChar.getActiveReflection()); } if(activeChar.getL2ArenaSide()==2) { activeChar.setPendingRevive(true); activeChar.teleToLocation(84232, -16696, -1840, activeChar.getActiveReflection()); } } но это не дело так хардкодить. Подскажи плз, как правильно в классе моей инсты задать 2 точки телепортации ? пробовал так: private static Location _blueloc = null; private static Location _redloc = null; _blueloc.set(81992, -16040, -1888); _blueloc.set(84232, -16696, -1840); Но ничего хорошего не получилось. Как задать их так, чтоб потом можно было обращаться к какому нибудь методу, возвращающему локацию по типу ctiveChar.teleToLocation(L2Arena.getBlueLoc(), activeChar.getActiveReflection()); ? Изменено 13 июня, 2018 пользователем pvpgate Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 14 июня, 2018 (изменено) если ты объявляешь их в датапаке, то из ядра будет достаточно сложно к ним обратиться. вобще, можешь сделать листенер на запрос воскрешения, зарегать в своем эвенте и дергать его в RequestRestartPoint т.е. первым делом дергается листенер и если он не отработал (обработка должна возвращать к примеру true/false как признак того что что-то сделано/не сделано), то только тогда обрабатываются стандартные варианты воскрешения. еще как вариант, заведи в классе Player сессионные переменные, в которых можно будет хранить любые данные до перезахода в игру - чисто в памяти, без сохранения в бд. т.е. по сути аналог кукисов в вебе - таким образом можно будет обмениваться любыми данными между датапаком и ядром. сделать это в виде обычной мапы <String, String> или <String, Object> к примеру. и вот туда можешь к примеру положить координаты, а потом в любое время взять обратно по ключу мапы. для примера, моя реализация сессионных переменных /** * -------------------------------------------------- * Работа с временными переменными, хранящимися в памяти и удаляющимися при выходе игрока из игры * -------------------------------------------------- */ private final Map<String, String> _sessionVars = new ConcurrentHashMap<>(); public Map<String, String> getSessionVars() { return _sessionVars; } public String getSessionVar(String name) { return _sessionVars.get(name); } public String getSessionVar(String name, String def) { String val = getSessionVar(name); return val != null && !val.isEmpty() ? val : def; } public int getSessionVar(String name, int def) { String val = getSessionVar(name, null); return val != null ? Integer.parseInt(val) : def; } public long getSessionVar(String name, long def) { String val = getSessionVar(name, null); return val != null ? Long.parseLong(val) : def; } public double getSessionVar(String name, double def) { String val = getSessionVar(name, null); return val != null ? Double.parseDouble(val) : def; } public boolean getSessionVar(String name, boolean def) { String val = getSessionVar(name, null); return val != null ? !val.equalsIgnoreCase("false") : def; } public void setSessionVar(String name, String val) { _sessionVars.put(name, val); } public void setSessionVar(String name, int val) { setSessionVar(name, Integer.toString(val)); } public void setSessionVar(String name, long val) { setSessionVar(name, Long.toString(val)); } public void setSessionVar(String name, double val) { setSessionVar(name, Double.toString(val)); } public void setSessionVar(String name, boolean val) { setSessionVar(name, Boolean.toString(val)); } public void unsetSessionVar(String... names) { for (String name : names) _sessionVars.remove(name); } вобщем по сути аналог стандартных setVar/getVar, просто без работы с бд. Изменено 14 июня, 2018 пользователем Gaikotsu 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
darkseed 6 Опубликовано 14 июня, 2018 (изменено) Извиняюсь что наверно не в теме есть инст фреи как из него выпилить проверку на командный канал ( тоесть что бы в инст можно было залазить 1й группой) и если не в коде то где можно это убрать. Заранее благодарен. public class FreyaNormal extends Reflection { private static final int FreyaThrone = 29177; private static final int FreyaStandNormal = 29179; private static final int IceKnightNormal = 18855; //state 1 - in ice, state 2 - ice shattering, then normal state private static final int IceKnightLeaderNormal = 25699; private static final int IceCastleBreath = 18854; private static final int Glacier = 18853; // state 1 - falling, state 2 - waiting private static final int IceCastleController = 18932; // state 1-7 private static final int Sirra = 32762; private static final int Jinia = 18850; private static final int Kegor = 18851; private static final int[] _eventTriggers = { 23140202, 23140204, 23140206, 23140208, 23140212, 23140214, 23140216 }; private Zone damagezone, attackUp, pcbuff, pcbuff2; private ScheduledFuture<?> firstStageGuardSpawn; private ScheduledFuture<?> secondStageGuardSpawn; private ScheduledFuture<?> thirdStageGuardSpawn; private ZoneListener _epicZoneListener = new ZoneListener(); private ZoneListenerL _landingZoneListener = new ZoneListenerL(); private DeathListener _deathListener = new DeathListener(); private CurrentHpListener _currentHpListener = new CurrentHpListener(); private boolean _entryLocked = false; private boolean _startLaunched = false; private boolean _freyaSlayed = false; private AtomicInteger raidplayers = new AtomicInteger(); private static Territory centralRoom = new Territory().add(new Polygon().add(114264, -113672).add(113640, -114344).add(113640, -115240).add(114264, -115912).add(115176, -115912).add(115800, -115272).add(115800, -114328).add(115192, -113672).setZmax(-11225).setZmin(-11225)); @Override protected void onCreate() { super.onCreate(); attackUp = getZone("[freya_attack_up]"); pcbuff = getZone("[freya_pc_buff1]"); pcbuff2 = getZone("[freya_pc_buff2]"); getZone("[freya_normal_epic]").addListener(_epicZoneListener); getZone("[freya_landing_room_epic]").addListener(_landingZoneListener); } private void manageDamageZone(int level, boolean disable) { if(disable) { damagezone.setActive(false); return; } if(damagezone != null) { damagezone.setActive(false); } switch(level) { case 1: damagezone = getZone("[freya_normal_freezing_01]"); break; case 2: damagezone = getZone("[freya_normal_freezing_02]"); break; case 3: damagezone = getZone("[freya_normal_freezing_03]"); break; case 4: damagezone = getZone("[freya_normal_freezing_04]"); break; case 5: damagezone = getZone("[freya_normal_freezing_05]"); break; case 6: damagezone = getZone("[freya_normal_freezing_06]"); break; case 7: damagezone = getZone("[freya_normal_freezing_07]"); break; default: break; } if(damagezone != null) { damagezone.setActive(true); } } private void manageAttackUpZone(boolean disable) { if(attackUp != null && disable) { attackUp.setActive(false); return; } if(attackUp != null) { attackUp.setActive(true); } } private void managePcBuffZone(boolean disable) { if(pcbuff != null && pcbuff2 != null && disable) { pcbuff.setActive(false); pcbuff2.setActive(false); return; } if(pcbuff != null) { pcbuff.setActive(true); } if(pcbuff2 != null) { pcbuff2.setActive(true); } } private void manageCastleController(int state) { // 1-7 enabled, 8 - disabled for(NpcInstance n : getNpcs()) { if(n.getNpcId() == IceCastleController) { n.setNpcState(state); } } } private void manageStorm(boolean active) { for(Player p : getPlayers()) { for(int _eventTrigger : _eventTriggers) { p.sendPacket(new EventTriggerPacket(_eventTrigger, active)); } } } private class StartNormalFreya extends RunnableImpl { @Override public void runImpl() throws Exception { _entryLocked = true; closeDoor(23140101); for(Player player : getPlayers()) { QuestState qs = player.getQuestState(10286); if(qs != null && qs.getCond() == 5) { qs.setCond(6); } player.startScenePlayer(SceneMovie.FREYA_OPENING); } ThreadPoolManager.getInstance().schedule(new PreStage(), 55000L); // 53.5sec for movie } } private class PreStage extends RunnableImpl { @Override public void runImpl() throws Exception { manageDamageZone(1, false); //screen message for(Player player : getPlayers()) { player.sendPacket(new ExShowScreenMessage(NpcString.BEGIN_STAGE_1_FREYA, 6000, ScreenMessageAlign.TOP_CENTER, true, 1, -1, true)); } //spawning few guards for(int i = 0; i < 10; i++) { addSpawnWithoutRespawn(IceKnightNormal, Territory.getRandomLoc(centralRoom, getGeoIndex()), 0); } ThreadPoolManager.getInstance().schedule(new FirstStage(), 40000L); } } private class FirstStage extends RunnableImpl { @Override public void runImpl() throws Exception { manageCastleController(1); manageDamageZone(2, false); for(Player player : getPlayers()) { player.sendPacket(new ExShowScreenMessage(NpcString.FREYA_HAS_STARTED_TO_MOVE, 4000, ScreenMessageAlign.MIDDLE_CENTER, true)); } //Spawning Freya Throne NpcInstance freyaTrhone = addSpawnWithoutRespawn(FreyaThrone, new Location(114720, -117085, -11088, 15956), 0); freyaTrhone.addListener(_deathListener); firstStageGuardSpawn = ThreadPoolManager.getInstance().scheduleAtFixedRate(new GuardSpawnTask(1), 2000L, 30000L); } } private class GuardSpawnTask extends RunnableImpl { int _mode, _knightsMin, _knightsMax, _breathMin, _breathMax; public GuardSpawnTask(int mode) // 1 - light, 2 - normal, 3 - hard, 4 - extreme { _mode = mode; if(_mode < 1 || _mode > 4) { _mode = 1; } } @Override public void runImpl() throws Exception { switch(_mode) { case 1: _knightsMin = 2; _knightsMax = 3; _breathMin = 1; _breathMax = 2; break; case 2: _knightsMin = 2; _knightsMax = 4; _breathMin = 1; _breathMax = 3; break; case 3: _knightsMin = 3; _knightsMax = 8; _breathMin = 2; _breathMax = 4; break; case 4: _knightsMin = 6; _knightsMax = 10; _breathMin = 3; _breathMax = 7; break; default: break; } for(int i = 0; i < Rnd.get(_knightsMin, _knightsMax); i++) { addSpawnWithoutRespawn(IceKnightNormal, Territory.getRandomLoc(centralRoom, getGeoIndex()), 0); } for(int i = 0; i < Rnd.get(_breathMin, _breathMax); i++) { addSpawnWithoutRespawn(IceCastleBreath, Territory.getRandomLoc(centralRoom, getGeoIndex()), 0); } if(Rnd.chance(60)) { for(int i = 0; i < Rnd.get(1, 3); i++) { addSpawnWithoutRespawn(Glacier, Territory.getRandomLoc(centralRoom, getGeoIndex()), 0); } } } } private class PreSecondStage extends RunnableImpl { @Override public void runImpl() throws Exception { firstStageGuardSpawn.cancel(true); for(NpcInstance n : getNpcs()) { if(n.getNpcId() != Sirra && n.getNpcId() != IceCastleController) { n.deleteMe(); } } for(Player p : getPlayers()) { p.startScenePlayer(SceneMovie.FREYA_PHASE_CHANGE_A); } ThreadPoolManager.getInstance().schedule(new TimerToSecondStage(), 22000L); // 22.1 secs for movie } } private class TimerToSecondStage extends RunnableImpl { @Override public void runImpl() throws Exception { for(Player p : getPlayers()) { p.sendPacket(new ExSendUIEventPacket(p, 0, 0, 60, 0, NpcString.TIME_REMAINING_UNTIL_NEXT_BATTLE)); } ThreadPoolManager.getInstance().schedule(new SecondStage(), 60000L); } } private class SecondStage extends RunnableImpl { @Override public void runImpl() throws Exception { manageCastleController(3); manageDamageZone(3, false); for(Player p : getPlayers()) { p.sendPacket(new ExShowScreenMessage(NpcString.BEGIN_STAGE_2_FREYA, 6000, ScreenMessageAlign.TOP_CENTER, true, 1, -1, true)); } secondStageGuardSpawn = ThreadPoolManager.getInstance().scheduleAtFixedRate(new GuardSpawnTask(2), 2000L, 30000L); ThreadPoolManager.getInstance().schedule(new KnightCaptainSpawnMovie(), 60000L); } } private class KnightCaptainSpawnMovie extends RunnableImpl { @Override public void runImpl() throws Exception { for(NpcInstance n : getNpcs()) { n.block(); } for(Player p : getPlayers()) { p.startScenePlayer(SceneMovie.ICE_HEAVY_KNIGHT_SPAWN); } ThreadPoolManager.getInstance().schedule(new KnightCaptainSpawn(), 7500L); } } private class KnightCaptainSpawn extends RunnableImpl { @Override public void runImpl() throws Exception { manageDamageZone(4, false); for(NpcInstance n : getNpcs()) { n.unblock(); } NpcInstance knightLeader = addSpawnWithoutRespawn(IceKnightLeaderNormal, new Location(114707, -114799, -11199, 15956), 0); knightLeader.addListener(_deathListener); } } private class PreThirdStage extends RunnableImpl { @Override public void runImpl() throws Exception { for(Player p : getPlayers()) { p.sendPacket(new ExSendUIEventPacket(p, 0, 0, 60, 0, NpcString.TIME_REMAINING_UNTIL_NEXT_BATTLE)); } secondStageGuardSpawn.cancel(true); for(NpcInstance n : getNpcs()) { if(n.getNpcId() != Sirra && n.getNpcId() != IceCastleController) { n.deleteMe(); } } ThreadPoolManager.getInstance().schedule(new PreThirdStageM(), 60000L); } } private class PreThirdStageM extends RunnableImpl { @Override public void runImpl() throws Exception { for(Player p : getPlayers()) { p.startScenePlayer(SceneMovie.FREYA_PHASE_CHANGE_B); } ThreadPoolManager.getInstance().schedule(new ThirdStage(), 22000L); // 21.5 secs for movie } } private class ThirdStage extends RunnableImpl { @Override public void runImpl() throws Exception { manageCastleController(4); manageAttackUpZone(false); manageDamageZone(5, false); manageStorm(true); for(Player p : getPlayers()) { p.sendPacket(new ExShowScreenMessage(NpcString.BEGIN_STAGE_3_FREYA, 6000, ScreenMessageAlign.TOP_CENTER, true, 1, -1, true)); p.sendPacket(new ExChangeClientEffectInfo(2)); } thirdStageGuardSpawn = ThreadPoolManager.getInstance().scheduleAtFixedRate(new GuardSpawnTask(3), 2000L, 30000L); NpcInstance freyaStand = addSpawnWithoutRespawn(FreyaStandNormal, new Location(114720, -117085, -11088, 15956), 0); freyaStand.addListener(_currentHpListener); freyaStand.addListener(_deathListener); } } private class PreForthStage extends RunnableImpl { @Override public void runImpl() throws Exception { for(NpcInstance n : getNpcs()) { n.block(); } for(Player p : getPlayers()) { p.block(); p.startScenePlayer(SceneMovie.KEGOR_INTRUSION); } ThreadPoolManager.getInstance().schedule(new ForthStage(), 28000L); // 27 secs for movie } } private class ForthStage extends RunnableImpl { @Override public void runImpl() throws Exception { for(NpcInstance n : getNpcs()) { n.unblock(); } for(Player p : getPlayers()) { p.unblock(); p.sendPacket(new ExShowScreenMessage(NpcString.BEGIN_STAGE_4_FREYA, 6000, ScreenMessageAlign.TOP_CENTER, true, 1, -1, true)); } addSpawnWithoutRespawn(Jinia, new Location(114727, -114700, -11200, -16260), 0); addSpawnWithoutRespawn(Kegor, new Location(114690, -114700, -11200, -16260), 0); managePcBuffZone(false); } } private class FreyaDeathStage extends RunnableImpl { @Override public void runImpl() throws Exception { setReenterTime(System.currentTimeMillis()); //Guard spawn task cancellation thirdStageGuardSpawn.cancel(true); //switching off zones manageDamageZone(1, true); manageAttackUpZone(true); managePcBuffZone(true); //Deleting all NPCs + Freya corpse for(NpcInstance n : getNpcs()) { n.deleteMe(); } //Movie + quest update for(Player p : getPlayers()) { QuestState qs = p.getQuestState(10286); if(qs != null && qs.getCond() == 6) { qs.setCond(7); } p.startScenePlayer(SceneMovie.FREYA_ENDING_A); } ThreadPoolManager.getInstance().schedule(new ConclusionMovie(), 16200L); // 16 secs for movie } } private class ConclusionMovie extends RunnableImpl { @Override public void runImpl() throws Exception { for(Player p : getPlayers()) { p.startScenePlayer(SceneMovie.FREYA_ENDING_B); } ThreadPoolManager.getInstance().schedule(new InstanceConclusion(), 57000L); // 56 secs for movie } } private class InstanceConclusion extends RunnableImpl { @Override public void runImpl() throws Exception { startCollapseTimer(5 * 60 * 1000L); doCleanup(); for(Player p : getPlayers()) { p.sendPacket(new SystemMessage(SystemMessage.THIS_DUNGEON_WILL_EXPIRE_IN_S1_MINUTES).addNumber(5)); } } } private class DeathListener implements OnDeathListener { @Override public void onDeath(Creature self, Creature killer) { if(self.isNpc() && self.getNpcId() == FreyaThrone) { ThreadPoolManager.getInstance().schedule(new PreSecondStage(), 10); self.deleteMe(); } else if(self.isNpc() && self.getNpcId() == IceKnightLeaderNormal) { ThreadPoolManager.getInstance().schedule(new PreThirdStage(), 10); } else if(self.isNpc() && self.getNpcId() == FreyaStandNormal) { ThreadPoolManager.getInstance().schedule(new FreyaDeathStage(), 10); } } } public class CurrentHpListener implements OnCurrentHpDamageListener { @Override public void onCurrentHpDamage(Creature actor, double damage, Creature attacker, Skill skill) { if(actor == null || actor.isDead() || actor.getNpcId() != FreyaStandNormal) { return; } double newHp = actor.getCurrentHp() - damage; double maxHp = actor.getMaxHp(); if(!_freyaSlayed && newHp <= 0.2 * maxHp) { _freyaSlayed = true; ThreadPoolManager.getInstance().schedule(new PreForthStage(), 10); actor.removeListener(_currentHpListener); } } } public class ZoneListener implements OnZoneEnterLeaveListener { @Override public void onZoneEnter(Zone zone, Creature cha) { if(_entryLocked) { return; } Player player = cha.getPlayer(); if(player == null || !cha.isPlayer()) { return; } if(checkstartCond(raidplayers.incrementAndGet())) { ThreadPoolManager.getInstance().schedule(new StartNormalFreya(), 30000L); _startLaunched = true; } } @Override public void onZoneLeave(Zone zone, Creature cha) { } } public class ZoneListenerL implements OnZoneEnterLeaveListener { @Override public void onZoneEnter(Zone zone, Creature cha) { if(cha.isPlayer()) { cha.sendPacket(new ExChangeClientEffectInfo(1)); } } @Override public void onZoneLeave(Zone zone, Creature cha) { } } private boolean checkstartCond(int raidplayers) { return !(raidplayers < getInstancedZone().getMinParty() || _startLaunched); } private void doCleanup() { if(firstStageGuardSpawn != null) { firstStageGuardSpawn.cancel(true); } if(secondStageGuardSpawn != null) { secondStageGuardSpawn.cancel(true); } if(thirdStageGuardSpawn != null) { thirdStageGuardSpawn.cancel(true); } } @Override protected void onCollapse() { super.onCollapse(); doCleanup(); } } Hide Изменено 14 июня, 2018 пользователем darkseed Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
pvpgate 11 Опубликовано 14 июня, 2018 17 часов назад, Gaikotsu сказал: еще как вариант, заведи в классе Player сессионные переменные, в которых можно будет хранить любые данные до перезахода в игру - чисто в памяти, без сохранения в бд. т.е. по сути аналог кукисов в вебе - таким образом можно будет обмениваться любыми данными между датапаком и ядром. сделать это в виде обычной мапы <String, String> или <String, Object> к примеру. и вот туда можешь к примеру положить координаты, а потом в любое время взять обратно по ключу мапы. Кажется я что-то подобное сделал чтобы хранить принадлежность к командам в классе Player: private int _l2arenaSide = -1; public void setL2ArenaSide(final int i) { _l2arenaSide = i; } public int getL2ArenaSide() { return _l2arenaSide; } Впринципе сюда же можно сохранять координаты, в зависимости от тимы, вот только я не понял что такое map? Я так понимаю есть класс Location, у которого есть метод set(int x, int y, int z); Сейчас будет совсем глупый вопрос, а не могу ли я создать 2 объекта класса Location в классе Player, на подобии как я создал интовые _l2atenaSide, а потом сделать методы set() и get() для них? Если да, то как правильно создать объект типа Location и как правильно настроить set() и get() для него по аналогии с моей _l2arenaSide ? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 15 июня, 2018 (изменено) 20 часов назад, darkseed сказал: Извиняюсь что наверно не в теме есть инст фреи как из него выпилить проверку на командный канал ( тоесть что бы в инст можно было залазить 1й группой) и если не в коде то где можно это убрать. Заранее благодарен. ... Скрыть ну к примеру в стандартном овере/лосте тип инстанса определяется по количеству игроков что могут в него войти, т.е. по данным из хмлки, описывающей свойства этого инстанса - так что обычно достаточно там просто убавить количество до одной пати. но к примеру я у себя давно доработал работу с инстансами в этом плане и у меня инстанс может быть одновременно как для пати, так и для кк, или к примеру для одиночного игрока или пати хотя я вобще хорошо так перелопатил оригинальный оверовский формат хмлок с данными по инстансам -------------------------------------------------------------------------------- --- Описание структуры файлов, описывающих инстансы --- --- Местонахождение: data/instances/*.xml -------------------------------------------------------------------------------- Нода instance: id - идентификатор инстанса. name - название инстанса. Так же может содержать в себе следующие субноды: params, return, teleport, spawns, doors, zones. Субнода params: Содержит в себе субноды param, с атрибутами name и value - название параметра и его значение. Допустимые параметры и их значения: entryType - тип инстанса. Допустимые значения: SOLO - для одного игрока, PARTY - для группы, COMMAND_CHANNEL - для командного канала. Можно перечислить несколько типов через точку с запятой. Если параметр не задан, то он определяется автоматически по параметру "players". Если перечисляется несколько типов входа, то для корректной работы желательно перечислять типы в следующем порядке: COMMAND_CHANNEL, PARTY, SOLO. levels - лимит уровней игроков. Строка вида "minLevel;maxLevel". Если не задан максимальный уровень, то он равен максимально достижимому уровню. Значение по умолчанию - 1;110. players - лимит количества игроков. Строка вида "minCount;maxCount". Если не задано максимальное количество, то оно равно минимальному количеству. Если не задан явно параметр "entryType", то именно от значения этого параметра зависит то, какой тип выставится инстансу (соло, для пати, для КК): минимальное количество равно 1 - соло; минимальное количество от 2 до 7 включительно и максимальное количество не больше 7 - для пати; максимальное количество больше 7 - для КК. Значение по умолчанию - 1;1. timeLimit - лимит времени инстанса, в минутах. Если значение больше 0, то при создании инстанса активируется задача, закрывающая этот инстанс через заданное время. Значение по умолчанию - 0. maxChannels - лимит одновременно существующих инстансов данного вида. Указывает, сколько инстансов этого вида может существовать одновременно на сервере. Значение по умолчанию - 20. collapseIfEmpty - через сколько минут закрыть инстанс, если его покинули все игроки. При значении равном -1 функция отключается. Значение по умолчанию - 0. collapseIfPartyDismiss - через сколько минут закрыть инстанс, если группа игроков, находящаяся в нем, была распущена. При значении равном 0 функция отключается. Значение по умолчанию - 1. collapseIfCommandChannelDismiss - через сколько минут закрыть инстанс, если командный канал игроков, находящихся в нем, был распущен. При значении равном 0 функция отключается. Значение по умолчанию - 0. kickIfDead - через сколько минут выбросить мертвого игрока из инстанса, если его никто за это время не воскресил. При значении равном 0 функция отключается. Значение по умолчанию - 1. dispelBuffs - снимать или нет все баффы с игроков при заходе в инстанс. Значение по умолчанию - false. timerMode - режим показа таймера, находящимся в инстансе игрокам. Допустимые значения: NONE - не показывать время, ELAPSED - прошло времени, REMAINING - осталось времени. Значение по умолчанию - NONE. timerTime - с какого значения, в секундах, начать отсчет времени на таймере. Значение по умолчанию - timeLimit * 60. removeItem - предметы, проверяемые у игроков при попытке входа в инстанс и удаляемые при успешном входе в него. Строка вида "itemId,itemId ... itemId;count;removeType". Если задано несколько разных предметов, то необходимо наличие хотя бы одного из них. Если количество предметов не задано, то оно равно 1. Значение removeType отвечает за то, у кого будут удалены требуемые предметы: 0 - у всех входящих в инстанс; 1 - только у лидера группы/КК. Если значение removeType не задано, то оно равно 0. Значение по умолчанию - 0;0;0. requiredItem - предметы, проверяемые у игроков при попытке входа в инстанс и не удаляемые при входе в него. Строка вида "itemId,itemId ... itemId;count". Если задано несколько разных предметов, то необходимо наличие хотя бы одного из них. Если количество предметов не задано, то оно равно 1. Значение по умолчанию - 0;0. giveItem - предметы, выдаваемые игрокам при входе в инстанс. Строка вида "itemId,itemId ... itemId;count". Если количество предметов не задано, то оно равно 1. Значение по умолчанию - 0;0. geodata - сектор геодаты, в котором находится инстанс. Необходим в инстансах с дверями, т.к. без указания сектора в таком инстансе будут проблемы с проходом через открытые двери. Значение по умолчанию - сектор не задан. requiredQuestId - идентификатор начатого или выполненного квеста, который должен быть у игрока для входа в инстанс. При значении равном 0 наличие квеста не проверяется. Значение по умолчанию - 0. onlyStartedQuest - дополнительное условие для предыдущего параметра. Если равно true, то проверяются только начатые квесты. Значение по умолчанию - true. resetReuse - ближайшее время, в которое сбрасывается ограничение на вход в инстанс. Задается строкой в формате Cron. Значение по умолчанию - "* * * * *" (можно сразу же повторно зайти в инстанс). setReuseUponEntry - устанавливать или нет реюз при входе в инстанс. Если значение равно false, то реюз по необходимости необходимо выставлять игрокам вручную. Значение по умолчанию - true. sharedReuseGroup - общая группа реюза. У всех инстансов с одинаковой группой, со значением больше 0, будет выставляться одинаковый реюз. Значение по умолчанию - 0. removeVisitor - Удалять или нет вышедшего из инстанса игрока из списка посетивших этот инстанс. Может пригодиться для статичных инстансов, которые существуют после создания до выключения сервера. Значение по умолчанию - false. Кроме того, можно задавать и свои параметры, читая их потом через метод getParams() инстанса. Для параметров removeItem и requiredItem, кроме обычных предметов можно так же указывать очки PC Cafe (-100), славу (-300) и рейдовые очки (-500) - в скобках указаны их идентификаторы. Субнода return: loc - координаты, в которые перемещаются игроки при закрытии инстанса или выходе через SOE/смерть. Субнода teleport (можно задавать несколько таких субнод): loc - координаты, в которые перемещаются игроки при телепорте в инстанс. Субнода spawns: Может содержать в себе субноды group и spawn. Субнода group может иметь следующие атрибуты: name - название группы спавна. spawned - должна ли группа спавнится сразу же после создания инстанса. Значение по умолчанию - false. Субнода spawn может иметь следующие атрибуты: id - идентификаторы нпс. Строка вида "npcId;npcId ... npcId". count - количество нпс для спавна. Значение по умолчанию - 1. respawn - время респавна в секундах. При значении равном 0 респавн отключается. Значение по умолчанию - 0. respawnRnd - разброс времени респавна в секундах. Значение по умолчанию - 0. type - тип спавна. Может принимать следующие значения: 0 - точечный, в каждой указанной точке; 1 - один точечный спаун в рандомной точке; 2 - локационный. Значение по умолчанию - 0. Так же данная субнода имеет субноды coords, в которых описываются точки спавна или территория, внутри которой будут заспавлены нпс. Субнода doors: Может содержать в себе субноды door, описывающие двери в инстансе. Субнода door может иметь следующие атрибуты: id - идентификатор двери. opened - начальное состояние двери. При значении равном true - открыта. Значение по умолчанию - false. invul - неуязвима или нет дверь. Значение по умолчанию - true. Субнода zones: Может содержать в себе субноды zone, описывающие зоны в инстансе. Субнода zone может иметь следующие атрибуты: name - название зоны. active - начальное состояние зоны. Значение по умолчанию - false. Скрыть Изменено 15 июня, 2018 пользователем Gaikotsu 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 15 июня, 2018 6 часов назад, pvpgate сказал: Впринципе сюда же можно сохранять координаты, в зависимости от тимы, вот только я не понял что такое map? Я так понимаю есть класс Location, у которого есть метод set(int x, int y, int z); Сейчас будет совсем глупый вопрос, а не могу ли я создать 2 объекта класса Location в классе Player, на подобии как я создал интовые _l2atenaSide, а потом сделать методы set() и get() для них? Если да, то как правильно создать объект типа Location и как правильно настроить set() и get() для него по аналогии с моей _l2arenaSide ? 1. Map/HashMap и т.п. 2. есть 3. можешь 4. да как хочешь, к примеру private Location _loc; public void setLoc(Location loc) { _loc = loc; } public Location getLoc() { return _loc; } и не забывай проверять на null значение возвращаемое getLoc, т.к. по умолчанию новосозданный объект равен null. 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты