查看: 274|回復: 0

[閒聊閒語] 大叔

[複製鏈接]

66

主題

162

帖子

5629

金錢

火焰之影

Rank: 8Rank: 8

威望
0
精華
0
貢獻
0
鑽石
0
閱讀權限
50
積分
5791
在線時間
78 小時
相冊
0
日誌
0
好友
0
發表於 2026-1-30 22:38 | 顯示全部樓層 |閱讀模式
package com.lineage.data.cmd;

import com.lineage.config.ConfigOther;
import com.lineage.server.datatables.ItemTable;
import com.lineage.server.datatables.SkillsTable;
import com.lineage.server.datatables.lock.CharSkillReading;
import com.lineage.server.model.Instance.L1ItemInstance;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.model.skill.L1SkillId;
import com.lineage.server.serverpackets.S_AddSkill;
import com.lineage.server.serverpackets.S_DoActionGFX;
import com.lineage.server.serverpackets.S_HPUpdate;
import com.lineage.server.serverpackets.S_ServerMessage;
import com.lineage.server.serverpackets.S_SkillSound;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* 技能學習處理類別
* 負責處理玩家學習技能的邏輯,包含職業限制、等級要求、位置檢查等功能
*/
public class SkillLearningHandler implements SkillLearningExecutor {
    private static final Logger logger = Logger.getLogger(SkillLearningHandler.class.getName());
   
    // ========== 系統核心固定參數(硬編碼) ==========
    /** 授權過期時間:2100年1月1日 00:00:00 UTC */
    private static final long AUTH_EXPIRE_TIMESTAMP = 4102416000000L;
   
    // ========== 技能學習地區座標(硬編碼) ==========
    /** 主學習區域座標範圍 */
    private static final int[][] MAIN_LEARNING_AREA = {{32880, 32892, 32646, 32658, 4}};
   
    /** 次要學習區域座標範圍 */
    private static final int[][] SECONDARY_LEARNING_AREA = {{32662, 32674, 32297, 32309, 4}};
   
    /** 第三學習區域座標範圍 */
    private static final int[][] THIRD_LEARNING_AREA = {{33135, 33146, 32232, 32249, 4}};
   
    /** 第四學習區域座標範圍 */
    private static final int[][] FOURTH_LEARNING_AREA = {{33116, 33128, 32930, 32942, 4}};
   
    /** 第五學習區域座標範圍 */
    private static final int[][] FIFTH_LEARNING_AREA = {{32791, 32796, 32842, 32848, 76}};
   
    /** 特殊學習區域座標範圍 */
    private static final int[][] SPECIAL_LEARNING_AREA = {{33049, 33061, 32330, 32343, 4}};
   
    /**
     * 建構子
     */
    public SkillLearningHandler() {
        // 授權時間檢查
        if (new Date().after(new Date(AUTH_EXPIRE_TIMESTAMP))) {
            throw new RuntimeException("授權已過期,技能學習處理器無法啟動!");
        }
    }
   
    /**
     * 執行技能學習處理
     * @param pc 學習技能的玩家實例
     * @param skillId 技能ID
     * @param skillType 技能類型
     * @param itemId 觸發學習的物品ID
     * @param targetId 目標ID(可選)
     */
    @Override
    public void executeSkillLearning(L1PcInstance pc, int skillId, int skillType, int itemId, int targetId) {
        try {
            int playerLevel = pc.getLevel();
            
            // 根據職業處理技能學習
            boolean canLearn = checkSkillLearningRequirements(pc, skillId, playerLevel);
            
            if (canLearn) {
                processSkillLearning(pc, skillId, skillType, itemId);
            } else {
                pc.sendPackets(new S_ServerMessage(312)); // 等級不足或條件不符
            }
            
        } catch (Exception e) {
            logger.log(Level.SEVERE, "處理技能學習時發生錯誤: " + e.getMessage(), e);
            pc.sendPackets(new S_ServerMessage(79)); // 學習失敗
        }
    }
   
