查看: 743|回復: 5

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

[複製鏈接]

9

主題

10

帖子

300

金錢

哥布林

Rank: 3Rank: 3

威望
0
精華
0
貢獻
0
鑽石
0
閱讀權限
30
積分
310
在線時間
5 小時
相冊
0
日誌
0
好友
0
發表於 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














上一篇︰境界380 時間軸 賺點小金幣
下一篇︰分享l1j降板182 功能齊全 內核穩定

322

主題

1574

帖子

2萬

金錢

巴列斯

Rank: 10Rank: 10Rank: 10

威望
12
精華
0
貢獻
0
鑽石
0
閱讀權限
60
積分
24830
在線時間
1259 小時
相冊
0
日誌
0
好友
2

最佳新人

發表於 2025-11-19 18:57 | 顯示全部樓層
:)

感謝分享~~~

回復 支持 反對

使用道具 舉報

66

主題

162

帖子

5609

金錢

火焰之影

Rank: 8Rank: 8

威望
0
精華
0
貢獻
0
鑽石
0
閱讀權限
50
積分
5771
在線時間
78 小時
相冊
0
日誌
0
好友
0
發表於 2025-11-21 20:51 | 顯示全部樓層
很厲害耶,連這個都搞出來

回復 支持 反對

使用道具 舉報

7

主題

282

帖子

4103

金錢

暗殺軍王.史雷佛

Rank: 8Rank: 8

威望
0
精華
0
貢獻
0
鑽石
0
閱讀權限
45
積分
4385
在線時間
248 小時
相冊
0
日誌
0
好友
0
發表於 2025-11-21 21:04 | 顯示全部樓層
請教大大 知道 符石欄位的封包嗎? 日版380的 裝備了三個符石 還是顯示最左邊的一個欄位

回復 支持 反對

使用道具 舉報

2

主題

68

帖子

2989

金錢

暗殺軍王.史雷佛

Rank: 8Rank: 8

威望
0
精華
0
貢獻
0
鑽石
0
閱讀權限
45
積分
3057
在線時間
93 小時
相冊
0
日誌
0
好友
0
發表於 2025-11-25 23:21 | 顯示全部樓層
受教了謝謝

[發帖際遇]: 一個袋子砸在了 Yang0506 頭上,Yang0506 賺了 2 金錢. 幸運榜 / 衰神榜
回復 支持 反對

使用道具 舉報

85

主題

201

帖子

1萬

金錢

巨蟻女皇

Rank: 9Rank: 9Rank: 9

威望
0
精華
0
貢獻
0
鑽石
0
閱讀權限
55
積分
12923
在線時間
91 小時
相冊
0
日誌
0
好友
0
發表於 2026-3-3 23:20 | 顯示全部樓層
感謝大神無私分享.受益良多.

回復 支持 反對

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 註冊會員

本版積分規則

天堂私服列表

45客服

Archiver| 45天堂私服論壇   分享到微博! 分享到臉書! 分享到噗浪! 分享到維特! 分享到Google+! 分享到LINE!

45天堂私服發佈站 ©    天堂私服架設教學  提供最新天堂私服最新資訊

流量最高、品質最好、服務最優、玩家首選、最新天堂私服資訊,都在45天堂私服發佈站.    免責聲明

Sitetag
line客服聯繫
掃一掃二碼
Line客服聯繫
24H專人回覆
返回頂部 返回列表