Roarl

Members
  • Content Count

    41
  • Joined

  • Last visited

Community Reputation

29 Excellent

2 Followers

About Roarl

  • Rank
    Advanced Member

Personal Information

  • Specialty
    Level Design
    DBC Editing
    Lore/Quests

Contacts

  • Discord
    Pixel Weaver#5446
  • Skype
    antoine.cajot

Recent Profile Visitors

6,388 profile views
    Loooooooooveeeee those WMOs!! Great job and thanks a lot for sharing.
  1. If the lua interface file appeared only in BFA I really think it makes sense it was hardcoded before. Looking into it as well.
  2. Did you try what he said ? Like both forcing the check to true and outputting something in the error or debug log if the HasSpell (easiest one to check) condition is true ?
  3. Maybe give the player the spell but don't script anything linked with it. Like if you are giving that buff to race = RACE_TAUREN, just check for race == RACE_TAUREN instead of HasAura... Maybe that's kind of hackish though I don't know... And if you want this to be some spell you can learn, then, yeah, it also defeats the purpose.
  4. Could you also post your modification in spell.dbc ?
  5. Try HasAura instead of HasSpell EDIT: It is a passive and I never toyed with passives so I am not sure how they work... Well try it just in case. The only think I can promise you is that there is no interface limitation for xp rate : it's all server-side.
  6. Very first result I got on Google... Everything you need to know and download, including the LoginScreen tool that Mordred made, is provided here. Then, about Interface\Glues, have a look inside MPQ files.
  7. Yeah Nagrand is my favorite zone too ! Hope you can emulate or even improve its feel. Keep us updated and keep it up
  8. Roarl

    Noggit custom map

    Hey, I cannot recognize your Noggit version, never used that one. It shouldn't be the issue but here is a more recent release : Also, could you enclose your .adt and .wdt files so I can have a look at them ? On your screenshot, there seem to be a clickable area which I highlighted in yellow below. Did you try to click on it ? Regards.
  9. Hey, You could start by checking this out : Regards, Roarl // Update : So sorry, I misunderstood your request. I am afraid I cannot help. (If a moderator sees this, could you please delete my answer? It is kind of useless! Thanks <3)
  10. Hi, thanks for your answer. I get your point and indeed, adding a second GossipItem in the menu before sending it works. But do you know why it is that way ? And do you have any idea why it works for Rochet2's script and not for mine ? For instance, in the code below at case case EQUIPMENT_SLOT_END + 9: the menu is working as it should. static bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) { ClearGossipMenuFor(player); 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 (!newItem->transmog) continue; newItem->transmog = 0; newItem->SetState(ITEM_CHANGED, player); sTransmogrification->UpdateItem(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 (newItem->transmog) { newItem->transmog = 0; newItem->SetState(ITEM_CHANGED, player); sTransmogrification->UpdateItem(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) AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Book_11:30:30:-18:0|tHow sets work", EQUIPMENT_SLOT_END + 10, 0); if (!player->presetMap.empty()) { for (PresetMapType::const_iterator it = player->presetMap.begin(); it != player->presetMap.end(); ++it) AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Statue_02:30:30:-18:0|t" + it->second.name, EQUIPMENT_SLOT_END + 6, it->first); if (player->presetMap.size() < sTransmogrification->MaxSets) AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/GuildBankFrame/UI-GuildBankFrame-NewTab:30:30:-18:0|tSave set", EQUIPMENT_SLOT_END + 8, 0); } else AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/GuildBankFrame/UI-GuildBankFrame-NewTab:30:30:-18:0|tSave set", EQUIPMENT_SLOT_END + 8, 0); AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack..", EQUIPMENT_SLOT_END + 1, 0); SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID()); } break; case EQUIPMENT_SLOT_END + 5: // Use preset { if (!sTransmogrification->EnableSets) { OnGossipHello(player, creature); return true; } // action = presetID PresetMapType::const_iterator it = player->presetMap.find(action); if (it != player->presetMap.end()) { for (PresetslotMapType::const_iterator it2 = it->second.slotMap.begin(); it2 != it->second.slotMap.end(); ++it2) if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, it2->first)) sTransmogrification->PresetTransmog(player, item, it2->second, it2->first); } OnGossipSelect(player, creature, EQUIPMENT_SLOT_END + 6, action); } break; case EQUIPMENT_SLOT_END + 6: // view preset { if (!sTransmogrification->EnableSets) { OnGossipHello(player, creature); return true; } // action = presetID PresetMapType::const_iterator it = player->presetMap.find(action); if (it == player->presetMap.end()) { OnGossipSelect(player, creature, EQUIPMENT_SLOT_END + 4, 0); return true; } for (PresetslotMapType::const_iterator it2 = it->second.slotMap.begin(); it2 != it->second.slotMap.end(); ++it2) AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, sTransmogrification->GetItemIcon(it2->second, 30, 30, -18, 0) + sTransmogrification->GetItemLink(it2->second, session), sender, action); AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Statue_02:30:30:-18:0|tUse set", EQUIPMENT_SLOT_END + 5, action, "Using this set for transmogrify will bind transmogrified items to you and make them non-refundable and non-tradeable.\nDo you wish to continue?\n\n" + it->second.name, 0, false); AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/PaperDollInfoFrame/UI-GearManager-LeaveItem-Opaque:30:30:-18:0|tDelete set", EQUIPMENT_SLOT_END + 7, action, "Are you sure you want to delete " + it->second.name + "?", 0, false); AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack..", EQUIPMENT_SLOT_END + 4, 0); SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID()); } break; case EQUIPMENT_SLOT_END + 7: // Delete preset { if (!sTransmogrification->EnableSets) { OnGossipHello(player, creature); return true; } // action = presetID auto it = player->presetMap.find(action); if (it != player->presetMap.end()) { CharacterDatabase.PExecute("DELETE FROM `custom_transmogrification_sets` WHERE `Owner` = %u AND `PresetID` = %u", player->GetGUID().GetCounter(), uint32(action)); player->presetMap.erase(it); } OnGossipSelect(player, creature, EQUIPMENT_SLOT_END + 4, 0); } break; case EQUIPMENT_SLOT_END + 8: // Save preset { if (!sTransmogrification->EnableSets) { OnGossipHello(player, creature); return true; } if (player->presetMap.size() >= sTransmogrification->MaxSets) { OnGossipHello(player, creature); return true; } uint32 cost = 0; bool canSave = false; for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) { if (!sTransmogrification->GetSlotName(slot, session)) continue; if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) { uint32 entry = newItem->transmog; if (!entry) continue; const ItemTemplate* temp = sObjectMgr->GetItemTemplate(entry); if (!temp) continue; if (!sTransmogrification->SuitableForTransmogrification(player, temp)) // no need to check? continue; cost += sTransmogrification->GetSpecialPrice(temp); canSave = true; AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, sTransmogrification->GetItemIcon(entry, 30, 30, -18, 0) + sTransmogrification->GetItemLink(entry, session), EQUIPMENT_SLOT_END + 8, 0); } } if (canSave) AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/GuildBankFrame/UI-GuildBankFrame-NewTab:30:30:-18:0|tSave set", 0, 0, "Insert set name", cost*sTransmogrification->SetCostModifier + sTransmogrification->SetCopperCost, true); AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/PaperDollInfoFrame/UI-GearManager-Undo:30:30:-18:0|tUpdate menu", sender, action); AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack..", EQUIPMENT_SLOT_END + 4, 0); SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID()); } break; case EQUIPMENT_SLOT_END + 10: // Set info { AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack..", EQUIPMENT_SLOT_END + 4, 0); SendGossipMenuFor(player, sTransmogrification->SetNpcText, creature->GetGUID()); } break; #endif case EQUIPMENT_SLOT_END + 9: // Transmog info { AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack..", EQUIPMENT_SLOT_END + 1, 0); SendGossipMenuFor(player, sTransmogrification->TransmogNpcText, creature->GetGUID()); } break; default: // Transmogrify { if (!sender && !action) { OnGossipHello(player, creature); return true; } // sender = slot, action = display TransmogTrinityStrings res = sTransmogrification->Transmogrify(player, ObjectGuid(HighGuid::Item, 0, action), sender); if (res == LANG_ERR_TRANSMOG_OK) session->SendAreaTriggerMessage("%s", GTS(LANG_ERR_TRANSMOG_OK)); else session->SendNotification(res); // OnGossipSelect(player, EQUIPMENT_SLOT_END, sender); new Timed(player, creature, EQUIPMENT_SLOT_END, sender); } break; } return true; }
  11. What version of the game are you using ? What emulator are you using ? ( I am going to guess 3.3.5 and TrinityCore from now on ) In any case, you should start by getting used to TrinityCore code and understanding how they implemented battlegrounds in the first place. When you are done coding the battleground itself, you can either replace one of the existing battlegrounds with it, or create a custom NPC to queue for it, or add it in BattlemasterList.dbc I guess. There might be additionnal .dbc work involved, I am not sure.
  12. Not sure I am gonna use this anytime soon but this is amazing... No idea why I didn't stumble on it earlier ! Good work both, and very nice and exhaustive tutorial !
  13. Version 1.0

    172 downloads

    I always disliked how the AuctionHouseBot handled selling and buying items randomly in the recent TrinityCore releases. It used the in-game npc seller price to determine both the sell and buy prices on the AH for the bot resulting in prices being to damn low (generally) or really too high (less often) and sold strange random items sometimes never sold by players. With this version of the AuctionHouseBot, the sell and buy prices are worked out from an external table in the world database called auction_prices which simply contains item ids and their price in copper. ONLY items belonging to this table can be sold or bought by the bot and their price in the table is used to determine both the sell price and the buy price. The contents of the auction_prices table has been generated using sampled AH data from several private servers and will be updated from time to time. General rules : The chance of an item being bought when the price is higher than the table price is a decaying exponential. The exponential decays later if no other instance of an item is sold. E.G. If you have a monopoly on [Copper Ore] then the bot knows that the price of [Copper Ore] is a bit higher than usual. The bot will NEVER buy an item if another instance of that item is sold for less. This is simply more realistic. An item sold by a player that can be bought from a npc using base money will never be bought by the bot even if it appears in auction_prices, to avoid exploit. They still can be sold by the bot, though. Of course, a code is never perfect. Should you have any suggestion for the bot behavior, problems to report or improvements to make in the code, feel free to leave a comment. Installation : Move the 6 .cpp files to your \src\server\game\AuctionHouseBot TrinityCore source directory and replace the existing ones Don't forget to commit them if you use git Recompile your core Apply the auction_prices.sql statement to your world database Apply the update.sql statement to your world database, if there is one. [Repeat step 5 only for each future update]
  14. Hello, I am currently working on a small housing system and am almost done with the bare bones but something is still refusing to work properly. I want to add a very small description of how the housing system works in a gossip menu, but as soon as SendGossipMenuFor it triggers the OnGossipHello instantly. I compared this part to the Transmogrifier script of Rochet2, which works fine, and it really looks the same so I do not get what I am doing wrong. More concretly, when I click "Why acquire a property ?" in the first menu, the relevant action (case 1 in OnGossipSelect in the code below) is executed (as expected) but then instantly the action made available in the next menu is also executed instantly (default case, with action = 3) : in the end the second menu never appears, instead OnGossipHello is executed again. Does anyone have any idea how to avoid this ? Thanks in advance for your time ! class npc_house_seller : public CreatureScript { public: npc_house_seller() : CreatureScript("npc_house_seller") { } class npc_house_sellerAI : public ScriptedAI { public: npc_house_sellerAI(Creature* creature) : ScriptedAI(creature) {} bool GossipHello(Player* player) override { return OnGossipHello(player, me); } static bool OnGossipHello(Player* player, Creature* creature) { WorldSession* session = player->GetSession(); AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Book_11:30:30:-18:0|tWhy acquire a property ?", 1, 0); std::stringstream warningMessage; warningMessage.str(std::string()); warningMessage << "Are you sure you want to proceed ? It will cost you " << HousingSystem::instance()->HouseFromSeller(creature->GetSpawnId())->_price / 10000 << " gold and strip you of any previous estate property."; AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Enchant_Disenchant:30:30:-18:0|tPurchase this estate", 2, 0, warningMessage.str().c_str(), 0, false); SendGossipMenuFor(player, 800001, creature->GetGUID()); return true; } bool GossipSelect(Player* player, uint32 /*menu_id*/, uint32 gossipListId) override { uint32 sender = player->PlayerTalkClass->GetGossipOptionSender(gossipListId); uint32 action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId); return OnGossipSelect(player, me, sender, action); } static bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) { ClearGossipMenuFor(player); WorldSession* session = player->GetSession(); switch (sender) { case 1: { AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack..", 3, 0); SendGossipMenuFor(player, 800002, creature->GetGUID()); } break; case 2: if (player->HasEnoughMoney(HousingSystem::instance()->HouseFromSeller(creature->GetSpawnId())->_price)) { House* house = HousingSystem::instance()->HouseFromPlayer(player->GetGUID().GetCounter()); if (house != nullptr) { house->_owner = 0; // Respawn NPC Map* map = sMapMgr->FindBaseNonInstanceMap(house->_map_id); Position pos(house->_coord_x, house->_coord_y, house->_coord_z, house->_orientation); Creature* cbuffer = new Creature(); if (!cbuffer->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, PHASEMASK_ANYWHERE, 50006, pos)) delete cbuffer; cbuffer->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), PHASEMASK_ANYWHERE); ObjectGuid::LowType db_guid = cbuffer->GetSpawnId(); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells() // current "creature" variable is deleted and created fresh new, otherwise old values might trigger asserts or cause undefined behavior cbuffer->CleanupsBeforeDelete(); delete cbuffer; cbuffer = new Creature(); if (!cbuffer->LoadFromDB(db_guid, map, true, true)) delete cbuffer; sObjectMgr->AddCreatureToGrid(db_guid, sObjectMgr->GetCreatureData(db_guid)); house->_seller = db_guid; HousingSystem::instance()->AdaptSellerMapOnHouseChange(db_guid, house); house->SaveToDB(); } house = HousingSystem::instance()->HouseFromSeller(creature->GetSpawnId()); house->_owner = player->GetGUID().GetCounter(); house->_seller = 0; house->SaveToDB(); HousingSystem::instance()->AdaptPlayerMapOnHouseChange(house->_owner, house); // Remove Creature ObjectGuid::LowType guid = creature->GetGUID().GetCounter(); creature->CombatStop(); creature->DeleteFromDB(); creature->AddObjectToRemoveList(); player->ModifyMoney(0-HousingSystem::instance()->HouseFromSeller(creature->GetSpawnId())->_price, false); std::stringstream yay; yay.str(std::string()); yay << "Congratulations ! You are now the proud owner of this estate ! "; WorldPacket data(SMSG_MOTD); Tokenizer motdTokens(yay.str(), '@'); data << uint32(motdTokens.size()); for (Tokenizer::const_reference token : motdTokens) data << token; player->GetSession()->SendPacket(&data); player->AddItem(60073,1); player->PlayerTalkClass->SendCloseGossip(); } else { std::stringstream nope; nope.str(std::string()); nope << "You cannot afford that property ! You need at least " << HousingSystem::instance()->HouseFromSeller(creature->GetSpawnId())->_price/10000 << " gold."; session->SendNotification(nope.str().c_str()); player->PlayerTalkClass->SendCloseGossip(); } break; default: { std::stringstream nope; nope.str(std::string()); nope << "Triggered " << sender << " !"; session->SendNotification(nope.str().c_str()); } return OnGossipHello(player, creature); } return true; } }; CreatureAI* GetAI(Creature *creature) const override { return new npc_house_sellerAI(creature); } };