diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp index e193c9785..280393fbb 100755 --- a/src/bindings/scripts/include/sc_creature.cpp +++ b/src/bindings/scripts/include/sc_creature.cpp @@ -186,7 +186,7 @@ void ScriptedAI::CastNextSpellIfAnyAndReady(uint32 diff) bool casted = false; - if (m_creature->hasUnitState(UNIT_STAT_CASTING)) + if (me->IsNonMeleeSpellCasted(false)) casted = true; if (!spellList.empty() && !casted) @@ -294,7 +294,7 @@ void ScriptedAI::CastNextSpellIfAnyAndReady(uint32 diff) void ScriptedAI::DoCast(Unit* victim, uint32 spellId, bool triggered) { - if (/*!victim || */m_creature->hasUnitState(UNIT_STAT_CASTING) && !triggered) + if (/*!victim || */me->IsNonMeleeSpellCasted(false) && !triggered) return; //m_creature->StopMoving(); @@ -303,7 +303,7 @@ void ScriptedAI::DoCast(Unit* victim, uint32 spellId, bool triggered) void ScriptedAI::DoCastAOE(uint32 spellId, bool triggered) { - if(!triggered && m_creature->hasUnitState(UNIT_STAT_CASTING)) + if(!triggered && me->IsNonMeleeSpellCasted(false)) return; m_creature->CastSpell((Unit*)NULL, spellId, triggered); @@ -1029,8 +1029,8 @@ void ScriptedAI::DoModifyThreatPercent(Unit *pUnit, int32 pct) void ScriptedAI::DoTeleportTo(float x, float y, float z, uint32 time) { - m_creature->Relocate(x,y,z); - m_creature->SendMonsterMove(x, y, z, time); + m_creature->NearTeleportTo(x,y,z, me->GetOrientation()); + //m_creature->SendMonsterMove(x, y, z, time); } void ScriptedAI::DoTeleportPlayer(Unit* pUnit, float x, float y, float z, float o) diff --git a/src/bindings/scripts/scripts/guard/guard_ai.cpp b/src/bindings/scripts/scripts/guard/guard_ai.cpp index e596d6a4d..2dd7133a0 100755 --- a/src/bindings/scripts/scripts/guard/guard_ai.cpp +++ b/src/bindings/scripts/scripts/guard/guard_ai.cpp @@ -98,80 +98,6 @@ void guardAI::UpdateAI(const uint32 diff) if (!UpdateVictim()) return; - // Make sure our attack is ready and we arn't currently casting - if( m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false)) - { - //If we are within range melee the target - if( m_creature->IsWithinMeleeRange(m_creature->getVictim())) - { - bool Healing = false; - SpellEntry const *info = NULL; - - //Select a healing spell if less than 30% hp - if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 30) - info = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING); - - //No healing spell available, select a hostile spell - if (info) Healing = true; - else info = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, 0, 0, SELECT_EFFECT_DONTCARE); - - //20% chance to replace our white hit with a spell - if (info && rand() % 5 == 0 && !GlobalCooldown) - { - //Cast the spell - if (Healing)DoCastSpell(m_creature, info); - else DoCastSpell(m_creature->getVictim(), info); - - //Set our global cooldown - GlobalCooldown = GENERIC_CREATURE_COOLDOWN; - } - else m_creature->AttackerStateUpdate(m_creature->getVictim()); - - m_creature->resetAttackTimer(); - } - } - else - { - //Only run this code if we arn't already casting - if (!m_creature->IsNonMeleeSpellCasted(false)) - { - bool Healing = false; - SpellEntry const *info = NULL; - - //Select a healing spell if less than 30% hp ONLY 33% of the time - if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 30 && rand() % 3 == 0) - info = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING); - - //No healing spell available, See if we can cast a ranged spell (Range must be greater than ATTACK_DISTANCE) - if (info) Healing = true; - else info = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, NOMINAL_MELEE_RANGE, 0, SELECT_EFFECT_DONTCARE); - - //Found a spell, check if we arn't on cooldown - if (info && !GlobalCooldown) - { - //If we are currently moving stop us and set the movement generator - if ((*m_creature).GetMotionMaster()->GetCurrentMovementGeneratorType()!=IDLE_MOTION_TYPE) - { - (*m_creature).GetMotionMaster()->Clear(false); - (*m_creature).GetMotionMaster()->MoveIdle(); - } - - //Cast spell - if (Healing) DoCastSpell(m_creature,info); - else DoCastSpell(m_creature->getVictim(),info); - - //Set our global cooldown - GlobalCooldown = GENERIC_CREATURE_COOLDOWN; - - } //If no spells available and we arn't moving run to target - else if ((*m_creature).GetMotionMaster()->GetCurrentMovementGeneratorType()!=TARGETED_MOTION_TYPE) - { - //Cancel our current spell and then mutate new movement generator - m_creature->InterruptNonMeleeSpells(false); - (*m_creature).GetMotionMaster()->Clear(false); - (*m_creature).GetMotionMaster()->MoveChase(m_creature->getVictim()); - } - } - } + DoMeleeAttackIfReady(); } diff --git a/src/bindings/scripts/scripts/item/item_scripts.cpp b/src/bindings/scripts/scripts/item/item_scripts.cpp index f63a762d7..01462d7ed 100755 --- a/src/bindings/scripts/scripts/item/item_scripts.cpp +++ b/src/bindings/scripts/scripts/item/item_scripts.cpp @@ -75,7 +75,7 @@ bool ItemUse_item_only_for_flight(Player *player, Item* _Item, SpellCastTargets } // allow use in flight only - if( player->isInFlight() && !disabled) + if( player->IsTaxiFlying() && !disabled) return false; // error diff --git a/src/bindings/scripts/scripts/npc/escort_ai.cpp b/src/bindings/scripts/scripts/npc/escort_ai.cpp index a6813ff3d..f79c4322d 100644 --- a/src/bindings/scripts/scripts/npc/escort_ai.cpp +++ b/src/bindings/scripts/scripts/npc/escort_ai.cpp @@ -98,7 +98,7 @@ void npc_escortAI::MoveInLineOfSight(Unit* pWho) if (HasEscortState(STATE_ESCORT_ESCORTING) && AssistPlayerInCombat(pWho)) return; - if (!m_creature->canFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) return; if (m_creature->IsHostileTo(pWho) && m_bIsActiveAttacker) @@ -324,10 +324,10 @@ void npc_escortAI::MovementInform(uint32 uiMoveType, uint32 uiPointId) { debug_log("TSCR: EscortAI has returned to original position before combat"); - if (m_bIsRunning && m_creature->HasUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE)) - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); - else if (!m_bIsRunning && !m_creature->HasUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE)) - m_creature->AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + if (m_bIsRunning && m_creature->IsWalking()) + m_creature->SetWalk(false); + else if (!m_bIsRunning && !m_creature->IsWalking()) + m_creature->SetWalk(true); RemoveEscortState(STATE_ESCORT_RETURNING); @@ -419,14 +419,14 @@ void npc_escortAI::SetRun(bool bRun) if (bRun) { if (!m_bIsRunning) - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(false); else debug_log("TSCR: EscortAI attempt to set run mode, but is already running."); } else { if (m_bIsRunning) - m_creature->AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(true); else debug_log("TSCR: EscortAI attempt to set walk mode, but is already walking."); } @@ -493,9 +493,9 @@ void npc_escortAI::Start(bool bIsActiveAttacker, bool bRun, uint64 uiPlayerGUID, //Set initial speed if (m_bIsRunning) - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(false); else - m_creature->AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(true); AddEscortState(STATE_ESCORT_ESCORTING); } diff --git a/src/bindings/scripts/scripts/npc/follower_ai.cpp b/src/bindings/scripts/scripts/npc/follower_ai.cpp index 0f57ae69a..cab977084 100644 --- a/src/bindings/scripts/scripts/npc/follower_ai.cpp +++ b/src/bindings/scripts/scripts/npc/follower_ai.cpp @@ -92,7 +92,7 @@ void FollowerAI::MoveInLineOfSight(Unit* pWho) if (HasFollowState(STATE_FOLLOW_INPROGRESS) && AssistPlayerInCombat(pWho)) return; - if (!me->canFly() && me->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + if (!me->CanFly() && me->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) return; if (me->IsHostileTo(pWho)) @@ -166,7 +166,7 @@ void FollowerAI::EnterEvadeMode() { // sLog.outDebug("OSCR: FollowerAI left combat, returning to CombatStartPosition."); - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) { float fPosX, fPosY, fPosZ; me->GetPosition(fPosX, fPosY, fPosZ); @@ -175,7 +175,7 @@ void FollowerAI::EnterEvadeMode() } else { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) me->GetMotionMaster()->MoveTargetedHome(); } diff --git a/src/bindings/scripts/scripts/npc/npcs_special.cpp b/src/bindings/scripts/scripts/npc/npcs_special.cpp index 1a26aecd1..4a7ab01b3 100755 --- a/src/bindings/scripts/scripts/npc/npcs_special.cpp +++ b/src/bindings/scripts/scripts/npc/npcs_special.cpp @@ -165,11 +165,8 @@ struct TRINITY_DLL_DECL npc_dancing_flamesAI : public ScriptedAI float x, y, z; m_creature->GetPosition(x,y,z); m_creature->Relocate(x,y,z + 0.94f); - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_DANCE); - WorldPacket data; //send update position to client - m_creature->BuildHeartBeatMsg(&data); - m_creature->SendMessageToSet(&data,true); } void UpdateAI(const uint32 diff) @@ -200,9 +197,6 @@ bool ReceiveEmote_npc_dancing_flames( Player *player, Creature *flame, uint32 em flame->SetInFront(player); ((npc_dancing_flamesAI*)flame->AI())->active = false; - WorldPacket data; - flame->BuildHeartBeatMsg(&data); - flame->SendMessageToSet(&data,true); switch(emote) { case TEXTEMOTE_KISS: flame->HandleEmoteCommand(EMOTE_ONESHOT_SHY); break; @@ -413,7 +407,7 @@ struct TRINITY_DLL_DECL npc_injured_patientAI : public ScriptedAI DoSay(SAY_DOC1,LANG_UNIVERSAL,NULL); uint32 mobId = m_creature->GetEntry(); - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(false); switch (mobId) { case 12923: @@ -1978,7 +1972,9 @@ struct TRINITY_DLL_DECL npc_crashin_trashin_robotAI : public ScriptedAI m_creature->SetDefaultMovementType(RANDOM_MOTION_TYPE); m_creature->GetMotionMaster()->Initialize(); m_creature->GetMotionMaster()->Clear(); - m_creature->GetMotionMaster()->MoveRandom(10.0); + + // Need random ? + m_creature->GetMotionMaster()->MoveRandom(); moveTimer = urand(1000, 10000); despawnTimer = 180000; } @@ -2198,7 +2194,7 @@ struct TRINITY_DLL_DECL npc_lurkyAI : public ScriptedAI void UpdateAI(const uint32 diff) { - if (inDance || m_creature->hasUnitState(UNIT_STAT_MOVE)) + if (inDance || !me->IsStopped()) return; if (danceTimer < diff) diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/mana_tombs/boss_nexusprince_shaffar.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/mana_tombs/boss_nexusprince_shaffar.cpp index 733d718e2..e99fb858d 100755 --- a/src/bindings/scripts/scripts/zone/aunchindoun/mana_tombs/boss_nexusprince_shaffar.cpp +++ b/src/bindings/scripts/scripts/zone/aunchindoun/mana_tombs/boss_nexusprince_shaffar.cpp @@ -138,7 +138,7 @@ struct TRINITY_DLL_DECL boss_nexusprince_shaffarAI : public ScriptedAI HasTaunted = true; } - if (!m_creature->canFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + if (!m_creature->CanFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) return; float attackRadius = m_creature->GetAttackDistance(who); diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp index 56336742e..03e2537ad 100755 --- a/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp +++ b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp @@ -99,7 +99,7 @@ struct TRINITY_DLL_DECL boss_talon_king_ikissAI : public ScriptedAI DoScriptText(SAY_INTRO, m_creature); } - if (!m_creature->canFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + if (!m_creature->CanFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) return; float attackRadius = m_creature->GetAttackDistance(who); @@ -194,8 +194,7 @@ struct TRINITY_DLL_DECL boss_talon_king_ikissAI : public ScriptedAI //Spell doesn't work, but we use for visual effect at least DoCast(target,SPELL_BLINK); - m_creature->Relocate(wLoc.coord_x,wLoc.coord_y,wLoc.coord_z); - m_creature->SendMonsterMove(wLoc.coord_x,wLoc.coord_y,wLoc.coord_z, 0); + m_creature->NearTeleportTo(wLoc.coord_x,wLoc.coord_y,wLoc.coord_z, 0.0f); DoCast(target,SPELL_BLINK_TELEPORT); Blink = true; diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp index 4166e8128..01c33e80f 100755 --- a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp +++ b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp @@ -94,7 +94,7 @@ struct TRINITY_DLL_DECL boss_murmurAI : public Scripted_NoMovementAI // Resonance if(Resonance_Timer < diff) { - if(!m_creature->hasUnitState(UNIT_STAT_CASTING)) + if(!m_creature->IsNonMeleeSpellCasted(false)) { Unit *target = SelectUnit(SELECT_TARGET_NEAREST, 0, 100, true); diff --git a/src/bindings/scripts/scripts/zone/azshara/azshara.cpp b/src/bindings/scripts/scripts/zone/azshara/azshara.cpp index 91fda0915..316264206 100755 --- a/src/bindings/scripts/scripts/zone/azshara/azshara.cpp +++ b/src/bindings/scripts/scripts/zone/azshara/azshara.cpp @@ -305,13 +305,13 @@ struct TRINITY_DLL_DECL mob_rizzle_sprysprocketAI : public ScriptedAI if(map) { map->CreatureRelocation(m_creature, 3706.39, -3969.15, 35.9118, 0); - m_creature->AI_SendMoveToPacket(3706.39, -3969.15, 35.9118, 0, 0, 0); + //m_creature->AI_SendMoveToPacket(3706.39, -3969.15, 35.9118, 0, 0, 0); } //begin swimming and summon depth charges Player* player = Unit::GetPlayer(PlayerGUID); SendText(MSG_ESCAPE_NOTICE, player); DoCast(m_creature, SPELL_PERIODIC_DEPTH_CHARGE); - m_creature->SetUnitMovementFlags(SPLINEFLAG_FLYINGING2 | MOVEFLAG_SWIMMING); + m_creature->SetLevitate(true); m_creature->SetSpeed(MOVE_RUN, 0.85f, true); m_creature->GetMotionMaster()->MovementExpired(); m_creature->GetMotionMaster()->MovePoint(CurrWP, WPs[CurrWP][0], WPs[CurrWP][1], WPs[CurrWP][2]); @@ -440,7 +440,7 @@ struct TRINITY_DLL_DECL mob_depth_chargeAI : public ScriptedAI void Reset() { - m_creature->SetUnitMovementFlags(SPLINEFLAG_FLYINGING2 | MOVEFLAG_SWIMMING); + m_creature->SetLevitate(true); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); we_must_die = false; must_die_timer = 1000; diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp index 1ccb8b81a..35dafc4ff 100755 --- a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp @@ -243,7 +243,7 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public BossAI SetWarglaivesEquipped(false); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveUnitMovementFlag(MOVEFLAG_LEVITATING); + me->SetLevitate(false); me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); me->SetSelection(NULL); @@ -262,7 +262,7 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public BossAI ClearCastQueue(); events.CancelEventsByGCD(m_phase); - me->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + me->SetWalk(false); switch (m_phase = phase) { @@ -330,7 +330,7 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public BossAI me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEFLAG_LEVITATING); + me->SetLevitate(true); me->GetMotionMaster()->MovePoint(0, CENTER_X +5.0f, CENTER_Y, CENTER_Z); @@ -523,7 +523,7 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public BossAI } case EVENT_ILLIDAN_LAND: { - me->RemoveUnitMovementFlag(MOVEFLAG_LEVITATING); + me->SetLevitate(false); me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); @@ -1239,7 +1239,7 @@ struct TRINITY_DLL_DECL boss_illidan_akamaAI : public BossAI } else { - me->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE); + me->SetWalk(false); me->GetMotionMaster()->MovePoint(0, 728.379f, 314.462f, 352.996f); } break; @@ -1698,7 +1698,7 @@ struct TRINITY_DLL_DECL boss_illidan_flameofazzinothAI : public ScriptedAI if(check_timer < diff) { - me->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + me->SetWalk(false); me->UpdateSpeed(MOVE_RUN, 2.5f); me->UpdateSpeed(MOVE_WALK, 4.5f); // test? check_timer = 2000; diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp index 1eb083ff1..f3badf967 100755 --- a/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp @@ -193,7 +193,7 @@ struct TRINITY_DLL_DECL mob_ashtongue_defenderAI : public ScriptedAI void DoMeleeAttackIfReady() { - if (me->hasUnitState(UNIT_STAT_CASTING)) + if (me->IsNonMeleeSpellCasted(false)) return; //Make sure our attack is ready and we aren't currently casting before checking distance @@ -226,7 +226,7 @@ struct TRINITY_DLL_DECL mob_ashtongue_defenderAI : public ScriptedAI if (m_shieldBashTimer < diff) { - if (m_creature->getVictim() && m_creature->getVictim()->hasUnitState(UNIT_STAT_CASTING)) + if (m_creature->getVictim() && m_creature->getVictim()->IsNonMeleeSpellCasted(false)) { AddSpellToCast(m_creature->getVictim(), SPELL_SHIELD_BASH); m_shieldBashTimer = 10000; @@ -703,7 +703,7 @@ struct TRINITY_DLL_DECL boss_shade_of_akamaAI : public ScriptedAI if(Unit *owner = me->GetCharmerOrOwner()) { me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, m_creature->GetFollowAngle(), MOTION_SLOT_ACTIVE); + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, m_creature->GetFollowAngle()); Reset(); } else @@ -1063,8 +1063,8 @@ struct TRINITY_DLL_DECL boss_shade_of_akamaAI : public ScriptedAI if (m_updateSpeed) { - if (me->GetUnitMovementFlags() & SPLINEFLAG_WALKMODE_MODE) - me->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + if (me->IsWalking()) + me->SetWalk(false); me->UpdateSpeed(MOVE_RUN, true); @@ -1340,7 +1340,7 @@ struct TRINITY_DLL_DECL npc_akamaAI : public ScriptedAI if (broken) { m_summons.Summon(broken); - broken->AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + broken->SetWalk(true); broken->GetMotionMaster()->MovePoint(0, BrokenMoveTo[i][0], BrokenMoveTo[i][1], SPAWN_Z); broken->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_KNEEL); } diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp index 512fa58c2..563f8c9bd 100755 --- a/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp @@ -281,7 +281,8 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI { WorldLocation temp; target->GetClosePoint(temp.coord_x, temp.coord_y, temp.coord_z, 20.0f, false, m_creature->GetOrientation()); //if boss >40yd from victim make him run fast till 20yd and charge without damage - m_creature->SendMonsterMoveWithSpeed(temp.coord_x, temp.coord_y, temp.coord_z, SPLINEFLAG_WALKMODE_MODE); + // we will try to implement charge later ;P + m_creature->GetMotionMaster()->MovePoint(0, temp.coord_x, temp.coord_y, temp.coord_z); m_creature->CastSpell(target, SPELL_CHARGE, false); } } diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_teron_gorefiend.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_teron_gorefiend.cpp index 5d658dbba..87ea55946 100755 --- a/src/bindings/scripts/scripts/zone/black_temple/boss_teron_gorefiend.cpp +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_teron_gorefiend.cpp @@ -84,7 +84,7 @@ struct TRINITY_DLL_DECL mob_doom_blossomAI : public NullCreatureAI m_creature->setFaction(Teron->getFaction()); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); float newX, newY, newZ; m_creature->GetRandomPoint(m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(), 10.0, newX, newY, newZ); @@ -392,7 +392,7 @@ struct TRINITY_DLL_DECL boss_teron_gorefiendAI : public ScriptedAI void SpellHit(Unit* caster, const SpellEntry* spell) // Ghosts spells cant be applied on Teron { - if(caster->GetTypeId() == TYPEID_UNIT && caster->isPossessedByPlayer()) + if(caster->GetTypeId() == TYPEID_UNIT && caster->GetCharmerOrOwner()) m_creature->RemoveAurasByCasterSpell(spell->Id, caster->GetGUID()); } diff --git a/src/bindings/scripts/scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp b/src/bindings/scripts/scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp index 99a4d103a..3b883fb4e 100755 --- a/src/bindings/scripts/scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp +++ b/src/bindings/scripts/scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp @@ -164,7 +164,7 @@ struct TRINITY_DLL_DECL mobs_nether_drakeAI : public ScriptedAI case 5: m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); // | MOVEFLAG_LEVITATING - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT); + m_creature->SetLevitate(true); //then take off to random location. creature is initially summoned, so don't bother do anything else. m_creature->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX()+100, m_creature->GetPositionY(), m_creature->GetPositionZ()+100); NihilSpeech_Phase = 0; @@ -523,7 +523,7 @@ struct TRINITY_DLL_DECL mob_aetherrayAI : public ScriptedAI void JustSummoned(Creature* summoned) { - summoned->GetMotionMaster()->MoveFollow(Unit::GetPlayer(PlayerGUID), PET_FOLLOW_DIST, m_creature->GetFollowAngle(), MOTION_SLOT_ACTIVE); + summoned->GetMotionMaster()->MoveFollow(Unit::GetPlayer(PlayerGUID), PET_FOLLOW_DIST, m_creature->GetFollowAngle()); } void UpdateAI(const uint32 diff) diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp index ec4eefcdb..b114a0451 100755 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp @@ -501,7 +501,7 @@ void hyjalAI::SummonCreature(uint32 entry, float Base[4][3]) // Increment Enemy Count to be used in World States and instance script ++EnemyCount; - pCreature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + pCreature->SetWalk(false); pCreature->setActive(true); switch(entry) { @@ -1050,7 +1050,7 @@ void hyjalAI::WaypointReached(uint32 i) if((*itr) && (*itr)->isAlive() && (*itr) != m_creature && (*itr)->GetEntry() != JAINA) { if(!(*itr)->IsWithinDistInMap(m_creature, 60)) - (*itr)->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + (*itr)->SetWalk(false); float x, y, z; (*itr)->SetDefaultMovementType(IDLE_MOTION_TYPE); (*itr)->GetMotionMaster()->Initialize(); diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp index e3ccc1fea..e0bd46190 100755 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp @@ -448,7 +448,7 @@ struct mob_giant_infernalAI : public hyjal_trashAI { trigger->SetVisibility(VISIBILITY_OFF); trigger->setFaction(m_creature->getFaction()); - trigger->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + trigger->SetLevitate(true); trigger->CastSpell(m_creature,SPELL_METEOR,true); } m_creature->GetMotionMaster()->Clear(); @@ -1313,7 +1313,7 @@ struct mob_frost_wyrmAI : public hyjal_trashAI { FrostBreathTimer = 5000; MoveTimer = 0; - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); } void WaypointReached(uint32 i) @@ -1439,7 +1439,7 @@ struct mob_gargoyleAI : public hyjal_trashAI Zpos = 10.0; StrikeTimer = 2000+rand()%5000; MoveTimer = 0; - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); } void WaypointReached(uint32 i) diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp index 707ec0b30..5e70b624b 100755 --- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp @@ -675,7 +675,7 @@ struct TRINITY_DLL_DECL mob_enchanted_elementalAI : public ScriptedAI if(move < diff) { - m_creature->SetUnitMovementFlags(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(true); if (phase == 1) { m_creature->GetMotionMaster()->MovePoint(0, x, y, z); @@ -802,7 +802,7 @@ struct TRINITY_DLL_DECL mob_toxic_sporebatAI : public ScriptedAI void Reset() { - m_creature->AddUnitMovementFlag(/*MOVEFLAG_ONTRANSPORT + */MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); m_creature->setFaction(14); movement_timer = 0; ToxicSpore_Timer = 5000; diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp index f0c32a244..f73e985b6 100755 --- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp @@ -86,7 +86,7 @@ struct TRINITY_DLL_DECL boss_the_lurker_belowAI : public Scripted_NoMovementAI } // Do not fall to the ground ;] - me->AddUnitMovementFlag(MOVEFLAG_SWIMMING | MOVEFLAG_LEVITATING); + me->SetLevitate(true); // Set reactstate to: Aggresive me->SetReactState(REACT_AGGRESSIVE); @@ -155,7 +155,7 @@ struct TRINITY_DLL_DECL boss_the_lurker_belowAI : public Scripted_NoMovementAI void MovementInform(uint32 type, uint32 data) { // data: 0 = FINALIZE - // data: 1 = UPDATE + /*/ data: 1 = UPDATE if (type == ROTATE_MOTION_TYPE) { if (data == 1) //Rotate movegen update @@ -180,9 +180,9 @@ struct TRINITY_DLL_DECL boss_the_lurker_belowAI : public Scripted_NoMovementAI m_immunemap[pPlayer->GetGUID()]++; continue; } - } + } - if (/*pPlayer->IsInWater() ||*/ pPlayer->GetPositionZ() < -19.9645) + if (/*pPlayer->IsInWater() || pPlayer->GetPositionZ() < -19.9645) continue; if (me->GetDistance2d(pPlayer) > 100.0f) @@ -208,12 +208,12 @@ struct TRINITY_DLL_DECL boss_the_lurker_belowAI : public Scripted_NoMovementAI me->SetReactState(REACT_AGGRESSIVE); m_rotating = false; } - } + } */ } void DoMeleeAttackIfReady() { - if (me->hasUnitState(UNIT_STAT_CASTING)) + if (me->IsNonMeleeSpellCasted(false)) return; //Make sure our attack is ready and we aren't currently casting before checking distance @@ -318,7 +318,7 @@ struct TRINITY_DLL_DECL boss_the_lurker_belowAI : public Scripted_NoMovementAI } me->SetSelection(0); - me->GetMotionMaster()->MoveRotate(20000, RAND(ROTATE_DIRECTION_LEFT, ROTATE_DIRECTION_RIGHT)); + //me->GetMotionMaster()->MoveRotate(20000, RAND(ROTATE_DIRECTION_LEFT, ROTATE_DIRECTION_RIGHT)); ForceSpellCast(me, SPELL_SPOUT_VISUAL, INTERRUPT_AND_CAST_INSTANTLY); diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp index 488b4961b..59fa4d81a 100755 --- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp @@ -436,7 +436,7 @@ struct TRINITY_DLL_DECL instance_serpentshrine_cavern : public ScriptedInstance { if(Creature* frenzy = pPlayer->SummonCreature(MOB_COILFANG_FRENZY,pPlayer->GetPositionX(),pPlayer->GetPositionY(),pPlayer->GetPositionZ(),pPlayer->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,2000)) { - frenzy->AddUnitMovementFlag(MOVEFLAG_SWIMMING | MOVEFLAG_LEVITATING); + frenzy->SetLevitate(true); frenzy->AI()->AttackStart(pPlayer); } DoSpawnFrenzy = false; diff --git a/src/bindings/scripts/scripts/zone/deadmines/deadmines.cpp b/src/bindings/scripts/scripts/zone/deadmines/deadmines.cpp index dca301b8e..0ee9d115b 100755 --- a/src/bindings/scripts/scripts/zone/deadmines/deadmines.cpp +++ b/src/bindings/scripts/scripts/zone/deadmines/deadmines.cpp @@ -120,7 +120,7 @@ struct TRINITY_DLL_DECL instance_deadmines : public ScriptedInstance void MoveCreatureInside(Creature *creature) { - creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + creature->SetWalk(false); creature->GetMotionMaster()->MovePoint(0, -102.7,-655.9, creature->GetPositionZ()); } diff --git a/src/bindings/scripts/scripts/zone/dustwallow_marsh/dustwallow_marsh.cpp b/src/bindings/scripts/scripts/zone/dustwallow_marsh/dustwallow_marsh.cpp index 639543da2..dcb5faa53 100755 --- a/src/bindings/scripts/scripts/zone/dustwallow_marsh/dustwallow_marsh.cpp +++ b/src/bindings/scripts/scripts/zone/dustwallow_marsh/dustwallow_marsh.cpp @@ -786,7 +786,7 @@ struct npc_private_hendelAI : public ScriptedAI void JustSummoned(Creature* pSummoned) { - pSummoned->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + pSummoned->SetWalk(false); if (pSummoned->GetEntry() == NPC_TERVOSH) { @@ -885,7 +885,7 @@ struct npc_private_hendelAI : public ScriptedAI me->RemoveAllAuras(); me->DeleteThreatList(); me->CombatStop(true); - me->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + me->SetWalk(false); me->SetHomePosition(-2892.28f,-3347.81f,31.8609f,0.160719f); me->GetMotionMaster()->MoveTargetedHome(); @@ -905,7 +905,7 @@ struct npc_private_hendelAI : public ScriptedAI (*itr)->RemoveAllAuras(); (*itr)->DeleteThreatList(); (*itr)->CombatStop(true); - (*itr)->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + (*itr)->SetWalk(false); (*itr)->GetMotionMaster()->MovePoint(0, m_afEventMoveTo[N].m_fX, m_afEventMoveTo[N].m_fY, m_afEventMoveTo[N].m_fZ); (*itr)->ForcedDespawn(5000); } diff --git a/src/bindings/scripts/scripts/zone/ghostlands/ghostlands.cpp b/src/bindings/scripts/scripts/zone/ghostlands/ghostlands.cpp index f0c4f637a..f30afd6ac 100755 --- a/src/bindings/scripts/scripts/zone/ghostlands/ghostlands.cpp +++ b/src/bindings/scripts/scripts/zone/ghostlands/ghostlands.cpp @@ -189,8 +189,8 @@ struct TRINITY_DLL_DECL npc_ranger_lilathaAI : public npc_escortAI m_creature->AI()->AttackStart(Summ1); break; } - case 19: m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); break; - case 25: m_creature->AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); break; + case 19: m_creature->SetWalk(false); break; + case 25: m_creature->SetWalk(true); break; case 30: player->GroupEventHappens(QUEST_ESCAPE_FROM_THE_CATACOMBS,m_creature); break; diff --git a/src/bindings/scripts/scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp b/src/bindings/scripts/scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp index 56c2f734f..e30a1735c 100755 --- a/src/bindings/scripts/scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp +++ b/src/bindings/scripts/scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp @@ -722,7 +722,7 @@ struct TRINITY_DLL_DECL boss_krosh_firehandAI : public ScriptedAI if(GreaterFireball_Timer < diff) { // will cast only when in range of spell - if(m_creature->GetDistance2d(m_creature->getVictim()) < 30 && !m_creature->hasUnitState(UNIT_STAT_CASTING)) + if(m_creature->GetDistance2d(m_creature->getVictim()) < 30 && !m_creature->IsNonMeleeSpellCasted(false)) AddSpellToCast(m_creature->getVictim(), SPELL_GREATER_FIREBALL); //DoCast(m_creature->getVictim(), SPELL_GREATER_FIREBALL); GreaterFireball_Timer = 3000; diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp index 4955b96a9..eed829e6c 100755 --- a/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp @@ -125,7 +125,7 @@ struct TRINITY_DLL_DECL boss_omor_the_unscarredAI : public ScriptedAI if (Unit* temp = Unit::GetUnit(*m_creature,playerGUID)) { //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) - if (temp->HasUnitMovementFlag(MOVEFLAG_FALLINGFAR)) + if (temp->m_movementInfo.HasMovementFlag(MOVEFLAG_FALLINGFAR)) { m_creature->InterruptNonMeleeSpells(false); DoCast(temp,SPELL_SHADOW_WHIP); diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp index 0bc417068..d0d1ddf39 100755 --- a/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp @@ -131,8 +131,8 @@ struct TRINITY_DLL_DECL boss_nazanAI : public ScriptedAI flight = false; BellowingRoar_Timer = 6000; ConeOfFire_Timer = 12000; - m_creature->RemoveUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); - m_creature->AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetLevitate(false); + m_creature->SetWalk(true); m_creature->GetMotionMaster()->Clear(); if(Unit *victim = SelectUnit(SELECT_TARGET_NEAREST,0)) m_creature->AI()->AttackStart(victim); @@ -325,7 +325,7 @@ struct TRINITY_DLL_DECL boss_vazruden_the_heraldAI : public ScriptedAI if(summoned->GetEntry() == ENTRY_NAZAN) { ((boss_nazanAI *)summoned->AI())->VazrudenGUID = VazrudenGUID; - summoned->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + summoned->SetLevitate(true); summoned->SetSpeed(MOVE_FLIGHT, 2.5); if(victim) ((ScriptedAI*)summoned->AI())->AttackStart(victim,false); diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp index 8e5914936..b8f3f424b 100755 --- a/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp @@ -73,7 +73,7 @@ struct TRINITY_DLL_DECL boss_watchkeeper_gargolmarAI : public ScriptedAI { if (!m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessiblePlacefor(m_creature) ) { - if (!m_creature->canFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + if (!m_creature->CanFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) return; float attackRadius = m_creature->GetAttackDistance(who); diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp index 684cfc801..8e500508a 100755 --- a/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp +++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp @@ -60,7 +60,7 @@ struct TRINITY_DLL_DECL boss_warchief_kargath_bladefistAI : public ScriptedAI removeAdds(); m_creature->SetSpeed(MOVE_RUN,2); - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(false); summoned = 2; InBlade = false; diff --git a/src/bindings/scripts/scripts/zone/hinterlands/hinterlands.cpp b/src/bindings/scripts/scripts/zone/hinterlands/hinterlands.cpp index 140e73c7a..c3a375002 100644 --- a/src/bindings/scripts/scripts/zone/hinterlands/hinterlands.cpp +++ b/src/bindings/scripts/scripts/zone/hinterlands/hinterlands.cpp @@ -219,7 +219,7 @@ struct npc_rinjiAI : public npc_escortAI void JustSummoned(Creature* pSummoned) { - pSummoned->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + pSummoned->SetWalk(false); pSummoned->GetMotionMaster()->MovePoint(0, m_afAmbushMoveTo[m_iSpawnId].m_fX, m_afAmbushMoveTo[m_iSpawnId].m_fY, m_afAmbushMoveTo[m_iSpawnId].m_fZ); } diff --git a/src/bindings/scripts/scripts/zone/isle_of_queldanas/isle_of_queldanas.cpp b/src/bindings/scripts/scripts/zone/isle_of_queldanas/isle_of_queldanas.cpp index 3fa238419..74511faf8 100755 --- a/src/bindings/scripts/scripts/zone/isle_of_queldanas/isle_of_queldanas.cpp +++ b/src/bindings/scripts/scripts/zone/isle_of_queldanas/isle_of_queldanas.cpp @@ -105,11 +105,11 @@ struct TRINITY_DLL_DECL npc_shattered_sun_bombardierAI : public ScriptedAI if(who->GetTypeId() != TYPEID_PLAYER) return; - if (who->isInFlight() && who->IsWithinDistInMap(me, 40) && !PathFly) + if (who->IsTaxiFlying() && who->IsWithinDistInMap(me, 40) && !PathFly) { PlayerGUID = who->GetGUID(); me->GetMotionMaster()->Clear(false); - m_creature->SetUnitMovementFlags(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); m_creature->GetMotionMaster()->MovePath(BOMBARDIER_FLY_PATH, false); me->SetSpeed(MOVE_WALK, 1.4*who->GetSpeed(MOVE_FLIGHT)); me->SetVisibility(VISIBILITY_ON); diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_nightbane.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_nightbane.cpp index 029933503..b1ea3be68 100755 --- a/src/bindings/scripts/scripts/zone/karazhan/boss_nightbane.cpp +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_nightbane.cpp @@ -126,8 +126,8 @@ struct TRINITY_DLL_DECL boss_nightbaneAI : public ScriptedAI MovePhase = 0; m_creature->SetSpeed(MOVE_RUN, 2.0f); - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetLevitate(true); + m_creature->SetWalk(false); if(pInstance && pInstance->GetData(DATA_NIGHTBANE_EVENT) != DONE) pInstance->SetData(DATA_NIGHTBANE_EVENT, NOT_STARTED); @@ -243,7 +243,7 @@ struct TRINITY_DLL_DECL boss_nightbaneAI : public ScriptedAI m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); (*m_creature).GetMotionMaster()->Clear(false); (*m_creature).GetMotionMaster()->MovePoint(0,IntroWay[2][0],IntroWay[2][1],IntroWay[2][2]); @@ -266,7 +266,7 @@ struct TRINITY_DLL_DECL boss_nightbaneAI : public ScriptedAI { if(MovePhase >= 7) { - m_creature->RemoveUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(false); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); m_creature->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]); } @@ -281,7 +281,7 @@ struct TRINITY_DLL_DECL boss_nightbaneAI : public ScriptedAI { if(MovePhase >= 7) { - m_creature->RemoveUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(false); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); m_creature->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]); } diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_shade_of_aran.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_shade_of_aran.cpp index 9f66c14ce..bdb43515e 100755 --- a/src/bindings/scripts/scripts/zone/karazhan/boss_shade_of_aran.cpp +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_shade_of_aran.cpp @@ -208,8 +208,7 @@ struct TRINITY_DLL_DECL boss_aranAI : public ScriptedAI void TeleportCenter() { m_creature->CastSpell(m_creature, SPELL_BLINK_CENTER, true); - m_creature->Relocate(wLoc.coord_x,wLoc.coord_y,wLoc.coord_z); - m_creature->SendMonsterMove(wLoc.coord_x,wLoc.coord_y,wLoc.coord_z, 0); + m_creature->NearTeleportTo(wLoc.coord_x,wLoc.coord_y,wLoc.coord_z, me->GetOrientation()); } void JustDied(Unit *victim) diff --git a/src/bindings/scripts/scripts/zone/karazhan/bosses_opera.cpp b/src/bindings/scripts/scripts/zone/karazhan/bosses_opera.cpp index b3ba33090..ffad49933 100755 --- a/src/bindings/scripts/scripts/zone/karazhan/bosses_opera.cpp +++ b/src/bindings/scripts/scripts/zone/karazhan/bosses_opera.cpp @@ -1626,7 +1626,7 @@ struct TRINITY_DLL_DECL npc_barnesAI : public ScriptedAI case 4: m_creature->GetMotionMaster()->Clear(); m_creature->GetMotionMaster()->MovePoint(id+1, StageLocations[id+1][0], StageLocations[id+1][1], SPAWN_Z); - m_creature->SendMonsterMove(StageLocations[id+1][0], StageLocations[id+1][1], SPAWN_Z, 0, NULL); + //m_creature->SendMonsterMove(StageLocations[id+1][0], StageLocations[id+1][1], SPAWN_Z, 0, NULL); break; case 2: IsTalking = true; diff --git a/src/bindings/scripts/scripts/zone/karazhan/chess_event.cpp b/src/bindings/scripts/scripts/zone/karazhan/chess_event.cpp index 65157076b..3edbd89b3 100644 --- a/src/bindings/scripts/scripts/zone/karazhan/chess_event.cpp +++ b/src/bindings/scripts/scripts/zone/karazhan/chess_event.cpp @@ -83,7 +83,7 @@ void move_triggerAI::MakeMove() case PIECE_MOVE: me->CastSpell(m_creature, SPELL_MOVE_MARKER, false); temp->StopMoving(); - temp->RemoveUnitMovementFlag(MOVEFLAG_ROOT); + temp->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ROOT); temp->GetMotionMaster()->Clear(); temp->GetMotionMaster()->MovePoint(0, wLoc.coord_x, wLoc.coord_y, wLoc.coord_z); @@ -94,7 +94,7 @@ void move_triggerAI::MakeMove() } break; case PIECE_CHANGE_FACING: - temp->RemoveUnitMovementFlag(MOVEFLAG_ROOT); + temp->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ROOT); if (temp2) { ((boss_MedivhAI*)temp2->AI())->ChangePieceFacing(temp, me); @@ -420,7 +420,7 @@ void npc_chesspieceAI::MovementInform(uint32 MovementType, uint32 Data) if (npc_medivh) ((boss_MedivhAI*)npc_medivh->AI())->SetOrientation(m_creature->GetGUID()); - me->AddUnitMovementFlag(MOVEFLAG_ROOT); + me->m_movementInfo.AddMovementFlag(MOVEFLAG_ROOT); } void npc_chesspieceAI::JustRespawned() @@ -450,7 +450,7 @@ void npc_chesspieceAI::OnCharmed(bool apply) if (Creature * medivh = me->GetCreature(MedivhGUID)) ((boss_MedivhAI*)medivh->AI())->SetOrientation(me->GetGUID()); - me->AddUnitMovementFlag(MOVEFLAG_ROOT); + me->m_movementInfo.AddMovementFlag(MOVEFLAG_ROOT); } void npc_chesspieceAI::SpellHit(Unit * caster, const SpellEntry * spell) @@ -3072,12 +3072,14 @@ void boss_MedivhAI::SetOrientation(uint64 piece, ChessOrientation ori) me->GetMap()->CreatureRelocation(cPiece, chessBoard[tmpi][tmpj].position.coord_x, chessBoard[tmpi][tmpj].position.coord_y, chessBoard[tmpi][tmpj].position.coord_z, cPiece->GetOrientation()); - Map::PlayerList const& players = m_creature->GetMap()->GetPlayers(); + // With current system should work without it L:P + /*Map::PlayerList const& players = m_creature->GetMap()->GetPlayers(); if (!players.isEmpty()) for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) if (Player* plr = itr->getSource()) cPiece->SendMonsterMove(chessBoard[tmpi][tmpj].position.coord_x, chessBoard[tmpi][tmpj].position.coord_y, chessBoard[tmpi][tmpj].position.coord_z, 0, plr); + */ } } @@ -4014,7 +4016,7 @@ bool GossipHello_npc_chesspiece(Player* player, Creature* _Creature) return true; } - if (!(_Creature->isPossessedByPlayer())) + if (!(_Creature->GetCharmerOrOwner())) { switch (_Creature->GetEntry()) { @@ -4074,9 +4076,9 @@ bool GossipHello_npc_chesspiece(Player* player, Creature* _Creature) void npc_chess_statusAI::Reset() { - m_creature->AddUnitMovementFlag(MOVEFLAG_CAN_FLY|MOVEFLAG_LEVITATING); - m_creature->Relocate(-11080.599609, -1876.380005, 231.000092); - m_creature->SendMonsterMove(-11080.599609, -1876.380005, 231.000092, 0); + m_creature->SetLevitate(true); + //m_creature->Relocate(-11080.599609, -1876.380005, 231.000092); + m_creature->NearTeleportTo(-11080.599609, -1876.380005, 231.000092, me->GetOrientation()); me->CastSpell(me, SPELL_GAME_IN_SESSION, false); } @@ -4126,7 +4128,7 @@ bool GossipSelect_npc_echo_of_medivh(Player* player, Creature* _Creature, uint32 ((boss_MedivhAI*)_Creature->AI())->StartMiniEvent(); pInstance->SetData(CHESS_EVENT_TEAM, player->GetTeam()); - _Creature->GetMotionMaster()->MoveRandom(10); + _Creature->GetMotionMaster()->MoveRandom(); } player->CLOSE_GOSSIP_MENU(); diff --git a/src/bindings/scripts/scripts/zone/karazhan/karazhan.cpp b/src/bindings/scripts/scripts/zone/karazhan/karazhan.cpp index 20810cdb0..eedfa7358 100755 --- a/src/bindings/scripts/scripts/zone/karazhan/karazhan.cpp +++ b/src/bindings/scripts/scripts/zone/karazhan/karazhan.cpp @@ -135,7 +135,7 @@ struct TRINITY_DLL_DECL npc_image_of_medivhAI : public ScriptedAI if(!Arcanagos) return; ArcanagosGUID = Arcanagos->GetGUID(); - Arcanagos->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + Arcanagos->SetLevitate(true); (*Arcanagos).GetMotionMaster()->MovePoint(0,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2]); Arcanagos->SetOrientation(ArcanagosPos[3]); m_creature->SetOrientation(MedivPos[3]); diff --git a/src/bindings/scripts/scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp index c16740da0..3bd8f5f3e 100755 --- a/src/bindings/scripts/scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp +++ b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_felblood_kaelthas.cpp @@ -609,7 +609,7 @@ struct TRINITY_DLL_DECL mob_arcane_sphereAI : public ScriptedAI void Reset() { - m_creature->SetUnitMovementFlags(MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); DespawnTimer = 30000; ChangeTargetTimer = 5000; CheckTimer = 1000; diff --git a/src/bindings/scripts/scripts/zone/magisters_terrace/boss_selin_fireheart.cpp b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_selin_fireheart.cpp index 28bff3c6b..a6837da14 100755 --- a/src/bindings/scripts/scripts/zone/magisters_terrace/boss_selin_fireheart.cpp +++ b/src/bindings/scripts/scripts/zone/magisters_terrace/boss_selin_fireheart.cpp @@ -118,7 +118,7 @@ struct TRINITY_DLL_DECL boss_selin_fireheartAI : public ScriptedAI float x, y, z; // coords that we move to, close to the crystal. CrystalChosen->GetClosePoint(x, y, z, m_creature->GetObjectSize(), CONTACT_DISTANCE); - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(false); m_creature->GetMotionMaster()->MovePoint(1, x, y, z); DrainingCrystal = true; } diff --git a/src/bindings/scripts/scripts/zone/mulgore/mulgore.cpp b/src/bindings/scripts/scripts/zone/mulgore/mulgore.cpp index 9ff93b492..96fd967f1 100755 --- a/src/bindings/scripts/scripts/zone/mulgore/mulgore.cpp +++ b/src/bindings/scripts/scripts/zone/mulgore/mulgore.cpp @@ -88,7 +88,7 @@ struct TRINITY_DLL_DECL npc_kyle_frenziedAI : public ScriptedAI z = (z2 <= INVALID_HEIGHT) ? z : z2; m_creature->SetDefaultMovementType(IDLE_MOTION_TYPE); //there is other way to stop waypoint movement? m_creature->GetMotionMaster()->Initialize(); - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(false); m_creature->GetMotionMaster()->MovePoint(0,x, y, z); } } @@ -105,9 +105,6 @@ struct TRINITY_DLL_DECL npc_kyle_frenziedAI : public ScriptedAI if(plr) m_creature->SetOrientation(m_creature->GetAngle(plr)); m_creature->HandleEmoteCommand(EMOTE_STATE_USESTANDING); //eat - WorldPacket data; - m_creature->BuildHeartBeatMsg(&data); - m_creature->SendMessageToSet(&data,true); wait = 3000; STATE = 2; break; diff --git a/src/bindings/scripts/scripts/zone/nagrand/nagrand.cpp b/src/bindings/scripts/scripts/zone/nagrand/nagrand.cpp index cdb835d9f..f5abe482e 100755 --- a/src/bindings/scripts/scripts/zone/nagrand/nagrand.cpp +++ b/src/bindings/scripts/scripts/zone/nagrand/nagrand.cpp @@ -834,7 +834,7 @@ struct npc_nagrand_captiveAI : public npc_escortAI if (pSummoned->isTotem()) return; - pSummoned->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + pSummoned->SetWalk(false); pSummoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); pSummoned->AI()->AttackStart(me); diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_kelthuzad.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_kelthuzad.cpp index c9bd3646e..424e50854 100755 --- a/src/bindings/scripts/scripts/zone/naxxramas/boss_kelthuzad.cpp +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_kelthuzad.cpp @@ -263,7 +263,7 @@ struct TRINITY_DLL_DECL boss_kelthuzadAI : public ScriptedAI Walk_Pos_Z = ADDZ_RIGHT_NEAR; break; } - pUnit->SendMonsterMoveWithSpeed(Walk_Pos_X, Walk_Pos_Y, Walk_Pos_Z,SPLINEFLAG_WALKMODE_MODE); + pUnit->GetMotionMaster()->MovePoint(0, Walk_Pos_X, Walk_Pos_Y, Walk_Pos_Z); } if (pInstance) pInstance->SetData(DATA_KEL_THUZAD, DONE); @@ -413,7 +413,7 @@ struct TRINITY_DLL_DECL boss_kelthuzadAI : public ScriptedAI { //if we find no one to figth walk to the center if(!pUnit->isInCombat()) - pUnit->SendMonsterMoveWithSpeed(Walk_Pos_X,Walk_Pos_Y,Walk_Pos_Z,SPLINEFLAG_WALKMODE_MODE); + pUnit->GetMotionMaster()->MovePoint(0, Walk_Pos_X,Walk_Pos_Y,Walk_Pos_Z); //Safe storing of creatures GuardiansOfIcecrown[GuardiansOfIcecrown_Count] = pUnit->GetGUID(); diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp index 3fd7e0685..11f83549e 100755 --- a/src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp +++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp @@ -69,7 +69,7 @@ struct TRINITY_DLL_DECL boss_sapphironAI : public ScriptedAI Icebolt_Count = 0; IsInFly = false; - m_creature->RemoveUnitMovementFlag(MOVEFLAG_LEVITATING | MOVEFLAG_ONTRANSPORT); + m_creature->SetLevitate(false); if (pInstance) pInstance->SetData(DATA_SAPPHIRON, NOT_STARTED); @@ -121,7 +121,7 @@ struct TRINITY_DLL_DECL boss_sapphironAI : public ScriptedAI { phase = 2; m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - m_creature->AddUnitMovementFlag(MOVEFLAG_LEVITATING | MOVEFLAG_ONTRANSPORT); + m_creature->SetLevitate(true); m_creature->GetMotionMaster()->Clear(false); m_creature->GetMotionMaster()->MoveIdle(); m_creature->setHover(true); @@ -159,7 +159,7 @@ struct TRINITY_DLL_DECL boss_sapphironAI : public ScriptedAI { phase = 1; m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - m_creature->RemoveUnitMovementFlag(MOVEFLAG_LEVITATING | MOVEFLAG_ONTRANSPORT); + m_creature->SetLevitate(false); m_creature->GetMotionMaster()->Clear(false); m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); m_creature->setHover(true); diff --git a/src/bindings/scripts/scripts/zone/onyxias_lair/boss_onyxia.cpp b/src/bindings/scripts/scripts/zone/onyxias_lair/boss_onyxia.cpp index b01ab3998..43736ce10 100755 --- a/src/bindings/scripts/scripts/zone/onyxias_lair/boss_onyxia.cpp +++ b/src/bindings/scripts/scripts/zone/onyxias_lair/boss_onyxia.cpp @@ -105,24 +105,24 @@ struct TRINITY_DLL_DECL boss_onyxiaAI : public ScriptedAI void Fly() { - if (m_creature->HasUnitMovementFlag(MOVEFLAG_LEVITATING | MOVEFLAG_ONTRANSPORT)) + if (m_creature->IsLevitating()) { m_creature->SendMeleeAttackStart(m_creature->getVictim()); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - m_creature->RemoveUnitMovementFlag(MOVEFLAG_LEVITATING | MOVEFLAG_ONTRANSPORT); + m_creature->SetLevitate(false); DoStartMovement(m_creature->getVictim()); } else { m_creature->SendMeleeAttackStop(m_creature->getVictim()); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - m_creature->AddUnitMovementFlag(MOVEFLAG_LEVITATING | MOVEFLAG_ONTRANSPORT); + m_creature->SetLevitate(true); } } void DoMeleeAttackIfReady() { - if(me->hasUnitState(UNIT_STAT_CASTING)) + if(me->IsNonMeleeSpellCasted(false)) return; if (m_phaseMask & PHASE_2) @@ -164,7 +164,7 @@ struct TRINITY_DLL_DECL boss_onyxiaAI : public ScriptedAI if (pInstance) pInstance->SetData(DATA_ONYXIA, NOT_STARTED); - m_creature->RemoveUnitMovementFlag(MOVEFLAG_LEVITATING | MOVEFLAG_ONTRANSPORT); + m_creature->SetLevitate(false); m_phaseMask = PHASE_1; m_nextWay = 0; diff --git a/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_ayamiss.cpp b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_ayamiss.cpp index 834a275af..681775a41 100755 --- a/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_ayamiss.cpp +++ b/src/bindings/scripts/scripts/zone/ruins_of_ahnqiraj/boss_ayamiss.cpp @@ -67,7 +67,7 @@ struct TRINITY_DLL_DECL boss_ayamissAI : public ScriptedAI POISONSTINGER_Timer = 3500; SUMMONSWARMER_Timer = 60000; phase=1; - m_creature->SetUnitMovementFlags(MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); if (pInstance) pInstance->SetData(DATA_AYAMISS_THE_HUNTER, NOT_STARTED); @@ -76,7 +76,7 @@ struct TRINITY_DLL_DECL boss_ayamissAI : public ScriptedAI void EnterCombat(Unit *who) { pTarget = who; - m_creature->SetUnitMovementFlags(MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); m_creature->GetMotionMaster()->MovePoint(0, position[0], position[1], position[2]); if (pInstance) diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_headless_horseman.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_headless_horseman.cpp index 152e888a9..30b2c259b 100755 --- a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_headless_horseman.cpp +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_headless_horseman.cpp @@ -426,7 +426,7 @@ struct TRINITY_DLL_DECL boss_headless_horsemanAI : public ScriptedAI { m_creature->SetVisibility(VISIBILITY_OFF); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->AddUnitMovementFlag(SPLINEFLAG_FLYINGING2); + m_creature->SetLevitate(true); m_creature->SetSpeed(MOVE_WALK,5.0f,true); wp_reached = false; count = 0; @@ -463,7 +463,7 @@ struct TRINITY_DLL_DECL boss_headless_horsemanAI : public ScriptedAI pInstance->SetData(GAMEOBJECT_PUMPKIN_SHRINE, 0); //hide gameobject break; case 19: - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_FLYINGING2);break; + m_creature->SetLevitate(false);break; case 20: { Phase = 1; diff --git a/src/bindings/scripts/scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp b/src/bindings/scripts/scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp index 3bbde7da3..49ae28b81 100755 --- a/src/bindings/scripts/scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp +++ b/src/bindings/scripts/scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp @@ -212,7 +212,7 @@ struct TRINITY_DLL_DECL mob_mature_netherwing_drakeAI : public ScriptedAI { float PlayerX, PlayerY, PlayerZ; caster->GetClosePoint(PlayerX, PlayerY, PlayerZ, m_creature->GetObjectSize()); - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); m_creature->GetMotionMaster()->MovePoint(1, PlayerX, PlayerY, PlayerZ); PlayerGUID = caster->GetGUID(); } @@ -228,7 +228,7 @@ struct TRINITY_DLL_DECL mob_mature_netherwing_drakeAI : public ScriptedAI IsEating = true; EatTimer = 5000; m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACKUNARMED); - m_creature->RemoveUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(false); } } @@ -309,7 +309,7 @@ struct TRINITY_DLL_DECL mob_enslaved_netherwing_drakeAI : public ScriptedAI m_creature->setFaction(FACTION_DEFAULT); FlyTimer = 10000; - m_creature->RemoveUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(false); m_creature->SetVisibility(VISIBILITY_ON); } @@ -356,7 +356,7 @@ struct TRINITY_DLL_DECL mob_enslaved_netherwing_drakeAI : public ScriptedAI PlayerGUID = 0; } m_creature->SetVisibility(VISIBILITY_OFF); - m_creature->RemoveUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(false); m_creature->DealDamage(m_creature, m_creature->GetHealth(), DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); m_creature->RemoveCorpse(); } @@ -395,7 +395,7 @@ struct TRINITY_DLL_DECL mob_enslaved_netherwing_drakeAI : public ScriptedAI dz += 25; } - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); m_creature->GetMotionMaster()->MovePoint(1, dx, dy, dz); } } @@ -444,7 +444,7 @@ struct TRINITY_DLL_DECL mob_dragonmaw_peonAI : public ScriptedAI float x, y, z; caster->GetClosePoint(x, y, z, m_creature->GetObjectSize()); - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(false); m_creature->GetMotionMaster()->MovePoint(1, x, y, z); } } @@ -937,7 +937,7 @@ struct TRINITY_DLL_DECL npc_overlord_morghorAI : public ScriptedAI case 19: DoScriptText(LORD_ILLIDAN_SAY_7, Illi); return 5000; break; case 20: Illi->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - Illi->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + Illi->SetLevitate(true); return 500; break; case 21: DoScriptText(OVERLORD_SAY_5, m_creature); return 500; break; case 22: @@ -2176,8 +2176,7 @@ struct TRINITY_DLL_DECL npc_AkamaAI : public ScriptedAI OlumGUID = Olum->GetGUID(); DoScriptText(SAY_DIALOG_OLUM_1,Olum); - Olum->SendMonsterMove(OlumNewPos[0],OlumNewPos[1],OlumNewPos[2],5000); - Olum->Relocate(OlumNewPos[0],OlumNewPos[1],OlumNewPos[2],OlumNewPos[3]); + Olum->GetMotionMaster()->MovePoint(0, OlumNewPos[0],OlumNewPos[1],OlumNewPos[2]); TalkTimer = 13000; } @@ -2221,8 +2220,7 @@ struct TRINITY_DLL_DECL npc_AkamaAI : public ScriptedAI DoScriptText(SAY_DIALOG_OLUM_5,(Creature*)olum); return 14500; case 9: - m_creature->SendMonsterMove(AkamaNewPos[0],AkamaNewPos[1],AkamaNewPos[2],2000); - m_creature->Relocate(AkamaNewPos[0],AkamaNewPos[1],AkamaNewPos[2], AkamaNewPos[3]); + m_creature->GetMotionMaster()->MovePoint(0, AkamaNewPos[0],AkamaNewPos[1],AkamaNewPos[2]); return 2500; case 10: if (olum) @@ -2235,9 +2233,9 @@ struct TRINITY_DLL_DECL npc_AkamaAI : public ScriptedAI if (Creature* spirit = m_creature->SummonCreature(OLUMS_SPIRIT,OlumNewPos[0],OlumNewPos[1],OlumNewPos[2],OlumNewPos[3]-2.0f,TEMPSUMMON_TIMED_DESPAWN,16000)) { spirit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - spirit->SetUnitMovementFlags(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + spirit->SetLevitate(true); // spirit->SetUInt32Value(UNIT_NPC_EMOTESTATE,STATE_DROWNED); // improve Olum's Spirit animation using Drowned State, right movement flag or monster move type needed - spirit->SendMonsterMove(OlumNewPos[0],OlumNewPos[1],OlumNewPos[2]+8.0f,16000); + spirit->GetMotionMaster()->MovePoint(0, OlumNewPos[0],OlumNewPos[1],OlumNewPos[2]+8.0f); } } return 7000; @@ -2245,11 +2243,10 @@ struct TRINITY_DLL_DECL npc_AkamaAI : public ScriptedAI DoScriptText(SAY_DIALOG_PRE_AKAMA_5,m_creature); return 12000; case 13: - m_creature->SendMonsterMove((AkamaPos[0]+0.1f), (AkamaPos[1]-0.1f), AkamaPos[2], 2000); - m_creature->Relocate(AkamaPos[0]+0.1f, AkamaPos[1]-0.1f, AkamaPos[2]); + m_creature->GetMotionMaster()->MovePoint(0, (AkamaPos[0]+0.1f), (AkamaPos[1]-0.1f), AkamaPos[2]); return 2100; case 14: - m_creature->SendMonsterMove((AkamaPos[0]-0.05f), (AkamaPos[1]), AkamaPos[2], 200); // just to turn back Akama to Illidan + m_creature->GetMotionMaster()->MovePoint(0, (AkamaPos[0]-0.05f), (AkamaPos[1]), AkamaPos[2]); // just to turn back Akama to Illidan return 6000; case 15: DoScriptText(SAY_DIALOG_PRE_AKAMA_6,m_creature); @@ -2528,7 +2525,7 @@ struct TRINITY_DLL_DECL mob_shadowlord_deathwailAI : public ScriptedAI if(trigger->isAlive()) { m_creature->GetMotionMaster()->Initialize(); - m_creature->SetUnitMovementFlags(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->GetMotionMaster()->MovePath(DEATHWAIL_FLYPATH, true); landed = false; @@ -2536,7 +2533,7 @@ struct TRINITY_DLL_DECL mob_shadowlord_deathwailAI : public ScriptedAI } else { - m_creature->SetUnitMovementFlags(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(true); m_creature->SetSpeed(MOVE_RUN, 1.4); m_creature->GetMotionMaster()->MovePoint(1, -3247, 284, 138.1); } @@ -2579,7 +2576,7 @@ struct TRINITY_DLL_DECL mob_shadowlord_deathwailAI : public ScriptedAI { m_creature->setFaction(1813); m_creature->GetMotionMaster()->Initialize(); - m_creature->SetUnitMovementFlags(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); m_creature->GetMotionMaster()->MovePoint(1, -3247, 284, 138.1); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); landed = true; @@ -2589,9 +2586,9 @@ struct TRINITY_DLL_DECL mob_shadowlord_deathwailAI : public ScriptedAI if(!m_creature->isInCombat() && landed && trigger && trigger->isAlive()) Reset(); - if(!m_creature->HasUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE) && m_creature->GetPositionZ() < 142) + if(!m_creature->IsWalking() && m_creature->GetPositionZ() < 142) { - m_creature->SetUnitMovementFlags(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(false); m_creature->SetSpeed(MOVE_WALK, 4.0); m_creature->SetSpeed(MOVE_RUN, 2.0); } @@ -3223,11 +3220,11 @@ struct TRINITY_DLL_DECL npc_xiriAI : public Scripted_NoMovementAI //Summon Ashtongue Deathsworns for(uint32 i = 0; i < 8; ++i) { - Unit* DeathswornAttacker = m_creature->SummonCreature(NPC_ASHTONGUE_DEATHSWORN, Deathsworn[i][0], Deathsworn[i][1], Deathsworn[i][2], Deathsworn[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); + Creature* DeathswornAttacker = m_creature->SummonCreature(NPC_ASHTONGUE_DEATHSWORN, Deathsworn[i][0], Deathsworn[i][1], Deathsworn[i][2], Deathsworn[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); if(DeathswornAttacker) { - if(DeathswornAttacker->HasUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE)) - DeathswornAttacker->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + if(DeathswornAttacker->IsWalking()) + DeathswornAttacker->SetWalk(false); DeathswornAttacker->GetMotionMaster()->MovePoint(1, DeathswornPath[i][0], DeathswornPath[i][1], DeathswornPath[i][2]); } } diff --git a/src/bindings/scripts/scripts/zone/shattrath/shattrath_city.cpp b/src/bindings/scripts/scripts/zone/shattrath/shattrath_city.cpp index 6aa59e697..add6b4cdf 100755 --- a/src/bindings/scripts/scripts/zone/shattrath/shattrath_city.cpp +++ b/src/bindings/scripts/scripts/zone/shattrath/shattrath_city.cpp @@ -767,7 +767,7 @@ struct TRINITY_DLL_DECL npc_kaelthas_imageAI : public ScriptedAI PlayersInCity.push_back((*i)->GetGUID()); } - me->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + me->SetLevitate(true); me->SetVisibility(VISIBILITY_OFF); me->StopMoving(); //DoCast(me, SPELL_OTHERWORLDLY_PORTAL, true); diff --git a/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp b/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp index b492316c3..eeecdf7a9 100755 --- a/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp +++ b/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp @@ -420,7 +420,7 @@ struct npc_marzon_silent_bladeAI : public ScriptedAI { npc_marzon_silent_bladeAI(Creature* pCreature) : ScriptedAI(pCreature) { - me->AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + me->SetWalk(true); } void Reset() @@ -1101,7 +1101,7 @@ struct TRINITY_DLL_DECL npc_reginald_windsorAI : public npc_escortAI { tmpCreature = me->SummonCreature(NPC_STORMWIND_ELITE_GUARD_ID, StormwindGuardsCoords[i+1][0], StormwindGuardsCoords[i+1][1], StormwindGuardsCoords[i+1][2], StormwindGuardsCoords[i+1][3], TEMPSUMMON_TIMED_DESPAWN, 300000); ((npc_stormwind_elite_guardAI*)(tmpCreature->AI()))->npcNumber = i; - tmpCreature->AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + tmpCreature->SetWalk(true); if (i < 3) npcRight[i] = tmpCreature->GetGUID(); else @@ -1428,7 +1428,7 @@ struct TRINITY_DLL_DECL npc_reginald_windsorAI : public npc_escortAI if (majesty) { - majesty->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + majesty->SetWalk(false); majesty->SetSpeed(MOVE_RUN, 1.5); majesty->GetMotionMaster()->MovePoint(0, MAJESTY_MOVE_COORDS); majesty->TextEmote(ANDUIN_WRYN_EMOTE, NULL); @@ -1484,7 +1484,7 @@ struct TRINITY_DLL_DECL npc_reginald_windsorAI : public npc_escortAI break; case 10: fordragon->SetSpeed(MOVE_RUN, 2.0); - fordragon->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + fordragon->SetWalk(false); fordragon->GetMotionMaster()->MovePoint(0, FORDRAGON_MOVE_COORDS); phaseTimer = 1000; break; @@ -1574,7 +1574,7 @@ struct TRINITY_DLL_DECL npc_reginald_windsorAI : public npc_escortAI break; case 16: fordragon->SetSpeed(MOVE_RUN, 2.0); - fordragon->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + fordragon->SetWalk(false); fordragon->GetMotionMaster()->MovePoint(0, FORDRAGON_MOVE_COORDS); phaseTimer = 1500; break; diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_brutallus.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_brutallus.cpp index 38742c8c5..81611ee32 100755 --- a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_brutallus.cpp +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_brutallus.cpp @@ -165,7 +165,7 @@ struct TRINITY_DLL_DECL boss_brutallusAI : public ScriptedAI void DoIntro() { - Unit *pMadrigosa = me->GetUnit(pInstance->GetData64(DATA_MADRIGOSA)); + Creature *pMadrigosa = (Creature*)me->GetUnit(pInstance->GetData64(DATA_MADRIGOSA)); if (!pMadrigosa) return; @@ -192,7 +192,7 @@ struct TRINITY_DLL_DECL boss_brutallusAI : public ScriptedAI case 3: { AddSpellToCast(me, SPELL_INTRO_FROST_BLAST); - pMadrigosa->AddUnitMovementFlag(SPLINEFLAG_FLYINGING2 | MOVEFLAG_CAN_FLY); + pMadrigosa->SetLevitate(true); float x, y, z; pMadrigosa->GetPosition(x, y, z); pMadrigosa->GetMotionMaster()->MovePoint(1, x, y, z+10); @@ -373,13 +373,13 @@ struct TRINITY_DLL_DECL npc_death_cloudAI : public ScriptedAI } else { - if (Unit* pFelmyst= me->GetUnit(pInstance->GetData64(DATA_FELMYST))) + if (Creature* pFelmyst= (Creature*)me->GetUnit(pInstance->GetData64(DATA_FELMYST))) { pMadrigosa->GetPosition(x, y, z); ((Creature*)pFelmyst)->Respawn(); pFelmyst->Relocate(x, y, z); - pFelmyst->RemoveUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); - pFelmyst->GetMotionMaster()->MoveRandom(1); + pFelmyst->SetLevitate(false); + pFelmyst->GetMotionMaster()->MoveRandom(); } ((Creature*)pMadrigosa)->RemoveCorpse(); } diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp index 0a6c5a483..6457dadd1 100755 --- a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp @@ -177,7 +177,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI OutroPhase = 0; OutroTimer = 0; - m_creature->AddUnitMovementFlag(FELMYST_FLY_FLAGS); + m_creature->SetLevitate(true); m_creature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); m_creature->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); m_creature->setHover(true); @@ -194,7 +194,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI m_creature->setActive(true); DoZoneInCombat(); m_creature->CastSpell(m_creature, AURA_NOXIOUS_FUMES, true); - m_creature->RemoveUnitMovementFlag(FELMYST_FLY_FLAGS); + m_creature->SetLevitate(false); EnterPhase(PHASE_GROUND); if(pInstance) @@ -260,7 +260,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI else if(summon->GetEntry() == MOB_KALECGOS) { summon->setActive(true); - summon->AddUnitMovementFlag(SPLINEFLAG_FLYINGING2 | MOVEFLAG_CAN_FLY); + summon->SetLevitate(true); summon->GetMotionMaster()->MovePoint(0, 1471, 632, 37); KalecgosGUID = summon->GetGUID(); OutroTimer = 20000; @@ -357,7 +357,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI { case 0: m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - m_creature->AddUnitMovementFlag(FELMYST_FLY_FLAGS); + m_creature->SetLevitate(true); DoScriptText(YELL_TAKEOFF, m_creature); Timer[EVENT_FLIGHT_SEQUENCE] = 2000; break; @@ -431,7 +431,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI Timer[EVENT_FLIGHT_SEQUENCE] = 0; break; case 10: - m_creature->RemoveUnitMovementFlag(FELMYST_FLY_FLAGS); + m_creature->SetLevitate(false); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); EnterPhase(PHASE_GROUND); AttackStart(m_creature->getVictim()); @@ -449,7 +449,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI { if(EvadeTimer <= diff) { - m_creature->AddUnitMovementFlag(FELMYST_FLY_FLAGS); + m_creature->SetLevitate(true); EnterEvadeMode(); EvadeTimer = 0; return; diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp index df949a174..1d275852b 100755 --- a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp @@ -134,7 +134,7 @@ struct TRINITY_DLL_DECL boss_kalecgosAI : public ScriptedAI { m_creature->setFaction(14); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_FLYINGING2 | MOVEFLAG_CAN_FLY); + m_creature->SetLevitate(false); m_creature->SetStandState(PLAYER_STATE_SLEEP); ArcaneBuffetTimer = 8000; @@ -202,7 +202,7 @@ struct TRINITY_DLL_DECL boss_kalecgosAI : public ScriptedAI TalkTimer = 10000; break; case 3: - m_creature->AddUnitMovementFlag(SPLINEFLAG_FLYINGING2 | MOVEFLAG_CAN_FLY); + m_creature->SetLevitate(true); m_creature->GetMotionMaster()->Clear(); m_creature->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); TalkTimer = 60000; @@ -227,7 +227,7 @@ struct TRINITY_DLL_DECL boss_kalecgosAI : public ScriptedAI TalkTimer = 3000; break; case 2: - m_creature->AddUnitMovementFlag(SPLINEFLAG_FLYINGING2 | MOVEFLAG_CAN_FLY); + m_creature->SetLevitate(true); m_creature->GetMotionMaster()->Clear(); m_creature->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); TalkTimer = 10000; diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kiljaeden.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kiljaeden.cpp index 95bc72487..a6a229501 100755 --- a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kiljaeden.cpp +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kiljaeden.cpp @@ -312,7 +312,7 @@ struct TRINITY_DLL_DECL boss_kalecgos_kjAI : public ScriptedAI FindOrbs(); OrbsEmpowered = 0; EmpowerCount = 0; - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->setActive(true); Searched = false; @@ -756,7 +756,7 @@ struct TRINITY_DLL_DECL mob_kiljaeden_controllerAI : public Scripted_NoMovementA summoned->CastSpell(summoned, SPELL_SHADOW_CHANNELING, false); break; case CREATURE_ANVEENA: - summoned->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + summoned->SetLevitate(true); summoned->CastSpell(summoned, SPELL_ANVEENA_PRISON, true); summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); break; @@ -1055,7 +1055,7 @@ struct TRINITY_DLL_DECL mob_shield_orbAI : public ScriptedAI float x, y, r, c, mx, my; void InitializeAI(){ - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); PointReached = true; Timer = 500+ rand()%500; CheckTimer = 1000; diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/arcatraz.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/arcatraz.cpp index 2444c11b6..67745dd6f 100755 --- a/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/arcatraz.cpp +++ b/src/bindings/scripts/scripts/zone/tempest_keep/arcatraz/arcatraz.cpp @@ -284,7 +284,7 @@ struct TRINITY_DLL_DECL npc_warden_mellicharAI : public ScriptedAI if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessiblePlacefor(m_creature) ) { - if (!m_creature->canFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + if (!m_creature->CanFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) return; if (who->GetTypeId() != TYPEID_PLAYER) return; diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp index caf678748..237f3bee5 100755 --- a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp @@ -129,7 +129,7 @@ struct TRINITY_DLL_DECL boss_alarAI : public ScriptedAI m_creature->SetDisplayId(m_creature->GetNativeDisplayId()); m_creature->SetSpeed(MOVE_RUN, 3.0); m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - m_creature->SetUnitMovementFlags(MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->setActive(false); @@ -141,7 +141,7 @@ struct TRINITY_DLL_DECL boss_alarAI : public ScriptedAI pInstance->SetData(DATA_ALAREVENT, IN_PROGRESS); m_creature->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); - m_creature->SetUnitMovementFlags(MOVEFLAG_LEVITATING); // after enterevademode will be set walk movement + m_creature->SetLevitate(true); // after enterevademode will be set walk movement m_creature->setActive(true); DoZoneInCombat(); } @@ -507,7 +507,7 @@ struct TRINITY_DLL_DECL boss_alarAI : public ScriptedAI if(m_creature->IsWithinMeleeRange(temp, 6.0)) { - if(m_creature->hasUnitState(UNIT_STAT_CASTING)) // TO JEST DO POTWIERDZENIA: + if(m_creature->IsNonMeleeSpellCasted(false)) // TO JEST DO POTWIERDZENIA: m_creature->InterruptNonMeleeSpells(true); // PRZERWAC CASTA FLAME BUFFET, // GDY CEL ZNAJDZIE SIE W MELEE RANGE CZY NIE ! UnitAI::DoMeleeAttackIfReady(); @@ -540,7 +540,7 @@ struct TRINITY_DLL_DECL mob_ember_of_alarAI : public ScriptedAI mob_ember_of_alarAI(Creature *c) : ScriptedAI(c) { pInstance = (ScriptedInstance*)c->GetInstanceData(); - c->SetUnitMovementFlags(MOVEFLAG_LEVITATING); + c->SetLevitate(true); c->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); } diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp index e1432be9a..e644bbb1c 100755 --- a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp @@ -498,7 +498,7 @@ struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && who->isTargetableForAttack() && m_creature->IsHostileTo(who)) { - if (!m_creature->canFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + if (!m_creature->CanFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) return; float attackRadius = m_creature->GetAttackDistance(who); @@ -614,8 +614,9 @@ struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI DoScriptText(SAY_PHASE5_NUTS, m_creature); return 1000; case 5: - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); - m_creature->SendMonsterMove(GRAVITY_X-0.5f, GRAVITY_Y, GRAVITY_Z+25.0f, 12000); + m_creature->SetLevitate(true); + // Need to set proper speed ? + m_creature->GetMotionMaster()->MovePoint(0, GRAVITY_X-0.5f, GRAVITY_Y, GRAVITY_Z+25.0f); DoCast(m_creature, SPELL_EXPLODE_SHAKE1, true); return 4000; case 6: @@ -650,15 +651,15 @@ struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI case 14: return 2000; case 15: - m_creature->SendMonsterMove(GRAVITY_X-1.0f, GRAVITY_Y, GRAVITY_Z, 13000); - m_creature->Relocate(GRAVITY_X-1.0f, GRAVITY_Y, GRAVITY_Z); + m_creature->GetMotionMaster()->MovePoint(0, GRAVITY_X-1.0f, GRAVITY_Y, GRAVITY_Z); + //m_creature->Relocate(GRAVITY_X-1.0f, GRAVITY_Y, GRAVITY_Z); return 13000; case 16: m_creature->Relocate(GRAVITY_X-1.0f, GRAVITY_Y, GRAVITY_Z); m_creature->InterruptNonMeleeSpells(false); m_creature->RemoveAurasDueToSpell(SPELL_FULLPOWER); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->RemoveUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(false); Phase = 6; if (Unit * target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0)) { @@ -1313,7 +1314,7 @@ struct TRINITY_DLL_DECL boss_thaladred_the_darkenerAI : public advisorbase_ai Check_Timer = 1000; Check_Timer2 = 3000; - m_creature->AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(true); m_creature->SetSpeed(MOVE_WALK, 2.0f, false); advisorbase_ai::Reset(); @@ -1797,7 +1798,7 @@ struct TRINITY_DLL_DECL mob_phoenix_tkAI : public ScriptedAI void Reset() { - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING);//birds can fly! :) + m_creature->SetLevitate(true);//birds can fly! :) Cycle_Timer = 2000; Egg = true; m_creature->CastSpell(m_creature,SPELL_BURN,true); @@ -1965,7 +1966,7 @@ struct TRINITY_DLL_DECL mob_nether_vaporAI : public ScriptedAI Move_Timer = 500; m_creature->setFaction(16); - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->CastSpell(m_creature, SPELL_NETHER_VAPOR, false); @@ -1989,7 +1990,7 @@ struct TRINITY_DLL_DECL mob_nether_vaporAI : public ScriptedAI float newX, newY, newZ; m_creature->Relocate(m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ()); m_creature->GetRandomPoint(m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(), 6.0, newX, newY, newZ); - m_creature->SendMonsterMoveWithSpeed(newX, newY, newZ, 2500); + m_creature->GetMotionMaster()->MovePoint(0, newX, newY, newZ); Move_Timer = 3000; } else diff --git a/src/bindings/scripts/scripts/zone/terokkar_forest/terokkar_forest.cpp b/src/bindings/scripts/scripts/zone/terokkar_forest/terokkar_forest.cpp index 3c70b7f50..33ff50581 100755 --- a/src/bindings/scripts/scripts/zone/terokkar_forest/terokkar_forest.cpp +++ b/src/bindings/scripts/scripts/zone/terokkar_forest/terokkar_forest.cpp @@ -409,7 +409,7 @@ struct TRINITY_DLL_DECL npc_isla_starmaneAI : public npc_escortAI m_creature->SetInFront(player); break; case 30: m_creature->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); break; case 31: DoCast(m_creature, SPELL_CAT); - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); break; + m_creature->SetWalk(false); break; } } @@ -1933,7 +1933,7 @@ struct TRINITY_DLL_DECL quest_the_vengeful_harbringerAI : public ScriptedAI return; visual_energy->CastSpell(visual_energy,46242,true); // Visual magic ball - visual_energy->SendMonsterMove(portal_trigger->GetPositionX(),portal_trigger->GetPositionY(),portal_trigger->GetPositionZ(),1500); + visual_energy->NearTeleportTo(portal_trigger->GetPositionX(),portal_trigger->GetPositionY(),portal_trigger->GetPositionZ(), portal_trigger->GetOrientation()); std::list beam_visual_triggers = DoFindAllCreaturesWithEntry(21451, 30.0f); for (std::list::iterator itr = beam_visual_triggers.begin(); itr != beam_visual_triggers.end(); ++itr) @@ -1972,7 +1972,7 @@ struct TRINITY_DLL_DECL quest_the_vengeful_harbringerAI : public ScriptedAI return; Dranei_Guardian->GetMotionMaster()->MovePoint(0,Defender_Trigger->GetPositionX(),Defender_Trigger->GetPositionY(),Defender_Trigger->GetPositionZ()); - Dranei_Guardian->SendMonsterMove(Defender_Trigger->GetPositionX(),Defender_Trigger->GetPositionY(),Defender_Trigger->GetPositionZ(),6000); //we ned this to visual movement with delay + //Dranei_Guardian->SendMonsterMove(Defender_Trigger->GetPositionX(),Defender_Trigger->GetPositionY(),Defender_Trigger->GetPositionZ(),6000); //we ned this to visual movement with delay } } else @@ -2178,7 +2178,7 @@ struct npc_akunoAI : public npc_escortAI void JustSummoned(Creature* pSummoned) { - pSummoned->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + pSummoned->SetWalk(false); pSummoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); pSummoned->AI()->AttackStart(me); } diff --git a/src/bindings/scripts/scripts/zone/undercity/undercity.cpp b/src/bindings/scripts/scripts/zone/undercity/undercity.cpp index 8f936f73a..5c05c4449 100755 --- a/src/bindings/scripts/scripts/zone/undercity/undercity.cpp +++ b/src/bindings/scripts/scripts/zone/undercity/undercity.cpp @@ -86,12 +86,11 @@ struct TRINITY_DLL_DECL npc_lady_sylvanas_windrunnerAI : public ScriptedAI { if( Unit* target = Unit::GetUnit(*summoned,targetGUID) ) { - target->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), myZ+15.0,0); - target->Relocate(target->GetPositionX(), target->GetPositionY(), myZ+15.0); + target->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), myZ+15.0,0); summoned->CastSpell(target, SPELL_RIBBON_OF_SOULS, false); } - summoned->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT); + summoned->SetLevitate(true); targetGUID = summoned->GetGUID(); } } @@ -174,8 +173,8 @@ struct TRINITY_DLL_DECL npc_highborne_lamenterAI : public ScriptedAI { if( EventMove_Timer < diff ) { - m_creature->AddUnitMovementFlag(MOVEFLAG_ONTRANSPORT | MOVEFLAG_LEVITATING); - m_creature->SendMonsterMoveWithSpeed(m_creature->GetPositionX(),m_creature->GetPositionY(),HIGHBORNE_LOC_Y_NEW,5000); m_creature->GetMap()->CreatureRelocation(m_creature,m_creature->GetPositionX(),m_creature->GetPositionY(),HIGHBORNE_LOC_Y_NEW,m_creature->GetOrientation()); + m_creature->SetLevitate(true); + m_creature->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(),m_creature->GetPositionY(),HIGHBORNE_LOC_Y_NEW); m_creature->GetMap()->CreatureRelocation(m_creature,m_creature->GetPositionX(),m_creature->GetPositionY(),HIGHBORNE_LOC_Y_NEW,m_creature->GetOrientation()); EventMove = false; }else EventMove_Timer -= diff; } diff --git a/src/bindings/scripts/scripts/zone/western_plaguelands/western_plaguelands.cpp b/src/bindings/scripts/scripts/zone/western_plaguelands/western_plaguelands.cpp index 6d1c3eadd..284010e39 100755 --- a/src/bindings/scripts/scripts/zone/western_plaguelands/western_plaguelands.cpp +++ b/src/bindings/scripts/scripts/zone/western_plaguelands/western_plaguelands.cpp @@ -278,7 +278,7 @@ struct npc_anchorite_truuenAI : public npc_escortAI if(Creature* Ughost = m_creature->SummonCreature(NPC_GHOST_UTHER, 971.86,-1825.42 ,81.99 , 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) { UghostGUID = Ughost->GetGUID(); - Ughost->AddUnitMovementFlag(MOVEFLAG_LEVITATING); + Ughost->SetLevitate(true); DoScriptText(SAY_WP_4, Ughost, m_creature); m_uiChatTimer = 4000; } diff --git a/src/bindings/scripts/scripts/zone/westfall/westfall.cpp b/src/bindings/scripts/scripts/zone/westfall/westfall.cpp index cf8013c66..e60050c6e 100755 --- a/src/bindings/scripts/scripts/zone/westfall/westfall.cpp +++ b/src/bindings/scripts/scripts/zone/westfall/westfall.cpp @@ -89,8 +89,8 @@ struct TRINITY_DLL_DECL npc_daphne_stilwellAI : public npc_escortAI if (!player) return; - if (IsWalking && !m_creature->HasUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE)) - m_creature->AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + if (IsWalking && !m_creature->IsWalking()) + m_creature->SetWalk(true); switch (i) { @@ -132,9 +132,9 @@ struct TRINITY_DLL_DECL npc_daphne_stilwellAI : public npc_escortAI void Reset() { - if (IsWalking && !m_creature->HasUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE)) + if (IsWalking && !m_creature->IsWalking()) { - m_creature->AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(true); return; } IsWalking = false; diff --git a/src/bindings/scripts/scripts/zone/zangarmarsh/zangarmarsh.cpp b/src/bindings/scripts/scripts/zone/zangarmarsh/zangarmarsh.cpp index c53f63d8c..a06af169d 100755 --- a/src/bindings/scripts/scripts/zone/zangarmarsh/zangarmarsh.cpp +++ b/src/bindings/scripts/scripts/zone/zangarmarsh/zangarmarsh.cpp @@ -296,13 +296,13 @@ struct TRINITY_DLL_DECL npc_kayra_longmaneAI : public npc_escortAI m_creature->SummonCreature(MOB_AMBUSH, -922.24, 5357.98, 17.93, 5.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); break; case 6: DoScriptText(SAY_PROGRESS_3, m_creature, player); - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(false); break; case 18: DoScriptText(SAY_PROGRESS_4, m_creature, player); m_creature->SummonCreature(MOB_AMBUSH, -671.86, 5379.81, 22.12, 5.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); m_creature->SummonCreature(MOB_AMBUSH, -671.86, 5379.81, 22.12, 5.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); break; - case 19: m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + case 19: m_creature->SetWalk(false); DoScriptText(SAY_PROGRESS_5, m_creature, player); break; case 26: DoScriptText(SAY_PROGRESS_6, m_creature, player); if(player) diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp index 430f6aed1..70550d0c9 100755 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp @@ -129,11 +129,11 @@ struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI float x, y, z; m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()+15.0f, 30.0f, x, y, z); - Unit* Eagle = m_creature->SummonCreature(NPC_SOARING_EAGLE, x, y, z, m_creature->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); + Creature* Eagle = m_creature->SummonCreature(NPC_SOARING_EAGLE, x, y, z, m_creature->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); if(Eagle) { Eagle->setFaction(me->getFaction()); - Eagle->SetUnitMovementFlags(MOVEFLAG_LEVITATING | MOVEFLAG_ONTRANSPORT); + Eagle->SetLevitate(true); Eagle->GetMotionMaster()->MoveIdle(); } } @@ -240,7 +240,7 @@ struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI // throw player to air and cast electrical storm on (should be handled by proper script effect targeting?) float x,y,z; target->GetPosition(x,y,z); - target->SendMonsterMove(x,y,m_creature->GetPositionZ()+15,0); + target->NearTeleportTo(x,y,m_creature->GetPositionZ()+15.0f, target->GetOrientation()); DoScriptText(EMOTE_STORM, m_creature, 0, true); m_creature->CastSpell(target, SPELL_ELECTRICAL_STORM, false); @@ -305,8 +305,8 @@ struct TRINITY_DLL_DECL mob_soaring_eagleAI : public ScriptedAI { float x, y, z; Akil->GetRandomPoint(Akil->GetPositionX(), Akil->GetPositionY(), Akil->GetPositionZ()+15.0f, 30.0f, x, y, z); - if(m_creature->HasUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE)) - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + if(m_creature->IsWalking()) + m_creature->SetWalk(false); m_creature->GetMotionMaster()->MovePoint(1, x, y, z); canMoveRandom = false; } diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp index af5f11834..ce893c6c0 100755 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp @@ -648,7 +648,7 @@ struct TRINITY_DLL_DECL mob_hatchlingAI : public ScriptedAI else m_creature->GetMotionMaster()->MovePoint(0,hatcherway[1][3][0]+rand()%4-2,1150+rand()%4-2,hatcherway[1][3][2]); - m_creature->SetUnitMovementFlags(MOVEFLAG_LEVITATING); + m_creature->SetLevitate(true); } void EnterCombat(Unit *who) {/*DoZoneInCombat();*/} diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp index 55164ff98..37c245672 100755 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp @@ -127,7 +127,7 @@ struct TRINITY_DLL_DECL boss_nalorakkAI : public ScriptedAI inMove = false; waitTimer = 0; m_creature->SetSpeed(MOVE_RUN,2); - m_creature->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + m_creature->SetWalk(false); }else { (*m_creature).GetMotionMaster()->MovePoint(0,NalorakkWay[7][0],NalorakkWay[7][1],NalorakkWay[7][2]); diff --git a/src/bindings/scripts/scripts/zone/zulaman/zulaman.cpp b/src/bindings/scripts/scripts/zone/zulaman/zulaman.cpp index ea53d7a25..096c5faef 100755 --- a/src/bindings/scripts/scripts/zone/zulaman/zulaman.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/zulaman.cpp @@ -432,7 +432,7 @@ struct TRINITY_DLL_DECL npc_ashliAI : public ScriptedAI CheckTimer -= diff; } - if(Fire && !m_creature->hasUnitState(UNIT_STAT_CASTING)) + if(Fire && !m_creature->IsNonMeleeSpellCasted(false)) { Unit *target = NULL; if(!targets.empty()) diff --git a/src/game/AntiCheat.h b/src/game/AntiCheat.h index b7bcdf59c..3256f8917 100644 --- a/src/game/AntiCheat.h +++ b/src/game/AntiCheat.h @@ -1,7 +1,6 @@ #ifndef _ANTICHEAT_H #define _ANTICHEAT_H - ///////////////// old #include @@ -34,13 +33,13 @@ class ACRequest : public ACE_Method_Request return -1; // teleport to plane cheat - if (m_newPacket.pos.z == 0.0f) + if (m_newPacket.GetPos()->z == 0.0f) { - float tmpZ = pPlayer->GetMap()->GetHeight(m_newPacket.pos.x, m_newPacket.pos.y, MAX_HEIGHT, false); + float tmpZ = pPlayer->GetMap()->GetHeight(m_newPacket.GetPos()->x, m_newPacket.GetPos()->y, MAX_HEIGHT, false); if ((tmpZ > 2.0f || tmpZ < -2.0f) && tmpZ > -100000.0f) { sLog.outCheat("Player %s (GUID: %u / ACCOUNT_ID: %u) - teleport to plane cheat. MapId: %u, MapHeight: %u, coords: %f, %f, %f. MOVEMENTFLAGS: %u LATENCY: %u. BG/Arena: %s", - pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), tmpZ, m_newPacket.pos.x, m_newPacket.pos.y, m_newPacket.pos.z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); + pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), tmpZ, m_newPacket.GetPos()->x, m_newPacket.GetPos()->y, m_newPacket.GetPos()->z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); pPlayer->Relocate(m_pos.x, m_pos.y, tmpZ, m_pos.o); pPlayer->GetSession()->KickPlayer(); return 0; @@ -63,19 +62,19 @@ class ACRequest : public ACE_Method_Request return -1; // charging - if (pPlayer->hasUnitState(UNIT_STAT_CHARGING)) - return -1; + //if (pPlayer->hasUnitState(UNIT_STAT_CHARGING)) + // return -1; uint32 latency = pPlayer->GetSession()->GetLatency(); // fly cheat - if (!m_newPacket.HasMovementFlag(MOVEFLAG_SWIMMING) && m_newPacket.GetMovementFlags() & (MOVEFLAG_CAN_FLY | SPLINEFLAG_FLYINGING | SPLINEFLAG_FLYINGING2) && - !(pPlayer->HasAuraType(SPELL_AURA_FLY) || pPlayer->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || pPlayer->HasAuraType(SPELL_AURA_MOD_SPEED_FLIGHT))) + if (!m_newPacket.HasMovementFlag(MOVEFLAG_SWIMMING) && m_newPacket.GetMovementFlags() & (MOVEFLAG_CAN_FLY | MOVEFLAG_FLYING | MOVEFLAG_DESCENDING) && + !pPlayer->IsFreeFlying()) { if (latency == 0 || latency > AC_MAX_LATENCY) { sLog.outCheat("Player %s (GUID: %u / ACCOUNT_ID: %u) - possible Fly Cheat (LATENCY KICKED). MapId: %u, coords: x: %f, y: %f, z: %f. MOVEMENTFLAGS: %u LATENCY: %u. BG/Arena: %s", - pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), m_newPacket.pos.x, m_newPacket.pos.y, m_newPacket.pos.z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); + pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), m_newPacket.GetPos()->x, m_newPacket.GetPos()->y, m_newPacket.GetPos()->z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); pPlayer->GetSession()->KickPlayer(); return 0; @@ -83,7 +82,7 @@ class ACRequest : public ACE_Method_Request sWorld.SendGMText(LANG_ANTICHEAT_FLY, pPlayer->GetName()); sLog.outCheat("Player %s (GUID: %u / ACCOUNT_ID: %u) - possible Fly Cheat. MapId: %u, coords: x: %f, y: %f, z: %f. MOVEMENTFLAGS: %u LATENCY: %u. BG/Arena: %s", - pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), m_newPacket.pos.x, m_newPacket.pos.y, m_newPacket.pos.z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); + pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), m_newPacket.GetPos()->x, m_newPacket.GetPos()->y, m_newPacket.GetPos()->z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); } // water walk cheat @@ -93,13 +92,13 @@ class ACRequest : public ACE_Method_Request if (latency == 0 || latency > AC_MAX_LATENCY) { sLog.outCheat("Player %s (GUID: %u / ACCOUNT_ID: %u) - possible water walk Cheat (LATENCY KICKED). MapId: %u, coords: %f %f %f. MOVEMENTFLAGS: %u LATENCY: %u. BG/Arena: %s", - pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), m_newPacket.pos.x, m_newPacket.pos.y, m_newPacket.pos.z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); + pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), m_newPacket.GetPos()->x, m_newPacket.GetPos()->y, m_newPacket.GetPos()->z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); pPlayer->GetSession()->KickPlayer(); return 0; } sLog.outCheat("Player %s (GUID: %u / ACCOUNT_ID: %u) - possible water walk Cheat. MapId: %u, coords: %f %f %f. MOVEMENTFLAGS: %u LATENCY: %u. BG/Arena: %s", - pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), m_newPacket.pos.x, m_newPacket.pos.y, m_newPacket.pos.z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); + pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), m_newPacket.GetPos()->x, m_newPacket.GetPos()->y, m_newPacket.GetPos()->z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); //m_newPacket.RemoveMovementFlag(MOVEFLAG_WATERWALKING); sWorld.SendGMText(LANG_ANTICHEAT_WATERWALK, pPlayer->GetName()); @@ -133,12 +132,12 @@ class ACRequest : public ACE_Method_Request //if (pPlayer->GetMap() && pPlayer->GetMap()->IsBattleGroundOrArena()) // return -1; - float dx = m_newPacket.pos.x - m_pos.x; - float dy = m_newPacket.pos.y - m_pos.y; + float dx = m_newPacket.GetPos()->x - m_pos.x; + float dy = m_newPacket.GetPos()->y - m_pos.y; float fDistance2d = sqrt(dx*dx + dy*dy); // time between packets - uint32 uiDiffTime = WorldTimer::getMSTimeDiff(m_oldPacket.time, m_newPacket.time); + uint32 uiDiffTime = WorldTimer::getMSTimeDiff(m_oldPacket.GetTime(), m_newPacket.GetTime()); float fClientRate = (fDistance2d * 1000 / uiDiffTime) / m_speed; float fServerRate = m_speed * uiDiffTime / 1000 +1.0f; @@ -151,7 +150,7 @@ class ACRequest : public ACE_Method_Request if (latency == 0 || latency > AC_MAX_LATENCY) { sLog.outCheat("Player %s (GUID: %u / ACCOUNT_ID: %u) (LATENCY KICKED) moved for distance %f with server speed : %f (client speed: %f). MapID: %u, player's coord before X:%f Y:%f Z:%f. Player's coord now X:%f Y:%f Z:%f. MOVEMENTFLAGS: %u LATENCY: %u. BG/Arena: %s", - pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), fDistance2d, m_speed, m_speed*fClientRate, pPlayer->GetMapId(), m_pos.x, m_pos.y, m_pos.z, m_newPacket.pos.x, m_newPacket.pos.y, m_newPacket.pos.z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); + pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), fDistance2d, m_speed, m_speed*fClientRate, pPlayer->GetMapId(), m_pos.x, m_pos.y, m_pos.z, m_newPacket.GetPos()->x, m_newPacket.GetPos()->y, m_newPacket.GetPos()->z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); pPlayer->GetSession()->KickPlayer(); return 0; } @@ -163,7 +162,7 @@ class ACRequest : public ACE_Method_Request sWorld.SendGMText(LANG_ANTICHEAT, pPlayer->GetName(), pPlayer->m_AC_count, m_speed, m_speed*fClientRate); sLog.outCheat("Player %s (GUID: %u / ACCOUNT_ID: %u) moved for distance %f with server speed : %f (client speed: %f). MapID: %u, player's coord before X:%f Y:%f Z:%f. Player's coord now X:%f Y:%f Z:%f. MOVEMENTFLAGS: %u LATENCY: %u. BG/Arena: %s", - pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), fDistance2d, m_speed, m_speed*fClientRate, pPlayer->GetMapId(), m_pos.x, m_pos.y, m_pos.z, m_newPacket.pos.x, m_newPacket.pos.y, m_newPacket.pos.z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); + pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), fDistance2d, m_speed, m_speed*fClientRate, pPlayer->GetMapId(), m_pos.x, m_pos.y, m_pos.z, m_newPacket.GetPos()->x, m_newPacket.GetPos()->y, m_newPacket.GetPos()->z, m_newPacket.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); } return 0; } diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 15ac4a794..a7f1c1d38 100755 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -439,7 +439,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode(WorldPacket &recv_data) _player->SpawnCorpseBones(); } // stop taxi flight at port - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 5b14e887c..2e7698a95 100755 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -692,55 +692,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) pCurrChar->SetMovement(MOVE_WATER_WALK); } - if (uint32 sourceNode = pCurrChar->m_taxi.GetTaxiSource()) - { - - sLog.outDebug("WORLD: Restart character %u taxi flight", pCurrChar->GetGUIDLow()); - - uint32 MountId = objmgr.GetTaxiMount(sourceNode, pCurrChar->GetTeam()); - uint32 path = pCurrChar->m_taxi.GetCurrentTaxiPath(); - - // search appropriate start path node - uint32 startNode = 0; - - TaxiPathNodeList const& nodeList = sTaxiPathNodesByPath[path]; - - float distPrev = MAP_SIZE*MAP_SIZE; - float distNext = - (nodeList[0].x-pCurrChar->GetPositionX())*(nodeList[0].x-pCurrChar->GetPositionX())+ - (nodeList[0].y-pCurrChar->GetPositionY())*(nodeList[0].y-pCurrChar->GetPositionY())+ - (nodeList[0].z-pCurrChar->GetPositionZ())*(nodeList[0].z-pCurrChar->GetPositionZ()); - - for (uint32 i = 1; i < nodeList.size(); ++i) - { - TaxiPathNode const& node = nodeList[i]; - TaxiPathNode const& prevNode = nodeList[i-1]; - - // skip nodes at another map - if (node.mapid != pCurrChar->GetMapId()) - continue; - - distPrev = distNext; - - distNext = - (node.x-pCurrChar->GetPositionX())*(node.x-pCurrChar->GetPositionX())+ - (node.y-pCurrChar->GetPositionY())*(node.y-pCurrChar->GetPositionY())+ - (node.z-pCurrChar->GetPositionZ())*(node.z-pCurrChar->GetPositionZ()); - - float distNodes = - (node.x-prevNode.x)*(node.x-prevNode.x)+ - (node.y-prevNode.y)*(node.y-prevNode.y)+ - (node.z-prevNode.z)*(node.z-prevNode.z); - - if (distNext + distPrev < distNodes) - { - startNode = i; - break; - } - } - - SendDoFlight(MountId, path, startNode); - } + pCurrChar->ContinueTaxiFlight(); // Load pet if any and player is alive and not in taxi flight if (pCurrChar->isAlive() && pCurrChar->m_taxi.GetTaxiSource()==0) diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp index e9e103143..68e02604b 100755 --- a/src/game/ChatHandler.cpp +++ b/src/game/ChatHandler.cpp @@ -517,8 +517,9 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) void WorldSession::HandleEmoteOpcode(WorldPacket & recv_data) { - if (!GetPlayer()->isAlive() || GetPlayer()->isPossessed() || GetPlayer()->isCharmed()) + if (!GetPlayer()->isAlive() || GetPlayer()->isCharmed()) return; + CHECK_PACKET_SIZE(recv_data,4); uint32 emote; @@ -528,7 +529,7 @@ void WorldSession::HandleEmoteOpcode(WorldPacket & recv_data) void WorldSession::HandleTextEmoteOpcode(WorldPacket & recv_data) { - if (!GetPlayer()->isAlive() || GetPlayer()->isPossessed() || GetPlayer()->isCharmed()) + if (!GetPlayer()->isAlive() || GetPlayer()->isCharmed()) return; if (!GetPlayer()->CanSpeak()) diff --git a/src/game/CombatAI.cpp b/src/game/CombatAI.cpp index 222de5c60..375f3effe 100644 --- a/src/game/CombatAI.cpp +++ b/src/game/CombatAI.cpp @@ -83,7 +83,7 @@ void CombatAI::UpdateAI(const uint32 diff) events.Update(diff); - if (me->hasUnitState(UNIT_STAT_CASTING)) + if (me->IsNonMeleeSpellCasted(false)) return; if (uint32 spellId = events.ExecuteEvent()) @@ -143,7 +143,7 @@ void CasterAI::UpdateAI(const uint32 diff) events.Update(diff); - if (me->hasUnitState(UNIT_STAT_CASTING)) + if (me->IsNonMeleeSpellCasted(false)) return; if (uint32 spellId = events.ExecuteEvent()) diff --git a/src/game/ConfusedMovementGenerator.cpp b/src/game/ConfusedMovementGenerator.cpp index e67ce6b29..bf10417b1 100755 --- a/src/game/ConfusedMovementGenerator.cpp +++ b/src/game/ConfusedMovementGenerator.cpp @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,133 +8,154 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "Creature.h" -#include "MapManager.h" -#include "Opcodes.h" #include "ConfusedMovementGenerator.h" -#include "DestinationHolderImp.h" -#include "VMapFactory.h" +#include "MapManager.h" +#include "Creature.h" +#include "Player.h" +#include "movement/MoveSplineInit.h" +#include "movement/MoveSpline.h" template -void ConfusedMovementGenerator::Initialize(T &unit) +void +ConfusedMovementGenerator::Initialize(T &unit) { - i_nextMove = 1; - - GenerateMovement(unit); + const float wander_distance=11; + float x,y,z; + x = unit.GetPositionX(); + y = unit.GetPositionY(); + z = unit.GetPositionZ(); - unit.CastStop(); - unit.StopMoving(); - unit.RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); - unit.addUnitState(UNIT_STAT_CONFUSED); - unit.SetUInt64Value(UNIT_FIELD_TARGET, 0); - unit.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); + Map const* map = unit.GetMap(); -} + i_nextMove = 1; -template -void ConfusedMovementGenerator::GenerateMovement(T &unit) -{ bool is_water_ok, is_land_ok; _InitSpecific(unit, is_water_ok, is_land_ok); - for (uint8 idx = 0; idx < MAX_CONF_WAYPOINTS+1; ++idx) + for(unsigned int idx=0; idx < MAX_CONF_WAYPOINTS+1; ++idx) { - unit.GetNearPoint(&unit, i_waypoints[idx][0], i_waypoints[idx][1], i_waypoints[idx][2], unit.GetObjectSize(), WANDER_DISTANCE, frand(0, M_PI)); + const float wanderX=wander_distance*rand_norm() - wander_distance/2; + const float wanderY=wander_distance*rand_norm() - wander_distance/2; - if (!is_land_ok || !is_water_ok) - { - bool inWater = unit.GetMap()->IsInWater(i_waypoints[idx][0], i_waypoints[idx][1], i_waypoints[idx][2]); - if (!is_water_ok && inWater || !is_land_ok && !inWater) - { - i_waypoints[idx][0] = unit.GetPositionX(); - i_waypoints[idx][1] = unit.GetPositionY(); - i_waypoints[idx][2] = unit.GetPositionZ(); - continue; - } - } + i_waypoints[idx][0] = x + wanderX; + i_waypoints[idx][1] = y + wanderY; - VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unit.GetMapId(), unit.GetPositionX(), unit.GetPositionY(), unit.GetPositionZ(), i_waypoints[idx][0], i_waypoints[idx][1], i_waypoints[idx][2], i_waypoints[idx][0], i_waypoints[idx][1], i_waypoints[idx][2], 0.0f); + // prevent invalid coordinates generation + Trinity::NormalizeMapCoord(i_waypoints[idx][0]); + Trinity::NormalizeMapCoord(i_waypoints[idx][1]); - if (unit.IsWithinLOS(i_waypoints[idx][0] ,i_waypoints[idx][1], i_waypoints[idx][2] -1.5f)) - continue; - else + bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1],z); + // if generated wrong path just ignore + if ((is_water && !is_water_ok) || (!is_water && !is_land_ok)) { - i_waypoints[idx][0] = unit.GetPositionX(); - i_waypoints[idx][1] = unit.GetPositionY(); - i_waypoints[idx][2] = unit.GetPositionZ(); + i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x; + i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y; } + + unit.UpdateAllowedPositionZ(i_waypoints[idx][0],i_waypoints[idx][1],z); + i_waypoints[idx][2] = z; } + + unit.StopMoving(); + unit.addUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE); } template<> -void ConfusedMovementGenerator::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok) +void +ConfusedMovementGenerator::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok) { - is_water_ok = creature.canSwim(); - is_land_ok = creature.canWalk(); + is_water_ok = creature.CanSwim(); + is_land_ok = creature.CanWalk(); } template<> -void ConfusedMovementGenerator::_InitSpecific(Player &, bool &is_water_ok, bool &is_land_ok) +void +ConfusedMovementGenerator::_InitSpecific(Player &, bool &is_water_ok, bool &is_land_ok) { is_water_ok = true; is_land_ok = true; } +template +void ConfusedMovementGenerator::Interrupt(T &unit) +{ + // confused state still applied while movegen disabled + unit.clearUnitState(UNIT_STAT_CONFUSED_MOVE); +} + template void ConfusedMovementGenerator::Reset(T &unit) { i_nextMove = 1; - i_destinationHolder.ResetUpdate(); + i_nextMoveTime.Reset(0); unit.StopMoving(); + unit.addUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE); } template bool ConfusedMovementGenerator::Update(T &unit, const uint32 &diff) { - if (!&unit) + // ignore in case other no reaction state + if (unit.hasUnitState(UNIT_STAT_CAN_NOT_REACT & ~UNIT_STAT_CONFUSED)) return true; - if (unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED)) - return true; - - Traveller traveller(unit); + if (i_nextMoveTime.Passed()) + { + // currently moving, update location + unit.addUnitState(UNIT_STAT_CONFUSED_MOVE); - if (i_destinationHolder.UpdateTraveller(traveller, diff)) + if (unit.movespline->Finalized()) + { + i_nextMove = urand(1,MAX_CONF_WAYPOINTS); + i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher + } + } + else { - if (i_destinationHolder.HasArrived()) + // waiting for next move + i_nextMoveTime.Update(diff); + if(i_nextMoveTime.Passed() ) { - assert(i_nextMove <= MAX_CONF_WAYPOINTS); - const float x = i_waypoints[i_nextMove][0]; - const float y = i_waypoints[i_nextMove][1]; - const float z = i_waypoints[i_nextMove][2]; - i_destinationHolder.SetDestination(traveller, x, y, z); - i_nextMove = urand(1, MAX_CONF_WAYPOINTS); + // start moving + unit.addUnitState(UNIT_STAT_CONFUSED_MOVE); + + ASSERT( i_nextMove <= MAX_CONF_WAYPOINTS ); + float x = i_waypoints[i_nextMove][0]; + float y = i_waypoints[i_nextMove][1]; + float z = i_waypoints[i_nextMove][2]; + Movement::MoveSplineInit init(unit); + init.MoveTo(x, y, z); + init.SetWalk(true); + init.Launch(); } } return true; } -template -void ConfusedMovementGenerator::Finalize(T &unit) +template<> +void ConfusedMovementGenerator::Finalize(Player &unit) +{ + unit.clearUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE); +} + +template<> +void ConfusedMovementGenerator::Finalize(Creature &unit) { - unit.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); - unit.clearUnitState(UNIT_STAT_CONFUSED); - if (unit.GetTypeId() == TYPEID_UNIT && unit.getVictim()) - unit.SetUInt64Value(UNIT_FIELD_TARGET, unit.getVictimGUID()); + unit.clearUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE); } template void ConfusedMovementGenerator::Initialize(Player &player); template void ConfusedMovementGenerator::Initialize(Creature &creature); -template void ConfusedMovementGenerator::Finalize(Player &player); -template void ConfusedMovementGenerator::Finalize(Creature &creature); +template void ConfusedMovementGenerator::Interrupt(Player &player); +template void ConfusedMovementGenerator::Interrupt(Creature &creature); template void ConfusedMovementGenerator::Reset(Player &player); template void ConfusedMovementGenerator::Reset(Creature &creature); template bool ConfusedMovementGenerator::Update(Player &player, const uint32 &diff); diff --git a/src/game/ConfusedMovementGenerator.h b/src/game/ConfusedMovementGenerator.h index 1840ce105..679bbca1e 100755 --- a/src/game/ConfusedMovementGenerator.h +++ b/src/game/ConfusedMovementGenerator.h @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,53 +8,40 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITY_CONFUSEDGENERATOR_H -#define TRINITY_CONFUSEDGENERATOR_H +#ifndef MANGOS_CONFUSEDMOVEMENTGENERATOR_H +#define MANGOS_CONFUSEDMOVEMENTGENERATOR_H #include "MovementGenerator.h" -#include "DestinationHolder.h" -#include "Traveller.h" +#include "Timer.h" -#define WANDER_DISTANCE 5.0f -#define MAX_CONF_WAYPOINTS 6 +#define MAX_CONF_WAYPOINTS 24 template class TRINITY_DLL_SPEC ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMovementGenerator > { public: - explicit ConfusedMovementGenerator() {} + explicit ConfusedMovementGenerator() : i_nextMoveTime(0) {} void Initialize(T &); void Finalize(T &); + void Interrupt(T &); void Reset(T &); bool Update(T &, const uint32 &); - bool GetDestination(float &x, float &y, float &z) const - { - if (i_destinationHolder.HasArrived()) - return false; - - i_destinationHolder.GetDestination(x,y,z); - return true; - } - - void GenerateMovement(T &unit); - - MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; } + MovementGeneratorType GetMovementGeneratorType() const { return CONFUSED_MOTION_TYPE; } private: void _InitSpecific(T &, bool &, bool &); + TimeTracker i_nextMoveTime; float i_waypoints[MAX_CONF_WAYPOINTS+1][3]; - DestinationHolder< Traveller > i_destinationHolder; uint32 i_nextMove; }; #endif - diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 9f0329874..67f4abf67 100755 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -52,6 +52,8 @@ #include "Policies/SingletonImp.h" #include "Map.h" +#include "movement/MoveSplineInit.h" + std::map CreatureAIReInitialize; void TrainerSpellData::Clear() @@ -166,7 +168,7 @@ m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),m_creatureInfo(NULL), m_DBTabl m_CreatureSpellCooldowns.clear(); m_CreatureCategoryCooldowns.clear(); - m_unit_movement_flags = SPLINEFLAG_WALKMODE_MODE; + SetWalk(true); DisableReputationGain = false; } @@ -332,6 +334,8 @@ bool Creature::InitEntry(uint32 Entry, uint32 team, const CreatureData *data) SetFloatValue(OBJECT_FIELD_SCALE_X, cinfo->scale); + SetLevitate(CanFly()); + // checked at loading m_defaultMovementType = MovementGeneratorType(cinfo->MovementType); if (!m_respawnradius && m_defaultMovementType==RANDOM_MOTION_TYPE) @@ -1156,29 +1160,6 @@ void Creature::LoadGossipOptions() m_gossipOptionLoaded = true; } -void Creature::AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type) -{ - /* uint32 timeElap = WorldTimer::getMSTime(); - if ((timeElap - m_startMove) < m_moveTime) - { - oX = (dX - oX) * ((timeElap - m_startMove) / m_moveTime); - oY = (dY - oY) * ((timeElap - m_startMove) / m_moveTime); - } - else - { - oX = dX; - oY = dY; - } - - dX = x; - dY = y; - m_orientation = atan2((oY - dY), (oX - dX)); - - m_startMove = WorldTimer::getMSTime(); - m_moveTime = time;*/ - SendMonsterMove(x, y, z, time); -} - Player *Creature::GetLootRecipient() const { if (!m_lootRecipient) return NULL; @@ -1487,7 +1468,7 @@ bool Creature::LoadFromDB(uint32 guid, Map *map) if (isWorldBoss()) loot.loadLootFromDB(this); - if (canFly()) + if (CanFly()) { float tz = GetMap()->GetHeight(data->posX,data->posY,data->posZ,false); if (data->posZ - tz > 0.1) @@ -1638,7 +1619,7 @@ bool Creature::canStartAttack(Unit const* who) const { if (isCivilian() || !who->isInAccessiblePlacefor (this) - || !canFly() && GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE + || !CanFly() && GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE || !IsWithinDistInMap(who, GetAttackDistance(who))) return false; @@ -1736,7 +1717,7 @@ void Creature::setDeathState(DeathState s) Unit::setDeathState(ALIVE); CreatureInfo const *cinfo = GetCreatureInfo(); RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); - AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + SetWalk(true); SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag); clearUnitState(UNIT_STAT_ALL_STATE); i_motionMaster.Initialize(); @@ -1757,7 +1738,15 @@ bool Creature::FallGround() if (fabs(z - ground_Z) < 0.1f) return false; - GetMotionMaster()->MoveFall(ground_Z, EVENT_FALL_GROUND); + Movement::MoveSplineInit init(*this); + init.MoveTo(GetPositionX(),GetPositionY(),z); + init.SetFall(); + init.Launch(); + + // hacky solution: by some reason died creatures not updated, that's why need finalize movement state + GetMap()->CreatureRelocation(this, GetPositionX(), GetPositionY(), ground_Z, GetOrientation()); + DisableSpline(); + Unit::setDeathState(DEAD_FALLING); return true; } @@ -2177,8 +2166,8 @@ bool Creature::LoadCreaturesAddon(bool reload) if (cainfo->emote != 0) SetUInt32Value(UNIT_NPC_EMOTESTATE, cainfo->emote); - if (cainfo->move_flags != 0) - SetUnitMovementFlags(cainfo->move_flags); + if (cainfo->move_flags & SPLINEFLAG_FLYING) + SetLevitate(true); //Load Path if (cainfo->path_id != 0) @@ -2558,3 +2547,27 @@ time_t Creature::GetLinkedCreatureRespawnTime() const return 0; } + +void Creature::SetWalk(bool enable) +{ + if (enable) + m_movementInfo.AddMovementFlag(MOVEFLAG_WALK_MODE); + else + m_movementInfo.RemoveMovementFlag(MOVEFLAG_WALK_MODE); + WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_WALK_MODE : SMSG_SPLINE_MOVE_SET_RUN_MODE, 9); + data << GetPackGUID(); + SendMessageToSet(&data, true); +} + +void Creature::SetLevitate(bool enable) +{ + if (enable) + m_movementInfo.AddMovementFlag(MOVEFLAG_LEVITATING); + else + m_movementInfo.RemoveMovementFlag(MOVEFLAG_LEVITATING); + + // GUESSED ! prev opcode not present in 2.4.3 + WorldPacket data(enable ? SMSG_SPLINE_MOVE_UNSET_FLYING : SMSG_SPLINE_MOVE_SET_FLYING, 9); + data << GetPackGUID(); + SendMessageToSet(&data, true); +} diff --git a/src/game/Creature.h b/src/game/Creature.h index 63752fe26..9e5f3280b 100755 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -453,9 +453,11 @@ class TRINITY_DLL_SPEC Creature : public Unit bool isRacialLeader() const { return GetCreatureInfo()->RacialLeader; } bool isCivilian() const { return GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_CIVILIAN; } bool isTrigger() const { return GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER; } - bool canWalk() const { return GetCreatureInfo()->InhabitType & INHABIT_GROUND; } - bool canSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; } - bool canFly() const { return GetCreatureInfo()->InhabitType & INHABIT_AIR; } + + bool CanWalk() const { return GetCreatureInfo()->InhabitType & INHABIT_GROUND; } + bool CanSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; } + bool CanFly() const { return GetCreatureInfo()->InhabitType & INHABIT_AIR; } + void SetReactState(ReactStates st) { m_reactState = st; } ReactStates GetReactState() { return m_reactState; } bool HasReactState(ReactStates state) const { return (m_reactState == state); } @@ -491,9 +493,11 @@ class TRINITY_DLL_SPEC Creature : public Unit bool AIM_Initialize(CreatureAI* ai = NULL); - void AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type); CreatureAI* AI() { return (CreatureAI*)i_AI; } + void SetWalk(bool enable); + void SetLevitate(bool enable); + uint32 GetShieldBlockValue() const //dunno mob block value { return (getLevel()/2 + uint32(GetStat(STAT_STRENGTH)/20)); diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index 41ff9962b..d20c20ef4 100755 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -117,7 +117,7 @@ void CreatureAI::EnterEvadeMode() if (Unit *owner = me->GetCharmerOrOwner()) { me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, m_creature->GetFollowAngle(), MOTION_SLOT_ACTIVE); + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, m_creature->GetFollowAngle()); } else me->GetMotionMaster()->MoveTargetedHome(); diff --git a/src/game/CreatureAIImpl.h b/src/game/CreatureAIImpl.h index e08d9f925..f6af321e2 100755 --- a/src/game/CreatureAIImpl.h +++ b/src/game/CreatureAIImpl.h @@ -599,7 +599,7 @@ inline bool CreatureAI::_EnterEvadeMode() inline void UnitAI::DoCast(Unit* victim, uint32 spellId, bool triggered) { - if (!victim || me->hasUnitState(UNIT_STAT_CASTING) && !triggered) + if (!victim || me->IsNonMeleeSpellCasted(false) && !triggered) return; me->CastSpell(victim, spellId, triggered); @@ -612,7 +612,7 @@ inline void UnitAI::DoCastVictim(uint32 spellId, bool triggered) inline void UnitAI::DoCastAOE(uint32 spellId, bool triggered) { - if (!triggered && me->hasUnitState(UNIT_STAT_CASTING)) + if (!triggered && me->IsNonMeleeSpellCasted(false)) return; me->CastSpell((Unit*)NULL, spellId, triggered); @@ -639,4 +639,3 @@ inline Creature *CreatureAI::DoSummonFlyer(uint32 uiEntry, WorldObject *obj, flo } #endif - diff --git a/src/game/CreatureAIRegistry.cpp b/src/game/CreatureAIRegistry.cpp index 6bbef2ee8..58b373f01 100755 --- a/src/game/CreatureAIRegistry.cpp +++ b/src/game/CreatureAIRegistry.cpp @@ -31,7 +31,6 @@ #include "WaypointMovementGenerator.h" #include "CreatureAIFactory.h" -//#include "CreatureAIImpl.h" namespace AIRegistry { void Initialize() diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp index 583928ac8..c7fdd1b68 100755 --- a/src/game/CreatureAISelector.cpp +++ b/src/game/CreatureAISelector.cpp @@ -55,7 +55,7 @@ namespace FactorySelector ai_factory = ai_registry.GetRegistryItem("PetAI"); else if (creature->isGuard()) ai_factory = ai_registry.GetRegistryItem("GuardAI"); - else if (creature->isPet() || (creature->isCharmed() && !creature->isPossessed())) + else if (creature->isPet() || (creature->isCharmed() && !creature->HasAuraType(SPELL_AURA_MOD_POSSESS))) // MOD_POSSESS - dunno it work :p { switch (creature->GetEntry()) { diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 2a58d3713..334482db6 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -506,18 +506,23 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 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 + // Melee current victim if flag not set if (!(action.cast.castFlags & CAST_NO_MELEE_IF_OOM)) { - if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + switch(m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType()) { - AttackDistance = 0.0f; - AttackAngle = 0.0f; - - m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle); + case CHASE_MOTION_TYPE: + case FOLLOW_MOTION_TYPE: + AttackDistance = 0.0f; + AttackAngle = 0.0f; + + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle); + break; + default: + break; } } - } else { @@ -568,15 +573,21 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 if (!(action.castguid.castFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) && !CanCast(target, tSpell, (action.castguid.castFlags & CAST_TRIGGERED))) { - //Melee current victim if flag not set - if (!(action.castguid.castFlags & CAST_NO_MELEE_IF_OOM)) + // Melee current victim if flag not set + if (!(action.cast.castFlags & CAST_NO_MELEE_IF_OOM)) { - if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + switch(m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType()) { - AttackDistance = 0.0f; - AttackAngle = 0.0f; - - m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle); + case CHASE_MOTION_TYPE: + case FOLLOW_MOTION_TYPE: + AttackDistance = 0.0f; + AttackAngle = 0.0f; + + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle); + break; + default: + break; } } diff --git a/src/game/CreatureGroups.cpp b/src/game/CreatureGroups.cpp index 099eaaad1..41adf0293 100755 --- a/src/game/CreatureGroups.cpp +++ b/src/game/CreatureGroups.cpp @@ -216,7 +216,8 @@ void CreatureGroup::FormationReset(bool dismiss) if (dismiss) mem->GetMotionMaster()->Initialize(); else - mem->GetMotionMaster()->MoveIdle(MOTION_SLOT_IDLE); + mem->GetMotionMaster()->MoveIdle(); + sLog.outDebug("Set %s movement for member GUID: %u", dismiss ? "default" : "idle", mem->GetGUIDLow()); } } @@ -254,14 +255,14 @@ void CreatureGroup::LeaderMoveTo(float x, float y, float z) member->UpdateGroundPositionZ(dx, dy, dz); if (member->GetDistance(m_leader) < dist + MAX_DESYNC) - member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags()); + member->m_movementInfo.SetMovementFlags(m_leader->m_movementInfo.GetMovementFlags()); else { // jak sie za bardzo rozjada xO if (member->GetDistance(m_leader) > 40.0f) - member->Relocate(m_leader->GetPositionX(), m_leader->GetPositionY(), m_leader->GetPositionZ(), 0.0f); + member->NearTeleportTo(m_leader->GetPositionX(), m_leader->GetPositionY(), m_leader->GetPositionZ(), 0.0f); else - member->RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + member->SetWalk(false); } member->GetMotionMaster()->MovePoint(0, dx, dy, dz); diff --git a/src/game/DestinationHolder.h b/src/game/DestinationHolder.h deleted file mode 100755 index 8ea14bae2..000000000 --- a/src/game/DestinationHolder.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_DESTINATION_HOLDER_H -#define TRINITY_DESTINATION_HOLDER_H - -#include "Platform/Define.h" -#include "Timer.h" - -class WorldObject; -class Map; - -#define TRAVELLER_UPDATE_INTERVAL 300 - -template -class TRINITY_DLL_DECL DestinationHolder -{ - TimeTrackerSmall i_tracker; - uint32 i_totalTravelTime; - uint32 i_timeElapsed; - bool i_destSet; - float i_fromX, i_fromY, i_fromZ; - float i_destX, i_destY, i_destZ; - - public: - DestinationHolder() : i_tracker(TRAVELLER_UPDATE_INTERVAL), i_totalTravelTime(0), i_timeElapsed(0), - i_destSet(false), i_fromX(0), i_fromY(0), i_fromZ(0), i_destX(0), i_destY(0), i_destZ(0) {} - - uint32 SetDestination(TRAVELLER &traveller, float dest_x, float dest_y, float dest_z, bool sendMove = true); - void GetDestination(float &x, float &y, float &z) const { x = i_destX; y = i_destY; z = i_destZ; } - bool UpdateExpired(void) const { return i_tracker.Passed(); } - void ResetUpdate(uint32 t = TRAVELLER_UPDATE_INTERVAL) { i_tracker.Reset(t); } - uint32 GetTotalTravelTime(void) const { return i_totalTravelTime; } - void IncreaseTravelTime(uint32 increment) { i_totalTravelTime += increment; } - void ResetTravelTime() { i_totalTravelTime = 0; } - bool HasDestination(void) const { return i_destSet; } - float GetDestinationDiff(float x, float y, float z) const; - bool HasArrived(void) const { return (i_totalTravelTime == 0 || i_timeElapsed >= i_totalTravelTime); } - bool UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool micro_movement=false); - uint32 StartTravel(TRAVELLER &traveller, bool sendMove = true); - void GetLocationNow(const Map *map, float &x, float &y, float &z, bool is3D = false) const; - void GetLocationNowNoMicroMovement(float &x, float &y, float &z) const; // For use without micro movement - float GetDistance3dFromDestSq(const WorldObject &obj) const; - - private: - void _findOffSetPoint(float x1, float y1, float x2, float y2, float offset, float &x, float &y); - -}; -#endif - diff --git a/src/game/DestinationHolderImp.h b/src/game/DestinationHolderImp.h deleted file mode 100755 index da1397ae8..000000000 --- a/src/game/DestinationHolderImp.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_DESTINATIONHOLDERIMP_H -#define TRINITY_DESTINATIONHOLDERIMP_H - -#include "Creature.h" -#include "MapManager.h" -#include "DestinationHolder.h" - -#include - -template -void -DestinationHolder::_findOffSetPoint(float x1, float y1, float x2, float y2, float offset, float &x, float &y) -{ - /* given the point (x1, y1) and (x2, y2).. need to find the point (x,y) on the same line - * such that the distance from (x, y) to (x2, y2) is offset. - * Let the distance of p1 to p2 = d.. then the ratio of offset/d = (x2-x)/(x2-x1) - * hence x = x2 - (offset/d)*(x2-x1) - * like wise offset/d = (y2-y)/(y2-y1); - */ - if (offset == 0) - { - x = x2; - y = y2; - } - else - { - double x_diff = double(x2 - x1); - double y_diff = double(y2 - y1); - double distance_d = (double)((x_diff*x_diff) + (y_diff * y_diff)); - if (distance_d == 0) - { - x = x2; - y = y2; - } - else - { - distance_d = ::sqrt(distance_d); // starting distance - double distance_ratio = (double)(distance_d - offset)/(double)distance_d; - // line above has revised formula which is more correct, I think - x = (float)(x1 + (distance_ratio*x_diff)); - y = (float)(y1 + (distance_ratio*y_diff)); - } - } -} - -template -uint32 -DestinationHolder::SetDestination(TRAVELLER &traveller, float dest_x, float dest_y, float dest_z, bool sendMove) -{ - i_destSet = true; - i_destX = dest_x; - i_destY = dest_y; - i_destZ = dest_z; - - return StartTravel(traveller, sendMove); -} - -template -uint32 -DestinationHolder::StartTravel(TRAVELLER &traveller, bool sendMove) -{ - if (!i_destSet) return 0; - - i_fromX = traveller.GetPositionX(); - i_fromY = traveller.GetPositionY(); - i_fromZ = traveller.GetPositionZ(); - - i_totalTravelTime = traveller.GetTotalTrevelTimeTo(i_destX,i_destY,i_destZ); - - i_timeElapsed = 0; - if (sendMove) - traveller.MoveTo(i_destX, i_destY, i_destZ, i_totalTravelTime); - return i_totalTravelTime; -} - -template -bool -DestinationHolder::UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool micro_movement) -{ - i_timeElapsed += diff; - - // Update every TRAVELLER_UPDATE_INTERVAL - i_tracker.Update(diff); - if (!i_tracker.Passed()) - return false; - else - ResetUpdate(); - - if (!i_destSet) return true; - - float x, y, z; - if (!micro_movement) - GetLocationNowNoMicroMovement(x, y, z); - else - { - if (!traveller.GetTraveller().hasUnitState(UNIT_STAT_MOVING | UNIT_STAT_IN_FLIGHT)) - return true; - - if (traveller.GetTraveller().hasUnitState(UNIT_STAT_IN_FLIGHT)) - GetLocationNow(traveller.GetTraveller().GetBaseMap() ,x, y, z, true); // Should repositione Object with right Coord, so I can bypass some Grid Relocation - else - GetLocationNow(traveller.GetTraveller().GetBaseMap(), x, y, z, false); - - // Change movement computation to micro movement based on last tick coords, this makes system work - // even on multiple floors zones without hugh vmaps usage ;) - - // Take care of underrun of uint32 - if (i_totalTravelTime >= i_timeElapsed) - i_totalTravelTime -= i_timeElapsed; // Consider only the remaining part - else - i_totalTravelTime = 0; - - i_timeElapsed = 0; - i_fromX = x; // and change origine - i_fromY = y; // then I take into account only micro movement - i_fromZ = z; - } - - if (traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y) - { - float ori = traveller.GetTraveller().GetAngle(x, y); - traveller.Relocation(x, y, z, ori); - } - - return true; -} - -template -void -DestinationHolder::GetLocationNow(const Map *map, float &x, float &y, float &z, bool is3D) const -{ - if (HasArrived()) - { - x = i_destX; - y = i_destY; - z = i_destZ; - } - else if (HasDestination()) - { - double percent_passed = (double)i_timeElapsed / (double)i_totalTravelTime; - const float distanceX = ((i_destX - i_fromX) * percent_passed); - const float distanceY = ((i_destY - i_fromY) * percent_passed); - const float distanceZ = ((i_destZ - i_fromZ) * percent_passed); - x = i_fromX + distanceX; - y = i_fromY + distanceY; - float z2 = i_fromZ + distanceZ; - // All that is not finished but previous code neither... Traveller need be able to swim. - if (is3D) - z = z2; - else - { - //That part is good for mob Walking on the floor. But the floor is not allways what we thought. - z = map->GetHeight(x,y,i_fromZ,false); // Disable cave check - const float groundDist = sqrt(distanceX*distanceX + distanceY*distanceY); - const float zDist = fabs(i_fromZ - z) + 0.000001f; - const float slope = groundDist / zDist; - if (slope < 1.0f) // This prevents the ground returned by GetHeight to be used when in cave - z = z2; // a climb or jump of more than 45 is denied - } - } -} - -template -float -DestinationHolder::GetDistance3dFromDestSq(const WorldObject &obj) const -{ - float x,y,z; - obj.GetPosition(x,y,z); - return (i_destX-x)*(i_destX-x)+(i_destY-y)*(i_destY-y)+(i_destZ-z)*(i_destZ-z); -} - -template -float -DestinationHolder::GetDestinationDiff(float x, float y, float z) const -{ - return sqrt(((x-i_destX)*(x-i_destX)) + ((y-i_destY)*(y-i_destY)) + ((z-i_destZ)*(z-i_destZ))); -} - -template -void -DestinationHolder::GetLocationNowNoMicroMovement(float &x, float &y, float &z) const -{ - if (HasArrived()) - { - x = i_destX; - y = i_destY; - z = i_destZ; - } - else - { - double percent_passed = (double)i_timeElapsed / (double)i_totalTravelTime; - x = i_fromX + ((i_destX - i_fromX) * percent_passed); - y = i_fromY + ((i_destY - i_fromY) * percent_passed); - z = i_fromZ + ((i_destZ - i_fromZ) * percent_passed); - } -} - -#endif - diff --git a/src/game/FleeingMovementGenerator.cpp b/src/game/FleeingMovementGenerator.cpp index d25ce295d..e2a2b1285 100755 --- a/src/game/FleeingMovementGenerator.cpp +++ b/src/game/FleeingMovementGenerator.cpp @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,219 +8,340 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Creature.h" +#include "CreatureAI.h" #include "MapManager.h" #include "FleeingMovementGenerator.h" -#include "DestinationHolderImp.h" #include "ObjectAccessor.h" -#include "VMapFactory.h" -#include "CreatureAI.h" +#include "movement/MoveSplineInit.h" +#include "movement/MoveSpline.h" #define MIN_QUIET_DISTANCE 28.0f #define MAX_QUIET_DISTANCE 43.0f template -void FleeingMovementGenerator::_setTargetLocation(T &owner) +void +FleeingMovementGenerator::_setTargetLocation(T &owner) { - if (!&owner) + if( !&owner ) + return; + + // ignore in case other no reaction state + if (owner.hasUnitState(UNIT_STAT_CAN_NOT_REACT & ~UNIT_STAT_FLEEING)) return; - if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED)) + if(!_setMoveData(owner)) return; float x, y, z; - if (!_getPoint(owner, x, y, z)) + if(!_getPoint(owner, x, y, z)) return; - owner.addUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING); + owner.addUnitState(UNIT_STAT_FLEEING_MOVE); - Traveller traveller(owner); - i_destinationHolder.SetDestination(traveller, i_dest_x, i_dest_y, i_dest_z); -} - -template<> -bool FleeingMovementGenerator::GetDestination(float &x, float &y, float &z) const -{ - if (i_destinationHolder.HasArrived()) - return false; - - i_destinationHolder.GetDestination(x, y, z); - return true; -} - -template<> -bool FleeingMovementGenerator::GetDestination(float &x, float &y, float &z) const -{ - return false; + Movement::MoveSplineInit init(owner); + init.MoveTo(x,y,z); + init.SetWalk(false); + init.Launch(); } template -bool FleeingMovementGenerator::_getPoint(T &owner, float &x, float &y, float &z) +bool +FleeingMovementGenerator::_getPoint(T &owner, float &x, float &y, float &z) { - if (!&owner) + if(!&owner) return false; x = owner.GetPositionX(); y = owner.GetPositionY(); z = owner.GetPositionZ(); - float temp_x, temp_y, temp_z, angle; - const Map *_map = owner.GetBaseMap(); + float temp_x, temp_y, angle; + const Map * _map = owner.GetMap(); //primitive path-finding - for (uint8 i = 0; i < 8; ++i) + for(uint8 i = 0; i < 18; ++i) { - float distance = 14.0f; + if(i_only_forward && i > 2) + break; - switch (i) + float distance = 5.0f; + + switch(i) { case 0: angle = i_cur_angle; break; case 1: - angle = i_cur_angle + M_PI/4.0f; + angle = i_cur_angle; + distance /= 2; break; case 2: - angle = i_cur_angle + M_PI/2.0f; + angle = i_cur_angle; + distance /= 4; break; case 3: - angle = i_cur_angle - M_PI/4.0f; + angle = i_cur_angle + M_PI/4.0f; break; case 4: - angle = i_cur_angle - M_PI/2.0f; + angle = i_cur_angle - M_PI/4.0f; break; case 5: - angle = i_cur_angle + M_PI*3/4.0f; + angle = i_cur_angle + M_PI/4.0f; + distance /= 2; break; case 6: - angle = i_cur_angle - M_PI*3/4.0f; + angle = i_cur_angle - M_PI/4.0f; + distance /= 2; break; case 7: + angle = i_cur_angle + M_PI/2.0f; + break; + case 8: + angle = i_cur_angle - M_PI/2.0f; + break; + case 9: + angle = i_cur_angle + M_PI/2.0f; + distance /= 2; + break; + case 10: + angle = i_cur_angle - M_PI/2.0f; + distance /= 2; + break; + case 11: + angle = i_cur_angle + M_PI/4.0f; + distance /= 4; + break; + case 12: + angle = i_cur_angle - M_PI/4.0f; + distance /= 4; + break; + case 13: + angle = i_cur_angle + M_PI/2.0f; + distance /= 4; + break; + case 14: + angle = i_cur_angle - M_PI/2.0f; + distance /= 4; + break; + case 15: + angle = i_cur_angle + M_PI*3/4.0f; + distance /= 2; + break; + case 16: + angle = i_cur_angle - M_PI*3/4.0f; + distance /= 2; + break; + case 17: angle = i_cur_angle + M_PI; + distance /= 2; break; } - - // destination point temp_x = x + distance * cos(angle); temp_y = y + distance * sin(angle); Trinity::NormalizeMapCoord(temp_x); Trinity::NormalizeMapCoord(temp_y); + if( owner.IsWithinLOS(temp_x,temp_y,z)) + { + bool is_water_now = _map->IsInWater(x,y,z); - float ground, floor; - ground = _map->GetHeight(temp_x, temp_y, MAX_HEIGHT, true); - floor = _map->GetHeight(temp_x, temp_y, z, true); - - temp_z = (fabs(ground - z) >= fabs(floor - z)) ? floor : ground; + if(is_water_now && _map->IsInWater(temp_x,temp_y,z)) + { + x = temp_x; + y = temp_y; + return true; + } + float new_z = _map->GetHeight(temp_x,temp_y,z,true); - if (temp_z <= INVALID_HEIGHT) - continue; + if(new_z <= INVALID_HEIGHT) + continue; - // if something on way get Hit Position and update distance - if (VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(owner.GetMapId(), x, y, z+0.5f, temp_x, temp_y, temp_z+0.5f, temp_x, temp_y, temp_z, -1.0f)) - distance = owner.GetDistance2d(temp_x, temp_y); + bool is_water_next = _map->IsInWater(temp_x,temp_y,new_z); - float dest_floor, dest_ground; - float dest_x = x; - float dest_y = y; - float dest_z = z; + if((is_water_now && !is_water_next && !is_land_ok) || (!is_water_now && is_water_next && !is_water_ok)) + continue; - for (int j = 1; j <= 7; ++j) - { - float dist = j*2.0f; - if (dist > distance) + if( !(new_z - z) || distance / fabs(new_z - z) > 1.0f) { - dist = distance; - j = 8; // end loop after executing code below + float new_z_left = _map->GetHeight(temp_x + 1.0f*cos(angle+M_PI/2),temp_y + 1.0f*sin(angle+M_PI/2),z,true); + float new_z_right = _map->GetHeight(temp_x + 1.0f*cos(angle-M_PI/2),temp_y + 1.0f*sin(angle-M_PI/2),z,true); + if(fabs(new_z_left - new_z) < 1.2f && fabs(new_z_right - new_z) < 1.2f) + { + x = temp_x; + y = temp_y; + z = new_z; + return true; + } } + } + } + i_to_distance_from_caster = 0.0f; + i_nextCheckTime.Reset( urand(500,1000) ); + return false; +} - temp_x = x + dist*cos(angle); - temp_y = y + dist*sin(angle); - dest_ground = _map->GetHeight(temp_x, temp_y, MAX_HEIGHT, true); - dest_floor = _map->GetHeight(temp_x, temp_y, dest_z, true); - temp_z = (fabs(dest_ground - dest_z) >= fabs(dest_floor - dest_z)) ? dest_floor : dest_ground; - - if (temp_z < INVALID_HEIGHT || fabs(temp_z - dest_z) > 1.6f) - break; +template +bool +FleeingMovementGenerator::_setMoveData(T &owner) +{ + float cur_dist_xyz = owner.GetDistance(i_caster_x, i_caster_y, i_caster_z); - dest_x = temp_x; - dest_y = temp_y; - dest_z = temp_z; + if (i_to_distance_from_caster > 0.0f) + { + if ((i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz < i_to_distance_from_caster) || + // if we reach lower distance + (i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz > i_last_distance_from_caster) || + // if we can't be close + (i_last_distance_from_caster < i_to_distance_from_caster && cur_dist_xyz > i_to_distance_from_caster) || + // if we reach bigger distance + (cur_dist_xyz > MAX_QUIET_DISTANCE) || // if we are too far + (i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE) ) + // if we leave 'quiet zone' + { + // we are very far or too close, stopping + i_to_distance_from_caster = 0.0f; + i_nextCheckTime.Reset( urand(500,1000) ); + return false; } - - if (i_dest_x != dest_x || i_dest_y != dest_y) + else { - i_dest_x = dest_x; - i_dest_y = dest_y; - i_dest_z = dest_z; + // now we are running, continue + i_last_distance_from_caster = cur_dist_xyz; return true; } } - return false; -} -template -bool FleeingMovementGenerator::_setMoveData(T &owner) -{ + float cur_dist; + float angle_to_caster; + + if (Unit* fright = owner.GetMap()->GetUnit(i_frightGuid)) + { + cur_dist = fright->GetDistance(&owner); + if (cur_dist < cur_dist_xyz) + { + i_caster_x = fright->GetPositionX(); + i_caster_y = fright->GetPositionY(); + i_caster_z = fright->GetPositionZ(); + angle_to_caster = fright->GetAngle(&owner); + } + else + { + cur_dist = cur_dist_xyz; + angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI; + } + } + else + { + cur_dist = cur_dist_xyz; + angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + M_PI; + } + + // if we too close may use 'path-finding' else just stop + i_only_forward = cur_dist >= MIN_QUIET_DISTANCE/3; + + //get angle and 'distance from caster' to run + float angle; + + if(i_cur_angle == 0.0f && i_last_distance_from_caster == 0.0f) //just started, first time + { + angle = rand_norm()*(1.0f - cur_dist/MIN_QUIET_DISTANCE) * M_PI/3 + rand_norm()*M_PI*2/3; + i_to_distance_from_caster = MIN_QUIET_DISTANCE; + i_only_forward = true; + } + else if(cur_dist < MIN_QUIET_DISTANCE) + { + angle = M_PI/6 + rand_norm()*M_PI*2/3; + i_to_distance_from_caster = cur_dist*2/3 + rand_norm()*(MIN_QUIET_DISTANCE - cur_dist*2/3); + } + else if(cur_dist > MAX_QUIET_DISTANCE) + { + angle = rand_norm()*M_PI/3 + M_PI*2/3; + i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f); + } + else + { + angle = rand_norm()*M_PI; + i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f); + } + + int8 sign = rand_norm() > 0.5f ? 1 : -1; + i_cur_angle = sign*angle + angle_to_caster; + + // current distance + i_last_distance_from_caster = cur_dist; + return true; } template -void FleeingMovementGenerator::Initialize(T &owner) +void +FleeingMovementGenerator::Initialize(T &owner) { - if (!&owner) - return; - - Unit * fright = owner.GetMap()->GetUnit(i_frightGUID); - if (!fright) - return; + owner.addUnitState(UNIT_STAT_FLEEING|UNIT_STAT_FLEEING_MOVE); _Init(owner); - owner.CastStop(); - owner.addUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING); - owner.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner.SetUInt64Value(UNIT_FIELD_TARGET, 0); - owner.RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); - i_dest_x = i_caster_x = fright->GetPositionX(); - i_dest_y = i_caster_y = fright->GetPositionY(); - i_dest_z = i_caster_z = fright->GetPositionZ(); - - i_cur_angle = fright->GetAngle(&owner); + if (Unit * fright = owner.GetMap()->GetUnit(i_frightGuid)) + { + i_caster_x = fright->GetPositionX(); + i_caster_y = fright->GetPositionY(); + i_caster_z = fright->GetPositionZ(); + } + else + { + i_caster_x = owner.GetPositionX(); + i_caster_y = owner.GetPositionY(); + i_caster_z = owner.GetPositionZ(); + } + i_only_forward = true; + i_cur_angle = 0.0f; + i_last_distance_from_caster = 0.0f; + i_to_distance_from_caster = 0.0f; _setTargetLocation(owner); } template<> -void FleeingMovementGenerator::_Init(Creature &owner) +void +FleeingMovementGenerator::_Init(Creature &owner) { - if (!&owner) - return; - - is_water_ok = owner.canSwim(); - is_land_ok = owner.canWalk(); + owner.SetSelection(0); + is_water_ok = owner.CanSwim(); + is_land_ok = owner.CanWalk(); } template<> -void FleeingMovementGenerator::_Init(Player &) +void +FleeingMovementGenerator::_Init(Player &) { is_water_ok = true; is_land_ok = true; } +template<> +void FleeingMovementGenerator::Finalize(Player &owner) +{ + owner.clearUnitState(UNIT_STAT_FLEEING|UNIT_STAT_FLEEING_MOVE); +} + +template<> +void FleeingMovementGenerator::Finalize(Creature &owner) +{ + owner.clearUnitState(UNIT_STAT_FLEEING|UNIT_STAT_FLEEING_MOVE); +} + template -void FleeingMovementGenerator::Finalize(T &owner) +void FleeingMovementGenerator::Interrupt(T &owner) { - owner.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner.clearUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING); - if (owner.GetTypeId() == TYPEID_UNIT && owner.getVictim()) - owner.SetUInt64Value(UNIT_FIELD_TARGET, owner.getVictimGUID()); + // flee state still applied while movegen disabled + owner.clearUnitState(UNIT_STAT_FLEEING_MOVE); } template @@ -234,16 +353,19 @@ void FleeingMovementGenerator::Reset(T &owner) template bool FleeingMovementGenerator::Update(T &owner, const uint32 & time_diff) { - if (!&owner || !owner.isAlive()) + if( !&owner || !owner.isAlive() ) return false; - if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED)) + // ignore in case other no reaction state + if (owner.hasUnitState(UNIT_STAT_CAN_NOT_REACT & ~UNIT_STAT_FLEEING)) + { + owner.clearUnitState(UNIT_STAT_FLEEING_MOVE); return true; + } - Traveller traveller(owner); - if (i_destinationHolder.UpdateTraveller(traveller, time_diff)) - if (i_destinationHolder.HasArrived()) - _setTargetLocation(owner); + i_nextCheckTime.Update(time_diff); + if (i_nextCheckTime.Passed() && owner.movespline->Finalized()) + _setTargetLocation(owner); return true; } @@ -256,8 +378,8 @@ template bool FleeingMovementGenerator::_getPoint(Player &, float &, flo template bool FleeingMovementGenerator::_getPoint(Creature &, float &, float &, float &); template void FleeingMovementGenerator::_setTargetLocation(Player &); template void FleeingMovementGenerator::_setTargetLocation(Creature &); -template void FleeingMovementGenerator::Finalize(Player &); -template void FleeingMovementGenerator::Finalize(Creature &); +template void FleeingMovementGenerator::Interrupt(Player &); +template void FleeingMovementGenerator::Interrupt(Creature &); template void FleeingMovementGenerator::Reset(Player &); template void FleeingMovementGenerator::Reset(Creature &); template bool FleeingMovementGenerator::Update(Player &, const uint32 &); @@ -265,8 +387,7 @@ template bool FleeingMovementGenerator::Update(Creature &, const uint3 void TimedFleeingMovementGenerator::Finalize(Unit &owner) { - owner.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner.clearUnitState(UNIT_STAT_FLEEING | UNIT_STAT_ROAMING); + owner.clearUnitState(UNIT_STAT_FLEEING|UNIT_STAT_FLEEING_MOVE); if (Unit* victim = owner.getVictim()) { if (owner.isAlive()) @@ -279,11 +400,15 @@ void TimedFleeingMovementGenerator::Finalize(Unit &owner) bool TimedFleeingMovementGenerator::Update(Unit & owner, const uint32 & time_diff) { - if (!owner.isAlive()) + if( !owner.isAlive() ) return false; - if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED)) + // ignore in case other no reaction state + if (owner.hasUnitState(UNIT_STAT_CAN_NOT_REACT & ~UNIT_STAT_FLEEING)) + { + owner.clearUnitState(UNIT_STAT_FLEEING_MOVE); return true; + } i_totalFleeTime.Update(time_diff); if (i_totalFleeTime.Passed()) diff --git a/src/game/FleeingMovementGenerator.h b/src/game/FleeingMovementGenerator.h index 748bce57b..63964cf02 100755 --- a/src/game/FleeingMovementGenerator.h +++ b/src/game/FleeingMovementGenerator.h @@ -1,7 +1,5 @@ /* -* Copyright (C) 2005-2008 MaNGOS -* -* Copyright (C) 2008 Trinity +* Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,36 +8,34 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITY_FLEEINGMOVEMENTGENERATOR_H -#define TRINITY_FLEEINGMOVEMENTGENERATOR_H +#ifndef MANGOS_FLEEINGMOVEMENTGENERATOR_H +#define MANGOS_FLEEINGMOVEMENTGENERATOR_H #include "MovementGenerator.h" -#include "DestinationHolder.h" -#include "Traveller.h" -#include "MapManager.h" +#include "ObjectGuid.h" template class TRINITY_DLL_SPEC FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovementGenerator > { public: - FleeingMovementGenerator(uint64 fright) : i_frightGUID(fright) {} + FleeingMovementGenerator(uint64 fright) : i_frightGuid(fright), i_nextCheckTime(0) {} void Initialize(T &); void Finalize(T &); + void Interrupt(T &); void Reset(T &); bool Update(T &, const uint32 &); - bool GetDestination(float &x, float &y, float &z) const; - MovementGeneratorType GetMovementGeneratorType() { return FLEEING_MOTION_TYPE; } + MovementGeneratorType GetMovementGeneratorType() const { return FLEEING_MOTION_TYPE; } private: void _setTargetLocation(T &owner); @@ -49,18 +45,16 @@ class TRINITY_DLL_SPEC FleeingMovementGenerator bool is_water_ok :1; bool is_land_ok :1; + bool i_only_forward:1; float i_caster_x; float i_caster_y; float i_caster_z; - + float i_last_distance_from_caster; + float i_to_distance_from_caster; float i_cur_angle; - float i_dest_x; - float i_dest_y; - float i_dest_z; - uint64 i_frightGUID; - - DestinationHolder< Traveller > i_destinationHolder; + uint64 i_frightGuid; + TimeTracker i_nextCheckTime; }; class TRINITY_DLL_SPEC TimedFleeingMovementGenerator @@ -71,7 +65,7 @@ class TRINITY_DLL_SPEC TimedFleeingMovementGenerator FleeingMovementGenerator(fright), i_totalFleeTime(time) {} - MovementGeneratorType GetMovementGeneratorType() { return TIMED_FLEEING_MOTION_TYPE; } + MovementGeneratorType GetMovementGeneratorType() const { return TIMED_FLEEING_MOTION_TYPE; } bool Update(Unit &, const uint32 &); void Finalize(Unit &); @@ -80,4 +74,3 @@ class TRINITY_DLL_SPEC TimedFleeingMovementGenerator }; #endif - diff --git a/src/game/GameObject.h b/src/game/GameObject.h index 15da2b453..a2aca0475 100755 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -357,6 +357,18 @@ struct GameObjectInfo uint32 data[24]; } raw; }; + + uint32 GetEventScriptId() const + { + switch(type) + { + case GAMEOBJECT_TYPE_GOOBER: return goober.eventId; + case GAMEOBJECT_TYPE_CHEST: return chest.eventId; + case GAMEOBJECT_TYPE_CAMERA: return camera.eventID; + default: return 0; + } + } + uint32 ScriptId; }; diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp index 71f973e41..0a0d3973b 100755 --- a/src/game/GridNotifiers.cpp +++ b/src/game/GridNotifiers.cpp @@ -113,10 +113,10 @@ inline void CreatureUnitRelocationWorker(Creature* c, Unit* u) return; // hacky exception for Sunblade Lookout, Shattered Sun Bombardier and Brutallus - if (u->isInFlight() && c->GetEntry() != 25132 && c->GetEntry() != 25144 && c->GetEntry() != 25158) + if (u->IsTaxiFlying() && c->GetEntry() != 25132 && c->GetEntry() != 25144 && c->GetEntry() != 25158) return; - if (c->HasReactState(REACT_AGGRESSIVE) && !c->hasUnitState(UNIT_STAT_SIGHTLESS)) + if (c->HasReactState(REACT_AGGRESSIVE)) if (c->_IsWithinDist(u, DEFAULT_VISIBILITY_DISTANCE, true) && c->IsAIEnabled) c->AI()->MoveInLineOfSight_Safe(u); } @@ -248,7 +248,7 @@ void AIRelocationNotifier::Visit(CreatureMapType &m) void DynamicObjectUpdater::VisitHelper(Unit* target) { - if (!target->isAlive() || target->isInFlight()) + if (!target->isAlive() || target->IsTaxiFlying()) return; if (target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) @@ -385,7 +385,7 @@ void Deliverer::SendPacket(Player* plr) return; // Don't send the packet to possesor if not supposed to - if (!i_toPossessor && plr->isPossessing() && plr->GetCharmGUID() == i_source.GetGUID()) + if (!i_toPossessor && plr->GetCharmGUID() == i_source.GetGUID()) return; if (plr_list.find(plr->GetGUID()) == plr_list.end()) diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h index 16cf9a17e..48b75dd10 100755 --- a/src/game/GridNotifiers.h +++ b/src/game/GridNotifiers.h @@ -489,7 +489,7 @@ namespace Trinity CannibalizeObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} bool operator()(Player* u) { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight()) + if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->IsTaxiFlying()) return false; if (i_funit->IsWithinDistInMap(u, i_range)) @@ -500,7 +500,7 @@ namespace Trinity bool operator()(Corpse* u); bool operator()(Creature* u) { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || + if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->IsTaxiFlying() || (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD)==0) return false; diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp index a4099d4e8..ec9579e00 100755 --- a/src/game/GuardAI.cpp +++ b/src/game/GuardAI.cpp @@ -40,7 +40,7 @@ GuardAI::GuardAI(Creature *c) : CreatureAI(c), i_victimGuid(0), i_state(STATE_NO void GuardAI::MoveInLineOfSight(Unit *u) { // Ignore Z for flying creatures - if (!m_creature->canFly() && m_creature->GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE) + if (!m_creature->CanFly() && m_creature->GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE) return; if (!m_creature->getVictim() && m_creature->canAttack(u) && @@ -86,7 +86,7 @@ void GuardAI::EnterEvadeMode() { DEBUG_LOG("Creature stopped attacking because victim is using stealth [guid=%u]", m_creature->GetGUIDLow()); } - else if (pVictim->isInFlight()) + else if (pVictim->IsTaxiFlying()) { DEBUG_LOG("Creature stopped attacking because victim is flying away [guid=%u]", m_creature->GetGUIDLow()); } @@ -101,8 +101,8 @@ void GuardAI::EnterEvadeMode() m_creature->CombatStop(true); i_state = STATE_NORMAL; - // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead - if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + // Remove ChaseMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead + if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) m_creature->GetMotionMaster()->MoveTargetedHome(); } diff --git a/src/game/HomeMovementGenerator.cpp b/src/game/HomeMovementGenerator.cpp index 07c936065..585487057 100755 --- a/src/game/HomeMovementGenerator.cpp +++ b/src/game/HomeMovementGenerator.cpp @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,26 +8,24 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "HomeMovementGenerator.h" #include "Creature.h" #include "CreatureAI.h" -#include "Traveller.h" -#include "MapManager.h" -#include "ObjectAccessor.h" -#include "DestinationHolderImp.h" +#include "ObjectMgr.h" #include "WorldPacket.h" +#include "movement/MoveSplineInit.h" +#include "movement/MoveSpline.h" void HomeMovementGenerator::Initialize(Creature & owner) { - owner.RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); _setTargetLocation(owner); } @@ -39,57 +35,37 @@ void HomeMovementGenerator::Reset(Creature &) void HomeMovementGenerator::_setTargetLocation(Creature & owner) { - if (!&owner) - return; - - if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED)) + if (owner.hasUnitState(UNIT_STAT_NOT_MOVE)) return; - float x, y, z; - owner.GetHomePosition(x, y, z, ori); - - CreatureTraveller traveller(owner); + Movement::MoveSplineInit init(owner); + float x, y, z, o; + // at apply we can select more nice return points base at current movegen + if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner,x,y,z)) + { + owner.GetRespawnCoord(x, y, z, &o); + init.SetFacing(o); + } + init.MoveTo(x,y,z); + init.SetWalk(false); + init.Launch(); - uint32 travel_time = i_destinationHolder.SetDestination(traveller, x, y, z); - modifyTravelTime(travel_time); + arrived = false; owner.clearUnitState(UNIT_STAT_ALL_STATE); } bool HomeMovementGenerator::Update(Creature &owner, const uint32& time_diff) { - CreatureTraveller traveller(owner); - i_destinationHolder.UpdateTraveller(traveller, time_diff); - - if (time_diff >= i_travel_timer) - { - i_travel_timer = 0; // Used as check in Finalize - return false; - } - - i_travel_timer -= time_diff; - return true; + arrived = owner.movespline->Finalized(); + return !arrived; } + void HomeMovementGenerator::Finalize(Creature& owner) { - if (i_travel_timer == 0) + if (arrived) { - owner.AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); - - // restore orientation of not moving creature at returning to home - if (owner.GetDefaultMovementType()==IDLE_MOTION_TYPE) - { - owner.SetOrientation(ori); - WorldPacket packet; - owner.BuildHeartBeatMsg(&packet); - owner.SendMessageToSet(&packet, false); - } - - if (owner.IsAIEnabled) - { - owner.AI()->MovementInform(HOME_MOTION_TYPE, RAND_MAX); - owner.AI()->JustReachedHome(); - } + owner.SetWalk(true); + owner.LoadCreaturesAddon(true); + owner.AI()->JustReachedHome(); } - } - diff --git a/src/game/HomeMovementGenerator.h b/src/game/HomeMovementGenerator.h index c6230cf0f..32616b743 100755 --- a/src/game/HomeMovementGenerator.h +++ b/src/game/HomeMovementGenerator.h @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,20 +8,18 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITY_HOMEMOVEMENTGENERATOR_H -#define TRINITY_HOMEMOVEMENTGENERATOR_H +#ifndef MANGOS_HOMEMOVEMENTGENERATOR_H +#define MANGOS_HOMEMOVEMENTGENERATOR_H #include "MovementGenerator.h" -#include "DestinationHolder.h" -#include "Traveller.h" class Creature; @@ -36,23 +32,18 @@ class TRINITY_DLL_SPEC HomeMovementGenerator { public: - HomeMovementGenerator() {} + HomeMovementGenerator() : arrived(false) {} ~HomeMovementGenerator() {} void Initialize(Creature &); void Finalize(Creature &); + void Interrupt(Creature &) {} void Reset(Creature &); bool Update(Creature &, const uint32 &); - void modifyTravelTime(uint32 travel_time) { i_travel_timer = travel_time; } - MovementGeneratorType GetMovementGeneratorType() { return HOME_MOTION_TYPE; } + MovementGeneratorType GetMovementGeneratorType() const { return HOME_MOTION_TYPE; } - bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; } private: void _setTargetLocation(Creature &); - DestinationHolder< Traveller > i_destinationHolder; - - float ori; - uint32 i_travel_timer; + bool arrived; }; #endif - diff --git a/src/game/IdleMovementGenerator.cpp b/src/game/IdleMovementGenerator.cpp index 305b7155c..07511692c 100755 --- a/src/game/IdleMovementGenerator.cpp +++ b/src/game/IdleMovementGenerator.cpp @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,106 +8,68 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "IdleMovementGenerator.h" -#include "Creature.h" #include "CreatureAI.h" +#include "Creature.h" IdleMovementGenerator si_idleMovement; -// StopMoving is needed to make unit stop if its last movement generator expires -// But it should not be sent otherwise there are many redundent packets -void IdleMovementGenerator::Initialize(Unit &owner) -{ - if (owner.hasUnitState(UNIT_STAT_MOVE)) - owner.StopMoving(); -} - -void IdleMovementGenerator::Reset(Unit& owner) +void +IdleMovementGenerator::Reset(Unit& /*owner*/) { - if (owner.hasUnitState(UNIT_STAT_MOVE)) - owner.StopMoving(); } -void RotateMovementGenerator::Initialize(Unit& owner) +void +DistractMovementGenerator::Initialize(Unit& owner) { - if (owner.hasUnitState(UNIT_STAT_MOVE)) - owner.StopMoving(); - - if (owner.getVictim()) - owner.SetInFront(owner.getVictim()); - - owner.addUnitState(UNIT_STAT_ROTATING); - - owner.AttackStop(); -} - -bool RotateMovementGenerator::Update(Unit& owner, const uint32& diff) -{ - float angle = owner.GetOrientation(); - if (m_direction == ROTATE_DIRECTION_LEFT) - { - angle += (float)diff * M_PI * 2 / m_maxDuration; - while (angle >= M_PI * 2) angle -= M_PI * 2; - } - else - { - angle -= (float)diff * M_PI * 2 / m_maxDuration; - while (angle < 0) angle += M_PI * 2; - } - - owner.SetOrientation(angle); - owner.SendMovementFlagUpdate(); // this is a hack. we do not have anything correct to send in the beginning - - if (owner.GetTypeId() == TYPEID_UNIT) - { - if (owner.IsAIEnabled) - ((Creature *)&owner)->AI()->MovementInform(ROTATE_MOTION_TYPE, 1); - } - - if (m_duration > diff) - m_duration -= diff; - else - return false; - - return true; + owner.addUnitState(UNIT_STAT_DISTRACTED); } -void RotateMovementGenerator::Finalize(Unit &unit) +void +DistractMovementGenerator::Finalize(Unit& owner) { - unit.clearUnitState(UNIT_STAT_ROTATING); - if (unit.GetTypeId() == TYPEID_UNIT) - ((Creature*)&unit)->AI()->MovementInform(ROTATE_MOTION_TYPE, 0); + owner.clearUnitState(UNIT_STAT_DISTRACTED); } -void DistractMovementGenerator::Initialize(Unit& owner) +void +DistractMovementGenerator::Reset(Unit& owner) { - owner.addUnitState(UNIT_STAT_DISTRACTED); + Initialize(owner); } -void DistractMovementGenerator::Finalize(Unit& owner) +void +DistractMovementGenerator::Interrupt(Unit& /*owner*/) { - owner.clearUnitState(UNIT_STAT_DISTRACTED); } -bool DistractMovementGenerator::Update(Unit& owner, const uint32& time_diff) +bool +DistractMovementGenerator::Update(Unit& /*owner*/, const uint32& time_diff) { - if (time_diff > m_timer) + if(time_diff > m_timer) return false; m_timer -= time_diff; return true; } -void AssistanceDistractMovementGenerator::Finalize(Unit &unit) +void +AssistanceDistractMovementGenerator::Finalize(Unit &unit) { unit.clearUnitState(UNIT_STAT_DISTRACTED); - ((Creature*)&unit)->SetReactState(REACT_AGGRESSIVE); + if (Unit* victim = unit.getVictim()) + { + if (unit.isAlive()) + { + unit.AttackStop(); + ((Creature*)&unit)->AI()->AttackStart(victim); + } + } } diff --git a/src/game/IdleMovementGenerator.h b/src/game/IdleMovementGenerator.h index 134d905ec..2ca0be0fd 100755 --- a/src/game/IdleMovementGenerator.h +++ b/src/game/IdleMovementGenerator.h @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,16 +8,16 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITY_IDLEMOVEMENTGENERATOR_H -#define TRINITY_IDLEMOVEMENTGENERATOR_H +#ifndef MANGOS_IDLEMOVEMENTGENERATOR_H +#define MANGOS_IDLEMOVEMENTGENERATOR_H #include "MovementGenerator.h" @@ -27,31 +25,16 @@ class TRINITY_DLL_SPEC IdleMovementGenerator : public MovementGenerator { public: - void Initialize(Unit &); - void Finalize(Unit &) { } + void Initialize(Unit &) {} + void Finalize(Unit &) {} + void Interrupt(Unit &) {} void Reset(Unit &); bool Update(Unit &, const uint32 &) { return true; } - MovementGeneratorType GetMovementGeneratorType() { return IDLE_MOTION_TYPE; } + MovementGeneratorType GetMovementGeneratorType() const { return IDLE_MOTION_TYPE; } }; extern IdleMovementGenerator si_idleMovement; -class TRINITY_DLL_SPEC RotateMovementGenerator : public MovementGenerator -{ - public: - explicit RotateMovementGenerator(uint32 time, RotateDirection direction) : m_duration(time), m_maxDuration(time), m_direction(direction) {} - - void Initialize(Unit& owner); - void Finalize(Unit& owner); - void Reset(Unit& owner) { Initialize(owner); } - bool Update(Unit& owner, const uint32& time_diff); - MovementGeneratorType GetMovementGeneratorType() { return ROTATE_MOTION_TYPE; } - - private: - uint32 m_duration, m_maxDuration; - RotateDirection m_direction; -}; - class TRINITY_DLL_SPEC DistractMovementGenerator : public MovementGenerator { public: @@ -59,9 +42,10 @@ class TRINITY_DLL_SPEC DistractMovementGenerator : public MovementGenerator void Initialize(Unit& owner); void Finalize(Unit& owner); - void Reset(Unit& owner) { Initialize(owner); } + void Interrupt(Unit& ); + void Reset(Unit& ); bool Update(Unit& owner, const uint32& time_diff); - MovementGeneratorType GetMovementGeneratorType() { return DISTRACT_MOTION_TYPE; } + MovementGeneratorType GetMovementGeneratorType() const { return DISTRACT_MOTION_TYPE; } private: uint32 m_timer; @@ -73,9 +57,8 @@ class TRINITY_DLL_SPEC AssistanceDistractMovementGenerator : public DistractMove AssistanceDistractMovementGenerator(uint32 timer) : DistractMovementGenerator(timer) {} - MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_DISTRACT_MOTION_TYPE; } + MovementGeneratorType GetMovementGeneratorType() const { return ASSISTANCE_DISTRACT_MOTION_TYPE; } void Finalize(Unit& unit); }; #endif - diff --git a/src/game/Level0.cpp b/src/game/Level0.cpp index 7eddcec4e..91145d146 100755 --- a/src/game/Level0.cpp +++ b/src/game/Level0.cpp @@ -68,7 +68,7 @@ bool ChatHandler::HandleStartCommand(const char* /*args*/) { Player *chr = m_session->GetPlayer(); - if (chr->isInFlight()) + if (chr->IsTaxiFlying()) { SendSysMessage(LANG_YOU_IN_FLIGHT); SetSentErrorMessage(true); @@ -137,7 +137,7 @@ bool ChatHandler::HandleDismountCommand(const char* /*args*/) return false; } - if (m_session->GetPlayer()->isInFlight()) + if (m_session->GetPlayer()->IsTaxiFlying()) { SendSysMessage(LANG_YOU_IN_FLIGHT); SetSentErrorMessage(true); diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 34efa4139..06c5f85a4 100755 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -940,7 +940,7 @@ bool ChatHandler::HandleNamegoCommand(const char* args) ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, GetName()); // stop flight if need - if (target->isInFlight()) + if (target->IsTaxiFlying()) { target->GetMotionMaster()->MovementExpired(); target->CleanupAfterTaxiFlight(); @@ -1069,7 +1069,7 @@ bool ChatHandler::HandleGonameCommand(const char* args) ChatHandler(target).PSendSysMessage(LANG_APPEARING_TO, _player->GetName()); // stop flight if need - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); @@ -1097,7 +1097,7 @@ bool ChatHandler::HandleGonameCommand(const char* args) if (Player::LoadPositionFromDB(map,x,y,z,o,in_flight,guid)) { // stop flight if need - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); @@ -1157,7 +1157,7 @@ bool ChatHandler::HandleRecallCommand(const char* args) } // stop flight if need - if (chr->isInFlight()) + if (chr->IsTaxiFlying()) { chr->GetMotionMaster()->MovementExpired(); chr->CleanupAfterTaxiFlight(); @@ -1595,7 +1595,7 @@ bool ChatHandler::HandleModifyASpeedCommand(const char* args) return false; } - if (chr->isInFlight()) + if (chr->IsTaxiFlying()) { PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); SetSentErrorMessage(true); @@ -1637,7 +1637,7 @@ bool ChatHandler::HandleModifySpeedCommand(const char* args) return false; } - if (chr->isInFlight()) + if (chr->IsTaxiFlying()) { PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); SetSentErrorMessage(true); @@ -1676,7 +1676,7 @@ bool ChatHandler::HandleModifySwimCommand(const char* args) return false; } - if (chr->isInFlight()) + if (chr->IsTaxiFlying()) { PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); SetSentErrorMessage(true); @@ -1715,7 +1715,7 @@ bool ChatHandler::HandleModifyBWalkCommand(const char* args) return false; } - if (chr->isInFlight()) + if (chr->IsTaxiFlying()) { PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); SetSentErrorMessage(true); @@ -2204,7 +2204,7 @@ bool ChatHandler::HandleTeleCommand(const char * args) } // stop flight if need - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); @@ -2538,7 +2538,7 @@ bool ChatHandler::HandleNameTeleCommand(const char * args) ChatHandler(chr).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetName()); // stop flight if need - if (chr->isInFlight()) + if (chr->IsTaxiFlying()) { chr->GetMotionMaster()->MovementExpired(); chr->CleanupAfterTaxiFlight(); @@ -2616,7 +2616,7 @@ bool ChatHandler::HandleGroupTeleCommand(const char * args) ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetName()); // stop flight if need - if (pl->isInFlight()) + if (pl->IsTaxiFlying()) { pl->GetMotionMaster()->MovementExpired(); pl->CleanupAfterTaxiFlight(); @@ -2709,7 +2709,7 @@ bool ChatHandler::HandleGroupgoCommand(const char* args) ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, GetName()); // stop flight if need - if (pl->isInFlight()) + if (pl->IsTaxiFlying()) { pl->GetMotionMaster()->MovementExpired(); pl->CleanupAfterTaxiFlight(); @@ -2757,7 +2757,7 @@ bool ChatHandler::HandleGoXYCommand(const char* args) } // stop flight if need - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); @@ -2807,7 +2807,7 @@ bool ChatHandler::HandleGoXYZCommand(const char* args) } // stop flight if need - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); @@ -2873,7 +2873,7 @@ bool ChatHandler::HandleGoZoneXYCommand(const char* args) } // stop flight if need - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); @@ -2920,7 +2920,7 @@ bool ChatHandler::HandleGoGridCommand(const char* args) } // stop flight if need - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 746333960..a8412d643 100755 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -442,7 +442,7 @@ bool ChatHandler::HandleGoObjectCommand(const char* args) } // stop flight if need - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); @@ -485,7 +485,7 @@ bool ChatHandler::HandleGoTicketCommand(const char * args) mapid = ticket->map; Player* _player = m_session->GetPlayer(); - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); @@ -529,7 +529,7 @@ bool ChatHandler::HandleGoTriggerCommand(const char* args) } // stop flight if need - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); @@ -574,7 +574,7 @@ bool ChatHandler::HandleGoGraveyardCommand(const char* args) } // stop flight if need - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); @@ -679,7 +679,7 @@ bool ChatHandler::HandleGoCreatureCommand(const char* args) } // stop flight if need - if (_player->isInFlight()) + if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); @@ -3746,16 +3746,16 @@ bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/) return false; } - if (/*creature->GetMotionMaster()->empty() ||*/ - creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE) + if (creature->GetMotionMaster()->empty() || + creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=FOLLOW_MOTION_TYPE) { - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName()); + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); SetSentErrorMessage(true); return false; } - TargetedMovementGenerator const* mgen - = static_cast const*>((creature->GetMotionMaster()->top())); + FollowMovementGenerator const* mgen + = static_cast const*>((creature->GetMotionMaster()->top())); if (mgen->GetTarget()!=player) { diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 2c7583680..321625a69 100755 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -6408,7 +6408,8 @@ bool ChatHandler::HandleMovegensCommand(const char* /*args*/) PSendSysMessage(LANG_MOVEGENS_LIST,(unit->GetTypeId()==TYPEID_PLAYER ? "Player" : "Creature"),unit->GetGUIDLow()); - MotionMaster* mm = unit->GetMotionMaster(); + // If u need IT, fix it ;p + /*MotionMaster* mm = unit->GetMotionMaster(); for (int i = 0; i < MAX_MOTION_SLOT; ++i) { MovementGenerator* mg = mm->GetMotionSlot(i); @@ -6422,7 +6423,6 @@ bool ChatHandler::HandleMovegensCommand(const char* /*args*/) case IDLE_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_IDLE); break; case RANDOM_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_RANDOM); break; case WAYPOINT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_WAYPOINT); break; - case ANIMAL_RANDOM_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_ANIMAL_RANDOM); break; case CONFUSED_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_CONFUSED); break; case TARGETED_MOTION_TYPE: { @@ -6470,7 +6470,7 @@ bool ChatHandler::HandleMovegensCommand(const char* /*args*/) PSendSysMessage(LANG_MOVEGENS_UNKNOWN,mg->GetMovementGeneratorType()); break; } - } + }*/ return true; } @@ -6597,15 +6597,8 @@ bool ChatHandler::HandleCastBackCommand(const char* args) bool triggered = (trig_str != NULL); // update orientation at server - if (!caster->hasUnitState(UNIT_STAT_CANNOT_TURN)) - caster->SetOrientation(caster->GetAngle(m_session->GetPlayer())); - - //sky mod update - //WorldPacket data; - //caster->BuildHeartBeatMsg(&data); - //caster->SendMessageToSet(&data,true); - - caster->SendMovementFlagUpdate(); + //if (!caster->hasUnitState(UNIT_STAT_CANNOT_TURN)) + caster->SetFacingToObject(m_session->GetPlayer()); caster->CastSpell(m_session->GetPlayer(),spell,triggered); @@ -6691,14 +6684,7 @@ bool ChatHandler::HandleCastTargetCommand(const char* args) bool triggered = (trig_str != NULL); // update orientation at server - if (!caster->hasUnitState(UNIT_STAT_CANNOT_TURN)) - caster->SetOrientation(caster->GetAngle(m_session->GetPlayer())); - - // and client - WorldPacket data; - caster->BuildHeartBeatMsg(&data); - caster->SendMessageToSet(&data,true); - + caster->SetFacingToObject(m_session->GetPlayer()); caster->CastSpell(caster->getVictim(),spell,triggered); return true; @@ -6711,24 +6697,14 @@ when attempting to use the PointMovementGenerator */ bool ChatHandler::HandleComeToMeCommand(const char *args) { - char* newFlagStr = strtok((char*)args, " "); - - if (!newFlagStr) - return false; - - uint32 newFlags = (uint32)strtoul(newFlagStr, NULL, 0); - Creature* caster = getSelectedCreature(); if (!caster) { - m_session->GetPlayer()->SetUnitMovementFlags(newFlags); SendSysMessage(LANG_SELECT_CREATURE); SetSentErrorMessage(true); return false; } - caster->SetUnitMovementFlags(newFlags); - Player* pl = m_session->GetPlayer(); caster->GetMotionMaster()->MovePoint(0, pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ()); diff --git a/src/game/Map.cpp b/src/game/Map.cpp index a38633221..3a57df082 100755 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -836,7 +836,7 @@ void Map::PlayerRelocation(Player *player, float x, float y, float z, float orie DEBUG_LOG("Player %s relocation grid[%u,%u]cell[%u,%u]->grid[%u,%u]cell[%u,%u]", player->GetName(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); // update player position for group at taxi flight - if (player->GetGroup() && player->isInFlight()) + if (player->GetGroup() && player->IsTaxiFlying()) player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION); NGridType* oldGrid = getNGrid(old_cell.GridX(), old_cell.GridY()); @@ -1992,6 +1992,7 @@ void Map::ScriptsProcess() source->SetUInt32Value(step.script->datalong, step.script->datalong2); break; case SCRIPT_COMMAND_MOVE_TO: + { if (!source) { sLog.outError("SCRIPT_COMMAND_MOVE_TO call for NULL creature."); @@ -2003,9 +2004,17 @@ void Map::ScriptsProcess() sLog.outError("SCRIPT_COMMAND_MOVE_TO call for non-creature (TypeId: %u), skipping.",source->GetTypeId()); break; } - ((Unit *)source)->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, step.script->datalong2); - ((Unit *)source)->GetMap()->CreatureRelocation(((Creature *)source), step.script->x, step.script->y, step.script->z, 0); + + Unit * unit = (Unit*)source; + if (step.script->datalong2 != 0) + { + float speed = unit->GetDistance(step.script->x, step.script->y, step.script->z) / ((float)step.script->datalong2 * 0.001f); + unit->MonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, speed); + } + else + unit->NearTeleportTo(step.script->x, step.script->y, step.script->z, unit->GetOrientation()); break; + } case SCRIPT_COMMAND_FLAG_SET: if (!source) { diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp index 4d23217d5..26fa3c20e 100755 --- a/src/game/MapManager.cpp +++ b/src/game/MapManager.cpp @@ -28,7 +28,6 @@ #include "GridDefines.h" #include "InstanceData.h" #include "MapInstanced.h" -#include "DestinationHolderImp.h" #include "World.h" #include "CellImpl.h" #include "Corpse.h" diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 366ff2f9c..289a64bf1 100755 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -362,7 +362,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recv_data*/) GetPlayer()->duel || //...is in Duel GetPlayer()->HasAura(9454,0) || //...is frozen by GM via freeze command //...is jumping ...is falling - GetPlayer()->HasUnitMovementFlag(MOVEFLAG_FALLING | MOVEFLAG_FALLINGFAR)) + GetPlayer()->m_movementInfo.HasMovementFlag(MovementFlags(MOVEFLAG_FALLING | MOVEFLAG_FALLINGFAR))) { WorldPacket data(SMSG_LOGOUT_RESPONSE, (2+4)) ; data << (uint8)0xC; @@ -374,7 +374,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recv_data*/) } //instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in mangosd.conf - if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || GetPlayer()->isInFlight() || + if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || GetPlayer()->IsTaxiFlying() || GetSecurity() >= sWorld.getConfig(CONFIG_INSTANT_LOGOUT)) { LogoutPlayer(true); @@ -522,7 +522,7 @@ void WorldSession::HandleStandStateChangeOpcode(WorldPacket & recv_data) uint8 animstate; recv_data >> animstate; - if (!GetPlayer()->isPossessed() && !GetPlayer()->isCharmed()) + if (GetPlayer()->GetCharmerOrOwner() == NULL) _player->SetStandState(animstate); } @@ -828,7 +828,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) recv_data >> Trigger_ID; sLog.outDebug("Trigger ID:%u",Trigger_ID); - if (GetPlayer()->isInFlight()) + if (GetPlayer()->IsTaxiFlying()) { sLog.outDebug("Player '%s' (GUID: %u) in flight, ignore Area Trigger ID:%u",GetPlayer()->GetName(),GetPlayer()->GetGUIDLow(), Trigger_ID); return; @@ -1245,7 +1245,7 @@ void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) //sLog.outDebug("Received opcode CMSG_WORLD_TELEPORT"); - if (GetPlayer()->isInFlight()) + if (GetPlayer()->IsTaxiFlying()) { sLog.outDebug("Player '%s' (GUID: %u) in flight, ignore worldport command.",GetPlayer()->GetName(),GetPlayer()->GetGUIDLow()); return; @@ -1614,7 +1614,7 @@ void WorldSession::HandleDismountOpcode(WorldPacket & /*recv_data*/) return; } - if (_player->isInFlight()) // not blizz like; no any messages on blizz + if (_player->IsTaxiFlying()) // not blizz like; no any messages on blizz { ChatHandler(this).SendSysMessage(LANG_YOU_IN_FLIGHT); return; @@ -1636,7 +1636,7 @@ void WorldSession::HandleMoveFlyModeChangeAckOpcode(WorldPacket & recv_data) recv_data >> movementInfo; recv_data.read_skip(); // unk2 - _player->SetUnitMovementFlags(movementInfo.GetMovementFlags()); + _player->m_movementInfo.SetMovementFlags(movementInfo.GetMovementFlags()); } void WorldSession::HandleRequestPetInfoOpcode(WorldPacket & /*recv_data */) diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index 63a9bc9f4..04ebec428 100755 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2009 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,19 +8,17 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "MotionMaster.h" #include "CreatureAISelector.h" #include "Creature.h" -#include "Traveller.h" - #include "ConfusedMovementGenerator.h" #include "FleeingMovementGenerator.h" #include "HomeMovementGenerator.h" @@ -31,6 +27,8 @@ #include "TargetedMovementGenerator.h" #include "WaypointMovementGenerator.h" #include "RandomMovementGenerator.h" +#include "movement/MoveSpline.h" +#include "movement/MoveSplineInit.h" #include @@ -41,58 +39,45 @@ inline bool isStatic(MovementGenerator *mv) void MotionMaster::Initialize() { - // clear ALL movement generators (including default) - while (!empty()) - { - MovementGenerator *curr = top(); - - pop(); + // stop current move + if (!m_owner->IsStopped()) + m_owner->StopMoving(); - if (curr) - DirectDelete(curr); - } + // clear ALL movement generators (including default) + Clear(false,true); // set new default movement generator - InitDefault(); -} - -void MotionMaster::InitDefault() -{ - if (i_owner->GetTypeId() == TYPEID_UNIT) + if (m_owner->GetTypeId() == TYPEID_UNIT && !m_owner->hasUnitState(UNIT_STAT_CONTROLLED)) { - MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)i_owner); - Mutate(movement == NULL ? &si_idleMovement : movement, MOTION_SLOT_IDLE); + MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)m_owner); + push(movement == NULL ? &si_idleMovement : movement); + top()->Initialize(*m_owner); } else - { - Mutate(&si_idleMovement, MOTION_SLOT_IDLE); - } + push(&si_idleMovement); } MotionMaster::~MotionMaster() { - // clear ALL movement generators (including default) - while (!empty()) + // just deallocate movement generator, but do not Finalize since it may access to already deallocated owner's memory + while(!empty()) { - MovementGenerator *curr = top(); - + MovementGenerator * m = top(); pop(); - - if (curr) - DirectDelete(curr); + if (!isStatic(m)) + delete m; } } void MotionMaster::UpdateMotion(uint32 diff) { - if (i_owner->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED)) + if (m_owner->hasUnitState(UNIT_STAT_CAN_NOT_MOVE)) return; - assert(!empty()); - + ASSERT( !empty() ); m_cleanFlag |= MMCF_UPDATE; - if (!top()->Update(*i_owner, diff)) + if (!top()->Update(*m_owner, diff)) { m_cleanFlag &= ~MMCF_UPDATE; MovementExpired(); @@ -102,302 +87,258 @@ void MotionMaster::UpdateMotion(uint32 diff) if (m_expList) { - for (int i = 0; i < m_expList->size(); ++i) + for (size_t i = 0; i < m_expList->size(); ++i) { MovementGenerator* mg = (*m_expList)[i]; - DirectDelete(mg); + if (!isStatic(mg)) + delete mg; } delete m_expList; m_expList = NULL; if (empty()) - { Initialize(); - } - else if (needInitTop()) - { - InitTop(); - } - else if (m_cleanFlag & MMCF_RESET) + + if (m_cleanFlag & MMCF_RESET) { - top()->Reset(*i_owner); + top()->Reset(*m_owner); + m_cleanFlag &= ~MMCF_RESET; } - - m_cleanFlag &= ~MMCF_RESET; } } -void MotionMaster::DirectClean(bool reset) +void MotionMaster::DirectClean(bool reset, bool all) { - while (size() > 1) + while( all ? !empty() : size() > 1 ) { MovementGenerator *curr = top(); - pop(); + curr->Finalize(*m_owner); - if (curr) - DirectDelete(curr); + if (!isStatic(curr)) + delete curr; } - if (needInitTop()) + if (!all && reset) { - InitTop(); - } - else if (reset) - { - top()->Reset(*i_owner); + ASSERT( !empty() ); + top()->Reset(*m_owner); } } -void MotionMaster::DelayedClean() +void MotionMaster::DelayedClean(bool reset, bool all) { - while (size() > 1) + if (reset) + m_cleanFlag |= MMCF_RESET; + else + m_cleanFlag &= ~MMCF_RESET; + + if (empty() || (!all && size() == 1)) + return; + + if (!m_expList) + m_expList = new ExpireList(); + + while( all ? !empty() : size() > 1 ) { MovementGenerator *curr = top(); - pop(); + curr->Finalize(*m_owner); - if (curr) - DelayedDelete(curr); + if (!isStatic(curr)) + m_expList->push_back(curr); } } void MotionMaster::DirectExpire(bool reset) { - if (size() > 1) - { - MovementGenerator *curr = top(); - - pop(); + if (empty() || size() == 1) + return; - DirectDelete(curr); - } + MovementGenerator *curr = top(); + pop(); - while (!top()) + // also drop stored under top() targeted motions + while (!empty() && (top()->GetMovementGeneratorType() == CHASE_MOTION_TYPE || top()->GetMovementGeneratorType() == FOLLOW_MOTION_TYPE)) { - --i_top; + MovementGenerator *temp = top(); + pop(); + temp->Finalize(*m_owner); + delete temp; } + // Store current top MMGen, as Finalize might push a new MMGen + MovementGenerator* nowTop = empty() ? NULL : top(); + // it can add another motions instead + curr->Finalize(*m_owner); + + if (!isStatic(curr)) + delete curr; + if (empty()) - { Initialize(); - } - else if (needInitTop()) - { - InitTop(); - } - else if (reset) - { - top()->Reset(*i_owner); - } + + // Prevent reseting possible new pushed MMGen + if (reset && top() == nowTop) + top()->Reset(*m_owner); } -void MotionMaster::DelayedExpire() +void MotionMaster::DelayedExpire(bool reset) { - if (size() > 1) - { - MovementGenerator *curr = top(); + if (reset) + m_cleanFlag |= MMCF_RESET; + else + m_cleanFlag &= ~MMCF_RESET; - pop(); + if (empty() || size() == 1) + return; - DelayedDelete(curr); - } + MovementGenerator *curr = top(); + pop(); + + if (!m_expList) + m_expList = new ExpireList(); - while (!top()) + // also drop stored under top() targeted motions + while (!empty() && (top()->GetMovementGeneratorType() == CHASE_MOTION_TYPE || top()->GetMovementGeneratorType() == FOLLOW_MOTION_TYPE)) { - --i_top; + MovementGenerator *temp = top(); + pop(); + temp ->Finalize(*m_owner); + m_expList->push_back(temp ); } + + curr->Finalize(*m_owner); + + if (!isStatic(curr)) + m_expList->push_back(curr); } -void MotionMaster::MoveIdle(MovementSlot slot) +void MotionMaster::MoveIdle() { - if (!isStatic(Impl[slot])) - { - Mutate(&si_idleMovement, slot); - } + if (empty() || !isStatic(top())) + push(&si_idleMovement); } -void MotionMaster::MoveRandom(float spawndist) +void MotionMaster::MoveRandom() { - if (i_owner->GetTypeId() == TYPEID_UNIT) + if (m_owner->GetTypeId() == TYPEID_PLAYER) { - Mutate(new RandomMovementGenerator(spawndist), MOTION_SLOT_IDLE); + //sLog.outError("%s attempt to move random.", m_owner->GetGuidStr().c_str()); + return; + } + else + { + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s move random.", m_owner->GetGuidStr().c_str()); + Mutate(new RandomMovementGenerator(*m_owner)); } } void MotionMaster::MoveTargetedHome() { + if (m_owner->hasUnitState(UNIT_STAT_LOST_CONTROL)) + return; + Clear(false); - if (i_owner->GetTypeId()==TYPEID_UNIT && !((Creature*)i_owner)->GetCharmerOrOwnerGUID()) + if (m_owner->GetTypeId() == TYPEID_UNIT && !((Creature*)m_owner)->GetCharmerOrOwnerGUID()) { - Mutate(new HomeMovementGenerator(), MOTION_SLOT_ACTIVE); + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s targeted home", m_owner->GetGuidStr().c_str()); + Mutate(new HomeMovementGenerator()); } - else if (i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID()) + else if (m_owner->GetTypeId() == TYPEID_UNIT && ((Creature*)m_owner)->GetCharmerOrOwnerGUID()) { - if (Unit *target = ((Creature*)i_owner)->GetCharmerOrOwner()) + if (Unit *target = ((Creature*)m_owner)->GetCharmerOrOwner()) { - i_owner->addUnitState(UNIT_STAT_FOLLOW); - - Mutate(new TargetedMovementGenerator(*target,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE), MOTION_SLOT_ACTIVE); + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s follow to %s", m_owner->GetGuidStr().c_str(), target->GetGuidStr().c_str()); + Mutate(new FollowMovementGenerator(*target,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE)); } } - else - { - sLog.outError("Player (GUID: %u) attempt targeted home", i_owner->GetGUIDLow()); - } + //else + //sLog.outError("%s attempt targeted home", m_owner->GetGuidStr().c_str()); } void MotionMaster::MoveConfused() { - if (i_owner->GetTypeId() == TYPEID_PLAYER) - { - Mutate(new ConfusedMovementGenerator(), MOTION_SLOT_CONTROLLED); - } + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s move confused", m_owner->GetGuidStr().c_str()); + + if (m_owner->GetTypeId() == TYPEID_PLAYER) + Mutate(new ConfusedMovementGenerator()); else - { - Mutate(new ConfusedMovementGenerator(), MOTION_SLOT_CONTROLLED); - } + Mutate(new ConfusedMovementGenerator()); } void MotionMaster::MoveChase(Unit* target, float dist, float angle) { // ignore movement request if target not exist - if (!target || target == i_owner) - return; - - if (i_owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) + if (!target) return; - i_owner->clearUnitState(UNIT_STAT_FOLLOW); + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s chase to %s", m_owner->GetGuidStr().c_str(), target->GetGuidStr().c_str()); - if (i_owner->GetTypeId() == TYPEID_PLAYER) - { - Mutate(new TargetedMovementGenerator(*target,dist,angle), MOTION_SLOT_ACTIVE); - } + if (m_owner->GetTypeId() == TYPEID_PLAYER) + Mutate(new ChaseMovementGenerator(*target,dist,angle)); else - { - Mutate(new TargetedMovementGenerator(*target,dist,angle), MOTION_SLOT_ACTIVE); - } + Mutate(new ChaseMovementGenerator(*target,dist,angle)); } -void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlot slot) +void MotionMaster::MoveFollow(Unit* target, float dist, float angle) { - // ignore movement request if target not exist - if (!target || target == i_owner) + if (m_owner->hasUnitState(UNIT_STAT_LOST_CONTROL)) return; - if (i_owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) - return; - - i_owner->addUnitState(UNIT_STAT_FOLLOW); - - if (i_owner->GetTypeId() == TYPEID_PLAYER) - { - Mutate(new TargetedMovementGenerator(*target,dist,angle), slot); - } - else - { - Mutate(new TargetedMovementGenerator(*target,dist,angle), slot); - } -} - -void MotionMaster::MovePoint(uint32 id, float x, float y, float z) -{ - if (i_owner->GetTypeId() == TYPEID_PLAYER) - { - Mutate(new PointMovementGenerator(id,x,y,z), MOTION_SLOT_ACTIVE); - } - else - { - Mutate(new PointMovementGenerator(id,x,y,z), MOTION_SLOT_ACTIVE); - } -} + Clear(); -void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ) -{ - //this function may make players fall below map - if (i_owner->GetTypeId() == TYPEID_PLAYER) + // ignore movement request if target not exist + if (!target) return; - float x, y, z; - float dist = speedXY * speedZ * 0.1f; - - i_owner->GetClosePoint(x, y, z, i_owner->GetObjectSize(), dist, angle); - MoveJump(x, y, z, speedXY, speedZ); -} - -void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float speedZ) -{ - uint32 moveFlag = SPLINEFLAG_JUMP | SPLINEFLAG_WALKMODE; - uint32 time = speedZ * 100; + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s follow to %s", m_owner->GetGuidStr().c_str(), target->GetGuidStr().c_str()); - i_owner->addUnitState(UNIT_STAT_CHARGING | UNIT_STAT_JUMPING); - i_owner->m_TempSpeed = speedXY; - - if (i_owner->GetTypeId() == TYPEID_PLAYER) - { - Mutate(new PointMovementGenerator(0,x,y,z), MOTION_SLOT_CONTROLLED); - } + if (m_owner->GetTypeId() == TYPEID_PLAYER) + Mutate(new FollowMovementGenerator(*target,dist,angle)); else - { - Mutate(new PointMovementGenerator(0,x,y,z), MOTION_SLOT_CONTROLLED); - } - - i_owner->SendMonsterMove(x, y, z, moveFlag, time, speedZ); + Mutate(new FollowMovementGenerator(*target,dist,angle)); } -void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id) +void MotionMaster::MovePoint(uint32 id, float x, float y, float z) { - if (Impl[MOTION_SLOT_CONTROLLED] && Impl[MOTION_SLOT_CONTROLLED]->GetMovementGeneratorType() != DISTRACT_MOTION_TYPE) - return; - - i_owner->addUnitState(UNIT_STAT_CHARGING); - i_owner->m_TempSpeed = speed; + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s targeted point (Id: %u X: %f Y: %f Z: %f)", m_owner->GetGuidStr().c_str(), id, x, y, z ); - if (i_owner->GetTypeId() == TYPEID_PLAYER) - { - Mutate(new PointMovementGenerator(id,x,y,z), MOTION_SLOT_CONTROLLED); - } + if (m_owner->GetTypeId() == TYPEID_PLAYER) + Mutate(new PointMovementGenerator(id,x,y,z)); else - { - Mutate(new PointMovementGenerator(id,x,y,z), MOTION_SLOT_CONTROLLED); - } -} - -void MotionMaster::MoveFall(float z, uint32 id) -{ - i_owner->SetFlying(false); - i_owner->SendMovementFlagUpdate(); - - MoveCharge(i_owner->GetPositionX(), i_owner->GetPositionY(), z, SPEED_CHARGE, id); + Mutate(new PointMovementGenerator(id,x,y,z)); } void MotionMaster::MoveSeekAssistance(float x, float y, float z) { - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (m_owner->GetTypeId() == TYPEID_PLAYER) { - sLog.outError("Player (GUID: %u) attempt to seek assistance",i_owner->GetGUIDLow()); + //sLog.outError("%s attempt to seek assistance", m_owner->GetGuidStr().c_str()); + return; } else { - i_owner->AttackStop(); - ((Creature*)i_owner)->SetReactState(REACT_PASSIVE); - - Mutate(new AssistanceMovementGenerator(x,y,z), MOTION_SLOT_ACTIVE); + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s seek assistance (X: %f Y: %f Z: %f)", + // m_owner->GetGuidStr().c_str(), x, y, z ); + Mutate(new AssistanceMovementGenerator(x,y,z)); } } void MotionMaster::MoveSeekAssistanceDistract(uint32 time) { - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (m_owner->GetTypeId() == TYPEID_PLAYER) { - sLog.outError("Player (GUID: %u) attempt to call distract after assistance",i_owner->GetGUIDLow()); + //sLog.outError("%s attempt to call distract after assistance", m_owner->GetGuidStr().c_str()); + return; } else { - Mutate(new AssistanceDistractMovementGenerator(time), MOTION_SLOT_ACTIVE); + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s is distracted after assistance call (Time: %u)", + // m_owner->GetGuidStr().c_str(), time ); + Mutate(new AssistanceDistractMovementGenerator(time)); } } @@ -406,148 +347,134 @@ void MotionMaster::MoveFleeing(Unit* enemy, uint32 time) if (!enemy) return; - if (i_owner->HasAuraType(SPELL_AURA_PREVENTS_FLEEING)) - return; + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s flee from %s", m_owner->GetGuidStr().c_str(), enemy->GetGuidStr().c_str()); - if (i_owner->GetTypeId() == TYPEID_PLAYER) - { - Mutate(new FleeingMovementGenerator(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); - } + if (m_owner->GetTypeId() == TYPEID_PLAYER) + Mutate(new FleeingMovementGenerator(enemy->GetGUID())); else { if (time) - { - Mutate(new TimedFleeingMovementGenerator(enemy->GetGUID(), time), MOTION_SLOT_CONTROLLED); - } + Mutate(new TimedFleeingMovementGenerator(enemy->GetGUID(), time)); else + Mutate(new FleeingMovementGenerator(enemy->GetGUID())); + } +} + +void MotionMaster::MoveWaypoint() +{ + if (m_owner->GetTypeId() == TYPEID_UNIT) + { + if (GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) { - Mutate(new FleeingMovementGenerator(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); + //sLog.outError("Creature %s (Entry %u) attempt to MoveWaypoint() but creature is already using waypoint", m_owner->GetGuidStr().c_str(), m_owner->GetEntry()); + return; } + + Creature* creature = (Creature*)m_owner; + + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature %s (Entry %u) start MoveWaypoint()", m_owner->GetGuidStr().c_str(), m_owner->GetEntry()); + Mutate(new WaypointMovementGenerator(*creature)); } + //else + //{ + //sLog.outError("Non-creature %s attempt to MoveWaypoint()", m_owner->GetGuidStr().c_str()); + //} } void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode) { - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (m_owner->GetTypeId() == TYPEID_PLAYER) { - FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(path,pathnode); - Mutate(mgen, MOTION_SLOT_CONTROLLED); - } - else - { - sLog.outError("Creature (Entry: %u GUID: %u) attempt taxi to (Path %u node %u)", i_owner->GetEntry(), i_owner->GetGUIDLow(), path, pathnode); + if (path < sTaxiPathNodesByPath.size()) + { + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s taxi to (Path %u node %u)", m_owner->GetGuidStr().c_str(), path, pathnode); + FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(sTaxiPathNodesByPath[path],pathnode); + Mutate(mgen); + } } } void MotionMaster::MoveDistract(uint32 timer) { - if (Impl[MOTION_SLOT_CONTROLLED]) - return; - + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s distracted (timer: %u)", m_owner->GetGuidStr().c_str(), timer); DistractMovementGenerator* mgen = new DistractMovementGenerator(timer); - Mutate(mgen, MOTION_SLOT_CONTROLLED); -} - -void MotionMaster::MoveRotate(uint32 time, RotateDirection direction) -{ - if (!time) - return; - - Mutate(new RotateMovementGenerator(time, direction), MOTION_SLOT_ACTIVE); + Mutate(mgen); } -void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot) +void MotionMaster::Mutate(MovementGenerator *m) { - if (MovementGenerator *curr = Impl[slot]) + if (!empty()) { - Impl[slot] = NULL; // in case a new one is generated in this slot during directdelete - if (i_top == slot && (m_cleanFlag & MMCF_UPDATE)) - DelayedDelete(curr); - else - DirectDelete(curr); - } - else if (i_top < slot) - { - i_top = slot; - } + switch(top()->GetMovementGeneratorType()) + { + // HomeMovement is not that important, delete it if meanwhile a new comes + case HOME_MOTION_TYPE: + // DistractMovement interrupted by any other movement + case DISTRACT_MOTION_TYPE: + case EFFECT_MOTION_TYPE: + MovementExpired(false); + default: + break; + } - if (i_top > slot) - needInit[slot] = true; - else - { - m->Initialize(*i_owner); - needInit[slot] = false; + if (!empty()) + top()->Interrupt(*m_owner); } - Impl[slot] = m; -} - -void MotionMaster::MovePath(uint32 path_id, bool repeatable) -{ - if (!path_id) - return; - - Mutate(new WaypointMovementGenerator(path_id, repeatable), MOTION_SLOT_IDLE); + m->Initialize(*m_owner); + push(m); } void MotionMaster::propagateSpeedChange() { - for (int i = 0; i <= i_top; ++i) + Impl::container_type::iterator it = Impl::c.begin(); + for ( ;it != end(); ++it) { - if (Impl[i]) - Impl[i]->unitSpeedChanged(); + (*it)->unitSpeedChanged(); } } MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const { - if (empty() || !top()) - return IDLE_MOTION_TYPE; + if (empty()) + return IDLE_MOTION_TYPE; - return top()->GetMovementGeneratorType(); + return top()->GetMovementGeneratorType(); } -MovementGeneratorType MotionMaster::GetMotionSlotType(int slot) const +bool MotionMaster::GetDestination(float &x, float &y, float &z) { - if (!Impl[slot]) - return NULL_MOTION_TYPE; - else - return Impl[slot]->GetMovementGeneratorType(); -} + if (m_owner->movespline->Finalized()) + return false; -void MotionMaster::InitTop() -{ - top()->Initialize(*i_owner); - needInit[i_top] = false; + const G3D::Vector3& dest = m_owner->movespline->FinalDestination(); + x = dest.x; + y = dest.y; + z = dest.z; + return true; } -void MotionMaster::DirectDelete(_Ty curr) +void MotionMaster::UpdateFinalDistanceToTarget(float fDistance) { - if (isStatic(curr)) - return; - - curr->Finalize(*i_owner); - delete curr; + if (!empty()) + top()->UpdateFinalDistance(fDistance); } -void MotionMaster::DelayedDelete(_Ty curr) +void MotionMaster::MoveJump(float x, float y, float z, float horizontalSpeed, float max_height, uint32 id) { - sLog.outError("CRASH ALARM! Unit (Entry %u) is trying to delete its updating MG (Type %u)!", i_owner->GetEntry(), curr->GetMovementGeneratorType()); - - if (isStatic(curr)) - return; - - if (!m_expList) - m_expList = new ExpireList(); - - m_expList->push_back(curr); + Movement::MoveSplineInit init(*m_owner); + init.MoveTo(x,y,z); + init.SetParabolic(max_height,0,false); + init.SetVelocity(horizontalSpeed); + init.Launch(); + Mutate(new EffectMovementGenerator(id)); } -bool MotionMaster::GetDestination(float &x, float &y, float &z) +void MotionMaster::MoveCharge(float x, float y, float z) { - if (empty()) - return false; - - return top() ? top()->GetDestination(x,y,z) : false; + Movement::MoveSplineInit init(*m_owner); + init.MoveTo(x,y,z); + init.SetVelocity(42.0f); + init.Launch(); + Mutate(new EffectMovementGenerator(EVENT_CHARGE)); } - diff --git a/src/game/MotionMaster.h b/src/game/MotionMaster.h index 436e3af93..39cb0d812 100755 --- a/src/game/MotionMaster.h +++ b/src/game/MotionMaster.h @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2009 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,20 +8,20 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITY_MOTIONMASTER_H -#define TRINITY_MOTIONMASTER_H +#ifndef MANGOS_MOTIONMASTER_H +#define MANGOS_MOTIONMASTER_H #include "Common.h" +#include #include -#include "SharedDefines.h" class MovementGenerator; class Unit; @@ -34,152 +32,107 @@ class Unit; // values 0 ... MAX_DB_MOTION_TYPE-1 used in DB enum MovementGeneratorType { - IDLE_MOTION_TYPE = 0, // IdleMovementGenerator.h - RANDOM_MOTION_TYPE = 1, // RandomMovementGenerator.h - WAYPOINT_MOTION_TYPE = 2, // WaypointMovementGenerator.h - MAX_DB_MOTION_TYPE = 3, // *** this and below motion types can't be set in DB. - ANIMAL_RANDOM_MOTION_TYPE = MAX_DB_MOTION_TYPE, // AnimalRandomMovementGenerator.h - CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h - TARGETED_MOTION_TYPE = 5, // TargetedMovementGenerator.h - HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h - FLIGHT_MOTION_TYPE = 7, // WaypointMovementGenerator.h - POINT_MOTION_TYPE = 8, // PointMovementGenerator.h - FLEEING_MOTION_TYPE = 9, // FleeingMovementGenerator.h - DISTRACT_MOTION_TYPE = 10, // IdleMovementGenerator.h - ASSISTANCE_MOTION_TYPE= 11, // PointMovementGenerator.h (first part of flee for assistance) + IDLE_MOTION_TYPE = 0, // IdleMovementGenerator.h + RANDOM_MOTION_TYPE = 1, // RandomMovementGenerator.h + WAYPOINT_MOTION_TYPE = 2, // WaypointMovementGenerator.h + MAX_DB_MOTION_TYPE = 3, // *** this and below motion types can't be set in DB. + + CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h + CHASE_MOTION_TYPE = 5, // TargetedMovementGenerator.h + HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h + FLIGHT_MOTION_TYPE = 7, // WaypointMovementGenerator.h + POINT_MOTION_TYPE = 8, // PointMovementGenerator.h + FLEEING_MOTION_TYPE = 9, // FleeingMovementGenerator.h + DISTRACT_MOTION_TYPE = 10, // IdleMovementGenerator.h + ASSISTANCE_MOTION_TYPE = 11, // PointMovementGenerator.h (first part of flee for assistance) ASSISTANCE_DISTRACT_MOTION_TYPE = 12, // IdleMovementGenerator.h (second part of flee for assistance) - TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h (alt.second part of flee for assistance) - ROTATE_MOTION_TYPE = 14, - NULL_MOTION_TYPE = 15, -}; - -enum MovementSlot -{ - MOTION_SLOT_IDLE, - MOTION_SLOT_ACTIVE, - MOTION_SLOT_CONTROLLED, - MAX_MOTION_SLOT, -}; - -enum RotateDirection -{ - ROTATE_DIRECTION_LEFT, - ROTATE_DIRECTION_RIGHT, + TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h (alt.second part of flee for assistance) + FOLLOW_MOTION_TYPE = 14, // TargetedMovementGenerator.h + EFFECT_MOTION_TYPE = 15, }; -// assume it is 25 yard per 0.6 second -#define SPEED_CHARGE 42.0f - enum MMCleanFlag { MMCF_NONE = 0, - MMCF_UPDATE = 1, // Clear or Expire called from update - MMCF_RESET = 2 // Flag if need top()->Reset() + MMCF_UPDATE = 1, // Clear or Expire called from update + MMCF_RESET = 2 // Flag if need top()->Reset() }; -class TRINITY_DLL_SPEC MotionMaster //: private std::stack +class TRINITY_DLL_SPEC MotionMaster : private std::stack { private: - //typedef std::stack Impl; - typedef MovementGenerator* _Ty; - _Ty Impl[MAX_MOTION_SLOT]; - bool needInit[MAX_MOTION_SLOT]; - typedef std::vector<_Ty> ExpireList; - int i_top; - - bool empty() const { return i_top < 0; } - void pop() { Impl[i_top] = NULL; --i_top; } - void push(_Ty _Val) { ++i_top; Impl[i_top] = _Val; } - - bool needInitTop() const { return needInit[i_top]; } - void InitTop(); + typedef std::stack Impl; + typedef std::vector ExpireList; public: - explicit MotionMaster(Unit *unit) : i_owner(unit), m_expList(NULL), m_cleanFlag(MMCF_NONE), i_top(-1) - { - for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i) - { - Impl[i] = NULL; - needInit[i] = true; - } - } + explicit MotionMaster(Unit *unit) : m_owner(unit), m_expList(NULL), m_cleanFlag(MMCF_NONE) {} ~MotionMaster(); void Initialize(); - void InitDefault(); - int size() const { return i_top + 1; } - _Ty top() const { return Impl[i_top]; } - _Ty GetMotionSlot(int slot) const { return Impl[slot]; } + MovementGenerator* operator->(void) { return top(); } + + using Impl::top; + using Impl::empty; - void DirectDelete(_Ty curr); - void DelayedDelete(_Ty curr); + typedef Impl::container_type::const_iterator const_iterator; + const_iterator begin() const { return Impl::c.begin(); } + const_iterator end() const { return Impl::c.end(); } void UpdateMotion(uint32 diff); - void Clear(bool reset = true) + void Clear(bool reset = true, bool all = false) { if (m_cleanFlag & MMCF_UPDATE) - { - if (reset) - m_cleanFlag |= MMCF_RESET; - else - m_cleanFlag &= ~MMCF_RESET; - DelayedClean(); - } + DelayedClean(reset, all); else - DirectClean(reset); + DirectClean(reset, all); } void MovementExpired(bool reset = true) { if (m_cleanFlag & MMCF_UPDATE) - { - if (reset) - m_cleanFlag |= MMCF_RESET; - else - m_cleanFlag &= ~MMCF_RESET; - DelayedExpire(); - } + DelayedExpire(reset); else DirectExpire(reset); } - void MoveIdle(MovementSlot slot = MOTION_SLOT_ACTIVE); + void MoveIdle(); + void MoveRandom(); void MoveTargetedHome(); - void MoveRandom(float spawndist = 0.0f); - void MoveFollow(Unit* target, float dist, float angle, MovementSlot slot = MOTION_SLOT_ACTIVE); + void MoveFollow(Unit* target, float dist, float angle); void MoveChase(Unit* target, float dist = 0.0f, float angle = 0.0f); void MoveConfused(); - void MoveFleeing(Unit* enemy, uint32 time = 0); + void MoveFleeing(Unit* enemy, uint32 timeLimit = 0); void MovePoint(uint32 id, float x,float y,float z); - void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE); - void MoveFall(float z, uint32 id = 0); - void MoveJumpTo(float angle, float speedXY, float speedZ); - void MoveJump(float x, float y, float z, float speedXY, float speedZ); void MoveSeekAssistance(float x,float y,float z); void MoveSeekAssistanceDistract(uint32 timer); + void MoveWaypoint(); void MoveTaxiFlight(uint32 path, uint32 pathnode); - void MoveDistract(uint32 time); - void MovePath(uint32 path_id, bool repeatable); - void MoveRotate(uint32 time, RotateDirection direction); + void MoveDistract(uint32 timeLimit); + void MoveJump(float x, float y, float z, float horizontalSpeed, float max_height, uint32 id = 0); + void MoveCharge(float x, float y, float z); + + // to implement + void MovePath(uint32 x, uint32 s){return;} MovementGeneratorType GetCurrentMovementGeneratorType() const; - MovementGeneratorType GetMotionSlotType(int slot) const; void propagateSpeedChange(); + // will only work in MMgens where we have a target (TARGETED_MOTION_TYPE) + void UpdateFinalDistanceToTarget(float fDistance); + bool GetDestination(float &x, float &y, float &z); private: - void Mutate(MovementGenerator *m, MovementSlot slot); // use Move* functions instead + void Mutate(MovementGenerator *m); // use Move* functions instead - void DirectClean(bool reset); - void DelayedClean(); + void DirectClean(bool reset, bool all); + void DelayedClean(bool reset, bool all); void DirectExpire(bool reset); - void DelayedExpire(); + void DelayedExpire(bool reset); - Unit *i_owner; + Unit *m_owner; ExpireList *m_expList; uint8 m_cleanFlag; }; #endif - diff --git a/src/game/MovementGenerator.cpp b/src/game/MovementGenerator.cpp index ee314ffae..fd9dfd302 100755 --- a/src/game/MovementGenerator.cpp +++ b/src/game/MovementGenerator.cpp @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,17 +8,24 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "MovementGenerator.h" +#include "Unit.h" MovementGenerator::~MovementGenerator() { } +bool MovementGenerator::IsActive( Unit& u ) +{ + // When movement generator list modified from Update movegen object erase delayed, + // so pointer still valid and be used for check + return !u.GetMotionMaster()->empty() && u.GetMotionMaster()->top() == this; +} diff --git a/src/game/MovementGenerator.h b/src/game/MovementGenerator.h index 49d0ce879..b81883b4b 100755 --- a/src/game/MovementGenerator.h +++ b/src/game/MovementGenerator.h @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,22 +8,22 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITY_MOVEMENTGENERATOR_H -#define TRINITY_MOVEMENTGENERATOR_H +#ifndef MANGOS_MOVEMENTGENERATOR_H +#define MANGOS_MOVEMENTGENERATOR_H +#include "Common.h" #include "Platform/Define.h" #include "Policies/Singleton.h" #include "Dynamic/ObjectRegistry.h" #include "Dynamic/FactoryHolder.h" -#include "Common.h" #include "MotionMaster.h" class Unit; @@ -35,18 +33,30 @@ class TRINITY_DLL_SPEC MovementGenerator public: virtual ~MovementGenerator(); + // called before adding movement generator to motion stack virtual void Initialize(Unit &) = 0; + // called aftre remove movement generator from motion stack virtual void Finalize(Unit &) = 0; + // called before lost top position (before push new movement generator above) + virtual void Interrupt(Unit &) = 0; + // called after return movement generator to top position (after remove above movement generator) virtual void Reset(Unit &) = 0; virtual bool Update(Unit &, const uint32 &time_diff) = 0; - virtual MovementGeneratorType GetMovementGeneratorType() = 0; + virtual MovementGeneratorType GetMovementGeneratorType() const = 0; virtual void unitSpeedChanged() { } - virtual bool GetDestination(float& /*x*/, float& /*y*/, float& /*z*/) const { return false; } + virtual void UpdateFinalDistance(float /*fDistance*/) { } + + // used by Evade code for select point to evade with expected restart default movement + virtual bool GetResetPosition(Unit &, float& /*x*/, float& /*y*/, float& /*z*/) { return false; } + + // used for check from Update call is movegen still be active (top movement generator) + // after some not safe for this calls + bool IsActive(Unit& u); }; template @@ -63,6 +73,11 @@ class TRINITY_DLL_SPEC MovementGeneratorMedium : public MovementGenerator //u->AssertIsType(); (static_cast(this))->Finalize(*((T*)&u)); } + void Interrupt(Unit &u) + { + //u->AssertIsType(); + (static_cast(this))->Interrupt(*((T*)&u)); + } void Reset(Unit &u) { //u->AssertIsType(); @@ -73,12 +88,21 @@ class TRINITY_DLL_SPEC MovementGeneratorMedium : public MovementGenerator //u->AssertIsType(); return (static_cast(this))->Update(*((T*)&u), time_diff); } + bool GetResetPosition(Unit& u, float& x, float& y, float& z) + { + //u->AssertIsType(); + return (static_cast(this))->GetResetPosition(*((T*)&u), x, y, z); + } public: // will not link if not overridden in the generators void Initialize(T &u); void Finalize(T &u); + void Interrupt(T &u); void Reset(T &u); bool Update(T &u, const uint32 &time_diff); + + // not need always overwrites + bool GetResetPosition(T& /*u*/, float& /*x*/, float& /*y*/, float& /*z*/) { return false; } }; struct SelectableMovement : public FactoryHolder @@ -97,5 +121,5 @@ struct MovementGeneratorFactory : public SelectableMovement typedef FactoryHolder MovementGeneratorCreator; typedef FactoryHolder::FactoryHolderRegistry MovementGeneratorRegistry; typedef FactoryHolder::FactoryHolderRepository MovementGeneratorRepository; -#endif +#endif diff --git a/src/game/MovementGeneratorImpl.h b/src/game/MovementGeneratorImpl.h index 7197adb5d..c8270094b 100755 --- a/src/game/MovementGeneratorImpl.h +++ b/src/game/MovementGeneratorImpl.h @@ -27,7 +27,7 @@ template inline MovementGenerator* MovementGeneratorFactory::Create(void *data) const { - return (new MOVEMENT_GEN()); + Creature* creature = reinterpret_cast(data); + return (new MOVEMENT_GEN(*creature)); } #endif - diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index c8b53dfb6..7c5be6238 100755 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -121,7 +121,7 @@ void WorldSession::HandleMoveWorldportAckOpcode() // short preparations to continue flight GetPlayer()->SetDontMove(false); FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); - flight->Initialize(*GetPlayer()); + flight->Reset(*GetPlayer()); return; } @@ -218,7 +218,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) pPlayer->m_AC_NoFall_count ++; // falltime = 357 <--- WEH No Fall Damage Cheat sLog.outCheat("Player %s (GUID: %u / ACCOUNT_ID: %u) - possible no fall damage cheat. MapId: %u, falltime: %u, coords old: %f, %f, %f,coords new: %f, %f, %f. MOVEMENTFLAGS: %u LATENCY: %u. BG/Arena: %s", - pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), oldMovementInfo.GetFallTime(), oldMovementInfo.pos.x, oldMovementInfo.pos.y, oldMovementInfo.pos.z, movementInfo.pos.x, movementInfo.pos.y, movementInfo.pos.z, movementInfo.pos.z, movementInfo.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); + pPlayer->GetName(), pPlayer->GetGUIDLow(), pPlayer->GetSession()->GetAccountId(), pPlayer->GetMapId(), oldMovementInfo.GetFallTime(), oldMovementInfo.GetPos()->x, oldMovementInfo.GetPos()->y, oldMovementInfo.GetPos()->z, movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetMovementFlags(), m_latency, pPlayer->GetMap() ? (pPlayer->GetMap()->IsBattleGroundOrArena() ? "Yes" : "No") : "No"); //pPlayer->Kill(pPlayer, true); if (!(pPlayer->m_AC_NoFall_count % 5)) @@ -263,7 +263,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) */ //Save movement flags - pPlayer->SetUnitMovementFlags(movementInfo.GetMovementFlags()); + pPlayer->m_movementInfo.SetMovementFlags(movementInfo.GetMovementFlags()); /* handle special cases */ if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT)) @@ -287,7 +287,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) // elevators also cause the client to send MOVEFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list for (MapManager::TransportSet::iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter) { - if ((*iter)->GetGUID() == movementInfo.t_guid) + if ((*iter)->GetGUID() == movementInfo.GetTransportGuid()) { // unmount before boarding pPlayer->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); @@ -307,7 +307,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). - if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND && !pPlayer->isInFlight()) + if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND && !pPlayer->IsTaxiFlying()) pPlayer->HandleFallDamage(movementInfo); if (movementInfo.HasMovementFlag(MOVEFLAG_SWIMMING) != pPlayer->IsInWater()) @@ -345,7 +345,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) if (pPlayer->isMoving()) pPlayer->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_NOT_SEATED); - if (pPlayer->isTurning()) + if (pPlayer->isMovingOrTurning()) pPlayer->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING | AURA_INTERRUPT_FLAG_NOT_SEATED); if (movementInfo.GetPos()->z < -500.0f) @@ -363,7 +363,7 @@ void WorldSession::HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& return; //Save movement flags - pos_unit->SetUnitMovementFlags(movementInfo.GetMovementFlags()); + pos_unit->m_movementInfo.SetMovementFlags(movementInfo.GetMovementFlags()); // Remove possession if possessed unit enters a transport if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT)) @@ -396,7 +396,7 @@ void WorldSession::HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& plr->SetPosition(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o, false); plr->m_movementInfo = movementInfo; - if (plr->isTurning()) + if (plr->isMovingOrTurning()) plr->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); if (movementInfo.GetPos()->z < -500.0f) @@ -531,7 +531,7 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket & recv_data) return; // Save movement flags - _player->SetUnitMovementFlags(movementInfo.GetMovementFlags()); + _player->m_movementInfo.SetMovementFlags(movementInfo.GetMovementFlags()); // skip not personal message; GetPlayer()->m_movementInfo = movementInfo; diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 455c595cc..499c84948 100755 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -48,6 +48,7 @@ #include "TemporarySummon.h" #include "OutdoorPvPMgr.h" +#include "movement/packet_builder.h" uint32 GuidHigh2TypeId(uint32 guid_hi) { @@ -259,45 +260,29 @@ void Object::DestroyForPlayer(Player *target) const void Object::BuildMovementUpdate(ByteBuffer * data, uint8 updateFlags) const { - uint32 moveFlags = MOVEFLAG_NONE; - *data << uint8(updateFlags); // update flags + // 0x20 if (updateFlags & UPDATEFLAG_LIVING) { - switch (GetTypeId()) + Unit *unit = ((Unit*)this); + if (GetTypeId() == TYPEID_PLAYER) { - case TYPEID_UNIT: - { - moveFlags = ((Unit*)this)->GetUnitMovementFlags(); - moveFlags &= ~MOVEFLAG_ONTRANSPORT; - moveFlags &= ~MOVEFLAG_SPLINE_ENABLED; - } - break; - case TYPEID_PLAYER: - { - moveFlags = ((Player*)this)->GetUnitMovementFlags(); - - if (((Player*)this)->GetTransport()) - moveFlags |= MOVEFLAG_ONTRANSPORT; - else - moveFlags &= ~MOVEFLAG_ONTRANSPORT; - - // remove unknown, unused etc flags for now - moveFlags &= ~MOVEFLAG_SPLINE_ENABLED; // will be set manually - - if (((Player*)this)->isInFlight()) - { - WPAssert(((Player*)this)->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE); - moveFlags = (MOVEFLAG_FORWARD | MOVEFLAG_SPLINE_ENABLED); - } - } - break; + Player *player = ((Player*)unit); + if(player->GetTransport()) + player->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT); + else + player->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT); } - *data << uint32(moveFlags); // movement flags - *data << uint8(0); // movemoveFlags - *data << uint32(WorldTimer::getMSTime()); // time (in milliseconds) + // Update movement info time + unit->m_movementInfo.UpdateTime(WorldTimer::getMSTime()); + // Write movement info + //unit->m_movementInfo.Write(*data); + + *data << uint32(unit->m_movementInfo.GetMovementFlags()); // movement flags + *data << uint8(unit->m_movementInfo.GetMovementFlags2()); // movemoveFlags + *data << uint32(WorldTimer::getMSTime()); // time (in milliseconds) } // 0x40 @@ -323,140 +308,22 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint8 updateFlags) const // 0x20 if (updateFlags & UPDATEFLAG_LIVING) { - // 0x00000200 - if (moveFlags & MOVEFLAG_ONTRANSPORT) - { - if (GetTypeId() == TYPEID_PLAYER) - { - *data << (uint64)((Player*)this)->GetTransport()->GetGUID(); - *data << (float)((Player*)this)->GetTransOffsetX(); - *data << (float)((Player*)this)->GetTransOffsetY(); - *data << (float)((Player*)this)->GetTransOffsetZ(); - *data << (float)((Player*)this)->GetTransOffsetO(); - *data << (uint32)((Player*)this)->GetTransTime(); - } - //TrinIty currently not have support for other than player on transport - } - - // 0x02200000 - if (moveFlags & (MOVEFLAG_SWIMMING | SPLINEFLAG_FLYINGING2)) - { - if (GetTypeId() == TYPEID_PLAYER) - *data << (float)((Player*)this)->m_movementInfo.s_pitch; - else - *data << float(0); // is't part of movement packet, we must store and send it... - } - - if (GetTypeId() == TYPEID_PLAYER) - *data << (uint32)((Player*)this)->m_movementInfo.GetFallTime(); - else - *data << uint32(0); // last fall time - - // 0x00001000 - if (moveFlags & MOVEFLAG_FALLING) - { - if (GetTypeId() == TYPEID_PLAYER) - { - *data << float(((Player*)this)->m_movementInfo.j_velocity); - *data << float(((Player*)this)->m_movementInfo.j_sinAngle); - *data << float(((Player*)this)->m_movementInfo.j_cosAngle); - *data << float(((Player*)this)->m_movementInfo.j_xyspeed); - } - else - { - *data << float(0); - *data << float(0); - *data << float(0); - *data << float(0); - } - } - - // 0x04000000 - if (moveFlags & MOVEFLAG_SPLINE_ELEVATION) - { - if (GetTypeId() == TYPEID_PLAYER) - *data << float(((Player*)this)->m_movementInfo.u_unk1); - else - *data << float(0); - } + Unit *unit = ((Unit*)this); + unit->m_movementInfo.Write(*data, false); // Unit speeds - *data << ((Unit*)this)->GetSpeed(MOVE_WALK); - *data << ((Unit*)this)->GetSpeed(MOVE_RUN); - *data << ((Unit*)this)->GetSpeed(MOVE_SWIM_BACK); - *data << ((Unit*)this)->GetSpeed(MOVE_SWIM); - *data << ((Unit*)this)->GetSpeed(MOVE_RUN_BACK); - *data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT); - *data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT_BACK); - *data << ((Unit*)this)->GetSpeed(MOVE_TURN_RATE); + *data << float(unit->GetSpeed(MOVE_WALK)); + *data << float(unit->GetSpeed(MOVE_RUN)); + *data << float(unit->GetSpeed(MOVE_SWIM_BACK)); + *data << float(unit->GetSpeed(MOVE_SWIM)); + *data << float(unit->GetSpeed(MOVE_RUN_BACK)); + *data << float(unit->GetSpeed(MOVE_FLIGHT)); + *data << float(unit->GetSpeed(MOVE_FLIGHT_BACK)); + *data << float(unit->GetSpeed(MOVE_TURN_RATE)); // 0x08000000 - if (moveFlags & MOVEFLAG_SPLINE_ENABLED) - { - if (GetTypeId() != TYPEID_PLAYER) - { - sLog.outDebug("BuildMovementUpdate: MOVEFLAG_SPLINE_ENABLED for non-player"); - return; - } - - if (!((Player*)this)->isInFlight()) - { - sLog.outDebug("BuildMovementUpdate: MOVEFLAG_SPLINE_ENABLED but not in flight"); - return; - } - - WPAssert(((Player*)this)->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE); - - FlightPathMovementGenerator *fmg = (FlightPathMovementGenerator*)(((Player*)this)->GetMotionMaster()->top()); - - uint32 flags3 = 0x00000300; - - *data << uint32(flags3); // splines flag? - - if (flags3 & 0x10000) // probably x,y,z coords there - { - *data << (float)0; - *data << (float)0; - *data << (float)0; - } - - if (flags3 & 0x20000) // probably guid there - { - *data << uint64(0); - } - - if (flags3 & 0x40000) // may be orientation - { - *data << (float)0; - } - - Path &path = fmg->GetPath(); - - float x, y, z; - ((Player*)this)->GetPosition(x, y, z); - - uint32 inflighttime = uint32(path.GetPassedLength(fmg->GetCurrentNode(), x, y, z) * 32); - uint32 traveltime = uint32(path.GetTotalLength() * 32); - - *data << uint32(inflighttime); // passed move time? - *data << uint32(traveltime); // full move time? - *data << uint32(0); // ticks count? - - uint32 poscount = uint32(path.Size()); - - *data << uint32(poscount); // points count - - for (uint32 i = 0; i < poscount; ++i) - { - *data << float(path.GetNodes()[i].x); - *data << float(path.GetNodes()[i].y); - *data << float(path.GetNodes()[i].z); - } - - *data << float(path.GetNodes()[poscount-1].x); - *data << float(path.GetNodes()[poscount-1].y); - *data << float(path.GetNodes()[poscount-1].z); - } + if (unit->m_movementInfo.GetMovementFlags() & MOVEFLAG_SPLINE_ENABLED) + Movement::PacketBuilder::WriteCreate(*unit->movespline, *data); } // 0x8 @@ -507,9 +374,12 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint8 updateFlags) const } // 0x4 - if (updateFlags & UPDATEFLAG_HAS_ATTACKING_TARGET) + if (updateFlags & UPDATEFLAG_HAS_ATTACKING_TARGET) // packed guid (current target guid) { - *data << uint8(0); // packed guid (probably target guid) + if (((Unit*)this)->getVictim()) + *data << ((Unit*)this)->getVictim()->GetPackGUID(); + else + data->appendPackGUID(0); } // 0x2 @@ -1092,6 +962,45 @@ void WorldObject::_Create(uint32 guidlow, HighGuid guidhigh, uint32 mapid) m_mapId = mapid; } +void WorldObject::Relocate(Position pos) +{ + m_positionX = pos.x; + m_positionY = pos.y; + m_positionZ = pos.z; + m_orientation = pos.o; + + if(isType(TYPEMASK_UNIT)) + ((Unit*)this)->m_movementInfo.ChangePosition(pos.x, pos.y, pos.z, orientation); +} + +void WorldObject::Relocate(float x, float y, float z, float orientation) +{ + m_positionX = x; + m_positionY = y; + m_positionZ = z; + m_orientation = orientation; + + if(isType(TYPEMASK_UNIT)) + ((Unit*)this)->m_movementInfo.ChangePosition(x, y, z, orientation); +} + +void WorldObject::Relocate(float x, float y, float z) +{ + m_positionX = x; + m_positionY = y; + m_positionZ = z; + + if(isType(TYPEMASK_UNIT)) + ((Unit*)this)->m_movementInfo.ChangePosition(x, y, z, GetOrientation()); +} + +void WorldObject::SetOrientation(float orientation) +{ + m_orientation = orientation; + + if(isType(TYPEMASK_UNIT)) + ((Unit*)this)->m_movementInfo.ChangeOrientation(orientation); +} uint32 WorldObject::GetZoneId() const { @@ -1384,9 +1293,9 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const { // non fly unit don't must be in air // non swim unit must be at ground (mostly speedup, because it don't must be in water and water level check less fast - if (!((Creature const*)this)->canFly()) + if (!((Creature const*)this)->CanFly()) { - bool CanSwim = ((Creature const*)this)->canSwim(); + bool CanSwim = ((Creature const*)this)->CanSwim(); float ground_z = z; float max_z = CanSwim ? GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK)) diff --git a/src/game/Object.h b/src/game/Object.h index 70acc8501..c37bebde5 100755 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -395,25 +395,11 @@ class TRINITY_DLL_SPEC WorldObject : public Object, public WorldLocation void _Create(uint32 guidlow, HighGuid guidhigh, uint32 mapid); - void Relocate(float x, float y, float z, float orientation) - { - m_positionX = x; - m_positionY = y; - m_positionZ = z; - m_orientation = orientation; - } - - void Relocate(float x, float y, float z) - { - m_positionX = x; - m_positionY = y; - m_positionZ = z; - } - - void Relocate(Position pos) - { m_positionX = pos.x; m_positionY = pos.y; m_positionZ = pos.z; m_orientation = pos.o; } + void Relocate(float x, float y, float z, float orientation); + void Relocate(float x, float y, float z); + void Relocate(Position pos); - void SetOrientation(float orientation) { m_orientation = orientation; } + void SetOrientation(float orientation); float GetPositionX() const { return m_positionX; } float GetPositionY() const { return m_positionY; } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 6a0b835c4..df6d45b59 100755 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3689,23 +3689,9 @@ void ObjectMgr::LoadEventScripts() // Load all possible script entries from gameobjects for (uint32 i = 1; i < sGOStorage.MaxEntry; ++i) { - GameObjectInfo const * goInfo = sGOStorage.LookupEntry(i); - if (goInfo) - { - switch (goInfo->type) - { - case GAMEOBJECT_TYPE_GOOBER: - if (goInfo->goober.eventId) - evt_scripts.insert(goInfo->goober.eventId); - break; - case GAMEOBJECT_TYPE_CHEST: - if (goInfo->chest.eventId) - evt_scripts.insert(goInfo->chest.eventId); - break; - default: - break; - } - } + if (GameObjectInfo const * goInfo = sGOStorage.LookupEntry(i)) + if (uint32 eventId = goInfo->GetEventScriptId()) + evt_scripts.insert(eventId); } // Load all possible script entries from spells @@ -3725,6 +3711,20 @@ void ObjectMgr::LoadEventScripts() } } + for(size_t path_idx = 0; path_idx < sTaxiPathNodesByPath.size(); ++path_idx) + { + for(size_t node_idx = 0; node_idx < sTaxiPathNodesByPath[path_idx].size(); ++node_idx) + { + TaxiPathNodeEntry const& node = sTaxiPathNodesByPath[path_idx][node_idx]; + + if (node.arrivalEventID) + evt_scripts.insert(node.arrivalEventID); + + if (node.departureEventID) + evt_scripts.insert(node.departureEventID); + } + } + // Then check if all scripts are in above list of possible script entries for (ScriptMapMap::const_iterator itr = sEventScripts.begin(); itr != sEventScripts.end(); ++itr) { @@ -4319,33 +4319,44 @@ void ObjectMgr::LoadAreaTriggerScripts() sLog.outString(">> Loaded %u areatrigger scripts", count); } -uint32 ObjectMgr::GetNearestTaxiNode(float x, float y, float z, uint32 mapid) +uint32 ObjectMgr:: GetNearestTaxiNode(float x, float y, float z, uint32 mapid, uint32 team) { bool found = false; float dist; uint32 id = 0; - for (uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) + for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) { TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i); - if (node && node->map_id == mapid) + if (!node || node->map_id != mapid) + continue; + + uint32 MountCreatureID = team == ALLIANCE ? node->alliance_mount_type : node->horde_mount_type; + if (!MountCreatureID) + continue; + + uint8 field = (uint8)((i - 1) / 32); + uint32 submask = 1<<((i-1)%32); + + // skip not taxi network nodes + if ((sTaxiNodesMask[field] & submask)==0) + continue; + + float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z); + if (found) { - float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z); - if (found) - { - if (dist2 < dist) - { - dist = dist2; - id = i; - } - } - else + if(dist2 < dist) { - found = true; dist = dist2; id = i; } } + else + { + found = true; + dist = dist2; + id = i; + } } return id; @@ -4411,46 +4422,6 @@ uint16 ObjectMgr::GetTaxiMount(uint32 id, uint32 team) return mount_id; } -void ObjectMgr::GetTaxiPathNodes(uint32 path, Path &pathnodes, std::vector& mapIds) -{ - if (path >= sTaxiPathNodesByPath.size()) - return; - - TaxiPathNodeList& nodeList = sTaxiPathNodesByPath[path]; - - pathnodes.Resize(nodeList.size()); - mapIds.resize(nodeList.size()); - - for (size_t i = 0; i < nodeList.size(); ++i) - { - pathnodes[ i ].x = nodeList[i].x; - pathnodes[ i ].y = nodeList[i].y; - pathnodes[ i ].z = nodeList[i].z; - - mapIds[i] = nodeList[i].mapid; - } -} - -void ObjectMgr::GetTransportPathNodes(uint32 path, TransportPath &pathnodes) -{ - if (path >= sTaxiPathNodesByPath.size()) - return; - - TaxiPathNodeList& nodeList = sTaxiPathNodesByPath[path]; - - pathnodes.Resize(nodeList.size()); - - for (size_t i = 0; i < nodeList.size(); ++i) - { - pathnodes[ i ].mapid = nodeList[i].mapid; - pathnodes[ i ].x = nodeList[i].x; - pathnodes[ i ].y = nodeList[i].y; - pathnodes[ i ].z = nodeList[i].z; - pathnodes[ i ].actionFlag = nodeList[i].actionFlag; - pathnodes[ i ].delay = nodeList[i].delay; - } -} - void ObjectMgr::LoadGraveyardZones() { mGraveYardMap.clear(); // need for reload case diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 4aad2613e..1c997c082 100755 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -30,7 +30,6 @@ #include "GameObject.h" #include "Corpse.h" #include "QuestDef.h" -#include "Path.h" #include "ItemPrototype.h" #include "NPCHandler.h" #include "Database/DatabaseEnv.h" @@ -58,8 +57,6 @@ extern SQLStorage sInstanceTemplate; class Group; class Guild; class ArenaTeam; -class Path; -class TransportPath; class Item; struct GameTele @@ -381,11 +378,9 @@ class ObjectMgr uint32 GetPlayerAccountIdByGUID(const uint64 &guid) const; uint32 GetPlayerAccountIdByPlayerName(const std::string& name) const; - uint32 GetNearestTaxiNode(float x, float y, float z, uint32 mapid); + uint32 GetNearestTaxiNode(float x, float y, float z, uint32 mapid, uint32 team); void GetTaxiPath(uint32 source, uint32 destination, uint32 &path, uint32 &cost); uint16 GetTaxiMount(uint32 id, uint32 team); - void GetTaxiPathNodes(uint32 path, Path &pathnodes, std::vector& mapIds); - void GetTransportPathNodes(uint32 path, TransportPath &pathnodes); Quest const* GetQuestTemplate(uint32 quest_id) const { diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 52ed49c2a..f49379ca8 100755 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -737,15 +737,15 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemNameQueryOpcode }, - /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, - /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, + /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, + /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleChangePlayerNameOpcode }, - /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, - /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiNextDestinationOpcode }, - /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes }, - /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, - /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, - /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRaidInfoOpcode }, + /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, + /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveSplineDoneOpcode }, + /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes }, + /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, + /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, + /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRaidInfoOpcode}, /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleMoveTimeSkippedOpcode }, /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleFeatherFallAck }, /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveWaterWalkAck }, diff --git a/src/game/Path.h b/src/game/Path.h index 99b32708e..ac16c5436 100755 --- a/src/game/Path.h +++ b/src/game/Path.h @@ -24,65 +24,63 @@ #include "Common.h" #include +struct SimplePathNode +{ + float x,y,z; +}; + +template class Path { public: - struct PathNode - { - float x,y,z; - }; + size_t size() const { return i_nodes.size(); } + bool empty() const { return i_nodes.empty(); } + void resize(unsigned int sz) { i_nodes.resize(sz); } + void clear() { i_nodes.clear(); } + void erase(uint32 idx) { i_nodes.erase(i_nodes.begin()+idx); } - void SetLength(const unsigned int sz) - { - i_nodes.resize(sz); - } - - unsigned int Size() const { return i_nodes.size(); } - bool Empty() const { return i_nodes.empty(); } - void Resize(unsigned int sz) { i_nodes.resize(sz); } - void Clear(void) { i_nodes.clear(); } - PathNode const* GetNodes(uint32 start = 0) const { return &i_nodes[start]; } - float GetTotalLength() const { return GetTotalLength(0,Size()); } float GetTotalLength(uint32 start, uint32 end) const { - float len = 0, xd, yd, zd; + float len = 0.0f; for (unsigned int idx=start+1; idx < end; ++idx) { - xd = i_nodes[ idx ].x - i_nodes[ idx-1 ].x; - yd = i_nodes[ idx ].y - i_nodes[ idx-1 ].y; - zd = i_nodes[ idx ].z - i_nodes[ idx-1 ].z; + PathNode const& node = i_nodes[idx]; + PathNode const& prev = i_nodes[idx-1]; + float xd = node.x - prev.x; + float yd = node.y - prev.y; + float zd = node.z - prev.z; len += sqrtf(xd*xd + yd*yd + zd*zd); } return len; } - float GetPassedLength(uint32 curnode, float x, float y, float z) + float GetTotalLength() const { return GetTotalLength(0,size()); } + + float GetPassedLength(uint32 curnode, float x, float y, float z) const { - float len = 0, xd, yd, zd; - for (unsigned int idx=1; idx < curnode; ++idx) - { - xd = i_nodes[ idx ].x - i_nodes[ idx-1 ].x; - yd = i_nodes[ idx ].y - i_nodes[ idx-1 ].y; - zd = i_nodes[ idx ].z - i_nodes[ idx-1 ].z; - len += sqrtf(xd*xd + yd*yd + zd*zd); - } + float len = GetTotalLength(0,curnode); if (curnode > 0) { - xd = x - i_nodes[curnode-1].x; - yd = y - i_nodes[curnode-1].y; - zd = z - i_nodes[curnode-1].z; + PathNode const& node = i_nodes[curnode-1]; + float xd = x - node.x; + float yd = y - node.y; + float zd = z - node.z; len += sqrtf(xd*xd + yd*yd + zd*zd); } return len; } - PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } - const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } + PathNode& operator[](size_t idx) { return i_nodes[idx]; } + PathNode const& operator[](size_t idx) const { return i_nodes[idx]; } + + void set(size_t idx, PathElem elem) { i_nodes[idx] = elem; } protected: - std::vector i_nodes; + std::vector i_nodes; }; -#endif +typedef Path SimplePath; + +#endif diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 8de81250a..95026b42f 100755 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -269,7 +269,7 @@ void PetAI::UpdateAI(const uint32 diff) if (!me->GetCharmInfo()) return; - if (!m_creature->hasUnitState(UNIT_STAT_CASTING)) + if (!me->IsNonMeleeSpellCasted(false)) { //Autocast for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); i++) @@ -394,7 +394,7 @@ void ImpAI::UpdateAI(const uint32 diff) if (!me->GetCharmInfo()) return; - if (!m_creature->hasUnitState(UNIT_STAT_CASTING)) + if (!me->IsNonMeleeSpellCasted(false)) { //Autocast for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); i++) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 9fc99b0f0..ba2ae20d0 100755 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -173,7 +173,7 @@ void PlayerTaxi::LoadTaxiMask(const char* data) for (iter = tokens.begin(), index = 0; (index < TaxiMaskSize) && (iter != tokens.end()); ++iter, ++index) { - // load and set bits only for existed taxi nodes + // load and set bits only for existing taxi nodes m_taximask[index] = sTaxiNodesMask[index] & uint32(atol((*iter).c_str())); } } @@ -182,12 +182,12 @@ void PlayerTaxi::AppendTaximaskTo(ByteBuffer& data, bool all) { if (all) { - for (uint8 i=0; i const& nodes, uint32 mount_i return true; } +void Player::ContinueTaxiFlight() +{ + if (uint32 sourceNode = m_taxi.GetTaxiSource()) + { + + sLog.outDebug("WORLD: Restart character %u taxi flight", GetGUIDLow()); + + uint32 MountId = objmgr.GetTaxiMount(sourceNode, GetTeam()); + uint32 path = m_taxi.GetCurrentTaxiPath(); + + // search appropriate start path node + uint32 startNode = 0; + + TaxiPathNodeList const& nodeList = sTaxiPathNodesByPath[path]; + + float distPrev = MAP_SIZE*MAP_SIZE; + float distNext = + (nodeList[0].x-GetPositionX())*(nodeList[0].x-GetPositionX())+ + (nodeList[0].y-GetPositionY())*(nodeList[0].y-GetPositionY())+ + (nodeList[0].z-GetPositionZ())*(nodeList[0].z-GetPositionZ()); + + for (uint32 i = 1; i < nodeList.size(); ++i) + { + TaxiPathNodeEntry const& node = nodeList[i]; + TaxiPathNodeEntry const& prevNode = nodeList[i-1]; + + // skip nodes at another map + if (node.mapid != GetMapId()) + continue; + + distPrev = distNext; + + distNext = + (node.x-GetPositionX())*(node.x-GetPositionX())+ + (node.y-GetPositionY())*(node.y-GetPositionY())+ + (node.z-GetPositionZ())*(node.z-GetPositionZ()); + + float distNodes = + (node.x-prevNode.x)*(node.x-prevNode.x)+ + (node.y-prevNode.y)*(node.y-prevNode.y)+ + (node.z-prevNode.z)*(node.z-prevNode.z); + + if (distNext + distPrev < distNodes) + { + startNode = i; + break; + } + } + + m_session->SendDoFlight(MountId, path, startNode); + } +} + void Player::CleanupAfterTaxiFlight() { m_taxi.ClearTaxiDestinations(); // not destinations, clear source node @@ -18460,7 +18515,7 @@ bool Player::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList, bool if (!viewPoint || !HasFarsightVision()) viewPoint = u; // different visible distance checks - if (isInFlight()) // what see player in flight + if (IsTaxiFlying()) // what see player in flight { if (!viewPoint->IsWithinDistInMap(u, _map.GetVisibilityDistance() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), is3dDistance)) return false; @@ -18699,8 +18754,6 @@ void Player::SendInitialVisiblePackets(Unit* target) SendAuraDurationsForTarget(target); if (target->isAlive()) { - if (target->GetMotionMaster()->GetCurrentMovementGeneratorType() != IDLE_MOTION_TYPE) - target->SendMonsterMoveWithSpeedToCurrentDestination(this); if (target->hasUnitState(UNIT_STAT_MELEE_ATTACKING) && target->getVictim()) target->SendMeleeAttackStart(target->getVictim()); } @@ -18895,8 +18948,8 @@ void Player::SendInitialPacketsBeforeAddToMap() GetSession()->SendPacket(&data); // set fly flag if in fly form or taxi flight to prevent visually drop at ground in showup moment - if (HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || isInFlight()) - AddUnitMovementFlag(SPLINEFLAG_FLYINGING2); + if (IsFreeFlying() || IsTaxiFlying()) + m_movementInfo.AddMovementFlag(MOVEFLAG_FLYING); } void Player::SendInitialPacketsAfterAddToMap() @@ -19362,7 +19415,7 @@ void Player::SummonIfPossible(bool agree) return; // stop taxi flight at summon - if (isInFlight()) + if (IsTaxiFlying()) { GetMotionMaster()->MovementExpired(); CleanupAfterTaxiFlight(); @@ -20333,7 +20386,7 @@ void Player::UpdateUnderwaterState(Map* m, float x, float y, float z) } // Allow travel in dark water on taxi or transport - if ((liquid_status.type & MAP_LIQUID_TYPE_DARK_WATER) && !isInFlight() && !GetTransport()) + if ((liquid_status.type & MAP_LIQUID_TYPE_DARK_WATER) && !IsTaxiFlying() && !GetTransport()) m_MirrorTimerFlags |= UNDERWATER_INDARKWATER; else m_MirrorTimerFlags &= ~UNDERWATER_INDARKWATER; @@ -20569,17 +20622,13 @@ bool Player::isTotalImmunity() void Player::BuildTeleportAckMsg(WorldPacket *data, float x, float y, float z, float ang) const { + MovementInfo mi = m_movementInfo; + mi.ChangePosition(x, y, z, ang); + data->Initialize(MSG_MOVE_TELEPORT_ACK, 41); *data << GetPackGUID(); *data << uint32(0); // this value increments every time - *data << uint32(GetUnitMovementFlags()); // movement flags - *data << uint8(0); // 2.3.0 - *data << uint32(WorldTimer::getMSTime()); // time - *data << x; - *data << y; - *data << z; - *data << ang; - *data << uint32(0); + *data << mi; } void Player::ResetTimeSync() diff --git a/src/game/Player.h b/src/game/Player.h index ae39cbf97..e7c6acb16 100755 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -984,6 +984,7 @@ class TRINITY_DLL_SPEC Player : public Unit PlayerTaxi m_taxi; void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(),getLevel()); } bool ActivateTaxiPathTo(std::vector const& nodes, uint32 mount_id = 0 , Creature* npc = NULL); + void ContinueTaxiFlight(); void CleanupAfterTaxiFlight(); bool isAcceptWhispers() const { return m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS; } @@ -2025,7 +2026,7 @@ class TRINITY_DLL_SPEC Player : public Unit /*********************************************************/ /*** VARIOUS SYSTEMS ***/ /*********************************************************/ - MovementInfo m_movementInfo; + uint32 m_lastFallTime; float m_lastFallZ; void SetFallInformation(uint32 time, float z) @@ -2036,12 +2037,12 @@ class TRINITY_DLL_SPEC Player : public Unit void BuildTeleportAckMsg( WorldPacket *data, float x, float y, float z, float ang) const; - bool isMoving() const { return HasUnitMovementFlag(MOVEFLAG_MOVING); } - bool isTurning() const { return HasUnitMovementFlag(MOVEFLAG_TURNING); } - bool isMovingOrTurning() const { return HasUnitMovementFlag(MOVEFLAG_TURNING | MOVEFLAG_MOVING); } + bool isMoving() const { return m_movementInfo.HasMovementFlag(movementFlagsMask); } + bool isMovingOrTurning() const { return m_movementInfo.HasMovementFlag(movementOrTurningFlagsMask); } - bool CanFly() const { return HasUnitMovementFlag(MOVEFLAG_CAN_FLY); } - bool IsFlying() const { return HasUnitMovementFlag(SPLINEFLAG_FLYINGING2); } + bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_CAN_FLY); } + bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_FLYING); } + bool IsFreeFlying() const { return HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || HasAuraType(SPELL_AURA_FLY); } void HandleDrowning(uint32 time_diff); void HandleFallDamage(MovementInfo& movementInfo); diff --git a/src/game/PointMovementGenerator.cpp b/src/game/PointMovementGenerator.cpp index 757b7cbce..c531ac568 100755 --- a/src/game/PointMovementGenerator.cpp +++ b/src/game/PointMovementGenerator.cpp @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,21 +8,22 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "PointMovementGenerator.h" #include "Errors.h" #include "Creature.h" #include "CreatureAI.h" -#include "MapManager.h" -#include "DestinationHolderImp.h" +#include "TemporarySummon.h" #include "World.h" +#include "movement/MoveSplineInit.h" +#include "movement/MoveSpline.h" //----- Point Movement Generator template @@ -33,88 +32,103 @@ void PointMovementGenerator::Initialize(T &unit) if (!unit.IsStopped()) unit.StopMoving(); - unit.addUnitState(UNIT_STAT_ROAMING); - - Traveller traveller(unit); - i_destinationHolder.SetDestination(traveller,i_x,i_y,i_z); + unit.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); + Movement::MoveSplineInit init(unit); + init.MoveTo(i_x, i_y, i_z); + init.Launch(); } template -bool PointMovementGenerator::Update(T &unit, const uint32 &diff) +void PointMovementGenerator::Finalize(T &unit) { - if (!&unit) - return false; - - if (unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED)) - { - if (unit.hasUnitState(UNIT_STAT_CHARGING)) - return false; - else - return true; - } + unit.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); - Traveller traveller(unit); + if (unit.movespline->Finalized()) + MovementInform(unit); +} - if (i_destinationHolder.UpdateTraveller(traveller, diff, false)) - { - //if (!IsActive(unit)) // force stop processing (movement can move out active zone with cleanup movegens list) - // return true; // not expire now, but already lost - } +template +void PointMovementGenerator::Interrupt(T &unit) +{ + unit.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); +} - if (i_destinationHolder.HasArrived()) - { - unit.clearUnitState(UNIT_STAT_MOVE); - return false; - } +template +void PointMovementGenerator::Reset(T &unit) +{ + if (!unit.IsStopped()) + unit.StopMoving(); - return true; + unit.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); } template -void PointMovementGenerator:: Finalize(T &unit) +bool PointMovementGenerator::Update(T &unit, const uint32 &diff) { - if (unit.hasUnitState(UNIT_STAT_CHARGING)) - unit.clearUnitState(UNIT_STAT_CHARGING | UNIT_STAT_JUMPING); + if(!&unit) + return false; - unit.clearUnitState(UNIT_STAT_ROAMING); + if(unit.hasUnitState(UNIT_STAT_CAN_NOT_MOVE)) + { + unit.clearUnitState(UNIT_STAT_ROAMING_MOVE); + return true; + } - if (i_destinationHolder.HasArrived()) // without this crash! - MovementInform(unit); + unit.addUnitState(UNIT_STAT_ROAMING_MOVE); + return !unit.movespline->Finalized(); } -template -void PointMovementGenerator::MovementInform(T &unit) +template<> +void PointMovementGenerator::MovementInform(Player&) { } template <> void PointMovementGenerator::MovementInform(Creature &unit) { - if (id == EVENT_FALL_GROUND) - { - unit.setDeathState(JUST_DIED); - //TODO: SKY FIX TEMP!!! - unit.SetFlying(true); - //unit.AddUnitMovementFlag(SPLINEFLAG_FLYINGING2); - } - unit.AI()->MovementInform(POINT_MOTION_TYPE, id); + if (unit.AI()) + unit.AI()->MovementInform(POINT_MOTION_TYPE, id); } template void PointMovementGenerator::Initialize(Player&); -template bool PointMovementGenerator::Update(Player &, const uint32 &diff); -template void PointMovementGenerator::MovementInform(Player&); -template void PointMovementGenerator::Finalize(Player&); - template void PointMovementGenerator::Initialize(Creature&); -template bool PointMovementGenerator::Update(Creature&, const uint32 &diff); +template void PointMovementGenerator::Finalize(Player&); template void PointMovementGenerator::Finalize(Creature&); +template void PointMovementGenerator::Interrupt(Player&); +template void PointMovementGenerator::Interrupt(Creature&); +template void PointMovementGenerator::Reset(Player&); +template void PointMovementGenerator::Reset(Creature&); +template bool PointMovementGenerator::Update(Player &, const uint32 &diff); +template bool PointMovementGenerator::Update(Creature&, const uint32 &diff); void AssistanceMovementGenerator::Finalize(Unit &unit) { - unit.clearUnitState(UNIT_STAT_ROAMING); + unit.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); ((Creature*)&unit)->SetNoCallAssistance(false); ((Creature*)&unit)->CallAssistance(); if (unit.isAlive()) unit.GetMotionMaster()->MoveSeekAssistanceDistract(sWorld.getConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY)); } + +bool EffectMovementGenerator::Update(Unit &unit, const uint32 &) +{ + return !unit.movespline->Finalized(); +} + +void EffectMovementGenerator::Finalize(Unit &unit) +{ + if (unit.GetTypeId() != TYPEID_UNIT) + return; + + if (((Creature&)unit).AI() && unit.movespline->Finalized()) + ((Creature&)unit).AI()->MovementInform(EFFECT_MOTION_TYPE, m_Id); + // Need restore previous movement since we have no proper states system + if (unit.isAlive() && !unit.hasUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_FLEEING)) + { + if (Unit * victim = unit.getVictim()) + unit.GetMotionMaster()->MoveChase(victim); + else + unit.GetMotionMaster()->Initialize(); + } +} diff --git a/src/game/PointMovementGenerator.h b/src/game/PointMovementGenerator.h index 6ce65b522..37e64aa19 100755 --- a/src/game/PointMovementGenerator.h +++ b/src/game/PointMovementGenerator.h @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,21 +8,20 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITY_POINTMOVEMENTGENERATOR_H -#define TRINITY_POINTMOVEMENTGENERATOR_H +#ifndef MANGOS_POINTMOVEMENTGENERATOR_H +#define MANGOS_POINTMOVEMENTGENERATOR_H #include "MovementGenerator.h" -#include "DestinationHolder.h" -#include "Traveller.h" #include "FollowerReference.h" +#include "Creature.h" template class TRINITY_DLL_SPEC PointMovementGenerator @@ -32,24 +29,22 @@ class TRINITY_DLL_SPEC PointMovementGenerator { public: PointMovementGenerator(uint32 _id, float _x, float _y, float _z) : id(_id), - i_x(_x), i_y(_y), i_z(_z), i_nextMoveTime(0), arrived(false) {} + i_x(_x), i_y(_y), i_z(_z) {} void Initialize(T &); - void Finalize(T &unit); - void Reset(T &unit){unit.StopMoving();} + void Finalize(T &); + void Interrupt(T &); + void Reset(T &unit); bool Update(T &, const uint32 &diff); void MovementInform(T &); - MovementGeneratorType GetMovementGeneratorType() { return POINT_MOTION_TYPE; } + MovementGeneratorType GetMovementGeneratorType() const { return POINT_MOTION_TYPE; } bool GetDestination(float& x, float& y, float& z) const { x=i_x; y=i_y; z=i_z; return true; } private: - TimeTracker i_nextMoveTime; - float i_x,i_y,i_z; uint32 id; - DestinationHolder< Traveller > i_destinationHolder; - bool arrived; + float i_x,i_y,i_z; }; class TRINITY_DLL_SPEC AssistanceMovementGenerator @@ -59,9 +54,23 @@ class TRINITY_DLL_SPEC AssistanceMovementGenerator AssistanceMovementGenerator(float _x, float _y, float _z) : PointMovementGenerator(0, _x, _y, _z) {} - MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_MOTION_TYPE; } + MovementGeneratorType GetMovementGeneratorType() const { return ASSISTANCE_MOTION_TYPE; } void Finalize(Unit &); }; -#endif +// Does almost nothing - just doesn't allows previous movegen interrupt current effect. Can be reused for charge effect +class EffectMovementGenerator : public MovementGenerator +{ + public: + explicit EffectMovementGenerator(uint32 Id) : m_Id(Id) {} + void Initialize(Unit &) {} + void Finalize(Unit &unit); + void Interrupt(Unit &) {} + void Reset(Unit &) {} + bool Update(Unit &u, const uint32 &); + MovementGeneratorType GetMovementGeneratorType() const { return EFFECT_MOTION_TYPE; } + private: + uint32 m_Id; +}; +#endif diff --git a/src/game/RandomMovementGenerator.cpp b/src/game/RandomMovementGenerator.cpp index 2975883e0..e23a29296 100755 --- a/src/game/RandomMovementGenerator.cpp +++ b/src/game/RandomMovementGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 MaNGOS + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,24 +19,26 @@ #include "Creature.h" #include "MapManager.h" #include "RandomMovementGenerator.h" -#include "DestinationHolderImp.h" #include "Map.h" #include "Util.h" +#include "movement/MoveSplineInit.h" +#include "movement/MoveSpline.h" template<> -void RandomMovementGenerator::_setRandomLocation(Creature &creature) +void +RandomMovementGenerator::_setRandomLocation(Creature &creature) { float respX, respY, respZ, respO, currZ, destX, destY, destZ, wander_distance, travelDistZ; creature.GetRespawnCoord(respX, respY, respZ, &respO, &wander_distance); currZ = creature.GetPositionZ(); - Map const* map = creature.GetBaseMap(); + Map const* map = creature.GetMap(); // For 2D/3D system selection //bool is_land_ok = creature.CanWalk(); // not used? //bool is_water_ok = creature.CanSwim(); // not used? - bool is_air_ok = creature.canFly(); + bool is_air_ok = creature.CanFly(); const float angle = rand_norm() * (M_PI*2.0f); const float range = rand_norm() * wander_distance; @@ -90,23 +92,17 @@ void RandomMovementGenerator::_setRandomLocation(Creature &creature) } } - Traveller traveller(creature); - - creature.SetOrientation(creature.GetAngle(destX, destY)); - i_destinationHolder.SetDestination(traveller, destX, destY, destZ); - creature.addUnitState(UNIT_STAT_ROAMING); - if (is_air_ok) - { - i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); - creature.AddUnitMovementFlag(SPLINEFLAG_FLYINGING2); - } - //else if (is_water_ok) // Swimming mode to be done with more than this check + i_nextMoveTime.Reset(0); else - { - i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime() + urand(500, 10000)); - creature.AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); - } + i_nextMoveTime.Reset(urand(500, 10000)); + + creature.addUnitState(UNIT_STAT_ROAMING_MOVE); + + Movement::MoveSplineInit init(creature); + init.MoveTo(destX, destY, destZ); + init.SetWalk(true); + init.Launch(); } template<> @@ -115,11 +111,7 @@ void RandomMovementGenerator::Initialize(Creature &creature) if (!creature.isAlive()) return; - if (creature.canFly()) - creature.AddUnitMovementFlag(SPLINEFLAG_FLYINGING2); - else - creature.AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); - + creature.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); _setRandomLocation(creature); } @@ -129,42 +121,48 @@ void RandomMovementGenerator::Reset(Creature &creature) Initialize(creature); } +template<> +void RandomMovementGenerator::Interrupt(Creature &creature) +{ + creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); + creature.SetWalk(false); +} + +template<> +void RandomMovementGenerator::Finalize(Creature &creature) +{ + creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); + creature.SetWalk(false); +} + template<> bool RandomMovementGenerator::Update(Creature &creature, const uint32 &diff) { - if (creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED | UNIT_STAT_DIED)) + if (creature.hasUnitState(UNIT_STAT_NOT_MOVE)) { - i_nextMoveTime.Update(i_nextMoveTime.GetExpiry()); // Expire the timer - creature.clearUnitState(UNIT_STAT_ROAMING); + i_nextMoveTime.Reset(0); // Expire the timer + creature.clearUnitState(UNIT_STAT_ROAMING_MOVE); return true; } - i_nextMoveTime.Update(diff); - - if (i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly()) - creature.clearUnitState(UNIT_STAT_ROAMING); - - if (!i_destinationHolder.HasArrived() && creature.IsStopped()) - creature.addUnitState(UNIT_STAT_ROAMING); - - CreatureTraveller traveller(creature); - - if (i_destinationHolder.UpdateTraveller(traveller, diff, true)) + if (creature.movespline->Finalized()) { + i_nextMoveTime.Update(diff); if (i_nextMoveTime.Passed()) - { - if (creature.canFly()) - creature.AddUnitMovementFlag(SPLINEFLAG_FLYINGING2); - else - creature.AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); - _setRandomLocation(creature); - } - else if (creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(), PET_FOLLOW_DIST+2.5f)) - { - creature.AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); - _setRandomLocation(creature); - } } return true; } + +template<> +bool RandomMovementGenerator::GetResetPosition(Creature& c, float& x, float& y, float& z) +{ + float radius; + c.GetRespawnCoord(x, y, z, NULL, &radius); + + // use current if in range + if (c.IsInRange3d(x, y, z, 0.0f, radius)) + c.GetPosition(x,y,z); + + return true; +} diff --git a/src/game/RandomMovementGenerator.h b/src/game/RandomMovementGenerator.h index dcb0a2ec9..1e8ac0672 100755 --- a/src/game/RandomMovementGenerator.h +++ b/src/game/RandomMovementGenerator.h @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,45 +8,38 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITY_RANDOMMOTIONGENERATOR_H -#define TRINITY_RANDOMMOTIONGENERATOR_H +#ifndef MANGOS_RANDOMMOTIONGENERATOR_H +#define MANGOS_RANDOMMOTIONGENERATOR_H #include "MovementGenerator.h" -#include "DestinationHolder.h" -#include "Traveller.h" template class TRINITY_DLL_SPEC RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovementGenerator > { public: - // Wander dist is related on db spawn dist. So what if we wanna set eandom movement on summoned creature?! - RandomMovementGenerator(float spawn_dist = 0.0f) : i_nextMoveTime(0), wander_distance(spawn_dist) {} + explicit RandomMovementGenerator(const Unit &) : i_nextMoveTime(0) {} void _setRandomLocation(T &); void Initialize(T &); - void Finalize(T &){} + void Finalize(T &); + void Interrupt(T &); void Reset(T &); bool Update(T &, const uint32 &); - void UpdateMapPosition(uint32 mapid, float &x ,float &y, float &z) - { - i_destinationHolder.GetLocationNow(mapid, x,y,z); - } - MovementGeneratorType GetMovementGeneratorType() { return RANDOM_MOTION_TYPE; } - private: - TimeTrackerSmall i_nextMoveTime; + MovementGeneratorType GetMovementGeneratorType() const { return RANDOM_MOTION_TYPE; } - DestinationHolder< Traveller > i_destinationHolder; - float wander_distance; + bool GetResetPosition(T&, float& x, float& y, float& z); + private: + ShortTimeTracker i_nextMoveTime; uint32 i_nextMove; }; -#endif +#endif diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 058c04021..43b0578f1 100755 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2809,7 +2809,7 @@ void Spell::update(uint32 difftime) // check if caster has moved before the spell finished if (m_timer != 0 && (m_castPositionX != m_caster->GetPositionX() || m_castPositionY != m_caster->GetPositionY() || m_castPositionZ != m_caster->GetPositionZ()) && - (m_spellInfo->Effect[0] != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEFLAG_FALLINGFAR))) + (m_spellInfo->Effect[0] != SPELL_EFFECT_STUCK || !m_caster->m_movementInfo.HasMovementFlag(MOVEFLAG_FALLINGFAR))) { if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !m_IsTriggeredSpell && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT)) cancel(); @@ -2837,7 +2837,7 @@ void Spell::update(uint32 difftime) if (m_caster->GetTypeId() == TYPEID_PLAYER) { // check if player has jumped before the channeling finished - if (m_caster->HasUnitMovementFlag(MOVEFLAG_FALLING)) + if (m_caster->m_movementInfo.HasMovementFlag(MOVEFLAG_FALLING)) cancel(); } @@ -2924,9 +2924,6 @@ void Spell::finish(bool ok) if (IsChanneledSpell(m_spellInfo)) m_caster->UpdateInterruptMask(); - if (!m_caster->IsNonMeleeSpellCasted(false, false, true)) - m_caster->clearUnitState(UNIT_STAT_CASTING); - if (!ok) { //restore spell mods @@ -3700,7 +3697,7 @@ uint8 Spell::CanCast(bool strict) if (m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->isMoving()) { // skip stuck spell to allow use it in falling case and apply spell limitations at movement - if ((!m_caster->HasUnitMovementFlag(MOVEFLAG_FALLINGFAR) || m_spellInfo->Effect[0] != SPELL_EFFECT_STUCK) && + if ((!m_caster->m_movementInfo.HasMovementFlag(MOVEFLAG_FALLINGFAR) || m_spellInfo->Effect[0] != SPELL_EFFECT_STUCK) && (IsAutoRepeat() || (m_spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) != 0)) return SPELL_FAILED_MOVING; } @@ -3733,7 +3730,7 @@ uint8 Spell::CanCast(bool strict) return SPELL_FAILED_TARGET_AURASTATE; // Not allow players casting on flying player - if (target->isInFlight() && m_caster->GetTypeId() == TYPEID_PLAYER) + if (target->IsTaxiFlying() && m_caster->GetTypeId() == TYPEID_PLAYER) return SPELL_FAILED_BAD_TARGETS; if (!m_IsTriggeredSpell && !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_IGNORE_LOS) && VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOSInMap(target)) @@ -3889,7 +3886,7 @@ uint8 Spell::CanCast(bool strict) if (m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell && !IsPassiveSpell(m_spellInfo->Id) && !(m_spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED)) { - if (m_caster->isInFlight()) + if (m_caster->IsTaxiFlying()) return SPELL_FAILED_NOT_FLYING; else return SPELL_FAILED_NOT_MOUNTED; diff --git a/src/game/Spell.h b/src/game/Spell.h index deea320dd..4eb52e910 100755 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -738,7 +738,7 @@ namespace Trinity for (typename GridRefManager::iterator itr = m.begin(); itr != m.end(); ++itr) { - if (!itr->getSource()->isAlive() || (itr->getSource()->GetTypeId() == TYPEID_PLAYER && ((Player*)itr->getSource())->isInFlight())) + if (!itr->getSource()->isAlive() || (itr->getSource()->GetTypeId() == TYPEID_PLAYER && ((Player*)itr->getSource())->IsTaxiFlying())) continue; if (itr->getSource()->m_invisibilityMask && itr->getSource()->m_invisibilityMask & (1 << 10) && !i_caster->canDetectInvisibilityOf(itr->getSource())) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 7c762ce9d..d9edabce3 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1694,7 +1694,7 @@ void Aura::TriggerSpell() } } - if (!caster->HasUnitMovementFlag(MOVEFLAG_FALLINGFAR)) + if (!caster->m_movementInfo.HasMovementFlag(MOVEFLAG_FALLINGFAR)) { if (height < 55 && height > 50) { @@ -3819,7 +3819,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real) for (std::list::iterator iter = targets.begin(); iter != targets.end(); ++iter) { - if (!(*iter)->hasUnitState(UNIT_STAT_CASTING)) + if (!(*iter)->IsNonMeleeSpellCasted(false)) continue; for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) @@ -4762,8 +4762,8 @@ void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real) } case 43648: // Electrical Storm makes target levitating { - if (m_target->HasUnitMovementFlag(MOVEFLAG_LEVITATING)) - m_target->RemoveUnitMovementFlag(MOVEFLAG_LEVITATING); + if (m_target->m_movementInfo.HasMovementFlag(MOVEFLAG_LEVITATING)) + m_target->m_movementInfo.RemoveMovementFlag(MOVEFLAG_LEVITATING); break; } case 40106: // Merge @@ -4815,8 +4815,8 @@ void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real) } case 43648: // Electrical Storm - stop levitating when spell ends { - if (!m_target->HasUnitMovementFlag(MOVEFLAG_LEVITATING)) - m_target->SetUnitMovementFlags(MOVEFLAG_LEVITATING); + if (!m_target->m_movementInfo.HasMovementFlag(MOVEFLAG_LEVITATING)) + m_target->m_movementInfo.SetMovementFlags(MOVEFLAG_LEVITATING); break; } } @@ -6346,9 +6346,6 @@ void Aura::HandleAuraAllowFlight(bool apply, bool Real) if (!Real) return; - if (m_target->GetTypeId() == TYPEID_UNIT) - m_target->SetFlying(apply); - // allow fly WorldPacket data; if (apply) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 1b7c0f445..9ea398920 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2650,7 +2650,7 @@ void Spell::EffectTriggerMissileSpell(uint32 effect_idx) void Spell::EffectTeleportUnits(uint32 i) { - if (!unitTarget || unitTarget->isInFlight()) + if (!unitTarget || unitTarget->IsTaxiFlying()) return; // If not exist data for dest location - return @@ -4460,7 +4460,7 @@ void Spell::EffectTeleUnitsFaceCaster(uint32 i) if (!unitTarget) return; - if (unitTarget->isInFlight()) + if (unitTarget->IsTaxiFlying()) return; uint32 mapid = m_caster->GetMapId(); @@ -6305,7 +6305,7 @@ void Spell::EffectSanctuary(uint32 /*i*/) for (std::list::iterator iter = targets.begin(); iter != targets.end(); ++iter) { - if (!(*iter)->hasUnitState(UNIT_STAT_CASTING)) + if (!(*iter)->IsNonMeleeSpellCasted(false)) continue; for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) @@ -6436,7 +6436,7 @@ void Spell::EffectStuck(uint32 /*i*/) sLog.outDebug("Spell Effect: Stuck"); sLog.outDetail("Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", pTarget->GetName(), pTarget->GetGUIDLow(), m_caster->GetMapId(), m_caster->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); - if (pTarget->isInFlight()) + if (pTarget->IsTaxiFlying()) return; // homebind location is loaded always @@ -6854,7 +6854,7 @@ void Spell::EffectBlock(uint32 /*i*/) void Spell::EffectLeapForward(uint32 i) { - if (unitTarget->isInFlight()) + if (unitTarget->IsTaxiFlying()) return; if (m_spellInfo->rangeIndex== 1) //self range @@ -6916,7 +6916,7 @@ void Spell::EffectLeapForward(uint32 i) } void Spell::EffectLeapBack(uint32 i) { - if (unitTarget->isInFlight()) + if (unitTarget->IsTaxiFlying()) return; m_caster->KnockBackFrom(unitTarget,float(m_spellInfo->EffectMiscValue[i])/10,float(damage)/10); @@ -7050,8 +7050,8 @@ void Spell::EffectCharge2(uint32 /*i*/) else return; - m_caster->SendMonsterMoveWithSpeed(x, y, z, SPLINEFLAG_WALKMODE_MODE); - m_caster->Relocate(x, y, z); + // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags + m_caster->MonsterMoveWithSpeed(x, y, z, 24.f); // not all charge effects used in negative spells if (unitTarget && unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id)) @@ -7300,8 +7300,8 @@ void Spell::EffectSummonDeadPet(uint32 /*i*/) float x,y,z; _player->GetPosition(x, y, z); - _player->GetMap()->CreatureRelocation(pet, x, y, z, _player->GetOrientation()); - pet->SendMonsterMove(x,y,z,0,NULL); + + pet->NearTeleportTo(x, y, z, _player->GetOrientation()); pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 29988b6b9..62cbe8803 100755 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -345,10 +345,6 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) return; } - // can't use our own spells when we're in possession of another unit, - if (_player->isPossessing()) - return; - // client provided targets SpellCastTargets targets; recvPacket >> targets.ReadForCaster(_player); diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 7d156ebe1..5c9c8534f 100755 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2626,7 +2626,7 @@ void SpellMgr::LoadSpellCustomAttr() case SPELL_EFFECT_CHARGE: case SPELL_EFFECT_CHARGE2: if (!spellInfo->speed && !spellInfo->SpellFamilyName) - spellInfo->speed = SPEED_CHARGE; + spellInfo->speed = 42.0f; spellInfo->AttributesCu |= SPELL_ATTR_CU_CHARGE; break; case SPELL_EFFECT_TRIGGER_SPELL: diff --git a/src/game/TargetedMovementGenerator.cpp b/src/game/TargetedMovementGenerator.cpp index edfb2d154..f371d63a9 100755 --- a/src/game/TargetedMovementGenerator.cpp +++ b/src/game/TargetedMovementGenerator.cpp @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,46 +8,54 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ByteBuffer.h" #include "TargetedMovementGenerator.h" #include "Errors.h" #include "Creature.h" -#include "MapManager.h" -#include "DestinationHolderImp.h" +#include "Player.h" #include "World.h" -#include "Spell.h" - -#define SMALL_ALPHA 0.05f +#include "movement/MoveSplineInit.h" +#include "movement/MoveSpline.h" #include -template -void TargetedMovementGenerator::_setTargetLocation(T &owner) +//-----------------------------------------------// +template +void TargetedMovementGeneratorMedium::_setTargetLocation(T &owner) { - if (!i_target.isValid() || !&owner) + if (!i_target.isValid() || !i_target->IsInWorld()) return; - if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED)) + if (owner.hasUnitState(UNIT_STAT_NOT_MOVE)) return; float x, y, z; - if (!i_offset) + + // prevent redundant micro-movement for pets, other followers. + if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset)) + { + if (!owner.movespline->Finalized()) + return; + + owner.GetPosition(x, y, z); + } + else if (!i_offset) { - // to nearest random contact position - i_target->GetRandomContactPoint(&owner, x, y, z, 0, MELEE_RANGE - 0.5f); + // to nearest contact position + i_target->GetContactPoint( &owner, x, y, z ); } else { // to at i_offset distance from target and i_angle from target facing - i_target->GetClosePoint(x,y,z,owner.GetObjectSize(),i_offset,i_angle); + i_target->GetClosePoint(x, y, z, owner.GetObjectBoundingRadius(), i_offset, i_angle/*, &owner*/); } /* @@ -64,167 +70,240 @@ void TargetedMovementGenerator::_setTargetLocation(T &owner) ralf //We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize - float bothObjectSize = i_target->GetObjectSize() + owner.GetObjectSize() + CONTACT_DISTANCE; - if (i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize) + float bothObjectSize = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + CONTACT_DISTANCE; + if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize ) return; */ - if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly()) - z = i_target->GetPositionZ(); - Traveller traveller(owner); - i_destinationHolder.SetDestination(traveller, x, y, z); - owner.addUnitState(UNIT_STAT_CHASE); - if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly()) - owner.AddUnitMovementFlag(SPLINEFLAG_FLYINGING2); + D::_addUnitStateMove(owner); + i_targetReached = false; + i_recalculateTravel = false; + + Movement::MoveSplineInit init(owner); + init.MoveTo(x,y,z); + init.SetWalk(((D*)this)->EnableWalking()); + init.Launch(); } -template -void TargetedMovementGenerator::_adaptSpeedToTarget(T &owner) +template<> +void TargetedMovementGeneratorMedium >::UpdateFinalDistance(float /*fDistance*/) { - if (!owner.GetOwner()) - return; - - float lowerCritDist = 3*i_offset; - float upperCritDist = 6*i_offset; - - float maxSpeed = owner.GetMaxSpeedRate(MOVE_RUN); - float currSpeed = owner.GetSpeedRate(MOVE_RUN); - float targetSpeed = i_target->GetSpeedRate(MOVE_RUN); - - if (targetSpeed > maxSpeed) - targetSpeed = maxSpeed; - - float dist_to_target = owner.GetDistance2d(i_target.getTarget()); - - if (dist_to_target <= lowerCritDist && currSpeed < targetSpeed) - owner.SetSpeed(MOVE_RUN, targetSpeed, true); - // distance is greater than threashold: go to max speed - else if (dist_to_target > upperCritDist && currSpeed < maxSpeed) - owner.SetSpeed(MOVE_RUN, maxSpeed, true); + // nothing to do for Player } -template -void TargetedMovementGenerator::Initialize(T &owner) +template<> +void TargetedMovementGeneratorMedium >::UpdateFinalDistance(float /*fDistance*/) { - if (!&owner) - return; - - if (owner.GetTypeId() != TYPEID_UNIT || !(((Creature*)&owner)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_ALWAYS_WALK)) - owner.RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); - - if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly()) - owner.AddUnitMovementFlag(SPLINEFLAG_FLYINGING2); - - _setTargetLocation(owner); + // nothing to do for Player } -template -void TargetedMovementGenerator::Finalize(T &owner) +template<> +void TargetedMovementGeneratorMedium >::UpdateFinalDistance(float fDistance) { - owner.clearUnitState(UNIT_STAT_CHASE); - - // make sure that owner is at maxspeed - if (owner.GetSpeedRate(MOVE_RUN) != owner.GetMaxSpeedRate(MOVE_RUN)) - owner.SetSpeed(MOVE_RUN, owner.GetMaxSpeedRate(MOVE_RUN), true); - + i_offset = fDistance; + i_recalculateTravel = true; } -template -void TargetedMovementGenerator::Reset(T &owner) +template<> +void TargetedMovementGeneratorMedium >::UpdateFinalDistance(float fDistance) { - Initialize(owner); + i_offset = fDistance; + i_recalculateTravel = true; } -template -bool TargetedMovementGenerator::Update(T &owner, const uint32 & time_diff) +template +bool TargetedMovementGeneratorMedium::Update(T &owner, const uint32 & time_diff) { - if (!i_target.isValid()) + if (!i_target.isValid() || !i_target->IsInWorld()) return false; - if (!&owner || !owner.isAlive()) + if (!owner.isAlive()) return true; - if (owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_DISTRACTED)) + if (owner.hasUnitState(UNIT_STAT_NOT_MOVE)) + { + D::_clearUnitStateMove(owner); return true; + } // prevent movement while casting spells with cast time or channel time - if (owner.IsNonMeleeSpellCasted(false, false, true) && (!owner.m_currentSpells[CURRENT_GENERIC_SPELL] || owner.m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT)) + if (owner.IsNonMeleeSpellCasted(false, false, true)) { if (!owner.IsStopped()) owner.StopMoving(); - return true; } // prevent crash after creature killed pet - if (!owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != i_target.getTarget()) - return true; - - Traveller traveller(owner); - - if (!i_destinationHolder.HasDestination()) - _setTargetLocation(owner); - - if (owner.IsStopped() && !i_destinationHolder.HasArrived()) + if (static_cast(this)->_lostTarget(owner)) { - owner.addUnitState(UNIT_STAT_CHASE); - if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly()) - owner.AddUnitMovementFlag(SPLINEFLAG_FLYINGING2); - - i_destinationHolder.StartTravel(traveller); + D::_clearUnitStateMove(owner); return true; } - if (i_destinationHolder.UpdateTraveller(traveller, time_diff)) + i_recheckDistance.Update(time_diff); + if (i_recheckDistance.Passed()) { - // put targeted movement generators on a higher priority - if (owner.GetObjectSize()) - i_destinationHolder.ResetUpdate(50); - - // adapt speed at follow mode - if (owner.hasUnitState(UNIT_STAT_FOLLOW)) - _adaptSpeedToTarget(owner); + i_recheckDistance.Reset(50); + //More distance let have better performance, less distance let have more sensitive reaction at target move. + float allowed_dist = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + + sWorld.getRate(RATE_TARGET_POS_RECALCULATION_RANGE); + float dist = (owner.movespline->FinalDestination() - + G3D::Vector3(i_target->GetPositionX(),i_target->GetPositionY(),i_target->GetPositionZ())).squaredLength(); + if (dist >= allowed_dist * allowed_dist) + _setTargetLocation(owner); + } - if ((i_offset ? !i_target->IsWithinDistInMap(&owner,2*i_offset) - : !i_target->IsWithinMeleeRange(&owner)) || i_recalculateTravel) - { - owner.SetInFront(i_target.getTarget()); // Set new Angle For Map:: - _setTargetLocation(owner); //Calculate New Dest and Send data To Player - i_recalculateTravel = false; - } - // Update the Angle of the target only for Map::, no need to send packet for player - else if (!i_angle && !owner.HasInArc(0.01f, i_target.getTarget())) + if (owner.movespline->Finalized()) + { + if (i_angle == 0.f && !owner.HasInArc(0.01f, i_target.getTarget())) owner.SetInFront(i_target.getTarget()); - if ((owner.IsStopped() && !i_destinationHolder.HasArrived())) + if (!i_targetReached) { - //Angle update will take place into owner.StopMoving() - owner.SetInFront(i_target.getTarget()); - - owner.StopMoving(); - if (owner.IsWithinMeleeRange(i_target.getTarget()) && !owner.hasUnitState(UNIT_STAT_FOLLOW)) - owner.Attack(i_target.getTarget(),true); + i_targetReached = true; + static_cast(this)->_reachTarget(owner); } } + else + { + if (i_recalculateTravel) + _setTargetLocation(owner); + } return true; } +//-----------------------------------------------// +template +void ChaseMovementGenerator::_reachTarget(T &owner) +{ + if (owner.IsWithinMeleeRange(this->i_target.getTarget())) + owner.Attack(this->i_target.getTarget(),true); +} + +template<> +void ChaseMovementGenerator::Initialize(Player &owner) +{ + owner.addUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE); + _setTargetLocation(owner); +} + +template<> +void ChaseMovementGenerator::Initialize(Creature &owner) +{ + owner.SetWalk(false); + owner.addUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE); + _setTargetLocation(owner); +} + +template +void ChaseMovementGenerator::Finalize(T &owner) +{ + owner.clearUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE); +} + +template +void ChaseMovementGenerator::Interrupt(T &owner) +{ + owner.clearUnitState(UNIT_STAT_CHASE|UNIT_STAT_CHASE_MOVE); +} + template -Unit* TargetedMovementGenerator::GetTarget() const -{ - return i_target.getTarget(); -} - -template void TargetedMovementGenerator::_setTargetLocation(Player &); -template void TargetedMovementGenerator::_setTargetLocation(Creature &); -template void TargetedMovementGenerator::Initialize(Player &); -template void TargetedMovementGenerator::Initialize(Creature &); -template void TargetedMovementGenerator::Finalize(Player &); -template void TargetedMovementGenerator::Finalize(Creature &); -template void TargetedMovementGenerator::Reset(Player &); -template void TargetedMovementGenerator::Reset(Creature &); -template bool TargetedMovementGenerator::Update(Player &, const uint32 &); -template bool TargetedMovementGenerator::Update(Creature &, const uint32 &); -template Unit* TargetedMovementGenerator::GetTarget() const; -template Unit* TargetedMovementGenerator::GetTarget() const; \ No newline at end of file +void ChaseMovementGenerator::Reset(T &owner) +{ + Initialize(owner); +} + +//-----------------------------------------------// +template<> +bool FollowMovementGenerator::EnableWalking() const +{ + return i_target.isValid() && i_target->IsWalking(); +} + +template<> +bool FollowMovementGenerator::EnableWalking() const +{ + return false; +} + +template<> +void FollowMovementGenerator::_updateSpeed(Player &/*u*/) +{ + // nothing to do for Player +} + +template<> +void FollowMovementGenerator::_updateSpeed(Creature &u) +{ + // pet only sync speed with owner + if (!((Creature&)u).isPet() || !i_target.isValid() || i_target->GetGUID() != u.GetOwnerGUID()) + return; + + u.UpdateSpeed(MOVE_RUN,true); + u.UpdateSpeed(MOVE_WALK,true); + u.UpdateSpeed(MOVE_SWIM,true); +} + +template<> +void FollowMovementGenerator::Initialize(Player &owner) +{ + owner.addUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE); + _updateSpeed(owner); + _setTargetLocation(owner); +} + +template<> +void FollowMovementGenerator::Initialize(Creature &owner) +{ + owner.addUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE); + _updateSpeed(owner); + _setTargetLocation(owner); +} + +template +void FollowMovementGenerator::Finalize(T &owner) +{ + owner.clearUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE); + _updateSpeed(owner); +} + +template +void FollowMovementGenerator::Interrupt(T &owner) +{ + owner.clearUnitState(UNIT_STAT_FOLLOW|UNIT_STAT_FOLLOW_MOVE); + _updateSpeed(owner); +} + +template +void FollowMovementGenerator::Reset(T &owner) +{ + Initialize(owner); +} + +//-----------------------------------------------// +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player &); +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player &); +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature &); +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature &); +template bool TargetedMovementGeneratorMedium >::Update(Player &, const uint32 &); +template bool TargetedMovementGeneratorMedium >::Update(Player &, const uint32 &); +template bool TargetedMovementGeneratorMedium >::Update(Creature &, const uint32 &); +template bool TargetedMovementGeneratorMedium >::Update(Creature &, const uint32 &); + +template void ChaseMovementGenerator::_reachTarget(Player &); +template void ChaseMovementGenerator::_reachTarget(Creature &); +template void ChaseMovementGenerator::Finalize(Player &); +template void ChaseMovementGenerator::Finalize(Creature &); +template void ChaseMovementGenerator::Interrupt(Player &); +template void ChaseMovementGenerator::Interrupt(Creature &); +template void ChaseMovementGenerator::Reset(Player &); +template void ChaseMovementGenerator::Reset(Creature &); + +template void FollowMovementGenerator::Finalize(Player &); +template void FollowMovementGenerator::Finalize(Creature &); +template void FollowMovementGenerator::Interrupt(Player &); +template void FollowMovementGenerator::Interrupt(Creature &); +template void FollowMovementGenerator::Reset(Player &); +template void FollowMovementGenerator::Reset(Creature &); diff --git a/src/game/TargetedMovementGenerator.h b/src/game/TargetedMovementGenerator.h index 7993ffb8d..cfc7c1ffe 100755 --- a/src/game/TargetedMovementGenerator.h +++ b/src/game/TargetedMovementGenerator.h @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,21 +8,20 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITY_TARGETEDMOVEMENTGENERATOR_H -#define TRINITY_TARGETEDMOVEMENTGENERATOR_H +#ifndef MANGOS_TARGETEDMOVEMENTGENERATOR_H +#define MANGOS_TARGETEDMOVEMENTGENERATOR_H #include "MovementGenerator.h" -#include "DestinationHolder.h" -#include "Traveller.h" #include "FollowerReference.h" +#include "Unit.h" class TRINITY_DLL_SPEC TargetedMovementGeneratorBase { @@ -35,44 +32,84 @@ class TRINITY_DLL_SPEC TargetedMovementGeneratorBase FollowerReference i_target; }; +template +class TRINITY_DLL_SPEC TargetedMovementGeneratorMedium +: public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase +{ + protected: + TargetedMovementGeneratorMedium(Unit &target, float offset, float angle) : + TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle), + i_recalculateTravel(false), i_targetReached(false), i_recheckDistance(0) + { + } + ~TargetedMovementGeneratorMedium() {} + + public: + bool Update(T &, const uint32 &); + + Unit* GetTarget() const { return i_target.getTarget(); } + + void unitSpeedChanged() { i_recalculateTravel=true; } + void UpdateFinalDistance(float fDistance); + + protected: + void _setTargetLocation(T &); + + ShortTimeTracker i_recheckDistance; + float i_offset; + float i_angle; + bool i_recalculateTravel : 1; + bool i_targetReached : 1; +}; + template -class TRINITY_DLL_SPEC TargetedMovementGenerator -: public MovementGeneratorMedium< T, TargetedMovementGenerator >, public TargetedMovementGeneratorBase +class TRINITY_DLL_SPEC ChaseMovementGenerator : public TargetedMovementGeneratorMedium > { public: + ChaseMovementGenerator(Unit &target) + : TargetedMovementGeneratorMedium >(target) {} + ChaseMovementGenerator(Unit &target, float offset, float angle) + : TargetedMovementGeneratorMedium >(target, offset, angle) {} + ~ChaseMovementGenerator() {} - TargetedMovementGenerator(Unit &target) - : TargetedMovementGeneratorBase(target), i_offset(0), i_angle(0), i_recalculateTravel(false) {} - TargetedMovementGenerator(Unit &target, float offset, float angle) - : TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle), i_recalculateTravel(false) {} - ~TargetedMovementGenerator() {} + MovementGeneratorType GetMovementGeneratorType() const { return CHASE_MOTION_TYPE; } void Initialize(T &); void Finalize(T &); + void Interrupt(T &); void Reset(T &); - bool Update(T &, const uint32 &); - MovementGeneratorType GetMovementGeneratorType() { return TARGETED_MOTION_TYPE; } - Unit* GetTarget() const; + static void _clearUnitStateMove(T &u) { u.clearUnitState(UNIT_STAT_CHASE_MOVE); } + static void _addUnitStateMove(T &u) { u.addUnitState(UNIT_STAT_CHASE_MOVE); } + bool EnableWalking() const { return false;} + bool _lostTarget(T &u) const { return u.getVictim() != this->GetTarget(); } + void _reachTarget(T &); +}; - bool GetDestination(float &x, float &y, float &z) const - { - if (i_destinationHolder.HasArrived()) return false; - i_destinationHolder.GetDestination(x,y,z); - return true; - } +template +class TRINITY_DLL_SPEC FollowMovementGenerator : public TargetedMovementGeneratorMedium > +{ + public: + FollowMovementGenerator(Unit &target) + : TargetedMovementGeneratorMedium >(target){} + FollowMovementGenerator(Unit &target, float offset, float angle) + : TargetedMovementGeneratorMedium >(target, offset, angle) {} + ~FollowMovementGenerator() {} - void unitSpeedChanged() { i_recalculateTravel=true; } - private: + MovementGeneratorType GetMovementGeneratorType() const { return FOLLOW_MOTION_TYPE; } - void _setTargetLocation(T &); - void _adaptSpeedToTarget(T &); + void Initialize(T &); + void Finalize(T &); + void Interrupt(T &); + void Reset(T &); - float i_offset; - float i_angle; - DestinationHolder< Traveller > i_destinationHolder; - bool i_recalculateTravel; - float i_targetX, i_targetY, i_targetZ; + static void _clearUnitStateMove(T &u) { u.clearUnitState(UNIT_STAT_FOLLOW_MOVE); } + static void _addUnitStateMove(T &u) { u.addUnitState(UNIT_STAT_FOLLOW_MOVE); } + bool EnableWalking() const; + bool _lostTarget(T &) const { return false; } + void _reachTarget(T &) {} + private: + void _updateSpeed(T &u); }; -#endif +#endif diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp index 03bc43f35..a873daae7 100755 --- a/src/game/TaxiHandler.cpp +++ b/src/game/TaxiHandler.cpp @@ -30,14 +30,11 @@ #include "UpdateMask.h" #include "Path.h" #include "WaypointMovementGenerator.h" -#include "DestinationHolderImp.h" #include void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket & recv_data) { - CHECK_PACKET_SIZE(recv_data,8); - sLog.outDebug("WORLD: Received CMSG_TAXINODE_STATUS_QUERY"); uint64 guid; @@ -56,7 +53,7 @@ void WorldSession::SendTaxiStatus(uint64 guid) return; } - uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId()); + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer()->GetTeam()); // not found nearest if (curloc == 0) @@ -68,13 +65,12 @@ void WorldSession::SendTaxiStatus(uint64 guid) data << guid; data << uint8(GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) ? 1 : 0); SendPacket(&data); + sLog.outDebug("WORLD: Sent SMSG_TAXINODE_STATUS"); } void WorldSession::HandleTaxiQueryAvailableNodesOpcode(WorldPacket & recv_data) { - CHECK_PACKET_SIZE(recv_data,8); - sLog.outDebug("WORLD: Received CMSG_TAXIQUERYAVAILABLENODES"); uint64 guid; @@ -103,7 +99,7 @@ void WorldSession::HandleTaxiQueryAvailableNodesOpcode(WorldPacket & recv_data) void WorldSession::SendTaxiMenu(Creature* unit) { // find current node - uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId()); + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer()->GetTeam()); if (curloc == 0) return; @@ -129,14 +125,16 @@ void WorldSession::SendDoFlight(uint16 MountId, uint32 path, uint32 pathNode) while (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE) GetPlayer()->GetMotionMaster()->MovementExpired(false); - GetPlayer()->Mount(MountId); + if (MountId) + GetPlayer()->Mount(MountId); + GetPlayer()->GetMotionMaster()->MoveTaxiFlight(path,pathNode); } bool WorldSession::SendLearnNewTaxiNode(Creature* unit) { // find current node - uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId()); + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer()->GetTeam()); if (curloc == 0) return true; // `true` send to avoid WorldSession::SendTaxiMenu call with one more curlock seartch with same false result. @@ -159,8 +157,6 @@ bool WorldSession::SendLearnNewTaxiNode(Creature* unit) void WorldSession::HandleActivateTaxiFarOpcode (WorldPacket & recv_data) { - CHECK_PACKET_SIZE(recv_data,8+4+4); - sLog.outDebug("WORLD: Received CMSG_ACTIVATETAXIEXPRESS"); uint64 guid; @@ -174,8 +170,6 @@ void WorldSession::HandleActivateTaxiFarOpcode (WorldPacket & recv_data) sLog.outDebug("WORLD: HandleActivateTaxiFarOpcode - Unit (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid))); return; } - // recheck - CHECK_PACKET_SIZE(recv_data,8+4+4+node_count*4); std::vector nodes; @@ -189,23 +183,24 @@ void WorldSession::HandleActivateTaxiFarOpcode (WorldPacket & recv_data) if (nodes.empty()) return; - sLog.outDebug("WORLD: Received CMSG_ACTIVATETAXIEXPRESS from %d to %d" ,nodes.front(),nodes.back()); GetPlayer()->ActivateTaxiPathTo(nodes, 0, npc); } -void WorldSession::HandleTaxiNextDestinationOpcode(WorldPacket& recv_data) +void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data) { sLog.outDebug("WORLD: Received CMSG_MOVE_SPLINE_DONE"); + uint64 guid; MovementInfo movementInfo; // used only for proper packet read - recv_data >> movementInfo; - recv_data >> Unused(); // unk + //recv_data >> guid; + //recv_data >> movementInfo; + //recv_data >> Unused(); // unk // in taxi flight packet received in 2 case: // 1) end taxi path in far (multi-node) flight - // 2) switch from one map to other in case multim-map taxi path + // 2) switch from one map to other in case multi-map taxi path // we need process only (1) uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination(); if (!curDest) @@ -221,8 +216,10 @@ void WorldSession::HandleTaxiNextDestinationOpcode(WorldPacket& recv_data) // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); + flight->Interrupt(*GetPlayer()); // will reset at map landing + flight->SetCurrentNodeAfterTeleport(); - Path::PathNode const& node = flight->GetPath()[flight->GetCurrentNode()]; + TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()]; flight->SkipCurrentNode(); GetPlayer()->TeleportTo(curDestNode->map_id,node.x,node.y,node.z,GetPlayer()->GetOrientation()); @@ -239,10 +236,10 @@ void WorldSession::HandleTaxiNextDestinationOpcode(WorldPacket& recv_data) // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) if (GetPlayer()->isTaxiCheater()) { - if (GetPlayer()->m_taxi.SetTaximaskNode(sourcenode)) + if(GetPlayer()->m_taxi.SetTaximaskNode(sourcenode)) { WorldPacket data(SMSG_NEW_TAXI_PATH, 0); - _player->GetSession()->SendPacket(&data); + GetPlayer()->GetSession()->SendPacket( &data ); } } @@ -254,9 +251,9 @@ void WorldSession::HandleTaxiNextDestinationOpcode(WorldPacket& recv_data) objmgr.GetTaxiPath(sourcenode, destinationnode, path, cost); if (path && MountId) - SendDoFlight(MountId, path, 1); // skip start fly node + SendDoFlight(MountId, path, 1); // skip start fly node else - GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next + GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next } else GetPlayer()->m_taxi.ClearTaxiDestinations(); // not destinations, clear source node @@ -275,8 +272,6 @@ void WorldSession::HandleTaxiNextDestinationOpcode(WorldPacket& recv_data) void WorldSession::HandleActivateTaxiOpcode(WorldPacket & recv_data) { - CHECK_PACKET_SIZE(recv_data,8+4+4); - sLog.outDebug("WORLD: Received CMSG_ACTIVATETAXI"); uint64 guid; @@ -294,4 +289,3 @@ void WorldSession::HandleActivateTaxiOpcode(WorldPacket & recv_data) GetPlayer()->ActivateTaxiPathTo(nodes, 0, npc); } - diff --git a/src/game/TemporarySummon.cpp b/src/game/TemporarySummon.cpp index 2613b6b37..1dc58f24d 100755 --- a/src/game/TemporarySummon.cpp +++ b/src/game/TemporarySummon.cpp @@ -26,10 +26,7 @@ #include "CreatureAI.h" TemporarySummon::TemporarySummon(uint64 summoner) : -Creature(), m_type(TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN), m_timer(0), m_lifetime(0), m_summoner(summoner) -{ - m_unit_movement_flags = 0; -} +Creature(), m_type(TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN), m_timer(0), m_lifetime(0), m_summoner(summoner) {} void TemporarySummon::Update(uint32 update_diff, uint32 diff) { diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index 8a758c8bc..31e6d663f 100755 --- a/src/game/ThreatManager.cpp +++ b/src/game/ThreatManager.cpp @@ -132,7 +132,7 @@ void HostilReference::updateOnlineStatus() // target is not in flight if (isValid() && ((getTarget()->GetTypeId() != TYPEID_PLAYER || !((Player*)getTarget())->isGameMaster()) || - !getTarget()->hasUnitState(UNIT_STAT_IN_FLIGHT))) + !getTarget()->IsTaxiFlying())) { Creature* creature = (Creature*) getSourceUnit(); online = getTarget()->isInAccessiblePlacefor (creature); diff --git a/src/game/TradeHandler.cpp b/src/game/TradeHandler.cpp index 9c42117b7..2c3454203 100755 --- a/src/game/TradeHandler.cpp +++ b/src/game/TradeHandler.cpp @@ -551,7 +551,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) return; } - if (GetPlayer()->isInFlight()) + if (GetPlayer()->IsTaxiFlying()) { SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); return; @@ -579,7 +579,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) return; } - if (pOther->isInFlight()) + if (pOther->IsTaxiFlying()) { SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); return; diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index 8d96bc96c..c626f3462 100755 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -206,22 +206,22 @@ struct keyFrame bool Transport::GenerateWaypoints(uint32 pathid, std::set &mapids) { - TransportPath path; - objmgr.GetTransportPathNodes(pathid, path); - - if (path.Empty()) + if (pathid >= sTaxiPathNodesByPath.size()) return false; + TaxiPathNodeList const& path = sTaxiPathNodesByPath[pathid]; + std::vector keyFrames; int mapChange = 0; mapids.clear(); - for (size_t i = 1; i < path.Size() - 1; i++) + for (size_t i = 1; i < path.size() - 1; i++) { if (mapChange == 0) { - if ((path[i].mapid == path[i+1].mapid)) + TaxiPathNodeEntry const& node_i = path[i]; + if (node_i.mapid == path[i+1].mapid) { - keyFrame k(path[i].x, path[i].y, path[i].z, path[i].mapid, path[i].actionFlag, path[i].delay); + keyFrame k(node_i.x, node_i.y, node_i.z, node_i.mapid, node_i.actionFlag, node_i.delay); keyFrames.push_back(k); mapids.insert(k.mapid); } diff --git a/src/game/Transports.h b/src/game/Transports.h index a32d616d3..770dab498 100755 --- a/src/game/Transports.h +++ b/src/game/Transports.h @@ -27,35 +27,6 @@ #include #include -class TransportPath -{ - public: - struct PathNode - { - uint32 mapid; - float x,y,z; - uint32 actionFlag; - uint32 delay; - }; - - inline void SetLength(const unsigned int sz) - { - i_nodes.resize(sz); - } - - inline unsigned int Size(void) const { return i_nodes.size(); } - inline bool Empty(void) const { return i_nodes.empty(); } - inline void Resize(unsigned int sz) { i_nodes.resize(sz); } - inline void Clear(void) { i_nodes.clear(); } - inline PathNode* GetNodes(void) { return static_cast(&i_nodes[0]); } - - PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } - const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } - - protected: - std::vector i_nodes; -}; - class Transport : public GameObject { public: diff --git a/src/game/Traveller.h b/src/game/Traveller.h deleted file mode 100755 index 47589e405..000000000 --- a/src/game/Traveller.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_TRAVELLER_H -#define TRINITY_TRAVELLER_H - -#include "MapManager.h" -#include "Creature.h" -#include "Player.h" -#include -#include "CreatureGroups.h" - -/** Traveller is a wrapper for units (creatures or players) that - * travel from point A to point B using the destination holder. - */ -#define PLAYER_FLIGHT_SPEED 32.0f - -template -struct TRINITY_DLL_DECL Traveller -{ - T &i_traveller; - Traveller(T &t) : i_traveller(t) {} - Traveller(const Traveller &obj) : i_traveller(obj) {} - Traveller& operator=(const Traveller &obj) - { - this->~Traveller(); - new (this) Traveller(obj); - return *this; - } - - operator T&(void) { return i_traveller; } - operator const T&(void) { return i_traveller; } - float GetPositionX() const { return i_traveller.GetPositionX(); } - float GetPositionY() const { return i_traveller.GetPositionY(); } - float GetPositionZ() const { return i_traveller.GetPositionZ(); } - T& GetTraveller(void) { return i_traveller; } - - float Speed(void) { assert(false); return 0.0f; } - float GetMoveDestinationTo(float x, float y, float z); - uint32 GetTotalTrevelTimeTo(float x, float y, float z); - - void Relocation(float x, float y, float z, float orientation) {} - void Relocation(float x, float y, float z) { Relocation(x, y, z, i_traveller.GetOrientation()); } - void MoveTo(float x, float y, float z, uint32 t) {} -}; - -template -inline uint32 Traveller::GetTotalTrevelTimeTo(float x, float y, float z) -{ - float dist = GetMoveDestinationTo(x,y,z); - float speed = Speed();; - if (speed <= 0.0f) - return 0xfffffffe; // almost infinity-unit should stop - else - speed *= 0.001f; // speed is in seconds so convert from second to millisecond - return static_cast(dist/speed); -} - -// specialization for creatures -template<> -inline float Traveller::Speed() -{ - if (i_traveller.hasUnitState(UNIT_STAT_CHARGING)) - return i_traveller.m_TempSpeed; - else if (i_traveller.HasUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE)) - return i_traveller.GetSpeed(MOVE_WALK); - else if (i_traveller.HasUnitMovementFlag(SPLINEFLAG_FLYINGING2)) - return i_traveller.GetSpeed(MOVE_FLIGHT); - else - return i_traveller.GetSpeed(MOVE_RUN); -} - -template<> -inline void Traveller::Relocation(float x, float y, float z, float orientation) -{ - i_traveller.GetMap()->CreatureRelocation(&i_traveller, x, y, z, orientation); -} - -template<> -inline float Traveller::GetMoveDestinationTo(float x, float y, float z) -{ - float dx = x - GetPositionX(); - float dy = y - GetPositionY(); - float dz = z - GetPositionZ(); - - if (i_traveller.canFly()) - return sqrt((dx*dx) + (dy*dy) + (dz*dz)); - else //Walking on the ground - return sqrt((dx*dx) + (dy*dy)); -} - -template<> -inline void Traveller::MoveTo(float x, float y, float z, uint32 t) -{ - i_traveller.AI_SendMoveToPacket(x, y, z, t, i_traveller.GetUnitMovementFlags(), 0); -} - -// specialization for players -template<> -inline float Traveller::Speed() -{ - if (i_traveller.hasUnitState(UNIT_STAT_CHARGING)) - return i_traveller.m_TempSpeed; - else if (i_traveller.isInFlight()) - return PLAYER_FLIGHT_SPEED; - else - return i_traveller.GetSpeed(i_traveller.HasUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE) ? MOVE_WALK : MOVE_RUN); -} - -template<> -inline float Traveller::GetMoveDestinationTo(float x, float y, float z) -{ - float dx = x - GetPositionX(); - float dy = y - GetPositionY(); - float dz = z - GetPositionZ(); - - //if (i_traveller.isInFlight()) - return sqrt((dx*dx) + (dy*dy) + (dz*dz)); - //else //Walking on the ground - // return sqrt((dx*dx) + (dy*dy)); -} - -template<> -inline void Traveller::Relocation(float x, float y, float z, float orientation) -{ - i_traveller.SetPosition(x, y, z, orientation); -} - -template<> -inline void Traveller::MoveTo(float x, float y, float z, uint32 t) -{ - //Only send SPLINEFLAG_WALKMODE_MODE, client has strange issues with other move flags - i_traveller.SendMonsterMove(x, y, z, t); -} - -typedef Traveller CreatureTraveller; -typedef Traveller PlayerTraveller; -#endif - diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 2ed4bdc92..b86adfc6d 100755 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -46,15 +46,17 @@ #include "InstanceSaveMgr.h" #include "GridNotifiersImpl.h" #include "CellImpl.h" -#include "Path.h" #include "CreatureGroups.h" #include "PetAI.h" #include "PassiveAI.h" #include "CreatureAI.h" #include "VMapFactory.h" -#include "Traveller.h" #include "UnitAI.h" +#include "MovementGenerator.h" +#include "movement/MoveSplineInit.h" +#include "movement/MoveSpline.h" + #include float baseMoveSpeed[MAX_MOVE_TYPE] = @@ -172,33 +174,40 @@ void MovementInfo::Read(ByteBuffer &data) data >> t_pos.z; data >> t_pos.o; data >> t_time; + + if (moveFlags2 & MOVEFLAG2_INTERP_MOVEMENT) + data >> t_time2; } - if (HasMovementFlag(MovementFlags(MOVEFLAG_SWIMMING | SPLINEFLAG_FLYINGING2))) + if ((HasMovementFlag(MovementFlags(MOVEFLAG_SWIMMING | MOVEFLAG_FLYING))) || (moveFlags2 & MOVEFLAG2_ALLOW_PITCHING)) data >> s_pitch; data >> fallTime; + if (HasMovementFlag(MOVEFLAG_FALLING)) { - data >> j_velocity; - data >> j_sinAngle; - data >> j_cosAngle; - data >> j_xyspeed; + data >> jump.velocity; + data >> jump.sinAngle; + data >> jump.cosAngle; + data >> jump.xyspeed; } if (HasMovementFlag(MOVEFLAG_SPLINE_ELEVATION)) data >> u_unk1; } -void MovementInfo::Write(ByteBuffer &data) const +void MovementInfo::Write(ByteBuffer &data, bool full) const { - data << moveFlags; - data << moveFlags2; - data << time; - data << pos.x; - data << pos.y; - data << pos.z; - data << pos.o; + if (full) + { + data << moveFlags; + data << moveFlags2; + data << time; + data << pos.x; + data << pos.y; + data << pos.z; + data << pos.o; + } if (HasMovementFlag(MOVEFLAG_ONTRANSPORT)) { @@ -208,28 +217,35 @@ void MovementInfo::Write(ByteBuffer &data) const data << t_pos.z; data << t_pos.o; data << t_time; + + if(moveFlags2 & MOVEFLAG2_INTERP_MOVEMENT) + data << t_time2; } - if (HasMovementFlag(MovementFlags(MOVEFLAG_SWIMMING | SPLINEFLAG_FLYINGING2))) + if ((HasMovementFlag(MovementFlags(MOVEFLAG_SWIMMING | MOVEFLAG_FLYING))) || (moveFlags2 & MOVEFLAG2_ALLOW_PITCHING)) + { data << s_pitch; + } data << fallTime; if (HasMovementFlag(MOVEFLAG_FALLING)) { - data << j_velocity; - data << j_sinAngle; - data << j_cosAngle; - data << j_xyspeed; + data << jump.velocity; + data << jump.sinAngle; + data << jump.cosAngle; + data << jump.xyspeed; } if (HasMovementFlag(MOVEFLAG_SPLINE_ELEVATION)) + { data << u_unk1; + } } Unit::Unit() : WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostilRefManager(this) -, IsAIEnabled(false), NeedChangeAI(false) +, IsAIEnabled(false), NeedChangeAI(false), movespline(new Movement::MoveSpline()) , i_AI(NULL), i_disabledAI(NULL), m_procDeep(0), m_AI_locked(false), m_removedAurasCount(0) { m_modAuras = new AuraList[TOTAL_AURAS]; @@ -318,7 +334,6 @@ Unit::Unit() } m_charmInfo = NULL; - m_unit_movement_flags = 0; m_reducedThreatPercent = 0; m_misdirectionTargetGUID = 0; @@ -366,11 +381,8 @@ Unit::~Unit() RemoveAllDynObjects(); _DeleteAuras(); - if (m_charmInfo) - { - delete m_charmInfo; - m_charmInfo = NULL; - } + delete m_charmInfo; + delete movespline; for (int i = 0; i < TOTAL_AURAS; i++) { @@ -431,6 +443,7 @@ void Unit::Update(uint32 update_diff, uint32 p_time) ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, GetHealth() < GetMaxHealth()*0.20f); ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, GetHealth() < GetMaxHealth()*0.35f); + UpdateSplineMovement(p_time); i_motionMaster.UpdateMotion(p_time); } @@ -442,32 +455,6 @@ bool Unit::haveOffhandWeapon() const return m_canDualWield; } -void Unit::SendMonsterMoveWithSpeedToCurrentDestination(Player* player) -{ - float x, y, z; - if (!IsStopped() && GetMotionMaster()->GetDestination(x, y, z)) - SendMonsterMoveWithSpeed(x, y, z, 0, player); -} - -void Unit::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime, Player* player) -{ - if (!transitTime) - { - if (GetTypeId() == TYPEID_PLAYER) - { - Traveller traveller(*(Player*)this); - transitTime = traveller.GetTotalTrevelTimeTo(x,y,z); - } - else - { - Traveller traveller(*(Creature*)this); - transitTime = traveller.GetTotalTrevelTimeTo(x,y,z); - } - } - //float orientation = (float)atan2((double)dy, (double)dx); - SendMonsterMove(x, y, z, transitTime, player); -} - void Unit::SendMonsterStop() { WorldPacket data(SMSG_MONSTER_MOVE, (17 + GetPackGUID().size())); @@ -476,87 +463,6 @@ void Unit::SendMonsterStop() data << WorldTimer::getMSTime(); data << uint8(1); SendMessageToSet(&data, true); - - clearUnitState(UNIT_STAT_MOVE); -} - -void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player) -{ - WorldPacket data(SMSG_MONSTER_MOVE, (41 + GetPackGUID().size())); - data << GetPackGUID(); - - data << GetPositionX() << GetPositionY() << GetPositionZ(); - data << WorldTimer::getMSTime(); - - data << uint8(0); - data << uint32((GetUnitMovementFlags() & MOVEFLAG_LEVITATING) ? SPLINEFLAG_FLYING : SPLINEFLAG_WALKMODE); - - data << Time; // Time in between points - data << uint32(1); // 1 single waypoint - data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B - - if (player) - player->GetSession()->SendPacket(&data); - else - SendMessageToSet(&data, true); - - addUnitState(UNIT_STAT_MOVE); -} - -void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player *player) -{ - WorldPacket data(SMSG_MONSTER_MOVE, 12+4+1+4+4+4+12+GetPackGUID().size()); - data << GetPackGUID(); - - data << uint8(0); // new in 3.1 - data << GetPositionX() << GetPositionY() << GetPositionZ(); - data << WorldTimer::getMSTime(); - - data << uint8(0); - data << MoveFlags; - - if (MoveFlags & SPLINEFLAG_JUMP) - { - data << time; - data << speedZ; - data << (uint32)0; // walk time after jump - } - else - data << time; - - data << uint32(1); // 1 single waypoint - data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B - - if (player) - player->GetSession()->SendPacket(&data); - else - SendMessageToSet(&data, true); -} - -void Unit::SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end) -{ - uint32 traveltime = uint32(path.GetTotalLength(start, end) * 32); - - uint32 pathSize = end-start; - - WorldPacket data(SMSG_MONSTER_MOVE, (GetPackGUID().size()+4+4+4+4+1+4+4+4+pathSize*4*3)); - data << GetPackGUID(); - data << GetPositionX(); - data << GetPositionY(); - data << GetPositionZ(); - - data << uint32(WorldTimer::getMSTime()); - - data << uint8(0); - data << uint32(((GetUnitMovementFlags() & MOVEFLAG_LEVITATING) || isInFlight())? (SPLINEFLAG_FLYING|SPLINEFLAG_WALKMODE) : SPLINEFLAG_WALKMODE); - data << uint32(traveltime); - data << uint32(pathSize); - data.append((char*)path.GetNodes(start), pathSize * 4 * 3); - - //WPAssert(data.size() == 37 + pathnodes.Size() * 4 * 3); - SendMessageToSet(&data, true); - - addUnitState(UNIT_STAT_MOVE); } void Unit::resetAttackTimer(WeaponAttackType type) @@ -807,7 +713,7 @@ bool SpellCantDealDmgToPlayer(uint32 id) uint32 Unit::DealDamage(DamageLog *damageInfo, DamageEffectType damagetype, const SpellEntry *spellProto, bool durabilityLoss) { Unit *pVictim = damageInfo->target; - if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode() || pVictim->HasAura(27827, 2)) + if (!pVictim->isAlive() || pVictim->IsTaxiFlying() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode() || pVictim->HasAura(27827, 2)) return 0; //You don't lose health from damage taken from another player while in a sanctuary @@ -1478,7 +1384,7 @@ void Unit::DealSpellDamage(SpellDamageLog *damageInfo, bool durabilityLoss) if (!this || !pVictim) return; - if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) + if (!pVictim->isAlive() || pVictim->IsTaxiFlying() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) return; SpellEntry const *spellProto = sSpellStore.LookupEntry(damageInfo->spell_id); @@ -1601,7 +1507,7 @@ void Unit::DealMeleeDamage(MeleeDamageLog *damageInfo, bool durabilityLoss) if (!this || !pVictim) return; - if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) + if (!pVictim->isAlive() || pVictim->IsTaxiFlying() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) return; //You don't lose health from damage taken from another player while in a sanctuary @@ -2117,7 +2023,7 @@ bool Unit::CalcBinaryResist(Unit *pVictim, SpellSchoolMask schoolMask) { void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool extra) { - if (!extra && hasUnitState(UNIT_STAT_CANNOT_AUTOATTACK) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) + if (!extra || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) return; if (!pVictim->isAlive()) @@ -3234,7 +3140,6 @@ void Unit::SetCurrentCastedSpell(Spell * pSpell) InterruptSpell(CURRENT_AUTOREPEAT_SPELL); m_AutoRepeatFirstCast = true; } - addUnitState(UNIT_STAT_CASTING); } break; case CURRENT_CHANNELED_SPELL: @@ -3247,7 +3152,6 @@ void Unit::SetCurrentCastedSpell(Spell * pSpell) if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351) InterruptSpell(CURRENT_AUTOREPEAT_SPELL); - addUnitState(UNIT_STAT_CASTING); } break; case CURRENT_AUTOREPEAT_SPELL: @@ -3376,21 +3280,22 @@ bool Unit::isInFront(GameObject const* target, float distance, float arc) const void Unit::SetInFront(Unit const* target) { - // update orientation at server - if (!hasUnitState(UNIT_STAT_CANNOT_TURN)) - SetOrientation(GetAngle(target)); + SetOrientation(GetAngle(target)); +} + +void Unit::SetFacingTo(float ori) +{ + Movement::MoveSplineInit init(*this); + init.SetFacing(ori); + init.Launch(); } void Unit::SetFacingToObject(WorldObject* pObject) { - // update orientation at server - if (!hasUnitState(UNIT_STAT_CANNOT_TURN)) - SetOrientation(GetAngle(pObject)); + if (!IsStopped()) + return; - // and client - WorldPacket data; - BuildHeartBeatMsg(&data); - SendMessageToSet(&data, false); + SetFacingTo(GetAngle(pObject)); } bool Unit::isInBack(Unit const* target, float distance, float arc) const @@ -3447,9 +3352,9 @@ bool Unit::isBetween(WorldObject *s, WorldObject *e, float offset) const bool Unit::isInAccessiblePlacefor (Creature const* c) const { if (IsInWater()) - return c->canSwim(); + return c->CanSwim(); else - return c->canWalk() || c->canFly(); + return c->CanWalk() || c->CanFly(); } bool Unit::IsInWater() const @@ -9180,7 +9085,7 @@ bool Unit::isAttackableByAOE() const if (GetTypeId()==TYPEID_PLAYER && ((Player *)this)->isGameMaster()) return false; - return !isInFlight(); + return !IsTaxiFlying(); } int32 Unit::ModifyHealth(int32 dVal) @@ -9391,13 +9296,32 @@ void Unit::SetVisibility(UnitVisibility x) void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) { - int32 main_speed_mod = 0; - float stack_bonus = 1.0f; - float non_stack_bonus = 1.0f; + // not in combat pet have same speed as owner + switch (mtype) + { + case MOVE_RUN: + case MOVE_WALK: + case MOVE_SWIM: + if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet() && hasUnitState(UNIT_STAT_FOLLOW)) + { + if(Unit* owner = GetOwner()) + { + SetSpeed(mtype, owner->GetSpeedRate(mtype), forced); + return; + } + } + break; + default: + break; + } if (GetTypeId() == TYPEID_PLAYER) ((Player *)this)->m_AC_timer = 2000; + int32 main_speed_mod = 0; + float stack_bonus = 1.0f; + float non_stack_bonus = 1.0f; + switch (mtype) { case MOVE_WALK: @@ -9446,10 +9370,6 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) float bonus = non_stack_bonus > stack_bonus ? non_stack_bonus : stack_bonus; - //apply creature's base speed - if (GetTypeId() == TYPEID_UNIT) - bonus *= ((Creature*)this)->GetBaseSpeed(); - // now we ready for speed calculation float speed = main_speed_mod ? bonus*(100.0f + main_speed_mod)/100.0f : bonus; @@ -9474,9 +9394,11 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) break; } - if (Unit* owner = GetOwner()) { - float owner_speed = owner->GetMaxSpeedRate(mtype) * 1.1f; - speed = owner_speed > speed ? owner_speed : speed; + // for creature case, we check explicit if mob searched for assistance + if (GetTypeId() == TYPEID_UNIT) + { + if (((Creature*)this)->HasSearchedAssistance()) + speed *= 0.66f; // best guessed value, so this will be 33% reduction. Based off initial speed, mob can then "run", "walk fast" or "walk". } // Apply strongest slow aura mod to speed @@ -9486,16 +9408,20 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) if (slow) speed *=(100.0f + slow)/100.0f; - //store max possible speed - m_max_speed_rate[mtype] = speed; - - // on follow TMG handels speed change - if (!hasUnitState(UNIT_STAT_FOLLOW)) - SetSpeed(mtype, speed, forced); + if (GetTypeId() == TYPEID_UNIT) + { + switch(mtype) + { + case MOVE_RUN: + case MOVE_WALK: + speed *= ((Creature*)this)->GetCreatureInfo()->speed; + break; + default: + break; + } + } - // update speed of pets - if (Pet *pet = GetPet()) - pet->UpdateSpeed(mtype, forced); + SetSpeed(mtype, speed, forced); } float Unit::GetSpeed(UnitMoveType mtype) const @@ -9509,108 +9435,54 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) rate = 0.0f; // Update speed only on change - if (m_speed_rate[mtype] == rate) - return; - - if (GetTypeId() == TYPEID_PLAYER) - ((Player *)this)->m_AC_timer = 2000; - - m_speed_rate[mtype] = rate; - - propagateSpeedChange(); + if (m_speed_rate[mtype] != rate) + { + m_speed_rate[mtype] = rate; + propagateSpeedChange(); - // Send speed change packet only for player - if (GetTypeId()!=TYPEID_PLAYER) - return; + const uint16 SetSpeed2Opc_table[MAX_MOVE_TYPE][2]= + { + {MSG_MOVE_SET_WALK_SPEED, SMSG_FORCE_WALK_SPEED_CHANGE}, + {MSG_MOVE_SET_RUN_SPEED, SMSG_FORCE_RUN_SPEED_CHANGE}, + {MSG_MOVE_SET_RUN_BACK_SPEED, SMSG_FORCE_RUN_BACK_SPEED_CHANGE}, + {MSG_MOVE_SET_SWIM_SPEED, SMSG_FORCE_SWIM_SPEED_CHANGE}, + {MSG_MOVE_SET_SWIM_BACK_SPEED, SMSG_FORCE_SWIM_BACK_SPEED_CHANGE}, + {MSG_MOVE_SET_TURN_RATE, SMSG_FORCE_TURN_RATE_CHANGE}, + {MSG_MOVE_SET_FLIGHT_SPEED, SMSG_FORCE_FLIGHT_SPEED_CHANGE}, + {MSG_MOVE_SET_FLIGHT_BACK_SPEED,SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE} + }; - WorldPacket data; - if (!forced) - { - switch (mtype) + if (forced) { - case MOVE_WALK: - data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+1+4+4+4+4+4+4+4); - break; - case MOVE_RUN: - data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+1+4+4+4+4+4+4+4); - break; - case MOVE_RUN_BACK: - data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); - break; - case MOVE_SWIM: - data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+1+4+4+4+4+4+4+4); - break; - case MOVE_SWIM_BACK: - data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); - break; - case MOVE_TURN_RATE: - data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+1+4+4+4+4+4+4+4); - break; - case MOVE_FLIGHT: - data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+1+4+4+4+4+4+4+4); - break; - case MOVE_FLIGHT_BACK: - data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); - break; - default: - sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype); - return; - } + if (GetTypeId() == TYPEID_PLAYER) + { + // register forced speed changes for WorldSession::HandleForceSpeedChangeAck + // and do it only for real sent packets and use run for run/mounted as client expected + ++((Player*)this)->m_forced_speed_changes[mtype]; + } - data << GetPackGUID(); - data << uint32(0); //movement flags - data << uint8(0); //unk - data << uint32(WorldTimer::getMSTime()); - data << float(GetPositionX()); - data << float(GetPositionY()); - data << float(GetPositionZ()); - data << float(GetOrientation()); - data << uint32(0); //flag unk - data << float(GetSpeed(mtype)); - SendMessageToSet(&data, true); - } - else - { - // register forced speed changes for WorldSession::HandleForceSpeedChangeAck - // and do it only for real sent packets and use run for run/mounted as client expected - ++((Player*)this)->m_forced_speed_changes[mtype]; - switch (mtype) + WorldPacket data(SetSpeed2Opc_table[mtype][1], 18); + data << GetPackGUID(); + data << (uint32)0; // moveEvent, NUM_PMOVE_EVTS = 0x39 + if (mtype == MOVE_RUN) + data << uint8(0); // new 2.1.0 + data << float(GetSpeed(mtype)); + SendMessageToSet(&data, true); + } + else { - case MOVE_WALK: - data.Initialize(SMSG_FORCE_WALK_SPEED_CHANGE, 16); - break; - case MOVE_RUN: - data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17); - break; - case MOVE_RUN_BACK: - data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16); - break; - case MOVE_SWIM: - data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16); - break; - case MOVE_SWIM_BACK: - data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16); - break; - case MOVE_TURN_RATE: - data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16); - break; - case MOVE_FLIGHT: - data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16); - break; - case MOVE_FLIGHT_BACK: - data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16); - break; - default: - sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype); - return; + m_movementInfo.UpdateTime(WorldTimer::getMSTime()); + + WorldPacket data(SetSpeed2Opc_table[mtype][0], 64); + data << GetPackGUID(); + data << m_movementInfo; + data << float(GetSpeed(mtype)); + SendMessageToSet(&data, true); } - data << GetPackGUID(); - data << (uint32)0; // moveEvent, NUM_PMOVE_EVTS = 0x39 - if (mtype == MOVE_RUN) - data << uint8(0); // new 2.1.0 - data << float(GetSpeed(mtype)); - SendMessageToSet(&data, true); } + + //CallForAllControlledUnits(SetSpeedRateHelper(mtype,forced), CONTROLLED_PET|CONTROLLED_GUARDIANS|CONTROLLED_CHARM|CONTROLLED_MINIPET); + } void Unit::setDeathState(DeathState s) @@ -9630,7 +9502,10 @@ void Unit::setDeathState(DeathState s) { RemoveAllAurasOnDeath(); UnsummonAllTotems(); + StopMoving(); + DisableSpline(); + ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); // remove aurastates allowing special moves @@ -11313,14 +11188,9 @@ void Unit::StopMoving() if (!IsInWorld()) return; - Relocate(GetPositionX(), GetPositionY(),GetPositionZ()); - - SendMonsterStop(); - - // update position and orientation; - WorldPacket data; - BuildHeartBeatMsg(&data); - SendMessageToSet(&data,false); + Movement::MoveSplineInit init(*this); + init.SetFacing(GetOrientation()); + init.Launch(); } bool Unit::IsSitState() const @@ -11895,30 +11765,28 @@ void Unit::RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo, Unit * cast void Unit::NearTeleportTo(float x, float y, float z, float orientation, bool casting /*= false*/ ) { + DisableSpline(); + if (GetTypeId() == TYPEID_PLAYER) ((Player*)this)->TeleportTo(GetMapId(), x, y, z, orientation, TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (casting ? TELE_TO_SPELL : 0)); else { + Creature* c = (Creature*)this; + // Creature relocation acts like instant movement generator, so current generator expects interrupt/reset calls to react properly + if (!c->GetMotionMaster()->empty()) + if (MovementGenerator *movgen = c->GetMotionMaster()->top()) + movgen->Interrupt(*c); + GetMap()->CreatureRelocation(((Creature*)this), x, y, z, orientation); - WorldPacket data; - BuildHeartBeatMsg(&data); - SendMessageToSet(&data, false); - } -} + SendHeartBeat(); -void Unit::BuildHeartBeatMsg(WorldPacket *data) const -{ - data->Initialize(MSG_MOVE_HEARTBEAT, 32); - *data << GetPackGUID(); - *data << uint32(((GetUnitMovementFlags() & MOVEFLAG_LEVITATING) || isInFlight())? (SPLINEFLAG_FLYING|SPLINEFLAG_WALKMODE) : GetUnitMovementFlags()); - *data << uint8(0); // 2.3.0 - *data << uint32(WorldTimer::getMSTime()); // time - *data << float(GetPositionX()); - *data << float(GetPositionY()); - *data << float(GetPositionZ()); - *data << float(GetOrientation()); - *data << uint32(0); + // finished relocation, movegen can different from top before creature relocation, + // but apply Reset expected to be safe in any case + if (!c->GetMotionMaster()->empty()) + if (MovementGenerator *movgen = c->GetMotionMaster()->top()) + movgen->Reset(*c); + } } /*-----------------------TRINITY-----------------------------*/ @@ -12279,7 +12147,7 @@ void Unit::SetStunned(bool apply) if (GetTypeId() != TYPEID_PLAYER) ((Creature*)this)->StopMoving(); else - SetUnitMovementFlags(0); //Clear movement flags + m_movementInfo.SetMovementFlags(MOVEFLAG_NONE); //Clear movement flags WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8); data << GetPackGUID(); @@ -12315,7 +12183,7 @@ void Unit::SetRooted(bool apply) if (GetTypeId() == TYPEID_PLAYER) { - SetUnitMovementFlags(0); + m_movementInfo.SetMovementFlags(MOVEFLAG_NONE); WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10); data << GetPackGUID(); @@ -12342,13 +12210,6 @@ void Unit::SetRooted(bool apply) } } -void Unit::SendMovementFlagUpdate() -{ - WorldPacket data; - BuildHeartBeatMsg(&data); - SendMessageToSet(&data, false); -} - void Unit::SetFeared(bool apply) { if (apply) @@ -12379,20 +12240,6 @@ void Unit::SetFeared(bool apply) ((Player*)this)->SetClientControl(this, !apply); } -void Unit::SetFlying(bool apply) -{ - if (apply) - { - SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0x02); - AddUnitMovementFlag(SPLINEFLAG_FLYINGING + SPLINEFLAG_FLYINGING2); - } - else - { - RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, 0x02); - RemoveUnitMovementFlag(SPLINEFLAG_FLYINGING + SPLINEFLAG_FLYINGING2); - } -} - void Unit::SetConfused(bool apply) { if (apply) @@ -12419,13 +12266,15 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess) if (this == charmer) return; - if (isInFlight()) + if (IsTaxiFlying()) return; if (GetTypeId() == TYPEID_PLAYER && ((Player*)this)->GetTransport()) return; - RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + if (GetTypeId() == TYPEID_UNIT) + ((Creature*)this)->SetWalk(false); + CastStop(); CombatStop(); //TODO: CombatStop(true) may cause crash (interrupt spells) DeleteThreatList(); @@ -12478,7 +12327,6 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess) //Set possessed if (possess) { - addUnitState(UNIT_STAT_POSSESSED); SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); AddPlayerToVision((Player*)charmer); ((Player*)charmer)->SetViewport(GetGUID(), true); @@ -12518,7 +12366,7 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer) else if (charmer != GetCharmer()) // one aura overrides another? return; - bool possess = hasUnitState(UNIT_STAT_POSSESSED); + bool possess = isPossessed(); CastStop(); CombatStop(); //TODO: CombatStop(true) may cause crash (interrupt spells) @@ -12526,13 +12374,12 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer) DeleteThreatList(); SetCharmerGUID(0); RestoreFaction(); - GetMotionMaster()->InitDefault(); + + // Will work as needed /? + GetMotionMaster()->Initialize(); if (possess) - { - clearUnitState(UNIT_STAT_POSSESSED); RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); - } if (GetTypeId() == TYPEID_UNIT) { @@ -12777,7 +12624,7 @@ void Unit::KnockBackFrom(Unit* target, float horizintalSpeed, float verticalSpee // Effect propertly implemented only for players if (GetTypeId() == TYPEID_PLAYER) { - WorldPacket data(SMSG_MOVE_KNOCK_BACK, 8+4+4+4+4+4); + WorldPacket data(SMSG_MOVE_KNOCK_BACK, 9+4+4+4+4+4); data << GetPackGUID(); data << uint32(0); // Sequence data << float(vcos); // x direction @@ -12790,8 +12637,10 @@ void Unit::KnockBackFrom(Unit* target, float horizintalSpeed, float verticalSpee } else { - float dis = horizintalSpeed; + float moveTimeHalf = verticalSpeed / Movement::gravity; + float max_height = -Movement::computeFallElevation(moveTimeHalf,false,-verticalSpeed); + float dis = 2 * moveTimeHalf * horizintalSpeed; float ox, oy, oz; GetPosition(ox, oy, oz); @@ -12808,9 +12657,7 @@ void Unit::KnockBackFrom(Unit* target, float horizintalSpeed, float verticalSpee UpdateGroundPositionZ(fx, fy, fz); } - //FIXME: this mostly hack, must exist some packet for proper creature move at client side - // with CreatureRelocation at server side - GetMap()->CreatureRelocation(((Creature*)this), fx, fy, fz, GetOrientation()); + GetMotionMaster()->MoveJump(fx,fy,fz,horizintalSpeed,max_height); } } @@ -12872,3 +12719,54 @@ Unit* Unit::GetNextRandomRaidMember(float radius) uint32 randTarget = GetMap()->urand(0,nearMembers.size()-1); return nearMembers[randTarget]; } + +void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed) +{ + Movement::MoveSplineInit init(*this); + init.MoveTo(x,y,z); + init.SetVelocity(speed); + init.Launch(); +} + +void Unit::UpdateSplineMovement(uint32 t_diff) +{ + enum{ + POSITION_UPDATE_DELAY = 400, + }; + + if (movespline->Finalized()) + return; + + movespline->updateState(t_diff); + bool arrived = movespline->Finalized(); + + if (arrived) + DisableSpline(); + + m_movesplineTimer.Update(t_diff); + if (m_movesplineTimer.Passed() || arrived) + { + m_movesplineTimer.Reset(POSITION_UPDATE_DELAY); + Movement::Location loc = movespline->ComputePosition(); + + if (GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->SetPosition(loc.x,loc.y,loc.z,loc.orientation); + else + GetMap()->CreatureRelocation((Creature*)this,loc.x,loc.y,loc.z,loc.orientation); + } +} + +void Unit::DisableSpline() +{ + m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEFLAG_SPLINE_ENABLED|MOVEFLAG_FORWARD)); + movespline->_Interrupt(); +} + +void Unit::SendHeartBeat() +{ + m_movementInfo.UpdateTime(WorldTimer::getMSTime()); + WorldPacket data(MSG_MOVE_HEARTBEAT, 64); + data << GetPackGUID(); + data << m_movementInfo; + SendMessageToSet(&data, true); +} diff --git a/src/game/Unit.h b/src/game/Unit.h index a76cb7b5c..c336a4ee5 100755 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -267,7 +267,6 @@ class DynamicObject; class GameObject; class Item; class Pet; -class Path; class PetAura; class UnitAI; @@ -373,37 +372,66 @@ enum DeathState DEAD_FALLING= 5 }; +// internal state flags for some auras and movement generators, other. enum UnitState { - UNIT_STAT_DIED = 0x00000001, - UNIT_STAT_MELEE_ATTACKING = 0x00000002, // player is melee attacking someone - //UNIT_STAT_MELEE_ATTACK_BY = 0x00000004, // player is melee attack by someone - UNIT_STAT_STUNNED = 0x00000008, - UNIT_STAT_ROAMING = 0x00000010, - UNIT_STAT_CHASE = 0x00000020, - //UNIT_STAT_SEARCHING = 0x00000040, - UNIT_STAT_FLEEING = 0x00000080, - UNIT_STAT_IN_FLIGHT = 0x00000100, // player is in flight mode - UNIT_STAT_FOLLOW = 0x00000200, - UNIT_STAT_ROOT = 0x00000400, - UNIT_STAT_CONFUSED = 0x00000800, - UNIT_STAT_DISTRACTED = 0x00001000, - UNIT_STAT_ISOLATED = 0x00002000, // area auras do not affect other players - UNIT_STAT_ATTACK_PLAYER = 0x00004000, - UNIT_STAT_CASTING = 0x00008000, - UNIT_STAT_POSSESSED = 0x00010000, - UNIT_STAT_CHARGING = 0x00020000, - UNIT_STAT_JUMPING = 0x00040000, - UNIT_STAT_MOVE = 0x00100000, - UNIT_STAT_ROTATING = 0x00200000, - UNIT_STAT_EVADE = 0x00400000, - UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE), - UNIT_STAT_LOST_CONTROL = (UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_CHARGING), - UNIT_STAT_SIGHTLESS = (UNIT_STAT_LOST_CONTROL), - UNIT_STAT_NOT_MOVE = (UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_DISTRACTED), - UNIT_STAT_CANNOT_AUTOATTACK = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_CASTING), - UNIT_STAT_CANNOT_TURN = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_ROTATING), - UNIT_STAT_ALL_STATE = 0xffffffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT) + // persistent state (applied by aura/etc until expire) + UNIT_STAT_MELEE_ATTACKING = 0x00000001, // unit is melee attacking someone Unit::Attack + UNIT_STAT_ATTACK_PLAYER = 0x00000002, // unit attack player or player's controlled unit and have contested pvpv timer setup, until timer expire, combat end and etc + UNIT_STAT_DIED = 0x00000004, // Unit::SetFeignDeath + UNIT_STAT_STUNNED = 0x00000008, // Aura::HandleAuraModStun + UNIT_STAT_ROOT = 0x00000010, // Aura::HandleAuraModRoot + UNIT_STAT_ISOLATED = 0x00000020, // area auras do not affect other players, Aura::HandleAuraModSchoolImmunity + UNIT_STAT_CONTROLLED = 0x00000040, // Aura::HandleAuraModPossess + + // persistent movement generator state (all time while movement generator applied to unit (independent from top state of movegen) + UNIT_STAT_TAXI_FLIGHT = 0x00000080, // player is in flight mode (in fact interrupted at far teleport until next map telport landing) + UNIT_STAT_DISTRACTED = 0x00000100, // DistractedMovementGenerator active + + // persistent movement generator state with non-persistent mirror states for stop support + // (can be removed temporary by stop command or another movement generator apply) + // not use _MOVE versions for generic movegen state, it can be removed temporary for unit stop and etc + UNIT_STAT_CONFUSED = 0x00000200, // ConfusedMovementGenerator active/onstack + UNIT_STAT_CONFUSED_MOVE = 0x00000400, + UNIT_STAT_ROAMING = 0x00000800, // RandomMovementGenerator/PointMovementGenerator/WaypointMovementGenerator active (now always set) + UNIT_STAT_ROAMING_MOVE = 0x00001000, + UNIT_STAT_CHASE = 0x00002000, // ChaseMovementGenerator active + UNIT_STAT_CHASE_MOVE = 0x00004000, + UNIT_STAT_FOLLOW = 0x00008000, // FollowMovementGenerator active + UNIT_STAT_FOLLOW_MOVE = 0x00010000, + UNIT_STAT_FLEEING = 0x00020000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack + UNIT_STAT_FLEEING_MOVE = 0x00040000, + + // masks (only for check) + + // can't move currently + UNIT_STAT_CAN_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED, + + // stay by different reasons + UNIT_STAT_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | + UNIT_STAT_DISTRACTED, + + // stay or scripted movement for effect( = in player case you can't move by client command) + UNIT_STAT_NO_FREE_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | + UNIT_STAT_TAXI_FLIGHT | + UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING, + + // not react at move in sight or other + UNIT_STAT_CAN_NOT_REACT = UNIT_STAT_STUNNED | UNIT_STAT_DIED | + UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING, + + // AI disabled by some reason + UNIT_STAT_LOST_CONTROL = UNIT_STAT_FLEEING | UNIT_STAT_CONTROLLED, + + // above 2 state cases + UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL = UNIT_STAT_CAN_NOT_REACT | UNIT_STAT_LOST_CONTROL, + + // masks (for check or reset) + + // for real move using movegen check and stop (except unstoppable flight) + UNIT_STAT_MOVING = UNIT_STAT_ROAMING_MOVE | UNIT_STAT_CHASE_MOVE | UNIT_STAT_FOLLOW_MOVE | UNIT_STAT_FLEEING_MOVE, + + UNIT_STAT_ALL_STATE = 0xFFFFFFFF }; enum UnitStandStateType @@ -572,6 +600,7 @@ enum NPCFlags UNIT_NPC_FLAG_OUTDOORPVP = 0x20000000, // custom flag for outdoor pvp creatures }; +// used in most movement packets (send and received) enum MovementFlags { MOVEFLAG_NONE = 0x00000000, @@ -583,52 +612,126 @@ enum MovementFlags MOVEFLAG_TURN_RIGHT = 0x00000020, MOVEFLAG_PITCH_UP = 0x00000040, MOVEFLAG_PITCH_DOWN = 0x00000080, - SPLINEFLAG_WALKMODE_MODE = 0x00000100, // Walking - MOVEFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures + MOVEFLAG_WALK_MODE = 0x00000100, // Walking + MOVEFLAG_ONTRANSPORT = 0x00000200, MOVEFLAG_LEVITATING = 0x00000400, MOVEFLAG_ROOT = 0x00000800, MOVEFLAG_FALLING = 0x00001000, - MOVEFLAG_FALLINGFAR = 0x00004000, + MOVEFLAG_FALLINGFAR = 0x00002000, + /*MOVEFLAG_PENDINGSTOP = 0x00004000, + MOVEFLAG_PENDINGSTRAFESTOP = 0x00008000, + MOVEFLAG_PENDINGFORWARD = 0x00010000, + MOVEFLAG_PENDINGBACKWARD = 0x00020000, + MOVEFLAG_PENDINGSTRAFELEFT = 0x00040000, + MOVEFLAG_PENDINGSTRAFERIGHT = 0x00080000, + MOVEFLAG_PENDINGROOT = 0x00100000,*/ MOVEFLAG_SWIMMING = 0x00200000, // appears with fly flag also MOVEFLAG_ASCENDING = 0x00400000, // swim up also - MOVEFLAG_CAN_FLY = 0x00800000, - SPLINEFLAG_FLYINGING = 0x01000000, - SPLINEFLAG_FLYINGING2 = 0x02000000, // Actual flying mode + MOVEFLAG_CAN_FLY = 0x00800000, // can fly in 2.4.3? + MOVEFLAG_DESCENDING = 0x01000000, // proper ? + MOVEFLAG_FLYING = 0x02000000, // Actual flying mode MOVEFLAG_SPLINE_ELEVATION = 0x04000000, // used for flight paths MOVEFLAG_SPLINE_ENABLED = 0x08000000, // used for flight paths MOVEFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water MOVEFLAG_SAFE_FALL = 0x20000000, // active rogue safe fall spell (passive) - MOVEFLAG_HOVER = 0x40000000, - - MOVEFLAG_MOVING = - MOVEFLAG_FORWARD |MOVEFLAG_BACKWARD |MOVEFLAG_STRAFE_LEFT |MOVEFLAG_STRAFE_RIGHT| - MOVEFLAG_PITCH_UP|MOVEFLAG_PITCH_DOWN|MOVEFLAG_ROOT | - MOVEFLAG_FALLING |MOVEFLAG_FALLINGFAR|MOVEFLAG_ASCENDING | - SPLINEFLAG_FLYINGING2 |MOVEFLAG_SPLINE_ELEVATION, - MOVEFLAG_TURNING = - MOVEFLAG_TURN_LEFT | MOVEFLAG_TURN_RIGHT, + MOVEFLAG_HOVER = 0x40000000 +}; + +// flags that use in movement check for example at spell casting +MovementFlags const movementFlagsMask = MovementFlags( + MOVEFLAG_FORWARD |MOVEFLAG_BACKWARD |MOVEFLAG_STRAFE_LEFT |MOVEFLAG_STRAFE_RIGHT| + MOVEFLAG_PITCH_UP|MOVEFLAG_PITCH_DOWN|MOVEFLAG_ROOT | + MOVEFLAG_FALLING |MOVEFLAG_FALLINGFAR|MOVEFLAG_ASCENDING | + MOVEFLAG_FLYING |MOVEFLAG_SPLINE_ELEVATION +); + +MovementFlags const movementOrTurningFlagsMask = MovementFlags( + movementFlagsMask | MOVEFLAG_TURN_LEFT | MOVEFLAG_TURN_RIGHT +); + +enum MovementFlags2 +{ + MOVEFLAG2_NONE = 0x0000, + MOVEFLAG2_NO_STRAFE = 0x0001, + MOVEFLAG2_NO_JUMPING = 0x0002, + MOVEFLAG2_UNK3 = 0x0004, + MOVEFLAG2_FULLSPEEDTURNING = 0x0008, + MOVEFLAG2_FULLSPEEDPITCHING = 0x0010, + MOVEFLAG2_ALLOW_PITCHING = 0x0020, + MOVEFLAG2_UNK4 = 0x0040, + MOVEFLAG2_UNK5 = 0x0080, + MOVEFLAG2_UNK6 = 0x0100, // transport related + MOVEFLAG2_UNK7 = 0x0200, + MOVEFLAG2_INTERP_MOVEMENT = 0x0400, + MOVEFLAG2_INTERP_TURNING = 0x0800, + MOVEFLAG2_INTERP_PITCHING = 0x1000, + MOVEFLAG2_UNK8 = 0x2000, + MOVEFLAG2_UNK9 = 0x4000, + MOVEFLAG2_UNK10 = 0x8000, + MOVEFLAG2_INTERP_MASK = MOVEFLAG2_INTERP_MOVEMENT | MOVEFLAG2_INTERP_TURNING | MOVEFLAG2_INTERP_PITCHING }; -// used in SMSG_MONSTER_MOVE -// only some values known as correct for 2.4.3 enum SplineFlags { - SPLINEFLAG_NONE = 0x00000000, - SPLINEFLAG_JUMP = 0x00000008, - SPLINEFLAG_WALKMODE = 0x00000100, - SPLINEFLAG_FLYING = 0x00000200, - }; + SPLINEFLAG_NONE = 0x00000000, + SPLINEFLAG_FORWARD = 0x00000001, + SPLINEFLAG_BACKWARD = 0x00000002, + SPLINEFLAG_STRAFE_LEFT = 0x00000004, + SPLINEFLAG_STRAFE_RIGHT = 0x00000008, + SPLINEFLAG_LEFT = 0x00000010, + SPLINEFLAG_RIGHT = 0x00000020, + SPLINEFLAG_PITCH_UP = 0x00000040, + SPLINEFLAG_PITCH_DOWN = 0x00000080, + SPLINEFLAG_DONE = 0x00000100, + SPLINEFLAG_FALLING = 0x00000200, + SPLINEFLAG_NO_SPLINE = 0x00000400, + SPLINEFLAG_TRAJECTORY = 0x00000800, + SPLINEFLAG_WALKMODE = 0x00001000, + SPLINEFLAG_FLYING = 0x00002000, + SPLINEFLAG_KNOCKBACK = 0x00004000, + SPLINEFLAG_FINALPOINT = 0x00008000, + SPLINEFLAG_FINALTARGET = 0x00010000, + SPLINEFLAG_FINALFACING = 0x00020000, + SPLINEFLAG_CATMULLROM = 0x00040000, + SPLINEFLAG_UNKNOWN1 = 0x00080000, + SPLINEFLAG_UNKNOWN2 = 0x00100000, + SPLINEFLAG_UNKNOWN3 = 0x00200000, + SPLINEFLAG_UNKNOWN4 = 0x00400000, + SPLINEFLAG_UNKNOWN5 = 0x00800000, + SPLINEFLAG_UNKNOWN6 = 0x01000000, + SPLINEFLAG_UNKNOWN7 = 0x02000000, + SPLINEFLAG_UNKNOWN8 = 0x04000000, + SPLINEFLAG_UNKNOWN9 = 0x08000000, + SPLINEFLAG_UNKNOWN10 = 0x10000000, + SPLINEFLAG_UNKNOWN11 = 0x20000000, + SPLINEFLAG_UNKNOWN12 = 0x40000000 +}; + +enum SplineMode +{ + SPLINEMODE_LINEAR = 0, + SPLINEMODE_CATMULLROM = 1, + SPLINEMODE_BEZIER3 = 2 +}; + +enum SplineType +{ + SPLINETYPE_NORMAL = 0, + SPLINETYPE_STOP = 1, + SPLINETYPE_FACINGSPOT = 2, + SPLINETYPE_FACINGTARGET = 3, + SPLINETYPE_FACINGANGLE = 4 +}; class MovementInfo { public: - MovementInfo() : moveFlags(MOVEFLAG_NONE), moveFlags2(0), time(0), t_guid(0), - t_time(0), s_pitch(0.0f), fallTime(0), j_velocity(0.0f), j_sinAngle(0.0f), - j_cosAngle(0.0f), j_xyspeed(0.0f), u_unk1(0.0f) {} + MovementInfo() : moveFlags(MOVEFLAG_NONE), moveFlags2(MOVEFLAG2_NONE), time(0), + t_time(0), t_time2(0), s_pitch(0.0f), fallTime(0), u_unk1(0.0f) {} // Read/Write methods void Read(ByteBuffer &data); - void Write(ByteBuffer &data) const; + void Write(ByteBuffer &data, bool full = true) const; // Movement flags manipulations void AddMovementFlag(MovementFlags f) { moveFlags |= f; } @@ -636,6 +739,7 @@ class MovementInfo bool HasMovementFlag(MovementFlags f) const { return moveFlags & f; } MovementFlags GetMovementFlags() const { return MovementFlags(moveFlags); } void SetMovementFlags(MovementFlags f) { moveFlags = f; } + MovementFlags2 GetMovementFlags2() const { return MovementFlags2(moveFlags2); } // Position manipulations Position const *GetPos() const { return &pos; } @@ -661,27 +765,45 @@ class MovementInfo Position const *GetTransportPos() const { return &t_pos; } uint32 GetTransportTime() const { return t_time; } uint32 GetFallTime() const { return fallTime; } + void ChangeOrientation(float o) { pos.o = o; } void ChangePosition(float x, float y, float z, float o) { pos.x = x; pos.y = y; pos.z = z; pos.o = o; } void UpdateTime(uint32 _time) { time = _time; } - //private: + struct JumpInfo + { + JumpInfo() : velocity(0.f), sinAngle(0.f), cosAngle(0.f), xyspeed(0.f) {} + float velocity, sinAngle, cosAngle, xyspeed; + }; + + JumpInfo const& GetJumpInfo() const { return jump; } + uint32 const &GetTime() { return time; } + + private: // common - uint32 moveFlags; // see enum MovementFlags - uint8 moveFlags2; - uint32 time; + uint32 time; + + uint32 moveFlags; // see enum MovementFlags + uint8 moveFlags2; // see enum MovementFlags2 + Position pos; + // transport - uint64 t_guid; + uint64 t_guid; Position t_pos; - uint32 t_time; - // swimming and unknown - float s_pitch; + uint32 t_time; + uint32 t_time2; + + // swimming and flying + float s_pitch; + // last fall time - uint32 fallTime; + uint32 fallTime; + // jumping - float j_velocity, j_sinAngle, j_cosAngle, j_xyspeed; + JumpInfo jump; + // spline - float u_unk1; + float u_unk1; }; inline ByteBuffer& operator<< (ByteBuffer& buf, MovementInfo const& mi) @@ -696,6 +818,10 @@ inline ByteBuffer& operator>> (ByteBuffer& buf, MovementInfo& mi) return buf; } +namespace Movement{ + class MoveSpline; +} + enum DiminishingLevels { DIMINISHING_LEVEL_1 = 0, @@ -948,7 +1074,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject float GetObjectBoundingRadius() const // overwrite WorldObject version { - return m_floatValues[UNIT_FIELD_BOUNDINGRADIUS]; + return 1.0f; //m_floatValues[UNIT_FIELD_BOUNDINGRADIUS]; } DiminishingLevels GetDiminishing(DiminishingGroup group); @@ -1016,10 +1142,10 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void addUnitState(uint32 f) { m_state |= f; } bool hasUnitState(const uint32 f) const { return (m_state & f); } void clearUnitState(uint32 f) { m_state &= ~f; } + bool CanFreeMove() const { - return !hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_IN_FLIGHT | - UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED) && GetOwnerGUID()==0; + return !hasUnitState(UNIT_STAT_NO_FREE_MOVE) && !GetOwnerGUID(); } uint32 getLevel() const { return GetUInt32Value(UNIT_FIELD_LEVEL); } @@ -1171,7 +1297,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject //Need fix or use this bool isGuard() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GUARD); } - bool isInFlight() const { return hasUnitState(UNIT_STAT_IN_FLIGHT); } + bool IsTaxiFlying() const { return hasUnitState(UNIT_STAT_TAXI_FLIGHT); } bool isInCombat() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); } void CombatStart(Unit* target, bool initialAggro = true); @@ -1228,19 +1354,17 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo); void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false); + void MonsterMoveWithSpeed(float x, float y, float z, float speed); - void SendMonsterStop(); - void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player = NULL); - //void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); - void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end); - void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL); + void DisableSpline(); - void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL); - void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player *player = NULL); + void SendMonsterStop(); - void SendMovementFlagUpdate(); + void SetInFront(Unit const* target); + void SetFacingTo(float ori); + void SetFacingToObject(WorldObject* pObject); - void BuildHeartBeatMsg(WorldPacket *data) const; + void SendHeartBeat(); virtual void MoveOutOfRange(Player &) {}; @@ -1290,16 +1414,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void RestoreFaction(); bool isCharmed() const { return GetCharmerGUID() != 0; } - bool isPossessed() const { return hasUnitState(UNIT_STAT_POSSESSED); } - bool isPossessedByPlayer() const { return hasUnitState(UNIT_STAT_POSSESSED) && IS_PLAYER_GUID(GetCharmerGUID()); } - bool isPossessing() const - { - if (Unit *u = GetCharm()) - return u->isPossessed(); - else - return false; - } - bool isPossessing(Unit* u) const { return u->isPossessed() && GetCharmGUID() == u->GetGUID(); } + bool isPossessed() const { return HasAuraType(SPELL_AURA_MOD_POSSESS) || HasAuraType(SPELL_AURA_MOD_POSSESS_PET); } CharmInfo* GetCharmInfo() { return m_charmInfo; } CharmInfo* InitCharmInfo(); @@ -1436,8 +1551,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject bool isInFront(Unit const* target,float distance, float arc = M_PI) const; bool isInFront(GameObject const* target,float distance, float arc = M_PI) const; - void SetInFront(Unit const* target); - void SetFacingToObject(WorldObject* pObject); bool isInBack(Unit const* target, float distance, float arc = M_PI) const; bool isInBack(GameObject const* target, float distance, float arc = M_PI) const; bool isInLine(Unit const* target, float distance) const; @@ -1585,21 +1698,13 @@ class TRINITY_DLL_SPEC Unit : public WorldObject MotionMaster* GetMotionMaster() { return &i_motionMaster; } bool IsStopped() const { return !(hasUnitState(UNIT_STAT_MOVING)); } + bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_LEVITATING);} + bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE);} virtual bool SetPosition(float x, float y, float z, float ang, bool teleport = false); void StopMoving(); - void AddUnitMovementFlag(uint32 f) { m_unit_movement_flags |= f; } - void RemoveUnitMovementFlag(uint32 f) - { - uint32 oldval = m_unit_movement_flags; - m_unit_movement_flags = oldval & ~f; - } - uint32 HasUnitMovementFlag(uint32 f) const { return m_unit_movement_flags & f; } - uint32 GetUnitMovementFlags() const { return m_unit_movement_flags; } - void SetUnitMovementFlags(uint32 f) { m_unit_movement_flags = f; } - void SetControlled(bool apply, UnitState state); void SetFeared(bool apply/*, uint64 casterGUID = 0, uint32 spellID = 0*/); void SetConfused(bool apply/*, uint64 casterGUID = 0, uint32 spellID = 0*/); @@ -1647,13 +1752,17 @@ class TRINITY_DLL_SPEC Unit : public WorldObject int32 GetMeleeApAttackerBonus() { return m_meleeAPAttackerBonus; } virtual float GetFollowAngle() const { return PET_FOLLOW_ANGLE; } - void SetFlying(bool apply); bool HasEventAISummonedUnits (); bool preventApplyPersistentAA(SpellEntry const *spellInfo, uint8 eff_index); bool IsAIEnabled, NeedChangeAI; + + // Movement info + MovementInfo m_movementInfo; + Movement::MoveSpline * movespline; + protected: explicit Unit (); @@ -1709,7 +1818,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject virtual SpellSchoolMask GetMeleeDamageSchoolMask() const; MotionMaster i_motionMaster; - uint32 m_unit_movement_flags; uint32 m_reactiveTimer[MAX_REACTIVE]; @@ -1718,6 +1826,9 @@ class TRINITY_DLL_SPEC Unit : public WorldObject int32 m_meleeAPAttackerBonus; private: + void UpdateSplineMovement(uint32 t_diff); + ShortTimeTracker m_movesplineTimer; + bool IsTriggeredAtSpellProcEvent(Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent); bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); @@ -1732,8 +1843,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject UnitVisibility m_Visibility; Diminishing m_Diminishing; - // Manage all Units threatening us -// ThreatManager m_ThreatManager; + // Manage all Units that are threatened by us HostilRefManager m_HostilRefManager; diff --git a/src/game/UnitAI.cpp b/src/game/UnitAI.cpp index f41b4e5e3..32f726ac7 100644 --- a/src/game/UnitAI.cpp +++ b/src/game/UnitAI.cpp @@ -39,7 +39,7 @@ void UnitAI::AttackStartCaster(Unit *victim, float dist) void UnitAI::DoMeleeAttackIfReady() { - if (me->hasUnitState(UNIT_STAT_CASTING)) + if (me->IsNonMeleeSpellCasted(false)) return; //Make sure our attack is ready and we aren't currently casting before checking distance @@ -65,7 +65,7 @@ void UnitAI::DoMeleeAttackIfReady() bool UnitAI::DoSpellAttackIfReady(uint32 spell) { - if (me->hasUnitState(UNIT_STAT_CASTING)) + if (me->IsNonMeleeSpellCasted(false)) return true; if (me->isAttackReady()) @@ -365,7 +365,7 @@ Unit* UnitAI::SelectUnit(AttackingTarget target, uint32 position) bool UnitAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered) { //No target so we can't cast - if (!Target || !Spell || me->hasUnitState(UNIT_STAT_CASTING)) + if (!Target || !Spell || me->IsNonMeleeSpellCasted(false)) return false; //Silenced so we can't cast diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp index e33fafa55..100ceda8e 100755 --- a/src/game/WaypointMovementGenerator.cpp +++ b/src/game/WaypointMovementGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,313 +15,339 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -//Basic headers + +/* +creature_movement Table + +alter table creature_movement add `textid1` int(11) NOT NULL default '0'; +alter table creature_movement add `textid2` int(11) NOT NULL default '0'; +alter table creature_movement add `textid3` int(11) NOT NULL default '0'; +alter table creature_movement add `textid4` int(11) NOT NULL default '0'; +alter table creature_movement add `textid5` int(11) NOT NULL default '0'; +alter table creature_movement add `emote` int(10) unsigned default '0'; +alter table creature_movement add `spell` int(5) unsigned default '0'; +alter table creature_movement add `wpguid` int(11) default '0'; + +*/ + +#include + #include "WaypointMovementGenerator.h" -#include "DestinationHolderImp.h" -//Extended headers #include "ObjectMgr.h" -#include "World.h" -//Creature-specific headers #include "Creature.h" #include "CreatureAI.h" -//Player-specific -#include "Player.h" +#include "WaypointManager.h" +#include "WorldPacket.h" +//#include "ScriptMgr.h" +#include "movement/MoveSplineInit.h" +#include "movement/MoveSpline.h" + +#include -template -void -WaypointMovementGenerator::Initialize(T &u){} +//-----------------------------------------------// +void WaypointMovementGenerator::LoadPath(Creature &creature) +{ + return; + /*/DETAIL_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "LoadPath: loading waypoint path for %s", creature.GetGuidStr().c_str()); -template<> -void -WaypointMovementGenerator::Finalize(Creature &u){} + i_path = WaypointMgr.GetPath(creature.GetGUIDLow()); -template<> -void -WaypointMovementGenerator::Finalize(Player &u){} + // We may LoadPath() for several occasions: -template -void -WaypointMovementGenerator::MovementInform(T &unit){} + // 1: When creature.MovementType=2 + // 1a) Path is selected by creature.guid == creature_movement.id + // 1b) Path for 1a) does not exist and then use path from creature.GetEntry() == creature_movement_template.entry -template<> -void WaypointMovementGenerator::MovementInform(Creature &unit) -{ - unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode); + // 2: When creature_template.MovementType=2 + // 2a) Creature is summoned and has creature_template.MovementType=2 + // Creators need to be sure that creature_movement_template is always valid for summons. + // Mob that can be summoned anywhere should not have creature_movement_template for example. + + // No movement found for guid + if (!i_path) + { + i_path = sWaypointMgr.GetPathTemplate(creature.GetEntry()); + + // No movement found for entry + if (!i_path) + { + sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u) doesn't have waypoint path", + creature.GetName(), creature.GetEntry(), creature.GetGUIDLow()); + return; + } + } + + StartMoveNow(creature); */ } -template<> -bool WaypointMovementGenerator::GetDestination(float &x, float &y, float &z) const +void WaypointMovementGenerator::Initialize(Creature &creature) { - if (i_destinationHolder.HasArrived()) - return false; - - i_destinationHolder.GetDestination(x, y, z); - return true; + LoadPath(creature); + creature.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); } -template<> -bool WaypointMovementGenerator::GetDestination(float &x, float &y, float &z) const +void WaypointMovementGenerator::Finalize(Creature &creature) { - return false; + creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); + creature.SetWalk(false); } -template<> -void WaypointMovementGenerator::Reset(Creature &unit) +void WaypointMovementGenerator::Interrupt(Creature &creature) { - StopedByPlayer = true; - i_nextMoveTime.Reset(0); + creature.clearUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); + creature.SetWalk(false); } -template<> -void WaypointMovementGenerator::Reset(Player &unit){} +void WaypointMovementGenerator::Reset(Creature &creature) +{ + creature.addUnitState(UNIT_STAT_ROAMING|UNIT_STAT_ROAMING_MOVE); + StartMoveNow(creature); +} -template<> -void WaypointMovementGenerator::InitTraveller(Creature &unit, const WaypointData &node) +void WaypointMovementGenerator::OnArrived(Creature& creature) { - node.run ? unit.RemoveUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE): - unit.AddUnitMovementFlag(SPLINEFLAG_WALKMODE_MODE); + /* + if (!i_path || i_path->empty()) + return; - unit.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); - unit.SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + if (m_isArrivalDone) + return; - if (unit.canFly()) - unit.AddUnitMovementFlag(SPLINEFLAG_FLYINGING2); + creature.clearUnitState(UNIT_STAT_ROAMING_MOVE); + m_isArrivalDone = true; - unit.addUnitState(UNIT_STAT_ROAMING); -} + if (i_path->at(i_currentNode).script_id) + { + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for %s.", i_path->at(i_currentNode).script_id, i_currentNode, creature.GetGuidStr().c_str()); + creature.GetMap()->ScriptsStart(sCreatureMovementScripts, i_path->at(i_currentNode).script_id, &creature, &creature); + } -template<> -void -WaypointMovementGenerator::Initialize(Creature &u) -{ - u.StopMoving(); - //i_currentNode = -1; // uint32, become 0 in the first update - //i_nextMoveTime.Reset(0); - StopedByPlayer = false; - if (!path_id) - path_id = u.GetWaypointPath(); - waypoints = WaypointMgr.GetPath(path_id); - i_currentNode = 0; - if (waypoints && waypoints->size()) + // We have reached the destination and can process behavior + if (WaypointBehavior *behavior = i_path->at(i_currentNode).behavior) { - if (CreatureData const *cdata = objmgr.GetCreatureData(u.GetDBTableGUIDLow())) - i_currentNode = cdata->currentwaypoint - 1; + if (behavior->emote != 0) + creature.HandleEmoteCommand(behavior->emote); - if (i_currentNode > waypoints->size() - 1) - i_currentNode = 0; + if (behavior->spell != 0) + creature.CastSpell(&creature, behavior->spell, false); - node = waypoints->at(i_currentNode); + if (behavior->model1 != 0) + creature.SetDisplayId(behavior->model1); - Traveller traveller(u); - InitTraveller(u, *node); - i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z); - i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); + if (behavior->textid[0]) + { + // Not only one text is set + if (behavior->textid[1]) + { + // Select one from max 5 texts (0 and 1 already checked) + int i = 2; + for(; i < MAX_WAYPOINT_TEXT; ++i) + { + if (!behavior->textid[i]) + break; + } - if (u.GetFormation() && u.GetFormation()->getLeader()) - if (u.GetFormation()->getLeader()->GetGUID() == u.GetGUID()) - u.GetFormation()->LeaderMoveTo(node->x, node->y, node->z); + creature.MonsterSay(behavior->textid[rand() % i], LANG_UNIVERSAL); + } + else + creature.MonsterSay(behavior->textid[0], LANG_UNIVERSAL); + } } - else - node = NULL; -} -template<> -void WaypointMovementGenerator::InitTraveller(Player &unit, const WaypointData &node){} - -template -bool -WaypointMovementGenerator::Update(T &unit, const uint32 &diff) -{ - return false; + // Inform script + MovementInform(creature); + Stop(i_path->at(i_currentNode).delay); + */ } -template<> -bool -WaypointMovementGenerator::Update(Creature &unit, const uint32 &diff) +void WaypointMovementGenerator::StartMove(Creature &creature) { - if (!&unit) - return true; + /* + if (!i_path || i_path->empty()) + return; - if (!path_id) - return false; + if (Stopped()) + return; - // Waypoint movement can be switched on/off - // This is quite handy for escort quests and other stuff - if (unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED)) - return true; + if (WaypointBehavior *behavior = i_path->at(i_currentNode).behavior) + { + if (behavior->model2 != 0) + creature.SetDisplayId(behavior->model2); + creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); + } - // Clear the generator if the path doesn't exist - if (!waypoints || !waypoints->size()) - return false; + if (m_isArrivalDone) + i_currentNode = (i_currentNode+1) % i_path->size(); - Traveller traveller(unit); + m_isArrivalDone = false; - i_nextMoveTime.Update(diff); - i_destinationHolder.UpdateTraveller(traveller, diff, true); + creature.addUnitState(UNIT_STAT_ROAMING_MOVE); - if (i_nextMoveTime.GetExpiry() < TIMEDIFF_NEXT_WP) - { - if (unit.IsStopped()) - { - if (StopedByPlayer) - { - assert(node); - InitTraveller(unit, *node); - i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z); - i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); - StopedByPlayer = false; - - if (unit.GetFormation() && unit.GetFormation()->getLeader()) - if (unit.GetFormation()->getLeader()->GetGUID() == unit.GetGUID()) - unit.GetFormation()->LeaderMoveTo(node->x, node->y, node->z); - return true; - } + const WaypointNode &node = i_path->at(i_currentNode); + Movement::MoveSplineInit init(creature); + init.MoveTo(node.x, node.y, node.z); - if (i_currentNode == waypoints->size() - 1) //If that's our last waypoint - { - if (repeating) //If the movement is repeating - i_currentNode = 0; //Start moving all over again - else - { - unit.SetHomePosition(node->x, node->y, node->z, unit.GetOrientation()); - unit.GetMotionMaster()->Initialize(); - return false; //Clear the waypoint movement - } - } - else - i_currentNode++; + if (node.orientation != 100 && node.delay != 0) + init.SetFacing(node.orientation); + init.SetWalk(!creature.IsLevitating()); + init.Launch(); + */ +} - node = waypoints->at(i_currentNode); - InitTraveller(unit, *node); - i_destinationHolder.SetDestination(traveller, node->x, node->y, node->z); - i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); +bool WaypointMovementGenerator::Update(Creature &creature, const uint32 &diff) +{ + // Waypoint movement can be switched on/off + // This is quite handy for escort quests and other stuff + if (creature.hasUnitState(UNIT_STAT_NOT_MOVE)) + { + creature.clearUnitState(UNIT_STAT_ROAMING_MOVE); + return true; + } - if (unit.GetFormation() && unit.GetFormation()->getLeader()) - if (unit.GetFormation()->getLeader()->GetGUID() == unit.GetGUID()) - unit.GetFormation()->LeaderMoveTo(node->x, node->y, node->z); - } - else - { - //Determine waittime - if (node->delay) - i_nextMoveTime.Reset(node->delay); - - //note: disable "start" for mtmap - if (node->event_id && rand()%100 < node->event_chance) - unit.GetMap()->ScriptsStart(sWaypointScripts, node->event_id, &unit, NULL/*, false*/); - - i_destinationHolder.ResetTravelTime(); - MovementInform(unit); - unit.UpdateWaypointID(i_currentNode); - unit.clearUnitState(UNIT_STAT_ROAMING); - unit.Relocate(node->x, node->y, node->z); - } + // prevent a crash at empty waypoint path. + if (!i_path || i_path->empty()) + { + creature.clearUnitState(UNIT_STAT_ROAMING_MOVE); + return true; + } + + if (Stopped()) + { + if (CanMove(diff)) + StartMove(creature); } else { - if (unit.IsStopped() && !i_destinationHolder.HasArrived()) + if (creature.IsStopped()) + Stop(STOP_TIME_FOR_PLAYER); + else if (creature.movespline->Finalized()) { - if (!StopedByPlayer) - { - i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER); - i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER); - StopedByPlayer = true; - } + OnArrived(creature); + StartMove(creature); } } return true; } -template void WaypointMovementGenerator::Initialize(Player &); -template bool WaypointMovementGenerator::Update(Player &, const uint32 &); -template void WaypointMovementGenerator::MovementInform(Player &); +void WaypointMovementGenerator::MovementInform(Creature &creature) +{ + if (creature.AI()) + creature.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode); +} -//----------------------------------------------------// -void -FlightPathMovementGenerator::LoadPath(Player &) +bool WaypointMovementGenerator::GetResetPosition(Creature&, float& x, float& y, float& z) { - objmgr.GetTaxiPathNodes(i_pathId, i_path,i_mapIds); + /* + // prevent a crash at empty waypoint path. + if (!i_path || i_path->empty()) + return false; + + const WaypointNode& node = i_path->at(i_currentNode); + x = node.x; y = node.y; z = node.z; */ + return false; //true; } -uint32 -FlightPathMovementGenerator::GetPathAtMapEnd() const +//----------------------------------------------------// +uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const { - if (i_currentNode >= i_mapIds.size()) - return i_mapIds.size(); + if (i_currentNode >= i_path->size()) + return i_path->size(); + + uint32 curMapId = (*i_path)[i_currentNode].mapid; - uint32 curMapId = i_mapIds[i_currentNode]; - for (uint32 i = i_currentNode; i < i_mapIds.size(); ++i) + for(uint32 i = i_currentNode; i < i_path->size(); ++i) { - if (i_mapIds[i] != curMapId) + if ((*i_path)[i].mapid != curMapId) return i; } - return i_mapIds.size(); + return i_path->size(); } -void -FlightPathMovementGenerator::Initialize(Player &player) +void FlightPathMovementGenerator::Initialize(Player &player) { - player.getHostilRefManager().setOnlineOfflineState(false); - player.addUnitState(UNIT_STAT_IN_FLIGHT); - player.SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); - LoadPath(player); - Traveller traveller(player); - // do not send movement, it was sent already - i_destinationHolder.SetDestination(traveller, i_path[i_currentNode].x, i_path[i_currentNode].y, i_path[i_currentNode].z, false); - - player.SendMonsterMoveByPath(GetPath(),GetCurrentNode(),GetPathAtMapEnd()); + Reset(player); } void FlightPathMovementGenerator::Finalize(Player & player) { + // remove flag to prevent send object build movement packets for flight state and crash (movement generator already not at top of stack) + player.clearUnitState(UNIT_STAT_TAXI_FLIGHT); - float x, y, z; - i_destinationHolder.GetLocationNow(player.GetBaseMap(), x, y, z); - player.SetPosition(x, y, z, player.GetOrientation()); - - player.clearUnitState(UNIT_STAT_IN_FLIGHT); player.Unmount(); player.RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); if (player.m_taxi.empty()) { player.getHostilRefManager().setOnlineOfflineState(true); - if (player.pvpInfo.inHostileArea) + if(player.pvpInfo.inHostileArea) player.CastSpell(&player, 2479, true); - player.SetUnitMovementFlags(SPLINEFLAG_WALKMODE_MODE); + // update z position to ground and orientation for landing point + // this prevent cheating with landing point at lags + // when client side flight end early in comparison server side + player.m_movementInfo.AddMovementFlag(MOVEFLAG_WALK_MODE); player.StopMoving(); } } -bool -FlightPathMovementGenerator::Update(Player &player, const uint32 &diff) +void FlightPathMovementGenerator::Interrupt(Player & player) +{ + player.clearUnitState(UNIT_STAT_TAXI_FLIGHT); +} + +#define PLAYER_FLIGHT_SPEED 32.0f + +void FlightPathMovementGenerator::Reset(Player & player) { - if (MovementInProgress()) + player.getHostilRefManager().setOnlineOfflineState(false); + player.addUnitState(UNIT_STAT_TAXI_FLIGHT); + player.SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); + + Movement::MoveSplineInit init(player); + /* uint32 end = GetPathAtMapEnd(); + for (uint32 i = GetCurrentNode(); i != end; ++i) { - Traveller traveller(player); - if (i_destinationHolder.UpdateTraveller(traveller, diff)) + G3D::Vector3 vertice((*i_path)[i].x,(*i_path)[i].y,(*i_path)[i].z); + init.Path().push_back(vertice); + } + init.SetFirstPointId(GetCurrentNode());*/ + + // if pathed spline subsystem is fixed remove moveto + init.MoveTo((*i_path)[GetCurrentNode()].x, (*i_path)[GetCurrentNode()].y, (*i_path)[GetCurrentNode()].z); + + init.SetFly(); + init.SetVelocity(PLAYER_FLIGHT_SPEED); + init.Launch(); +} + +bool FlightPathMovementGenerator::Update(Player &player, const uint32 &diff) +{ + if (GetCurrentNode() < GetPath().size()) + { + if (player.movespline->Finalized()) { - i_destinationHolder.ResetUpdate(FLIGHT_TRAVEL_UPDATE); - if (i_destinationHolder.HasArrived()) + DoEventIfAny(player,(*i_path)[i_currentNode],true); + + uint32 curMap = GetPath()[GetCurrentNode()].mapid; + ++i_currentNode; + if (GetCurrentNode() < GetPath().size()) { - uint32 curMap = i_mapIds[i_currentNode]; - ++i_currentNode; - if (MovementInProgress()) + DEBUG_LOG("loading node %u for player %s", i_currentNode, player.GetName()); + if (GetPath()[GetCurrentNode()].mapid == curMap) { - DEBUG_LOG("loading node %u for player %s", i_currentNode, player.GetName()); - if (i_mapIds[i_currentNode]==curMap) - { - // do not send movement, it was sent already - i_destinationHolder.SetDestination(traveller, i_path[i_currentNode].x, i_path[i_currentNode].y, i_path[i_currentNode].z, false); - } - return true; + player.MonsterSay("1", LANG_UNIVERSAL, 0); + // IF SOMEONE FIGURE OUT WHY SPLINE SUBSYSTEM WHEN USING PATH IS FINALIZED RIGHT AFTER LAUNCH THAT SHIT CAN BE REMOVED AND DONE IN PROPER WAY SEE: COMMENTED OUT CODE IN ::Reset + Movement::MoveSplineInit init(player); + init.MoveTo(GetPath()[GetCurrentNode()].x, GetPath()[GetCurrentNode()].y, GetPath()[GetCurrentNode()].z); + init.SetFly(); + init.SetVelocity(PLAYER_FLIGHT_SPEED); + init.Launch(); + + DoEventIfAny(player,(*i_path)[i_currentNode],false); } - //else HasArrived() - } - else return true; + } } else return true; @@ -331,16 +357,16 @@ FlightPathMovementGenerator::Update(Player &player, const uint32 &diff) return false; } -void -FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() +void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() { - if (i_mapIds.empty()) + if (i_path->empty()) return; - uint32 map0 = i_mapIds[0]; - for (int i = 1; i < i_mapIds.size(); ++i) + uint32 map0 = (*i_path)[0].mapid; + + for (size_t i = 1; i < i_path->size(); ++i) { - if (i_mapIds[i]!=map0) + if ((*i_path)[i].mapid != map0) { i_currentNode = i; return; @@ -348,6 +374,23 @@ FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() } } +void FlightPathMovementGenerator::DoEventIfAny(Player& player, TaxiPathNodeEntry const& node, bool departure) +{ + if (uint32 eventid = departure ? node.departureEventID : node.arrivalEventID) + { + //DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node.index, node.path, player.GetName()); + + //if (!sScriptMgr.OnProcessEvent(eventid, &player, &player, departure)) + player.GetMap()->ScriptsStart(sEventScripts, eventid, &player, &player); + } +} + +bool FlightPathMovementGenerator::GetResetPosition(Player&, float& x, float& y, float& z) +{ + const TaxiPathNodeEntry& node = (*i_path)[i_currentNode]; + x = node.x; y = node.y; z = node.z; + return true; +} // // Unique1's ASTAR Pathfinding Code... For future use & reference... // @@ -501,7 +544,7 @@ int CreatePathAStar(gentity_t *bot, int from, int to, short int *pathlist) break; } - for (i = 0; i < nodes[atNode].enodenum; i++) //loop through all the links for this node + for (i = 0; i < nodes[atNode].enodenum; ++i) //loop through all the links for this node { newnode = nodes[atNode].links[i].targetNode; @@ -559,7 +602,7 @@ int CreatePathAStar(gentity_t *bot, int from, int to, short int *pathlist) parent[newnode] = atNode; //set the new parent for this node gcost[newnode] = gc; //and the new g cost - for (i = 1; i < numOpen; i++) //loop through all the items on the open list + for (i = 1; i < numOpen; ++i) //loop through all the items on the open list { if (openlist[i] == newnode) //find this node in the list { @@ -673,4 +716,3 @@ int GetFCost(int to, int num, int parentNum, float *gcost) return (int)(gc + hc); } #endif //__PATHFINDING__ - diff --git a/src/game/WaypointMovementGenerator.h b/src/game/WaypointMovementGenerator.h index f1aad75ad..a1465248c 100755 --- a/src/game/WaypointMovementGenerator.h +++ b/src/game/WaypointMovementGenerator.h @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS - * - * Copyright (C) 2008 Trinity + * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,16 +8,16 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITY_WAYPOINTMOVEMENTGENERATOR_H -#define TRINITY_WAYPOINTMOVEMENTGENERATOR_H +#ifndef MANGOS_WAYPOINTMOVEMENTGENERATOR_H +#define MANGOS_WAYPOINTMOVEMENTGENERATOR_H /** @page PathMovementGenerator is used to generate movements * of waypoints and flight paths. Each serves the purpose @@ -28,10 +26,7 @@ */ #include "MovementGenerator.h" -#include "DestinationHolder.h" #include "WaypointManager.h" -#include "Path.h" -#include "Traveller.h" #include "Player.h" @@ -39,53 +34,78 @@ #include #define FLIGHT_TRAVEL_UPDATE 100 -#define STOP_TIME_FOR_PLAYER 3 * 60 * 1000 // 3 Minutes -#define TIMEDIFF_NEXT_WP 250 +#define STOP_TIME_FOR_PLAYER 3 * MINUTE * IN_MILISECONDS // 3 Minutes -template +template class TRINITY_DLL_SPEC PathMovementBase { public: PathMovementBase() : i_currentNode(0) {} virtual ~PathMovementBase() {}; - inline bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); } - + // template pattern, not defined .. override required void LoadPath(T &); - void ReloadPath(T &); uint32 GetCurrentNode() const { return i_currentNode; } protected: - uint32 i_currentNode; - DestinationHolder< Traveller > i_destinationHolder; P i_path; + uint32 i_currentNode; }; +/** WaypointMovementGenerator loads a series of way points + * from the DB and apply it to the creature's movement generator. + * Hence, the creature will move according to its predefined way points. + */ + template +class TRINITY_DLL_SPEC WaypointMovementGenerator; -class TRINITY_DLL_SPEC WaypointMovementGenerator - : public MovementGeneratorMedium< T, WaypointMovementGenerator >, public PathMovementBase +template<> +class TRINITY_DLL_SPEC WaypointMovementGenerator +: public MovementGeneratorMedium< Creature, WaypointMovementGenerator >, +public PathMovementBase { public: - WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true) : - i_nextMoveTime(0), path_id(_path_id), repeating(_repeating), StopedByPlayer(false), node(NULL) {} - - void Initialize(T &); - void Finalize(T &); - void MovementInform(T &); - void InitTraveller(T &, const WaypointData &); - void GeneratePathId(T &); - void Reset(T &unit); - bool Update(T &, const uint32 &); - bool GetDestination(float &x, float &y, float &z) const; - MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; } + WaypointMovementGenerator(Creature &) : i_nextMoveTime(0), m_isArrivalDone(false) {} + ~WaypointMovementGenerator() { i_path = NULL; } + void Initialize(Creature &u); + void Interrupt(Creature &); + void Finalize(Creature &); + void Reset(Creature &u); + bool Update(Creature &u, const uint32 &diff); + + void MovementInform(Creature &); + + MovementGeneratorType GetMovementGeneratorType() const { return WAYPOINT_MOTION_TYPE; } + + // now path movement implmementation + void LoadPath(Creature &c); + + bool GetResetPosition(Creature&, float& x, float& y, float& z); private: - WaypointData *node; - uint32 path_id; - TimeTrackerSmall i_nextMoveTime; - WaypointPath *waypoints; - bool repeating, StopedByPlayer; + + void Stop(int32 time) { i_nextMoveTime.Reset(time);} + + bool Stopped() { return !i_nextMoveTime.Passed();} + + bool CanMove(int32 diff) + { + i_nextMoveTime.Update(diff); + return i_nextMoveTime.Passed(); + } + + void OnArrived(Creature&); + void StartMove(Creature&); + + void StartMoveNow(Creature& creature) + { + i_nextMoveTime.Reset(0); + StartMove(creature); + } + + ShortTimeTracker i_nextMoveTime; + bool m_isArrivalDone; }; /** FlightPathMovementGenerator generates movement of the player for the paths @@ -93,28 +113,27 @@ class TRINITY_DLL_SPEC WaypointMovementGenerator */ class TRINITY_DLL_SPEC FlightPathMovementGenerator : public MovementGeneratorMedium< Player, FlightPathMovementGenerator >, -public PathMovementBase +public PathMovementBase { - uint32 i_pathId; - std::vector i_mapIds; public: - explicit FlightPathMovementGenerator(uint32 id, uint32 startNode = 0) : i_pathId(id) { i_currentNode = startNode; } + explicit FlightPathMovementGenerator(TaxiPathNodeList const& pathnodes, uint32 startNode = 0) + { + i_path = &pathnodes; + i_currentNode = startNode; + } void Initialize(Player &); void Finalize(Player &); - void Reset(Player &) {} + void Interrupt(Player &); + void Reset(Player &); bool Update(Player &, const uint32 &); - MovementGeneratorType GetMovementGeneratorType() { return FLIGHT_MOTION_TYPE; } - - void LoadPath(Player &); - void ReloadPath(Player &) { /* don't reload flight path */ } + MovementGeneratorType GetMovementGeneratorType() const { return FLIGHT_MOTION_TYPE; } - Path& GetPath() { return i_path; } + TaxiPathNodeList const& GetPath() { return *i_path; } uint32 GetPathAtMapEnd() const; - inline bool HasArrived() const { return (i_currentNode >= i_path.Size()); } + bool HasArrived() const { return (i_currentNode >= i_path->size()); } void SetCurrentNodeAfterTeleport(); void SkipCurrentNode() { ++i_currentNode; } - bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; } - + void DoEventIfAny(Player& player, TaxiPathNodeEntry const& node, bool departure); + bool GetResetPosition(Player&, float& x, float& y, float& z); }; #endif - diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index f6bf620a1..212d355b4 100755 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -453,7 +453,7 @@ class TRINITY_DLL_SPEC WorldSession void HandleTaxiQueryAvailableNodesOpcode(WorldPacket& recvPacket); void HandleActivateTaxiOpcode(WorldPacket& recvPacket); void HandleActivateTaxiFarOpcode(WorldPacket& recvPacket); - void HandleTaxiNextDestinationOpcode(WorldPacket& recvPacket); + void HandleMoveSplineDoneOpcode(WorldPacket& recvPacket); void HandleTabardVendorActivateOpcode(WorldPacket& recvPacket); void HandleBankerActivateOpcode(WorldPacket& recvPacket); diff --git a/src/game/movement/MoveSpline.cpp b/src/game/movement/MoveSpline.cpp new file mode 100644 index 000000000..98059ffb5 --- /dev/null +++ b/src/game/movement/MoveSpline.cpp @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MoveSpline.h" +#include +#include "Log.h" + +namespace Movement{ + +extern float computeFallTime(float path_length, bool isSafeFall); +extern float computeFallElevation(float time_passed, bool isSafeFall, float start_velocy); +extern float computeFallElevation(float time_passed); + +Location MoveSpline::ComputePosition() const +{ + ASSERT(Initialized()); + + float u = 1.f; + int32 seg_time = spline.length(point_Idx,point_Idx+1); + if (seg_time > 0) + u = (time_passed - spline.length(point_Idx)) / (float)seg_time; + Location c; + spline.evaluate_percent(point_Idx, u, c); + + if (splineflags.animation) + ;// MoveSplineFlag::Animation disables falling or parabolic movement + else if (splineflags.parabolic) + computeParabolicElevation(c.z); + else if (splineflags.falling) + computeFallElevation(c.z); + + if (splineflags.done && splineflags.isFacing()) + { + if (splineflags.final_angle) + c.orientation = facing.angle; + else if (splineflags.final_point) + c.orientation = atan2(facing.f.y-c.y, facing.f.x-c.x); + //nothing to do for MoveSplineFlag::Final_Target flag + } + else + { + Vector3 hermite; + spline.evaluate_derivative(point_Idx,u,hermite); + c.orientation = atan2(hermite.y, hermite.x); + + if (splineflags.backward) + c.orientation = -c.orientation; + } + return c; +} + +void MoveSpline::computeParabolicElevation(float& el) const +{ + if (time_passed > effect_start_time) + { + float t_passedf = MSToSec(time_passed - effect_start_time); + float t_durationf = MSToSec(Duration() - effect_start_time); //client use not modified duration here + + // -a*x*x + bx + c: + //(dur * v3->z_acceleration * dt)/2 - (v3->z_acceleration * dt * dt)/2 + Z; + el += (t_durationf - t_passedf) * 0.5f * vertical_acceleration * t_passedf; + } +} + +void MoveSpline::computeFallElevation(float& el) const +{ + float z_now = spline.getPoint(spline.first()).z - Movement::computeFallElevation(MSToSec(time_passed)); + float final_z = FinalDestination().z; + if (z_now < final_z) + el = final_z; + else + el = z_now; +} + +inline uint32 computeDuration(float length, float velocity) +{ + return SecToMS(length / velocity); +} + +struct FallInitializer +{ + FallInitializer(float _start_elevation) : start_elevation(_start_elevation) {} + float start_elevation; + inline int32 operator()(Spline& s, int32 i) + { + return Movement::computeFallTime(start_elevation - s.getPoint(i+1).z,false) * 1000.f; + } +}; + +enum{ + minimal_duration = 1, +}; + +struct CommonInitializer +{ + CommonInitializer(float _velocity) : velocityInv(1000.f/_velocity), time(minimal_duration) {} + float velocityInv; + int32 time; + inline int32 operator()(Spline& s, int32 i) + { + time += (s.SegLength(i) * velocityInv); + return time; + } +}; + +void MoveSpline::init_spline(const MoveSplineInitArgs& args) +{ + const SplineBase::EvaluationMode modes[2] = {SplineBase::ModeLinear,SplineBase::ModeCatmullrom}; + if (args.flags.cyclic) + { + uint32 cyclic_point = 0; + // MoveSplineFlag::Enter_Cycle support dropped + //if (splineflags & SPLINEFLAG_ENTER_CYCLE) + //cyclic_point = 1; // shouldn't be modified, came from client + spline.init_cyclic_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()], cyclic_point); + } + else + { + spline.init_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()]); + } + + // init spline timestamps + if (splineflags.falling) + { + FallInitializer init(spline.getPoint(spline.first()).z); + spline.initLengths(init); + } + else + { + CommonInitializer init(args.velocity); + spline.initLengths(init); + } + + // TODO: what to do in such cases? problem is in input data (all points are at same coords) + if (spline.length() < minimal_duration) + { + sLog.outError("MoveSpline::init_spline: zero length spline, wrong input data?"); + spline.set_length(spline.last(), spline.isCyclic() ? 1000 : 1); + } + point_Idx = spline.first(); +} + +void MoveSpline::Initialize(const MoveSplineInitArgs& args) +{ + splineflags = args.flags; + facing = args.facing; + m_Id = args.splineId; + point_Idx_offset = args.path_Idx_offset; + + time_passed = 0; + vertical_acceleration = 0.f; + effect_start_time = 0; + + init_spline(args); + + // init parabolic / animation + // spline initialized, duration known and i able to compute parabolic acceleration + if (args.flags & (MoveSplineFlag::Parabolic | MoveSplineFlag::Animation)) + { + effect_start_time = Duration() * args.time_perc; + if (args.flags.parabolic && effect_start_time < Duration()) + { + float f_duration = MSToSec(Duration() - effect_start_time); + vertical_acceleration = args.parabolic_amplitude * 8.f / (f_duration * f_duration); + } + } +} + +MoveSpline::MoveSpline() : m_Id(0), time_passed(0), + vertical_acceleration(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0) +{ + splineflags.done = true; +} + +/// ============================================================================================ + +bool MoveSplineInitArgs::Validate() const +{ +#define CHECK(exp) \ + if (!(exp))\ + {\ + sLog.outError("MoveSplineInitArgs::Validate: expression '%s' failed", #exp);\ + return false;\ + } + CHECK(path.size() > 1); + CHECK(velocity > 0.f); + CHECK(time_perc >= 0.f && time_perc <= 1.f); + //CHECK(_checkPathBounds()); + return true; +#undef CHECK +} + +// MONSTER_MOVE packet format limitation for not CatmullRom movement: +// each vertex offset packed into 11 bytes +bool MoveSplineInitArgs::_checkPathBounds() const +{ + if (!(flags & MoveSplineFlag::Mask_CatmullRom) && path.size() > 2) + { + enum{ + MAX_OFFSET = (1 << 11) / 2, + }; + Vector3 middle = (path.front()+path.back()) / 2; + Vector3 offset; + for (uint32 i = 1; i < path.size()-1; ++i) + { + offset = path[i] - middle; + if (fabs(offset.x) >= MAX_OFFSET || fabs(offset.y) >= MAX_OFFSET || fabs(offset.z) >= MAX_OFFSET) + { + sLog.outError("MoveSplineInitArgs::_checkPathBounds check failed"); + return false; + } + } + } + return true; +} + +/// ============================================================================================ + +MoveSpline::UpdateResult MoveSpline::_updateState(int32& ms_time_diff) +{ + if (Finalized()) + { + ms_time_diff = 0; + return Result_Arrived; + } + + UpdateResult result = Result_None; + + int32 minimal_diff = std::min(ms_time_diff, segment_time_elapsed()); + ASSERT(minimal_diff >= 0); + time_passed += minimal_diff; + ms_time_diff -= minimal_diff; + + if (time_passed >= next_timestamp()) + { + ++point_Idx; + if (point_Idx < spline.last()) + { + result = Result_NextSegment; + } + else + { + if (spline.isCyclic()) + { + point_Idx = spline.first(); + time_passed = time_passed % Duration(); + result = Result_NextSegment; + } + else + { + _Finalize(); + ms_time_diff = 0; + result = Result_Arrived; + } + } + } + + return result; +} + +std::string MoveSpline::ToString() const +{ + std::stringstream str; + str << "MoveSpline" << std::endl; + str << "spline Id: " << GetId() << std::endl; + str << "flags: " << splineflags.ToString() << std::endl; + if (splineflags.final_angle) + str << "facing angle: " << facing.angle; + else if (splineflags.final_target) + str << "facing target: " << facing.target; + else if(splineflags.final_point) + str << "facing point: " << facing.f.x << " " << facing.f.y << " " << facing.f.z; + str << std::endl; + str << "time passed: " << time_passed << std::endl; + str << "total time: " << Duration() << std::endl; + str << "spline point Id: " << point_Idx << std::endl; + str << "path point Id: " << currentPathIdx() << std::endl; + str << spline.ToString(); + return str.str(); +} + +void MoveSpline::_Finalize() +{ + splineflags.done = true; + point_Idx = spline.last() - 1; + time_passed = Duration(); +} + +int32 MoveSpline::currentPathIdx() const +{ + int32 point = point_Idx_offset + point_Idx - spline.first() + (int)Finalized(); + if (isCyclic()) + point = point % (spline.last()-spline.first()); + return point; +} +} diff --git a/src/game/movement/MoveSpline.h b/src/game/movement/MoveSpline.h new file mode 100644 index 000000000..1c143de7f --- /dev/null +++ b/src/game/movement/MoveSpline.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_MOVEPLINE_H +#define MANGOSSERVER_MOVEPLINE_H + +#include "spline.h" +#include "MoveSplineInitArgs.h" + +namespace Movement +{ + struct Location : public Vector3 + { + Location() : orientation(0) {} + Location(float x, float y, float z, float o) : Vector3(x,y,z), orientation(o) {} + Location(const Vector3& v) : Vector3(v), orientation(0) {} + Location(const Vector3& v, float o) : Vector3(v), orientation(o) {} + + float orientation; + }; + + // MoveSpline represents smooth catmullrom or linear curve and point that moves belong it + // curve can be cyclic - in this case movement will be cyclic + // point can have vertical acceleration motion componemt(used in fall, parabolic movement) + class MoveSpline + { + public: + typedef Spline MySpline; + enum UpdateResult{ + Result_None = 0x01, + Result_Arrived = 0x02, + Result_NextCycle = 0x04, + Result_NextSegment = 0x08, + }; + #pragma region fields + friend class PacketBuilder; + protected: + MySpline spline; + + FacingInfo facing; + + uint32 m_Id; + + MoveSplineFlag splineflags; + + int32 time_passed; + // currently duration mods are unused, but its _currently_ + //float duration_mod; + //float duration_mod_next; + float vertical_acceleration; + int32 effect_start_time; + int32 point_Idx; + int32 point_Idx_offset; + + void init_spline(const MoveSplineInitArgs& args); + protected: + + const MySpline::ControlArray& getPath() const { return spline.getPoints();} + void computeParabolicElevation(float& el) const; + void computeFallElevation(float& el) const; + + UpdateResult _updateState(int32& ms_time_diff); + int32 next_timestamp() const { return spline.length(point_Idx+1);} + int32 segment_time_elapsed() const { return next_timestamp()-time_passed;} + int32 Duration() const { return spline.length();} + int32 timeElapsed() const { return Duration() - time_passed;} + int32 timePassed() const { return time_passed;} + + public: + const MySpline& _Spline() const { return spline;} + int32 _currentSplineIdx() const { return point_Idx;} + void _Finalize(); + void _Interrupt() { splineflags.done = true;} + + #pragma endregion + public: + + void Initialize(const MoveSplineInitArgs&); + bool Initialized() const { return !spline.empty();} + + explicit MoveSpline(); + + template + void updateState(int32 difftime, UpdateHandler& handler) + { + ASSERT(Initialized()); + do + handler(_updateState(difftime)); + while(difftime > 0); + } + + void updateState(int32 difftime) + { + ASSERT(Initialized()); + do _updateState(difftime); + while(difftime > 0); + } + + Location ComputePosition() const; + + uint32 GetId() const { return m_Id;} + bool Finalized() const { return splineflags.done; } + bool isCyclic() const { return splineflags.cyclic;} + const Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3();} + const Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx+1) : Vector3();} + int32 currentPathIdx() const; + + std::string ToString() const; + }; +} +#endif // MANGOSSERVER_MOVEPLINE_H diff --git a/src/game/movement/MoveSplineFlag.h b/src/game/movement/MoveSplineFlag.h new file mode 100644 index 000000000..c76f15c1d --- /dev/null +++ b/src/game/movement/MoveSplineFlag.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_MOVESPLINEFLAG_H +#define MANGOSSERVER_MOVESPLINEFLAG_H + +#include "typedefs.h" +#include + +namespace Movement +{ +#if defined( __GNUC__ ) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + + class MoveSplineFlag + { + public: + enum eFlags{ + None = 0x00000000, + // x00-xFF(first byte) used as animation Ids storage in pair with Animation flag + Done = 0x00000100, + Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag + No_Spline = 0x00000400, + Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag + Walkmode = 0x00001000, + Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation + Knockback = 0x00004000, // Model orientation fixed + Final_Point = 0x00008000, + Final_Target = 0x00010000, + Final_Angle = 0x00020000, + Catmullrom = 0x00040000, // Used Catmullrom interpolation mode + Cyclic = 0x00080000, // Movement by cycled spline + Enter_Cycle = 0x00100000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done + Animation = 0x00200000, // Plays animation after some time passed + Frozen = 0x00400000, // Will never arrive + Unknown5 = 0x00800000, + Unknown6 = 0x01000000, + Unknown7 = 0x02000000, + Unknown8 = 0x04000000, + Backward = 0x08000000, + Unknown10 = 0x10000000, + Unknown11 = 0x20000000, + Unknown12 = 0x40000000, + Unknown13 = 0x80000000, + + // Masks + Mask_Final_Facing = Final_Point | Final_Target | Final_Angle, + // animation ids stored here, see AnimType enum, used with Animation flag + Mask_Animations = 0xFF, + // flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably + Mask_No_Monster_Move = Mask_Final_Facing | Mask_Animations | Done, + // CatmullRom interpolation mode used + Mask_CatmullRom = Flying | Catmullrom, + // Unused, not suported flags + Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown5|Unknown6|Unknown7|Unknown8|Unknown10|Unknown11|Unknown12|Unknown13, + }; + + inline uint32& raw() { return (uint32&)*this;} + inline const uint32& raw() const { return (const uint32&)*this;} + + MoveSplineFlag() { raw() = 0; } + MoveSplineFlag(uint32 f) { raw() = f; } + MoveSplineFlag(const MoveSplineFlag& f) { raw() = f.raw(); } + + // Constant interface + + bool isSmooth() const { return raw() & Mask_CatmullRom;} + bool isLinear() const { return !isSmooth();} + bool isFacing() const { return raw() & Mask_Final_Facing;} + + uint8 getAnimationId() const { return animId;} + bool hasAllFlags(uint32 f) const { return (raw() & f) == f;} + uint32 operator & (uint32 f) const { return (raw() & f);} + uint32 operator | (uint32 f) const { return (raw() | f);} + std::string ToString() const; + + // Not constant interface + + void operator &= (uint32 f) { raw() &= f;} + void operator |= (uint32 f) { raw() |= f;} + + void EnableAnimation(uint8 anim) { raw() = raw() & ~(Mask_Animations|Falling|Parabolic|Knockback) | Animation|anim;} + void EnableParabolic() { raw() = raw() & ~(Mask_Animations|Falling|Animation) | Parabolic;} + void EnableFalling() { raw() = raw() & ~(Mask_Animations|Parabolic|Knockback|Animation) | Falling;} + void EnableFlying() { raw() = raw() & ~Catmullrom | Flying; } + void EnableCatmullRom() { raw() = raw() & ~Flying | Catmullrom; } + void EnableFacingPoint() { raw() = raw() & ~Mask_Final_Facing | Final_Point;} + void EnableFacingAngle() { raw() = raw() & ~Mask_Final_Facing | Final_Angle;} + void EnableFacingTarget() { raw() = raw() & ~Mask_Final_Facing | Final_Target;} + + uint8 animId : 8; + bool done : 1; + bool falling : 1; + bool no_spline : 1; + bool parabolic : 1; + bool walkmode : 1; + bool flying : 1; + bool knockback : 1; + bool final_point : 1; + bool final_target : 1; + bool final_angle : 1; + bool catmullrom : 1; + bool cyclic : 1; + bool enter_cycle : 1; + bool animation : 1; + bool frozen : 1; + bool unknown5 : 1; + bool unknown6 : 1; + bool unknown7 : 1; + bool unknown8 : 1; + bool backward : 1; + bool unknown10 : 1; + bool unknown11 : 1; + bool unknown12 : 1; + bool unknown13 : 1; + }; +#if defined( __GNUC__ ) +#pragma pack() +#else +#pragma pack(pop) +#endif +} + +#endif // MANGOSSERVER_MOVESPLINEFLAG_H diff --git a/src/game/movement/MoveSplineInit.cpp b/src/game/movement/MoveSplineInit.cpp new file mode 100644 index 000000000..765f38b3f --- /dev/null +++ b/src/game/movement/MoveSplineInit.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MoveSplineInit.h" +#include "MoveSpline.h" +#include "packet_builder.h" +#include "../Unit.h" +#include "../../shared/WorldPacket.h" + +namespace Movement +{ + UnitMoveType SelectSpeedType(uint32 moveFlags) + { + if (moveFlags & MOVEFLAG_FLYING) + { + if ( moveFlags & MOVEFLAG_BACKWARD /*&& speed_obj.flight >= speed_obj.flight_back*/ ) + return MOVE_FLIGHT_BACK; + else + return MOVE_FLIGHT; + } + else if (moveFlags & MOVEFLAG_SWIMMING) + { + if (moveFlags & MOVEFLAG_BACKWARD /*&& speed_obj.swim >= speed_obj.swim_back*/) + return MOVE_SWIM_BACK; + else + return MOVE_SWIM; + } + else if (moveFlags & MOVEFLAG_WALK_MODE) + { + //if ( speed_obj.run > speed_obj.walk ) + return MOVE_WALK; + } + else if (moveFlags & MOVEFLAG_BACKWARD /*&& speed_obj.run >= speed_obj.run_back*/) + return MOVE_RUN_BACK; + + return MOVE_RUN; + } + + void MoveSplineInit::Launch() + { + MoveSpline& move_spline = *unit.movespline; + + Vector3 real_position(unit.GetPositionX(),unit.GetPositionY(),unit.GetPositionZ()); + // there is a big chane that current position is unknown if current state is not finalized, need compute it + // this also allows calculate spline position and update map position in much greater intervals + if (!move_spline.Finalized()) + real_position = move_spline.ComputePosition(); + + if (args.path.empty()) + { + // should i do the things that user should do? + MoveTo(real_position); + } + + // corrent first vertex + args.path[0] = real_position; + uint32 moveFlags = unit.m_movementInfo.GetMovementFlags(); + if (args.flags.walkmode) + moveFlags |= MOVEFLAG_WALK_MODE; + else + moveFlags &= ~MOVEFLAG_WALK_MODE; + + moveFlags |= (MOVEFLAG_SPLINE_ENABLED|MOVEFLAG_FORWARD); + + if (args.velocity == 0.f) + args.velocity = unit.GetSpeed(SelectSpeedType(moveFlags)); + + if (!args.Validate()) + return; + + unit.m_movementInfo.SetMovementFlags((MovementFlags)moveFlags); + move_spline.Initialize(args); + + WorldPacket data(SMSG_MONSTER_MOVE, 64); + data << unit.GetPackGUID(); + PacketBuilder::WriteMonsterMove(move_spline, data); + unit.SendMessageToSet(&data,true); + } + + MoveSplineInit::MoveSplineInit(Unit& m) : unit(m) + { + // mix existing state into new + args.flags.walkmode = unit.m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE); + args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_FLYING|MOVEFLAG_LEVITATING)); + } + + void MoveSplineInit::SetFacing(const Unit * target) + { + args.flags.EnableFacingTarget(); + args.facing.target = target->GetGUID(); + } +} diff --git a/src/game/movement/MoveSplineInit.h b/src/game/movement/MoveSplineInit.h new file mode 100644 index 000000000..23a6f298e --- /dev/null +++ b/src/game/movement/MoveSplineInit.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_MOVESPLINEINIT_H +#define MANGOSSERVER_MOVESPLINEINIT_H + +#include "MoveSplineInitArgs.h" + +class Unit; + +namespace Movement +{ + /* Initializes and launches spline movement + */ + class TRINITY_DLL_SPEC MoveSplineInit + { + public: + + explicit MoveSplineInit(Unit& m); + + /* Final pass of initialization that launches spline movement. + */ + void Launch(); + + /* Adds movement by parabolic trajectory + * @param amplitude - the maximum height of parabola, value could be negative and positive + * @param start_time - delay between movement starting time and beginning to move by parabolic trajectory + * can't be combined with final animation + */ + void SetParabolic(float amplitude, float start_time, bool is_knockback = false); + + /* Adds final facing animation + * sets unit's facing to specified point/angle after all path done + * you can have only one final facing: previous will be overriden + */ + void SetFacing(float angle); + void SetFacing(Vector3 const& point); + void SetFacing(const Unit * target); + + /* Initializes movement by path + * @param path - array of points, shouldn't be empty + * @param pointId - Id of fisrt point of the path. Example: when third path point will be done it will notify that pointId + 3 done + */ + void MovebyPath(const PointsArray& path, int32 pointId = 0); + + /* Initializes simple A to B mition, A is current unit's position, B is destination + */ + void MoveTo(const Vector3& destination); + void MoveTo(float x, float y, float z); + + /* Sets Id of fisrt point of the path. When N-th path point will be done ILisener will notify that pointId + N done + * Needed for waypoint movement where path splitten into parts + */ + void SetFirstPointId(int32 pointId) { args.path_Idx_offset = pointId; } + + /* Enables CatmullRom spline interpolation mode(makes path smooth) + * if not enabled linear spline mode will be choosen. Disabled by default + */ + void SetSmooth(); + /* Enables CatmullRom spline interpolation mode, enables flying animation. Disabled by default + */ + void SetFly(); + /* Enables walk mode. Disabled by default + */ + void SetWalk(bool enable); + /* Makes movement cyclic. Disabled by default + */ + void SetCyclic(); + /* Enables falling mode. Disabled by default + */ + void SetFall(); + /* Disabled by default + */ + void SetBackward(); + + /* Sets the velocity (in case you want to have custom movement velocity) + * if no set, speed will be selected based on unit's speeds and current movement mode + * Has no effect if falling mode enabled + * velocity shouldn't be negative + */ + void SetVelocity(float velocity); + + PointsArray& Path() { return args.path; } + + protected: + + MoveSplineInitArgs args; + Unit& unit; + }; + + inline void MoveSplineInit::SetFly() { args.flags.EnableFlying();} + inline void MoveSplineInit::SetWalk(bool enable) { args.flags.walkmode = enable;} + inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom();} + inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true;} + inline void MoveSplineInit::SetFall() { args.flags.EnableFalling();} + inline void MoveSplineInit::SetVelocity(float vel){ args.velocity = vel;} + inline void MoveSplineInit::SetBackward() { args.flags.backward = true;} + + inline void MoveSplineInit::MovebyPath(const PointsArray& controls, int32 path_offset) + { + args.path_Idx_offset = path_offset; + args.path.assign(controls.begin(),controls.end()); + } + + inline void MoveSplineInit::MoveTo(float x, float y, float z) + { + Vector3 v(x,y,z); + MoveTo(v); + } + + inline void MoveSplineInit::MoveTo(const Vector3& dest) + { + args.path_Idx_offset = 0; + args.path.resize(2); + args.path[1] = dest; + } + + inline void MoveSplineInit::SetParabolic(float amplitude, float time_shift, bool is_knockback) + { + args.time_perc = time_shift; + args.parabolic_amplitude = amplitude; + args.flags.EnableParabolic(); + args.flags.knockback = is_knockback; + } + + inline void MoveSplineInit::SetFacing(float o) + { + args.facing.angle = G3D::wrap(o, 0.f, (float)G3D::twoPi()); + args.flags.EnableFacingAngle(); + } + + inline void MoveSplineInit::SetFacing(Vector3 const& spot) + { + args.facing.f.x = spot.x; + args.facing.f.y = spot.y; + args.facing.f.z = spot.z; + args.flags.EnableFacingPoint(); + } +} +#endif // MANGOSSERVER_MOVESPLINEINIT_H diff --git a/src/game/movement/MoveSplineInitArgs.h b/src/game/movement/MoveSplineInitArgs.h new file mode 100644 index 000000000..4dba63675 --- /dev/null +++ b/src/game/movement/MoveSplineInitArgs.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_MOVESPLINEINIT_ARGS_H +#define MANGOSSERVER_MOVESPLINEINIT_ARGS_H + +#include "MoveSplineFlag.h" +#include + +namespace Movement +{ + typedef std::vector PointsArray; + + union FacingInfo + { + struct{ + float x,y,z; + }f; + uint64 target; + float angle; + + FacingInfo(float o) : angle(o) {} + FacingInfo(uint64 t) : target(t) {} + FacingInfo() {} + }; + + struct MoveSplineInitArgs + { + MoveSplineInitArgs(size_t path_capacity = 16) : path_Idx_offset(0), + velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0) + { + path.reserve(path_capacity); + } + + PointsArray path; + FacingInfo facing; + MoveSplineFlag flags; + int32 path_Idx_offset; + float velocity; + float parabolic_amplitude; + float time_perc; + uint32 splineId; + + /** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */ + bool Validate() const; + private: + bool _checkPathBounds() const; + }; +} + +#endif // MANGOSSERVER_MOVESPLINEINIT_ARGS_H diff --git a/src/game/movement/packet_builder.cpp b/src/game/movement/packet_builder.cpp new file mode 100644 index 000000000..118d73857 --- /dev/null +++ b/src/game/movement/packet_builder.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "packet_builder.h" +#include "MoveSpline.h" +#include "WorldPacket.h" + +namespace Movement +{ + inline void operator << (ByteBuffer& b, const Vector3& v) + { + b << v.x << v.y << v.z; + } + + inline void operator >> (ByteBuffer& b, Vector3& v) + { + b >> v.x >> v.y >> v.z; + } + + enum MonsterMoveType + { + MonsterMoveNormal = 0, + MonsterMoveStop = 1, + MonsterMoveFacingSpot = 2, + MonsterMoveFacingTarget = 3, + MonsterMoveFacingAngle = 4 + }; + + void PacketBuilder::WriteCommonMonsterMovePart(const MoveSpline& move_spline, WorldPacket& data) + { + MoveSplineFlag splineflags = move_spline.splineflags; + + /*if (mov.IsBoarded()) + { + data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT); + data << mov.GetTransport()->Owner.GetPackGUID(); + data << int8(mov.m_unused.transport_seat); + }*/ + + // not exist in 2.4.3 mangos-one SendMonsterMove + //data << uint8(0); + data << move_spline.spline.getPoint(move_spline.spline.first()); + + // in mangos-one it is WorldTimer::getMSTime() + data << move_spline.GetId(); + + switch(splineflags & MoveSplineFlag::Mask_Final_Facing) + { + default: + data << uint8(MonsterMoveNormal); + break; + case MoveSplineFlag::Final_Target: + data << uint8(MonsterMoveFacingTarget); + data << move_spline.facing.target; + break; + case MoveSplineFlag::Final_Angle: + data << uint8(MonsterMoveFacingAngle); + data << move_spline.facing.angle; + break; + case MoveSplineFlag::Final_Point: + data << uint8(MonsterMoveFacingSpot); + data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z; + break; + } + + // add fake Enter_Cycle flag - needed for client-side cyclic movement (client will erase first spline vertex after first cycle done) + splineflags.enter_cycle = move_spline.isCyclic(); + data << uint32(splineflags & ~MoveSplineFlag::Mask_No_Monster_Move); + + if (splineflags.animation) + { + data << splineflags.getAnimationId(); + data << move_spline.effect_start_time; + } + + data << move_spline.Duration(); + + if (splineflags.parabolic) + { + data << move_spline.vertical_acceleration; + data << move_spline.effect_start_time; + } + } + + void WriteLinearPath(const Spline& spline, ByteBuffer& data) + { + sLog.outString("WriteLinearPath"); + uint32 last_idx = spline.getPointCount() - 3; + const Vector3 * real_path = &spline.getPoint(1); + + data << last_idx; + data << real_path[last_idx]; // destination + + if (last_idx > 1) + { + sLog.outString("Appennd path"); + Vector3 middle = (real_path[0] + real_path[last_idx]) / 2.f; + Vector3 offset; + // first and last points already appended + for(uint32 i = 1; i < last_idx; ++i) + { + offset = middle - real_path[i]; + data.appendPackXYZ(offset.x, offset.y, offset.z); + } + } + } + + void WriteCatmullRomPath(const Spline& spline, ByteBuffer& data) + { + sLog.outString("WriteCatmullRomPath"); + uint32 count = spline.getPointCount() - 3; + data << count; + data.append(&spline.getPoint(2), count); + } + + void WriteCatmullRomCyclicPath(const Spline& spline, ByteBuffer& data) + { + sLog.outString("WriteCatmullCyclicPath"); + uint32 count = spline.getPointCount() - 3; + data << uint32(count + 1); + data << spline.getPoint(1); // fake point, client will erase it from the spline after first cycle done + data.append(&spline.getPoint(1), count); + } + + void PacketBuilder::WriteMonsterMove(const MoveSpline& move_spline, WorldPacket& data) + { + WriteCommonMonsterMovePart(move_spline, data); + + const Spline& spline = move_spline.spline; + MoveSplineFlag splineflags = move_spline.splineflags; + if (splineflags & MoveSplineFlag::Mask_CatmullRom) + { + if (splineflags.cyclic) + WriteCatmullRomCyclicPath(spline, data); + else + WriteCatmullRomPath(spline, data); + } + else + WriteLinearPath(spline, data); + } + + void PacketBuilder::WriteCreate(const MoveSpline& move_spline, ByteBuffer& data) + { + //WriteClientStatus(mov,data); + //data.append(&mov.m_float_values[SpeedWalk], SpeedMaxCount); + //if (mov.SplineEnabled()) + { + MoveSplineFlag splineFlags = move_spline.splineflags; + + data << splineFlags.raw(); + + if (splineFlags.final_angle) + { + data << move_spline.facing.angle; + } + else if (splineFlags.final_target) + { + data << move_spline.facing.target; + } + else if (splineFlags.final_point) + { + data << move_spline.facing.f.x; + data << move_spline.facing.f.y; + data << move_spline.facing.f.z; + } + + data << move_spline.timePassed(); + data << move_spline.Duration(); + data << move_spline.GetId(); + + /*data << float(1.f);//splineInfo.duration_mod; + data << float(1.f);//splineInfo.duration_mod_next; + + data << move_spline.vertical_acceleration; + data << move_spline.effect_start_time;*/ + + uint32 nodes = move_spline.getPath().size(); + data << nodes; + data.append(&move_spline.getPath()[0], nodes); + + // 2.4.3 not exists + //data << uint8(move_spline.spline.mode()); + + data << (move_spline.isCyclic() ? Vector3::zero() : move_spline.FinalDestination()); + } + } +} diff --git a/src/game/movement/packet_builder.h b/src/game/movement/packet_builder.h new file mode 100644 index 000000000..a831c3a62 --- /dev/null +++ b/src/game/movement/packet_builder.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_PACKET_BUILDER_H +#define MANGOSSERVER_PACKET_BUILDER_H + +class ByteBuffer; +class WorldPacket; + +namespace Movement +{ + class MoveSpline; + class PacketBuilder + { + static void WriteCommonMonsterMovePart(const MoveSpline& mov, WorldPacket& data); + public: + + static void WriteMonsterMove(const MoveSpline& mov, WorldPacket& data); + static void WriteCreate(const MoveSpline& mov, ByteBuffer& data); + }; +} +#endif // MANGOSSERVER_PACKET_BUILDER_H diff --git a/src/game/movement/spline.cpp b/src/game/movement/spline.cpp new file mode 100644 index 000000000..9e3159485 --- /dev/null +++ b/src/game/movement/spline.cpp @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "spline.h" +#include +#include + +namespace Movement{ + +SplineBase::EvaluationMethtod SplineBase::evaluators[SplineBase::ModesEnd] = +{ + &SplineBase::EvaluateLinear, + &SplineBase::EvaluateCatmullRom, + &SplineBase::EvaluateBezier3, + (EvaluationMethtod)&SplineBase::UninitializedSpline, +}; + +SplineBase::EvaluationMethtod SplineBase::derivative_evaluators[SplineBase::ModesEnd] = +{ + &SplineBase::EvaluateDerivativeLinear, + &SplineBase::EvaluateDerivativeCatmullRom, + &SplineBase::EvaluateDerivativeBezier3, + (EvaluationMethtod)&SplineBase::UninitializedSpline, +}; + +SplineBase::SegLenghtMethtod SplineBase::seglengths[SplineBase::ModesEnd] = +{ + &SplineBase::SegLengthLinear, + &SplineBase::SegLengthCatmullRom, + &SplineBase::SegLengthBezier3, + (SegLenghtMethtod)&SplineBase::UninitializedSpline, +}; + +SplineBase::InitMethtod SplineBase::initializers[SplineBase::ModesEnd] = +{ + //&SplineBase::InitLinear, + &SplineBase::InitCatmullRom, // we should use catmullrom initializer even for linear mode! (client's internal structure limitation) + &SplineBase::InitCatmullRom, + &SplineBase::InitBezier3, + (InitMethtod)&SplineBase::UninitializedSpline, +}; + +/////////// +#pragma region evaluation methtods + +using G3D::Matrix4; +static const Matrix4 s_catmullRomCoeffs( + -0.5f, 1.5f,-1.5f, 0.5f, + 1.f, -2.5f, 2.f, -0.5f, + -0.5f, 0.f, 0.5f, 0.f, + 0.f, 1.f, 0.f, 0.f); + +static const Matrix4 s_Bezier3Coeffs( + -1.f, 3.f, -3.f, 1.f, + 3.f, -6.f, 3.f, 0.f, + -3.f, 3.f, 0.f, 0.f, + 1.f, 0.f, 0.f, 0.f); + +/* classic view: +inline void C_Evaluate(const Vector3 *vertice, float t, const float (&matrix)[4][4], Vector3 &position) +{ + Vector3 tvec(t*t*t, t*t, t); + int i = 0; + double c; + double x = 0, y = 0, z = 0; + while ( i < 4 ) + { + c = matrix[0][i]*tvec.x + matrix[1][i]*tvec.y + matrix[2][i]*tvec.z + matrix[3][i]; + + x += c * vertice->x; + y += c * vertice->y; + z += c * vertice->z; + + ++i; + ++vertice; + } + + position.x = x; + position.y = y; + position.z = z; +}*/ + +inline void C_Evaluate(const Vector3 *vertice, float t, const Matrix4& matr, Vector3 &result) +{ + Vector4 tvec(t*t*t, t*t, t, 1.f); + Vector4 weights(tvec * matr); + + result = vertice[0] * weights[0] + vertice[1] * weights[1] + + vertice[2] * weights[2] + vertice[3] * weights[3]; +} + +inline void C_Evaluate_Derivative(const Vector3 *vertice, float t, const Matrix4& matr, Vector3 &result) +{ + Vector4 tvec(3.f*t*t, 2.f*t, 1.f, 0.f); + Vector4 weights(tvec * matr); + + result = vertice[0] * weights[0] + vertice[1] * weights[1] + + vertice[2] * weights[2] + vertice[3] * weights[3]; +} + +void SplineBase::EvaluateLinear(index_type index, float u, Vector3& result) const +{ + ASSERT(index >= index_lo && index < index_hi); + result = points[index] + (points[index+1] - points[index]) * u; +} + +void SplineBase::EvaluateCatmullRom( index_type index, float t, Vector3& result) const +{ + ASSERT(index >= index_lo && index < index_hi); + C_Evaluate(&points[index - 1], t, s_catmullRomCoeffs, result); +} + +void SplineBase::EvaluateBezier3(index_type index, float t, Vector3& result) const +{ + index *= 3u; + ASSERT(index >= index_lo && index < index_hi); + C_Evaluate(&points[index], t, s_Bezier3Coeffs, result); +} + +void SplineBase::EvaluateDerivativeLinear(index_type index, float, Vector3& result) const +{ + ASSERT(index >= index_lo && index < index_hi); + result = points[index+1] - points[index]; +} + +void SplineBase::EvaluateDerivativeCatmullRom(index_type index, float t, Vector3& result) const +{ + ASSERT(index >= index_lo && index < index_hi); + C_Evaluate_Derivative(&points[index - 1], t, s_catmullRomCoeffs, result); +} + +void SplineBase::EvaluateDerivativeBezier3(index_type index, float t, Vector3& result) const +{ + index *= 3u; + ASSERT(index >= index_lo && index < index_hi); + C_Evaluate_Derivative(&points[index], t, s_Bezier3Coeffs, result); +} + +float SplineBase::SegLengthLinear(index_type index) const +{ + ASSERT(index >= index_lo && index < index_hi); + return (points[index] - points[index+1]).length(); +} + +float SplineBase::SegLengthCatmullRom( index_type index ) const +{ + ASSERT(index >= index_lo && index < index_hi); + + Vector3 curPos, nextPos; + const Vector3 * p = &points[index - 1]; + curPos = nextPos = p[1]; + + index_type i = 1; + double length = 0; + while (i <= STEPS_PER_SEGMENT) + { + C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_catmullRomCoeffs, nextPos); + length += (nextPos - curPos).length(); + curPos = nextPos; + ++i; + } + return length; +} + +float SplineBase::SegLengthBezier3(index_type index) const +{ + index *= 3u; + ASSERT(index >= index_lo && index < index_hi); + + Vector3 curPos, nextPos; + const Vector3 * p = &points[index]; + + C_Evaluate(p, 0.f, s_Bezier3Coeffs, nextPos); + curPos = nextPos; + + index_type i = 1; + double length = 0; + while (i <= STEPS_PER_SEGMENT) + { + C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_Bezier3Coeffs, nextPos); + length += (nextPos - curPos).length(); + curPos = nextPos; + ++i; + } + return length; +} +#pragma endregion + +void SplineBase::init_spline(const Vector3 * controls, index_type count, EvaluationMode m) +{ + m_mode = m; + cyclic = false; + + (this->*initializers[m_mode])(controls, count, cyclic, 0); +} + +void SplineBase::init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point) +{ + m_mode = m; + cyclic = true; + + (this->*initializers[m_mode])(controls, count, cyclic, cyclic_point); +} + +void SplineBase::InitLinear(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point) +{ + ASSERT(count >= 2); + const int real_size = count + 1; + + points.resize(real_size); + + memcpy(&points[0],controls, sizeof(Vector3) * count); + + // first and last two indexes are space for special 'virtual points' + // these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work + if (cyclic) + points[count] = controls[cyclic_point]; + else + points[count] = controls[count-1]; + + index_lo = 0; + index_hi = cyclic ? count : (count - 1); +} + +void SplineBase::InitCatmullRom(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point) +{ + const int real_size = count + (cyclic ? (1+2) : (1+1)); + + points.resize(real_size); + + int lo_index = 1; + int high_index = lo_index + count - 1; + + memcpy(&points[lo_index],controls, sizeof(Vector3) * count); + + // first and last two indexes are space for special 'virtual points' + // these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work + if (cyclic) + { + if (cyclic_point == 0) + points[0] = controls[count-1]; + else + points[0] = controls[0].lerp(controls[1], -1); + + points[high_index+1] = controls[cyclic_point]; + points[high_index+2] = controls[cyclic_point+1]; + } + else + { + points[0] = controls[0].lerp(controls[1], -1); + points[high_index+1] = controls[count-1]; + } + + index_lo = lo_index; + index_hi = high_index + (cyclic ? 1 : 0); +} + +void SplineBase::InitBezier3(const Vector3* controls, index_type count, bool /*cyclic*/, index_type /*cyclic_point*/) +{ + index_type c = count / 3u * 3u; + index_type t = c / 3u; + + points.resize(c); + memcpy(&points[0],controls, sizeof(Vector3) * c); + + index_lo = 0; + index_hi = t-1; + //mov_assert(points.size() % 3 == 0); +} + +void SplineBase::clear() +{ + index_lo = 0; + index_hi = 0; + points.clear(); +} + +std::string SplineBase::ToString() const +{ + std::stringstream str; + const char * mode_str[ModesEnd] = {"Linear", "CatmullRom", "Bezier3", "Uninitialized"}; + + index_type count = this->points.size(); + str << "mode: " << mode_str[mode()] << std::endl; + str << "points count: " << count << std::endl; + for (index_type i = 0; i < count; ++i) + str << "point " << i << " : " << points[i].toString() << std::endl; + + return str.str(); +} + +} diff --git a/src/game/movement/spline.h b/src/game/movement/spline.h new file mode 100644 index 000000000..1408f6551 --- /dev/null +++ b/src/game/movement/spline.h @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_SPLINE_H +#define MANGOSSERVER_SPLINE_H + +#include "typedefs.h" +#include + +namespace Movement { + +class SplineBase +{ +public: + typedef int index_type; + typedef std::vector ControlArray; + + enum EvaluationMode + { + ModeLinear, + ModeCatmullrom, + ModeBezier3_Unused, + UninitializedMode, + ModesEnd + }; + + #pragma region fields +protected: + ControlArray points; + + index_type index_lo; + index_type index_hi; + + uint8 m_mode; + bool cyclic; + + enum{ + // could be modified, affects segment length evaluation precision + // lesser value saves more performance in cost of lover precision + // minimal value is 1 + // client's value is 20, blizzs use 2-3 steps to compute length + STEPS_PER_SEGMENT = 3, + }; + static_assert(STEPS_PER_SEGMENT > 0, "shouldn't be lesser than 1"); + +protected: + void EvaluateLinear(index_type, float, Vector3&) const; + void EvaluateCatmullRom(index_type, float, Vector3&) const; + void EvaluateBezier3(index_type, float, Vector3&) const; + typedef void (SplineBase::*EvaluationMethtod)(index_type,float,Vector3&) const; + static EvaluationMethtod evaluators[ModesEnd]; + + void EvaluateDerivativeLinear(index_type, float, Vector3&) const; + void EvaluateDerivativeCatmullRom(index_type, float, Vector3&) const; + void EvaluateDerivativeBezier3(index_type, float, Vector3&) const; + static EvaluationMethtod derivative_evaluators[ModesEnd]; + + float SegLengthLinear(index_type) const; + float SegLengthCatmullRom(index_type) const; + float SegLengthBezier3(index_type) const; + typedef float (SplineBase::*SegLenghtMethtod)(index_type) const; + static SegLenghtMethtod seglengths[ModesEnd]; + + void InitLinear(const Vector3*, index_type, bool, index_type); + void InitCatmullRom(const Vector3*, index_type, bool, index_type); + void InitBezier3(const Vector3*, index_type, bool, index_type); + typedef void (SplineBase::*InitMethtod)(const Vector3*, index_type, bool, index_type); + static InitMethtod initializers[ModesEnd]; + + void UninitializedSpline() const { ASSERT(false);} + + #pragma endregion +public: + + explicit SplineBase() : m_mode(UninitializedMode), index_lo(0), index_hi(0), cyclic(false) {} + + /** Caclulates the position for given segment Idx, and percent of segment length t + @param t - percent of segment length, assumes that t in range [0, 1] + @param Idx - spline segment index, should be in range [first, last) + */ + void evaluate_percent(index_type Idx, float u, Vector3& c) const {(this->*evaluators[m_mode])(Idx,u,c);} + + /** Caclulates derivation in index Idx, and percent of segment length t + @param Idx - spline segment index, should be in range [first, last) + @param t - percent of spline segment length, assumes that t in range [0, 1] + */ + void evaluate_derivative(index_type Idx, float u, Vector3& hermite) const {(this->*derivative_evaluators[m_mode])(Idx,u,hermite);} + + /** Bounds for spline indexes. All indexes should be in range [first, last). */ + index_type first() const { return index_lo;} + index_type last() const { return index_hi;} + + bool empty() const { return index_lo == index_hi;} + EvaluationMode mode() const { return (EvaluationMode)m_mode;} + bool isCyclic() const { return cyclic;} + + const ControlArray& getPoints() const { return points;} + index_type getPointCount() const { return points.size();} + const Vector3& getPoint(index_type i) const { return points[i];} + + /** Initializes spline. Don't call other methods while spline not initialized. */ + void init_spline(const Vector3 * controls, index_type count, EvaluationMode m); + void init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point); + + /** As i can see there are a lot of ways how spline can be initialized + would be no harm to have some custom initializers. */ + template inline void init_spline(Init& initializer) + { + initializer(m_mode,cyclic,points,index_lo,index_hi); + } + + void clear(); + + /** Calculates distance between [i; i+1] points, assumes that index i is in bounds. */ + float SegLength(index_type i) const { return (this->*seglengths[m_mode])(i);} + + std::string ToString() const; +}; + +template +class Spline : public SplineBase +{ +public: + typedef length_type LengthType; + typedef std::vector LengthArray; + #pragma region fields +protected: + + LengthArray lengths; + + index_type computeIndexInBounds(length_type length) const; + #pragma endregion +public: + + explicit Spline(){} + + /** Calculates the position for given t + @param t - percent of spline's length, assumes that t in range [0, 1]. */ + void evaluate_percent(float t, Vector3 & c) const; + + /** Calculates derivation for given t + @param t - percent of spline's length, assumes that t in range [0, 1]. */ + void evaluate_derivative(float t, Vector3& hermite) const; + + /** Calculates the position for given segment Idx, and percent of segment length t + @param t = partial_segment_length / whole_segment_length + @param Idx - spline segment index, should be in range [first, last). */ + void evaluate_percent(index_type Idx, float u, Vector3& c) const { SplineBase::evaluate_percent(Idx,u,c);} + + /** Caclulates derivation for index Idx, and percent of segment length t + @param Idx - spline segment index, should be in range [first, last) + @param t - percent of spline segment length, assumes that t in range [0, 1]. */ + void evaluate_derivative(index_type Idx, float u, Vector3& c) const { SplineBase::evaluate_derivative(Idx,u,c);} + + // Assumes that t in range [0, 1] + index_type computeIndexInBounds(float t) const; + void computeIndex(float t, index_type& out_idx, float& out_u) const; + + /** Initializes spline. Don't call other methods while spline not initialized. */ + void init_spline(const Vector3 * controls, index_type count, EvaluationMode m) { SplineBase::init_spline(controls,count,m);} + void init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point) { SplineBase::init_cyclic_spline(controls,count,m,cyclic_point);} + + /** Initializes lengths with SplineBase::SegLength method. */ + void initLengths(); + + /** Initializes lengths in some custom way + Note that value returned by cacher must be greater or equal to previous value. */ + template inline void initLengths(T& cacher) + { + index_type i = index_lo; + lengths.resize(index_hi+1); + length_type prev_length = 0, new_length = 0; + while(i < index_hi) + { + new_length = cacher(*this, i); + lengths[++i] = new_length; + + ASSERT(prev_length <= new_length); + prev_length = new_length; + } + } + + /** Returns length of the whole spline. */ + length_type length() const { return lengths[index_hi];} + /** Returns length between given nodes. */ + length_type length(index_type first, index_type last) const { return lengths[last]-lengths[first];} + length_type length(index_type Idx) const { return lengths[Idx];} + + void set_length(index_type i, length_type length) { lengths[i] = length;} + void clear(); +}; + +} + +#include "spline.impl.h" + +#endif // MANGOSSERVER_SPLINE_H diff --git a/src/game/movement/spline.impl.h b/src/game/movement/spline.impl.h new file mode 100644 index 000000000..eded2d8c9 --- /dev/null +++ b/src/game/movement/spline.impl.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +namespace Movement +{ +template void Spline::evaluate_percent( float t, Vector3 & c ) const +{ + index_type Index; + float u; + computeIndex(t, Index, u); + evaluate_percent(Index, u, c); +} + +template void Spline::evaluate_derivative(float t, Vector3& hermite) const +{ + index_type Index; + float u; + computeIndex(t, Index, u); + evaluate_derivative(Index, u, hermite); +} + +template SplineBase::index_type Spline::computeIndexInBounds(length_type length_) const +{ +// Temporary disabled: causes infinite loop with t = 1.f +/* + index_type hi = index_hi; + index_type lo = index_lo; + + index_type i = lo + (float)(hi - lo) * t; + + while ((lengths[i] > length) || (lengths[i + 1] <= length)) + { + if (lengths[i] > length) + hi = i - 1; // too big + else if (lengths[i + 1] <= length) + lo = i + 1; // too small + + i = (hi + lo) / 2; + }*/ + + index_type i = index_lo; + index_type N = index_hi; + while (i+1 < N && lengths[i+1] < length_) + ++i; + + return i; +} + +template void Spline::computeIndex(float t, index_type& index, float& u) const +{ + ASSERT(t >= 0.f && t <= 1.f); + length_type length_ = t * length(); + index = computeIndexInBounds(length_); + ASSERT(index < index_hi); + u = (length_ - length(index)) / (float)length(index, index+1); +} + +template SplineBase::index_type Spline::computeIndexInBounds( float t ) const +{ + ASSERT(t >= 0.f && t <= 1.f); + return computeIndexInBounds(t * length()); +} + +template void Spline::initLengths() +{ + index_type i = index_lo; + length_type length = 0; + lengths.resize(index_hi+1); + while(i < index_hi ) + { + length += SegLength(i); + lengths[++i] = length; + } +} + +template void Spline::clear() +{ + SplineBase::clear(); + lengths.clear(); +} + +} diff --git a/src/game/movement/typedefs.h b/src/game/movement/typedefs.h new file mode 100644 index 000000000..0aa9d0c88 --- /dev/null +++ b/src/game/movement/typedefs.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_TYPEDEFS_H +#define MANGOSSERVER_TYPEDEFS_H + +#include "Common.h" + +namespace G3D +{ + class Vector2; + class Vector3; + class Vector4; +} + +namespace Movement +{ + using G3D::Vector2; + using G3D::Vector3; + using G3D::Vector4; + + inline uint32 SecToMS(float sec) + { + return static_cast(sec * 1000.f); + } + + inline float MSToSec(uint32 ms) + { + return ms / 1000.f; + } + +#ifndef static_assert + #define CONCAT(x, y) CONCAT1 (x, y) + #define CONCAT1(x, y) x##y + #define static_assert(expr, msg) typedef char CONCAT(static_assert_failed_at_line_, __LINE__) [(expr) ? 1 : -1] +#endif + + template + class counter + { + public: + counter() { init();} + + void Increase() + { + if (m_counter == limit) + init(); + else + ++m_counter; + } + + T NewId() { Increase(); return m_counter;} + T getCurrent() const { return m_counter;} + + private: + void init() { m_counter = 0; } + T m_counter; + }; + + typedef counter UInt32Counter; + + extern double gravity; + extern float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity); +} + +#endif // MANGOSSERVER_TYPEDEFS_H diff --git a/src/game/movement/util.cpp b/src/game/movement/util.cpp new file mode 100644 index 000000000..e912926ad --- /dev/null +++ b/src/game/movement/util.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MoveSplineFlag.h" +#include +#include + +namespace Movement +{ + double gravity = 19.29110527038574; + + /// Velocity bounds that makes fall speed limited + float terminalVelocity = 60.148003f; + float terminalSavefallVelocity = 7.f; + + const float terminal_length = float(terminalVelocity * terminalVelocity) / (2.f * gravity); + const float terminal_savefall_length = (terminalSavefallVelocity * terminalSavefallVelocity) / (2.f * gravity); + const float terminalFallTime = float(terminalVelocity/gravity); // the time that needed to reach terminalVelocity + + float computeFallTime(float path_length, bool isSafeFall) + { + if (path_length < 0.f) + return 0.f; + + float time; + if ( isSafeFall ) + { + if (path_length >= terminal_savefall_length) + time = (path_length - terminal_savefall_length)/terminalSavefallVelocity + terminalSavefallVelocity/gravity; + else + time = sqrtf(2.f * path_length/gravity); + } + else + { + if (path_length >= terminal_length) + time = (path_length - terminal_length)/terminalVelocity + terminalFallTime; + else + time = sqrtf(2.f * path_length/gravity); + } + + return time; + } + + float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity) + { + float termVel; + float result; + + if ( isSafeFall ) + termVel = terminalSavefallVelocity; + else + termVel = terminalVelocity; + + if ( start_velocity > termVel ) + start_velocity = termVel; + + float terminal_time = terminalFallTime - start_velocity / gravity; // the time that needed to reach terminalVelocity + + if ( t_passed > terminal_time ) + { + result = terminalVelocity*(t_passed - terminal_time) + + start_velocity*terminal_time + gravity*terminal_time*terminal_time*0.5f; + } + else + result = t_passed * (start_velocity + t_passed * gravity * 0.5f); + + return result; + } + + float computeFallElevation(float t_passed) + { + float result; + + if (t_passed > terminalFallTime) + { + //result = terminalVelocity * (t_passed - terminal_time) + gravity*terminal_time*terminal_time*0.5f; + // simplified view: + result = terminalVelocity * (t_passed - terminalFallTime) + terminal_length; + } + else + result = t_passed * t_passed * gravity * 0.5f; + + return result; + } + + #define STR(x) #x + + const char * g_MovementFlag_names[]= + { + STR(Forward ),// 0x00000001, + STR(Backward ),// 0x00000002, + STR(Strafe_Left ),// 0x00000004, + STR(Strafe_Right ),// 0x00000008, + STR(Turn_Left ),// 0x00000010, + STR(Turn_Right ),// 0x00000020, + STR(Pitch_Up ),// 0x00000040, + STR(Pitch_Down ),// 0x00000080, + + STR(Walk ),// 0x00000100, // Walking + STR(Ontransport ),// 0x00000200, + STR(Levitation ),// 0x00000400, + STR(Root ),// 0x00000800, + STR(Falling ),// 0x00001000, + STR(Fallingfar ),// 0x00002000, + STR(Pendingstop ),// 0x00004000, + STR(PendingSTRafestop ),// 0x00008000, + STR(Pendingforward ),// 0x00010000, + STR(Pendingbackward ),// 0x00020000, + STR(PendingSTRafeleft ),// 0x00040000, + STR(PendingSTRaferight ),// 0x00080000, + STR(Pendingroot ),// 0x00100000, + STR(Swimming ),// 0x00200000, // Appears With Fly Flag Also + STR(Ascending ),// 0x00400000, // Swim Up Also + STR(Descending ),// 0x00800000, // Swim Down Also + STR(Can_Fly ),// 0x01000000, // Can Fly In 3.3? + STR(Flying ),// 0x02000000, // Actual Flying Mode + STR(Spline_Elevation ),// 0x04000000, // Used For Flight Paths + STR(Spline_Enabled ),// 0x08000000, // Used For Flight Paths + STR(Waterwalking ),// 0x10000000, // Prevent Unit From Falling Through Water + STR(Safe_Fall ),// 0x20000000, // Active Rogue Safe Fall Spell (Passive) + STR(Hover ),// 0x40000000 + STR(Unknown13 ),// 0x80000000 + STR(Unk1 ), + STR(Unk2 ), + STR(Unk3 ), + STR(Fullspeedturning ), + STR(Fullspeedpitching ), + STR(Allow_Pitching ), + STR(Unk4 ), + STR(Unk5 ), + STR(Unk6 ), + STR(Unk7 ), + STR(Interp_Move ), + STR(Interp_Turning ), + STR(Interp_Pitching ), + STR(Unk8 ), + STR(Unk9 ), + STR(Unk10 ), + }; + + const char * g_SplineFlag_names[32]= + { + STR(Forward ),// 0x00000001, + STR(Backward ),// 0x00000002, + STR(Strafe_Left ),// 0x00000004, + STR(Strafe_Right ),// 0x00000008, + STR(Left ),// 0x00000010, + STR(Right ),// 0x00000020, + STR(Pitch_Up ),// 0x00000040, + STR(Pitch_Down ),// 0x00000080, + STR(Done ),// 0x00000100, + STR(Falling ),// 0x00000200, // Not Compartible With Trajectory Movement + STR(No_Spline ),// 0x00000400, + STR(Trajectory ),// 0x00000800, // Not Compartible With Fall Movement + STR(Walkmode ),// 0x00001000, + STR(Flying ),// 0x00002000, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation + STR(Knockback ),// 0x00004000, // Model Orientation Fixed + STR(Final_Point ),// 0x00008000, + STR(Final_Target ),// 0x00010000, + STR(Final_Angle ),// 0x00020000, + STR(Catmullrom ),// 0x00040000, // Used Catmullrom Interpolation Mode + STR(Cyclic ),// 0x00080000, // Movement By Cycled Spline + STR(Enter_Cycle ),// 0x00100000, // Everytime Appears With Cyclic Flag In Monster Move Packet + STR(Animation ),// 0x00200000, // Animationid (0...3), Uint32 Time, Not Compartible With Trajectory And Fall Movement + STR(Unknown4 ),// 0x00400000, // Disables Movement By Path + STR(Unknown5 ),// 0x00800000, + STR(Unknown6 ),// 0x01000000, + STR(Unknown7 ),// 0x02000000, + STR(Unknown8 ),// 0x04000000, + STR(Backward ),// 0x08000000, // Appears With Walkmode Flag, Nodes ),// 1, Handles Orientation + STR(Unknown10 ),// 0x10000000, + STR(Unknown11 ),// 0x20000000, + STR(Unknown12 ),// 0x40000000, + STR(Unknown13 ),// 0x80000000, + }; + + template + void print_flags(Flags t, const char* (&names)[N], std::string& str) + { + for (int i = 0; i < N; ++i) + { + if ((t & (Flags)(1 << i)) && names[i] != NULL) + str.append(" ").append(names[i]); + } + } + + std::string MoveSplineFlag::ToString() const + { + std::string str; + print_flags(raw(),g_SplineFlag_names,str); + return str; + } +} diff --git a/src/shared/ByteBuffer.h b/src/shared/ByteBuffer.h index c936cf449..a401ad40d 100755 --- a/src/shared/ByteBuffer.h +++ b/src/shared/ByteBuffer.h @@ -372,6 +372,15 @@ class ByteBuffer append(buffer.contents(), buffer.wpos()); } + void appendPackXYZ(float x, float y, float z) + { + uint32 packed = 0; + packed |= ((int)(x / 0.25f) & 0x7FF); + packed |= ((int)(y / 0.25f) & 0x7FF) << 11; + packed |= ((int)(z / 0.25f) & 0x3FF) << 22; + *this << packed; + } + void appendPackGUID(uint64 guid) { uint8 packGUID[8+1]; diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp index c48027c7a..2f80024fd 100755 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -408,18 +408,6 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiNodesStore, dbcPath,"TaxiNodes.dbc"); - // Initialize global taxinodes mask - memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask)); - for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) - { - if(sTaxiNodesStore.LookupEntry(i)) - { - uint8 field = (uint8)((i - 1) / 32); - uint32 submask = 1<<((i-1)%32); - sTaxiNodesMask[field] |= submask; - } - } - LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathStore, dbcPath,"TaxiPath.dbc"); for(uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i) if(TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i)) @@ -433,16 +421,60 @@ void LoadDBCStores(const std::string& dataPath) pathLength.resize(pathCount); // 0 and some other indexes not used for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) - ++pathLength[entry->path]; + { + if (pathLength[entry->path] < entry->index + 1) + pathLength[entry->path] = entry->index + 1; + } // Set path length sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used for(uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i) sTaxiPathNodesByPath[i].resize(pathLength[i]); - // fill data + // fill data (pointers to sTaxiPathNodeStore elements for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) - sTaxiPathNodesByPath[entry->path][entry->index] = TaxiPathNode(entry->mapid,entry->x,entry->y,entry->z,entry->actionFlag,entry->delay); - sTaxiPathNodeStore.Clear(); + sTaxiPathNodesByPath[entry->path].set(entry->index, entry); + + // Initialize global taxinodes mask + // include existing nodes that have at least single not spell base (scripted) path + { + std::set spellPaths; + for(uint32 i = 1; i < sSpellStore.GetNumRows (); ++i) + if(SpellEntry const* sInfo = sSpellStore.LookupEntry (i)) + for(int j=0; j < 3; ++j) + if(sInfo->Effect[j]==123 /*SPELL_EFFECT_SEND_TAXI*/) + spellPaths.insert(sInfo->EffectMiscValue[j]); + + memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask)); + for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) + { + TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i); + if(!node) + continue; + + TaxiPathSetBySource::const_iterator src_i = sTaxiPathSetBySource.find(i); + if(src_i!=sTaxiPathSetBySource.end() && !src_i->second.empty()) + { + bool ok = false; + for(TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin();dest_i != src_i->second.end(); ++dest_i) + { + // not spell path + if(spellPaths.find(dest_i->second.ID)==spellPaths.end()) + { + ok = true; + break; + } + } + + if(!ok) + continue; + } + + // valid taxi network node + uint8 field = (uint8)((i - 1) / 32); + uint32 submask = 1<<((i-1)%32); + sTaxiNodesMask[field] |= submask; + } + } LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTotemCategoryStore, dbcPath,"TotemCategory.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWMOAreaTableStore, dbcPath,"WMOAreaTable.dbc"); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 5158fba4f..05a462faf 100755 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -21,7 +21,9 @@ #ifndef DBCSTRUCTURE_H #define DBCSTRUCTURE_H +#include "Common.h" #include "DBCEnums.h" +#include "../game/Path.h" #include "Platform/Define.h" #include @@ -838,6 +840,9 @@ struct TaxiPathNodeEntry float z; uint32 actionFlag; uint32 delay; + + uint32 arrivalEventID; + uint32 departureEventID; }; struct TotemCategoryEntry @@ -920,19 +925,17 @@ struct TaxiPathBySourceAndDestination typedef std::map TaxiPathSetForSource; typedef std::map TaxiPathSetBySource; -struct TaxiPathNode +struct TaxiPathNodePtr { - TaxiPathNode() : mapid(0), x(0),y(0),z(0),actionFlag(0),delay(0) {} - TaxiPathNode(uint32 _mapid, float _x, float _y, float _z, uint32 _actionFlag, uint32 _delay) : mapid(_mapid), x(_x),y(_y),z(_z),actionFlag(_actionFlag),delay(_delay) {} + TaxiPathNodePtr() : i_ptr(NULL) {} + TaxiPathNodePtr(TaxiPathNodeEntry const* ptr) : i_ptr(ptr) {} - uint32 mapid; - float x; - float y; - float z; - uint32 actionFlag; - uint32 delay; + TaxiPathNodeEntry const* i_ptr; + + operator TaxiPathNodeEntry const& () const { return *i_ptr; } }; -typedef std::vector TaxiPathNodeList; + +typedef Path TaxiPathNodeList; typedef std::vector TaxiPathNodesByPath; #define TaxiMaskSize 16 diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 863b78bd8..46d73fc5c 100755 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -81,7 +81,7 @@ const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxi"; const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiix"; const char TaxiNodesEntryfmt[]="nifffxxxxxxxxxxxxxxxxxii"; const char TaxiPathEntryfmt[]="niii"; -const char TaxiPathNodeEntryfmt[]="diiifffiixx"; +const char TaxiPathNodeEntryfmt[]="diiifffiiii"; const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; const char WorldMapAreaEntryfmt[]="xinxffffi"; const char WMOAreaTableEntryfmt[]="niiixxxxxiixxxxxxxxxxxxxxxxx"; diff --git a/src/shared/Timer.h b/src/shared/Timer.h index 5429a8ef4..91d994211 100755 --- a/src/shared/Timer.h +++ b/src/shared/Timer.h @@ -141,4 +141,17 @@ struct PeriodicTimer int32 i_expireTime; }; +struct ShortTimeTracker +{ + public: + ShortTimeTracker(int32 expiry = 0) : i_expiryTime(expiry) {} + void Update(int32 diff) { i_expiryTime -= diff; } + bool Passed() const { return (i_expiryTime <= 0); } + void Reset(int32 interval) { i_expiryTime = interval; } + int32 GetExpiry() const { return i_expiryTime; } + + private: + int32 i_expiryTime; +}; + #endif diff --git a/win/VC10/game.vcxproj b/win/VC10/game.vcxproj index 8d443ddfd..04fe60b31 100644 --- a/win/VC10/game.vcxproj +++ b/win/VC10/game.vcxproj @@ -234,6 +234,11 @@ + + + + + @@ -246,7 +251,6 @@ - @@ -383,6 +387,14 @@ + + + + + + + + @@ -398,8 +410,6 @@ - - @@ -474,7 +484,6 @@ - diff --git a/win/VC10/game.vcxproj.filters b/win/VC10/game.vcxproj.filters index e102e1e89..5a911e694 100644 --- a/win/VC10/game.vcxproj.filters +++ b/win/VC10/game.vcxproj.filters @@ -52,6 +52,9 @@ {8944d8f8-adfe-406e-aeae-235e04130e1b} + + {ce30d0aa-dd1b-4030-b7eb-2695053e3691} + @@ -93,9 +96,6 @@ Objects - - Objects - Objects @@ -493,6 +493,21 @@ Warden + + Movement + + + Movement + + + Movement + + + Movement + + + Movement + @@ -534,12 +549,6 @@ Objects - - Objects - - - Objects - Objects @@ -762,9 +771,6 @@ Artificial Intelligence\PlayerAI - - Movement Generators - Movement Generators @@ -922,5 +928,29 @@ Warden + + Movement + + + Movement + + + Movement + + + Movement + + + Movement + + + Movement + + + Movement + + + Movement + \ No newline at end of file