Skip to content

Instantly share code, notes, and snippets.

@mindsear
Last active April 19, 2018 10:35
Show Gist options
  • Save mindsear/51a02e40180b9b4665ba757e1a91ff0b to your computer and use it in GitHub Desktop.
Save mindsear/51a02e40180b9b4665ba757e1a91ff0b to your computer and use it in GitHub Desktop.
/*
Fixed and explained Srzm's script
http://www.ac-web.org/forums/showthread.php?231858-Help-Getting-started-with-Custom-NPC-and-Boss-Scripting
I'm using Trinity Core 3.3.5 (22-march-2018 updated version)
-- ==================================================================================================================================
-- This is the npc I used in my database
Set @Entry = 55000,
@Npc_Name = "Test",
@Subname = "",
@ModelID = 31833,
@Level = 80,
@ScriptName = "Innkeeperhealer";
INSERT INTO `world`.`creature_template` (`entry`, `modelid1`, `name`, `subname`, `minlevel`, `maxlevel`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `type`, `HoverHeight`, `HealthModifier`, `ManaModifier`, `ArmorModifier`, `DamageModifier`, `ExperienceModifier`, `RegenHealth`, `ScriptName`, `VerifiedBuild`) VALUES
(@Entry, @ModelID, @Npc_Name, @Subname, @Level, @Level, 35, 1, 1, 1.14286, 1, 1, 2000, 2000, 1, 1, 2, 0, 2048, 7, 1, 50, 50, 1, 1, 1, 1, @ScriptName, 12340);
-- ==================================================================================================================================
Short video showing the NPC that uses this script
https://streamable.com/l50ah
*/
#include "ScriptMgr.h"
#include "ScriptedGossip.h"
#include "ScriptedCreature.h"
#include "GossipDef.h"
#include "Creature.h"
#include "Player.h"
#include "WorldSession.h"
enum GossipMenuID
{
/* it's easier to understand and search if you're using string instead of plain numbers */
Menu_Close1 = 1,
Menu_Close2 = 2,
Menu_Heal1,
Menu_Heal2,
Menu_Morph,
Menu_DeMorph,
Menu_ShowBank,
Menu_ShowMailBox,
Menu_NPC_SAY,
Menu_NPC_YELL,
Menu_NPC_Whisper,
Menu_BuffNpc,
Menu_BuffPlayer,
Menu_RemoveBuffNpc,
Menu_RemoveBuffPlayer,
};
enum Spells
{
GREATER_HEAL = 71931,
POWER_WORD_FORTITUDE = 48161, // Power infuses the target increasing their Stamina by 165 for 30 min. (Rank 8)
SOME_OTHER_SPELL = 123
};
#define CLOSE1 "I wanna close the window THIS way!"
#define CLOSE2 "No, better close it THIS way..!"
#define HEAL1 "Heal me! (function SetFullHealth())"
#define HEAL2 "Heal me! (cast a healing spell)"
#define Morph_plr "Morph Me into a crab"
#define DeMorph_plr "DeMorph Me"
#define Show_Bank "Show Bank"
#define Show_MailBox "Show Mail"
#define Npc_Say "Say Something"
#define Npc_Yell "Yell Something"
#define Npc_Whisper "Whisper Something"
#define Buff_NPC "Buff npc"
#define Buff_Player "Buff player"
#define RemoveBuff_NPC "Remove Buff from npc"
#define RemoveBuff_Player "Remove Buff from player"
// gossip text id can be taken from world database, npc_text table. For example id 1 = "Greetings, $n." ($n means player's name)
#define GOSSIP_TEXT_ID_HEY_CITIZEN 197 // "Hey citizen! You look like a stout one. We guards are spread a little thin out here, and I could use you help..."
class Innkeeperhealer : public CreatureScript
{
public:
Innkeeperhealer() : CreatureScript("Innkeeperhealer") {}
struct InnkeeperhealerAI : public ScriptedAI
{
InnkeeperhealerAI(Creature* creature) : ScriptedAI(creature) { }
bool GossipHello(Player* plr) override
{
//if (true) // What is this ?? I don't think you need it ( no logic behind this if statement)
//{
/* Option 1: Closing the Gossip Menu with the text: "I wanna close the window THIS way!" */
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, CLOSE1, GOSSIP_SENDER_MAIN, Menu_Close1);
/* Option 2: Closing the Gossip Menu with the text: "No, better close it THIS way..!" */
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, CLOSE2, GOSSIP_SENDER_MAIN, Menu_Close2);
// I've added the healing menus
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, HEAL1, GOSSIP_SENDER_MAIN, Menu_Heal1);
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, HEAL2, GOSSIP_SENDER_MAIN, Menu_Heal2);
//this is another example - morph player
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, Morph_plr, GOSSIP_SENDER_MAIN, Menu_Morph);
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, DeMorph_plr, GOSSIP_SENDER_MAIN, Menu_DeMorph);
// show player's bank ui
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, Show_Bank, GOSSIP_SENDER_MAIN, Menu_ShowBank);
// show player's mailbox ui
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, Show_MailBox, GOSSIP_SENDER_MAIN, Menu_ShowMailBox);
// npc say something
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, Npc_Say, GOSSIP_SENDER_MAIN, Menu_NPC_SAY);
// npc yell something
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, Npc_Yell, GOSSIP_SENDER_MAIN, Menu_NPC_YELL);
// npc whisper something
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, Npc_Whisper, GOSSIP_SENDER_MAIN, Menu_NPC_Whisper);
// buff npc
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, Buff_NPC, GOSSIP_SENDER_MAIN, Menu_BuffNpc);
// remove buff from npc
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, RemoveBuff_NPC, GOSSIP_SENDER_MAIN, Menu_RemoveBuffNpc);
// buff player
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, Buff_Player, GOSSIP_SENDER_MAIN, Menu_BuffPlayer);
// remove buff from player
AddGossipItemFor(plr, GOSSIP_ICON_CHAT, RemoveBuff_Player, GOSSIP_SENDER_MAIN, Menu_RemoveBuffPlayer);
/* Display both of those options when a player talks to me. */
SendGossipMenuFor(plr, GOSSIP_TEXT_ID_HEY_CITIZEN, me->GetGUID());
//}
return true;
}
bool GossipSelect(Player* plr, uint32 /*menuId*/, uint32 uiAction) override
{
/* If there is no player around, don't do anything. */
//if (!plr) // There is no need for this check
// return false;
uint32 const action = plr->PlayerTalkClass->GetGossipOptionAction(uiAction); // this line should be first
ClearGossipMenuFor(plr); // this should be the second line, otherwise it wouldn't work
switch (action)
{
/*
In c++ you can do "case 1: case 2: case n: DO SOMETHING break;" if
you want all cases to do the same thing. It's not a must but it looks easier and less writing
of the same function/s for all cases.
e.g.
case 1:
case 2:
CloseGossipMenuFor(player);
break;
*/
case Menu_Close1:
CloseGossipMenuFor(plr);
break; // You forgot to add the break for the case
case Menu_Close2:
CloseGossipMenuFor(plr);
break; // You forgot to add the break for the case
case Menu_Heal1: // Heal the player: you can either use a healing spell or a tc function
if (plr->GetHealthPct() == 100.0f)
{
plr->GetSession()->SendAreaTriggerMessage("Your health is already full.");
}
else // if player's health is less than 100%
{
plr->SetFullHealth();
plr->GetSession()->SendAreaTriggerMessage("Your health has been restored.");
CloseGossipMenuFor(plr);
}
break;
case Menu_Heal2: // Heal the player: you can either use a healing spell or a tc function
// in this case "me" is the npc who's casting the spell. If you want the player to cast the spell, just replace me with plr
me->CastSpell(plr, GREATER_HEAL, false); // the third argument is either true (don't cast the spell) or false (cast the spell)
plr->GetSession()->SendAreaTriggerMessage("You've been healed.");
CloseGossipMenuFor(plr);
break;
case Menu_Morph:
plr->SetDisplayId(999); // display id 999 = crab ( these ID's can be found in CreatureDisplayInfo.dbc and CreatureModelData.dbc)
break;
case Menu_DeMorph:
plr->DeMorph();
break;
case Menu_ShowBank:
plr->GetSession()->SendShowBank(plr->GetGUID());
break;
case Menu_ShowMailBox:
plr->GetSession()->SendShowMailBox(plr->GetGUID());
break;
case Menu_NPC_SAY:
me->Say("I'm saying Something!", LANG_UNIVERSAL, plr);
break;
case Menu_NPC_YELL:
me->Yell("I'm yelling Something!", LANG_UNIVERSAL, plr);
break;
case Menu_NPC_Whisper:
me->Whisper("I'm whispering Something!", LANG_UNIVERSAL, plr);
break;
case Menu_BuffNpc:
me->AddAura(POWER_WORD_FORTITUDE, me);
break;
case Menu_RemoveBuffNpc:
me->RemoveAura(POWER_WORD_FORTITUDE);
break;
case Menu_BuffPlayer:
me->AddAura(POWER_WORD_FORTITUDE, plr);
break;
case Menu_RemoveBuffPlayer:
plr->RemoveAura(POWER_WORD_FORTITUDE);
break;
}
CloseGossipMenuFor(plr); // if cases are missing this, you can add it here for all cases to close after functions are executed.
return true;
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new InnkeeperhealerAI(creature);
}
};
void ADDSC_Innkeeperhealer()
{
new Innkeeperhealer();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment