diff --git a/sql/migrations/20170531142831_world.sql b/sql/migrations/20170531142831_world.sql new file mode 100644 index 000000000..c5deedaaf --- /dev/null +++ b/sql/migrations/20170531142831_world.sql @@ -0,0 +1,30 @@ +INSERT INTO `migrations` VALUES ('20170531142831'); + +-- Quest flag for Sentinel Selarin is added after dialogue. +UPDATE `creature_template` SET `npcflag`=0 WHERE `entry`=3694; +-- Assign core script to Terenthis. +UPDATE `creature_template` SET `ScriptName`='npc_terenthis' WHERE `entry`=3693; + +-- Waypoints for Sentinel Selarin. +INSERT INTO `creature_movement_template` (`entry`, `point`, `position_x`, `position_y`, `position_z`, `waittime`, `script_id`, `textid1`, `textid2`, `textid3`, `textid4`, `textid5`, `emote`, `spell`, `wpguid`, `orientation`, `model1`, `model2`) VALUES (3694, 1, 6422.38, 398.54, 11.162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `creature_movement_template` (`entry`, `point`, `position_x`, `position_y`, `position_z`, `waittime`, `script_id`, `textid1`, `textid2`, `textid3`, `textid4`, `textid5`, `emote`, `spell`, `wpguid`, `orientation`, `model1`, `model2`) VALUES (3694, 2, 6429.16, 395.69, 11.6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0); +INSERT INTO `creature_movement_template` (`entry`, `point`, `position_x`, `position_y`, `position_z`, `waittime`, `script_id`, `textid1`, `textid2`, `textid3`, `textid4`, `textid5`, `emote`, `spell`, `wpguid`, `orientation`, `model1`, `model2`) VALUES (3694, 3, 6437.87, 372.91, 13.941, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.581, 0, 0); +INSERT INTO `creature_movement_template` (`entry`, `point`, `position_x`, `position_y`, `position_z`, `waittime`, `script_id`, `textid1`, `textid2`, `textid3`, `textid4`, `textid5`, `emote`, `spell`, `wpguid`, `orientation`, `model1`, `model2`) VALUES (3694, 4, 6435.33, 365.925, 13.941, 19000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.471, 0, 0); +INSERT INTO `creature_movement_template` (`entry`, `point`, `position_x`, `position_y`, `position_z`, `waittime`, `script_id`, `textid1`, `textid2`, `textid3`, `textid4`, `textid5`, `emote`, `spell`, `wpguid`, `orientation`, `model1`, `model2`) VALUES (3694, 5, 6436.43, 362.265, 13.941, 120000, 15, 0, 0, 0, 0, 0, 0, 0, 0, 1.472, 0, 0); +INSERT INTO `creature_movement_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `datalong3`, `datalong4`, `data_flags`, `dataint`, `dataint2`, `dataint3`, `dataint4`, `x`, `y`, `z`, `o`, `comments`) VALUES (15, 0, 29, 2, 1, 3694, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Sentinel Selarin add quest giver flag'); +-- Script for Sentinel Selarin. +DELETE FROM `quest_end_scripts` WHERE `id`=994; +INSERT INTO `quest_end_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `datalong3`, `datalong4`, `data_flags`, `dataint`, `dataint2`, `dataint3`, `dataint4`, `x`, `y`, `z`, `o`, `comments`) VALUES (994, 1, 20, 2, 3694, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Sentinel Selarin start moving'); +INSERT INTO `quest_end_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `datalong3`, `datalong4`, `data_flags`, `dataint`, `dataint2`, `dataint3`, `dataint4`, `x`, `y`, `z`, `o`, `comments`) VALUES (994, 9, 0, 0, 3694, 40, 0, 0, 2000000008, 0, 0, 0, 0, 0, 0, 0, 'Sentinel Selarin Say1'); +INSERT INTO `quest_end_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `datalong3`, `datalong4`, `data_flags`, `dataint`, `dataint2`, `dataint3`, `dataint4`, `x`, `y`, `z`, `o`, `comments`) VALUES (994, 9, 1, 1, 3694, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Sentinel Selarin emote talk'); +INSERT INTO `quest_end_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `datalong3`, `datalong4`, `data_flags`, `dataint`, `dataint2`, `dataint3`, `dataint4`, `x`, `y`, `z`, `o`, `comments`) VALUES (994, 12, 25, 0, 3694, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Sentinel Selarin set walk'); +INSERT INTO `quest_end_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `datalong3`, `datalong4`, `data_flags`, `dataint`, `dataint2`, `dataint3`, `dataint4`, `x`, `y`, `z`, `o`, `comments`) VALUES (994, 14, 0, 0, 0, 0, 0, 0, 2000000007, 0, 0, 0, 0, 0, 0, 0, 'Terenthis Say1'); +INSERT INTO `quest_end_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `datalong3`, `datalong4`, `data_flags`, `dataint`, `dataint2`, `dataint3`, `dataint4`, `x`, `y`, `z`, `o`, `comments`) VALUES (994, 14, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Terenthis emote talk'); +INSERT INTO `quest_end_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `datalong3`, `datalong4`, `data_flags`, `dataint`, `dataint2`, `dataint3`, `dataint4`, `x`, `y`, `z`, `o`, `comments`) VALUES (994, 20, 0, 0, 3694, 40, 0, 0, 2000000006, 0, 0, 0, 0, 0, 0, 0, 'Sentinel Selarin Say2'); +INSERT INTO `quest_end_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `datalong3`, `datalong4`, `data_flags`, `dataint`, `dataint2`, `dataint3`, `dataint4`, `x`, `y`, `z`, `o`, `comments`) VALUES (994, 20, 1, 1, 3694, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Sentinel Selarin emote talk'); +INSERT INTO `quest_end_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `datalong3`, `datalong4`, `data_flags`, `dataint`, `dataint2`, `dataint3`, `dataint4`, `x`, `y`, `z`, `o`, `comments`) VALUES (994, 25, 0, 0, 3694, 40, 0, 0, 2000000005, 0, 0, 0, 0, 0, 0, 0, 'Sentinel Selarin Say3'); +INSERT INTO `quest_end_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `datalong3`, `datalong4`, `data_flags`, `dataint`, `dataint2`, `dataint3`, `dataint4`, `x`, `y`, `z`, `o`, `comments`) VALUES (994, 25, 1, 1, 3694, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Sentinel Selarin emote talk'); +-- The sentinel should spawn and make her quest available when completing either Escape Through Force or Escape Through Stealth. +UPDATE `quest_template` SET `PrevQuestId`=0 WHERE `entry`=990; +UPDATE `quest_template` SET `NextQuestId`=990, `NextQuestInChain`=990 WHERE `entry`=994; +UPDATE `quest_template` SET `CompleteScript`=994, `NextQuestId`=990, `NextQuestInChain`=990 WHERE `entry`=995; \ No newline at end of file diff --git a/src/game/Maps/Map.cpp b/src/game/Maps/Map.cpp index 32a762981..ddab4d830 100644 --- a/src/game/Maps/Map.cpp +++ b/src/game/Maps/Map.cpp @@ -3466,6 +3466,74 @@ void Map::ScriptsProcess() ((Unit*)pSource)->SetStandState(step.script->standState.stand_state); break; } + case SCRIPT_COMMAND_MODIFY_NPC_FLAGS: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_MODIFY_NPC_FLAGS (script id %u) call for NULL source.", step.script->id); + break; + } + + if (!source->isType(TYPEMASK_WORLDOBJECT)) + { + sLog.outError("SCRIPT_COMMAND_MODIFY_NPC_FLAGS (script id %u) call for unsupported non-worldobject (TypeId: %u), skipping.", step.script->id, source->GetTypeId()); + break; + } + + WorldObject* pSource = (WorldObject*)source; + Creature* pOwner = NULL; + + // No buddy defined, so try use source (or target if source is not creature) + if (!step.script->npcFlag.creatureEntry) + { + if (pSource->GetTypeId() != TYPEID_UNIT) + { + // we can't be non-creature, so see if target is creature + if (target && target->GetTypeId() == TYPEID_UNIT) + pOwner = (Creature*)target; + } + else if (pSource->GetTypeId() == TYPEID_UNIT) + pOwner = (Creature*)pSource; + } + else // If step has a buddy entry defined, search for it + { + MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*pSource, step.script->npcFlag.creatureEntry, true, step.script->npcFlag.searchRadius); + MaNGOS::CreatureLastSearcher searcher(pOwner, u_check); + + Cell::VisitGridObjects(pSource, searcher, step.script->npcFlag.searchRadius); + } + + if (!pOwner) + { + sLog.outError("SCRIPT_COMMAND_MODIFY_NPC_FLAGS (script id %u) call for non-creature (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", step.script->id, source->GetTypeId(), target ? target->GetTypeId() : 0); + break; + } + + // Add Flags + if (step.script->npcFlag.change_flag & 0x01) + { + pOwner->SetFlag(UNIT_NPC_FLAGS, step.script->npcFlag.flag); + } + // Remove Flags + else if (step.script->npcFlag.change_flag & 0x02) + { + pOwner->RemoveFlag(UNIT_NPC_FLAGS, step.script->npcFlag.flag); + } + // Toggle Flags + else + { + if (pOwner->HasFlag(UNIT_NPC_FLAGS, step.script->npcFlag.flag)) + { + pOwner->RemoveFlag(UNIT_NPC_FLAGS, step.script->npcFlag.flag); + } + else + { + pOwner->SetFlag(UNIT_NPC_FLAGS, step.script->npcFlag.flag); + } + } + + break; + } default: sLog.outError("Unknown SCRIPT_COMMAND_ %u called for script id %u.", step.script->command, step.script->id); break; diff --git a/src/game/ScriptMgr.cpp b/src/game/ScriptMgr.cpp index 409dddd9f..81287bb29 100644 --- a/src/game/ScriptMgr.cpp +++ b/src/game/ScriptMgr.cpp @@ -556,6 +556,20 @@ void ScriptMgr::LoadScripts(ScriptMapMap& scripts, const char* tablename) } break; } + case SCRIPT_COMMAND_MODIFY_NPC_FLAGS: + { + if (tmp.npcFlag.creatureEntry && !ObjectMgr::GetCreatureTemplate(tmp.npcFlag.creatureEntry)) + { + sLog.outErrorDb("Table `%s` has datalong3 = %u in SCRIPT_COMMAND_MODIFY_NPC_FLAGS for script id %u, but this creature_template does not exist.", tablename, tmp.npcFlag.creatureEntry, tmp.id); + continue; + } + if (tmp.npcFlag.creatureEntry && !tmp.npcFlag.searchRadius) + { + sLog.outErrorDb("Table `%s` has datalong3 = %u in SCRIPT_COMMAND_MODIFY_NPC_FLAGS for script id %u, but search radius is too small (datalong4 = %u).", tablename, tmp.npcFlag.creatureEntry, tmp.id, tmp.npcFlag.searchRadius); + continue; + } + break; + } } if (scripts.find(tmp.id) == scripts.end()) diff --git a/src/game/ScriptMgr.h b/src/game/ScriptMgr.h index 590d818ea..a2b1d2f82 100644 --- a/src/game/ScriptMgr.h +++ b/src/game/ScriptMgr.h @@ -101,6 +101,10 @@ enum eScriptCommand // datalong = stand state (enum UnitStandStateType) // datalong2 = creature entry (searching for a buddy, closest to source), datalong3 = creature search radius // data_flags = flag_target_as_source = 0x01 + SCRIPT_COMMAND_MODIFY_NPC_FLAGS = 29, // source=any, target=creature + // datalong=NPCFlags + // datalong2:0x00=toggle, 0x01=add, 0x02=remove + // datalong3 = creature entry (searching for a buddy, closest to source), datalong4 = creature search radius }; #define MAX_TEXT_ID 4 // used for SCRIPT_COMMAND_TALK @@ -316,6 +320,14 @@ struct ScriptInfo uint32 flags; // data_flags } standState; + struct // SCRIPT_COMMAND_MODIFY_NPC_FLAGS (29) + { + uint32 flag; // datalong + uint32 change_flag; // datalong2 + uint32 creatureEntry; // datalong3 + uint32 searchRadius; // datalong4 + } npcFlag; + struct { uint32 data[9]; diff --git a/src/scripts/kalimdor/darkshore/darkshore.cpp b/src/scripts/kalimdor/darkshore/darkshore.cpp index 61d8078a9..92bca0de1 100644 --- a/src/scripts/kalimdor/darkshore/darkshore.cpp +++ b/src/scripts/kalimdor/darkshore/darkshore.cpp @@ -916,6 +916,38 @@ bool QuestComplete_npc_tharnariun_treetender(Player* pPlayer, Creature* pQuestGi return false; } +/*#### +# npc_terenthis +####*/ + +enum +{ + NPC_SENTINEL_SELARIN = 3694 +}; + +bool QuestComplete_npc_terenthis(Player* pPlayer, Creature* pQuestGiver, Quest const* pQuest) +{ + if (!pQuestGiver) + return false; + + if (!pPlayer) + return false; + + if ((pQuest->GetQuestId() == QUEST_ESCAPE_THROUGH_FORCE) || (pQuest->GetQuestId() == QUEST_ESCAPE_THROUGH_STEALTH)) + { + if (pQuestGiver->FindNearestCreature(NPC_SENTINEL_SELARIN, 40)) + return true; // prevent starting db script if sentinel is already spawned + else if (Creature* pSentinel = pQuestGiver->SummonCreature(NPC_SENTINEL_SELARIN, 6409.01f, 381.597f, 13.7997f, 1, TEMPSUMMON_TIMED_COMBAT_OR_DEAD_DESPAWN, 120000)) + { + pSentinel->SetWalk(false); + return false; // let quest_end_script take over from here + } + else + return true; // prevent starting db script if sentinel was not spawned + } + return false; +} + /*#### # npc_sentinel_aynasha ####*/ @@ -1445,6 +1477,11 @@ void AddSC_darkshore() newscript->pQuestRewardedNPC = &QuestComplete_npc_tharnariun_treetender; newscript->RegisterSelf(); + newscript = new Script; + newscript->Name = "npc_terenthis"; + newscript->pQuestRewardedNPC = &QuestComplete_npc_terenthis; + newscript->RegisterSelf(); + newscript = new Script; newscript->Name = "npc_sentinel_aynasha"; newscript->GetAI = &GetAI_npc_sentinel_aynasha;