Система рифтов в Подземный Каталам
Сопоставимые версии v4.8+
ЯДРО
Добавляем в автозагрузку GameServer сервис
Сам сервис
Аи для сервиса
ДАТА
Добавляем в статик дату портал
C:\Server_AioN\AioN_5.8_MASTER_TEST\Game\data\static_data\npcs\npc_templates
C:\Server_AioN\AioN_5.8_MASTER_TEST\Game\data\static_data\portals
Сопоставимые версии v4.8+
ЯДРО
Добавляем в автозагрузку GameServer сервис
Код:
KatalamUnderRiftService.getInstance().spawn();
Сам сервис
Код:
/*
* M.O.G. Devs Team
* www.mmorpg-onlinegames.ru
* Teg's {/aiononline, /eveonline}
*
* F5 Katalam Under rift Service
*/
package com.mog.gameserver.services.upheaval.f5Event;
import java.util.Map.Entry;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mog.gameserver.model.gameobjects.VisibleObject;
import com.mog.gameserver.model.gameobjects.player.Player;
import com.mog.gameserver.model.rift.RiftList;
import com.mog.gameserver.network.aion.AionServerPacket;
import com.mog.gameserver.network.aion.serverpackets.SM_RIFT_ANNOUNCE;
import com.mog.gameserver.spawnengine.SpawnEngine;
import com.mog.gameserver.utils.PacketSendUtility;
import com.mog.gameserver.utils.ThreadPoolManager;
import com.mog.gameserver.world.World;
import com.mog.gameserver.world.WorldMapInstance;
import com.mog.gameserver.world.knownlist.Visitor;
import javolution.util.FastMap;
/**
* @author Dision
*/
public class KatalamUnderRiftService {
private static final Logger log = LoggerFactory.getLogger(KatalamUnderRiftService.class);
private FastMap<Integer, Future<?>> tasks = FastMap.newInstance();
private FastMap<Integer, VisibleObject> objects = new FastMap<>();
private FastMap<Integer, RiftList> rifts = new FastMap<>();
private int RIFT_SPAWN_DELAY = 5; // 5 min.
private int RIFT_RESPAWN_DELAY = 3600; // 1 hour
private int RIFT_LIFETIME = 1800; // 30 min.
private int key = 0;
public void spawn() {
tasks.put(key++, ThreadPoolManager.getInstance().scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
spawnRift(210070000, 731631, 777.01f, 1479.86f, 457.37f, (byte) 34);
spawnRift(220080000, 731632, 233.35f, 1136.98f, 225.87f, (byte) 115);
}
}, RIFT_SPAWN_DELAY * 60000, RIFT_RESPAWN_DELAY * 1000));
}
public FastMap<Integer, VisibleObject> getObjects() {
return objects;
}
public FastMap<Integer, RiftList> getRifts() {
return rifts;
}
public void loadRiftList(boolean isActive) {
if (rifts != null) {
for (Entry<Integer, RiftList> entry : rifts.entrySet()) {
globalRiftPacket(entry.getValue(), isActive);
}
}
}
private void spawnRift(int worldId, int npcId, float x, float y, float z, byte h) {
objects.put(npcId, SpawnEngine.spawnObject(SpawnEngine.addNewSingleTimeSpawn(worldId, npcId, x, y, z, h), 1));
rifts.put(objects.get(npcId).getObjectId(), new RiftList(objects.get(npcId).getObjectId(), worldId, x, y, z));
loadRiftList(true);
sendAnnounce(objects.get(npcId));
scheduleDelete(npcId);
log.info("KatalamUnderRiftService: spawnRift [npcId = " + npcId + "]");
}
public void globalRiftPacket(final RiftList riftList, final boolean isActive) {
World.getInstance().getWorldMap(riftList.getWorldId()).getMainWorldMapInstance().doOnAllPlayers(new Visitor<Player>() {
@Override
public void visit(Player player) {
if (isActive) {
PacketSendUtility.sendPacket(player, riftPacketInfo(riftList.getObjectId(), riftList.getX(), riftList.getY(), riftList.getZ(), true));
log.info("KatalamUnderRiftService: globalRiftPacket add [Id = " + riftList.getObjectId() + "] [x = " + riftList.getX() + "] [y = " + riftList.getY() + "] [z = " + riftList.getZ() + "]");
}
else {
PacketSendUtility.sendPacket(player, riftPacketInfoRemove(riftList.getObjectId()));
log.info("KatalamUnderRiftService: globalRiftPacket remove [Id = " + riftList.getObjectId() + "]");
}
}
});
}
private AionServerPacket riftPacketInfo(int objectId, float x, float y, float z, boolean isMaster) {
return new SM_RIFT_ANNOUNCE(objectId, x, y, z, isMaster);
}
private AionServerPacket riftPacketInfoRemove(int objectId) {
return new SM_RIFT_ANNOUNCE(4, objectId);
}
private void scheduleDelete(int npcId) {
tasks.put(npcId, ThreadPoolManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (objects.containsKey(npcId)) {
// Rift remove
if (rifts.containsKey(objects.get(npcId).getObjectId())) {
globalRiftPacket(rifts.get(objects.get(npcId).getObjectId()), false);
rifts.remove(objects.get(npcId).getObjectId());
}
objects.get(npcId).getController().onDelete();
objects.remove(npcId);
}
// Task remove
if (tasks != null && tasks.containsKey(npcId)) {
tasks.get(npcId).cancel(true);
tasks.remove(npcId);
}
log.info("KatalamUnderRiftService: scheduleDelete [npcId = " + npcId + "]");
}
}, RIFT_LIFETIME * 1000));
}
public void sendAnnounce(VisibleObject object) {
if (object.isSpawned()) {
WorldMapInstance instance = object.getPosition().getMapRegion().getParent();
instance.doOnAllPlayers(new Visitor<Player>() {
@Override
public void visit(Player player) {
if (player.isSpawned()) {
PacketSendUtility.sendMessage(player, "Появился тоннель ведущий в Подземный Каталам.");
}
}
});
}
}
public static KatalamUnderRiftService getInstance() {
return KatalamUnderRiftService.SingletonHolder.instance;
}
private static class SingletonHolder {
protected static final KatalamUnderRiftService instance = new KatalamUnderRiftService();
}
}
Код:
/*
* M.O.G. Devs Team
* www.mmorpg-onlinegames.ru
* Teg's {/aiononline, /eveonline}
*/
package com.mog.gameserver.model.rift;
/**
* @author Dision
*/
public class RiftList {
private int objectId = 0;
private int worldId = 0;
private float x = 0;
private float y = 0;
private float z = 0;
public RiftList(int objectId, int worldId, float x, float y, float z) {
this.objectId = objectId;
this.worldId = worldId;
this.x = x;
this.y = y;
this.z = z;
}
public int getObjectId() {
return objectId;
}
public void setObjectId(int objectId) {
this.objectId = objectId;
}
public int getWorldId() {
return worldId;
}
public void setWorldId(int worldId) {
this.worldId = worldId;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public float getZ() {
return z;
}
public void setZ(float z) {
this.z = z;
}
}
Код:
/*
* SM_RIFT_ANNOUNCE
*/
package com.mog.gameserver.network.aion.serverpackets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mog.gameserver.controllers.RVController;
import com.mog.gameserver.network.aion.AionConnection;
import com.mog.gameserver.network.aion.AionServerPacket;
import javolution.util.FastMap;
/**
* @author Sweetkr, Dision
*/
public class SM_RIFT_ANNOUNCE extends AionServerPacket {
private static final Logger log = LoggerFactory.getLogger(SM_RIFT_ANNOUNCE.class);
private int actionId;
private RVController rift;
private FastMap<Integer, Integer> rifts;
private int objectId;
private float x, y, z;
private boolean type;
public SM_RIFT_ANNOUNCE(FastMap<Integer, Integer> rifts) {
this.actionId = 0;
this.rifts = rifts;
}
public SM_RIFT_ANNOUNCE(RVController rift, boolean isMaster) {
this.rift = rift;
this.actionId = isMaster ? 2 : 3;
this.type = true;
}
public SM_RIFT_ANNOUNCE(int actionId) {
this.actionId = actionId;
}
public SM_RIFT_ANNOUNCE(int actionId, int objectId) {
this.actionId = actionId;
this.objectId = objectId;
}
public SM_RIFT_ANNOUNCE(int objectId, float x, float y, float z, boolean isMaster) {
this.objectId = objectId;
this.x = x;
this.y = y;
this.z = z;
this.actionId = isMaster ? 2 : 3;
this.type = false;
}
/**
* {@inheritDoc}
*/
@Override
protected void writeImpl(AionConnection con) {
switch (actionId) {
case 0: // announce
writeH(0x39); // 5.6
writeC(actionId);
for (int value : rifts.values()) {
writeD(value);
}
break;
case 1:
writeH(0x09); // 0x09
writeC(actionId);
writeD(0x01);
writeD(0x01);
break;
case 2:
if (type) {
writeH(0x23); // 0x23
writeC(actionId);
writeD(rift.getOwner().getObjectId());
writeD(rift.getMaxEntries());
writeD(rift.getRemainTime());
writeD(rift.getMinLevel());
writeD(rift.getMaxLevel());
writeF(rift.getOwner().getX());
writeF(rift.getOwner().getY());
writeF(rift.getOwner().getZ());
writeC(rift.isVortex() ? 1 : 0); // red | blue
writeC(rift.isMaster() ? 1 : 0); // display | hide
}
else {
writeH(0x23); // 0x23
writeC(actionId);
writeD(objectId);
writeD(100);
writeD(((int) (System.currentTimeMillis() / 1000) + 3600) - (int) (System.currentTimeMillis() / 1000));
writeD(65);
writeD(75);
writeF(x);
writeF(y);
writeF(z);
writeC(1); // red | blue
writeC(1); // display | hide
}
break;
case 3:
if (type) {
writeH(0x0f); // 0x0f
writeC(actionId);
writeD(rift.getOwner().getObjectId());
writeD(rift.getUsedEntries());
writeD(rift.getRemainTime());
writeC(rift.isVortex() ? 1 : 0);
writeC(0); // unk
}
else {
writeH(0x0f); // 0x0f
writeC(actionId);
writeD(objectId);
writeD(100);
writeD(((int) (System.currentTimeMillis() / 1000) + 3600) - (int) (System.currentTimeMillis() / 1000));
writeC(1);
writeC(0); // unk
}
break;
case 4:
writeH(0x05);
writeC(actionId);
writeD(objectId);
break;
case 5:
writeH(0x05);
writeC(actionId);
writeC(0x00);
writeC(0x00);
writeC(0x00);
writeC(0x00);
break;
}
log.info("writeImpl RiftAnnounce packet count: 0x" + actionId);
}
}
Аи для сервиса
Код:
/*
* Direct portal katalam under
*/
package com.mog.gameserver.ai2.handlers.worlds.upheaval.f5Event;
import com.mog.gameserver.ai2.AIName;
import com.mog.gameserver.ai2.handlers.general.ActionItemNpcAI2;
import com.mog.gameserver.dataholders.DataManager;
import com.mog.gameserver.model.gameobjects.Creature;
import com.mog.gameserver.model.gameobjects.player.Player;
import com.mog.gameserver.model.gameobjects.player.RequestResponseHandler;
import com.mog.gameserver.model.templates.portal.PortalPath;
import com.mog.gameserver.model.templates.portal.PortalUse;
import com.mog.gameserver.network.aion.serverpackets.SM_QUESTION_WINDOW;
import com.mog.gameserver.services.teleport.PortalService;
import com.mog.gameserver.utils.PacketSendUtility;
/**
* M.O.G. Devs Team
* @author Dision
*/
@AIName("directportal_katalam_under")
public class DirectPortalKatalamUnderAI2 extends ActionItemNpcAI2 {
protected PortalUse portalUse;
@Override
protected void handleSpawned() {
super.handleSpawned();
portalUse = DataManager.PORTAL2_DATA.getPortalUse(getNpcId());
}
@Override
protected void handleUseItemFinish(Player player) {
RequestResponseHandler responseHandler = new RequestResponseHandler(getOwner()) {
@Override
public void acceptRequest(Creature requester, Player responder) {
if (portalUse != null) {
PortalPath portalPath = portalUse.getPortalPath(player.getRace());
if (portalPath != null) {
PortalService.port(portalPath, player, getObjectId());
}
}
}
@Override
public void denyRequest(Creature requester, Player responder) {
}
@Override
public void enterInstanceRequest(Creature requester, Player responder) {
}
};
boolean requested = player.getResponseRequester().putRequest(SM_QUESTION_WINDOW.STR_ASK_PASS_BY_DIRECT_PORTAL, responseHandler);
if (requested) {
PacketSendUtility.sendPacket(player, new SM_QUESTION_WINDOW(SM_QUESTION_WINDOW.STR_ASK_PASS_BY_DIRECT_PORTAL, 0, 0));
}
}
}
ДАТА
Добавляем в статик дату портал
C:\Server_AioN\AioN_5.8_MASTER_TEST\Game\data\static_data\npcs\npc_templates
HTML:
<npc_template npc_id="731631" level="65" name="Тоннель в подземный Каталам" name_id="466433" desc="ldf5_under_l_entrance_in01" rank="VETERAN" rating="NORMAL" race="ELYOS" height="2.0" tribe="FIELD_OBJECT_LIGHT" type="GENERAL" ai="directportal_katalam_under" adelay="2000" hpgauge="3">
<stats maxHp="200000" maxXp="5000" main_hand_attack="1500" main_hand_accuracy="1500" pdef="4000" mresist="1500" power="1500" evasion="1500" accuracy="1500"/>
<bound_radius front="0.5" side="0.7" upper="2.0"/>
<talk_info distance="5" delay="3"/>
</npc_template>
<npc_template npc_id="731632" level="65" name="Тоннель в подземный Каталам" name_id="466434" desc="ldf5_under_d_entrance_in01" rank="VETERAN" rating="NORMAL" race="ASMODIANS" height="2.0" tribe="FIELD_OBJECT_DARK" type="GENERAL" ai="directportal_katalam_under" adelay="2000" hpgauge="3">
<stats maxHp="200000" maxXp="5000" main_hand_attack="1500" main_hand_accuracy="1500" pdef="4000" mresist="1500" power="1500" evasion="1500" accuracy="1500"/>
<bound_radius front="0.5" side="0.7" upper="2.0"/>
<talk_info distance="5" delay="3"/>
</npc_template>
C:\Server_AioN\AioN_5.8_MASTER_TEST\Game\data\static_data\portals
HTML:
portal_loc
<!-- Подземный каталам -->
<portal_loc world_id="210090000" loc_id="2100900" x="688.61" y="709.18" z="514.87" h="119"/> <!-- Вход L -->
<portal_loc world_id="220100000" loc_id="2201000" x="688.61" y="709.18" z="514.87" h="119"/> <!-- Вход D -->
<portal_loc world_id="210090000" loc_id="2100901" x="292.50" y="688.08" z="562.41" h="59"/> <!-- 1-й гарнизон Раты L -->
<portal_loc world_id="220100000" loc_id="2201001" x="292.50" y="688.08" z="562.41" h="59"/> <!-- 1-й гарнизон Раты D -->
<portal_loc world_id="110010000" loc_id="1100108" x="1317.04" y="1512.10" z="568.10" h="119"/> <!-- Выход L -->
<portal_loc world_id="120010000" loc_id="1200110" x="1681.02" y="1400.54" z="195.37" h="59"/> <!-- Выход D -->
portal_template2
<!-- 4.8 Подземный Каталам (Вход) L -->
<portal_use npc_id="731631">
<portal_path loc_id="2100900">
<portal_req min_level="10"/>
</portal_path>
</portal_use>
<!-- 4.8 Подземный Каталам (Вход) D -->
<portal_use npc_id="731632">
<portal_path loc_id="2201000">
<portal_req min_level="10"/>
</portal_path>
</portal_use>
<!-- 4.8 Подземный Каталам (Выход) L -->
<portal_use npc_id="731633">
<portal_path loc_id="1100108">
<portal_req min_level="10"/>
</portal_path>
</portal_use>
<!-- 4.8 Подземный Каталам (Выход) D -->
<portal_use npc_id="731634">
<portal_path loc_id="1200110">
<portal_req min_level="10"/>
</portal_path>
</portal_use>
<!-- 4.8 1-й гарнизон Раты L -->
<portal_use npc_id="731635">
<portal_path loc_id="2100901">
<portal_req min_level="10"/>
</portal_path>
</portal_use>
<!-- 4.8 1-й гарнизон Раты D -->
<portal_use npc_id="731636">
<portal_path loc_id="2201001">
<portal_req min_level="10"/>
</portal_path>
</portal_use>
