bool EffectDummyCreature_npc_kitten(Unit* /*pCaster*/, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Creature* pCreatureTarget, ObjectGuid /*originalCasterGuid*/) { // always check spellid and effectindex if (uiSpellId == SPELL_CORRUPT_SABER_VISUAL && uiEffIndex == EFFECT_INDEX_0) { // Not nice way, however using UpdateEntry will not be correct. if (const CreatureInfo* pTemp = GetCreatureTemplateStore(NPC_CORRUPT_SABER)) { pCreatureTarget->SetEntry(pTemp->Entry); pCreatureTarget->SetDisplayId(Creature::ChooseDisplayId(pTemp)); pCreatureTarget->SetName(pTemp->Name); pCreatureTarget->SetFloatValue(OBJECT_FIELD_SCALE_X, pTemp->Scale); } if (Unit* pOwner = pCreatureTarget->GetOwner()) DoScriptText(EMOTE_SAB_FOLLOW, pCreatureTarget, pOwner); // always return true when we are handling this spell and effect return true; } return false; }
//we expect this spell to be triggered from spell casted at questAccept bool EffectDummyCreature_npc_clintar_dw_spirit(Unit *pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature *pCreatureTarget) { //always check spellid and effectindex if (spellId == SPELL_EMERALD_DREAM && effIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER || pCaster->HasAura(SPELL_EMERALD_DREAM)) return true; if (pCreatureTarget->GetEntry() != NPC_CLINTAR_DW_SPIRIT) return true; if (CreatureInfo const* pTemp = GetCreatureTemplateStore(NPC_CLINTAR_SPIRIT)) pCreatureTarget->SetDisplayId(pTemp->DisplayID_H[0]); else return true; //done here, escort can start ((npc_clintar_dw_spiritAI*)pCreatureTarget->AI())->DoStart(pCaster->GetGUID()); //always return true when we are handling this spell and effect return true; } return true; }
void SystemMgr::LoadScriptWaypoints() { // Drop Existing Waypoint list m_mPointMoveMap.clear(); uint64 uiCreatureCount = 0; // Load Waypoints QueryResult_AutoPtr Result = WorldDatabase.PQuery("SELECT COUNT(entry) FROM script_waypoint GROUP BY entry"); if (Result) uiCreatureCount = Result->GetRowCount(); outstring_log("TSCR: Loading Script Waypoints for %u creature(s)...", uiCreatureCount); Result = WorldDatabase.PQuery("SELECT entry, pointid, location_x, location_y, location_z, waittime FROM script_waypoint ORDER BY pointid"); if (Result) { barGoLink bar(Result->GetRowCount()); uint32 uiNodeCount = 0; do { bar.step(); Field* pFields = Result->Fetch(); ScriptPointMove pTemp; pTemp.uiCreatureEntry = pFields[0].GetUInt32(); uint32 uiEntry = pTemp.uiCreatureEntry; pTemp.uiPointId = pFields[1].GetUInt32(); pTemp.fX = pFields[2].GetFloat(); pTemp.fY = pFields[3].GetFloat(); pTemp.fZ = pFields[4].GetFloat(); pTemp.uiWaitTime = pFields[5].GetUInt32(); CreatureInfo const* pCInfo = GetCreatureTemplateStore(pTemp.uiCreatureEntry); if (!pCInfo) { error_db_log("TSCR: DB table script_waypoint has waypoint for non-existant creature entry %u", pTemp.uiCreatureEntry); continue; } if (!pCInfo->ScriptID) error_db_log("TSCR: DB table script_waypoint has waypoint for creature entry %u, but creature does not have ScriptName defined and then useless.", pTemp.uiCreatureEntry); m_mPointMoveMap[uiEntry].push_back(pTemp); ++uiNodeCount; } while (Result->NextRow()); outstring_log(""); outstring_log(">> Loaded %u Script Waypoint nodes.", uiNodeCount); } else { barGoLink bar(1); bar.step(); outstring_log(""); outstring_log(">> Loaded 0 Script Waypoints. DB table `script_waypoint` is empty."); } }
void SystemMgr::LoadScriptWaypoints() { uint32 oldMSTime = getMSTime(); // Drop Existing Waypoint list m_mPointMoveMap.clear(); uint64 uiCreatureCount = 0; // Load Waypoints QueryResult result = WorldDatabase.Query( "SELECT COUNT(entry) FROM script_waypoint GROUP BY entry"); if (result) uiCreatureCount = result->GetRowCount(); sLog->outString( "TSCR: Loading Script Waypoints for " UI64FMTD " creature(s)...", uiCreatureCount); result = WorldDatabase.Query( "SELECT entry, pointid, location_x, location_y, location_z, waittime FROM script_waypoint ORDER BY pointid"); if (!result) { sLog->outString( ">> Loaded 0 Script Waypoints. DB table `script_waypoint` is empty."); sLog->outString(); return; } uint32 count = 0; do { Field* pFields = result->Fetch(); ScriptPointMove pTemp; pTemp.uiCreatureEntry = pFields[0].GetUInt32(); uint32 uiEntry = pTemp.uiCreatureEntry; pTemp.uiPointId = pFields[1].GetUInt32(); pTemp.fX = pFields[2].GetFloat(); pTemp.fY = pFields[3].GetFloat(); pTemp.fZ = pFields[4].GetFloat(); pTemp.uiWaitTime = pFields[5].GetUInt32(); CreatureInfo const* pCInfo = GetCreatureTemplateStore( pTemp.uiCreatureEntry); if (!pCInfo) { sLog->outErrorDb( "TSCR: DB table script_waypoint has waypoint for non-existant creature entry %u", pTemp.uiCreatureEntry); continue; } if (!pCInfo->ScriptID) sLog->outErrorDb( "TSCR: DB table script_waypoint has waypoint for creature entry %u, but creature does not have ScriptName defined and then useless.", pTemp.uiCreatureEntry); m_mPointMoveMap[uiEntry].push_back(pTemp); ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u Script Waypoint nodes in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 EventId, Unit* pActionInvoker) { switch (action.type) { case ACTION_T_TEXT: { if (!action.text.TextId1) return; int32 temp = 0; if (action.text.TextId2 && action.text.TextId3) temp = RAND(action.text.TextId1, action.text.TextId2, action.text.TextId3); else if (action.text.TextId2 && urand(0, 1)) temp = action.text.TextId2; else temp = action.text.TextId1; if (temp) { Unit* target = NULL; if (pActionInvoker) { if (pActionInvoker->GetTypeId() == TYPEID_PLAYER) target = pActionInvoker; else if (Unit* owner = pActionInvoker->GetOwner()) { if (owner->GetTypeId() == TYPEID_PLAYER) target = owner; } } else { target = me->getVictim(); if (target && target->GetTypeId() != TYPEID_PLAYER) if (Unit* owner = target->GetOwner()) if (owner->GetTypeId() == TYPEID_PLAYER) target = owner; } DoScriptText(temp, me, target); } break; } case ACTION_T_SET_FACTION: { if (action.set_faction.factionId) me->setFaction(action.set_faction.factionId); else { if (CreatureInfo const* ci = GetCreatureTemplateStore(me->GetEntry())) { //if no id provided, assume reset and then use default if (me->getFaction() != ci->faction_A) me->setFaction(ci->faction_A); } } break; } case ACTION_T_MORPH_TO_ENTRY_OR_MODEL: { if (action.morph.creatureId || action.morph.modelId) { //set model based on entry from creature_template if (action.morph.creatureId) { if (CreatureInfo const* ci = GetCreatureTemplateStore(action.morph.creatureId)) { uint32 display_id = sObjectMgr->ChooseDisplayId(0, ci); me->SetDisplayId(display_id); } } //if no param1, then use value from param2 (modelId) else me->SetDisplayId(action.morph.modelId); } else me->DeMorph(); break; } case ACTION_T_SOUND: me->PlayDirectSound(action.sound.soundId); break; case ACTION_T_EMOTE: me->HandleEmoteCommand(action.emote.emoteId); break; case ACTION_T_RANDOM_SOUND: { int32 temp = GetRandActionParam(rnd, action.random_sound.soundId1, action.random_sound.soundId2, action.random_sound.soundId3); if (temp >= 0) me->PlayDirectSound(temp); break; } case ACTION_T_RANDOM_EMOTE: { int32 temp = GetRandActionParam(rnd, action.random_emote.emoteId1, action.random_emote.emoteId2, action.random_emote.emoteId3); if (temp >= 0) me->HandleEmoteCommand(temp); break; } case ACTION_T_CAST: { Unit* target = GetTargetByType(action.cast.target, pActionInvoker); Unit* caster = me; if (!target) return; if (action.cast.castFlags & CAST_FORCE_TARGET_SELF) caster = target; //Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered bool canCast = !caster->IsNonMeleeSpellCasted(false) || (action.cast.castFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS)); // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them if (action.cast.castFlags & CAST_AURA_NOT_PRESENT) { if (target->HasAura(action.cast.spellId)) return; } if (canCast) { const SpellEntry* tSpell = GetSpellStore()->LookupEntry(action.cast.spellId); //Verify that spell exists if (tSpell) { //Check if cannot cast spell if (!(action.cast.castFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) && !CanCast(target, tSpell, (action.cast.castFlags & CAST_TRIGGERED))) { //Melee current victim if flag not set if (!(action.cast.castFlags & CAST_NO_MELEE_IF_OOM)) { if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) { m_AttackDistance = 0.0f; m_AttackAngle = 0.0f; me->GetMotionMaster()->MoveChase(me->getVictim(), m_AttackDistance, m_AttackAngle); } } } else { //Interrupt any previous spell if (caster->IsNonMeleeSpellCasted(false) && action.cast.castFlags & CAST_INTERRUPT_PREVIOUS) caster->InterruptNonMeleeSpells(false); caster->CastSpell(target, action.cast.spellId, (action.cast.castFlags & CAST_TRIGGERED)); } } else sLog->outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", EventId, me->GetEntry(), action.cast.spellId); } break; } case ACTION_T_SUMMON: { Unit* target = GetTargetByType(action.summon.target, pActionInvoker); Creature* pCreature = NULL; if (action.summon.duration) pCreature = me->SummonCreature(action.summon.creatureId, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, action.summon.duration); else pCreature = me->SummonCreature(action.summon.creatureId, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); if (!pCreature) sLog->outErrorDb("CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", action.summon.creatureId, EventId, me->GetEntry()); else if (action.summon.target != TARGET_T_SELF && target) pCreature->AI()->AttackStart(target); break; } case ACTION_T_THREAT_SINGLE_PCT: if (Unit* target = GetTargetByType(action.threat_single_pct.target, pActionInvoker)) me->getThreatManager().modifyThreatPercent(target, action.threat_single_pct.percent); break; case ACTION_T_THREAT_ALL_PCT: { std::list<HostileReference*>& threatList = me->getThreatManager().getThreatList(); for (std::list<HostileReference*>::iterator i = threatList.begin(); i != threatList.end(); ++i) if (Unit* Temp = Unit::GetUnit(*me, (*i)->getUnitGuid())) me->getThreatManager().modifyThreatPercent(Temp, action.threat_all_pct.percent); break; } case ACTION_T_QUEST_EVENT: if (Unit* target = GetTargetByType(action.quest_event.target, pActionInvoker)) if (target->GetTypeId() == TYPEID_PLAYER) target->ToPlayer()->AreaExploredOrEventHappens(action.quest_event.questId); break; case ACTION_T_CAST_EVENT: if (Unit* target = GetTargetByType(action.cast_event.target, pActionInvoker)) if (target->GetTypeId() == TYPEID_PLAYER) target->ToPlayer()->CastedCreatureOrGO(action.cast_event.creatureId, me->GetGUID(), action.cast_event.spellId); break; case ACTION_T_SET_UNIT_FIELD: { Unit* target = GetTargetByType(action.set_unit_field.target, pActionInvoker); // not allow modify important for integrity object fields if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END) return; if (target) target->SetUInt32Value(action.set_unit_field.field, action.set_unit_field.value); break; } case ACTION_T_SET_UNIT_FLAG: if (Unit* target = GetTargetByType(action.unit_flag.target, pActionInvoker)) target->SetFlag(UNIT_FIELD_FLAGS, action.unit_flag.value); break; case ACTION_T_REMOVE_UNIT_FLAG: if (Unit* target = GetTargetByType(action.unit_flag.target, pActionInvoker)) target->RemoveFlag(UNIT_FIELD_FLAGS, action.unit_flag.value); break; case ACTION_T_AUTO_ATTACK: m_MeleeEnabled = action.auto_attack.state != 0; break; case ACTION_T_COMBAT_MOVEMENT: // ignore no affect case if (m_CombatMovementEnabled == (action.combat_movement.state != 0)) return; m_CombatMovementEnabled = action.combat_movement.state != 0; //Allow movement (create new targeted movement gen only if idle) if (m_CombatMovementEnabled) { Unit* victim = me->getVictim(); if (me->isInCombat() && victim) { if (action.combat_movement.melee) { me->AddUnitState(UNIT_STAT_MELEE_ATTACKING); me->SendMeleeAttackStart(victim); } if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE) me->GetMotionMaster()->MoveChase(victim, m_AttackDistance, m_AttackAngle); // Targeted movement generator will start melee automatically, no need to send it explicitly } } else { if (me->isInCombat()) { Unit* victim = me->getVictim(); if (action.combat_movement.melee && victim) { me->ClearUnitState(UNIT_STAT_MELEE_ATTACKING); me->SendMeleeAttackStop(victim); } if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) me->GetMotionMaster()->MoveIdle(); } } break; case ACTION_T_SET_PHASE: m_Phase = action.set_phase.phase; break; case ACTION_T_INC_PHASE: { int32 new_phase = int32(m_Phase) + action.set_inc_phase.step; if (new_phase < 0) { sLog->outErrorDb("CreatureEventAI: Event %d decrease m_Phase under 0. CreatureEntry = %d", EventId, me->GetEntry()); m_Phase = 0; } else if (new_phase >= MAX_PHASE) { sLog->outErrorDb("CreatureEventAI: Event %d incremented m_Phase above %u. m_Phase mask cannot be used with phases past %u. CreatureEntry = %d", EventId, MAX_PHASE - 1, MAX_PHASE - 1, me->GetEntry()); m_Phase = MAX_PHASE - 1; } else m_Phase = new_phase; break; } case ACTION_T_EVADE: EnterEvadeMode(); break; case ACTION_T_FLEE_FOR_ASSIST: me->DoFleeToGetAssistance(); break; case ACTION_T_QUEST_EVENT_ALL: if (pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER) { if (Unit* Temp = Unit::GetUnit(*me, pActionInvoker->GetGUID())) if (Temp->GetTypeId() == TYPEID_PLAYER) Temp->ToPlayer()->GroupEventHappens(action.quest_event_all.questId, me); } break; case ACTION_T_CAST_EVENT_ALL: { std::list<HostileReference*>& threatList = me->getThreatManager().getThreatList(); for (std::list<HostileReference*>::iterator i = threatList.begin(); i != threatList.end(); ++i) if (Unit* Temp = Unit::GetUnit(*me, (*i)->getUnitGuid())) if (Temp->GetTypeId() == TYPEID_PLAYER) Temp->ToPlayer()->CastedCreatureOrGO(action.cast_event_all.creatureId, me->GetGUID(), action.cast_event_all.spellId); break; } case ACTION_T_REMOVEAURASFROMSPELL: if (Unit* target = GetTargetByType(action.remove_aura.target, pActionInvoker)) target->RemoveAurasDueToSpell(action.remove_aura.spellId); break; case ACTION_T_RANGED_MOVEMENT: m_AttackDistance = (float) action.ranged_movement.distance; m_AttackAngle = action.ranged_movement.angle / 180.0f * M_PI; if (m_CombatMovementEnabled) { me->GetMotionMaster()->MoveChase(me->getVictim(), m_AttackDistance, m_AttackAngle); } break; case ACTION_T_RANDOM_PHASE: m_Phase = GetRandActionParam(rnd, action.random_phase.phase1, action.random_phase.phase2, action.random_phase.phase3); break; case ACTION_T_RANDOM_PHASE_RANGE: if (action.random_phase_range.phaseMin <= action.random_phase_range.phaseMax) m_Phase = urand(action.random_phase_range.phaseMin, action.random_phase_range.phaseMax); else sLog->outErrorDb("CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 < Param1. Event = %d. CreatureEntry = %d", EventId, me->GetEntry()); break; case ACTION_T_SUMMON_ID: { Unit* target = GetTargetByType(action.summon_id.target, pActionInvoker); CreatureEventAI_Summon_Map::const_iterator i = sEventAIMgr->GetCreatureEventAISummonMap().find(action.summon_id.spawnId); if (i == sEventAIMgr->GetCreatureEventAISummonMap().end()) { sLog->outErrorDb("CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", action.summon_id.creatureId, action.summon_id.spawnId, EventId, me->GetEntry()); return; } Creature* pCreature = NULL; if ((*i).second.SpawnTimeSecs) pCreature = me->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs); else pCreature = me->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); if (!pCreature) sLog->outErrorDb("CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", action.summon_id.creatureId, EventId, me->GetEntry()); else if (action.summon_id.target != TARGET_T_SELF && target) pCreature->AI()->AttackStart(target); break; } case ACTION_T_KILLED_MONSTER: //first attempt player who tapped creature if (Player* pPlayer = me->GetLootRecipient()) pPlayer->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, pPlayer); // pPlayer as param is a hacky solution not to use GUID else { //if not available, use pActionInvoker if (Unit* pTarget = GetTargetByType(action.killed_monster.target, pActionInvoker)) if (Player* pPlayer2 = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself()) pPlayer2->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, pPlayer2); } break; case ACTION_T_SET_INST_DATA: { InstanceScript* pInst = (InstanceScript*) me->GetInstanceScript(); if (!pInst) { sLog->outErrorDb("CreatureEventAI: Event %d attempt to set instance data without instance script. Creature %d", EventId, me->GetEntry()); return; } pInst->SetData(action.set_inst_data.field, action.set_inst_data.value); break; } case ACTION_T_SET_INST_DATA64: { Unit* target = GetTargetByType(action.set_inst_data64.target, pActionInvoker); if (!target) { sLog->outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", EventId, me->GetEntry()); return; } InstanceScript* pInst = (InstanceScript*) me->GetInstanceScript(); if (!pInst) { sLog->outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 without instance script. Creature %d", EventId, me->GetEntry()); return; } pInst->SetData64(action.set_inst_data64.field, target->GetGUID()); break; } case ACTION_T_UPDATE_TEMPLATE: if (me->GetEntry() == action.update_template.creatureId) { sLog->outErrorDb("CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", EventId, me->GetEntry()); return; } me->UpdateEntry(action.update_template.creatureId, action.update_template.team ? HORDE : ALLIANCE); break; case ACTION_T_DIE: if (me->isDead()) { sLog->outErrorDb("CreatureEventAI: Event %d ACTION_T_DIE on dead creature. Creature %d", EventId, me->GetEntry()); return; } me->Kill(me); break; case ACTION_T_ZONE_COMBAT_PULSE: { me->SetInCombatWithZone(); break; } case ACTION_T_CALL_FOR_HELP: { me->CallForHelp((float) action.call_for_help.radius); break; } break; // FrenchCORE ONLY case ACTION_T_MOVE_RANDOM_POINT: //dosen't work in combat { float x, y, z; me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, (float) action.raw.param1); me->GetMotionMaster()->MovePoint(0, x, y, z); break; } case ACTION_T_SET_STAND_STATE: me->SetStandState(UnitStandStateType(action.raw.param1)); break; case ACTION_T_SET_PHASE_MASK: me->SetPhaseMask(action.raw.param1, true); break; case ACTION_T_SET_VISIBILITY: me->SetVisible(bool(action.raw.param1)); break; case ACTION_T_SET_ACTIVE: me->setActive(action.raw.param1 ? true : false); break; case ACTION_T_SET_AGGRESSIVE: me->SetReactState(ReactStates(action.raw.param1)); break; case ACTION_T_ATTACK_START_PULSE: AttackStart(me->SelectNearestTarget((float) action.raw.param1)); break; case ACTION_T_SUMMON_GO: { GameObject* pObject = NULL; float x, y, z; me->GetPosition(x, y, z); pObject = me->SummonGameObject(action.raw.param1, x, y, z, 0, 0, 0, 0, 0, action.raw.param2); if (!pObject) { sLog->outErrorDb("TSCR: EventAI failed to spawn object %u. Spawn event %d is on creature %d", action.raw.param1, EventId, me->GetEntry()); } break; } case ACTION_T_SET_SHEATH: { me->SetSheath(SheathState(action.set_sheath.sheath)); break; } case ACTION_T_FORCE_DESPAWN: { me->ForcedDespawn(action.forced_despawn.msDelay); break; } case ACTION_T_SET_INVINCIBILITY_HP_LEVEL: { if (action.invincibility_hp_level.is_percent) m_InvinceabilityHpLevel = me->CountPctFromMaxHealth(action.invincibility_hp_level.hp_level); else m_InvinceabilityHpLevel = action.invincibility_hp_level.hp_level; break; } case ACTION_T_MOUNT_TO_ENTRY_OR_MODEL: { if (action.mount.creatureId || action.mount.modelId) { // set model based on entry from creature_template if (action.mount.creatureId) { if (CreatureInfo const* cInfo = GetCreatureTemplateStore(action.mount.creatureId)) { uint32 display_id = sObjectMgr->ChooseDisplayId(0, cInfo); me->Mount(display_id); } } //if no param1, then use value from param2 (modelId) else me->Mount(action.mount.modelId); } else me->Unmount(); break; } } }
void SystemMgr::LoadScriptWaypoints() { uint64 creatureCount = 0; // Load Waypoints QueryResult* result = WorldDatabase.PQuery("SELECT COUNT(entry) FROM script_waypoint GROUP BY entry"); if (result) { creatureCount = result->GetRowCount(); delete result; } outstring_log("SD2: Loading Script Waypoints for " UI64FMTD " creature(s)...", creatureCount); result = WorldDatabase.PQuery("SELECT entry, pathId, pointid, position_x, position_y, position_z, orientation, waittime, script_id FROM script_waypoint ORDER BY entry, pathId, pointid"); if (result) { BarGoLink bar(result->GetRowCount()); uint32 nodeCount = 0; do { bar.step(); Field* fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); CreatureInfo const* info = GetCreatureTemplateStore(entry); if (!info) { error_db_log("SD2: DB table script_waypoint has waypoint for nonexistent creature entry %u", entry); continue; } uint32 pathId = fields[1].GetUInt32(); uint32 pointId = fields[2].GetUInt32(); float position_x = fields[3].GetFloat(); float position_y = fields[4].GetFloat(); float position_z = fields[5].GetFloat(); float orientation = fields[6].GetFloat(); uint32 waitTime = fields[7].GetUInt32(); uint32 scriptId = fields[8].GetUInt32(); sWaypointMgr.AddExternalNode(entry, pathId, pointId, position_x, position_y, position_z, orientation, waitTime, scriptId); ++nodeCount; } while (result->NextRow()); delete result; outstring_log("\n>> Loaded %u Script Waypoint nodes.", nodeCount); } else { BarGoLink bar(1); bar.step(); outstring_log("\n>> Loaded 0 Script Waypoints. DB table `script_waypoint` is empty."); } }