socket@618 發表於 2025-11-19 00:26

血盟穿雲箭 隊伍穿雲箭 聯盟穿雲箭 源代碼分享+解析 (免....

本帖最後由 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










天堂迷 發表於 2025-11-19 18:57

:):):):):):):):):):):)

感謝分享~~~

skyalcon 發表於 2025-11-21 20:51

很厲害耶,連這個都搞出來

drt78113 發表於 2025-11-21 21:04

請教大大 知道 符石欄位的封包嗎? 日版380的 裝備了三個符石 還是顯示最左邊的一個欄位

Yang0506 發表於 2025-11-25 23:21

受教了謝謝

liao0825 發表於 2026-3-3 23:20

感謝大神無私分享.受益良多.
頁: [1]
查看完整版本: 血盟穿雲箭 隊伍穿雲箭 聯盟穿雲箭 源代碼分享+解析 (免....