血盟穿雲箭 隊伍穿雲箭 聯盟穿雲箭 源代碼分享+解析 (免....
本帖最後由 socket@618 於 2025-11-19 00:31 編輯----------------------------血盟穿雲箭-----------------------------
第一步:在Item_etcitem下創建類ClanTelete
第二部:寫入代碼
package com.lineage.data.item_etcitem;
import com.lineage.data.executor.ItemExecutor;
import com.lineage.server.datatables.CallClanMapTable;
import com.lineage.server.datatables.MapsTable;
import com.lineage.server.model.L1CastleLocation;
import com.lineage.server.model.L1Object;
import com.lineage.server.model.Instance.L1ItemInstance;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.serverpackets.S_GreenMessage;
import com.lineage.server.serverpackets.S_Message_YN;
import com.lineage.server.serverpackets.S_ServerMessage;
import com.lineage.server.serverpackets.S_SkillSound;
import com.lineage.server.serverpackets.S_SystemMessage;
import com.lineage.server.world.L1World;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ClanTelete extends ItemExecutor {
private static final Log _log = LogFactory.getLog(ClanTelete.class);
private ClanTelete() {
// TODO Auto-generated constructor stub
}
public static ItemExecutor get() {
return new ClanTelete();
}
@Override
public void execute(int[] data, L1PcInstance pc, L1ItemInstance item) {
try {
// 例外狀況:物件為空
if (item == null) {
return;
}
// 例外狀況:人物為空
if (pc == null) {
return;
}
final boolean castle_area = L1CastleLocation.checkInAllWarArea(
pc.getX(), pc.getY(), pc.getMapId());//這裡是判定PC是否在城戰旗幟內false代表不在true代表在
for (L1Object obj : L1World.getInstance().getVisibleObjects(pc,-1)){//這裡代表PC畫面內
if(obj instanceof L1PcInstance){
final L1PcInstance tgpc = (L1PcInstance) obj;
if(tgpc.getClanid()!=0 && pc.getClanid() != tgpc.getClanid()){//這裡代表畫面內是否有其他血盟玩家
pc.sendPackets(new S_ServerMessage(166,"畫面內有其他血盟成員無法使用"));
return;
}
}
}
if (castle_area) {
pc.sendPackets(new S_SystemMessage("你不能在這裡使用。"));
return;
}
if (pc.getClanid() == 0 || pc.getClan() == null){
pc.sendPackets(new S_SystemMessage("你還沒有血盟不能使用。"));
return;
}
if (pc.getMapId() == 998) {
pc.sendPackets(new S_SystemMessage("此地圖不能使用。"));
return;
}
if (CallClanMapTable.get().IsNoMap(pc.getMapId())){
pc.sendPackets(new S_SystemMessage("此地圖不能使用。"));
return;
}
if (pc.getClan().getOnlineClanMemberSize() < 2){
pc.sendPackets(new S_SystemMessage("沒有其他血盟成員在線。"));
return;
}
int mapid = pc.getMapId();
pc.sendPacketsAll(new S_SkillSound(pc.getId(), 6780));
L1World.getInstance().broadcastPacketToAll(new S_GreenMessage("\\fH玩家\\fM【" + pc.getName() +"\\fM】\\fH在\\fM【" + MapsTable.getInstance().getMapName1(mapid) + "\\fM】\\fH使用了一隻穿雲箭,血盟成員來相見。"));
pc.getInventory().removeItem(item, 1);
for(final L1PcInstance tagpc : pc.getClan().getOnlineClanMember()){//這裡代表 循環血盟玩家
if (tagpc.getId() != pc.getId()){//這裡代表 血盟其他玩家 不包含自己
tagpc.setClanTeletePcId(pc.getId());//發送給血盟玩家自己的objid
tagpc.sendPackets(new S_Message_YN(4531, pc.getName()));//發送指令 這裡就要走到C_Attr 下的case 4531:文字對應String-c.tbl的4529行
}
}
} catch (final Exception e) {
_log.error(e.getLocalizedMessage(), e);
}
}
}
註明 case 4531:這裡代表 yes/no 是否接受傳送的控制封包 那麼我們繼續往下看
在類別 C_Attr下 添加代碼
case 4531: c = this.readC(); if (c == 1){//這裡代表 被發送訊息的血盟成員 選擇了yes callClantelete(pc);//這裡代表執行傳送 } break;那麼我們繼續來看 如何傳送的在類別 C_Attr下 添加代碼 private void callClantelete(final L1PcInstance pc) { final L1Object objpc = L1World.getInstance().findObject(pc.getClanTeletePcId());//這裡代表先判定發送者的obj
pc.setClanTeletePcId(0);//清空objid
if (pc.getTradeID() != 0) {
pc.sendPackets(new S_SystemMessage("交易中無法傳送"));
return;
}
if (pc.isDead()){
pc.sendPackets(new S_SystemMessage("你已經死亡"));
return;
}
if (objpc == null){
pc.sendPackets(new S_SystemMessage("對方已經不在線上"));
return;
}
if (pc.getMapId() == 99){
pc.sendPackets(new S_SystemMessage("你不能過去"));
return;
}
if (pc.getSkillEffectTimeSec(L1SkillId.GRACE_AVTAR) > 0){
pc.sendPackets(new S_SystemMessage(String.format("\\F2你現在無法移動 沖暈倒計時%d秒", pc.getSkillEffectTimeSec(L1SkillId.GRACE_AVTAR))));
return;
}
if (pc.getSkillEffectTimeSec(L1SkillId.SHOCK_STUN) > 0){
pc.sendPackets(new S_SystemMessage(String.format("\\F2你現在無法移動 沖暈倒計時%d秒", pc.getSkillEffectTimeSec(L1SkillId.SHOCK_STUN))));
return;
}
if (pc.getSkillEffectTimeSec(L1SkillId.EARTH_BIND) > 0){
pc.sendPackets(new S_SystemMessage(String.format("\\F2你現在無法移動 大地屏障倒計時%d秒", pc.getSkillEffectTimeSec(L1SkillId.EARTH_BIND))));
return;
}
if (pc.getSkillEffectTimeSec(L1SkillId.ICE_LANCE) > 0){
pc.sendPackets(new S_SystemMessage(String.format("\\F2你現在無法移動 冰矛圍籬倒計時%d秒", pc.getSkillEffectTimeSec(L1SkillId.ICE_LANCE))));
return;
}
if (pc.getSkillEffectTimeSec(L1SkillId.FOG_OF_SLEEPING) > 0){
pc.sendPackets(new S_SystemMessage(String.format("\\F2你現在無法移動 沉睡倒計時%d秒", pc.getSkillEffectTimeSec(L1SkillId.FOG_OF_SLEEPING))));
return;
}
if (!pc.getMap().isEscapable()) {
// 647 這附近的能量影響到瞬間移動。在此地無法使用瞬間移動。
pc.sendPackets(new S_ServerMessage(647));
return;
}
if (objpc instanceof L1PcInstance){//這裡代表 obj是pc 也就是指是玩家
final L1PcInstance callClanPc = (L1PcInstance)objpc;//這裡代表 可以準確指定是PC
boolean isInWarArea = false;
final int castleId = L1CastleLocation.getCastleIdByArea(callClanPc);
if (castleId != 0){
if (WarTimeController.getInstance()
.isNowWar(castleId)) {
isInWarArea = true;
}
}
final short mapId = callClanPc.getMapId();
if (CallClanMapTable.get().IsNoMap(mapId) || isInWarArea){
pc.sendPackets(new S_ServerMessage(629));
return;
}
final L1Location newLocation = callClanPc.getLocation().randomLocation(3,
true);
if (newLocation != null){
final int newX = newLocation.getX();
final int newY = newLocation.getY();
final short mapId0 = (short) newLocation.getMapId();
L1Teleport.teleport(pc, newX,newY, mapId0, pc.getHeading(), true,0);
}else{
L1Teleport.teleport(pc, callClanPc.getX(),callClanPc.getY(), callClanPc.getMapId(), pc.getHeading(), true,L1Teleport.CALL_CLAN);//沒坐標重疊
}
}
}以上就是血盟穿雲箭的寫法 以及詳細說明 希望新手可以看得懂!--------------------------隊伍穿雲箭------------------------第一步:在Item_etcitem下創建類PartyTelete
第二部:寫入代碼package com.lineage.data.item_etcitem;import com.lineage.data.executor.ItemExecutor;import com.lineage.server.datatables.CallClanMapTable;import com.lineage.server.datatables.MapsTable;import com.lineage.server.model.L1CastleLocation;import com.lineage.server.model.L1Object;import com.lineage.server.model.Instance.L1ItemInstance;import com.lineage.server.model.Instance.L1PcInstance;import com.lineage.server.serverpackets.S_GreenMessage;import com.lineage.server.serverpackets.S_Message_YN;import com.lineage.server.serverpackets.S_ServerMessage;import com.lineage.server.serverpackets.S_SkillSound;import com.lineage.server.serverpackets.S_SystemMessage;import com.lineage.server.world.L1World;public class PartyTelete extends ItemExecutor { /** * */ private PartyTelete() { // TODO Auto-generated constructor stub } public static ItemExecutor get() { return new PartyTelete(); } /** * 組隊穿雲箭 * @param data 參數 * @param pc 執行者 * @param item 物件 */ @Override public void execute(final int[] data, final L1PcInstance pc, final L1ItemInstance item) { // 例外狀況:物件為空 if (item == null) { return; } // 例外狀況:人物為空 if (pc == null) { return; } final boolean castle_area = L1CastleLocation.checkInAllWarArea( pc.getX(), pc.getY(), pc.getMapId()); if (castle_area) { pc.sendPackets(new S_SystemMessage("你不能在這裡使用。")); return; } if (pc.getMapId() == 998) { pc.sendPackets(new S_SystemMessage("此地圖不能使用。")); return; } if (CallClanMapTable.get().IsNoMap(pc.getMapId())){ pc.sendPackets(new S_SystemMessage("此地圖不能使用。")); return; } if (!pc.isInParty()) { pc.sendPackets(new S_SystemMessage("\\fY目前沒有組隊,因此無法使用")); return; } for (L1Object obj : L1World.getInstance().getVisibleObjects(pc,-1)){ if(obj instanceof L1PcInstance){ final L1PcInstance tgpc = (L1PcInstance) obj; if(tgpc.getClanid()!=0 && pc.getClanid() != tgpc.getClanid()){ pc.sendPackets(new S_ServerMessage(166,"畫面內有其他血盟成員無法使用")); return; } } } for (L1PcInstance find_pc : pc.getParty().getMembers()) {//這裡代表 循環隊伍成員 // 組隊與人員 if (find_pc.getId() != pc.getId()) {//這裡確認隊伍成員 不包含PC find_pc.setClanTeletePcId(pc.getId());//這裡代表發送PC的OBJID // 729 盟主正在呼喚你,你要接受他的呼喚嗎?(Y/N) find_pc.sendPackets(new S_Message_YN(4531, pc.getName()));//發送指令 } } int mapid = pc.getMapId(); pc.sendPacketsAll(new S_SkillSound(pc.getId(), 6780)); L1World.getInstance().broadcastPacketToAll(new S_GreenMessage("\\fH玩家\\fM【" + pc.getName() +"\\fM】\\fH在\\fM【" + MapsTable.getInstance().getMapName1(mapid) + "\\fM】\\fH使用了一隻組隊穿雲箭,隊伍成員來相見。")); pc.getInventory().removeItem(item, 1); }}以上就是隊伍穿雲箭的寫法 可能會有瑕疵 希望不要噴。。之後的代碼 和血盟穿雲箭是一個性質 也可以單獨添加 4532 換一套文字輸出yes/no------------------------------聯盟穿雲箭-----------------------------
第一步:在Item_etcitem下創建類ClanAllianceTelete
第二部:寫入代碼package com.lineage.data.item_etcitem;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.lineage.data.executor.ItemExecutor;
import com.lineage.server.WarTimeController;
import com.lineage.server.datatables.CallClanMapTable;
import com.lineage.server.datatables.MapsTable;
import com.lineage.server.datatables.lock.ClanAllianceReading;
import com.lineage.server.model.L1Alliance;
import com.lineage.server.model.L1CastleLocation;
import com.lineage.server.model.L1Clan;
import com.lineage.server.model.L1Object;
import com.lineage.server.model.Instance.L1ItemInstance;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.serverpackets.S_GreenMessage;
import com.lineage.server.serverpackets.S_Message_YN;
import com.lineage.server.serverpackets.S_SkillSound;
import com.lineage.server.serverpackets.S_SystemMessage;
import com.lineage.server.world.L1World;
/**
* 聯盟穿雲箭
* BY Socket
* @author Administrator
*
*/
public class ClanAllianceTelete extends ItemExecutor {
private static final Log _log = LogFactory.getLog(ClanAllianceTelete.class);
/**
*
*/
private ClanAllianceTelete() {
// TODO Auto-generated constructor stub
}
public static ItemExecutor get() {
return new ClanAllianceTelete();
}
/**
* 道具物件執行
* @param data 參數
* @param pc 執行者
* @param item 物件
*/
@Override
public void execute(final int[] data, final L1PcInstance pc, final L1ItemInstance item) {
try {
// 例外狀況:物件為空
if (item == null) {
return;
}
// 例外狀況:人物為空
if (pc == null) {
return;
}
final boolean castle_area = L1CastleLocation.checkInAllWarArea(
pc.getX(), pc.getY(), pc.getMapId());
if (castle_area) {
pc.sendPackets(new S_SystemMessage("你不能在這裡使用。"));
return;
}
if (pc.getClanid() == 0) {
pc.sendPackets(new S_SystemMessage("\\fY無血盟狀態無法使用"));
return;
}
if (pc.getMapId() == 998) {
pc.sendPackets(new S_SystemMessage("此地圖不能使用。"));
return;
}
if (CallClanMapTable.get().IsNoMap(pc.getMapId())){
pc.sendPackets(new S_SystemMessage("此地圖不能使用。"));
return;
}
for (L1Object obj : L1World.getInstance().getVisibleObjects(pc,-1)){//同畫面內判定目標
if(obj instanceof L1PcInstance){//如果目標是PC
final L1PcInstance tgpc = (L1PcInstance) obj;//轉換目標PC調用
L1Clan clan = L1World.getInstance().getClan(pc.getClanname());//判定PC血盟
final L1Alliance alliance = ClanAllianceReading.get().getAlliance(
clan.getClanId());//判定PC聯盟狀態
if (tgpc.getClanid() != 0) {//目標PC是否有血盟 == 0 (無) !=0(有)
L1Clan clan1 = L1World.getInstance().getClan(tgpc.getClanname());//目標PC血盟
final L1Alliance alliance1 = ClanAllianceReading.get().getAlliance(
clan1.getClanId());//目標PC聯盟狀態
if (alliance1 == null || alliance.getOrderId() != alliance1.getOrderId()) {
pc.sendPackets(new S_SystemMessage("\\fY畫面中有其他血盟成員,導致無法使用"));
return;
}
}
if (pc.getClanid() != 0 && tgpc.getClanid() == 0) {
pc.sendPackets(new S_SystemMessage("\\fY畫面中有其他玩家,導致無法使用"));
return;
}
}
}
boolean isNowWar = false;
int castleId = 0;
castleId = L1CastleLocation.getCastleIdByArea(pc);
if (castleId != 0) {
isNowWar = WarTimeController.getInstance().isNowWar(castleId);
}
if (isNowWar){
pc.sendPackets(new S_SystemMessage("城戰旗幟內無法使用."));
return;
}
L1Clan clan = L1World.getInstance().getClan(pc.getClanname());
final L1Alliance alliance = ClanAllianceReading.get().getAlliance(
clan.getClanId());//這裡是判定聯盟
if (alliance == null) {
pc.sendPackets(new S_SystemMessage("您還沒有加入聯盟。"));
return;
}
int mapid = pc.getMapId();
if (alliance != null) {//如果擁有聯盟執行下面代碼
alliance.sendPacketsAll1(pc.getName(), new S_Message_YN(4531,pc.getName()),pc);//發送給聯盟成員 不包含PC自己
pc.sendPacketsAll(new S_SkillSound(pc.getId(), 6780));
L1World.getInstance().broadcastPacketToAll(new S_GreenMessage("\\fH玩家\\fM【" + pc.getName() +"\\fM】\\fH在\\fM【" + MapsTable.getInstance().getMapName1(mapid) + "\\fM】\\fH使用了一隻穿雲箭,血盟成員來相見。"));
}
pc.getInventory().removeItem(item, 1);
} catch (final Exception e) {
_log.error(e.getLocalizedMessage(), e);
}
}
}
下面我要提供一下sendPacketsAll1的代碼
/**
* 對所有締結血盟線上成員發送封包 (遮蔽特定玩家)
* 聯盟穿雲箭指定
* @param excludingPcName
* @param packet
* @param pc
*/
public void sendPacketsAll1(final String excludingPcName,
final ServerBasePacket packet, L1PcInstance pc) {
try {
for (final L1Clan clan : totalList) {
// 血盟不存在
if (clan == null
|| L1World.getInstance().getClan(clan.getClanName()) == null) {
continue;
}
// 血盟線上成員
for (final L1PcInstance listner : clan.getOnlineClanMember()) {
listner.setClanTeletePcId(pc.getId());
// //不包含自己
if (listner.getName().contains(excludingPcName)) {
continue;
}
listner.sendPackets(packet);
}
}
} catch (final Exception e) {
_log.error(e.getLocalizedMessage(), e);
}
}
好了 以上就是 三種穿雲箭的寫法 以及說明
大家一定要記得在l1pci中寫入引用哦
private int _clanteleteId = 0;
public void setClanTeletePcId(final int id) {
_clanteleteId = id;
}
public int getClanTeletePcId() {
return _clanteleteId;
}
這段引用是要調用發送者的Objid方便 被傳送的玩家 找到發送者的坐標判定發送者使用
代碼寫的 不夠規矩 不要見笑!
如果有朋友需要修復核心BUG 提前準備any遠端軟件 和源代碼 和EC
LineID:socket618
:):):):):):):):):):):)
感謝分享~~~ 很厲害耶,連這個都搞出來 請教大大 知道 符石欄位的封包嗎? 日版380的 裝備了三個符石 還是顯示最左邊的一個欄位 受教了謝謝 感謝大神無私分享.受益良多.
頁:
[1]