diff --git a/README.md b/README.md index 6c6467740..723a3c797 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # ![logo](https://raw.githubusercontent.com/azerothcore/azerothcore.github.io/master/images/logo-github.png) AzerothCore + + Coverity Scan Build Status + + [![GetBadges Game](https://azerothcore-azerothcore-wotlk.getbadges.io/shield/company/azerothcore-azerothcore-wotlk)](https://azerothcore-azerothcore-wotlk.getbadges.io/?ref=shield-game) [![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=40032087)](https://www.bountysource.com/teams/azerothcore/bounties) [![Master Build Status](https://travis-ci.org/azerothcore/azerothcore-wotlk.svg)](https://travis-ci.org/azerothcore/azerothcore-wotlk) [![Issue Stats](http://www.issuestats.com/github/AzerothCore/azerothcore-wotlk/badge/issue)](http://www.issuestats.com/github/AzerothCore/azerothcore-wotlk) [![Issue Stats](http://www.issuestats.com/github/AzerothCore/azerothcore-wotlk/badge/pr)](http://www.issuestats.com/github/AzerothCore/azerothcore-wotlk) diff --git a/issue_template.md b/issue_template.md index d5375cfe7..961558357 100644 --- a/issue_template.md +++ b/issue_template.md @@ -1,3 +1,12 @@ + + + + + + + + + **Description**: **Current behaviour**: Tell us what happens @@ -12,7 +21,7 @@ **Branch(es)**: 0.x / 1.x / master (Specify the branch(es) affected by this issue) -**AC hash/commit**: +**AC hash/commit**: **Operating system**: diff --git a/src/game/World/World.cpp b/src/game/World/World.cpp index 684f9af76..e7cdd9aa3 100644 --- a/src/game/World/World.cpp +++ b/src/game/World/World.cpp @@ -844,7 +844,7 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_START_ARENA_POINTS] = m_int_configs[CONFIG_MAX_ARENA_POINTS]; } - m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = sConfigMgr->GetIntDefault("RecruitAFriend.MaxLevel", 60); + m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = sConfigMgr->GetIntDefault("RecruitAFriend.MaxLevel", 60); if (m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL]) { sLog->outError("RecruitAFriend.MaxLevel (%i) must be in the range 0..MaxLevel(%u). Set to %u.", @@ -858,6 +858,7 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_INSTANCE_IGNORE_LEVEL] = sConfigMgr->GetBoolDefault("Instance.IgnoreLevel", false); m_bool_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfigMgr->GetBoolDefault("Instance.IgnoreRaid", false); + m_bool_configs[CONFIG_INSTANCE_GMSUMMON_PLAYER] = sConfigMgr->GetBoolDefault("Instance.GMSummonPlayer", false); m_bool_configs[CONFIG_INSTANCE_SHARED_ID] = sConfigMgr->GetBoolDefault("Instance.SharedNormalHeroicId", false); m_int_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfigMgr->GetIntDefault("Instance.ResetTimeHour", 4); diff --git a/src/game/World/World.h b/src/game/World/World.h index a32bf65b8..96eecf073 100644 --- a/src/game/World/World.h +++ b/src/game/World/World.h @@ -93,6 +93,7 @@ enum WorldBoolConfigs CONFIG_INSTANT_TAXI, CONFIG_INSTANCE_IGNORE_LEVEL, CONFIG_INSTANCE_IGNORE_RAID, + CONFIG_INSTANCE_GMSUMMON_PLAYER, CONFIG_INSTANCE_SHARED_ID, CONFIG_GM_LOG_TRADE, CONFIG_ALLOW_GM_GROUP, diff --git a/src/scripts/Commands/cs_misc.cpp b/src/scripts/Commands/cs_misc.cpp index f7eb61d7d..edf485191 100644 --- a/src/scripts/Commands/cs_misc.cpp +++ b/src/scripts/Commands/cs_misc.cpp @@ -688,12 +688,16 @@ public: } else if (map->IsDungeon()) { - // pussywizard: prevent unbinding normal player's perm bind by just summoning him >_> - if (!target->GetSession()->GetSecurity()) + // Allow GM to summon players or only other GM accounts inside instances. + if (!sWorld->getBoolConfig(CONFIG_INSTANCE_GMSUMMON_PLAYER)) { - handler->PSendSysMessage("Only GMs can be summoned to an instance!"); - handler->SetSentErrorMessage(true); - return false; + // pussywizard: prevent unbinding normal player's perm bind by just summoning him >_> + if (!target->GetSession()->GetSecurity()) + { + handler->PSendSysMessage("Only GMs can be summoned to an instance!"); + handler->SetSentErrorMessage(true); + return false; + } } Map* destMap = target->GetMap(); diff --git a/src/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp b/src/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp index 09ccab27b..8e1411794 100644 --- a/src/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp +++ b/src/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp @@ -23,6 +23,21 @@ const Position BlackGuardPos[10] = {4032.73f-2.0f, -3407.38f-2.0f, 115.56f, 0.0f} }; +// Creatures to be spawned during the trap events +static const uint32 aPlaguedCritters[] = +{ + NPC_PLAGUED_RAT, NPC_PLAGUED_MAGGOT, NPC_PLAGUED_INSECT +}; + +// Positions of the two Gate Traps +static const Position aGateTrap[] = +{ + {3612.29f, -3335.39f, 124.077f, 3.14159f}, // Scarlet side + {3919.88f, -3547.34f, 134.269f, 2.94961f} // Undead side +}; + +// uint32 m_uiGateTrapTimers[2][3] = { {0,0,0}, {0,0,0} }; + class instance_stratholme : public InstanceMapScript { public: @@ -54,6 +69,9 @@ class instance_stratholme : public InstanceMapScript _slaughterGateGUID = 0; _baronRivendareGUID = 0; + _gateTrapsCooldown[0] = false; + _gateTrapsCooldown[1] = false; + events.Reset(); } @@ -185,6 +203,18 @@ class instance_stratholme : public InstanceMapScript if (_slaughterProgress >= 2) go->SetGoState(GO_STATE_ACTIVE); break; + case GO_PORT_TRAP_GATE_1: + _trapGatesGUIDs[0] = go->GetGUID(); + break; + case GO_PORT_TRAP_GATE_2: + _trapGatesGUIDs[1] = go->GetGUID(); + break; + case GO_PORT_TRAP_GATE_3: + _trapGatesGUIDs[2] = go->GetGUID(); + break; + case GO_PORT_TRAP_GATE_4: + _trapGatesGUIDs[3] = go->GetGUID(); + break; } } @@ -203,6 +233,23 @@ class instance_stratholme : public InstanceMapScript } } + void DoSpawnPlaguedCritters(uint8 /*uiGate*/, Player* player) + { + if (!player) + return; + + + uint32 uiEntry = aPlaguedCritters[urand(0, 2)]; + for (uint8 i = 0; i < 30; ++i) + { + float x, y, z; + const Position pPos = { player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation() }; + player->GetRandomPoint(pPos, 8.0f, x, y, z); + z = player->GetPositionZ() + 1; + player->SummonCreature(uiEntry, x, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 0)->AI()->AttackStart(player); + } + } + void SetData(uint32 type, uint32 data) { switch (type) @@ -324,8 +371,88 @@ class instance_stratholme : public InstanceMapScript void Update(uint32 diff) { events.Update(diff); + + Map::PlayerList const& players = instance->GetPlayers(); + // Loop over the two Gate traps, each one has up to three timers (trap reset, gate opening delay, critters spawning delay) + for (uint8 i = 0; i < 2; i++) + { + // if the gate is in cooldown, skip the other checks + if (_gateTrapsCooldown[i]) + break; + + + // Check that the trap is not on cooldown, if so check if player/pet is in range + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* player = itr->GetSource()) + { + // should pet also trigger the trap? could not find any source for it + if (player && !player->IsGameMaster() && player->IsWithinDist2d(aGateTrap[i].m_positionX, aGateTrap[i].m_positionY, 5.5f)) + { + // Check if timer was not already set by another player/pet a few milliseconds before + if (_gateTrapsCooldown[i]) + return; + + _gateTrapsCooldown[i] = true; + + // close the gates + if (_trapGatesGUIDs[2 * i]) + DoUseDoorOrButton(_trapGatesGUIDs[2 * i]); + if (_trapGatesGUIDs[2 * i + 1]) + DoUseDoorOrButton(_trapGatesGUIDs[2 * i + 1]); + + _trappedPlayerGUID = player->GetGUID(); + + if (i == 0) + { + // set timer to reset the trap + events.ScheduleEvent(EVENT_GATE1_TRAP, 30 * MINUTE * IN_MILLISECONDS); + // set timer to reopen gates + events.ScheduleEvent(EVENT_GATE1_DELAY, 20 * IN_MILLISECONDS); + // set timer to spawn the plagued critters + events.ScheduleEvent(EVENT_GATE1_CRITTER_DELAY, 2 * IN_MILLISECONDS); + } + else if (i == 1) + { + // set timer to reset the trap + events.ScheduleEvent(EVENT_GATE2_TRAP, 30 * MINUTE * IN_MILLISECONDS); + // set timer to reopen gates + events.ScheduleEvent(EVENT_GATE2_DELAY, 20 * IN_MILLISECONDS); + // set timer to spawn the plagued critters + events.ScheduleEvent(EVENT_GATE2_CRITTER_DELAY, 2 * IN_MILLISECONDS); + } + } + } + } + } + + int gate = 1; switch (events.ExecuteEvent()) { + case EVENT_GATE1_TRAP: + gate = 0; + case EVENT_GATE2_TRAP: + _gateTrapsCooldown[gate] = false; + break; + case EVENT_GATE1_DELAY: + gate = 0; + case EVENT_GATE2_DELAY: + if (_trapGatesGUIDs[2 * gate]) + DoUseDoorOrButton(_trapGatesGUIDs[2 * gate]); + if (_trapGatesGUIDs[2 * gate + 1]) + DoUseDoorOrButton(_trapGatesGUIDs[2 * gate + 1]); + break; + case EVENT_GATE1_CRITTER_DELAY: + gate = 0; + case EVENT_GATE2_CRITTER_DELAY: + if (_trappedPlayerGUID) + { + if (Player* pPlayer = instance->GetPlayer(_trappedPlayerGUID)) + { + DoSpawnPlaguedCritters(gate, pPlayer); + } + } + break; case EVENT_BARON_TIME: { --_baronRunTime; @@ -434,6 +561,10 @@ class instance_stratholme : public InstanceMapScript uint64 _slaughterGateGUID; uint64 _gauntletGateGUID; uint64 _baronRivendareGUID; + + bool _gateTrapsCooldown[2]; + uint64 _trappedPlayerGUID; + uint64 _trapGatesGUIDs[4]; }; InstanceScript* GetInstanceScript(InstanceMap* map) const @@ -445,4 +576,4 @@ class instance_stratholme : public InstanceMapScript void AddSC_instance_stratholme() { new instance_stratholme(); -} \ No newline at end of file +} diff --git a/src/scripts/EasternKingdoms/Stratholme/stratholme.h b/src/scripts/EasternKingdoms/Stratholme/stratholme.h index f57877fe5..0ee7b2a1b 100644 --- a/src/scripts/EasternKingdoms/Stratholme/stratholme.h +++ b/src/scripts/EasternKingdoms/Stratholme/stratholme.h @@ -28,7 +28,10 @@ enum CreatureIds NPC_RAMSTEIN_THE_GORGER = 10439, NPC_MINDLESS_UNDEAD = 11030, NPC_BLACK_GUARD = 10394, - NPC_YSIDA = 16031 + NPC_YSIDA = 16031, + NPC_PLAGUED_RAT = 10441, + NPC_PLAGUED_INSECT = 10461, + NPC_PLAGUED_MAGGOT = 10536, }; enum GameobjectIds @@ -41,7 +44,11 @@ enum GameobjectIds GO_GAUNTLET_GATE = 175374, GO_SLAUGTHER_GATE = 175373, GO_SLAUGHTER_GATE_SIDE = 175358, - GO_EXIT_GATE = 176424 + GO_EXIT_GATE = 176424, + GO_PORT_TRAP_GATE_1 = 175351, // Portcullis used in the gate traps (rats trap) + GO_PORT_TRAP_GATE_2 = 175350, // Gate trap scarlet side + GO_PORT_TRAP_GATE_3 = 175355, // Gate trap undead side + GO_PORT_TRAP_GATE_4 = 175354, }; enum MiscIds @@ -60,6 +67,12 @@ enum MiscIds EVENT_FORCE_SLAUGHTER_EVENT = 3, EVENT_SPAWN_BLACK_GUARD = 4, EVENT_EXECUTE_PRISONER = 5, + EVENT_GATE1_TRAP = 6, + EVENT_GATE1_DELAY = 7, + EVENT_GATE1_CRITTER_DELAY = 8, + EVENT_GATE2_TRAP = 9, + EVENT_GATE2_DELAY = 10, + EVENT_GATE2_CRITTER_DELAY = 11, SPELL_BARON_ULTIMATUM = 27861 }; diff --git a/src/worldserver/worldserver.conf.dist b/src/worldserver/worldserver.conf.dist index 6572a9d28..375643f80 100644 --- a/src/worldserver/worldserver.conf.dist +++ b/src/worldserver/worldserver.conf.dist @@ -1198,6 +1198,14 @@ Instance.IgnoreLevel = 0 Instance.IgnoreRaid = 0 +# +# Instance.GMSummonPlayer +# Description: Allow GM to summon players or only other GM accounts inside instances. +# Default: 0 - (Disabled, Only GM accounts can be summoned by GM) +# 1 - (Enabled, GM and Player accounts can be summoned by GM) + +Instance.GMSummonPlayer = 0 + # # Instance.ResetTimeHour # Description: Hour of the day when the global instance reset occurs.