• This is a read only backup of the old Emudevs forum. If you want to have anything removed, please message me on Discord: KittyKaev

TrinityCore 3.3.5 NPC Chat Timed Event

Grim

Emulation Addict
Does anyone happen to have a template for this? I wanted to make an event where 2 NPCs talk to each other then one NPC summons guards and teleports away, but how I would I make it so it the event can progress through itself without a need of a gossip and through a timer like when 5 seconds passes, npc 1 talks. Then 5 seconds later NPC 2 talks. 10 seconds later NPC 2 summons guards and teleports away.

Wanted to do something like this.

Thanks

- Grim
 

Rochet2

Moderator / Eluna Dev
There are many ways to do this.
You could use normal AI scripts by making the npc say something, wait for a moment, search the other NPC by guid or entry etc and make him say stuff, then wait and repeat.
 

Grim

Emulation Addict
Indeed, but the biggest problem I run into is that I don't know how to make the actual event occur after a certain amount of time. I've seen it work with BossAI, but I wanted to get it working with straight CreatureScript.
For example, how would I make this progress automatically?
Code:
  // Handle the Ashbringer-Endevent here
        uint32 AshbringerEvent(uint32 uiSteps)
        {
            Creature* mograine = me->FindNearestCreature(NPC_HIGHLORD_MOGRAINE, 200.0f);

            switch (uiSteps)
            {
                case 1:
                    me->GetMotionMaster()->MovePoint(0, 1152.039795f, 1398.405518f, 32.527878f);
                    return 2 * IN_MILLISECONDS;
                case 2:
                    me->SetSheath(SHEATH_STATE_UNARMED);
                    me->SetStandState(UNIT_STAND_STATE_KNEEL);
                    return 2 * IN_MILLISECONDS;
                case 3:
                    Talk(SAY_ASHBRINGER_ONE);
                    return 10 * IN_MILLISECONDS;
                case 4:
                    me->SummonCreature(NPC_HIGHLORD_MOGRAINE, 1065.130737f, 1399.350586f, 30.763723f, 6.282961f, TEMPSUMMON_TIMED_DESPAWN, 400000);
                    return 30 * IN_MILLISECONDS;
                case 5:
                    mograine->AI()->Talk(MOGRAINE_ONE);
                    mograine->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
                    return 4 * IN_MILLISECONDS;
                case 6:
                    me->SetStandState(UNIT_STAND_STATE_STAND);
                    return 2 * IN_MILLISECONDS;
                case 7:
                    Talk(SAY_ASHBRINGER_TWO);
                    return 4 * IN_MILLISECONDS;
                case 8:
                    mograine->AI()->Talk(MOGRAINE_TWO);
                    return 11 * IN_MILLISECONDS;
                case 9:
                    mograine->HandleEmoteCommand(EMOTE_ONESHOT_BATTLE_ROAR);
                    return 4 * IN_MILLISECONDS;
                case 10:
                    me->SetSheath(SHEATH_STATE_UNARMED);
                    me->SetStandState(UNIT_STAND_STATE_KNEEL);
                    Talk(SAY_ASHBRINGER_THREE);
                    return 2 * IN_MILLISECONDS;
                case 11:
                    mograine->CastSpell(me, SPELL_COSMETIC_CHAIN, true);
                    mograine->AI()->Talk(MOGRAINE_THREE);
                    mograine->DespawnOrUnsummon(7 * IN_MILLISECONDS);
                    return 4 * IN_MILLISECONDS;
                case 12:
                    mograine->Kill(me, true);
                default:
                    return 0;
            }
        }
 
Last edited:

Rochet2

Moderator / Eluna Dev
You either have to make some kind of creature AI
or you need to use the event processor: me->m_Events
Take a look at the BasicEvent at the bottom of this:
http://pastebin.com/fUCi5kp1

You ofcourse want to use Creature* instead of Player*. That creature would be "me" which is the one who does all the timing
 

MrPixelMC

Member
You can do all that with smartAI, no need for coding imo. Use action ID 1 for talking, then set param2 to the time you want to wait for next action to be done. Use event ID 52 for triggering the next event.

Example:
NPC 1 -> Event ID 25 (on spawn) -> Action ID 1 (talk) -> param2 set to 2000
NPC 2 -> Event ID 52 (on text over) -> param2 of this event set to ID of NPC 1 -> Action ID 1 (talk)

What this will do:
NPC 1 will say the text you want him to say, then after 2 seconds NPC 2 will say the text you want him to say.
 

Grim

Emulation Addict
You can do all that with smartAI, no need for coding imo. Use action ID 1 for talking, then set param2 to the time you want to wait for next action to be done. Use event ID 52 for triggering the next event.