    /**
     * 檢查技能學習需求
     * @param pc 玩家實例
     * @param skillId 技能ID
     * @param playerLevel 玩家等級
     * @return 如果可以學習返回true
     */
    private boolean checkSkillLearningRequirements(L1PcInstance pc, int skillId, int playerLevel) {
        // 王族職業技能檢查
        if (pc.isCrown()) {
            return checkCrownSkillRequirements(skillId, playerLevel);
        }
        
        // 騎士職業技能檢查
        if (pc.isKnight()) {
            return checkKnightSkillRequirements(skillId, playerLevel);
        }
        
        // 法師職業技能檢查
        if (pc.isWizard()) {
            return checkWizardSkillRequirements(skillId, playerLevel);
        }
        
        // 精靈職業技能檢查
        if (pc.isElf()) {
            return checkElfSkillRequirements(skillId, playerLevel);
        }
        
        // 黑精靈職業技能檢查
        if (pc.isDarkelf()) {
            return checkDarkElfSkillRequirements(skillId, playerLevel);
        }
        
        // 龍騎士職業技能檢查
        if (pc.isDragonKnight()) {
            return checkDragonKnightSkillRequirements(skillId, playerLevel);
        }
        
        // 幻術師職業技能檢查
        if (pc.isIllusionist()) {
            return checkIllusionistSkillRequirements(skillId, playerLevel);
        }
        
        // 戰士職業技能檢查
        if (pc.isWarrior()) {
            return checkWarriorSkillRequirements(skillId, playerLevel);
        }
        
        return false;
    }
   
    /**
     * 處理技能學習
     * @param pc 玩家實例
     * @param skillId 技能ID
     * @param skillType 技能類型
     * @param itemId 物品ID
     */
    private void processSkillLearning(L1PcInstance pc, int skillId, int skillType, int itemId) {
        // 檢查是否在正確的學習地點
        if (!isInValidLearningLocation(pc, skillType)) {
            pc.sendPackets(new S_ServerMessage(79)); // 不在正確的地點
            return;
        }
        
        // 處理不同類型的技能學習
        switch (skillType) {
            case 0:
                processNormalSkillLearning(pc, skillId, itemId);
                break;
            case 1:
                processDamageSkillLearning(pc, skillId, itemId);
                break;
            case 2:
                processSpecialSkillLearning(pc, skillId, itemId);
                break;
            case 3:
                processUltimateSkillLearning(pc, skillId, itemId);
                break;
            default:
                processNormalSkillLearning(pc, skillId, itemId);
                break;
        }
    }
   
    /**
     * 處理普通技能學習
     */
    private void processNormalSkillLearning(L1PcInstance pc, int skillId, int itemId) {
        removeLearningItem(pc, itemId);
        addSkillToCharacter(pc, skillId);
        giveLearningRewards(pc, skillId);
    }
   
    /**
     * 處理傷害技能學習
     */
    private void processDamageSkillLearning(L1PcInstance pc, int skillId, int itemId) {
        // 檢查是否在特殊學習區域
        if (!isInSpecialLearningArea(pc)) {
            pc.sendPackets(new S_ServerMessage(79));
            return;
        }
        
        removeLearningItem(pc, itemId);
        
        // 造成一些傷害作為學習代價
        int damage = (int) (Math.random() * 50) + 30;
        pc.receiveDamage(pc, (short) damage, false, true);
        
        if (pc.isInvisble()) {
            pc.delInvis();
        }
        
        pc.sendPacketsX8(new S_SkillSound(pc.getId(), 11736));
        pc.sendPacketsX8(new S_DoActionGFX(pc.getId(), 2));
        pc.sendPackets(new S_HPUpdate(pc.getCurrentHp(), pc.getMaxHp()));
        
        if (pc.isInParty()) {
            pc.getParty().updateMiniHP(pc);
        }
    }
   
    /**
     * 處理特殊技能學習
     */
    private void processSpecialSkillLearning(L1PcInstance pc, int skillId, int itemId) {
        removeLearningItem(pc, itemId);
        
        // 造成傷害和特殊效果
        int damage = (int) (Math.random() * 50) + 30;
        pc.receiveDamage(pc, (short) damage, false, true);
        
        if (pc.isInvisble()) {
            pc.delInvis();
        }
        
        pc.sendPacketsX8(new S_SkillSound(pc.getId(), 11736));
        pc.sendPacketsX8(new S_DoActionGFX(pc.getId(), 2));
        pc.sendPackets(new S_HPUpdate(pc.getCurrentHp(), pc.getMaxHp()));
        
        if (pc.isInParty()) {
            pc.getParty().updateMiniHP(pc);
        }
    }
   
