修正[自定义AI_物体]
1、去除PlayerScript方式、使用AllGameObjectScript 2、使用unordered_map按entry分组存储,提高查找效率
This commit is contained in:
parent
c084a36878
commit
74df244836
@ -54,8 +54,9 @@ void AddSC_Random_Enchant();
|
||||
void AddSC_RECRUIT();
|
||||
void AddSC_Reincarnation();
|
||||
void AddSC_ResetInsNPC();
|
||||
void AddSC_CustomCreatureScript(); // 自定义AI_生物
|
||||
void AddSC_CustomRandSpellScript(); // 随机技能组
|
||||
void AddSC_CustomCreatureScript(); // 自定义AI_生物
|
||||
void AddSC_CustomRandSpellScript(); // 随机技能组
|
||||
void AddSC_CustomGameObjectScript(); // 自定义AI_物体
|
||||
void AddSC_SpellScripts();
|
||||
void AddSC_SignIn();
|
||||
void AddSC_CUSTOM_SKILL();
|
||||
@ -170,8 +171,9 @@ void Addmod_GhostScriptsScripts(){
|
||||
AddSC_RECRUIT();
|
||||
AddSC_Reincarnation();
|
||||
AddSC_ResetInsNPC();
|
||||
AddSC_CustomCreatureScript(); // 自定义AI_生物
|
||||
AddSC_CustomRandSpellScript(); // 随机技能组
|
||||
AddSC_CustomCreatureScript(); // 自定义AI_生物
|
||||
AddSC_CustomRandSpellScript(); // 随机技能组
|
||||
AddSC_CustomGameObjectScript(); // 自定义AI_物体
|
||||
AddSC_SpellScripts();
|
||||
AddSC_SignIn();
|
||||
AddSC_CUSTOM_SKILL();
|
||||
|
||||
@ -148,7 +148,14 @@ public:
|
||||
void CastSpellToNearbyUnits(Unit* caster, uint32 e_spellId, uint32 f_spellId, float range);
|
||||
|
||||
void ReloadCreatureAI(uint32 entry); // 强制重新分配AI
|
||||
|
||||
bool HasCustomScript(uint32 entry);
|
||||
void ExecuteScript(Player* player, GameObject* gob);
|
||||
private:
|
||||
|
||||
// 使用unordered_map按entry分组存储,提高查找效率
|
||||
std::unordered_map<uint32, std::vector<GobScriptTemplate>> GobScriptMap;
|
||||
void Tele(Player* player, uint32 telePosId);
|
||||
|
||||
};
|
||||
#define sCustomScript CustomScript::instance()
|
||||
|
||||
@ -6,228 +6,240 @@
|
||||
#include "mod_CustomEvent/Event.h"
|
||||
#include "mod_CustomWorldData/mod_CustomWorldData.h"
|
||||
#include <WorldSessionMgr.h>
|
||||
|
||||
|
||||
std::vector<GobScriptTemplate> GobScriptVec;
|
||||
#include <Scripting/ScriptMgrMacros.h>
|
||||
|
||||
void CustomScript::LoadGobScripts()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
GobScriptVec.clear();
|
||||
GobScriptMap.clear();
|
||||
QueryResult result = WorldDatabase.Query("SELECT 物体ID,动作类型,动作参数1,动作参数2 FROM acore_custom._自定义AI_物体");
|
||||
|
||||
if (result)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
GobScriptTemplate Temp;
|
||||
Temp.ID = fields[0].Get<int32>();
|
||||
GobScriptTemplate temp;
|
||||
temp.ID = fields[0].Get<int32>();
|
||||
|
||||
std::string str2 = fields[1].Get<std::string>();
|
||||
if (!str2.empty())
|
||||
{
|
||||
if (strcmp("传送玩家", str2.c_str()) == 0)
|
||||
Temp.gobActionType = gob_ACTION_TYPE_TELE;
|
||||
temp.gobActionType = gob_ACTION_TYPE_TELE;
|
||||
else if (strcmp("激活或使失活", str2.c_str()) == 0)
|
||||
Temp.gobActionType = gob_ACTION_TYPE_ACTIVE_OR_DEACTIVE_OBJECT;
|
||||
temp.gobActionType = gob_ACTION_TYPE_ACTIVE_OR_DEACTIVE_OBJECT;
|
||||
else if (strcmp("释放技能", str2.c_str()) == 0)
|
||||
Temp.gobActionType = gob_ACTION_TYPE_AURA;
|
||||
temp.gobActionType = gob_ACTION_TYPE_AURA;
|
||||
else if (strcmp("说话", str2.c_str()) == 0)
|
||||
Temp.gobActionType = gob_ACTION_TALK;
|
||||
temp.gobActionType = gob_ACTION_TALK;
|
||||
else if (strcmp("召唤", str2.c_str()) == 0)
|
||||
Temp.gobActionType = gob_ACTION_SUMMON;
|
||||
temp.gobActionType = gob_ACTION_SUMMON;
|
||||
else
|
||||
Temp.gobActionType = gob_ACTION_TYPE_NONE;
|
||||
temp.gobActionType = gob_ACTION_TYPE_NONE;
|
||||
}
|
||||
|
||||
Temp.actionParam1 = fields[2].Get<std::string>();
|
||||
Temp.actionParam2 = fields[3].Get<int32>();
|
||||
temp.actionParam1 = fields[2].Get<std::string>();
|
||||
temp.actionParam2 = fields[3].Get<int32>();
|
||||
|
||||
// 按entry分组存储
|
||||
uint32 entry = abs(temp.ID);
|
||||
GobScriptMap[entry].push_back(temp);
|
||||
|
||||
GobScriptVec.push_back(Temp);
|
||||
} while (result->NextRow());
|
||||
sLog->outMessage("server", LogLevel::LOG_LEVEL_INFO, ">> 读取自定义功能数据表【_自定义AI_物体------------】,共{}条数据读取加载,用时{}毫秒", GobScriptVec.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
sLog->outMessage("server", LogLevel::LOG_LEVEL_INFO,
|
||||
">> 读取自定义功能数据表【_自定义AI_物体】,共{}个物体,{}条脚本数据,用时{}毫秒",
|
||||
GobScriptMap.size(),
|
||||
[this]() {
|
||||
uint32 total = 0;
|
||||
for (const auto& pair : GobScriptMap)
|
||||
total += pair.second.size();
|
||||
return total;
|
||||
}(),
|
||||
GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
}
|
||||
|
||||
class CustomGameObject : PlayerScript
|
||||
bool CustomScript::HasCustomScript(uint32 entry)
|
||||
{
|
||||
public:
|
||||
CustomGameObject() : PlayerScript("CustomGameObject") {}
|
||||
auto it = GobScriptMap.find(entry);
|
||||
return it != GobScriptMap.end() && !it->second.empty();
|
||||
}
|
||||
|
||||
void OnUseGameObject(Player* player, GameObject* gob)
|
||||
void CustomScript::ExecuteScript(Player* player, GameObject* gob)
|
||||
{
|
||||
uint32 entry = gob->GetEntry();
|
||||
int32 guid = gob->GetGUID().GetCounter();
|
||||
|
||||
// 快速查找对应的脚本
|
||||
auto it = GobScriptMap.find(entry);
|
||||
if (it == GobScriptMap.end())
|
||||
return;
|
||||
|
||||
for (const auto& script : it->second)
|
||||
{
|
||||
uint32 entry = gob->GetEntry();
|
||||
int32 guid = gob->GetGUID();
|
||||
// 检查是否匹配entry或guid
|
||||
if (script.ID != entry && guid != abs(script.ID))
|
||||
continue;
|
||||
|
||||
for (std::vector<GobScriptTemplate>::iterator itr = GobScriptVec.begin(); itr != GobScriptVec.end(); ++itr)
|
||||
int32 i_actionParam1 = atoi(script.actionParam1.c_str());
|
||||
std::string s_actionParam1 = script.actionParam1;
|
||||
int32 i_actionParam2 = script.actionParam2;
|
||||
|
||||
switch (script.gobActionType)
|
||||
{
|
||||
int32 ID = itr->ID;
|
||||
case gob_ACTION_TYPE_AURA:
|
||||
player->CastSpell(player, i_actionParam1, true);
|
||||
if (i_actionParam2 > 0)
|
||||
player->CastSpell(player, i_actionParam2, true);
|
||||
break;
|
||||
|
||||
if (ID != entry && guid != abs(ID))
|
||||
continue;
|
||||
|
||||
int32 i_actionParam1 = atoi(itr->actionParam1.c_str());
|
||||
std::string s_actionParam1 = itr->actionParam1;
|
||||
int32 i_actionParam2 = itr->actionParam2;
|
||||
|
||||
GobActionTypes gobActionType = itr->gobActionType;
|
||||
switch (gobActionType)
|
||||
case gob_ACTION_TYPE_TELE:
|
||||
if (!player->HasAura(i_actionParam2))
|
||||
{
|
||||
case gob_ACTION_TYPE_AURA:
|
||||
player->AddAura(i_actionParam1, player);
|
||||
player->AddAura(i_actionParam2, player);
|
||||
break;
|
||||
case gob_ACTION_TYPE_TELE:
|
||||
if (!player->HasAura(i_actionParam2))
|
||||
{
|
||||
player->AddAura(i_actionParam2, player);
|
||||
Tele(player, i_actionParam1);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "|cFFFF1717[" << gob->GetName() << "]|r正处于冷却中,传送失败...";
|
||||
player->GetSession()->SendAreaTriggerMessage(oss.str().c_str());
|
||||
}
|
||||
break;
|
||||
case gob_ACTION_TYPE_ACTIVE_OR_DEACTIVE_OBJECT:
|
||||
Tele(player, i_actionParam1);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 guid = abs(i_actionParam1);
|
||||
bool isCreature = i_actionParam2 == 0 ? true : false;
|
||||
bool active = i_actionParam1 > 0 ? true : false;
|
||||
std::ostringstream oss;
|
||||
oss << "|cFFFF1717[" << gob->GetName() << "]|r正处于冷却中,传送失败...";
|
||||
player->GetSession()->SendAreaTriggerMessage(oss.str().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
/*if (isCreature)
|
||||
{
|
||||
if (CreatureData const* data = sObjectMgr->GetCreatureData(guid))
|
||||
if (Creature* target = ObjectAccessor::GetObjectInWorld(MAKE_NEW_GUID(guid, data->id, HIGHGUID_UNIT), (Creature*)NULL))
|
||||
active ? target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE) : target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GameObjectData const* data = sObjectMgr->GetGOData(guid))
|
||||
if (GameObject* target = ObjectAccessor::GetObjectInWorld(MAKE_NEW_GUID(guid, data->id, HIGHGUID_GAMEOBJECT), (GameObject*)NULL))
|
||||
active ? target->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE) : target->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
}*/
|
||||
case gob_ACTION_TYPE_ACTIVE_OR_DEACTIVE_OBJECT:
|
||||
{
|
||||
uint32 targetGuid = abs(i_actionParam1);
|
||||
bool isCreature = i_actionParam2 == 0;
|
||||
bool active = i_actionParam1 > 0;
|
||||
|
||||
if (isCreature)
|
||||
if (isCreature)
|
||||
{
|
||||
if (CreatureData const* data = sObjectMgr->GetCreatureData(targetGuid))
|
||||
{
|
||||
if (CreatureData const* data = sObjectMgr->GetCreatureData(guid))
|
||||
ObjectGuid creatureGuid = ObjectGuid(HighGuid::Unit, data->id1, targetGuid);
|
||||
if (Creature* target = ObjectAccessor::GetCreature(*player, creatureGuid))
|
||||
{
|
||||
ObjectGuid creatureGuid = ObjectGuid(HighGuid::Unit, data->id1, static_cast<uint32>(guid));
|
||||
// 使用GUID获取Creature
|
||||
if (Creature* target = ObjectAccessor::GetCreature(*player, creatureGuid))
|
||||
{
|
||||
active ? target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE) : target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GameObjectData const* data = sObjectMgr->GetGameObjectData(guid))
|
||||
{
|
||||
ObjectGuid gameObjectGuid = ObjectGuid(HighGuid::GameObject, data->id, static_cast<uint32>(guid));
|
||||
// 使用GUID获取GameObject
|
||||
if (GameObject* target = ObjectAccessor::GetGameObject(*player, gameObjectGuid))
|
||||
{
|
||||
active ? target->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE) : target->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
if (active)
|
||||
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
else
|
||||
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case gob_ACTION_TALK:
|
||||
|
||||
switch (i_actionParam2)
|
||||
{
|
||||
// 1zone text 2 中间刷屏 3 两者都有
|
||||
case 1:
|
||||
sWorldSessionMgr->SendZoneText(player->GetZoneId(), s_actionParam1.c_str());
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
WorldSessionMgr::SessionMap m_sessions = sWorldSessionMgr->GetAllSessions();
|
||||
for (WorldSessionMgr::SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
|
||||
{
|
||||
if (!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld() || itr->second->GetPlayer()->GetZoneId() != gob->GetZoneId())
|
||||
continue;
|
||||
itr->second->SendAreaTriggerMessage(s_actionParam1.c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
WorldSessionMgr::SessionMap m_sessions = sWorldSessionMgr->GetAllSessions();
|
||||
for (WorldSessionMgr::SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
|
||||
{
|
||||
if (!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld() || itr->second->GetPlayer()->GetZoneId() != gob->GetZoneId())
|
||||
continue;
|
||||
itr->second->SendAreaTriggerMessage(s_actionParam1.c_str());
|
||||
}
|
||||
|
||||
sWorldSessionMgr->SendZoneText(player->GetZoneId(), s_actionParam1.c_str());
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
sCustomWorldData->SendScreenMessage(s_actionParam1.c_str());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case gob_ACTION_SUMMON:
|
||||
else
|
||||
{
|
||||
bool isCreature = i_actionParam1 > 0 ? true : false;
|
||||
uint32 entry = abs(i_actionParam1);
|
||||
uint32 despawntime = i_actionParam2 * MINUTE * IN_MILLISECONDS;
|
||||
|
||||
if (isCreature)
|
||||
gob->SummonCreature(entry, gob->GetPositionX(), gob->GetPositionY(), gob->GetPositionZ(), gob->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, despawntime);
|
||||
else
|
||||
gob->SummonGameObject(entry, gob->GetPositionX(), gob->GetPositionY(), gob->GetPositionZ(), gob->GetOrientation(), 0, 0, 0, 0, despawntime);
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (GameObjectData const* data = sObjectMgr->GetGameObjectData(targetGuid))
|
||||
{
|
||||
ObjectGuid gameObjectGuid = ObjectGuid(HighGuid::GameObject, data->id, targetGuid);
|
||||
if (GameObject* target = ObjectAccessor::GetGameObject(*player, gameObjectGuid))
|
||||
{
|
||||
if (active)
|
||||
target->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
else
|
||||
target->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_TALK:
|
||||
switch (i_actionParam2)
|
||||
{
|
||||
case 1:
|
||||
sWorldSessionMgr->SendZoneText(player->GetZoneId(), s_actionParam1.c_str());
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
WorldSessionMgr::SessionMap m_sessions = sWorldSessionMgr->GetAllSessions();
|
||||
for (auto const& session : m_sessions)
|
||||
{
|
||||
if (!session.second || !session.second->GetPlayer() ||
|
||||
!session.second->GetPlayer()->IsInWorld() ||
|
||||
session.second->GetPlayer()->GetZoneId() != gob->GetZoneId())
|
||||
continue;
|
||||
session.second->SendAreaTriggerMessage(s_actionParam1.c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
WorldSessionMgr::SessionMap m_sessions = sWorldSessionMgr->GetAllSessions();
|
||||
for (auto const& session : m_sessions)
|
||||
{
|
||||
if (!session.second || !session.second->GetPlayer() ||
|
||||
!session.second->GetPlayer()->IsInWorld() ||
|
||||
session.second->GetPlayer()->GetZoneId() != gob->GetZoneId())
|
||||
continue;
|
||||
session.second->SendAreaTriggerMessage(s_actionParam1.c_str());
|
||||
}
|
||||
sWorldSessionMgr->SendZoneText(player->GetZoneId(), s_actionParam1.c_str());
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
sCustomWorldData->SendScreenMessage(s_actionParam1.c_str());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_SUMMON:
|
||||
{
|
||||
bool isCreature = i_actionParam1 > 0;
|
||||
uint32 summonEntry = abs(i_actionParam1);
|
||||
uint32 despawntime = i_actionParam2 * MINUTE * IN_MILLISECONDS;
|
||||
|
||||
if (isCreature)
|
||||
gob->SummonCreature(summonEntry, gob->GetPositionX(), gob->GetPositionY(),
|
||||
gob->GetPositionZ(), gob->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, despawntime);
|
||||
else
|
||||
gob->SummonGameObject(summonEntry, gob->GetPositionX(), gob->GetPositionY(),
|
||||
gob->GetPositionZ(), gob->GetOrientation(), 0, 0, 0, 0, despawntime);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Tele(Player* player, uint32 telePosId)
|
||||
void CustomScript::Tele(Player* player, uint32 telePosId)
|
||||
{
|
||||
// 这里需要访问PosMap,可能需要从Event模块获取
|
||||
// 或者重新设计传送位置的获取方式
|
||||
if (sEvent)
|
||||
{
|
||||
std::unordered_map<uint32, PosTemplate>::iterator it = PosMap.find(telePosId);
|
||||
|
||||
if (it != PosMap.end())
|
||||
player->TeleportTo(it->second.map, it->second.x, it->second.y, it->second.z, it->second.o);
|
||||
uint32 map;
|
||||
float x, y, z, o;
|
||||
sEvent->GetTelePos(telePosId, map, x, y, z, o);
|
||||
player->TeleportTo(map, x, y, z, o);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class KeyStone :public GameObjectScript
|
||||
class CustomGameObjectHook : public AllGameObjectScript
|
||||
{
|
||||
public:
|
||||
KeyStone() : GameObjectScript("KeyStone") { }
|
||||
CustomGameObjectHook() : AllGameObjectScript("CustomGameObjectHook") {}
|
||||
|
||||
bool OnGossipHello(Player* player, GameObject* go) override
|
||||
void OnGameObjectAddWorld(GameObject* go) override
|
||||
{
|
||||
if (Creature* target = go->FindNearestCreature(1, 5.0f))
|
||||
{
|
||||
go->CastSpell(target, 64986);
|
||||
target->SetVisible(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!go)
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* player, GameObject* go, uint32 sender, uint32 action) override
|
||||
bool CanGameObjectGossipHello(Player* player, GameObject* go) override
|
||||
{
|
||||
|
||||
return true;
|
||||
// 检查是否有自定义脚本
|
||||
if (sCustomScript->HasCustomScript(go->GetEntry()))
|
||||
{
|
||||
sCustomScript->ExecuteScript(player, go);
|
||||
return true; // 阻止默认处理
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_CustomGameObjectScript()
|
||||
{
|
||||
new KeyStone();
|
||||
new CustomGameObject();
|
||||
new CustomGameObjectHook();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user