void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) { ObjectGuid playerGuid = holder->GetGuid(); Player* pCurrChar = new Player(this); pCurrChar->GetMotionMaster()->Initialize(); // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) if (!pCurrChar->LoadFromDB(playerGuid, holder)) { KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick delete pCurrChar; // delete it manually delete holder; // delete all unprocessed queries m_playerLoading = false; return; } SetPlayer(pCurrChar); WorldPacket data(SMSG_LOGIN_VERIFY_WORLD, 20); data << pCurrChar->GetMapId(); data << pCurrChar->GetPositionX(); data << pCurrChar->GetPositionY(); data << pCurrChar->GetPositionZ(); data << pCurrChar->GetOrientation(); SendPacket(&data); data.Initialize(SMSG_ACCOUNT_DATA_TIMES, 128); for (int i = 0; i < 32; ++i) data << uint32(0); SendPacket(&data); // Send MOTD (1.12.1 not have SMSG_MOTD, so do it in another way) { uint32 linecount = 0; std::string str_motd = sWorld.GetMotd(); std::string::size_type pos, nextpos; std::string motd; pos = 0; while ((nextpos = str_motd.find('@', pos)) != std::string::npos) { if (nextpos != pos) { ChatHandler(pCurrChar).PSendSysMessage(str_motd.substr(pos, nextpos - pos).c_str()); ++linecount; } pos = nextpos + 1; } if (pos < str_motd.length()) { ChatHandler(pCurrChar).PSendSysMessage(str_motd.substr(pos).c_str()); ++linecount; } DEBUG_LOG("WORLD: Sent motd (SMSG_MOTD)"); } // QueryResult *result = CharacterDatabase.PQuery("SELECT guildid,rank FROM guild_member WHERE guid = '%u'",pCurrChar->GetGUIDLow()); QueryResult* resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD); if (resultGuild) { Field* fields = resultGuild->Fetch(); pCurrChar->SetInGuild(fields[0].GetUInt32()); pCurrChar->SetRank(fields[1].GetUInt32()); delete resultGuild; } else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about nonexistent membership { pCurrChar->SetInGuild(0); pCurrChar->SetRank(0); } if (pCurrChar->GetGuildId() != 0) { Guild* guild = sGuildMgr.GetGuildById(pCurrChar->GetGuildId()); if (guild) { data.Initialize(SMSG_GUILD_EVENT, (1 + 1 + guild->GetMOTD().size() + 1)); data << uint8(GE_MOTD); data << uint8(1); data << guild->GetMOTD(); SendPacket(&data); DEBUG_LOG("WORLD: Sent guild-motd (SMSG_GUILD_EVENT)"); guild->BroadcastEvent(GE_SIGNED_ON, pCurrChar->GetObjectGuid(), pCurrChar->GetName()); } else { // remove wrong guild data sLog.outError("Player %s (GUID: %u) marked as member of nonexistent guild (id: %u), removing guild membership for player.", pCurrChar->GetName(), pCurrChar->GetGUIDLow(), pCurrChar->GetGuildId()); pCurrChar->SetInGuild(0); } } if (!pCurrChar->isAlive()) pCurrChar->SendCorpseReclaimDelay(true); pCurrChar->SendInitialPacketsBeforeAddToMap(); // Show cinematic at the first time that player login if (!pCurrChar->getCinematic()) { pCurrChar->setCinematic(1); if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace())) pCurrChar->SendCinematicStart(rEntry->CinematicSequence); } if (!pCurrChar->GetMap()->Add(pCurrChar)) { // normal delayed teleport protection not applied (and this correct) for this case (Player object just created) AreaTrigger const* at = sObjectMgr.GetGoBackTrigger(pCurrChar->GetMapId()); if (at) pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); else pCurrChar->TeleportToHomebind(); } sObjectAccessor.AddObject(pCurrChar); // DEBUG_LOG("Player %s added to Map.",pCurrChar->GetName()); pCurrChar->GetSocial()->SendFriendList(); pCurrChar->GetSocial()->SendIgnoreList(); pCurrChar->SendInitialPacketsAfterAddToMap(); static SqlStatementID updChars; static SqlStatementID updAccount; SqlStatement stmt = CharacterDatabase.CreateStatement(updChars, "UPDATE characters SET online = 1 WHERE guid = ?"); stmt.PExecute(pCurrChar->GetGUIDLow()); stmt = LoginDatabase.CreateStatement(updAccount, "UPDATE account SET active_realm_id = ? WHERE id = ?"); stmt.PExecute(realmID, GetAccountId()); pCurrChar->SetInGameTime(WorldTimer::getMSTime()); // announce group about member online (must be after add to player list to receive announce to self) if (Group* group = pCurrChar->GetGroup()) group->SendUpdate(); // friend status sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetObjectGuid(), true); // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); // setting Ghost+speed if dead if (pCurrChar->m_deathState != ALIVE) { // not blizz like, we must correctly save and load player instead... if (pCurrChar->getRace() == RACE_NIGHTELF) pCurrChar->CastSpell(pCurrChar, 20584, true); // auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) pCurrChar->SetWaterWalk(true); } pCurrChar->ContinueTaxiFlight(); // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned) pCurrChar->LoadPet(); // Set FFA PvP for non GM in non-rest mode if (sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING)) pCurrChar->SetFFAPvP(true); if (pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) pCurrChar->SetContestedPvP(); // Apply at_login requests if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) { pCurrChar->resetSpells(); SendNotification(LANG_RESET_SPELLS); } if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) { pCurrChar->resetTalents(true); SendNotification(LANG_RESET_TALENTS); // we can use SMSG_TALENTS_INVOLUNTARILY_RESET here } if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST)) pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST); // show time before shutdown if shutdown planned. if (sWorld.IsShutdowning()) sWorld.ShutdownMsg(true, pCurrChar); if (sWorld.getConfig(CONFIG_BOOL_ALL_TAXI_PATHS)) pCurrChar->SetTaxiCheater(true); if (pCurrChar->isGameMaster()) SendNotification(LANG_GM_ON); if (!pCurrChar->isGMVisible()) { SendNotification(LANG_INVISIBLE_INVISIBLE); SpellEntry const* invisibleAuraInfo = sSpellStore.LookupEntry(sWorld.getConfig(CONFIG_UINT32_GM_INVISIBLE_AURA)); if (invisibleAuraInfo && IsSpellAppliesAura(invisibleAuraInfo)) pCurrChar->CastSpell(pCurrChar, invisibleAuraInfo, true); } std::string IP_str = GetRemoteAddress(); sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid: %u)", GetAccountId(), IP_str.c_str(), pCurrChar->GetName(), pCurrChar->GetGUIDLow()); if (!pCurrChar->IsStandState() && !pCurrChar->hasUnitState(UNIT_STAT_STUNNED)) pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); m_playerLoading = false; delete holder; }
//spawn go static bool HandleGameObjectAddCommand(ChatHandler* handler, char const* args) { if (!*args) return false; // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r char* id = handler->extractKeyFromLink((char*)args, "Hgameobject_entry"); if (!id) return false; uint32 objectId = atol(id); if (!objectId) return false; char* spawntimeSecs = strtok(NULL, " "); const GameObjectTemplate* objectInfo = sObjectMgr->GetGameObjectTemplate(objectId); if (!objectInfo) { handler->PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST, objectId); handler->SetSentErrorMessage(true); return false; } if (objectInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(objectInfo->displayId)) { // report to DB errors log as in loading case sLog->outErrorDb("Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned.", objectId, objectInfo->type, objectInfo->displayId); handler->PSendSysMessage(LANG_GAMEOBJECT_HAVE_INVALID_DATA, objectId); handler->SetSentErrorMessage(true); return false; } Player* player = handler->GetSession()->GetPlayer(); float x = float(player->GetPositionX()); float y = float(player->GetPositionY()); float z = float(player->GetPositionZ()); float o = float(player->GetOrientation()); Map* map = player->GetMap(); GameObject* object = new GameObject; uint32 guidLow = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT); if (!object->Create(guidLow, objectInfo->entry, map, player->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete object; return false; } if (spawntimeSecs) { uint32 value = atoi((char*)spawntimeSecs); object->SetRespawnTime(value); } // fill the gameobject data and save to the db object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), player->GetPhaseMaskForSpawn()); // this will generate a new guid if the object is in an instance if (!object->LoadGameObjectFromDB(guidLow, map)) { delete object; return false; } // TODO: is it really necessary to add both the real and DB table guid here ? sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGOData(guidLow)); handler->PSendSysMessage(LANG_GAMEOBJECT_ADD, objectId, objectInfo->name.c_str(), guidLow, x, y, z); return true; }
uint8 WorldSession::HandleLoadPetFromDBFirstCallback(PreparedQueryResult result, uint8 asynchLoadType) { if (!GetPlayer() || GetPlayer()->GetPet() || GetPlayer()->GetVehicle() || GetPlayer()->IsSpectator()) return PET_LOAD_ERROR; if (!result) return PET_LOAD_NO_RESULT; Field* fields = result->Fetch(); // Xinef: this can happen if fetch is called twice, impossibru. if (!fields) return PET_LOAD_ERROR; Player* owner = GetPlayer(); // update for case of current pet "slot = 0" uint32 petentry = fields[1].GetUInt32(); if (!petentry) return PET_LOAD_NO_RESULT; uint8 petSlot = fields[7].GetUInt8(); bool current = petSlot == PET_SAVE_AS_CURRENT; uint32 summon_spell_id = fields[15].GetUInt32(); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summon_spell_id); // CANT BE NULL bool is_temporary_summoned = spellInfo && spellInfo->GetDuration() > 0; uint32 pet_number = fields[0].GetUInt32(); uint32 savedhealth = fields[10].GetUInt32(); uint32 savedmana = fields[11].GetUInt32(); PetType pet_type = PetType(fields[16].GetUInt8()); // xinef: BG resurrect, overwrite saved value if (asynchLoadType == PET_LOAD_BG_RESURRECT) savedhealth = 1; if (pet_type == HUNTER_PET && savedhealth == 0 && asynchLoadType != PET_LOAD_SUMMON_DEAD_PET) { WorldPacket data(SMSG_CAST_FAILED, 1+4+1+4); data << uint8(0); data << uint32(883); data << uint8(SPELL_FAILED_TARGETS_DEAD); SendPacket(&data); owner->RemoveSpellCooldown(883, false); return PET_LOAD_ERROR; } // check temporary summoned pets like mage water elemental if (current && is_temporary_summoned) return PET_LOAD_ERROR; if (pet_type == HUNTER_PET) { CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petentry); if (!creatureInfo || !creatureInfo->IsTameable(owner->CanTameExoticPets())) return PET_LOAD_ERROR; } Map* map = owner->GetMap(); uint32 guid = sObjectMgr->GenerateLowGuid(HIGHGUID_PET); Pet* pet = new Pet(owner, pet_type); LoadPetFromDBQueryHolder* holder = new LoadPetFromDBQueryHolder(pet_number, current, uint32(time(NULL) - fields[14].GetUInt32()), fields[13].GetString(), savedhealth, savedmana); if (!pet->Create(guid, map, owner->GetPhaseMask(), petentry, pet_number) || !holder->Initialize()) { delete pet; delete holder; return PET_LOAD_ERROR; } float px, py, pz; owner->GetClosePoint(px, py, pz, pet->GetObjectSize(), PET_FOLLOW_DIST, pet->GetFollowAngle()); if (!pet->IsPositionValid()) { sLog->outError("Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)", pet->GetGUIDLow(), pet->GetEntry(), pet->GetPositionX(), pet->GetPositionY()); delete pet; delete holder; return PET_LOAD_ERROR; } pet->SetLoading(true); pet->Relocate(px, py, pz, owner->GetOrientation()); pet->setPetType(pet_type); pet->setFaction(owner->getFaction()); pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); if (pet->IsCritter()) { map->AddToMap(pet->ToCreature(), true); pet->SetLoading(false); // xinef, mine delete holder; return PET_LOAD_OK; } pet->GetCharmInfo()->SetPetNumber(pet_number, pet->IsPermanentPetFor(owner)); pet->SetDisplayId(fields[3].GetUInt32()); pet->SetNativeDisplayId(fields[3].GetUInt32()); uint32 petlevel = fields[4].GetUInt8(); pet->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); pet->SetName(fields[8].GetString()); switch (pet->getPetType()) { case SUMMON_PET: petlevel = owner->getLevel(); if (pet->IsPetGhoul()) pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x400); // class = rogue else pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x800); // class = mage pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet dismiss, cancel) break; case HUNTER_PET: pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); // class = warrior, gender = none, power = focus pet->SetSheath(SHEATH_STATE_MELEE); pet->SetByteFlag(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_CAN_BE_ABANDONED : UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED); pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet abandon, cancel) pet->SetMaxPower(POWER_HAPPINESS, pet->GetCreatePowers(POWER_HAPPINESS)); pet->SetPower(POWER_HAPPINESS, fields[12].GetUInt32()); pet->setPowerType(POWER_FOCUS); break; default: if (!pet->IsPetGhoul()) sLog->outError("Pet have incorrect type (%u) for pet loading.", pet->getPetType()); break; } pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped here pet->SetCreatorGUID(owner->GetGUID()); owner->SetMinion(pet, true); pet->InitStatsForLevel(petlevel); pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32()); pet->SynchronizeLevelWithOwner(); pet->SetReactState(ReactStates(fields[6].GetUInt8())); pet->SetCanModifyStats(true); // set current pet as current // 0=current // 1..MAX_PET_STABLES in stable slot // PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning)) if (petSlot) { SQLTransaction trans = CharacterDatabase.BeginTransaction(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_PET_SLOT_BY_SLOT_EXCLUDE_ID); stmt->setUInt8(0, uint8(PET_SAVE_NOT_IN_SLOT)); stmt->setUInt32(1, owner->GetGUIDLow()); stmt->setUInt8(2, uint8(PET_SAVE_AS_CURRENT)); stmt->setUInt32(3, pet_number); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID); stmt->setUInt8(0, uint8(PET_SAVE_AS_CURRENT)); stmt->setUInt32(1, owner->GetGUIDLow()); stmt->setUInt32(2, pet_number); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); } // Send fake summon spell cast - this is needed for correct cooldown application for spells // Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside // TODO: pets should be summoned from real cast instead of just faking it? if (summon_spell_id) { WorldPacket data(SMSG_SPELL_GO, (8+8+4+4+2)); data.append(owner->GetPackGUID()); data.append(owner->GetPackGUID()); data << uint8(0); data << uint32(summon_spell_id); data << uint32(256); // CAST_FLAG_UNKNOWN3 data << uint32(0); owner->SendMessageToSet(&data, true); } // do it as early as possible! pet->InitTalentForLevel(); // set original talents points before spell loading if (!is_temporary_summoned) pet->GetCharmInfo()->InitPetActionBar(); map->AddToMap(pet->ToCreature(), true); if (pet->getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current pet->SetPower(POWER_MANA, pet->GetMaxPower(POWER_MANA)); else { pet->SetHealth(savedhealth > pet->GetMaxHealth() ? pet->GetMaxHealth() : savedhealth); pet->SetPower(POWER_MANA, savedmana > pet->GetMaxPower(POWER_MANA) ? pet->GetMaxPower(POWER_MANA) : savedmana); } pet->SetAsynchLoadType(asynchLoadType); // xinef: clear any old result if (_loadPetFromDBSecondCallback.ready()) { SQLQueryHolder* param; _loadPetFromDBSecondCallback.get(param); delete param; } _loadPetFromDBSecondCallback.cancel(); _loadPetFromDBSecondCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder); return PET_LOAD_OK; }
bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, std::string const& fullcmd) { char const* oldtext = text; std::string cmd = ""; while (*text != ' ' && *text != '\0') { cmd += *text; ++text; } while (*text == ' ') ++text; for (uint32 i = 0; table[i].Name != NULL; ++i) { if (!hasStringAbbr(table[i].Name, cmd.c_str())) continue; bool match = false; if (strlen(table[i].Name) > cmd.length()) { for (uint32 j = 0; table[j].Name != NULL; ++j) { if (!hasStringAbbr(table[j].Name, cmd.c_str())) continue; if (strcmp(table[j].Name, cmd.c_str()) == 0) { match = true; break; } } } if (match) continue; // select subcommand from child commands list if (table[i].ChildCommands != NULL) { if (!ExecuteCommandInTable(table[i].ChildCommands, text, fullcmd)) { if (text[0] != '\0') SendSysMessage(LANG_NO_SUBCMD); else SendSysMessage(LANG_CMD_SYNTAX); ShowHelpForCommand(table[i].ChildCommands, text); } return true; } // must be available and have handler if (!table[i].Handler || !isAvailable(table[i])) continue; SetSentErrorMessage(false); // table[i].Name == "" is special case: send original command to handler if ((table[i].Handler)(this, table[i].Name[0] != '\0' ? text : oldtext)) { if (!m_session) // ignore console return true; Player* player = m_session->GetPlayer(); if (!AccountMgr::IsPlayerAccount(m_session->GetSecurity())) { ObjectGuid guid = player->GetTarget(); uint32 areaId = player->GetAreaId(); std::string areaName = "Unknown"; std::string zoneName = "Unknown"; if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId)) { areaName = area->AreaName_lang; if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->ParentAreaID)) zoneName = zone->AreaName_lang; } sLog->outCommand(m_session->GetAccountId(), "Command: %s [Player: %s (%s) (Account: %u) X: %f Y: %f Z: %f Map: %u (%s) Area: %u (%s) Zone: %s Selected: %s (%s)]", fullcmd.c_str(), player->GetName().c_str(), player->GetGUID().ToString().c_str(), m_session->GetAccountId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), player->GetMap() ? player->GetMap()->GetMapName() : "Unknown", areaId, areaName.c_str(), zoneName.c_str(), (player->GetSelectedUnit()) ? player->GetSelectedUnit()->GetName().c_str() : "", guid.ToString().c_str()); } } // some commands have custom error messages. Don't send the default one in these cases. else if (!HasSentErrorMessage()) { if (!table[i].Help.empty()) SendSysMessage(table[i].Help.c_str()); else SendSysMessage(LANG_CMD_SYNTAX); } return true; } return false; }
static bool HandleWpShowCommand(ChatHandler* handler, const char* args) { if (!*args) return false; // first arg: on, off, first, last char* show_str = strtok((char*)args, " "); if (!show_str) return false; // second arg: GUID (optional, if a creature is selected) char* guid_str = strtok((char*)NULL, " "); uint32 pathid = 0; Creature* target = handler->getSelectedCreature(); // Did player provide a PathID? if (!guid_str) { // No PathID provided // -> Player must have selected a creature if (!target) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } pathid = target->GetWaypointPath(); } else { // PathID provided // Warn if player also selected a creature // -> Creature selection is ignored <- if (target) handler->SendSysMessage(LANG_WAYPOINT_CREATSELECTED); pathid = atoi((char*)guid_str); } std::string show = show_str; //handler->PSendSysMessage("wpshow - show: %s", show); // Show info for the selected waypoint if (show == "info") { // Check if the user did specify a visual waypoint if (!target || target->GetEntry() != VISUAL_WAYPOINT) { handler->PSendSysMessage(LANG_WAYPOINT_VP_SELECT); handler->SetSentErrorMessage(true); return false; } PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_ALL_BY_WPGUID); stmt->setUInt32(0, target->GetGUIDLow()); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { handler->SendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM); return true; } handler->SendSysMessage("|cff00ffffDEBUG: wp show info:|r"); do { Field* fields = result->Fetch(); pathid = fields[0].GetUInt32(); uint32 point = fields[1].GetUInt32(); uint32 delay = fields[2].GetUInt32(); uint32 flag = fields[3].GetUInt32(); uint32 ev_id = fields[4].GetUInt32(); uint32 ev_chance = fields[5].GetUInt32(); handler->PSendSysMessage("|cff00ff00Show info: for current point: |r|cff00ffff%u|r|cff00ff00, Path ID: |r|cff00ffff%u|r", point, pathid); handler->PSendSysMessage("|cff00ff00Show info: delay: |r|cff00ffff%u|r", delay); handler->PSendSysMessage("|cff00ff00Show info: Move flag: |r|cff00ffff%u|r", flag); handler->PSendSysMessage("|cff00ff00Show info: Waypoint event: |r|cff00ffff%u|r", ev_id); handler->PSendSysMessage("|cff00ff00Show info: Event chance: |r|cff00ffff%u|r", ev_chance); } while (result->NextRow()); return true; } if (show == "on") { PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_POS_BY_ID); stmt->setUInt32(0, pathid); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { handler->SendSysMessage("|cffff33ffPath no found.|r"); handler->SetSentErrorMessage(true); return false; } handler->PSendSysMessage("|cff00ff00DEBUG: wp on, PathID: |cff00ffff%u|r", pathid); // Delete all visuals for this NPC stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_WPGUID_BY_ID); stmt->setUInt32(0, pathid); PreparedQueryResult result2 = WorldDatabase.Query(stmt); if (result2) { bool hasError = false; do { Field* fields = result2->Fetch(); uint32 wpguid = fields[0].GetUInt32(); Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpguid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); if (!creature) { handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid); hasError = true; PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE); stmt->setUInt32(0, wpguid); WorldDatabase.Execute(stmt); } else { creature->CombatStop(); creature->DeleteFromDB(); creature->AddObjectToRemoveList(); } } while (result2->NextRow()); if (hasError) { handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR1); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR2); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR3); } } do { Field* fields = result->Fetch(); uint32 point = fields[0].GetUInt32(); float x = fields[1].GetFloat(); float y = fields[2].GetFloat(); float z = fields[3].GetFloat(); uint32 id = VISUAL_WAYPOINT; Player* chr = handler->GetSession()->GetPlayer(); Map* map = chr->GetMap(); float o = chr->GetOrientation(); Creature* wcreature = new Creature(); if (!wcreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMask(), id, 0, 0, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete wcreature; return false; } // Set "wpguid" column to the visual waypoint PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID); stmt->setInt32(0, int32(wcreature->GetGUIDLow())); stmt->setUInt32(1, pathid); stmt->setUInt32(2, point); WorldDatabase.Execute(stmt); wcreature->CopyPhaseFrom(chr); wcreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); if (!wcreature->LoadCreatureFromDB(wcreature->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete wcreature; return false; } if (target) { wcreature->SetDisplayId(target->GetDisplayId()); wcreature->SetObjectScale(0.5f); wcreature->SetLevel(std::min<uint32>(point, STRONG_MAX_LEVEL)); } } while (result->NextRow()); handler->SendSysMessage("|cff00ff00Showing the current creature's path.|r"); return true; } if (show == "first") { handler->PSendSysMessage("|cff00ff00DEBUG: wp first, GUID: %u|r", pathid); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_POS_FIRST_BY_ID); stmt->setUInt32(0, pathid); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUND, pathid); handler->SetSentErrorMessage(true); return false; } Field* fields = result->Fetch(); float x = fields[0].GetFloat(); float y = fields[1].GetFloat(); float z = fields[2].GetFloat(); uint32 id = VISUAL_WAYPOINT; Player* chr = handler->GetSession()->GetPlayer(); float o = chr->GetOrientation(); Map* map = chr->GetMap(); Creature* creature = new Creature(); if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMask(), id, 0, 0, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete creature; return false; } creature->CopyPhaseFrom(chr); creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete creature; return false; } if (target) { creature->SetDisplayId(target->GetDisplayId()); creature->SetObjectScale(0.5f); } return true; } if (show == "last") { handler->PSendSysMessage("|cff00ff00DEBUG: wp last, PathID: |r|cff00ffff%u|r", pathid); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_POS_LAST_BY_ID); stmt->setUInt32(0, pathid); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, pathid); handler->SetSentErrorMessage(true); return false; } Field* fields = result->Fetch(); float x = fields[0].GetFloat(); float y = fields[1].GetFloat(); float z = fields[2].GetFloat(); float o = fields[3].GetFloat(); uint32 id = VISUAL_WAYPOINT; Player* chr = handler->GetSession()->GetPlayer(); Map* map = chr->GetMap(); Creature* creature = new Creature(); if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMask(), id, 0, 0, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); delete creature; return false; } creature->CopyPhaseFrom(chr); creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); delete creature; return false; } if (target) { creature->SetDisplayId(target->GetDisplayId()); creature->SetObjectScale(0.5f); } return true; } if (show == "off") { PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_BY_ID); stmt->setUInt32(0, 1); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { handler->SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND); handler->SetSentErrorMessage(true); return false; } bool hasError = false; do { Field* fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(guid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); if (!creature) { handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid); hasError = true; PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE); stmt->setUInt32(0, guid); WorldDatabase.Execute(stmt); } else { creature->CombatStop(); creature->DeleteFromDB(); creature->AddObjectToRemoveList(); } } while (result->NextRow()); // set "wpguid" column to "empty" - no visual waypoint spawned stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_ALL_WPGUID); WorldDatabase.Execute(stmt); //WorldDatabase.PExecute("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'"); if (hasError) { handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR1); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR2); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR3); } handler->SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); return true; } handler->PSendSysMessage("|cffff33ffDEBUG: wpshow - no valid command found|r"); return true; }
void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recv_data) { sLog.outDebug("WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player* player = GetPlayer(); uint64 lguid = player->GetLootGUID(); Loot* loot = NULL; uint8 lootSlot = 0; recv_data >> lootSlot; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject *go = player->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))) { player->SendLootRelease(lguid); return; } loot = &go->loot; } else if (IS_ITEM_GUID(lguid)) { Item *pItem = player->GetItemByGuid(lguid); if (!pItem) { player->SendLootRelease(lguid); return; } loot = &pItem->loot; } else if (IS_CORPSE_GUID(lguid)) { Corpse *bones = ObjectAccessor::GetCorpse(*player, lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; } 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)) { player->SendLootRelease(lguid); return; } loot = &pCreature->loot; } player->StoreLootItem(lootSlot, loot); }
//spawn go static bool HandleGameObjectAddCommand(ChatHandler* handler, char const* args) { if (!*args) return false; // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r char* id = handler->extractKeyFromLink((char*)args, "Hgameobject_entry"); if (!id) return false; uint32 objectId = atol(id); if (!objectId) return false; if (handler->GetSession()->GetSecurity() == SEC_MODERATOR && handler->GetSession()->GetPlayer()->GetPhaseMask() == 1) { handler->SendSysMessage("You cannot permanently spawn in the main phase. Use .modify phase $number to spawn your GameObject, or spawn your GameObject temporarily."); return true; } if (handler->GetSession()->GetSecurity() == SEC_MODERATOR && handler->GetSession()->GetPlayer()->GetPhaseMask() == -1) { handler->SendSysMessage("You cannot permanently spawn in the main phase. Use .modify phase $number to spawn your GameObject, or spawn your GameObject temporarily."); return true; } char* spawntimeSecs = strtok(NULL, " "); const GameObjectTemplate* objectInfo = sObjectMgr->GetGameObjectTemplate(objectId); if (!objectInfo) { handler->PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST, objectId); handler->SetSentErrorMessage(true); return false; } if (objectInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(objectInfo->displayId)) { // report to DB errors log as in loading case TC_LOG_ERROR("sql.sql", "Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned.", objectId, objectInfo->type, objectInfo->displayId); handler->PSendSysMessage(LANG_GAMEOBJECT_HAVE_INVALID_DATA, objectId); handler->SetSentErrorMessage(true); return false; } Player* player = handler->GetSession()->GetPlayer(); float x = float(player->GetPositionX()); float y = float(player->GetPositionY()); float z = float(player->GetPositionZ()); float o = float(player->GetOrientation()); Map* map = player->GetMap(); GameObject* object = new GameObject; uint32 guidLow = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT); if (!object->Create(guidLow, objectInfo->entry, map, player->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete object; return false; } if (spawntimeSecs) { uint32 value = atoi((char*)spawntimeSecs); object->SetRespawnTime(value); } // fill the gameobject data and save to the db object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), player->GetPhaseMaskForSpawn()); // delete the old object and do a clean load from DB with a fresh new GameObject instance. // this is required to avoid weird behavior and memory leaks delete object; object = new GameObject(); // this will generate a new guid if the object is in an instance if (!object->LoadGameObjectFromDB(guidLow, map)) { delete object; return false; } /// @todo is it really necessary to add both the real and DB table guid here ? sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGOData(guidLow)); handler->PSendSysMessage(LANG_GAMEOBJECT_ADD, objectId, objectInfo->name.c_str(), guidLow, x, y, z); return true; }
void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player* player = GetPlayer(); uint64 lguid = player->GetLootGUID(); Loot* loot = NULL; uint8 lootSlot = 0; recvData >> lootSlot; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject* go = player->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))) { player->SendLootRelease(lguid); return; } loot = &go->loot; } else if (IS_ITEM_GUID(lguid)) { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) { player->SendLootRelease(lguid); return; } loot = &pItem->loot; } else if (IS_CORPSE_GUID(lguid)) { Corpse* bones = ObjectAccessor::GetCorpse(*player, lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; } else { Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid); bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed); if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { player->SendLootRelease(lguid); return; } loot = &creature->loot; } player->StoreLootItem(lootSlot, loot); // If player is removing the last LootItem, delete the empty container. if (loot->isLooted() && IS_ITEM_GUID(lguid)) player->GetSession()->DoLootRelease(lguid); }
//Summon Player bool ChatHandler::HandleSummonCommand(const char* args) { Player* target; uint64 target_guid; std::string target_name; if (!extractPlayerTarget((char*)args, &target, &target_guid, &target_name)) return false; Player* _player = m_session->GetPlayer(); if (target == _player || target_guid == _player->GetGUID()) { PSendSysMessage(LANG_CANT_TELEPORT_SELF); SetSentErrorMessage(true); return false; } if (target) { std::string nameLink = playerLink(target_name); // check online security if (HasLowerSecurity(target, 0)) return false; if (target->IsBeingTeleported()) { PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str()); SetSentErrorMessage(true); return false; } Map* map = m_session->GetPlayer()->GetMap(); if (map->IsBattlegroundOrArena()) { // only allow if gm mode is on if (!_player->isGameMaster()) { PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM, nameLink.c_str()); SetSentErrorMessage(true); return false; } // if both players are in different bgs else if (target->GetBattlegroundId() && m_session->GetPlayer()->GetBattlegroundId() != target->GetBattlegroundId()) target->LeaveBattleground(false); // Note: should be changed so target gets no Deserter debuff // all's well, set bg id // when porting out from the bg, it will be reset to 0 target->SetBattlegroundId(m_session->GetPlayer()->GetBattlegroundId(), m_session->GetPlayer()->GetBattlegroundTypeId()); // remember current position as entry point for return at bg end teleportation if (!target->GetMap()->IsBattlegroundOrArena()) target->SetBattlegroundEntryPoint(); } else if (map->IsDungeon()) { Map* cMap = target->GetMap(); if (cMap->Instanceable() && cMap->GetInstanceId() != map->GetInstanceId()) target->UnbindInstance(map->GetInstanceId(), target->GetDungeonDifficulty(), true); // we are in instance, and can summon only player in our group with us as lead if (!m_session->GetPlayer()->GetGroup() || !target->GetGroup() || (target->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID())) // the last check is a bit excessive, but let it be, just in case { PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, nameLink.c_str()); SetSentErrorMessage(true); return false; } } PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), ""); if (needReportToTarget(target)) ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, playerLink(_player->GetName()).c_str()); // stop flight if need if (target->isInFlight()) { target->GetMotionMaster()->MovementExpired(); target->CleanupAfterTaxiFlight(); } // save only in non-flight case else target->SaveRecallPosition(); // before GM float x, y, z; m_session->GetPlayer()->GetClosePoint(x, y, z, target->GetObjectSize()); target->TeleportTo(m_session->GetPlayer()->GetMapId(), x, y, z, target->GetOrientation()); target->SetPhaseMask(m_session->GetPlayer()->GetPhaseMask(), true); } else { // check offline security if (HasLowerSecurity(NULL, target_guid)) return false; std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), GetTrinityString(LANG_OFFLINE)); // in point where GM stay Player::SavePositionInDB(m_session->GetPlayer()->GetMapId(), m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetOrientation(), m_session->GetPlayer()->GetZoneId(), target_guid); } return true; }
//Teleport to Player bool ChatHandler::HandleAppearCommand(const char* args) { Player* target; uint64 target_guid; std::string target_name; if (!extractPlayerTarget((char*)args, &target, &target_guid, &target_name)) return false; Player* _player = m_session->GetPlayer(); if (target == _player || target_guid == _player->GetGUID()) { SendSysMessage(LANG_CANT_TELEPORT_SELF); SetSentErrorMessage(true); return false; } if (target) { // check online security if (HasLowerSecurity(target, 0)) return false; std::string chrNameLink = playerLink(target_name); Map* cMap = target->GetMap(); if (cMap->IsBattlegroundOrArena()) { // only allow if gm mode is on if (!_player->isGameMaster()) { PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM, chrNameLink.c_str()); SetSentErrorMessage(true); return false; } // if both players are in different bgs else if (_player->GetBattlegroundId() && _player->GetBattlegroundId() != target->GetBattlegroundId()) _player->LeaveBattleground(false); // Note: should be changed so _player gets no Deserter debuff // all's well, set bg id // when porting out from the bg, it will be reset to 0 _player->SetBattlegroundId(target->GetBattlegroundId(), target->GetBattlegroundTypeId()); // remember current position as entry point for return at bg end teleportation if (!_player->GetMap()->IsBattlegroundOrArena()) _player->SetBattlegroundEntryPoint(); } else if (cMap->IsDungeon()) { // we have to go to instance, and can go to player only if: // 1) we are in his group (either as leader or as member) // 2) we are not bound to any group and have GM mode on if (_player->GetGroup()) { // we are in group, we can go only if we are in the player group if (_player->GetGroup() != target->GetGroup()) { PSendSysMessage(LANG_CANNOT_GO_TO_INST_PARTY, chrNameLink.c_str()); SetSentErrorMessage(true); return false; } } else { // we are not in group, let's verify our GM mode if (!_player->isGameMaster()) { PSendSysMessage(LANG_CANNOT_GO_TO_INST_GM, chrNameLink.c_str()); SetSentErrorMessage(true); return false; } } // if the player or the player's group is bound to another instance // the player will not be bound to another one InstancePlayerBind* pBind = _player->GetBoundInstance(target->GetMapId(), target->GetDifficulty(cMap->IsRaid())); if (!pBind) { Group* group = _player->GetGroup(); // if no bind exists, create a solo bind InstanceGroupBind* gBind = group ? group->GetBoundInstance(target) : NULL; // if no bind exists, create a solo bind if (!gBind) if (InstanceSave* save = sInstanceSaveMgr->GetInstanceSave(target->GetInstanceId())) _player->BindToInstance(save, !save->CanReset()); } if (cMap->IsRaid()) _player->SetRaidDifficulty(target->GetRaidDifficulty()); else _player->SetDungeonDifficulty(target->GetDungeonDifficulty()); } PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str()); // stop flight if need if (_player->isInFlight()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); } // save only in non-flight case else _player->SaveRecallPosition(); // to point to see at target with same orientation float x, y, z; target->GetContactPoint(_player, x, y, z); _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE); _player->SetPhaseMask(target->GetPhaseMask(), true); } else { // check offline security if (HasLowerSecurity(NULL, target_guid)) return false; std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_APPEARING_AT, nameLink.c_str()); // to point where player stay (if loaded) float x, y, z, o; uint32 map; bool in_flight; if (!Player::LoadPositionFromDB(map, x, y, z, o, in_flight, target_guid)) return false; // stop flight if need if (_player->isInFlight()) { _player->GetMotionMaster()->MovementExpired(); _player->CleanupAfterTaxiFlight(); } // save only in non-flight case else _player->SaveRecallPosition(); _player->TeleportTo(map, x, y, z, _player->GetOrientation()); } return true; }
void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data ) { DEBUG_LOG("WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player *player = GetPlayer(); ObjectGuid lguid = player->GetLootGuid(); Loot *loot; uint8 lootSlot; recv_data >> lootSlot; switch( lguid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject *go = player->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))) { player->SendLootRelease(lguid); return; } loot = &go->loot; break; } case HIGHGUID_ITEM: { Item* pItem = player->GetItemByGuid(lguid); if (!pItem || !pItem->HasGeneratedLoot()) { player->SendLootRelease(lguid); return; } loot = &pItem->loot; break; } case HIGHGUID_CORPSE: { Corpse *bones = player->GetMap()->GetCorpse(lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; break; } case HIGHGUID_UNIT: case HIGHGUID_VEHICLE: { 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) ) { player->SendLootRelease(lguid); return; } loot = &pCreature->loot; break; } default: { sLog.outError("%s is unsupported for looting.",lguid.GetString().c_str()); return; } } player->StoreLootItem(lootSlot, loot); }
bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, const std::string& fullcmd) { char const* oldtext = text; std::string cmd = ""; while (*text != ' ' && *text != '\0') { cmd += *text; ++text; } while (*text == ' ') ++text; for (uint32 i = 0; table[i].Name != NULL; ++i) { if (!hasStringAbbr(table[i].Name, cmd.c_str())) continue; bool match = false; if (strlen(table[i].Name) > cmd.length()) { for (uint32 j = 0; table[j].Name != NULL; ++j) { if (!hasStringAbbr(table[j].Name, cmd.c_str())) continue; if (strcmp(table[j].Name, cmd.c_str()) != 0) continue; else { match = true; break; } } } if (match) continue; // select subcommand from child commands list if (table[i].ChildCommands != NULL) { if (!ExecuteCommandInTable(table[i].ChildCommands, text, fullcmd)) { if (text[0] != '\0') SendSysMessage(LANG_NO_SUBCMD); else SendSysMessage(LANG_CMD_SYNTAX); ShowHelpForCommand(table[i].ChildCommands, text); } return true; } // must be available and have handler if (!table[i].Handler || !isAvailable(table[i])) continue; SetSentErrorMessage(false); // table[i].Name == "" is special case: send original command to handler if ((table[i].Handler)(this, table[i].Name[0] != '\0' ? text : oldtext)) { // FIXME: When Command system is moved to RBAC this check must be changed if (!AccountMgr::IsPlayerAccount(table[i].SecurityLevel)) { // chat case if (m_session) { Player* p = m_session->GetPlayer(); uint64 sel_guid = p->GetSelection(); uint32 areaId = p->GetAreaId(); std::string areaName = "Unknown"; std::string zoneName = "Unknown"; if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId)) { int locale = GetSessionDbcLocale(); areaName = area->area_name[locale]; if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone)) zoneName = zone->area_name[locale]; } sLog->outCommand(m_session->GetAccountId(), "Command: %s [Player: %s (Guid: %u) (Account: %u) X: %f Y: %f Z: %f Map: %u (%s) Area: %u (%s) Zone: %s Selected %s: %s (GUID: %u)]", fullcmd.c_str(), p->GetName().c_str(), GUID_LOPART(p->GetGUID()), m_session->GetAccountId(), p->GetPositionX(), p->GetPositionY(), p->GetPositionZ(), p->GetMapId(), p->GetMap() ? p->GetMap()->GetMapName() : "Unknown", areaId, areaName.c_str(), zoneName.c_str(), GetLogNameForGuid(sel_guid), (p->GetSelectedUnit()) ? p->GetSelectedUnit()->GetName().c_str() : "", GUID_LOPART(sel_guid)); } } } // some commands have custom error messages. Don't send the default one in these cases. else if (!HasSentErrorMessage()) { if (!table[i].Help.empty()) SendSysMessage(table[i].Help.c_str()); else SendSysMessage(LANG_CMD_SYNTAX); } return true; } return false; }
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { uint32 opcode = recv_data.GetOpcode(); sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); Unit *mover = _player->m_mover; Player *plMover = mover->GetTypeId()==TYPEID_PLAYER ? (Player*)mover : NULL; // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if(plMover && plMover->IsBeingTeleported()) { // movement anticheat plMover->m_anti_JustTeleported = 1; // end movement anticheat return; } /* extract packet */ MovementInfo movementInfo; ReadMovementInfo(recv_data, &movementInfo); /*----------------*/ if(!(movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) && _player->GetVehicleGUID()) { if(mover->GetGUID() == _player->GetGUID()) { return; } } // we sent a movement packet with MOVEMENTFLAG_ONTRANSPORT and we are on vehicle // this can be moving on vehicle or entering another transport (eg. boat) if((movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) && _player->GetVehicleGUID()) { // we are controlling that vehicle if(mover->GetGUID() == _player->GetVehicleGUID()) { // we sent movement packet, related to movement ON vehicle, // but not WITH vehicle, so mover = player if(_player->GetVehicleGUID() == movementInfo.t_guid) { // this is required to avoid client crash, otherwise it will result // in moving with vehicle on the same vehicle and that = crash mover = _player; plMover = _player; } } if(_player->GetVehicleGUID() == movementInfo.t_guid) { _player->m_SeatData.OffsetX = movementInfo.t_x; _player->m_SeatData.OffsetY = movementInfo.t_y; _player->m_SeatData.OffsetZ = movementInfo.t_z; _player->m_SeatData.Orientation = movementInfo.t_o; } } if(recv_data.size() != recv_data.rpos()) { sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is " SIZEFMTD " bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), recv_data.GetOpcode(), recv_data.size() - recv_data.rpos()); KickPlayer(); return; } if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o)) return; /* handle special cases */ if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && !mover->GetVehicleGUID()) { // transports size limited // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) if( movementInfo.t_x > 60 || movementInfo.t_y > 60 || movementInfo.t_x < -60 || movementInfo.t_y < -60 ) return; if( !MaNGOS::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y + movementInfo.t_y, movementInfo.z + movementInfo.t_z, movementInfo.o + movementInfo.t_o) ) return; if (plMover && plMover->m_anti_TransportGUID == 0 && (movementInfo.t_guid !=0)) { // if we boarded a transport, add us to it if (plMover && !plMover->m_transport) { // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list for (MapManager::TransportSet::const_iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) { if ((*iter)->GetGUID() == movementInfo.t_guid) { plMover->m_transport = (*iter); (*iter)->AddPassenger(plMover); break; } } } //movement anticheat; //Correct finding GO guid in DB (thanks to GriffonHeart) GameObject *obj = HashMapHolder<GameObject>::Find(movementInfo.t_guid); if(obj) plMover->m_anti_TransportGUID = obj->GetDBTableGUIDLow(); else plMover->m_anti_TransportGUID = GUID_LOPART(movementInfo.t_guid); // end movement anticheat } } else if (plMover && plMover->m_anti_TransportGUID != 0){ if (plMover && plMover->m_transport) // if we were on a transport, leave { plMover->m_transport->RemovePassenger(plMover); plMover->m_transport = NULL; } movementInfo.t_x = 0.0f; movementInfo.t_y = 0.0f; movementInfo.t_z = 0.0f; movementInfo.t_o = 0.0f; movementInfo.t_time = 0; movementInfo.t_seat = -1; plMover->m_anti_TransportGUID = 0; } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight()) { //movement anticheat plMover->m_anti_JustJumped = 0; plMover->m_anti_JumpBaseZ = 0; //end movement anticheat plMover->HandleFall(movementInfo); } if (plMover && (movementInfo.HasMovementFlag(MOVEMENTFLAG_SWIMMING) != plMover->IsInWater())) { // now client not include swimming flag in case jumping under water plMover->SetInWater( !plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) ); } if (movementInfo.HasMovementFlag(MOVEMENTFLAG_SWIMMING)) { if(mover->GetTypeId() == TYPEID_UNIT) { if(((Creature*)mover)->isVehicle() && !((Creature*)mover)->canSwim()) { // NOTE : we should enter evade mode here, but... ((Vehicle*)mover)->SetSpawnDuration(1); } } } /*----------------------*/ //---- anti-cheat features -->>> bool check_passed = true; #ifdef MOVEMENT_ANTICHEAT_DEBUG if (plMover){ sLog.outBasic("MA-%s > client-time:%d fall-time:%d | xyzo: %f,%f,%fo(%f) flags[%X] opcode[%s]| transport (xyzo): %f,%f,%fo(%f)", plMover->GetName(),movementInfo.time,movementInfo.fallTime,movementInfo.x,movementInfo.y,movementInfo.z,movementInfo.o, movementInfo.flags, LookupOpcodeName(opcode),movementInfo.t_x,movementInfo.t_y,movementInfo.t_z,movementInfo.t_o); sLog.outBasic("MA-%s Transport > server GUID: %d | client GUID: (lo)%d - (hi)%d", plMover->GetName(),plMover->m_anti_TransportGUID, GUID_LOPART(movementInfo.t_guid), GUID_HIPART(movementInfo.t_guid)); } else { sLog.outBasic("MA > client-time:%d fall-time:%d | xyzo: %f,%f,%fo(%f) flags[%X] opcode[%s]| transport (xyzo): %f,%f,%fo(%f)", movementInfo.time,movementInfo.fallTime,movementInfo.x,movementInfo.y,movementInfo.z,movementInfo.o, movementInfo.flags, LookupOpcodeName(opcode),movementInfo.t_x,movementInfo.t_y,movementInfo.t_z,movementInfo.t_o); sLog.outBasic("MA Transport > server GUID: | client GUID: (lo)%d - (hi)%d", GUID_LOPART(movementInfo.t_guid), GUID_HIPART(movementInfo.t_guid)); } #endif if (plMover && World::GetEnableMvAnticheat()) { //calc time deltas int32 cClientTimeDelta = 1500; if (plMover->m_anti_LastClientTime !=0){ cClientTimeDelta = movementInfo.time - plMover->m_anti_LastClientTime; plMover->m_anti_DeltaClientTime += cClientTimeDelta; plMover->m_anti_LastClientTime = movementInfo.time; } else { plMover->m_anti_LastClientTime = movementInfo.time; } uint32 cServerTime=getMSTime(); uint32 cServerTimeDelta = 1500; if (plMover->m_anti_LastServerTime != 0){ cServerTimeDelta = cServerTime - plMover->m_anti_LastServerTime; plMover->m_anti_DeltaServerTime += cServerTimeDelta; plMover->m_anti_LastServerTime = cServerTime; } else { plMover->m_anti_LastServerTime = cServerTime; } //resync times on client login (first 15 sec for heavy areas) if (plMover->m_anti_DeltaServerTime < 15000 && plMover->m_anti_DeltaClientTime < 15000) plMover->m_anti_DeltaClientTime = plMover->m_anti_DeltaServerTime; int32 sync_time = plMover->m_anti_DeltaClientTime - plMover->m_anti_DeltaServerTime; #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outBasic("MA-%s Time > cClientTimeDelta: %d, cServerTime: %d || deltaC: %d - deltaS: %d || SyncTime: %d", plMover->GetName(),cClientTimeDelta, cServerTime, plMover->m_anti_DeltaClientTime, plMover->m_anti_DeltaServerTime, sync_time); #endif //mistiming checks int32 gmd = World::GetMistimingDelta(); if (sync_time > gmd || sync_time < -gmd){ cClientTimeDelta = cServerTimeDelta; plMover->m_anti_MistimingCount++; sLog.outError("MA-%s, mistiming exception. #:%d, mistiming: %dms ", plMover->GetName(), plMover->m_anti_MistimingCount, sync_time); if (plMover->m_anti_MistimingCount > World::GetMistimingAlarms()) { sWorld.SendWorldText(3,"Bye Cheto! ",plMover->GetName()); plMover->GetSession()->KickPlayer(); return; } check_passed = false; } // end mistiming checks uint32 curDest = plMover->m_taxi.GetTaxiDestination(); //check taxi flight if ((plMover->m_anti_TransportGUID == 0) && !curDest) { UnitMoveType move_type; // calculating section --------------------- //current speed if (movementInfo.flags & MOVEMENTFLAG_FLYING) move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_FLIGHT_BACK : MOVE_FLIGHT; else if (movementInfo.flags & MOVEMENTFLAG_SWIMMING) move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_SWIM_BACK : MOVE_SWIM; else if (movementInfo.flags & MOVEMENTFLAG_WALK_MODE) move_type = MOVE_WALK; //hmm... in first time after login player has MOVE_SWIMBACK instead MOVE_WALKBACK else move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_SWIM_BACK : MOVE_RUN; float current_speed = plMover->GetSpeed(move_type); // end current speed // movement distance float allowed_delta= 0; float delta_x = plMover->GetPositionX() - movementInfo.x; float delta_y = plMover->GetPositionY() - movementInfo.y; float delta_z = plMover->GetPositionZ() - movementInfo.z; float real_delta = delta_x * delta_x + delta_y * delta_y; float tg_z = -99999; //tangens // end movement distance if (cClientTimeDelta < 0) {cClientTimeDelta = 0;} float time_delta = (cClientTimeDelta < 1500) ? (float)cClientTimeDelta/1000 : 1.5f; //normalize time - 1.5 second allowed for heavy loaded server if (!(movementInfo.flags & (MOVEMENTFLAG_FLYING | MOVEMENTFLAG_SWIMMING))) tg_z = (real_delta !=0) ? (delta_z*delta_z / real_delta) : -99999; if (current_speed < plMover->m_anti_Last_HSpeed) { allowed_delta = plMover->m_anti_Last_HSpeed; if (plMover->m_anti_LastSpeedChangeTime == 0 ) plMover->m_anti_LastSpeedChangeTime = movementInfo.time + (uint32)floor(((plMover->m_anti_Last_HSpeed / current_speed) * 1500)) + 100; //100ms above for random fluctuating =))) } else { allowed_delta = current_speed; } allowed_delta = allowed_delta * time_delta; allowed_delta = allowed_delta * allowed_delta + 2; if (tg_z > 2.2) allowed_delta = allowed_delta + (delta_z*delta_z)/2.37; // mountain fall allowed speed if (movementInfo.time>plMover->m_anti_LastSpeedChangeTime) { plMover->m_anti_Last_HSpeed = current_speed; // store current speed plMover->m_anti_Last_VSpeed = -2.3f; if (plMover->m_anti_LastSpeedChangeTime != 0) plMover->m_anti_LastSpeedChangeTime = 0; } // end calculating section --------------------- //AntiGravitation (thanks to Meekro) float JumpHeight = plMover->m_anti_JumpBaseZ - movementInfo.z; if ((plMover->m_anti_JumpBaseZ != 0) && !(movementInfo.flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING | MOVEMENTFLAG_FLYING2)) && (JumpHeight < plMover->m_anti_Last_VSpeed)) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, GraviJump exception. JumpHeight = %f, Allowed Veritcal Speed = %f", plMover->GetName(), JumpHeight, plMover->m_anti_Last_VSpeed); #endif check_passed = false; } //multi jump checks if (opcode == MSG_MOVE_JUMP && !plMover->IsInWater()) { if (plMover->m_anti_JustJumped >= 1){ check_passed = false; //don't process new jump packet } else { plMover->m_anti_JustJumped += 1; plMover->m_anti_JumpBaseZ = movementInfo.z; } } else if (plMover->IsInWater()) { plMover->m_anti_JustJumped = 0; } //speed hack checks if ((real_delta > allowed_delta)) // && (delta_z < 0)) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, speed exception | cDelta=%f aDelta=%f | cSpeed=%f lSpeed=%f deltaTime=%f", plMover->GetName(), real_delta, allowed_delta, current_speed, plMover->m_anti_Last_HSpeed,time_delta); #endif check_passed = false; } //teleport hack checks if ((real_delta>4900.0f) && !(real_delta < allowed_delta)) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, is teleport exception | cDelta=%f aDelta=%f | cSpeed=%f lSpeed=%f deltaToime=%f", plMover->GetName(),real_delta, allowed_delta, current_speed, plMover->m_anti_Last_HSpeed,time_delta); #endif check_passed = false; } //mountian hack checks // 1.56f (delta_z < GetPlayer()->m_anti_Last_VSpeed)) if ((delta_z < plMover->m_anti_Last_VSpeed) && (plMover->m_anti_JustJumped == 0) && (tg_z > 2.37f)) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, mountain exception | tg_z=%f", plMover->GetName(),tg_z); #endif check_passed = false; } //Fly hack checks if (((movementInfo.flags & (MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING | MOVEMENTFLAG_FLYING2)) != 0) && !plMover->isGameMaster() && !(plMover->HasAuraType(SPELL_AURA_FLY) || plMover->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED))) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, flight exception. {SPELL_AURA_FLY=[%X]} {SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED=[%X]} {SPELL_AURA_MOD_SPEED_FLIGHT=[%X]} {SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS=[%X]} {SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK=[%X]}", plMover->GetName(), plMover->HasAuraType(SPELL_AURA_FLY), plMover->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED), plMover->HasAuraType(SPELL_AURA_MOD_SPEED_FLIGHT), plMover->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS), plMover->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK)); #endif check_passed = false; } //Water-Walk checks if (((movementInfo.flags & MOVEMENTFLAG_WATERWALKING) != 0) && !plMover->isGameMaster() && !(plMover->HasAuraType(SPELL_AURA_WATER_WALK) | plMover->HasAuraType(SPELL_AURA_GHOST))) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, water-walk exception. [%X]{SPELL_AURA_WATER_WALK=[%X]}", plMover->GetName(), movementInfo.flags, plMover->HasAuraType(SPELL_AURA_WATER_WALK)); #endif check_passed = false; } //Teleport To Plane checks if (movementInfo.z < 0.0001f && movementInfo.z > -0.0001f && ((movementInfo.flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING | MOVEMENTFLAG_FLYING2)) == 0) && !plMover->isGameMaster()) { // Prevent using TeleportToPlan. Map *map = plMover->GetMap(); if (map){ float plane_z = map->GetHeight(movementInfo.x, movementInfo.y, MAX_HEIGHT) - movementInfo.z; plane_z = (plane_z < -500.0f) ? 0 : plane_z; //check holes in heigth map if(plane_z > 0.1f || plane_z < -0.1f) { plMover->m_anti_TeleToPlane_Count++; check_passed = false; #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outDebug("MA-%s, teleport to plan exception. plane_z: %f ", plMover->GetName(), plane_z); #endif if (plMover->m_anti_TeleToPlane_Count > World::GetTeleportToPlaneAlarms()) { sLog.outError("MA-%s, teleport to plan exception. Exception count: %d ", plMover->GetName(), plMover->m_anti_TeleToPlane_Count); sWorld.SendWorldText(3,"Bye Cheto! ",plMover->GetName()); plMover->GetSession()->KickPlayer(); return; } } } } else { if (plMover->m_anti_TeleToPlane_Count != 0) plMover->m_anti_TeleToPlane_Count = 0; } } else if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) { //antiwrap checks if (plMover->m_transport) { float trans_rad = movementInfo.t_x*movementInfo.t_x + movementInfo.t_y*movementInfo.t_y + movementInfo.t_z*movementInfo.t_z; if (trans_rad > 3600.0f){ check_passed = false; #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, leave transport.", plMover->GetName()); #endif } } else { if (GameObjectData const* go_data = objmgr.GetGOData(plMover->m_anti_TransportGUID)) { float delta_gox = go_data->posX - movementInfo.x; float delta_goy = go_data->posY - movementInfo.y; float delta_goz = go_data->posZ - movementInfo.z; int mapid = go_data->mapid; #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outDebug("MA-%s, transport movement. GO xyzo: %f,%f,%f", plMover->GetName(), go_data->posX,go_data->posY,go_data->posZ); #endif if (plMover->GetMapId() != mapid){ check_passed = false; } else if (mapid !=369) { float delta_go = delta_gox*delta_gox + delta_goy*delta_goy; if (delta_go > 3600.0f) { check_passed = false; #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, leave transport. GO xyzo: %f,%f,%f", plMover->GetName(), go_data->posX,go_data->posY,go_data->posZ); #endif } } } else { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outDebug("MA-%s, undefined transport.", plMover->GetName()); #endif check_passed = false; } } if (!check_passed){ if (plMover->m_transport) { plMover->m_transport->RemovePassenger(plMover); plMover->m_transport = NULL; } movementInfo.t_x = 0.0f; movementInfo.t_y = 0.0f; movementInfo.t_z = 0.0f; movementInfo.t_o = 0.0f; movementInfo.t_time = 0; plMover->m_anti_TransportGUID = 0; } } } /* process position-change */ if (check_passed) { recv_data.put<uint32>(6, getMSTime()); // fix time, offset flags(4) + unk(2) WorldPacket data(recv_data.GetOpcode(), (mover->GetPackGUID().size()+recv_data.size())); data.append(mover->GetPackGUID()); // use mover guid data.append(recv_data.contents(), recv_data.size()); GetPlayer()->SendMessageToSet(&data, false); if(plMover) // nothing is charmed, or player charmed { plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); plMover->m_movementInfo = movementInfo; plMover->UpdateFallInformationIfNeed(movementInfo, recv_data.GetOpcode()); if(plMover->isMovingOrTurning()) plMover->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); if(movementInfo.z < -500.0f) { if(plMover->InBattleGround() && plMover->GetBattleGround() && plMover->GetBattleGround()->HandlePlayerUnderMap(_player)) { // do nothing, the handle already did if returned true } else { // NOTE: this is actually called many times while falling // even after the player has been teleported away // TODO: discard movement packets after the player is rooted if(plMover->isAlive()) { plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); // pl can be alive if GM/etc if(!plMover->isAlive()) { // change the death state to CORPSE to prevent the death timer from // starting in the next player update plMover->KillPlayer(); plMover->BuildPlayerRepop(); } } // cancel the death timer here if started plMover->RepopAtGraveyard(); } } //movement anticheat >>> if (plMover->m_anti_AlarmCount > 0){ sLog.outError("MA-%s produce %d anticheat alarms",plMover->GetName(),plMover->m_anti_AlarmCount); plMover->m_anti_AlarmCount = 0; } // end movement anticheat } else // creature charmed { if(mover->IsInWorld()) { mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); if(((Creature*)mover)->isVehicle()) ((Vehicle*)mover)->RellocatePassengers(mover->GetMap()); } } } else if (plMover) { plMover->m_anti_AlarmCount++; WorldPacket data; //GetPlayer()->m_movementInfo.SetMovementFlags(MovementFlags(MOVEMENTFLAG_NONE)); plMover->m_movementInfo.SetMovementFlags(MovementFlags(MOVEMENTFLAG_NONE)); plMover->BuildTeleportAckMsg(&data, plMover->GetPositionX(), plMover->GetPositionY(), plMover->GetPositionZ(), plMover->GetOrientation()); plMover->GetSession()->SendPacket(&data); plMover->BuildHeartBeatMsg(&data); plMover->SendMessageToSet(&data, true); } }
void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data ) { DEBUG_LOG("WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player *player = GetPlayer(); ObjectGuid lguid = player->GetLootGUID(); Loot *loot; uint8 lootSlot; recv_data >> lootSlot; switch( lguid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject *go = player->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))) { player->SendLootRelease(lguid); return; } loot = &go->loot; break; } case HIGHGUID_ITEM: { Item *pItem = player->GetItemByGuid( lguid ); if (!pItem) { player->SendLootRelease(lguid); return; } loot = &pItem->loot; break; } case HIGHGUID_CORPSE: { Corpse *bones = player->GetMap()->GetCorpse(lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; break; } 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) ) { player->SendLootRelease(lguid); return; } loot = &pCreature->loot; break; } default: { sLog.outError("%s is unsupported for looting.",lguid.GetString().c_str()); return; } } QuestItem *qitem = NULL; QuestItem *ffaitem = NULL; QuestItem *conditem = NULL; LootItem *item = loot->LootItemInSlot(lootSlot,player,&qitem,&ffaitem,&conditem); if(!item) { player->SendEquipError( EQUIP_ERR_ALREADY_LOOTED, NULL, NULL ); return; } // questitems use the blocked field for other purposes if (!qitem && item->is_blocked) { player->SendLootRelease(lguid); return; } ItemPosCountVec dest; uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count ); if ( msg == EQUIP_ERR_OK ) { Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId); if (qitem) { qitem->is_looted = true; //freeforall is 1 if everyone's supposed to get the quest item. if (item->freeforall || loot->GetPlayerQuestItems().size() == 1) player->SendNotifyLootItemRemoved(lootSlot); else loot->NotifyQuestItemRemoved(qitem->index); } else { if (ffaitem) { //freeforall case, notify only one player of the removal ffaitem->is_looted=true; player->SendNotifyLootItemRemoved(lootSlot); } else { //not freeforall, notify everyone if(conditem) conditem->is_looted=true; loot->NotifyItemRemoved(lootSlot); } } //if only one person is supposed to loot the item, then set it to looted if (!item->freeforall) item->is_looted = true; --loot->unlootedCount; player->SendNewItem(newitem, uint32(item->count), false, false, true); } else player->SendEquipError( msg, NULL, NULL ); }
// Summon group of player static bool HandleGroupSummonCommand(ChatHandler* handler, char const* args) { Player* target; if (!handler->extractPlayerTarget((char*)args, &target)) return false; // check online security if (handler->HasLowerSecurity(target, 0)) return false; Group* group = target->GetGroup(); std::string nameLink = handler->GetNameLink(target); if (!group) { handler->PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); handler->SetSentErrorMessage(true); return false; } Player* gmPlayer = handler->GetSession()->GetPlayer(); Group* gmGroup = gmPlayer->GetGroup(); Map* gmMap = gmPlayer->GetMap(); bool toInstance = gmMap->Instanceable(); // we are in instance, and can summon only player in our group with us as lead if (toInstance && ( !gmGroup || group->GetLeaderGUID() != gmPlayer->GetGUID() || gmGroup->GetLeaderGUID() != gmPlayer->GetGUID())) // the last check is a bit excessive, but let it be, just in case { handler->SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); handler->SetSentErrorMessage(true); return false; } for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* player = itr->GetSource(); if (!player || player == gmPlayer || !player->GetSession()) continue; // check online security if (handler->HasLowerSecurity(player, 0)) return false; std::string plNameLink = handler->GetNameLink(player); if (player->IsBeingTeleported()) { handler->PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); handler->SetSentErrorMessage(true); return false; } if (toInstance) { Map* playerMap = player->GetMap(); if (playerMap->Instanceable() && playerMap->GetInstanceId() != gmMap->GetInstanceId()) { // cannot summon from instance to instance handler->PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, plNameLink.c_str()); handler->SetSentErrorMessage(true); return false; } } handler->PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(), ""); if (handler->needReportToTarget(player)) ChatHandler(player->GetSession()).PSendSysMessage(LANG_SUMMONED_BY, handler->GetNameLink().c_str()); // stop flight if need if (player->IsInFlight()) { player->GetMotionMaster()->MovementExpired(); player->CleanupAfterTaxiFlight(); } // save only in non-flight case else player->SaveRecallPosition(); // before GM float x, y, z; gmPlayer->GetClosePoint(x, y, z, player->GetObjectSize()); player->TeleportTo(gmPlayer->GetMapId(), x, y, z, player->GetOrientation()); } return true; }
void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/) { TC_LOG_DEBUG("network", "WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); uint64 guid = player->GetLootGUID(); if (!guid) return; Loot* loot = NULL; bool shareMoney = true; switch (GUID_HIPART(guid)) { case HIGHGUID_GAMEOBJECT: { GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid); // do not check distance for GO if player is the owner of it (ex. fishing bobber) if (go && ((go->GetOwnerGUID() == player->GetGUID() || go->IsWithinDistInMap(player, INTERACTION_DISTANCE)))) loot = &go->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = ObjectAccessor::GetCorpse(*player, guid); if (bones && bones->IsWithinDistInMap(player, INTERACTION_DISTANCE)) { loot = &bones->loot; shareMoney = false; } break; } case HIGHGUID_ITEM: { if (Item* item = player->GetItemByGuid(guid)) { loot = &item->loot; shareMoney = false; } break; } case HIGHGUID_UNIT: case HIGHGUID_VEHICLE: { Creature* creature = player->GetMap()->GetCreature(guid); bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed); if (lootAllowed && creature->IsWithinDistInMap(player, INTERACTION_DISTANCE)) { loot = &creature->loot; if (creature->IsAlive()) shareMoney = false; } break; } default: return; // unlootable type } if (loot) { loot->NotifyMoneyRemoved(); if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->GetSource(); if (!member) continue; if (player->IsWithinDistInMap(member, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false)) playersNear.push_back(member); } uint32 goldPerPlayer = uint32((loot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(goldPerPlayer); (*i)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); data << uint32(goldPerPlayer); data << uint8(playersNear.size() <= 1); // Controls the text displayed in chat. 0 is "Your share is..." and 1 is "You loot..." (*i)->GetSession()->SendPacket(&data); } } else { player->ModifyMoney(loot->gold); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); data << uint32(loot->gold); data << uint8(1); // "You loot..." SendPacket(&data); } loot->gold = 0; // Delete the money loot record from the DB if (loot->containerID > 0) loot->DeleteLootMoneyFromContainerItemDB(); // Delete container if empty if (loot->isLooted() && IS_ITEM_GUID(guid)) player->GetSession()->DoLootRelease(guid); } }
static bool HandleWpShowCommand(ChatHandler* handler, const char* args) { if (!*args) return false; // first arg: on, off, first, last char* show_str = strtok((char*)args, " "); if (!show_str) return false; // second arg: GUID (optional, if a creature is selected) char* guid_str = strtok((char*)NULL, " "); uint32 pathid = 0; Creature* target = handler->getSelectedCreature(); // Did player provide a PathID? if (!guid_str) { // No PathID provided // -> Player must have selected a creature if (!target) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } pathid = target->GetWaypointPath(); } else { // PathID provided // Warn if player also selected a creature // -> Creature selection is ignored <- if (target) handler->SendSysMessage(LANG_WAYPOINT_CREATSELECTED); pathid = atoi((char*)guid_str); } std::string show = show_str; uint32 Maxpoint; //handler->PSendSysMessage("wpshow - show: %s", show); // Show info for the selected waypoint if (show == "info") { // Check if the user did specify a visual waypoint if (target->GetEntry() != VISUAL_WAYPOINT) { handler->PSendSysMessage(LANG_WAYPOINT_VP_SELECT); handler->SetSentErrorMessage(true); return false; } QueryResult result = WorldDatabase.PQuery("SELECT id, point, delay, move_flag, action, action_chance FROM waypoint_data WHERE wpguid = %u", target->GetGUIDLow()); if (!result) { handler->SendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM); return true; } handler->SendSysMessage("|cff00ffffDEBUG: wp show info:|r"); do { Field* fields = result->Fetch(); pathid = fields[0].GetUInt32(); uint32 point = fields[1].GetUInt32(); uint32 delay = fields[2].GetUInt32(); uint32 flag = fields[3].GetUInt32(); uint32 ev_id = fields[4].GetUInt32(); uint32 ev_chance = fields[5].GetUInt32(); handler->PSendSysMessage("|cff00ff00Show info: for current point: |r|cff00ffff%u|r|cff00ff00, Path ID: |r|cff00ffff%u|r", point, pathid); handler->PSendSysMessage("|cff00ff00Show info: delay: |r|cff00ffff%u|r", delay); handler->PSendSysMessage("|cff00ff00Show info: Move flag: |r|cff00ffff%u|r", flag); handler->PSendSysMessage("|cff00ff00Show info: Waypoint event: |r|cff00ffff%u|r", ev_id); handler->PSendSysMessage("|cff00ff00Show info: Event chance: |r|cff00ffff%u|r", ev_chance); } while (result->NextRow()); return true; } if (show == "on") { QueryResult result = WorldDatabase.PQuery("SELECT point, position_x, position_y, position_z FROM waypoint_data WHERE id = '%u'", pathid); if (!result) { handler->SendSysMessage("|cffff33ffPath no found.|r"); handler->SetSentErrorMessage(true); return false; } handler->PSendSysMessage("|cff00ff00DEBUG: wp on, PathID: |cff00ffff%u|r", pathid); // Delete all visuals for this NPC QueryResult result2 = WorldDatabase.PQuery("SELECT wpguid FROM waypoint_data WHERE id = '%u' and wpguid <> 0", pathid); if (result2) { bool hasError = false; do { Field* fields = result2->Fetch(); uint32 wpguid = fields[0].GetUInt32(); Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpguid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); if (!creature) { handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid); hasError = true; WorldDatabase.PExecute("DELETE FROM creature WHERE guid = '%u'", wpguid); } else { creature->CombatStop(); creature->DeleteFromDB(); creature->AddObjectToRemoveList(); } } while (result2->NextRow()); if (hasError) { handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR1); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR2); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR3); } } do { Field* fields = result->Fetch(); uint32 point = fields[0].GetUInt32(); float x = fields[1].GetFloat(); float y = fields[2].GetFloat(); float z = fields[3].GetFloat(); uint32 id = VISUAL_WAYPOINT; Player* chr = handler->GetSession()->GetPlayer(); Map* map = chr->GetMap(); float o = chr->GetOrientation(); Creature* wpCreature = new Creature; if (!wpCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete wpCreature; return false; } // set "wpguid" column to the visual waypoint WorldDatabase.PExecute("UPDATE waypoint_data SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), pathid, point); wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); if (!wpCreature->LoadCreatureFromDB(wpCreature->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete wpCreature; return false; } if (target) { wpCreature->SetDisplayId(target->GetDisplayId()); wpCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5f); wpCreature->SetLevel(point > STRONG_MAX_LEVEL ? STRONG_MAX_LEVEL : point); } } while (result->NextRow()); handler->SendSysMessage("|cff00ff00Showing the current creature's path.|r"); return true; } if (show == "first") { handler->PSendSysMessage("|cff00ff00DEBUG: wp first, GUID: %u|r", pathid); QueryResult result = WorldDatabase.PQuery("SELECT position_x, position_y, position_z FROM waypoint_data WHERE point='1' AND id = '%u'", pathid); if (!result) { handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUND, pathid); handler->SetSentErrorMessage(true); return false; } Field* fields = result->Fetch(); float x = fields[0].GetFloat(); float y = fields[1].GetFloat(); float z = fields[2].GetFloat(); uint32 id = VISUAL_WAYPOINT; Player* chr = handler->GetSession()->GetPlayer(); float o = chr->GetOrientation(); Map* map = chr->GetMap(); Creature* creature = new Creature; if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete creature; return false; } creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete creature; return false; } if (target) { creature->SetDisplayId(target->GetDisplayId()); creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5f); } return true; } if (show == "last") { handler->PSendSysMessage("|cff00ff00DEBUG: wp last, PathID: |r|cff00ffff%u|r", pathid); QueryResult result = WorldDatabase.PQuery("SELECT MAX(point) FROM waypoint_data WHERE id = '%u'", pathid); if (result) Maxpoint = (*result)[0].GetUInt32(); else Maxpoint = 0; result = WorldDatabase.PQuery("SELECT position_x, position_y, position_z, orientation FROM waypoint_data WHERE point ='%u' AND id = '%u'", Maxpoint, pathid); if (!result) { handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, pathid); handler->SetSentErrorMessage(true); return false; } Field* fields = result->Fetch(); float x = fields[0].GetFloat(); float y = fields[1].GetFloat(); float z = fields[2].GetFloat(); float o = fields[3].GetFloat(); uint32 id = VISUAL_WAYPOINT; Player* chr = handler->GetSession()->GetPlayer(); Map* map = chr->GetMap(); Creature* creature = new Creature; if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); delete creature; return false; } creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); delete creature; return false; } if (target) { creature->SetDisplayId(target->GetDisplayId()); creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5f); } return true; } if (show == "off") { QueryResult result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%u'", 1); if (!result) { handler->SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND); handler->SetSentErrorMessage(true); return false; } bool hasError = false; do { Field* fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(guid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); if (!creature) { handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid); hasError = true; WorldDatabase.PExecute("DELETE FROM creature WHERE guid = '%u'", guid); } else { creature->CombatStop(); creature->DeleteFromDB(); creature->AddObjectToRemoveList(); } } while (result->NextRow()); // set "wpguid" column to "empty" - no visual waypoint spawned WorldDatabase.PExecute("UPDATE waypoint_data SET wpguid = '0'"); //WorldDatabase.PExecute("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'"); if (hasError) { handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR1); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR2); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR3); } handler->SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); return true; } handler->PSendSysMessage("|cffff33ffDEBUG: wpshow - no valid command found|r"); return true; }
static bool HandleWpModifyCommand(ChatHandler* handler, const char* args) { if (!*args) return false; // first arg: add del text emote spell waittime move char* show_str = strtok((char*)args, " "); if (!show_str) { return false; } std::string show = show_str; // Check // Remember: "show" must also be the name of a column! if ((show != "delay") && (show != "action") && (show != "action_chance") && (show != "move_flag") && (show != "del") && (show != "move") && (show != "wpadd") ) { return false; } // Next arg is: <PATHID> <WPNUM> <ARGUMENT> char* arg_str = nullptr; // Did user provide a GUID // or did the user select a creature? // -> variable lowguid is filled with the GUID of the NPC uint32 pathid = 0; uint32 point = 0; uint32 wpGuid = 0; Creature* target = handler->getSelectedCreature(); if (!target || target->GetEntry() != VISUAL_WAYPOINT) { handler->SendSysMessage("|cffff33ffERROR: You must select a waypoint.|r"); return false; } // The visual waypoint wpGuid = target->GetGUIDLow(); // User did select a visual waypoint? // Check the creature PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_BY_WPGUID); stmt->setUInt32(0, wpGuid); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow()); // Select waypoint number from database // Since we compare float values, we have to deal with // some difficulties. // Here we search for all waypoints that only differ in one from 1 thousand // (0.001) - There is no other way to compare C++ floats with mySQL floats // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html std::string maxDiff = "0.01"; PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_BY_POS); stmt->setFloat(0, target->GetPositionX()); stmt->setString(1, maxDiff); stmt->setFloat(2, target->GetPositionY()); stmt->setString(3, maxDiff); stmt->setFloat(4, target->GetPositionZ()); stmt->setString(5, maxDiff); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid); return true; } } do { Field* fields = result->Fetch(); pathid = fields[0].GetUInt32(); point = fields[1].GetUInt32(); } while (result->NextRow()); // We have the waypoint number and the GUID of the "master npc" // Text is enclosed in "<>", all other arguments not arg_str = strtok((char*)NULL, " "); // Check for argument if (show != "del" && show != "move" && arg_str == NULL) { handler->PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str); return false; } if (show == "del") { handler->PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff%u|r", pathid); if (wpGuid != 0) if (Creature* wcreature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT))) { wcreature->CombatStop(); wcreature->DeleteFromDB(); wcreature->AddObjectToRemoveList(); } PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_DATA); stmt->setUInt32(0, pathid); stmt->setUInt32(1, point); WorldDatabase.Execute(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POINT); stmt->setUInt32(0, pathid); stmt->setUInt32(1, point); WorldDatabase.Execute(stmt); handler->PSendSysMessage(LANG_WAYPOINT_REMOVED); return true; } // del if (show == "move") { handler->PSendSysMessage("|cff00ff00DEBUG: wp move, PathID: |r|cff00ffff%u|r", pathid); Player* chr = handler->GetSession()->GetPlayer(); Map* map = chr->GetMap(); { // What to do: // Move the visual spawnpoint // Respawn the owner of the waypoints if (wpGuid != 0) { if (Creature* wcreature = map->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT))) { wcreature->CombatStop(); wcreature->DeleteFromDB(); wcreature->AddObjectToRemoveList(); } // re-create Creature* wcreature2 = new Creature(); if (!wcreature2->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMask(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation())) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wcreature2; wcreature2 = nullptr; return false; } wcreature2->CopyPhaseFrom(chr); wcreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); /// @todo Should we first use "Create" then use "LoadFromDB"? if (!wcreature2->LoadCreatureFromDB(wcreature2->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wcreature2; wcreature2 = nullptr; return false; } //sMapMgr->GetMap(npcCreature->GetMapId())->Add(wcreature2); } PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POSITION); stmt->setFloat(0, chr->GetPositionX()); stmt->setFloat(1, chr->GetPositionY()); stmt->setFloat(2, chr->GetPositionZ()); stmt->setUInt32(3, pathid); stmt->setUInt32(4, point); WorldDatabase.Execute(stmt); handler->PSendSysMessage(LANG_WAYPOINT_CHANGED); } return true; } // move const char *text = arg_str; if (text == 0) { // show_str check for present in list of correct values, no sql injection possible WorldDatabase.PExecute("UPDATE waypoint_data SET %s=NULL WHERE id='%u' AND point='%u'", show_str, pathid, point); // Query can't be a prepared statement } else { // show_str check for present in list of correct values, no sql injection possible std::string text2 = text; WorldDatabase.EscapeString(text2); WorldDatabase.PExecute("UPDATE waypoint_data SET %s='%s' WHERE id='%u' AND point='%u'", show_str, text2.c_str(), pathid, point); // Query can't be a prepared statement } handler->PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str); return true; }
void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket) { uint16 opcode = recvPacket.GetOpcode(); Unit* mover = _player->m_mover; ASSERT(mover != NULL); // there must always be a mover Player* plrMover = mover->ToPlayer(); // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if (plrMover && plrMover->IsBeingTeleported()) { recvPacket.rfinish(); // prevent warnings spam return; } /* extract packet */ MovementInfo movementInfo; GetPlayer()->ReadMovementInfo(recvPacket, &movementInfo); // prevent tampered movement data if (movementInfo.guid != mover->GetGUID()) { TC_LOG_ERROR("network", "HandleMovementOpcodes: guid error"); return; } if (!movementInfo.pos.IsPositionValid()) { TC_LOG_ERROR("network", "HandleMovementOpcodes: Invalid Position"); return; } /* handle special cases */ if (movementInfo.transport.guid) { // transports size limited // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) if (movementInfo.transport.pos.GetPositionX() > 50 || movementInfo.transport.pos.GetPositionY() > 50 || movementInfo.transport.pos.GetPositionZ() > 50) { recvPacket.rfinish(); // prevent warnings spam return; } if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(), movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation())) { recvPacket.rfinish(); // prevent warnings spam return; } // if we boarded a transport, add us to it if (plrMover) { if (!plrMover->GetTransport()) { if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid)) { plrMover->m_transport = transport; transport->AddPassenger(plrMover); } } else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid) { bool foundNewTransport = false; plrMover->m_transport->RemovePassenger(plrMover); if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid)) { foundNewTransport = true; plrMover->m_transport = transport; transport->AddPassenger(plrMover); } if (!foundNewTransport) { plrMover->m_transport = NULL; movementInfo.ResetTransport(); } } } if (!mover->GetTransport() && !mover->GetVehicle()) { GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid); if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) movementInfo.transport.guid = 0; } } else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave { plrMover->m_transport->RemovePassenger(plrMover); plrMover->m_transport = NULL; movementInfo.ResetTransport(); } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight()) plrMover->HandleFall(movementInfo); if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) { // now client not include swimming flag in case jumping under water plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); } uint32 mstime = getMSTime(); /*----------------------*/ if (m_clientTimeDelay == 0) m_clientTimeDelay = mstime - movementInfo.time; /* process position-change */ movementInfo.time = movementInfo.time + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY; movementInfo.guid = mover->GetGUID(); mover->m_movementInfo = movementInfo; /*----------------------*/ /* process position-change */ // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle() if (mover->GetVehicle()) { mover->SetOrientation(movementInfo.pos.GetOrientation()); return; } mover->UpdatePosition(movementInfo.pos); WorldPacket data(SMSG_PLAYER_MOVE, recvPacket.size()); mover->WriteMovementInfo(data); mover->SendMessageToSet(&data, _player); if (plrMover) // nothing is charmed, or player charmed { plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); AreaTableEntry const* zone = GetAreaEntryByAreaID(plrMover->GetAreaId()); float depth = zone ? zone->MaxDepth : -500.0f; if (movementInfo.pos.GetPositionZ() < depth) { if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player))) { // NOTE: this is actually called many times while falling // even after the player has been teleported away /// @todo discard movement packets after the player is rooted if (plrMover->IsAlive()) { plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); // player can be alive if GM/etc // change the death state to CORPSE to prevent the death timer from // starting in the next player update if (!plrMover->IsAlive()) plrMover->KillPlayer(); } } } } }
void WorldSession::HandlePlayerLogin(LoginQueryHolder *holder) { uint64 playerGuid = holder->GetGuid(); Player *pCurrChar = new Player(this); pCurrChar->GetMotionMaster()->Initialize(); // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) if(!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) { KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick delete pCurrChar; // delete it manually delete holder; // delete all unprocessed queries m_playerLoading = false; return; } SetPlayer(pCurrChar); pCurrChar->SendDungeonDifficulty(false); WorldPacket data( SMSG_LOGIN_VERIFY_WORLD, 20 ); data << pCurrChar->GetMapId(); data << pCurrChar->GetPositionX(); data << pCurrChar->GetPositionY(); data << pCurrChar->GetPositionZ(); data << pCurrChar->GetOrientation(); SendPacket(&data); // load player specific part before send times LoadAccountData(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA),PER_CHARACTER_CACHE_MASK); SendAccountDataTimes(PER_CHARACTER_CACHE_MASK); data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 data << uint8(2); // unknown value data << uint8(0); // enable(1)/disable(0) voice chat interface in client SendPacket(&data); // Send MOTD { data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 data << (uint32)0; uint32 linecount=0; std::string str_motd = sWorld.GetMotd(); std::string::size_type pos, nextpos; pos = 0; while ( (nextpos= str_motd.find('@',pos)) != std::string::npos ) { if (nextpos != pos) { data << str_motd.substr(pos, nextpos-pos); ++linecount; } pos = nextpos + 1; } if (pos < str_motd.length()) { data << str_motd.substr(pos); ++linecount; } data.put(0, linecount); SendPacket( &data ); DEBUG_LOG( "WORLD: Sent motd (SMSG_MOTD)" ); } //QueryResult *result = CharacterDatabase.PQuery("SELECT guildid,rank FROM guild_member WHERE guid = '%u'",pCurrChar->GetGUIDLow()); QueryResult *resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD); if(resultGuild) { Field *fields = resultGuild->Fetch(); pCurrChar->SetInGuild(fields[0].GetUInt32()); pCurrChar->SetRank(fields[1].GetUInt32()); delete resultGuild; } else if(pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about nonexistent membership { pCurrChar->SetInGuild(0); pCurrChar->SetRank(0); } if(pCurrChar->GetGuildId() != 0) { Guild* guild = sObjectMgr.GetGuildById(pCurrChar->GetGuildId()); if(guild) { data.Initialize(SMSG_GUILD_EVENT, (1+1+guild->GetMOTD().size()+1)); data << uint8(GE_MOTD); data << uint8(1); data << guild->GetMOTD(); SendPacket(&data); DEBUG_LOG( "WORLD: Sent guild-motd (SMSG_GUILD_EVENT)" ); guild->DisplayGuildBankTabsInfo(this); guild->BroadcastEvent(GE_SIGNED_ON, pCurrChar->GetGUID(), 1, pCurrChar->GetName(), "", ""); } else { // remove wrong guild data sLog.outError("Player %s (GUID: %u) marked as member of nonexistent guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); pCurrChar->SetInGuild(0); } } data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4); data << uint32(0); data << uint32(0); SendPacket(&data); pCurrChar->SendInitialPacketsBeforeAddToMap(); //Show cinematic at the first time that player login if( !pCurrChar->getCinematic() ) { pCurrChar->setCinematic(1); if(ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->getClass())) { if (cEntry->CinematicSequence) pCurrChar->SendCinematicStart(cEntry->CinematicSequence); else if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace())) pCurrChar->SendCinematicStart(rEntry->CinematicSequence); } } if (!pCurrChar->GetMap()->Add(pCurrChar)) { // normal delayed teleport protection not applied (and this correct) for this case (Player object just created) AreaTrigger const* at = sObjectMgr.GetGoBackTrigger(pCurrChar->GetMapId()); if(at) pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); else pCurrChar->TeleportToHomebind(); } sObjectAccessor.AddObject(pCurrChar); //DEBUG_LOG("Player %s added to Map.",pCurrChar->GetName()); pCurrChar->SendInitialPacketsAfterAddToMap(); CharacterDatabase.PExecute("UPDATE characters SET online = 1 WHERE guid = '%u'", pCurrChar->GetGUIDLow()); LoginDatabase.PExecute("UPDATE account SET active_realm_id = %d WHERE id = '%u'", realmID, GetAccountId()); pCurrChar->SetInGameTime( getMSTime() ); // announce group about member online (must be after add to player list to receive announce to self) if (Group *group = pCurrChar->GetGroup()) group->SendUpdate(); // friend status sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true); // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); // setting Ghost+speed if dead if (pCurrChar->m_deathState != ALIVE) { // not blizz like, we must correctly save and load player instead... if(pCurrChar->getRace() == RACE_NIGHTELF) pCurrChar->CastSpell(pCurrChar, 20584, true); // auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) pCurrChar->SetMovement(MOVE_WATER_WALK); } pCurrChar->ContinueTaxiFlight(); // reset for all pets before pet loading if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) Pet::resetTalentsForAllPetsOf(pCurrChar); // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned) pCurrChar->LoadPet(); // Set FFA PvP for non GM in non-rest mode if(sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING) ) pCurrChar->SetFFAPvP(true); if(pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) pCurrChar->SetContestedPvP(); // Apply at_login requests if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) { pCurrChar->resetSpells(); SendNotification(LANG_RESET_SPELLS); } if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) { pCurrChar->resetTalents(true,true); pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state SendNotification(LANG_RESET_TALENTS); // we can use SMSG_TALENTS_INVOLUNTARILY_RESET here } if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST)) pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST); // show time before shutdown if shutdown planned. if(sWorld.IsShutdowning()) sWorld.ShutdownMsg(true,pCurrChar); if(sWorld.getConfig(CONFIG_BOOL_ALL_TAXI_PATHS)) pCurrChar->SetTaxiCheater(true); if(pCurrChar->isGameMaster()) SendNotification(LANG_GM_ON); std::string IP_str = GetRemoteAddress(); sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid: %u)", GetAccountId(), IP_str.c_str(), pCurrChar->GetName(), pCurrChar->GetGUIDLow()); if(!pCurrChar->IsStandState() && !pCurrChar->hasUnitState(UNIT_STAT_STUNNED)) pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); m_playerLoading = false; delete holder; }
void TowerDefenseInstanceScript::TowerDefenseMapInstanceScript::UpgradeGuard(uint64 guid) { if(!guid) return; Player* player = GetPlayer(); if(!player) return; Creature* creature = player->GetMap()->GetCreature(guid); if(!creature) return; uint32 currentLevel = 0; uint32 entry = GUID_ENPART(guid); if (Guards.find(guid) != Guards.end()) { GuardInfo* guard = Guards[guid]; currentLevel = guard->Level; uint32 newLevel = currentLevel +1; if(QueryResult queryResult = CharacterDatabase.PQuery("SELECT creatureName, creatureEntry, creatureCost FROM custom_td_base_stats WHERE creatureEntry = '%u'", entry)) { uint32 UpgradeCost = guard->GetUpgradeCost(); switch(GetEventMode()) { case TD_EVENT_MODE_HARD: UpgradeCost = UpgradeCost + (UpgradeCost/4); break; case TD_EVENT_MODE_EXTREME: UpgradeCost = UpgradeCost + (UpgradeCost/2); break; } if(GetResources() < UpgradeCost){ SendMessageToPlayer(TD_SYSTEM_MSG_MORE_RESOURCES_UPG, UpgradeCost - GetResources()); return; } if(QueryResult queryResult = CharacterDatabase.PQuery("SELECT * FROM custom_td_base_levels WHERE creatureEntry = '%u' AND creatureLevel = '%u'", entry, newLevel)) { creature->CastSpell(creature, GetSpellIdByUniqueId(4),true); // upgrade level visual guard->SetLevel(newLevel); UpdateResources(TD_EVENT_DEC,UpgradeCost); // remove resource cost from player creature->RemoveAllAuras(); // remove all auras to apply new ones. SendMessageToPlayer(TD_SYSTEM_MSG_UPGRADED_TOWER_FOR, creature->GetName(),UpgradeCost); Field* Fields = queryResult->Fetch(); uint32 newDefaultSpell = Fields[4].GetUInt32(); if(newDefaultSpell) guard->SetDefSpell(newDefaultSpell); uint32 newAttackSpeed = Fields[9].GetUInt32(); if (newAttackSpeed) guard->SetAttSpeed(newAttackSpeed); float newAttackDistance = Fields[8].GetFloat(); if(newAttackDistance) guard->SetAttackDistance(newAttackDistance); uint32 newAura = Fields[7].GetUInt32(); if(newAura) creature->CastSpell(creature,newAura,true); uint32 newDisplay = Fields[6].GetUInt32(); if(newDisplay) creature->SetDisplayId(newDisplay); float newScale = Fields[5].GetFloat(); if(newScale) creature->SetObjectScale(newScale); uint32 newDamage = Fields[10].GetUInt32(); if (newDamage) guard->SetDamage(newDamage); uint32 newIsAntiAir = Fields[11].GetBool(); if (newIsAntiAir) guard->SetIsAntiAir(newIsAntiAir); uint32 newIsAntiGround = Fields[12].GetBool(); if (newIsAntiGround) guard->SetIsAntiGround(newIsAntiGround); } } } }