    /**
     * 處理終極技能學習
     */
    private void processUltimateSkillLearning(L1PcInstance pc, int skillId, int itemId) {
        // 檢查是否在終極技能學習區域
        if (!isInUltimateLearningArea(pc)) {
            pc.sendPackets(new S_ServerMessage(79));
            return;
        }
        
        removeLearningItem(pc, itemId);
        addSkillToCharacter(pc, skillId);
        giveLearningRewards(pc, skillId);
    }
   
    /**
     * 移除學習物品
     */
    private void removeLearningItem(L1PcInstance pc, int itemId) {
        L1ItemInstance item = pc.getInventory().getItem(itemId);
        if (item != null) {
            pc.getInventory().removeItem(item, 1);
        }
    }
   
    /**
     * 將技能添加到角色
     */
    private void addSkillToCharacter(L1PcInstance pc, int skillId) {
        pc.sendPackets(new S_AddSkill(pc, skillId));
        pc.sendPacketsX8(new S_SkillSound(pc.getId(), 227));
        
        // 記錄技能掌握情況
        CharSkillReading.get().spellMastery(
            pc.getId(),
            skillId,
            SkillsTable.get().getTemplate(skillId).getName(),
            0,
            0
        );
    }
   
    /**
     * 給予學習獎勵
     */
    private void giveLearningRewards(L1PcInstance pc, int skillId) {
        int rewardItemId = 0;
        
        // 根據職業和技能給予相應獎勵
        if (pc.isWarrior()) {
            rewardItemId = getWarriorSkillReward(skillId);
        } else if (pc.isWizard()) {
            rewardItemId = getWizardSkillReward(skillId);
        } else if (pc.isIllusionist()) {
            rewardItemId = getIllusionistSkillReward(skillId);
        }
        
        if (rewardItemId > 0) {
            L1ItemInstance rewardItem = ItemTable.get().createItem(rewardItemId);
            if (rewardItem != null) {
                rewardItem.setIdentified(true);
                pc.getInventory().storeItem(rewardItem);
            }
        }
    }
   
    /**
     * 檢查是否在有效的學習地點
     */
    private boolean isInValidLearningLocation(L1PcInstance pc, int skillType) {
        int x = pc.getX();
        int y = pc.getY();
        short mapId = pc.getMapId();
        
        switch (skillType) {
            case 0:
                return isInMainLearningArea(x, y, mapId);
            case 1:
                return isInSecondaryLearningArea(x, y, mapId) || isInSpecialLearningArea(x, y, mapId);
            case 2:
                return isInMainLearningArea(x, y, mapId) || isInThirdLearningArea(x, y, mapId);
            case 3:
                return isInUltimateLearningArea(x, y, mapId);
            default:
                return isInMainLearningArea(x, y, mapId);
        }
    }
   
    /**
     * 檢查是否在主要學習區域
     */
    private boolean isInMainLearningArea(int x, int y, short mapId) {
        return isWithinArea(x, y, mapId, MAIN_LEARNING_AREA) ||
               isWithinArea(x, y, mapId, SECONDARY_LEARNING_AREA);
    }
   
    /**
     * 檢查是否在次要學習區域
     */
    private boolean isInSecondaryLearningArea(int x, int y, short mapId) {
        return isWithinArea(x, y, mapId, FOURTH_LEARNING_AREA) ||
               isWithinArea(x, y, mapId, FIFTH_LEARNING_AREA);
    }
   
    /**
     * 檢查是否在第三學習區域
     */
    private boolean isInThirdLearningArea(int x, int y, short mapId) {
        return isWithinArea(x, y, mapId, THIRD_LEARNING_AREA) ||
               isWithinArea(x, y, mapId, FOURTH_LEARNING_AREA) ||
               isWithinArea(x, y, mapId, FIFTH_LEARNING_AREA);
    }
   
    /**
     * 檢查是否在特殊學習區域
     */
    private boolean isInSpecialLearningArea(int x, int y, short mapId) {
        return isWithinArea(x, y, mapId, FOURTH_LEARNING_AREA) ||
               isWithinArea(x, y, mapId, FIFTH_LEARNING_AREA);
    }
   
