- // Error Types
- enum msg_type {
- MSG_NONE,
- MSG_STATUS,
- MSG_SQL,
- MSG_INFO,
- MSG_NOTICE,
- MSG_WARNING,
- MSG_DEBUG,
- MSG_ERROR,
- MSG_FATALERROR,
- MSG_HACK,
- MSG_LOAD,
- MSG_SDEBUG,
- MSG_GMACTION,
- MSG_START,
- MSG_QUERY,
- MSG_CONSOLE,
- MSG_QUESTDEBUG
- };
I would define MSG_QUESTDEBUG myself if I knew how. :-S
Soooo I tried a mix of your code and the one I had in there, but of course it then does more errors.
OOPSY Sorry about that
The MSG_QUESTDEBUG option is something I just added.
If you would like to add it for yourself you can do it very easily. Here is how
first go to Log.h and find this code
Of course you won't have MSG_QUESTDEBUG at the bottom of your list so add it
Then you need to go into Log.cpp and find some code that looks like this
- case MSG_LOAD:
- textcolor(BROWN);
- sprintf(msgtype,"%s","[LOADING]: ");
- printf("%s",msgtype);
- break;
- case MSG_GMACTION:
- textcolor(MAGENTA);
- sprintf(msgtype,"%s","[GM ACTION]: ");
- printf("%s",msgtype);
- break;
- case MSG_QUESTDEBUG:
- textcolor(LIGHTBLUE);
- sprintf(msgtype,"%s","[QUEST DEBUG]: ");
- printf("%s",msgtype);
- break;
It's just a long list of case statements. I've only shown the last few here, including the one I added to the bottom to output log messages for MSG_QUESTDEBUG
I just wanted my quest debugging to stand out from the rest of the messages in the console
Yes, I see the quest window do not show the proof of exterminations.
Still investigating things.
When I logged off, then back in, I got the reward (it seems) for the 10 Flanae quest, and the quest is gone from my list, while this didn't happen while I was killing the Flanae in the first place.
The thing is that the server is crediting you with the proof of extermination but the client is never receiving instructions to display it as it happens. Basically, the correct packet is not being sent. When you log back in, the data that the server already has is sent to the client and it's all good again.
In order to fix it we have to first understand the way that quests are handled (which is all kinds of messed up TBH)
Basically it goes like this
- first you kill a monster and then it runs function GiveExp() in WorldProcesses.cpp. In this function it scans your quest array and compares each of them to the "dies_quest" value of the monster you just killed. If it finds a match it means that one of your quests was asking for that particular monster so it goes on to give your reward. Up to this point no problem it all works great
- The server sends an 0x0731 packet to the client containing the Monster ID of the monster that you killed.
- The Client takes that value and returns a hash value of it in a 0x0730 packet
- The server receives this packet and runs pakGiveQuest() which runs the local QSD code to determine if you get a reward or not. Often the chance of getting it is not 100% so yo won't always get one.
- This is where it starts to go wrong. there is a whole lot of Lmame's code in there at this point that has a nasty tendency to reject perfectly good quests. I had to completely re-write pakGiveQuest() to make it work properly. Additionally there is a logical flaw in the way it handles incoming 0x0730 packets but I won't go into that in detail.
- At this point (assuming it has got through the stupid rejection code) it gives your quest reward and [i]should[/] send a 0x0730 packet back to the client before calling function SendQuestUpdate() which sends another packet that actually makes the client display the quest items. Except that for pretty much all monster extermination quests it never gets this far
So one of the ridiculous things about this whole deal is that it is completely pointless to send the 0x0731 packet to the client in the first place. We already know the hash value that it will send back
The reason it was designed that way was most likely to minimize the amount of QSD code that is run in the main loop so it does serve a small purpose in that way by shifting the QSD execution into a function that is called externally to the main loop. It's still really pointless though because it adds unnecessary packets and it's really easy to get rid of it just by modifying the code in GiveEXP()
This is the code that will make it send the quest update properly
WorldProcesses.cpp
- if( thismon->MonsterDrop->firsthit == thisclient->CharInfo->charid )
- {
- for( int q=0;q<10;q++)
- {
- // Give Quest Item
- if( thisclient->quest.quests[q].QuestID!=0 )
- {
- //PY why not just run the QSD?? That's what it's there for. die_quest is already a hash
- if(thisclient->questdebug)
- Log(MSG_QUESTDEBUG,"Recieving exp. now run die quest %i",thismon->die_quest);
- int success = thisclient->ExecuteQuestTrigger(thismon->die_quest,true);
- // 0x0731 sends the monster id to the client
- //BEGINPACKET( pak, 0x731 )
- //ADDWORD ( pak, thismon->montype );
- //thisclient->client->SendPacket( &pak );
- //bypassing the 731 altogether to see what happens
- if (success == QUEST_SUCCESS)
- {
- if(thisclient->questdebug)
- Log(MSG_QUESTDEBUG,"QSD Success now sending the 0x0730 packet");
- BEGINPACKET ( pak, 0x730);
- ADDBYTE ( pak, success);
- ADDBYTE ( pak, q);
- ADDDWORD( pak, thismon->die_quest);
- thisclient->client->SendPacket(&pak);
- //updating client side quest data (hopefully)
- thisclient->SendQuestUpdate();
- }
- break;
- }
- }
- }
Just find that section of the GiveEXP() function and modify it. It's pretty easy to find. The original code is still there in my code snippet, just commented out
If you JUST do this one thing you might well find that you start to get TWO messages saying that you exterminated the monster rather than NONE
So there is one more thing you will need to do
Go to PlayerFunctions.cpp and find a function called int CPlayer::ExecuteQuestTrigger(dword hash,bool send_packet, UINT index)
then find this bit of code
- if(send_packet&&success == QUEST_SUCCESS)
- {
- if( GServer->questdebug )
- Log(MSG_QUESTDEBUG, "ExecuteQuestTrigger:: QSD returned success. Sending 0x730 for questid %u for slot %i",hash, index);
- BEGINPACKET ( pak, 0x730);
- ADDBYTE ( pak, success);
- ADDBYTE ( pak, index);
- ADDDWORD( pak, hash);
- client->SendPacket(&pak);
- }
It's absolutely not necessary for that packet to ever be sent from that location in the code.
The way I fixed it all for myself is a little more complicated than this but what I have posted here should get the job done.