aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/3.3.5/2019_08_01_00_world.sql4
-rw-r--r--src/server/game/AI/CreatureAI.h4
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp21
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.h3
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp140
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h27
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp6
-rw-r--r--src/server/game/Entities/Creature/Creature.h2
-rw-r--r--src/server/game/Maps/Map.cpp2
-rw-r--r--src/server/scripts/Kalimdor/zone_darkshore.cpp2
-rw-r--r--src/server/scripts/Kalimdor/zone_tanaris.cpp9
-rw-r--r--src/server/scripts/Kalimdor/zone_ungoro_crater.cpp2
12 files changed, 77 insertions, 145 deletions
diff --git a/sql/updates/world/3.3.5/2019_08_01_00_world.sql b/sql/updates/world/3.3.5/2019_08_01_00_world.sql
new file mode 100644
index 00000000000..f8e082bbe20
--- /dev/null
+++ b/sql/updates/world/3.3.5/2019_08_01_00_world.sql
@@ -0,0 +1,4 @@
+--
+DELETE FROM `spawn_group` WHERE `spawnType`=0 AND `spawnId` IN (22831,36626,23708,39059);
+INSERT INTO `spawn_group` (`groupId`,`spawnType`,`spawnId`) VALUES
+(3,0,22831), (3,0,36626), (3,0,23708), (3,0,39059);
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index 1d3f7736d17..ea021f44347 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -146,6 +146,7 @@ class TC_GAME_API CreatureAI : public UnitAI
virtual void SpellHitTarget(Unit* /*target*/, SpellInfo const* /*spellInfo*/) { }
virtual void SpellHitTargetGameObject(GameObject* /*target*/, SpellInfo const* /*spellInfo*/) { }
+ // Should return true if the NPC is currently being escorted
virtual bool IsEscorted() const { return false; }
// Called when creature appears in the world (spawn, respawn, grid load etc...)
@@ -228,9 +229,6 @@ class TC_GAME_API CreatureAI : public UnitAI
// If a PlayerAI* is returned, that AI is placed on the player instead of the default charm AI
// Object destruction is handled by Unit::RemoveCharmedBy
virtual PlayerAI* GetAIForCharmedPlayer(Player* /*who*/) { return nullptr; }
- // Should return true if the NPC is target of an escort quest
- // If onlyIfActive is set, should return true only if the escort quest is currently active
- virtual bool IsEscortNPC(bool /*onlyIfActive*/) const { return false; }
// intended for encounter design/debugging. do not use for other purposes. expensive.
int32 VisualizeBoundary(uint32 duration, Unit* owner = nullptr, bool fill = false) const;
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
index cd42ffa5157..d591450f4f6 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -283,14 +283,8 @@ void EscortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false */,
{
if (CreatureData const* cdata = me->GetCreatureData())
{
- if (SpawnGroupTemplateData const* groupdata = cdata->spawnGroupData)
- {
- if (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && (groupdata->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC) && !map->GetCreatureRespawnTime(me->GetSpawnId()))
- {
- me->SetRespawnTime(me->GetRespawnDelay());
- me->SaveRespawnTime();
- }
- }
+ if (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && (cdata->spawnGroupData->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC))
+ me->SaveRespawnTime(me->GetRespawnDelay());
}
}
@@ -378,17 +372,6 @@ void EscortAI::SetEscortPaused(bool on)
}
}
-bool EscortAI::IsEscortNPC(bool onlyIfActive) const
-{
- if (!onlyIfActive)
- return true;
-
- if (GetEventStarterGUID())
- return true;
-
- return false;
-}
-
Player* EscortAI::GetPlayerForEscort()
{
return ObjectAccessor::GetPlayer(*me, _playerGUID);
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
index d24c94bfb78..5da71eecccb 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
@@ -56,7 +56,7 @@ struct TC_GAME_API EscortAI : public ScriptedAI
void SetEscortPaused(bool on);
void SetPauseTimer(uint32 Timer) { _pauseTimer = Timer; }
bool HasEscortState(uint32 escortState) { return (_escortState & escortState) != 0; }
- virtual bool IsEscorted() const override { return (_escortState & STATE_ESCORT_ESCORTING); }
+ bool IsEscorted() const override { return !_playerGUID.IsEmpty(); }
void SetMaxPlayerDistance(float newMax) { _maxPlayerDistance = newMax; }
float GetMaxPlayerDistance() const { return _maxPlayerDistance; }
void SetDespawnAtEnd(bool despawn) { _despawnAtEnd = despawn; }
@@ -64,7 +64,6 @@ struct TC_GAME_API EscortAI : public ScriptedAI
bool IsActiveAttacker() const { return _activeAttacker; } // obsolete
void SetActiveAttacker(bool enable) { _activeAttacker = enable; }
ObjectGuid GetEventStarterGUID() const { return _playerGUID; }
- virtual bool IsEscortNPC(bool isEscorting) const override;
protected:
Player* GetPlayerForEscort();
diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
index 6d9c9d6fe69..73fdf3af997 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
@@ -32,37 +32,11 @@ enum Points
POINT_COMBAT_START = 0xFFFFFF
};
-FollowerAI::FollowerAI(Creature* creature) : ScriptedAI(creature), _updateFollowTimer(2500), _followState(STATE_FOLLOW_NONE), _questForFollow(nullptr) { }
-
-void FollowerAI::MovementInform(uint32 type, uint32 id)
-{
- if (type != POINT_MOTION_TYPE || !HasFollowState(STATE_FOLLOW_INPROGRESS))
- return;
-
- if (id == POINT_COMBAT_START)
- {
- if (GetLeaderForFollower())
- {
- if (!HasFollowState(STATE_FOLLOW_PAUSED))
- AddFollowState(STATE_FOLLOW_RETURNING);
- }
- else
- me->DespawnOrUnsummon();
- }
-}
-
-void FollowerAI::AttackStart(Unit* who)
-{
- ScriptedAI::AttackStart(who);
-}
+FollowerAI::FollowerAI(Creature* creature) : ScriptedAI(creature), _updateFollowTimer(2500), _followState(STATE_FOLLOW_NONE), _questForFollow(0) { }
void FollowerAI::MoveInLineOfSight(Unit* who)
{
- // TODO: what in the world is this?
- if (me->HasReactState(REACT_AGGRESSIVE) && !me->HasUnitState(UNIT_STATE_STUNNED) && who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me))
- return;
-
- if (HasFollowState(STATE_FOLLOW_INPROGRESS) && AssistPlayerInCombatAgainst(who))
+ if (HasFollowState(STATE_FOLLOW_INPROGRESS) && !ShouldAssistPlayerInCombatAgainst(who))
return;
ScriptedAI::MoveInLineOfSight(who);
@@ -81,53 +55,32 @@ void FollowerAI::JustDied(Unit* /*killer*/)
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next())
if (Player* member = groupRef->GetSource())
if (member->IsInMap(player))
- member->FailQuest(_questForFollow->GetQuestId());
+ member->FailQuest(_questForFollow);
}
else
- player->FailQuest(_questForFollow->GetQuestId());
+ player->FailQuest(_questForFollow);
}
}
-void FollowerAI::JustAppeared()
-{
- _followState = STATE_FOLLOW_NONE;
-
- if (!IsCombatMovementAllowed())
- SetCombatMovement(true);
-
- if (me->GetFaction() != me->GetCreatureTemplate()->faction)
- me->SetFaction(me->GetCreatureTemplate()->faction);
-
- Reset();
-}
-
-void FollowerAI::EnterEvadeMode(EvadeReason /*why*/)
+void FollowerAI::JustReachedHome()
{
- if (!me->IsAlive())
- {
- EngagementOver();
+ if (!HasFollowState(STATE_FOLLOW_INPROGRESS))
return;
- }
-
- me->RemoveAllAuras();
- me->CombatStop(true);
- me->SetLootRecipient(nullptr);
- me->SetCannotReachTarget(false);
- me->DoNotReacquireTarget();
-
- EngagementOver();
- if (HasFollowState(STATE_FOLLOW_INPROGRESS))
+ if (Player* player = GetLeaderForFollower())
{
- TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::EnterEvadeMode: left combat, returning to CombatStartPosition. (%s)", me->GetGUID().ToString().c_str());
-
- if (me->HasUnitState(UNIT_STATE_CHASE))
- me->GetMotionMaster()->Remove(CHASE_MOTION_TYPE);
+ if (HasFollowState(STATE_FOLLOW_PAUSED))
+ return;
+ me->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
}
else
- me->GetMotionMaster()->MoveTargetedHome();
+ me->DespawnOrUnsummon();
+}
- Reset();
+void FollowerAI::OwnerAttackedBy(Unit* other)
+{
+ if (!me->HasReactState(REACT_PASSIVE) && ShouldAssistPlayerInCombatAgainst(other))
+ me->EngageWithTarget(other);
}
void FollowerAI::UpdateAI(uint32 uiDiff)
@@ -144,27 +97,23 @@ void FollowerAI::UpdateAI(uint32 uiDiff)
}
bool maxRangeExceeded = true;
-
+ bool questAbandoned = (_questForFollow != 0);
if (Player* player = GetLeaderForFollower())
{
- if (HasFollowState(STATE_FOLLOW_RETURNING))
- {
- TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::UpdateAI: is returning to leader. (%s)", me->GetGUID().ToString().c_str());
-
- RemoveFollowState(STATE_FOLLOW_RETURNING);
- me->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
- return;
- }
-
if (Group* group = player->GetGroup())
{
- for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next())
+ for (GroupReference* groupRef = group->GetFirstMember(); groupRef && (maxRangeExceeded || questAbandoned); groupRef = groupRef->next())
{
Player* member = groupRef->GetSource();
- if (member && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE))
- {
+ if (!member)
+ continue;
+ if (maxRangeExceeded && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE))
maxRangeExceeded = false;
- break;
+ if (questAbandoned)
+ {
+ QuestStatus status = member->GetQuestStatus(_questForFollow);
+ if ((status == QUEST_STATUS_COMPLETE) || (status == QUEST_STATUS_INCOMPLETE))
+ questAbandoned = false;
}
}
}
@@ -172,10 +121,16 @@ void FollowerAI::UpdateAI(uint32 uiDiff)
{
if (me->IsWithinDistInMap(player, MAX_PLAYER_DISTANCE))
maxRangeExceeded = false;
+ if (questAbandoned)
+ {
+ QuestStatus status = player->GetQuestStatus(_questForFollow);
+ if ((status == QUEST_STATUS_COMPLETE) || (status == QUEST_STATUS_INCOMPLETE))
+ questAbandoned = false;
+ }
}
}
- if (maxRangeExceeded)
+ if (maxRangeExceeded || questAbandoned)
{
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::UpdateAI: failed because player/group was to far away or not found (%s)", me->GetGUID().ToString().c_str());
me->DespawnOrUnsummon();
@@ -199,8 +154,17 @@ void FollowerAI::UpdateFollowerAI(uint32 /*uiDiff*/)
DoMeleeAttackIfReady();
}
-void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, Quest const* quest)
+void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, uint32 quest)
{
+ if (Map* map = me->GetMap())
+ {
+ if (CreatureData const* cdata = me->GetCreatureData())
+ {
+ if (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && (cdata->spawnGroupData->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC))
+ me->SaveRespawnTime(me->GetRespawnDelay());
+ }
+ }
+
if (me->IsEngaged())
{
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::StartFollow: attempt to StartFollow while in combat. (%s)", me->GetGUID().ToString().c_str());
@@ -301,22 +265,15 @@ Player* FollowerAI::GetLeaderForFollower()
// This part provides assistance to a player that are attacked by who, even if out of normal aggro range
// It will cause me to attack who that are attacking _any_ player (which has been confirmed may happen also on offi)
// The flag (type_flag) is unconfirmed, but used here for further research and is a good candidate.
-bool FollowerAI::AssistPlayerInCombatAgainst(Unit* who)
+bool FollowerAI::ShouldAssistPlayerInCombatAgainst(Unit* who) const
{
if (!who || !who->GetVictim())
return false;
- if (me->HasReactState(REACT_PASSIVE))
- return false;
-
// experimental (unknown) flag not present
if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST))
return false;
- // not a player
- if (!who->EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
- return false;
-
if (!who->isInAccessiblePlaceFor(me))
return false;
@@ -336,11 +293,8 @@ bool FollowerAI::AssistPlayerInCombatAgainst(Unit* who)
return false;
// too far away and no free sight
- if (me->IsWithinDistInMap(who, MAX_PLAYER_DISTANCE) && me->IsWithinLOSInMap(who))
- {
- me->EngageWithTarget(who);
- return true;
- }
+ if (!me->IsWithinDistInMap(who, MAX_PLAYER_DISTANCE) || !me->IsWithinLOSInMap(who))
+ return false;
- return false;
+ return true;
}
diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h
index f099caefe39..52b56d83934 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h
@@ -27,11 +27,10 @@ enum FollowerState : uint32
{
STATE_FOLLOW_NONE = 0x000,
STATE_FOLLOW_INPROGRESS = 0x001, // must always have this state for any follow
- STATE_FOLLOW_RETURNING = 0x002, // when returning to combat start after being in combat
- STATE_FOLLOW_PAUSED = 0x004, // disables following
- STATE_FOLLOW_COMPLETE = 0x008, // follow is completed and may end
- STATE_FOLLOW_PREEVENT = 0x010, // not implemented (allow pre event to run, before follow is initiated)
- STATE_FOLLOW_POSTEVENT = 0x020 // can be set at complete and allow post event to run
+ STATE_FOLLOW_PAUSED = 0x002, // disables following
+ STATE_FOLLOW_COMPLETE = 0x004, // follow is completed and may end
+ STATE_FOLLOW_PREEVENT = 0x008, // not implemented (allow pre event to run, before follow is initiated)
+ STATE_FOLLOW_POSTEVENT = 0x010 // can be set at complete and allow post event to run
};
class TC_GAME_API FollowerAI : public ScriptedAI
@@ -40,24 +39,23 @@ class TC_GAME_API FollowerAI : public ScriptedAI
explicit FollowerAI(Creature* creature);
~FollowerAI() { }
- void MovementInform(uint32 type, uint32 id) override;
- void AttackStart(Unit*) override;
void MoveInLineOfSight(Unit*) override;
- void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override;
void JustDied(Unit*) override;
- void JustAppeared() override;
+ void JustReachedHome() override;
+ void OwnerAttackedBy(Unit* other) override;
+
// the "internal" update, calls UpdateFollowerAI()
void UpdateAI(uint32) override;
-
// used when it's needed to add code in update (abilities, scripted events, etc)
virtual void UpdateFollowerAI(uint32);
- void StartFollow(Player* player, uint32 factionForFollower = 0, Quest const* quest = nullptr);
+ void StartFollow(Player* player, uint32 factionForFollower = 0, uint32 quest = 0);
// if special event require follow mode to hold/resume during the follow
void SetFollowPaused(bool paused);
void SetFollowComplete(bool withEndEvent = false);
- bool HasFollowState(uint32 uiFollowState) { return (_followState & uiFollowState) != 0; }
+ bool IsEscorted() const override { return HasFollowState(STATE_FOLLOW_INPROGRESS); }
+ bool HasFollowState(uint32 uiFollowState) const { return (_followState & uiFollowState) != 0; }
protected:
Player* GetLeaderForFollower();
@@ -65,13 +63,12 @@ class TC_GAME_API FollowerAI : public ScriptedAI
private:
void AddFollowState(uint32 followState) { _followState |= followState; }
void RemoveFollowState(uint32 followState) { _followState &= ~followState; }
- bool AssistPlayerInCombatAgainst(Unit* who);
+ bool ShouldAssistPlayerInCombatAgainst(Unit* who) const;
ObjectGuid _leaderGUID;
uint32 _updateFollowTimer;
uint32 _followState;
-
- Quest const* _questForFollow;
+ uint32 _questForFollow;
};
#endif
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 9457b8bfde7..6d708476b96 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -3285,10 +3285,10 @@ void Creature::AtDisengage()
}
}
-bool Creature::IsEscortNPC(bool onlyIfActive)
+bool Creature::IsEscorted() const
{
- if (CreatureAI* ai = AI())
- return ai->IsEscortNPC(onlyIfActive);
+ if (CreatureAI const* ai = AI())
+ return ai->IsEscorted();
return false;
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index e2016f09cc4..90f69dcb5a1 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -355,7 +355,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
CreatureTextRepeatIds GetTextRepeatGroup(uint8 textGroup);
void SetTextRepeatId(uint8 textGroup, uint8 id);
void ClearTextRepeatGroup(uint8 textGroup);
- bool IsEscortNPC(bool onlyIfActive = true);
+ bool IsEscorted() const;
bool CanGiveExperience() const;
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 78f8c2e1ed3..6abf49b81b0 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -2964,7 +2964,7 @@ bool Map::CheckRespawn(RespawnInfo* info)
if (!creature->IsAlive())
continue;
// escort NPCs are allowed to respawn as long as all other instances are already escorting
- if (isEscort && creature->IsEscortNPC(true))
+ if (isEscort && creature->IsEscorted())
continue;
doDelete = true;
break;
diff --git a/src/server/scripts/Kalimdor/zone_darkshore.cpp b/src/server/scripts/Kalimdor/zone_darkshore.cpp
index 9ff9a03b3e1..f7c936fe873 100644
--- a/src/server/scripts/Kalimdor/zone_darkshore.cpp
+++ b/src/server/scripts/Kalimdor/zone_darkshore.cpp
@@ -161,7 +161,7 @@ public:
{
me->SetStandState(UNIT_STAND_STATE_STAND);
Talk(SAY_KER_START, player);
- StartFollow(player, FACTION_ESCORTEE_N_NEUTRAL_PASSIVE, quest);
+ StartFollow(player, FACTION_ESCORTEE_N_NEUTRAL_PASSIVE, QUEST_SLEEPER_AWAKENED);
}
}
};
diff --git a/src/server/scripts/Kalimdor/zone_tanaris.cpp b/src/server/scripts/Kalimdor/zone_tanaris.cpp
index 728aef81fef..97a2e31beba 100644
--- a/src/server/scripts/Kalimdor/zone_tanaris.cpp
+++ b/src/server/scripts/Kalimdor/zone_tanaris.cpp
@@ -326,7 +326,7 @@ public:
if (me->IsWithinDistInMap(who, INTERACTION_DISTANCE))
{
Player* player = GetLeaderForFollower();
- if (player && player->GetQuestStatus(QUEST_TOOGA) == QUEST_STATUS_INCOMPLETE)
+ if (player)
player->GroupEventHappens(QUEST_TOOGA, me);
TortaGUID = who->GetGUID();
@@ -339,10 +339,7 @@ public:
{
FollowerAI::MovementInform(MotionType, PointId);
- if (MotionType != POINT_MOTION_TYPE)
- return;
-
- if (PointId == POINT_ID_TO_WATER)
+ if ((MotionType == POINT_MOTION_TYPE) && (PointId == POINT_ID_TO_WATER))
SetFollowComplete();
}
@@ -416,7 +413,7 @@ public:
void QuestAccept(Player* player, Quest const* quest) override
{
if (quest->GetQuestId() == QUEST_TOOGA)
- StartFollow(player, FACTION_ESCORTEE_N_NEUTRAL_PASSIVE, quest);
+ StartFollow(player, FACTION_ESCORTEE_N_NEUTRAL_PASSIVE, QUEST_TOOGA);
}
};
diff --git a/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp b/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp
index 41401fb8c7c..2e06e92f285 100644
--- a/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp
+++ b/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp
@@ -340,7 +340,7 @@ public:
if (quest->GetQuestId() == QUEST_A_LITTLE_HELP)
{
me->SetStandState(UNIT_STAND_STATE_STAND);
- StartFollow(player, FACTION_ESCORTEE_N_NEUTRAL_PASSIVE, quest);
+ StartFollow(player, FACTION_ESCORTEE_N_NEUTRAL_PASSIVE, QUEST_A_LITTLE_HELP);
}
}
};