Example:
NPC 1 -> Event ID 25 (on spawn) -> Action ID 1 (talk) -> param2 set to 2000
NPC 2 -> Event ID 52 (on text over) -> param2 of this event set to ID of NPC 1 -> Action ID 1 (talk)

What this will do:
NPC 1 will say the text you want him to say, then after 2 seconds NPC 2 will say the text you want him to say.

I seemed to have gotten the first NPC to say something, but the second NPC doesn't respond at all (rude) k3k.
I wanted to use code so I can learn some C++.

This is the script that I want to redo: http://wowwiki.wikia.com/wiki/Quest:The_Great_Masquerade#NPC_scripts
The main scene I mostly care about is everything after "Reginald Windsor says: Onward!" I don't care about anything above.
A video on what I am aiming for: https://www.youtube.com/watch?v=FXJ_V2yoKW0
I hate that I cannot get events happening after a certain amount of time. :/
 

Rochet2

Moderator / Eluna Dev
I seemed to have gotten the first NPC to say something, but the second NPC doesn't respond at all (rude) k3k.
I wanted to use code so I can learn some C++.

This is the script that I want to redo: http://wowwiki.wikia.com/wiki/Quest:The_Great_Masquerade#NPC_scripts
The main scene I mostly care about is everything after "Reginald Windsor says: Onward!" I don't care about anything above.
A video on what I am aiming for: https://www.youtube.com/watch?v=FXJ_V2yoKW0
I hate that I cannot get events happening after a certain amount of time. :/

If you didnt get it to work and want help with it, then post what you made so far.

Nobody wants to do stuff for you. Everyone wants to point what you got wrong.
 
Last edited:

Grim

Emulation Addict
I apologize, I wasn't at home so I couldn't upload the script, I had a worker of mine do the SmartAI and he reported back that nothing siginificant really occured.

UPDATE:
I had just gotten home and just uploaded the script.

Code:
enum Windsor
{
	SAY_WINDSOR_1 = 0, // The masquerade is over, Lady Prestor. Or should I call you by your true name... Onyxia...
	SAY_WINDSOR_2 = 1, // You will not escape your fate, Onyxia. It has been prophesied - a vision resonating from the great halls of Karazhan. It ends now...
	SAY_WINDSOR_3 = 2, // The Dark Iron's thought these tablets to be encoded. This is not any form of coding, it is the tongue of ancient dragon.
	SAY_WINDSOR_4 = 3, // Listen, dragon. Let the truth resonate throughout these halls.
	SAY_WINDSOR_5 = 4, // DO NOT LET HER ESCAPE!

	SAY_PRESTOR_1 = 0, // You will be incarcerated and tried for treason, Windsor. I shall watch with glee as they hand down a guilty verdict and sentence you to death by hanging...
	SAY_PRESTOR_2 = 1, // And as your limp body dangles from the rafters, I shall take pleasure in knowing that a mad man has been put to death. After all, what proof do you have? Did you expect to come in here and point your fingers at royalty and leave unscathed?
	SAY_LADY_ONYXIA_1 = 0, // Curious... Windsor, in this vision, did you survive? I only ask because one thing that I can and will assure is your death. Here and now.

	NPC_LADY_ONYXIA = 12756,
	NPC_WINDSOR = 12580,	
};

class npc_windsor : public CreatureScript
{
public:
	npc_windsor() : CreatureScript("npc_windsor") { }

	CreatureAI* GetAI(Creature* creature) const
	{
		return new npc_windsorAI(creature);
	}
	
	bool OnGossipHello(Player* plr, Creature* npc)
	{
		if (npc_windsorAI* WinAI = CAST_AI(npc_windsorAI, npc->GetAI()))
		{
			if (!WinAI->start)
			{
				npc->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
				WinAI->start;
			}
		}
		return true;
	}


	struct npc_windsorAI : public ScriptedAI
	{
		npc_windsorAI(Creature* creature) : ScriptedAI(creature) { }
		Creature* Prestor = me->FindNearestCreature(1749, 300.0f, true);

		uint32 uiTimer;
		uint32 uiPhase;
		bool start = false;

