Jump to content

NoFantasy

Members
  • Posts

    175
  • Joined

  • Last visited

    Never
  • Donations

    0.00 GBP 

Posts posted by NoFantasy

  1. probably when spell script target is NPCs corpse it should be despawned after successful cast. I can't immagin situation where it should't happen.

    It start to get offtopic, but i also agree the patch is "wrong". Meaning, it's not wrong to remove corpse, but we must find a better way to determine when corpse must be removed instead of adding explicit RemoveCorpse() for each spellId that are expected to do it.

    A few similar examples where corpse always removed is when gathered (Skinned, Gathered (mining, herbalism, engineering, gas extraction)), so the theory about certain spells should also remove corpse if creature is dead is very likely.

    However, there are other spell that does not have implicitTargetA/B==38 that are also expected to remove corpse.

    I have made a small list of example spells (and a few notes) in http://www.scriptdev2.com/project.php?issueid=187

  2. Note that the Icon may change, even if it's the same npc flag. UNIT_NPC_FLAG_SPELLCLICK is a mechanical wheel by default i think, but for some creature_template.iconName are defined in addition. Some are for taxi master(npc supposed to take you from ground at map 609, up to "main city" for example), others may be for a vehicle. They all work in same way though (at least as far as i can tell); you click the npc (like any gossip, attack or whatever), client will send opcode, and Mangos should then handle the rest.

    I personally don't think using EventAI is ok here though, it's not some aggro event taking place. Like arrai explain, the most logical will be to create a link between creature entry and spell and check for the npc flag. It may be some conditions here. For example, when you are not on quest, should the "wheel" show? Probably not, the "lootable" mob should most likely act like any other, being attackackble.

  3. sounds like a scripting question?

    No, this is Mangos. This feature must be implemented before script library can (additionally) make any sort of script.

    GO's use a different system for this (for selection of textId's), but the gossip item / menus are same/very similar.

  4. Method doesn't have anything to do with quest objectives. Method=0 will simply make it so that client skip request the Details/Objectives text page, and go directly to RequestItemsText page.

    If you still haven't fulfilled the objectives of the quest (for example it has ReqItemIdN=1234) you still need to obtain that item.

  5. Feature: Add option to define quest required done for heroic mode instance in areatrigger_teleport.

    Revision: patch created with revision 7382(Master)

    Author: NoFantasy

    Info: Works in same way as current required_quest_done, just for the heroic mode instead. Example quest where this can be used is entry 11492.

    Patch:

    http://paste2.org/p/159162

    SQL:

    ALTER TABLE areatrigger_teleport
     ADD COLUMN required_quest_done_heroic int(11) unsigned NOT NULL default '0' AFTER required_quest_done;

    Can be ported to 0.12 branch too.

  6. Feature: Add field to define IconName in gameobject_template (same as IconName in creature_template)

    Revision: patch created with revision 7371(Master)

    Author: NoFantasy

    Info: This will add db-field to define the name of icon to be used instead of default icon for gameobject as expected for some GO's. "Attack" will for example make icon become a sword when hover over the gameobject instead of a 'wheel' (or whatever the default is for this type).

    Example data:

    UPDATE gameobject_template SET IconName='Attack' WHERE entry=192932;

    Patch:

    http://paste2.org/p/158669

    SQL:

    ALTER TABLE gameobject_template
     ADD COLUMN IconName varchar(100) NOT NULL default '' AFTER name;

  7. Feature: Add fields to define delay in quest_template DetailsEmote and OfferRewardEmote

    Revision: patch created with revision 7338(Master)

    Author: NoFantasy

    Info: This will add fields to define a delay-value for DetailsEmoteN and OfferRewardEmoteN -fields in quest_template. It will make emotes play more nice client-side when more than one is used for some emotes.

    Example data:

    UPDATE quest_template SET
    OfferRewardEmote1=1, OfferRewardEmote2=1, OfferRewardEmote3=1,
    OfferRewardEmoteDelay2=1000, OfferRewardEmoteDelay3=1000
    WHERE entry=8795;

    Patch:

    http://paste2.org/p/155593

    SQL:

    ALTER TABLE quest_template
     ADD COLUMN DetailsEmoteDelay1 int(11) unsigned NOT NULL default '0' AFTER DetailsEmote4,
     ADD COLUMN DetailsEmoteDelay2 int(11) unsigned NOT NULL default '0' AFTER DetailsEmoteDelay1,
     ADD COLUMN DetailsEmoteDelay3 int(11) unsigned NOT NULL default '0' AFTER DetailsEmoteDelay2,
     ADD COLUMN DetailsEmoteDelay4 int(11) unsigned NOT NULL default '0' AFTER DetailsEmoteDelay3,
     ADD COLUMN OfferRewardEmoteDelay1 int(11) unsigned NOT NULL default '0' AFTER OfferRewardEmote4,
     ADD COLUMN OfferRewardEmoteDelay2 int(11) unsigned NOT NULL default '0' AFTER OfferRewardEmoteDelay1,
     ADD COLUMN OfferRewardEmoteDelay3 int(11) unsigned NOT NULL default '0' AFTER OfferRewardEmoteDelay2,
     ADD COLUMN OfferRewardEmoteDelay4 int(11) unsigned NOT NULL default '0' AFTER OfferRewardEmoteDelay3;
    

    Edit: and one typo fixed in there (EnbleNext to EnableNext)

  8. Feature/adjustment: remove quest_template.ReqSourceRefN, adjust behavior of ReqSourceCountN

    Revision: patch created with revision 7302(Master)

    Author: NoFantasy

    Info: ReqSourceRef is considered to be obsolete. No examples can be found where ReqSourceId must be related to a specific quest objective. Instead, the ReqSourceId are related to quest status. Data also suggest ReqSourceId must be filled, even when no ReqItemId or ReqCreatureOrGoId exist as objectives.

    Simple version: if quest objective == QUEST_STATUS_INCOMPLETE then ReqSourceId are allowed to drop. In other cases, they are not (yes, bugs did indeed exist in earlier client versions where item dropped after, but this seem to be fixed in later versions).

    About new way of dealing with ReqSourceCount: Apart from the condition above, it also seem to be needless to define a amount of items that are allowed to drop. Instead, the amount allowed to drop can be determined by using item_template.maxcount/item_template.stackable.

    Example for this can be quest entry11523 where you need 4x item entry 34338 (this item are expected to be ReqSourceId). This item has maxcount==4, which will then be our limit. Player will never get this item in loot if he already has 4x. In case player complete the quest by using the 4x items, quest will change status and then item can no longer drop.

    For cases where item are not "unique", we allow items to drop, but use stackable as the limit.

    I have not been able to 100% determine if there are cases where item can drop _more_ than maxcount/stackable, that is the reason i've chosen to keep ReqSourceCount. This will also allow us to make custom data (normal case will in other words be ReqSourceCount=0).

    Patch too long to use code tags:

    http://paste2.org/p/153321

    ALTER TABLE quest_template
     DROP COLUMN ReqSourceRef1,
     DROP COLUMN ReqSourceRef2,
     DROP COLUMN ReqSourceRef3,
     DROP COLUMN ReqSourceRef4;
    

  9. The aggro sound played by mobs is actually MaNGOS controlled and uses a DBC file to figure out what sound op code to send to client (the mrgrrlglgl from murlocs for example).

    Not entirely correct, Mangos does not send anything but a notification about aggro, nothing read from any dbc, nor does it control anything except sending the below.

    bool Unit::Attack(Unit *victim, bool meleeAttack)
    ...
    ...
       if(GetTypeId()==TYPEID_UNIT)
       {
           WorldPacket data(SMSG_AI_REACTION, 12);
           data << uint64(GetGUID());
           data << uint32(AI_REACTION_AGGRO);                  // Aggro sound
           ((WorldObject*)this)->SendMessageToSet(&data, true);
    
           ((Creature*)this)->CallAssistance();
           ((Creature*)this)->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
       }

    When client receive this, it select sound and plays it all by itself, all out of Mangos' control.

  10. Grab your backup and try replace the related SQL in 2008_12_22_19_characters_item_instance.sql with:

    UPDATE item_instance SET data= CONCAT(
     SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',54),' ',-54),' 0 0 0 ',
     SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',60),' ',-60+54),' 0 ')
    WHERE SUBSTRING_INDEX(data,' ',60) = data AND SUBSTRING_INDEX(data,' ',60-1) <> data;

    I can not verify it's correct, however i see for my test characters the problem is gone regarding gems/sockets. Some more tests will perhaps tell what would be a better way to solve it.

  11. I can confirm there is a problem with gems, but you really need to explain more in detail for it to make any sense.

    If you are not able to, here are some:

    Case: character from 2.4.3 exist, having entries in item_instance. Run 2008_12_22_19_characters_item_instance.sql will update the data fields for items. This seem to be ok, however:

    After logging in, your itemX (let's say item_template has 2 sockets, socket1=red, socket2=yellow) will have socket1 filled with the red, socket2 empty and socket3 filled with the yellow. ItemX does not really have a socket3, but in both database and client side this will still show _and_ be applied to the stats.

    Also it should be noted that you are able to fill socket2 wih a new gem, without loosing the one in socket3.

  12. Restore work of display Required Money: If quest require money to complete, then we display the amount in "RequestItems" quest window.

    Revision: 6670+ (patch made for 6670)

    Who made it: NoFantasy

    Info: It used to work so i assume it just got mixed up at a point. If RewOrReqMoney is negative then the amount needed to continue will be displayed.

    Patch:

    Index: src/game/GossipDef.cpp
    ===================================================================
    --- src/game/GossipDef.cpp        (revision 6670)
    +++ src/game/GossipDef.cpp        (working copy)
    @@ -721,11 +721,11 @@
            else
                    data << uint32(0x00);
    
    +        data << uint32(0x00);                                                                     // unknown
    +
            // Required Money
            data << uint32(pQuest->GetRewOrReqMoney() < 0 ? -pQuest->GetRewOrReqMoney() : 0);
    
    -        data << uint32(0x00);                                                                     // unknown
    -
            data << uint32( pQuest->GetReqItemsCount() );
            ItemPrototype const *pItem;
            for (int i = 0; i < QUEST_OBJECTIVES_COUNT; i++)

  13. Implement use of "Method" for quest: quest_template.Method a more clear way to determine IsAutoComplete()

    Revision: 6670+ (patch made for 6670)

    Who made it: NoFantasy

    Info: The field "Method" is data in client wdb. This has three (known) values. 0, 1 or 2. It is clear that Method=0 is used for quests where it's expected the client should "skip" Objectives and go directly to RequestItemsText or in case empty only show OfferRewardText. Current way of determine this is not fully correct. Examples of this is quest id 349 and 11442. Both have text like [PH] and temp, but should never show to player. Ofc, it can be simple to remove such text to achieve the IsAutoComplete() function, however by implementing Method, the two remaining values may be implemented and handeled later. It is not know what 1 and 2 stands for (2 are used for the vaste majority of quests).

    Have in mind if proper data are not present, all quests will act as if they was all AutoComplete. Data are posted at other forum (db-project udb) for those interested and can help review patch for correctness.

    Side note 1: patch also removes comments from sLog.outDebug(). We have outDebug for a reason so i suggest use them :)

    Side note 2: a small re-definition of QuestFlags|2 Name this QUEST_FLAGS_PARTY_ACCEPT (part of patch are in progress). See note about this redefinition in patch comments.

    Patch:

    Index: sql/updates/xxxx_mangos_quest_template.sql
    ===================================================================
    --- sql/updates/xxxx_mangos_quest_template.sql        (revision 0)
    +++ sql/updates/xxxx_mangos_quest_template.sql        (revision 0)
    @@ -0,0 +1 @@
    +ALTER TABLE `quest_template` ADD COLUMN `Method` tinyint unsigned NOT NULL default '2' AFTER `entry`;
    
    Property changes on: sql\\updates\\xxxx_mangos_quest_template.sql
    ___________________________________________________________________
    Name: svn:eol-style
        + native
    
    Index: src/game/GossipDef.cpp
    ===================================================================
    --- src/game/GossipDef.cpp        (revision 6670)
    +++ src/game/GossipDef.cpp        (working copy)
    @@ -382,7 +382,7 @@
            data << uint8(questStatus);
    
            pSession->SendPacket( &data );
    -        //sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC Guid=%u, status=%u",GUID_LOPART(npcGUID),questStatus);
    +        sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC Guid=%u, status=%u",GUID_LOPART(npcGUID),questStatus);
    }
    
    void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID, bool ActivateAccept )
    @@ -468,7 +468,7 @@
            }
            pSession->SendPacket( &data );
    
    -        //sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId());
    +        sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId());
    }
    
    void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
    @@ -506,7 +506,7 @@
            WorldPacket data( SMSG_QUEST_QUERY_RESPONSE, 100 );         // guess size
    
            data << uint32(pQuest->GetQuestId());
    -        data << uint32(pQuest->GetMinLevel());                                    // not MinLevel. Accepted values: 0, 1 or 2 Possible theory for future dev: 0==cannot in quest log, 1==can in quest log session only(removed on log out), 2==can in quest log always (save to db)
    +        data << uint32(pQuest->GetQuestMethod());                             // Accepted values: 0, 1 or 2. 0==IsAutoComplete() (skip objectives/details)
            data << uint32(pQuest->GetQuestLevel());                                // may be 0
            data << uint32(pQuest->GetZoneOrSort());                                // zone or sort to display in quest log
    
    @@ -588,7 +588,7 @@
                    data << ObjectiveText[iI];
    
            pSession->SendPacket( &data );
    -        //sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u",pQuest->GetQuestId() );
    +        sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u",pQuest->GetQuestId() );
    }
    
    void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID, bool EnbleNext )
    @@ -670,7 +670,7 @@
            data << uint32(pQuest->GetRewSpellCast());                            // casted spell
            data << uint32(0);                                                                            // Honor points reward, not implemented
            pSession->SendPacket( &data );
    -        //sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() );
    +        sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() );
    }
    
    void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel )
    @@ -749,5 +749,5 @@
            data << uint32(0x04) << uint32(0x08) << uint32(0x10);
    
            pSession->SendPacket( &data );
    -        //sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() );
    +        sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() );
    }
    Index: src/game/ObjectMgr.cpp
    ===================================================================
    --- src/game/ObjectMgr.cpp        (revision 6670)
    +++ src/game/ObjectMgr.cpp        (working copy)
    @@ -2690,35 +2690,35 @@
    
            mExclusiveQuestGroups.clear();
    
    -        //                                                                                                0            1                     2                         3                 4                     5         6                            7
    -        QueryResult *result = WorldDatabase.Query("SELECT entry, ZoneOrSort, SkillOrClass, MinLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue,"
    -        //     8                                        9                                    10                                         11                                     12                                         13                                     14                                15
    +        //                                                                                                0            1             2                     3                         4                 5                     6         7                            8
    +        QueryResult *result = WorldDatabase.Query("SELECT entry, Method, ZoneOrSort, SkillOrClass, MinLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue,"
    +        //     9                                        10                                 11                                         12                                     13                                         14                                     15                                16
                    "RepObjectiveFaction, RepObjectiveValue, RequiredMinRepFaction, RequiredMinRepValue, RequiredMaxRepFaction, RequiredMaxRepValue, SuggestedPlayers, LimitTime,"
    -        //     16                    17                        18                     19                     20                     21                            22                                23                 24                        25
    +        //     17                    18                        19                     20                     21                     22                            23                                24                 25                        26
                    "QuestFlags, SpecialFlags, CharTitleId, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell,"
    -        //     26         27             28                    29                             30                                31             32                            33                            34                            35
    +        //     27         28             29                    30                             31                                32             33                            34                            35                            36
                    "Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4,"
    -        //     36                    37                    38                    39                    40                         41                         42                         43
    +        //     37                    38                    39                    40                    41                         42                         43                         44
                    "ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4,"
    -        //     44                        45                        46                        47                        48                             49                             50                             51                             52                         53                         54                         55
    +        //     45                        46                        47                        48                        49                             50                             51                             52                             53                         54                         54                         55
                    "ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4, ReqSourceRef1, ReqSourceRef2, ReqSourceRef3, ReqSourceRef4,"
    -        //     56                                    57                                    58                                    59                                    60                                         61                                         62                                         63
    +        //     57                                    58                                    59                                    60                                    61                                         62                                         63                                         64
                    "ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4,"
    -        //     64                         65                         66                         67
    +        //     65                         66                         67                         68
                    "ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4,"
    -        //     68                                69                                70                                71                                72                                73
    +        //     69                                70                                71                                72                                73                                74
                    "RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6,"
    -        //     74                                     75                                     76                                     77                                     78                                     79
    +        //     75                                     76                                     77                                     78                                     79                                     80
                    "RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6,"
    -        //     80                    81                    82                    83                    84                         85                         86                         87
    +        //     81                    82                    83                    84                    85                         86                         87                         88
                    "RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4,"
    -        //     88                            89                            90                            91                            92                            93                        94                        95                        96                        97
    +        //     89                            90                            91                            92                            93                            94                        95                        96                        97                        98
                    "RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5,"
    -        //     98                         99                                100             101                     102                                103                             104                 105         106         107
    +        //     99                         100                             101             102                     103                                104                             105                 106         107         108
                    "RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt,"
    -        //     108                        109                        110                        111                     112                            113                        114                                115                                116                                117
    +        //     109                        110                        111                        112                     113                            114                        115                                116                                117                                118
                    "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4,IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4,"
    -        //     118                    119
    +        //     119                    120
                    "StartScript, CompleteScript"
                    " FROM quest_template");
            if(result == NULL)
    @@ -2754,6 +2754,11 @@
    
                    // additional quest integrity checks (GO, creature_template and item_template must be loaded already)
    
    +                if( qinfo->GetQuestMethod() >= 3 )
    +                {
    +                        sLog.outErrorDb("Quest %u has `Method` = %u, expected values are 0, 1 or 2.",qinfo->GetQuestId(),qinfo->GetQuestMethod());
    +                }
    +
                    if (qinfo->QuestFlags & ~QUEST_MANGOS_FLAGS_DB_ALLOWED)
                    {
                            sLog.outErrorDb("Quest %u has `SpecialFlags` = %u > max allowed value. Correct `SpecialFlags` to value <= %u",
    Index: src/game/QuestDef.cpp
    ===================================================================
    --- src/game/QuestDef.cpp        (revision 6670)
    +++ src/game/QuestDef.cpp        (working copy)
    @@ -23,105 +23,106 @@
    Quest::Quest(Field * questRecord)
    {
            QuestId = questRecord[0].GetUInt32();
    -        ZoneOrSort = questRecord[1].GetInt32();
    -        SkillOrClass = questRecord[2].GetInt32();
    -        MinLevel = questRecord[3].GetUInt32();
    -        QuestLevel = questRecord[4].GetUInt32();
    -        Type = questRecord[5].GetUInt32();
    -        RequiredRaces = questRecord[6].GetUInt32();
    -        RequiredSkillValue = questRecord[7].GetUInt32();
    -        RepObjectiveFaction = questRecord[8].GetUInt32();
    -        RepObjectiveValue = questRecord[9].GetInt32();
    -        RequiredMinRepFaction = questRecord[10].GetUInt32();
    -        RequiredMinRepValue = questRecord[11].GetInt32();
    -        RequiredMaxRepFaction = questRecord[12].GetUInt32();
    -        RequiredMaxRepValue = questRecord[13].GetInt32();
    -        SuggestedPlayers = questRecord[14].GetUInt32();
    -        LimitTime = questRecord[15].GetUInt32();
    -        QuestFlags = questRecord[16].GetUInt16();
    -        uint32 SpecialFlags = questRecord[17].GetUInt16();
    -        CharTitleId = questRecord[18].GetUInt32();
    -        PrevQuestId = questRecord[19].GetInt32();
    -        NextQuestId = questRecord[20].GetInt32();
    -        ExclusiveGroup = questRecord[21].GetInt32();
    -        NextQuestInChain = questRecord[22].GetUInt32();
    -        SrcItemId = questRecord[23].GetUInt32();
    -        SrcItemCount = questRecord[24].GetUInt32();
    -        SrcSpell = questRecord[25].GetUInt32();
    -        Title = questRecord[26].GetCppString();
    -        Details = questRecord[27].GetCppString();
    -        Objectives = questRecord[28].GetCppString();
    -        OfferRewardText = questRecord[29].GetCppString();
    -        RequestItemsText = questRecord[30].GetCppString();
    -        EndText = questRecord[31].GetCppString();
    +        QuestMethod = questRecord[1].GetUInt32();
    +        ZoneOrSort = questRecord[2].GetInt32();
    +        SkillOrClass = questRecord[3].GetInt32();
    +        MinLevel = questRecord[4].GetUInt32();
    +        QuestLevel = questRecord[5].GetUInt32();
    +        Type = questRecord[6].GetUInt32();
    +        RequiredRaces = questRecord[7].GetUInt32();
    +        RequiredSkillValue = questRecord[8].GetUInt32();
    +        RepObjectiveFaction = questRecord[9].GetUInt32();
    +        RepObjectiveValue = questRecord[10].GetInt32();
    +        RequiredMinRepFaction = questRecord[11].GetUInt32();
    +        RequiredMinRepValue = questRecord[12].GetInt32();
    +        RequiredMaxRepFaction = questRecord[13].GetUInt32();
    +        RequiredMaxRepValue = questRecord[14].GetInt32();
    +        SuggestedPlayers = questRecord[15].GetUInt32();
    +        LimitTime = questRecord[16].GetUInt32();
    +        QuestFlags = questRecord[17].GetUInt16();
    +        uint32 SpecialFlags = questRecord[18].GetUInt16();
    +        CharTitleId = questRecord[19].GetUInt32();
    +        PrevQuestId = questRecord[20].GetInt32();
    +        NextQuestId = questRecord[21].GetInt32();
    +        ExclusiveGroup = questRecord[22].GetInt32();
    +        NextQuestInChain = questRecord[23].GetUInt32();
    +        SrcItemId = questRecord[24].GetUInt32();
    +        SrcItemCount = questRecord[25].GetUInt32();
    +        SrcSpell = questRecord[26].GetUInt32();
    +        Title = questRecord[27].GetCppString();
    +        Details = questRecord[28].GetCppString();
    +        Objectives = questRecord[29].GetCppString();
    +        OfferRewardText = questRecord[30].GetCppString();
    +        RequestItemsText = questRecord[31].GetCppString();
    +        EndText = questRecord[32].GetCppString();
    
            for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
    -                ObjectiveText[i] = questRecord[32+i].GetCppString();
    +                ObjectiveText[i] = questRecord[33+i].GetCppString();
    
            for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
    -                ReqItemId[i] = questRecord[36+i].GetUInt32();
    +                ReqItemId[i] = questRecord[37+i].GetUInt32();
    
            for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
    -                ReqItemCount[i] = questRecord[40+i].GetUInt32();
    +                ReqItemCount[i] = questRecord[41+i].GetUInt32();
    
            for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
    -                ReqSourceId[i] = questRecord[44+i].GetUInt32();
    +                ReqSourceId[i] = questRecord[45+i].GetUInt32();
    
            for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
    -                ReqSourceCount[i] = questRecord[48+i].GetUInt32();
    +                ReqSourceCount[i] = questRecord[49+i].GetUInt32();
    
            for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
    -                ReqSourceRef[i] = questRecord[52+i].GetUInt32();
    +                ReqSourceRef[i] = questRecord[53+i].GetUInt32();
    
            for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
    -                ReqCreatureOrGOId[i] = questRecord[56+i].GetInt32();
    +                ReqCreatureOrGOId[i] = questRecord[57+i].GetInt32();
    
            for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
    -                ReqCreatureOrGOCount[i] = questRecord[60+i].GetUInt32();
    +                ReqCreatureOrGOCount[i] = questRecord[61+i].GetUInt32();
    
            for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
    -                ReqSpell[i] = questRecord[64+i].GetUInt32();
    +                ReqSpell[i] = questRecord[65+i].GetUInt32();
    
            for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
    -                RewChoiceItemId[i] = questRecord[68+i].GetUInt32();
    +                RewChoiceItemId[i] = questRecord[69+i].GetUInt32();
    
            for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
    -                RewChoiceItemCount[i] = questRecord[74+i].GetUInt32();
    +                RewChoiceItemCount[i] = questRecord[75+i].GetUInt32();
    
            for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
    -                RewItemId[i] = questRecord[80+i].GetUInt32();
    +                RewItemId[i] = questRecord[81+i].GetUInt32();
    
            for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
    -                RewItemCount[i] = questRecord[84+i].GetUInt32();
    +                RewItemCount[i] = questRecord[85+i].GetUInt32();
    
            for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
    -                RewRepFaction[i] = questRecord[88+i].GetUInt32();
    +                RewRepFaction[i] = questRecord[89+i].GetUInt32();
    
            for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
    -                RewRepValue[i] = questRecord[93+i].GetInt32();
    +                RewRepValue[i] = questRecord[94+i].GetInt32();
    
    -        RewOrReqMoney = questRecord[98].GetInt32();
    -        RewMoneyMaxLevel = questRecord[99].GetUInt32();
    -        RewSpell = questRecord[100].GetUInt32();
    -        RewSpellCast = questRecord[101].GetUInt32();
    -        RewMailTemplateId = questRecord[102].GetUInt32();
    -        RewMailDelaySecs = questRecord[103].GetUInt32();
    -        PointMapId = questRecord[104].GetUInt32();
    -        PointX = questRecord[105].GetFloat();
    -        PointY = questRecord[106].GetFloat();
    -        PointOpt = questRecord[107].GetUInt32();
    +        RewOrReqMoney = questRecord[99].GetInt32();
    +        RewMoneyMaxLevel = questRecord[100].GetUInt32();
    +        RewSpell = questRecord[101].GetUInt32();
    +        RewSpellCast = questRecord[102].GetUInt32();
    +        RewMailTemplateId = questRecord[103].GetUInt32();
    +        RewMailDelaySecs = questRecord[104].GetUInt32();
    +        PointMapId = questRecord[105].GetUInt32();
    +        PointX = questRecord[106].GetFloat();
    +        PointY = questRecord[107].GetFloat();
    +        PointOpt = questRecord[108].GetUInt32();
    
            for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
    -                DetailsEmote[i] = questRecord[108+i].GetUInt32();
    +                DetailsEmote[i] = questRecord[109+i].GetUInt32();
    
    -        IncompleteEmote = questRecord[112].GetUInt32();
    -        CompleteEmote = questRecord[113].GetUInt32();
    +        IncompleteEmote = questRecord[113].GetUInt32();
    +        CompleteEmote = questRecord[114].GetUInt32();
    
            for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
    -                OfferRewardEmote[i] = questRecord[114+i].GetInt32();
    +                OfferRewardEmote[i] = questRecord[115+i].GetInt32();
    
    -        QuestStartScript = questRecord[118].GetUInt32();
    -        QuestCompleteScript = questRecord[119].GetUInt32();
    +        QuestStartScript = questRecord[119].GetUInt32();
    +        QuestCompleteScript = questRecord[120].GetUInt32();
    
            QuestFlags |= SpecialFlags << 16;
    
    Index: src/game/QuestDef.h
    ===================================================================
    --- src/game/QuestDef.h        (revision 6670)
    +++ src/game/QuestDef.h        (working copy)
    @@ -114,7 +114,7 @@
    {
            // Flags used at server and sended to client
            QUEST_FLAGS_STAY_ALIVE         = 1,                                                 // Not used currently
    -        QUEST_FLAGS_EVENT                    = 2,                                                 // Not used currently
    +        QUEST_FLAGS_PARTY_ACCEPT     = 2,                                                 // Not used currently. If player in party, all players that can accept this quest will receive confirmation box to accept quest CMSG_QUEST_CONFIRM_ACCEPT/SMSG_QUEST_CONFIRM_ACCEPT
            QUEST_FLAGS_EXPLORATION        = 4,                                                 // Not used currently
            QUEST_FLAGS_SHARABLE             = 8,                                                 // Can be shared: Player::CanShareQuest()
            //QUEST_FLAGS_NONE2                = 16,                                                // Not used currently
    @@ -167,6 +167,7 @@
    
                    // table data accessors:
                    uint32 GetQuestId() const { return QuestId; }
    +                uint32 GetQuestMethod() const { return QuestMethod; }
                    int32    GetZoneOrSort() const { return ZoneOrSort; }
                    int32    GetSkillOrClass() const { return SkillOrClass; }
                    uint32 GetMinLevel() const { return MinLevel; }
    @@ -212,7 +213,7 @@
                    uint32 GetQuestStartScript() const { return QuestStartScript; }
                    uint32 GetQuestCompleteScript() const { return QuestCompleteScript; }
                    bool     IsRepeatable() const { return QuestFlags & QUEST_MANGOS_FLAGS_REPEATABLE; }
    -                bool     IsAutoComplete() const { return Objectives.empty(); }
    +                bool     IsAutoComplete() const { return QuestMethod ? false : true; }
                    uint32 GetFlags() const { return QuestFlags; }
                    bool     IsDaily() const { return QuestFlags & QUEST_FLAGS_DAILY; }
    
    @@ -255,6 +256,7 @@
                    // table data
            protected:
                    uint32 QuestId;
    +                uint32 QuestMethod;
                    int32    ZoneOrSort;
                    int32    SkillOrClass;
                    uint32 MinLevel;

  14. Implement two chat options: CHAT_MSG_RAID_BOSS_EMOTE and CHAT_MSG_RAID_BOSS_WHISPER

    Revision: 6541+ (patch made for 6541)

    Who made it: NoFantasy

    Info: if the optional bool=true, text will display as yellow text on screen and in addition in chat log. I chose to use already existing functions since i _think_ the packet will look the same for these two. From script it can be tested using creature->MonsterTextEmote("does the happy dance.",0,true);

    Patch:

    Index: src/game/Creature.h
    ===================================================================
    --- src/game/Creature.h        (revision 6541)
    +++ src/game/Creature.h        (working copy)
    @@ -464,8 +464,8 @@
                    void setEmoteState(uint8 emote) { m_emoteState = emote; };
                    void Say(const char* text, const uint32 language, const uint64 TargetGuid) { MonsterSay(text,language,TargetGuid); }
                    void Yell(const char* text, const uint32 language, const uint64 TargetGuid) { MonsterYell(text,language,TargetGuid); }
    -                void TextEmote(const char* text, const uint64 TargetGuid) { MonsterTextEmote(text,TargetGuid); }
    -                void Whisper(const uint64 receiver, const char* text) { MonsterWhisper(receiver,text); }
    +                void TextEmote(const char* text, const uint64 TargetGuid, bool IsBossEmote = false) { MonsterTextEmote(text,TargetGuid,IsBossEmote); }
    +                void Whisper(const uint64 receiver, const char* text, bool IsBossWhisper = false) { MonsterWhisper(receiver,text,IsBossWhisper); }
    
                    void setDeathState(DeathState s);                                     // overwrite virtual Unit::setDeathState
    
    Index: src/game/Object.cpp
    ===================================================================
    --- src/game/Object.cpp        (revision 6541)
    +++ src/game/Object.cpp        (working copy)
    @@ -1177,13 +1177,13 @@
            SendMessageToSet(&data, true);
    }
    
    -void WorldObject::MonsterTextEmote(const char* text, const uint64 TargetGuid)
    +void WorldObject::MonsterTextEmote(const char* text, const uint64 TargetGuid, bool IsBossEmote)
    {
            std::string rightText = "%s ";
            rightText.append(text);
    
            WorldPacket data(SMSG_MESSAGECHAT, 200);
    -        data << (uint8)CHAT_MSG_MONSTER_EMOTE;
    +        data << (uint8)(IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE);
            data << (uint32)LANG_UNIVERSAL;
            data << (uint64)GetGUID();                                                            // 2.1.0
            data << (uint32)0;                                                                            // 2.1.0
    @@ -1202,10 +1202,10 @@
            SendMessageToSet(&data, true);                                                    // SendMessageToOwnTeamSet()?
    }
    
    -void WorldObject::MonsterWhisper(const uint64 receiver, const char* text)
    +void WorldObject::MonsterWhisper(const uint64 receiver, const char* text, bool IsBossWhisper)
    {
            WorldPacket data(SMSG_MESSAGECHAT, 200);
    -        data << (uint8)CHAT_MSG_MONSTER_WHISPER;
    +        data << (uint8)(IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER);
            data << (uint32)LANG_UNIVERSAL;
            data << (uint64)GetGUID();
            data << (uint32)0;                                                                            //unk1
    Index: src/game/Object.h
    ===================================================================
    --- src/game/Object.h        (revision 6541)
    +++ src/game/Object.h        (working copy)
    @@ -416,8 +416,8 @@
    
                    void MonsterSay(const char* text, const uint32 language, const uint64 TargetGuid);
                    void MonsterYell(const char* text, const uint32 language, const uint64 TargetGuid);
    -                void MonsterTextEmote(const char* text, const uint64 TargetGuid);
    -                void MonsterWhisper(const uint64 receiver, const char* text);
    +                void MonsterTextEmote(const char* text, const uint64 TargetGuid, bool IsBossEmote = false);
    +                void MonsterWhisper(const uint64 receiver, const char* text, bool IsBossWhisper = false);
    
                    void SendObjectDeSpawnAnim(uint64 guid);

  15. Implement two more log options for script library: Consider it implementing the basic log options for ScriptLibrary

    Revision: 6528+ (patch made for 6528)

    Bug report: None

    Who made it: NoFantasy

    Info: especially the log option error_db_log will prove to become useful. SL already has the option to have database on it's own and in my opinion errors related to database should not just only display in console as they would be hard to find. It's expected SL will use proper prefix in errors and include data (such as table name, fields) to make the error clear.

    Patch:

    Index: src/shared/Log.cpp
    ===================================================================
    --- src/shared/Log.cpp        (revision 6528)
    +++ src/shared/Log.cpp        (working copy)
    @@ -705,6 +705,20 @@
            MaNGOS::Singleton<Log>::Instance().outString(buf);
    }
    
    +void detail_log(const char * str, ...)
    +{
    +        if( !str )
    +                return;
    +
    +        char buf[256];
    +        va_list ap;
    +        va_start(ap, str);
    +        vsnprintf(buf,256, str, ap);
    +        va_end(ap);
    +
    +        MaNGOS::Singleton<Log>::Instance().outDetail(buf);
    +}
    +
    void debug_log(const char * str, ...)
    {
            if( !str )
    @@ -732,3 +746,17 @@
    
            MaNGOS::Singleton<Log>::Instance().outError(buf);
    }
    +
    +void error_db_log(const char * str, ...)
    +{
    +        if( !str )
    +                return;
    +
    +        char buf[256];
    +        va_list ap;
    +        va_start(ap, str);
    +        vsnprintf(buf,256, str, ap);
    +        va_end(ap);
    +
    +        MaNGOS::Singleton<Log>::Instance().outErrorDb(buf);
    +}
    Index: src/shared/Log.h
    ===================================================================
    --- src/shared/Log.h        (revision 6528)
    +++ src/shared/Log.h        (working copy)
    @@ -147,6 +147,8 @@
    
    // primary for script library
    void MANGOS_DLL_SPEC outstring_log(const char * str, ...) ATTR_PRINTF(1,2);
    +void MANGOS_DLL_SPEC detail_log(const char * str, ...) ATTR_PRINTF(1,2);
    void MANGOS_DLL_SPEC debug_log(const char * str, ...) ATTR_PRINTF(1,2);
    void MANGOS_DLL_SPEC error_log(const char * str, ...) ATTR_PRINTF(1,2);
    +void MANGOS_DLL_SPEC error_db_log(const char * str, ...) ATTR_PRINTF(1,2);
    #endif

  16. Implement QuestFlags 1024: Quests with QuestFlags|1024 should never end up in client quest log and they are expected to be automatically rewarded.

    Revision: 6480+ (patch made for 6480)

    Bug report: None found, but possibly exist

    Who made it: NoFantasy

    Info: Not many quests have this flag, however the few having this flag are causing issues. Normally a spell with effect16 is used to complete these quests. They all share the same thing, they are expected to work as flag quests, or a dummy quest if you like. Mostly used to "unlock" other quests or simply a check being used in instance attunements.

    Example: Three different quests are possible to complete and give attunement to map 533 (old school raid instance). All three will reward player with spell 28006. This spell are expected to trigger spell 29294 (CompleteQuest(9378)). Quest 9378 has QuestFlags|1024. This quest has no real objectives, and from what we know only being used as a check to see if player has completed one of the three attunement quests required to enter instance.

    We must make sure this quest will not end up in client quest log and we must also make sure this quest are automatically rewarded in database.

    Patch:

    Index: src/game/Player.cpp
    ===================================================================
    --- src/game/Player.cpp        (revision 6480)
    +++ src/game/Player.cpp        (working copy)
    @@ -11708,11 +11708,22 @@
            {
                    SetQuestStatus( quest_id, QUEST_STATUS_COMPLETE );
    
    -                uint16 log_slot = FindQuestSlot( quest_id );
    -                if( log_slot < MAX_QUEST_LOG_SIZE)
    -                        SetQuestSlotState(log_slot,QUEST_STATE_COMPLETE);
    +                Quest const* qInfo = objmgr.GetQuestTemplate(quest_id);
    +                if( qInfo )
    +                {
    +                        if( qInfo->HasFlag(QUEST_FLAGS_AUTO_REWARDED) )
    +                        {
    +                                mQuestStatus[quest_id].m_rewarded = true;
    +                        }
    +                        else
    +                        {
    +                                uint16 log_slot = FindQuestSlot( quest_id );
    +                                if( log_slot < MAX_QUEST_LOG_SIZE)
    +                                        SetQuestSlotState(log_slot,QUEST_STATE_COMPLETE);
    
    -                SendQuestComplete( quest_id );
    +                                SendQuestComplete( quest_id );
    +                        }
    +                }
            }
    }
    
    Index: src/game/QuestDef.h
    ===================================================================
    --- src/game/QuestDef.h        (revision 6480)
    +++ src/game/QuestDef.h        (working copy)
    @@ -123,7 +123,7 @@
            QUEST_FLAGS_TBC                        = 128,                                             // Not used currently: Available if TBC expension enabled only
            QUEST_FLAGS_UNK2                     = 256,                                             // Not used currently: _DELIVER_MORE Quest needs more than normal _q-item_ drops from mobs
            QUEST_FLAGS_HIDDEN_REWARDS = 512,                                             // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
    -        QUEST_FLAGS_UNK4                     = 1024,                                            // Not used currently: Unknown tbc flag
    +        QUEST_FLAGS_AUTO_REWARDED    = 1024,                                            // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
            QUEST_FLAGS_TBC_RACES            = 2048,                                            // Not used currently: Bloodelf/draenei starting zone quests
            QUEST_FLAGS_DAILY                    = 4096,                                            // Used to know quest is Daily one

  17. Bug: When reputation with faction is objective of quest, quest will not complete when reaching the required value (example: qId 1385).

    Patch: Tested for rev 5491/5538. Patch will check if any quests can be completed when gaining reputation with any faction.

    Who: NoFantasy

    Info: Unsure if this is correct place to do this check.

    Index: src/game/Player.cpp
    ===================================================================
    --- src/game/Player.cpp        (revision 5538)
    +++ src/game/Player.cpp        (working copy)
    @@ -5379,7 +5379,34 @@
                    itr->second.Flags |= FACTION_FLAG_VISIBLE;
                    itr->second.Changed = true;
    
    +                uint32 questid;
    +                for( int i = 0; i < MAX_QUEST_LOG_SIZE; i++ )
    +                {
    +                        questid = GetUInt32Value(PLAYER_QUEST_LOG_1_1 + 3*i);
    +                        if ( questid != 0 )
    +                        {
    +                                Quest const* qInfo = objmgr.GetQuestTemplate(questid);
    +                                if( qInfo && qInfo->GetRepObjectiveFaction() == factionEntry->ID )
    +                                {
    +                                        if( mQuestStatus[questid].m_status == QUEST_STATUS_INCOMPLETE )
    +                                        {
    +                                                if(GetReputation(factionEntry) >= qInfo->GetRepObjectiveValue())
    +                                                {
    +                                                        if ( CanCompleteQuest( questid ) )
    +                                                                CompleteQuest( questid );
    +                                                }
    +                                        }
    +                                        else if( mQuestStatus[questid].m_status == QUEST_STATUS_COMPLETE )
    +                                        {
    +                                                if(GetReputation(factionEntry) < qInfo->GetRepObjectiveValue())
    +                                                        IncompleteQuest( questid );
    +                                        }
    +                                }
    +                        }
    +                }
    +
                    SendSetFactionStanding(&(itr->second));
    +
                    return true;
            }
            return false;

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use