Index: src/game/Object.cpp =================================================================== --- src/game/Object.cpp (working copy) +++ src/game/Object.cpp (working copy) @@ -808,31 +808,32 @@ void WorldObject::BuildHeartBeatMsg(WorldPacket *data) const { - data->Initialize(MSG_MOVE_HEARTBEAT, 32); //2 + data->Initialize(MSG_MOVE_HEARTBEAT, 32); - *data << GetGUID(); //8 - *data << uint32(0); //4 - *data << uint32(0); //4 + data->append(GetPackGUID()); + *data << uint32(0); + *data << uint32(0); - *data << m_positionX; //4 - *data << m_positionY; //4 - *data << m_positionZ; //4 + *data << m_positionX; + *data << m_positionY; + *data << m_positionZ; - *data << m_orientation; //4 + *data << m_orientation; + *data << uint32(0x0); } void WorldObject::BuildTeleportAckMsg(WorldPacket *data, float x, float y, float z, float ang) const { data->Initialize(MSG_MOVE_TELEPORT_ACK, 41); - *data << uint8(0xFF); - *data << GetGUID(); - *data << uint32(0x800000); - *data << uint16(0x67EE); - *data << uint16(0xD1EB); - *data << m_orientation; // instead of *data << z; + data->append(GetPackGUID()); + *data << uint32(0x0); + *data << uint32(0x0); + *data << getMSTime(); + + *data << x; *data << y; - *data << z; // instead of *data << ang; + *data << z; *data << ang; *data << uint32(0x0); } Index: src/game/Creature.h =================================================================== --- src/game/Creature.h (working copy) +++ src/game/Creature.h (working copy) @@ -244,6 +244,7 @@ bool Create (uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 Entry); bool CreateFromProto(uint32 guidlow,uint32 Entry); + bool LoadCreaturesAddon(uint32 guidlow); void SelectLevel(const CreatureInfo *cinfo); uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; } @@ -359,9 +360,6 @@ void setDeathState(DeathState s); // overwrite virtual Unit::setDeathState - void Say(char const* text, uint32 language); - void MonsterSay(char const *text, uint32 language, uint64 targetGUID); - bool LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId); virtual void SaveToDB(); // overwrited in Pet virtual void DeleteFromDB(); // overwrited in Pet Index: src/game/SpellEffects.cpp =================================================================== --- src/game/SpellEffects.cpp (working copy) +++ src/game/SpellEffects.cpp (working copy) @@ -46,6 +46,7 @@ #include "CreatureAI.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" +#include "BattleGround.h" pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= { @@ -53,7 +54,7 @@ &Spell::EffectInstaKill, //SPELL_EFFECT_INSTAKILL = 1 &Spell::EffectSchoolDMG, //SPELL_EFFECT_SCHOOL_DAMAGE = 2 &Spell::EffectDummy, //SPELL_EFFECT_DUMMY = 3 - &Spell::EffectNULL, //SPELL_EFFECT_PORTAL_TELEPORT = 4 + &Spell::EffectNULL, //SPELL_EFFECT_PORTAL_TELEPORT = 4, unused &Spell::EffectTeleportUnits, //SPELL_EFFECT_TELEPORT_UNITS = 5 &Spell::EffectApplyAura, //SPELL_EFFECT_APPLY_AURA = 6 &Spell::EffectSchoolDMG, //SPELL_EFFECT_ENVIRONMENTAL_DAMAGE =7 @@ -62,31 +63,31 @@ &Spell::EffectHeal, //SPELL_EFFECT_HEAL = 10 &Spell::EffectNULL, //SPELL_EFFECT_BIND = 11 &Spell::EffectNULL, //SPELL_EFFECT_PORTAL = 12 - &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_BASE = 13 - &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_SPECIALIZE = 14 - &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15 + &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_BASE = 13, unused + &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_SPECIALIZE = 14, unused + &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15, unused &Spell::EffectQuestComplete, //SPELL_EFFECT_QUEST_COMPLETE = 16 &Spell::EffectWeaponDmg, //SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL = 17 &Spell::EffectResurrect, //SPELL_EFFECT_RESURRECT = 18 &Spell::EffectNULL, //SPELL_EFFECT_ADD_EXTRA_ATTACKS = 19 - &Spell::EffectNULL, //SPELL_EFFECT_DODGE = 20 - &Spell::EffectNULL, //SPELL_EFFECT_EVADE = 21 + &Spell::EffectNULL, //SPELL_EFFECT_DODGE = 20, one spell: Dodge + &Spell::EffectNULL, //SPELL_EFFECT_EVADE = 21, one spell: Evade (DND) &Spell::EffectParry, //SPELL_EFFECT_PARRY = 22 - &Spell::EffectNULL, //SPELL_EFFECT_BLOCK = 23 + &Spell::EffectNULL, //SPELL_EFFECT_BLOCK = 23, one spell: Block &Spell::EffectCreateItem, //SPELL_EFFECT_CREATE_ITEM = 24 &Spell::EffectNULL, //SPELL_EFFECT_WEAPON = 25 - &Spell::EffectNULL, //SPELL_EFFECT_DEFENSE = 26 + &Spell::EffectNULL, //SPELL_EFFECT_DEFENSE = 26, one spell: Defence &Spell::EffectPersistentAA, //SPELL_EFFECT_PERSISTENT_AREA_AURA = 27 &Spell::EffectSummon, //SPELL_EFFECT_SUMMON = 28 &Spell::EffectMomentMove, //SPELL_EFFECT_LEAP = 29 &Spell::EffectEnergize, //SPELL_EFFECT_ENERGIZE = 30 &Spell::EffectWeaponDmg, //SPELL_EFFECT_WEAPON_PERCENT_DAMAGE = 31 - &Spell::EffectNULL, //SPELL_EFFECT_TRIGGER_MISSILE = 32 //Useless + &Spell::EffectNULL, //SPELL_EFFECT_TRIGGER_MISSILE = 32 &Spell::EffectOpenLock, //SPELL_EFFECT_OPEN_LOCK = 33 &Spell::EffectSummonChangeItem, //SPELL_EFFECT_SUMMON_CHANGE_ITEM = 34 &Spell::EffectApplyAA, //SPELL_EFFECT_APPLY_AREA_AURA = 35 &Spell::EffectLearnSpell, //SPELL_EFFECT_LEARN_SPELL = 36 - &Spell::EffectNULL, //SPELL_EFFECT_SPELL_DEFENSE = 37 //Useless + &Spell::EffectNULL, //SPELL_EFFECT_SPELL_DEFENSE = 37, one spell: SPELLDEFENSE (DND) &Spell::EffectDispel, //SPELL_EFFECT_DISPEL = 38 &Spell::EffectNULL, //SPELL_EFFECT_LANGUAGE = 39 &Spell::EffectDualWield, //SPELL_EFFECT_DUAL_WIELD = 40 @@ -94,14 +95,14 @@ &Spell::EffectSummonWild, //SPELL_EFFECT_SUMMON_GUARDIAN = 42 &Spell::EffectTeleUnitsFaceCaster, //SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER = 43 &Spell::EffectLearnSkill, //SPELL_EFFECT_SKILL_STEP = 44 - &Spell::EffectNULL, //unknown45 = 45 - &Spell::EffectNULL, //SPELL_EFFECT_SPAWN = 46 + &Spell::EffectNULL, //unknown45 = 45, honor/pvp related + &Spell::EffectNULL, //SPELL_EFFECT_SPAWN = 46, we must spawn pet there &Spell::EffectTradeSkill, //SPELL_EFFECT_TRADE_SKILL = 47 - &Spell::EffectNULL, //SPELL_EFFECT_STEALTH = 48 //Useless - &Spell::EffectNULL, //SPELL_EFFECT_DETECT = 49 + &Spell::EffectNULL, //SPELL_EFFECT_STEALTH = 48, one spell: Base Stealth + &Spell::EffectNULL, //SPELL_EFFECT_DETECT = 49, one spell: Detect &Spell::EffectTransmitted, //SPELL_EFFECT_TRANS_DOOR = 50 - &Spell::EffectNULL, //SPELL_EFFECT_FORCE_CRITICAL_HIT = 51 //Useless - &Spell::EffectNULL, //SPELL_EFFECT_GUARANTEE_HIT = 52 + &Spell::EffectNULL, //SPELL_EFFECT_FORCE_CRITICAL_HIT = 51, unused + &Spell::EffectNULL, //SPELL_EFFECT_GUARANTEE_HIT = 52, one spell: zzOLDCritical Shot &Spell::EffectEnchantItemPerm, //SPELL_EFFECT_ENCHANT_ITEM = 53 &Spell::EffectEnchantItemTmp, //SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY = 54 &Spell::EffectTameCreature, //SPELL_EFFECT_TAMECREATURE = 55 @@ -114,23 +115,23 @@ &Spell::EffectPowerDrain, //SPELL_EFFECT_POWER_BURN = 62 &Spell::EffectThreat, //SPELL_EFFECT_THREAT = 63 &Spell::EffectTriggerSpell, //SPELL_EFFECT_TRIGGER_SPELL = 64 - &Spell::EffectNULL, //SPELL_EFFECT_HEALTH_FUNNEL = 65 //Useless - &Spell::EffectNULL, //SPELL_EFFECT_POWER_FUNNEL = 66 //Useless + &Spell::EffectNULL, //SPELL_EFFECT_HEALTH_FUNNEL = 65, unused + &Spell::EffectNULL, //SPELL_EFFECT_POWER_FUNNEL = 66, unused &Spell::EffectHealMaxHealth, //SPELL_EFFECT_HEAL_MAX_HEALTH = 67 &Spell::EffectInterruptCast, //SPELL_EFFECT_INTERRUPT_CAST = 68 &Spell::EffectNULL, //SPELL_EFFECT_DISTRACT = 69 - &Spell::EffectNULL, //SPELL_EFFECT_PULL = 70 + &Spell::EffectNULL, //SPELL_EFFECT_PULL = 70, one spell: Distract Move &Spell::EffectPickPocket, //SPELL_EFFECT_PICKPOCKET = 71 &Spell::EffectAddFarsight, //SPELL_EFFECT_ADD_FARSIGHT = 72 &Spell::EffectSummonWild, //SPELL_EFFECT_SUMMON_POSSESSED = 73 - &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_TOTEM = 74 //Useless - &Spell::EffectNULL, //SPELL_EFFECT_HEAL_MECHANICAL = 75 + &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_TOTEM = 74 + &Spell::EffectNULL, //SPELL_EFFECT_HEAL_MECHANICAL = 75, one spell: Mechanical Patch Kit &Spell::EffectSummonObjectWild, //SPELL_EFFECT_SUMMON_OBJECT_WILD = 76 &Spell::EffectScriptEffect, //SPELL_EFFECT_SCRIPT_EFFECT = 77 - &Spell::EffectNULL, //SPELL_EFFECT_ATTACK = 78 //Useless + &Spell::EffectNULL, //SPELL_EFFECT_ATTACK = 78 &Spell::EffectSanctuary, //SPELL_EFFECT_SANCTUARY = 79 &Spell::EffectAddComboPoints, //SPELL_EFFECT_ADD_COMBO_POINTS = 80 - &Spell::EffectNULL, //SPELL_EFFECT_CREATE_HOUSE = 81 + &Spell::EffectNULL, //SPELL_EFFECT_CREATE_HOUSE = 81: one spell: Create House (TEST) &Spell::EffectNULL, //SPELL_EFFECT_BIND_SIGHT = 82 &Spell::EffectDuel, //SPELL_EFFECT_DUEL = 83 &Spell::EffectStuck, //SPELL_EFFECT_STUCK = 84 @@ -140,7 +141,7 @@ &Spell::EffectSummonTotem, //SPELL_EFFECT_SUMMON_TOTEM_SLOT2 = 88 &Spell::EffectSummonTotem, //SPELL_EFFECT_SUMMON_TOTEM_SLOT3 = 89 &Spell::EffectSummonTotem, //SPELL_EFFECT_SUMMON_TOTEM_SLOT4 = 90 - &Spell::EffectNULL, //SPELL_EFFECT_THREAT_ALL = 91 + &Spell::EffectNULL, //SPELL_EFFECT_THREAT_ALL = 91, one spell: zzOLDBrainwash &Spell::EffectEnchantHeldItem, //SPELL_EFFECT_ENCHANT_HELD_ITEM = 92 &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_PHANTASM = 93 &Spell::EffectSelfResurrect, //SPELL_EFFECT_SELF_RESURRECT = 94 @@ -165,12 +166,26 @@ &Spell::EffectResurrectNew, //SPELL_EFFECT_RESURRECT_NEW = 113 &Spell::EffectAttackMe, //SPELL_EFFECT_ATTACK_ME = 114 &Spell::EffectNULL, //SPELL_EFFECT_DURABILITY_DAMAGE_PCT = 115 - &Spell::EffectNULL, //SPELL_EFFECT_SKIN_PLAYER_CORPSE = 116 - &Spell::EffectNULL, //SPELL_EFFECT_SPIRIT_HEAL = 117 + &Spell::EffectNULL, //SPELL_EFFECT_SKIN_PLAYER_CORPSE = 116, one spell: Remove Insignia, bg usage, required special corpse flags... + &Spell::EffectNULL, //SPELL_EFFECT_SPIRIT_HEAL = 117, one spell: Spirit Heal &Spell::EffectSkill, //SPELL_EFFECT_SKILL = 118 -- professions and more &Spell::EffectNULL, //SPELL_EFFECT_APPLY_AURA_NEW = 119 - &Spell::EffectNULL, //SPELL_EFFECT_TELEPORT_GRAVEYARD = 120 - &Spell::EffectWeaponDmg //SPELL_EFFECT_NORMALIZED_WEAPON_DMG = 121 + &Spell::EffectNULL, //SPELL_EFFECT_TELEPORT_GRAVEYARD = 120, two spells: Graveyard Teleport and Graveyard Teleport Test + &Spell::EffectWeaponDmg, //SPELL_EFFECT_NORMALIZED_WEAPON_DMG = 121 + &Spell::EffectNULL, //SPELL_EFFECT_122 = 122 -- silithist cap reward spell + &Spell::EffectNULL, //SPELL_EFFECT_123 = 123 -- taxi/fligth related + &Spell::EffectNULL, //SPELL_EFFECT_124 = 124 -- aggro redirect? + &Spell::EffectNULL, //SPELL_EFFECT_125 = 125 -- invis? + &Spell::EffectNULL, //SPELL_EFFECT_126 = 126 -- spell steal effect? + &Spell::EffectNULL, //SPELL_EFFECT_127 = 127 -- Prospecting spell + &Spell::EffectNULL, //SPELL_EFFECT_128 = 128 + &Spell::EffectNULL, //SPELL_EFFECT_129 = 129 + &Spell::EffectNULL, //SPELL_EFFECT_130 = 130 -- threat redirect + &Spell::EffectNULL, //SPELL_EFFECT_131 = 131 -- unused + &Spell::EffectNULL, //SPELL_EFFECT_132 = 132 -- taxi related, one spell: Brazen Taxi + &Spell::EffectNULL, //SPELL_EFFECT_133 = 133 -- one spell: Forget + &Spell::EffectNULL, //SPELL_EFFECT_134 = 134 + &Spell::EffectNULL, //SPELL_EFFECT_135 = 135 -- pet related }; void Spell::EffectNULL(uint32 i) @@ -603,7 +618,7 @@ { if(!unitTarget) return; - if(!unitTarget->isAlive()) + if(!unitTarget->isAlive() && !(m_spellInfo->Id == 20584 || m_spellInfo->Id == 8326)) // ghost spell check return; //If m_immuneToState type contain this aura type, IMMUNE aura. @@ -617,6 +632,9 @@ Aura* Aur = new Aura(m_spellInfo, i, unitTarget,m_caster, m_CastItem); + if(!Aur) // is it useless? + return; + if (!Aur->IsPositive() && Aur->GetCasterGUID() != Aur->GetTarget()->GetGUID()) { switch (Aur->GetModifier()->m_auraname) @@ -630,6 +648,7 @@ case SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS: case SPELL_AURA_PERIODIC_TRIGGER_SPELL: case SPELL_AURA_EMPATHY: + case SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS: break; default: if(Aur->GetTarget()->GetTypeId() == TYPEID_UNIT && !Aur->GetTarget()->isInCombat()) @@ -672,6 +691,11 @@ bool added = unitTarget->AddAura(Aur); + // found crash at character loading, broken pointer to Aur... + // Aur was deleted in AddAura()... + if(!Aur) + return; + if (added) { if(auraDuration == 0) @@ -1595,10 +1619,10 @@ pet->SetPower( POWER_HAPPINESS,600000); pet->setPowerType(POWER_FOCUS); pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); - pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0); + pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,time(NULL)); pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0); pet->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000); - pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN1 + UNIT_FLAG_RESTING + UNIT_FLAG_RENAME); + pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN1);// + UNIT_FLAG_RENAME + UNIT_FLAG_RESTING); // this enables popup window (pet details, abandon, rename) uint32 new_id = 1; @@ -1698,7 +1722,7 @@ NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0,2048); NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1,0); - NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,5); + NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,time(NULL)); NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0); NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000); NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); @@ -1752,9 +1776,10 @@ NewSummon->SetName(new_name); } else if(NewSummon->getPetType()==HUNTER_PET) - { + { // this enables popup window (pet details, abandon, rename) - NewSummon->SetFlag(UNIT_FIELD_FLAGS,(UNIT_FLAG_RESTING | UNIT_FLAG_RENAME)); + //NewSummon->SetFlag(UNIT_FIELD_FLAGS,(UNIT_FLAG_RESTING | UNIT_FLAG_RENAME)); // changed in 2.0.8? + NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_2, uint32(2 << 16)); // check it! } NewSummon->AIM_Initialize(); @@ -2003,7 +2028,7 @@ m_caster->GetClosePoint(NULL,x,y,z); if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, target->GetMapId(), - x, y, z, target->GetOrientation(), 0, 0, 0, 0, 0, 0)) + x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 0)) { delete pGameObj; return; @@ -2019,6 +2044,8 @@ void Spell::EffectScriptEffect(uint32 i) { + // we must implement hunter pet summon at login there (spell 6962) + if(!m_spellInfo->Reagent[0]) { // paladin's holy light / flash of light @@ -2155,7 +2182,7 @@ pGameObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 787 ); pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() ); - pGameObj->SetUInt32Value(GAMEOBJECT_TYPE_ID, 16 ); + pGameObj->SetUInt32Value(GAMEOBJECT_TYPE_ID, GAMEOBJECT_TYPE_DUEL_ARBITER ); pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 ); int32 duration = GetDuration(m_spellInfo); pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); @@ -2199,7 +2226,16 @@ return; sLog.outDebug("Spell Effect: Stuck"); + sLog.outCommand("Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", m_caster->GetName(), m_caster->GetGUIDLow(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ()); HandleTeleport(m_spellInfo->Id, m_caster); + + // from patch 2.0.12 Stuck spell trigger Hearthstone cooldown + //((Player*)m_caster)->AddSpellCooldown(8690, time(NULL) + 3600); // add 1 hour cooldown to Hearthstone + SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690); + if(!spellInfo) + return; + Spell spell(m_caster,spellInfo,true,0); + spell.SendSpellCooldown(); } void Spell::EffectSummonPlayer(uint32 i) @@ -2211,6 +2247,11 @@ return; //FIXME: must send accepting request for summon to target instead explicit teleportation + // SMSG_SUMMON_REQUEST (683) + // uint64 summoner_guid + // uint32 summon_zoneid + // uint32 ms_time (auto decline?) + // CMSG_SUMMON_RESPONSE - empty // before caster float x,y,z; @@ -2297,22 +2338,25 @@ if(!pEnchant) return; - // remove old enchanting before applying new - if(uint32 old_enchant_id = item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3)) - item_owner->AddItemEnchant(item,old_enchant_id,pEnchant->display_type,false); + // remove old enchanting before appling new + for (int s=0;s<3;s++) + { + if(uint32 old_enchant_id = item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type[s]*3)) + item_owner->AddItemEnchant(item,old_enchant_id,pEnchant->display_type[s],false); - for(int x=0;x<3;x++) - item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3+x,0); + for(int x=0;x<3;x++) + item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type[s]*3+x,0); - item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3, enchant_id); - item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3+1, duration*1000); - item->SetState(ITEM_CHANGED); + item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type[s]*3, enchant_id); + item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type[s]*3+1, duration*1000); + item->SetState(ITEM_CHANGED); - // add new enchanting - item_owner->AddItemEnchant(item,enchant_id,pEnchant->display_type,true); + // add new enchanting + item_owner->AddItemEnchant(item,enchant_id,pEnchant->display_type[s],true); - // set duration - item_owner->AddEnchantDuration(item,1,duration*1000); + // set duration + item_owner->AddEnchantDuration(item,1,duration*1000); + } } } @@ -2774,8 +2818,8 @@ pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); } - pGameObj->SetUInt32Value(12, 0x3F63BB3C ); - pGameObj->SetUInt32Value(13, 0xBEE9E017 ); + //pGameObj->SetUInt32Value(12, 0x3F63BB3C ); // useless rotation + //pGameObj->SetUInt32Value(13, 0xBEE9E017 ); // useless rotation pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); pGameObj->SetSpellId(m_spellInfo->Id); Index: src/game/Transports.cpp =================================================================== --- src/game/Transports.cpp (working copy) +++ src/game/Transports.cpp (working copy) @@ -420,9 +420,9 @@ plr->TeleportTo(newMapid, x, y, z, GetOrientation(), true,false); - WorldPacket data(0x32B, 4); - data << uint32(0); - plr->GetSession()->SendPacket(&data); + //WorldPacket data(SMSG_811, 4); + //data << uint32(0); + //plr->GetSession()->SendPacket(&data); } return; Index: src/game/QuestDef.h =================================================================== --- src/game/QuestDef.h (working copy) +++ src/game/QuestDef.h (working copy) @@ -161,8 +161,8 @@ float GetPointX() { return PointX; } float GetPointY (){ return PointY; } uint32 GetPointOpt() { return PointOpt; } - uint32 GetOfferRewardEmote() { return OfferRewardEmote; } - uint32 GetRequestItemsEmote() { return RequestItemsEmote; } + uint32 GetIncompleteEmote() { return IncompleteEmote; } + uint32 GetCompleteEmote() { return CompleteEmote; } uint32 GetQuestCompleteScript() { return QuestCompleteScript; } bool IsRepeatable() { return bool(Repeatable); } bool IsAutoComplete() { return strlen(GetObjectives()) == 0; } @@ -183,7 +183,9 @@ uint32 RewItemId[QUEST_REWARDS_COUNT]; uint32 RewItemCount[QUEST_REWARDS_COUNT]; uint32 RewRepFaction[QUEST_REPUTATIONS_COUNT]; - int32 RewRepValue[QUEST_REPUTATIONS_COUNT]; + int32 RewRepValue[QUEST_REPUTATIONS_COUNT]; + uint32 DetailsEmote[QUEST_EMOTE_COUNT]; + uint32 OfferRewardEmote[QUEST_EMOTE_COUNT]; uint32 GetReqItemsCount() { return m_reqitemscount; } uint32 GetReqCreatureOrGOcount() { return m_reqCreatureOrGOcount; } @@ -234,10 +236,10 @@ uint32 RewSpell; uint32 PointMapId; float PointX; - float PointY; - uint32 PointOpt; - uint32 OfferRewardEmote; - uint32 RequestItemsEmote; + float PointY; + uint32 PointOpt; + uint32 IncompleteEmote; + uint32 CompleteEmote; uint32 QuestCompleteScript; uint32 Repeatable; }; Index: src/game/PetHandler.cpp =================================================================== --- src/game/PetHandler.cpp (working copy) +++ src/game/PetHandler.cpp (working copy) @@ -299,11 +299,12 @@ recv_data >> name; Pet* pet = ObjectAccessor::Instance().GetPet(petguid); - if(!pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || !pet->HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_RENAME) || pet->GetOwnerGUID() != _player->GetGUID() ) + if(!pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || (pet->GetUInt32Value(UNIT_FIELD_BYTES_2) >> 16) != 3 || pet->GetOwnerGUID() != _player->GetGUID() ) // check it! return; pet->SetName(name); - pet->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_RENAME); + //pet->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_RENAME); + pet->SetUInt32Value(UNIT_FIELD_BYTES_2, uint32(2 << 16)); // check it! sDatabase.escape_string(name); sDatabase.PExecute("UPDATE `character_pet` SET `name` = '%s', `renamed` = '1' WHERE `owner` = '%u' AND `id` = '%u'", name.c_str(),_player->GetGUIDLow(),pet->GetPetNumber() ); Index: src/game/MovementHandler.cpp =================================================================== --- src/game/MovementHandler.cpp (working copy) +++ src/game/MovementHandler.cpp (working copy) @@ -35,9 +35,12 @@ GetPlayer()->RemoveFromWorld(); MapManager::Instance().GetMap(GetPlayer()->GetMapId(), GetPlayer())->Add(GetPlayer()); WorldPacket data(SMSG_SET_REST_START, 4); - data << uint32(8129); + data << uint32(time(NULL));//getMSTime(); SendPacket(&data); + GetPlayer()->SetDontMove(false); + + _player->SendAllowMove(); // resend after worldport complete } void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) @@ -58,7 +61,7 @@ recv_data >> flags >> time; recv_data >> x >> y >> z >> orientation; - if (flags & MOVEMENTFLAG_ONTRANSPORT) + if (flags & MOVEMENTFLAG_ONTRANSPORT) // and if opcode 909? { // recheck CHECK_PACKET_SIZE(recv_data,recv_data.rpos()+4+4+4+4+4+4); @@ -79,7 +82,7 @@ recv_data >> fallTime; // duration of last jump (when in jump duration from jump begin to now) - if (flags & MOVEMENTFLAG_JUMPING) + if ( (flags & MOVEMENTFLAG_JUMPING) || (flags & MOVEMENTFLAG_FALLING) ) { // recheck CHECK_PACKET_SIZE(recv_data,recv_data.rpos()+4+4+4+4); @@ -228,7 +231,7 @@ UnitMoveType move_type; - static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "Walkback", "Swim", "Swimback", "Turn" }; + static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "Walkback", "Swim", "Swimback", "Turn", "Fly", "Flyback" }; uint16 opcode = recv_data.GetOpcode(); switch(opcode) @@ -239,6 +242,8 @@ case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; break; case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIMBACK; break; case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN; break; + case CMSG_FORCE_FLY_SPEED_CHANGE_ACK: move_type = MOVE_FLY; break; + case CMSG_FORCE_FLY_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLYBACK; break; default: sLog.outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u",opcode); return; @@ -271,13 +276,12 @@ void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data) { - //CMSG_SET_ACTIVE_MOVER sLog.outDebug("WORLD: Recvd CMSG_SET_ACTIVE_MOVER"); - CHECK_PACKET_SIZE(recv_data,4+4); + CHECK_PACKET_SIZE(recv_data,8); - uint32 guild, time; - recv_data >> guild >> time; + uint64 guid; + recv_data >> guid; } void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket &recvdata) @@ -293,7 +297,7 @@ void WorldSession::HandleMoveKnockBackAck( WorldPacket & recv_data ) { // CHECK_PACKET_SIZE(recv_data,?); - + sLog.outDebug("CMSG_MOVE_KNOCK_BACK_ACK"); // Currently not used but maybe use later for recheck final player position // (must be at call same as into "recv_data >> x >> y >> z >> orientation;" @@ -322,10 +326,10 @@ void WorldSession::HandleMoveHoverAck( WorldPacket & recv_data ) { + sLog.outDebug("CMSG_MOVE_HOVER_ACK"); } void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recv_data) { - // TODO - // we receive guid,x,y,z + sLog.outDebug("CMSG_MOVE_WATER_WALK_ACK"); } Index: src/game/ItemHandler.cpp =================================================================== --- src/game/ItemHandler.cpp (working copy) +++ src/game/ItemHandler.cpp (working copy) @@ -199,16 +199,21 @@ sLog.outDetail("STORAGE: Item Query = %u", item); ItemPrototype const *pProto = objmgr.GetItemPrototype( item ); + + uint16 itempos = _player->GetPosByGuid(guidLow); + Item *pItem = _player->GetItemByPos( itempos ); + if( pProto ) { data << pProto->ItemId; data << pProto->Class; // client known only 0 subclass (and 1-2 obsolute subclasses) - data << (pProto->Class==ITEM_CLASS_CONSUMABLE ? uint32(0) : pProto->SubClass); + data << (pProto->Class==ITEM_CLASS_CONSUMABLE ? uint32(0) : pProto->SubClass); // probably wrong + data << uint32(-1); // new 2.0.3, not exist in wdb cache? data << pProto->Name1; - data << pProto->Name2; - data << pProto->Name3; - data << pProto->Name4; + data << pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name... + data << pProto->Name3; // blizz not send name there, just uint8(0x00); + data << pProto->Name4; // blizz not send name there, just uint8(0x00); data << pProto->DisplayInfoID; data << pProto->Quality; data << pProto->Flags; @@ -259,8 +264,23 @@ if(!spell) { data << uint32(0); + if (pItem) + { + if ((s < 3) && (pItem->GetUInt32Value(ITEM_FIELD_SOCKETS_ENCHANTMENT+s*3))) + { + data << uint32(1); + } + else + { + data <Material; data << pProto->Sheath; data << pProto->Extra; + data << pProto->Unk4; // new 2.0.3 data << pProto->Block; data << pProto->ItemSet; data << pProto->MaxDurability; data << pProto->Area; - data << pProto->Unknown1; - data << pProto->Unknown1; // Added in 1.12.x client branch + data << pProto->Map; // Added in 1.12.x & 2.0.1 client branch + data << pProto->BagFamily; + data << pProto->TotemCategory; + for(int s = 0; s < 3; s++) + { + data << pProto->Socket[s].Color; + data << pProto->Socket[s].Content; + } + data << pProto->socketBonus; + data << pProto->GemProperties; + data << pProto->ExtendedCost; + data << pProto->RequiredDisenchantSkill; } else { + // this is not blizz like responce + // blizz responce: item | 0x80000000 data << item; - for(int a = 0; a < 11; a++) + for(int a = 0; a < 18; a++) data << uint64(0); data << uint32(0); // Added in 1.12.x client branch SendPacket( &data ); @@ -580,7 +613,7 @@ price = 9 * price / 10; data << price; - data << uint32( 0xFFFFFFFF ); + data << pProto->MaxDurability; data << pProto->BuyCount; } } @@ -733,7 +766,7 @@ void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID) { - WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); + WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 2.0.10 data << Target; data << Caster; data << ItemID; @@ -742,12 +775,13 @@ SendPacket(&data); } -void WorldSession::SendItemEnchantTimeUpdate(uint64 Itemguid,uint32 slot,uint32 Duration) +void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,uint32 slot,uint32 Duration) { - WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, (8+4+4)); + WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, (8+4+4+8)); // last check 2.0.10 data << Itemguid; data << slot; data << Duration; + data << Playerguid; SendPacket(&data); } @@ -868,3 +902,64 @@ uint32 count = 1; _player->DestroyItemCount(gift, count, true); } + +void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) +{ + sLog.outDebug("Received opcode CMSG_SOCKET_ITEM"); + uint64 itemguid; + uint64 gemguid[3]; + uint32 gemProperty[3]; + + recv_data >> itemguid >> gemguid[0] >> gemguid[1] >> gemguid[2]; + + bool propercolor[3],full[3]; + uint16 itempos = _player->GetPosByGuid(itemguid); + Item *pItem = _player->GetItemByPos( itempos ); + if( pItem ) + { + ItemPrototype const *pItemProto = objmgr.GetItemPrototype( pItem->GetEntry() ); + bool HasBonus=1; + for (int s=0; s<3; s++) + { + if (gemguid[s]) + { + uint16 gempos = _player->GetPosByGuid(gemguid[s]); + Item *pGem = _player->GetItemByPos( gempos ); + ItemPrototype const *pGemProto = objmgr.GetItemPrototype( pGem->GetEntry() ); + gemProperty[s] = pGemProto->GemProperties; + GemPropertiesEntry const *gemInfo = sGemPropertiesStore.LookupEntry(gemProperty[s]); + propercolor[s] = (gemInfo->color & pItemProto->Socket[s].Color); + if ((gemInfo->color & SOCKET_COLOR_META) & !propercolor[s]) + { + // ToDo : Error message + continue; + } + pItem->SetUInt32Value(ITEM_FIELD_SOCKETS_ENCHANTMENT+s*3, gemInfo->spellitemenchantement); + _player->DestroyItem((gempos >> 8), (gempos & 255), true); + full[s] = 1; + } + else + { + gemProperty[s] = 0; + propercolor[s] = 1; + if (pItemProto->Socket[s].Color) + { + full[s]=0; + } + else + { + full[s]=1; + }; + }; + HasBonus &= full[s] & propercolor[s]; + } + + // Now if all full[s] are true and all propercolor[s] are true, also apply the bonus pItemProto->socketBonus + if (HasBonus) + { + pItem->SetUInt32Value(ITEM_FIELD_SOCKETS_ENCHANTMENT+3*3, pItemProto->socketBonus); + } + + _player->_ApplyItemMods(pItem, pItem->GetSlot(), true); + } +} Index: src/game/Formulas.h =================================================================== --- src/game/Formulas.h (working copy) +++ src/game/Formulas.h (working copy) @@ -28,8 +28,7 @@ namespace Honor { //TODO: Implement this function - // NOTE: DO NOT IMPLEMENT A FUNCTION THAT USES A QUERY, SAVE THE DATA - inline int32 CalculeStanding(Player *plr) + /*inline int CalculeStanding(Player *plr) { uint64 guid = 0; int standing = 0; @@ -43,9 +42,9 @@ delete result; } return standing; - } + }*/ //TODO: Fix this formula, for now the weekly rating is how many honor player gain all life time - inline float CalculeRating(Player *plr) + /*inline float CalculeRating(Player *plr) { return plr->GetTotalHonor(); } @@ -83,7 +82,7 @@ int f = (4 - total_kills) >= 0 ? (4 - total_kills) : 0; int honor_points = int(((float)(f * 0.25)*(float)((k_level+(v_rank*5+1))*(1+0.05*diff_honor)*diff_level))); return (honor_points <= 400 ? honor_points : 400); - } + }*/ } Index: src/game/QueryHandler.cpp =================================================================== --- src/game/QueryHandler.cpp (working copy) +++ src/game/QueryHandler.cpp (working copy) @@ -39,7 +39,7 @@ WorldPacket data( SMSG_NAME_QUERY_RESPONSE, (8+1+4+4+4+10) ); data << p->GetGUID(); data << p->GetName(); - data << uint8(0); + data << uint8(0); // it's realm name, for BG usage :) data << uint32(p->getRace()); data << uint32(p->getGender()); data << uint32(p->getClass()); @@ -102,82 +102,7 @@ recv_data >> entry; recv_data >> guid; - Creature *unit = ObjectAccessor::Instance().GetCreatureOrPet(*_player, guid); - - if (unit == NULL) - { - sLog.outDebug( "WORLD: HandleCreatureQueryOpcode - (%u) NO SUCH UNIT! (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entry ); - /* data.Initialize( SMSG_CREATURE_QUERY_RESPONSE ); - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint16)0; - SendPacket( &data ); - return;*/ - } - - //CreatureInfo const *ci = unit->GetCreatureInfo(); - CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry); - if (!ci) - { - sLog.outDebug( "WORLD: HandleCreatureQueryOpcode - (%u) NO CREATUREINFO! (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entry ); - data.Initialize( SMSG_CREATURE_QUERY_RESPONSE, (11*4+2) ); - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint16)0; - SendPacket( &data ); - return; - } - - sLog.outDetail("WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u - GUID: %u.", ci->Name, entry, guid); - data.Initialize( SMSG_CREATURE_QUERY_RESPONSE, (100) ); // guess size - data << (uint32)entry; - data << (unit ? unit->GetName() : ci->Name); - - data << uint8(0) << uint8(0) << uint8(0); - //if (unit) - // data << ((unit->isPet()) ? "Pet" : ci->SubName); - //else - data << ci->SubName; - - uint32 wdbFeild11=0,wdbFeild12=0; - - data << ci->flag1; //flag1 wdbFeild7=wad flags1 - if (unit) - data << (uint32)((unit->isPet()) ? 0 : ci->type); //creatureType wdbFeild8 - else - data << (uint32)ci->type; - - data << (uint32)ci->family; //family wdbFeild9 - data << (uint32)ci->rank; //rank wdbFeild10 - data << (uint32)wdbFeild11; //unknow wdbFeild11 - data << (uint32)wdbFeild12; //unknow wdbFeild12 - if (unit) - data << unit->GetUInt32Value(UNIT_FIELD_DISPLAYID); //DisplayID wdbFeild13 - else - data << (uint32)ci->randomDisplayID(); - - data << (uint16)ci->civilian; //wdbFeild14 - - SendPacket( &data ); - + SendCreatureQuery(entry, guid); } void WorldSession::SendCreatureQuery( uint32 entry, uint64 guid ) @@ -203,18 +128,16 @@ sLog.outDetail("WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u - GUID: %u.", ci->Name, entry, guid); WorldPacket data( SMSG_CREATURE_QUERY_RESPONSE, 100 ); // guess size - data << (uint32)entry; - data << (unit ? unit->GetName() : ci->Name); + data << (uint32)entry; // creature entry + data << (unit ? unit->GetName() : ci->Name); // creature name - data << uint8(0) << uint8(0) << uint8(0); + data << uint8(0) << uint8(0) << uint8(0); // unk 3 x uint8 if (unit) - data << ((unit->isPet()) ? "Pet" : ci->SubName); + data << ((unit->isPet()) ? "Pet" : ci->SubName); // subname else data << ci->Name; - uint32 wdbFeild11=0,wdbFeild12=0; - data << ci->flag1; //flags wdbFeild7=wad flags1 if (unit) @@ -224,151 +147,19 @@ data << (uint32)ci->family; //family wdbFeild9 data << (uint32)(unit && unit->isPet() ? 0 : ci->rank); //rank wdbFeild10 - data << (uint32)wdbFeild11; //unknow wdbFeild11 - data << (uint32)wdbFeild12; //unknow wdbFeild12 - if (unit) - data << unit->GetUInt32Value(UNIT_FIELD_DISPLAYID); //DisplayID wdbFeild13 - else - data << (uint32)ci->randomDisplayID(); + data << uint32(0); //unknow wdbFeild11 + data << uint32(0); //unknow wdbFeild12 - data << (uint16)ci->civilian; //wdbFeild14 - - SendPacket( &data ); - /* - uint32 npcflags = unit->GetUInt32Value(UNIT_NPC_FLAGS); - - data.Initialize( SMSG_CREATURE_QUERY_RESPONSE ); - data << (uint32)entry; - data << ci->Name.c_str(); - data << uint8(0) << uint8(0) << uint8(0); - data << ci->SubName.c_str(); - - data << (uint32)npcflags; - - if ((ci->Type & 2) > 0) - { - data << uint32(7); - } - else - { - data << uint32(0); - } - - data << ci->Type; - - if (ci->level >= 16 && ci->level < 32) - data << (uint32)CREATURE_ELITE_ELITE; - else if (ci->level >= 32 && ci->level < 48) - data << (uint32)CREATURE_ELITE_RAREELITE; - else if (ci->level >= 48 && ci->level < 59) - data << (uint32)CREATURE_ELITE_WORLDBOSS; - else if (ci->level >= 60) - data << (uint32)CREATURE_ELITE_RARE; - else - data << (uint32)CREATURE_ELITE_NORMAL; - - data << (uint32)ci->family; - - data << (uint32)0; - data << ci->DisplayID; - - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - - SendPacket( &data ); - */ -} - -void WorldSession::SendTestCreatureQueryOpcode( uint32 entry, uint64 guid, uint32 testvalue ) -{ - Creature *unit = ObjectAccessor::Instance().GetCreatureOrPet(*_player, guid); - - if (unit == NULL) - { - sLog.outDebug( "WORLD: SendTestCreatureQueryOpcode - (%u) NO SUCH UNIT! (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entry ); - //return; - } - - //CreatureInfo const *ci = unit->GetCreatureInfo(); - CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry); - if (!ci) - { - sLog.outDebug( "WORLD: SendTestCreatureQueryOpcode - (%u) NO CREATUREINFO! (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entry ); - return; - } - - sLog.outDetail("WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u - GUID: %u.", ci->Name, entry, guid); - - uint8 u8unk1=0,u8unk2=0,u8unk3=0; - //------------------------------------------------------------------------ - WorldPacket data( SMSG_CREATURE_QUERY_RESPONSE, 100 ); // guess size - data << (uint32)entry; - data << ci->Name; - data << uint8(u8unk1) << uint8(u8unk2) << uint8(u8unk3); - data << ci->SubName; - - uint32 wdbFeild11=0,wdbFeild12=0; - - data << ci->flag1; //flags wdbFeild7=wad flags1 - data << uint32(ci->type); //creatureType wdbFeild8 - data << (uint32)ci->family; //family wdbFeild9 - data << (uint32)ci->rank; //unknow wdbFeild10 - data << (uint32)wdbFeild11; //unknow wdbFeild11 - data << (uint32)wdbFeild12; //unknow wdbFeild12 if (unit) data << unit->GetUInt32Value(UNIT_FIELD_DISPLAYID); //DisplayID wdbFeild13 else data << (uint32)ci->randomDisplayID(); - data << (uint16)ci->civilian; //wdbFeild14 - + data << (float)1; // unk + data << (float)1; // unk + data << uint8(0); // unk + data << uint8(0); // boss flag? SendPacket( &data ); - //----------------------------------------------------------------------- - /* - data.Initialize( SMSG_CREATURE_QUERY_RESPONSE ); - data << (uint32)entry; - data << ci->Name.c_str(); - data << uint8(0) << uint8(0) << uint8(0); - data << ci->SubName.c_str(); - - data << (uint32)npcflags; - - if ((ci->Type & 2) > 0) - { - data << uint32(7); - } - else - { - data << uint32(0); - } - - data << ci->Type; - - if (ci->level >= 16 && ci->level < 32) - data << (uint32)CREATURE_ELITE_ELITE; - else if (ci->level >= 32 && ci->level < 48) - data << (uint32)CREATURE_ELITE_RAREELITE; - else if (ci->level >= 48 && ci->level < 59) - data << (uint32)CREATURE_ELITE_WORLDBOSS; - else if (ci->level >= 60) - data << (uint32)CREATURE_ELITE_RARE; - else - data << (uint32)CREATURE_ELITE_NORMAL; - - data << (uint32)ci->family; - - data << (uint32)0; - data << ci->DisplayID; - - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - data << (uint32)0; - - SendPacket( &data ); - */ } void WorldSession::HandleGameObjectQueryOpcode( WorldPacket & recv_data ) @@ -417,9 +208,8 @@ data << (uint32)info->type; data << (uint32)info->displayId; data << info->name; - data << uint16(0); //unknown - data << uint8(0); //unknown - data << uint8(0); // Added in 1.12.x client branch + data << uint32(0); // 2.0.3 + data << uint16(0); // 2.0.3 data << uint32(info->sound0); data << uint32(info->sound1); data << uint32(info->sound2); @@ -452,13 +242,12 @@ WorldPacket data(MSG_CORPSE_QUERY, (5*4+1)); data << uint8(0x01); - data << uint32(0x01); + data << corpse->GetMapId(); data << corpse->GetPositionX(); data << corpse->GetPositionY(); data << corpse->GetPositionZ(); - data << uint32(0x01); + data << _player->GetMapId(); SendPacket(&data); - } void WorldSession::HandleNpcTextQueryOpcode( WorldPacket & recv_data ) Index: src/game/SpellHandler.cpp =================================================================== --- src/game/SpellHandler.cpp (working copy) +++ src/game/SpellHandler.cpp (working copy) @@ -72,7 +72,7 @@ uint8 trade_goods = proto->Class == ITEM_CLASS_TRADE_GOODS && proto->SubClass != ITEM_SUBCLASS_EXPLOSIVES; if (consumable || trade_goods || - proto->Class == ITEM_CLASS_KEY || proto->Class == ITEM_CLASS_JUNK) + proto->Class == ITEM_CLASS_KEY || proto->Class == ITEM_CLASS_MISC) { pUser->SendEquipError(EQUIP_ERR_CANT_DO_IN_COMBAT,pItem,NULL); return; @@ -276,11 +276,25 @@ if (spellId == 0) spellId = info->sound3; - guid=_player->GetGUID(); + //guid=_player->GetGUID(); } break; + case GAMEOBJECT_TYPE_CAMERA: //13 + info = obj->GetGOInfo(); + if(info) + { + uint32 cinematic_id = info->sound1; + if(cinematic_id) + { + WorldPacket data(SMSG_TRIGGER_CINEMATIC, 4); + data << cinematic_id; + _player->GetSession()->SendPacket(&data); + } + return; + } + break; //fishing bobber case GAMEOBJECT_TYPE_FISHINGNODE: //17 { @@ -510,6 +524,7 @@ void WorldSession::HandleCancelAutoRepeatSpellOpcode( WorldPacket& recvPacket) { + // may be better send SMSG_CANCEL_AUTO_REPEAT? // cancel and prepare for deleting _player->castSpell(NULL); } Index: src/game/ArenaTeamHandler.cpp =================================================================== --- src/game/ArenaTeamHandler.cpp (revision 0) +++ src/game/ArenaTeamHandler.cpp (working copy) @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2005,2006,2007 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 "WorldSession.h" +#include "WorldPacket.h" +#include "Log.h" +#include "Database/DatabaseEnv.h" +#include "Player.h" +#include "ObjectMgr.h" + +void WorldSession::HandleInspectArenaStatsOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("MSG_INSPECT_ARENA_STATS"); + recv_data.hexlike(); + uint64 guid; + recv_data >> guid; + sLog.outDebug("Inspect Arena stats " I64FMTD, guid); + + QueryResult *result = sDatabase.PQuery("SELECT `teamslot`, `teamguid`, `rating`, `games`, `wins`, `played` FROM `arena_team_member` WHERE `guid`='%u'", _player->GetGUIDLow()); + if(result) + { + Field *fields = result->Fetch(); + do + { + WorldPacket data(MSG_INSPECT_ARENA_STATS); + data << guid; + data << fields[0].GetUInt8(); // slot (0...2) + data << fields[1].GetUInt32(); // arena team id + data << fields[2].GetUInt32(); // rating + data << fields[3].GetUInt32(); // games + data << fields[4].GetUInt32(); // wins + data << fields[5].GetUInt32(); // played (count of all games, that played...) + SendPacket(&data); + } + while( result->NextRow() ); + delete result; + } + else + { + sLog.outDebug("Error..."); + } +} + +void WorldSession::HandleArenaTeamQueryOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_ARENA_TEAM_QUERY"); + recv_data.hexlike(); + + char *teamname = "test_arena_team_name"; + + uint32 teamid; + recv_data >> teamid; + sLog.outDebug("Arena Team Info %u", teamid); + + // check arena team existence + + WorldPacket data(SMSG_ARENA_TEAM_QUERY_RESPONSE, 4*7+strlen(teamname)+1); + data << teamid; + data << teamname; + data << uint32(0x00000002); // arena team type (2=2x2, 3=3x3 or 5=5x5) probably + // emblem/color(RGB?) related things below? + data << (float)urand(1, 1000); // emblem style? + data << urand(1, 100); // emblem color? + data << (float)urand(1, 1000); // border style? + data << urand(1, 100); // border color? + data << (float)urand(1, 1000); // background color? + SendPacket(&data); + + uint32 rating = 1, games = 2, wins = 3, played = 4, wins2 = 5, rank = 6; // for testing... + WorldPacket data2(SMSG_ARENA_TEAM_STATS, 4*7); + data2 << teamid; + data2 << rating; + data2 << games; + data2 << wins; + data2 << played; + data2 << wins2; + data2 << rank; + SendPacket(&data2); +} + +void WorldSession::HandleArenaTeamRosterOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_ARENA_TEAM_ROSTER"); + recv_data.hexlike(); + + uint8 unk; // probably team_size or slot + recv_data >> unk; + + // opcode structure only guessed + WorldPacket data(SMSG_ARENA_TEAM_ROSTER, 4*7); + data << uint8(0); // slot + data << uint32(2); // members count + + for(uint8 i = 0; i < 2; i++) + { + data << _player->GetName(); // member name + data << _player->getClass(); // class there... + data << uint32(20); // played this week + data << uint32(11); // wins this week + data << uint32(40); // played this season + data << uint32(12); // wins this season + } + data.hexlike(); + SendPacket(&data); +} + +void WorldSession::HandleArenaTeamAddMemberOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_ARENA_TEAM_ADD_MEMBER"); + recv_data.hexlike(); + + uint8 team_slot; // slot? + char *teamname = "test_arena_team_name"; + std::string name; + + recv_data >> team_slot >> name; + + Player *plr = objmgr.GetPlayer(name.c_str()); + + if(plr) + { + // packet structure only quessed... + WorldPacket data(SMSG_ARENA_TEAM_INVITE); + data << _player->GetName(); // player name + data << teamname; // arena team name + plr->GetSession()->SendPacket(&data); + } +} + +void WorldSession::HandleArenaTeamInviteAcceptOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_ARENA_TEAM_INVITE_ACCEPT"); // empty opcode +} + +void WorldSession::HandleArenaTeamInviteDeclineOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_ARENA_TEAM_INVITE_DECLINE"); // empty opcode +} + +void WorldSession::HandleArenaTeamLeaveOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_ARENA_TEAM_LEAVE"); + uint8 team_slot; // slot? + recv_data >> team_slot; +} + +void WorldSession::HandleArenaTeamDisbandOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_ARENA_TEAM_DISBAND"); + uint8 team_slot; // slot? + recv_data >> team_slot; +} Index: src/game/Player.h =================================================================== --- src/game/Player.h (working copy) +++ src/game/Player.h (working copy) @@ -128,7 +128,7 @@ struct PlayerInfo { - PlayerInfo() : displayId(0),levelInfo(NULL) // existance checked by displayId != 0 + PlayerInfo() : displayId_m(0),displayId_f(0),levelInfo(NULL) // existence checked by displayId != 0 // existance checked by displayId != 0 { } @@ -137,7 +137,8 @@ float positionX; float positionY; float positionZ; - uint16 displayId; + uint16 displayId_m; + uint16 displayId_f; PlayerCreateInfoItems item; std::list spell; std::list skill; @@ -651,23 +652,6 @@ void TextEmote(const std::string text); void Whisper(const uint64 receiver, const std::string text, const uint32 language); - float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? PLAYER_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); } - void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? PLAYER_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE+school,val); } - void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply) { ApplyModFloatValue(positive ? PLAYER_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); } - void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply) { ApplyPercentModFloatValue(positive ? PLAYER_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); } - void SetPosStat(Stats stat, float val) { SetFloatValue(PLAYER_FIELD_POSSTAT0+stat, val); } - void ApplyPosStatMod(Stats stat, float val, bool apply) { ApplyModFloatValue(PLAYER_FIELD_POSSTAT0+stat, val, apply); } - void ApplyPosStatPercentMod(Stats stat, float val, bool apply) { ApplyPercentModFloatValue(PLAYER_FIELD_POSSTAT0+stat, val, apply); } - void SetNegStat(Stats stat, float val) { SetFloatValue(PLAYER_FIELD_NEGSTAT0+stat, val); } - void ApplyNegStatMod(Stats stat, float val, bool apply) { ApplyModFloatValue(PLAYER_FIELD_NEGSTAT0+stat, val, apply); } - void ApplyNegStatPercentMod(Stats stat, float val, bool apply) { ApplyPercentModFloatValue(PLAYER_FIELD_NEGSTAT0+stat, val, apply); } - void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; } - void ApplyCreateStatMod(Stats stat, float val, bool apply) { m_createStats[stat] += (apply ? val : -val); } - void ApplyCreateStatPercentMod(Stats stat, float val, bool apply) { m_createStats[stat] *= (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val)); } - float GetPosStat(Stats stat) const { return GetFloatValue(PLAYER_FIELD_POSSTAT0+stat); } - float GetNegStat(Stats stat) const { return GetFloatValue(PLAYER_FIELD_NEGSTAT0+stat); } - float GetCreateStat(Stats stat) const { return m_createStats[stat]; } - /*********************************************************/ /*** STORAGE SYSTEM ***/ /*********************************************************/ @@ -1020,6 +1004,9 @@ int GetGuildIdInvited() { return m_GuildIdInvited; } static void RemovePetitionsAndSigns(uint64 guid); + void SetDungeonDifficulty(uint32 difficulty) { m_dungeonDifficulty = difficulty; } + uint32 GetDungeonDifficulty() { return m_dungeonDifficulty; } + bool UpdateSkill(uint32 skill_id); bool UpdateSkillPro(uint16 SkillId, int32 Chance); @@ -1055,6 +1042,9 @@ void SendAttackSwingBadFacingAttack(); void SendExplorationExperience(uint32 Area, uint32 Experience); + void SendDungeonDifficulty(); + void SendAllowMove(); + bool SetPosition(float x, float y, float z, float orientation); void SendMessageToSet(WorldPacket *data, bool self);// overwrite Object::SendMessageToSet void SendMessageToOwnTeamSet(WorldPacket *data, bool self); @@ -1126,6 +1116,7 @@ void SendInitialReputations(); void SetFactionAtWar(uint32 repListID, bool atWar); + void SendSetFactionVisible(const Faction* faction) const; void UpdateMaxSkills(); void UpdateSkillsToMaxSkillsForLevel(); // for .levelup void ModifySkillBonus(uint32 skillid,int32 val); @@ -1168,8 +1159,8 @@ bool IsItemSpellToEquip(SpellEntry const *spellInfo); bool IsItemSpellToCombat(SpellEntry const *spellInfo); - void SendInitWorldStates(uint32 MapID); - void SendUpdateWordState(uint16 Field, uint16 Value); + void SendInitWorldStates(); + void SendUpdateWorldState(uint32 Field, uint32 Value); void SendDirectMessage(WorldPacket *data); PlayerMenu* PlayerTalkClass; @@ -1225,6 +1216,11 @@ bool HasMovementFlags(uint32 flags) const { return m_movement_flags & flags; } void SetMovementFlags(uint32 Flags) { m_movement_flags = Flags;} + bool CanFly() const { return m_canFly; } + void SetCanFly(bool value) { m_canFly = value; } + bool IsFlying() const { return m_Flying; } + void SetFlying(bool value) { m_Flying = value; } + // Transports Transport * GetTransport() { return m_transport; } void SetTransport(Transport * t) { m_transport = t; } @@ -1349,13 +1345,12 @@ uint64 m_lootGuid; - float m_createStats[5]; - uint32 m_race; uint32 m_class; uint32 m_team; uint32 m_dismountCost; uint32 m_nextSave; + uint32 m_dungeonDifficulty; Item* m_items[PLAYER_SLOTS_COUNT]; uint32 m_currentBuybackSlot; @@ -1365,6 +1360,9 @@ uint32 m_movement_flags; + bool m_canFly; + bool m_Flying; + uint32 m_GMFlags; uint64 m_curTarget; uint64 m_curSelection; @@ -1395,11 +1393,6 @@ TaxiMask m_taximask; std::deque m_TaxiDestinations; - float m_total_honor_points; - float m_rating; - uint32 m_highest_rank; - int32 m_standing; - int m_cinematic; Player *pTrader; Index: src/game/GossipDef.cpp =================================================================== --- src/game/GossipDef.cpp (working copy) +++ src/game/GossipDef.cpp (working copy) @@ -119,8 +119,16 @@ { data << uint32( iI ); data << uint8( pGossipMenu->GetItem(iI).m_gIcon ); - data << uint8( pGossipMenu->GetItem(iI).m_gCoded); + // icons: + // 0 unlearn talents/misc + // 1 trader + // 2 taxi + // 3 trainer + // 9 BG/arena + data << uint8( pGossipMenu->GetItem(iI).m_gCoded ); + data << uint32(0); // req money to open menu, 2.0.3 data << pGossipMenu->GetItem(iI).m_gMessage; + data << uint8(0); // 2.0.3 } data << uint32( pQuestMenu->MenuItemCount() ); @@ -296,12 +304,16 @@ data << npcGUID; data << pQuest->GetQuestId() << pQuest->GetTitle() << pQuest->GetDetails(); - data << pQuest->GetObjectives() << uint32( ActivateAccept ); + data << pQuest->GetObjectives(); + data << (uint32)ActivateAccept; ItemPrototype const* IProto; + data << uint32(0); // suggested players + data << pQuest->GetRewChoiceItemsCount(); for (uint32 i=0; i < QUEST_REWARD_CHOICES_COUNT; i++) { + if ( !pQuest->RewChoiceItemId[i] ) continue; data << uint32(pQuest->RewChoiceItemId[i]); data << uint32(pQuest->RewChoiceItemCount[i]); IProto = objmgr.GetItemPrototype(pQuest->RewChoiceItemId[i]); @@ -314,6 +326,7 @@ data << pQuest->GetRewItemsCount(); for (uint32 i=0; i < QUEST_REWARDS_COUNT; i++) { + if ( !pQuest->RewItemId[i] ) continue; data << pQuest->RewItemId[i]; data << pQuest->RewItemCount[i]; IProto = objmgr.GetItemPrototype(pQuest->RewItemId[i]); @@ -325,20 +338,34 @@ data << uint32(pQuest->GetRewOrReqMoney()); - data << pQuest->GetReqItemsCount(); - for (uint32 i=0; i < QUEST_OBJECTIVES_COUNT; i++) + // check if RewSpell is teaching another spell + if(pQuest->GetRewSpell()) { - data << pQuest->ReqItemId[i]; - data << pQuest->ReqItemCount[i]; + SpellEntry const *rewspell = sSpellStore.LookupEntry(pQuest->GetRewSpell()); + if(rewspell) + { + if(rewspell->Effect[0] == SPELL_EFFECT_LEARN_SPELL) + data << uint32(rewspell->EffectTriggerSpell[0]); + else + data << uint32(0); + } + else + { + sLog.outErrorDb("Quest %u have non-existed RewSpell %u, ignored.",pQuest->GetQuestId(),pQuest->GetRewSpell()); + data << uint32(0); + } } + else + data << uint32(0); // reward spell - data << pQuest->GetReqCreatureOrGOcount(); - for (uint32 i=0; i GetRewSpell()); // cast spell + + data << uint32(QUEST_EMOTE_COUNT); + for (uint32 i=0; i < QUEST_EMOTE_COUNT; i++) { - data << uint32(pQuest->ReqCreatureOrGOId[i]); - data << pQuest->ReqCreatureOrGOCount[i]; + data << pQuest->DetailsEmote[i]; + data << uint32(0); // DetailsEmoteDelay } - pSession->SendPacket( &data ); //sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId()); @@ -349,7 +376,7 @@ WorldPacket data( SMSG_QUEST_QUERY_RESPONSE, 100 ); // guess size data << uint32(pQuest->GetQuestId()); - data << uint32(pQuest->GetMinLevel()); + data << uint32(pQuest->GetMinLevel()); // it's not min lvl in 2.0.x data << uint32(pQuest->GetQuestLevel()); if(pQuest->GetQuestSort() > 0) @@ -358,6 +385,7 @@ data << uint32(pQuest->GetZoneId()); data << uint32(pQuest->GetType()); + data << uint32(0);//SuggestedPlayers data << uint32(pQuest->GetRequiredRepFaction()); data << uint32(pQuest->GetRequiredRepValue()); data << uint32(0); @@ -376,7 +404,7 @@ if(rewspell->Effect[0] == SPELL_EFFECT_LEARN_SPELL) data << uint32(rewspell->EffectTriggerSpell[0]); else - data << uint32(pQuest->GetRewSpell()); + data << uint32(0); } else { @@ -387,6 +415,7 @@ else data << uint32(0); + data << uint32(pQuest->GetRewSpell()); // spellid, The following spell will be casted on you spell_name data << uint32(pQuest->GetSrcItemId()); data << uint32(pQuest->GetSpecialFlags()); @@ -415,8 +444,10 @@ for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; iI++) { - data << uint32(pQuest->ReqCreatureOrGOId[iI]) << uint32(pQuest->ReqCreatureOrGOCount[iI]); - data << uint32(pQuest->ReqItemId[iI]) << uint32(pQuest->ReqItemCount[iI]); + data << uint32(pQuest->ReqCreatureOrGOId[iI]); + data << uint32(pQuest->ReqCreatureOrGOCount[iI]); + data << uint32(pQuest->ReqItemId[iI]); + data << uint32(pQuest->ReqItemCount[iI]); } for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; iI++) @@ -441,26 +472,21 @@ data << uint32( EnbleNext ); - /*if ( EmoteCnt > 0 ) - { - data << uint32( EmoteCnt ); + data << uint32(0); //unk - for (unsigned int iI = 0; iI < EmoteCnt; iI++ ) - { - data << Emotes[iI]._Delay; - data << Emotes[iI]._Emote; - } - } else data << uint32( 0x00 ); */ - // Must be extended later, but for now: - if (qInfo->GetOfferRewardEmote() == 0) + uint32 EmoteCount = 0; + for (uint32 i = 0; i < QUEST_EMOTE_COUNT; i++) { - data << uint32(0x00); + if(qInfo->OfferRewardEmote[i] <= 0) + break; + EmoteCount++; } - else + + data << EmoteCount; //Emote Count + for (uint32 i = 0; i < EmoteCount; i++) { - data << uint32(0x1); - data << uint32(0x0); - data << qInfo->GetOfferRewardEmote(); + data << uint32(0); //Delay Emote + data << qInfo->OfferRewardEmote[i]; } ItemPrototype const *pItem; @@ -483,7 +509,8 @@ for (uint16 i=0; i < qInfo->GetRewItemsCount(); i++) { pItem = objmgr.GetItemPrototype(qInfo->RewItemId[i]); - data << uint32(qInfo->RewItemId[i]) << uint32(qInfo->RewItemCount[i]); + data << uint32(qInfo->RewItemId[i]); + data << uint32(qInfo->RewItemCount[i]); if ( pItem ) data << uint32(pItem->DisplayInfoID); @@ -492,7 +519,7 @@ } data << uint32(qInfo->GetRewOrReqMoney()); - data << uint32(0x00); + data << uint32(0x08); // check if RewSpell is teaching another spell if(qInfo->GetRewSpell()) @@ -514,7 +541,8 @@ else data << uint32(0); - // more data here--zoneid uint32 + 0x00000000? + uint32(0x00); // new 2.0.3 + pSession->SendPacket( &data ); //sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),quest_id ); } @@ -538,9 +566,13 @@ data << pQuest->GetRequestItemsText(); - data << uint32(0x00); - data << pQuest->GetRequestItemsEmote(); + data << uint32(0x00); // unk + if(Completable) + data << pQuest->GetCompleteEmote(); + else + data << pQuest->GetIncompleteEmote(); + // Close Window after cancel if (CloseOnCancel) data << uint32(0x01); @@ -550,13 +582,13 @@ // Req Money data << uint32(pQuest->GetRewOrReqMoney() < 0 ? -pQuest->GetRewOrReqMoney() : 0); + data << uint32(0x00); // unk + data << uint32( pQuest->GetReqItemsCount() ); - ItemPrototype const *pItem; for (int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) { if ( !pQuest->ReqItemId[i] ) continue; - pItem = objmgr.GetItemPrototype(pQuest->ReqItemId[i]); data << uint32(pQuest->ReqItemId[i]); data << uint32(pQuest->ReqItemCount[i]); @@ -566,12 +598,14 @@ else data << uint32(0); } + else + uint32(0x0); - data << uint32(0x02); if ( !Completable ) data << uint32(0x00); else data << uint32(0x03); + data << uint32(0x04) << uint32(0x08) << uint32(0x10); pSession->SendPacket( &data ); Index: src/game/QuestDef.cpp =================================================================== --- src/game/QuestDef.cpp (working copy) +++ src/game/QuestDef.cpp (working copy) @@ -101,11 +101,19 @@ PointX = questRecord[97].GetFloat(); PointY = questRecord[98].GetFloat(); PointOpt = questRecord[99].GetUInt32(); - OfferRewardEmote = questRecord[100].GetUInt32(); - RequestItemsEmote = questRecord[101].GetUInt32(); - QuestCompleteScript = questRecord[102].GetUInt32(); - Repeatable = questRecord[103].GetUInt32(); + for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) + DetailsEmote[i] = questRecord[100+i].GetUInt32(); + + IncompleteEmote = questRecord[104].GetUInt32(); + CompleteEmote = questRecord[105].GetUInt32(); + + for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) + OfferRewardEmote[i] = questRecord[106+i].GetInt32(); + + QuestCompleteScript = questRecord[110].GetUInt32(); + Repeatable = questRecord[111].GetUInt32(); + m_reqitemscount = 0; m_reqCreatureOrGOcount = 0; m_rewitemscount = 0; Index: src/game/Unit.h =================================================================== --- src/game/Unit.h (working copy) +++ src/game/Unit.h (working copy) @@ -556,10 +556,10 @@ uint32 getClassMask() const { return 1 << (getClass()-1); }; uint8 getGender() const { return (uint8)((GetUInt32Value(UNIT_FIELD_BYTES_0) >> 16) & 0xFF); }; - float GetStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_STR+stat); } - void SetStat(Stats stat, float val) { SetFloatValue(UNIT_FIELD_STR+stat, val); } - void ApplyStatMod(Stats stat, float val, bool apply) { ApplyModFloatValue(UNIT_FIELD_STR+stat, val, apply); } - void ApplyStatPercentMod(Stats stat, float val, bool apply) { ApplyPercentModFloatValue(UNIT_FIELD_STR+stat, val, apply); } + float GetStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_STAT0+stat); } + void SetStat(Stats stat, float val) { SetFloatValue(UNIT_FIELD_STAT0+stat, val); } + void ApplyStatMod(Stats stat, float val, bool apply) { ApplyModFloatValue(UNIT_FIELD_STAT0+stat, val, apply); } + void ApplyStatPercentMod(Stats stat, float val, bool apply) { ApplyPercentModFloatValue(UNIT_FIELD_STAT0+stat, val, apply); } float GetArmor() const { return GetResistance(SPELL_SCHOOL_NORMAL) ; } void SetArmor(float val) { SetResistance(SPELL_SCHOOL_NORMAL, val); } @@ -753,6 +753,23 @@ bool SetAurDuration(uint32 spellId, uint32 effindex, uint32 duration); uint32 GetAurDuration(uint32 spellId, uint32 effindex); + float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); } + void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school,val); } + void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply) { ApplyModFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); } + void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply) { ApplyPercentModFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); } + void SetPosStat(Stats stat, float val) { SetFloatValue(UNIT_FIELD_POSSTAT0+stat, val); } + void ApplyPosStatMod(Stats stat, float val, bool apply) { ApplyModFloatValue(UNIT_FIELD_POSSTAT0+stat, val, apply); } + void ApplyPosStatPercentMod(Stats stat, float val, bool apply) { ApplyPercentModFloatValue(UNIT_FIELD_POSSTAT0+stat, val, apply); } + void SetNegStat(Stats stat, float val) { SetFloatValue(UNIT_FIELD_NEGSTAT0+stat, val); } + void ApplyNegStatMod(Stats stat, float val, bool apply) { ApplyModFloatValue(UNIT_FIELD_NEGSTAT0+stat, val, apply); } + void ApplyNegStatPercentMod(Stats stat, float val, bool apply) { ApplyPercentModFloatValue(UNIT_FIELD_NEGSTAT0+stat, val, apply); } + void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; } + void ApplyCreateStatMod(Stats stat, float val, bool apply) { m_createStats[stat] += (apply ? val : -val); } + void ApplyCreateStatPercentMod(Stats stat, float val, bool apply) { m_createStats[stat] *= (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val)); } + float GetPosStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_POSSTAT0+stat); } + float GetNegStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_NEGSTAT0+stat); } + float GetCreateStat(Stats stat) const { return m_createStats[stat]; } + void castSpell(Spell * pSpell); virtual void ProhibitSpellScholl(uint32 idSchool /* from SpellSchools */, uint32 unTimeMs ) { } void InterruptSpell(); @@ -857,7 +874,7 @@ float GetSpeed( UnitMoveType mtype ) const; float GetSpeedRate( UnitMoveType mtype ) const { return m_speed_rate[mtype]; } void SetSpeed(UnitMoveType mtype, float rate, bool forced = false); - virtual void ApplySpeedMod(UnitMoveType mtype, float rate, bool forced, bool aplly); + virtual void ApplySpeedMod(UnitMoveType mtype, float rate, bool forced, bool apply); void SetHover(bool on); bool isHover() const { return HasAuraType(SPELL_AURA_HOVER); } @@ -882,6 +899,7 @@ uint32 m_attackTimer[3]; + float m_createStats[5]; AttackerSet m_attackers; Unit* m_attacking; Index: src/game/Makefile.am =================================================================== --- src/game/Makefile.am (working copy) +++ src/game/Makefile.am (working copy) @@ -33,6 +33,7 @@ AggressorAI.cpp \ AggressorAI.h \ AnimalRandomMovementGenerator.h \ + ArenaTeamHandler.cpp \ AuctionHouse.cpp \ AuctionHouseObject.h \ Bag.cpp \ @@ -113,6 +114,7 @@ Level1.cpp \ Level2.cpp \ Level3.cpp \ + LFGHandler.cpp \ LootHandler.cpp \ LootMgr.cpp \ LootMgr.h \ Index: src/game/MiscHandler.cpp =================================================================== --- src/game/MiscHandler.cpp (working copy) +++ src/game/MiscHandler.cpp (working copy) @@ -137,7 +137,10 @@ for(uint32 i = 0; i < zones_count; i++) { if(zoneids[i] == pzoneid) + { + z_show = true; break; + } z_show = false; } @@ -262,6 +265,7 @@ //!we can move again data.Initialize( SMSG_FORCE_MOVE_UNROOT, 8 ); // guess size data.append(GetPlayer()->GetPackGUID()); + data << uint32(0); SendPacket( &data ); //! Stand Up @@ -278,13 +282,17 @@ void WorldSession::SendGMTicketGetTicket(uint32 status, char const* text) { int len = text ? strlen(text) : 0; - WorldPacket data; - data.Initialize( SMSG_GMTICKET_GETTICKET, (4+len+4) ); - data << uint32(6); - if(len > 0) - data.append((uint8 *)text,len+1); - else - data << uint32(0); + WorldPacket data( SMSG_GMTICKET_GETTICKET, (4+len+1+4+2+4+4) ); + data << status; // standart 0x0A, 0x06 if text present + if(status == 6) + { + data << text; // ticket text + data << uint8(0x7); // ticket category + data << uint32(0); // time from ticket creation? + data << uint16(0); // const + data << uint32(49024); // const + data << uint32(49024); // const + } SendPacket( &data ); } @@ -314,26 +322,23 @@ assert(result2); Field *fields2 = result2->Fetch(); - SendGMTicketGetTicket(6,fields2[0].GetString()); + SendGMTicketGetTicket(0x06,fields2[0].GetString()); delete result2; } else - SendGMTicketGetTicket(1,0); + SendGMTicketGetTicket(0x0A,0); } } void WorldSession::HandleGMTicketUpdateTextOpcode( WorldPacket & recv_data ) { - WorldPacket data; - uint32 guid = GetPlayer()->GetGUIDLow(); - std::string ticketText = ""; - uint8 buf[516]; - memcpy( buf, recv_data.contents(), sizeof buf > unk; + recv_data >> ticketText; - ticketText = (char *)buf + 1; sDatabase.escape_string(ticketText); - sDatabase.PExecute("UPDATE `character_ticket` SET `ticket_text` = '%s' WHERE `guid` = '%u'", ticketText.c_str(), guid); - + sDatabase.PExecute("UPDATE `character_ticket` SET `ticket_text` = '%s' WHERE `guid` = '%u'", ticketText.c_str(), _player->GetGUIDLow()); } void WorldSession::HandleGMTicketDeleteOpcode( WorldPacket & recv_data ) @@ -347,31 +352,32 @@ data << uint32(0); SendPacket( &data ); - SendGMTicketGetTicket(1,0); + SendGMTicketGetTicket(0x0A,0); } void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data ) { - WorldPacket data; - uint32 guid; - guid = GetPlayer()->GetGUIDLow(); + + uint32 unk1, time1, time2, time3; + uint8 category; std::string ticketText = ""; - Field *fields; - uint8 buf[516]; - uint32 cat[] = { 0,5,1,2,0,6,4,7,0,8,3 }; - memcpy( buf, recv_data.contents(), sizeof buf < recv_data.size() ? sizeof buf : recv_data.size() ); - buf[272] = 0; + std::string unk_text; // reserved for future use text - ticketText = (char *)buf + 17; + recv_data >> category >> unk1 >> time1 >> time2 >> time3; // last check 2.0.10 + recv_data >> ticketText; + recv_data >> unk_text; + + sLog.outDebug("TicketCreate: category %u, unk1 %u, time1 %u, time2 %u, time3 %u, text %s, unk_text %s", category, unk1, time1/1000, time2/1000, time3/1000, ticketText.c_str(), unk_text.c_str()); + sDatabase.escape_string(ticketText); - QueryResult *result = sDatabase.PQuery("SELECT COUNT(*) FROM `character_ticket` WHERE `guid` = '%u'",guid); + QueryResult *result = sDatabase.PQuery("SELECT COUNT(*) FROM `character_ticket` WHERE `guid` = '%u'", _player->GetGUIDLow()); if (result) { int cnt; - fields = result->Fetch(); + Field *fields = result->Fetch(); cnt = fields[0].GetUInt32(); delete result; @@ -383,11 +389,9 @@ } else { + sDatabase.PExecute("INSERT INTO `character_ticket` (`guid`,`ticket_text`,`ticket_category`) VALUES ('%u', '%s', '%u')", _player->GetGUIDLow(), ticketText.c_str(), category); - sDatabase.PExecute("INSERT INTO `character_ticket` (`guid`,`ticket_text`,`ticket_category`) VALUES ('%u', '%s', '%u')", guid, ticketText.c_str(), cat[buf[0]]); - data.Initialize( SMSG_QUERY_TIME_RESPONSE, 4 ); - //data << (uint32)20; data << (uint32)getMSTime(); SendPacket( &data ); @@ -409,7 +413,7 @@ void WorldSession::HandleGMTicketSystemStatusOpcode( WorldPacket & recv_data ) { WorldPacket data( SMSG_GMTICKET_SYSTEMSTATUS,4 ); - data << uint32(1); + data << uint32(1); // we can also disable ticket system by sending 0 value SendPacket( &data ); } @@ -439,6 +443,9 @@ sLog.outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone); + if(newZone != _player->GetZoneId()) + GetPlayer()->SendInitWorldStates(); // only if really enters to new zone, not just area change, works strange... + GetPlayer()->UpdateZone(newZone); } @@ -891,29 +898,14 @@ { if(GetPlayer()->getLevel() >= at->requiredLevel || sWorld.getConfig(CONFIG_IGNORE_AT_LEVEL_REQUIREMENT) || GetPlayer()->isGameMaster()) { - if(at->mapId == GetPlayer()->GetMapId() && !GetPlayer()->InBattleGround() ) + if(GetPlayer()->InBattleGround()) { - WorldPacket movedata; - _player->BuildTeleportAckMsg(&movedata, at->X, at->Y, at->Z, at->Orientation ); - _player->SendMessageToSet(&movedata,true); - //_player->SetPosition( at->X, at->Y, at->Z, _player->GetOrientation()); - //_player->BuildHeartBeatMsg(&data); - //_player->SendMessageToSet(&data, true); - } - else if (GetPlayer()->InBattleGround()) //if player is playing in a BattleGround - { - //! AreaTrigger BattleGround - - //Get current BattleGround the player is in BattleGround* TempBattlegrounds = sBattleGroundMgr.GetBattleGround(GetPlayer()->GetBattleGroundId()); - //Run the areatrigger code if(TempBattlegrounds) TempBattlegrounds->HandleAreaTrigger(GetPlayer(),Trigger_ID); } else - { GetPlayer()->TeleportTo(at->mapId,at->X,at->Y,at->Z,at->Orientation,true,false); - } } else { @@ -921,10 +913,7 @@ msgstr << "You must be at least level " << (uint32)at->requiredLevel << " to enter."; std::string msg = msgstr.str(); - WorldPacket data(SMSG_AREA_TRIGGER_MESSAGE, (4+msg.length()+1)); - data << (uint32)(msg.length()+1); - data << msg; - SendPacket(&data); + SendAreaTriggerMessage(msg.c_str()); } delete at; } @@ -934,11 +923,14 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) { + sLog.outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); + recv_data.hexlike(); } void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) { sLog.outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); + recv_data.hexlike(); } void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) @@ -988,17 +980,15 @@ DEBUG_LOG( "WORLD: Which movie to play" ); } -void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & recv_data ) -{ - - DEBUG_LOG( "WORLD: Battleground status - not yet" ); -} - void WorldSession::HandleMoveTimeSkippedOpcode( WorldPacket & recv_data ) { WorldSession::Update( getMSTime() ); DEBUG_LOG( "WORLD: Time Lag/Synchronization Resent/Update" ); +} +void WorldSession::HandleFeatherFallAck(WorldPacket &recv_data) +{ + sLog.outString("WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); } void WorldSession::HandleMoveUnRootAck(WorldPacket& recv_data) @@ -1006,7 +996,8 @@ CHECK_PACKET_SIZE(recv_data,8+8+4+4+4+4+4); sLog.outDebug( "WORLD: CMSG_FORCE_MOVE_UNROOT_ACK" ); - WorldPacket data; + recv_data.hexlike(); +/* WorldPacket data; uint64 guid; uint64 unknown1; uint32 unknown2; @@ -1030,21 +1021,17 @@ // DEBUG_LOG("X %f",PositionX); // DEBUG_LOG("Y %f",PositionY); // DEBUG_LOG("Z %f",PositionZ); - // DEBUG_LOG("O %f",Orientation); + // DEBUG_LOG("O %f",Orientation);*/ } -void WorldSession::HandleLookingForGroup(WorldPacket& recv_data) -{ - // TODO send groups need data - sLog.outDebug( "WORLD: MSG_LOOKING_FOR_GROUP" ); -} void WorldSession::HandleMoveRootAck(WorldPacket& recv_data) { CHECK_PACKET_SIZE(recv_data,8+8+4+4+4+4+4); sLog.outDebug( "WORLD: CMSG_FORCE_MOVE_ROOT_ACK" ); - WorldPacket data; + recv_data.hexlike(); +/* WorldPacket data; uint64 guid; uint64 unknown1; uint32 unknown2; @@ -1068,21 +1055,22 @@ // DEBUG_LOG("X %f",PositionX); // DEBUG_LOG("Y %f",PositionY); // DEBUG_LOG("Z %f",PositionZ); - // DEBUG_LOG("O %f",Orientation); + // DEBUG_LOG("O %f",Orientation);*/ } void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data) { CHECK_PACKET_SIZE(recv_data,8+4); + sLog.outDebug("MSG_MOVE_TELEPORT_ACK"); WorldPacket data; uint64 guid; - uint32 value1; + uint32 flags, time; recv_data >> guid; - recv_data >> value1; // ms time ? + recv_data >> flags >> time; DEBUG_LOG("Guid " I64FMTD,guid); - DEBUG_LOG("Value 1 %u",value1); + DEBUG_LOG("Flags %u, time %u",flags, time/1000); } void WorldSession::HandleSetActionBar(WorldPacket& recv_data) @@ -1153,43 +1141,25 @@ { CHECK_PACKET_SIZE(recv_data,8); - Player *pl; uint64 guid; recv_data >> guid; - DEBUG_LOG("Party Stats guid is " I64FMTD,guid); - pl = objmgr.GetPlayer(guid); - if(pl) + Player *player = objmgr.GetPlayer(guid); + + if(!player) { - WorldPacket data( MSG_INSPECT_HONOR_STATS, (8+1+4+4+4+4+4+4+4+4+4+4+1) ); - data << guid; // player guid - // Rank, filling bar, PLAYER_BYTES_3, ?? - data << (uint8)pl->GetUInt32Value(PLAYER_FIELD_BYTES2); - // Today Honorable and Dishonorable Kills - data << pl->GetUInt32Value(PLAYER_FIELD_SESSION_KILLS); - // Yesterday Honorable Kills - data << pl->GetUInt32Value(PLAYER_FIELD_YESTERDAY_KILLS); - // Last Week Honorable Kills - data << pl->GetUInt32Value(PLAYER_FIELD_LAST_WEEK_KILLS); - // This Week Honorable kills - data << pl->GetUInt32Value(PLAYER_FIELD_THIS_WEEK_KILLS); - // Lifetime Honorable Kills - data << pl->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS); - // Lifetime Dishonorable Kills - data << pl->GetUInt32Value(PLAYER_FIELD_LIFETIME_DISHONORABLE_KILLS); - // Yesterday Honor - data << pl->GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION); - // Last Week Honor - data << pl->GetUInt32Value(PLAYER_FIELD_LAST_WEEK_CONTRIBUTION); - // This Week Honor - data << pl->GetUInt32Value(PLAYER_FIELD_THIS_WEEK_CONTRIBUTION); - // Last Week Standing - data << pl->GetUInt32Value(PLAYER_FIELD_LAST_WEEK_RANK); - data << (uint8)pl->GetHonorHighestRank(); // Highest Rank, ?? - SendPacket(&data); + sLog.outError("InspectHonorStats: WFT, player not found..."); + return; } - else - sLog.outDebug("Player %u not found!", guid); + + WorldPacket data( MSG_INSPECT_HONOR_STATS, 13 ); + data << player->GetGUID(); + data << (uint8)player->GetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY); + data << player->GetUInt32Value(PLAYER_FIELD_KILLS); + data << player->GetUInt32Value(PLAYER_FIELD_HONOR_TODAY); + data << player->GetUInt32Value(PLAYER_FIELD_HONOR_YESTERDAY); + data << player->GetUInt32Value(PLAYER_FIELD_KILLS_LIFETIME); + SendPacket(&data); } void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) @@ -1231,12 +1201,12 @@ sLog.outDebug("Received worldport command from player %s", GetPlayer()->GetName()); } -void WorldSession::SendNotification(char const* msg) +void WorldSession::SendNotification(const char *format,...) { - if(msg) + if(format) { - WorldPacket data(SMSG_NOTIFICATION, (strlen(msg)+1)); - data << msg; + WorldPacket data(SMSG_NOTIFICATION, (strlen(format)+1)); + data << format; SendPacket(&data); } } Index: src/game/BattleGround.cpp =================================================================== --- src/game/BattleGround.cpp (working copy) +++ src/game/BattleGround.cpp (working copy) @@ -137,7 +137,7 @@ // Needs vars added to player class and I'm too lazy to rebuild.. plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO()); - plr->SendInitWorldStates(plr->GetBattleGroundEntryPointMap()); + plr->SendInitWorldStates(); //sLog.outDetail("BATTLEGROUND: Sending %s to %f,%f,%f,%f", pl->GetName(), x,y,z,O); } @@ -170,7 +170,7 @@ m_PlayerScores[guid] = sc; - plr->SendInitWorldStates(plr->GetMapId()); + plr->SendInitWorldStates(); WorldPacket data; sBattleGroundMgr.BuildPlayerJoinedBattleGroundPacket(&data,plr); Index: src/game/Item.cpp =================================================================== --- src/game/Item.cpp (working copy) +++ src/game/Item.cpp (working copy) @@ -583,7 +583,7 @@ { SKILL_AXES, SKILL_2H_AXES,SKILL_BOWS, SKILL_GUNS,SKILL_MACES, SKILL_2H_MACES, SKILL_POLEARMS, SKILL_SWORDS,SKILL_2H_SWORDS,0, SKILL_STAVES,0,0,0,0, SKILL_DAGGERS, - SKILL_THROWN, SKILL_SPEARS, SKILL_CROSSBOWS, SKILL_WANDS, SKILL_FISHING + SKILL_THROWN, SKILL_ASSASSINATION, SKILL_CROSSBOWS, SKILL_WANDS, SKILL_FISHING }; const static uint32 item_armor_skills[]= @@ -814,205 +814,208 @@ weapon_subclass = -1; int32 inv_type = itemProto->InventoryType; float tempmod, mod = 0; - uint32 en_display = entry->display_type; - uint32 en_value1 = entry->value1; - uint32 en_spellid = entry->spellid; - if(en_display == 4) + for (int s=0;s<3;s++) { - mod += pow((float)(en_value1 * ITEM_STAT_ARMOR_MOD), 1.50f); - } - else if(en_display == 2) - { - mod += pow((float)(en_value1 * ITEM_STAT_ATTACK_POWER_MOD * 3), 1.50f); - } - else if(en_display == 3 && en_spellid) - { - SpellEntry const *en_spellinfo = sSpellStore.LookupEntry(en_spellid); - if(!en_spellinfo) - return 0; - for(uint8 i = 0; i<3; i++) + uint32 en_display = entry->display_type[s]; + uint32 en_value1 = entry->amount[s]; + uint32 en_spellid = entry->spellid[s]; + if(en_display == 4) { - if(!en_spellinfo->EffectApplyAuraName[i]) - break; - int32 points = en_spellinfo->EffectBasePoints[i]+1; - int32 misc = en_spellinfo->EffectMiscValue[i]; - switch(en_spellinfo->EffectApplyAuraName[i]) + mod += pow((float)(en_value1 * ITEM_STAT_ARMOR_MOD), 1.50f); + } + else if(en_display == 2) + { + mod += pow((float)(en_value1 * ITEM_STAT_ATTACK_POWER_MOD * 3), 1.50f); + } + else if(en_display == 3 && en_spellid) + { + SpellEntry const *en_spellinfo = sSpellStore.LookupEntry(en_spellid); + if(!en_spellinfo) + return 0; + for(uint8 i = 0; i<3; i++) { - case SPELL_AURA_MOD_CREATURE_ATTACK_POWER: - switch(misc) - { - case (0x0001 << (CREATURE_TYPE_BEAST-1)): - case (0x0001 << (CREATURE_TYPE_DEMON-1)): - case (0x0001 << (CREATURE_TYPE_UNDEAD-1)): - mod += pow((float)(points * ITEM_STAT_DBU_ATTACK_POWER_MOD), 1.50f); break; - } + if(!en_spellinfo->EffectApplyAuraName[i]) break; - case SPELL_AURA_MOD_DAMAGE_DONE_CREATURE: - switch(misc) - { - case (0x0001 << (CREATURE_TYPE_BEAST-1)): - case (0x0001 << (CREATURE_TYPE_DEMON-1)): - case (0x0001 << (CREATURE_TYPE_UNDEAD-1)): - mod += pow((float)(points * ITEM_STAT_DBU_SPELL_DAMAGE_MOD), 1.50f); break; - } - break; - case SPELL_AURA_MOD_RANGED_ATTACK_POWER: - mod += pow((float)(points * ITEM_STAT_RANGED_ATTACK_POWER_MOD), 1.50f); break; - case SPELL_AURA_MOD_HEALING_DONE: - mod += pow((float)(points * ITEM_STAT_HEALING_MOD), 1.50f); break; - case SPELL_AURA_MOD_ATTACK_POWER: - mod += pow((float)(points * ITEM_STAT_ATTACK_POWER_MOD), 1.50f); break; - case SPELL_AURA_MOD_SHIELD_BLOCK_PCT: - if(inv_type == INVTYPE_2HWEAPON || inv_type == INVTYPE_HOLDABLE || inv_type == INVTYPE_WEAPONOFFHAND || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; - if(inv_type == INVTYPE_SHIELD) - mod += pow((float)(points * ITEM_STAT_BLOCK_SHIELD_MOD), 1.50f); - else - mod += pow((float)(points * ITEM_STAT_BLOCK_MOD), 1.50f); - break; - case SPELL_AURA_MOD_DAMAGE_DONE: - if(misc == 126) - { - mod += pow((float)(points * ITEM_STAT_ALL_SPELL_DAMAGE_MOD), 1.50f); - } - else - { - if(misc & (0x0001 << SPELL_SCHOOL_HOLY)) + int32 points = en_spellinfo->EffectBasePoints[i]+1; + int32 misc = en_spellinfo->EffectMiscValue[i]; + switch(en_spellinfo->EffectApplyAuraName[i]) + { + case SPELL_AURA_MOD_CREATURE_ATTACK_POWER: + switch(misc) { - if(itemProto->Class == ITEM_CLASS_WEAPON) - if(itemProto->SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_BOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_GUN) - return 0; - mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); + case (0x0001 << (CREATURE_TYPE_BEAST-1)): + case (0x0001 << (CREATURE_TYPE_DEMON-1)): + case (0x0001 << (CREATURE_TYPE_UNDEAD-1)): + mod += pow((float)(points * ITEM_STAT_DBU_ATTACK_POWER_MOD), 1.50f); break; } - if(misc & (0x0001 << SPELL_SCHOOL_FIRE) && !(itemProto->Class == ITEM_CLASS_ARMOR && itemProto->SubClass == ITEM_SUBCLASS_ARMOR_PLATE)) mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); - if(misc & (0x0001 << SPELL_SCHOOL_NATURE) && !(itemProto->Class == ITEM_CLASS_ARMOR && itemProto->SubClass == ITEM_SUBCLASS_ARMOR_PLATE)) mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); - if(misc & (0x0001 << SPELL_SCHOOL_FROST) && !(itemProto->Class == ITEM_CLASS_ARMOR && itemProto->SubClass == ITEM_SUBCLASS_ARMOR_PLATE)) mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); - if(misc & (0x0001 << SPELL_SCHOOL_SHADOW) && !(itemProto->Class == ITEM_CLASS_ARMOR && itemProto->SubClass == ITEM_SUBCLASS_ARMOR_PLATE)) + break; + case SPELL_AURA_MOD_DAMAGE_DONE_CREATURE: + switch(misc) { - if(itemProto->Class == ITEM_CLASS_WEAPON) - if(itemProto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_MACE2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_BOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_GUN) - return 0; - if(inv_type == INVTYPE_SHIELD) - return 0; - mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); + case (0x0001 << (CREATURE_TYPE_BEAST-1)): + case (0x0001 << (CREATURE_TYPE_DEMON-1)): + case (0x0001 << (CREATURE_TYPE_UNDEAD-1)): + mod += pow((float)(points * ITEM_STAT_DBU_SPELL_DAMAGE_MOD), 1.50f); break; } - if(misc & (0x0001 << SPELL_SCHOOL_ARCANE) && !(itemProto->Class == ITEM_CLASS_ARMOR && itemProto->SubClass == ITEM_SUBCLASS_ARMOR_PLATE)) + break; + case SPELL_AURA_MOD_RANGED_ATTACK_POWER: + mod += pow((float)(points * ITEM_STAT_RANGED_ATTACK_POWER_MOD), 1.50f); break; + case SPELL_AURA_MOD_HEALING_DONE: + mod += pow((float)(points * ITEM_STAT_HEALING_MOD), 1.50f); break; + case SPELL_AURA_MOD_ATTACK_POWER: + mod += pow((float)(points * ITEM_STAT_ATTACK_POWER_MOD), 1.50f); break; + case SPELL_AURA_MOD_SHIELD_BLOCK_PCT: + if(inv_type == INVTYPE_2HWEAPON || inv_type == INVTYPE_HOLDABLE || inv_type == INVTYPE_WEAPONOFFHAND || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; + if(inv_type == INVTYPE_SHIELD) + mod += pow((float)(points * ITEM_STAT_BLOCK_SHIELD_MOD), 1.50f); + else + mod += pow((float)(points * ITEM_STAT_BLOCK_MOD), 1.50f); + break; + case SPELL_AURA_MOD_DAMAGE_DONE: + if(misc == 126) { - if(itemProto->Class == ITEM_CLASS_WEAPON) - if(itemProto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_MACE2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_BOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_GUN) + mod += pow((float)(points * ITEM_STAT_ALL_SPELL_DAMAGE_MOD), 1.50f); + } + else + { + if(misc & (0x0001 << SPELL_SCHOOL_HOLY)) + { + if(itemProto->Class == ITEM_CLASS_WEAPON) + if(itemProto->SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_BOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_GUN) + return 0; + mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); + } + if(misc & (0x0001 << SPELL_SCHOOL_FIRE) && !(itemProto->Class == ITEM_CLASS_ARMOR && itemProto->SubClass == ITEM_SUBCLASS_ARMOR_PLATE)) mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); + if(misc & (0x0001 << SPELL_SCHOOL_NATURE) && !(itemProto->Class == ITEM_CLASS_ARMOR && itemProto->SubClass == ITEM_SUBCLASS_ARMOR_PLATE)) mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); + if(misc & (0x0001 << SPELL_SCHOOL_FROST) && !(itemProto->Class == ITEM_CLASS_ARMOR && itemProto->SubClass == ITEM_SUBCLASS_ARMOR_PLATE)) mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); + if(misc & (0x0001 << SPELL_SCHOOL_SHADOW) && !(itemProto->Class == ITEM_CLASS_ARMOR && itemProto->SubClass == ITEM_SUBCLASS_ARMOR_PLATE)) + { + if(itemProto->Class == ITEM_CLASS_WEAPON) + if(itemProto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_MACE2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_BOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_GUN) + return 0; + if(inv_type == INVTYPE_SHIELD) return 0; - if(inv_type == INVTYPE_SHIELD) - return 0; - mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); + mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); + } + if(misc & (0x0001 << SPELL_SCHOOL_ARCANE) && !(itemProto->Class == ITEM_CLASS_ARMOR && itemProto->SubClass == ITEM_SUBCLASS_ARMOR_PLATE)) + { + if(itemProto->Class == ITEM_CLASS_WEAPON) + if(itemProto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_MACE2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2 || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_BOW || itemProto->SubClass == ITEM_SUBCLASS_WEAPON_GUN) + return 0; + if(inv_type == INVTYPE_SHIELD) + return 0; + mod += pow((float)(points * ITEM_STAT_SCHOOL_SPELL_DAMAGE_MOD), 1.50f); + } } - } - break; - case SPELL_AURA_MOD_RESISTANCE: - if(misc == 126) - { - if(inv_type == INVTYPE_FINGER) - mod += pow((float)(points * ITEM_STAT_ALL_SPELL_RESIST_RING_MOD), 1.50f); + break; + case SPELL_AURA_MOD_RESISTANCE: + if(misc == 126) + { + if(inv_type == INVTYPE_FINGER) + mod += pow((float)(points * ITEM_STAT_ALL_SPELL_RESIST_RING_MOD), 1.50f); + else + mod += pow((float)(points * ITEM_STAT_ALL_SPELL_RESIST_MOD), 1.50f); + } else - mod += pow((float)(points * ITEM_STAT_ALL_SPELL_RESIST_MOD), 1.50f); - } - else - { + { + if(inv_type == INVTYPE_FINGER) + tempmod = ITEM_STAT_SCHOOL_RESIST_RING_MOD; + else + tempmod = ITEM_STAT_SCHOOL_RESIST_MOD; + if(misc & (0x0001 << SPELL_SCHOOL_FIRE)) mod += pow((float)(points * tempmod), 1.50f); + if(misc & (0x0001 << SPELL_SCHOOL_NATURE)) mod += pow((float)(points * tempmod), 1.50f); + if(misc & (0x0001 << SPELL_SCHOOL_FROST)) mod += pow((float)(points * tempmod), 1.50f); + if(misc & (0x0001 << SPELL_SCHOOL_SHADOW)) mod += pow((float)(points * tempmod), 1.50f); + if(misc & (0x0001 << SPELL_SCHOOL_ARCANE)) mod += pow((float)(points * tempmod), 1.50f); + } + break; + case SPELL_AURA_MOD_STAT: + mod += pow((float)(points * ITEM_STAT_ATTRIBUTE_MOD), 1.50f); break; + case SPELL_AURA_MOD_SKILL: + switch(misc) + { + case SKILL_DEFENSE: + if(inv_type == INVTYPE_SHIELD) + mod += pow((float)(points * ITEM_STAT_DEFENSE_SHIELD_MOD), 1.50f); + else + mod += pow((float)(points * ITEM_STAT_DEFENSE_MOD), 1.50f); + break; + case SKILL_DAGGERS: + if(weapon_subclass != -1 && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONOFFHAND && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT) return 0; + mod += pow((float)(points * ITEM_STAT_DAGGER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_SWORDS: + if(weapon_subclass != -1 && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONOFFHAND && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_AXES: + if(weapon_subclass != -1 && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONOFFHAND && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_BOWS: + if(weapon_subclass != -1 && weapon_subclass != ITEM_SUBCLASS_WEAPON_BOW && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_2HWEAPON) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_GUNS: + if(weapon_subclass != -1 && weapon_subclass != ITEM_SUBCLASS_WEAPON_GUN && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_2HWEAPON) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_MACES: + if(weapon_subclass != -1 && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONOFFHAND && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_2H_SWORDS: + if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_SWORD2 && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_STAVES: + if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_STAFF && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_2H_MACES: + if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_MACE2 && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_2H_AXES: + if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_AXE2 && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_CROSSBOWS: + if(weapon_subclass != -1 && weapon_subclass != ITEM_SUBCLASS_WEAPON_CROSSBOW && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_2HWEAPON) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_SPEARS: + if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_SPEAR && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_WANDS: + if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD) && weapon_subclass != ITEM_SUBCLASS_WEAPON_WAND && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_2HWEAPON) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + case SKILL_POLEARMS: + if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_POLEARM && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; + mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; + } + break; + case SPELL_AURA_MOD_POWER_REGEN: + mod += pow((float)(points * ITEM_STAT_REGEN_IN_5_SEC_MOD), 1.50f); break; + case SPELL_AURA_MOD_REGEN: + case SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT: if(inv_type == INVTYPE_FINGER) - tempmod = ITEM_STAT_SCHOOL_RESIST_RING_MOD; + mod += pow((float)(points * ITEM_STAT_HP_REGEN_IN_5_SEC_RING_MOD), 1.50f); + else if(inv_type == INVTYPE_NECK) + mod += pow((float)(points * ITEM_STAT_HP_REGEN_IN_5_SEC_NECK_MOD), 1.50f); else - tempmod = ITEM_STAT_SCHOOL_RESIST_MOD; - if(misc & (0x0001 << SPELL_SCHOOL_FIRE)) mod += pow((float)(points * tempmod), 1.50f); - if(misc & (0x0001 << SPELL_SCHOOL_NATURE)) mod += pow((float)(points * tempmod), 1.50f); - if(misc & (0x0001 << SPELL_SCHOOL_FROST)) mod += pow((float)(points * tempmod), 1.50f); - if(misc & (0x0001 << SPELL_SCHOOL_SHADOW)) mod += pow((float)(points * tempmod), 1.50f); - if(misc & (0x0001 << SPELL_SCHOOL_ARCANE)) mod += pow((float)(points * tempmod), 1.50f); - } - break; - case SPELL_AURA_MOD_STAT: - mod += pow((float)(points * ITEM_STAT_ATTRIBUTE_MOD), 1.50f); break; - case SPELL_AURA_MOD_SKILL: - switch(misc) - { - case SKILL_DEFENSE: - if(inv_type == INVTYPE_SHIELD) - mod += pow((float)(points * ITEM_STAT_DEFENSE_SHIELD_MOD), 1.50f); - else - mod += pow((float)(points * ITEM_STAT_DEFENSE_MOD), 1.50f); - break; - case SKILL_DAGGERS: - if(weapon_subclass != -1 && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONOFFHAND && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT) return 0; - mod += pow((float)(points * ITEM_STAT_DAGGER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_SWORDS: - if(weapon_subclass != -1 && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONOFFHAND && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_AXES: - if(weapon_subclass != -1 && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONOFFHAND && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_BOWS: - if(weapon_subclass != -1 && weapon_subclass != ITEM_SUBCLASS_WEAPON_BOW && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_2HWEAPON) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_GUNS: - if(weapon_subclass != -1 && weapon_subclass != ITEM_SUBCLASS_WEAPON_GUN && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_2HWEAPON) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_MACES: - if(weapon_subclass != -1 && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONOFFHAND && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_2H_SWORDS: - if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_SWORD2 && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_STAVES: - if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_STAFF && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_2H_MACES: - if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_MACE2 && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_2H_AXES: - if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_AXE2 && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_CROSSBOWS: - if(weapon_subclass != -1 && weapon_subclass != ITEM_SUBCLASS_WEAPON_CROSSBOW && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_2HWEAPON) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_SPEARS: - if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_SPEAR && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_WANDS: - if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD) && weapon_subclass != ITEM_SUBCLASS_WEAPON_WAND && inv_type != INVTYPE_WEAPON && inv_type != INVTYPE_WEAPONMAINHAND && inv_type != INVTYPE_2HWEAPON) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - case SKILL_POLEARMS: - if((weapon_subclass != -1 || inv_type == INVTYPE_SHIELD || inv_type == INVTYPE_HOLDABLE) && weapon_subclass != ITEM_SUBCLASS_WEAPON_POLEARM && inv_type != INVTYPE_RANGED && inv_type != INVTYPE_RANGEDRIGHT || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; - mod += pow((float)(points * ITEM_STAT_OTHER_WEAPON_SKILL_MOD), 1.50f); break; - } - break; - case SPELL_AURA_MOD_POWER_REGEN: - mod += pow((float)(points * ITEM_STAT_REGEN_IN_5_SEC_MOD), 1.50f); break; - case SPELL_AURA_MOD_REGEN: - case SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT: - if(inv_type == INVTYPE_FINGER) - mod += pow((float)(points * ITEM_STAT_HP_REGEN_IN_5_SEC_RING_MOD), 1.50f); - else if(inv_type == INVTYPE_NECK) - mod += pow((float)(points * ITEM_STAT_HP_REGEN_IN_5_SEC_NECK_MOD), 1.50f); - else - mod += pow((float)(points * ITEM_STAT_REGEN_IN_5_SEC_MOD), 1.50f); - break; - case SPELL_AURA_PROC_TRIGGER_DAMAGE: - mod += pow((float)(points * ITEM_STAT_MAGIC_PENETRATION_MOD), 1.50f); break; - case SPELL_AURA_DAMAGE_SHIELD: - if(inv_type == INVTYPE_2HWEAPON || inv_type == INVTYPE_HOLDABLE || inv_type == INVTYPE_WEAPONOFFHAND || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; - mod += pow((float)(points * ITEM_STAT_DAMAGE_SHIELD_MOD), 1.50f); break; - case SPELL_AURA_MOD_BLOCK_PERCENT: - if(inv_type == INVTYPE_2HWEAPON || inv_type == INVTYPE_HOLDABLE || inv_type == INVTYPE_WEAPONOFFHAND || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; - mod += pow((float)(points * ITEM_STAT_BLOCK_PCT_MOD), 1.50f); break; - case SPELL_AURA_MOD_HIT_CHANCE: - mod += pow((float)(points * ITEM_STAT_HIT_PCT_MOD), 1.50f); break; - case SPELL_AURA_MOD_SPELL_HIT_CHANCE: - mod += pow((float)(points * ITEM_STAT_SPELL_HIT_PCT_MOD), 1.50f); break; - case SPELL_AURA_MOD_DODGE_PERCENT: - mod += pow((float)(points * ITEM_STAT_DODGE_PCT_MOD), 1.50f); break; - case SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL: - mod += pow((float)(points * ITEM_STAT_SPELL_CRIT_PCT_MOD), 1.50f); break; - case SPELL_AURA_MOD_CRIT_PERCENT: - mod += pow((float)(points * ITEM_STAT_CRIT_PCT_MOD), 1.50f); break; - case SPELL_AURA_MOD_PARRY_PERCENT: - mod += pow((float)(points * ITEM_STAT_PARRY_PCT_MOD), 1.50f); break; + mod += pow((float)(points * ITEM_STAT_REGEN_IN_5_SEC_MOD), 1.50f); + break; + case SPELL_AURA_PROC_TRIGGER_DAMAGE: + mod += pow((float)(points * ITEM_STAT_MAGIC_PENETRATION_MOD), 1.50f); break; + case SPELL_AURA_DAMAGE_SHIELD: + if(inv_type == INVTYPE_2HWEAPON || inv_type == INVTYPE_HOLDABLE || inv_type == INVTYPE_WEAPONOFFHAND || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; + mod += pow((float)(points * ITEM_STAT_DAMAGE_SHIELD_MOD), 1.50f); break; + case SPELL_AURA_MOD_BLOCK_PERCENT: + if(inv_type == INVTYPE_2HWEAPON || inv_type == INVTYPE_HOLDABLE || inv_type == INVTYPE_WEAPONOFFHAND || weapon_subclass == ITEM_SUBCLASS_WEAPON_WAND) return 0; + mod += pow((float)(points * ITEM_STAT_BLOCK_PCT_MOD), 1.50f); break; + case SPELL_AURA_MOD_HIT_CHANCE: + mod += pow((float)(points * ITEM_STAT_HIT_PCT_MOD), 1.50f); break; + case SPELL_AURA_MOD_SPELL_HIT_CHANCE: + mod += pow((float)(points * ITEM_STAT_SPELL_HIT_PCT_MOD), 1.50f); break; + case SPELL_AURA_MOD_DODGE_PERCENT: + mod += pow((float)(points * ITEM_STAT_DODGE_PCT_MOD), 1.50f); break; + case SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL: + mod += pow((float)(points * ITEM_STAT_SPELL_CRIT_PCT_MOD), 1.50f); break; + case SPELL_AURA_MOD_CRIT_PERCENT: + mod += pow((float)(points * ITEM_STAT_CRIT_PCT_MOD), 1.50f); break; + case SPELL_AURA_MOD_PARRY_PERCENT: + mod += pow((float)(points * ITEM_STAT_PARRY_PCT_MOD), 1.50f); break; + } } } } Index: src/game/WorldSession.h =================================================================== --- src/game/WorldSession.h (working copy) +++ src/game/WorldSession.h (working copy) @@ -55,7 +55,8 @@ void SizeError(WorldPacket const& packet, uint32 size) const; void SendPacket(WorldPacket* packet); - void SendNotification(char const* msg); + void SendNotification(const char *format,...); + void SendLfgResult(uint32 type, uint32 entry); void SendPartyResult(uint32 unk, std::string member, uint32 state); void SendAreaTriggerMessage(const char* Text, ...); @@ -92,7 +93,7 @@ void QueuePacket(WorldPacket& packet); bool Update(uint32 diff); - void SendTestCreatureQueryOpcode( uint32 entry, uint64 guid, uint32 testvalue ); + //void SendTestCreatureQueryOpcode( uint32 entry, uint64 guid, uint32 testvalue ); void SendNameQueryOpcode(Player* p); void SendNameQueryOpcodeFromDB(uint64 guid); @@ -130,7 +131,7 @@ //Item Enchantement void SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID); - void SendItemEnchantTimeUpdate(uint64 Itemguid,uint32 slot,uint32 Duration); + void SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,uint32 slot,uint32 Duration); //Taxi void SendTaxiStatus( uint64 guid ); @@ -159,6 +160,8 @@ void HandleInspectHonorStatsOpcode(WorldPacket& recvPacket); void HandleMoveWaterWalkAck(WorldPacket& recvPacket); + void HandleFeatherFallAck(WorldPacket &recv_data); + void HandleMoveHoverAck( WorldPacket & recv_data ); void HandleMountSpecialAnimOpcode(WorldPacket &recvdata); @@ -257,7 +260,8 @@ void HandleRaidReadyCheckOpcode( WorldPacket & recv_data ); void HandleRaidConvertOpcode( WorldPacket & recv_data ); void HandleGroupChangeSubGroupOpcode( WorldPacket & recv_data ); - void HandleAssistantOpcode( WorldPacket & recv_data ); + void HandleGroupAssistantOpcode( WorldPacket & recv_data ); + void HandleGroupPromoteOpcode( WorldPacket & recv_data ); void HandlePetitionBuyOpcode(WorldPacket& recv_data); void HandlePetitionShowSignOpcode(WorldPacket& recv_data); @@ -459,7 +463,41 @@ void HandleMinimapPingOpcode(WorldPacket& recv_data); void HandleRandomRollOpcode(WorldPacket& recv_data); void HandleFarSightOpcode(WorldPacket& recv_data); + void HandleSetLfgOpcode(WorldPacket& recv_data); + void HandleDungeonDifficultyOpcode(WorldPacket& recv_data); + void HandleMoveFlyModeChangeAckOpcode(WorldPacket& recv_data); + void HandleLfgAutoJoinOpcode(WorldPacket& recv_data); + void HandleLfgCancelAutoJoinOpcode(WorldPacket& recv_data); + void HandleLfmAutoAddMembersOpcode(WorldPacket& recv_data); + void HandleLfmCancelAutoAddmembersOpcode(WorldPacket& recv_data); + void HandleLfgClearOpcode(WorldPacket& recv_data); + void HandleLfmSetNoneOpcode(WorldPacket& recv_data); + void HandleLfmSetOpcode(WorldPacket& recv_data); + void HandleLfgSetCommentOpcode(WorldPacket& recv_data); + void HandleNewUnknownOpcode(WorldPacket& recv_data); + void HandleInspectArenaStatsOpcode(WorldPacket& recv_data); + void HandleArenaTeamQueryOpcode(WorldPacket& recv_data); + void HandleChooseTitleOpcode(WorldPacket& recv_data); + void HandleRealmStateRequestOpcode(WorldPacket& recv_data); + void HandleAllowMoveAckOpcode(WorldPacket& recv_data); + void HandleWhoisOpcode(WorldPacket& recv_data); + void HandleResetInstancesOpcode(WorldPacket& recv_data); + void HandleArenaTeamRosterOpcode(WorldPacket& recv_data); + void HandleArenaTeamAddMemberOpcode(WorldPacket& recv_data); + void HandleArenaTeamInviteAcceptOpcode(WorldPacket& recv_data); + void HandleArenaTeamInviteDeclineOpcode(WorldPacket& recv_data); + void HandleArenaTeamLeaveOpcode(WorldPacket& recv_data); + void HandleArenaTeamDisbandOpcode(WorldPacket& recv_data); + void HandleAreaSpiritHealerQueryOpcode(WorldPacket& recv_data); + void HandleDismountOpcode(WorldPacket& recv_data); + // testing... + void HandleMoveShipOpcode(WorldPacket& recv_data); + void HandleMoveFlyStateChangeOpcode(WorldPacket& recv_data); + + // Socket gem + void HandleSocketOpcode(WorldPacket& recv_data); + OpcodeHandler* _GetOpcodeHandlerTable() const; private: Index: src/game/Unit.cpp =================================================================== --- src/game/Unit.cpp (working copy) +++ src/game/Unit.cpp (working copy) @@ -417,9 +417,7 @@ // self or owner of pet if(player) { - float honordiff = player->GetTotalHonor(); player->CalculateHonor(pVictim); - honordiff -= player->GetTotalHonor(); player->CalculateReputation(pVictim); @@ -462,7 +460,7 @@ player->KilledMonster(pVictim->GetEntry(),pVictim->GetGUID()); } // if-else (pGroup) - if(xp || honordiff < 0) + if(xp) // || honordiff < 0) ProcDamageAndSpell(pVictim,PROC_FLAG_KILL_XP_GIVER,PROC_FLAG_NONE); } // if (!PvP) } @@ -904,16 +902,50 @@ sLog.outDetail("PeriodicAuraLog: %u %X attacked %u %X for %u dmg inflicted by %u abs is %u", GetGUIDLow(), GetGUIDHigh(), pVictim->GetGUIDLow(), pVictim->GetGUIDHigh(), pdamage, spellProto->Id,absorb); + // this packet has random structure, probably based on auraid... WorldPacket data(SMSG_PERIODICAURALOG, (21+16)); // we guess size data.append(pVictim->GetPackGUID()); - data.append(this->GetPackGUID()); + data.append(GetPackGUID()); data << spellProto->Id; data << uint32(1); data << mod->m_auraname; - data << (uint32)(mod->m_amount); - data << spellProto->School; - data << uint32(0); + switch(mod->m_auraname) + { + case SPELL_AURA_PERIODIC_DAMAGE: + data << (uint32)mod->m_amount; // ? + data << spellProto->School; // ? + data << (uint32)0; // ? + data << (uint32)0; // ? + break; + case SPELL_AURA_PERIODIC_HEAL: + data << (uint32)mod->m_amount; // ? + break; + case SPELL_AURA_OBS_MOD_HEALTH: + data << (uint32)mod->m_amount; // ? + break; + //case SPELL_AURA_PERIODIC_TRIGGER_SPELL: + // break; + case SPELL_AURA_PERIODIC_ENERGIZE: + data << (uint32)mod->m_amount; // ? + data << (uint32)0; // ? + break; + //case SPELL_AURA_PERIODIC_LEECH: + // break; + //case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: + // break; + //case SPELL_AURA_PERIODIC_MANA_FUNNEL: + // break; + //case SPELL_AURA_PERIODIC_MANA_LEECH: + // break; + //case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + // break; + default: + sLog.outError("PeriodicAuraLog: unhandled aura %u", mod->m_auraname); + break; + } + //data << (uint32)mod->m_amount; + //data << spellProto->School; SendMessageToSet(&data,true); if(mod->m_auraname == SPELL_AURA_PERIODIC_DAMAGE) @@ -1712,9 +1744,9 @@ WorldPacket data( SMSG_ATTACKSTOP, (4+16) ); // we guess size data.append(GetPackGUID()); - data.append(victim->GetPackGUID()); - data << uint32( 0 ); - data << (uint32)0; + data.append(victim->GetPackGUID()); // can be 0x00... + data << uint32( 0 ); // can be 0x1 + //data << (uint32)0; // removed in 2.0.8 SendMessageToSet(&data, true); sLog.outDetail("%s %u stopped attacking %s %u", (GetTypeId()==TYPEID_PLAYER ? "player" : "creature"), GetGUIDLow(), (victim->GetTypeId()==TYPEID_PLAYER ? "player" : "creature"),victim->GetGUIDLow()); @@ -2146,7 +2178,7 @@ bool Unit::AddAura(Aura *Aur, bool uniq) { - if (!isAlive()) + if (!isAlive() && !(Aur->GetSpellProto()->Id == 20584 || Aur->GetSpellProto()->Id == 8326)) // ghost spell check { delete Aur; return false; @@ -2177,7 +2209,8 @@ RemoveAura(i); } - if (!Aur->IsPassive()) // passive auras stack with all + // passive auras stack with all + if (!Aur->IsPassive() && !(Aur->GetSpellProto()->Id == 20584 || Aur->GetSpellProto()->Id == 8326)) // ghost spell check { if (!RemoveNoStackAurasDueToAura(Aur)) { @@ -2956,49 +2989,153 @@ if(!item->IsEquipped()) return; - if(enchant_slot > 7) + if(enchant_slot > 11) return; SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); if(!pEnchant) return; - uint32 enchant_display = pEnchant->display_type; - uint32 enchant_value1 = pEnchant->value1; - uint32 enchant_spell_id = pEnchant->spellid; + for (int s=0; s<3; s++) + { + uint32 enchant_display_type = pEnchant->display_type[s]; + uint32 enchant_amount = pEnchant->amount[s]; + uint32 enchant_spell_id = pEnchant->spellid[s]; - SpellEntry const *enchantSpell_info = sSpellStore.LookupEntry(enchant_spell_id); - - if(enchant_display ==4) - { - ApplyArmorMod(enchant_value1,apply); - } - else if(enchant_display ==2) - { - if(getClass() == CLASS_HUNTER) + SpellEntry const *enchantSpell_info = sSpellStore.LookupEntry(enchant_spell_id); + + if (enchant_display_type == 0) { - ApplyModFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,enchant_value1,apply); - ApplyModFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,enchant_value1,apply); + // Nothing } - else + else if(enchant_display_type ==4) { - ApplyModFloatValue(UNIT_FIELD_MINDAMAGE,enchant_value1,apply); - ApplyModFloatValue(UNIT_FIELD_MAXDAMAGE,enchant_value1,apply); + ApplyArmorMod(enchant_amount,apply); } - } - else - { - if(apply && enchant_display == 3) + else if(enchant_display_type == 6) // Shaman Rockbiter Weapon { - Spell spell(this, enchantSpell_info, true, 0); - SpellCastTargets targets; - targets.setUnitTarget(this); - spell.prepare(&targets); + // enchant_amount is then containing the number of damage per second to add to the weapon + if(getClass() == CLASS_SHAMAN) + { + ApplyModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,enchant_amount,apply); + //ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,enchant_amount,apply); + } } - else RemoveAurasDueToSpell(enchant_spell_id); + else if(enchant_display_type == 5) // + { + sLog.outDebug("Adding %u to stat nb %u",enchant_amount,enchant_spell_id); + switch (enchant_spell_id) + { + case ITEM_STAT_AGILITY: + sLog.outDebug("+ %u AGILITY",enchant_amount); + ApplyPosStatMod(STAT_AGILITY, enchant_amount, apply); + ApplyStatMod(STAT_AGILITY, enchant_amount, apply); + break; + case ITEM_STAT_STRENGTH: + sLog.outDebug("+ %u STRENGTH",enchant_amount); + ApplyPosStatMod(STAT_STRENGTH, enchant_amount, apply); + ApplyStatMod(STAT_STRENGTH, enchant_amount, apply); + break; + case ITEM_STAT_INTELLECT: + sLog.outDebug("+ %u INTELLECT",enchant_amount); + ApplyPosStatMod(STAT_INTELLECT, enchant_amount, apply); + ApplyStatMod(STAT_INTELLECT, enchant_amount, apply); + break; + case ITEM_STAT_SPIRIT: + sLog.outDebug("+ %u SPIRIT",enchant_amount); + ApplyPosStatMod(STAT_SPIRIT, enchant_amount, apply); + ApplyStatMod(STAT_SPIRIT, enchant_amount, apply); + break; + case ITEM_STAT_STAMINA: + sLog.outDebug("+ %u STAMINA",enchant_amount); + ApplyPosStatMod(STAT_STAMINA, enchant_amount, apply); + ApplyStatMod(STAT_STAMINA, enchant_amount, apply); + break; + case ITEM_STAT_DEFENCE_RATING: + ApplyModUInt32Value(PLAYER_FIELD_DEFENCE_RATING, enchant_amount, apply); + sLog.outDebug("+ %u DEFENCE", enchant_amount); + break; + case ITEM_STAT_DODGE_RATING: + ApplyModUInt32Value(PLAYER_FIELD_DODGE_RATING, enchant_amount, apply); + sLog.outDebug("+ %u DODGE", enchant_amount); + break; + case ITEM_STAT_PARRY_RATING: + ApplyModUInt32Value(PLAYER_FIELD_PARRY_RATING, enchant_amount, apply); + sLog.outDebug("+ %u PARRY", enchant_amount); + break; + case ITEM_STAT_SHIELD_BLOCK_RATING: + ApplyModUInt32Value(PLAYER_FIELD_BLOCK_RATING, enchant_amount, apply); + sLog.outDebug("+ %u SHIELD_BLOCK", enchant_amount); + break; + case ITEM_STAT_MELEE_HIT_RATING: + ApplyModUInt32Value(PLAYER_FIELD_MELEE_HIT_RATING, enchant_amount, apply); + sLog.outDebug("+ %u MELEE_HIT", enchant_amount); + break; + case ITEM_STAT_RANGED_HIT_RATING: + ApplyModUInt32Value(PLAYER_FIELD_RANGED_HIT_RATING, enchant_amount, apply); + sLog.outDebug("+ %u RANGED_HIT", enchant_amount); + break; + case ITEM_STAT_SPELL_HIT_RATING: + ApplyModUInt32Value(PLAYER_FIELD_SPELL_HIT_RATING, enchant_amount, apply); + sLog.outDebug("+ %u SPELL_HIT", enchant_amount); + break; + case ITEM_STAT_MELEE_CS_RATING: // CS = Critical Strike + ApplyModUInt32Value(PLAYER_FIELD_MELEE_CRIT_RATING, enchant_amount, apply); + sLog.outDebug("+ %u MELEE_CRIT", enchant_amount); + break; + case ITEM_STAT_RANGED_CS_RATING: + ApplyModUInt32Value(PLAYER_FIELD_RANGED_CRIT_RATING, enchant_amount, apply); + sLog.outDebug("+ %u RANGED_CRIT", enchant_amount); + break; + case ITEM_STAT_SPELL_CS_RATING: + ApplyModUInt32Value(PLAYER_FIELD_SPELL_CRIT_RATING, enchant_amount, apply); + sLog.outDebug("+ %u SPELL_CRIT", enchant_amount); + break; + // Values from ITEM_STAT_MELEE_HA_RATING to ITEM_STAT_SPELL_HASTE_RATING are never used + // in Enchantments + case ITEM_STAT_HIT_RATING: + ApplyModUInt32Value(PLAYER_FIELD_HIT_RATING, enchant_amount, apply); + sLog.outDebug("+ %u HIT", enchant_amount); + break; + case ITEM_STAT_CS_RATING: + ApplyModUInt32Value(PLAYER_FIELD_CRIT_RATING, enchant_amount, apply); + sLog.outDebug("+ %u CRITICAL", enchant_amount); + break; + // Values ITEM_STAT_HA_RATING and ITEM_STAT_CA_RATING are never used in Enchantment + case ITEM_STAT_RESILIENCE_RATING: + ApplyModUInt32Value(PLAYER_FIELD_RESILIENCE_RATING, enchant_amount, apply); + sLog.outDebug("+ %u RESILIENCE", enchant_amount); + break; + // Value ITEM_STAT_HASTE_RATING is never used in Enchantment + } + } + else if(enchant_display_type ==2) + { + if(getClass() == CLASS_HUNTER) + { + ApplyModFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,enchant_amount,apply); + ApplyModFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,enchant_amount,apply); + } + else + { + ApplyModFloatValue(UNIT_FIELD_MINDAMAGE,enchant_amount,apply); + ApplyModFloatValue(UNIT_FIELD_MAXDAMAGE,enchant_amount,apply); + } + } + else + { + if(apply && enchant_display_type == 3) + { + Spell spell(this, enchantSpell_info, true, 0); + SpellCastTargets targets; + targets.setUnitTarget(this); + spell.prepare(&targets); + } + else RemoveAurasDueToSpell(enchant_spell_id); + } } // visualize enchantment at player and equipped items - int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (item->GetSlot() * 12); + int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (item->GetSlot() * 16); SetUInt32Value(VisibleBase+1 + enchant_slot, apply? item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+enchant_slot*3) : 0); } @@ -3088,7 +3225,7 @@ data << (uint8)PhysicalDamage; data << uint8(0); data << Blocked; //blocked - data << uint8(CriticalHit ? 2 : 0); + data << uint8(CriticalHit ? 2 : 0); //seen 0x05 also... data << uint32(0); SendMessageToSet( &data, true ); } @@ -4438,6 +4575,9 @@ bool Unit::isVisibleFor(Unit* u, bool detect) { + if(!u) + return false; + // Visible units, always are visible for all pjs if (m_Visibility == VISIBILITY_ON) return true; @@ -4569,10 +4709,19 @@ else { data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 16); } break; case MOVE_SWIMBACK: - data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 16); + if(forced) { data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16); } + else { data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 16); } break; case MOVE_TURN: - return; // ignore + if(forced) { data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16); } + else { data.Initialize(MSG_MOVE_SET_TURN_RATE, 16); } + break; + case MOVE_FLY: + if(forced) { data.Initialize(SMSG_FORCE_FLY_SPEED_CHANGE, 16); } + else { data.Initialize(SMSG_MOVE_SET_FLY_SPEED, 16); } + break; + case MOVE_FLYBACK: + break; default: sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype); return; Index: src/game/SpellAuras.h =================================================================== --- src/game/SpellAuras.h (working copy) +++ src/game/SpellAuras.h (working copy) @@ -81,6 +81,7 @@ void HandleModThreat(bool Apply, bool Real); void HandleModTaunt(bool Apply, bool Real); void HandleFeignDeath(bool Apply, bool Real); + void HandleAuraModDisarm(bool Apply, bool Real); void HandleAuraModStalked(bool Apply, bool Real); void HandleAuraWaterWalk(bool Apply, bool Real); void HandleAuraFeatherFall(bool Apply, bool Real); @@ -89,6 +90,7 @@ void HandleAuraModStun(bool Apply, bool Real); void HandleModDamageDone(bool Apply, bool Real); void HandleModHealingPercent(bool Apply, bool Real); + void HandleAuraUntrackable(bool Apply, bool Real); void HandleAuraEmpathy(bool Apply, bool Real); void HandleModOffhandDamagePercent(bool apply, bool Real); void HandleAuraModRangedAttackPower(bool Apply, bool Real); @@ -168,6 +170,10 @@ void HandleModTotalPercentStat(bool Apply, bool Real); void HandleAuraModTotalThreat(bool Apply, bool Real); void HandleInterruptRegen(bool Apply, bool Real); + void HandleAuraModPacify(bool Apply, bool Real); + void HandleAuraGhost(bool Apply, bool Real); + void HandleAuraAllowFlight(bool Apply, bool Real); + void HandleAuraModSpeedMountedFlight(bool Apply, bool Real); Aura(SpellEntry const* spellproto, uint32 eff, Unit *target, Unit *caster = NULL, Item* castItem = NULL); virtual ~Aura(); Index: src/game/ObjectMgr.h =================================================================== --- src/game/ObjectMgr.h (working copy) +++ src/game/ObjectMgr.h (working copy) @@ -220,7 +220,7 @@ if(race >= MAX_RACES) return NULL; if(class_ >= MAX_CLASSES) return NULL; PlayerInfo const* info = &playerInfo[race][class_]; - if(info->displayId==0) return NULL; + if(info->displayId_m==0 || info->displayId_f==0) return NULL; return info; } void GetPlayerLevelInfo(uint32 race, uint32 class_,uint32 level, PlayerLevelInfo* info) const; Index: src/game/CharacterHandler.cpp =================================================================== --- src/game/CharacterHandler.cpp (working copy) +++ src/game/CharacterHandler.cpp (working copy) @@ -33,6 +33,7 @@ #include "ObjectAccessor.h" #include "Transports.h" #include "Group.h" +#include "../realmd/AuthCodes.h" void WorldSession::HandleCharEnumOpcode( WorldPacket & recv_data ) { @@ -97,7 +98,7 @@ if(name.size() == 0) { data.Initialize( SMSG_CHAR_CREATE, 1 ); - data << (uint8)0x33; + data << (uint8)CHAR_NAME_INVALID_CHARACTER; SendPacket( &data ); return; } @@ -110,7 +111,7 @@ if(name.find_first_of(notAllowedChars)!=name.npos) { data.Initialize( SMSG_CHAR_CREATE, 1 ); - data << (uint8)0x33; + data << (uint8)CHAR_NAME_INVALID_CHARACTER;; SendPacket( &data ); return; } @@ -123,7 +124,7 @@ delete result; data.Initialize(SMSG_CHAR_CREATE, 1); - data << (uint8)0x31; + data << (uint8)CHAR_LOGIN_DUPLICATE_CHARACTER; SendPacket( &data ); return; @@ -136,7 +137,7 @@ if (result->GetRowCount() >= 10) { data.Initialize(SMSG_CHAR_CREATE, 1); - data << (uint8)0x2F; + data << (uint8)CHAR_CREATE_ACCOUNT_LIMIT; SendPacket( &data ); delete result; return; @@ -164,7 +165,7 @@ if(team != team_ && GetSecurity() < 2 && !AllowTwoSideAccounts) { data.Initialize( SMSG_CHAR_CREATE, 1 ); - data << (uint8)0x33; + data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; SendPacket( &data ); return; } @@ -196,22 +197,14 @@ delete pNewChar; data.Initialize(SMSG_CHAR_CREATE, 1); - data << (uint8)0x2F; + data << (uint8)CHAR_CREATE_ERROR; SendPacket( &data ); return; } - // we have successfull creation - // note all error codes moved + 1 - // 0x2E - Character created - // 0x30 - Char create failed - // 0x31 - Char name is in use - // 0x35 - Char delete Okay - // 0x36 - Char delete failed - data.Initialize( SMSG_CHAR_CREATE, 1 ); - data << (uint8)0x2E; + data << (uint8)CHAR_CREATE_SUCCESS; SendPacket( &data ); sLog.outBasic("Account: %d Create New Character:[%s]",GetAccountId(),name.c_str()); @@ -238,10 +231,8 @@ plr.DeleteFromDB(); } - //data.Initialize(SMSG_CHAR_CREATE); - //data << (uint8)0x34; - WorldPacket data(SMSG_CHAR_DELETE, 1); // Changed in 1.12.x client branch - data << (uint8)0x39; // Changed in 1.12.x client branch + WorldPacket data(SMSG_CHAR_DELETE, 1); + data << (uint8)CHAR_DELETE_SUCCESS; SendPacket( &data ); } @@ -281,24 +272,43 @@ SetPlayer(plr); - WorldPacket data( SMSG_ACCOUNT_DATA_MD5, (80) ); + Player *pCurrChar = GetPlayer(); - for(int i = 0; i < 80; i++) - data << uint8(0); + pCurrChar->SendDungeonDifficulty(); + WorldPacket data( SMSG_LOGIN_VERIFY_WORLD, 20 ); + data << plr->GetMapId(); + data << plr->GetPositionX(); + data << plr->GetPositionY(); + data << plr->GetPositionZ(); + data << plr->GetOrientation(); SendPacket(&data); - Player *pCurrChar = GetPlayer(); + data.Initialize( SMSG_ACCOUNT_DATA_MD5, 128 ); + for(int i = 0; i < 128; i++) + data << uint8(0); + SendPacket(&data); pCurrChar->LoadIgnoreList(); pCurrChar->SendFriendlist(); pCurrChar->SendIgnorelist(); - sChatHandler.FillSystemMessageData(&data, this, sWorld.GetMotd()); + data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 + data << (uint32)0; + + uint32 linecount=0; + char* line = strtok((char*)sWorld.GetMotd(), "@"); + while(line != NULL) + { + data << line; + linecount++; + line = strtok(NULL, "@"); + } + + data.put(0, linecount); SendPacket( &data ); + DEBUG_LOG( "WORLD: Sent motd (SMSG_MOTD)" ); - DEBUG_LOG( "WORLD: Sent motd (SMSG_MESSAGECHAT)" ); - if(pCurrChar->GetGuildId() != 0) { Guild* guild = objmgr.GetGuildById(pCurrChar->GetGuildId()); @@ -315,7 +325,7 @@ data<<(uint8)GE_SIGNED_ON; data<<(uint8)1; data<GetName(); - data<<(uint8)0<<(uint8)0<<(uint8)0; + data<GetGUID(); guild->BroadcastPacket(&data); DEBUG_LOG( "WORLD: Sent guild-signed-on (SMSG_GUILD_EVENT)" ); } @@ -328,6 +338,8 @@ } } + // rest_start + // home bind stuff Field *fields; QueryResult *result7 = sDatabase.PQuery("SELECT COUNT(`guid`) FROM `character_homebind` WHERE `guid` = '%u'", GUID_LOPART(playerGuid)); @@ -371,15 +383,14 @@ } data.Initialize( SMSG_TUTORIAL_FLAGS, 8*32 ); - for (int i = 0; i < 8; i++) data << uint32( GetPlayer()->GetTutorialInt(i) ); - SendPacket(&data); //sLog.outDebug( "WORLD: Sent tutorial flags." ); GetPlayer()->SendInitialSpells(); GetPlayer()->SendInitialActionButtons(); + GetPlayer()->SendInitialReputations(); /*if(GetPlayer()->getClass() == CLASS_HUNTER || GetPlayer()->getClass() == CLASS_ROGUE) { @@ -399,20 +410,6 @@ } }*/ - GetPlayer()->SendInitialReputations(); - - GetPlayer()->UpdateHonor(); - - data.Initialize(SMSG_LOGIN_SETTIMESPEED, 8); - time_t gameTime = sWorld.GetGameTime(); - struct tm *lt = localtime(&gameTime); - uint32 xmitTime = (lt->tm_year - 100) << 24 | lt->tm_mon << 20 | - (lt->tm_mday - 1) << 14 | lt->tm_wday << 11 | - lt->tm_hour << 6 | lt->tm_min; - data << xmitTime; - data << (uint32)0x3C888889; //(float)0.017f; - SendPacket( &data ); - //Show cinematic at the first time that player login if( !GetPlayer()->getCinematic() ) { @@ -427,6 +424,22 @@ } } + pCurrChar->SendInitWorldStates(); + + pCurrChar->CastSpell(pCurrChar, 836, false); // LOGINEFFECT + + data.Initialize(SMSG_LOGIN_SETTIMESPEED, 8); + time_t gameTime = sWorld.GetGameTime(); + struct tm *lt = localtime(&gameTime); + uint32 xmitTime = (lt->tm_year - 100) << 24 | lt->tm_mon << 20 | + (lt->tm_mday - 1) << 14 | lt->tm_wday << 11 | + lt->tm_hour << 6 | lt->tm_min; + data << xmitTime; + data << (uint32)0x3C888889; //(float)0.017f; + SendPacket( &data ); + + GetPlayer()->UpdateHonorFields(); + QueryResult *result = sDatabase.PQuery("SELECT `guildid`,`rank` FROM `guild_member` WHERE `guid` = '%u'",pCurrChar->GetGUIDLow()); if(result) @@ -445,7 +458,7 @@ // this remained from raid group load (raid group load was moved to player code) if(pCurrChar->groupInfo.group) { - pCurrChar->groupInfo.group->SendInit(this); + //pCurrChar->groupInfo.group->SendInit(this); // useless pCurrChar->groupInfo.group->SendUpdate(); } @@ -490,40 +503,50 @@ data<getClass(); pCurrChar->BroadcastPacketToFriendListers(&data); - // setting new speed if dead - if ( pCurrChar->m_deathState == DEAD ) - { - pCurrChar->SetMovement(MOVE_WATER_WALK); - - if (pCurrChar->getRace() == RACE_NIGHTELF) - { - pCurrChar->SetSpeed(MOVE_RUN, 1.5f*1.2f, true); - pCurrChar->SetSpeed(MOVE_SWIM, 1.5f*1.2f, true); - } - else - { - pCurrChar->SetSpeed(MOVE_RUN, 1.5f, true); - pCurrChar->SetSpeed(MOVE_SWIM, 1.5f, true); - } - } - pCurrChar->LoadEnchant(); pCurrChar->_LoadSpellCooldowns(); - // Place charcter in world (and load zone) before some object loading + // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); + // setting Ghost+speed if dead + //if ( pCurrChar->m_deathState == DEAD ) + if ( pCurrChar->m_deathState != ALIVE ) + { + // not blizz like, we must correctly save and load player instead... + pCurrChar->CastSpell(pCurrChar, 20584, true, 0); // auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) + pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) + //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+41, 8326); + //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+42, 20584); + //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAFLAGS+6, 238); + //pCurrChar->SetUInt32Value(UNIT_FIELD_AURALEVELS+11, 514); + //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+11, 65535); + //pCurrChar->SetUInt32Value(UNIT_FIELD_DISPLAYID, 1825); + //if (pCurrChar->getRace() == RACE_NIGHTELF) + //{ + // pCurrChar->SetSpeed(MOVE_RUN, 1.5f*1.2f, true); + // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f*1.2f, true); + //} + //else + //{ + // pCurrChar->SetSpeed(MOVE_RUN, 1.5f, true); + // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f, true); + //} + pCurrChar->SetMovement(MOVE_WATER_WALK); + } + // Load pet if any and player is alive if(pCurrChar->isAlive()) pCurrChar->LoadPet(); - // show time before shutdown if shudown planned. + // show time before shutdown if shutdown planned. if(sWorld.IsShutdowning()) sWorld.ShutdownMsg(true,pCurrChar); if(pCurrChar->isGameMaster()) SendNotification("GM mode is ON"); m_playerLoading = false; + pCurrChar->SendAllowMove(); // may be add it to CMSG_SET_ACTIVE_MOVER handler? } void WorldSession::HandleSetFactionAtWar( WorldPacket & recv_data ) Index: src/game/WorldSession.cpp =================================================================== --- src/game/WorldSession.cpp (working copy) +++ src/game/WorldSession.cpp (working copy) @@ -36,6 +36,7 @@ #include "MapManager.h" #include "ObjectAccessor.h" #include "BattleGroundMgr.h" +#include "Language.h" // for CMSG_DISMOUNT handler /// Player state enum SessionStatus @@ -111,6 +112,12 @@ { packet = _recvQueue.next(); + /*#if 1 + sLog.outError( "MOEP: %s (0x%.4X)", + LookupName(packet->GetOpcode(), g_worldOpcodeNames), + packet->GetOpcode()); + #endif*/ + for (i = 0; table[i].handler != NULL; i++) { if (table[i].opcode == packet->GetOpcode()) @@ -238,6 +245,9 @@ _player->SaveToDB(); } + ///- Leave all channels before player delete... + _player->CleanupChannels(); + ///- Remove the player's pet from the world _player->RemovePet(NULL,PET_SAVE_AS_CURRENT); @@ -276,7 +286,7 @@ _player->groupInfo.group->SendUpdate(); ///- Broadcast a logout message to the player's friends - WorldPacket data(SMSG_FRIEND_STATUS, (9)); + WorldPacket data(SMSG_FRIEND_STATUS, 9); data<GetGUID(); _player->BroadcastPacketToFriendListers(&data); @@ -348,11 +358,6 @@ // new inspect stats { MSG_INSPECT_HONOR_STATS, STATUS_LOGGEDIN, &WorldSession::HandleInspectHonorStatsOpcode }, - // new - { CMSG_FORCE_MOVE_UNROOT_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveUnRootAck }, - { CMSG_FORCE_MOVE_ROOT_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveRootAck }, - { CMSG_MOVE_WATER_WALK_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveWaterWalkAck }, - // charater view { CMSG_TOGGLE_HELM, STATUS_LOGGEDIN, &WorldSession::HandleToggleHelmOpcode }, { CMSG_TOGGLE_CLOAK, STATUS_LOGGEDIN, &WorldSession::HandleToggleCloakOpcode }, @@ -360,18 +365,6 @@ // repair item { CMSG_REPAIR_ITEM, STATUS_LOGGEDIN, &WorldSession::HandleRepairItemOpcode }, - // movements - { CMSG_MOVE_KNOCK_BACK_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveKnockBackAck }, - { CMSG_MOVE_HOVER_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveHoverAck }, - { CMSG_SET_ACTIVE_MOVER, STATUS_LOGGEDIN, &WorldSession::HandleSetActiveMoverOpcode }, - { MSG_MOVE_TELEPORT_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveTeleportAck }, - { CMSG_FORCE_WALK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - { CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - { CMSG_FORCE_TURN_RATE_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - { CMSG_FORCE_RUN_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - { CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - { CMSG_FORCE_SWIM_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - { MSG_LOOKING_FOR_GROUP, STATUS_LOGGEDIN, &WorldSession::HandleLookingForGroup }, { CMSG_SET_FACTION_ATWAR, STATUS_LOGGEDIN, &WorldSession::HandleSetFactionAtWar }, { CMSG_SET_FACTION_CHEAT, STATUS_LOGGEDIN, &WorldSession::HandleSetFactionCheat }, @@ -397,16 +390,14 @@ { CMSG_CREATURE_QUERY, STATUS_LOGGEDIN, &WorldSession::HandleCreatureQueryOpcode }, { CMSG_GAMEOBJECT_QUERY, STATUS_LOGGEDIN, &WorldSession::HandleGameObjectQueryOpcode }, - { MSG_MOVE_WORLDPORT_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveWorldportAckOpcode }, - { MSG_MOVE_HEARTBEAT, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - { MSG_MOVE_JUMP, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + // movements { MSG_MOVE_START_FORWARD, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_START_BACKWARD, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - { MSG_MOVE_SET_FACING, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_STOP, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_START_STRAFE_LEFT, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_START_STRAFE_RIGHT, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_STOP_STRAFE, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + { MSG_MOVE_JUMP, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_START_TURN_LEFT, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_START_TURN_RIGHT, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_STOP_TURN, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, @@ -415,10 +406,30 @@ { MSG_MOVE_STOP_PITCH, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_SET_RUN_MODE, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_SET_WALK_MODE, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - { MSG_MOVE_SET_PITCH, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + { MSG_MOVE_TELEPORT_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveTeleportAck }, + { MSG_MOVE_FALL_LAND, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_START_SWIM, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { MSG_MOVE_STOP_SWIM, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - { MSG_MOVE_FALL_LAND, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + { MSG_MOVE_SET_FACING, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + { MSG_MOVE_SET_PITCH, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + { MSG_MOVE_WORLDPORT_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveWorldportAckOpcode }, + { CMSG_FORCE_RUN_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + { CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + { CMSG_FORCE_SWIM_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + { CMSG_FORCE_MOVE_ROOT_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveRootAck }, + { CMSG_FORCE_MOVE_UNROOT_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveUnRootAck }, + { MSG_MOVE_HEARTBEAT, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + { CMSG_MOVE_KNOCK_BACK_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveKnockBackAck }, + { CMSG_MOVE_HOVER_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveHoverAck }, + { CMSG_SET_ACTIVE_MOVER, STATUS_LOGGEDIN, &WorldSession::HandleSetActiveMoverOpcode }, + { CMSG_MOVE_FALL_RESET, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + { CMSG_MOVE_FEATHER_FALL_ACK, STATUS_LOGGEDIN, &WorldSession::HandleFeatherFallAck }, + { CMSG_MOVE_WATER_WALK_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveWaterWalkAck }, + { CMSG_FORCE_WALK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + { CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + { CMSG_FORCE_TURN_RATE_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + { CMSG_FORCE_FLY_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + { CMSG_MOUNTSPECIAL_ANIM, STATUS_LOGGEDIN, &WorldSession::HandleMountSpecialAnimOpcode }, { CMSG_GROUP_INVITE, STATUS_LOGGEDIN, &WorldSession::HandleGroupInviteOpcode }, @@ -437,7 +448,8 @@ { CMSG_GROUP_RAID_CONVERT, STATUS_LOGGEDIN, &WorldSession::HandleRaidConvertOpcode }, { MSG_RAID_READY_CHECK, STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckOpcode }, { CMSG_GROUP_CHANGE_SUB_GROUP, STATUS_LOGGEDIN, &WorldSession::HandleGroupChangeSubGroupOpcode }, - { CMSG_GROUP_ASSISTANT, STATUS_LOGGEDIN, &WorldSession::HandleAssistantOpcode }, + { CMSG_GROUP_ASSISTANT, STATUS_LOGGEDIN, &WorldSession::HandleGroupAssistantOpcode }, + { CMSG_GROUP_PROMOTE, STATUS_LOGGEDIN, &WorldSession::HandleGroupPromoteOpcode }, { CMSG_PETITION_SHOWLIST, STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowListOpcode }, { CMSG_PETITION_BUY, STATUS_LOGGEDIN, &WorldSession::HandlePetitionBuyOpcode }, @@ -448,7 +460,6 @@ { MSG_PETITION_DECLINE, STATUS_LOGGEDIN, &WorldSession::HandlePetitionDeclineOpcode }, { CMSG_OFFER_PETITION, STATUS_LOGGEDIN, &WorldSession::HandleOfferPetitionOpcode }, { CMSG_TURN_IN_PETITION, STATUS_LOGGEDIN, &WorldSession::HandleTurnInPetitionOpcode }, - { CMSG_MOVE_FALL_RESET, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, { CMSG_GUILD_QUERY, STATUS_AUTHED, &WorldSession::HandleGuildQueryOpcode }, { CMSG_GUILD_CREATE, STATUS_LOGGEDIN, &WorldSession::HandleGuildCreateOpcode }, @@ -489,7 +500,7 @@ { CMSG_SPIRIT_HEALER_ACTIVATE, STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode }, { CMSG_NPC_TEXT_QUERY, STATUS_LOGGEDIN, &WorldSession::HandleNpcTextQueryOpcode }, { CMSG_BINDER_ACTIVATE, STATUS_LOGGEDIN, &WorldSession::HandleBinderActivateOpcode }, - { MSG_LIST_STABLED_PETS , STATUS_LOGGEDIN, &WorldSession::HandleListStabledPetsOpcode }, + { MSG_LIST_STABLED_PETS, STATUS_LOGGEDIN, &WorldSession::HandleListStabledPetsOpcode }, { CMSG_DUEL_ACCEPTED, STATUS_LOGGEDIN, &WorldSession::HandleDuelAcceptedOpcode }, { CMSG_DUEL_CANCELLED, STATUS_LOGGEDIN, &WorldSession::HandleDuelCancelledOpcode }, @@ -625,8 +636,6 @@ //BattleGround - { CMSG_BATTLEFIELD_STATUS, STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldStatusOpcode }, - //{ CMSG_BATTLEMASTER_HELLO, STATUS_LOGGEDIN, &WorldSession::HandleBattleMasterHelloOpcode }, { CMSG_BATTLEMASTER_HELLO, STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundHelloOpcode }, { CMSG_BATTLEMASTER_JOIN, STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundJoinOpcode }, { MSG_BATTLEGROUND_PLAYER_POSITIONS,STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPositionsOpcode }, @@ -638,13 +647,48 @@ { CMSG_SET_ACTIONBAR_TOGGLES, STATUS_LOGGEDIN, &WorldSession::HandleSetActionBar }, { CMSG_FIELD_WATCHED_FACTION_SHOW_BAR, STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionIndexOpcode }, - { CMSG_LOOT_ROLL, STATUS_LOGGEDIN, &WorldSession::HandleLootRoll }, + { CMSG_LOOT_ROLL, STATUS_LOGGEDIN, &WorldSession::HandleLootRoll }, // WTF, why it 2 times there? { CMSG_WARDEN_DATA, STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode }, { CMSG_WORLD_TELEPORT, STATUS_LOGGEDIN, &WorldSession::HandleWorldTeleportOpcode }, { MSG_MINIMAP_PING, STATUS_LOGGEDIN, &WorldSession::HandleMinimapPingOpcode }, { MSG_RANDOM_ROLL, STATUS_LOGGEDIN, &WorldSession::HandleRandomRollOpcode }, { CMSG_FAR_SIGHT, STATUS_LOGGEDIN, &WorldSession::HandleFarSightOpcode }, + { MSG_LOOKING_FOR_GROUP, STATUS_LOGGEDIN, &WorldSession::HandleLookingForGroup }, + { CMSG_SET_LOOKING_FOR_GROUP, STATUS_LOGGEDIN, &WorldSession::HandleSetLfgOpcode }, + { MSG_SET_DUNGEON_DIFFICULTY, STATUS_LOGGEDIN, &WorldSession::HandleDungeonDifficultyOpcode }, + { CMSG_MOVE_FLY_MODE_CHANGE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleMoveFlyModeChangeAckOpcode }, + { CMSG_ARENA_TEAM_QUERY, STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamQueryOpcode }, + { MSG_MOVE_START_FLY_UP, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + { MSG_MOVE_STOP_FLY_UP, STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + { CMSG_LFG_SET_AUTOJOIN, STATUS_AUTHED, &WorldSession::HandleLfgAutoJoinOpcode }, + { CMSG_LFG_UNSET_AUTOJOIN, STATUS_LOGGEDIN, &WorldSession::HandleLfgCancelAutoJoinOpcode }, + { CMSG_LFM_SET_AUTOADD, STATUS_AUTHED, &WorldSession::HandleLfmAutoAddMembersOpcode }, + { CMSG_LFM_UNSET_AUTOADD, STATUS_LOGGEDIN, &WorldSession::HandleLfmCancelAutoAddmembersOpcode }, + { CMSG_LOOKING_FOR_GROUP_CLEAR, STATUS_LOGGEDIN, &WorldSession::HandleLfgClearOpcode }, + { CMSG_SET_LOOKING_FOR_NONE, STATUS_LOGGEDIN, &WorldSession::HandleLfmSetNoneOpcode }, + { CMSG_SET_LOOKING_FOR_MORE, STATUS_LOGGEDIN, &WorldSession::HandleLfmSetOpcode }, + { CMSG_SET_COMMENTARY, STATUS_LOGGEDIN, &WorldSession::HandleLfgSetCommentOpcode }, + { CMSG_CHOOSE_TITLE, STATUS_LOGGEDIN, &WorldSession::HandleChooseTitleOpcode }, + { MSG_INSPECT_ARENA_STATS, STATUS_LOGGEDIN, &WorldSession::HandleInspectArenaStatsOpcode }, + { CMSG_REALM_STATE_REQUEST, STATUS_AUTHED, &WorldSession::HandleRealmStateRequestOpcode }, + { CMSG_ALLOW_MOVE_ACK, STATUS_LOGGEDIN, &WorldSession::HandleAllowMoveAckOpcode }, + { CMSG_WHOIS, STATUS_LOGGEDIN, &WorldSession::HandleWhoisOpcode }, + { CMSG_RESET_INSTANCES, STATUS_LOGGEDIN, &WorldSession::HandleResetInstancesOpcode }, + { CMSG_ARENA_TEAM_ROSTER, STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRosterOpcode }, + { CMSG_ARENA_TEAM_ADD_MEMBER, STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamAddMemberOpcode }, + { CMSG_ARENA_TEAM_INVITE_ACCEPT, STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteAcceptOpcode }, + { CMSG_ARENA_TEAM_INVITE_DECLINE, STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteDeclineOpcode }, + { CMSG_ARENA_TEAM_LEAVE, STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaveOpcode }, + { CMSG_ARENA_TEAM_DISBAND, STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDisbandOpcode }, + { CMSG_AREA_SPIRIT_HEALER_QUERY, STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueryOpcode }, + { CMSG_MOVE_SHIP_909, STATUS_LOGGEDIN, &WorldSession::HandleMoveShipOpcode }, + { CMSG_MOVE_FLY_STATE_CHANGE, STATUS_LOGGEDIN, &WorldSession::HandleMoveFlyStateChangeOpcode }, + { CMSG_DISMOUNT, STATUS_LOGGEDIN, &WorldSession::HandleDismountOpcode }, + + // Socket gem + { CMSG_SOCKET_ITEM, STATUS_LOGGEDIN, &WorldSession::HandleSocketOpcode }, + { 0, 0, NULL } }; @@ -685,22 +729,315 @@ } } -// TODO: Make a warper for all this type of opcodes, and add this one to it -// because this is a relative universal opcode void WorldSession::SendAreaTriggerMessage(const char* Text, ...) { - va_list ap; // - char str [1024]; //1024 seems to be rather large - va_start(ap, Text); - vsnprintf(str,1024,Text, ap ); - va_end(ap); + uint32 lenght = strlen(Text)+1; + WorldPacket data(SMSG_AREA_TRIGGER_MESSAGE, 4+lenght); + data << lenght; + data << Text; + SendPacket(&data); +} - WorldPacket data; - data.Initialize(SMSG_AREA_TRIGGER_MESSAGE); - data << uint32(0); - data << str; - data << uint8(0); +void WorldSession::HandleDungeonDifficultyOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("MSG_SET_DUNGEON_DIFFICULTY"); + + uint32 difficulty; + recv_data >> difficulty; + + GetPlayer()->SetDungeonDifficulty(difficulty); + GetPlayer()->SendDungeonDifficulty(); +} + +void WorldSession::HandleChooseTitleOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_CHOOSE_TITLE"); + + uint32 title; + recv_data >> title; + + uint32 available = GetPlayer()->GetUInt32Value(PLAYER_FIELD_KNOWN_TITLES); + if(!(available & (1<SetUInt32Value(PLAYER_CHOSEN_TITLE, title); +/* +PLAYER_FIELD_KNOWN_TITLES: +1 << title# (0=none) +*/ +} + +void WorldSession::HandleNewUnknownOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("New Unknown Opcode %u", recv_data.GetOpcode()); + recv_data.hexlike(); +/* +New Unknown Opcode 837 +STORAGE_SIZE: 60 +02 00 00 00 00 00 00 00 | 00 00 00 00 01 20 00 00 +89 EB 33 01 71 5C 24 C4 | 15 03 35 45 74 47 8B 42 +BA B8 1B 40 00 00 00 00 | 00 00 00 00 77 66 42 BF +23 91 26 3F 00 00 60 41 | 00 00 00 00 + +New Unknown Opcode 837 +STORAGE_SIZE: 44 +02 00 00 00 00 00 00 00 | 00 00 00 00 00 00 80 00 +7B 80 34 01 84 EA 2B C4 | 5F A1 36 45 C9 39 1C 42 +BA B8 1B 40 CE 06 00 00 | 00 00 80 3F +*/ +} + +void WorldSession::HandleRealmStateRequestOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_REALM_STATE_REQUEST"); + + uint32 unk; + recv_data >> unk; + + WorldPacket data(SMSG_REALM_STATE_RESPONSE, 17); + data << unk; + data << uint32(0x00000000); // reamd split state... + // 0x0 realm normal + // 0x1 realm split + // 0x2 realm split pending + data << uint16(0x3130) << uint8(0x2F); + data << uint16(0x3130) << uint8(0x2F); + data << uint16(0x3130) << uint8(0x00); SendPacket(&data); + sLog.outDebug("response sent %u", unk); } +void WorldSession::HandleAllowMoveAckOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_ALLOW_MOVE_ACK"); + uint32 unk, time; + recv_data >> unk >> time; + sLog.outDebug("response sent %u %u", unk, time/1000); +} + +void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) +{ + sLog.outDebug("Received opcode CMSG_WHOIS"); + std::string charname, acc, email, lastip, msg; + WorldPacket data; + recv_data >> charname; + + if (GetSecurity() < 3) + { + SendNotification("You do not have permission to perform that function"); + return; + } + + if(charname.size()) + { + SendNotification("Please provide character name"); + return; + } + + uint32 accid; + Field *fields; + + Player *plr = objmgr.GetPlayer(charname.c_str()); + + if(plr) + accid = plr->GetSession()->GetAccountId(); + else + { + SendNotification("Player %s not found or offline", charname.c_str()); + return; + } + + if(!accid) + { + SendNotification("Account for character %s not found", charname.c_str()); + return; + } + + QueryResult *result = loginDatabase.PQuery("SELECT `username`,`email`,`last_ip` FROM `account` WHERE `id`=%u", accid); + if(result) + { + fields = result->Fetch(); + acc = fields[0].GetCppString(); + if(!acc.size()) + acc = "Unknown"; + email = fields[1].GetCppString(); + if(!email.size()) + email = "Unknown"; + lastip = fields[2].GetCppString(); + if(!lastip.size()) + lastip = "Unknown"; + msg = charname + "'s " + "account is " + acc + ", e-mail " + email + ", last ip: " + lastip; + data.Initialize(SMSG_WHOIS); + data << msg; + _player->GetSession()->SendPacket(&data); + } + else + SendNotification("Account for character %s not found", charname.c_str()); + + delete result; + sLog.outDebug("Received whois command from player %s for character %s", GetPlayer()->GetName(), charname.c_str()); +} + +void WorldSession::HandleResetInstancesOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: CMSG_RESET_INSTANCES"); +/* + WorldPacket data(SMSG_RESET_INSTANCES_RESULT, 4); // todo: find packet structure + _player->GetSession()->SendPacket(&data); +*/ +} + +void WorldSession::HandleMoveShipOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: CMSG_MOVE_SHIP_909"); + recv_data.hexlike(); +/* +WORLD: CMSG_MOVE_SHIP_909 +STORAGE_SIZE: 56 +01 02 80 00 7A 48 DF 00 | BA 8A 05 46 19 9D 7E 44 +42 10 BA 40 5C 90 77 40 | 74 B0 02 00 00 00 00 80 +42 D4 0B C0 65 FD 50 C1 | 42 10 BA 40 20 7F 13 40 +5E 49 DF 00 C0 00 00 00 + +WORLD: CMSG_MOVE_SHIP_909 +STORAGE_SIZE: 60 +01 02 80 04 F0 D6 E0 00 | 3A B2 CD 45 C3 5B 3F 44 +E4 4F B8 40 58 E7 4B 40 | 00 00 00 00 00 00 00 00 +3A B2 CD 45 C3 5B 3F 44 | E4 4F B8 40 58 E7 4B 40 +D4 D7 E0 00 CF 00 00 00 | E4 4F B8 40 +*/ +} + +void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY"); + recv_data.hexlike(); +} + +void WorldSession::HandleDismountOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: CMSG_DISMOUNT"); + recv_data.hexlike(); + + //If player is not mounted, so go out :) + if (!_player->IsMounted()) // not blizz like; no any messages on blizz + { + sChatHandler.SendSysMessage(this, LANG_CHAR_NON_MOUNTED); + return; + } + + if(_player->isInFlight()) // not blizz like; no any messages on blizz + { + sChatHandler.SendSysMessage(this, LANG_YOU_IN_FLIGHT); + return; + } + + _player->Unmount(); + _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); +} + +void WorldSession::HandleMoveFlyModeChangeAckOpcode( WorldPacket & recv_data ) +{ + // fly mode on/off + sLog.outDebug("WORLD: CMSG_MOVE_FLY_MODE_CHANGE_ACK"); + recv_data.hexlike(); + + uint64 guid; + uint32 unk; + uint32 flags; + + recv_data >> guid >> unk >> flags; + + // set field for checking if player able to flight + if((flags & MOVEMENTFLAG_CAN_FLY) != 0) // 0x800000 + _player->SetCanFly(true); + else + _player->SetCanFly(false); + +/* +on: +25 00 00 00 00 00 00 00 | 00 00 00 00 00 00 80 00 +85 4E A9 01 19 BA 7A C3 | 42 0D 70 44 44 B0 A8 42 +78 15 94 40 39 03 00 00 | 00 00 80 3F +off: +25 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 +10 FD A9 01 19 BA 7A C3 | 42 0D 70 44 44 B0 A8 42 +78 15 94 40 39 03 00 00 | 00 00 00 00 +*/ +} + +void WorldSession::HandleMoveFlyStateChangeOpcode( WorldPacket & recv_data ) +{ + /* + 00 08 A0 01 4C AE DC 01 | F8 18 56 45 03 97 BD 44 + A2 8D 33 43 1C B3 29 40 | 00 00 00 00 45 00 00 00 + 00 00 80 3F + + 01 20 80 00 5F D3 DC 01 | 8B B3 55 45 4C 77 BD 44 + F 65 33 43 DC AB 53 40 | 00 00 00 00 00 00 00 00 + 96 7D 7C BF 54 F9 28 BE | 00 00 60 41 00 00 00 00 + */ + + // fly state: start flying/landing + sLog.outDebug("WORLD: CMSG_MOVE_FLY_STATE_CHANGE"); + recv_data.hexlike(); + CHECK_PACKET_SIZE(recv_data,4+4+4+4+4+4); + + /* extract packet */ + uint32 flags, time, fallTime; + float x, y, z, orientation; + + uint32 t_GUIDl, t_GUIDh; + float t_x, t_y, t_z, t_o; + float s_angle; + float j_unk1, j_sinAngle, j_cosAngle, j_xyspeed; + float f_speed; + + recv_data >> flags >> time; + recv_data >> x >> y >> z >> orientation; + + // set field that determine if player flying or walking on terrain (able to flight) + if(flags & MOVEMENTFLAG_FLYING) // 0x1000000 + _player->SetFlying(true); + else + _player->SetFlying(false); + + if (flags & MOVEMENTFLAG_ONTRANSPORT) // and if opcode 909? + { + // recheck + CHECK_PACKET_SIZE(recv_data,recv_data.rpos()+4+4+4+4+4+4); + + recv_data >> t_GUIDl >> t_GUIDh; + recv_data >> t_x >> t_y >> t_z >> t_o; + } + if (flags & MOVEMENTFLAG_SWIMMING) + { + // recheck + CHECK_PACKET_SIZE(recv_data,recv_data.rpos()+4); + + recv_data >> s_angle; // kind of angle, -1.55=looking down, 0=looking straight forward, +1.55=looking up + } + + // recheck + CHECK_PACKET_SIZE(recv_data,recv_data.rpos()+4); + + recv_data >> fallTime; // duration of last jump (when in jump duration from jump begin to now) + + if ( (flags & MOVEMENTFLAG_JUMPING) || (flags & MOVEMENTFLAG_FALLING) ) + { + // recheck + CHECK_PACKET_SIZE(recv_data,recv_data.rpos()+4+4+4+4); + + recv_data >> j_unk1; // constant, but different when jumping in water and on land? + recv_data >> j_sinAngle >> j_cosAngle; // sin + cos of angle between orientation0 and players orientation + recv_data >> j_xyspeed; // speed of xy movement + } + + // recheck + CHECK_PACKET_SIZE(recv_data,recv_data.rpos()+4); + + recv_data >> f_speed; // this is difference from standart movement opcodes... + sLog.outDebug("f_speed %f", f_speed); + /*----------------*/ +} Index: src/game/Player.cpp =================================================================== --- src/game/Player.cpp (working copy) +++ src/game/Player.cpp (working copy) @@ -45,12 +45,13 @@ #include "Util.h" #include "Transports.h" #include "Weather.h" +#include "BattleGround.h" #include #define DEFAULT_SWITCH_WEAPON 1500 -typedef struct +typedef struct FriendStr { uint64 PlayerGUID; unsigned char Status; @@ -64,9 +65,9 @@ UpdateMask Player::updateVisualBits; -Player::Player (WorldSession *session): Unit( NULL ) +Player::Player (WorldSession *session): Unit( 0 ) { - m_transport = NULL; + m_transport = 0; m_transX = 0.0f; m_transY = 0.0f; m_transZ = 0.0f; @@ -107,19 +108,18 @@ memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT); - groupInfo.group = NULL; - groupInfo.invite = NULL; + groupInfo.group = 0; + groupInfo.invite = 0; - duel = NULL; + duel = 0; m_GuildIdInvited = 0; + m_dungeonDifficulty = DUNGEONDIFFICULTY_NORMAL; + m_dontMove = false; - m_total_honor_points = 0; - - pTrader = NULL; - + pTrader = 0; ClearTrade(); m_cinematic = 0; @@ -129,9 +129,9 @@ for ( int aX = 0 ; aX < 8 ; aX++ ) m_Tutorials[ aX ] = 0x00; - ItemsSetEff[0]=NULL; - ItemsSetEff[1]=NULL; - ItemsSetEff[2]=NULL; + ItemsSetEff[0]=0; + ItemsSetEff[1]=0; + ItemsSetEff[2]=0; m_regenTimer = 0; m_weaponChangeTimer = 0; m_breathTimer = 0; @@ -269,7 +269,7 @@ // Taxi nodes setup memset(m_taximask, 0, sizeof(m_taximask)); - +/* // Automatically add the race's taxi hub to the character's taximask at creation time ( 1 << (taxi_node_id-1) ) ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(race); if(!rEntry) @@ -279,6 +279,21 @@ } m_taximask[0] = rEntry->startingTaxiMask; +*/ + + switch(race) + { + case 1: m_taximask[0]= 1 << ( 2-1); break; // Human + case 2: m_taximask[0]= 1 << (23-1); break; // Orc + case 3: m_taximask[0]= 1 << ( 6-1); break; // Dwarf + case 4: m_taximask[0]= (1 << (26-1)) | (1 << (27-1)); break; // Night Elf + case 5: m_taximask[0]= 1 << (11-1); break; // Undead + case 6: m_taximask[0]= 1 << (22-1); break; // Tauren + case 7: m_taximask[0]= 1 << ( 6-1); break; // Gnome + case 8: m_taximask[0]= 1 << (23-1); break; // Troll + //case 10: m_taximask[0]= 1 << (1-1); break; // Blood Elf + //case 11: m_taximask[0]= 1 << (1-1); break; // Draenei + } ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(class_); if(!cEntry) @@ -291,11 +306,11 @@ uint32 unitfield; if(powertype == POWER_RAGE) - unitfield = 0x1100EE00; + unitfield = 0x00110000; else if(powertype == POWER_ENERGY) unitfield = 0x00000000; else if(powertype == POWER_MANA) - unitfield = 0x0000EE00; + unitfield = 0x00000000; else { sLog.outError("Invalid default powertype %u for player (class %u)",powertype,class_); @@ -305,34 +320,49 @@ SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 0.388999998569489f ); SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f ); - SetUInt32Value(UNIT_FIELD_DISPLAYID, info->displayId + gender ); - SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, info->displayId + gender ); + switch(gender) + { + case GENDER_FEMALE: + SetUInt32Value(UNIT_FIELD_DISPLAYID, info->displayId_f ); + SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, info->displayId_f ); + break; + case GENDER_MALE: + SetUInt32Value(UNIT_FIELD_DISPLAYID, info->displayId_m ); + SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, info->displayId_m ); + break; + default: + break; + } setFactionForRace(m_race); SetUInt32Value(UNIT_FIELD_BYTES_0, ( ( race ) | ( class_ << 8 ) | ( gender << 16 ) | ( powertype << 24 ) ) ); SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield ); - SetUInt32Value(UNIT_FIELD_BYTES_2, 0xEEEEEE00 ); - SetUInt32Value(UNIT_FIELD_FLAGS , UNIT_FLAG_NONE | UNIT_FLAG_UNKNOWN1 ); + SetUInt32Value(UNIT_FIELD_BYTES_2, ( 0x28 << 8 ) ); // players - 0x2800, 0x2801, units - 0x1001 + SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN1 ); - SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO); + //SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO); // wrong... //-1 is default value SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); - SetUInt32Value(PLAYER_BYTES, ((skin) | (face << 8) | (hairStyle << 16) | (hairColor << 24))); - SetUInt32Value(PLAYER_BYTES_2, (facialHair | (0xEE << 8) | (0x00 << 16) | (0x02 << 24))); + SetUInt32Value(PLAYER_BYTES, (skin | (face << 8) | (hairStyle << 16) | (hairColor << 24))); + SetUInt32Value(PLAYER_BYTES_2, (facialHair | (0x00 << 8) | (0x00 << 16) | (0x02 << 24))); SetUInt32Value(PLAYER_BYTES_3, gender); - SetUInt32Value(PLAYER_FIELD_BYTES, 0xEEE00000 ); + //SetUInt32Value(PLAYER_FIELD_BYTES, 0xEEE00000 ); - /* - SetUInt32Value(PLAYER_GUILDID, 0); - SetUInt32Value(PLAYER_GUILDRANK, 0); - SetUInt32Value(PLAYER_GUILD_TIMESTAMP, 0); + SetUInt32Value( PLAYER_GUILDID, 0 ); + SetUInt32Value( PLAYER_GUILDRANK, 0 ); + SetUInt32Value( PLAYER_GUILD_TIMESTAMP, 0 ); - SetUInt32Value(PLAYER_FIELD_HONOR_RANK, 0); - SetUInt32Value(PLAYER_FIELD_HONOR_HIGHEST_RANK, 0); SetUInt32Value(PLAYER_FIELD_TODAY_KILLS, 0); SetUInt32Value(PLAYER_FIELD_YESTERDAY_HONORABLE_KILLS, 0); SetUInt32Value(PLAYER_FIELD_LAST_WEEK_HONORABLE_KILLS, 0); SetUInt32Value(PLAYER_FIELD_THIS_WEEK_HONORABLE_KILLS, 0); SetUInt32Value(PLAYER_FIELD_THIS_WEEK_HONOR, 0); SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0); SetUInt32Value(PLAYER_FIELD_LIFETIME_DISHONORABLE_KILLS, 0); SetUInt32Value(PLAYER_FIELD_YESTERDAY_HONOR, 0); SetUInt32Value(PLAYER_FIELD_LAST_WEEK_HONOR, 0); SetUInt32Value(PLAYER_FIELD_LAST_WEEK_STANDING, 0); SetUInt32Value(PLAYER_FIELD_LIFETIME_HONOR, 0); SetUInt32Value(PLAYER_FIELD_SESSION_KILLS, 0); - */ + SetUInt32Value( PLAYER_FIELD_KNOWN_TITLES, 0 ); // 0=disabled + SetUInt32Value( PLAYER_CHOSEN_TITLE, 0 ); + SetUInt32Value( PLAYER_FIELD_KILLS, 0 ); + SetUInt32Value( PLAYER_FIELD_KILLS_LIFETIME, 0 ); + SetUInt32Value( PLAYER_FIELD_HONOR_TODAY, 0 ); + SetUInt32Value( PLAYER_FIELD_HONOR_YESTERDAY, 0 ); + SetUInt32Value( PLAYER_FIELD_MAX_LEVEL, 70 ); + // Played time m_Last_tick = time(NULL); m_Played_time[0] = 0; @@ -392,10 +422,6 @@ action_itr[i]++; } - m_rating = 0; - m_highest_rank = 0; - m_standing = 0; - UpdateBlockPercentage(); uint16 dest; @@ -481,8 +507,8 @@ data << MaxValue; data << MaxValue; data << BreathRegen; - data << (uint32)0; - data << (uint8)0; + data << (uint8)0; + data << (uint32)0; // spell id GetSession()->SendPacket(&data); } @@ -496,8 +522,8 @@ data << CurrentValue; data << MaxValue; data << Regen; - data << (uint32)0; data << (uint8)0; + data << (uint32)0; // spell id GetSession()->SendPacket( &data ); } @@ -1038,7 +1064,7 @@ *p_data << (uint8)0; } } - // EQUIPMENT_SLOT_END always 0,0 + // EQUIPMENT_SLOT_END always 0,0 <-- WRONG: should be bag! *p_data << (uint32)0; *p_data << (uint8)0; } @@ -1205,9 +1231,64 @@ void Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, bool outofrange, bool ignore_transport, bool is_gm_command) { - // prepering unsommon pet if lost (we must get pet before teleportation or will not find it later) + // preparing unsummon pet if lost (we must get pet before teleportation or will not find it later) Pet* pet = GetPet(); + MapEntry const* mEntry = sMapStore.LookupEntry(mapid); + + if(!mEntry) + return; // this map not exist in client + + QueryResult *result = loginDatabase.PQuery("SELECT `tbc` FROM `account` WHERE `id`='%u'", GetSession()->GetAccountId()); + + if(!result) + return; // unknown client or error + + Field *fields = result->Fetch(); + + uint32 not_tbc_map = 0x10; // if any problems, then check 0x80000 also... + // with 0x80000 we can teleport to Kharazan with normal client + // with 0x10 we can't teleport to Kharazan with normal client + uint8 tbc = fields[0].GetUInt8(); + delete result; + + if(tbc == 0 && (mEntry->map_flag & not_tbc_map) == 0) // normal client and TBC map + { + sLog.outDebug("Player %s using Normal client and tried teleport to non existing map %u", GetName(), mapid); + + if(GetTransport()) + RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :) + + // send error message + WorldPacket data(SMSG_TRANSFER_ABORTED, 4+2); + data << mapid; + data << uint16(0x0106); // unk, probably error message id, now it's "You must have The Burning Crusade expansion installed to access this area.", look for other messages in GlobalStrings.lua (TRANSFER_ABORT_*). + GetSession()->SendPacket(&data); + + return; // normal client can't teleport to this map... + } + else if(tbc == 1) // can teleport to any existing map + { + sLog.outDebug("Player %s have TBC client and will teleported to map %u", GetName(), mapid); + } + else + { + sLog.outDebug("Player %s have normal client and will teleported to standard map %u", GetName(), mapid); + } +/* +only TBC (no 0x80000 and 0x10 flags...) +3604590=0x37006E=0x200000 + 0x100000 + 0x40000 + 0x20000 + 0x10000 + 0x40 + 0x20 + 0x8 + 0x4 + 0x2 + +Kharazan (normal/TBC??), but not have 0x10 flag (accessible by normal client?) +4128878=0x3F006E=0x200000 + 0x100000 + 0x80000 + 0x40000 + 0x20000 + 0x10000 + 0x40 + 0x20 + 0x8 + 0x4 + 0x2 + +normal+TBC maps +4128894=0x3F007E=0x200000 + 0x100000 + 0x80000 + 0x40000 + 0x20000 + 0x10000 + 0x40 + 0x20 + 0x10 + 0x8 + 0x4 + 0x2 + +normal+TBC maps +8323198=0x7F007E=0x400000 + 0x200000 + 0x100000 + 0x80000 + 0x40000 + 0x20000 + 0x10000 + 0x40 + 0x20 + 0x10 + 0x8 + 0x4 + 0x2 +*/ + // preper zone change detect uint32 old_zone = GetZoneId(); @@ -1293,7 +1374,6 @@ Corpse* corpse = GetCorpse(); if (corpse && corpse->GetType() == CORPSE_RESURRECTABLE && corpse->GetMapId() == mapid) { - MapEntry const* mEntry = sMapStore.LookupEntry(mapid); if( mEntry && (mEntry->map_type == MAP_INSTANCE || mEntry->map_type == MAP_RAID) ) { ResurrectPlayer(); @@ -1306,6 +1386,7 @@ //SaveToDB(); // Client reset some data at NEW_WORLD teleport, resending its to client. + SendInitWorldStates(); SendInitialSpells(); SendInitialActionButtons(); @@ -1595,8 +1676,8 @@ if(m_form == FORM_TRAVEL || m_form == FORM_GHOSTWOLF) RemoveAurasDueToSpell(m_ShapeShiftForm); - // remove mounts - if(IsMounted()) + // remove mounts, check flight mounts also (flying=swimming in air :D) + if(IsMounted() && !IsFlying()) RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); } else @@ -1940,10 +2021,24 @@ data << uint16(itr->first); data << uint16(itr->second->slotId); } - data << uint16(0); + uint16 spellCooldowns = m_spellCooldowns.size(); + data << spellCooldowns; + for(SpellCooldowns::const_iterator itr=m_spellCooldowns.begin(); itr!=m_spellCooldowns.end(); itr++) + { + data << uint16(itr->first); + data << uint32(0); // unk not everytime 0 - WPAssert(data.size() == 5+(4*size_t(spellCount))); + time_t curTime = time(NULL); + if(itr->second <= curTime) + data << uint32(0); // expired + else + data << uint32((itr->second-curTime)*1000); + //data << uint32(itr->second); // always cooldown (in ms?) + data << uint32(0); // seems to be some flags (0x80000000 when cooldown locked) + } + WPAssert(data.size() == 1+2+(4*spellCount)+2+(14*spellCooldowns)); // correct? + GetSession()->SendPacket(&data); sLog.outDetail( "CHARACTER: Sent Initial Spells" ); @@ -2260,13 +2355,12 @@ WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8+4)); data << uint32(itr->first); data << GetGUID(); - data << uint32(0); + //data << uint32(0); GetSession()->SendPacket(&data); } m_spellCooldowns.clear(); } } - void Player::_LoadSpellCooldowns() { m_spellCooldowns.clear(); @@ -2277,9 +2371,6 @@ { time_t curTime = time(NULL); - WorldPacket data(SMSG_SPELL_COOLDOWN, (8+result->GetRowCount()*8)); - data << GetGUID(); - do { Field *fields = result->Fetch(); @@ -2297,9 +2388,6 @@ if(db_time <= curTime) continue; - data << uint32(spell_id); - data << uint32(uint32(db_time-curTime)*1000); // in m.secs - AddSpellCooldown(spell_id,db_time); sLog.outDebug("Player (GUID: %u) spell %u cooldown loaded (%u secs).",GetGUIDLow(),spell_id,uint32(db_time-curTime)); @@ -2307,9 +2395,6 @@ while( result->NextRow() ); delete result; - - if(m_spellCooldowns.size() > 0) - GetSession()->SendPacket(&data); } if(!m_spellCooldowns.empty()) @@ -2594,8 +2679,7 @@ for(uint16 i = UNIT_FIELD_AURA; i < UNIT_FIELD_AURASTATE; i ++) updateVisualBits.SetBit(i); updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME); - // TODO CHECK THIS - //updateVisualBits.SetBit(UNIT_FIELD_OFFHANDATTACKTIME); not exsisting in 1.12 + updateVisualBits.SetBit(UNIT_FIELD_OFFHANDATTACKTIME); updateVisualBits.SetBit(UNIT_FIELD_RANGEDATTACKTIME); updateVisualBits.SetBit(UNIT_FIELD_BOUNDINGRADIUS); updateVisualBits.SetBit(UNIT_FIELD_COMBATREACH); @@ -2607,6 +2691,8 @@ updateVisualBits.SetBit(UNIT_FIELD_PETNUMBER); updateVisualBits.SetBit(UNIT_FIELD_PET_NAME_TIMESTAMP); updateVisualBits.SetBit(UNIT_DYNAMIC_FLAGS); + updateVisualBits.SetBit(UNIT_MOD_CAST_SPEED); // ? + updateVisualBits.SetBit(UNIT_FIELD_BYTES_2); // ? updateVisualBits.SetBit(PLAYER_FLAGS); updateVisualBits.SetBit(PLAYER_BYTES); @@ -2619,6 +2705,10 @@ updateVisualBits.SetBit(PLAYER_DUEL_ARBITER); updateVisualBits.SetBit(PLAYER_DUEL_ARBITER+1); + // PLAYER_QUEST_LOG_x also visible bit on official... + for(uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_LAST_2; i+=3) + updateVisualBits.SetBit(i); + for(uint16 i = 0; i < INVENTORY_SLOT_BAG_END; i++) { updateVisualBits.SetBit((uint16)(PLAYER_FIELD_INV_SLOT_HEAD + i*2)); @@ -2628,17 +2718,17 @@ //431) = 884 (0x374) = main weapon for(uint16 i = 0; i < EQUIPMENT_SLOT_END; i++) { - uint16 visual_base = PLAYER_VISIBLE_ITEM_1_0 + (i*12); + uint16 visual_base = PLAYER_VISIBLE_ITEM_1_0 + (i*16); // item entry updateVisualBits.SetBit(visual_base + 0); // item enchantment IDs - for(uint8 j = 0; j < 7; ++j) + for(uint8 j = 0; j < 11; ++j) updateVisualBits.SetBit(visual_base +1 + j); // random properties - updateVisualBits.SetBit((uint16)(PLAYER_VISIBLE_ITEM_1_PROPERTIES + (i*12))); + updateVisualBits.SetBit((uint16)(PLAYER_VISIBLE_ITEM_1_PROPERTIES + (i*16))); } updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY); @@ -2755,7 +2845,8 @@ if( skill != SKILL_HERBALISM && skill != SKILL_MINING && skill != SKILL_LEATHERWORKING && skill != SKILL_BLACKSMITHING && skill != SKILL_ALCHEMY && skill != SKILL_ENCHANTING - && skill != SKILL_TAILORING && skill != SKILL_ENGINERING && skill != SKILL_SKINNING) + && skill != SKILL_TAILORING && skill != SKILL_ENGINERING && skill != SKILL_SKINNING + && skill != SKILL_JEWELCRAFTING) return true; for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) @@ -2769,7 +2860,8 @@ uint32 pskill = pSpellInfo->EffectMiscValue[1]; if( pskill != SKILL_HERBALISM && pskill != SKILL_MINING && pskill != SKILL_LEATHERWORKING && pskill != SKILL_BLACKSMITHING && pskill != SKILL_ALCHEMY && pskill != SKILL_ENCHANTING - && pskill != SKILL_TAILORING && pskill != SKILL_ENGINERING && pskill != SKILL_SKINNING) + && pskill != SKILL_TAILORING && pskill != SKILL_ENGINERING && pskill != SKILL_SKINNING + && pskill != SKILL_JEWELCRAFTING) continue; // not check prof count for not first prof. spells (when skill already known) @@ -2854,26 +2946,30 @@ { case MOVE_ROOT: { - data.Initialize(SMSG_FORCE_MOVE_ROOT, GetPackGUID().size()); + data.Initialize(SMSG_FORCE_MOVE_ROOT, GetPackGUID().size()+4); data.append(GetPackGUID()); + data << uint32(0); GetSession()->SendPacket( &data ); }break; case MOVE_UNROOT: { - data.Initialize(SMSG_FORCE_MOVE_UNROOT, GetPackGUID().size()); + data.Initialize(SMSG_FORCE_MOVE_UNROOT, GetPackGUID().size()+4); data.append(GetPackGUID()); + data << uint32(0); GetSession()->SendPacket( &data ); }break; case MOVE_WATER_WALK: { - data.Initialize(SMSG_MOVE_WATER_WALK, GetPackGUID().size()); + data.Initialize(SMSG_MOVE_WATER_WALK, GetPackGUID().size()+4); data.append(GetPackGUID()); + data << uint32(0); GetSession()->SendPacket( &data ); }break; case MOVE_LAND_WALK: { - data.Initialize(SMSG_MOVE_LAND_WALK, GetPackGUID().size()); + data.Initialize(SMSG_MOVE_LAND_WALK, GetPackGUID().size()+4); data.append(GetPackGUID()); + data << uint32(0); GetSession()->SendPacket( &data ); }break; default:break; @@ -2882,6 +2978,13 @@ void Player::BuildPlayerRepop() { + CastSpell(this, 20584, true); // auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) + // there must be SMSG.FORCE_RUN_SPEED_CHANGE, SMSG.FORCE_SWIM_SPEED_CHANGE, SMSG.MOVE_WATER_WALK + + CastSpell(this, 8326, true); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) + // there must be SMSG.STOP_MIRROR_TIMER + // there we must send 888 opcode + // place corpse instead player body Corpse* corpse = GetCorpse(); if(!corpse) @@ -2902,7 +3005,7 @@ SetMovement(MOVE_UNROOT); // setting new speed - if (getRace() == RACE_NIGHTELF) + /*if (getRace() == RACE_NIGHTELF) { SetSpeed(MOVE_RUN, 1.5f*1.2f, true); SetSpeed(MOVE_SWIM, 1.5f*1.2f, true); @@ -2911,7 +3014,7 @@ { SetSpeed(MOVE_RUN, 1.5f, true); SetSpeed(MOVE_SWIM, 1.5f, true); - } + }*/ //! corpse reclaim delay 30 * 1000ms WorldPacket data(SMSG_CORPSE_RECLAIM_DELAY, 4); @@ -2922,53 +3025,34 @@ if(corpse) corpse->ResetGhostTime(); - //TODO: Check/research this - data.Initialize(SMSG_SPELL_START, (GetPackGUID().size()*2 + 12)); - data.append(GetPackGUID()); //9 - data.append(GetPackGUID()); //9 - //<< uint16(8326); //2 - data << uint32(20305); //2 - data << uint16(2); - data << uint32(0) << uint16(0); //6 + data.Initialize(SMSG_UPDATE_AURA_DURATION, 5); // last check 2.0.10 + data << uint8(0x28) << uint32(0); GetSession()->SendPacket( &data ); - data.Initialize(SMSG_SPELL_GO, (GetPackGUID().size()*2 + 23)); - data.append(GetPackGUID()); - data.append(GetPackGUID()); - data << uint16(8326); - /// uint8(0x0D) = probably race + 2 - data << uint16(0) << uint8(0x0D) << uint8(0x01)<< uint8(0x01) << GetGUID(); - data << uint32(0) << uint16(0x0200) << uint16(0); - GetSession()->SendPacket( &data ); - - data.Initialize(SMSG_UPDATE_AURA_DURATION, 5); - data << uint32(0x20) << uint8(0); - GetSession()->SendPacket( &data ); - StopMirrorTimer(FATIGUE_TIMER); //disable timers(bars) StopMirrorTimer(BREATH_TIMER); StopMirrorTimer(FIRE_TIMER); - SetUInt32Value(UNIT_FIELD_AURA + 32, 8326); // set ghost form - SetUInt32Value(UNIT_FIELD_AURA + 33, 0x5068 ); //!dono + //SetUInt32Value(UNIT_FIELD_AURA + 32, 8326); // set ghost form + //SetUInt32Value(UNIT_FIELD_AURA + 33, 20584); //!dono - SetUInt32Value(UNIT_FIELD_AURAFLAGS + 4, 0xEE); + //SetUInt32Value(UNIT_FIELD_AURAFLAGS + 4, 0xEE); - SetUInt32Value(UNIT_FIELD_AURASTATE, 0x02); + //SetUInt32Value(UNIT_FIELD_AURASTATE, 0x02); SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS,(float)1.0); //see radius of death player? SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_ALWAYS_STAND); - if (getRace() == RACE_NIGHTELF) - SetUInt32Value(UNIT_FIELD_DISPLAYID, 10045); //10045 correct wisp model + //if (getRace() == RACE_NIGHTELF) + // SetUInt32Value(UNIT_FIELD_DISPLAYID, 10045); //10045 - wrong wisp model // set initial flags + set ghost + restore pvp - SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NONE | UNIT_FLAG_UNKNOWN1 | (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP)?UNIT_FLAG_PVP:0) ); + //SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NONE | UNIT_FLAG_UNKNOWN1 | (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP)?UNIT_FLAG_PVP:0) ); // reserve some flags + ad ghost flag - uint32 old_safe_flags = GetUInt32Value(PLAYER_FLAGS) & ( PLAYER_FLAGS_IN_PVP | PLAYER_FLAGS_HIDE_CLOAK | PLAYER_FLAGS_HIDE_HELM ); - SetUInt32Value(PLAYER_FLAGS, old_safe_flags | PLAYER_FLAGS_GHOST ); + //uint32 old_safe_flags = GetUInt32Value(PLAYER_FLAGS) & ( PLAYER_FLAGS_IN_PVP | PLAYER_FLAGS_HIDE_CLOAK | PLAYER_FLAGS_HIDE_HELM ); + //SetUInt32Value(PLAYER_FLAGS, old_safe_flags | PLAYER_FLAGS_GHOST ); } void Player::SendDelayResponse(const uint32 ml_seconds) @@ -2980,34 +3064,45 @@ void Player::ResurrectPlayer() { + WorldPacket data(SMSG_SH_POSITION, 4*4); // remove spirit healer position + data << uint32(-1); + data << uint32(0); + data << uint32(0); + data << uint32(0); + GetSession()->SendPacket(&data); + + // speed change, land walk + // remove death flag + set aura - RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); + //RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_ALL); + RemoveAurasDueToSpell(8326); // SPELL_AURA_GHOST + RemoveAurasDueToSpell(20584); // speed bonuses setDeathState(ALIVE); SetMovement(MOVE_LAND_WALK); SetMovement(MOVE_UNROOT); - SetSpeed(MOVE_RUN, 1.0f, true); - SetSpeed(MOVE_SWIM, 1.0f, true); + //SetSpeed(MOVE_RUN, 1.0f, true); + //SetSpeed(MOVE_SWIM, 1.0f, true); - SetUInt32Value(CONTAINER_FIELD_SLOT_1+29, 0); + //SetUInt32Value(CONTAINER_FIELD_SLOT_1+29, 0); - SetUInt32Value(UNIT_FIELD_AURA+32, 0); - SetUInt32Value(UNIT_FIELD_AURALEVELS+8, 0xeeeeeeee); - SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+8, 0xeeeeeeee); - SetUInt32Value(UNIT_FIELD_AURAFLAGS+4, 0); - SetUInt32Value(UNIT_FIELD_AURASTATE, 0); + //SetUInt32Value(UNIT_FIELD_AURA+32, 0); + //SetUInt32Value(UNIT_FIELD_AURALEVELS+8, 0xeeeeeeee); + //SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+8, 0xeeeeeeee); + //SetUInt32Value(UNIT_FIELD_AURAFLAGS+4, 0); + //SetUInt32Value(UNIT_FIELD_AURASTATE, 0); - if(getRace() == RACE_NIGHTELF) - { - DeMorph(); - } + //if(getRace() == RACE_NIGHTELF) + //{ + // DeMorph(); + //} m_deathTimer = 0; - // set resurection sickness if not expired + // set resurrection sickness if not expired if(!m_resurrectingSicknessExpire) return; @@ -3019,7 +3114,7 @@ return; } - // set resurection sickness! + // set resurrection sickness! uint32 delta = m_resurrectingSicknessExpire-time(NULL); SpellEntry const *spellInfo = sSpellStore.LookupEntry( SPELL_PASSIVE_RESURRECTION_SICKNESS ); @@ -3221,6 +3316,15 @@ TeleportTo(ClosestGrave->map_id, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, GetOrientation()); + if(isDead()) // not send if alive, because it used in TeleportTo() + { + WorldPacket data(SMSG_SH_POSITION, 4*4); // show spirit healer position on minimap + data << ClosestGrave->map_id; + data << ClosestGrave->x; + data << ClosestGrave->y; + data << ClosestGrave->z; + GetSession()->SendPacket(&data); + } if(Corpse* corpse = GetCorpse()) corpse->UpdateForPlayer(this,true); } @@ -3240,7 +3344,8 @@ { list::iterator i; for(i = m_channels.begin(); i != m_channels.end(); i++) - (*i)->Leave(this,false); + (*i)->Leave(GetGUID(),false,0); + sLog.outDebug("Player: channels cleaned up!"); } void Player::BroadcastPacketToFriendListers(WorldPacket *packet) @@ -3543,7 +3648,7 @@ || pskill == SKILL_FIRST_AID || pskill == SKILL_COOKING || pskill == SKILL_LEATHERWORKING || pskill == SKILL_BLACKSMITHING || pskill == SKILL_ALCHEMY || pskill == SKILL_ENCHANTING || pskill == SKILL_TAILORING || pskill == SKILL_ENGINERING || pskill == SKILL_SKINNING - || pskill == SKILL_RIDING) + || pskill == SKILL_RIDING || pskill == SKILL_JEWELCRAFTING) continue; uint32 data = GetUInt32Value(PLAYER_SKILL(i)+1); uint32 max = data>>16; @@ -3567,7 +3672,7 @@ || pskill == SKILL_FIRST_AID || pskill == SKILL_COOKING || pskill == SKILL_LEATHERWORKING || pskill == SKILL_BLACKSMITHING || pskill == SKILL_ALCHEMY || pskill == SKILL_ENCHANTING || pskill == SKILL_TAILORING || pskill == SKILL_ENGINERING || pskill == SKILL_SKINNING - || pskill == SKILL_RIDING) + || pskill == SKILL_RIDING || pskill == SKILL_JEWELCRAFTING) continue; uint32 data = GetUInt32Value(PLAYER_SKILL(i)+1); @@ -3942,19 +4047,35 @@ { if(faction->Flags & 0x00000001 ) //If faction is visible then update it { - WorldPacket data(SMSG_SET_FACTION_STANDING, (12)); - data << (uint32) faction->Flags; + WorldPacket data(SMSG_SET_FACTION_STANDING, (12)); // last check 2.0.10 + //data << (uint32) faction->Flags; + data << (uint32) 1; data << (uint32) faction->ReputationListID; data << (uint32) faction->Standing; GetSession()->SendPacket(&data); } + /* + Packet SMSG.SET_FACTION_STANDING (292), len: 54 + 0000: 24 01 06 00 00 00 13 00 00 00 8f 21 00 00 0b 00 : $..........!.... + 0010: 00 00 91 0c 00 00 31 00 00 00 91 0c 00 00 14 00 : ......1......... + 0020: 00 00 22 12 00 00 15 00 00 00 67 45 00 00 12 00 : ..".......gE.... + 0030: 00 00 a4 0c 00 00 -- -- -- -- -- -- -- -- -- -- : ...... + */ + //changed in 2.0.x: + /*uint32 count; + for (uint32 i = 0; i < count; i++) + { + uint32 ReputationListID; + uint32 Standing; + } + */ } void Player::SendInitialReputations() { - WorldPacket data(SMSG_INITIALIZE_FACTIONS, (4+64*5)); - data << uint32 (0x00000040); - for(uint32 a=0; a<64; a++) + WorldPacket data(SMSG_INITIALIZE_FACTIONS, (4+128*5)); + data << uint32 (0x00000080); + for(uint32 a=0; a<128; a++) { FactionsList::iterator itr = FindReputationListIdInFactionList(a); @@ -4000,6 +4121,29 @@ return m_factions.end(); } +void Player::SendSetFactionVisible(const Faction* faction) const +{ +/* + // this code must be use at Gossip/NPC handler + // we must check if faction already visible/in list? + uint32 faction = unit->getFactionTemplateEntry()->faction; + for(FactionsList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) + { + if(itr->ID == faction) + { + //if(!_player->FactionIsInTheList(itr->ReputationListID) + SendSetFactionVisible(&*itr); + break; + } + } +*/ + // make faction visible in reputation list, on blizz it use when talking with NPC of new faction + // we must check if faction already visible? + WorldPacket data(SMSG_SET_FACTION_VISIBLE, 4); + data << faction->ReputationListID; + GetSession()->SendPacket(&data); +} + void Player::SetInitialFactions() { Faction newFaction; @@ -4365,14 +4509,36 @@ else // in friendly area { if(IsPvP() && !HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_IN_PVP) && pvpInfo.endTimer == 0) - pvpInfo.endTimer = time(NULL); // start toggle-off + pvpInfo.endTimer = time(0); // start toggle-off } - if(zone->zone_type == 312) // in city + // zonetype is flags + // flags & 0x00000001 (1) - snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring) + // flags & 0x00000002 (2) - unknown, (only Naxxramas and Razorfen Downs) + // flags & 0x00000004 (4) - On Map Dungeon + // flags & 0x00000008 (8) - slave capital city flag? + // flags & 0x00000010 (16) - unknown + // flags & 0x00000020 (32) - slave capital city flag? + // flags & 0x00000040 (64) - many zones have this flag + // flags & 0x00000080 (128) - arena + // flags & 0x00000100 (256) - main capital city flag + // flags & 0x00000200 (512) - only for one area named "City" (where it located?) + // flags & 0x00000400 (1024) - outland zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag) + // flags & 0x00000800 (2048) - sanctuary area (PvP disabled) + // flags & 0x00001000 (4096) - only Netherwing Ledge, Socrethar's Seat, Tempest Keep, The Arcatraz, The Botanica, The Mechanar + // flags & 0x00002000 (8192) - not used now (no area/zones with this flag set) ... + // flags & 0x00004000 (16384) - outland zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag) + // flags & 0x00008000 (32768) - pvp objective area? + + if((zone->flags & 0x800) != 0) // in sanctuary { + UpdatePvP(false, true); // i'm right? need disable PvP in this area... + } + else if((zone->flags & 0x100) != 0) // in capital city + { SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); SetRestType(2); - InnEnter(time(NULL),0,0,0); + InnEnter(time(0),0,0,0); } else // anywhere else { @@ -4441,14 +4607,20 @@ } // cool-down duel spell - data.Initialize(SMSG_SPELL_COOLDOWN, 12); + /*data.Initialize(SMSG_SPELL_COOLDOWN, 17); + + data<SendPacket(&data); - data.Initialize(SMSG_SPELL_COOLDOWN, 12); + data.Initialize(SMSG_SPELL_COOLDOWN, 17); + data<opponent->GetGUID(); + data<opponent->GetGUID(); - duel->opponent->GetSession()->SendPacket(&data); + data<opponent->GetSession()->SendPacket(&data);*/ //Remove Duel Flag object GameObject* obj = ObjectAccessor::Instance().GetGameObject(*this, GetUInt64Value(PLAYER_DUEL_ARBITER)); @@ -4483,9 +4655,9 @@ duel->opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 0); delete duel->opponent->duel; - duel->opponent->duel = NULL; + duel->opponent->duel = 0; delete duel; - duel = NULL; + duel = 0; } //---------------------------------------------------------// @@ -4562,7 +4734,7 @@ if(proto->Spells[i].SpellId) RemoveAurasDueToSpell(proto->Spells[i].SpellId ); - for(int enchant_slot = 0 ; enchant_slot < 7; enchant_slot++) + for(int enchant_slot = 0 ; enchant_slot < 11; enchant_slot++) { uint32 Enchant_id = item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+enchant_slot*3); if(Enchant_id) @@ -4814,19 +4986,22 @@ } // item combat enchantments - for(int e_slot = 0; e_slot < 7; e_slot++) + for(int e_slot = 0; e_slot < 11; e_slot++) { uint32 enchant_id = item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+e_slot*3); SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); if(!pEnchant) continue; - uint32 enchant_display = pEnchant->display_type; - float chance = pEnchant->value1 != 0 ? float(pEnchant->value1) : GetWeaponProcChance(); - uint32 enchant_spell_id = pEnchant->spellid; - SpellEntry const *enchantSpell_info = sSpellStore.LookupEntry(enchant_spell_id); - if(!enchantSpell_info) continue; - if(enchant_display!=4 && enchant_display!=2 && IsItemSpellToCombat(enchantSpell_info)) - if (roll_chance_f(chance)) - this->CastSpell(Target, enchantSpell_info->Id, true); + for (int s=0;s<3;s++) + { + uint32 enchant_display = pEnchant->display_type[s]; + float chance = pEnchant->amount[s] != 0 ? float(pEnchant->amount[s]) : GetWeaponProcChance(); + uint32 enchant_spell_id = pEnchant->spellid[s]; + SpellEntry const *enchantSpell_info = sSpellStore.LookupEntry(enchant_spell_id); + if(!enchantSpell_info) continue; + if(enchant_display!=4 && enchant_display!=2 && IsItemSpellToCombat(enchantSpell_info)) + if (roll_chance_f(chance)) + this->CastSpell(Target, enchantSpell_info->Id, true); + } } } @@ -4911,7 +5086,7 @@ RemoveAurasDueToSpell(proto->Spells[m].SpellId ); } - for(int enchant_slot = 0 ; enchant_slot < 7; ++enchant_slot) + for(int enchant_slot = 0 ; enchant_slot < 11; ++enchant_slot) { uint32 Enchant_id = m_items[i]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+enchant_slot*3); if(Enchant_id) @@ -5027,7 +5202,7 @@ CastItemEquipSpell(m_items[i]); - for(int enchant_slot = 0 ; enchant_slot < 7; enchant_slot++) + for(int enchant_slot = 0 ; enchant_slot < 11; enchant_slot++) { uint32 Enchant_id = m_items[i]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+enchant_slot*3); if(Enchant_id) @@ -5069,7 +5244,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) { - Loot *loot = NULL; + Loot *loot = 0; PermissionTypes permission = ALL_PERMISSION; sLog.outDebug("Player::SendLoot"); @@ -5239,7 +5414,7 @@ m_lootGuid = guid; - QuestItemList *q_list = NULL; + QuestItemList *q_list = 0; if (permission != NONE_PERMISSION) { QuestItemMap::iterator itr = loot->PlayerQuestItems.find(this); @@ -5279,268 +5454,297 @@ GetSession()->SendPacket( &data ); } -void Player::SendUpdateWordState(uint16 Field, uint16 Value) +void Player::SendUpdateWorldState(uint32 Field, uint32 Value) { - WorldPacket data(SMSG_UPDATE_WORLD_STATE, 8); //0x2D4 - data << uint32(Field); - data << uint32(Value); - GetSession()->SendPacket(&data); + WorldPacket data(SMSG_UPDATE_WORLD_STATE, 8); + data << Field; + data << Value; + SendMessageToSet(&data, true); + //GetSession()->SendPacket(&data); } -void Player::SendInitWorldStates(uint32 MapID) +void Player::SendInitWorldStates() { - // TODO Figure out the unknown data. - - if ((MapID == 0) || (MapID == 1)) + // data depends on zoneid/mapid... + uint16 NumberOfFields = 0; + uint32 mapid = GetMapId(); + uint32 zoneid = GetZoneId(); + sLog.outDebug("Sending SMSG_INIT_WORLD_STATES to Map:%u, Zone: %u", mapid, zoneid); + // may be exist better way to do this... + switch(zoneid) { - sLog.outDebug("Sending SMSG_INIT_WORLD_STATES to Map:%u",MapID); - - uint16 NumberOfFields = 108; - //0x2C5 - WorldPacket data(SMSG_INIT_WORLD_STATES, (4+2+NumberOfFields)); - data << - (uint32)MapID << - (uint16)NumberOfFields << - //field (uint16) value (uint16) - (uint16)0x07AE<< (uint16)0x01<< - (uint16)0x0532<< (uint16)0x01<< - (uint16)0x0531<< (uint16)0x00<< - (uint16)0x052E<< (uint16)0x00<< - (uint16)0x06F9<< (uint16)0x00<< - (uint16)0x06F3<< (uint16)0x00<< - (uint16)0x06F1<< (uint16)0x00<< - (uint16)0x06EE<< (uint16)0x00<< - (uint16)0x06ED<< (uint16)0x00<< - (uint16)0x0571<< (uint16)0x00<< - (uint16)0x0570<< (uint16)0x00<< - (uint16)0x0567<< (uint16)0x01<< - (uint16)0x0566<< (uint16)0x01<< - (uint16)0x0550<< (uint16)0x01<< - (uint16)0x0544<< (uint16)0x00<< - (uint16)0x0536<< (uint16)0x00<< - (uint16)0x0535<< (uint16)0x01<< - (uint16)0x03C6<< (uint16)0x00<< - (uint16)0x03C4<< (uint16)0x00<< - (uint16)0x03C2<< (uint16)0x00<< - (uint16)0x07A8<< (uint16)0x00<< - (uint16)0x07A3<< (uint16)0x270F<< - (uint16)0x0574<< (uint16)0x00<< - (uint16)0x0573<< (uint16)0x00<< - (uint16)0x0572<< (uint16)0x00<< - (uint16)0x056F<< (uint16)0x00<< - (uint16)0x056E<< (uint16)0x00<< - (uint16)0x056D<< (uint16)0x00<< - (uint16)0x056C<< (uint16)0x00<< - (uint16)0x056B<< (uint16)0x00<< - (uint16)0x056A<< (uint16)0x01<< - (uint16)0x0569<< (uint16)0x01<< - (uint16)0x0568<< (uint16)0x01<< - (uint16)0x0565<< (uint16)0x00<< - (uint16)0x0564<< (uint16)0x00<< - (uint16)0x0563<< (uint16)0x00<< - (uint16)0x0562<< (uint16)0x00<< - (uint16)0x0561<< (uint16)0x00<< - (uint16)0x0560<< (uint16)0x00<< - (uint16)0x055F<< (uint16)0x00<< - (uint16)0x055E<< (uint16)0x00<< - (uint16)0x055D<< (uint16)0x00<< - (uint16)0x055C<< (uint16)0x00<< - (uint16)0x055B<< (uint16)0x00<< - (uint16)0x055A<< (uint16)0x00<< - (uint16)0x0559<< (uint16)0x00<< - (uint16)0x0558<< (uint16)0x00<< - (uint16)0x0557<< (uint16)0x00<< - (uint16)0x0556<< (uint16)0x00<< - (uint16)0x0555<< (uint16)0x00<< - (uint16)0x0554<< (uint16)0x01<< - (uint16)0x0553<< (uint16)0x01<< - (uint16)0x0552<< (uint16)0x01<< - (uint16)0x0551<< (uint16)0x01<< - (uint16)0x054F<< (uint16)0x00<< - (uint16)0x054E<< (uint16)0x00<< - (uint16)0x054D<< (uint16)0x01<< - (uint16)0x054C<< (uint16)0x00<< - (uint16)0x054B<< (uint16)0x00<< - (uint16)0x0545<< (uint16)0x00<< - (uint16)0x0543<< (uint16)0x01<< - (uint16)0x0542<< (uint16)0x00<< - (uint16)0x0540<< (uint16)0x00<< - (uint16)0x053F<< (uint16)0x00<< - (uint16)0x053E<< (uint16)0x00<< - (uint16)0x053D<< (uint16)0x00<< - (uint16)0x053C<< (uint16)0x00<< - (uint16)0x053B<< (uint16)0x00<< - (uint16)0x053A<< (uint16)0x01<< - (uint16)0x0539<< (uint16)0x00<< - (uint16)0x0538<< (uint16)0x00<< - (uint16)0x0537<< (uint16)0x00<< - (uint16)0x0534<< (uint16)0x00<< - (uint16)0x0533<< (uint16)0x00<< - (uint16)0x0530<< (uint16)0x00<< - (uint16)0x052F<< (uint16)0x00<< - (uint16)0x052D<< (uint16)0x01<< - (uint16)0x0516<< (uint16)0x01<< - (uint16)0x0515<< (uint16)0x00<< - (uint16)0x03B6<< (uint16)0x00<< - (uint16)0x0745<< (uint16)0x02<< - (uint16)0x0736<< (uint16)0x01<< - (uint16)0x0735<< (uint16)0x01<< - (uint16)0x0734<< (uint16)0x01<< - (uint16)0x0733<< (uint16)0x01<< - (uint16)0x0732<< (uint16)0x01<< - (uint16)0x0702<< (uint16)0x00<< - (uint16)0x0701<< (uint16)0x00<< - (uint16)0x0700<< (uint16)0x00<< - (uint16)0x06FE<< (uint16)0x00<< - (uint16)0x06FD<< (uint16)0x00<< - (uint16)0x06FC<< (uint16)0x00<< - (uint16)0x06FB<< (uint16)0x00<< - (uint16)0x06F8<< (uint16)0x00<< - (uint16)0x06F7<< (uint16)0x00<< - (uint16)0x06F6<< (uint16)0x00<< - (uint16)0x06F4<< (uint16)0x7D0<< - (uint16)0x06F2<< (uint16)0x00<< - (uint16)0x06F0<< (uint16)0x00<< - (uint16)0x06EF<< (uint16)0x00<< - (uint16)0x06EC<< (uint16)0x00<< - (uint16)0x06EA<< (uint16)0x00<< - (uint16)0x06E9<< (uint16)0x00<< - (uint16)0x06E8<< (uint16)0x00<< - (uint16)0x06E7<< (uint16)0x00<< - (uint16)0x0518<< (uint16)0x00<< - (uint16)0x0517<< (uint16)0x00<< - (uint16)0x0703<< (uint16)0x00; - GetSession()->SendPacket(&data); + case 0: + case 1: + case 4: + case 8: + case 10: + case 11: + case 12: + case 36: + case 38: + case 40: + case 41: + case 51: + case 267: + case 1519: + case 1537: + case 2257: + case 2918: + NumberOfFields = 6; + break; + case 2597: + NumberOfFields = 81; + break; + case 3277: + NumberOfFields = 14; + break; + case 3358: + NumberOfFields = 38; + break; + case 3483: + NumberOfFields = 22; + break; + case 3519: + NumberOfFields = 36; + break; + case 3521: + NumberOfFields = 35; + break; + case 3703: + NumberOfFields = 9; + break; + default: + NumberOfFields = 10; + break; } - //BattleGround currently only map 489 - else if (MapID == 489) // && and guid is in a current Battlefield) + WorldPacket data(SMSG_INIT_WORLD_STATES, (4+4+2+(NumberOfFields*8))); + data << mapid; // mapid + data << zoneid; // zone id + data << NumberOfFields; // count of uint64 blocks + data << uint32(0x8d8) << uint32(0x0); // 1 + data << uint32(0x8d7) << uint32(0x0); // 2 + data << uint32(0x8d6) << uint32(0x0); // 3 + data << uint32(0x8d5) << uint32(0x0); // 4 + data << uint32(0x8d4) << uint32(0x0); // 5 + data << uint32(0x8d3) << uint32(0x0); // 6 + if(mapid == 530) // Outland { - sLog.outDebug("Sending SMSG_INIT_WORLD_STATES to Map:%u",MapID); - - uint16 NumberOfFields = 114; - WorldPacket data(SMSG_INIT_WORLD_STATES, (4+2+NumberOfFields)); - data << - - (uint32)MapID<< - (uint16)NumberOfFields << - //field (uint16) value (uint16) - (uint16)0x07AE<< (uint16)0x01<< - (uint16)0x0532<< (uint16)0x01<< - (uint16)0x0531<< (uint16)0x00<< - (uint16)0x052E<< (uint16)0x00<< - (uint16)0x06F9<< (uint16)0x00<< - (uint16)0x06F3<< (uint16)0x00<< - (uint16)0x06F1<< (uint16)0x00<< - (uint16)0x06EE<< (uint16)0x00<< - (uint16)0x06ED<< (uint16)0x00<< - (uint16)0x0571<< (uint16)0x00<< - (uint16)0x0570<< (uint16)0x00<< - (uint16)0x0567<< (uint16)0x01<< - (uint16)0x0566<< (uint16)0x01<< - (uint16)0x0550<< (uint16)0x01<< - (uint16)0x0544<< (uint16)0x00<< - (uint16)0x0536<< (uint16)0x00<< - (uint16)0x0535<< (uint16)0x01<< - (uint16)0x03C6<< (uint16)0x00<< - (uint16)0x03C4<< (uint16)0x00<< - (uint16)0x03C2<< (uint16)0x00<< - (uint16)0x07A8<< (uint16)0x00<< - (uint16)0x07A3<< (uint16)0x270F << - (uint16)0x060B<< (uint16)0x02<< - (uint16)0x0574<< (uint16)0x00<< - (uint16)0x0573<< (uint16)0x00<< - (uint16)0x0572<< (uint16)0x00<< - (uint16)0x056F<< (uint16)0x00<< - (uint16)0x056E<< (uint16)0x00<< - (uint16)0x056D<< (uint16)0x00<< - (uint16)0x056C<< (uint16)0x00<< - (uint16)0x056B<< (uint16)0x00<< - (uint16)0x056A<< (uint16)0x01<< - (uint16)0x0569<< (uint16)0x01<< - (uint16)0x0568<< (uint16)0x01<< - (uint16)0x0565<< (uint16)0x00<< - (uint16)0x0564<< (uint16)0x00<< - (uint16)0x0563<< (uint16)0x00<< - (uint16)0x0562<< (uint16)0x00<< - (uint16)0x0561<< (uint16)0x00<< - (uint16)0x0560<< (uint16)0x00<< - (uint16)0x055F<< (uint16)0x00<< - (uint16)0x055E<< (uint16)0x00<< - (uint16)0x055D<< (uint16)0x00<< - (uint16)0x055C<< (uint16)0x00<< - (uint16)0x055B<< (uint16)0x00<< - (uint16)0x055A<< (uint16)0x00<< - (uint16)0x0559<< (uint16)0x00<< - (uint16)0x0558<< (uint16)0x00<< - (uint16)0x0557<< (uint16)0x00<< - (uint16)0x0556<< (uint16)0x00<< - (uint16)0x0555<< (uint16)0x00<< - (uint16)0x0554<< (uint16)0x01<< - (uint16)0x0553<< (uint16)0x01<< - (uint16)0x0552<< (uint16)0x01<< - (uint16)0x0551<< (uint16)0x01<< - (uint16)0x054F<< (uint16)0x00<< - (uint16)0x054E<< (uint16)0x00<< - (uint16)0x054D<< (uint16)0x01<< - (uint16)0x054C<< (uint16)0x00<< - (uint16)0x054B<< (uint16)0x00<< - (uint16)0x0545<< (uint16)0x00<< - (uint16)0x0543<< (uint16)0x01<< - (uint16)0x0542<< (uint16)0x00<< - (uint16)0x0540<< (uint16)0x00<< - (uint16)0x053F<< (uint16)0x00<< - (uint16)0x053E<< (uint16)0x00<< - (uint16)0x053D<< (uint16)0x00<< - (uint16)0x053C<< (uint16)0x00<< - (uint16)0x053B<< (uint16)0x00<< - (uint16)0x053A<< (uint16)0x01<< - (uint16)0x0539<< (uint16)0x00<< - (uint16)0x0538<< (uint16)0x00<< - (uint16)0x0537<< (uint16)0x00<< - (uint16)0x0534<< (uint16)0x00<< - (uint16)0x0533<< (uint16)0x00<< - (uint16)0x0530<< (uint16)0x00<< - (uint16)0x052F<< (uint16)0x00<< - (uint16)0x052D<< (uint16)0x01<< - (uint16)0x0516<< (uint16)0x01<< - (uint16)0x0515<< (uint16)0x00<< - (uint16)0x03B6<< (uint16)0x00<< - (uint16)0x0745<< (uint16)0x02<< - (uint16)0x0736<< (uint16)0x01<< - (uint16)0x0735<< (uint16)0x01<< - (uint16)0x0734<< (uint16)0x01<< - (uint16)0x0733<< (uint16)0x01<< - (uint16)0x0732<< (uint16)0x01<< - (uint16)0x0702<< (uint16)0x00<< - (uint16)0x0701<< (uint16)0x00<< - (uint16)0x0700<< (uint16)0x00<< - (uint16)0x06FE<< (uint16)0x00<< - (uint16)0x06FD<< (uint16)0x00<< - (uint16)0x06FC<< (uint16)0x00<< - (uint16)0x06FB<< (uint16)0x00<< - (uint16)0x06F8<< (uint16)0x00<< - (uint16)0x06F7<< (uint16)0x00<< - (uint16)0x06F6<< (uint16)0x00<< - (uint16)0x06F4<< (uint16)0x07D0 << - (uint16)0x06F2<< (uint16)0x00<< - (uint16)0x06F0<< (uint16)0x00<< - (uint16)0x06EF<< (uint16)0x00<< - (uint16)0x06EC<< (uint16)0x00<< - (uint16)0x06EA<< (uint16)0x00<< - (uint16)0x06E9<< (uint16)0x00<< - (uint16)0x06E8<< (uint16)0x00<< - (uint16)0x06E7<< (uint16)0x00<< - (uint16)0x0641<< (uint16)0x03<< - (uint16)0x062E<< (uint16)0x00<< - (uint16)0x062D<< (uint16)0x00<< - (uint16)0x060A<< (uint16)0x00<< - (uint16)0x0609<< (uint16)0x00<< - (uint16)0x0518<< (uint16)0x00<< - (uint16)0x0517<< (uint16)0x00<< - (uint16)0x0703<< (uint16)0x00; - GetSession()->SendPacket(&data); + data << uint32(0x9bf) << uint32(0x0); // 7 + data << uint32(0x9bd) << uint32(0xF); // 8 + data << uint32(0x9bb) << uint32(0xF); // 9 } + switch(zoneid) + { + case 1: + case 11: + case 12: + case 38: + case 40: + case 51: + case 1519: + case 1537: + case 2257: + break; + case 2597: // AV + data << uint32(0x7ae) << uint32(0x1); // 7 + data << uint32(0x532) << uint32(0x1); // 8 + data << uint32(0x531) << uint32(0x0); // 9 + data << uint32(0x52e) << uint32(0x0); // 10 + data << uint32(0x571) << uint32(0x0); // 11 + data << uint32(0x570) << uint32(0x0); // 12 + data << uint32(0x567) << uint32(0x1); // 13 + data << uint32(0x566) << uint32(0x1); // 14 + data << uint32(0x550) << uint32(0x1); // 15 + data << uint32(0x544) << uint32(0x0); // 16 + data << uint32(0x536) << uint32(0x0); // 17 + data << uint32(0x535) << uint32(0x1); // 18 + data << uint32(0x518) << uint32(0x0); // 19 + data << uint32(0x517) << uint32(0x0); // 20 + data << uint32(0x574) << uint32(0x0); // 21 + data << uint32(0x573) << uint32(0x0); // 22 + data << uint32(0x572) << uint32(0x0); // 23 + data << uint32(0x56f) << uint32(0x0); // 24 + data << uint32(0x56e) << uint32(0x0); // 25 + data << uint32(0x56d) << uint32(0x0); // 26 + data << uint32(0x56c) << uint32(0x0); // 27 + data << uint32(0x56b) << uint32(0x0); // 28 + data << uint32(0x56a) << uint32(0x1); // 29 + data << uint32(0x569) << uint32(0x1); // 30 + data << uint32(0x568) << uint32(0x1); // 13 + data << uint32(0x565) << uint32(0x0); // 32 + data << uint32(0x564) << uint32(0x0); // 33 + data << uint32(0x563) << uint32(0x0); // 34 + data << uint32(0x562) << uint32(0x0); // 35 + data << uint32(0x561) << uint32(0x0); // 36 + data << uint32(0x560) << uint32(0x0); // 37 + data << uint32(0x55f) << uint32(0x0); // 38 + data << uint32(0x55e) << uint32(0x0); // 39 + data << uint32(0x55d) << uint32(0x0); // 40 + data << uint32(0x3c6) << uint32(0x4); // 41 + data << uint32(0x3c4) << uint32(0x6); // 42 + data << uint32(0x3c2) << uint32(0x4); // 43 + data << uint32(0x516) << uint32(0x1); // 44 + data << uint32(0x515) << uint32(0x0); // 45 + data << uint32(0x3b6) << uint32(0x6); // 46 + data << uint32(0x55c) << uint32(0x0); // 47 + data << uint32(0x55b) << uint32(0x0); // 48 + data << uint32(0x55a) << uint32(0x0); // 49 + data << uint32(0x559) << uint32(0x0); // 50 + data << uint32(0x558) << uint32(0x0); // 51 + data << uint32(0x557) << uint32(0x0); // 52 + data << uint32(0x556) << uint32(0x0); // 53 + data << uint32(0x555) << uint32(0x0); // 54 + data << uint32(0x554) << uint32(0x1); // 55 + data << uint32(0x553) << uint32(0x1); // 56 + data << uint32(0x552) << uint32(0x1); // 57 + data << uint32(0x551) << uint32(0x1); // 58 + data << uint32(0x54f) << uint32(0x0); // 59 + data << uint32(0x54e) << uint32(0x0); // 60 + data << uint32(0x54d) << uint32(0x1); // 61 + data << uint32(0x54c) << uint32(0x0); // 62 + data << uint32(0x54b) << uint32(0x0); // 63 + data << uint32(0x545) << uint32(0x0); // 64 + data << uint32(0x543) << uint32(0x1); // 65 + data << uint32(0x542) << uint32(0x0); // 66 + data << uint32(0x540) << uint32(0x0); // 67 + data << uint32(0x53f) << uint32(0x0); // 68 + data << uint32(0x53e) << uint32(0x0); // 69 + data << uint32(0x53d) << uint32(0x0); // 70 + data << uint32(0x53c) << uint32(0x0); // 71 + data << uint32(0x53b) << uint32(0x0); // 72 + data << uint32(0x53a) << uint32(0x1); // 73 + data << uint32(0x539) << uint32(0x0); // 74 + data << uint32(0x538) << uint32(0x0); // 75 + data << uint32(0x537) << uint32(0x0); // 76 + data << uint32(0x534) << uint32(0x0); // 77 + data << uint32(0x533) << uint32(0x0); // 78 + data << uint32(0x530) << uint32(0x0); // 79 + data << uint32(0x52f) << uint32(0x0); // 80 + data << uint32(0x52d) << uint32(0x1); // 81 + case 3277: // WSG + data << uint32(0x62d) << uint32(0x0); // 7 1581 alliance flag captures + data << uint32(0x62e) << uint32(0x0); // 8 1582 horde flag captures + data << uint32(0x609) << uint32(0x0); // 9 1545 unk, set to 1 on alliance flag pickup... + data << uint32(0x60a) << uint32(0x0); // 10 1546 unk, set to 1 on horde flag pickup, after drop it's -1 + data << uint32(0x60b) << uint32(0x2); // 11 1547 unk + data << uint32(0x641) << uint32(0x3); // 12 1601 unk (max flag captures?) + data << uint32(0x922) << uint32(0x1); // 13 2338 horde (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing) + data << uint32(0x923) << uint32(0x1); // 14 2339 alliance (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing) + break; + case 3358: // AB + data << uint32(0x6e7) << uint32(0x0); // 7 1767 stables alliance + data << uint32(0x6e8) << uint32(0x0); // 8 1768 stables horde + data << uint32(0x6e9) << uint32(0x0); // 9 1769 unk, ST? + data << uint32(0x6ea) << uint32(0x0); // 10 1770 stables (show/hide) + data << uint32(0x6ec) << uint32(0x0); // 11 1772 farm (0 - horde controlled, 1 - alliance controlled) + data << uint32(0x6ed) << uint32(0x0); // 12 1773 farm (show/hide) + data << uint32(0x6ee) << uint32(0x0); // 13 1774 farm color + data << uint32(0x6ef) << uint32(0x0); // 14 1775 gold mine color, may be FM? + data << uint32(0x6f0) << uint32(0x0); // 15 1776 alliance resources + data << uint32(0x6f1) << uint32(0x0); // 16 1777 horde resources + data << uint32(0x6f2) << uint32(0x0); // 17 1778 horde bases + data << uint32(0x6f3) << uint32(0x0); // 18 1779 alliance bases + data << uint32(0x6f4) << uint32(0x7d0); // 19 1780 max resources (2000) + data << uint32(0x6f6) << uint32(0x0); // 20 1782 blacksmith color + data << uint32(0x6f7) << uint32(0x0); // 21 1783 blacksmith (show/hide) + data << uint32(0x6f8) << uint32(0x0); // 22 1784 unk, bs? + data << uint32(0x6f9) << uint32(0x0); // 23 1785 unk, bs? + data << uint32(0x6fb) << uint32(0x0); // 24 1787 gold mine (0 - horde contr, 1 - alliance contr) + data << uint32(0x6fc) << uint32(0x0); // 25 1788 gold mine (0 - conflict, 1 - horde) + data << uint32(0x6fd) << uint32(0x0); // 26 1789 gold mine (1 - show/0 - hide) + data << uint32(0x6fe) << uint32(0x0); // 27 1790 gold mine color + data << uint32(0x700) << uint32(0x0); // 28 1792 gold mine color, wtf?, may be LM? + data << uint32(0x701) << uint32(0x0); // 29 1793 lumber mill color (0 - conflict, 1 - horde contr) + data << uint32(0x702) << uint32(0x0); // 30 1794 lumber mill (show/hide) + data << uint32(0x703) << uint32(0x0); // 31 1795 lumber mill color color + data << uint32(0x732) << uint32(0x1); // 32 1842 stables (1 - uncontrolled) + data << uint32(0x733) << uint32(0x1); // 33 1843 gold mine (1 - uncontrolled) + data << uint32(0x734) << uint32(0x1); // 34 1844 lumber mill (1 - uncontrolled) + data << uint32(0x735) << uint32(0x1); // 35 1845 farm (1 - uncontrolled) + data << uint32(0x736) << uint32(0x1); // 36 1846 blacksmith (1 - uncontrolled) + data << uint32(0x745) << uint32(0x2); // 37 1861 unk + data << uint32(0x7a3) << uint32(0x708); // 38 1955 warning limit (1800) + break; + case 3483: // Hellfire Peninsula + data << uint32(0x9ba) << uint32(0x1); // 10 + data << uint32(0x9b9) << uint32(0x1); // 11 + data << uint32(0x9b5) << uint32(0x0); // 12 + data << uint32(0x9b4) << uint32(0x1); // 13 + data << uint32(0x9b3) << uint32(0x0); // 14 + data << uint32(0x9b2) << uint32(0x0); // 15 + data << uint32(0x9b1) << uint32(0x1); // 16 + data << uint32(0x9b0) << uint32(0x0); // 17 + data << uint32(0x9ae) << uint32(0x3); // 18 + data << uint32(0x9ac) << uint32(0x0); // 19 + data << uint32(0x9a8) << uint32(0x0); // 20 + data << uint32(0x9a7) << uint32(0x0); // 21 + data << uint32(0x9a6) << uint32(0x1); // 22 + case 3519: // Terokkar Forest + data << uint32(0xa41) << uint32(0x0); // 10 + data << uint32(0xa40) << uint32(0x14); // 11 + data << uint32(0xa3f) << uint32(0x0); // 12 + data << uint32(0xa3e) << uint32(0x0); // 13 + data << uint32(0xa3d) << uint32(0x5); // 14 + data << uint32(0xa3c) << uint32(0x0); // 15 + data << uint32(0xa87) << uint32(0x0); // 16 + data << uint32(0xa86) << uint32(0x0); // 17 + data << uint32(0xa85) << uint32(0x0); // 18 + data << uint32(0xa84) << uint32(0x0); // 19 + data << uint32(0xa83) << uint32(0x0); // 20 + data << uint32(0xa82) << uint32(0x0); // 21 + data << uint32(0xa81) << uint32(0x0); // 22 + data << uint32(0xa80) << uint32(0x0); // 23 + data << uint32(0xa7e) << uint32(0x0); // 24 + data << uint32(0xa7d) << uint32(0x0); // 25 + data << uint32(0xa7c) << uint32(0x0); // 26 + data << uint32(0xa7b) << uint32(0x0); // 27 + data << uint32(0xa7a) << uint32(0x0); // 28 + data << uint32(0xa79) << uint32(0x0); // 29 + data << uint32(0x9d0) << uint32(0x5); // 30 + data << uint32(0x9ce) << uint32(0x0); // 31 + data << uint32(0x9cd) << uint32(0x0); // 32 + data << uint32(0x9cc) << uint32(0x0); // 33 + data << uint32(0xa88) << uint32(0x0); // 34 + data << uint32(0xad0) << uint32(0x0); // 35 + data << uint32(0xacf) << uint32(0x1); // 36 + case 3521: // Zangarmarsh + data << uint32(0x9e1) << uint32(0x0); // 10 + data << uint32(0x9e0) << uint32(0x0); // 11 + data << uint32(0x9df) << uint32(0x0); // 12 + data << uint32(0xa5d) << uint32(0x1); // 13 + data << uint32(0xa5c) << uint32(0x0); // 14 + data << uint32(0xa5b) << uint32(0x1); // 15 + data << uint32(0xa5a) << uint32(0x0); // 16 + data << uint32(0xa59) << uint32(0x1); // 17 + data << uint32(0xa58) << uint32(0x0); // 18 + data << uint32(0xa57) << uint32(0x0); // 19 + data << uint32(0xa56) << uint32(0x0); // 20 + data << uint32(0xa55) << uint32(0x1); // 21 + data << uint32(0xa54) << uint32(0x0); // 22 + data << uint32(0x9e7) << uint32(0x0); // 23 + data << uint32(0x9e6) << uint32(0x0); // 24 + data << uint32(0x9e5) << uint32(0x0); // 25 + data << uint32(0xa00) << uint32(0x0); // 26 + data << uint32(0x9ff) << uint32(0x1); // 27 + data << uint32(0x9fe) << uint32(0x0); // 28 + data << uint32(0x9fd) << uint32(0x0); // 29 + data << uint32(0x9fc) << uint32(0x1); // 30 + data << uint32(0x9fb) << uint32(0x0); // 31 + data << uint32(0xa62) << uint32(0x0); // 32 + data << uint32(0xa61) << uint32(0x1); // 33 + data << uint32(0xa60) << uint32(0x1); // 34 + data << uint32(0xa5f) << uint32(0x0); // 35 + case 3703: // Shattrath City + break; + default: + data << uint32(0x914) << uint32(0x0); // 7 + data << uint32(0x913) << uint32(0x0); // 8 + data << uint32(0x912) << uint32(0x0); // 9 + data << uint32(0x915) << uint32(0x0); // 10 + break; + } + GetSession()->SendPacket(&data); } uint32 Player::GetXPRestBonus(uint32 xp) @@ -5715,6 +5919,7 @@ SetVirtualItemSlot(2,NULL); break; } + SetUInt32Value(UNIT_FIELD_BYTES_2, 0x2800+sheathed); // this must visualize Sheath changing for other players... } uint8 Player::FindEquipSlot( uint32 type, uint32 slot, bool swap ) const @@ -6150,7 +6355,6 @@ uint8 Player::CanTakeMoreSimilarItems(Item* pItem) const { - ItemPrototype const *pProto = pItem->GetProto(); if( !pProto ) return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; @@ -6472,7 +6676,6 @@ return 0; } - ////////////////////////////////////////////////////////////////////////// uint8 Player::CanStoreItems( Item **pItems,int count) const { @@ -6519,7 +6722,6 @@ } } - // check free space for all items for (int k=0;kIsBag() && !((Bag*)pItem)->IsEmpty()) return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS; - // All equiped items can swaped (not in combat case) + // All equiped items can swapped (not in combat case) if(swap) return EQUIP_ERR_OK; @@ -7117,8 +7317,6 @@ } if( pProto->RequiredSpell != 0 && !HasSpell( pProto->RequiredSpell ) ) return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; - if( not_loading && GetHonorRank() < pProto->RequiredHonorRank ) - return EQUIP_ITEM_RANK_NOT_ENOUGH; if( pProto->RequiredReputationFaction && GetReputationRank(pProto->RequiredReputationFaction) < pProto->RequiredReputationRank ) return EQUIP_ITEM_REPUTATION_NOT_ENOUGH; if( getLevel() < pProto->RequiredLevel ) @@ -7146,8 +7344,6 @@ } if( pProto->RequiredSpell != 0 && !HasSpell( pProto->RequiredSpell ) ) return false; - if( GetHonorRank() < pProto->RequiredHonorRank ) - return false; if( getLevel() < pProto->RequiredLevel ) return false; return true; @@ -7178,8 +7374,6 @@ } if( pProto->RequiredSpell != 0 && !HasSpell( pProto->RequiredSpell ) ) return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; - if( GetHonorRank() < pProto->RequiredHonorRank ) - return EQUIP_ITEM_RANK_NOT_ENOUGH; /*if( GetReputation() < pProto->RequiredReputation ) return EQUIP_ITEM_REPUTATION_NOT_ENOUGH; */ @@ -7421,10 +7615,10 @@ if( slot < EQUIPMENT_SLOT_END ) { - int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * 12); + int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * 16); SetUInt32Value(VisibleBase, pItem->GetEntry()); - for(int i = 0; i < 7; ++i) + for(int i = 0; i < 11; ++i) SetUInt32Value(VisibleBase + 1 + i, pItem->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + i*3 )); SetUInt32Value(VisibleBase + 8, pItem->GetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID)); @@ -7463,7 +7657,7 @@ if ( slot < EQUIPMENT_SLOT_END ) { - int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * 12); + int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * 16); for (int i = VisibleBase; i < VisibleBase + 12; ++i) SetUInt32Value(i, 0); } @@ -7597,35 +7791,38 @@ if ( slot < EQUIPMENT_SLOT_END ) { _ApplyItemMods(pItem, slot, false); - int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * 12); + int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * 16); for (int i = VisibleBase; i < VisibleBase + 12; ++i) SetUInt32Value(i, 0); - for(int enchant_slot = 0 ; enchant_slot < 7; enchant_slot++) + for(int enchant_slot = 0 ; enchant_slot < 11 ; enchant_slot++) { uint32 Enchant_id = pItem->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+enchant_slot*3); if( Enchant_id) { - SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(Enchant_id); - if(!pEnchant) - continue; - uint32 enchant_display = pEnchant->display_type; - uint32 enchant_value1 = pEnchant->value1; - //uint32 enchant_value2 = pEnchant->value2; - uint32 enchant_spell_id = pEnchant->spellid; - //uint32 enchant_aura_id = pEnchant->aura_id; - //uint32 enchant_description = pEnchant->description; - //SpellEntry *enchantSpell_info = sSpellStore.LookupEntry(enchant_spell_id); - if(enchant_display ==4) - SetArmor(GetArmor()-enchant_value1); - else if(enchant_display ==2) + for (int s=0;s<3;s++) { - SetFloatValue(UNIT_FIELD_MINDAMAGE,GetFloatValue(UNIT_FIELD_MINDAMAGE)-enchant_value1); - SetFloatValue(UNIT_FIELD_MAXDAMAGE,GetFloatValue(UNIT_FIELD_MAXDAMAGE)-enchant_value1); + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(Enchant_id); + if(!pEnchant) + continue; + uint32 enchant_display = pEnchant->display_type[s]; + uint32 enchant_value1 = pEnchant->amount[s]; + //uint32 enchant_value2 = pEnchant->value2; + uint32 enchant_spell_id = pEnchant->spellid[s]; + //uint32 enchant_aura_id = pEnchant->aura_id; + //uint32 enchant_description = pEnchant->description; + //SpellEntry *enchantSpell_info = sSpellStore.LookupEntry(enchant_spell_id); + if(enchant_display ==4) + SetArmor(GetArmor()-enchant_value1); + else if(enchant_display ==2) + { + SetFloatValue(UNIT_FIELD_MINDAMAGE,GetFloatValue(UNIT_FIELD_MINDAMAGE)-enchant_value1); + SetFloatValue(UNIT_FIELD_MAXDAMAGE,GetFloatValue(UNIT_FIELD_MAXDAMAGE)-enchant_value1); + } + else + { + RemoveAurasDueToSpell(enchant_spell_id); + } } - else - { - RemoveAurasDueToSpell(enchant_spell_id); - } } } } @@ -7979,7 +8176,7 @@ } - // prevent put equiped/bank bag in self + // prevent put equipped/bank bag in self if( IsBagPos ( src ) && srcslot == dstbag) { SendEquipError( EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG, pSrcItem, pDstItem ); @@ -8250,7 +8447,7 @@ SetUInt32Value( PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, 0 ); SetUInt32Value( PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + eslot, 0 ); - // if cuurent backslot is filled set to now free slot + // if current backslot is filled set to now free slot if(m_items[m_currentBuybackSlot]) m_currentBuybackSlot = slot; } @@ -8265,7 +8462,7 @@ data << (pItem && pItem->GetProto() ? pItem->GetProto()->RequiredLevel : uint32(0)); data << (pItem ? pItem->GetGUID() : uint64(0)); data << (pItem2 ? pItem2->GetGUID() : uint64(0)); - data << uint8(0); + data << uint8(0); // not 0 there... GetSession()->SendPacket(&data); } @@ -8284,7 +8481,7 @@ void Player::SendSellError( uint8 msg, Creature* pCreature, uint64 guid, uint32 param ) { sLog.outDetail( "WORLD: Sent SMSG_SELL_ITEM" ); - WorldPacket data( SMSG_SELL_ITEM, (8+4+4+1) ); + WorldPacket data( SMSG_SELL_ITEM, (8+4+4+1) ); // last check 2.0.10 data << (pCreature ? pCreature->GetGUID() : uint64(0)); data << guid; if( param > 0 ) @@ -8385,7 +8582,7 @@ } if(item && duration > 0 ) { - GetSession()->SendItemEnchantTimeUpdate(item->GetGUID(),slot,uint32(duration/1000)); + GetSession()->SendItemEnchantTimeUpdate(GetGUID(), item->GetGUID(),slot,uint32(duration/1000)); m_enchantDuration.push_back(EnchantDuration(item,slot,duration)); } } @@ -8406,7 +8603,7 @@ pItem = GetItemByPos( pos ); if(!pItem) continue; - for(int x=0;x<7;x++) + for(int x=0;x<11;x++) { charges = pItem->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+x*3+2); if(charges == 0) @@ -8509,17 +8706,21 @@ void Player::SendNewItem(Item *item, uint32 count, bool received, bool created, bool broadcast) { - WorldPacket data( SMSG_ITEM_PUSH_RESULT, (8+4+4+4+1+4+4+4+4+4) ); - data << GetGUID(); - data << uint32(received); - data << uint32(created); - data << uint32(1); - data << uint8(0xFF); - data << uint32(0xFFFFFFFF); - data << uint32(item->GetEntry()); - data << uint32(0); + if(!item) // prevent crash + return; + + WorldPacket data( SMSG_ITEM_PUSH_RESULT, (8+4+4+4+1+4+4+4+4+4) ); // last check 2.0.10 + data << GetGUID(); // player GUID + data << uint32(received); // 0=looted, 1=from npc + data << uint32(created); // 0=received, 1=created + data << uint32(1); // always 0x01 (propably meant to be count of listed items) + data << (uint8)item->GetBagSlot(); // bagslot + data << (uint32) ((item->GetCount()==count) ? item->GetSlot() : -1); // item slot, but when added to stack: 0xFFFFFFFF + data << uint32(item->GetEntry()); // item id + data << (uint32)urand(0, 255); // 0 when bought from npc otherwise ??? data << uint32(item->GetItemRandomPropertyId()); - data << uint32(count); + data << uint32(count); // count of items + data << GetItemCount(item->GetEntry()); // count of items in inventory if (broadcast && groupInfo.group) groupInfo.group->BroadcastPacket(&data); @@ -9106,8 +9307,7 @@ bool Player::SatisfyQuestLog( bool msg ) { - uint16 log_slot = GetQuestSlot( 0 ); - if( log_slot ) + if( GetQuestSlot(0) ) return true; else { @@ -9335,7 +9535,6 @@ Quest * qInfo = objmgr.QuestTemplates[quest_id]; if( qInfo ) { - uint32 srcitem = qInfo->GetSrcItemId(); if( srcitem > 0 ) { @@ -9434,7 +9633,6 @@ uint32 curitemcount = GetItemCount(qInfo->ReqItemId[i]) + GetBankItemCount(qInfo->ReqItemId[i]); mQuestStatus[quest_id].m_itemcount[i] = min(curitemcount, reqitemcount); if (mQuestStatus[quest_id].uState != QUEST_NEW) mQuestStatus[quest_id].uState = QUEST_CHANGED; - } } } @@ -9971,8 +10169,8 @@ bool Player::LoadFromDB( uint32 guid ) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 - QueryResult *result = sDatabase.PQuery("SELECT `guid`,`account`,`data`,`name`,`race`,`class`,`position_x`,`position_y`,`position_z`,`map`,`orientation`,`taximask`,`highest_rank`,`standing`,`rating`,`cinematic`,`totaltime`,`leveltime`,`rest_bonus`,`logout_time`,`is_logout_resting`,`resettalents_cost`,`resettalents_time`,`trans_x`,`trans_y`,`trans_z`,`trans_o`, `transguid`,`gmstate`,`stable_slots` FROM `character` WHERE `guid` = '%u'",guid); + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + QueryResult *result = sDatabase.PQuery("SELECT `guid`,`account`,`data`,`name`,`race`,`class`,`position_x`,`position_y`,`position_z`,`map`,`orientation`,`taximask`,`cinematic`,`totaltime`,`leveltime`,`rest_bonus`,`logout_time`,`is_logout_resting`,`resettalents_cost`,`resettalents_time`,`trans_x`,`trans_y`,`trans_z`,`trans_o`, `transguid`,`gmstate`,`stable_slots` FROM `character` WHERE `guid` = '%u'", guid); if(!result) { @@ -10007,8 +10205,8 @@ { SetUInt64Value( (uint16)(PLAYER_FIELD_INV_SLOT_HEAD + (slot * 2) ), 0 ); - int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * 12); - for(int i = 0; i < 9; ++i ) + int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * 16); + for(int i = 0; i < 11; ++i ) SetUInt32Value(VisibleBase + i, 0); if (m_items[slot]) @@ -10041,8 +10239,7 @@ return false; } - uint32 transGUID = fields[27].GetUInt32(); - + uint32 transGUID = fields[24].GetUInt32(); Relocate(fields[6].GetFloat(),fields[7].GetFloat(),fields[8].GetFloat(),fields[10].GetFloat()); SetMapId(fields[9].GetUInt32()); @@ -10054,10 +10251,10 @@ if (transGUID != 0) { - m_transX = fields[23].GetFloat(); - m_transY = fields[24].GetFloat(); - m_transZ = fields[25].GetFloat(); - m_transO = fields[26].GetFloat(); + m_transX = fields[20].GetFloat(); + m_transY = fields[21].GetFloat(); + m_transZ = fields[22].GetFloat(); + m_transO = fields[23].GetFloat(); for (int i = 0; i < MapManager::Instance().m_Transports.size(); i++) { @@ -10071,17 +10268,17 @@ } // since last logout (in seconds) - uint32 time_diff = (time(NULL) - fields[19].GetUInt32()); + uint32 time_diff = (time(NULL) - fields[16].GetUInt32()); - m_rest_bonus = fields[18].GetFloat(); + m_rest_bonus = fields[15].GetFloat(); //speed collect rest bonus in offline, in logout, far from tavern, city (section/in hour) float bubble0 = 0.0416; //speed collect rest bonus in offline, in logout, in tavern, city (section/in hour) float bubble1 = 0.083; - if((int32)fields[19].GetUInt32() > 0) + if((int32)fields[16].GetUInt32() > 0) { - float bubble = fields[20].GetUInt32() > 0 + float bubble = fields[17].GetUInt32() > 0 ? bubble1*sWorld.getRate(RATE_REST_OFFLINE_IN_TAVERN_OR_CITY) : bubble0*sWorld.getRate(RATE_REST_OFFLINE_IN_WILDERNESS); @@ -10096,36 +10293,27 @@ Relocate(info->positionX,info->positionY,info->positionZ); } - m_highest_rank = fields[12].GetUInt32(); - if(m_highest_rank >= HONOR_RANK_COUNT) - { - sLog.outError("ERROR: Player (guidlow %d) have invalid honor rank (%d). Reset to no rank.",guid,m_highest_rank); - m_highest_rank = 0; - } + m_cinematic = fields[12].GetUInt32(); + m_Played_time[0]= fields[13].GetUInt32(); + m_Played_time[1]= fields[14].GetUInt32(); - m_standing = fields[13].GetUInt32(); - m_rating = fields[14].GetFloat(); - m_cinematic = fields[15].GetUInt32(); - m_Played_time[0]= fields[16].GetUInt32(); - m_Played_time[1]= fields[17].GetUInt32(); + m_resetTalentsCost = fields[18].GetUInt32(); + m_resetTalentsTime = fields[19].GetUInt64(); - m_resetTalentsCost = fields[21].GetUInt32(); - m_resetTalentsTime = fields[22].GetUInt64(); - // reserve some flags + ad ghost flag uint32 old_safe_flags = GetUInt32Value(PLAYER_FLAGS) & ( PLAYER_FLAGS_HIDE_CLOAK | PLAYER_FLAGS_HIDE_HELM ); if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM) ) - SetUInt32Value(PLAYER_FLAGS, 0 | old_safe_flags ); + SetUInt32Value(PLAYER_FLAGS, 0 | old_safe_flags); if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) ) m_deathState = DEAD; _LoadTaxiMask( fields[11].GetString() ); - uint32 gmstate = fields[28].GetUInt32(); + uint32 gmstate = fields[25].GetUInt32(); - m_stableSlots = fields[29].GetUInt32(); + m_stableSlots = fields[26].GetUInt32(); if(m_stableSlots > 2) { sLog.outError("Player can have not more 2 stable slots, but have in DB %u",uint32(m_stableSlots)); @@ -10135,8 +10323,7 @@ delete result; // clear channel spell data (if saved at channel spell casting) - SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT,0); - SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT+1,0); + SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0); SetUInt32Value(UNIT_CHANNEL_SPELL,0); // clear charm/summon related fields @@ -10226,7 +10413,6 @@ void Player::_LoadActions() { - m_actionButtons.clear(); QueryResult *result = sDatabase.PQuery("SELECT `button`,`action`,`type`,`misc` FROM `character_action` WHERE `guid` = '%u' ORDER BY `button`",GetGUIDLow()); @@ -10664,7 +10850,6 @@ for (int iI=0; iI<8; iI++) m_Tutorials[iI] = fields[iI].GetUInt32(); - } while( result->NextRow() ); @@ -10685,6 +10870,10 @@ if (isInFlight()) return; + // Must saved before enter into BattleGround + if(InBattleGround()) + return; + int is_save_resting = HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0; //save, far from tavern/city //save, but in tavern/city @@ -10718,7 +10907,7 @@ SetUInt32Value(UNIT_FIELD_DISPLAYID,GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); // remove restflag when save - //this is becouse of the rename char stuff + //this is because of the rename char stuff RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); bool inworld = IsInWorld(); @@ -10729,7 +10918,7 @@ for(uint32 i = 0; i < MAX_POWERS; ++i) basePower[i] = GetFloatValue(UNIT_FIELD_POWER1+i); - // temorary set current power/health values to save + // temporary set current power/health values to save SetUInt32Value(UNIT_FIELD_HEALTH,currentHealth); for(uint32 i = 0; i < MAX_POWERS; ++i) SetFloatValue(UNIT_FIELD_POWER1+i,float(currentPower[i])); @@ -10741,7 +10930,7 @@ std::ostringstream ss; ss << "INSERT INTO `character` (`guid`,`account`,`name`,`race`,`class`," "`map`,`position_x`,`position_y`,`position_z`,`orientation`,`data`," - "`taximask`,`online`,`highest_rank`,`standing`,`rating`,`cinematic`," + "`taximask`,`online`,`cinematic`," "`totaltime`,`leveltime`,`rest_bonus`,`logout_time`,`is_logout_resting`,`resettalents_cost`,`resettalents_time`," "`trans_x`, `trans_y`, `trans_z`, `trans_o`, `transguid`, `gmstate`, `stable_slots` ) VALUES (" << GetGUIDLow() << ", " @@ -10770,15 +10959,6 @@ inworld ? ss << 1: ss << 0; ss << ", "; - ss << m_highest_rank; - - ss << ", "; - ss << m_standing; - - ss << ", "; - ss << m_rating; - - ss << ", "; ss << m_cinematic; ss << ", "; @@ -10861,7 +11041,7 @@ _ApplyAllItemMods(); } - // save pet (hunter pet level and experience and all type pets health/mana. + // save pet (hunter pet level and experience and all type pets health/mana). if(Pet* pet = GetPet()) pet->SavePetToDB(PET_SAVE_AS_CURRENT); } @@ -11015,7 +11195,7 @@ sDatabase.PExecute("DELETE FROM `mail` WHERE `id` = '%u'", m->messageID); } } - //dealocate deleted mails... + //deallocate deleted mails... bool continueDeleting = true; while ( continueDeleting ) { @@ -11248,6 +11428,15 @@ GetSession()->SendPacket(&data); } +void Player::SendDungeonDifficulty() +{ + WorldPacket data(MSG_SET_DUNGEON_DIFFICULTY, 12); + data << m_dungeonDifficulty; + data << uint32(0x00000001); + data << uint32(0x00000000); + GetSession()->SendPacket(&data); +} + /*********************************************************/ /*** Update timers ***/ /*********************************************************/ @@ -11386,25 +11575,9 @@ if(player->isAFK()) { - data.Initialize(SMSG_MESSAGECHAT, 200); - data << (uint8)CHAT_MSG_AFK; - data << (uint32)language; - data << (uint64)player->GetGUID(); - data << (uint32)(player->afkMsg.length()+1); - data << player->afkMsg; - data << (uint8)0; - GetSession()->SendPacket(&data); } if(player->isDND()) { - data.Initialize(SMSG_MESSAGECHAT, 200); - data << (uint8)CHAT_MSG_DND; - data << (uint32)language; - data << (uint64)player->GetGUID(); - data << (uint32)(player->dndMsg.length()+1); - data << player->dndMsg; - data << (uint8)0; - GetSession()->SendPacket(&data); } if(!isAcceptWhispers()) @@ -11448,12 +11621,19 @@ for(uint32 i=0; i < CREATURE_MAX_SPELLS; i++) { - if (pet->HasActState(STATE_RA_SPELL1 << i)) + if(!pet->m_spells[i]) + { + data << uint16(pet->m_spells[i]) << uint16((i+2) << 8); + } + else + { + if (pet->HasActState(STATE_RA_SPELL1 << i)) // Spell enabled - data << uint16 (pet->m_spells[i]) << uint16 (0xC100); - else + data << uint16 (pet->m_spells[i]) << uint16 (0xC100); + else // Spell disabled - data << uint16 (pet->m_spells[i]) << uint16 (0x8100); + data << uint16 (pet->m_spells[i]) << uint16 (0x8100); + } } data << uint16 (2) << uint16(State << 8); // 2 command from 0x600 group place to 8 slot @@ -11470,6 +11650,15 @@ } data << uint8(addlist); + /*data << uint8(0x08); // just for testing pet spell book + data << uint32(0x0100433a); + data << uint32(0x0100105f); + data << uint32(0x01005fe8); + data << uint32(0x01005f77); + data << uint32(0x01005f7f); + data << uint32(0x01005fb6); + data << uint32(0x01005fb1); + data << uint32(0x01005fb9);*/ if(pet->isControlled()) { @@ -11486,20 +11675,28 @@ if(pet->m_spells[i] == spellInfo->EffectTriggerSpell[0]) { if (pet->HasActState(STATE_RA_SPELL1 << i)) - data << uint16(0xC1); // Spell enabled + data << uint16(0xC100); // Spell enabled else - data << uint16(0x81); // Spell disabled + data << uint16(0x8100); // Spell disabled hasthisspell = true; break; } } if(!hasthisspell) - data << uint16(0x01); + data << uint16(0x0100); } } } - data << uint8(0x01) << uint32(0x6010) << uint32(0x00) << uint32(0x00) << uint16(0x00); + uint8 count = 3; + // if count = 0, then end of packet... + data << count; + // uint32 value is spell id... + // uint64 value is constant 0, unknown... + data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 + //data << uint32(0x5fd1) << uint64(0); // if count = 2 + data << uint32(0x8e8c) << uint64(0); // if count = 3 + data << uint32(0x8e8b) << uint64(0); // if count = 3 GetSession()->SendPacket(&data); } @@ -11754,7 +11951,7 @@ // Save before flight (player must loaded in start taxinode is disconnected at flight,etc) SaveToDB(); - // unsommon pet, it will be lost anyway + // unsummon pet, it will be lost anyway RemovePet(NULL,PET_SAVE_NOT_IN_SLOT); //Checks and preparations done, DO FLIGHT @@ -11773,11 +11970,13 @@ void Player::ProhibitSpellScholl(uint32 idSchool /* from SpellSchools */, uint32 unTimeMs ) { - WorldPacket data(SMSG_SPELL_COOLDOWN, 8 + m_spells.size()*8); + WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+m_spells.size()*8); // last check 2.0.10 data << GetGUID(); + data << uint8(0x0); time_t curTime = time(NULL); for(PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) { + // WTF, we can send multiple cooldowns in one packet? I don't think so... if (itr->second->state == PLAYERSPELL_REMOVED) continue; uint32 unSpellId = itr->first; @@ -11789,8 +11988,8 @@ } if(idSchool == spellInfo->School && GetSpellCooldownDelay(unSpellId) < unTimeMs ) { - data << uint32(unSpellId); - data << uint32(unTimeMs); // in m.secs + data << unSpellId; + data << unTimeMs; // in m.secs AddSpellCooldown(unSpellId, curTime + unTimeMs/1000); } } @@ -11864,7 +12063,7 @@ void Player::ApplySpeedMod(UnitMoveType mtype, float rate, bool forced, bool apply) { if(forced) - ++m_forced_speed_changes[mtype]; // register forced speed chaged for WorldSession::HandleForceSpeedChangeAck + ++m_forced_speed_changes[mtype]; // register forced speed changes for WorldSession::HandleForceSpeedChangeAck Unit::ApplySpeedMod(mtype,rate,forced,apply); } @@ -11899,13 +12098,40 @@ SendBuyError( BUY_ERR_ITEM_ALREADY_SOLD, pCreature, item, 0); return; } - - // not check level requiremnt for normal items (PvP related bonus items is another case) - if(pProto->RequiredHonorRank && (GetHonorHighestRank() < pProto->RequiredHonorRank || getLevel() < pProto->RequiredLevel) ) + if( getLevel() < pProto->RequiredLevel ) { SendBuyError( BUY_ERR_LEVEL_REQUIRE, pCreature, item, 0); return; } + if(pProto->ExtendedCost) + { + ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(pProto->ExtendedCost); + if(iece) + { + if(GetHonorPoints() < iece->reqhonorpoints) + { + SendEquipError(EQUIP_DONT_HAVE_ENOUGHT_HONOR_POINTS, NULL, NULL); + return; + } + if(GetArenaPoints() < iece->reqarenapoints) + { + SendEquipError(EQUIP_DONT_HAVE_ENOUGHT_ARENA_POINTS, NULL, NULL); + return; + } + if( (iece->reqitem1 && !HasItemCount(iece->reqitem1, iece->reqitemcount1)) || + (iece->reqitem2 && !HasItemCount(iece->reqitem2, iece->reqitemcount2)) || + (iece->reqitem3 && !HasItemCount(iece->reqitem3, iece->reqitemcount3)) ) + { + SendEquipError(EQUIP_DONT_HAVE_REQITEMS_FOR_THAT_PURCHASE, NULL, NULL); + return; + } + } + else + { + sLog.outError("Item %u have wrong ExtendedCost field value %u", pProto->ItemId, pProto->ExtendedCost); + return; + } + } // 10% reputation discount uint32 price = pProto->BuyPrice * count; @@ -11954,9 +12180,32 @@ if( msg == EQUIP_ERR_OK ) { ModifyMoney( -(int32)price ); - StoreNewItem( dest, item, pProto->BuyCount * count, true ); + if(pProto->ExtendedCost) // case for new honor system + { + ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(pProto->ExtendedCost); + if(iece->reqhonorpoints) + SetHonorPoints(GetHonorPoints() - iece->reqhonorpoints); + if(iece->reqarenapoints) + SetArenaPoints(GetArenaPoints() - iece->reqarenapoints); + if(iece->reqitem1) + DestroyItemCount(iece->reqitem1, iece->reqitemcount1, true); + if(iece->reqitem2) + DestroyItemCount(iece->reqitem2, iece->reqitemcount2, true); + if(iece->reqitem3) + DestroyItemCount(iece->reqitem3, iece->reqitemcount3, true); + } + Item *it = StoreNewItem( dest, item, pProto->BuyCount * count, true ); if( crItem->maxcount != 0 ) crItem->count -= pProto->BuyCount; + + WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4)); + data << pCreature->GetGUID(); + data << (uint32)crItem->id; // entry + data << (uint32)crItem->count; + data << (uint32)count; + GetSession()->SendPacket(&data); + + SendNewItem(it, count, true, false, false); } else SendEquipError( msg, NULL, NULL ); @@ -11967,9 +12216,32 @@ if( msg == EQUIP_ERR_OK ) { ModifyMoney( -(int32)price ); - EquipNewItem( dest, item, pProto->BuyCount * count, true ); + if(pProto->ExtendedCost) // case for new honor system + { + ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(pProto->ExtendedCost); + if(iece->reqhonorpoints) + SetHonorPoints(GetHonorPoints() - iece->reqhonorpoints); + if(iece->reqarenapoints) + SetArenaPoints(GetArenaPoints() - iece->reqarenapoints); + if(iece->reqitem1) + DestroyItemCount(iece->reqitem1, iece->reqitemcount1, true); + if(iece->reqitem2) + DestroyItemCount(iece->reqitem2, iece->reqitemcount2, true); + if(iece->reqitem3) + DestroyItemCount(iece->reqitem3, iece->reqitemcount3, true); + } + Item *it = EquipNewItem( dest, item, pProto->BuyCount * count, true ); if( crItem->maxcount != 0 ) crItem->count -= pProto->BuyCount; + + WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4)); + data << pCreature->GetGUID(); + data << (uint32)crItem->id; // entry + data << (uint32)crItem->count; + data << (uint32)count; + GetSession()->SendPacket(&data); + + SendNewItem(it, count, true, false, false); } else SendEquipError( msg, NULL, NULL ); @@ -12043,6 +12315,14 @@ // GMs never get homebind timer online if (m_InstanceValid || isGameMaster()) { + if(m_HomebindTimer) // instance valid, but timer not reset + { + // hide reminder + WorldPacket data(SMSG_RAID_GROUP_ONLY, 4+4); + data << uint32(0); + data << uint32(0); + GetSession()->SendPacket(&data); + } // instance is valid, reset homebind timer m_HomebindTimer = 0; } @@ -12057,16 +12337,6 @@ { uint32 oldTimer = m_HomebindTimer; m_HomebindTimer -= time; - - // re-warn user if the time stepped over 30 sec or over 10 sec - if (m_HomebindTimer < 10000) - { - if (oldTimer >= 10000) GetSession()->SendAreaTriggerMessage("You must join your old group or you will be teleported to your home location in 10 seconds"); - } - else if (m_HomebindTimer < 30000) - { - if (oldTimer >= 30000) GetSession()->SendAreaTriggerMessage("You must join your old group or you will be teleported to your home location in 30 seconds"); - } } } else @@ -12074,7 +12344,10 @@ // instance is invalid, start homebind timer m_HomebindTimer = 60000; // send message to player - GetSession()->SendAreaTriggerMessage("You must join your old group or you will be teleported to your home location in 60 seconds"); + WorldPacket data(SMSG_RAID_GROUP_ONLY, 4+4); + data << m_HomebindTimer; + data << uint32(1); + GetSession()->SendPacket(&data); sLog.outDebug("PLAYER: Player '%s' will be teleported to homebind in 60 seconds", GetName()); } } @@ -12106,3 +12379,10 @@ } } } + +void Player::SendAllowMove() +{ + WorldPacket data(SMSG_ALLOW_MOVE, 4); // new 2.0.x, enable movement + data << uint32(0x00000000); // on blizz it increments periodically + GetSession()->SendPacket(&data); +} Index: src/game/SpellAuras.cpp =================================================================== --- src/game/SpellAuras.cpp (working copy) +++ src/game/SpellAuras.cpp (working copy) @@ -43,14 +43,15 @@ #include "ConfusedMovementGenerator.h" #include "TargetedMovementGenerator.h" #include "Formulas.h" +#include "BattleGround.h" pAuraHandler AuraHandler[TOTAL_AURAS]= { - &Aura::HandleNULL, //SPELL_AURA_NONE - &Aura::HandleBindSight, //SPELL_AURA_BIND_SIGHT = 1 + &Aura::HandleNULL, //SPELL_AURA_NONE = 0, + &Aura::HandleBindSight, //SPELL_AURA_BIND_SIGHT = 1, &Aura::HandleModPossess, //SPELL_AURA_MOD_POSSESS = 2, &Aura::HandlePeriodicDamage, //SPELL_AURA_PERIODIC_DAMAGE = 3, - &Aura::HandleAuraDummy, //SPELL_AURA_DUMMY //missing 4 + &Aura::HandleAuraDummy, //SPELL_AURA_DUMMY = 4, &Aura::HandleModConfuse, //SPELL_AURA_MOD_CONFUSE = 5, &Aura::HandleModCharm, //SPELL_AURA_MOD_CHARM = 6, &Aura::HandleModFear, //SPELL_AURA_MOD_FEAR = 7, @@ -71,7 +72,7 @@ &Aura::HandleAuraModResistance, //SPELL_AURA_MOD_RESISTANCE = 22, &Aura::HandlePeriodicTriggerSpell, //SPELL_AURA_PERIODIC_TRIGGER_SPELL = 23, &Aura::HandlePeriodicEnergize, //SPELL_AURA_PERIODIC_ENERGIZE = 24, - &Aura::HandleNULL, //SPELL_AURA_MOD_PACIFY = 25, + &Aura::HandleAuraModPacify, //SPELL_AURA_MOD_PACIFY = 25, &Aura::HandleAuraModRoot, //SPELL_AURA_MOD_ROOT = 26, &Aura::HandleAuraModSilence, //SPELL_AURA_MOD_SILENCE = 27, &Aura::HandleNoImmediateEffect, //SPELL_AURA_REFLECT_SPELLS = 28, @@ -113,7 +114,7 @@ &Aura::HandlePeriodicManaLeech, //SPELL_AURA_PERIODIC_MANA_LEECH = 64, &Aura::HandleModCastingSpeed, //SPELL_AURA_MOD_CASTING_SPEED = 65, &Aura::HandleFeignDeath, //SPELL_AURA_FEIGN_DEATH = 66, - &Aura::HandleNULL, //SPELL_AURA_MOD_DISARM = 67, + &Aura::HandleAuraModDisarm, //SPELL_AURA_MOD_DISARM = 67, &Aura::HandleAuraModStalked, //SPELL_AURA_MOD_STALKED = 68, &Aura::HandleAuraSchoolAbsorb, //SPELL_AURA_SCHOOL_ABSORB = 69, &Aura::HandleNULL, //SPELL_AURA_EXTRA_ATTACKS = 70,// Useless @@ -141,7 +142,7 @@ &Aura::HandleNULL, //SPELL_AURA_PREVENTS_FLEEING = 92, &Aura::HandleNULL, //SPELL_AURA_MOD_UNATTACKABLE = 93, &Aura::HandleInterruptRegen, //SPELL_AURA_INTERRUPT_REGEN = 94, - &Aura::HandleNULL, //SPELL_AURA_GHOST = 95, + &Aura::HandleAuraGhost, //SPELL_AURA_GHOST = 95, &Aura::HandleNULL, //SPELL_AURA_SPELL_MAGNET = 96, &Aura::HandleAuraManaShield, //SPELL_AURA_MANA_SHIELD = 97, &Aura::HandleAuraModSkill, //SPELL_AURA_MOD_SKILL_TALENT = 98, @@ -165,8 +166,8 @@ &Aura::HandleNULL, //SPELL_AURA_IGNORE_REGEN_INTERRUPT = 116, &Aura::HandleNULL, //SPELL_AURA_MOD_MECHANIC_RESISTANCE = 117, &Aura::HandleModHealingPercent, //SPELL_AURA_MOD_HEALING_PCT = 118, - &Aura::HandleNULL, //SPELL_AURA_SHARE_PET_TRACKING = 119, - &Aura::HandleNULL, //SPELL_AURA_UNTRACKABLE = 120, + &Aura::HandleNULL, //SPELL_AURA_SHARE_PET_TRACKING = 119, useless + &Aura::HandleAuraUntrackable, //SPELL_AURA_UNTRACKABLE = 120, &Aura::HandleAuraEmpathy, //SPELL_AURA_EMPATHY = 121, &Aura::HandleModOffhandDamagePercent, //SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT = 122, &Aura::HandleNULL, //SPELL_AURA_MOD_POWER_COST_PCT = 123, @@ -204,40 +205,69 @@ &Aura::HandleNULL, //SPELL_AURA_MOD_WATER_BREATHING = 155 ,// Mod Water Breathing &Aura::HandleNoImmediateEffect, //SPELL_AURA_MOD_REPUTATION_GAIN = 156 ,// Mod Reputation Gain &Aura::HandleNULL, //SPELL_AURA_PET_DAMAGE_MULTI = 157 ,// Mod Pet Damage - &Aura::HandleNULL, //SPELL_AURA_MOD_SHIELD_BLOCK = 158 ,// - &Aura::HandleNULL, //SPELL_AURA_NO_PVP_CREDIT = 159 ,// - &Aura::HandleNULL, //SPELL_AURA_MOD_AOE_AVOIDANCE = 160 ,// - &Aura::HandleNULL, //SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT = 161 ,// - &Aura::HandleNULL, //SPELL_AURA_POWER_BURN_MANA = 162 ,// - &Aura::HandleNULL, //SPELL_AURA = 163 - &Aura::HandleNULL, //SPELL_AURA = 164 - &Aura::HandleNULL, //SPELL_AURA = 165 - &Aura::HandleNULL, //SPELL_AURA = 166 - &Aura::HandleNULL, //SPELL_AURA = 167 - &Aura::HandleNULL, //SPELL_AURA = 168 - &Aura::HandleNULL, //SPELL_AURA = 169 - &Aura::HandleNULL, //SPELL_AURA = 170 - &Aura::HandleNULL, //SPELL_AURA = 171 - &Aura::HandleNULL, //SPELL_AURA = 172 - &Aura::HandleNULL, //SPELL_AURA = 173 - &Aura::HandleNULL, //SPELL_AURA = 174 - &Aura::HandleNULL, //SPELL_AURA = 175 - &Aura::HandleNULL, //SPELL_AURA = 176 - &Aura::HandleNULL, //SPELL_AURA = 177 - &Aura::HandleNULL, //SPELL_AURA = 178 - &Aura::HandleNULL, //SPELL_AURA = 179 - &Aura::HandleNULL, //SPELL_AURA = 180 - &Aura::HandleNULL, //SPELL_AURA = 181 - &Aura::HandleNULL, //SPELL_AURA = 182 - &Aura::HandleNULL, //SPELL_AURA = 183 - &Aura::HandleNULL, //SPELL_AURA = 184 - &Aura::HandleNULL, //SPELL_AURA = 185 - &Aura::HandleNULL, //SPELL_AURA = 186 - &Aura::HandleNULL, //SPELL_AURA = 187 - &Aura::HandleNULL, //SPELL_AURA = 188 - &Aura::HandleNULL, //SPELL_AURA = 189 - &Aura::HandleNULL, //SPELL_AURA = 190 - &Aura::HandleNULL //SPELL_AURA = 191 + &Aura::HandleNULL, //SPELL_AURA_MOD_SHIELD_BLOCK = 158, + &Aura::HandleNULL, //SPELL_AURA_NO_PVP_CREDIT = 159, // only for Honorless Target spell + &Aura::HandleNULL, //SPELL_AURA_MOD_AOE_AVOIDANCE = 160, + &Aura::HandleNULL, //SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT = 161, + &Aura::HandleNULL, //SPELL_AURA_POWER_BURN_MANA = 162, + &Aura::HandleNULL, //SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE = 163, + &Aura::HandleNULL, // = 164, + &Aura::HandleNULL, //SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS = 165, + &Aura::HandleNULL, //SPELL_AURA_MOD_ATTACK_POWER_PCT = 166, + &Aura::HandleNULL, //SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT = 167, + &Aura::HandleNULL, //SPELL_AURA_MOD_DAMAGE_DONE_VERSUS= 168, + &Aura::HandleNULL, //SPELL_AURA_MOD_CRIT_PERCENT_VERSUS = 169, + &Aura::HandleNULL, //SPELL_AURA_DETECT_AMORE = 170, // only for Detect Amore spell + &Aura::HandleNULL, //SPELL_AURA_MOD_PARTY_SPEED = 171, unused + &Aura::HandleNULL, //SPELL_AURA_MOD_PARTY_SPEED_MOUNTED = 172, + &Aura::HandleNULL, //SPELL_AURA_ALLOW_CHAMPION_SPELLS = 173, // only for Proclaim Champion spell + &Aura::HandleNULL, //SPELL_AURA_MOD_SPELL_DAMAGE_OF_SPIRIT = 174, + &Aura::HandleNULL, //SPELL_AURA_MOD_SPELL_HEALING_OF_SPIRIT = 175, + &Aura::HandleNULL, //SPELL_AURA_SPIRIT_OF_REDEMPTION = 176, // only for Spirit of Redemption spell + &Aura::HandleNULL, //SPELL_AURA_AOE_CHARM = 177, + &Aura::HandleNULL, //SPELL_AURA_MOD_DEBUFF_RESISTANCE = 178, + &Aura::HandleNULL, //SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE = 179, + &Aura::HandleNULL, //SPELL_AURA_MOD_SPELL_DAMAGE_VS_UNDEAD = 180, + &Aura::HandleNULL, // = 181, + &Aura::HandleNULL, //SPELL_AURA_MOD_ARMOR_OF_INTELLECT = 182, + &Aura::HandleNULL, //SPELL_AURA_MOD_CRITICAL_THREAT = 183, + &Aura::HandleNULL, //SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE = 184, + &Aura::HandleNULL, //SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE = 185, + &Aura::HandleNULL, //SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE = 186, + &Aura::HandleNULL, //SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE = 187, + &Aura::HandleNULL, //SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE = 188, + &Aura::HandleNULL, //SPELL_AURA_MOD_RATING = 189, + &Aura::HandleNULL, //SPELL_AURA_MOD_FACTION_REPUTATION_GAIN = 190, + &Aura::HandleNULL, // = 191, + &Aura::HandleNULL, //SPELL_AURA_HASTE_MELEE = 192, + &Aura::HandleNULL, //SPELL_AURA_MELEE_SLOW = 193, + &Aura::HandleNULL, //SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT = 194, + &Aura::HandleNULL, //SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT = 195, + &Aura::HandleNULL, // = 196,unused + &Aura::HandleNULL, // = 197, = 179 + &Aura::HandleNULL, //SPELL_AURA_MOD_ALL_WEAPON_SKILLS = 198, + &Aura::HandleNULL, //SPELL_AURA_MOD_SPELL_HIT_CHANCE = 199, + &Aura::HandleNULL, // = 200, + &Aura::HandleAuraAllowFlight, // = 201, // this aura brobably must enable flight mode... + &Aura::HandleNULL, //SPELL_AURA_CANNOT_BE_DODGED = 202, + &Aura::HandleNULL, //SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE = 203, + &Aura::HandleNULL, //SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE = 204, + &Aura::HandleNULL, // = 205,unused + &Aura::HandleNULL, //SPELL_AURA_MOD_SPEED_MOUNTED = 206, + &Aura::HandleAuraModSpeedMountedFlight, //SPELL_AURA_MOD_SPEED_MOUNTED_FLIGHT = 207, + &Aura::HandleAuraAllowFlight, // = 208, // flight related, used only in spell: Flight Form (Passive) + &Aura::HandleNULL, // = 209,unused + &Aura::HandleNULL, // = 210,unused + &Aura::HandleNULL, // = 211, = 207 unused + &Aura::HandleNULL, //SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_INTELLECT = 212, + &Aura::HandleNULL, //SPELL_AURA_MOD_RANGE_FROM_DAMAGE_DEALT = 213, + &Aura::HandleNULL, // = 214, + &Aura::HandleNULL, // = 215, + &Aura::HandleNULL, //SPELL_AURA_HASTE_SPELLS = 216, + &Aura::HandleNULL, // = 217, + &Aura::HandleNULL, // = 218, + &Aura::HandleNULL, //SPELL_AURA_MOD_MANA_REGEN = 219, + &Aura::HandleNULL, // = 220, }; Aura::Aura(SpellEntry const* spellproto, uint32 eff, Unit *target, Unit *caster, Item* castItem) : @@ -1026,11 +1056,16 @@ if(apply) { CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue); - if(!ci)return; + if(!ci) + { + sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue); + return; + } uint32 displayId = ci->randomDisplayID(); if(displayId != 0) m_target->Mount(displayId); - }else + } + else { m_target->Unmount(); } @@ -1044,10 +1079,11 @@ WorldPacket data; if(apply) - data.Initialize(SMSG_MOVE_WATER_WALK, 8); + data.Initialize(SMSG_MOVE_WATER_WALK, 8+4); else - data.Initialize(SMSG_MOVE_LAND_WALK, 8); + data.Initialize(SMSG_MOVE_LAND_WALK, 8+4); data.append(m_target->GetPackGUID()); + data << uint32(0); m_target->SendMessageToSet(&data,true); } @@ -1059,10 +1095,11 @@ WorldPacket data; if(apply) - data.Initialize(SMSG_MOVE_FEATHER_FALL, 8); + data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4); else - data.Initialize(SMSG_MOVE_NORMAL_FALL, 8); + data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4); data.append(m_target->GetPackGUID()); + data << (uint32)0; m_target->SendMessageToSet(&data,true); } @@ -1074,10 +1111,11 @@ WorldPacket data; if(apply) - data.Initialize(SMSG_MOVE_SET_HOVER, 8); + data.Initialize(SMSG_MOVE_SET_HOVER, 8+4); else - data.Initialize(SMSG_MOVE_UNSET_HOVER, 8); + data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4); data.append(m_target->GetPackGUID()); + data << uint32(0); m_target->SendMessageToSet(&data,true); } @@ -1150,6 +1188,9 @@ case FORM_GHOSTWOLF: modelid = 4613; break; + case FORM_FLIGHT: + modelid = 20013; //test it !! (20857, 20872, 20013) + break; case FORM_MOONKIN: if(unit_target->getRace() == RACE_NIGHTELF) modelid = 15374; @@ -1252,6 +1293,10 @@ if(!m_target) return; + if(m_target->GetTypeId() == TYPEID_PLAYER && GetSpellProto()->Id == 20584 && m_target->getRace() != RACE_NIGHTELF) // required creature_template=12861 with modelid=1825 in database for ghost spell + return; + + if (apply) { // special case @@ -1407,10 +1452,11 @@ WorldPacket data; if(apply) - data.Initialize(SMSG_MOVE_FEATHER_FALL, 8); + data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4); else - data.Initialize(SMSG_MOVE_NORMAL_FALL, 8); + data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4); data.append(m_target->GetPackGUID()); + data << uint32(0); m_target->SendMessageToSet(&data,true); } @@ -1554,8 +1600,16 @@ if(caster->GetPet() != m_target) return; - if(caster->GetTypeId() == TYPEID_PLAYER) - caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_target->GetGUID() : 0); + if(apply) + { + caster->SetUInt64Value(PLAYER_FARSIGHT, m_target->GetGUID()); + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + } + else + { + caster->SetUInt64Value(PLAYER_FARSIGHT, 0); + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + } } void Aura::HandleModCharm(bool apply, bool Real) @@ -1700,44 +1754,63 @@ if(!m_target || m_target->GetTypeId() == TYPEID_UNIT) return; - uint32 apply_stat = UNIT_STAT_DIED; + if( Apply ) { - //m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16)); - // only at real add aura + + /* WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9); data<GetGUID(); data<SendMessageToSet(&data,true); */ - m_target->HandleEmoteCommand(EMOTE_STATE_DEAD); + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); // blizz like 2.0.x + m_target->SetFlag(UNIT_FIELD_FLAGS_2, 0x00000001); // blizz like 2.0.x + m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); // blizz like 2.0.x + m_target->addUnitState(UNIT_STAT_DIED); - m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_DEAD); + m_target->CombatStop(); m_target->DeleteInHateListOf(); } else { - //m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16)); - // only at real remove aura + + /* WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9); data<GetGUID(); data<SendMessageToSet(&data,true); */ + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); // blizz like 2.0.x + m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, 0x00000001); // blizz like 2.0.x + m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); // blizz like 2.0.x + m_target->clearUnitState(UNIT_STAT_DIED); - if(m_target->isAlive()) // only if still alive really - { - m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_DEAD); - } + + + + } } +void Aura::HandleAuraModDisarm(bool Apply, bool Real) +{ + if(!Real) + return; + + // not sure for it's correctness + if(Apply) + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); + else + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); +} + void Aura::HandleAuraModStun(bool apply, bool Real) { Unit* caster = GetCaster(); @@ -1758,8 +1831,9 @@ if(m_target->GetTypeId() != TYPEID_PLAYER) ((Creature *)m_target)->StopMoving(); - WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8); + WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8+4); data.append(m_target->GetPackGUID()); + data << uint32(0); m_target->SendMessageToSet(&data,true); } } @@ -1773,8 +1847,9 @@ // only at real remove aura if(Real) { - WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8); + WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8+4); data.append(m_target->GetPackGUID()); + data << uint32(0); m_target->SendMessageToSet(&data,true); if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721) @@ -3078,10 +3153,10 @@ Unit* caster = GetCaster(); if(caster) { - WorldPacket data(SMSG_COOLDOWN_EVENT, (4+8+4)); + WorldPacket data(SMSG_COOLDOWN_EVENT, (4+8+4)); // last check 2.0.10 data << uint32(m_spellId) << m_caster_guid; - data << uint32(0); //CoolDown Time ? - caster->SendMessageToSet(&data,true); + //data << uint32(0); // removed + caster->SendMessageToSet(&data,true); // WTF? why we send cooldown message to set? } } @@ -3240,7 +3315,7 @@ void Aura::HandleAuraEmpathy(bool apply, bool Real) { - if(m_target->GetTypeId()!=TYPEID_UNIT) + if(m_target->GetTypeId() != TYPEID_UNIT) return; CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry()); @@ -3249,3 +3324,117 @@ m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply); } } + +void Aura::HandleAuraUntrackable(bool apply, bool Real) +{ + // value 100% blizz like (2.0.10) + m_target->ApplyModUInt32Value(UNIT_FIELD_BYTES_1, 0x4000000, apply); +/* +Packet offset 00 +Packet number: 1 +Opcode: 00A9 +Object count: 1 +Unk: 0 +Update block for object 1: +Block offset 07 +Updatetype: UPDATETYPE_VALUES +Object guid: 00000000004765CE +=== values_update_block_start === +Bit mask blocks count: 45 +UNIT_FIELD_POWER1 (23): 1105 +UNIT_FIELD_AURA1 (48): 13161 +UNIT_FIELD_AURAFLAGS1 (104): 9 +UNIT_FIELD_BYTES_1 (152): 67108864 +=== values_update_block_end === + +Packet offset 00 +Packet number: 1 +Opcode: 00A9 +Object count: 1 +Unk: 0 +Update block for object 1: +Block offset 07 +Updatetype: UPDATETYPE_VALUES +Object guid: 00000000004765CE +=== values_update_block_start === +Bit mask blocks count: 45 +UNIT_FIELD_AURA1 (48): 0 +UNIT_FIELD_AURAFLAGS1 (104): 0 +UNIT_FIELD_BYTES_1 (152): 0 +=== values_update_block_end === +*/ +} + +void Aura::HandleAuraModPacify(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + if(apply) + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); + else + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); +} + +void Aura::HandleAuraGhost(bool apply, bool Real) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + if(apply) + { + m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); + } + else + { + m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); + } +} + +void Aura::HandleAuraAllowFlight(bool apply, bool Real) +{ + // all applied/removed only at real aura add/remove + if(!Real) + return; + + // allow fly + sLog.outDebug("%u %u %u %u %u", m_modifier.m_amount, m_modifier.m_auraname, m_modifier.m_miscvalue, m_modifier.m_miscvalue2, m_modifier.periodictime); + + WorldPacket data; + if(apply) + data.Initialize(SMSG_FLY_MODE_START, 12); + else + data.Initialize(SMSG_FLY_MODE_STOP, 12); + data.append(m_target->GetPackGUID()); + data << uint32(0); // unk + m_target->SendMessageToSet(&data, true); +} + +void Aura::HandleAuraModSpeedMountedFlight(bool apply, bool Real) +{ + // all applied/removed only at real aura add/remove + if(!Real) + return; + + sLog.outDebug("HandleAuraModSpeedMountedFlight: Current Speed:%f \tmodify percent:%f", m_target->GetSpeed(MOVE_FLY),(float)m_modifier.m_amount); + if(m_modifier.m_amount<=1) + return; + + float rate = (100.0f + m_modifier.m_amount)/100.0f; + + m_target->ApplySpeedMod(MOVE_FLY, rate, true, apply ); + + sLog.outDebug("ChangeSpeedTo:%f", m_target->GetSpeed(MOVE_FLY)); + + // allow fly + sLog.outDebug("%u %u %u %u %u", m_modifier.m_amount, m_modifier.m_auraname, m_modifier.m_miscvalue, m_modifier.m_miscvalue2, m_modifier.periodictime); + + WorldPacket data; + if(apply) + data.Initialize(SMSG_FLY_MODE_START, 12); + else + data.Initialize(SMSG_FLY_MODE_STOP, 12); + data.append(m_target->GetPackGUID()); + data << uint32(0); // unk + m_target->SendMessageToSet(&data, true); +} Index: src/game/NPCHandler.cpp =================================================================== --- src/game/NPCHandler.cpp (working copy) +++ src/game/NPCHandler.cpp (working copy) @@ -265,7 +265,7 @@ _player->ModifyMoney( -int32(proto->spellcost) ); if(spellInfo->powerType == 2) { - _player->addSpell(spellId,4); // ative = 4 for spell book of hunter's pet + _player->addSpell(spellId,4); // active = 4 for spell book of hunter's pet return; } @@ -299,7 +299,16 @@ uint64 guid; recv_data >> guid; - Creature *unit = ObjectAccessor::Instance().GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_NONE); + // fix for spirit healers (temp?) + Creature *temp = ObjectAccessor::Instance().GetCreature(*_player, guid); + if (!temp) + return; + + uint32 npcflags = UNIT_NPC_FLAG_NONE; + if(temp->isSpiritHealer()) + npcflags = UNIT_NPC_FLAG_SPIRITHEALER; + + Creature *unit = ObjectAccessor::Instance().GetNPCIfCanInteractWith(*_player, guid, npcflags); if (!unit) { sLog.outDebug( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -324,7 +333,16 @@ recv_data >> guid >> option; - Creature *unit = ObjectAccessor::Instance().GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_NONE); + // fix for spirit healers (temp?) + Creature *temp = ObjectAccessor::Instance().GetCreature(*_player, guid); + if (!temp) + return; + + uint32 npcflags = UNIT_NPC_FLAG_NONE; + if(temp->isSpiritHealer()) + npcflags = UNIT_NPC_FLAG_SPIRITHEALER; + + Creature *unit = ObjectAccessor::Instance().GetNPCIfCanInteractWith(*_player, guid, npcflags); if (!unit) { sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -345,7 +363,7 @@ recv_data >> guid; - Creature *unit = ObjectAccessor::Instance().GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_SPIRITHEALER); + Creature *unit = ObjectAccessor::Instance().GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_SPIRITHEALER); if (!unit) { sLog.outDebug( "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -432,33 +450,12 @@ void WorldSession::SendBindPoint(Creature *npc) { WorldPacket data; + uint32 bindspell = 3286, hearthstone_itemid = 6948; - // binding - data.Initialize( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) ); - data << float(_player->GetPositionX()); - data << float(_player->GetPositionY()); - data << float(_player->GetPositionZ()); - data << uint32(_player->GetMapId()); - data << uint32(_player->GetZoneId()); - SendPacket( &data ); - - DEBUG_LOG("New Home Position X is %f",_player->GetPositionX()); - DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY()); - DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ()); - DEBUG_LOG("New Home MapId is %u",_player->GetMapId()); - DEBUG_LOG("New Home ZoneId is %u",_player->GetZoneId()); - - // zone update - data.Initialize( SMSG_PLAYERBOUND, 12 ); - data << uint64(_player->GetGUID()); - data << uint32(_player->GetZoneId()); - SendPacket( &data ); - // update sql homebind sDatabase.PExecute("UPDATE `character_homebind` SET `map` = '%u', `zone` = '%u', `position_x` = '%f', `position_y` = '%f', `position_z` = '%f' WHERE `guid` = '%u'", _player->GetMapId(), _player->GetZoneId(), _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow()); // if a player lost/dropped hist hearthstone, he will get a new one - uint32 hearthstone_itemid = 6948; if ( !_player->HasItemCount(hearthstone_itemid, 1) && _player->GetBankItemCount(hearthstone_itemid) <1) { uint16 dest; @@ -475,18 +472,54 @@ } // send spell for bind 3286 bind magic - data.Initialize(SMSG_SPELL_START, (8+8+2+2+2+4+2) ); - data.append(_player->GetPackGUID()); + data.Initialize(SMSG_SPELL_START, (8+8+4+2+4+2+8) ); data.append(npc->GetPackGUID()); - data << uint16(3286) << uint16(0x00) << uint16(0x0F) << uint32(0x00)<< uint16(0x00); + data.append(npc->GetPackGUID()); + data << bindspell; // spell id + data << uint16(0); // cast flags + data << uint32(0); // time + data << uint16(0x0002); // target mask + data.append(_player->GetPackGUID()); // target's packed guid SendPacket( &data ); - data.Initialize(SMSG_SPELL_GO, (8+8+2+2+1+1+1+8+4+2+2)); - data.append(_player->GetPackGUID()); + data.Initialize(SMSG_SPELL_GO, (8+8+4+2+1+8+1+2+8)); data.append(npc->GetPackGUID()); - data << uint16(3286) << uint16(0x00) << uint8(0x0D) << uint8(0x01)<< uint8(0x01) << _player->GetGUID(); - data << uint32(0x00) << uint16(0x0200) << uint16(0x00); + data.append(npc->GetPackGUID()); + data << bindspell; // spell id + data << uint16(0x0100); // cast flags + data << uint8(0x01); // targets count + data << _player->GetGUID(); // target's full guid + data << uint8(0x00); // ? + data << uint16(0x0002); // target mask + data.append(_player->GetPackGUID()); // target's packed guid SendPacket( &data ); + + data.Initialize( SMSG_TRAINER_BUY_SUCCEEDED, (8+4)); + data << npc->GetGUID(); + data << bindspell; + SendPacket( &data ); + + // binding + data.Initialize( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) ); + data << float(_player->GetPositionX()); + data << float(_player->GetPositionY()); + data << float(_player->GetPositionZ()); + data << uint32(_player->GetMapId()); + data << uint32(_player->GetZoneId()); + SendPacket( &data ); + + DEBUG_LOG("New Home Position X is %f",_player->GetPositionX()); + DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY()); + DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ()); + DEBUG_LOG("New Home MapId is %u",_player->GetMapId()); + DEBUG_LOG("New Home ZoneId is %u",_player->GetZoneId()); + + // zone update + data.Initialize( SMSG_PLAYERBOUND, 8+4 ); + data << uint64(_player->GetGUID()); + data << uint32(_player->GetZoneId()); + SendPacket( &data ); + _player->PlayerTalkClass->CloseGossip(); } Index: src/game/Spell.cpp =================================================================== --- src/game/Spell.cpp (working copy) +++ src/game/Spell.cpp (working copy) @@ -1024,6 +1024,7 @@ return; Player* _player = (Player*)m_caster; + bool send = false; // init cooldown values uint32 cat = 0; @@ -1082,8 +1083,9 @@ time_t recTime = curTime+rec/1000; // in secs time_t catrecTime = curTime+catrec/1000; // in secs - WorldPacket data(SMSG_SPELL_COOLDOWN, (8+4+4+4+4)); + WorldPacket data(SMSG_SPELL_COOLDOWN, (8+1+4+4+4+4)); data << m_caster->GetGUID(); + data << uint8(0x0); // self spell cooldown if (rec > 0) @@ -1093,6 +1095,7 @@ { data << uint32(m_spellInfo->Id); data << uint32(rec); + send = true; } _player->AddSpellCooldown(m_spellInfo->Id,recTime); } @@ -1103,10 +1106,22 @@ { data << uint32(m_spellInfo->Id); data << uint32(catrec); + send = true; } _player->AddSpellCooldown(m_spellInfo->Id,catrecTime); } + if(send) // prevent send wrong (not complete packet) + { + _player->GetSession()->SendPacket(&data); + send = false; + } + data.clear(); + + data.Initialize(SMSG_SPELL_COOLDOWN, (8+1+4+4+4+4)); + data << m_caster->GetGUID(); + data << uint8(0x0); + if (catrec) { SpellCategoryStore::const_iterator i_scstore = sSpellCategoryStore.find(cat); @@ -1122,6 +1137,7 @@ { data << uint32(*i_scset); data << uint32(catrec); + send = true; } _player->AddSpellCooldown(*i_scset,catrecTime); } @@ -1130,6 +1146,9 @@ _player->GetSession()->SendPacket(&data); + if(send) // prevent send wrong (not complete packet) + _player->GetSession()->SendPacket(&data); + // show cooldown for item if(m_CastItem) _player->SetItemsCooldown(cat); @@ -1323,6 +1342,9 @@ if (m_caster->GetTypeId() != TYPEID_PLAYER) return; + if(((Player*)m_caster)->GetSession()->PlayerLoading()) // don't send cast results at loading time + return; + WorldPacket data(SMSG_CAST_RESULT, (4+2)); data << m_spellInfo->Id; if(result != 0) @@ -1334,6 +1356,9 @@ case CAST_FAIL_REQUIRES_XXX: data << uint32(m_spellInfo->RequiresSpellFocus); break; + case CAST_FAIL_YOU_NEED_TO_BE_IN_XXX: + data << uint32(m_spellInfo->AreaId); + break; } } else @@ -1545,13 +1570,13 @@ WorldPacket data; data.Initialize(SMSG_SPELL_FAILURE, (8+4+1)); - data.append(m_caster->GetGUID()); + data.append(m_caster->GetPackGUID()); data << m_spellInfo->Id; data << result; m_caster->SendMessageToSet(&data, true); data.Initialize(SMSG_SPELL_FAILED_OTHER, (8+4)); - data.append(m_caster->GetGUID()); + data.append(m_caster->GetPackGUID()); data << m_spellInfo->Id; m_caster->SendMessageToSet(&data, true); } @@ -1561,15 +1586,16 @@ if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - WorldPacket data( MSG_CHANNEL_UPDATE, 4 ); + WorldPacket data( MSG_CHANNEL_UPDATE, 8+4 ); + data.append(m_caster->GetPackGUID()); data << time; ((Player*)m_caster)->GetSession()->SendPacket( &data ); if(time == 0) { - m_caster->SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT,0); - m_caster->SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT+1,0); + m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,0); + m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL,0); } } @@ -1583,7 +1609,8 @@ target = ObjectAccessor::Instance().GetUnit(*m_caster, ((Player *)m_caster)->GetSelection()); - WorldPacket data( MSG_CHANNEL_START, (4+4) ); + WorldPacket data( MSG_CHANNEL_START, (8+4+4) ); + data.append(m_caster->GetPackGUID()); data << m_spellInfo->Id; data << duration; @@ -1601,9 +1628,9 @@ void Spell::SendResurrectRequest(Player* target) { - WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+1)); + WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+2+4)); data << m_caster->GetGUID(); - data << uint32(0) << uint8(0); + data << uint32(1) << uint16(0) << uint32(1); target->GetSession()->SendPacket(&data); } @@ -1780,7 +1807,7 @@ itemTarget = pItemTarget; gameObjTarget = pGOTarget; - damage = CalculateDamage((uint8)i)*DamageMultiplier; + damage = uint32(CalculateDamage((uint8)i)*DamageMultiplier); uint8 eff = m_spellInfo->Effect[i]; sLog.outDebug( "Spell: Effect : %u", eff); @@ -1947,6 +1974,12 @@ if(m_caster->hasUnitState(UNIT_STAT_CONFUSED)) castResult = CAST_FAIL_CANT_DO_WHILE_CONFUSED; + if((m_spellInfo->AttributesEx3 & 0x800) != 0) // need check... + castResult = CAST_FAIL_CAN_ONLY_USE_IN_BATTLEGROUNDS; + + if(m_spellInfo->AreaId && m_spellInfo->AreaId != m_caster->GetAreaId()) + castResult = CAST_FAIL_YOU_NEED_TO_BE_IN_XXX; + if(castResult!=0) return castResult; } @@ -1984,7 +2017,7 @@ { if (!m_targets.getUnitTarget()) { - castResult = CAST_FAIL_FAILED; + castResult = CAST_FAIL_NO_TARGET; break; } // Execute @@ -2021,7 +2054,7 @@ { if (!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER) { - castResult = CAST_FAIL_FAILED; + castResult = CAST_FAIL_NO_TARGET; break; } @@ -2063,7 +2096,7 @@ if(!learn_spellproto) { - castResult = CAST_FAIL_FAILED; + castResult = CAST_FAIL_SPELL_NOT_LEARNED; break; } @@ -2097,7 +2130,7 @@ { if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_targets.m_itemTarget ) { - castResult = CAST_FAIL_FAILED; + castResult = CAST_FAIL_INVALID_TARGET; break; } @@ -2121,7 +2154,7 @@ { if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetTypeId() != TYPEID_UNIT) { - castResult = CAST_FAIL_FAILED; + castResult = CAST_FAIL_INVALID_TARGET; break; } @@ -2157,7 +2190,7 @@ if (m_spellInfo->EffectImplicitTargetA[i] != TARGET_GAMEOBJECT) break; if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_targets.getGOTarget()) - return CAST_FAIL_FAILED; + return CAST_FAIL_INVALID_TARGET; // chance for fail at orange mining/herb/LockPicking gathering attempt if (m_targets.getGOTarget()->GetGoType() == GAMEOBJECT_TYPE_CHEST && m_caster->m_currentSpell == this) @@ -2206,7 +2239,7 @@ if(pet->isAlive()) { - castResult = CAST_FAIL_FAILED; + castResult = CAST_FAIL_ALREADY_HAVE_SUMMON; break; } break; @@ -2591,7 +2624,7 @@ if (msg != EQUIP_ERR_OK ) { p_caster->SendEquipError( msg, NULL, NULL ); - return uint8(CAST_FAIL_FAILED); // TODO: don't show two errors + return uint8(CAST_FAIL_DONT_REPORT); // TODO: don't show two errors } } break; @@ -2601,6 +2634,14 @@ if(!m_targets.m_itemTarget) return CAST_FAIL_ENCHANT_NOT_EXISTING_ITEM; break; + case SPELL_EFFECT_ENCHANT_HELD_ITEM: + { + if(!m_targets.m_itemTarget) + return CAST_FAIL_ENCHANT_NOT_EXISTING_ITEM; + if (!m_targets.m_itemTarget->IsEquipped()) + return CAST_FAIL_MUST_HAVE_ITEM_EQUIPPED; + break; + } case SPELL_EFFECT_DISENCHANT: { if(!m_targets.m_itemTarget) @@ -2609,31 +2650,23 @@ // prevent disenchanting in trade slot if( m_targets.m_itemTarget->GetOwnerGUID() != m_caster->GetGUID() ) return (uint8)CAST_FAIL_CANT_BE_DISENCHANTED; - + uint32 item_quality = m_targets.m_itemTarget->GetProto()->Quality; + // 2.0.x addon: Check player enchanting level agains the item desenchanting requirements + uint32 item_disenchantskilllevel = m_targets.m_itemTarget->GetProto()->RequiredDisenchantSkill; + if (item_disenchantskilllevel > p_caster->GetSkillValue(SKILL_ENCHANTING)) + return CAST_FAIL_SKILL_NOT_HIGH_ENOUGH; + if(item_quality > 4 || item_quality < 2) + return CAST_FAIL_CANT_BE_DISENCHANTED; + if(m_targets.m_itemTarget->GetProto()->Class != ITEM_CLASS_WEAPON && m_targets.m_itemTarget->GetProto()->Class != ITEM_CLASS_ARMOR) + return CAST_FAIL_CANT_BE_DISENCHANTED; if (!m_targets.m_itemTarget->GetProto()->DisenchantID) return CAST_FAIL_CANT_BE_DISENCHANTED; - - uint16 skill_val = p_caster->GetSkillValue(SKILL_ENCHANTING); - uint32 itemLevel = m_targets.m_itemTarget->GetProto()->ItemLevel; - if ((skill_val < 25 && itemLevel > 15) || - (skill_val < 50 && itemLevel > 20) || - (skill_val < 75 && itemLevel > 29) || - (skill_val < 100 && itemLevel > 34) || - (skill_val < 125 && itemLevel > 39) || - (skill_val < 150 && itemLevel > 44) || - (skill_val < 175 && itemLevel > 49) || - (skill_val < 200 && itemLevel > 54) || - (skill_val < 225 && itemLevel > 59) || - (skill_val < 275 && itemLevel > 63)) - { - return CAST_FAIL_SKILL_NOT_HIGH_ENOUGH; - } break; } case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: { - if(m_caster->GetTypeId() != TYPEID_PLAYER) return CAST_FAIL_FAILED; + if(m_caster->GetTypeId() != TYPEID_PLAYER) return CAST_FAIL_TARGET_IS_NOT_PLAYER; if(m_spellInfo->rangeIndex == 1 || m_spellInfo->rangeIndex == 2 || m_spellInfo->rangeIndex == 7) break; Item *pItem = ((Player*)m_caster)->GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED ); @@ -2699,7 +2732,7 @@ if(Target->isInFlight()) return; - if(m_spellInfo->Id == 8690 || m_spellInfo->Id == 556) + if(m_spellInfo->Id == 8690 || m_spellInfo->Id == 556 || m_spellInfo->Id == 7355) { Field *fields; QueryResult *result = sDatabase.PQuery("SELECT `map`,`zone`,`position_x`,`position_y`,`position_z` FROM `character_homebind` WHERE `guid` = '%u'", m_caster->GetGUIDLow()); @@ -2721,17 +2754,7 @@ ((Player*)Target)->TeleportTo(TC.mapId,TC.x,TC.y,TC.z,Target->GetOrientation()); } else - if(m_spellInfo->Id == 7355) // Stuck { - PlayerInfo const *info = objmgr.GetPlayerInfo(Target->getRace(), Target->getClass()); - - Target->SetUInt32Value(PLAYER_FARSIGHT, 0x01); - ((Player*)Target)->SetRecallPosition(Target->GetMapId(),Target->GetPositionX(),Target->GetPositionY(),Target->GetPositionZ(),Target->GetOrientation()); - ((Player*)Target)->TeleportTo(info->mapId, info->positionX, info->positionY,info->positionZ,Target->GetOrientation()); - Target->SetUInt32Value(PLAYER_FARSIGHT, 0x00); - } - else - { TeleportCoords const* TC = objmgr.GetTeleportCoords(id); if(!TC) { @@ -2752,8 +2775,8 @@ if(m_timer > casttime) m_timer = (casttime > 0 ? casttime : 0); - WorldPacket data(SMSG_SPELL_DELAYED, 12); - data << m_caster->GetGUID(); + WorldPacket data(SMSG_SPELL_DELAYED, 8+4); + data.append(m_caster->GetPackGUID()); data << uint32(delaytime); ((Player*)m_caster)->GetSession()->SendPacket(&data); Index: src/game/Mail.cpp =================================================================== --- src/game/Mail.cpp (working copy) +++ src/game/Mail.cpp (working copy) @@ -394,6 +394,10 @@ uint64 mailbox; recv_data >> mailbox; + //GameObject* obj = ObjectAccessor::Instance().GetGameObject(_player, mailbox); + //if(!obj || !obj->IsMailBox()) + // return; + Player* pl = _player; //load players mails, and mailed items @@ -401,7 +405,7 @@ pl ->_LoadMail(); WorldPacket data(SMSG_MAIL_LIST_RESULT, (200)); // guess size - data << uint8(0); + data << uint8(0); // mail's count uint8 mails_count = 0; std::deque::iterator itr; for (itr = pl->GetmailBegin(); itr != pl->GetmailEnd();itr++) @@ -409,16 +413,16 @@ if ((*itr)->state == DELETED) continue; mails_count++; - data << (uint32) (*itr)->messageID; - data << (uint8) (*itr)->messageType; // Message Type, once = 3 - data << (uint32) (*itr)->sender; // SenderID + data << (*itr)->messageID; + data << (*itr)->messageType; // Message Type, once = 3 + data << (*itr)->sender; // SenderID if ((*itr)->messageType == 0) data << (uint32) 0; // HIGHGUID_PLAYER data << (*itr)->subject.c_str(); // Subject string - once 00, when mail type = 3 data << (uint32) (*itr)->itemTextId; // sure about this data << (uint32) 0; // Constant if ((*itr)->messageType == 0) - data << (uint32) 0x29; // Constant + data << (uint32) 0x29; // Constant, messageType == 0 and 0x3D - message from gm... else data << (uint32) 0x3E; uint8 icount = 1; @@ -428,7 +432,7 @@ if(it = pl->GetMItem((*itr)->item_guid)) { //item prototype - data << (uint32) it->GetUInt32Value(OBJECT_FIELD_ENTRY); + data << it->GetUInt32Value(OBJECT_FIELD_ENTRY); icount = it->GetCount(); } else @@ -440,22 +444,35 @@ else data << (uint32) 0; // Any item attached - data << (uint32) (it ? it->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+0*3+0) : 0); - // Permanent enchantment id - data << (uint32) (it ? it->GetItemRandomPropertyId() : 0); - // Item random property Id + data << (uint32) 0; // items count? + + for(uint8 i = 0; i < 6; i++) // new 2.0.1 + { + data << getMSTime(); // probably time + if(i == 5) + { + data << (uint32) (it ? it->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+0*3+0) : 0); + data << (uint32) (it ? it->GetItemRandomPropertyId() : 0); + } + else + { + data << (uint32) 0; + data << (uint32) 0; + } + } + data << (uint32) 0; // not item->creator, it is enchating? data << (uint8) icount; // Attached item stack count //sometimes more than zero, not sure when int32 charges = (it) ? int32(it->GetUInt32Value(ITEM_FIELD_SPELL_CHARGES)) : 0; data << (uint32) charges; // item -> charges sure - uint32 maxDurability = (it)? it->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0; - uint32 curDurability = (it)? it->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0; - data << (uint32) maxDurability; // MaxDurability - data << (uint32) curDurability; // Durability - data << (uint32) (*itr)->money; // Gold - data << (uint32) (*itr)->COD; // COD - data << (uint32) (*itr)->checked; // checked + uint32 maxDurability = (it) ? it->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0; + uint32 curDurability = (it) ? it->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0; + data << maxDurability; // MaxDurability + data << curDurability; // Durability + data << (*itr)->money; // Gold + data << (*itr)->COD; // COD + data << (*itr)->checked; // checked data << (float) ((*itr)->time - time(NULL)) / DAY; // Time data << (uint32) 0; // Constant, something like end.. } Index: src/game/Pet.cpp =================================================================== --- src/game/Pet.cpp (working copy) +++ src/game/Pet.cpp (working copy) @@ -129,13 +129,19 @@ // this enables popup window (pet dismiss, cancel) break; case HUNTER_PET: + SetUInt32Value(UNIT_FIELD_BYTES_0, 0x2020100); //?? SetUInt32Value(UNIT_FIELD_BYTES_1,(fields[13].GetUInt32()<<8)); - SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN1 + UNIT_FLAG_RESTING); + SetUInt32Value(UNIT_FIELD_BYTES_2, 0x00022801); // can't be renamed (byte (0x02)) + SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN1);// + UNIT_FLAG_RESTING); // this enables popup window (pet abandon, cancel) // pet not renamed yet, let rename if wont if(!fields[17].GetBool()) - SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_RENAME); + { + //SetUInt32Value(UNIT_FIELD_BYTES_2, uint32(0x03 << 16)); // check it... + SetUInt32Value(UNIT_FIELD_BYTES_2, 0x00032801); // 0x03 + //SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_RENAME); // old, not working... + } SetUInt32Value(UNIT_MOD_CAST_SPEED, fields[14].GetUInt32() ); SetUInt32Value(UNIT_TRAINING_POINTS, (getLevel()<<16) + getUsedTrainPoint() ); @@ -147,7 +153,7 @@ sLog.outError("Pet have incorrect type (%u) for pet loading.",getPetType()); } InitStatsForLevel( petlevel); - SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0); + SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32()); SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, fields[6].GetUInt32()); SetUInt64Value(UNIT_FIELD_CREATEDBY, owner->GetGUID()); @@ -240,7 +246,7 @@ "VALUES (%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,'%s','%u','%u','%u','%u')", GetPetNumber(),GetEntry(), owner, GetUInt32Value(UNIT_FIELD_DISPLAYID), getLevel(), GetUInt32Value(UNIT_FIELD_PETEXPERIENCE), GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP), m_spells[0], m_spells[1], m_spells[2], m_spells[3], m_actState, GetPower(POWER_HAPPINESS),getloyalty(),getUsedTrainPoint(), name.c_str(), - uint32(HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_RENAME)?0:1),uint32(mode),(GetHealth()<1?1:GetHealth()),GetPower(POWER_MANA)); + uint32(((GetUInt32Value(UNIT_FIELD_BYTES_2) >> 16) == 3)?0:1),uint32(mode),(GetHealth()<1?1:GetHealth()),GetPower(POWER_MANA)); sDatabase.CommitTransaction(); break; } @@ -495,8 +501,12 @@ SetName(creature->GetName()); if(cinfo->type == CREATURE_TYPE_BEAST) { - SetUInt32Value(UNIT_FIELD_BYTES_1,creature->GetUInt32Value(UNIT_FIELD_BYTES_1)); + SetUInt32Value(UNIT_FIELD_BYTES_0, 0x2020100); + SetUInt32Value(UNIT_FIELD_BYTES_1, 0x100); + SetUInt32Value(UNIT_FIELD_BYTES_2, 0x00032801); // can be renamed (byte 0x03)... + //SetUInt32Value(UNIT_FIELD_BYTES_1,creature->GetUInt32Value(UNIT_FIELD_BYTES_1)); + SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED) ); SetUInt32Value(UNIT_TRAINING_POINTS, (getLevel()<<16) + getUsedTrainPoint() ); } Index: src/game/Opcodes.cpp =================================================================== --- src/game/Opcodes.cpp (working copy) +++ src/game/Opcodes.cpp (working copy) @@ -684,6 +684,7 @@ { SMSG_AUCTION_REMOVED_NOTIFICATION, "SMSG_AUCTION_REMOVED_NOTIFICATION"}, { CMSG_GROUP_RAID_CONVERT, "CMSG_GROUP_RAID_CONVERT"}, { CMSG_GROUP_ASSISTANT, "CMSG_GROUP_ASSISTANT"}, + { CMSG_GROUP_PROMOTE, "CMSG_GROUP_PROMOTE"}, { MSG_RAID_ICON_TARGET, "MSG_RAID_ICON_TARGET"}, { MSG_RAID_READY_CHECK, "MSG_RAID_READY_CHECK"}, { CMSG_BUYBACK_ITEM, "CMSG_BUYBACK_ITEM"}, @@ -771,8 +772,8 @@ { CMSG_AREA_SPIRIT_HEALER_QUERY, "CMSG_AREA_SPIRIT_HEALER_QUERY"}, { CMSG_AREA_SPIRIT_HEALER_QUEUE, "CMSG_AREA_SPIRIT_HEALER_QUEUE"}, { SMSG_AREA_SPIRIT_HEALER_TIME, "SMSG_AREA_SPIRIT_HEALER_TIME"}, - { CMSG_GM_UNTEACH, "CMSG_GM_UNTEACH"}, - { SMSG_HARDWARE_SURVEY_REQUEST, "SMSG_HARDWARE_SURVEY_REQUEST"}, + //{ CMSG_GM_UNTEACH, "CMSG_GM_UNTEACH"}, + //{ SMSG_HARDWARE_SURVEY_REQUEST, "SMSG_HARDWARE_SURVEY_REQUEST"}, { CMSG_HARDWARE_SURVEY_RESULTS, "CMSG_HARDWARE_SURVEY_RESULTS"}, { SMSG_WARDEN_DATA, "SMSG_WARDEN_DATA"}, { CMSG_WARDEN_DATA, "CMSG_WARDEN_DATA"}, @@ -795,7 +796,7 @@ { CMSG_MINIGAME_MOVE, "CMSG_MINIGAME_MOVE"}, { SMSG_MINIGAME_MOVE_FAILED, "SMSG_MINIGAME_MOVE_FAILED"}, { CMSG_GUILD_CHANGEINFO, "CMSG_GUILD_CHANGEINFO"}, - { SMSG_UNKNOWN_INFO, "SMSG_UNKNOWN_INFO"}, + { CMSG_SOCKET_ITEM, "CMSG_SOCKET_ITEM"}, { // unofficial - first appeared in 1.12 SMSG_OUTDOORPVP_NOTIFY, "SMSG_OUTDOORPVP_NOTIFY" }, Index: src/game/BattleGroundMgr.cpp =================================================================== --- src/game/BattleGroundMgr.cpp (working copy) +++ src/game/BattleGroundMgr.cpp (working copy) @@ -158,5 +158,5 @@ sLog.outDetail("BATTLEGROUND: Sending %s to %f,%f,%f,%f", pl->GetName(), x,y,z,O); pl->TeleportTo(mapid, x, y, z, O); - pl->SendInitWorldStates(mapid); + pl->SendInitWorldStates(); } Index: src/game/ObjectGridLoader.cpp =================================================================== --- src/game/ObjectGridLoader.cpp (working copy) +++ src/game/ObjectGridLoader.cpp (working copy) @@ -160,7 +160,7 @@ uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; QueryResult *result = sDatabase.PQuery( // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - "SELECT `id`,`creature`.`map`,`creature`.`position_x`,`creature`.`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`spawn_position_x`,`spawn_position_y`,`spawn_position_z`,`curhealth`,`curmana`,`respawntime`,`state`,`MovementType`,`auras`,`creature`.`guid`" + "SELECT `id`,`creature`.`map`,`creature`.`position_x`,`creature`.`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`spawn_position_x`,`spawn_position_y`,`spawn_position_z`,`curhealth`,`curmana`,`respawntime`,`DeathState`,`MovementType`,`auras`,`creature`.`guid`" "FROM `creature` LEFT JOIN `creature_grid` ON `creature`.`guid` = `creature_grid`.`guid` " "LEFT JOIN `creature_respawn` ON ((`creature`.`guid`=`creature_respawn`.`guid`) AND (`creature_respawn`.`instance` = '%u'))" "WHERE `grid` = '%u' AND `cell` = '%u' AND `creature_grid`.`map` = '%u' ", i_map->GetInstanceId(), i_grid.GetGridId(), cell_id, i_map->GetId()); Index: src/game/LFGHandler.cpp =================================================================== --- src/game/LFGHandler.cpp (revision 0) +++ src/game/LFGHandler.cpp (working copy) @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2005,2006,2007 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 "WorldSession.h" +#include "Log.h" +#include "Database/DatabaseEnv.h" +#include "Player.h" +#include "WorldPacket.h" +#include "ObjectMgr.h" + +void WorldSession::HandleLfgAutoJoinOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_SET_LFG_AUTO_JOIN"); +} + +void WorldSession::HandleLfgCancelAutoJoinOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_UNSET_LFG_AUTO_JOIN"); +} + +void WorldSession::HandleLfmAutoAddMembersOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_SET_LFM_AUTOADD"); +} + +void WorldSession::HandleLfmCancelAutoAddmembersOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_UNSET_LFM_AUTOADD"); +} + +void WorldSession::HandleLfgClearOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_LOOKING_FOR_GROUP_CLEAR"); + sDatabase.PExecute("DELETE FROM `lfg` WHERE `guid` = '%u' AND `lfg_type` = '0'", _player->GetGUIDLow()); +} + +void WorldSession::HandleLfmSetNoneOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_SET_LOOKING_FOR_NONE"); + sDatabase.PExecute("UPDATE `lfg` SET `entry` = '0', `type` = '0' WHERE `guid` = '%u' AND `lfg_type` = '1'", _player->GetGUIDLow()); +} + +void WorldSession::HandleLfmSetOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_SET_LOOKING_FOR_MORE"); + recv_data.hexlike(); + uint32 temp, entry, type; + uint8 lfg_type = 1; + + recv_data >> temp; + + entry = ( temp & 0xFFFF); + type = ( (temp >> 24) & 0xFFFF); + //sDatabase.PExecute("UPDATE `lfg` SET `entry` = '0', `type` = '0' WHERE `guid` = '%u'", _player->GetGUIDLow()); + sDatabase.PExecute("UPDATE `lfg` SET `entry` = '%u', `type` = '%u', `lfg_type` = '1' WHERE `guid` = '%u' AND `slot` = '1'", entry, type, _player->GetGUIDLow()); + sLog.outDebug("LFM set: temp %u, zone %u, type %u", temp, entry, type); + SendLfgResult(type, entry); +} + +void WorldSession::HandleLfgSetCommentOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_SET_COMMENTARY"); + std::string comment; + uint32 number; + recv_data.hexlike(); + + QueryResult *result = sDatabase.PQuery("SELECT COUNT(*) FROM `lfg` WHERE `guid` = '%u'", _player->GetGUIDLow()); + + if(result) + { + Field *fields = result->Fetch(); + number = fields[0].GetUInt32(); + if(number == 0) + for(uint8 i = 0; i < 3; i++) + sDatabase.PExecute("INSERT INTO `lfg` (`guid`, `slot`, `comment`) VALUES ('%u', '%u', '')", _player->GetGUIDLow(), i); + recv_data >> comment; + sLog.outDebug("LFG comment %s", comment.c_str()); + sDatabase.PExecute("UPDATE `lfg` SET `comment` = '%s' WHERE `guid` = '%u'", comment.c_str(), _player->GetGUIDLow()); + } + else + sLog.outDebug("strange, DB problem?"); +} + +void WorldSession::HandleLookingForGroup(WorldPacket& recv_data) +{ + sLog.outDebug("MSG_LOOKING_FOR_GROUP"); + recv_data.hexlike(); + WorldPacket data; + uint32 type, entry, unk; + + recv_data >> type >> entry >> unk; + sLog.outDebug("MSG_LOOKING_FOR_GROUP: type %u, entry %u, unk %u", type, entry, unk); + //sDatabase.PExecute("UPDATE `lfg` SET `entry` = '0', `type` = '0' WHERE `guid` = '%u'", _player->GetGUIDLow()); + sDatabase.PExecute("UPDATE `lfg` SET `entry` = '%u', `type` = '%u', `lfg_type` = '1' WHERE `guid` = '%u' AND `slot` = '1'", entry, type, _player->GetGUIDLow()); + SendLfgResult(type, entry); +} + +void WorldSession::SendLfgResult(uint32 type, uint32 entry) +{ + WorldPacket data; + std::string comment; + uint32 number; + QueryResult *result = sDatabase.PQuery("SELECT COUNT(*) FROM `lfg` WHERE `type` = '%u' AND `entry` = '%u'", type, entry); + + if(result) + { + Field *fields = result->Fetch(); + number = fields[0].GetUInt32(); + } + else + { + return; + } + + data.Initialize(MSG_LOOKING_FOR_GROUP); + data << type; // type + data << entry; // entry from LFGDungeons.dbc + data << number; // count + data << number; // count again, strange + + result = sDatabase.PQuery("SELECT `guid`, `lfg_type`, `comment` FROM `lfg` WHERE `type` = '%u' AND `entry` = '%u'", type, entry); + if(result) + { + Field *fields = result->Fetch(); + do + { + uint64 guid = fields[0].GetUInt64(); + comment = fields[2].GetString(); + Player *plr = objmgr.GetPlayer(guid); + if(plr) + { + data.append(plr->GetPackGUID()); // packed guid + data << plr->getLevel(); // level + data << plr->GetZoneId(); // current zone + data << fields[1].GetUInt8(); // 0x00 - LFG, 0x01 - LFM + for(uint8 i = 0; i < 3; i++) // we have three slots + { + QueryResult *result2 = sDatabase.PQuery("SELECT `entry`, `type` FROM `lfg` WHERE `slot` = '%u' AND `guid` = '%u'", i, plr->GetGUID()); + if(result2) + { + Field *fields = result2->Fetch(); + data << uint32( fields[0].GetUInt32() | (fields[1].GetUInt32() << 24) ); + } + else + { + data << uint32(0x00); + } + delete result2; + } + data << comment; // commentary + Group *group = plr->groupInfo.group; + if(group) + { + data << group->GetMembersCount()-1; // count of group members without group leader + for(uint8 i = 0; i < group->GetMembersCount(); i++) + { + Player *member = objmgr.GetPlayer(group->GetMemberGUID(i)); + if(member && member->GetGUID() != plr->GetGUID()) + { + data.append(member->GetPackGUID()); // packed guid + data << member->getLevel(); // player level + } + } + } + else + { + data << uint32(0x00); + } + } + } + while( result->NextRow() ); + delete result; + } + else + return; + data.hexlike(); + SendPacket(&data); +} + +void WorldSession::HandleSetLfgOpcode( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_SET_LOOKING_FOR_GROUP"); + recv_data.hexlike(); + uint32 slot, temp, entry, type; + + recv_data >> slot >> temp; + + entry = ( temp & 0xFFFF); + type = ( (temp >> 24) & 0xFFFF); + + sDatabase.PExecute("UPDATE `lfg` SET `entry` = '%u', `type` = '%u' WHERE `guid` = '%u' and `slot` = '%u'", entry, type, _player->GetGUIDLow(), slot); + + sLog.outDebug("LFG set: looknumber %u, temp %X, type %u, entry %u", slot, temp, type, entry); + SendLfgResult(type, entry); +} Index: src/game/Creature.cpp =================================================================== --- src/game/Creature.cpp (working copy) +++ src/game/Creature.cpp (working copy) @@ -429,6 +429,8 @@ case RACE_TAUREN: pPlayer->PlayerTalkClass->SendGossipMenu(5864,GetGUID()); break; case RACE_TROLL: pPlayer->PlayerTalkClass->SendGossipMenu(5816,GetGUID()); break; case RACE_UNDEAD_PLAYER:pPlayer->PlayerTalkClass->SendGossipMenu( 624,GetGUID()); break; + case RACE_BLOODELF: pPlayer->PlayerTalkClass->SendGossipMenu(5862,GetGUID()); break; + case RACE_DRAENEI: pPlayer->PlayerTalkClass->SendGossipMenu(5864,GetGUID()); break; } } return false; @@ -607,7 +609,7 @@ break; case GOSSIP_OPTION_SPIRITHEALER: if( player->isDead() ) - player->GetSession()->SendSpiritResurrect(); + CastSpell(player,17251,true); // effect implemented in void Spell::EffectDummy(uint32 i) break; case GOSSIP_OPTION_QUESTGIVER: player->PrepareQuestMenu( guid ); @@ -880,11 +882,7 @@ << (float)(0) << "," //spawn_orientation << GetHealth() << "," //curhealth << GetPower(POWER_MANA) << "," //curmana - - << (uint32)(m_deathState) << "," // is it really death state or just state? - //or - //<< (uint32)(m_state) << "," // is it really death state or just state? - + << (uint32)(m_deathState) << "," //DeathState (0 or 65) << GetDefaultMovementType() << "," // default movement generator type << "'')"; // should save auras @@ -1035,9 +1033,6 @@ } else sLog.outErrorDb("Error: invalid faction (%u) for creature (GUIDLow: %u Entry: %u)", cinfo->faction, GetGUIDLow(),Entry); - if (cinfo->mount != 0) - Mount(cinfo->mount); - m_spells[0] = cinfo->spell1; m_spells[1] = cinfo->spell2; m_spells[2] = cinfo->spell3; @@ -1064,8 +1059,8 @@ { bool external = (result != NULL); if (!external) - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - result = sDatabase.PQuery("SELECT `id`,`map`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`spawn_position_x`,`spawn_position_y`,`spawn_position_z`,`curhealth`,`curmana`,`respawntime`,`state`,`MovementType`,`auras` " + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + result = sDatabase.PQuery("SELECT `id`,`map`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`spawn_position_x`,`spawn_position_y`,`spawn_position_z`,`curhealth`,`curmana`,`respawntime`,`DeathState`,`MovementType`,`auras` " "FROM `creature` LEFT JOIN `creature_respawn` ON ((`creature`.`guid`=`creature_respawn`.`guid`) AND (`creature_respawn`.`instance` = '%u')) WHERE `creature`.`guid` = '%u'", InstanceId, guid); if(!result) @@ -1137,7 +1132,7 @@ if(!external) delete result; LoadFlagRelatedData(); - + AIM_Initialize(); return true; } @@ -1494,3 +1489,50 @@ if ( HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER ) ) _LoadQuests(); } + +//creature_addon table +bool Creature::LoadCreaturesAddon(uint32 guidlow) +{ + // 0 1 2 3 4 5 6 7 8 9 + QueryResult *result = sDatabase.PQuery("SELECT `mount`,`bytes0`,`bytes1`,`bytes2`,`emote`,`aura`,`auraflags`,`auralevels`,`auraapplications`,`aurastate` FROM `creature_addon` WHERE `guid` = '%u'", guidlow); + if(!result) + { + return false; + } + + Field *fields = result->Fetch(); + + if (fields[0].GetUInt32() != 0) + Mount(fields[0].GetUInt32()); + + if (fields[1].GetUInt32() != 0) + SetUInt32Value(UNIT_FIELD_BYTES_0, fields[1].GetUInt32()); + + if (fields[2].GetUInt32() != 0) + SetUInt32Value(UNIT_FIELD_BYTES_1, fields[2].GetUInt32()); + + if (fields[3].GetUInt32() != 0) + SetUInt32Value(UNIT_FIELD_BYTES_2, fields[3].GetUInt32()); + + if (fields[4].GetUInt32() != 0) + SetUInt32Value(UNIT_NPC_EMOTESTATE, fields[4].GetUInt32()); + + if (fields[5].GetUInt32() != 0) + SetUInt32Value(UNIT_FIELD_AURA, fields[5].GetUInt32()); + + if (fields[6].GetUInt32() != 0) + SetUInt32Value(UNIT_FIELD_AURAFLAGS, fields[6].GetUInt32()); + + if (fields[7].GetUInt32() != 0) + SetUInt32Value(UNIT_FIELD_AURALEVELS, fields[7].GetUInt32()); + + if (fields[8].GetUInt32() != 0) + SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, fields[8].GetUInt32()); + + if (fields[9].GetUInt32() != 0) + SetUInt32Value(UNIT_FIELD_AURASTATE, fields[9].GetUInt32()); + + delete result; + + return true; +} Index: src/game/ObjectMgr.cpp =================================================================== --- src/game/ObjectMgr.cpp (working copy) +++ src/game/ObjectMgr.cpp (working copy) @@ -642,8 +642,8 @@ // Load playercreate { - // 0 1 2 3 4 5 6 7 - QueryResult *result = sDatabase.Query("SELECT `race`,`class`,`map`,`zone`,`position_x`,`position_y`,`position_z`,`displayID` FROM `playercreateinfo`"); + // 0 1 2 3 4 5 6 + QueryResult *result = sDatabase.Query("SELECT `race`,`class`,`map`,`zone`,`position_x`,`position_y`,`position_z` FROM `playercreateinfo`"); uint32 count = 0; @@ -684,8 +684,14 @@ pInfo->positionX = fields[4].GetFloat(); pInfo->positionY = fields[5].GetFloat(); pInfo->positionZ = fields[6].GetFloat(); - pInfo->displayId = fields[7].GetUInt16(); + ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(fields[0].GetUInt32()); + if(rEntry) + { + pInfo->displayId_m = rEntry->model_m; + pInfo->displayId_f = rEntry->model_f; + } + bar.step(); count++; } @@ -1003,7 +1009,7 @@ PlayerInfo* pInfo = &playerInfo[race][class_]; // skip non loaded combinations - if(!pInfo->displayId) + if(!pInfo->displayId_m || !pInfo->displayId_f) continue; // fatal error if no level 1 data @@ -1032,7 +1038,7 @@ if(race >= MAX_RACES) return; if(class_ >= MAX_CLASSES) return; PlayerInfo const* pInfo = &playerInfo[race][class_]; - if(pInfo->displayId==0) return; + if(pInfo->displayId_m==0 || pInfo->displayId_f==0) return; if(level <= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) *info = pInfo->levelInfo[level-1]; @@ -1223,7 +1229,9 @@ // 83 84 85 86 87 88 89 90 91 92 "`RewRepFaction1`,`RewRepFaction2`,`RewRepFaction3`,`RewRepFaction4`,`RewRepFaction5`,`RewRepValue1`,`RewRepValue2`,`RewRepValue3`,`RewRepValue4`,`RewRepValue5`," // 93 94 95 96 97 98 99 100 101 102 103 - "`RewOrReqMoney`,`RewXP`,`RewSpell`,`PointMapId`,`PointX`,`PointY`,`PointOpt`,`OfferRewardEmote`,`RequestItemsEmote`,`CompleteScript`,`Repeatable`" + "`RewOrReqMoney`,`RewXP`,`RewSpell`,`PointMapId`,`PointX`,`PointY`,`PointOpt`,`DetailsEmote1`,`DetailsEmote2`,`DetailsEmote3`,`DetailsEmote4`," + // 104 105 106 107 108 109 110 111 + "`IncompleteEmote`,`CompleteEmote`,`OfferRewardEmote1`,`OfferRewardEmote2`,`OfferRewardEmote3`,`OfferRewardEmote4`,`CompleteScript`,`Repeatable`" " FROM `quest_template`"); if(result == NULL) { @@ -2097,7 +2105,7 @@ path = dest_i->second.ID; } -uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team ) +uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team ) { uint16 mount_id = 0; @@ -2105,30 +2113,30 @@ if(node) { if (team == ALLIANCE) - switch(node->alliance_mount_type) - { - case 541: - mount_id = 1147; // alliance - break; - case 3837: - mount_id = 479; // nightelf - break; - //case 17760: - // unknown outer bg mount? - } - else if (team == HORDE) - switch(node->horde_mount_type) - { - case 2224: - mount_id = 295; // horde - break; - case 3574: - mount_id = 1566; // undead - break; - //case 17760: - // unknown outer bg mount? - } + { + CreatureInfo const *ci = objmgr.GetCreatureTemplate(node->alliance_mount_type); + if(ci) + mount_id = ci->randomDisplayID(); + } + if (team == HORDE) + { + CreatureInfo const *ci = objmgr.GetCreatureTemplate(node->horde_mount_type); + if(ci) + mount_id = ci->randomDisplayID(); + } + + + + + + + + + + + + } return mount_id; Index: src/game/Map.cpp =================================================================== --- src/game/Map.cpp (working copy) +++ src/game/Map.cpp (working copy) @@ -462,7 +462,7 @@ if (player->GetPet()) player->GetPet()->SetInstanceId(this->GetInstanceId()); player->SetInstanceId(this->GetInstanceId()); - player->SendInitWorldStates(player->GetMapId()); + player->SendInitWorldStates(); sLog.outDetail("MAP: Player '%s' entered the instance '%u' of map '%s'", player->GetName(), GetInstanceId(), GetMapName()); Index: win/VC71/game.vcproj =================================================================== --- win/VC71/game.vcproj (working copy) +++ win/VC71/game.vcproj (working copy) @@ -132,6 +132,9 @@ RelativePath="..\..\src\game\AddonHandler.h"> + + + + + + @@ -307,6 +311,10 @@ > + +