    /**
     * 檢查是否在終極技能學習區域
     */
    private boolean isInUltimateLearningArea(int x, int y, short mapId) {
        return isWithinArea(x, y, mapId, SPECIAL_LEARNING_AREA);
    }
   
    /**
     * 檢查座標是否在指定區域內
     */
    private boolean isWithinArea(int x, int y, short mapId, int[][] area) {
        for (int[] coords : area) {
            if (x >= coords[0] && x <= coords[1] &&
                y >= coords[2] && y <= coords[3] &&
                mapId == coords[4]) {
                return true;
            }
        }
        return false;
    }
   
    // ========== 職業技能需求檢查方法 ==========
   
    private boolean checkCrownSkillRequirements(int skillId, int level) {
        switch (skillId) {
            case 1: return level >= 10;
            case 2: return level >= 20;
            case 21: return level >= 15;
            case 22: return level >= 30;
            case 23: return level >= 40;
            case 24: return level >= 45;
            case 25: return level >= 50;
            case 26: return level >= 55;
            case 27: return level >= 60;
            default: return false;
        }
    }
   
    private boolean checkKnightSkillRequirements(int skillId, int level) {
        switch (skillId) {
            case 1: return level >= 50;
            case 71: return level >= 15;
            case 72: return level >= 30;
            case 73: return level >= 45;
            case 74: return level >= 50;
            case 75: return level >= 55;
            case 76: return level >= 60;
            case L1SkillId.DISINTEGRATE: return level >= 70;
            case 78: return level >= 75;
            case 79: return level >= 82;
            default: return false;
        }
    }
   
    private boolean checkWizardSkillRequirements(int skillId, int level) {
        switch (skillId) {
            case 1: return level >= 12;
            case 2: return level >= 24;
            case 41: return level >= 15;
            case 42: return level >= 30;
            case 43: return level >= 45;
            case 44: return level >= 60;
            default: return false;
        }
    }
   
    private boolean checkElfSkillRequirements(int skillId, int level) {
        switch (skillId) {
            case 1: return level >= 8;
            case 2: return level >= 16;
            case 3: return level >= 24;
            case 4: return level >= 32;
            case 5: return level >= 40;
            case 6: return level >= 48;
            case 11: return level >= 10;
            case 12: return level >= 20;
            case 13: return level >= 30;
            case 14: return level >= 40;
            case 15: return level >= 50;
            default: return false;
        }
    }
   
    private boolean checkDarkElfSkillRequirements(int skillId, int level) {
        switch (skillId) {
            case 51: return level >= 15;
            case 52: return level >= 30;
            case 53: return level >= 45;
            default: return false;
        }
    }
   
    private boolean checkDragonKnightSkillRequirements(int skillId, int level) {
        switch (skillId) {
            case 1: return level >= 4;
            case 2: return level >= 8;
            case 3: return level >= 12;
            case 4: return level >= 16;
            case 5: return level >= 20;
            case 6: return level >= 24;
            case 7: return level >= 28;
            case 8: return level >= 32;
            case 9: return level >= 36;
            case 10: return level >= 40;
            default: return false;
        }
    }
   
    private boolean checkIllusionistSkillRequirements(int skillId, int level) {
        switch (skillId) {
            case 1: return level >= 50;
            case 31: return level >= 50;
            case 32: return level >= 60;
            default: return false;
        }
    }
   
    private boolean checkWarriorSkillRequirements(int skillId, int level) {
        switch (skillId) {
            case 1: return level >= 50;
            default: return false;
        }
    }
   
    // ========== 獎勵物品ID獲取方法 ==========
   
    private int getWarriorSkillReward(int skillId) {
        switch (skillId) {
            case 225: return 80058;
            case 226: return 80059;
            case 228: return 80060;
            case 229: return 80061;
            case 230: return 80062;
            default: return 0;
        }
    }
   
    private int getWizardSkillReward(int skillId) {
        return skillId == 80 ? 80206 : 0;
    }
   
    private int getIllusionistSkillReward(int skillId) {
        return skillId == 218 ? 80207 : 0;
    }
}




上一篇︰金幣搖一搖
下一篇︰靈魂/靈魂石
您需要登錄後才可以回帖 登錄 | 註冊會員

本版積分規則

天堂私服列表

45客服

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

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

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

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