214 lines
8.8 KiB
C#
214 lines
8.8 KiB
C#
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
|
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
|
|
|
using Framework.Database;
|
|
using Game.Entities;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Game.Spells
|
|
{
|
|
public class SkillExtraItems
|
|
{
|
|
// loads the extra item creation info from DB
|
|
public static void LoadSkillExtraItemTable()
|
|
{
|
|
uint oldMSTime = Time.GetMSTime();
|
|
|
|
SkillExtraItemStorage.Clear(); // need for reload
|
|
|
|
// 0 1 2 3
|
|
SQLResult result = DB.World.Query("SELECT spellId, requiredSpecialization, additionalCreateChance, additionalMaxNum FROM skill_extra_item_template");
|
|
|
|
if (result.IsEmpty())
|
|
{
|
|
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 spell specialization definitions. DB table `skill_extra_item_template` is empty.");
|
|
return;
|
|
}
|
|
|
|
uint count = 0;
|
|
do
|
|
{
|
|
uint spellId = result.Read<uint>(0);
|
|
|
|
if (!Global.SpellMgr.HasSpellInfo(spellId, Framework.Constants.Difficulty.None))
|
|
{
|
|
Log.outError(LogFilter.Sql, "Skill specialization {0} has non-existent spell id in `skill_extra_item_template`!", spellId);
|
|
continue;
|
|
}
|
|
|
|
uint requiredSpecialization = result.Read<uint>(1);
|
|
if (!Global.SpellMgr.HasSpellInfo(requiredSpecialization, Framework.Constants.Difficulty.None))
|
|
{
|
|
Log.outError(LogFilter.Sql, "Skill specialization {0} have not existed required specialization spell id {1} in `skill_extra_item_template`!", spellId, requiredSpecialization);
|
|
continue;
|
|
}
|
|
|
|
float additionalCreateChance = result.Read<float>(2);
|
|
if (additionalCreateChance <= 0.0f)
|
|
{
|
|
Log.outError(LogFilter.Sql, "Skill specialization {0} has too low additional create chance in `skill_extra_item_template`!", spellId);
|
|
continue;
|
|
}
|
|
|
|
byte additionalMaxNum = result.Read<byte>(3);
|
|
if (additionalMaxNum == 0)
|
|
{
|
|
Log.outError(LogFilter.Sql, "Skill specialization {0} has 0 max number of extra items in `skill_extra_item_template`!", spellId);
|
|
continue;
|
|
}
|
|
|
|
SkillExtraItemEntry skillExtraItemEntry = new();
|
|
skillExtraItemEntry.requiredSpecialization = requiredSpecialization;
|
|
skillExtraItemEntry.additionalCreateChance = additionalCreateChance;
|
|
skillExtraItemEntry.additionalMaxNum = additionalMaxNum;
|
|
|
|
SkillExtraItemStorage[spellId] = skillExtraItemEntry;
|
|
++count;
|
|
}
|
|
while (result.NextRow());
|
|
|
|
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} spell specialization definitions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
|
}
|
|
|
|
public static bool CanCreateExtraItems(Player player, uint spellId, ref float additionalChance, ref byte additionalMax)
|
|
{
|
|
// get the info for the specified spell
|
|
var specEntry = SkillExtraItemStorage.LookupByKey(spellId);
|
|
if (specEntry == null)
|
|
return false;
|
|
|
|
// the player doesn't have the required specialization, return false
|
|
if (!player.HasSpell(specEntry.requiredSpecialization))
|
|
return false;
|
|
|
|
// set the arguments to the appropriate values
|
|
additionalChance = specEntry.additionalCreateChance;
|
|
additionalMax = specEntry.additionalMaxNum;
|
|
|
|
// enable extra item creation
|
|
return true;
|
|
}
|
|
|
|
static Dictionary<uint, SkillExtraItemEntry> SkillExtraItemStorage = new();
|
|
}
|
|
|
|
class SkillExtraItemEntry
|
|
{
|
|
public SkillExtraItemEntry(uint rS = 0, float aCC = 0f, byte aMN = 0)
|
|
{
|
|
requiredSpecialization = rS;
|
|
additionalCreateChance = aCC;
|
|
additionalMaxNum = aMN;
|
|
}
|
|
|
|
// the spell id of the specialization required to create extra items
|
|
public uint requiredSpecialization;
|
|
// the chance to create one additional item
|
|
public float additionalCreateChance;
|
|
// maximum number of extra items created per crafting
|
|
public byte additionalMaxNum;
|
|
}
|
|
|
|
public class SkillPerfectItems
|
|
{
|
|
// loads the perfection proc info from DB
|
|
public static void LoadSkillPerfectItemTable()
|
|
{
|
|
uint oldMSTime = Time.GetMSTime();
|
|
|
|
SkillPerfectItemStorage.Clear(); // reload capability
|
|
|
|
// 0 1 2 3
|
|
SQLResult result = DB.World.Query("SELECT spellId, requiredSpecialization, perfectCreateChance, perfectItemType FROM skill_perfect_item_template");
|
|
if (result.IsEmpty())
|
|
{
|
|
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 spell perfection definitions. DB table `skill_perfect_item_template` is empty.");
|
|
return;
|
|
}
|
|
|
|
uint count = 0;
|
|
do
|
|
{
|
|
uint spellId = result.Read<uint>(0);
|
|
if (!Global.SpellMgr.HasSpellInfo(spellId, Framework.Constants.Difficulty.None))
|
|
{
|
|
Log.outError(LogFilter.Sql, "Skill perfection data for spell {0} has non-existent spell id in `skill_perfect_item_template`!", spellId);
|
|
continue;
|
|
}
|
|
|
|
uint requiredSpecialization = result.Read<uint>(1);
|
|
if (!Global.SpellMgr.HasSpellInfo(requiredSpecialization, Framework.Constants.Difficulty.None))
|
|
{
|
|
Log.outError(LogFilter.Sql, "Skill perfection data for spell {0} has non-existent required specialization spell id {1} in `skill_perfect_item_template`!", spellId, requiredSpecialization);
|
|
continue;
|
|
}
|
|
|
|
float perfectCreateChance = result.Read<float>(2);
|
|
if (perfectCreateChance <= 0.0f)
|
|
{
|
|
Log.outError(LogFilter.Sql, "Skill perfection data for spell {0} has impossibly low proc chance in `skill_perfect_item_template`!", spellId);
|
|
continue;
|
|
}
|
|
|
|
uint perfectItemType = result.Read<uint>(3);
|
|
if (Global.ObjectMgr.GetItemTemplate(perfectItemType) == null)
|
|
{
|
|
Log.outError(LogFilter.Sql, "Skill perfection data for spell {0} references non-existent perfect item id {1} in `skill_perfect_item_template`!", spellId, perfectItemType);
|
|
continue;
|
|
}
|
|
|
|
SkillPerfectItemStorage[spellId] = new SkillPerfectItemEntry(requiredSpecialization, perfectCreateChance, perfectItemType);
|
|
|
|
++count;
|
|
}
|
|
while (result.NextRow());
|
|
|
|
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} spell perfection definitions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
|
}
|
|
|
|
public static bool CanCreatePerfectItem(Player player, uint spellId, ref float perfectCreateChance, ref uint perfectItemType)
|
|
{
|
|
var entry = SkillPerfectItemStorage.LookupByKey(spellId);
|
|
// no entry in DB means no perfection proc possible
|
|
if (entry == null)
|
|
return false;
|
|
|
|
// if you don't have the spell needed, then no procs for you
|
|
if (!player.HasSpell(entry.requiredSpecialization))
|
|
return false;
|
|
|
|
// set values as appropriate
|
|
perfectCreateChance = entry.perfectCreateChance;
|
|
perfectItemType = entry.perfectItemType;
|
|
|
|
// and tell the caller to start rolling the dice
|
|
return true;
|
|
}
|
|
|
|
static Dictionary<uint, SkillPerfectItemEntry> SkillPerfectItemStorage = new();
|
|
}
|
|
|
|
// struct to store information about perfection procs
|
|
// one entry per spell
|
|
class SkillPerfectItemEntry
|
|
{
|
|
public SkillPerfectItemEntry(uint rS = 0, float pCC = 0f, uint pIT = 0)
|
|
{
|
|
requiredSpecialization = rS;
|
|
perfectCreateChance = pCC;
|
|
perfectItemType = pIT;
|
|
}
|
|
|
|
// the spell id of the spell required - it's named "specialization" to conform with SkillExtraItemEntry
|
|
public uint requiredSpecialization;
|
|
// perfection proc chance
|
|
public float perfectCreateChance;
|
|
// itemid of the resulting perfect item
|
|
public uint perfectItemType;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|