添加大秘境的UI数据信息通信

This commit is contained in:
尚美 2025-09-28 16:00:49 +08:00
parent dec4648cf8
commit b1d25b2af7
6 changed files with 586 additions and 37 deletions

View File

@ -5,6 +5,7 @@
#include "Item.h"
#include "WorldDatabase.h"
#include "ScriptMgr.h"
#include <GCAddon.h>
MythicPlusWrapperInstanceScript::MythicPlusWrapperInstanceScript(Map* map, uint32 mapId)
: InstanceScript(map), _mapId(mapId), _originalScript(nullptr), _countdownTimer(0)
@ -45,38 +46,38 @@ void MythicPlusWrapperInstanceScript::OnCreatureCreate(Creature* creature)
void MythicPlusWrapperInstanceScript::OnGameObjectCreate(GameObject* go)
{
// 先让原始脚本处理
// 先让原始脚本处理
if (_originalScript)
_originalScript->OnGameObjectCreate(go);
// 处理大秘境特有的GameObject
// 处理大秘境特有的GameObject
HandleMythicPlusGameObjects(go);
}
void MythicPlusWrapperInstanceScript::SetData(uint32 type, uint32 data)
{
// 处理大秘境特有数据
// 处理大秘境特有数据
if (IsMythicPlusDataType(type))
{
HandleMythicPlusSetData(type, data);
return;
}
// 委托给原始脚本
// 委托给原始脚本
if (_originalScript)
_originalScript->SetData(type, data);
}
uint32 MythicPlusWrapperInstanceScript::GetData(uint32 type) const
{
// 处理大秘境特有数据
// 处理大秘境特有数据
if (IsMythicPlusDataType(type))
{
auto itr = _mythicPlusData.find(type);
return itr != _mythicPlusData.end() ? itr->second : 0;
}
// 委托给原始脚本
// 委托给原始脚本
if (_originalScript)
return _originalScript->GetData(type);
@ -85,36 +86,55 @@ uint32 MythicPlusWrapperInstanceScript::GetData(uint32 type) const
void MythicPlusWrapperInstanceScript::DoAction(int32 actionId)
{
// 处理大秘境特有动作
// 处理大秘境特有动作
if (actionId == ACTION_START_MYTHIC_COUNTDOWN)
{
StartMythicPlusCountdown();
return;
}
// 委托给原始脚本
// 委托给原始脚本
if (_originalScript)
_originalScript->DoAction(actionId);
}
void MythicPlusWrapperInstanceScript::Update(uint32 diff)
{
// 先更新原始脚本
// 先更新原始脚本
if (_originalScript)
_originalScript->Update(diff);
// 然后更新大秘境调度器
// 然后更新大秘境调度器
_scheduler.Update(diff);
}
// 私有方法实现
void MythicPlusWrapperInstanceScript::OnUnitDeath(Unit* unit)
{
// 先调用原始脚本的处理
if (_originalScript)
_originalScript->OnUnitDeath(unit);
// 处理大秘境敌方部队进度更新
if (GetData(DATA_MYTHIC_CHALLENGE_ACTIVE) == DONE)
{
if (Creature* creature = unit->ToCreature())
{
// 清除金钱掉落,避免显示可拾取标识
creature->loot.gold = 0;
UpdateEnemyProgress(creature);
}
}
}
// 私有方法实现
InstanceScript* MythicPlusWrapperInstanceScript::CreateOriginalInstanceScript(Map* map, uint32 mapId)
{
// 获取实例模板
// 获取实例模板
InstanceTemplate const* instanceTemplate = sObjectMgr->GetInstanceTemplate(mapId);
if (instanceTemplate && instanceTemplate->ScriptId)
{
// 直接使用模板中的脚本ID创建脚本
// 直接使用模板中的脚本ID创建脚本
auto tempScript = ScriptRegistry<InstanceMapScript>::GetScriptById(instanceTemplate->ScriptId);
if (tempScript)
{
@ -135,11 +155,11 @@ void MythicPlusWrapperInstanceScript::HandleMythicPlusSetData(uint32 type, uint3
if (type == DATA_KEYSTONE_VALIDATED && data == DONE)
{
// 显示空气墙
// 显示空气墙
if (GameObject* wall = instance->GetGameObject(_invisibleWallGUID))
wall->SetPhaseMask(1, true);
// 禁用能量之泉
// 禁用能量之泉
if (GameObject* well = instance->GetGameObject(_energyWellGUID))
well->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
}
@ -152,11 +172,11 @@ void MythicPlusWrapperInstanceScript::HandleMythicPlusGameObjects(GameObject* go
{
switch (go->GetEntry())
{
case 410004: // GO_INVISIBLE_WALL
case 410004: // GO_INVISIBLE_WALL
_invisibleWallGUID = go->GetGUID();
go->SetPhaseMask(2, true); // 初始隐藏
go->SetPhaseMask(2, true); // 初始隐藏
break;
case 410000: // GO_ENERGY_WELL
case 410000: // GO_ENERGY_WELL
_energyWellGUID = go->GetGUID();
break;
}
@ -164,13 +184,13 @@ void MythicPlusWrapperInstanceScript::HandleMythicPlusGameObjects(GameObject* go
void MythicPlusWrapperInstanceScript::StartMythicPlusCountdown()
{
// 应用大秘境属性
// 应用大秘境属性
ApplyMythicPlusScalingToExistingCreatures();
// 开始倒计时
// 开始倒计时
_countdownTimer = 10;
DoUpdateWorldState(20100, 1); // WORLD_STATE_MYTHIC_COUNTDOWN_SHOW
DoUpdateWorldState(20101, _countdownTimer); // WORLD_STATE_MYTHIC_COUNTDOWN_TIME
DoUpdateWorldState(20100, 1); // WORLD_STATE_MYTHIC_COUNTDOWN_SHOW
DoUpdateWorldState(20101, _countdownTimer); // WORLD_STATE_MYTHIC_COUNTDOWN_TIME
_scheduler.Schedule(1s, [this](TaskContext context)
{
@ -183,40 +203,363 @@ void MythicPlusWrapperInstanceScript::StartMythicPlusCountdown()
}
else
{
// 倒计时结束
// 倒计时结束
DoUpdateWorldState(20100, 0);
if (GameObject* wall = instance->GetGameObject(_invisibleWallGUID))
wall->SetPhaseMask(2, true);
SetData(DATA_MYTHIC_CHALLENGE_ACTIVE, DONE);
// 初始化敌方部队计数
InitializeEnemyForces();
//SendMythicPlusInfoToPlayers(); // 发送大秘境信息数据包
}
});
}
void MythicPlusWrapperInstanceScript::ApplyMythicPlusScalingToExistingCreatures()
{
// 获取副本中的所有玩家列表
Map::PlayerList const& players = instance->GetPlayers();
if (players.IsEmpty())
return;
return; // 如果副本中没有玩家,直接返回
// 获取第一个玩家作为钥石持有者(假设队伍中只有一个钥石)
Player* player = players.begin()->GetSource();
// 通过物品ID 999001 获取大秘境钥石物品
Item* keystone = player->GetItemByEntry(999001);
// 如果玩家没有钥石,直接返回
if (!keystone)
return;
uint8 keystoneLevel = MythicPlusCreatureManager::GetKeystoneLevel(keystone);
std::vector<uint32> affixes = MythicPlusCreatureManager::GetKeystoneAffixes(keystone);
uint32 dungeonId = keystone->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID);
// 从钥石中提取大秘境相关信息
uint8 keystoneLevel = MythicPlusCreatureManager::GetKeystoneLevel(keystone); // 获取钥石等级
std::vector<uint32> affixes = MythicPlusCreatureManager::GetKeystoneAffixes(keystone); // 获取词缀列表
uint32 dungeonId = keystone->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID); // 从物品属性中获取副本ID
// 遍历副本中所有已记录的生物GUID
for (const ObjectGuid& guid : _allCreatureGUIDs)
{
// 通过GUID获取生物实例
if (Creature* creature = instance->GetCreature(guid))
{
if (creature->IsAlive())
// 多重条件检查,确保只对合适的生物应用大秘境属性
if (creature->IsAlive() && // 必须是活着的生物
creature->GetFaction() != 35 && // 排除中立阵营NPC阵营35为友善
!creature->IsServiceProvider() && // 排除服务提供者(商人、训练师、银行家等)
!creature->IsCritter()) // 排除小动物(装饰性生物)
{
// 应用大秘境等级缩放(血量、伤害等属性提升)
MythicPlusCreatureManager::ApplyMythicPlusScaling(creature, keystoneLevel, dungeonId);
// 应用词缀效果
MythicPlusCreatureManager::ApplyAffixEffects(creature, affixes);
}
}
}
}
std::string MythicPlusWrapperInstanceScript::SendMythicPlusInfoToPlayers()
{
// 获取大秘境配置信息
MythicDungeonConfig const* config = sMythicPlusCache->GetDungeonConfigByMapId(_mapId);
if (!config)
return ""; // 修改这里,返回空字符串
// 构建数据包内容
std::string mythicInfo = BuildMythicPlusInfoPacket(config);
if (!mythicInfo.empty())
{
return mythicInfo;
}
return "";
}
std::string MythicPlusWrapperInstanceScript::BuildMythicPlusInfoPacket(MythicDungeonConfig const* config)
{
// 获取副本名称
std::string dungeonName = config->dungeonName;
// 获取挑战时间限制
uint32 timeLimit = config->baseTimeLimit;
// 获取所有BOSS信息
std::string bossInfo = GetAllBossInfo();
// 计算敌方部队数量和击杀进度
std::string enemyProgress = CalculateEnemyProgress();
// 构建数据包格式:名称|时间|BOSS信息|敌方进度
return fmt::format("{}|{}|{}|{}", dungeonName, timeLimit, bossInfo, enemyProgress);
}
// 获取全部BOSS信息
std::string MythicPlusWrapperInstanceScript::GetAllBossInfo()
{
std::vector<std::string> bossInfo;
uint32 mapId = _mapId;
Difficulty difficulty = instance->GetDifficulty();
DungeonEncounterList const* encounters = sObjectMgr->GetDungeonEncounterList(mapId, difficulty);
if (!encounters)
return "";
for (auto const& encounter : *encounters)
{
uint32 encounterId = encounter->dbcEntry->encounterIndex;
std::string bossName = encounter->dbcEntry->encounterName[6];
if (bossName.empty())
bossName = encounter->dbcEntry->encounterName[0];
uint32 encounterMask = GetCompletedEncounterMask();
bool isKilled = (encounterMask & (1 << encounter->dbcEntry->encounterIndex)) != 0;
// 使用 @ 符号分隔遭遇战ID和BOSS名称避免与主分隔符冲突
bossInfo.push_back(fmt::format("{}@{}:{}", encounterId, bossName, isKilled ? "1" : "0"));
}
std::string result;
for (size_t i = 0; i < bossInfo.size(); ++i)
{
if (i > 0) result += ",";
result += bossInfo[i];
}
return result;
}
// 计算敌方部队击杀进度
std::string MythicPlusWrapperInstanceScript::CalculateEnemyProgress()
{
uint32 totalEnemies = 0;
// 遍历所有存储的生物GUID
for (const ObjectGuid& guid : _allCreatureGUIDs)
{
if (Creature* creature = instance->GetCreature(guid))
{
// 排除BOSS和特殊NPC
if (IsBossCreature(creature) || IsSpecialNPC(creature))
continue;
totalEnemies++;
}
}
return fmt::format("{}:{}:{:.1f}", 0, totalEnemies, 0.0f);
}
// 是否BOSS
bool MythicPlusWrapperInstanceScript::IsBossCreature(Creature* creature)
{
// 利用遭遇战系统判断是否为BOSS
uint32 mapId = _mapId;
Difficulty difficulty = instance->GetDifficulty();
DungeonEncounterList const* encounters = sObjectMgr->GetDungeonEncounterList(mapId, difficulty);
if (!encounters)
return false;
uint32 entry = creature->GetEntry();
for (auto const& encounter : *encounters)
{
if (encounter->creditEntry == entry)
return true;
}
return false;
}
// 是否NPC
bool MythicPlusWrapperInstanceScript::IsSpecialNPC(Creature* creature)
{
// 排除任务NPC等特殊生物
if (_originalScript)
{
// 可以通过原始脚本的数据来判断特殊NPC
// 这里简化处理,可以根据需要扩展
return false;
}
return false;
}
void MythicPlusWrapperInstanceScript::InitializeEnemyForces()
{
_totalEnemyForces = 0;
_killedEnemyForces = 0;
_totalEnemyForcePoints = 0;
_currentEnemyForcePoints = 0;
// 计算总敌方部队数量和总点数
for (const ObjectGuid& guid : _allCreatureGUIDs)
{
if (Creature* creature = instance->GetCreature(guid))
{
if (IsEnemyForceCreature(creature))
{
_totalEnemyForces++;
float weight = GetCreatureWeight(creature);
_totalEnemyForcePoints += static_cast<uint32>(weight * 100);
// 添加详细日志
LOG_INFO("server.loading", "敌方生物:条目={},等级={},重量={:.1f}", creature->GetEntry(), creature->GetCreatureTemplate()->rank, weight);
}
}
}
_enemyForcesPercentage = 0.0f; // 初始进度为0
LOG_INFO("server.loading", "已初始化的敌方势力:共{}个生物,总{}点", _totalEnemyForces, _totalEnemyForcePoints);
}
bool MythicPlusWrapperInstanceScript::IsEnemyForceCreature(Creature* creature)
{
// 排除BOSS
if (IsBossCreature(creature))
return false;
// 排除特殊NPC如任务NPC
if (IsSpecialNPC(creature))
return false;
// 排除中立阵营
if (creature->GetFaction() == 35)
return false;
// 检查生物等级类型 - 包含所有有权重的类型
uint32 rank = creature->GetCreatureTemplate()->rank;
bool isValidRank = (rank == CREATURE_ELITE_NORMAL ||
rank == CREATURE_ELITE_ELITE ||
rank == CREATURE_ELITE_RARE ||
rank == CREATURE_ELITE_RAREELITE);
return isValidRank;
}
float MythicPlusWrapperInstanceScript::GetCreatureWeight(Creature* creature)
{
// 根据生物等级和类型计算权重 - 获取生物模板数据
CreatureTemplate const* creatureTemplate = sObjectMgr->GetCreatureTemplate(creature->GetEntry());
if (!creatureTemplate)
return 1.0f;// 如果找不到生物模板返回默认权重1.0
float weight = 1.0f;// 初始权重值
// 根据生物等级调整权重 - 使用生物模板中的rank字段
switch (creatureTemplate->rank)
{
case CREATURE_ELITE_NORMAL: // 普通生物
weight = 2000000.0f; // 基础权重
break;
case CREATURE_ELITE_ELITE: // 精英生物
weight = 4000000.0f; // 2倍权重
break;
case CREATURE_ELITE_RARE: // 稀有生物
weight = 6000000.0f; // 4倍权重表示更有价值/更难对付
break;
case CREATURE_ELITE_RAREELITE: // 稀有精英生物
weight = 8000000.0f; // 最高权重,最难对付的生物类型
break;
default:
weight = 1000000.0f; // 未知类型使用默认权重
break;
}
return weight;
}
// 实时进度更新
void MythicPlusWrapperInstanceScript::UpdateEnemyProgress(Creature* creature)
{
if (!IsEnemyForceCreature(creature))
return;
// 如果已经达到100%,不再处理更新
if (_enemyForcesPercentage >= 100.0f)
return;
// 更新击杀计数
_killedEnemyForces++;
// 获取生物权重并累加点数
float weight = GetCreatureWeight(creature);
_currentEnemyForcePoints += static_cast<uint32>(weight * 100);
// 使用点数系统计算百分比
_enemyForcesPercentage = _totalEnemyForcePoints > 0 ? (float(_currentEnemyForcePoints) / float(_totalEnemyForcePoints)) * 100.0f : 0.0f;
// 发送实时进度更新
SendEnemyProgressUpdate();
LOG_INFO("server.loading", "敌方部队进度更新:{}/{}{:.1f}%",
_killedEnemyForces, _totalEnemyForces, _enemyForcesPercentage);
// 如果达到100%,可以触发完成事件
if (_enemyForcesPercentage >= 100.0f)
{
LOG_INFO("server.loading", "敌方部队目标已达成!");
// 这里可以添加完成大秘境敌方部队目标的逻辑
}
}
// 发送实时进度更新
void MythicPlusWrapperInstanceScript::SendEnemyProgressUpdate()
{
std::string progressInfo = fmt::format("{}|{}|{:.1f}",
_killedEnemyForces, _totalEnemyForces, _enemyForcesPercentage);
Map::PlayerList const& players = instance->GetPlayers();
for (auto const& playerRef : players)
{
if (Player* player = playerRef.GetSource())
{
sGCAddon->SendPacketTo(player, "SM_S_MYTHICPLUS_PROGRESS_UPDATE", progressInfo);
}
}
}
// 发送击杀BOSS信息给玩家
void MythicPlusWrapperInstanceScript::SendBossKillUpdateToPlayers(Map* map, uint32 creditEntry)
{
if (!map || !map->IsDungeon())
return;
InstanceScript* instance = map->ToInstanceMap()->GetInstanceScript();
if (!instance)
return;
// 检查是否是大秘境模式
if (instance->GetData(DATA_MYTHIC_CHALLENGE_ACTIVE) != DONE)
return;
// 获取遭遇战信息
DungeonEncounterList const* encounters = sObjectMgr->GetDungeonEncounterList(map->GetId(), map->GetDifficulty());
if (!encounters)
return;
// 查找对应的BOSS遭遇战
for (auto const& encounter : *encounters)
{
if (encounter->creditEntry == creditEntry)
{
// 获取遭遇战ID
uint32 encounterId = encounter->dbcEntry->encounterIndex;
// 获取中文BOSS名称
std::string bossName = encounter->dbcEntry->encounterName[6];
if (bossName.empty())
bossName = encounter->dbcEntry->encounterName[0];
// 发送格式遭遇战ID|BOSS名称:状态
std::string bossUpdate = fmt::format("{}|{}:1", encounterId, bossName);
map->DoForAllPlayers([&](Player* player) {
sGCAddon->SendPacketTo(player, "SM_S_MYTHICPLUS_BOSS_UPDATE", bossUpdate);
});
LOG_INFO("server.loading", "Boss kill 更新已发送: {}", bossUpdate);
break;
}
}
}

View File

@ -33,6 +33,11 @@ public:
uint32 GetData(uint32 type) const override;
void DoAction(int32 actionId) override;
void Update(uint32 diff) override;
void OnUnitDeath(Unit* unit) override;
std::string SendMythicPlusInfoToPlayers(); // 发送大秘境信息数据包
void SendBossKillUpdateToPlayers(Map* map, uint32 creditEntry); // 发送击杀BOSS信息给玩家
private:
InstanceScript* _originalScript;
@ -48,6 +53,10 @@ private:
ObjectGuid _invisibleWallGUID;
ObjectGuid _energyWellGUID;
uint32 _totalEnemyForces = 0; // 总敌方部队数量(固定值)
uint32 _killedEnemyForces = 0; // 已击杀敌方部队数量
float _enemyForcesPercentage = 0.0f; // 敌方部队击杀百分比
// 私有方法
InstanceScript* CreateOriginalInstanceScript(Map* map, uint32 mapId);
bool IsMythicPlusDataType(uint32 type) const;
@ -55,6 +64,23 @@ private:
void HandleMythicPlusGameObjects(GameObject* go);
void StartMythicPlusCountdown();
void ApplyMythicPlusScalingToExistingCreatures();
std::string BuildMythicPlusInfoPacket(MythicDungeonConfig const* config);
std::string GetAllBossInfo();
std::string CalculateEnemyProgress(); // 计算敌方部队击杀进度
bool IsBossCreature(Creature* creature); // 是否BOSS
bool IsSpecialNPC(Creature* creature); // 是否NPC
uint32 _totalEnemyForcePoints = 0; // 总敌方部队点数(加权后)
uint32 _currentEnemyForcePoints = 0; // 当前获得的点数
std::unordered_map<uint32, float> _creatureWeights; // 生物权重映射
void InitializeEnemyForces(); // 初始化敌方部队计数
bool IsEnemyForceCreature(Creature* creature);
float GetCreatureWeight(Creature* creature);
void UpdateEnemyProgress(Creature* creature); // 实时进度更新
void SendEnemyProgressUpdate(); // 发送实时进度更新
};
#endif

View File

@ -19,7 +19,6 @@
#include <Mythic_Script.h>
#include <GCAddon.h>
#include <wailing_caverns_mythic.h>
#include <MythicPlusWrapperInstance.h>
// 实现单例
@ -739,22 +738,36 @@ public:
if (!player || !player->GetMap())
return false;
// 检查是否在大秘境模式中
// 检查是否在大秘境模式中
if (InstanceScript* instance = player->GetInstanceScript())
{
if (instance->GetData(DATA_MYTHIC_CHALLENGE_ACTIVE) == DONE)
{
// 大秘境激活时禁用生物掉落 - 返回 true 表示阻止掉落
// 大秘境激活时禁用生物掉落 - 返回 true 表示阻止掉落
return true;
}
}
return false; // 让其他脚本处理
return false; // 让其他脚本处理
}
void OnAfterUpdateEncounterState(Map* map, EncounterCreditType type, uint32 creditEntry, Unit* source, Difficulty difficulty_fixed, DungeonEncounterList const* encounters, uint32 dungeonCompleted, bool updated) override
{
LOG_INFO("server.loading", "我的脚本::遭遇状态更新后 - 地图ID={}, 击杀目标ID={}, 完成副本ID={}, 是否更新={}", map->GetId(), creditEntry, dungeonCompleted, updated);
// 检查是否是大秘境模式下的BOSS击杀
if (updated && map && map->IsDungeon() && type == ENCOUNTER_CREDIT_KILL_CREATURE)
{
if (InstanceMap* instanceMap = map->ToInstanceMap())
{
if (MythicPlusWrapperInstanceScript* mythicScript =
dynamic_cast<MythicPlusWrapperInstanceScript*>(instanceMap->GetInstanceScript()))
{
mythicScript->SendBossKillUpdateToPlayers(map, creditEntry);
}
}
}
if (dungeonCompleted && map && map->IsDungeon())
{
Map::PlayerList const& players = map->GetPlayers();
@ -1020,7 +1033,7 @@ void MythicPlusCreatureManager::ApplyMythicPlusScaling(Creature* creature, uint8
// 应用伤害调整(使用你的更好方式)
creature->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, (damageMultiplier - 1.0f) * 100.0f, true);
LOG_INFO("mythic.plus", "Applied scaling to creature {} - Level: {}, Health: {}, Damage: {}%",
LOG_INFO("mythic.plus", "对生物{}应用缩放 - 等级:{},生命值:{},伤害:{}%",
creature->GetEntry(), keystoneLevel, newMaxHealth, damageMultiplier * 100.0f);
}
@ -1031,7 +1044,8 @@ void MythicPlusCreatureManager::ApplyAffixEffects(Creature* creature, std::vecto
{
if (affixSpellId != 0)
{
creature->AddAura(affixSpellId, creature);
// 使用正常的法术施放这样会触发SpellScript
creature->CastSpell(creature, affixSpellId, true);
}
}
}
@ -1128,5 +1142,5 @@ void AddSC_MythicPlusKeystone()
new MythicPlusPlayerScript();
new MythicPlusGlobalScript();
new MythicPlusWorldScript(); // 周重置钥石逻辑
new Mod_MythicPlusAllMapScript(); // 全局拦截脚本
new Mod_MythicPlusAllMapScript(); // 全局拦截脚本
}

View File

@ -0,0 +1,166 @@
// modules\mod-mythic-plus\src\Script\Mythic_SpellScript.cpp
#include "Creature.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
#include "Log.h"
#include "Player.h"
#include "Map.h"
#include "ObjectAccessor.h"
#include "TaskScheduler.h"
// 定义NPC ID常量
#define NPC_VOLCANO_LAVA_PILLAR 91001
class spell_brutality_affix : public SpellScript
{
PrepareSpellScript(spell_brutality_affix);
void CheckTarget(WorldObject*& target)
{
LOG_INFO("server.loading", "spell_brutality_affix: 检查目标 {}", target ? target->GetName() : "null");
if (Creature const* creature = target->ToCreature())
{
bool isBoss = creature->isWorldBoss() || creature->IsDungeonBoss();
LOG_INFO("server.loading", "生物 {} 是否为首领: {}", creature->GetName(), isBoss);
if (!isBoss)
{
target = nullptr;
}
}
else
{
target = nullptr; // 移除非生物目标
}
}
void Register() override
{
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_brutality_affix::CheckTarget, EFFECT_0, TARGET_UNIT_CASTER);
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_brutality_affix::CheckTarget, EFFECT_1, TARGET_UNIT_CASTER);
}
};
// 火山周期性光环
class spell_volcano_periodic_aura : public AuraScript
{
PrepareAuraScript(spell_volcano_periodic_aura);
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
LOG_INFO("server.loading", "火山光环已应用到单位: {}", GetUnitOwner()->GetName());
}
void HandlePeriodic(AuraEffect const* aurEff)
{
LOG_INFO("server.loading", "火山技能周期性触发开始");
// PreventDefaultAction();
Unit* caster = GetUnitOwner();
if (!caster)
return;
Map::PlayerList const& playerList = caster->GetMap()->GetPlayers();
std::list<Player*> validTargets;
for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
{
if (Player* player = itr->GetSource())
{
if (player->IsAlive() &&
caster->IsValidAttackTarget(player) &&
caster->GetDistance2d(player) > 15.0f &&
caster->GetDistance2d(player) <= 40.0f)
{
validTargets.push_back(player);
}
}
}
if (!validTargets.empty())
{
Player* target = Acore::Containers::SelectRandomContainerElement(validTargets);
caster->CastSpell(target, 100002, true);
}
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_volcano_periodic_aura::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
OnEffectPeriodic += AuraEffectPeriodicFn(spell_volcano_periodic_aura::HandlePeriodic,
EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
// 岩浆柱召唤脚本
class spell_volcano_summon_lava_pillar : public SpellScript
{
PrepareSpellScript(spell_volcano_summon_lava_pillar);
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
if (!caster || !target)
return;
// 在目标位置召唤岩浆柱延迟1秒爆发
if (Creature* lavaPillar = caster->SummonCreature(
NPC_VOLCANO_LAVA_PILLAR,
target->GetPositionX(),
target->GetPositionY(),
target->GetPositionZ(),
0.0f,
TEMPSUMMON_TIMED_DESPAWN,
5000))
{
// 1秒后造成伤害
lavaPillar->m_Events.AddEventAtOffset([lavaPillar]() {
lavaPillar->CastSpell(lavaPillar, 100003, true); // 伤害技能
}, 1000ms);
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_volcano_summon_lava_pillar::HandleScriptEffect,
EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 岩浆柱伤害脚本
class spell_volcano_lava_damage : public SpellScript
{
PrepareSpellScript(spell_volcano_lava_damage);
void FilterTargets(std::list<WorldObject*>& targets)
{
// 只对8码范围内的敌对目标造成伤害
Unit* caster = GetCaster();
if (!caster)
return;
targets.remove_if([caster](WorldObject* target) {
Unit* unit = target->ToUnit();
return !unit || !caster->IsValidAttackTarget(unit) ||
caster->GetDistance(unit) > 8.0f;
});
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(
spell_volcano_lava_damage::FilterTargets,
EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
void AddSC_MythicPlus_Scripts()
{
RegisterSpellScript(spell_brutality_affix);
RegisterSpellScript(spell_volcano_periodic_aura);
RegisterSpellScript(spell_volcano_summon_lava_pillar);
RegisterSpellScript(spell_volcano_lava_damage);
}

View File

@ -2,11 +2,11 @@
void GO_KeystonePedestalScripts();
void AddSC_MythicPlusKeystone();
//void AddMythicPlusWailingCavernsScripts();
void AddSC_MythicPlus_Scripts();
void Addmod_mythic_plusScripts()
{
GO_KeystonePedestalScripts();
AddSC_MythicPlusKeystone();
//AddMythicPlusWailingCavernsScripts();
AddSC_MythicPlus_Scripts();
}