static void SaveObject(Player* player, uint32 GObjectID, bool isHex, bool message = false) { GameObject* object = GetObjectByGObjectID(player, GObjectID, isHex); if (!object) return; Map* map = player->GetMap(); GameObject* saved = new GameObject; uint32 guidLow = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT); float x, y, z, o; object->GetPosition(x, y, z, o); if (!saved->Create(guidLow, object->GetEntry(), map, object->GetPhaseMask(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete saved; return; } saved->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), object->GetPhaseMask()); if (!saved->LoadGameObjectFromDB(guidLow, map)) { delete saved; return; } sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGOData(guidLow)); DeleteObject(object/*, isHex ? GObjectID : 0*/); // delete old std::ostringstream ss; if(!isHex) ss << "GOMOVE|SWAP|" << std::dec << GObjectID << std::dec << "||" << guidLow; else ss << "GOMOVE|SWAP|" << "0x" << std::hex << GObjectID << std::dec << "||" << guidLow; SendAddonMessage(player, ss.str().c_str()); }
//add spawn of creature static bool HandleNpcAddCommand(ChatHandler* handler, const char* args) { if (!*args) return false; char* charID = handler->extractKeyFromLink((char*)args,"Hcreature_entry"); if (!charID) return false; char* team = strtok(NULL, " "); int32 teamval = 0; if (team) { teamval = atoi(team); } if (teamval < 0) { teamval = 0; } uint32 id = atoi(charID); Player *chr = handler->GetSession()->GetPlayer(); float x = chr->GetPositionX(); float y = chr->GetPositionY(); float z = chr->GetPositionZ(); float o = chr->GetOrientation(); Map *map = chr->GetMap(); if (chr->GetTransport()) { uint32 tguid = chr->GetTransport()->AddNPCPassenger(0, id, chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO()); if (tguid > 0) WorldDatabase.PQuery("INSERT INTO creature_transport (guid, npc_entry, transport_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO) values (%u, %u, %f, %f, %f, %f, %u)", tguid, id, chr->GetTransport()->GetEntry(), chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO()); return true; } Creature* pCreature = new Creature; if (!pCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o)) { delete pCreature; return false; } pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); uint32 db_guid = pCreature->GetDBTableGUIDLow(); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); pCreature->LoadFromDB(db_guid, map); map->Add(pCreature); sObjectMgr->AddCreatureToGrid(db_guid, sObjectMgr->GetCreatureData(db_guid)); return true; }
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; 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* 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 PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID); stmt->setInt32(0, int32(wpCreature->GetGUIDLow())); stmt->setUInt32(1, pathid); stmt->setUInt32(2, point); WorldDatabase.Execute(stmt); 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; 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 PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WOLRD_UPD_ALL_WAYPOINT_DATA_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; }
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 = NULL; // 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 QueryResult result = WorldDatabase.PQuery("SELECT id, point FROM waypoint_data WHERE wpguid = %u", wpGuid); 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 const char* maxDIFF = "0.01"; result = WorldDatabase.PQuery("SELECT id, point FROM waypoint_data WHERE (abs(position_x - %f) <= %s) and (abs(position_y - %f) <= %s) and (abs(position_z - %f) <= %s)", target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF); 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" && target) { handler->PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff%u|r", pathid); // wpCreature Creature* wpCreature = NULL; if (wpGuid != 0) { wpCreature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); wpCreature->CombatStop(); wpCreature->DeleteFromDB(); wpCreature->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" && target) { handler->PSendSysMessage("|cff00ff00DEBUG: wp move, PathID: |r|cff00ffff%u|r", pathid); Player* chr = handler->GetSession()->GetPlayer(); Map* map = chr->GetMap(); { // wpCreature Creature* wpCreature = NULL; // What to do: // Move the visual spawnpoint // Respawn the owner of the waypoints if (wpGuid != 0) { wpCreature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); wpCreature->CombatStop(); wpCreature->DeleteFromDB(); wpCreature->AddObjectToRemoveList(); // re-create Creature* wpCreature2 = new Creature; if (!wpCreature2->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation())) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wpCreature2; return false; } wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); //TODO: Should we first use "Create" then use "LoadFromDB"? if (!wpCreature2->LoadCreatureFromDB(wpCreature2->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wpCreature2; return false; } //sMapMgr->GetMap(npcCreature->GetMapId())->Add(wpCreature2); } 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; }
//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(LANGUAGE_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(LANGUAGE_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->GetPhaseMgr().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->GetPhaseMgr().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(LANGUAGE_GAMEOBJECT_ADD, objectId, objectInfo->name.c_str(), guidLow, x, y, z); return true; }
//spawn go static bool HandleGameObjectAddCommand(ChatHandler* handler, const char* args) { if (!*args) return false; // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r char* cId = handler->extractKeyFromLink((char*)args,"Hgameobject_entry"); if (!cId) return false; uint32 id = atol(cId); if (!id) return false; char* spawntimeSecs = strtok(NULL, " "); const GameObjectInfo *gInfo = ObjectMgr::GetGameObjectInfo(id); if (!gInfo) { handler->PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); handler->SetSentErrorMessage(true); return false; } if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId)) { // report to DB errors log as in loading case sLog->outErrorDb("Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned.",id, gInfo->type, gInfo->displayId); handler->PSendSysMessage(LANG_GAMEOBJECT_HAVE_INVALID_DATA,id); handler->SetSentErrorMessage(true); return false; } Player *chr = handler->GetSession()->GetPlayer(); float x = float(chr->GetPositionX()); float y = float(chr->GetPositionY()); float z = float(chr->GetPositionZ()); float o = float(chr->GetOrientation()); Map *map = chr->GetMap(); GameObject* pGameObj = new GameObject; uint32 db_lowGUID = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT); if (!pGameObj->Create(db_lowGUID, gInfo->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete pGameObj; return false; } if (spawntimeSecs) { uint32 value = atoi((char*)spawntimeSecs); pGameObj->SetRespawnTime(value); //sLog->outDebug(LOG_FILTER_TSCR, "*** spawntimeSecs: %d", value); } // fill the gameobject data and save to the db pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()),chr->GetPhaseMaskForSpawn()); // this will generate a new guid if the object is in an instance if (!pGameObj->LoadFromDB(db_lowGUID, map)) { delete pGameObj; return false; } map->Add(pGameObj); // TODO: is it really necessary to add both the real and DB table guid here ? sObjectMgr->AddGameobjectToGrid(db_lowGUID, sObjectMgr->GetGOData(db_lowGUID)); handler->PSendSysMessage(LANG_GAMEOBJECT_ADD,id,gInfo->name,db_lowGUID,x,y,z); return true; }
/* - return the right instance for the object, based on its InstanceId - create the instance if it's not created already - the player is not actually added to the instance (only in InstanceMap::Add) */ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) { if (GetId() != mapId || !player) return NULL; Map* map = NULL; uint32 newInstanceId = 0; // instanceId of the resulting map. if (IsBattlegroundOrArena()) { // Instantiate or find existing bg map for player. The instance id is set in battlegroundid. newInstanceId = player->GetBattlegroundId(); if (!newInstanceId) return NULL; map = sMapMgr->FindMap(mapId, newInstanceId); if (!map) { if (Battleground* bg = player->GetBattleground()) map = CreateBattleground(newInstanceId, bg); else { player->TeleportToBGEntryPoint(); return NULL; } } } else { InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficulty(IsRaid())); InstanceSave* pSave = pBind ? pBind->save : NULL; // The player's permanent player bind is taken into consideration first, then the player's group bind and finally the solo bind. if (!pBind || !pBind->perm) { InstanceGroupBind* groupBind = NULL; Group* group = player->GetGroup(); // Use the player's difficulty setting (it may not be the same as the group's). if (group) { groupBind = group->GetBoundInstance(this); if (groupBind) pSave = groupBind->save; } } if (pSave) { // Solo / permanent / group lock exists. newInstanceId = pSave->GetInstanceId(); map = FindInstanceMap(newInstanceId); if (IsRaid()) { if (player->IsOnDynamicDifficultyMap()) { // Dynamic Difficulty lock: create an instance that matches the difficulty the player changes to. if (player->GetDifficulty(IsRaid()) != pSave->GetDifficulty() || map && map->GetSpawnMode() != player->GetDifficulty(IsRaid())) map = CreateInstance(newInstanceId, pSave, player->GetDifficulty(IsRaid())); } else { // Shared locks: create an instance to match the current player raid difficulty, if the save and player difficulties don't match. // We must check for save difficulty going original diff -> new one, and map spawn mode going new -> original, to make sure all cases are handled. // Although Heroic 10 / 25 Man also theoretically share a cooldown, if you kill a boss on 10 / 25 Heroic you cannot enter any other Heroic size version of the raid (cannot switch). // Heroic size switching is already handled with no checks needed. The map is created on the save difficulty and you can only switch difficulty dynamically, from inside. if (pSave->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL || pSave->GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) { // Normal. The map is created on the player difficulty. if (player->GetDifficulty(IsRaid()) != pSave->GetDifficulty() || map && map->GetSpawnMode() != player->GetDifficulty(IsRaid())) map = CreateInstance(newInstanceId, pSave, player->GetDifficulty(IsRaid())); } } } // It is possible that the save exists but the map doesn't, create it. if (!map) map = CreateInstance(newInstanceId, pSave, pSave->GetDifficulty()); } else { // If no instanceId via group members or instance saves is found, the instance will be created for the first time. newInstanceId = sMapMgr->GenerateInstanceId(); Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid()); map = FindInstanceMap(newInstanceId); if (!map) map = CreateInstance(newInstanceId, NULL, diff); } } return map; }
//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 = atoul(id); if (!objectId) return false; char* spawntimeSecs = strtok(nullptr, " "); GameObjectTemplate const* 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(); Map* map = player->GetMap(); GameObject* object = new GameObject(); ObjectGuid::LowType guidLow = map->GenerateLowGuid<HighGuid::GameObject>(); QuaternionData rot = QuaternionData::fromEulerAnglesZYX(player->GetOrientation(), 0.f, 0.f); if (!object->Create(guidLow, objectInfo->entry, map, player->GetPhaseMaskForSpawn(), *player, rot, 255, GO_STATE_READY)) { delete object; return false; } if (spawntimeSecs) { int32 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()); guidLow = object->GetSpawnId(); // 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->LoadFromDB(guidLow, map, true)) { delete object; return false; } /// @todo is it really necessary to add both the real and DB table guid here ? sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGameObjectData(guidLow)); handler->PSendSysMessage(LANG_GAMEOBJECT_ADD, objectId, objectInfo->name.c_str(), guidLow, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); return true; }
static bool HandleNpcBotSpawnCommand(ChatHandler* handler, const char* args) { if (!*args) { handler->SendSysMessage(".npcbot spawn"); handler->SendSysMessage("Adds new npcbot spawn of given entry in world. You can shift-link the npc"); handler->SendSysMessage("Syntax: .npcbot spawn #entry"); handler->SetSentErrorMessage(true); return false; } char* charID = handler->extractKeyFromLink((char*)args, "Hcreature_entry"); if (!charID) return false; uint32 id = atoi(charID); CreatureTemplate const* creInfo = sObjectMgr->GetCreatureTemplate(id); if (!creInfo) { handler->PSendSysMessage("creature %u does not exist!", id); handler->SetSentErrorMessage(true); return false; } if (!(creInfo->flags_extra & CREATURE_FLAG_EXTRA_NPCBOT)) { handler->PSendSysMessage("creature %u is not a npcbot!", id); handler->SetSentErrorMessage(true); return false; } PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_NPCBOT_OWNER); //"SELECT owner FROM character_npcbot WHERE entry = ?", CONNECTION_SYNCH stmt->setUInt32(0, id); PreparedQueryResult res1 = CharacterDatabase.Query(stmt); if (res1) { handler->PSendSysMessage("Npcbot %u already exists in `characters_npcbot` table!", id); handler->SendSysMessage("If you want to replace this bot to new location use '.npc move' command"); handler->SetSentErrorMessage(true); return false; } stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_BY_ID); //"SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH stmt->setUInt32(0, id); PreparedQueryResult res2 = WorldDatabase.Query(stmt); if (res2) { handler->PSendSysMessage("Npcbot %u already exists in `creature` table!", id); handler->SetSentErrorMessage(true); return false; } Player* chr = handler->GetSession()->GetPlayer(); if (chr->GetTransport()) { handler->SendSysMessage("Cannot spawn bots on transport!"); handler->SetSentErrorMessage(true); return false; } float x = chr->GetPositionX(); float y = chr->GetPositionY(); float z = chr->GetPositionZ(); float o = chr->GetOrientation(); Map* map = chr->GetMap(); if (map->Instanceable()) { handler->SendSysMessage("Cannot spawn bots in instances!"); handler->SetSentErrorMessage(true); return false; } Creature* creature = new Creature(); if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o, 0)) { delete creature; return false; } uint8 roleMask = BOT_ROLE_DPS; uint8 m_class = creature->GetCreatureTemplate()->trainer_class; if (!(m_class == CLASS_WARRIOR || m_class == CLASS_ROGUE || m_class == CLASS_PALADIN || m_class == CLASS_DEATH_KNIGHT || m_class == CLASS_SHAMAN || m_class == BOT_CLASS_BM)) roleMask |= BOT_ROLE_RANGED; if (m_class == CLASS_PRIEST || m_class == CLASS_DRUID || m_class == CLASS_SHAMAN || m_class == CLASS_PALADIN) roleMask |= BOT_ROLE_HEAL; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_NPCBOT); //"INSERT INTO characters_npcbot (entry, roles) VALUES (?, ?)", CONNECTION_SYNCH stmt->setUInt32(0, id); stmt->setUInt8(1, roleMask); CharacterDatabase.DirectExecute(stmt); creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn()); uint32 db_guid = creature->GetDBTableGUIDLow(); if (!creature->LoadBotCreatureFromDB(db_guid, map)) { handler->SendSysMessage("Cannot load npcbot from DB!"); handler->SetSentErrorMessage(true); //return false; delete creature; return false; } sObjectMgr->AddCreatureToGrid(db_guid, sObjectMgr->GetCreatureData(db_guid)); handler->SendSysMessage("Npcbot successfully spawned."); return true; }
static GameObject* place(Player* player, float x, float y, float z, float o, uint32 phase, uint32 guid) { // e = !move && entry or move && guid (entryorguid if (!player || !guid) return NULL; phase = 1; const GameObjectTemplate* objectInfo = sObjectMgr->GetGameObjectTemplate(guid); if(player->GetDistance(x, y, z) > 20) { ChatHandler(player->GetSession()).PSendSysMessage("You cant place that object so far away."); ChatHandler(player->GetSession()).SetSentErrorMessage(true); return NULL; } if (!objectInfo) { ChatHandler(player->GetSession()).PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST, guid); ChatHandler(player->GetSession()).SetSentErrorMessage(true); return NULL; } if (objectInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(objectInfo->displayId)) { // sLog->outErrorDb("Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned.", e, objectInfo->type, objectInfo->displayId); ChatHandler(player->GetSession()).PSendSysMessage(LANG_GAMEOBJECT_HAVE_INVALID_DATA, guid); ChatHandler(player->GetSession()).SetSentErrorMessage(true); return NULL; } Map* map = player->GetMap(); if(player->GetMapId() == 608) { ChatHandler(player->GetSession()).PSendSysMessage("Stop! Not so fast. No placing APTs in here."); ChatHandler(player->GetSession()).SetSentErrorMessage(true); return NULL; } GameObject* object = new GameObject; uint32 guidLow = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT); if (!object->Create(guidLow, objectInfo->entry, map, phase, x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete object; return NULL; } object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), phase); if (!object->LoadGameObjectFromDB(guidLow, map)) { delete object; return NULL; } // STORE THE ITEM_INSTANCE THAT WAS USED TO SPAWN THIS ITEM!!! sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGOData(guidLow)); uint32 sec = time(NULL); QueryResult result = WorldDatabase.PQuery("INSERT INTO apt_placed_objects VALUES('%u', '%u')", item_script_apt::itemGuid, guidLow); result = WorldDatabase.PQuery("INSERT INTO legacy_gameobject VALUES ('%u', '1', '0', '%u')", guidLow, player->GetGUIDLow()); return object; }
//add spawn of creature static bool HandleNpcAddCommand(ChatHandler* handler, const char* args) { if (!*args) return false; char* charID = handler->extractKeyFromLink((char*)args, "Hcreature_entry"); if (!charID) return false; char* team = strtok(NULL, " "); int32 teamval = 0; if (team) { teamval = atoi(team); } if (teamval < 0) { teamval = 0; } uint32 id = atoi(charID); Player* chr = handler->GetSession()->GetPlayer(); float x = chr->GetPositionX(); float y = chr->GetPositionY(); float z = chr->GetPositionZ(); float o = chr->GetOrientation(); Map* map = chr->GetMap(); if (chr->GetTransport()) { uint32 tguid = chr->GetTransport()->AddNPCPassenger(0, id, chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO()); if (tguid > 0) { PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_CREATURE_TRANSPORT); stmt->setInt32(0, int32(tguid)); stmt->setInt32(1, int32(id)); stmt->setInt32(2, int32(chr->GetTransport()->GetEntry())); stmt->setFloat(3, chr->GetTransOffsetX()); stmt->setFloat(4, chr->GetTransOffsetY()); stmt->setFloat(5, chr->GetTransOffsetZ()); stmt->setFloat(6, chr->GetTransOffsetO()); WorldDatabase.Execute(stmt); } return true; } Creature* creature = new Creature(); if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o)) { delete creature; return false; } creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); uint32 db_guid = creature->GetDBTableGUIDLow(); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); if (!creature->LoadCreatureFromDB(db_guid, map)) { delete creature; return false; } sObjectMgr->AddCreatureToGrid(db_guid, sObjectMgr->GetCreatureData(db_guid)); return true; }
//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; }