AzerothCore 副本机制详解 – BOSS 技能实现 原创

温馨提示:
本文最后更新于 2026-04-02,已超过 2 天没有更新。 若文章内的图片失效(无法正常加载),请留言反馈或直接 联系我

副本是 WoW 的核心玩法之一,BOSS 战的设计直接影响玩家体验。本文深入讲解 AzerothCore 中副本机制和 BOSS 技能实现。

一、副本基础架构

1.1 副本类型

  • 5 人副本:普通/英雄难度
  • 10 人团队:普通/英雄难度
  • 25 人团队:普通/英雄难度
  • 场景战役:特殊机制副本

1.2 副本实例管理

class instance_blackwing_lair : public InstanceMapScript {
public:
    instance_blackwing_lair() : InstanceMapScript("instance_blackwing_lair", 267) {}

    struct instance_blackwing_lair_MapScript : public InstanceScript {
        uint64 razorgothGUID;
        uint64 vaelastraszGUID;
        uint64 chromaggusGUID;
        uint64 nefarianGUID;
        
        std::vector minionGUIDs;
        uint32 encounterMask;

        void Initialize() override {
            razorgothGUID = 0;
            vaelastraszGUID = 0;
            chromaggusGUID = 0;
            nefarianGUID = 0;
            encounterMask = 0;
        }

        void SetBossState(uint32 type, EncounterState state) override {
            if (state == DONE)
                encounterMask |= (1 << type);
            SaveToDB();
        }

        std::string GetSaveData() override {
            std::ostringstream saveStream;
            saveStream << "B W L " << encounterMask;
            return saveStream.str();
        }

        void Load(char const* data) override {
            if (!data) return;
            char dataHead1, dataHead2, dataHead3;
            uint32 data1;
            std::istringstream loadStream(data);
            loadStream >> dataHead1 >> dataHead2 >> dataHead3 >> data1;
            if (dataHead1 == 'B' && dataHead2 == 'W' && dataHead3 == 'L')
                encounterMask = data1;
        }
    };

    InstanceScript* GetInstanceScript(InstanceMap* map) const override {
        return new instance_blackwing_lair_MapScript(map);
    }
};

二、BOSS 技能框架

2.1 技能枚举

enum Spells {
    SPELL_CLEAVE           = 20691,
    SPELL_VOID_BOLT        = 35340,
    SPELL_SHADOW_FLAME     = 29384,
    SPELL_BURNING_FURY     = 29382,
    SPELL_FLAME_BREATH     = 29385,
    SPELL_ENRAGE           = 8599
};

enum Events {
    EVENT_CLEAVE           = 1,
    EVENT_VOID_BOLT        = 2,
    EVENT_SHADOW_FLAME     = 3,
    EVENT_ENRAGE           = 4
};

enum Phases {
    PHASE_ONE   = 1,
    PHASE_TWO   = 2,
    PHASE_THREE = 3
};

2.2 BOSS AI 基础

class boss_chromaggus : public CreatureScript {
public:
    boss_chromaggus() : CreatureScript("boss_chromaggus") { }

    struct boss_chromaggusAI : public ScriptedAI {
        boss_chromaggusAI(Creature* creature) : ScriptedAI(creature) {}

        void Reset() override {
            events.Reset();
            summons.DespawnAll();
            phase = PHASE_ONE;
            healthPercent = 100;
        }

        void EnterCombat(Unit* who) override {
            Talk(SAY_AGGRO);
            events.ScheduleEvent(EVENT_CLEAVE, 8000);
            events.ScheduleEvent(EVENT_FLAME_BREATH, 15000);
            events.ScheduleEvent(EVENT_SHADOW_FLAME, 25000);
        }

        void JustDied(Unit* killer) override {
            Talk(SAY_DEATH);
            instance->SetBossState(TYPE_CHROMAGGUS, DONE);
        }

        void UpdateAI(uint32 diff) override {
            if (!UpdateVictim()) return;

            events.Update(diff);

            while (uint32 eventId = events.ExecuteEvent()) {
                switch (eventId) {
                    case EVENT_CLEAVE:
                        DoCastVictim(SPELL_CLEAVE);
                        events.ScheduleEvent(EVENT_CLEAVE, 8000);
                        break;
                    case EVENT_FLAME_BREATH:
                        DoCastVictim(SPELL_FLAME_BREATH);
                        events.ScheduleEvent(EVENT_FLAME_BREATH, 15000);
                        break;
                    case EVENT_SHADOW_FLAME:
                        DoCastAOE(SPELL_SHADOW_FLAME);
                        events.ScheduleEvent(EVENT_SHADOW_FLAME, 25000);
                        break;
                }
            }

            // 检查阶段转换
            CheckPhaseTransition();

            DoMeleeAttackIfReady();
        }

        void CheckPhaseTransition() {
            float healthPct = ((float)me->GetHealth() / me->GetMaxHealth()) * 100;
            
            if (healthPct < 30 && phase == PHASE_TWO) {
                phase = PHASE_THREE;
                Talk(SAY_PHASE_THREE);
                events.ScheduleEvent(EVENT_ENRAGE, 1000);
            } else if (healthPct < 60 && phase == PHASE_ONE) {
                phase = PHASE_TWO;
                Talk(SAY_PHASE_TWO);
            }
        }

    private:
        EventMap events;
        SummonList summons;
        uint8 phase;
        float healthPercent;
    };

    CreatureAI* GetAI(Creature* creature) const override {
        return GetAzerothCoreAI(creature);
    }
};

三、特殊机制实现

3.1 点名技能

void CastTargetedSpell() {
    // 随机选择一个玩家
    Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true);
    if (target) {
        Talk(SAY_TARGET);
        DoCast(target, SPELL_TARGETED_SPELL);
        
        // 标记目标
        target->CastSpell(target, SPELL_MARK, true);
    }
}

3.2 范围技能

void CastAOESpell() {
    std::list<Creature*> targets;
    me->GetCreatureListWithEntryInGrid(targets, 0, 50.0f);
    
    for (auto target : targets) {
        if (target->IsPlayer()) {
            DoCast(target, SPELL_AOE_DAMAGE);
        }
    }
}

3.3 召唤小怪

void SummonMinions() {
    Talk(SAY_SUMMON);
    
    // 在指定位置召唤
    me->SummonCreature(NPC_MINION, 1234.5f, 567.8f, 100.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 300000);
    me->SummonCreature(NPC_MINION, 1240.0f, 570.0f, 100.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 300000);
    
    events.ScheduleEvent(EVENT_SUMMON_MINIONS, 60000);  // 60 秒后再次召唤
}

四、调试技巧

4.1 GM 命令测试

.phase              # 查看当前阶段
.phase          # 设置阶段
.cast        # 测试技能
.npc info           # 查看 NPC 信息
.go xyz    # 传送到副本

4.2 日志输出

LOG_INFO("scripts", "Boss entered combat");
LOG_DEBUG("scripts", "Casting spell {}", spellId);
LOG_ERROR("scripts", "Failed to find target");

五、总结

副本 BOSS 设计需要平衡难度和趣味性。建议:

  1. 从简单 BOSS 开始学习
  2. 多测试技能时间轴
  3. 注意技能伤害平衡
  4. 添加适当的机制提示

好的 BOSS 战让玩家既挑战又享受。