mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/SAI: Implemented new action SMART_ACTION_COMPLETE_QUEST (#30048)
This commit is contained in:
2
sql/updates/world/master/2024_08_15_00_world.sql
Normal file
2
sql/updates/world/master/2024_08_15_00_world.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
UPDATE `smart_scripts` SET `action_type`=152, `target_type`=16 WHERE `action_type`=26 AND `target_type`=7;
|
||||
UPDATE `smart_scripts` SET `action_type`=152 WHERE `action_type`=15;
|
||||
@@ -575,27 +575,6 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS:
|
||||
{
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
// Special handling for vehicles
|
||||
if (IsUnit(target))
|
||||
if (Vehicle* vehicle = target->ToUnit()->GetVehicleKit())
|
||||
for (std::pair<int8 const, VehicleSeat>& seat : vehicle->Seats)
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*target, seat.second.Passenger.Guid))
|
||||
player->AreaExploredOrEventHappens(e.action.quest.quest);
|
||||
|
||||
if (IsPlayer(target))
|
||||
{
|
||||
target->ToPlayer()->AreaExploredOrEventHappens(e.action.quest.quest);
|
||||
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: Player {} credited quest {}",
|
||||
target->GetGUID().ToString(), e.action.quest.quest);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_CAST:
|
||||
{
|
||||
if (targets.empty())
|
||||
@@ -869,27 +848,6 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature {} DoFleeToGetAssistance", me->GetGUID().ToString());
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_CALL_GROUPEVENTHAPPENS:
|
||||
{
|
||||
if (!unit)
|
||||
break;
|
||||
|
||||
// If invoker was pet or charm
|
||||
Player* playerCharmed = unit->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
if (playerCharmed && GetBaseObject())
|
||||
{
|
||||
playerCharmed->GroupEventHappens(e.action.quest.quest, GetBaseObject());
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_GROUPEVENTHAPPENS: Player {}, group credit for quest {}",
|
||||
unit->GetGUID().ToString(), e.action.quest.quest);
|
||||
}
|
||||
|
||||
// Special handling for vehicles
|
||||
if (Vehicle* vehicle = unit->GetVehicleKit())
|
||||
for (std::pair<int8 const, VehicleSeat>& seat : vehicle->Seats)
|
||||
if (Player* passenger = ObjectAccessor::GetPlayer(*unit, seat.second.Passenger.Guid))
|
||||
passenger->GroupEventHappens(e.action.quest.quest, GetBaseObject());
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_COMBAT_STOP:
|
||||
{
|
||||
if (!me)
|
||||
@@ -2637,6 +2595,34 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_COMPLETE_QUEST:
|
||||
{
|
||||
uint32 questId = e.action.quest.quest;
|
||||
Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
|
||||
if (!quest)
|
||||
break;
|
||||
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
Player* player = Object::ToPlayer(target);
|
||||
if (!player)
|
||||
continue;
|
||||
|
||||
QuestStatus questStatus = player->GetQuestStatus(questId);
|
||||
if (questStatus == QUEST_STATUS_REWARDED)
|
||||
continue;
|
||||
|
||||
if (quest->HasFlag(QUEST_FLAGS_COMPLETION_EVENT) || quest->HasFlag(QUEST_FLAGS_COMPLETION_AREA_TRIGGER))
|
||||
{
|
||||
if (questStatus == QUEST_STATUS_INCOMPLETE)
|
||||
player->AreaExploredOrEventHappens(questId);
|
||||
}
|
||||
else if (quest->HasFlag(QUEST_FLAGS_TRACKING_EVENT)) // Check if the quest is used as a serverside flag
|
||||
player->CompleteQuest(questId);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
TC_LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||
break;
|
||||
|
||||
@@ -340,7 +340,6 @@ void SmartAIMgr::LoadSmartAIFromDB()
|
||||
}
|
||||
break;
|
||||
case SMART_EVENT_VICTIM_CASTING:
|
||||
case SMART_EVENT_IS_BEHIND_TARGET:
|
||||
if (temp.event.minMaxRepeat.min == 0 && temp.event.minMaxRepeat.max == 0 && !(temp.event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE) && temp.source_type != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST)
|
||||
{
|
||||
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
|
||||
@@ -910,7 +909,6 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_SUMMON_CREATURE: return sizeof(SmartAction::summonCreature);
|
||||
case SMART_ACTION_THREAT_SINGLE_PCT: return sizeof(SmartAction::threatPCT);
|
||||
case SMART_ACTION_THREAT_ALL_PCT: return sizeof(SmartAction::threatPCT);
|
||||
case SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: return sizeof(SmartAction::quest);
|
||||
case SMART_ACTION_SET_INGAME_PHASE_GROUP: return sizeof(SmartAction::ingamePhaseGroup);
|
||||
case SMART_ACTION_SET_EMOTE_STATE: return sizeof(SmartAction::emote);
|
||||
case SMART_ACTION_AUTO_ATTACK: return sizeof(SmartAction::autoAttack);
|
||||
@@ -919,7 +917,6 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_INC_EVENT_PHASE: return sizeof(SmartAction::incEventPhase);
|
||||
case SMART_ACTION_EVADE: return sizeof(SmartAction::evade);
|
||||
case SMART_ACTION_FLEE_FOR_ASSIST: return sizeof(SmartAction::fleeAssist);
|
||||
case SMART_ACTION_CALL_GROUPEVENTHAPPENS: return sizeof(SmartAction::quest);
|
||||
case SMART_ACTION_COMBAT_STOP: return NO_PARAMS;
|
||||
case SMART_ACTION_REMOVEAURASFROMSPELL: return sizeof(SmartAction::removeAura);
|
||||
case SMART_ACTION_FOLLOW: return sizeof(SmartAction::follow);
|
||||
@@ -1028,6 +1025,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_BECOME_PERSONAL_CLONE_FOR_PLAYER: return sizeof(SmartAction::becomePersonalClone);
|
||||
case SMART_ACTION_TRIGGER_GAME_EVENT: return sizeof(SmartAction::triggerGameEvent);
|
||||
case SMART_ACTION_DO_ACTION: return sizeof(SmartAction::doAction);
|
||||
case SMART_ACTION_COMPLETE_QUEST: return sizeof(SmartAction::quest);
|
||||
default:
|
||||
TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.",
|
||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||
@@ -1792,22 +1790,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS:
|
||||
case SMART_ACTION_CALL_GROUPEVENTHAPPENS:
|
||||
if (Quest const* qid = sObjectMgr->GetQuestTemplate(e.action.quest.quest))
|
||||
{
|
||||
if (!qid->HasFlag(QUEST_FLAGS_COMPLETION_EVENT) && !qid->HasFlag(QUEST_FLAGS_COMPLETION_AREA_TRIGGER))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} Flags for Quest entry {} does not include QUEST_FLAGS_COMPLETION_EVENT or QUEST_FLAGS_COMPLETION_AREA_TRIGGER, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.quest.quest);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Quest entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.quest.quest);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case SMART_ACTION_SET_EVENT_PHASE:
|
||||
if (e.action.setEventPhase.phase >= SMART_EVENT_PHASE_MAX)
|
||||
{
|
||||
@@ -2465,7 +2447,24 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
TC_SAI_IS_BOOLEAN_VALID(e, e.action.triggerGameEvent.useSaiTargetAsGameEventSource);
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_COMPLETE_QUEST:
|
||||
if (Quest const* quest = sObjectMgr->GetQuestTemplate(e.action.quest.quest))
|
||||
{
|
||||
if (!quest->HasFlag(QUEST_FLAGS_COMPLETION_EVENT) && !quest->HasFlag(QUEST_FLAGS_COMPLETION_AREA_TRIGGER) && !quest->HasFlag(QUEST_FLAGS_TRACKING_EVENT))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} Flags for Quest entry {} does not include QUEST_FLAGS_COMPLETION_EVENT or QUEST_FLAGS_COMPLETION_AREA_TRIGGER or QUEST_FLAGS_TRACKING_EVENT, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.quest.quest);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Quest entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.quest.quest);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
// Unused
|
||||
case SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS:
|
||||
case SMART_ACTION_CALL_GROUPEVENTHAPPENS:
|
||||
case SMART_ACTION_SET_UNIT_FLAG:
|
||||
case SMART_ACTION_REMOVE_UNIT_FLAG:
|
||||
case SMART_ACTION_INSTALL_AI_TEMPLATE:
|
||||
|
||||
@@ -472,7 +472,7 @@ enum SMART_ACTION
|
||||
SMART_ACTION_SUMMON_CREATURE = 12, // CreatureID, summonType, duration in ms, attackInvoker, flags(SmartActionSummonCreatureFlags)
|
||||
SMART_ACTION_THREAT_SINGLE_PCT = 13, // Threat%
|
||||
SMART_ACTION_THREAT_ALL_PCT = 14, // Threat%
|
||||
SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS = 15, // QuestID
|
||||
SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS = 15, // UNUSED, DO NOT REUSE
|
||||
SMART_ACTION_SET_INGAME_PHASE_GROUP = 16, // phaseGroupId, apply
|
||||
SMART_ACTION_SET_EMOTE_STATE = 17, // emoteID
|
||||
SMART_ACTION_SET_UNIT_FLAG = 18, // UNUSED, DO NOT REUSE
|
||||
@@ -483,7 +483,7 @@ enum SMART_ACTION
|
||||
SMART_ACTION_INC_EVENT_PHASE = 23, // Value (may be negative to decrement phase, should not be 0)
|
||||
SMART_ACTION_EVADE = 24, // toRespawnPosition (0 = Move to RespawnPosition, 1 = Move to last stored home position)
|
||||
SMART_ACTION_FLEE_FOR_ASSIST = 25, // With Emote
|
||||
SMART_ACTION_CALL_GROUPEVENTHAPPENS = 26, // QuestID
|
||||
SMART_ACTION_CALL_GROUPEVENTHAPPENS = 26, // UNUSED, DO NOT REUSE
|
||||
SMART_ACTION_COMBAT_STOP = 27, //
|
||||
SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid (0 removes all auras), charges (0 removes aura)
|
||||
SMART_ACTION_FOLLOW = 29, // Distance (0 = default), Angle (0 = default), EndCreatureEntry, credit, creditType (0monsterkill, 1event)
|
||||
@@ -609,7 +609,8 @@ enum SMART_ACTION
|
||||
SMART_ACTION_BECOME_PERSONAL_CLONE_FOR_PLAYER = 149, // summonType 1-8, duration in ms
|
||||
SMART_ACTION_TRIGGER_GAME_EVENT = 150, // eventId, useSaiTargetAsGameEventSource
|
||||
SMART_ACTION_DO_ACTION = 151, // actionId
|
||||
SMART_ACTION_END = 152
|
||||
SMART_ACTION_COMPLETE_QUEST = 152, // QuestId. Regular quests with objectives can't be completed with this action (only quests with QUEST_FLAGS_COMPLETION_EVENT, QUEST_FLAGS_COMPLETION_AREA_TRIGGER or QUEST_FLAGS_TRACKING_EVENT)
|
||||
SMART_ACTION_END = 153
|
||||
};
|
||||
|
||||
enum class SmartActionSummonCreatureFlags
|
||||
|
||||
@@ -3690,11 +3690,17 @@ void Spell::EffectQuestComplete()
|
||||
if (!quest)
|
||||
return;
|
||||
|
||||
uint16 logSlot = player->FindQuestSlot(questId);
|
||||
if (logSlot < MAX_QUEST_LOG_SIZE)
|
||||
player->AreaExploredOrEventHappens(questId);
|
||||
else if (quest->HasFlag(QUEST_FLAGS_TRACKING_EVENT)) // Check if the quest is used as a serverside flag.
|
||||
player->SetRewardedQuest(questId); // If so, set status to rewarded without broadcasting it to client.
|
||||
QuestStatus questStatus = player->GetQuestStatus(questId);
|
||||
if (questStatus == QUEST_STATUS_REWARDED)
|
||||
return;
|
||||
|
||||
if (quest->HasFlag(QUEST_FLAGS_COMPLETION_EVENT) || quest->HasFlag(QUEST_FLAGS_COMPLETION_AREA_TRIGGER))
|
||||
{
|
||||
if (questStatus == QUEST_STATUS_INCOMPLETE)
|
||||
player->AreaExploredOrEventHappens(questId);
|
||||
}
|
||||
else if (quest->HasFlag(QUEST_FLAGS_TRACKING_EVENT)) // Check if the quest is used as a serverside flag
|
||||
player->CompleteQuest(questId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user