优化[自定义AI_物体]
1、扩展更多类型 2、添加param3和param4字段,作为条件扩展
This commit is contained in:
parent
604f8cd01f
commit
48a36cd260
@ -4,11 +4,24 @@
|
||||
enum GobActionTypes
|
||||
{
|
||||
gob_ACTION_TYPE_NONE,
|
||||
gob_ACTION_TYPE_AURA, //释放技能 AuraID1, AuraID2,
|
||||
gob_ACTION_TYPE_TELE, //传送玩家 TelePosId TeleAura
|
||||
gob_ACTION_TYPE_ACTIVE_OR_DEACTIVE_OBJECT, //激活或使失活 CreatureEntry GameObjectEntry
|
||||
gob_ACTION_TYPE_CAST_SPELL, // 修正:真正的技能释放 AuraID1, AuraID2,
|
||||
gob_ACTION_TYPE_ADD_AURA, // 新增:直接添加光环 AuraID1, AuraID2,
|
||||
gob_ACTION_TYPE_TELE, // 传送玩家 TelePosId TeleAura
|
||||
gob_ACTION_TYPE_ACTIVE_OR_DEACTIVE_OBJECT, // 激活或使失活 CreatureEntry GameObjectEntry
|
||||
gob_ACTION_TALK,
|
||||
gob_ACTION_SUMMON,
|
||||
|
||||
// 新增
|
||||
gob_ACTION_TYPE_GIVE_ITEM, // 给予物品
|
||||
gob_ACTION_TYPE_REMOVE_ITEM, // 移除物品
|
||||
gob_ACTION_TYPE_LEARN_SPELL, // 学习技能
|
||||
gob_ACTION_TYPE_UNLEARN_SPELL, // 遗忘技能
|
||||
gob_ACTION_TYPE_ADD_MONEY, // 给予金钱
|
||||
gob_ACTION_TYPE_REMOVE_MONEY, // 扣除金钱
|
||||
gob_ACTION_TYPE_SET_PHASE, // 设置相位
|
||||
gob_ACTION_TYPE_MORPH, // 变形
|
||||
gob_ACTION_TYPE_DEMORPH, // 取消变形
|
||||
gob_ACTION_TYPE_PLAYER_EMOTE, // 随机执行动
|
||||
};
|
||||
|
||||
|
||||
@ -18,9 +31,10 @@ struct GobScriptTemplate
|
||||
GobActionTypes gobActionType;
|
||||
std::string actionParam1;
|
||||
int32 actionParam2;
|
||||
};
|
||||
|
||||
extern std::vector<GobScriptTemplate> GobScriptVec;
|
||||
int32 actionParam3; // 新增第三个参数
|
||||
std::string actionParam4; // 新增第四个参数
|
||||
};
|
||||
|
||||
enum CreatureEventTypes
|
||||
{ // eventPhase delayTime repeatMinTime repeatMaxTime
|
||||
@ -151,11 +165,13 @@ public:
|
||||
|
||||
bool HasCustomScript(uint32 entry);
|
||||
void ExecuteScript(Player* player, GameObject* gob);
|
||||
private:
|
||||
|
||||
private:
|
||||
// 使用unordered_map按entry分组存储,提高查找效率
|
||||
std::unordered_map<uint32, std::vector<GobScriptTemplate>> GobScriptMap;
|
||||
void Tele(Player* player, uint32 telePosId);
|
||||
|
||||
bool CheckCondition(Player* player, int32 conditionType, int32 value);
|
||||
|
||||
};
|
||||
#define sCustomScript CustomScript::instance()
|
||||
|
||||
@ -7,12 +7,14 @@
|
||||
#include "mod_CustomWorldData/mod_CustomWorldData.h"
|
||||
#include <WorldSessionMgr.h>
|
||||
#include <Scripting/ScriptMgrMacros.h>
|
||||
#include <Spells/SpellMgr.h>
|
||||
|
||||
void CustomScript::LoadGobScripts()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
GobScriptMap.clear();
|
||||
QueryResult result = WorldDatabase.Query("SELECT 物体ID,动作类型,动作参数1,动作参数2 FROM acore_custom._自定义AI_物体");
|
||||
|
||||
QueryResult result = WorldDatabase.Query("SELECT 物体ID,动作类型,动作参数1,动作参数2,动作参数3,动作参数4 FROM acore_custom._自定义AI_物体");
|
||||
|
||||
if (result)
|
||||
{
|
||||
@ -22,25 +24,47 @@ void CustomScript::LoadGobScripts()
|
||||
GobScriptTemplate temp;
|
||||
temp.ID = fields[0].Get<int32>();
|
||||
|
||||
std::string str2 = fields[1].Get<std::string>();
|
||||
if (!str2.empty())
|
||||
std::string actionTypeStr = fields[1].Get<std::string>();
|
||||
if (!actionTypeStr.empty())
|
||||
{
|
||||
if (strcmp("传送玩家", str2.c_str()) == 0)
|
||||
if (actionTypeStr == "传送玩家")
|
||||
temp.gobActionType = gob_ACTION_TYPE_TELE;
|
||||
else if (strcmp("激活或使失活", str2.c_str()) == 0)
|
||||
else if (actionTypeStr == "激活或使失活")
|
||||
temp.gobActionType = gob_ACTION_TYPE_ACTIVE_OR_DEACTIVE_OBJECT;
|
||||
else if (strcmp("释放技能", str2.c_str()) == 0)
|
||||
temp.gobActionType = gob_ACTION_TYPE_AURA;
|
||||
else if (strcmp("说话", str2.c_str()) == 0)
|
||||
else if (actionTypeStr == "添加光环")
|
||||
temp.gobActionType = gob_ACTION_TYPE_ADD_AURA;
|
||||
else if (actionTypeStr == "说话")
|
||||
temp.gobActionType = gob_ACTION_TALK;
|
||||
else if (strcmp("召唤", str2.c_str()) == 0)
|
||||
else if (actionTypeStr == "召唤")
|
||||
temp.gobActionType = gob_ACTION_SUMMON;
|
||||
else if (actionTypeStr == "给予物品")
|
||||
temp.gobActionType = gob_ACTION_TYPE_GIVE_ITEM;
|
||||
else if (actionTypeStr == "移除物品")
|
||||
temp.gobActionType = gob_ACTION_TYPE_REMOVE_ITEM;
|
||||
else if (actionTypeStr == "学习技能")
|
||||
temp.gobActionType = gob_ACTION_TYPE_LEARN_SPELL;
|
||||
else if (actionTypeStr == "遗忘技能")
|
||||
temp.gobActionType = gob_ACTION_TYPE_UNLEARN_SPELL;
|
||||
else if (actionTypeStr == "给予金钱")
|
||||
temp.gobActionType = gob_ACTION_TYPE_ADD_MONEY;
|
||||
else if (actionTypeStr == "扣除金钱")
|
||||
temp.gobActionType = gob_ACTION_TYPE_REMOVE_MONEY;
|
||||
else if (actionTypeStr == "设置相位")
|
||||
temp.gobActionType = gob_ACTION_TYPE_SET_PHASE;
|
||||
else if (actionTypeStr == "变形")
|
||||
temp.gobActionType = gob_ACTION_TYPE_MORPH;
|
||||
else if (actionTypeStr == "取消变形")
|
||||
temp.gobActionType = gob_ACTION_TYPE_DEMORPH;
|
||||
else if (actionTypeStr == "表情")
|
||||
temp.gobActionType = gob_ACTION_TYPE_PLAYER_EMOTE;
|
||||
else
|
||||
temp.gobActionType = gob_ACTION_TYPE_NONE;
|
||||
}
|
||||
|
||||
temp.actionParam1 = fields[2].Get<std::string>();
|
||||
temp.actionParam2 = fields[3].Get<int32>();
|
||||
temp.actionParam3 = fields[4].Get<int32>();
|
||||
temp.actionParam4 = fields[5].Get<std::string>();
|
||||
|
||||
// 按entry分组存储
|
||||
uint32 entry = abs(temp.ID);
|
||||
@ -69,6 +93,9 @@ bool CustomScript::HasCustomScript(uint32 entry)
|
||||
|
||||
void CustomScript::ExecuteScript(Player* player, GameObject* gob)
|
||||
{
|
||||
if (!player || !gob)
|
||||
return;
|
||||
|
||||
uint32 entry = gob->GetEntry();
|
||||
int32 guid = gob->GetGUID().GetCounter();
|
||||
|
||||
@ -83,31 +110,218 @@ void CustomScript::ExecuteScript(Player* player, GameObject* gob)
|
||||
if (script.ID != entry && guid != abs(script.ID))
|
||||
continue;
|
||||
|
||||
// 条件检查 - 避免与特殊功能的param3使用冲突
|
||||
bool hasSpecialParam3Usage = (script.gobActionType == gob_ACTION_TYPE_TELE || script.gobActionType == gob_ACTION_TYPE_GIVE_ITEM || script.gobActionType == gob_ACTION_SUMMON);
|
||||
if (!hasSpecialParam3Usage && script.actionParam3 > 0)
|
||||
{
|
||||
if (!CheckCondition(player, script.actionParam3, atoi(script.actionParam4.c_str())))
|
||||
continue;
|
||||
}
|
||||
|
||||
int32 i_actionParam1 = atoi(script.actionParam1.c_str());
|
||||
std::string s_actionParam1 = script.actionParam1;
|
||||
int32 i_actionParam2 = script.actionParam2;
|
||||
int32 i_actionParam3 = script.actionParam3;
|
||||
std::string s_actionParam4 = script.actionParam4;
|
||||
|
||||
switch (script.gobActionType)
|
||||
{
|
||||
case gob_ACTION_TYPE_AURA:
|
||||
player->CastSpell(player, i_actionParam1, true);
|
||||
case gob_ACTION_TYPE_ADD_AURA:
|
||||
// 新增:专门用于添加光环
|
||||
if (i_actionParam1 > 0)
|
||||
player->AddAura(i_actionParam1, player);
|
||||
if (i_actionParam2 > 0)
|
||||
player->CastSpell(player, i_actionParam2, true);
|
||||
player->AddAura(i_actionParam2, player);
|
||||
break;
|
||||
|
||||
case gob_ACTION_TYPE_TELE:
|
||||
if (!player->HasAura(i_actionParam2))
|
||||
{
|
||||
uint32 cooldownSpell = i_actionParam2;
|
||||
uint32 requiredLevel = i_actionParam3; // 传送等级要求
|
||||
|
||||
// 等级检查
|
||||
if (requiredLevel > 0 && player->GetLevel() < requiredLevel)
|
||||
{
|
||||
player->AddAura(i_actionParam2, player);
|
||||
player->GetSession()->SendAreaTriggerMessage("等级不足,无法传送!");
|
||||
break;
|
||||
}
|
||||
|
||||
if (cooldownSpell > 0 && !player->HasAura(cooldownSpell))
|
||||
{
|
||||
player->AddAura(cooldownSpell, player);
|
||||
Tele(player, i_actionParam1);
|
||||
}
|
||||
else
|
||||
else if (cooldownSpell > 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "|cFFFF1717[" << gob->GetName() << "]|r正处于冷却中,传送失败...";
|
||||
player->GetSession()->SendAreaTriggerMessage(oss.str().c_str());
|
||||
}
|
||||
break;
|
||||
else
|
||||
{
|
||||
Tele(player, i_actionParam1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_TYPE_GIVE_ITEM:
|
||||
{
|
||||
uint32 itemId = i_actionParam1;
|
||||
uint32 count = i_actionParam2 > 0 ? i_actionParam2 : 1;
|
||||
uint32 requiredLevel = i_actionParam3; // 等级要求
|
||||
bool checkBagSpace = !s_actionParam4.empty() && s_actionParam4 == "checkbag"; // 背包检查
|
||||
|
||||
// 等级检查
|
||||
if (requiredLevel > 0 && player->GetLevel() < requiredLevel)
|
||||
{
|
||||
player->GetSession()->SendAreaTriggerMessage("等级不足,需要 {} 级", requiredLevel);
|
||||
break;
|
||||
}
|
||||
|
||||
// 背包空间检查
|
||||
if (checkBagSpace)
|
||||
{
|
||||
ItemPosCountVec dest;
|
||||
InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, count);
|
||||
if (msg != EQUIP_ERR_OK)
|
||||
{
|
||||
player->GetSession()->SendAreaTriggerMessage("背包空间不足!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId))
|
||||
{
|
||||
player->AddItem(itemId, count);
|
||||
std::ostringstream oss;
|
||||
oss << "获得物品:" << itemTemplate->Name1 << " x" << count;
|
||||
player->GetSession()->SendAreaTriggerMessage(oss.str().c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_TYPE_REMOVE_ITEM:
|
||||
{
|
||||
uint32 itemId = i_actionParam1;
|
||||
uint32 count = i_actionParam2 > 0 ? i_actionParam2 : 1;
|
||||
|
||||
if (player->HasItemCount(itemId, count))
|
||||
{
|
||||
player->DestroyItemCount(itemId, count, true);
|
||||
|
||||
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId))
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "失去物品:" << itemTemplate->Name1 << " x" << count;
|
||||
player->GetSession()->SendAreaTriggerMessage(oss.str().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player->GetSession()->SendAreaTriggerMessage("物品数量不足!");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_TYPE_LEARN_SPELL:
|
||||
{
|
||||
uint32 spellId = i_actionParam1;
|
||||
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
|
||||
{
|
||||
if (!player->HasSpell(spellId))
|
||||
{
|
||||
player->learnSpell(spellId, false);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "学会技能:" << spellInfo->SpellName[player->GetSession()->GetSessionDbcLocale()];
|
||||
player->GetSession()->SendAreaTriggerMessage(oss.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case gob_ACTION_TYPE_UNLEARN_SPELL:
|
||||
{
|
||||
uint32 spellId = i_actionParam1;
|
||||
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
|
||||
{
|
||||
if (player->HasSpell(spellId))
|
||||
{
|
||||
player->removeSpell(spellId, SPEC_MASK_ALL, false);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "遗忘技能:" << spellInfo->SpellName[player->GetSession()->GetSessionDbcLocale()];
|
||||
player->GetSession()->SendAreaTriggerMessage(oss.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_TYPE_ADD_MONEY:
|
||||
{
|
||||
uint32 money = i_actionParam1;
|
||||
if (money > 0)
|
||||
{
|
||||
player->ModifyMoney(money);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "获得金钱:" << money << " 铜币";
|
||||
player->GetSession()->SendAreaTriggerMessage(oss.str().c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_TYPE_REMOVE_MONEY:
|
||||
{
|
||||
uint32 money = i_actionParam1;
|
||||
if (money > 0 && player->HasEnoughMoney(money))
|
||||
{
|
||||
player->ModifyMoney(-int32(money));
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "失去金钱:" << money << " 铜币";
|
||||
player->GetSession()->SendAreaTriggerMessage(oss.str().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
player->GetSession()->SendAreaTriggerMessage("金钱不足!");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_TYPE_SET_PHASE:
|
||||
{
|
||||
uint32 phaseId = i_actionParam1;
|
||||
if (phaseId > 0)
|
||||
{
|
||||
player->SetPhaseMask(phaseId, true);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "设置相位:" << phaseId;
|
||||
player->GetSession()->SendAreaTriggerMessage(oss.str().c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_TYPE_MORPH:
|
||||
{
|
||||
uint32 displayId = i_actionParam1;
|
||||
if (displayId > 0)
|
||||
{
|
||||
player->SetDisplayId(displayId);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "变形为模型:" << displayId;
|
||||
player->GetSession()->SendAreaTriggerMessage(oss.str().c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_TYPE_DEMORPH:
|
||||
{
|
||||
player->DeMorph();
|
||||
player->GetSession()->SendAreaTriggerMessage("取消变形");
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_TYPE_ACTIVE_OR_DEACTIVE_OBJECT:
|
||||
{
|
||||
@ -190,19 +404,66 @@ void CustomScript::ExecuteScript(Player* player, GameObject* gob)
|
||||
bool isCreature = i_actionParam1 > 0;
|
||||
uint32 summonEntry = abs(i_actionParam1);
|
||||
uint32 despawntime = i_actionParam2 * MINUTE * IN_MILLISECONDS;
|
||||
uint32 summonCount = i_actionParam3 > 0 ? i_actionParam3 : 1; // 召唤数量
|
||||
float offsetRange = !s_actionParam4.empty() ? atof(s_actionParam4.c_str()) : 0.0f; // 位置偏移
|
||||
|
||||
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);
|
||||
for (uint32 i = 0; i < summonCount; ++i)
|
||||
{
|
||||
float x = gob->GetPositionX();
|
||||
float y = gob->GetPositionY();
|
||||
float z = gob->GetPositionZ();
|
||||
float o = gob->GetOrientation();
|
||||
|
||||
// 如果设置了偏移范围,随机偏移位置
|
||||
if (offsetRange > 0.0f)
|
||||
{
|
||||
float angle = frand(0.0f, 2 * M_PI);
|
||||
float distance = frand(0.0f, offsetRange);
|
||||
x += distance * cos(angle);
|
||||
y += distance * sin(angle);
|
||||
}
|
||||
|
||||
if (isCreature)
|
||||
gob->SummonCreature(summonEntry, x, y, z, o, TEMPSUMMON_TIMED_DESPAWN, despawntime);
|
||||
else
|
||||
gob->SummonGameObject(summonEntry, x, y, z, o, 0, 0, 0, 0, despawntime);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case gob_ACTION_TYPE_PLAYER_EMOTE:
|
||||
{
|
||||
uint32 emoteId = i_actionParam1; // 比如 EMOTE_ONESHOT_DANCE
|
||||
player->HandleEmoteCommand(emoteId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CustomScript::CheckCondition(Player* player, int32 conditionType, int32 value)
|
||||
{
|
||||
switch (conditionType)
|
||||
{
|
||||
case 1: // 等级检查
|
||||
return player->GetLevel() >= value;
|
||||
case 2: // 金钱检查
|
||||
return player->GetMoney() >= value;
|
||||
case 3: // 职业检查
|
||||
return player->getClass() == value;
|
||||
case 4: // 物品检查
|
||||
return player->HasItemCount(value, 1);
|
||||
case 5: // 任务状态检查
|
||||
return player->GetQuestStatus(value) == QUEST_STATUS_COMPLETE;
|
||||
case 6: // 光环检查
|
||||
return player->HasAura(value);
|
||||
case 7: // 技能检查
|
||||
return player->HasSpell(value);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CustomScript::Tele(Player* player, uint32 telePosId)
|
||||
{
|
||||
// 这里需要访问PosMap,可能需要从Event模块获取
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user