Здравствуйте, пользователи этого форума. Вообщем проблема такая, накатил патч на трансмогрификатора, вроде всё нормально подогнал под свою реву, но в игре у нпс не отображается госсип меню, просто пустой нпс. Поможет кто? И отвечу сразу в script_loader добавил, скрипт нейм мобу присвоил, и флаг госсипа мобу поставил. Вот сам скрипт на трансмогрификатора
class CS_Transmogrification : public CreatureScript { public: CS_Transmogrification() : CreatureScript("Creature_Transmogrify") { }
class TransmogAI : public ScriptedAI { public: TransmogAI(Creature* creature) : ScriptedAI(creature) {}
struct Timed : public BasicEvent { // This timed event tries to fix modify money breaking gossip // This event closes the gossip menu and on the second player update tries to open the next menu Timed(Player* player, Creature* creature, uint32 sender, uint32 action) : guid(creature->GetGUID()), player(player), sender(sender), action(action), triggered(false) { player->CLOSE_GOSSIP_MENU(player); player->m_Events.AddEvent(this, player->m_Events.CalculateTime(1)); }
static bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) { player->PlayerTalkClass->ClearMenus(); WorldSession* session = player->GetSession(); switch (sender) { case EQUIPMENT_SLOT_END: // Show items you can use ShowTransmogItems(player, creature, action); break; case EQUIPMENT_SLOT_END + 1: // Main menu OnGossipHello(player, creature); break; case EQUIPMENT_SLOT_END + 2: // Remove Transmogrifications { bool removed = false; for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) { if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) { if (!sTransmogrification->GetFakeEntry(newItem)) continue; sTransmogrification->DeleteFakeEntry(player, newItem); removed = true; } } if (removed) session->SendAreaTriggerMessage("%s", GTS(LANG_ERR_UNTRANSMOG_OK)); else session->SendNotification(LANG_ERR_UNTRANSMOG_NO_TRANSMOGS); OnGossipHello(player, creature); } break; case EQUIPMENT_SLOT_END + 3: // Remove Transmogrification from single item { if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, action)) { if (sTransmogrification->GetFakeEntry(newItem)) { sTransmogrification->DeleteFakeEntry(player, newItem); session->SendAreaTriggerMessage("%s", GTS(LANG_ERR_UNTRANSMOG_OK)); } else session->SendNotification(LANG_ERR_UNTRANSMOG_NO_TRANSMOGS); } OnGossipSelect(player, creature, EQUIPMENT_SLOT_END, action); } break; #ifdef PRESETS case EQUIPMENT_SLOT_END + 4: // Presets menu { if (!sTransmogrification->EnableSets) { OnGossipHello(player, creature); return true; } if (sTransmogrification->EnableSetInfo) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Book_11:30:30:-18:0|tКак работают комплекты трансмогрификации", EQUIPMENT_SLOT_END + 10, 0);
if (!player->presetMap.empty()) { for (PresetMapType::const_iterator it = player->presetMap.begin(); it != player->presetMap.end(); ++it) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Statue_02:30:30:-18:0|t" + it->second.name, EQUIPMENT_SLOT_END + 6, it->first);
int32 cost = 0; PresetslotMapType items; for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) { if (!sTransmogrification->GetSlotName(slot, player->GetSession())) continue; if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) { uint32 entry = sTransmogrification->GetFakeEntry(newItem); if (!entry) continue; const ItemTemplate* temp = sObjectMgr->GetItemTemplate(entry); if (!temp) continue; if (!sTransmogrification->SuitableForTransmogrification(player, temp)) continue; cost += sTransmogrification->GetSpecialPrice(temp); items [slot]= entry; } }
if (!items.empty()) { // transmogrified items were found to be saved cost *= sTransmogrification->SetCostModifier; cost += sTransmogrification->SetCopperCost;
if (!player->HasEnoughMoney(cost)) { player->GetSession()->SendNotification(LANG_ERR_TRANSMOG_NOT_ENOUGH_MONEY); } else { uint8 presetID = sTransmogrification->MaxSets; if (player->presetMap.size() < sTransmogrification->MaxSets) { for (uint8 i = 0; i < sTransmogrification->MaxSets; ++i) // should never reach over max { if (player->presetMap.find(i) == player->presetMap.end()) { presetID = i; break; } } }
if (presetID < sTransmogrification->MaxSets) { // Make sure code doesnt mess up SQL! player->presetMap[presetID].name = name; player->presetMap[presetID].slotMap = items;
static void ShowTransmogItems(Player* player, Creature* creature, uint8 slot) // Only checks bags while can use an item from anywhere in inventory { WorldSession* session = player->GetSession(); Item* oldItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); if (oldItem) { uint32 limit = 0; uint32 price = sTransmogrification->GetSpecialPrice(oldItem->GetTemplate()); price *= sTransmogrification->ScaledCostModifier; price += sTransmogrification->CopperCost; std::ostringstream ss; ss << std::endl; if (sTransmogrification->RequireToken) ss << std::endl << std::endl << sTransmogrification->TokenAmount << " x " << sTransmogrification->GetItemLink(sTransmogrification->TokenEntry, session);
for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i) { if (limit >= MAX_OPTIONS) break; Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (!newItem) continue; if (!sTransmogrification->CanTransmogrifyItemWithItem(player, oldItem->GetTemplate(), newItem->GetTemplate())) continue; if (sTransmogrification->GetFakeEntry(oldItem) == newItem->GetEntry()) continue; ++limit; player->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, sTransmogrification->GetItemIcon(newItem->GetEntry(), 30, 30, -18, 0) + sTransmogrification->GetItemLink(newItem, session), slot, newItem->GetGUID().GetCounter(), "Using this item for transmogrify will bind it to you and make it non-refundable and non-tradeable.\nDo you wish to continue?\n\n" + sTransmogrification->GetItemIcon(newItem->GetEntry(), 40, 40, -15, -10) + sTransmogrification->GetItemLink(newItem, session) + ss.str(), price, false); }
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) { Bag* bag = player->GetBagByPos(i); if (!bag) continue; for (uint32 j = 0; j < bag->GetBagSize(); ++j) { if (limit >= MAX_OPTIONS) break; Item* newItem = player->GetItemByPos(i, j); if (!newItem) continue; if (!sTransmogrification->CanTransmogrifyItemWithItem(player, oldItem->GetTemplate(), newItem->GetTemplate())) continue; if (sTransmogrification->GetFakeEntry(oldItem) == newItem->GetEntry()) continue; ++limit; player->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, sTransmogrification->GetItemIcon(newItem->GetEntry(), 30, 30, -18, 0) + sTransmogrification->GetItemLink(newItem, session), slot, newItem->GetGUID().GetCounter(), "Using this item for transmogrify will bind it to you and make it non-refundable and non-tradeable.\nDo you wish to continue?\n\n" + sTransmogrification->GetItemIcon(newItem->GetEntry(), 40, 40, -15, -10) + sTransmogrification->GetItemLink(newItem, session) + ss.str(), price, false); } } }
class PS_Transmogrification : public PlayerScript { public: PS_Transmogrification() : PlayerScript("PS_Transmogrification") { }
void OnSave(Player* player) override { uint32 lowguid = player->GetGUID().GetCounter(); SQLTransaction trans = CharacterDatabase.BeginTransaction(); trans->PAppend("DELETE FROM `custom_transmogrification` WHERE `Owner` = %u", lowguid); #ifdef PRESETS trans->PAppend("DELETE FROM `custom_transmogrification_sets` WHERE `Owner` = %u", lowguid); #endif
if (!player->transmogMap.empty()) { // Only save items that are in inventory / bank / etc std::vector<ObjectGuid> items = sTransmogrification->GetItemList(player); for (std::vector<ObjectGuid>::const_iterator it = items.begin(); it != items.end(); ++it) { TransmogMapType::const_iterator it2 = player->transmogMap.find(*it); if (it2 == player->transmogMap.end()) continue;
#ifdef PRESETS if (!player->presetMap.empty()) { for (PresetMapType::const_iterator it = player->presetMap.begin(); it != player->presetMap.end(); ++it) { std::ostringstream ss; for (PresetslotMapType::const_iterator it2 = it->second.slotMap.begin(); it2 != it->second.slotMap.end(); ++it2) ss << uint32(it2->first) << ' ' << it2->second << ' '; trans->PAppend("REPLACE INTO `custom_transmogrification_sets` (`Owner`, `PresetID`, `SetName`, `SetData`) VALUES (%u, %u, \"%s\", \"%s\")", lowguid, uint32(it->first), it->second.name.c_str(), ss.str().c_str()); } } #endif
if (trans->GetSize()) // basically never false CharacterDatabase.CommitTransaction(trans); }
void OnLogin(Player* player, bool /*firstLogin*/) override { QueryResult result = CharacterDatabase.PQuery("SELECT GUID, FakeEntry FROM custom_transmogrification WHERE Owner = %u", player->GetGUID().GetCounter());
if (result) { do { Field* field = result->Fetch(); ObjectGuid itemGUID(HighGuid::Item, 0, field[0].GetUInt32()); uint32 fakeEntry = field[1].GetUInt32(); // Only load items that are in inventory / bank / etc if (sObjectMgr->GetItemTemplate(fakeEntry) && player->GetItemByGuid(itemGUID)) { player->transmogMap [itemGUID]= fakeEntry; } else { // Ignore, will be erased on next save. // Additionally this can happen if an item was deleted from DB but still exists for the player // TC_LOG_ERROR("custom.transmog", "Item entry (Entry: %u, itemGUID: %u, playerGUID: %u) does not exist, ignoring.", fakeEntry, GUID_LOPART(itemGUID), player->GetGUID().GetCounter()); // CharacterDatabase.PExecute("DELETE FROM custom_transmogrification WHERE FakeEntry = %u", fakeEntry); } } while (result->NextRow());
if (!player->transmogMap.empty()) { for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) { if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) { player->SetVisibleItemSlot(slot, item); if (player->IsInWorld()) item->SendUpdateToPlayer(player); } } } }
#ifdef PRESETS if (sTransmogrification->EnableSets) sTransmogrification->LoadPlayerSets(player); #endif } };
class WS_Transmogrification : public WorldScript { public: WS_Transmogrification() : WorldScript("WS_Transmogrification") { }
void OnStartup() override { TC_LOG_INFO("custom.transmog", "Deleting non-existing transmogrification entries..."); CharacterDatabase.DirectExecute("DELETE FROM custom_transmogrification WHERE NOT EXISTS (SELECT 1 FROM item_instance WHERE item_instance.guid = custom_transmogrification.GUID)");
#ifdef PRESETS // Clean even if disabled // Dont delete even if player has more presets than should CharacterDatabase.DirectExecute("DELETE FROM `custom_transmogrification_sets` WHERE NOT EXISTS(SELECT 1 FROM characters WHERE characters.guid = custom_transmogrification_sets.Owner)"); #endif sTransmogrification->LoadConfig(false); } };
void AddSC_Transmogrification() { new WS_Transmogrification(); new PS_Transmogrification(); new CS_Transmogrification(); }
Допустим, флаг госсипа ты поставил, скрипт присвоил(еще бы раз проверил имя скрипта). Также, допустим, ты в скрипт лоудере чёто-то там добавил, что стоило бы указать, что именно ты там сделал, т.к от этого всё зависит.
А именно, указал ли ты прототип(предполагаю что это и сделал). Вызвал ли данную функцию(которую должен в скрипте иметь). Выделил ли память под новый объект(самого трансера), в самой этой функции, чей прототип указал и должен вызвать в скрипт лоудере.
От этого и зависит решение твоей проблемы, в остальном вроде всё верно. То что ты указал в скрипт нейме скрипт, он просто не находит в ядре, потому что, предполагаю, ты не всё сделал, что я написал выше.
Ranege, в скрипт лоудере я указал содержимое в конце скрипта, к тому же в патче было тоже самое, то что я добавил. void AddSC_Transmogrification() и AddSC_Transmogrification(), вот что я указал, к тому же не 1ый раз ставлю скрипты.
Все вроде как верно. В cmake добавлен же файлик скрипта?(иначе оно бы и не работало в принципе и не знаю как на новой версии)
Мобу указал CS_Transmogrification такой скрипт нейм?
У тебя просто все правильно по идее, предлагаю допустим этому мобу указать другой скрипт, заработает ли. Потом попробовать перетащить скрипт в другой файлик, поменять содержимое, посовмещать, сделать по аналогии с другими скрипами и даже в другом месте, чтоб заработало, а потом уже начинать искать проблему. Методом различных тестов можно самому добиться результата. Ведь не с 0 пишешь, уже много готового есть, так подставь, перестрой, перемести и ищи проблему. Потому что, например, я больше ничего подсказать не могу(а вникать более детальней, это уже сам)
Ну добавьте стучалку какую-нибудь в 'OnGossipHello', например, чтобы проверить, подцепили ли вы вообще сценарий корректно. Если стучалка отработает - сообщите, посмотрю код.
Ну добавьте стучалку какую-нибудь в 'OnGossipHello', например, чтобы проверить, подцепили ли вы вообще сценарий корректно. Если стучалка отработает - сообщите, посмотрю код.
Программный код, вызывающий некое легко отслеживаемое событие, по времени или факту возникновения которого можно произвести примитивную отладку контекста, в который таковой код встраивается. Самый простой вариант - написать что-нибудь в консоль (в многопоточном приложении, правда, это несколько неточный вариант, но в данном случае сойдет, поскольку нас интересует не время, а факт). Т.е. в данном случае требуется добавить безусловный вывод какой-нибудь строки в консоль из 'OnGossipHello', что позволит нам узнать, производился ли вызов этого метода, что, в свою очередь, покажет, корректно ли был подключен сценарий, частью которого данный метод является.
Если в релизе собираешь, то сделай assert(false) там и если сервер упал, значит код отработал, это если не понял как лог сделать. На старых версиях это было sLog->outError("message");
Если в релизе собираешь, то сделай assert(false) там и если сервер упал, значит код отработал, это если не понял как лог сделать. На старых версиях это было sLog->outError("message");
В релизе этот макрос ни во что существенное разворачиваться не должен. Уронить сервер он не сможет в любом случае, это делается другим способом.
p620, Я добавил мобу сообщение вы в бою, т.е. если ты в бою, то при открытии нпс будет писать сообщение "Вы в бою", но к сожелению ничего не пишет. Похоже и в правду скрипт криво поставил. Но проверил несколько раз скрипт нейм у нпс, всё верно. Так же проверил script_loader, там тоже всё верно. Создал даже 2 нпс с разными скрипт неймами и всё бестолку.
// This is where scripts' loading functions should be declared: void AddSC_System_Censure(); void AddSC_npc_1v1arena(); void AddSC_hello_first_login(); void AddSC_boss_zaladaaz(); void AddSC_boss_zeelalice(); void AddSC_boss_king_of_dask(); void AddSC_npc_informator_respawn(); void AddSC_island(); void AddSC_npc_work_player(); void AddSC_Transmogrification();
// The name of this function should match: // void Add${NameOfDirectory}Scripts() void AddCustomScripts() { AddSC_System_Censure(); AddSC_npc_1v1arena(); AddSC_hello_first_login(); AddSC_boss_zaladaaz(); AddSC_boss_zeelalice(); AddSC_boss_king_of_dask(); AddSC_npc_informator_respawn(); AddSC_island(); AddSC_npc_work_player(); AddSC_Transmogrification(); }
Сообщение # 13 отредактировано leriks123 - Воскресенье, 01.04.2018, 21:30
Покажите, куда Вы вставили "отладочный" код. По поводу записи в БД - во втором варианте Вы совершенно некорректный `script_name` используете. Попробуете в первый добавить какое-нибудь реальное диалоговое окно с любым текстом (позаимствуйте у существующего НИПа, например) и отпишитесь о результатах. В загрузчике все в порядке, там ошибиться негде, в принципе.
Сообщение # 14 отредактировано p620 - Воскресенье, 01.04.2018, 23:05
static bool OnGossipHello(Player* player, Creature* creature) { if (player->IsInCombat()) { player->GetSession()->SendNotification("Вы в бою!"); player->PlayerTalkClass->SendCloseGossip(); return false; }
WorldSession* session = player->GetSession(); if (sTransmogrification->EnableTransmogInfo) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Book_11:30:30:-18:0|tКак работает трансмогрификация", EQUIPMENT_SLOT_END + 9, 0); for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot)
Диалог я создал путём нового госсип меню и просвоил это госсип меню нпс, диалог успешно отобразился в нпс. Но насколько я знаю не должен был же, если бы мобу был присвоен скрипт. И кстати диалог мне нужно было в скрипте прописать или как я сделал в через новое госсип меню?
Пришлось залезть в репозиторий, чтобы убедиться, что Ваш трансмогрификатор нерабочий. Зато он превосходно иллюстрирует причину, по которой в языке появилось ключевое слово 'override'. Подсказка: Если добавить это слово к определениям (переопределениям, предположительно) 'OnGossipHello' и 'OnGossipSelect', возникнет ошибка компиляции.