diff options
-rw-r--r-- | sql/updates/world/2016_04_02_20_world_2016_01_09_toytrain.sql | 6 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStores.cpp | 14 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStores.h | 3 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStructure.h | 9 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCfmt.h | 1 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_item.cpp | 39 | ||||
-rw-r--r-- | src/server/scripts/World/go_scripts.cpp | 44 | ||||
-rw-r--r-- | src/server/scripts/World/npcs_special.cpp | 129 |
8 files changed, 245 insertions, 0 deletions
diff --git a/sql/updates/world/2016_04_02_20_world_2016_01_09_toytrain.sql b/sql/updates/world/2016_04_02_20_world_2016_01_09_toytrain.sql new file mode 100644 index 00000000000..fc0b8a0cda0 --- /dev/null +++ b/sql/updates/world/2016_04_02_20_world_2016_01_09_toytrain.sql @@ -0,0 +1,6 @@ +-- +UPDATE `gameobject_template` SET `ScriptName`="go_toy_train_set" WHERE `entry`=193963; +UPDATE `creature_template` SET `ScriptName`="npc_train_wrecker" WHERE `entry`=33404; +DELETE FROM `spell_script_names` WHERE `spell_id`=61551; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(61551,"spell_item_toy_train_set_pulse"); diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 460a9e5dac2..921db480853 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -75,6 +75,9 @@ DBCStorage<DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCost DBCStorage<EmotesEntry> sEmotesStore(Emotesfmt); DBCStorage<EmotesTextEntry> sEmotesTextStore(EmotesTextfmt); +typedef std::tuple<uint32, uint32, uint32> EmotesTextSoundKey; +static std::map<EmotesTextSoundKey, EmotesTextSoundEntry const*> sEmotesTextSoundMap; +DBCStorage <EmotesTextSoundEntry> sEmotesTextSoundStore(EmotesTextSoundEntryfmt); DBCStorage<FactionEntry> sFactionStore(Factionfmt); static FactionTeamMap sFactionTeamMap; @@ -314,6 +317,7 @@ void LoadDBCStores(const std::string& dataPath, uint32 defaultLocale) LOAD_DBC(sDurabilityCostsStore, "DurabilityCosts.dbc");//20444 LOAD_DBC(sEmotesStore, "Emotes.dbc");//20444 LOAD_DBC(sEmotesTextStore, "EmotesText.dbc");//20444 + LOAD_DBC(sEmotesTextSoundStore, "EmotesTextSound.dbc"); LOAD_DBC(sFactionStore, "Faction.dbc");//20444 LOAD_DBC(sFactionTemplateStore, "FactionTemplate.dbc");//20444 LOAD_DBC(sGameObjectDisplayInfoStore, "GameObjectDisplayInfo.dbc");//20444 @@ -392,6 +396,10 @@ void LoadDBCStores(const std::string& dataPath, uint32 defaultLocale) "MAX_DIFFICULTY is not large enough to contain all difficulties! (current value %d, required %d)", MAX_DIFFICULTY, sDifficultyStore.GetNumRows()); + for (uint32 i = 0; i < sEmotesTextSoundStore.GetNumRows(); ++i) + if (EmotesTextSoundEntry const* entry = sEmotesTextSoundStore.LookupEntry(i)) + sEmotesTextSoundMap[EmotesTextSoundKey(entry->EmotesTextId, entry->RaceId, entry->SexId)] = entry; + for (uint32 i = 0; i < sFactionStore.GetNumRows(); ++i) { FactionEntry const* faction = sFactionStore.LookupEntry(i); @@ -562,6 +570,12 @@ char const* GetCreatureFamilyPetName(uint32 petfamily, uint32 /*locale*/) return pet_family->Name_lang ? pet_family->Name_lang : NULL; } +EmotesTextSoundEntry const* FindTextSoundEmoteFor(uint32 emote, uint32 race, uint32 gender) +{ + auto itr = sEmotesTextSoundMap.find(EmotesTextSoundKey(emote, race, gender)); + return itr != sEmotesTextSoundMap.end() ? itr->second : nullptr; +} + WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid) { WMOAreaInfoByTripple::iterator i = sWMOAreaInfoByTripple.find(WMOAreaTableTripple(rootid, adtid, groupid)); diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index 2f30a00d3c0..7c7647dd4d9 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -39,6 +39,9 @@ typedef ChrSpecializationEntry const* ChrSpecializationByIndexArray[MAX_CLASSES] // CreatureFamilty TC_GAME_API char const* GetCreatureFamilyPetName(uint32 petfamily, uint32 locale); +// EmotesText +TC_GAME_API EmotesTextSoundEntry const* FindTextSoundEmoteFor(uint32 emote, uint32 race, uint32 gender); + // Faction TC_GAME_API std::vector<uint32> const* GetFactionTeamList(uint32 faction); diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index ec334fb3b8f..96a93832e09 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -393,6 +393,15 @@ struct EmotesTextEntry //uint32 EmoteText[16]; // 3-18 }; +struct EmotesTextSoundEntry +{ + uint32 Id; // 0 + uint32 EmotesTextId; // 1 + uint32 RaceId; // 2 + uint32 SexId; // 3, 0 male / 1 female + uint32 SoundId; // 4 +}; + struct FactionEntry { uint32 ID; // 0 diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index d52891576da..16f5383c343 100644 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -43,6 +43,7 @@ char const DungeonEncounterfmt[] = "niiixsxxx"; char const DurabilityCostsfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; char const Emotesfmt[] = "nxxiiixx"; char const EmotesTextfmt[] = "nxixxxxxxxxxxxxxxxx"; +char const EmotesTextSoundEntryfmt[] = "niiii"; char const Factionfmt[] = "niiiiiiiiiiiiiiiiiiffixsxixx"; char const FactionTemplatefmt[] = "niiiiiiiiiiiii"; char const GameObjectDisplayInfofmt[] = "nixxxxxxxxxxffffffxxx"; diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 824f2b30096..23dfd4d85a7 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -29,6 +29,7 @@ #include "SpellHistory.h" #include "SkillDiscovery.h" #include "Battleground.h" +#include "DBCStores.h" // Generic script for handling item dummy effects which trigger another spell. class spell_item_trigger_spell : public SpellScriptLoader @@ -2591,6 +2592,43 @@ public: } }; +class spell_item_toy_train_set_pulse : public SpellScriptLoader +{ +public: + spell_item_toy_train_set_pulse() : SpellScriptLoader("spell_item_toy_train_set_pulse") { } + + class spell_item_toy_train_set_pulse_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_toy_train_set_pulse_SpellScript); + + void HandleDummy(SpellEffIndex /*index*/) + { + if (Player* target = GetHitUnit()->ToPlayer()) + { + target->HandleEmoteCommand(EMOTE_ONESHOT_TRAIN); + if (EmotesTextSoundEntry const* soundEntry = FindTextSoundEmoteFor(TEXT_EMOTE_TRAIN, target->getRace(), target->getGender())) + target->PlayDistanceSound(soundEntry->SoundId); + } + } + + void HandleTargets(std::list<WorldObject*>& targetList) + { + targetList.remove_if([](WorldObject const* obj) { return obj->GetTypeId() != TYPEID_PLAYER; }); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_item_toy_train_set_pulse_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_item_toy_train_set_pulse_SpellScript::HandleTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_item_toy_train_set_pulse_SpellScript(); + } +}; + void AddSC_item_spell_scripts() { // 23074 Arcanite Dragonling @@ -2658,4 +2696,5 @@ void AddSC_item_spell_scripts() new spell_item_chicken_cover(); new spell_item_muisek_vessel(); new spell_item_greatmothers_soulcatcher(); + new spell_item_toy_train_set_pulse(); } diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index 70520d0a67e..8748c8a8fd8 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -41,6 +41,7 @@ go_tadpole_cage go_amberpine_outhouse go_hive_pod go_veil_skith_cage +go_toy_train_set EndContentData */ #include "ScriptMgr.h" @@ -1125,6 +1126,48 @@ public: } }; + +enum ToyTrainSpells +{ + SPELL_TOY_TRAIN_PULSE = 61551, +}; + +class go_toy_train_set : public GameObjectScript +{ + public: + go_toy_train_set() : GameObjectScript("go_toy_train_set") { } + + struct go_toy_train_setAI : public GameObjectAI + { + go_toy_train_setAI(GameObject* go) : GameObjectAI(go), _pulseTimer(3 * IN_MILLISECONDS) { } + + void UpdateAI(uint32 diff) override + { + if (diff < _pulseTimer) + _pulseTimer -= diff; + else + { + go->CastSpell(nullptr, SPELL_TOY_TRAIN_PULSE, true); + _pulseTimer = 6 * IN_MILLISECONDS; + } + } + + // triggered on wrecker'd + void DoAction(int32 /*action*/) override + { + go->Delete(); + } + + private: + uint32 _pulseTimer; + }; + + GameObjectAI* GetAI(GameObject* go) const override + { + return new go_toy_train_setAI(go); + } +}; + void AddSC_go_scripts() { new go_cat_figurine(); @@ -1160,4 +1203,5 @@ void AddSC_go_scripts() new go_veil_skith_cage(); new go_frostblade_shrine(); new go_midsummer_bonfire(); + new go_toy_train_set(); } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 62d6bce57c9..3b00c5e32d3 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -38,6 +38,7 @@ npc_snake_trap_serpents 80% AI for snakes that summoned by Snake Trap npc_shadowfiend 100% restore 5% of owner's mana when shadowfiend die from damage npc_locksmith 75% list of keys needs to be confirmed npc_firework 100% NPC's summoned by rockets and rocket clusters, for making them cast visual +npc_train_wrecker 100% Wind-Up Train Wrecker that kills train set EndContentData */ #include "ScriptMgr.h" @@ -49,6 +50,7 @@ EndContentData */ #include "World.h" #include "PassiveAI.h" #include "GameEventMgr.h" +#include "GameObjectAI.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" #include "Cell.h" @@ -2385,6 +2387,132 @@ public: } }; +enum TrainWrecker +{ + GO_TOY_TRAIN = 193963, + SPELL_TOY_TRAIN_PULSE = 61551, + SPELL_WRECK_TRAIN = 62943, + ACTION_WRECKED = 1, + EVENT_DO_JUMP = 1, + EVENT_DO_FACING = 2, + EVENT_DO_WRECK = 3, + EVENT_DO_DANCE = 4, + MOVEID_CHASE = 1, + MOVEID_JUMP = 2, + + NPC_EXULTING_WIND_UP_TRAIN_WRECKER = 81071 +}; +class npc_train_wrecker : public CreatureScript +{ + public: + npc_train_wrecker() : CreatureScript("npc_train_wrecker") { } + + struct npc_train_wreckerAI : public NullCreatureAI + { + npc_train_wreckerAI(Creature* creature) : NullCreatureAI(creature), _isSearching(true), _nextAction(0), _timer(1 * IN_MILLISECONDS) { } + + GameObject* VerifyTarget() const + { + if (GameObject* target = ObjectAccessor::GetGameObject(*me, _target)) + return target; + me->HandleEmoteCommand(EMOTE_ONESHOT_RUDE); + me->DespawnOrUnsummon(3 * IN_MILLISECONDS); + return nullptr; + } + + void UpdateAI(uint32 diff) override + { + if (_isSearching) + { + if (diff < _timer) + _timer -= diff; + else + { + if (GameObject* target = me->FindNearestGameObject(GO_TOY_TRAIN, 15.0f)) + { + _isSearching = false; + _target = target->GetGUID(); + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(MOVEID_CHASE, target->GetNearPosition(3.0f, target->GetAngle(me))); + } + else + _timer = 3 * IN_MILLISECONDS; + } + } + else + { + switch (_nextAction) + { + case EVENT_DO_JUMP: + if (GameObject* target = VerifyTarget()) + me->GetMotionMaster()->MoveJump(*target, 5.0, 10.0, MOVEID_JUMP); + _nextAction = 0; + break; + case EVENT_DO_FACING: + if (GameObject* target = VerifyTarget()) + { + me->SetFacingTo(target->GetOrientation()); + me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK1H); + _timer = 1.5 * IN_MILLISECONDS; + _nextAction = EVENT_DO_WRECK; + } + else + _nextAction = 0; + break; + case EVENT_DO_WRECK: + if (diff < _timer) + { + _timer -= diff; + break; + } + if (GameObject* target = VerifyTarget()) + { + me->CastSpell(target, SPELL_WRECK_TRAIN, false); + target->AI()->DoAction(ACTION_WRECKED); + _timer = 2 * IN_MILLISECONDS; + _nextAction = EVENT_DO_DANCE; + } + else + _nextAction = 0; + break; + case EVENT_DO_DANCE: + if (diff < _timer) + { + _timer -= diff; + break; + } + me->UpdateEntry(NPC_EXULTING_WIND_UP_TRAIN_WRECKER); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_DANCE); + me->DespawnOrUnsummon(5 * IN_MILLISECONDS); + _nextAction = 0; + break; + default: + break; + } + } + } + + void MovementInform(uint32 /*type*/, uint32 id) + { + if (id == MOVEID_CHASE) + _nextAction = EVENT_DO_JUMP; + else if (id == MOVEID_JUMP) + _nextAction = EVENT_DO_FACING; + } + + private: + bool _isSearching; + uint8 _nextAction; + uint32 _timer; + ObjectGuid _target; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_train_wreckerAI(creature); + } +}; + void AddSC_npcs_special() { new npc_air_force_bots(); @@ -2408,4 +2536,5 @@ void AddSC_npcs_special() new npc_firework(); new npc_spring_rabbit(); new npc_imp_in_a_ball(); + new npc_train_wrecker(); } |