Jump to content

Roarl

Members
  • Posts

    3
  • Joined

  • Last visited

Everything posted by Roarl

  1. Basic platform animationsSo, you are building a platform game and you want to spice things up a trifle? Or maybe you just want an elevator for your custom map? You just hit the right tutorial then! A. RequirementsDBCUtil ( or any DBC<->CSV tool) (I think MyDBCEditor sucks here because it uses hexa for some columns which tends to complicate things a lot)Ladik's MPQ EditorA TrinityCore serverA kebab skewerB. Table of ContentsCreating the GameObjectGetting TransportAnimation.dbcEditing TransportAnimation.dbc.csvBPAG releaseC. Tutorial1.Creating the GameObjectOpen your favorite SQL Editor and head to the gameobject_template table. Once you get there create an entry for your custom gameobject, set the type as 11 (GAMEOBJECT_TYPE_TRANSPORT)and use whatever displayID you want to use. SET THE FLAGS TO 40 (without that, your character will not move with the platform) Note down its Guid. N.B.I Modifying the size will NOT have any effect as animated gameobjects always have their standard size in-game ( that is to say 1 ). 2.Getting TransportAnimation.dbcIf you built TrinityCore in the "C:\Build" directory for instance, you should find the dbc files in "C:\Build\bin\Release\dbc". Copy TransportAnimation.dbc and paste it where you are going to use DBCUtil. 3.Editing TransportAnimation.dbc.csvAfter you have converted TransportAnimation.dbc to csv (simple drag and drop on DBCUtil will do), let us open it with your favorite text / csv editor. The columns of the TransportAnimation are 1 ID Integer 2 TransportID Integer 3 TimeIndex Integer 4 PosX Float 5 PosY Float 6 PosZ Float 7 iRefID_SequenceID Integer (from http://pxr.dk/wowdev/wiki/). Foremost, once the server notified your client that it is encountering a transport gameobject(GAMEOBJECT_TYPE_TRANSPORT), your client plays the transport animation which he reads from TransportAnimation.dbc. He will find the animation in the dbc using the Guid of the gameobject (TransportID). The animation is then sequenced through time using the TimeIndex which is expressed in milliseconds. The 4th, 5th and 6th columns express the relative displacement of the gameobject along the Y, X and Z axis respectively (careful here, the wiki states that it rather is X, Y, Z but it's actually not the case). Eventually, the last column is the animation played by the gameobject. It is NOT compulsory but when the model you are using as moving platform has animations, why not take advantage of it? Here an example : 179710, 301034, 0, 0, 0, 0, 148, 179711, 301034, 0, 0, 0, 0, 148, 179712, 301034, 3000, -29.1, -1.6, 0, 148, 179713, 301034, 3000, -29.1, -1.6, 0, 149, 179714, 301034, 3030, -29.1, -1.6, 0, 146, 179715, 301034, 6030, 0, 0, 0, 146,Once you have done all this, convert the csv file back to dbc and put it in the dbc folder of TrinityCore AS WELL AS in your custom patch using the MPQ Editor. 4.BPAG releaseAs you create animations, you will soon find out writing these rows is a tedious work. I have therefore written a tiny console tool which will write them for you (christened BPAG, an acronym for Basic Platform Animation Generator (the name is pretty cool but this piece of software is total bullshit )). You can download it here. You will need to feed the BPAG with several details, let me explain them to you. First ID : the ID (first column) of the last row of the TransportAnimation.dbc file PLUS one. gobGUID : the Guid of the gameobject you are using Start position : Coordinates of the starting point of your platform, X, Y, Z in order (E.G. 123 451 154) End Position : Coordinates of the return point of your platform, X, Y, Z in order (E.G. 123 451 154) Travel Time (ms) : The time that the platform will take to travel from the the starting point to the return point (in milliseconds). Pause Time (ms) : If you want your platform to stop at the starting position and at the return position (useful for elevators) (in milliseconds) Is it a two-speed platform ? (y/n) : Answer by y/Y (yes) or n/N (no). Two-speed platforms will speed up after some time interval. Speed ratio (if it is a two-speed platform) : If you want the platform to go 5 times faster after the previously mentioned time interval, input 5. Speed change time (ms) (if it is a two-speed platform) : Is the previously mentioned time interval in milliseconds Once you have provided the BPAG with all this, you will find the generated animation in output.txt (same directory as the .exe). You only have to paste that at the end of TransportAnimation.dbc.csv then convert it back to dbc.
  2. If the lua interface file appeared only in BFA I really think it makes sense it was hardcoded before. Looking into it as well.
  3. 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 ?
  4. 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.
  5. Could you also post your modification in spell.dbc ?
  6. 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.
  7. 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.
  8. Yeah Nagrand is my favorite zone too ! Hope you can emulate or even improve its feel. Keep us updated and keep it up
  9. 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.
  10. 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)
  11. 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; }
  12. 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.
  13. Roarl

    AuctionHouseBot

    Version 1.0

    158 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); } };
  15. Amazing work, keep it up !
  16. Oh, nothing serious. I think I spotted some typos in the F.A.Q. and in the description. Just corrected them.... Also added a quote of Amaroth in the F.A.Q so that the information given is relevant. I can PM you when I release the new models if you wanna.
  17. Hi dude, You need to provide a password in the Session Manager window of HeidiSQL (seen @ 0:44). You should be able to find it in the config files of your server (which I guess are located in the configs directory of Arcemu in your case). Once you get there look for something like LoginDatabaseInfo = "127.0.0.1;3306;root;ROOT;auth" WorldDatabaseInfo = "127.0.0.1;3306;root;ROOT;world" CharacterDatabaseInfo = "127.0.0.1;3306;root;ROOT;characters"In this example, root is the user and ROOT is the password. These lines are from TrinityCore but it should not be so different from Arcemu. Cheers
  18. Hi there! How do you access the (player) user of a gameobject? For instance, let us consider this simple gameobject script : class go_chairofjudgmentgood : public GameObjectScript { public: go_chairofjudgmentgood() : GameObjectScript("go_chairofjudgmentgood") { } struct go_chairofjudgmentgoodAI : public GameObjectAI { uint32 goTimer; go_chairofjudgmentgoodAI(GameObject* go) : GameObjectAI(go) {} void Reset() { goTimer = 7000; } void UpdateAI(uint32 diff) override { GameObjectAI::UpdateAI(diff); if (goTimer <= diff) { //HERE } else goTimer -= diff; } }; GameObjectAI * GetAI(GameObject * go) const { return new go_chairofjudgmentgoodAI(go); } };Let us assume the object type of the chairofjudgmentgood is indeed a chair. How could I get the Player (class) of the player sitting on the chair at line 23 (//HERE)? Thanks in advance for your help
  19. Haha I guess I made that mistake as well, and more than once. x) It's funny how it's always the small mistakes we fail to see!
  20. Hi there, Very very very very tiny (tiniest maybe?) release : a small macro (DOS) I'm using to start/stop mysql service on my computer. This saves me some time as I used to start it manually (I don't have a gargantuan computer, so... I can't afford to leave it running all the time if I wanna play/compile properly). Figured maybe some of you couldn't be fagged to do it (which I would understand) so maybe it'll be useful somehow. for /F "tokens=3 delims=: " %%H in ('sc query "MySQL56" ^| findstr " STATE"') do ( if /I "%%H" NEQ "RUNNING" ( net start "MySQL56" ) ELSE ( net stop "MySQL56" ) )(Don't forget to replace MYSQL56 by whatever version you are using ofc.) Cheers.
  21. Erm... solved. But before I tell how please promise you won't chop my head off... SOOOoooo... I built in Debug and was running the Release... =3 =3 (thanks anyway Kaev! / anyone who read this )
  22. Oops yes sorry it is gobject deletelast Exported the wrong line (just updated the original post)
  23. So sad and dramatic yet so pure. So empty yet so rich. Nicely done, perfect atmosphere for roleplay indeed, I FUCKING love it. (I have a thing for bleak / devastated landscapes =3 )
  24. Hi there! I added a command in cs_gobject.cpp, called "deletelast", which thus is a subcommand of "gobject". So, I added a ChatCommand in gobjectCommandTable : { "deletelast", rbac::RBAC_PERM_COMMAD_GOBJECT_DELETELAST, false, &HandleGameObjectDeleteLastCommand, "" },And the Handle is : static bool HandleGameObjectDeleteLastCommand(ChatHandler* handler, char const* args) { GameObject* object = NULL; // by DB guid Player* player = handler->GetSession()->GetPlayer(); Map* map = player->GetMap(); ObjectGuid::LowType guidLow = map->GenerateLowGuid<HighGuid::GameObject>() - 1; if (GameObjectData const* gameObjectData = sObjectMgr->GetGOData(guidLow)) object = handler->GetObjectGlobalyWithGuidOrNearWithDbGuid(guidLow, gameObjectData->id); if (!object) { handler->PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, guidLow); handler->SetSentErrorMessage(true); return false; } ObjectGuid ownerGuid = object->GetOwnerGUID(); if (ownerGuid) { Unit* owner = ObjectAccessor::GetUnit(*handler->GetSession()->GetPlayer(), ownerGuid); if (!owner || !ownerGuid.IsPlayer()) { handler->PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, ownerGuid.GetCounter(), object->GetGUID().GetCounter()); handler->SetSentErrorMessage(true); return false; } owner->RemoveGameObject(object, false); } object->SetRespawnTime(0); // not save respawn time object->Delete(); object->DeleteFromDB(); handler->PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, object->GetGUID().GetCounter()); return true; }I did create a permission in RBAC.h : RBAC_PERM_COMMAD_GOBJECT_DELETELAST = 1000,and I did create rows in auth's tables rbac_permissions and rbac_linked_permissions as well as in world's table commands. USE auth INSERT INTO `rbac_linked_permissions` VALUES (193, 1000); INSERT INTO `rbac_permissions` VALUES (1000, 'Command: gobject deletelast'); USE world INSERT INTO `command` VALUES ('gobject deletelast', 1000, 'Syntax: .gobject deletelast\r\nDelete last gobject in DB.'); Now, I have no problem with scripting the command itself. My problem is rather that the command doesn't even want to trigger. When I type ".gobject deletelast" in-game, TrinityCore World Server Daemon says : "Table 'command' have not existed subcommand 'deletelast' in command 'gobject deletelast', skip." . Would anyone know about what I did wrong here? Thanks in advance for your patience.
×
×
  • Create New...