Jump to content

Roarl

Members
  • Posts

    3
  • Joined

  • Last visited

Posts posted by Roarl

  1. Basic platform animations

    So, 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!

    WoWScrnShot_011416_173741.thumb.jpg.059a

    A. Requirements

    • DBCUtil ( 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 Editor
    • A TrinityCore server
    • A kebab skewer

    B. Table of Contents

    1. Creating the GameObject
    2. Getting TransportAnimation.dbc
    3. Editing TransportAnimation.dbc.csv
    4. BPAG release

    C. Tutorial

    1.Creating the GameObject

    Open 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.dbc

    If 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.csv

    After 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 release

    As 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. On 1/21/2019 at 8:47 AM, wungasaurus said:

    Have you tried to make sure it is the buff being the issue by changing the condition to something else, like your name or “true”? Are you sure that at the time of that calculation, auras are actually applied?

    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. 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.

     

    fBwHxS6.png

  4. 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)

  5. 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;
            }

     

  6. 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.

     

  7. 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);
        }
    };

     

  8. 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

  9. 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 :D

  10. 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. :)

  11. 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. :)

     

  12. I'm just really sad that there isn't a good studio recording of this version. It's absolutely beautiful. :D

    I recommend listening to more of this guy's stuff if you find the time. 

    Wow! This guy definitely has the look for this kind of song, haha!

    Like any pianist I enjoy piano covers... Especially the ones of Mercuzio, this guy is a genius.

    This one gets interesting at 0:50

    And second one is a pure marvel from the outset

     

×
×
  • Create New...