int32 Item::AddEnchantment( EnchantEntry* Enchantment, uint32 Duration, bool Perm /* = false */, bool apply /* = true */, bool RemoveAtLogout /* = false */, uint32 Slot_, uint32 RandomSuffix ) { int32 Slot = Slot_; m_isDirty = true; /* if(Perm) { if(Slot_) { Slot=Slot_; } else { Slot = FindFreeEnchantSlot(Enchantment); } } else { if(Enchantment->EnchantGroups > 1) // replaceable temp enchants { Slot = 1; RemoveEnchantment(1); } else { Slot = FindFreeEnchantSlot(Enchantment);*/ /* Slot = Enchantment->type ? 3 : 0; //that's 's code for(uint32 Index = ITEM_FIELD_ENCHANTMENT_09; Index < ITEM_FIELD_ENCHANTMENT_32; Index += 3) { if(m_uint32Values[Index] == 0) break;; ++Slot; } //Slot = FindFreeEnchantSlot(Enchantment); // reach max of temp enchants if(Slot >= 11) return -1; */ /*} } */ // Create the enchantment struct. EnchantmentInstance Instance; Instance.ApplyTime = UNIXTIME; Instance.BonusApplied = false; Instance.Slot = Slot; Instance.Enchantment = Enchantment; Instance.Duration = Duration; Instance.RemoveAtLogout = RemoveAtLogout; Instance.RandomSuffix = RandomSuffix; // Set the enchantment in the item fields. uint32 EnchantBase = Slot * 3 + ITEM_FIELD_ENCHANTMENT_1_1; SetUInt32Value( EnchantBase, Enchantment->Id ); SetUInt32Value( EnchantBase + 1, (uint32)Instance.ApplyTime ); SetUInt32Value( EnchantBase + 2, 0 ); // charges // Add it to our map. Enchantments[Slot] = Instance; if( m_owner == NULL ) return Slot; Player* owner = m_owner; // Add the removal event. if( Duration ) { sEventMgr.AddEvent( TO_ITEM(this), &Item::RemoveEnchantment, uint32(Slot), EVENT_REMOVE_ENCHANTMENT1 + Slot, Duration * 1000, 1, 0 ); } // No need to send the log packet, if the owner isn't in world (we're still loading) if( !owner->IsInWorld() ) return Slot; if( apply ) { WorldPacket EnchantLog( SMSG_ENCHANTMENTLOG, 25 ); EnchantLog << m_owner->GetGUID(); EnchantLog << m_owner->GetGUID(); EnchantLog << m_uint32Values[OBJECT_FIELD_ENTRY]; EnchantLog << Enchantment->Id; EnchantLog << uint8(0); owner->GetSession()->SendPacket( &EnchantLog ); if( owner->GetTradeTarget() ) { owner->SendTradeUpdate(); } /* Only apply the enchantment bonus if we're equipped */ uint8 slot = m_owner->GetItemInterface()->GetInventorySlotByGuid( GetGUID() ); if( slot > EQUIPMENT_SLOT_START && slot < EQUIPMENT_SLOT_END ) ApplyEnchantmentBonus( Slot, APPLY ); } owner->SaveToDB(false); return Slot; }
void WorldSession::SendLfgUpdateList(uint32 dungeonID) { if (!sWorld.getConfig(CONFIG_BOOL_LFR_ENABLE)) { DEBUG_LOG("SendLfgUpdateList %u failed - Raid finder disabled", GetPlayer()->GetObjectGuid().GetCounter()); return; } DEBUG_LOG("SMSG_LFG_SEARCH_RESULTS %u dungeonentry: %u ", GetPlayer()->GetObjectGuid().GetCounter(), dungeonID); LFGDungeonEntry const* dungeon = sLFGMgr.GetDungeon(dungeonID); if (!dungeon) return; Team team = sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP) ? TEAM_NONE : GetPlayer()->GetTeam(); GuidSet groups = sLFGMgr.GetDungeonGroupQueue(dungeon, team); GuidSet players = sLFGMgr.GetDungeonPlayerQueue(dungeon, team); uint32 groupCount = groups.size(); uint32 groupSize = 4+4; for (GuidSet::const_iterator itr = groups.begin(); itr != groups.end(); ++itr) { Group* pGroup = sObjectMgr.GetGroup(*itr); if (!pGroup) continue; Player* pLeader = sObjectMgr.GetPlayer(pGroup->GetLeaderGuid()); if (!pLeader) continue; sLFGMgr.GetLFGPlayerState(pLeader->GetObjectGuid())->AddFlags(LFG_MEMBER_FLAG_CHARINFO | LFG_MEMBER_FLAG_COMMENT | LFG_MEMBER_FLAG_GROUPLEADER | LFG_MEMBER_FLAG_GROUPGUID | LFG_MEMBER_FLAG_ROLES | LFG_MEMBER_FLAG_AREA | LFG_MEMBER_FLAG_STATUS | LFG_MEMBER_FLAG_BIND); uint32 flags = sLFGMgr.GetLFGPlayerState(pLeader->GetObjectGuid())->GetFlags(); if (flags & LFG_MEMBER_FLAG_COMMENT) groupSize += sLFGMgr.GetLFGPlayerState(pLeader->GetObjectGuid())->GetComment().size()+1; if (flags & LFG_MEMBER_FLAG_ROLES) groupSize +=3; if (flags & LFG_MEMBER_FLAG_BIND) groupSize += (8+4); players.insert(*itr); for (GroupReference *itr2 = pGroup->GetFirstMember(); itr2 != NULL; itr2 = itr2->next()) { Player* player = itr2->getSource(); if (!player || player == pLeader) continue; sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->AddFlags(LFG_MEMBER_FLAG_GROUPLEADER | LFG_MEMBER_FLAG_GROUPGUID | LFG_MEMBER_FLAG_STATUS); sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->RemoveFlags(LFG_MEMBER_FLAG_CHARINFO | LFG_MEMBER_FLAG_COMMENT | LFG_MEMBER_FLAG_ROLES | LFG_MEMBER_FLAG_AREA | LFG_MEMBER_FLAG_BIND); players.insert(player->GetObjectGuid()); } } uint32 playerCount = players.size(); uint32 playerSize = 4+4; uint32 guidsSize = 0; GuidSet playersUpdated; playersUpdated.clear(); for(GuidSet::const_iterator itr = players.begin(); itr != players.end(); ++itr) { Player* player = sObjectMgr.GetPlayer(*itr); if (!player || !player->IsInWorld()) continue; uint32 flags = sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->GetFlags(); playerSize += (8+4); if (flags & LFG_MEMBER_FLAG_CHARINFO) playerSize += (1+1+1+3+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4); if (flags & LFG_MEMBER_FLAG_COMMENT) playerSize += sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->GetComment().size()+1; // comment if (flags & LFG_MEMBER_FLAG_GROUPLEADER) playerSize += 1; if (flags & LFG_MEMBER_FLAG_GROUPGUID) playerSize += 8; if (flags & LFG_MEMBER_FLAG_ROLES) playerSize += 1; if (flags & LFG_MEMBER_FLAG_AREA) playerSize += 4; if (flags & LFG_MEMBER_FLAG_STATUS) playerSize += 1; if (flags & LFG_MEMBER_FLAG_BIND) playerSize += (8+4); if (flags & LFG_MEMBER_FLAG_UPDATE) { sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->RemoveFlags(LFG_MEMBER_FLAG_UPDATE); playersUpdated.insert(player->GetObjectGuid()); guidsSize += 8; } } WorldPacket data(SMSG_LFG_SEARCH_RESULTS, 4 + 4 + 1 + groupSize + playerSize + guidsSize); data << uint32(dungeon->type); // type data << uint32(dungeon->Entry()); // entry from LFGDungeons.dbc if (!playersUpdated.empty()) { data << uint8(playersUpdated.size()); for (GuidSet::const_iterator itr = playersUpdated.begin(); itr != playersUpdated.end(); ++itr) { data << *itr; // player guid } } else data << uint8(0); if (!groups.empty()) { data << uint32(groupCount); // groups count data << uint32(groupCount); // groups count2 for (GuidSet::const_iterator itr = groups.begin(); itr != groups.end(); ++itr) { Group* group = sObjectMgr.GetGroup(*itr); if (!group) continue; Player* leader = sObjectMgr.GetPlayer(group->GetLeaderGuid()); uint32 flags = sLFGMgr.GetLFGPlayerState(leader->GetObjectGuid())->GetFlags(); data << group->GetObjectGuid(); data << flags; if (flags & LFG_MEMBER_FLAG_COMMENT) { data << sLFGMgr.GetLFGPlayerState(leader->GetObjectGuid())->GetComment().c_str(); } if (flags & LFG_MEMBER_FLAG_ROLES) { for (int i = 0; i < 3; ++i) { // need implement function for roles count calculation. or not need? data << uint8(0); } } if (flags & LFG_MEMBER_FLAG_BIND) { ObjectGuid instanceGuid; uint32 encounters = 0; if (InstancePlayerBind* bind = leader->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) { if (DungeonPersistentState* state = bind->state) { instanceGuid = state->GetInstanceGuid(); encounters = state->GetCompletedEncountersMask(); } } data << instanceGuid; data << encounters; } } } else { data << uint32(0); data << uint32(0); // groups count2 } if (!players.empty()) { data << uint32(playerCount); // players count data << uint32(playerCount); // players count 2 for(GuidSet::const_iterator itr = players.begin(); itr != players.end(); ++itr) { Player* player = sObjectMgr.GetPlayer(*itr); if (!player || !player->IsInWorld()) continue; uint32 flags = sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->GetFlags(); data << *itr; // guid data << flags; // flags if (flags & LFG_MEMBER_FLAG_CHARINFO) // charinfo { data << uint8(player->getLevel()); data << uint8(player->getClass()); data << uint8(player->getRace()); for(int i = 0; i < 3; ++i) data << uint8(player->GetTalentsCount(i)); // spent talents count in specific tab data << uint32(player->GetArmor()); // armor data << uint32(player->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SPELL)); // spd data << uint32(player->SpellBaseHealingBonusDone(SPELL_SCHOOL_MASK_SPELL)); // heal data << uint32(player->GetRatingBonusValue(CR_CRIT_MELEE)); // crit rating melee data << uint32(player->GetRatingBonusValue(CR_CRIT_RANGED)); // crit rating ranged data << uint32(player->GetRatingBonusValue(CR_CRIT_SPELL)); // crit rating spell data << float(player->GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER)*5); // mp5 data << float(player->GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER)*5); // unk data << uint32(player->GetTotalAttackPowerValue(BASE_ATTACK)); // attack power data << uint32(player->GetTotalStatValue(STAT_AGILITY)); // agility data << uint32(player->GetMaxHealth()); // health data << uint32(player->GetMaxPower(player->GetPowerType())); // power data << uint32(player->GetFreeTalentPoints()); // free talent points (TOM_RUS) data << float(0); // unk data << uint32(player->GetRatingBonusValue(CR_DEFENSE_SKILL)); // defence rating data << uint32(player->GetRatingBonusValue(CR_DODGE)); // dodge rating data << uint32(player->GetRatingBonusValue(CR_BLOCK)); // block rating data << uint32(player->GetRatingBonusValue(CR_PARRY)); // parry rating data << uint32(player->GetRatingBonusValue(CR_HASTE_MELEE)); // crit rating data << uint32(player->GetRatingBonusValue(CR_EXPERTISE)); // expertize } if (flags & LFG_MEMBER_FLAG_COMMENT) data << sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->GetComment().c_str(); // comment if (flags & LFG_MEMBER_FLAG_GROUPLEADER) // Group leader flag { bool isLeader = false; if (Group* group = player->GetGroup()) if (player->GetObjectGuid() == group->GetLeaderGuid()) isLeader = true; data << uint8(isLeader); } if (flags & LFG_MEMBER_FLAG_GROUPGUID) // Group guid { ObjectGuid groupGuid = ObjectGuid(); if (Group* group = player->GetGroup()) groupGuid = group->GetObjectGuid(); data << groupGuid; } if (flags & LFG_MEMBER_FLAG_ROLES) // rolesMask data << uint8(sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->GetRoles()); if (flags & LFG_MEMBER_FLAG_AREA) // Area data << uint32(player->GetAreaId()); if (flags & LFG_MEMBER_FLAG_STATUS) // status data << uint8(0); if (flags & LFG_MEMBER_FLAG_BIND) { ObjectGuid instanceGuid; uint32 encounters = 0; if (InstancePlayerBind* bind = player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) { if (DungeonPersistentState* state = bind->state) { instanceGuid = state->GetInstanceGuid(); encounters = state->GetCompletedEncountersMask(); } } data << instanceGuid; data << encounters; } } } else { data << uint32(0); // players count data << uint32(0); // unk } SendPacket(&data); }
void WorldSession::DoLootRelease(uint64 lguid) { Player *player = GetPlayer(); Loot *loot; player->SetLootGUID(0); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned in next tick if (go->GetUseCount() >= go->GetGOValue()->FishingHole.MaxOpens) go->SetLootState(GO_JUST_DEACTIVATED); else go->SetLootState(GO_READY); } else go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else { // not fully looted object go->SetLootState(GO_ACTIVATED, player); // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) loot->roundRobinPlayer = 0; } } else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG { Corpse* corpse = ObjectAccessor::GetCorpse(*player, lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } } else if (IS_ITEM_GUID(lguid)) { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) return; ItemTemplate const* proto = pItem->GetTemplate(); // destroy only 5 items from stack in case prospecting and milling if (proto->Flags & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE)) { pItem->m_lootGenerated = false; pItem->loot.clear(); uint32 count = pItem->GetCount(); // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. if (count > 5) count = 5; player->DestroyItemCount(pItem, count, true); } else { // Only delete item if no loot or money (unlooted loot is saved to db) or if it isn't an openable item if (pItem->loot.isLooted() || !(proto->Flags & ITEM_PROTO_FLAG_OPENABLE)) player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } return; // item can be looted only single player } else { Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid); bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING); if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &creature->loot; if (loot->isLooted()) { creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); // skip pickpocketing loot for speed, skinning timer reduction is no-op in fact if (!creature->IsAlive()) creature->AllLootRemovedFromCorpse(); loot->clear(); } else { // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { loot->roundRobinPlayer = 0; if (Group* group = player->GetGroup()) { group->SendLooter(creature, NULL); // force update of dynamic flags, otherwise other group's players still not able to loot. creature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); } } } } //Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetGUID()); }
void WorldSession::HandleWhoOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received opcode CMSG_WHO"); // recv_data.hexlike(); uint32 level_min, level_max, racemask, classmask, zones_count, str_count; uint32 zoneids[10]; // 10 is client limit std::string player_name, guild_name; recv_data >> level_min; // maximal player level, default 0 recv_data >> level_max; // minimal player level, default 100 (MAX_LEVEL) recv_data >> player_name; // player name, case sensitive... recv_data >> guild_name; // guild name, case sensitive... recv_data >> racemask; // race mask recv_data >> classmask; // class mask recv_data >> zones_count; // zones count, client limit=10 (2.0.10) if (zones_count > 10) return; // can't be received from real client or broken packet for (uint32 i = 0; i < zones_count; ++i) { uint32 temp; recv_data >> temp; // zone id, 0 if zone is unknown... zoneids[i] = temp; DEBUG_LOG("Zone %u: %u", i, zoneids[i]); } recv_data >> str_count; // user entered strings count, client limit=4 (checked on 2.0.10) if (str_count > 4) return; // can't be received from real client or broken packet DEBUG_LOG("Minlvl %u, maxlvl %u, name %s, guild %s, racemask %u, classmask %u, zones %u, strings %u", level_min, level_max, player_name.c_str(), guild_name.c_str(), racemask, classmask, zones_count, str_count); std::wstring str[4]; // 4 is client limit for (uint32 i = 0; i < str_count; ++i) { std::string temp; recv_data >> temp; // user entered string, it used as universal search pattern(guild+player name)? if (!Utf8toWStr(temp, str[i])) continue; wstrToLower(str[i]); DEBUG_LOG("String %u: %s", i, temp.c_str()); } std::wstring wplayer_name; std::wstring wguild_name; if (!(Utf8toWStr(player_name, wplayer_name) && Utf8toWStr(guild_name, wguild_name))) return; wstrToLower(wplayer_name); wstrToLower(wguild_name); // client send in case not set max level value 100 but mangos support 255 max level, // update it to show GMs with characters after 100 level if (level_max >= MAX_LEVEL) level_max = STRONG_MAX_LEVEL; Team team = _player->GetTeam(); AccountTypes security = GetSecurity(); bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_WHO_LIST); AccountTypes gmLevelInWhoList = (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_WHO_LIST); uint32 matchcount = 0; uint32 displaycount = 0; WorldPacket data(SMSG_WHO, 50); // guess size data << uint32(matchcount); // placeholder, count of players matching criteria data << uint32(displaycount); // placeholder, count of players displayed // TODO: Guard Player map HashMapHolder<Player>::MapType& m = sObjectAccessor.GetPlayers(); for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) { Player* pl = itr->second; if (security == SEC_PLAYER) { // player can see member of other team only if CONFIG_BOOL_ALLOW_TWO_SIDE_WHO_LIST if (pl->GetTeam() != team && !allowTwoSideWhoList) continue; // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST if (pl->GetSession()->GetSecurity() > gmLevelInWhoList) continue; } // do not process players which are not in world if (!pl->IsInWorld()) continue; // check if target is globally visible for player if (!pl->IsVisibleGloballyFor(_player)) continue; // check if target's level is in level range uint32 lvl = pl->getLevel(); if (lvl < level_min || lvl > level_max) continue; // check if class matches classmask uint32 class_ = pl->getClass(); if (!(classmask & (1 << class_))) continue; // check if race matches racemask uint32 race = pl->getRace(); if (!(racemask & (1 << race))) continue; uint32 pzoneid = pl->GetZoneId(); uint8 gender = pl->getGender(); bool z_show = true; for (uint32 i = 0; i < zones_count; ++i) { if (zoneids[i] == pzoneid) { z_show = true; break; } z_show = false; } if (!z_show) continue; std::string pname = pl->GetName(); std::wstring wpname; if (!Utf8toWStr(pname, wpname)) continue; wstrToLower(wpname); if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos)) continue; std::string gname = sGuildMgr.GetGuildNameById(pl->GetGuildId()); std::wstring wgname; if (!Utf8toWStr(gname, wgname)) continue; wstrToLower(wgname); if (!(wguild_name.empty() || wgname.find(wguild_name) != std::wstring::npos)) continue; std::string aname; if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(pzoneid)) aname = areaEntry->area_name[GetSessionDbcLocale()]; bool s_show = true; for (uint32 i = 0; i < str_count; ++i) { if (!str[i].empty()) { if (wgname.find(str[i]) != std::wstring::npos || wpname.find(str[i]) != std::wstring::npos || Utf8FitTo(aname, str[i])) { s_show = true; break; } s_show = false; } } if (!s_show) continue; // 49 is maximum player count sent to client ++matchcount; if (matchcount > 49) continue; ++displaycount; data << pname; // player name data << gname; // guild name data << uint32(lvl); // player level data << uint32(class_); // player class data << uint32(race); // player race data << uint8(gender); // player gender data << uint32(pzoneid); // player zone id } data.put(0, displaycount); // insert right count, count displayed data.put(4, matchcount); // insert right count, count of matches SendPacket(&data); DEBUG_LOG("WORLD: Send SMSG_WHO Message"); }
void WorldSession::HandleAcceptTrade(WorldPacket & recv_data) { if(!_player->IsInWorld() || _player->mTradeTarget == 0) return; uint32 TradeStatus = TRADE_STATUS_ACCEPTED; Player* pTarget = _player->GetTradeTarget(); if(pTarget == NULL || !pTarget->IsInWorld()) TradeStatus = TRADE_STATUS_PLAYER_NOT_FOUND; // Tell the other player we're green. if(pTarget->m_session && pTarget->m_session->GetSocket()) pTarget->m_session->SendTradeStatus(TradeStatus); _player->mTradeStatus = TradeStatus; //Both sides accepted? Let's trade! if(_player->mTradeStatus == TRADE_STATUS_ACCEPTED && pTarget->mTradeStatus == TRADE_STATUS_ACCEPTED) { // Ready! uint32 ItemCount = 0; uint32 TargetItemCount = 0; Item* pItem; // Count items on both sides, check if bags are empty. for(uint32 Index = 0; Index < 6; ++Index) { if(_player->mTradeItems[Index] != NULL) { pItem = _player->mTradeItems[Index]; if( pItem != NULL && pItem->IsContainer() && TO_CONTAINER(pItem)->HasItems()) { sCheatLog.writefromsession(this, "%s involved in bag-trick trade with %s", _player->GetName(),pTarget->GetName()); _player->GetItemInterface()->BuildInventoryChangeError( pItem, NULL, INV_ERR_CANT_TRADE_EQUIP_BAGS); TradeStatus = TRADE_STATUS_CANCELLED; break; } else ++ItemCount; } if(pTarget->mTradeItems[Index] != NULL) { pItem = pTarget->mTradeItems[Index]; if( pItem != NULL && pItem->IsContainer() && TO_CONTAINER(pItem)->HasItems() ) { sCheatLog.writefromsession(this, "%s involved in bag-trick trade with %s.", pTarget->GetName(),_player->GetName()); pTarget->GetItemInterface()->BuildInventoryChangeError( pItem, NULL, INV_ERR_CANT_TRADE_EQUIP_BAGS); TradeStatus = TRADE_STATUS_CANCELLED; break; } else ++TargetItemCount; } } //Do we have something to trade? if( ItemCount == 0 && TargetItemCount == 0 && _player->mTradeGold == 0 && pTarget->mTradeGold == 0 ) TradeStatus = TRADE_STATUS_CANCELLED; //Do we have enough free slots on both sides? else if((_player->m_ItemInterface->CalculateFreeSlots(NULL) + ItemCount) < TargetItemCount || (pTarget->m_ItemInterface->CalculateFreeSlots(NULL) + TargetItemCount) < ItemCount ) TradeStatus = TRADE_STATUS_CANCELLED; //Everything still ok? else if(TradeStatus == TRADE_STATUS_ACCEPTED) { uint64 Guid; //Swapp 6 itemslots (7th will not trade) for(uint32 Index = 0; Index < 6; ++Index) { Guid = _player->mTradeItems[Index] ? _player->mTradeItems[Index]->GetGUID() : 0; if(Guid != 0) { if( _player->mTradeItems[Index]->IsSoulbound()) _player->GetItemInterface()->BuildInventoryChangeError( _player->mTradeItems[Index], NULL, INV_ERR_CANNOT_TRADE_THAT); else { //Remove from player pItem = _player->m_ItemInterface->SafeRemoveAndRetreiveItemByGuidRemoveStats(Guid, true); //and add to pTarget if(pItem != NULL) { pItem->SetOwner(pTarget); if( !pTarget->m_ItemInterface->AddItemToFreeSlot(pItem) ) { pItem->Destructor(); pItem = NULL; } } if(GetPermissionCount()>0 || pTarget->GetSession()->GetPermissionCount()>0) sGMLog.writefromsession(this, "trade item %s with %s (soulbound = %d)", _player->mTradeItems[Index]->GetProto()->Name1, pTarget->GetName()); } } Guid = pTarget->mTradeItems[Index] ? pTarget->mTradeItems[Index]->GetGUID() : 0; if(Guid != 0) { if( pTarget->mTradeItems[Index]->IsSoulbound()) pTarget->GetItemInterface()->BuildInventoryChangeError( pTarget->mTradeItems[Index], NULL, INV_ERR_CANNOT_TRADE_THAT); else { //Remove from pTarget pItem = pTarget->m_ItemInterface->SafeRemoveAndRetreiveItemByGuidRemoveStats(Guid, true); //and add to initiator if(pItem != NULL) { pItem->SetOwner(_player); if( !_player->m_ItemInterface->AddItemToFreeSlot(pItem) ) { pItem->Destructor(); pItem = NULL; } } if(GetPermissionCount()>0 || pTarget->GetSession()->GetPermissionCount()>0) sGMLog.writefromsession(this, "trade item %s with %s", pTarget->mTradeItems[Index]->GetProto()->Name1, _player->GetName()); } } } // Trade Gold if(_player->mTradeGold) { pTarget->ModUnsigned32Value(PLAYER_FIELD_COINAGE, _player->mTradeGold); _player->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -(int32)_player->mTradeGold); } if(pTarget->mTradeGold) { _player->ModUnsigned32Value(PLAYER_FIELD_COINAGE, pTarget->mTradeGold); pTarget->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -(int32)pTarget->mTradeGold); } pTarget->SaveToDB(false); _player->SaveToDB(false); TradeStatus = TRADE_STATUS_COMPLETE; } SendTradeStatus(TradeStatus); if(pTarget->m_session && pTarget->m_session->GetSocket()) pTarget->m_session->SendTradeStatus(TradeStatus); // Reset Trade Vars _player->ResetTradeVariables(); pTarget->ResetTradeVariables(); } }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) { DEBUG_LOG("WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); ObjectGuid guid; recv_data >> guid; Player * player = HashMapHolder<Player>::Find(guid); if(!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << guid.WriteAsPacked(); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Pet *pet = player->GetPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << player->GetPackGUID(); uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF if(pet) mask1 = 0x7FFFFFFF; // for hunters and other classes with pets uint16 online_status = GetPlayer()->IsReferAFriendLinked(player) ? (MEMBER_STATUS_ONLINE | MEMBER_STATUS_RAF) : MEMBER_STATUS_ONLINE; Powers powerType = player->getPowerType(); data << uint32(mask1); // group update mask data << uint16(online_status); // member's online status data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP data << uint8(powerType); // GROUP_UPDATE_FLAG_POWER_TYPE data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL //verify player coordinates and zoneid to send to teammates uint16 iZoneId = 0; uint16 iCoordX = 0; uint16 iCoordY = 0; if (player->IsInWorld()) { iZoneId = player->GetZoneId(); iCoordX = player->GetPositionX(); iCoordY = player->GetPositionY(); } else if (player->IsBeingTeleported()) // Player is in teleportation { WorldLocation& loc = player->GetTeleportDest(); // So take teleportation destination iZoneId = sTerrainMgr.GetZoneId(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); iCoordX = loc.coord_x; iCoordY = loc.coord_y; } else { //unknown player status. } data << uint16(iZoneId); // GROUP_UPDATE_FLAG_ZONE data << uint16(iCoordX); // GROUP_UPDATE_FLAG_POSITION data << uint16(iCoordY); // GROUP_UPDATE_FLAG_POSITION uint64 auramask = 0; size_t maskPos = data.wpos(); data << uint64(auramask); // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { if(uint32 aura = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << uint32(aura); data << uint8(1); } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if(pet) { Powers petpowertype = pet->getPowerType(); data << pet->GetObjectGuid(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet->GetDisplayId()); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << uint32(pet->GetHealth()); // GROUP_UPDATE_FLAG_PET_CUR_HP data << uint32(pet->GetMaxHealth()); // GROUP_UPDATE_FLAG_PET_MAX_HP data << uint8(petpowertype); // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << uint16(pet->GetPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << uint16(pet->GetMaxPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_MAX_POWER uint64 petauramask = 0; size_t petMaskPos = data.wpos(); data << uint64(petauramask); // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { if(uint32 petaura = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); data << uint32(petaura); data << uint8(1); } } data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS } else { data << uint8(0); // GROUP_UPDATE_FLAG_PET_NAME data << uint64(0); // GROUP_UPDATE_FLAG_PET_AURAS } SendPacket(&data); }
static bool HandleGroupListCommand(ChatHandler* handler, char const* args) { // Get ALL the variables! Player* playerTarget; uint32 phase = 0; ObjectGuid guidTarget; std::string nameTarget; std::string zoneName; const char* onlineState = ""; // Parse the guid to uint32... ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atol((char*)args))); // ... and try to extract a player out of it. if (sObjectMgr->GetPlayerNameByGUID(parseGUID, nameTarget)) { playerTarget = ObjectAccessor::FindPlayer(parseGUID); guidTarget = parseGUID; } // If not, we return false and end right away. else if (!handler->extractPlayerTarget((char*)args, &playerTarget, &guidTarget, &nameTarget)) return false; // Next, we need a group. So we define a group variable. Group* groupTarget = NULL; // We try to extract a group from an online player. if (playerTarget) groupTarget = playerTarget->GetGroup(); // If not, we extract it from the SQL. if (!groupTarget) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GROUP_MEMBER); stmt->setUInt32(0, guidTarget.GetCounter()); PreparedQueryResult resultGroup = CharacterDatabase.Query(stmt); if (resultGroup) groupTarget = sGroupMgr->GetGroupByDbStoreId((*resultGroup)[0].GetUInt32()); } // If both fails, players simply has no party. Return false. if (!groupTarget) { handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, nameTarget.c_str()); handler->SetSentErrorMessage(true); return false; } // We get the group members after successfully detecting a group. Group::MemberSlotList const& members = groupTarget->GetMemberSlots(); // To avoid a cluster f**k, namely trying multiple queries to simply get a group member count... handler->PSendSysMessage(LANG_GROUP_TYPE, (groupTarget->isRaidGroup() ? "raid" : "party"), members.size()); // ... we simply move the group type and member count print after retrieving the slots and simply output it's size. // While rather dirty codestyle-wise, it saves space (if only a little). For each member, we look several informations up. for (Group::MemberSlotList::const_iterator itr = members.begin(); itr != members.end(); ++itr) { // Define temporary variable slot to iterator. Group::MemberSlot const& slot = *itr; // Check for given flag and assign it to that iterator std::string flags; if (slot.flags & MEMBER_FLAG_ASSISTANT) flags = "Assistant"; if (slot.flags & MEMBER_FLAG_MAINTANK) { if (!flags.empty()) flags.append(", "); flags.append("MainTank"); } if (slot.flags & MEMBER_FLAG_MAINASSIST) { if (!flags.empty()) flags.append(", "); flags.append("MainAssist"); } if (flags.empty()) flags = "None"; // Check if iterator is online. If is... Player* p = ObjectAccessor::FindPlayer((*itr).guid); if (p && p->IsInWorld()) { // ... than, it prints information like "is online", where he is, etc... onlineState = "online"; phase = (!p->IsGameMaster() ? p->GetPhaseMask() : -1); uint32 locale = handler->GetSessionDbcLocale(); AreaTableEntry const* area = GetAreaEntryByAreaID(p->GetAreaId()); if (area) { AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone); if (zone) zoneName = zone->area_name[locale]; } } else { // ... else, everything is set to offline or neutral values. zoneName = "<ERROR>"; onlineState = "Offline"; phase = 0; } // Now we can print those informations for every single member of each group! handler->PSendSysMessage(LANG_GROUP_PLAYER_NAME_GUID, slot.name.c_str(), onlineState, zoneName.c_str(), phase, slot.guid.GetCounter(), flags.c_str(), lfg::GetRolesString(slot.roles).c_str()); } // And finish after every iterator is done. return true; }
bool ChatHandler::HandlePlayerbotMainTankCommand(const char *args) { uint64 guid = 0; uint64 pGuid = 0; char *charname ; Group *group = m_session->GetPlayer()->GetGroup(); if (group == NULL) { PSendSysMessage("Must be in a group to set a main tank."); SetSentErrorMessage(true); return false; } QueryResult result = CharacterDatabase.PQuery("SELECT memberGuid FROM group_member WHERE memberFlags='%u' AND guid = '%u'",MEMBER_FLAG_MAINTANK, group->GetGUID()); if(result) { pGuid = MAKE_NEW_GUID(result->Fetch()->GetInt32(),0,HIGHGUID_PLAYER); } // if no arguments are passed in, just say who the current main tank is if(!*args) { if (pGuid>0) { Player *pPlayer = sObjectMgr->GetPlayer(pGuid); if (pPlayer && pPlayer->isAlive()){ PSendSysMessage("Main tank is %s.", pPlayer->GetName()); return true; } } PSendSysMessage("Currently there is no main tank. "); return true; } else { charname = strtok ((char*)args, " "); std::string charnameStr = charname; guid = sObjectMgr->GetPlayerGUIDByName(charnameStr.c_str()); // clear if same player if (pGuid==guid) { group->SetGroupMemberFlag(guid, false, MEMBER_FLAG_MAINTANK); PSendSysMessage("Main tank has been cleared. "); return true; } if (m_session->GetPlayer()->GetGroup()->IsMember(guid)) { group->SetGroupMemberFlag(pGuid,false, MEMBER_FLAG_MAINTANK); // clear old one group->SetGroupMemberFlag(guid, true, MEMBER_FLAG_MAINTANK); // set new one Player *pPlayer = sObjectMgr->GetPlayer(guid); if (pPlayer->IsInWorld()) PSendSysMessage("Main tank is %s.", pPlayer->GetName()); else PSendSysMessage("Player is not online."); } else { PSendSysMessage("Player is not in your group."); } } return true; }
void Transporter::TransportPassengers(uint32 mapid, uint32 oldmap, float x, float y, float z) { sEventMgr.RemoveEvents(this, EVENT_TRANSPORTER_NEXT_WAYPOINT); #ifdef CLUSTERING WorldPacket data(ICMSG_TRANSPORTER_MAP_CHANGE, 24); data << GetEntry() << mapid << oldmap << x << y << z; sClusterInterface.SendPacket(&data); #endif if(mPassengers.size() > 0) { PassengerIterator itr = mPassengers.begin(); PassengerIterator it2; WorldPacket Pending(SMSG_TRANSFER_PENDING, 12); Pending << mapid << GetEntry() << oldmap; WorldPacket NewWorld; LocationVector v; for(; itr != mPassengers.end();) { it2 = itr; ++itr; Player* plr = objmgr.GetPlayer(it2->first); if(!plr) { // remove from map mPassengers.erase(it2); continue; } if(!plr->GetSession() || !plr->IsInWorld()) continue; v.x = x + plr->m_TransporterX; v.y = y + plr->m_TransporterY; v.z = z + plr->m_TransporterZ; v.o = plr->GetOrientation(); if(mapid == 530 && !plr->GetSession()->HasFlag(ACCOUNT_FLAG_XPACK_01)) { // player is not flagged to access bc content, repop at graveyard plr->RepopAtGraveyard(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetMapId()); continue; } if(mapid == 571 && !plr->GetSession()->HasFlag(ACCOUNT_FLAG_XPACK_02)) { plr->RepopAtGraveyard(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetMapId()); continue; } // Lucky bitch. Do it like on official. if(plr->isDead()) { /*plr->ResurrectPlayer(NULL); plr->SetUInt32Value(UNIT_FIELD_HEALTH, plr->GetUInt32Value(UNIT_FIELD_MAXHEALTH)); plr->SetUInt32Value(UNIT_FIELD_POWER1, plr->GetUInt32Value(UNIT_FIELD_MAXPOWER1));*/ plr->RemoteRevive(); } if( plr->m_CurrentVehicle ) plr->m_CurrentVehicle->RemovePassenger( plr ); plr->m_lockTransportVariables = true; plr->GetSession()->SendPacket(&Pending); } } // Set our position RemoveFromWorld(false); SetPosition(x,y,z,m_position.o,false); #ifndef CLUSTERING SetMapId(mapid); AddToWorld(); #endif }
bool OutdoorPvPHS::Update(uint32 diff) { bool changed = OutdoorPvP::Update(diff); // Resurrection System m_LastResurrectTime += diff; if (m_LastResurrectTime >= HS_RESURRECTION_INTERVAL) { //sLog->outString("HillsbradMGR : Reviving..."); if ( GetReviveQueueSize() ) { sLog->outString("HillsbradMGR : Dead players in queue."); for (std::map<uint64, std::vector<uint64> >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr) { Creature* sh = NULL; for (std::vector<uint64>::const_iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2) { Player* plr = ObjectAccessor::FindPlayer(*itr2); if (!plr) continue; if (!sh && plr->IsInWorld()) { sh = plr->GetMap()->GetCreature(itr->first); // only for visual effect if (sh) // Spirit Heal, effect 117 sh->CastSpell(sh, HS_SPELL_SPIRIT_HEAL, true); } // Resurrection visual plr->CastSpell(plr, HS_SPELL_RESURRECTION_VISUAL, true); m_ResurrectQueue.push_back(*itr2); } (itr->second).clear(); } m_ReviveQueue.clear(); } // Reset last resurrection time m_LastResurrectTime = 0; } else if (m_LastResurrectTime > 500) // Resurrect players only half a second later { if ( GetResurrectQueueSize() ) { //sLog->outString("HillsbradMGR : Resurrecting..."); for (std::vector<uint64>::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr) { Player* plr = ObjectAccessor::FindPlayer(*itr); if (!plr) continue; plr->ResurrectPlayer(1.0f, false); plr->CastSpell(plr, 6962, true); plr->CastSpell(plr, HS_SPELL_SPIRIT_HEAL_MANA, true); sObjectAccessor->ConvertCorpseForPlayer(*itr); } m_ResurrectQueue.clear(); } } // Arena Chest System. // Update the timer. //if( m_ChestGUID == 0 ) //{ if( m_ChestTimer < diff ) { uint32 ffachest = 0; ffachest = urand(0, 9); if( uint32 guid = sObjectMgr->AddGOData(HSChestPoints[ffachest].entry, HSChestPoints[ffachest].map, HSChestPoints[ffachest].x, HSChestPoints[ffachest].y, HSChestPoints[ffachest].z, HSChestPoints[ffachest].o, 99999999999, 0, 0, 0, 0) ) { //sLog->outString( "Hillsbrad : Spawned Chest(%u) at location %u.", guid, ffachest); m_ChestGUID = guid; SendMessageToAll( "FFA chest has been spawned in the fields. Good luck!" ); sLog->outString( "Hillsbrad : Spawned Chest(%u) at location %u.", m_ChestGUID, ffachest); } m_ChestTimer = HS_FFA_CHEST_TIMER; } else { m_ChestTimer -= diff; // Announce when? if( m_ChestAnnounceTimer < diff ) { uint32 ChestTimerSec = uint32( m_ChestTimer / IN_MILLISECONDS ); if ( (ChestTimerSec < 3 && ChestTimerSec > 0) || (ChestTimerSec < 30 && (ChestTimerSec % 5) == 0) || // < 30 sec; every 5 sec (ChestTimerSec <=5*MINUTE && (ChestTimerSec % MINUTE) == 0) || // < 5 min ; every 1 min (ChestTimerSec <=30*MINUTE && (ChestTimerSec % (5*MINUTE)) == 0) ) // < 30 min; every 5 min { std::string str = secsToTimeString( ChestTimerSec ); SendMessageToAll( "FFA chest will spawn in %s.", str.c_str() ); } m_ChestAnnounceTimer = HS_FFA_CHEST_ANNOUNCE_TIMER; } else m_ChestAnnounceTimer -= diff; } //} // Chest debug. if( m_ChestTimer < diff ) { sLog->outString( "HillsbradMGR : Chest Guid (%u), Timer (%u), Announce Timer (%u).", m_ChestGUID, m_ChestTimer, m_ChestAnnounceTimer ); m_ChestDebugTimer = 60000; } else m_ChestDebugTimer -= diff; /* // Player scale checker. if( m_TenacityTimer <= diff ) { float ratio = 0; uint32 stack = 0; // Reset the stack count m_HordeBuff = 0; m_AllianceBuff = 0; if( m_HordeCount > 0 && m_AllianceCount > 0 ) { if( m_AllianceCount > m_HordeCount ) ratio = m_AllianceCount / m_HordeCount; else ratio = m_HordeCount / m_AllianceCount; } if( ratio >= 1.25f ) { // Buff for lower team stack = ratio * ratio; if( stack > 20 ) stack = 20; if( m_HordeCount < m_AllianceCount ) m_HordeBuff = stack; else m_AllianceBuff = stack; } // Apply the buff to players. ApplyZoneBalanceBuff(); m_TenacityTimer = HS_TENACITY_TIME; } else m_TenacityTimer -= diff; */ ApplyZoneBalanceBuff(); return changed; }
void WorldSession::HandleLfgJoinOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received CMSG_LFG_JOIN"); if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_JOIN_LFG)) { sLfgMgr.SendJoinResult(_player, LFG_JOIN_INTERNAL_ERROR); return; } uint32 error = LFG_JOIN_OK; uint32 roles; uint8 count, unk; std::string comment; recv_data >> roles; recv_data.read_skip<uint8>(); // unk - always 0 recv_data.read_skip<uint8>(); // unk - always 0 recv_data >> count; Player *player = _player; // If in dungeon group, then set to leader //Some first checks if (_player->InBattleGround() || _player->InBattleGroundQueue() || _player->InArena()) error = LFG_JOIN_USING_BG_SYSTEM; else if (_player->HasAura(LFG_DESERTER)) error = LFG_JOIN_PARTY_DESERTER; else if (Group *group = _player->GetGroup()) { if(group->GetLeaderGUID() != _player->GetGUID()) { if(group->isLfgGroup()) { Player *leader = sObjectMgr.GetPlayer(group->GetLeaderGUID()); if(!leader || !leader->GetSession() || !leader->IsInWorld()) error = LFG_JOIN_DISCONNECTED; player = leader; } else error = LFG_JOIN_NOT_MEET_REQS; } } //TODO: Implement this else if (count > 1 || (player->GetMap()->IsDungeon() && (!player->GetGroup() || !player->GetGroup()->isLfgGroup()))) error = LFG_JOIN_DUNGEON_INVALID; if (error != LFG_JOIN_OK) { sLfgMgr.SendJoinResult(player, error); return; } if (!player->m_lookingForGroup.queuedDungeons.empty() || sLfgMgr.IsPlayerInQueue(player->GetGUID())) sLfgMgr.RemovePlayer(player, false); // for every dungeon check also if theres some error for(uint8 i = 0; i < count; ++i) { uint32 dungeonEntry; recv_data >> dungeonEntry; LFGDungeonEntry const *dungeonInfo = sLFGDungeonStore.LookupEntry((dungeonEntry & 0x00FFFFFF)); if (!dungeonInfo) { sLog.outError("WORLD: Player %u has attempted to join for non-exist dungeon from LFG", _player->GetGUID()); error = LFG_JOIN_DUNGEON_INVALID; } //Raids are not implemented yet, and they are not so popular on offi, so get rid of them for now else if (dungeonInfo->type == LFG_TYPE_RAID) error = LFG_JOIN_INTERNAL_ERROR; else if (dungeonInfo->type == LFG_TYPE_RANDOM && _player->HasAura(LFG_RANDOM_COOLDOWN)) error = LFG_JOIN_RANDOM_COOLDOWN; //Now the group else if (Group *group = player->GetGroup()) { if (group->isRaidGroup()) error = LFG_JOIN_MIXED_RAID_DUNGEON; //else if (group->GetMembersCount() == 5) // error = LFG_JOIN_GROUPFULL; else { Group::member_citerator citr, citr_next; for(citr = group->GetMemberSlots().begin(); citr != group->GetMemberSlots().end(); citr = citr_next) { citr_next = citr; ++citr_next; Player *plr = sObjectMgr.GetPlayer(citr->guid); if (!plr || !plr->GetSession()) { error = LFG_JOIN_DISCONNECTED; break; } if (plr->HasAura(LFG_DESERTER)) error = LFG_JOIN_PARTY_DESERTER; else if (dungeonInfo->type == LFG_TYPE_RANDOM && plr->HasAura(LFG_RANDOM_COOLDOWN)) error = LFG_JOIN_PARTY_RANDOM_COOLDOWN; else if(sLfgMgr.IsPlayerInQueue(citr->guid)) error = LFG_JOIN_DISCONNECTED; } } } if (error != LFG_JOIN_OK) { sLfgMgr.SendJoinResult(player, error); return; } player->m_lookingForGroup.queuedDungeons.insert(dungeonInfo); } recv_data >> unk; // looks like unk from LFGDungeons.dbc, so 0 = raid or zone, 3 = dungeon, 15 = world event. Possibly count of next data? anyway seems unused for (int8 i = 0 ; i < unk; ++i) recv_data.read_skip<uint8>(); // unk, always 0? recv_data >> comment; player->m_lookingForGroup.roles = uint8(roles); player->m_lookingForGroup.comment = comment; player->m_lookingForGroup.joinTime = getMSTime(); sLfgMgr.AddToQueue(player); }
void UpdateAI(const uint32 diff) { events.Update(diff); if (!UpdateVictim()) return; if (fixated) { if (target_after != NULL && target_after && target_after->IsInWorld() && target_after->isAlive() && target_after->HasAura(FIXATE_AURA)) { me->AttackStop(); // Stop attacking DoMeleeAttackIfReady() me->SetReactState(REACT_PASSIVE); me->GetMotionMaster()->MovePoint(1, target_after->GetPositionX(), target_after->GetPositionY(), target_after->GetPositionZ()); } else { fixated = false; target_after = NULL; AttackStart(me->getVictim()); // Start attack the victim (random?) me->SetReactState(REACT_AGGRESSIVE); } } // band of valor std::list<Creature*> Cr_list; JadeCore::AnyCreatureInObjectRangeCheck check(me, 8.0f); JadeCore::CreatureListSearcher<JadeCore::AnyCreatureInObjectRangeCheck> searcher(me, Cr_list, check); me->VisitNearbyObject(8.0f, searcher); for (std::list<Creature*>::const_iterator it = Cr_list.begin(); it != Cr_list.end(); ++it) { if (!(*it)) return; if ((*it)->GetEntry() == 63591 || (*it)->GetEntry() == 64453) { if (me->HasAura(125422)) { AuraPtr band_of_valor = me->GetAura(125422); if (band_of_valor) { band_of_valor->SetStackAmount(Cr_list.size() - 1); } } else { me->AddAura(125422, me); } } } while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_FIXATE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true)) { me->CastSpell(target, FIXATE); fixated = true; target_after = target->ToPlayer(); events.ScheduleEvent(EVENT_FIXATE, urand(32000, 60000)); } break; case EVENT_SONIC_BLADE: me->CastSpell(me->getVictim(), SONIC_BOMB); events.ScheduleEvent(EVENT_SONIC_BLADE, urand(6000, 10000)); break; case EVENT_DISPATCH: me->AddAura(DISPATCH, me); events.ScheduleEvent(DISPATCH, 21000); break; case EVENT_STICKY_RESIN: Position pos; int32 reduction = urand(0, 1); if (reduction == 1) { me->GetRandomNearPosition(pos, frand(5.0f, 10.0f)); me->SummonCreature(STICKY_RESIN_TRIGGER, pos, TEMPSUMMON_MANUAL_DESPAWN); events.ScheduleEvent(EVENT_STICKY_RESIN, urand(15000, 22000)); } break; } } DoMeleeAttackIfReady(); }
bool HandlePlayerAddItem(BaseConsole * pConsole, int argc, const char * argv[]) { if ( argc < 4 ) { pConsole->Write( "ERROR:Not enough parameters.\r\n"); return false; } const char *PlayerName = argv[1]; uint32 itemid = atoi( argv[2] ); uint32 itemCount = atoi( argv[3] ); Player *plr = objmgr.GetPlayer(PlayerName, false); if( !plr || plr->IsInWorld() == false ) { pConsole->Write( "ERROR:Could not find player %s.\r\n", argv[1]); return true; } ItemPrototype *m_itemProto = ItemPrototypeStorage.LookupEntry( itemid ); if( m_itemProto == NULL ) { pConsole->Write( "ERROR:Could not find item.\r\n" ); return true; } itemCount = MAX( 1, itemCount ); //morron protection :P uint32 max_stack = MAX( 1, m_itemProto->MaxCount ); if( itemCount < max_stack ) max_stack = itemCount; for( uint32 i=0; i< ( itemCount + max_stack - 1) / max_stack; i++ ) //roundup { Item *item = objmgr.CreateItem( itemid, plr ); if( item == NULL ) { pConsole->Write( "ERROR:Could not create new item.\r\n" ); return true; } uint32 added_until_now = i*max_stack; uint32 need_to_add = itemCount - added_until_now; uint32 add_now = MAX(1, MIN( need_to_add, max_stack )); FILE *fp = fopen("ConsoleCommands.Log","at"); if( fp ) { fprintf(fp,"GUID = %u, name = %s, acct = %u has received item = %u count = %u guid = %u at %I64u \n",(uint32)plr->GetGUID(),plr->GetName(), plr->GetSession()->GetAccountId(),itemid, add_now,(uint32)item->GetGUID(), UNIXTIME); fclose( fp ); } item->SetUInt32Value(ITEM_FIELD_STACK_COUNT, add_now ); if( plr->GetItemInterface()->SafeAddItem(item, INVENTORY_SLOT_NOT_SET, INVENTORY_SLOT_NOT_SET ) == ADD_ITEM_RESULT_ERROR ) { plr->RemoveAndMailItem( &item ); plr->BroadcastMessage("You have received a new item from a GM command in mail."); } else { plr->BroadcastMessage("You have received a new item from a GM command in your backpack. Your item has been saved"); } } plr->SaveToDB(false); pConsole->Write( "SUCCESS:Player has received the item\r\n" ); return true; }
void BattlegroundKT::PostUpdateImpl(uint32 diff) { if (GetStatus() == STATUS_WAIT_JOIN) { m_CheatersCheckTimer -= diff; if (m_CheatersCheckTimer <= 0) { for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) { Player * plr = ObjectAccessor::FindPlayer(itr->first); if (!plr || !plr->IsInWorld()) continue; if (plr->GetPositionZ() < 24.0f) { if (plr->GetBGTeam() == HORDE) plr->TeleportTo(998, 1781.31f, 1597.76f, 33.61f, plr->GetOrientation(), 0); else plr->TeleportTo(998, 1784.42f, 1072.73f, 29.88f, plr->GetOrientation(), 0); } } m_CheatersCheckTimer = 4000; } } if (GetStatus() == STATUS_IN_PROGRESS) { if (m_EndTimer <= diff) { uint32 allianceScore = GetTeamScore(ALLIANCE); uint32 hordeScore = GetTeamScore(HORDE); if (allianceScore > hordeScore) EndBattleground(ALLIANCE); else if (allianceScore < hordeScore) EndBattleground(HORDE); else EndBattleground(m_LastCapturedOrbTeam); // if 0 => tie } else { uint32 minutesLeftPrev = GetRemainingTimeInMinutes(); m_EndTimer -= diff; uint32 minutesLeft = GetRemainingTimeInMinutes(); if (minutesLeft != minutesLeftPrev) UpdateWorldState(BG_KT_TIME_REMAINING, minutesLeft); } if (m_UpdatePointsTimer <= diff) { for (uint8 i = 0; i < MAX_ORBS; ++i) { if (uint64 guid = m_OrbKeepers[i]) { if (m_playersZone.find(guid) != m_playersZone.end()) { if (Player* player = ObjectAccessor::FindPlayer(guid)) { AccumulateScore(player->GetBGTeam() == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE, m_playersZone[guid]); UpdatePlayerScore(player, SCORE_ORB_SCORE, m_playersZone[guid]); } } } } m_UpdatePointsTimer = BG_KT_POINTS_UPDATE_TIME; } else m_UpdatePointsTimer -= diff; } }
void BattlegroundEY::PostUpdateImpl(uint32 diff) { if (GetStatus() == STATUS_IN_PROGRESS) { m_PointAddingTimer -= diff; if (m_PointAddingTimer <= 0) { m_PointAddingTimer = BG_EY_FPOINTS_TICK_TIME; if (m_TeamPointsCount[BG_TEAM_ALLIANCE] > 0) AddPoints(ALLIANCE, BG_EY_TickPoints[m_TeamPointsCount[BG_TEAM_ALLIANCE] - 1]); if (m_TeamPointsCount[BG_TEAM_HORDE] > 0) AddPoints(HORDE, BG_EY_TickPoints[m_TeamPointsCount[BG_TEAM_HORDE] - 1]); } if (m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN || m_FlagState == BG_EY_FLAG_STATE_ON_GROUND) { m_FlagsTimer -= diff; if (m_FlagsTimer < 0) { m_FlagsTimer = 0; if (m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN) RespawnFlag(true); else RespawnFlagAfterDrop(); } } m_TowerCapCheckTimer -= diff; if (m_TowerCapCheckTimer <= 0) { // Check if the player joined the point. CheckSomeoneJoinedPoint(); // Check if the player left the point. CheckSomeoneLeftPoint(); UpdatePointStatuses(); m_TowerCapCheckTimer = BG_EY_FPOINTS_TICK_TIME; } } // Check for players below map / cheaters. if (GetStatus() == STATUS_WAIT_JOIN) { m_CheatersCheckTimer -= diff; if (m_CheatersCheckTimer <= 0) { if (!GetPlayers().empty()) { for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) { Player * plr = ObjectAccessor::FindPlayer(itr->first); if (!plr || !plr->IsInWorld()) continue; if (plr->GetPositionZ() < 1244.0f) { if (plr->GetBGTeam() == HORDE) plr->TeleportTo(566, 1807.98f, 1539.42f, 1247.52f, plr->GetOrientation(), 0); else plr->TeleportTo(566, 2527.18f, 1597.31f, 1248.78f, plr->GetOrientation(), 0); } } } m_CheatersCheckTimer = 4000; } } }
void WorldSession::DoLootRelease(ObjectGuid lguid) { Player* player = GetPlayer(); Loot* loot; player->SetLootGuid(ObjectGuid()); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) { return; } switch (lguid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGuid() != _player->GetObjectGuid() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) { return; } loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { // GO is mineral vein? so it is not removed after its looted if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) { uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; // only vein pass this check if (go_min != 0 && go_max > go_min) { float amount_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_AMOUNT); float min_amount = go_min * amount_rate; float max_amount = go_max * amount_rate; go->AddUse(); float uses = float(go->GetUseCount()); if (uses < max_amount) { if (uses >= min_amount) { float chance_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_NEXT); int32 ReqValue = 175; LockEntry const* lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if (lockInfo) { ReqValue = lockInfo->Skill[0]; } float skill = float(player->GetSkillValue(SKILL_MINING)) / (ReqValue + 25); double chance = pow(0.8 * chance_rate, 4 * (1 / double(max_amount)) * double(uses)); if (roll_chance_f(float(100.0f * chance + skill))) { go->SetLootState(GO_READY); } else // not have more uses { go->SetLootState(GO_JUST_DEACTIVATED); } } else // 100% chance until min uses { go->SetLootState(GO_READY); } } else // max uses already { go->SetLootState(GO_JUST_DEACTIVATED); } } else // not vein { go->SetLootState(GO_JUST_DEACTIVATED); } } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned at next tick if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens, go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); } else { go->SetLootState(GO_READY); } } else // not chest (or vein/herb/etc) { go->SetLootState(GO_JUST_DEACTIVATED); } loot->clear(); } else // not fully looted object { go->SetLootState(GO_ACTIVATED); } go->SetGoState(GO_STATE_READY); break; } /* Only used for removing insignia in battlegrounds */ case HIGHGUID_CORPSE: { /* Get pointer to corpse */ Corpse* corpse = _player->GetMap()->GetCorpse(lguid); /* If corpse is invalid or not in a valid position, dont allow looting */ if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { return; } loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } break; } case HIGHGUID_ITEM: { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) { return; } switch (pItem->loot.loot_type) { // temporary loot, auto loot move case LOOT_DISENCHANTING: { if (!pItem->loot.isLooted()) { player->AutoStoreLoot(pItem->loot); } // can be lost if no space pItem->loot.clear(); pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); break; } // normal persistence loot default: { // must be destroyed only if no loot if (pItem->loot.isLooted()) { pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } break; } } return; // item can be looted only single player } case HIGHGUID_UNIT: { /* Get creature pointer */ Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = (pCreature && // The creature exists (we dont have a null pointer) pCreature->IsAlive() == // Creature is alive and we're a rogue and creature can be pickpocketed (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed)); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { return; } /* Copy creature loot to loot variable */ loot = &pCreature->loot; /* Update for other players. */ if(!loot->isLooted()) { Group const* group = pCreature->GetGroupLootRecipient(); if (group && !pCreature->hasBeenLootedOnce) { // Checking whether it has been looted once by the designed looter (master loot case). switch (group->GetLootMethod()) { case FREE_FOR_ALL: case NEED_BEFORE_GREED: case ROUND_ROBIN: case GROUP_LOOT: { pCreature->hasBeenLootedOnce = true; break; } case MASTER_LOOT: { pCreature->hasBeenLootedOnce = (group->GetLooterGuid() == player->GetObjectGuid()); break; } } pCreature->MarkFlagUpdateForClient(UNIT_DYNAMIC_FLAGS); } } /* We've completely looted the creature, mark it as available for skinning */ if (loot->isLooted() && !pCreature->IsAlive()) { /* Update Creature: for example skinning after normal loot */ pCreature->PrepareBodyLootState(); pCreature->AllLootRemovedFromCorpse(); } break; } default: { sLog.outError("%s is unsupported for looting.", lguid.GetString().c_str()); return; } } // Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetObjectGuid()); }
void BattlegroundEY::Update(uint32 diff) { Battleground::Update(diff); if (GetStatus() == STATUS_IN_PROGRESS) { m_PointAddingTimer -= diff; if (m_PointAddingTimer <= 0) { m_PointAddingTimer = BG_EY_FPOINTS_TICK_TIME; if (m_TeamPointsCount[BG_TEAM_ALLIANCE] > 0) AddPoints(ALLIANCE, BG_EY_TickPoints[m_TeamPointsCount[BG_TEAM_ALLIANCE] - 1]); if (m_TeamPointsCount[BG_TEAM_HORDE] > 0) AddPoints(HORDE, BG_EY_TickPoints[m_TeamPointsCount[BG_TEAM_HORDE] - 1]); } if (m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN || m_FlagState == BG_EY_FLAG_STATE_ON_GROUND) { m_FlagsTimer -= diff; if (m_FlagsTimer < 0) { m_FlagsTimer = 0; if (m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN) RespawnFlag(true); else RespawnFlagAfterDrop(); } } m_TowerCapCheckTimer -= diff; if (m_TowerCapCheckTimer <= 0) { //check if player joined point /*I used this order of calls, because although we will check if one player is in gameobject's distance 2 times but we can count of players on current point in CheckSomeoneLeftPoint */ this->CheckSomeoneJoinedPoint(); //check if player left point this->CheckSomeoneLeftPoint(); this->UpdatePointStatuses(); m_TowerCapCheckTimer = BG_EY_FPOINTS_TICK_TIME; } } if (GetStatus() == STATUS_WAIT_JOIN) { m_CheatersCheckTimer -= diff; if(m_CheatersCheckTimer <= 0) { for(BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) { Player * plr = sObjectMgr->GetPlayer(itr->first); if (!plr || !plr->IsInWorld()) continue; if (plr->GetPositionZ() < 1249) { if (plr->GetTeam() == HORDE) plr->TeleportTo(566, 1807.73f, 1539.41f, 1267.63f, plr->GetOrientation(), 0); else plr->TeleportTo(566, 2523.68f, 1596.59f, 1269.35f, plr->GetOrientation(), 0); } } m_CheatersCheckTimer = 3000; } } }
static bool HandleGroupListCommand(ChatHandler* handler, char const* args) { Player* playerTarget; uint64 guidTarget; std::string nameTarget; uint32 parseGUID = MAKE_NEW_GUID(atol((char*)args), 0, HIGHGUID_PLAYER); if (sObjectMgr->GetPlayerNameByGUID(parseGUID, nameTarget)) { playerTarget = sObjectMgr->GetPlayerByLowGUID(parseGUID); guidTarget = parseGUID; } else if (!handler->extractPlayerTarget((char*)args, &playerTarget, &guidTarget, &nameTarget)) return false; Group* groupTarget = NULL; if (playerTarget) groupTarget = playerTarget->GetGroup(); if (!groupTarget) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GROUP_MEMBER); stmt->setUInt32(0, guidTarget); PreparedQueryResult resultGroup = CharacterDatabase.Query(stmt); if (resultGroup) groupTarget = sGroupMgr->GetGroupByDbStoreId((*resultGroup)[0].GetUInt32()); } if (!groupTarget) { handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, nameTarget.c_str()); handler->SetSentErrorMessage(true); return false; } handler->PSendSysMessage(LANG_GROUP_TYPE, (groupTarget->isRaidGroup() ? "raid" : "party")); Group::MemberSlotList const& members = groupTarget->GetMemberSlots(); for (Group::MemberSlotList::const_iterator itr = members.begin(); itr != members.end(); ++itr) { Group::MemberSlot const& slot = *itr; std::string flags; if (slot.flags & MEMBER_FLAG_ASSISTANT) flags = "Assistant"; if (slot.flags & MEMBER_FLAG_MAINTANK) { if (!flags.empty()) flags.append(", "); flags.append("MainTank"); } if (slot.flags & MEMBER_FLAG_MAINASSIST) { if (!flags.empty()) flags.append(", "); flags.append("MainAssist"); } if (flags.empty()) flags = "None"; Player* p = ObjectAccessor::FindPlayer((*itr).guid); const char* onlineState = (p && p->IsInWorld()) ? "online" : "offline"; handler->PSendSysMessage(LANG_GROUP_PLAYER_NAME_GUID, slot.name.c_str(), onlineState, GUID_LOPART(slot.guid), flags.c_str(), lfg::GetRolesString(slot.roles).c_str()); } return true; }
void WorldSession::DoLootRelease(ObjectGuid lguid) { Player* player = GetPlayer(); Loot* loot; player->SetLootGuid(ObjectGuid()); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; switch (lguid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGuid() != _player->GetObjectGuid() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { // GO is mineral vein? so it is not removed after its looted if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) { uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; // only vein pass this check if (go_min != 0 && go_max > go_min) { float amount_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_AMOUNT); float min_amount = go_min * amount_rate; float max_amount = go_max * amount_rate; go->AddUse(); float uses = float(go->GetUseCount()); if (uses < max_amount) { if (uses >= min_amount) { float chance_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_NEXT); int32 ReqValue = 175; LockEntry const* lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if (lockInfo) ReqValue = lockInfo->Skill[0]; float skill = float(player->GetSkillValue(SKILL_MINING)) / (ReqValue + 25); double chance = pow(0.8 * chance_rate, 4 * (1 / double(max_amount)) * double(uses)); if (roll_chance_f(float(100.0f * chance + skill))) { go->SetLootState(GO_READY); } else // not have more uses go->SetLootState(GO_JUST_DEACTIVATED); } else // 100% chance until min uses go->SetLootState(GO_READY); } else // max uses already go->SetLootState(GO_JUST_DEACTIVATED); } else // not vein go->SetLootState(GO_JUST_DEACTIVATED); } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned at next tick if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens, go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); } else go->SetLootState(GO_READY); } else // not chest (or vein/herb/etc) go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else // not fully looted object go->SetLootState(GO_ACTIVATED); break; } case HIGHGUID_CORPSE: // ONLY remove insignia at BG { Corpse* corpse = _player->GetMap()->GetCorpse(lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } break; } case HIGHGUID_ITEM: { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) return; switch (pItem->loot.loot_type) { // temporary loot, auto loot move case LOOT_DISENCHANTING: { if (!pItem->loot.isLooted()) player->AutoStoreLoot(pItem->loot); // can be lost if no space pItem->loot.clear(); pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); break; } // normal persistence loot default: { // must be destroyed only if no loot if (pItem->loot.isLooted()) { pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } break; } } return; // item can be looted only single player } case HIGHGUID_UNIT: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &pCreature->loot; // update next looter if (Group* group = pCreature->GetGroupLootRecipient()) if (group->GetLooterGuid() == player->GetObjectGuid()) group->UpdateLooterGuid(pCreature); if (loot->isLooted()) { // for example skinning after normal loot pCreature->PrepareBodyLootState(); if (!pCreature->isAlive()) pCreature->AllLootRemovedFromCorpse(); } break; } default: { sLog.outError("%s is unsupported for looting.", lguid.GetString().c_str()); return; } } // Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetObjectGuid()); }
void WorldSession::DoLootRelease( uint64 lguid ) { Player *player = GetPlayer(); Loot *loot; player->SetLootGUID(0); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if(!player->IsInWorld()) return; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject *go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { // GO is mineral vein? so it is not removed after its looted if(go->GetGoType() == GAMEOBJECT_TYPE_CHEST) { uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; if (player->GetInstanceId()) { Map *map = go->GetMap(); if (map->IsDungeon()) { if (map->IsRaid() || map->IsHeroic()) { ((InstanceMap *)map)->PermBindAllPlayers(player); } else { // the reset time is set but not added to the scheduler // until the players leave the instance time_t resettime = go->GetRespawnTimeEx() + 2 * HOUR; if(InstanceSave *save = sInstanceSaveManager.GetInstanceSave(player->GetInstanceId())) if(save->GetResetTime() < resettime) save->SetResetTime(resettime); } } } // only vein pass this check if(go_min != 0 && go_max > go_min) { float amount_rate = sWorld.getRate(RATE_MINING_AMOUNT); float min_amount = go_min*amount_rate; float max_amount = go_max*amount_rate; go->AddUse(); float uses = float(go->GetUseCount()); if(uses < max_amount) { if(uses >= min_amount) { float chance_rate = sWorld.getRate(RATE_MINING_NEXT); int32 ReqValue = 175; LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if(lockInfo) ReqValue = lockInfo->Skill[0]; float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25); double chance = pow(0.8*chance_rate,4*(1/double(max_amount))*double(uses)); if(roll_chance_f(100*chance+skill)) { go->SetLootState(GO_READY); } else // not have more uses go->SetLootState(GO_JUST_DEACTIVATED); } else // 100% chance until min uses go->SetLootState(GO_READY); } else // max uses already go->SetLootState(GO_JUST_DEACTIVATED); } else // not vein go->SetLootState(GO_JUST_DEACTIVATED); } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned in next tick if (go->GetUseCount()>=irand(go->GetGOInfo()->fishinghole.minSuccessOpens,go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); } else go->SetLootState(GO_READY); } else // not chest (or vein/herb/etc) go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else // not fully looted object go->SetLootState(GO_ACTIVATED); } else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG { Corpse *corpse = _player->GetMap()->GetCorpse(lguid); if (!corpse || !corpse->IsWithinDistInMap(_player,INTERACTION_DISTANCE) ) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } } else if (IS_ITEM_GUID(lguid)) { Item *pItem = player->GetItemByGuid(lguid ); if(!pItem) return; ItemPrototype const* proto = pItem->GetProto(); // destroy only 5 items from stack in case prospecting and milling if( (proto->BagFamily & (BAG_FAMILY_MASK_MINING_SUPP|BAG_FAMILY_MASK_HERBS)) && proto->Class == ITEM_CLASS_TRADE_GOODS) { pItem->m_lootGenerated = false; pItem->loot.clear(); uint32 count = pItem->GetCount(); // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. if(count > 5) count = 5; player->DestroyItemCount(pItem, count, true); } else // FIXME: item don't must be deleted in case not fully looted state. But this pre-request implement loot saving in DB at item save. Or checting possible. player->DestroyItem( pItem->GetBagSlot(),pItem->GetSlot(), true); return; // item can be looted only single player } else { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass()==CLASS_ROGUE && pCreature->lootForPickPocketed); if ( !ok_loot || !pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE) ) return; loot = &pCreature->loot; // update next looter if(Player *recipient = pCreature->GetLootRecipient()) if(Group* group = recipient->GetGroup()) if (group->GetLooterGuid() == player->GetGUID()) group->UpdateLooterGuid(pCreature); if (loot->isLooted()) { // skip pickpocketing loot for speed, skinning timer redunction is no-op in fact if(!pCreature->isAlive()) pCreature->AllLootRemovedFromCorpse(); pCreature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); loot->clear(); } } //Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetGUID()); }
void LfgGroup::UpdateRoleCheck(uint32 diff) { sLfgMgr.LfgLog("Updaterolecheck %u, diff %u", GetId(), diff); if (diff != 0) { m_readycheckTimer += diff; if (m_readycheckTimer >= LFG_TIMER_READY_CHECK && m_roleCheck.m_beforeCheck != m_roleCheck.m_rolesProposal.size()) { SendRoleCheckFail(LFG_ROLECHECK_MISSING_ROLE); return; } } //offline check bool offline = false; for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { Player *player = sObjectMgr.GetPlayer(citr->guid); if (!player) { offline = true; break; } } if (GetMembersCount() != m_roleCheck.m_beforeCheck || offline) { SendRoleCheckFail(LFG_ROLECHECK_ABORTED); return; } // add answers for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { Player *player = sObjectMgr.GetPlayer(citr->guid); if (m_roleCheck.m_rolesProposal.find(citr->guid) != m_roleCheck.m_rolesProposal.end() || !player || !player->GetSession() || player->m_lookingForGroup.roles == 0) continue; m_roleCheck.m_rolesProposal[player->GetGUID()] = player->m_lookingForGroup.roles; WorldPacket data(SMSG_LFG_ROLE_CHOSEN, 13); data << uint64(player->GetGUID()); data << uint8(1); data << uint32(player->m_lookingForGroup.roles); BroadcastPacket(&data, false); } //Offline members checked at join //Check roles if (m_roleCheck.m_beforeCheck > m_roleCheck.m_rolesProposal.size()) return; Player *leader = sObjectMgr.GetPlayer(GetLeaderGUID()); if(!leader || !leader->IsInWorld() || !m_roleCheck.TryRoles(this)) { SendRoleCheckFail(LFG_ROLECHECK_WRONG_ROLES); return; } SetAsRole(TANK, m_roleCheck.tank); SetAsRole(HEALER, m_roleCheck.heal); dps.clear(); dps = m_roleCheck.dps; //Move group to queue SendRoleCheckUpdate(LFG_ROLECHECK_FINISHED); for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { Player *player = sObjectMgr.GetPlayer(citr->guid); if (!player || !player->GetSession()) continue; if (player->GetGUID() == GetLeaderGUID()) sLfgMgr.SendJoinResult(player, LFG_JOIN_OK); else { //player->m_lookingForGroup.roles = GetPlayerRole(player->GetGUID()); player->m_lookingForGroup.comment = ""; player->m_lookingForGroup.joinTime = getMSTime(); player->m_lookingForGroup.queuedDungeons = leader->m_lookingForGroup.queuedDungeons; } if (IsInDungeon()) premadePlayers.insert(player->GetGUID()); } m_lfgFlags &= ~LFG_GRP_ROLECHECK; SendUpdate(); sLfgMgr.RemoveRoleCheckGroup(this); if(GetMembersCount() == LFG_GROUP) TeleportToDungeon(); else sLfgMgr.AddCheckedGroup(this, true); }
void WorldSession::SendLfgSearchResults(LfgType type, uint32 entry) { WorldPacket data(SMSG_LFG_SEARCH_RESULTS); data << uint32(type); // type data << uint32(entry); // entry from LFGDungeons.dbc uint8 isGuidsPresent = 0; data << uint8(isGuidsPresent); if (isGuidsPresent) { uint32 guids_count = 0; data << uint32(guids_count); for (uint32 i = 0; i < guids_count; ++i) { data << uint64(0); // player/group guid } } uint32 groups_count = 1; data << uint32(groups_count); // groups count data << uint32(groups_count); // groups count (total?) for (uint32 i = 0; i < groups_count; ++i) { data << uint64(1); // group guid uint32 flags = 0x92; data << uint32(flags); // flags if (flags & 0x2) { data << uint8(0); // comment string, max len 256 } if (flags & 0x10) { for (uint32 j = 0; j < 3; ++j) data << uint8(0); // roles } if (flags & 0x80) { data << uint64(0); // instance guid data << uint32(0); // completed encounters } } // TODO: Guard Player map HashMapHolder<Player>::MapType const& players = sObjectAccessor.GetPlayers(); uint32 playersSize = players.size(); data << uint32(playersSize); // players count data << uint32(playersSize); // players count (total?) for (HashMapHolder<Player>::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter) { Player* plr = iter->second; if (!plr || plr->GetTeam() != _player->GetTeam()) continue; if (!plr->IsInWorld()) continue; data << plr->GetObjectGuid(); // guid uint32 flags = 0xFF; data << uint32(flags); // flags if (flags & 0x1) { data << uint8(plr->getLevel()); data << uint8(plr->getClass()); data << uint8(plr->getRace()); for (uint32 i = 0; i < 3; ++i) data << uint8(0); // talent spec x/x/x data << uint32(0); // armor data << uint32(0); // spd/heal data << uint32(0); // spd/heal data << uint32(0); // HasteMelee data << uint32(0); // HasteRanged data << uint32(0); // HasteSpell data << float(0); // MP5 data << float(0); // MP5 Combat data << uint32(0); // AttackPower data << uint32(0); // Agility data << uint32(0); // Health data << uint32(0); // Mana data << uint32(0); // Unk1 data << float(0); // Unk2 data << uint32(0); // Defence data << uint32(0); // Dodge data << uint32(0); // Block data << uint32(0); // Parry data << uint32(0); // Crit data << uint32(0); // Expertise } if (flags & 0x2) data << ""; // comment if (flags & 0x4) data << uint8(0); // group leader if (flags & 0x8) data << uint64(1); // group guid if (flags & 0x10) data << uint8(0); // roles if (flags & 0x20) data << uint32(plr->GetZoneId()); // areaid if (flags & 0x40) data << uint8(0); // status if (flags & 0x80) { data << uint64(0); // instance guid data << uint32(0); // completed encounters } } SendPacket(&data); }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received opcode CMSG_REQUEST_PARTY_MEMBER_STATS"); ObjectGuid guid; recv_data >> guid; Player* player = ObjectAccessor::FindPlayer(guid, false); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3 + 4 + 2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << guid.WriteAsPacked(); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Pet* pet = player->GetPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4 + 2 + 2 + 2 + 1 + 2 * 6 + 8 + 1 + 8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << player->GetPackGUID(); uint32 mask1 = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP | GROUP_UPDATE_FLAG_POWER_TYPE | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_AURAS | GROUP_UPDATE_FLAG_PHASE; if (pet) mask1 = 0x7FEFFEFF; // full mask & ~(GROUP_UPDATE_FLAG_VEHICLE_SEAT | GROUP_UPDATE_FLAG_UNK) Powers powerType = player->GetPowerType(); data << uint32(mask1); // group update mask data << uint16(MEMBER_STATUS_ONLINE); // member's online status data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP data << uint8(powerType); // GROUP_UPDATE_FLAG_POWER_TYPE data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL // verify player coordinates and zoneid to send to teammates uint16 iZoneId = 0; uint16 iCoordX = 0; uint16 iCoordY = 0; uint16 iCoordZ = 0; if (player->IsInWorld()) { iZoneId = player->GetZoneId(); iCoordX = player->GetPositionX(); iCoordY = player->GetPositionY(); iCoordZ = player->GetPositionZ(); } else if (player->IsBeingTeleported()) // Player is in teleportation { WorldLocation& loc = player->GetTeleportDest(); // So take teleportation destination iZoneId = sTerrainMgr.GetZoneId(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); iCoordX = loc.coord_x; iCoordY = loc.coord_y; iCoordZ = loc.coord_z; } else { // unknown player status. } data << uint16(iZoneId); // GROUP_UPDATE_FLAG_ZONE data << uint16(iCoordX); // GROUP_UPDATE_FLAG_POSITION data << uint16(iCoordY); // GROUP_UPDATE_FLAG_POSITION data << uint16(iCoordZ); // GROUP_UPDATE_FLAG_POSITION data << uint8(1); // if true, client clears all auras that are not in auramask and whose index is lower amount sent below uint64 auramask = 0; size_t maskPos = data.wpos(); data << uint64(auramask); // placeholder, server sends 0xFFFFFFFFFFFFFFFF here, but with 1 above it seems no difference data << uint32(MAX_AURAS); // server sends here number of visible auras, but client checks // if aura is in auramask, so it seems no difference if there will be MAX_AURAS for (uint8 i = 0; i < MAX_AURAS; ++i) { if (SpellAuraHolder* holder = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << uint32(holder->GetId()); data << uint16(holder->GetAuraFlags()); if (holder->GetAuraFlags() & AFLAG_EFFECT_AMOUNT_SEND) for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) if (Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i))) data << int32(aura->GetModifier()->m_amount); else data << int32(0); } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if (pet) { Powers petpowertype = pet->GetPowerType(); data << pet->GetObjectGuid(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet->GetDisplayId()); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << uint32(pet->GetHealth()); // GROUP_UPDATE_FLAG_PET_CUR_HP data << uint32(pet->GetMaxHealth()); // GROUP_UPDATE_FLAG_PET_MAX_HP data << uint8(petpowertype); // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << uint16(pet->GetPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << uint16(pet->GetMaxPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_MAX_POWER data << uint8(1); // if true, client clears all auras that are not in auramask and whose index is lower amount sent below uint64 petauramask = 0; size_t petMaskPos = data.wpos(); data << uint64(petauramask); // placeholder, server sends 0xFFFFFFFFFFFFFFFF here, but with 1 above it seems no difference data << uint32(MAX_AURAS); // server sends here number of visible auras, but client checks // if aura is in auramask, so it seems no difference if there will be MAX_AURAS for (uint8 i = 0; i < MAX_AURAS; ++i) { if (SpellAuraHolder* holder = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); data << uint32(holder->GetId()); data << uint16(holder->GetAuraFlags()); if (holder->GetAuraFlags() & AFLAG_EFFECT_AMOUNT_SEND) for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) if (Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i))) data << int32(aura->GetModifier()->m_amount); else data << int32(0); } } data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS } else { data << uint8(0); // GROUP_UPDATE_FLAG_PET_NAME data << uint8(1); // GROUP_UPDATE_FLAG_PET_AURAS data << uint64(0); // GROUP_UPDATE_FLAG_PET_AURAS data << uint32(0); // GROUP_UPDATE_FLAG_PET_AURAS } if (player->GetTransportInfo()) // GROUP_UPDATE_FLAG_VEHICLE_SEAT data << uint32(((Unit*)player->GetTransportInfo()->GetTransport())->GetVehicleInfo()->GetVehicleEntry()->m_seatID[player->GetTransportInfo()->GetTransportSeat()]); data << uint32(8); // GROUP_UPDATE_FLAG_PHASE data << uint32(0); // GROUP_UPDATE_FLAG_PHASE data << uint8(0); // GROUP_UPDATE_FLAG_PHASE SendPacket(&data); }
void Transporter::TransportPassengers(uint32 mapid, uint32 oldmap, float x, float y, float z) { sEventMgr.RemoveEvents(this, EVENT_TRANSPORTER_NEXT_WAYPOINT); if(mPassengers.size() > 0) { PassengerIterator itr = mPassengers.begin(); PassengerIterator it2; WorldPacket Pending(SMSG_TRANSFER_PENDING, 12); Pending << mapid << GetEntry() << oldmap; WorldPacket NewWorld; LocationVector v; for(; itr != mPassengers.end();) { it2 = itr++; Player* plr = objmgr.GetPlayer(it2->first); if(!plr) { // remove from map mPassengers.erase(it2); continue; } if(!plr->GetSession() || !plr->IsInWorld()) continue; v.x = x + plr->m_transportPosition->x; v.y = y + plr->m_transportPosition->y; v.z = z + plr->m_transportPosition->z; v.o = plr->GetOrientation(); if(mapid == 530 && !plr->GetSession()->HasFlag(ACCOUNT_FLAG_XPACK_01)) { // player is not flagged to access bc content, repop at graveyard plr->RepopAtGraveyard(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetMapId()); continue; } if(mapid == 571 && !plr->GetSession()->HasFlag(ACCOUNT_FLAG_XPACK_02)) { plr->RepopAtGraveyard(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetMapId()); continue; } // Lucky bitch. Do it like on official. if(plr->isDead()) plr->RemoteRevive(); if( plr->m_CurrentVehicle ) plr->m_CurrentVehicle->RemovePassenger( plr ); plr->m_lockTransportVariables = true; plr->GetSession()->SendPacket(&Pending); #ifndef CLUSTERING plr->_Relocate(mapid, v, false, true, 0); #else plr->RelocateCallback(mapid); #endif } } // Set our position RemoveFromWorld(false); SetMapId(mapid); SetPosition(x,y,z,m_position.o,false); AddToWorld(); }
void WorldSession::SendLfgUpdateProposal(LFGProposal* pProposal) { if (!sWorld.getConfig(CONFIG_BOOL_LFG_ENABLE)) { DEBUG_LOG("SendLfgUpdateProposal %u failed - Dungeon finder disabled", GetPlayer()->GetObjectGuid().GetCounter()); return; } if (!pProposal) return; LFGDungeonEntry const* dungeon = pProposal->GetDungeon(); if (!dungeon) { DEBUG_LOG("SMSG_LFG_PROPOSAL_UPDATE: no dungeon in proposal %u, returning.", pProposal->m_uiID); return; } ObjectGuid guid = GetPlayer()->GetObjectGuid(); bool isSameDungeon = false; bool isSameGroup = false; uint32 completedEncounters = 0; LFGRolesMap rolesMap; if (Group* group = pProposal->GetGroup()) { for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pGroupMember = itr->getSource(); if (pGroupMember && pGroupMember->IsInWorld()) { rolesMap.insert(std::make_pair(pGroupMember->GetObjectGuid(), sLFGMgr.GetLFGPlayerState(pGroupMember->GetObjectGuid())->GetRoles())); if (InstancePlayerBind* bind = pGroupMember->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) { if (DungeonPersistentState* state = bind->state) completedEncounters |= state->GetCompletedEncountersMask(); } } } // isContinue = group->isLFGGroup() && sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON; isSameDungeon = dungeon->map == GetPlayer()->GetMapId(); isSameGroup = GetPlayer()->GetGroup() == group; } GuidSet const proposalGuids = pProposal->GetMembers(); if (!proposalGuids.empty()) { for (GuidSet::const_iterator itr = proposalGuids.begin(); itr != proposalGuids.end(); ++itr) { Player* player = sObjectMgr.GetPlayer(*itr); if (player && player->IsInWorld()) rolesMap.insert(std::make_pair(player->GetObjectGuid(), sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->GetRoles())); } } uint32 size = rolesMap.size(); DEBUG_LOG("SMSG_LFG_PROPOSAL_UPDATE proposal %u, player %u, state: %u", pProposal->m_uiID, GetPlayer()->GetObjectGuid().GetCounter(), pProposal->GetState()); WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + size * (4 + 1 + 1 + 1 + 1 +1)); data << uint32(dungeon->Entry()); // Dungeon data << uint8(pProposal->GetState()); // Result state data << uint32(pProposal->m_uiID); // Internal Proposal ID data << uint32(completedEncounters); // Bosses killed data << uint8(isSameDungeon); // Silent (show client window) data << uint8(size); // Group size for (LFGRolesMap::const_iterator itr = rolesMap.begin(); itr != rolesMap.end(); ++itr) { Player* pPlayer = sObjectMgr.GetPlayer(itr->first); if (!pPlayer) continue; isSameDungeon = dungeon->map == pPlayer->GetMapId(); isSameGroup = pPlayer->GetGroup() == pProposal->GetGroup(); data << uint32(itr->second); // Role data << uint8(pPlayer->GetObjectGuid() == guid); // Self player data << uint8(isSameDungeon); // Not in dungeon data << uint8(isSameGroup); // Not same group data << uint8(sLFGMgr.GetLFGPlayerState(pPlayer->GetObjectGuid())->GetAnswer() != LFG_ANSWER_PENDING); // Answered data << uint8(sLFGMgr.GetLFGPlayerState(pPlayer->GetObjectGuid())->GetAnswer() == LFG_ANSWER_AGREE); // Accepted } SendPacket(&data); }
void Transporter::TransportPassengers(uint32 mapid, uint32 oldmap, float x, float y, float z) { sEventMgr.RemoveEvents(this, EVENT_TRANSPORTER_NEXT_WAYPOINT); if(mPassengers.size() > 0) { PassengerIterator itr = mPassengers.begin(); PassengerIterator it2; WorldPacket Pending(SMSG_TRANSFER_PENDING, 12); Pending << mapid << GetEntry() << oldmap; WorldPacket NewWorld; LocationVector v; for(; itr != mPassengers.end();) { it2 = itr; ++itr; Player *plr = objmgr.GetPlayer(it2->first); if(!plr) { // remove all non players from map mPassengers.erase(it2); continue; } if(!plr->GetSession() || !plr->IsInWorld()) continue; plr->m_lockTransportVariables = true; v.x = x + plr->m_TransporterX; v.y = y + plr->m_TransporterY; v.z = z + plr->m_TransporterZ; v.o = plr->GetOrientation(); if(mapid == 530 && !plr->GetSession()->HasFlag(ACCOUNT_FLAG_XPACK_01)) { // player does not have BC content, repop at graveyard plr->RepopAtGraveyard(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetMapId()); continue; } plr->GetSession()->SendPacket(&Pending); plr->_Relocate(mapid, v, false, true, 0); // Lucky bitch. Do it like on official. if(plr->isDead()) { plr->ResurrectPlayer(); plr->SetUInt32Value(UNIT_FIELD_HEALTH, plr->GetUInt32Value(UNIT_FIELD_MAXHEALTH)); plr->SetUInt32Value(UNIT_FIELD_POWER1, plr->GetUInt32Value(UNIT_FIELD_MAXPOWER1)); } } } // Set our position RemoveFromWorld(false); SetMapId(mapid); SetPosition(x,y,z,m_position.o,false); AddToWorld(); }
bool Group::_addMember(ObjectGuid guid, const char* name, bool isAssistant, uint8 group) { if (IsFull()) return false; if (!guid) return false; Player* player = sObjectMgr.GetPlayer(guid, false); uint32 lastMap = 0; if (player && player->IsInWorld()) lastMap = player->GetMapId(); else if (player && player->IsBeingTeleported()) lastMap = player->GetTeleportDest().mapid; MemberSlot member; member.guid = guid; member.name = name; member.group = group; member.assistant = isAssistant; member.lastMap = lastMap; m_memberSlots.push_back(member); SubGroupCounterIncrease(group); if (player) { player->SetGroupInvite(nullptr); // if player is in group and he is being added to BG raid group, then call SetBattleGroundRaid() if (player->GetGroup() && isBGGroup()) player->SetBattleGroundRaid(this, group); // if player is in bg raid and we are adding him to normal group, then call SetOriginalGroup() else if (player->GetGroup()) player->SetOriginalGroup(this, group); // if player is not in group, then call set group else player->SetGroup(this, group); if (player->IsInWorld()) { // if the same group invites the player back, cancel the homebind timer if (InstanceGroupBind* bind = GetBoundInstance(player->GetMapId(), player)) if (bind->state->GetInstanceId() == player->GetInstanceId()) player->m_InstanceValid = true; } } if (!isRaidGroup()) // reset targetIcons for non-raid-groups { for (int i = 0; i < TARGET_ICON_COUNT; ++i) m_targetIcons[i].Clear(); } if (!isBGGroup()) { // insert into group table CharacterDatabase.PExecute("INSERT INTO group_member(groupId,memberGuid,assistant,subgroup) VALUES('%u','%u','%u','%u')", m_Id, member.guid.GetCounter(), ((member.assistant == 1) ? 1 : 0), member.group); } return true; }
Player* ObjectAccessor::GetObjectInWorld(uint64 guid, Player* /*typeSpecifier*/) { Player* player = HashMapHolder<Player>::Find(guid); return player && player->IsInWorld() ? player : NULL; }
void WorldSession::DoLootRelease(uint64 lguid) { Player *player = GetPlayer(); Loot *loot; player->SetLootGUID(0); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject *go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { // GO is mineral vein? so it is not removed after its looted if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) { uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; // only vein pass this check if (go_min != 0 && go_max > go_min) { float amount_rate = sWorld->getRate(RATE_MINING_AMOUNT); float min_amount = go_min*amount_rate; float max_amount = go_max*amount_rate; go->AddUse(); float uses = float(go->GetUseCount()); if (uses < max_amount) { if (uses >= min_amount) { float chance_rate = sWorld->getRate(RATE_MINING_NEXT); int32 ReqValue = 175; LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if (lockInfo) ReqValue = lockInfo->Skill[0]; float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25); double chance = pow(0.8*chance_rate, 4*(1/double(max_amount))*double(uses)); if (roll_chance_f((float)(100*chance+skill))) { go->SetLootState(GO_READY); } else // not have more uses go->SetLootState(GO_JUST_DEACTIVATED); } else // 100% chance until min uses go->SetLootState(GO_READY); } else // max uses already go->SetLootState(GO_JUST_DEACTIVATED); } else // not vein go->SetLootState(GO_JUST_DEACTIVATED); } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned in next tick if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens, go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); } else go->SetLootState(GO_READY); } else // not chest (or vein/herb/etc) go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else { // not fully looted object go->SetLootState(GO_ACTIVATED); // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { if (Group* pGroup = player->GetGroup()) { if (pGroup->GetLootMethod() != MASTER_LOOT) { loot->roundRobinPlayer = 0; } } else loot->roundRobinPlayer = 0; } } } else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG { Corpse *corpse = ObjectAccessor::GetCorpse(*player, lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } } else if (IS_ITEM_GUID(lguid)) { Item *pItem = player->GetItemByGuid(lguid); if (!pItem) return; ItemTemplate const* proto = pItem->GetTemplate(); // destroy only 5 items from stack in case prospecting and milling if (proto->Flags & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE)) { pItem->m_lootGenerated = false; pItem->loot.clear(); uint32 count = pItem->GetCount(); // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. if (count > 5) count = 5; player->DestroyItemCount(pItem, count, true); } else // FIXME: item must not be deleted in case not fully looted state. But this pre-request implement loot saving in DB at item save. Or cheating possible. player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); return; // item can be looted only single player } else { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &pCreature->loot; if (loot->isLooted()) { // skip pickpocketing loot for speed, skinning timer reduction is no-op in fact if (!pCreature->isAlive()) pCreature->AllLootRemovedFromCorpse(); pCreature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); loot->clear(); } else { // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { if (Group* pGroup = player->GetGroup()) { if (pGroup->GetLootMethod() != MASTER_LOOT) { loot->roundRobinPlayer = 0; pGroup->SendLooter(pCreature, NULL); // force update of dynamic flags, otherwise other group's players still not able to loot. pCreature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); } } else loot->roundRobinPlayer = 0; } } } //Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetGUID()); }
static bool HandleGMTicketUnAssignCommand(ChatHandler* handler, char const* args) { if (!*args) return false; uint32 ticketId = atoi(args); GmTicket* ticket = sTicketMgr->GetTicket(ticketId); if (!ticket || ticket->IsClosed()) { handler->SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); return true; } // Ticket must be assigned if (!ticket->IsAssigned()) { handler->PSendSysMessage(LANG_COMMAND_TICKETNOTASSIGNED, ticket->GetId()); return true; } // Get security level of player, whom this ticket is assigned to uint32 security = SEC_PLAYER; Player* assignedPlayer = ticket->GetAssignedPlayer(); if (assignedPlayer && assignedPlayer->IsInWorld()) security = assignedPlayer->GetSession()->GetSecurity(); else { ObjectGuid guid = ticket->GetAssignedToGUID(); uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(guid); security = AccountMgr::GetSecurity(accountId, realmID); } // Check security //! If no m_session present it means we're issuing this command from the console uint32 mySecurity = handler->GetSession() ? handler->GetSession()->GetSecurity() : SEC_CONSOLE; if (security > mySecurity) { handler->SendSysMessage(LANG_COMMAND_TICKETUNASSIGNSECURITY); return true; } std::string assignedTo = ticket->GetAssignedToName(); // copy assignedto name because we need it after the ticket has been unnassigned SQLTransaction trans = SQLTransaction(NULL); ticket->SetUnassigned(); ticket->SaveToDB(trans); sTicketMgr->UpdateLastChange(); std::string msg = ticket->FormatMessageString(*handler, NULL, assignedTo.c_str(), handler->GetSession() ? handler->GetSession()->GetPlayer()->GetName().c_str() : "Console", NULL, NULL); handler->SendGlobalGMSysMessage(msg.c_str()); if ((sIRC->TICMASK & 16) != 0 && (sIRC->BOTMASK & 1024) != 0 && sIRC->ticann.size() > 0) { std::string ircchan = "#"; std::ostringstream smsg; ircchan += sIRC->ticann; smsg << "[\00304Ticket Assigned\003][By:\00304 " << ticket->GetPlayerName().c_str() << " \003][ID: \00304" << ticket->GetId() << " \003][Unssigned From: \00304" << assignedTo.c_str() << " \003][By: \00304" << (GetSession() ? GetSession()->GetPLayer()->GetName().c_str() : 'Console') << " \003]"; /* Keeping old line incase i fubar this :D << assignedTo.c_str() << " \003][By: \00304" << handler->GetSession()->GetPlayer()->GetName().c_str() << " \003]"; */ sIRC->Send_IRC_Channel(ircchan, smsg.str().c_str() , true); } return true; }