Gossip Code select closing menu

Hi, I started experimenting with custom scripts yesterday and starting out I decided I’d try to make a npc that morph you to whatever ID you feed into it. If you talk to it a box comes up saying “Type in a display ID to morph to.” you press accept, the codebox pops up and if you give it a code it’ll morph you into it, works just fine.

However if you press cancel on any of the boxes, the npc doesn’t close the conversation so it’ll just stand there looking at you and you have to run far enough from it for it to return to a normal state and then be able to start a new conversation.

Also I have a question regarding

player->PlayerTalkClass->ClearMenus();
What is it’s use? I see it used in example scripts and other things however I don’t know what it does.

#include “ScriptPCH.h”
#include “ScriptMgr.h”
uint32 displayid = 0;
class fenix_test : public CreatureScript
{
public:

     fenix_test() : CreatureScript("fenix_test"){}
	 bool OnGossipHello(Player* player, Creature* npc) 
	 { 
		 player->ADD_GOSSIP_ITEM_EXTENDED(3, "Morph ID test", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2, "Morph ID testing", 0, true);
		 player->SEND_GOSSIP_MENU(2575, npc->GetGUID());
		 return true; 
	 }
	 bool OnGossipSelectCode(Player* player, Creature* npc, uint32 sender, uint32 uiAction, const char* code)
	 {
		switch(uiAction)
		{
			case GOSSIP_ACTION_INFO_DEF+2:
				player->DeMorph();
				displayid = uint32(atol(code));
				player->SetDisplayId(displayid);
				ChatHandler(player->GetSession()).PSendSysMessage("ID: %i", displayid); //Ignore this is just sending some info ingame.
				player->CLOSE_GOSSIP_MENU();
		}
		return true;
	 }

};

void AddSC_fenix_test()
{
new fenix_test();
}

What I want it to do is just return to a normal state if I press cancel on a box. Sorry if I explained my issue badly or if my code is written badly, recently started learning.

This is a bug related to the client. (if my assumptions are right…)

I assume you do not see a gossip menu when you talk to the NPC?

You should use correct type_flags or what were they ,…

for the gossip menu to show with the single option and then it should work as intended.

See http://www.trinitycore.org/f/topic/6320-single-gossip-item/?p=50110

player[COLOR=rgb(102,102,0)]->[COLOR=rgb(102,0,102)]PlayerTalkClass[COLOR=rgb(102,102,0)]->[COLOR=rgb(102,0,102)]ClearMenusCOLOR=rgb(102,102,0); is used to remove the old options from memory in the core.

Note that the core stores the sender and action of each option you add to the menu (and all other info as well)

This means that without clearing the menus (deleting old options), when you next time send a menu again, you send the same options + any new ones you have coded in.

Clear menu is used on GossipHello hook before it triggers, but not before GossipSelect hooks. (not sure why? Should probably be done automatically or not at all on both)

This means that you need to use it on gossip select hooks yourself, but not on gossip hello.

Basically it is only needed if you are sending more gossip menus than one in the same gossip script. But it is best to be used always, as otherwise you leave the options stored for no purpose for the player.

Note that uint32(atol(code)); can return 0 and atm on invalid input the code sets your displayid to 0

Also, the correct format would be %u, not %i, but that doesnt really matter I guess.

Another note that sender and action do not affect anything in the core. They are simply variables passed to the OnSelect functions.

Upon error they are 0 though, so I guess you can use them freely pretty much, as long as you stay away from 0 and possibly check if they are 0. (not sure if this can happen actually)

Also note that all checks you do on gossip hello should be done on select as well or users can pass the gossip hello with hacks and other NPCs.

Thank you this was very informative, sorry but I do have another question not really relating to this now, I made it so it checks if you’re a gm or not but I noticed “Player->IsGameMaster()” only works if you enabled GM mode, so I noticed you can do “player->GetSession()->GetSecurity()” however I’d much rather put it into a function to return true or false so I can do “Player->IsTrueGM” however how would I go about doing that? I’ve tried adding some stuff to player.h where IsGameMaster is defined. Here’s what I tried adding (To player.H right below IsGameMaster) however it did not work.

bool IsTrueGM(Player* player) const
{
if(player->GetSession()->GetSecurity() < 1)
return false;
else
return true;
}

I called it by player->IsTrueGM()

Thank you again, this is mainly for educational purposes hehe. /emoticons/default_smile.png

Hmm, if you dont really need the function that much, you can just code it in the scripts and not in the source, but obv you can do that aswell…

Hmm … looks fine to me … It is coded as a non method function though (not a member function).

So if it is in the player class, it should probably be static, or you need to do player->IsTrueGM(player), which makes no sense.

Use this if you want it to be a player function:

bool IsTrueGM() const
{
return GetSession()->GetSecurity() != SEC_PLAYER;
}
Usage: player->IsTrueGM()

Gives me these errors:

Error 1 error C2027: use of undefined type ‘WorldSession’ C:UsersInfDocumentsDevelopmentWoWTrinityCore-mastersrcservergameEntitiesPlayerPlayer.h 1131 1 scripts
Error 2 error C2227: left of ‘->GetSecurity’ must point to class/struct/union/generic type C:UsersInfDocumentsDevelopmentWoWTrinityCore-mastersrcservergameEntitiesPlayerPlayer.h 1131 1 scripts

Seems that WorldSession is not defined in the header, which means that you should separate the function declaration to the player.h and definition to player.cpp

I was watching mangos source accidently and it has worldsession defined.

I did as you said and it worked! Thank you for all your help!

Final code:

bool IsTrueGM() const; //Declared in Player.h
//In Player.CPP
bool Player::IsTrueGM() const 
{
    return GetSession()->GetSecurity() != SEC_PLAYER;
}