		void Reset()
		{
			uiTimer = 0;
			uiPhase = 0;
			start = false;
			
			if (!me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
				me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
		}

		void UpdateAI(uint32 uiDiff)
		{
			if (start)
			{
				if (uiPhase)
				{
					if (uiTimer <= uiDiff)
					{
						switch (uiPhase)
						{
						case 1:
							Talk(SAY_WINDSOR_1);
							uiTimer = 3000;
							uiPhase = 2;
							break;
						case 2:
							Prestor->MonsterTextEmote("Lady Katrana Prestor laughs.", me);
							uiTimer = 1000;
							uiPhase = 3;
							break;
						case 3:
							Prestor->MonsterSay(SAY_PRESTOR_1, LANG_UNIVERSAL, me);
							uiTimer = 4000;
							uiPhase = 4;
							break;
						case 4:
							Prestor->MonsterSay(SAY_PRESTOR_2, LANG_UNIVERSAL, me);
							uiPhase = 4000;
							uiTimer = 5;
							break;
						case 5:
							Talk(SAY_WINDSOR_2);
							uiTimer = 3000;
							uiPhase = 6;
							break;
						case 6:
							Talk(SAY_WINDSOR_3);
							uiTimer = 3000;
							uiPhase = 7;
							break;
						case 7:
							Talk(SAY_WINDSOR_4);
							uiTimer = 3000;
							uiPhase = 8;
							break;
						case 8:
							Prestor->UpdateEntry(NPC_LADY_ONYXIA);
							uiTimer = 3000;
							uiPhase = 9;
							break;
						case 9:
							Prestor->MonsterSay(SAY_LADY_ONYXIA_1, LANG_UNIVERSAL, me);
							uiTimer = 3000;
							uiPhase = 10;
							break;
						case 10:
							Talk(SAY_WINDSOR_5);
							uiTimer = 2000;
							uiPhase = 11;
							break;
						case 11:
							me->Kill(Prestor, me);
							Prestor->MonsterTextEmote("Lady Onyxia laughs as Reginald Windsor is mortally wounded", me);
							uiTimer = 2000;
							uiPhase = 12;
							break;
						}
					}
					else uiTimer -= uiDiff;
				}
				ScriptedAI::UpdateAI(uiDiff);

				if (!UpdateVictim())
					return;
			}
		}
	};
};

void AddSC_stormwind_city()
{
    new npc_archmage_malin();
    new npc_bartleby();
    new npc_lady_katrana_prestor();
    new npc_tyrion();
    new npc_tyrion_spybot();
    new npc_lord_gregor_lescovar();
    new npc_marzon_silent_blade();	
    new npc_windsor();
}

The source file is: zone_stormwind_city,cpp
There's not any errors at all, it simply just makes the npc not a gossip and thats that, nothing happens from there.
 
Last edited:

Rochet2

Moderator / Eluna Dev
WinAI->start;
This line does nothing at all.
You probably meant to set it as true? WinAI->start = true;
 

Grim

Emulation Addict
I think I may have figured out where the issue is located, but a bit unsure on how to solve it.
This method here:
Code:
void Reset()
		{
			uiTimer = 0;
			uiPhase = 0;
			start = false;			
			
			if (!me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
				me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
		}
is being ran EVERY time the gossip window closes and/or when I click the gossip menu option.
Therefore, always resetting the variables back to false and the phases and timer.

How I knew it was this method is because that the GOSSIP flag never goes away.

Updated Script here:
Code:
class npc_windsor : public CreatureScript
{
public:
	npc_windsor() : CreatureScript("npc_windsor") { }

	CreatureAI* GetAI(Creature* creature) const
	{
		return new npc_windsorAI(creature);
	}
	
	bool OnGossipHello(Player* player, Creature* creature)
	{
		player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Lets kill this bitch!", GOSSIP_SENDER_MAIN, 1);
		player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
		return true;
	}

	bool OnGossipSelect(Player* player, Creature* npc, uint32 /*sender*/, uint32 action)
	{
		player->PlayerTalkClass->ClearMenus();
		switch (action)
		{
		case 1:
			if (npc_windsorAI* WinAI = CAST_AI(npc_windsorAI, npc->GetAI()))
			{
				if (!WinAI->start)
				{
					WinAI->start = true;
					WinAI->uiTimer = 0;
					WinAI->uiPhase = 0;

					npc->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
					player->CLOSE_GOSSIP_MENU();

					return true;
				}
				return true;
			}
			return true;
		}
	}

	struct npc_windsorAI : public ScriptedAI
	{
		npc_windsorAI(Creature* creature) : ScriptedAI(creature) { }
		Creature* Prestor = me->FindNearestCreature(1749, 300.0f, true);

		uint32 uiTimer;
		uint32 uiPhase;
		bool start;

		void Reset()
		{
			uiTimer = 0;
			uiPhase = 0;
			start = false;			
			
			if (!me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
				me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
		}

		void UpdateAI(uint32 uiDiff)
		{
			if (start)
			{
				if (uiPhase)
				{
					if (uiTimer <= uiDiff)
					{
						switch (uiPhase)
						{
						case 1:
							me->MonsterSay("The masquerade is over, Lady Prestor. Or should I call you by your true name... Onyxia...", LANG_UNIVERSAL, Prestor);
							uiTimer = 3000;
							uiPhase = 2;
							break;
						case 2:
							Prestor->MonsterTextEmote("Lady Katrana Prestor laughs.", me);
							uiTimer = 1000;
							uiPhase = 3;
							break;
						case 3:
							Prestor->MonsterSay("You will be incarcerated and tried for treason, Windsor. I shall watch with glee as they hand down a guilty verdict and sentence you to death by hanging...", LANG_UNIVERSAL, me);
							uiTimer = 4000;
							uiPhase = 4;
							break;
						case 4:
							Prestor->MonsterSay("And as your limp body dangles from the rafters, I shall take pleasure in knowing that a mad man has been put to death. After all, what proof do you have? Did you expect to come in here and point your fingers at royalty and leave unscathed?", LANG_UNIVERSAL, me);
							uiPhase = 4000;
							uiTimer = 5;
							break;
						case 5:
							me->MonsterSay("You will not escape your fate, Onyxia. It has been prophesied - a vision resonating from the great halls of Karazhan. It ends now..", LANG_UNIVERSAL, Prestor);
							uiTimer = 3000;
							uiPhase = 6;
							break;
						case 6:
							me->MonsterSay("The Dark Iron's thought these tablets to be encoded. This is not any form of coding, it is the tongue of ancient dragon.", LANG_UNIVERSAL, Prestor);
							uiTimer = 3000;
							uiPhase = 7;
							break;
						case 7:
							me->MonsterSay("Listen, dragon. Let the truth resonate throughout these halls.", LANG_UNIVERSAL, Prestor);
							uiTimer = 3000;
							uiPhase = 8;
							break;
						case 8:
							Prestor->UpdateEntry(NPC_LADY_ONYXIA);
							uiTimer = 3000;
							uiPhase = 9;
							break;
						case 9:
							Prestor->MonsterSay("Curious... Windsor, in this vision, did you survive? I only ask because one thing that I can and will assure is your death. Here and now.", LANG_UNIVERSAL, me);
							uiTimer = 3000;
							uiPhase = 10;
							break;
						case 10:
							me->MonsterSay("DO NOT LET HER ESCAPE!", LANG_UNIVERSAL, Prestor);
							uiTimer = 2000;
							uiPhase = 11;
							break;
						case 11:
							me->Kill(Prestor, me);
							Prestor->MonsterTextEmote("Lady Onyxia laughs as Reginald Windsor is mortally wounded", me);
							uiTimer = 2000;
							uiPhase = 12;
							break;
						}
					}
					else uiTimer -= uiDiff;
				}
				ScriptedAI::UpdateAI(uiDiff);

				if (!UpdateVictim())
					return;
			}
		}
	};
};

void AddSC_stormwind_city()
{
    new npc_archmage_malin();
    new npc_bartleby();
    new npc_lady_katrana_prestor();
    new npc_tyrion();
    new npc_tyrion_spybot();
    new npc_lord_gregor_lescovar();
    new npc_marzon_silent_blade();	
	new npc_windsor();
}
 
Last edited:

Rochet2

Moderator / Eluna Dev
"How I knew it was this method is because that the GOSSIP flag never goes away."

Actually you are just using SetFlag wrong.
It doesnt set the flag to what you give it, it actually uses oldflag | newflag

So to remove all flags you should use RemoveFlag(UNIT_NPC_FLAGS, 0xFFFFFFFF)
However if this does not work properly (as I recall seeing on arcemu) it may be that you actually need to have at least some flag set.
Often for this purpose the flag number 4 is used because it does nothing (that I know of)
RemoveFlag(UNIT_NPC_FLAGS, 0xFFFFFFFF)
SetFlag(UNIT_NPC_FLAGS, 4)

You should try debugging in one way or another if you cannot know what runs and what does not.
Read here: http://pastebin.com/V1r1q45N
 
Last edited:

Grim

Emulation Addict
I just made it into a gossip script and rewrote the whole script and it works flawlessly, however, after a certain time do NPCs respawn? Like I did an UpdateEntry and then made the npc Despawn. Do these NPCs follow their respawn timers or does it have to be coded to respawn?
 

Rochet2

Moderator / Eluna Dev
I just made it into a gossip script and rewrote the whole script and it works flawlessly, however, after a certain time do NPCs respawn? Like I did an UpdateEntry and then made the npc Despawn. Do these NPCs follow their respawn timers or does it have to be coded to respawn?

npcs dont randomly respawn. They need to be killed first. .. or coded to respawn
 

Grim

Emulation Addict
I mean if they are despawned through a script, do they respawn according to their respawn timer?

Example:
Code:
creature->DespawnOrUnsummon();
 

Grim

Emulation Addict
Will alrighty, thanks Rochet.

Maybe eventually I'll try to attempt this again, but my testers like it as a gossip. :p
 
Top