Set Mount Price and Train Level

This patch will add the following parameters to the mangosd.conf configuration file:

MountCost                                 = 100000
TrainMountCost                            = 900000
MinTrainMountLevel                        = 40
EpicMountCost                             = 1000000
TrainEpicMountCost                        = 9000000
MinTrainEpicMountLevel                    = 60

and allow configuring the level of regular and epic mounts as well as the cost for training and the price of all mounts.

mount_settings.diff
From fad342064b06c87775902b0647f8439c0f46d241 Mon Sep 17 00:00:00 2001
From: [WaS] <office@grimore.org>
Date: Sun, 16 Mar 2014 22:46:23 +0000
Subject: [PATCH] Add the ability to specify in the configuration file the
 cost and the required level for training and acquiring both
 normal and epic mounts.
 
---
 src/game/ItemHandler.cpp            |   89 ++++++++++++++++++++++++++++++++++-
 src/game/NPCHandler.cpp             |   27 ++++++++++-
 src/game/Player.cpp                 |   18 ++++++-
 src/game/World.cpp                  |    7 +++
 src/game/World.h                    |    6 +++
 src/mangosd/mangosd.conf.dist.cmake |   30 ++++++++++++
 6 files changed, 171 insertions(+), 6 deletions(-)
 
diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp
index d1e4d06..21c5ac6 100644
--- a/src/game/ItemHandler.cpp
+++ b/src/game/ItemHandler.cpp
@@ -32,6 +32,7 @@
 #include "Item.h"
 #include "UpdateData.h"
 #include "Chat.h"
