I'm gonna release some usefull calculations... some of them converted from TQ Source, others may be done by myself... but here we go:
Linear spell calculation (FB/SS/DT/DT/ETC...)
Code:
public static void DDALine(int x0, int y0, int x1, int y1, int nRange, ref List<Point> vctPoint)
{
if (x0 == x1 && y0 == y1)
return;
float scale = (float)(1.0f * nRange / Math.Sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)));
x1 = (int)(0.5f + scale * (x1 - x0) + x0);
y1 = (int)(0.5f + scale * (y1 - y0) + y0);
DDALineEx(x0, y0, x1, y1, ref vctPoint);
}
public static void DDALineEx(int x0, int y0, int x1, int y1, ref List<Point> vctPoint)
{
if (x0 == x1 && y0 == y1)
return;
if (vctPoint == null)
vctPoint = new List<Point>();
int dx = x1 - x0;
int dy = y1 - y0;
int abs_dx = Math.Abs(dx);
int abs_dy = Math.Abs(dy);
Point point = new Point();
if (abs_dx > abs_dy)
{
int _0_5 = abs_dx * (dy > 0 ? 1 : -1);
int numerator = dy * 2;
int denominator = abs_dx * 2;
if (dx > 0)
{
// x0 ++
for (int i = 1; i <= abs_dx; i++)
{
point = new Point();
point.X = x0 + i;
point.Y = y0 + ((numerator * i + _0_5) / denominator);
vctPoint.Add(point);
}
}
else if (dx < 0)
{
// x0 --
for (int i = 1; i <= abs_dx; i++)
{
point = new Point();
point.X = x0 - i;
point.Y = y0 + ((numerator * i + _0_5) / denominator);
vctPoint.Add(point);
}
}
}
else
{
int _0_5 = abs_dy * (dx > 0 ? 1 : -1);
int numerator = dx * 2;
int denominator = abs_dy * 2;
if (dy > 0)
{
// y0 ++
for (int i = 1; i <= abs_dy; i++)
{
point = new Point();
point.Y = y0 + i;
point.X = x0 + ((numerator * i + _0_5) / denominator);
vctPoint.Add(point);
}
}
else if (dy < 0)
{
// y0 --
for (int i = 1; i <= abs_dy; i++)
{
point = new Point();
point.Y = y0 - i;
point.X = x0 + ((numerator * i + _0_5) / denominator);
vctPoint.Add(point);
}
}
}
}
This one is the item generator basically from TQ, but since we don't use the same source or the definitions change alot... I've addapted it only ;]
Code:
//nItem can be null to return a new one, dwValue is monster level, nQuality is the desired quality.. if its 0 then it'll be auto generated
public static Struct.Gear Create_Drop(Struct.Gear nItem, uint dwValue, byte nQuality)
{
// base data
Struct.Gear_Data nInfo = null;
// item quality
int dwItemQuality = 0;
// item sort & item color & item level
int dwItemSort = 0;
int dwItemColor = 0;
int dwItemLev = 0;
int dwSorted = 0;
int dwItemPlus = 0;
int nRand = 0;
int nRate = 0;
// check for null
if (nItem == null)
nItem = new Struct.Gear();
if (nQuality == 0)
{
// auto create quality param
dwItemQuality = 5;
nRand = Kernel.Random.Next(1500);
if (nRand == 1)
dwItemQuality = 9;
else if (nRand >= 10 && nRand <= 12)
dwItemQuality = 8;
else if (nRand >= 16 && nRand <= 30)
dwItemQuality = 7;
else if (nRand >= 51 && nRand <= 100)
dwItemQuality = 6;
}
else
dwItemQuality = nQuality;
nRand = Kernel.Random.Next(1200);
if (nRand >= 0 && nRand < 20)
{ // shoes
dwItemSort = 160;
}
else if (nRand >= 20 && nRand < 50)
{ // necklace
int[] dwSort = new int[2] { 120, 121 };
dwItemSort = dwSort[Kernel.Random.Next(2)];
}
else if (nRand >= 50 && nRand < 100)
{ // ring
int[] dwSort = new int[3] { 150, 151, 152 };
dwItemSort = dwSort[Kernel.Random.Next(3)];
}
else if (nRand >= 100 && nRand < 400)
{ // armet
int[] dwSort = new int[7] { 111, 112, 113, 114, 117, 118, 123 };
dwItemSort = dwSort[Kernel.Random.Next(7)];
if (dwItemSort <= 118 || dwItemSort == 123) // have color
dwItemColor = Kernel.Random.Next(7) + 3;
}
else if (nRand >= 400 && nRand < 700)
{ // armor
int[] dwSort = new int[6] { 130, 131, 133, 134, 135, 136 };
dwItemSort = dwSort[Kernel.Random.Next(6)];
dwItemColor = Kernel.Random.Next(7) + 3;
}
else
{ // weapon & shield
nRate = Kernel.Random.Next(100);
if (nRate >= 0 && nRate < 80)// 80% for single hand weapon
{
int[] dwSort = new int[12] { 410, 420, 421, 430, 440, 450, 460, 480, 481, 490, 601, 610 };
dwItemSort = dwSort[Kernel.Random.Next(11)];
}
else // 20% for two hand weapon
{
int[] dwSort = new int[7] { 500, 510, 530, 560, 561, 580, 900 };
dwItemSort = dwSort[Kernel.Random.Next(7)];
if (900 == dwItemSort)
dwItemColor = Kernel.Random.Next(7) + 3;
}
}
// item lev
if ((dwItemSort >= 111 && dwItemSort <= 123) || (dwItemSort >= 130 && dwItemSort <= 136) || dwItemSort == 900)
{ // headgear's/armor's/shield's
int[] dwSort = new int[10] { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 };
dwSorted = Kernel.Random.Next(10);
dwItemLev = dwSort[dwSorted];
}
else if (dwItemSort >= 410 && dwItemSort <= 610)
{ // weapon's
int[] dwSort = new int[23] { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220 };
dwSorted = Kernel.Random.Next(23);
dwItemLev = dwSort[dwSorted];
}
else if (dwItemSort >= 120 && dwItemSort <= 121)
{ // necklace's/bag's
int[] dwSort = new int[11] { 0, 20, 40, 60, 80, 90, 120, 150, 180, 210, 220 };
dwSorted = Kernel.Random.Next(11);
dwItemLev = dwSort[dwSorted];
}
else if (dwItemSort >= 150 && dwItemSort <= 152)
{ // ring's/heavyring's/bracelet's
int[] dwSort = new int[14] { 0, 10, 30, 50, 70, 90, 110, 130, 150, 170, 190, 210, 220, 230 };
dwSorted = Kernel.Random.Next(14);
dwItemLev = dwSort[dwSorted];
}
else if (dwItemSort == 160)
{ // boot's
int[] dwSort = new int[13] { 0, 10, 30, 50, 70, 90, 110, 130, 150, 170, 190, 210, 220 };
dwSorted = Kernel.Random.Next(13);
dwItemLev = dwSort[dwSorted];
}
// item type
Retry:
uint idItemType = (uint)((dwItemSort * 1000) + dwItemLev + dwItemQuality);
if (Pool.Items.TryGetValue(idItemType, out nInfo))
{
if (nInfo.Level > dwValue + 20)
{
if (dwItemLev > 0)
{
dwItemLev = ReSortLev(dwItemSort, dwSorted - 1);
goto Retry;
}
else
return new Struct.Gear();
}
// fill item info
nItem.ID = idItemType;
nItem.Color = (byte)dwItemColor;
nItem.Mode = Struct.Gear_Mode.Default;
// auto generate the maximum amount with maximum of 70% of real durability
nItem.Maximum_Amount = (ushort)((nInfo.Durability * 0.01) * (Kernel.Random.Next(1, 8) * 0.1));
if (nItem.Maximum_Amount < 1)
nItem.Maximum_Amount = 1;
nItem.Maximum_Amount *= 99;
if (dwItemQuality > 5)
nItem.Current_Amount = (ushort)(nItem.Maximum_Amount * (50 + Kernel.Random.Next(50)) / 100);
else
{
uint dwPrice = nInfo.Cost;
if (dwPrice <= 0)
dwPrice = 1;
nItem.Current_Amount = (ushort)((3 * nItem.Maximum_Amount * dwValue) / dwPrice);
if (nItem.Current_Amount >= nItem.Maximum_Amount)
nItem.Current_Amount = nItem.Maximum_Amount;
if (nItem.Current_Amount < 1)
nItem.Current_Amount = 1;
}
// gem hole
if (idItemType >= 410000 && idItemType < 610999)
{
nRate = Kernel.Random.Next(100);
if (nRate < 5)
{
nItem.HoleOne = 0xff;
nItem.HoleTwo = 0xff;
}
else if (nRate < 20)
nItem.HoleOne = 0xff;
}
nRate = Kernel.Random.Next(500);
if (nRate < 5)
{
int nBless = Kernel.Random.Next(6);
if (nBless == 0 || nBless == 2)
nBless = 1;
else if (nBless == 4)
nBless = 3;
nItem.Bless = (byte)nBless;
}
nRate = Kernel.Random.Next(500);
if (nRate < 5)
{
dwItemPlus = 1;
nItem.Plus = dwItemPlus;
}
}
else
Console.WriteLine("Unknown item id " + idItemType);
return nItem;
}
static int ReSortLev(int dwItemSort, int dwSorted)
{
int dwItemLev = 0;
if ((dwItemSort >= 111 && dwItemSort <= 123) || (dwItemSort >= 130 && dwItemSort <= 136) || dwItemSort == 900)
{ // headgear's/armor's/shield's
int[] dwSort = new int[10] { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 };
dwItemLev = dwSort[dwSorted];
}
else if (dwItemSort >= 410 && dwItemSort <= 610)
{ // weapon's
int[] dwSort = new int[23] { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220 };
dwItemLev = dwSort[dwSorted];
}
else if (dwItemSort >= 120 && dwItemSort <= 121)
{ // necklace's/bag's
int[] dwSort = new int[11] { 0, 20, 40, 60, 80, 90, 120, 150, 180, 210, 220 };
dwItemLev = dwSort[dwSorted];
}
else if (dwItemSort >= 150 && dwItemSort <= 152)
{ // ring's/heavyring's/bracelet's
int[] dwSort = new int[14] { 0, 10, 30, 50, 70, 90, 110, 130, 150, 170, 190, 210, 220, 230 };
dwItemLev = dwSort[dwSorted];
}
else if (dwItemSort == 160)
{ // boot's
int[] dwSort = new int[13] { 0, 10, 30, 50, 70, 90, 110, 130, 150, 170, 190, 210, 220 };
dwItemLev = dwSort[dwSorted];
}
return dwItemLev;
}
Here is the attack difference used by TQ (Was a surprise when i discovered that even mobs to players has a damage dif ;])
Code:
public const int NAME_BLACK = 3, NAME_RED = 2, NAME_WHITE = 1, NAME_GREEN = 0;
public static int GetNameType(byte nAtkLev, byte nDefLev)
{
int nDeltaLev = nAtkLev - nDefLev;
if (nDeltaLev < -3)
return Constants.NAME_BLACK;
else if (nDeltaLev >= -3 && nDeltaLev < 0)
return Constants.NAME_RED;
else if (nDeltaLev >= 0 && nDeltaLev < 5)
return Constants.NAME_WHITE;
return Constants.NAME_GREEN;
}
public int AdjustDamageUser2Monster(int nDamage, int nAtkLev, int nDefLev)
{
double Redduction = 1.0;
if (nAtkLev > nDefLev)
{
byte nAtkLvl = (mRole as Character).Level;
byte nDefLvl = (pRole as Monster).Level;
int nDeltaLev = nAtkLvl - nDefLvl;
if (nDeltaLev >= 3 && nDeltaLev <= 5)
Redduction = 1.5;
else if (nDeltaLev > 5 && nDeltaLev <= 10)
Redduction = 2.0;
else if (nDeltaLev > 10 && nDeltaLev <= 20)
Redduction = 2.5;
else if (nDeltaLev > 20)
Redduction = 3.0;
}
return (int)(nDamage * Redduction);
}
//This you may use inside the calculation for damage the player or create a method for it wherever you want and just call with the both levels, monster and user with the damage to be returned...
nNameType = Role_Adjust.GetNameType(Mob.Level, Client.Level);
if (nNameType == Constants.NAME_RED)
fMelee = (int)(fMelee * 1.5);
else if (nNameType == Constants.NAME_BLACK)
{
int nDeltaLev = Client.Level - Mob.Level;
if (nDeltaLev >= -10 && nDeltaLev <= -5)
fMelee = (int)(fMelee * 2);
else if (nDeltaLev >= -20 && nDeltaLev < -10)
fMelee = (int)(fMelee * 3.5);
else if (nDeltaLev < -20)
fMelee = (int)(fMelee * 5);
}
This is the ExpAdjustment ... very usefull tho ... even that we aren't like co its very good to have at last the base as this... the exp may change by using the exp multiplers ...
Code:
public static int AdjustExp(int nDamage, byte nAtkLev, byte nDefLev)
{
int nExp = nDamage;
int nNameType = GetNameType(nAtkLev, nDefLev);
int nDeltaLev = nAtkLev - nDefLev;
if (nNameType == Constants.NAME_GREEN)
{
if (nDeltaLev >= 3 && nDeltaLev <= 5)
nExp = nExp * 70 / 100;
else if (nDeltaLev > 5 && nDeltaLev <= 10)
nExp = nExp * 20 / 100;
else if (nDeltaLev > 10 && nDeltaLev <= 20)
nExp = nExp * 10 / 100;
else if (nDeltaLev > 20)
nExp = nExp * 5 / 100;
}
else if (nNameType == Constants.NAME_RED)
{
nExp = (int)(nExp * 1.3);
}
else if (nNameType == Constants.NAME_BLACK)
{
if (nDeltaLev >= -10 && nDeltaLev < -5)
nExp = (int)(nExp * 1.5);
else if (nDeltaLev >= -20 && nDeltaLev < -10)
nExp = (int)(nExp * 1.8);
else if (nDeltaLev < -20)
nExp = (int)(nExp * 2.3);
}
else if (nNameType == Constants.NAME_WHITE)
{
if (nDeltaLev >= 0 && nDeltaLev < 3)
nExp = nExp * 90 / 100;
else if (nDeltaLev >= 3 && nDeltaLev < 5)
nExp = nExp * 70 / 100;
}
return nExp;
}
Now i'm gonna bring the calculation for experience loss ;] how to use it is up to yourself ^^
Code:
public int CalcExpLostOfDeath(IEntity pKiller)
{
Character pUserKiller = pKiller as Character;
// return if there is no experience
if (!(Experience > 0))
return 0;
// normal condition
int nParam = 50;
// under red/black name condition
if (HasFlag(Struct.Flag_Effect.RedName))
nParam = 10;
else if (HasFlag(Struct.Flag_Effect.BlackName))
nParam = 5;
int nExpLost = Math.Max(0, (int)((long)Experience / nParam));
if (Guild != null && nExpLost > 0)
{
int nDecPercent = 10;
if (Guild != null)
{
int nExpPayBySyn = 0;
int nProffer = (int)(Guild_Member.Donation * 100000);
int nRank = (int)Guild_Rank;
if (nProffer > 0)
{
const int MONEYCOST_PEREXP = 100;
int nFundSyn = (int)Guild.Fund;
int nFundLost = (int)Extentions.MulDiv(nExpLost, nDecPercent, 100 * MONEYCOST_PEREXP);
if (nFundLost > nFundSyn)
nFundLost = nFundSyn;
// prevent the fund to be lower than 0
Guild.Fund = (uint)Math.Max(0, Guild.Fund - nFundLost);
if (nRank != 1000)
Guild_Member.Donation -= (uint)nFundLost;//should be fixed cuz members donation can be lower than 0
nExpPayBySyn = nFundLost * MONEYCOST_PEREXP;
nExpLost -= nExpPayBySyn;//nFundLost * MONEYCOST_PEREXP;
}
else
{
if (Guild.Name == War_Handler.Pole_Holder)
nDecPercent = 20;
else
nDecPercent = 10;
const int MONEYCOST_PEREXP = 100;
int nFundSyn = (int)Guild.Fund;
int nFundLost = (int)Extentions.MulDiv(nExpLost, nDecPercent, 100 * MONEYCOST_PEREXP); // 100µã¾*Ñé1Á½
if (nFundLost > nFundSyn)
nFundLost = nFundSyn;
Guild.Fund = (uint)Math.Max(0, Guild.Fund - nFundLost);
if (nRank != 1000)
Guild_Member.Donation = (uint)Math.Max(0, Guild_Member.Donation - nFundLost);//should be fixed cuz members donation can be lower than 0
nExpPayBySyn = nFundLost * MONEYCOST_PEREXP;
nExpLost -= nExpPayBySyn;//nFundLost * MONEYCOST_PEREXP;
}
Owner.Message("You have paid " + nExpPayBySyn + " exp loss with guild fund.", false, Color.Red, Struct.Message_Type.Talk);
}
}
Experience = (ulong)Math.Max(0, (long)Experience - nExpLost);
return Math.Max(0, nExpLost);
}
More calculations to be released soon ;]
//EDIT: Ohh forgot to fix something at drop generator... now fixed ;], also added bless and plus calculations for item, changed a bit the quality rating... ohh also remember to say that Talismans aren't included... and i'll include it soon ;]






