Jump to content

NoFantasy

Members
  • Posts

    175
  • Joined

  • Last visited

    Never
  • Donations

    0.00 GBP 

Everything posted by NoFantasy

  1. 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. 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. This is not related to quest itself, this sounds more like server missing some update-packets. You won't find this in questhandler afaik.
  5. 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.
  6. It may not be a good idea to use online translators like http://tashian.com/multibabel/ In fact, online translators seem to only give you a rough translation, and in my experience you always have to fix up the translated text a bit. Ofc, if you have no clue about the output it may be a good idea to ask others for help in your native language somewhere else than here.
  7. Ahh! Ok, i will have that in mind next time, thanks for comment on that.
  8. Yes, you are right about the aura. However, the code is generic so it can be used for custom things and not necessarily this quest. Same result
  9. 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.
  10. 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;
  11. 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)
  12. Added sql to remove fields. They got lost in the process
  13. 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;
  14. 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.
  15. ...and what does "Is not working" mean? Socket/gems still messed up? Explain what you did. If you already ran the original SQL in 2008_12_22_19_characters_item_instance.sql then of course the SQL i posted "Is not working". That's why i said "grab your backup"
  16. 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.
  17. 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.
  18. Updated the initial query to " tinyint unsigned NOT NULL default '2' " to avoid all quests become autoComplete by default. 2 is the most common value so we should probably use this as default instead.
  19. 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++)
  20. 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;
  21. 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);
  22. 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
  23. I suggest you study this: http://wiki.udbforums.org/index.php/Quest_template#Examples It's the most updated i can think of at the moment. Btw, no support is given here at this forum for specifics of content.
  24. 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
  25. 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