+#include "World.h"
 
 void WorldSession::HandleSplitItemOpcode(WorldPacket& recv_data)
 {
@@ -767,8 +768,92 @@ void WorldSession::SendListInventory(ObjectGuid vendorguid)
 
                 ++count;
 
-                // reputation discount
-                uint32 price = uint32(floor(pProto->BuyPrice * discountMod));
+                uint32 price = 0;
+                // check mounts
+                switch (itemId) {
+                    case 1132: //regular mounts
+                    case 2411:
+                    case 2414:
+                    case 5655:
+                    case 5656:
+                    case 5665:
+                    case 5668:
+                    case 5864:
+                    case 5872:
+                    case 5873:
+                    case 8563:
+                    case 8588:
+                    case 8591:
+                    case 8592:
+                    case 8595:
+                    case 8629:
+                    case 8631:
+                    case 8632:
+                    case 12325:
+                    case 12326:
+                    case 12327:
+                    case 13321:
+                    case 13322:
+                    case 13331:
+                    case 13332:
+                    case 13333:
+                    case 15277:
+                    case 15290:
+                    case 18241:
+                    case 18242:
+                    case 18243:
+                    case 18244:
+                    case 18245:
+                    case 18246:
+                    case 18247:
+                    case 18248:
+                        // apply discount and set price
+                        price = uint32(floor(AccountTypes(sWorld.getConfig(CONFIG_UINT32_MOUNT_COST)) * discountMod));
+                        break;
+                    case 12302: // epic mounts
+                    case 12303:
+                    case 12330:
+                    case 12351:
+                    case 12353:
+                    case 12354:
+                    case 13086:
+                    case 13326:
+                    case 13327:
+                    case 13328:
+                    case 13329:
+                    case 13334:
+                    case 13335:
+                    case 18766:
+                    case 18767:
+                    case 18768:
+                    case 18772:
+                    case 18773:
+                    case 18774:
+                    case 18776:
+                    case 18777:
+                    case 18778:
+                    case 18785:
+                    case 18786:
+                    case 18787:
+                    case 18788:
+                    case 18789:
+                    case 18790:
+                    case 18791:
+                    case 18793:
+                    case 18794:
+                    case 18795:
+                    case 18796:
+                    case 18797:
+                    case 18798:
+                    case 18902:
+                        // apply discount and set price
+                        price = uint32(floor(AccountTypes(sWorld.getConfig(CONFIG_UINT32_EPIC_MOUNT_COST)) * discountMod));
+                        break;
+                    default:
+                        // other items
+                        price = uint32(floor(pProto->BuyPrice * discountMod));
+                        break;
+                }
 
                 data << uint32(count);
                 data << uint32(itemId);
diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp
index 6875fdf..1b01de4 100644
--- a/src/game/NPCHandler.cpp
+++ b/src/game/NPCHandler.cpp
@@ -41,6 +41,7 @@
 #include "Spell.h"
 #include "GuildMgr.h"
 #include "Chat.h"
+#include "World.h"
 
 enum StableResultCode
 {
@@ -126,7 +127,18 @@ static void SendTrainerSpellHelper(WorldPacket& data, TrainerSpell const* tSpell
 
     data << uint32(tSpell->spell);
     data << uint8(state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state);
-    data << uint32(floor(tSpell->spellCost * fDiscountMod));
+    
+    switch (tSpell->spell) {
+        case 33389: // Apprentice Riding
+            data << uint32(floor(AccountTypes(sWorld.getConfig(CONFIG_UINT32_TRAIN_MOUNT_COST)) * fDiscountMod));
+            break;
+        case 33392: // Journeyman Riding
+            data << uint32(floor(AccountTypes(sWorld.getConfig(CONFIG_UINT32_TRAIN_EPIC_MOUNT_COST)) * fDiscountMod));
+            break;
+        default:
+            data << uint32(floor(tSpell->spellCost * fDiscountMod));
+            break;
+    }
 
     data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0);
     // primary prof. learn confirmation dialog
@@ -199,7 +211,18 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle)
             if (!_player->IsSpellFitByClassAndRace(tSpell->spell, &reqLevel))
                 { continue; }
 
-            reqLevel = tSpell->isProvidedReqLevel ? tSpell->reqLevel : std::max(reqLevel, tSpell->reqLevel);
+            // mount spells
+            switch (tSpell->spell) {
+                case 33389: // Apprentice Riding
+                    reqLevel = AccountTypes(sWorld.getConfig(CONFIG_UINT32_MIN_TRAIN_MOUNT_LEVEL));
+                    break;
+                case 33392: // Journeyman Riding
+                    reqLevel = AccountTypes(sWorld.getConfig(CONFIG_UINT32_MIN_TRAIN_EPIC_MOUNT_LEVEL));
+                    break;
+                default:
+                   reqLevel = tSpell->isProvidedReqLevel ? tSpell->reqLevel : std::max(reqLevel, tSpell->reqLevel);
+                   break;
+            }
 
             TrainerSpellState state = _player->GetTrainerSpellState(tSpell, reqLevel);
 
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 7ceb86b..877f920 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -18157,8 +18157,22 @@ bool Player::IsSpellFitByClassAndRace(uint32 spell_id, uint32* pReqlevel /*= NUL
                 }
                 else                                        // check availble case at train
                 {
-                    if (skillRCEntry->reqLevel && getLevel() < skillRCEntry->reqLevel)
-                        { return false; }
+                    switch (spell_id) {
+                        case 33388: // Riding 
+                        case 33389: // Apprentice Riding
+                            if (getLevel() < AccountTypes(sWorld.getConfig(CONFIG_UINT32_MIN_TRAIN_MOUNT_LEVEL)))
+                                { return false; }
+                            break;
+                        case 33391: // Riding
+                        case 33392: // Journeyman Riding
+                            if (getLevel() < AccountTypes(sWorld.getConfig(CONFIG_UINT32_MIN_TRAIN_EPIC_MOUNT_LEVEL)))
+                                { return false; }
+                            break;
+                        default:
+                            if (skillRCEntry->reqLevel && getLevel() < skillRCEntry->reqLevel)
+                                { return false; }
+                            break;
+                    }
                 }
             }
         }
diff --git a/src/game/World.cpp b/src/game/World.cpp
index 49d2f25..40d95b0 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -587,6 +587,13 @@ void World::LoadConfigSettings(bool reload)
 
     setConfig(CONFIG_BOOL_ALL_TAXI_PATHS, "AllFlightPaths", false);
 
+    setConfig(CONFIG_UINT32_MOUNT_COST, "MountCost", 100000);    
+    setConfigMin(CONFIG_UINT32_MIN_TRAIN_MOUNT_LEVEL, "MinTrainMountLevel", 40, 1);
+    setConfig(CONFIG_UINT32_TRAIN_MOUNT_COST, "TrainMountCost", 900000);
+    setConfig(CONFIG_UINT32_EPIC_MOUNT_COST, "EpicMountCost", 1000000);
+    setConfigMin(CONFIG_UINT32_MIN_TRAIN_EPIC_MOUNT_LEVEL, "MinTrainEpicMountLevel", 60, 1);
+    setConfig(CONFIG_UINT32_TRAIN_EPIC_MOUNT_COST, "TrainEpicMountCost", 9000000);
+
     setConfig(CONFIG_BOOL_INSTANCE_IGNORE_LEVEL, "Instance.IgnoreLevel", false);
     setConfig(CONFIG_BOOL_INSTANCE_IGNORE_RAID,  "Instance.IgnoreRaid", false);
 
diff --git a/src/game/World.h b/src/game/World.h
index 87c6715..adb08b0 100644
--- a/src/game/World.h
+++ b/src/game/World.h
@@ -113,6 +113,12 @@ enum eConfigUInt32Values
     CONFIG_UINT32_INSTANCE_RESET_TIME_HOUR,
     CONFIG_UINT32_INSTANCE_UNLOAD_DELAY,
     CONFIG_UINT32_MAX_SPELL_CASTS_IN_CHAIN,
+    CONFIG_UINT32_MIN_TRAIN_MOUNT_LEVEL,
+    CONFIG_UINT32_MOUNT_COST,
+    CONFIG_UINT32_TRAIN_MOUNT_COST,
+    CONFIG_UINT32_EPIC_MOUNT_COST,
+    CONFIG_UINT32_MIN_TRAIN_EPIC_MOUNT_LEVEL,
+    CONFIG_UINT32_TRAIN_EPIC_MOUNT_COST,
     CONFIG_UINT32_RABBIT_DAY,
     CONFIG_UINT32_MAX_PRIMARY_TRADE_SKILL,
     CONFIG_UINT32_TRADE_SKILL_GMIGNORE_MAX_PRIMARY_COUNT,
diff --git a/src/mangosd/mangosd.conf.dist.cmake b/src/mangosd/mangosd.conf.dist.cmake
index 75051cb..e63e765 100644
--- a/src/mangosd/mangosd.conf.dist.cmake
+++ b/src/mangosd/mangosd.conf.dist.cmake
@@ -535,6 +535,30 @@ LogColors                   = "13 7 11 9"
 #        Enable or disable instant logout for security level (0..4) or high (NOT in combat/while dueling/while falling)
 #        Default: 1 (Mods/GMs/Admins)
 #
+#    MountCost
+#        The price of the normal mount in copper.
+#        Default: 100000 (10g)
+#
+#    TrainMountCost
+#        The cost in copper for training the apprentice riding skill for the normal mounts.
+#        Default: 900000 (90g)
+#
+#    MinTrainMountLevel
+#        The minimal level at which players can train the apprentice riding skill for normal mounts.
+#        Default: 40 (level 40)
+#
+#    EpicMountCost
+#        The price in copper for epic mounts.
+#        Default: 1000000 (100g)
+#
+#    TrainEpicMountCost
+#        The price in copper for training the journeyman riding skill for epic mounts.
+#        Default: 9000000 (90g)
+#
+#    MinTrainEpicMountLevel
+#        The minimal level at which players can train the journeyman riding skill for epic mounts.
+#        Default: 60 (level 60)
+#
 #    AllFlightPaths
 #        Players will start with all flight paths (Note: ALL flight paths, not only player's team)
 #        Default: 0 (true)
@@ -726,6 +750,12 @@ StartHonorPoints                          = 0
 MinHonorKills                             = 15
 MaintenanceDay                            = 3
 InstantLogout                             = 1
+MountCost                                 = 100000
+TrainMountCost                            = 900000
+MinTrainMountLevel                        = 40
+EpicMountCost                             = 1000000
+TrainEpicMountCost                        = 9000000
+MinTrainEpicMountLevel                    = 60
 AllFlightPaths                            = 0
 AlwaysMaxSkillForLevel                    = 0
 ActivateWeather                           = 1
-- 
1.7.10.4