here are the proficiency functions
#region AddOrUpdateProf
public void AddOrUpdateProf(ushort _id, ushort _level, uint _exp = 0)
{
ConquerProficiency prof;
if (proficiencies.ContainsKey(_id))
{
proficiencies[_id].Level = _level;
proficiencies[_id].Experience = _exp;
proficiencies[_id].Save();
prof = proficiencies[_id];
}
else
{
prof = ConquerProficiency.Create(owner.UID, _id, _level, _exp);
proficiencies.TryAdd(prof.ID, prof);
prof.Save();
}
prof.Send(owner);
}
public void AddProficiencyExperience(ushort _id, ulong _amount)
{
if (_amount == 0)
return;
if (!proficiencies.ContainsKey(_id))
AddOrUpdateProf(_id, 1);
else
{
var prof = proficiencies[_id];
if (prof.Level >= 20)
return;
prof.Experience += (uint)_amount;
while (prof.Level < Constants.ProficiencyLevelExperience.Length && prof.Experience >= Constants.ProficiencyLevelExperience[prof.Level])
{
prof.Experience -= Constants.ProficiencyLevelExperience[prof.Level];
prof.Level++;
if (prof.PreviousLevel != 0 && (prof.PreviousLevel / 2) < prof.Level)
{
prof.Level = prof.PreviousLevel;
prof.PreviousLevel = 0;
prof.Save();
}
}
prof.Send(owner);
}
}
#endregion
#region AddOrUpdateSkill
public void AddSkillExperience(ushort _id, ulong _amount)
{
if (_amount == 0)
return;
if (!skills.ContainsKey(_id))
return;
var skill = skills[_id];
if (skill.Info == null || owner.Level < skill.Info.NeedLevel && skill.Info.NeedLevel > 0)
return;
skill.Experience += (uint)_amount;
while (skill.Experience > skill.Info.NeedExp && skill.Info.NeedExp > 0)
{
byte AddOn = 0;
if (skill.PreviousLevel != 0 && (skill.PreviousLevel / 2) < (skill.Level + 1))
{
AddOn = (byte)(skill.PreviousLevel - (skill.Level + 1));
}
var dbSkill = Database.ServerDatabase.Context.MagicType.GetMagic typeByIDAndLevel(skill.ID, (ushort)(skill.Level + 1 + AddOn));
if (dbSkill == null)
dbSkill = Database.ServerDatabase.Context.MagicType.GetMagic typeByIDAndLevel(skill.ID, (ushort)(skill.Level + 1));//Failsafe
if (dbSkill == null)
return;
ConquerSkill x;
if (skills.TryRemove(skill.ID, out x))
{
skill.Experience -= skill.Info.NeedExp;
skill.Level = dbSkill.Level;
skill.ID = dbSkill.ID;
skill.Save();
skills.TryAdd(skill.ID, skill);
}
}
skill.Send(owner);
}
And here is the launch attack handler
#region Launch Attack
private void LaunchAttack()
{
try
{
target = owner.Map.Search<Entity>(targetUID);
if (!owner.Alive || target == null || !IsValidTarget(target) || !IsInAttackRange(target) || target.HasEffect(ClientEffect.Fly) && target.AttackRange < 5)
{ AbortAttack(); return; }
//Do not check equipment if we have none
if (owner.Equipment != null)
{
skill = GetWeaponSkill();
if (skill != null)
{ location = target.Location; LaunchSkill(); return; }
}
DisplaySuperGemEffects();
//Deal damage to target
state = SkillState.Attack;
nextTrigger = Common.Clock + owner.AttackSpeed / (owner.HasEffect(ClientEffect.Cyclone) ? 3 : 1);
uint dmg;
if (owner.WeaponType == 500)
{
ConquerItem item;
owner.Equipment.TryGetItemBySlot(5, out item);
if (item == null || item.Durability < 1)
{
AbortAttack(); return;
}
if (!owner.Map.IsTGMap && item != null)
{
item.Durability -= 1;
owner.Send(ItemInformationPacket.Create(item, ItemInfoAction.Update));
if (item.Durability == 0)
{
uint id = item.StaticID;
AutoEquip(item, id);
}
}
dmg = owner.CalculateBowDamage(target, null, true);
}
else
dmg = owner.CalculatePhysicalDamage(target, null, true);
if (owner is Player)
{
var expGain = owner.CalculateExperienceGain(target, dmg);
((Player)owner).GainExperience(expGain);
//proficiency experience
if (owner.Map.IsTGMap)
{
expGain = 1000 * expGain;
AddProficiencyExperience(owner.WeaponType, expGain);
}
//proficiency experience on monsters
else
{
AddProficiencyExperience(owner.WeaponType, expGain);
}
}
else if (owner is Pet)
{
if (((Pet)owner).PetOwner != null)
{
var expGain = owner.CalculateExperienceGain(target, dmg);
((Pet)owner).PetOwner.GainExperience(expGain);
}
}
target.ReceiveDamage(dmg, owner.UID);
if (!target.Alive)
{
if (target is SOB)
{
target.Kill(1, owner.UID);
owner.SendToScreen(InteractPacket.Create(owner.UID , target.UID, (ushort)target.Location.X, (ushort)target.Location.Y, (owner.WeaponType == 500 ? InteractAction.Shoot : InteractAction.Attack), dmg), true);
}
else
{
owner.SendToScreen(InteractPacket.Create(owner.UID , target.UID, (ushort)target.Location.X, (ushort)target.Location.Y, (owner.WeaponType == 500 ? InteractAction.Shoot : InteractAction.Attack), dmg), true);
if (owner.HasEffect(ClientEffect.Cyclone))
{
((Player)owner).KOCount++;
owner.ClientEffects[ClientEffect.Cyclone] += 700;
target.Kill(65541 * ((Player)owner).KOCount, owner.UID);
}
else if (owner.HasEffect(ClientEffect.Superman))
{
((Player)owner).KOCount++;
owner.ClientEffects[ClientEffect.Superman] += 700;
target.Kill(65541 * ((Player)owner).KOCount, owner.UID);
}
else
{
target.Kill(1, owner.UID);
}
}
}
else
owner.SendToScreen(InteractPacket.Create(owner.UID , target.UID, (ushort)target.Location.X, (ushort)target.Location.Y, (owner.WeaponType == 500 ? InteractAction.Shoot : InteractAction.Attack), dmg), true);
}
catch (Exception p)
{ AbortAttack(); }
}
#endregion