添加大秘境的UI数据信息通信
This commit is contained in:
parent
dec4648cf8
commit
b1d25b2af7
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(); // 全局拦截脚本
|
||||
}
|
||||
|
||||
166
modules/mod-mythic-plus/src/Script/Mythic_SpellScript.cpp
Normal file
166
modules/mod-mythic-plus/src/Script/Mythic_SpellScript.cpp
Normal 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);
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user