diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..eb64e2f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +tab_width = 4 +insert_final_newline = true +trim_trailing_whitespace = true +max_line_length = 80 diff --git a/.gitattributes b/.gitattributes index eba1110..7ef9001 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,105 @@ -# Auto detect text files and perform LF normalization -* text=auto \ No newline at end of file +## AUTO-DETECT +## Handle line endings automatically for files detected as +## text and leave all files detected as binary untouched. +## This will handle all files NOT defined below. +* text=auto eol=lf + +# Text +*.conf text +*.conf.dist text +*.cmake text + +## Scripts +*.sh text +*.fish text +*.lua text + +## SQL +*.sql text + +## C++ +*.c text +*.cc text +*.cxx text +*.cpp text +*.c++ text +*.hpp text +*.h text +*.h++ text +*.hh text + + +## For documentation + +# Documents +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain + +## DOCUMENTATION +*.markdown text +*.md text +*.mdwn text +*.mdown text +*.mkd text +*.mkdn text +*.mdtxt text +*.mdtext text +*.txt text +AUTHORS text +CHANGELOG text +CHANGES text +CONTRIBUTING text +COPYING text +copyright text +*COPYRIGHT* text +INSTALL text +license text +LICENSE text +NEWS text +readme text +*README* text +TODO text + +## GRAPHICS +*.ai binary +*.bmp binary +*.eps binary +*.gif binary +*.ico binary +*.jng binary +*.jp2 binary +*.jpg binary +*.jpeg binary +*.jpx binary +*.jxr binary +*.pdf binary +*.png binary +*.psb binary +*.psd binary +*.svg text +*.svgz binary +*.tif binary +*.tiff binary +*.wbmp binary +*.webp binary + + +## ARCHIVES +*.7z binary +*.gz binary +*.jar binary +*.rar binary +*.tar binary +*.zip binary + +## EXECUTABLES +*.exe binary +*.pyc binary diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..5610d2b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,72 @@ +name: Bug report +description: Create a bug report to help us improve. +title: "Bug: " +body: + - type: textarea + id: current + attributes: + label: Current Behaviour + description: | + Description of the problem or issue here. + Include entries of affected creatures / items / quests / spells etc. + If this is a crash, post the crashlog (upload to https://gist.github.com/) and include the link here. + Never upload files! Use GIST for text and YouTube for videos! + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected Behaviour + description: | + Tell us what should happen instead. + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce the problem + description: | + What does someone else need to do to encounter the same bug? + placeholder: | + 1. Step 1 + 2. Step 2 + 3. Step 3 + validations: + required: true + - type: textarea + id: extra + attributes: + label: Extra Notes + description: | + Do you have any extra notes that can help solve the issue that does not fit any other field? + placeholder: | + None + validations: + required: false + - type: textarea + id: commit + attributes: + label: AC rev. hash/commit + description: | + Copy the result of the `.server debug` command (if you need to run it from the client get a prat addon) + validations: + required: true + - type: input + id: os + attributes: + label: Operating system + description: | + The Operating System the Server is running on. + i.e. Windows 11 x64, Debian 10 x64, macOS 12, Ubuntu 20.04 + validations: + required: true + - type: textarea + id: custom + attributes: + label: Custom changes or Modules + description: | + List which custom changes or modules you have applied, i.e. Eluna module, etc. + placeholder: | + None + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..58f79dd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,33 @@ +name: Feature request +description: Suggest an idea for this project +title: "Feature: " +body: + - type: markdown + attributes: + value: | + Thank you for taking your time to fill out a feature request. Remember to fill out all fields including the title above. + An issue that is not properly filled out will be closed. + - type: textarea + id: description + attributes: + label: Describe your feature request or suggestion in detail + description: | + A clear and concise description of what you want to happen. + validations: + required: true + - type: textarea + id: solution + attributes: + label: Describe a possible solution to your feature or suggestion in detail + description: | + A clear and concise description of any alternative solutions or features you've considered. + validations: + required: false + - type: textarea + id: additional + attributes: + label: Additional context + description: | + Add any other context or screenshots about the feature request here. + validations: + required: false diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 0000000..d8bf3ff --- /dev/null +++ b/.github/README.md @@ -0,0 +1,64 @@ +# ![logo](https://raw.githubusercontent.com/azerothcore/azerothcore.github.io/master/images/logo-github.png) AzerothCore + +## mod-solocraft + +- Latest build status with azerothcore: + +[![Build Status](https://github.com/azerothcore/mod-solocraft/workflows/core-build/badge.svg?branch=master&event=push)](https://github.com/azerothcore/mod-solocraft) + +## Description + +- Adjusts player stats for raids based on the # of players in the group +- Configurable debuff for groups trying to overload the difficulty modifier for an instance +- Adjustable stats modifier in config +- Config: Difficulty settings for each instance and type +- Now includes a Spellpower buff: Adjustable modifier in config +- Saves your modifier settings in database. +- Max level thresholds can be set to not buff players whose level is too far over the dungeon level + +## How to use ingame + +1. Enable in conf +2. Go into conf and set any features you want to enable or modify +3. Enter Dungeon or Raid + +## Requirements + +- AzerothCore v1.0.1+ + +## Installation + +``` +1) Simply place the module under the `modules` directory of your AzerothCore source. +2) Import the SQL to the right Database (character) +3) Re-run cmake and launch a clean build of AzerothCore. +``` + +## Edit module configuration (optional) + +If you need to change the module configuration, go to your server configuration folder (where your worldserver or worldserver.exe is), copy Solocraft.conf.dist to Solocraft.conf and edit that new file. + +### Data ### + +------------------------------------------------------------------------------------------------------------------ + +- Type: Server/Player +- Script: Solocraft +- Config: Yes +- SQL: Yes + +### Credits ### + +------------------------------------------------------------------------------------------------------------------ +- [DavidMacalaster](https://github.com/DavidMacalaster/Solocraft) +- [Blizzard Entertainment](http://blizzard.com) +- [TrinityCore](https://github.com/TrinityCore/TrinityCore/blob/3.3.5/THANKS) +- [SunwellCore](http://www.azerothcore.org/pages/sunwell.pl/) +- [EMUDevs](https://youtube.com/user/EmuDevs) +- [AC-Web](http://ac-web.org/) +- [ModCraft.io](http://modcraft.io/) +- [OwnedCore](http://ownedcore.com/) +- [OregonCore](https://wiki.oregon-core.net/) +- [Wowhead.com](http://wowhead.com) +- [AoWoW](https://wotlk.evowow.com/) +- AzerothCore: [repository](https://github.com/azerothcore) - [website](http://azerothcore.org/) - [discord chat community](https://discord.gg/PaqQRkd) diff --git a/.github/workflows/core-build.yml b/.github/workflows/core-build.yml new file mode 100644 index 0000000..a178aed --- /dev/null +++ b/.github/workflows/core-build.yml @@ -0,0 +1,11 @@ +name: core-build +on: + push: + pull_request: + workflow_dispatch: + +jobs: + build: + uses: azerothcore/reusable-workflows/.github/workflows/core_build_modules.yml@main + with: + module_repo: ${{ github.event.repository.name }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd7065f --- /dev/null +++ b/.gitignore @@ -0,0 +1,53 @@ +!.gitignore + +# +#Generic +# + +.directory +.mailmap +*.orig +*.rej +*.*~ +.hg/ +*.kdev* +.DS_Store +CMakeLists.txt.user +*.bak +*.patch +*.diff +*.REMOTE.* +*.BACKUP.* +*.BASE.* +*.LOCAL.* + +# +# IDE & other softwares +# +/.settings/ +/.externalToolBuilders/* +# exclude in all levels +nbproject/ +.sync.ffs_db +*.kate-swp + +# +# Eclipse +# +*.pydevproject +.metadata +.gradle +tmp/ +*.tmp +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.project +.cproject + +# +# Visual Studio Code +# +.vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 5f9604e..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ - -AC_ADD_SCRIPT("${CMAKE_CURRENT_LIST_DIR}/src/Solocraft.cpp") - -AC_ADD_SCRIPT_LOADER("Solocraft" "${CMAKE_CURRENT_LIST_DIR}/src/loader.h") - -CU_ADD_HOOK(AFTER_WORLDSERVER_CMAKE "${CMAKE_CURRENT_LIST_DIR}/src/cmake/after_ws_install.cmake") diff --git a/README.md b/README.md deleted file mode 100644 index f3a5b79..0000000 --- a/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# mod-solocraft - -## Solocraft module for AzerothCore. - -Solocraft creates a balance based on party size in the dungeons. - -# Original script: -https://github.com/DavidMacalaster/Solocraft \ No newline at end of file diff --git a/conf/Solocraft.conf.dist b/conf/Solocraft.conf.dist index 1d92375..75c4787 100644 --- a/conf/Solocraft.conf.dist +++ b/conf/Solocraft.conf.dist @@ -1,12 +1,453 @@ [worldserver] -# ################################################################################################### +# ____ __ ____ +# /\ _`\ /\ \__ __ /\ _`\ +# \ \,\L\_\ \ ,_\ __ __ __ /\_\ __ ___\ \ \/\_\ ___ _ __ __ +# \/_\__ \\ \ \/ /\ \/\ \ /'_ `\/\ \ /'__`\ /' _ `\ \ \/_/_ / __`\/\`'__\/'__`\ +# /\ \L\ \ \ \_\ \ \_\ \/\ \L\ \ \ \/\ \L\.\_/\ \/\ \ \ \L\ \/\ \L\ \ \ \//\ __/ +# \ `\____\ \__\\/`____ \ \____ \ \_\ \__/.\_\ \_\ \_\ \____/\ \____/\ \_\\ \____\ +# \/_____/\/__/ `/___/> \/___L\ \/_/\/__/\/_/\/_/\/_/\/___/ \/___/ \/_/ \/____/ +# /\___/ /\____/ +# \/__/ \_/__/ http://stygianthebest.github.io +################################################################################################### +# SOLOCRAFT +################################################################################################### + +# Enable the module? (1: true | 0: false) +Solocraft.Enable = 1 + +# Announce the module when the player logs in? +Solocraft.Announce = 1 + +################################################################################################### +# Balancing - Groups (Overloading), Global Spellpower and Stats modifier, Global Class Balancing, +# and XP Gain Balancing ################################################################################################### -# -# Solocraft.Enable -# Description: Solocraft is a script to increase players and bots stats in raids, -# based on group size. It feels a little Hacky, but raids is unfair hard with playerbots. -# Default: 0 -Solocraft.Enable = 0 +# Enable Debuff of new party members who enter the dungeon to avoid overloading the dungeon? +# Overloading is when a group member already in the dungeon has the full offset/buff of the +# dungeon applied then they invite new group members who enter the dungeon and also receive an +# offset which creates a huge imbalance. +# The debuff will make the new members weak until all members leave the instance/dungeon +# instance/dungeon and re-enter which will then split the offset among all the group members. + +# Default: 1 (on) +# 0 (off) +SoloCraft.Debuff.Enable = 1 + + +# Spellpower Bonus Multiplier +# Spellcasters spellpower bonus multiplier to offset no spellpower received from stats +# Formula: (player->level * multiplier) * ((classBalance / 100) * difficulty) +# Example Level 24 Mage with default modifier and a dungeon difficulty of 5 will receive a base +# Spellpower increase of 300. + +# Default: 2.5 +# 0.0 (Disable) +SoloCraft.Spellpower.Mult = 2.5 + + +# Stats Percentage Bonus Multiplier +# Forumla: player->Stats * (((classBalance / 100) * difficulty) * multiplier) + +# Default: 100.0 +# 0.0 (Disable) +SoloCraft.Stats.Mult = 100.0 + + +# Class Balancing Modifier +# This settings will only allow the percentage specified of the difficulty for the specified class +# Example Level 24 Mage with default modifier (2.5), a dungeon difficulty of 5, and a 80 percent class +# balance modifier will receive a base Spellpower increase of 240. +# Note: 0 will completely disable the class from receiving difficulty modifiers from any dungeon + +#Default: 100 (Full Dungeon Difficulty Modifer will be Applied) +# 0 (Disable) - 100 + +SoloCraft.DEATH_KNIGHT = 100 +SoloCraft.DRUID = 100 +SoloCraft.HUNTER = 100 +SoloCraft.MAGE = 100 +SoloCraft.PALADIN = 100 +SoloCraft.PRIEST = 100 +SoloCraft.ROGUE = 100 +SoloCraft.SHAMAN = 100 +SoloCraft.WARLOCK = 100 +SoloCraft.WARRIOR = 100 + + +# XP Gain +# This settings will Enable/Disable XP gained while in the current dungeon + +#Default: 1 (Enabled) +# 0 (Disable) + +Solocraft.XP.Enabled = 1 + + +# XP Balancing (XP Gain must be Enabled) +# This settings will decrease the XP gained based on the Difficulty setting of the dungeon +# and how many players are in the group. + +#Default: 1 (Enabled) +# 0 (Disable) + +Solocraft.XPBal.Enabled = 1 + + +################################################################################################ +#Catch all Bucket - Difficulty Offset Defaults +################################################################################################ + +# Difficulty Multipliers +# Defaults: 5, 10, 25, 40 +Solocraft.Dungeon = 5.0 +Solocraft.Heroic = 10.0 +Solocraft.Raid25 = 25.0 +Solocraft.Raid40 = 40.0 + + +################################################################################################ +#Classic Instances - Difficulty +################################################################################################ + +Solocraft.ShadowfangKeep = 5.0 +Solocraft.Stockades = 5.0 +Solocraft.Deadmines = 5.0 +Solocraft.WailingCaverns = 5.0 +Solocraft.RazorfenKraulInstance = 5.0 +Solocraft.Blackfathom = 5.0 +Solocraft.Uldaman = 5.0 +Solocraft.GnomeragonInstance = 5.0 +Solocraft.SunkenTemple = 5.0 +Solocraft.RazorfenDowns = 5.0 +# Scarlet Monastery +Solocraft.MonasteryInstances = 5.0 +# Zul'Farrak +Solocraft.TanarisInstance = 5.0 +Solocraft.BlackRockSpire = 10.0 +Solocraft.BlackrockDepths = 5.0 +Solocraft.OnyxiaLairInstance = 40.0 +#Scholomance +Solocraft.SchoolofNecromancy = 5.0 +Solocraft.Zul'gurub = 20.0 +Solocraft.Stratholme = 5.0 +Solocraft.Mauradon = 5.0 +# Ragefire Chasm +Solocraft.OrgrimmarInstance = 5.0 +Solocraft.MoltenCore = 40.0 +Solocraft.DireMaul = 5.0 +Solocraft.BlackwingLair = 40.0 +# Ruins of Ahn'Qiraj +Solocraft.AhnQiraj = 20.0 +Solocraft.AhnQirajTemple = 40.0 + + +################################################################################################ +#BC Instances - Difficulty +################################################################################################ + +# The Black Morass +Solocraft.CavernsOfTime = 5.0 +Solocraft.CavernsOfTimeH = 5.0 +Solocraft.Karazahn = 10.0 +# The Battle for Mount Hyjal - Hyjal Summit +Solocraft.HyjalPast = 25.0 +# The Shattered Halls +Solocraft.HellfireMilitary = 5.0 +Solocraft.HellfireMilitaryH = 5.0 +# The Blood Furnace +Solocraft.HellfireDemon = 5.0 +Solocraft.HellfireDemonH = 5.0 +Solocraft.HellfireRampart = 5.0 +Solocraft.HellfireRampartH = 5.0 +# Magtheridon's Lair +Solocraft.HellfireRaid = 25.0 +# The Steamvault +Solocraft.CoilfangPumping = 5.0 +Solocraft.CoilfangPumpingH = 5.0 +# The Underbog +Solocraft.CoilfangMarsh = 5.0 +Solocraft.CoilfangMarshH = 5.0 +# The Slavepens +Solocraft.CoilfangDraenei = 5.0 +Solocraft.CoilfangDraeneiH = 5.0 +# Serpentshrine Cavern +Solocraft.CoilfangRaid = 25.0 +# The Eye +Solocraft.TempestKeepRaid = 25.0 +# The Arcatraz +Solocraft.TempestKeepArcane = 5.0 +Solocraft.TempestKeepArcaneH = 5.0 +# The Botanica +Solocraft.TempestKeepAtrium = 5.0 +Solocraft.TempestKeepAtriumH = 5.0 +# The Mechanar +Solocraft.TempestKeepFactory = 5.0 +Solocraft.TempestKeepFactoryH = 5.0 +# Shadow Labyrinth +Solocraft.AuchindounShadow = 5.0 +Solocraft.AuchindounShadowH = 5.0 +# Sethekk Halls +Solocraft.AuchindounDemon = 5.0 +Solocraft.AuchindounDemonH = 5.0 +# Mana-Tombs +Solocraft.AuchindounEthereal = 5.0 +Solocraft.AuchindounEtherealH = 5.0 +# Auchenai Crypts +Solocraft.AuchindounDraenei = 5.0 +Solocraft.AuchindounDraeneiH = 5.0 +# Old Hillsbrad Foothills +Solocraft.HillsbradPast = 5.0 +Solocraft.HillsbradPastH = 5.0 +Solocraft.BlackTemple = 25.0 +Solocraft.GruulsLair = 25.0 +Solocraft.ZulAman = 5.0 +Solocraft.ZulAmanH = 5.0 +Solocraft.SunwellPlateau = 25.0 +# Magister's Terrace +Solocraft.Sunwell5ManFix = 5.0 +Solocraft.Sunwell5ManFixH = 5.0 + + +################################################################################################ +#WOTLK Instances - Difficulty +################################################################################################ + +# Naxxramas +Solocraft.StratholmeRaid = 10.0 +Solocraft.StratholmeRaidH = 25.0 +# Utgarde Keep +Solocraft.Valgarde70 = 5.0 +Solocraft.Valgarde70H = 5.0 +Solocraft.UtgardePinnacle = 5.0 +Solocraft.UtgardePinnacleH = 5.0 +# The Nexus +Solocraft.Nexus70 = 5.0 +Solocraft.Nexus70H = 5.0 +# The Occulus +Solocraft.Nexus80 = 5.0 +Solocraft.Nexus80H = 5.0 +# The Culling of Stratholme +Solocraft.StratholmeCOT = 5.0 +Solocraft.StratholmeCOTH = 5.0 +# Halls of Stone +Solocraft.Ulduar70 = 5.0 +Solocraft.Ulduar70H = 5.0 +# Drak'Tharon Keep +Solocraft.DrakTheronKeep = 5.0 +Solocraft.DrakTheronKeepH = 5.0 +# Azjol-Nerub +Solocraft.Azjol_Uppercity = 5.0 +Solocraft.Azjol_UppercityH = 5.0 +# Halls of Lighting +Solocraft.Ulduar80 = 5.0 +Solocraft.Ulduar80H = 5.0 +# Ulduar +Solocraft.UlduarRaid = 10.0 +Solocraft.UlduarRaidH = 25.0 +Solocraft.GunDrak = 5.0 +Solocraft.GunDrakH = 5.0 +# Violet Hold +Solocraft.DalaranPrison = 5.0 +Solocraft.DalaranPrisonH = 5.0 +# The Obsidian Sanctum +Solocraft.ChamberOfAspectsBlack = 10.0 +Solocraft.ChamberOfAspectsBlackH = 25.0 +# The Eye of Eternity +Solocraft.NexusRaid = 10.0 +Solocraft.NexusRaidH = 25.0 +# Ahn'kahet: The Old Kingdom +Solocraft.Azjol_LowerCity = 5.0 +Solocraft.Azjol_LowerCityH = 5.0 +Solocraft.IcecrownCitadel = 10.0 +Solocraft.IcecrownCitadelH = 25.0 +# The Forge of Souls +Solocraft.IcecrownCitadel5Man = 5.0 +Solocraft.IcecrownCitadel5ManH = 5.0 +# Trial of the Crusader +Solocraft.ArgentTournamentRaid = 10.0 +Solocraft.ArgentTournamentRaidH = 25.0 +# Grand Trial of the Crusader Heroic +Solocraft.ArgentTournamentRaidH10 = 10.0 +Solocraft.ArgentTournamentRaidH25 = 25.0 +# Trial of the Champion +Solocraft.ArgentTournamentDungeon = 5.0 +Solocraft.ArgentTournamentDungeonH = 5.0 +# Pit of Saron +Solocraft.QuarryOfTears = 5.0 +Solocraft.QuarryOfTearsH = 5.0 +# Halls of Reflection +Solocraft.HallsOfReflection = 5.0 +Solocraft.HallsOfReflectionH = 5.0 +# The Ruby Sanctum +Solocraft.ChamberOfAspectsRed = 5.0 +Solocraft.ChamberOfAspectsRedH = 5.0 + + +################################################################################################ +#Player Level Thresholds +################################################################################################ + +#Max player level difference over the Dungeon's Level for Solocraft to apply the +# difficulty offset buff. +# Default: 10 +# Disable: 80 +Solocraft.Max.Level.Diff = 10 + + +################################################################################################ +#Dungeon Base Levels +################################################################################################ + +#Catch All - Default 80 +Solocraft.Dungeon.Level = 80 + + +################################################################################################ +#Classic Instances - Base Level +################################################################################################ + +Solocraft.ShadowfangKeep.Level = 15 +Solocraft.Stockades.Level = 22 +Solocraft.Deadmines.Level = 18 +Solocraft.WailingCaverns.Level = 17 +Solocraft.RazorfenKraulInstance.Level = 30 +Solocraft.Blackfathom.Level = 20 +Solocraft.Uldaman.Level = 40 +Solocraft.GnomeragonInstance.Level = 24 +Solocraft.SunkenTemple.Level = 50 +Solocraft.RazorfenDowns.Level = 40 +# Scarlet Monastery +Solocraft.MonasteryInstances.Level = 35 +# Zul'Farrak +Solocraft.TanarisInstance.Level = 44 +Solocraft.BlackRockSpire.Level = 55 +Solocraft.BlackrockDepths.Level = 50 +Solocraft.OnyxiaLairInstance.Level = 60 +#Scholomance +Solocraft.SchoolofNecromancy.Level = 55 +Solocraft.Zul'gurub.Level = 60 +Solocraft.Stratholme.Level = 55 +Solocraft.Mauradon.Level = 48 +# Ragefire Chasm +Solocraft.OrgrimmarInstance.Level = 15 +Solocraft.MoltenCore.Level = 60 +Solocraft.DireMaul.Level = 48 +Solocraft.BlackwingLair.Level = 60 +# Ruins of Ahn'Qiraj +Solocraft.AhnQiraj.Level = 60 +Solocraft.AhnQirajTemple.Level = 60 + + +################################################################################################ +#BC Instances - Base Level +################################################################################################ + +# The Black Morass +Solocraft.CavernsOfTime.Level = 68 +Solocraft.Karazahn.Level = 68 +# The Battle for Mount Hyjal - Hyjal Summit +Solocraft.HyjalPast.Level = 70 +# The Shattered Halls +Solocraft.HellfireMilitary.Level = 68 +# The Blood Furnace +Solocraft.HellfireDemon.Level = 68 +Solocraft.HellfireRampart.Level = 68 +# Magtheridon's Lair +Solocraft.HellfireRaid.Level = 68 +# The Steamvault +Solocraft.CoilfangPumping.Level = 68 +# The Underbog +Solocraft.CoilfangMarsh.Level = 68 +# The Slavepens +Solocraft.CoilfangDraenei.Level = 68 +# Serpentshrine Cavern +Solocraft.CoilfangRaid.Level = 70 +# The Eye +Solocraft.TempestKeepRaid.Level = 70 +# The Arcatraz +Solocraft.TempestKeepArcane.Level = 68 +# The Botanica +Solocraft.TempestKeepAtrium.Level = 68 +# The Mechanar +Solocraft.TempestKeepFactory.Level = 68 +# Shadow Labyrinth +Solocraft.AuchindounShadow.Level = 68 +# Sethekk Halls +Solocraft.AuchindounDemon.Level = 68 +# Mana-Tombs +Solocraft.AuchindounEthereal.Level = 68 +# Auchenai Crypts +Solocraft.AuchindounDraenei.Level = 68 +# Old Hillsbrad Foothills +Solocraft.HillsbradPast.Level = 68 +Solocraft.BlackTemple.Level = 70 +Solocraft.GruulsLair.Level = 70 +Solocraft.ZulAman.Level = 68 +Solocraft.SunwellPlateau.Level = 70 +# Magister's Terrace +Solocraft.Sunwell5ManFix.Level = 68 + + +################################################################################################ +#WOTLK Instances - Base Level +################################################################################################ + +# Naxxramas +Solocraft.StratholmeRaid.Level = 78 +# Utgarde Keep +Solocraft.Valgarde70.Level = 78 +Solocraft.UtgardePinnacle.Level = 78 +# The Nexus +Solocraft.Nexus70.Level = 78 +# The Occulus +Solocraft.Nexus80.Level = 78 +# The Culling of Stratholme +Solocraft.StratholmeCOT.Level = 78 +# Halls of Stone +Solocraft.Ulduar70.Level = 78 +# Drak'Tharon Keep +Solocraft.DrakTheronKeep.Level = 78 +# Azjol-Nerub +Solocraft.Azjol_Uppercity.Level = 78 +# Halls of Lighting +Solocraft.Ulduar80.Level = 78 +# Ulduar +Solocraft.UlduarRaid.Level = 80 +Solocraft.GunDrak.Level = 78 +# Violet Hold +Solocraft.DalaranPrison.Level = 78 +# The Obsidian Sanctum +Solocraft.ChamberOfAspectsBlack.Level = 80 +# The Eye of Eternity +Solocraft.NexusRaid.Level = 80 +# Ahn'kahet: The Old Kingdom +Solocraft.Azjol_LowerCity.Level = 78 +#Icecrown Citadel +Solocraft.IcecrownCitadel.Level = 80 +# The Forge of Souls +Solocraft.IcecrownCitadel5Man.Level = 78 +# Trial of the Champion +Solocraft.ArgentTournamentDungeon.Level = 80 +# Trial of the Crusader +Solocraft.ArgentTournamentRaid.Level = 80 +# Pit of Saron +Solocraft.QuarryOfTears.Level = 78 +# Halls of Reflection +Solocraft.HallsOfReflection.Level = 78 +# The Ruby Sanctum +Solocraft.ChamberOfAspectsRed.Level = 80 + +################################################################################################### +# Misc +################################################################################################### + +# Map excluded +# This settings excludes some maps from the Solocraft instance scaling + +# Example: +# Solocraft.Instance.Excluded = "30,489,529,559,562,566,572,607,617,618,628" +# This example excludes scaling in PvP BG & Arena maps +Solocraft.Instance.Excluded = "" diff --git a/data/.gitkeep b/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/sql/.gitkeep b/data/sql/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/sql/db-characters/mod_solo_craft.sql b/data/sql/db-characters/mod_solo_craft.sql new file mode 100644 index 0000000..70c12e1 --- /dev/null +++ b/data/sql/db-characters/mod_solo_craft.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS `custom_solocraft_character_stats` ( + `GUID` bigint unsigned NOT NULL, + `Difficulty` float NOT NULL, + `GroupSize` int NOT NULL, + `SpellPower` int unsigned NOT NULL DEFAULT '0', + `Stats` float NOT NULL DEFAULT '100', + PRIMARY KEY (`GUID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; diff --git a/pull_request_template.md b/pull_request_template.md new file mode 100644 index 0000000..21c9245 --- /dev/null +++ b/pull_request_template.md @@ -0,0 +1,25 @@ + + +## Changes Proposed: +- +- + +## Issues Addressed: + +- Closes + +## SOURCE: + + +## Tests Performed: + +- +- + + +## How to Test the Changes: + + +1. +2. +3. diff --git a/src/SC_loader.cpp b/src/SC_loader.cpp new file mode 100644 index 0000000..5be0f48 --- /dev/null +++ b/src/SC_loader.cpp @@ -0,0 +1,6 @@ +void AddSolocraftScripts(); + +void Addmod_solocraftScripts() +{ + AddSolocraftScripts(); +} diff --git a/src/Solocraft.cpp b/src/Solocraft.cpp index 01e4d99..1a2b350 100644 --- a/src/Solocraft.cpp +++ b/src/Solocraft.cpp @@ -1,5 +1,5 @@ #include - +#include "Log.h" #include "Config.h" #include "ScriptMgr.h" #include "Unit.h" @@ -8,126 +8,739 @@ #include "Map.h" #include "Group.h" #include "InstanceScript.h" +#include "Chat.h" +#include +#include +#include "ObjectGuid.h" +#include "utils/Utils.h" +#include +#include +#include +#include -/* - * TODO: - * 1. Dispel target regeneration - * 2. Provide unlimited http://www.wowhead.com/item=17333/aqual-quintessence - */ +bool SoloCraftEnable = 1; +bool SoloCraftAnnounceModule = 1; +bool SoloCraftDebuffEnable = 1; +bool SolocraftXPBalEnabled = 1; +bool SolocraftXPEnabled = 1; +bool SolocraftNoXPFlag = 0; +float SoloCraftSpellMult = 1.0; +float SoloCraftStatsMult = 100.0; +float SoloCraftXPMod = 1.0; +uint32 SolocraftLevelDiff = 1; +uint32 SolocraftDungeonLevel = 1; +std::unordered_map classes; +std::unordered_map dungeons; +std::unordered_map diff_Multiplier; +std::unordered_map diff_Multiplier_Heroics; +std::vector SolocraftInstanceExcluded; -namespace { +float D5 = 1.0; +float D10 = 1.0; +float D25 = 1.0; +float D40 = 1.0; +float D649H10 = 1.0; +float D649H25 = 1.0; -class solocraft_player_instance_handler : public PlayerScript { +class SolocraftConfig : public WorldScript +{ public: - solocraft_player_instance_handler() : PlayerScript("solocraft_player_instance_handler") { - sLog->outString("scripts.solocraft.player.instance", "[Solocraft] solocraft_player_instance_handler Loaded"); - } - - void OnLogin(Player *player) override { - if (sConfigMgr->GetBoolDefault("Solocraft.Enable", true)) - { - ChatHandler(player->GetSession()).SendSysMessage("This server is running a Solocraft Module."); - } - } - - void OnMapChanged(Player *player) override { - if (sConfigMgr->GetBoolDefault("Solocraft.Enable", true)) { - Map *map = player->GetMap(); - int difficulty = CalculateDifficulty(map, player); - int numInGroup = GetNumInGroup(player); - ApplyBuffs(player, map, difficulty, numInGroup); - } - } -private: - std::map _unitDifficulty; - - int CalculateDifficulty(Map *map, Player *player) { - int difficulty = 1; - if (map) { - if (map->Is25ManRaid()) { - difficulty = 25; - } else if (map->IsHeroic()) { - difficulty = 10; - } else if (map->IsRaid()) { - difficulty = 40; - } else if (map->IsDungeon()) { - difficulty = 5; - } - } - return difficulty; - } - - int GetNumInGroup(Player *player) { - int numInGroup = 1; - Group *group = player->GetGroup(); - if (group) { - Group::MemberSlotList const& groupMembers = group->GetMemberSlots(); - numInGroup = groupMembers.size(); - } - return numInGroup; - } - - void ApplyBuffs(Player *player, Map *map, int difficulty, int numInGroup) { - ClearBuffs(player, map); - if (difficulty > 1) { - //InstanceMap *instanceMap = map->ToInstanceMap(); - //InstanceScript *instanceScript = instanceMap->GetInstanceScript(); - - ChatHandler(player->GetSession()).PSendSysMessage("Entered %s (difficulty = %d, numInGroup = %d)", - map->GetMapName(), difficulty, numInGroup); - - _unitDifficulty[player->GetGUID()] = difficulty; - for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) { - player->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(difficulty * 100), true); - } - player->SetFullHealth(); - if (player->getPowerType() == POWER_MANA) { - player->SetPower(POWER_MANA, player->GetMaxPower(POWER_MANA)); - } - } - } - - void ClearBuffs(Player *player, Map *map) { - std::map::iterator unitDifficultyIterator = _unitDifficulty.find(player->GetGUID()); - if (unitDifficultyIterator != _unitDifficulty.end()) { - int difficulty = unitDifficultyIterator->second; - _unitDifficulty.erase(unitDifficultyIterator); - - ChatHandler(player->GetSession()).PSendSysMessage("Left to %s (removing difficulty = %d)", - map->GetMapName(), difficulty); - - for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) { - player->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(difficulty * 100), false); - } - } - } -}; + SolocraftConfig() : WorldScript("SolocraftConfig") {} -} + void OnBeforeConfigLoad(bool /*reload*/) override + { + // Load Configuration Settings + SetInitialWorldSettings(); + } + + // Load Configuration Settings + void SetInitialWorldSettings() + { + SoloCraftEnable = sConfigMgr->GetOption("Solocraft.Enable", 1); + SoloCraftAnnounceModule = sConfigMgr->GetOption("Solocraft.Announce", 1); + + //Balancing + SoloCraftDebuffEnable = sConfigMgr->GetOption("SoloCraft.Debuff.Enable", 1); + SoloCraftSpellMult = sConfigMgr->GetOption("SoloCraft.Spellpower.Mult", 2.5); + SoloCraftStatsMult = sConfigMgr->GetOption("SoloCraft.Stats.Mult", 100.0); + classes = + { + {1, sConfigMgr->GetOption("SoloCraft.WARRIOR", 100) }, + {2, sConfigMgr->GetOption("SoloCraft.PALADIN", 100) }, + {3, sConfigMgr->GetOption("SoloCraft.HUNTER", 100) }, + {4, sConfigMgr->GetOption("SoloCraft.ROGUE", 100) }, + {5, sConfigMgr->GetOption("SoloCraft.PRIEST", 100) }, + {6, sConfigMgr->GetOption("SoloCraft.DEATH_KNIGHT", 100) }, + {7, sConfigMgr->GetOption("SoloCraft.SHAMAN", 100) }, + {8, sConfigMgr->GetOption("SoloCraft.MAGE", 100) }, + {9, sConfigMgr->GetOption("SoloCraft.WARLOCK", 100) }, + {11, sConfigMgr->GetOption("SoloCraft.DRUID", 100) }, + }; + + //XP Enabled + SolocraftXPEnabled = sConfigMgr->GetOption("Solocraft.XP.Enabled", 1); + + //XP Balancing + SolocraftXPBalEnabled = sConfigMgr->GetOption("Solocraft.XPBal.Enabled", 1); + + //Level Thresholds + SolocraftLevelDiff = sConfigMgr->GetOption("Solocraft.Max.Level.Diff", 10); + + //Catch All Dungeon Level Threshold + SolocraftDungeonLevel = sConfigMgr->GetOption("Solocraft.Dungeon.Level", 80); + + // Dungeon Base Level + dungeons = + { + // Wow Classic + {33, sConfigMgr->GetOption("Solocraft.ShadowfangKeep.Level", 15) }, + {34, sConfigMgr->GetOption("Solocraft.Stockades.Level", 22) }, + {36, sConfigMgr->GetOption("Solocraft.Deadmines.Level", 18) }, + {43, sConfigMgr->GetOption("Solocraft.WailingCaverns.Level", 17) }, + {47, sConfigMgr->GetOption("Solocraft.RazorfenKraulInstance.Level", 30) }, + {48, sConfigMgr->GetOption("Solocraft.Blackfathom.Level", 20) }, + {70, sConfigMgr->GetOption("Solocraft.Uldaman.Level", 40) }, + {90, sConfigMgr->GetOption("Solocraft.GnomeragonInstance.Level", 24) }, + {109, sConfigMgr->GetOption("Solocraft.SunkenTemple.Level", 50) }, + {129, sConfigMgr->GetOption("Solocraft.RazorfenDowns.Level", 40) }, + {189, sConfigMgr->GetOption("Solocraft.MonasteryInstances.Level", 35) }, // Scarlet Monastery + {209, sConfigMgr->GetOption("Solocraft.TanarisInstance.Level", 44) }, // Zul'Farrak + {229, sConfigMgr->GetOption("Solocraft.BlackRockSpire.Level", 55) }, + {230, sConfigMgr->GetOption("Solocraft.BlackrockDepths.Level", 50) }, + {249, sConfigMgr->GetOption("Solocraft.OnyxiaLairInstance.Level", 60) }, + {289, sConfigMgr->GetOption("Solocraft.SchoolofNecromancy.Level", 55) }, // Scholomance + {309, sConfigMgr->GetOption("Solocraft.Zul'gurub.Level", 60) }, + {329, sConfigMgr->GetOption("Solocraft.Stratholme.Level", 55) }, + {349, sConfigMgr->GetOption("Solocraft.Mauradon.Level", 48) }, + {389, sConfigMgr->GetOption("Solocraft.OrgrimmarInstance.Level", 15) }, // Ragefire Chasm + {409, sConfigMgr->GetOption("Solocraft.MoltenCore.Level", 60) }, + {429, sConfigMgr->GetOption("Solocraft.DireMaul.Level", 48) }, + {469, sConfigMgr->GetOption("Solocraft.BlackwingLair.Level", 40) }, + {509, sConfigMgr->GetOption("Solocraft.AhnQiraj.Level", 60) }, // Ruins of Ahn'Qiraj + {531, sConfigMgr->GetOption("Solocraft.AhnQirajTemple.Level", 60) }, -class SolocraftWorld : public WorldScript + // BC Instances + {269, sConfigMgr->GetOption("Solocraft.CavernsOfTime.Level", 68) }, // The Black Morass + {532, sConfigMgr->GetOption("Solocraft.Karazahn.Level", 68) }, + {534, sConfigMgr->GetOption("Solocraft.HyjalPast.Level", 70) }, // The Battle for Mount Hyjal - Hyjal Summit + {540, sConfigMgr->GetOption("Solocraft.HellfireMilitary.Level", 68) }, // The Shattered Halls + {542, sConfigMgr->GetOption("Solocraft.HellfireDemon.Level", 68) }, // The Blood Furnace + {543, sConfigMgr->GetOption("Solocraft.HellfireRampart.Level", 68) }, + {544, sConfigMgr->GetOption("Solocraft.HellfireRaid.Level", 68) }, // Magtheridon's Lair + {545, sConfigMgr->GetOption("Solocraft.CoilfangPumping.Level", 68) }, // The Steamvault + {546, sConfigMgr->GetOption("Solocraft.CoilfangMarsh.Level", 68) }, // The Underbog + {547, sConfigMgr->GetOption("Solocraft.CoilfangDraenei.Level", 68) }, // The Slavepens + {548, sConfigMgr->GetOption("Solocraft.CoilfangRaid.Level", 70) }, // Serpentshrine Cavern + {550, sConfigMgr->GetOption("Solocraft.TempestKeepRaid.Level", 70) }, // The Eye + {552, sConfigMgr->GetOption("Solocraft.TempestKeepArcane.Level", 68) }, // The Arcatraz + {553, sConfigMgr->GetOption("Solocraft.TempestKeepAtrium.Level", 68) }, // The Botanica + {554, sConfigMgr->GetOption("Solocraft.TempestKeepFactory.Level", 68) }, // The Mechanar + {555, sConfigMgr->GetOption("Solocraft.AuchindounShadow.Level", 68) }, // Shadow Labyrinth + {556, sConfigMgr->GetOption("Solocraft.AuchindounDemon.Level", 68) }, // Sethekk Halls + {557, sConfigMgr->GetOption("Solocraft.AuchindounEthereal.Level", 68) }, // Mana-Tombs + {558, sConfigMgr->GetOption("Solocraft.AuchindounDraenei.Level", 68) }, // Auchenai Crypts + {560, sConfigMgr->GetOption("Solocraft.HillsbradPast.Level", 68) }, // Old Hillsbrad Foothills + {564, sConfigMgr->GetOption("Solocraft.BlackTemple.Level", 70) }, + {565, sConfigMgr->GetOption("Solocraft.GruulsLair.Level", 70) }, + {568, sConfigMgr->GetOption("Solocraft.ZulAman.Level", 68) }, + {580, sConfigMgr->GetOption("Solocraft.SunwellPlateau.Level", 70) }, + {585, sConfigMgr->GetOption("Solocraft.Sunwell5ManFix.Level", 68) }, // Magister's Terrace + + // WOTLK Instances + {533, sConfigMgr->GetOption("Solocraft.StratholmeRaid.Level", 78) }, // Naxxramas + {574, sConfigMgr->GetOption("Solocraft.Valgarde70.Level", 78) }, // Utgarde Keep + {575, sConfigMgr->GetOption("Solocraft.UtgardePinnacle.Level", 78) }, + {576, sConfigMgr->GetOption("Solocraft.Nexus70.Level", 78) }, // The Nexus + {578, sConfigMgr->GetOption("Solocraft.Nexus80.Level", 78) }, // The Occulus + {595, sConfigMgr->GetOption("Solocraft.StratholmeCOT.Level", 78) }, // The Culling of Stratholme + {599, sConfigMgr->GetOption("Solocraft.Ulduar70.Level", 78) }, // Halls of Stone + {600, sConfigMgr->GetOption("Solocraft.DrakTheronKeep.Level", 78) }, // Drak'Tharon Keep + {601, sConfigMgr->GetOption("Solocraft.Azjol_Uppercity.Level", 78) }, // Azjol-Nerub + {602, sConfigMgr->GetOption("Solocraft.Ulduar80.Level", 78) }, // Halls of Lighting + {603, sConfigMgr->GetOption("Solocraft.UlduarRaid.Level", 80) }, // Ulduar + {604, sConfigMgr->GetOption("Solocraft.GunDrak.Level", 78) }, + {608, sConfigMgr->GetOption("Solocraft.DalaranPrison.Level", 78) }, // Violet Hold + {615, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsBlack.Level", 80) }, // The Obsidian Sanctum + {616, sConfigMgr->GetOption("Solocraft.NexusRaid.Level", 80) }, // The Eye of Eternity + {619, sConfigMgr->GetOption("Solocraft.Azjol_LowerCity.Level", 78) }, // Ahn'kahet: The Old Kingdom + {631, sConfigMgr->GetOption("Solocraft.IcecrownCitadel.Level", 80) }, // Icecrown Citadel + {632, sConfigMgr->GetOption("Solocraft.IcecrownCitadel5Man.Level", 78) }, // The Forge of Souls + {649, sConfigMgr->GetOption("Solocraft.ArgentTournamentRaid.Level", 80) }, // Trial of the Crusader + {650, sConfigMgr->GetOption("Solocraft.ArgentTournamentDungeon.Level", 80) }, // Trial of the Champion + {658, sConfigMgr->GetOption("Solocraft.QuarryOfTears.Level", 78) }, // Pit of Saron + {668, sConfigMgr->GetOption("Solocraft.HallsOfReflection.Level", 78) }, // Halls of Reflection + {724, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsRed.Level", 80) }, // The Ruby Sanctum + }; + + // Dungeon Difficulty | Catch alls + D5 = sConfigMgr->GetOption("Solocraft.Dungeon", 5.0); + D10 = sConfigMgr->GetOption("Solocraft.Heroic", 10.0); + D25 = sConfigMgr->GetOption("Solocraft.Raid25", 25.0); + D40 = sConfigMgr->GetOption("Solocraft.Raid40", 40.0); + + diff_Multiplier = + { + // WOW Classic Instances + {33, sConfigMgr->GetOption("Solocraft.ShadowfangKeep", 5.0) }, + {34, sConfigMgr->GetOption("Solocraft.Stockades", 5.0) }, + {36, sConfigMgr->GetOption("Solocraft.Deadmines", 5.0) }, + {43, sConfigMgr->GetOption("Solocraft.WailingCaverns", 5.0) }, + {47, sConfigMgr->GetOption("Solocraft.RazorfenKraulInstance", 5.0) }, + {48, sConfigMgr->GetOption("Solocraft.Blackfathom", 5.0) }, + {70, sConfigMgr->GetOption("Solocraft.Uldaman", 5.0) }, + {90, sConfigMgr->GetOption("Solocraft.GnomeragonInstance", 5.0) }, + {109, sConfigMgr->GetOption("Solocraft.SunkenTemple", 5.0) }, + {129, sConfigMgr->GetOption("Solocraft.RazorfenDowns", 5.0) }, + {189, sConfigMgr->GetOption("Solocraft.MonasteryInstances", 5.0) }, // Scarlet + {209, sConfigMgr->GetOption("Solocraft.TanarisInstance", 5.0) }, // Zul'Farrak + {229, sConfigMgr->GetOption("Solocraft.BlackRockSpire", 10.0) }, + {230, sConfigMgr->GetOption("Solocraft.BlackrockDepths", 5.0) }, + {249, sConfigMgr->GetOption("Solocraft.OnyxiaLairInstance", 40.0) }, + {289, sConfigMgr->GetOption("Solocraft.SchoolofNecromancy", 5.0) }, // Scholo + {309, sConfigMgr->GetOption("Solocraft.Zul'gurub", 20.0) }, + {329, sConfigMgr->GetOption("Solocraft.Stratholme", 5.0) }, + {349, sConfigMgr->GetOption("Solocraft.Mauradon", 5.0) }, + {389, sConfigMgr->GetOption("Solocraft.OrgrimmarInstance", 5.0) }, // Ragefire + {409, sConfigMgr->GetOption("Solocraft.MoltenCore", 40.0) }, + {429, sConfigMgr->GetOption("Solocraft.DireMaul", 5.0) }, + {469, sConfigMgr->GetOption("Solocraft.BlackwingLair", 40.0) }, + {509, sConfigMgr->GetOption("Solocraft.AhnQiraj", 20.0) }, + {531, sConfigMgr->GetOption("Solocraft.AhnQirajTemple", 40.0) }, + + // BC Instances + {269, sConfigMgr->GetOption("Solocraft.CavernsOfTime", 5.0) }, // Black Morass + {532, sConfigMgr->GetOption("Solocraft.Karazahn", 10.0) }, + {534, sConfigMgr->GetOption("Solocraft.HyjalPast", 25.0) }, // Mount Hyjal + {540, sConfigMgr->GetOption("Solocraft.HellfireMilitary", 5.0) }, // The Shattered Halls + {542, sConfigMgr->GetOption("Solocraft.HellfireDemon", 5.0) }, // The Blood Furnace + {543, sConfigMgr->GetOption("Solocraft.HellfireRampart", 5.0) }, + {544, sConfigMgr->GetOption("Solocraft.HellfireRaid", 25.0) }, // Magtheridon's Lair + {545, sConfigMgr->GetOption("Solocraft.CoilfangPumping", 5.0) }, // The Steamvault + {546, sConfigMgr->GetOption("Solocraft.CoilfangMarsh", 5.0) }, // The Underbog + {547, sConfigMgr->GetOption("Solocraft.CoilfangDraenei", 5.0) }, // The Slavepens + {548, sConfigMgr->GetOption("Solocraft.CoilfangRaid", 25.0) }, // Serpentshrine Cavern + {550, sConfigMgr->GetOption("Solocraft.TempestKeepRaid", 25.0) }, // The Eye + {552, sConfigMgr->GetOption("Solocraft.TempestKeepArcane", 5.0) }, // The Arcatraz + {553, sConfigMgr->GetOption("Solocraft.TempestKeepAtrium", 5.0) }, // The Botanica + {554, sConfigMgr->GetOption("Solocraft.TempestKeepFactory", 5.0) }, // The Mechanar + {555, sConfigMgr->GetOption("Solocraft.AuchindounShadow", 5.0) }, // Shadow Labyrinth + {556, sConfigMgr->GetOption("Solocraft.AuchindounDemon", 5.0) }, // Sethekk Halls + {557, sConfigMgr->GetOption("Solocraft.AuchindounEthereal", 5.0) }, // Mana-Tombs + {558, sConfigMgr->GetOption("Solocraft.AuchindounDraenei", 5.0) }, // Auchenai Crypts + {560, sConfigMgr->GetOption("Solocraft.HillsbradPast", 5.0) }, // Old Hillsbrad Foothills + {564, sConfigMgr->GetOption("Solocraft.BlackTemple", 25.0) }, + {565, sConfigMgr->GetOption("Solocraft.GruulsLair", 25.0) }, + {568, sConfigMgr->GetOption("Solocraft.ZulAman", 5.0) }, + {580, sConfigMgr->GetOption("Solocraft.SunwellPlateau", 25.0) }, + {585, sConfigMgr->GetOption("Solocraft.Sunwell5ManFix", 5.0) }, // Magister's Terrace + + // WOTLK Instances + {533, sConfigMgr->GetOption("Solocraft.StratholmeRaid", 10.0) }, // Nax 10 + {574, sConfigMgr->GetOption("Solocraft.Valgarde70", 5.0) }, // Utgarde Keep + {575, sConfigMgr->GetOption("Solocraft.UtgardePinnacle", 5.0) }, + {576, sConfigMgr->GetOption("Solocraft.Nexus70", 5.0) }, // The Nexus + {578, sConfigMgr->GetOption("Solocraft.Nexus80", 5.0) }, // The Occulus + {595, sConfigMgr->GetOption("Solocraft.StratholmeCOT", 5.0) }, // The Culling of Stratholme + {599, sConfigMgr->GetOption("Solocraft.Ulduar70", 5.0) }, // Halls of Stone + {600, sConfigMgr->GetOption("Solocraft.DrakTheronKeep", 5.0) }, // Drak'Tharon Keep + {601, sConfigMgr->GetOption("Solocraft.Azjol_Uppercity", 5.0) }, // Azjol-Nerub + {602, sConfigMgr->GetOption("Solocraft.Ulduar80", 5.0) }, // Halls of Lighting + {603, sConfigMgr->GetOption("Solocraft.UlduarRaid", 10.0) }, // Ulduar 10 + {604, sConfigMgr->GetOption("Solocraft.GunDrak", 5.0) }, + {608, sConfigMgr->GetOption("Solocraft.DalaranPrison", 5.0) }, // Violet Hold + {615, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsBlack", 10.0) }, // The Obsidian Sanctum 10 + {616, sConfigMgr->GetOption("Solocraft.NexusRaid", 10.0) }, // The Eye of Eternity 10 + {619, sConfigMgr->GetOption("Solocraft.Azjol_LowerCity", 5.0) }, // Ahn'kahet: The Old Kingdom + {631, sConfigMgr->GetOption("Solocraft.IcecrownCitadel", 10.0) }, // Icecrown Citadel 10 + {632, sConfigMgr->GetOption("Solocraft.IcecrownCitadel5Man", 5.0) }, // The Forge of Souls + {649, sConfigMgr->GetOption("Solocraft.ArgentTournamentRaid", 10.0) }, // Trial of the Crusader 10 + {650, sConfigMgr->GetOption("Solocraft.ArgentTournamentDungeon", 5.0) }, // Trial of the Champion + {658, sConfigMgr->GetOption("Solocraft.QuarryOfTears", 5.0) }, // Pit of Saron + {668, sConfigMgr->GetOption("Solocraft.HallsOfReflection", 5.0) }, // Halls of Reflection + {724, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsRed", 10.0) }, // The Ruby Sanctum 10 + }; + + // Heroics + diff_Multiplier_Heroics = + { + // BC Instances Heroics + {269, sConfigMgr->GetOption("Solocraft.CavernsOfTimeH", 5.0) }, // Black Morass H + {540, sConfigMgr->GetOption("Solocraft.HellfireMilitaryH", 5.0) }, // The Shattered Halls H + {542, sConfigMgr->GetOption("Solocraft.HellfireDemonH", 5.0) }, // The Blood Furnace H + {543, sConfigMgr->GetOption("Solocraft.HellfireRampartH", 5.0) }, // Heroic + {545, sConfigMgr->GetOption("Solocraft.CoilfangPumpingH", 5.0) }, // The Steamvault + {546, sConfigMgr->GetOption("Solocraft.CoilfangMarshH", 5.0) }, // The Underbog + {547, sConfigMgr->GetOption("Solocraft.CoilfangDraeneiH", 5.0) }, // The Slavepens H + {552, sConfigMgr->GetOption("Solocraft.TempestKeepArcaneH", 5.0) }, // The Arcatraz H + {553, sConfigMgr->GetOption("Solocraft.TempestKeepAtriumH", 5.0) }, // The Botanica H + {554, sConfigMgr->GetOption("Solocraft.TempestKeepFactoryH", 5.0) }, // The Mechanar H + {555, sConfigMgr->GetOption("Solocraft.AuchindounShadowH", 5.0) }, // Shadow Labyrinth H + {556, sConfigMgr->GetOption("Solocraft.AuchindounDemonH", 5.0) }, // Sethekk Halls H + {557, sConfigMgr->GetOption("Solocraft.AuchindounEtherealH", 5.0) }, // Mana-Tombs H + {558, sConfigMgr->GetOption("Solocraft.AuchindounDraeneiH", 5.0) }, // Auchenai Crypts H + {560, sConfigMgr->GetOption("Solocraft.HillsbradPastH", 5.0) }, // Old Hillsbrad Foothills H + {568, sConfigMgr->GetOption("Solocraft.ZulAmanH", 5.0) }, // Zul'Aman H + {585, sConfigMgr->GetOption("Solocraft.Sunwell5ManFixH", 5.0) }, // Magister's Terrace H + + // WOTLK Instances Heroics + {533, sConfigMgr->GetOption("Solocraft.StratholmeRaidH", 25.0) }, // Naxxramas 25 + {574, sConfigMgr->GetOption("Solocraft.Valgarde70H", 5.0) }, // Utgarde Keep H + {575, sConfigMgr->GetOption("Solocraft.UtgardePinnacleH", 5.0) }, // Utgarde Pinnacle H + {576, sConfigMgr->GetOption("Solocraft.Nexus70H", 5.0) }, // The Nexus H + {578, sConfigMgr->GetOption("Solocraft.Nexus80H", 5.0) }, // The Occulus H + {595, sConfigMgr->GetOption("Solocraft.StratholmeCOTH", 5.0) }, // The Culling of Stratholme H + {599, sConfigMgr->GetOption("Solocraft.Ulduar70H", 5.0) }, // Halls of Stone H + {600, sConfigMgr->GetOption("Solocraft.DrakTheronKeepH", 5.0) }, // Drak'Tharon Keep H + {601, sConfigMgr->GetOption("Solocraft.Azjol_UppercityH", 5.0) }, // Azjol-Nerub H + {602, sConfigMgr->GetOption("Solocraft.Ulduar80H", 5.0) }, // Halls of Lighting H + {603, sConfigMgr->GetOption("Solocraft.UlduarRaidH", 25.0) }, // Ulduar 25 + {604, sConfigMgr->GetOption("Solocraft.GunDrakH", 5.0) }, // Gundrak H + {608, sConfigMgr->GetOption("Solocraft.DalaranPrisonH", 5.0) }, // Violet Hold H + {615, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsBlackH", 25.0) }, // The Obsidian Sanctum 25 + {616, sConfigMgr->GetOption("Solocraft.NexusRaidH", 25.0) }, // The Eye of Eternity 25 + {619, sConfigMgr->GetOption("Solocraft.Azjol_LowerCityH", 5.0) }, // Ahn'kahet: The Old Kingdom H + {631, sConfigMgr->GetOption("Solocraft.IcecrownCitadelH", 25.0) }, // Icecrown Citadel 25 + {632, sConfigMgr->GetOption("Solocraft.IcecrownCitadel5ManH", 5.0) }, // The Forge of Souls + {649, sConfigMgr->GetOption("Solocraft.ArgentTournamentRaidH", 25.0) }, // Trial of the Crusader 25 + {650, sConfigMgr->GetOption("Solocraft.ArgentTournamentDungeonH", 5.0) }, // Trial of the Champion H + {658, sConfigMgr->GetOption("Solocraft.QuarryOfTearsH", 5.0) }, // Pit of Saron H + {668, sConfigMgr->GetOption("Solocraft.HallsOfReflectionH", 5.0) }, // Halls of Reflection H + {724, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsRedH", 25.0) }, // The Ruby Sanctum 25 + }; + + //Unique Raids beyond the heroic and normal versions of themselves + D649H10 = sConfigMgr->GetOption("Solocraft.ArgentTournamentRaidH10", 10.0); //Trial of the Crusader 10 Heroic + D649H25 = sConfigMgr->GetOption("Solocraft.ArgentTournamentRaidH25", 25.0); //Trial of the Crusader 25 Heroic + + //Get from conf excluded map for Solocraft scaling + LoadList(sConfigMgr->GetOption("Solocraft.Instance.Excluded", ""), SolocraftInstanceExcluded); + } +}; + +class SolocraftAnnounce : public PlayerScript { +private: + std::map playerInInstanceMap; + public: - SolocraftWorld() : WorldScript("SolocraftWorld") { } + SolocraftAnnounce() : PlayerScript("SolocraftAnnounce") {} + + void OnLogin(Player* player) override + { + if (SoloCraftEnable && SoloCraftAnnounceModule) + { + ChatHandler(player->GetSession()).SendSysMessage("This server is running the |cff4CFF00SoloCraft |rmodule."); + } + } - void OnBeforeConfigLoad(bool reload) override + void OnLogout(Player* player) override { - if (!reload) { - std::string conf_path = _CONF_DIR; - std::string cfg_file = conf_path + "/Solocraft.conf"; -#ifdef WIN32 - cfg_file = "Solocraft.conf"; -#endif - std::string cfg_def_file = cfg_file +".dist"; - sConfigMgr->LoadMore(cfg_def_file.c_str()); + QueryResult result = CharacterDatabase.Query("SELECT `GUID` FROM `custom_solocraft_character_stats` WHERE `GUID`={}", player->GetGUID().GetCounter()); + if (result) + { + //Remove database entry as the player has logged out + CharacterDatabase.Execute("DELETE FROM `custom_solocraft_character_stats` WHERE `GUID`={}", player->GetGUID().GetCounter()); + } + playerInInstanceMap.erase(player->GetGUID()); + } - sConfigMgr->LoadMore(cfg_file.c_str()); + void OnMapChanged(Player* player) override + { + if (player->GetMap()->IsDungeon() || player->GetMap()->IsRaid()) + { + playerInInstanceMap[player->GetGUID()] = true; + } + else + { + playerInInstanceMap[player->GetGUID()] = false; + } + } + + void OnGiveXP(Player* player, uint32& amount, Unit* /*victim*/, uint8 /*xpSource*/) override + { + if (SolocraftXPBalEnabled && playerInInstanceMap[player->GetGUID()]) + { + // Decrease Experience based on number of players and difficulty of instance (0 to 100%) + amount = uint32(amount * SoloCraftXPMod); } } }; +class SolocraftPlayerInstanceHandler : public PlayerScript +{ +public: + SolocraftPlayerInstanceHandler() : PlayerScript("SolocraftPlayerInstanceHandler") {} + + bool IsInSolocraftInstanceExcludedList(uint32 id) + { + return find(SolocraftInstanceExcluded.begin(), SolocraftInstanceExcluded.end(), id) != SolocraftInstanceExcluded.end(); + } + + void OnMapChanged(Player* player) override + { + if (sConfigMgr->GetOption("Solocraft.Enable", true)) + { + Map* map = player->GetMap(); + float difficulty = CalculateDifficulty(map); + uint32 dunLevel = CalculateDungeonLevel(map); + uint32 numInGroup = GetNumInGroup(player); + uint32 classBalance = GetClassBalance(player); + ApplyBuffs(player, map, difficulty, dunLevel, numInGroup, classBalance); + } + } + + // Set the instance difficulty + float CalculateDifficulty(Map* map) + { + if (map) + { + if (IsInSolocraftInstanceExcludedList(map->GetId())) + { + return 0; + } + + if (map->Is25ManRaid()) + { + if (map->IsHeroic() && map->GetId() == 649) + { + return D649H25; + } + else if (diff_Multiplier_Heroics.find(map->GetId()) == diff_Multiplier_Heroics.end()) + { + return D25; + } + else + return diff_Multiplier_Heroics[map->GetId()]; + } + + if (map->IsHeroic()) + { + if (map->GetId() == 649) + { + return D649H10; + } + else if (diff_Multiplier_Heroics.find(map->GetId()) == diff_Multiplier_Heroics.end()) + { + return D10; + } + else + return diff_Multiplier_Heroics[map->GetId()]; + } + + if (diff_Multiplier.find(map->GetId()) == diff_Multiplier.end()) + { + if (map->IsDungeon()) + { + return D5; + } + else if (map->IsRaid()) + { + return D40; + } + } + else + return diff_Multiplier[map->GetId()]; + } + + return 0; + } + + // Set the Dungeon Level + uint32 CalculateDungeonLevel(Map* map) + { + if (dungeons.find(map->GetId()) == dungeons.end()) + { + return SolocraftDungeonLevel; + } + else + { + return dungeons[map->GetId()]; + } + } + + // Get the group's size + uint32 GetNumInGroup(Player* player) + { + uint32 numInGroup = 1; + Group* group = player->GetGroup(); + + if (group) + { + Group::MemberSlotList const& groupMembers = group->GetMemberSlots(); + numInGroup = groupMembers.size(); + } + + return numInGroup; + } + + // Get the Player's class balance debuff + uint32 GetClassBalance(Player* player) + { + uint32 classBalance = 100; + + if (classes.find(player->getClass()) == classes.end()) + { + return classBalance; + } + else if (classes[player->getClass()] >= 0 && classes[player->getClass()] <= 100) + { + return classes[player->getClass()]; + } + else + return classBalance; + } + + // Get the current group members GUIDS and return the total sum of the difficulty offset by all group members currently in the dungeon + float GetGroupDifficulty(Player* player) + { + float GroupDifficulty = 0.0; + Group* group = player->GetGroup(); + + if (group) + { + Group::MemberSlotList const& groupMembers = group->GetMemberSlots(); + for (Group::member_citerator itr = groupMembers.begin(); itr != groupMembers.end(); ++itr) + { + if (itr->guid != player->GetGUID()) + { + QueryResult result = CharacterDatabase.Query("SELECT `GUID`, `Difficulty`, `GroupSize` FROM `custom_solocraft_character_stats` WHERE `GUID`={}", itr->guid.GetCounter()); + if (result) + { + if ((*result)[1].Get() > 0) + { + GroupDifficulty = GroupDifficulty + (*result)[1].Get(); + } + } + } + } + } + + return GroupDifficulty; + } + + // Resets buffers + void ClearBuffs(Player* player) + { + //Database query to get offset from the last instance player exited + QueryResult result = CharacterDatabase.Query("SELECT `GUID`, `Difficulty`, `GroupSize`, `SpellPower`, `Stats` FROM `custom_solocraft_character_stats` WHERE `GUID`={}", player->GetGUID().GetCounter()); + uint32 SpellPowerBonus = 0; + + if (result) + { + float difficulty = (*result)[1].Get(); + SpellPowerBonus = (*result)[3].Get(); + float StatsMultPct = (*result)[4].Get(); + SoloCraftXPMod = 1.0; + + for (uint32 i = STAT_STRENGTH; i < MAX_STATS; ++i) + { + player->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, difficulty * StatsMultPct, false); + } + + if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN) && !SolocraftNoXPFlag) + { + player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); + } + + SolocraftNoXPFlag = 0; + CharacterDatabase.Execute("DELETE FROM custom_solocraft_character_stats WHERE GUID = {}", player->GetGUID().GetCounter()); + } + + if (player->getPowerType() == POWER_MANA || player->getClass() == CLASS_DRUID) + { + player->ApplySpellPowerBonus(SpellPowerBonus, false); + } + } + + // Apply the player buffs + void ApplyBuffs(Player* player, Map* map, float difficulty, int dunLevel, int numInGroup, int classBalance) + { + // Check whether to debuff back to normal or check to buff the player + if (difficulty == 0 || IsInSolocraftInstanceExcludedList(map->GetId())) + { + ClearBuffs(player); // Check to revert player back to normal - Moving this here fixed logout and login while in instance buff and debuff issues + } + else + { + std::ostringstream ss; + + int SpellPowerBonus = 0; + + // Check for an existing No XP Gain flag - other mod compatibility + if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN)) + { + SolocraftNoXPFlag = 1; + } + + // If a player is too high level for dungeon don't buff but if in a group will count towards the group offset balancing. + if (player->GetLevel() <= dunLevel + SolocraftLevelDiff) + { + + // Get Current members total difficulty offset and if it exceeds the difficulty offset of the dungeon then debuff new group members coming in until all members leave and re-enter. This happens when a player already inside dungeon invite others to the group but the player already has the full difficulty offset. + float GroupDifficulty = GetGroupDifficulty(player); + + // Check to either debuff or buff player entering dungeon. Debuff must be enabled in Config + if (GroupDifficulty >= difficulty && SoloCraftDebuffEnable == 1) + { + // Current dungeon offset exceeded - Debuff player modified by ClassBalance Adjustment + difficulty = (-abs(difficulty)) + ((((float)classBalance / 100) * difficulty) / numInGroup); + // Float variables suck + difficulty = roundf(difficulty * 100) / 100; + + // Disable player XP gain if debuff applied + if (!player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN) && SolocraftXPBalEnabled) + { + player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); + } + } + else + { + // Current Dungeon offset not exceeded - Buff player + // Group difficulty and ClassBalance Adjustment + difficulty = (((float)classBalance / 100) * difficulty) / numInGroup; + // Float variables suck - two decimal rounding + difficulty = roundf(difficulty * 100) / 100; + + // Set XP Modifier + SoloCraftXPMod = (1.04 / difficulty) - 0.02; + SoloCraftXPMod = roundf(SoloCraftXPMod * 100) / 100; + + // Check for negative XP modifier - Disable XP Gain + if (SoloCraftXPMod < 0) + { + SoloCraftXPMod = 0; + if (!player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN) && SolocraftXPBalEnabled) + { + player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); + } + } + + // Check XP modifier for over max limit and adjust + if (SoloCraftXPMod > 1) + { + SoloCraftXPMod = 1.0; + } + } + + // Check Database for a current dungeon entry + QueryResult result = CharacterDatabase.Query("SELECT `GUID`, `Difficulty`, `GroupSize`, `SpellPower`, `Stats` FROM `custom_solocraft_character_stats` WHERE `GUID`={}", player->GetGUID().GetCounter()); + + // Modify Player Stats + // STATS defined/enum in SharedDefines.h + for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) + { + // Check for Dungeon to Dungeon Transfer and remove old buff + if (result) + { + player->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, (*result)[1].Get() * (*result)[4].Get(), false); + } + // Buff the player + // Unitmods enum UNIT_MOD_STAT_START defined in Unit.h line 391 + player->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, difficulty * SoloCraftStatsMult, true); + + } -void AddSolocraftScripts() { - new SolocraftWorld(); - new solocraft_player_instance_handler(); + // Set player health + // Defined in Unit.h line 1524 + player->SetFullHealth(); + + if (player->IsExistPet()) + { + // Set Pet Health + player->CastSpell(player, 6962, true); + + } + + // Spellcaster Stat modify + if (player->getPowerType() == POWER_MANA || player->getClass() == CLASS_DRUID) + { + // Buff the player's mana + player->SetPower(POWER_MANA, player->GetMaxPower(POWER_MANA)); + + // Check for Dungeon to Dungeon Transfer and remove old Spellpower buff + if (result) + { + // remove spellpower bonus + player->ApplySpellPowerBonus((*result)[3].Get() * (*result)[4].Get(), false); + } + + // Buff Spellpower + // Debuffed characters do not get spellpower + if (difficulty > 0) + { + SpellPowerBonus = static_cast((player->GetLevel() * SoloCraftSpellMult) * difficulty); + player->ApplySpellPowerBonus(SpellPowerBonus, true); + } + } + + // XP Gain Disabled + if (!SolocraftXPEnabled) + { + SoloCraftXPMod = 0; + if (!player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN)) + { + player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); + } + } + + // Announcements + if (difficulty > 0) + { + // Announce to player - Buff + if (!SolocraftXPEnabled) + { + ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - Difficulty Offset: %0.2f. Spellpower Bonus: %i. Class Balance Weight: %i. XP Gain: |cffFF0000Disabled"; + ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), difficulty, SpellPowerBonus, classBalance); + } + else + { + if (!SolocraftXPBalEnabled) + { + ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - Difficulty Offset: %0.2f. Spellpower Bonus: %i. Class Balance Weight: %i. XP Balancing: |cffFF0000Disabled"; + ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), difficulty, SpellPowerBonus, classBalance); + } + else + { + ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - Difficulty Offset: %0.2f. Spellpower Bonus: %i. Class Balance Weight: %i. XP Balancing: |cff4CFF00Enabled"; + ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), difficulty, SpellPowerBonus, classBalance); + } + } + } + else + { + // Announce to player - Debuff + if (!SolocraftXPBalEnabled && SolocraftXPEnabled) + { + ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - |cffFF0000BE ADVISED - You have been debuffed by offset: %0.2f with a Class Balance Weight: %i. |cffFF8000 A group member already inside has the dungeon's full buff offset. No Spellpower buff will be applied to spell casters. ALL group members must exit the dungeon and re-enter to receive a balanced offset."; + ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), difficulty, classBalance); + } + else + { + ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - |cffFF0000BE ADVISED - You have been debuffed by offset: %0.2f with a Class Balance Weight: %i and no XP will be awarded. |cffFF8000 A group member already inside has the dungeon's full buff offset. No Spellpower buff will be applied to spell casters. ALL group members must exit the dungeon and re-enter to receive a balanced offset."; + ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), difficulty, classBalance); + } + } + + // Save Player Dungeon Offsets to Database + CharacterDatabase.Execute("REPLACE INTO custom_solocraft_character_stats (GUID, Difficulty, GroupSize, SpellPower, Stats) VALUES ({}, {}, {}, {}, {})", player->GetGUID().GetCounter(), difficulty, numInGroup, SpellPowerBonus, SoloCraftStatsMult); + } + else + { + // Announce to player - Over Max Level Threshold + ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - |cffFF0000You have not been buffed. |cffFF8000 Your level is higher than the max level (%i) threshold for this dungeon."; + ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), dunLevel + SolocraftLevelDiff); + ClearBuffs(player); // Check to revert player back to normal + } + } + } + +private: + std::map _unitDifficulty; +}; + +void AddSolocraftScripts() +{ + new SolocraftConfig(); + new SolocraftAnnounce(); + new SolocraftPlayerInstanceHandler(); } diff --git a/src/cmake/after_ws_install.cmake b/src/cmake/after_ws_install.cmake deleted file mode 100644 index 7bf3036..0000000 --- a/src/cmake/after_ws_install.cmake +++ /dev/null @@ -1,15 +0,0 @@ -if( WIN32 ) - if ( MSVC ) - add_custom_command(TARGET worldserver - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/modules/mod-solocraft/conf/Solocraft.conf.dist" ${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/ - ) - elseif ( MINGW ) - add_custom_command(TARGET worldserver - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/modules/mod-solocraft/conf/Solocraft.conf.dist" ${CMAKE_BINARY_DIR}/bin/ - ) - endif() -endif() - -install(FILES "${CMAKE_SOURCE_DIR}/modules/mod-solocraft/conf/Solocraft.conf.dist" DESTINATION ${CONF_DIR}) diff --git a/src/loader.h b/src/loader.h deleted file mode 100644 index bc367fe..0000000 --- a/src/loader.h +++ /dev/null @@ -1 +0,0 @@ -void AddSolocraftScripts(); diff --git a/src/utils/Utils.cpp b/src/utils/Utils.cpp new file mode 100644 index 0000000..c3b705e --- /dev/null +++ b/src/utils/Utils.cpp @@ -0,0 +1,16 @@ +#include "Utils.h" +#include +#include +#include +#include + +std::vector split(const std::string& str, char delimiter) { + std::vector res; + if (str.empty()) return res; + std::string token; + std::istringstream tokenStream(str); + while (std::getline(tokenStream, token, delimiter)) { + res.push_back(token); + } + return res; +} diff --git a/src/utils/Utils.h b/src/utils/Utils.h new file mode 100644 index 0000000..9b65574 --- /dev/null +++ b/src/utils/Utils.h @@ -0,0 +1,21 @@ +#ifndef UTILS_H +#define UTILS_H + +#include +#include +#include +#include +#include + +std::vector split(const std::string& str, char delimiter); + +template +void LoadList(const std::string& value, T& list) { + std::vector ids = split(value, ','); + for (const std::string& id_str : ids) { + uint32_t id = static_cast(std::atoi(id_str.c_str())); + list.push_back(id); + } +} + +#endif