将[模板_随机技能组]功能独立出来

This commit is contained in:
尚美 2025-08-14 11:24:03 +08:00
parent 7b6e27c422
commit c084a36878
8 changed files with 155 additions and 127 deletions

View File

@ -0,0 +1,112 @@
#include "random"
#include <Utilities/Timer.h>
#include "algorithm"
#include "vector"
#include "Creature.h"
#include <DataLoader.h>
#include <Logging/Log.h>
#include "AllCreatureScript.h"
#include "RandSpell.h"
#include <mod_CustomCreature/mod_CustomCreature.h>
#include <mod_GhostScripts/src/mod_UnitMod/CreatureMod/CreatureMod.h>
void CustomRandSpellScript::Load()
{
uint32 oldMSTime = getMSTime();
AIRandSpellMap.clear();
QueryResult result = WorldDatabase.Query(
"SELECT 随机技能组ID,技能ID,释放下一技能最小延迟,释放下一技能最大延迟 FROM acore_custom._模板_随机技能组");
if (result)
{
do
{
Field* fields = result->Fetch();
AIRandSpellTemplate temp;
temp.GroupId = fields[0].Get<uint32>();
temp.SpellId = fields[1].Get<uint32>();
temp.MinDelayTime = fields[2].Get<uint32>() * IN_MILLISECONDS;
temp.MaxDelayTime = fields[3].Get<uint32>() * IN_MILLISECONDS;
if (temp.MaxDelayTime < temp.MinDelayTime)
temp.MaxDelayTime = temp.MinDelayTime;
// 按GroupId分组存储
AIRandSpellMap[temp.GroupId].push_back(temp);
} while (result->NextRow());
sLog->outMessage("server", LogLevel::LOG_LEVEL_INFO,
">> 读取自定义功能数据表【_模板_随机技能组】,共{}个技能组,{}条技能数据,用时{}毫秒",
AIRandSpellMap.size(),
[this]() {
uint32 total = 0;
for (const auto& pair : AIRandSpellMap)
total += pair.second.size();
return total;
}(),
GetMSTimeDiffToNow(oldMSTime));
}
}
void CustomRandSpellScript::CastRandSpell(Creature* creature, uint32 diff)
{
if (!creature)
return;
mod_CustomCreature* customCreature = mod_CustomCreature::GetForCreature(creature);
if (!customCreature || customCreature->RandSpellGroupId == 0)
return;
// 快速查找对应的技能组
auto it = AIRandSpellMap.find(customCreature->RandSpellGroupId);
if (it == AIRandSpellMap.end() || it->second.empty())
return;
if (creature->IsInCombat())
{
customCreature->RandSpellTimer -= diff;
if (customCreature->RandSpellTimer < 0)
{
const std::vector<AIRandSpellTemplate>& spellGroup = it->second;
// 直接使用随机索引避免创建临时vector和shuffle操作
uint32 index = urand(0, spellGroup.size() - 1);
const AIRandSpellTemplate& selectedSpell = spellGroup[index];
customCreature->RandSpellTimer = urand(selectedSpell.MinDelayTime, selectedSpell.MaxDelayTime);
if (Unit* victim = creature->GetVictim())
creature->CastSpell(victim, selectedSpell.SpellId);
}
}
else
{
customCreature->RandSpellTimer = 0;
}
}
class Mod_CustomAllCreatureRandSpellScript : public AllCreatureScript
{
public:
Mod_CustomAllCreatureRandSpellScript() : AllCreatureScript("Mod_CustomAllCreatureRandSpellScript") {}
// 生物更新结束时调用
virtual void OnAllCreatureUpdate(Creature* creature, uint32 diff) override
{
// 检查是否在"_属性调整_生物"表中且有随机技能组ID
if (mod_CustomCreature* customCreature = mod_CustomCreature::GetForCreature(creature))
{
if (customCreature->RandSpellGroupId > 0)
sCustomRandSpellScript->CastRandSpell(creature, diff);
}
}
};
void AddSC_CustomRandSpellScript()
{
new Mod_CustomAllCreatureRandSpellScript();
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <unordered_map>
#include <vector>
struct AIRandSpellTemplate
{
uint32 GroupId;
uint32 SpellId;
uint32 MinDelayTime;
uint32 MaxDelayTime;
};
class CustomRandSpellScript
{
public:
static CustomRandSpellScript* instance()
{
static CustomRandSpellScript instance;
return &instance;
}
void Load();
void CastRandSpell(Creature* creature, uint32 diff);
private:
// 使用unordered_map按GroupId分组存储提高查找效率
std::unordered_map<uint32, std::vector<AIRandSpellTemplate>> AIRandSpellMap;
};
#define sCustomRandSpellScript CustomRandSpellScript::instance()

View File

@ -84,6 +84,7 @@
#include <MountRestriction.h>
#include <rune_system.h>
#include <mod_ItemDisable_Enchantment.h>
#include <mod_GhostScripts/src/mod-RandSpell/RandSpell.h>
using namespace Acore::ChatCommands;
@ -207,6 +208,7 @@ void DataLoader::LoadAll()
sServerAnnounce->Load(); // __全服提示
sCustomScript->LoadGobScripts(); // _自定义AI_物体
sCustomScript->LoadCreautreScripts(); // _自定义AI_生物
sCustomRandSpellScript->Load(); // _模板_随机技能组
sCustomScript->LoadCircleData(); // _circle_script 代码已经注释了,好像没用?
sDeadline->Load(); // _副本_限时模式
sLeaderReward->Load(); // 团队领袖奖励系统 目前禁用状态

View File

@ -54,7 +54,8 @@ void AddSC_Random_Enchant();
void AddSC_RECRUIT();
void AddSC_Reincarnation();
void AddSC_ResetInsNPC();
void AddSC_CustomCreatureScript();
void AddSC_CustomCreatureScript(); // 自定义AI_生物
void AddSC_CustomRandSpellScript(); // 随机技能组
void AddSC_SpellScripts();
void AddSC_SignIn();
void AddSC_CUSTOM_SKILL();
@ -169,7 +170,8 @@ void Addmod_GhostScriptsScripts(){
AddSC_RECRUIT();
AddSC_Reincarnation();
AddSC_ResetInsNPC();
AddSC_CustomCreatureScript();
AddSC_CustomCreatureScript(); // 自定义AI_生物
AddSC_CustomRandSpellScript(); // 随机技能组
AddSC_SpellScripts();
AddSC_SignIn();
AddSC_CUSTOM_SKILL();

View File

@ -16,7 +16,6 @@
#include <WorldSessionMgr.h>
std::vector<CreatureScriptTemplate> CreatureScriptVec;
std::vector<AIRandSpellTemplate> AIRandSpellVec;
// 在文件开头添加这些辅助类用于延迟处理标志修改dsa
@ -180,66 +179,8 @@ void CustomScript::LoadCreautreScripts()
CreatureScriptVec.push_back(Temp);
} while (ResultCreatureScrip->NextRow());
sLog->outMessage("server", LogLevel::LOG_LEVEL_INFO, ">> 读取自定义功能数据表【_自定义AI_生物-----------】,共{}条数据读取加载,用时{}毫秒", CreatureScriptVec.size(), GetMSTimeDiffToNow(CreatureScriptVec_OldMSTime));
}
//for (uint32 i = 0; i < CreatureScriptVec.size(); i++)
//{
// uint32 entry = CreatureScriptVec[i].entry;
// // 使用const指针来接收数据
// const CreatureTemplateContainer* creatureTemplateStore = sCustomObjectMgr->GetCreatureTemplatesStore();
// // 使用const迭代器因为我们不能通过const指针修改数据
// CreatureTemplateContainer::const_iterator itr = creatureTemplateStore->find(entry);
// //if (itr != creatureTemplateStore->end())
// //{
// // itr->second.AIName = "";
// // itr->second.ScriptID = sObjectMgr->GetScriptId("CustomCreatureScript");
// //}
// for (uint32 i = 0; i < CreatureScriptVec.size(); i++)
// {
// uint32 entry = CreatureScriptVec[i].entry;
// sCustomObjectMgr->ModCreatureTemplate(entry, "CustomCreatureScript", sObjectMgr->GetScriptId("CustomCreatureScript"));
// }
//}
// 移除原来的ModCreatureTemplate调用改为动态检查
/*for (const auto& script : CreatureScriptVec)
{
sCustomObjectMgr->ModCreatureTemplate(script.entry, "CustomCreatureScript", sObjectMgr->GetScriptId("CustomCreatureScript"));
}*/
uint32 AIRandSpellVec_OldMSTime = getMSTime();
AIRandSpellVec.clear();
QueryResult ResultAIRandSpell = WorldDatabase.Query(
// 0 1 2 3
"SELECT 随机技能组ID,技能ID,释放下一技能最小延迟,释放下一技能最大延迟 FROM acore_custom._模板_随机技能组");
if (ResultAIRandSpell)
{
do
{
Field* fields = ResultAIRandSpell->Fetch();
AIRandSpellTemplate Temp;
Temp.GroupId = fields[0].Get<uint32>();
Temp.SpellId = fields[1].Get<uint32>();
Temp.MinDelayTime = fields[2].Get<uint32>() * IN_MILLISECONDS;
Temp.MaxDelayTime = fields[3].Get<uint32>() * IN_MILLISECONDS;
if (Temp.MaxDelayTime < Temp.MinDelayTime)
Temp.MaxDelayTime = Temp.MinDelayTime;
AIRandSpellVec.push_back(Temp);
} while (ResultAIRandSpell->NextRow());
sLog->outMessage("server", LogLevel::LOG_LEVEL_INFO, ">> 读取自定义功能数据表【_模板_随机技能组---------】,共{}条数据读取加载,用时{}毫秒", AIRandSpellVec.size(), GetMSTimeDiffToNow(AIRandSpellVec_OldMSTime));
}
// 在函数末尾添加:
std::set<uint32> uniqueEntries;
for (const auto& script : CreatureScriptVec)
{
@ -262,55 +203,6 @@ bool HasCustomAI(uint32 entry)
return false;
}
void CustomScript::CastRandSpell(Creature* creature, uint32 diff)
{
if (!creature)
return;
//std::unique_ptr<mod_CustomCreature> customCreature(new mod_CustomCreature(creature));
mod_CustomCreature* customCreature = mod_CustomCreature::GetForCreature(creature); // CreatureScripts.cpp 第251行附近
// 添加空指针检查
if (!customCreature)
return;
if (customCreature->RandSpellGroupId == 0)
return;
if (AIRandSpellVec.empty())
return;
if (creature->IsInCombat())
{
customCreature->RandSpellTimer -= diff;
if (customCreature->RandSpellTimer < 0)
{
std::vector<AIRandSpellTemplate> v;
for (auto itr = AIRandSpellVec.begin(); itr != AIRandSpellVec.end(); itr++)
if (itr->GroupId == customCreature->RandSpellGroupId)
v.push_back(*itr);
if (!v.empty())
{
//std::random_shuffle(v.begin(), v.end());
std::default_random_engine generator{ std::random_device{}() };
std::shuffle(std::begin(v), std::end(v), generator);
customCreature->RandSpellTimer = urand(v[0].MinDelayTime, v[0].MaxDelayTime);
if (creature->GetVictim())
creature->CastSpell(creature->GetVictim(), v[0].SpellId);
}
else
customCreature->RandSpellTimer = 0;
}
}
else
customCreature->RandSpellTimer = 0;
}
enum EVENT_IDS
{
EVENT_CHECK_HEALTH = 1,
@ -416,9 +308,6 @@ public:
void UpdateAI(uint32 diff)
{
// 添加随机技能处理
sCustomScript->CastRandSpell(me, diff);
if (!UpdateVictim())
return;

View File

@ -126,16 +126,6 @@ enum SpellModTypes
SMT_STUN_BREAKABLE, //受到伤害可打断昏迷
};
struct AIRandSpellTemplate
{
uint32 GroupId;
uint32 SpellId;
uint32 MinDelayTime;
uint32 MaxDelayTime;
};
extern std::vector<AIRandSpellTemplate> AIRandSpellVec;
class CustomScript
{
public:
@ -157,9 +147,6 @@ public:
void CastSpellToNearbyPlayers(Unit* caster, uint32 e_spellId, uint32 f_spellId, float range);
void CastSpellToNearbyUnits(Unit* caster, uint32 e_spellId, uint32 f_spellId, float range);
void CastRandSpell(Creature* creautre, uint32 diff);
void ReloadCreatureAI(uint32 entry); // 强制重新分配AI
private:

View File

@ -522,7 +522,6 @@ public:
virtual void OnAllCreatureUpdate(Creature* creature, uint32 diff) override
{
sCreatureMod->CreatureReset(creature, diff);//防止BOSS离开原位置过远
sCustomScript->CastRandSpell(creature, diff);//额外技能
}
//补丁用@尚美[模块] 20240316 当函数Respawn前调用

View File

@ -49,6 +49,13 @@ public:
// 快速查找函数
CreautreModTemplate* FindTemplate(uint32 entry, uint32 challengeLv, uint32 diff);
// 简单高效的检查函数,检查"_属性调整_生物"表中是否存在该生物
bool HasCreatureMod(uint32 entry)
{
auto entryIt = _modIndex.find(entry);
return entryIt != _modIndex.end();
}
private:
CreatureModIndex _modIndex; // [Entry][ChallengeLv][Diff] -> Template*
std::vector<CreautreModTemplate> _modTemplates; // 存储实际数据