Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding built-in spells to casting items #1230

Merged
merged 6 commits into from
Jan 5, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Source/ACE.Server/Managers/EnchantmentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ public virtual AddEnchantmentResult Add(Spell spell, WorldObject caster)
newEntry.LayerId = 1;
WorldObject.Biota.AddEnchantment(newEntry, WorldObject.BiotaDatabaseLock);
WorldObject.ChangesDetected = true;
//WorldObject.SaveBiotaToDatabase();

result.Enchantment = newEntry;
result.StackType = StackType.Initial;
Expand Down
3 changes: 3 additions & 0 deletions Source/ACE.Server/Network/Structure/AppraiseInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ private void AddPropertyEnchantments(WorldObject wo, WorldObject wielder)

if (wielder != null && PropertiesFloat.ContainsKey(PropertyFloat.WeaponDefense) && !(wo is Ammunition))
PropertiesFloat[PropertyFloat.WeaponDefense] += wielder.EnchantmentManager.GetDefenseMod();

if (wo.ItemSkillLimit != null)
PropertiesInt[PropertyInt.AppraisalItemSkill] = (int)wo.ItemSkillLimit;
}

private void BuildSpells(WorldObject wo)
Expand Down
11 changes: 9 additions & 2 deletions Source/ACE.Server/WorldObjects/Creature_Magic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ public void CreateCreatureSpell(uint spellId)

public uint CalculateManaUsage(Creature caster, Spell spell, WorldObject target = null)
{
var baseCost = spell.BaseMana;

// for casting spells built into a casting implement, use the ItemManaCost
var castItem = caster.GetEquippedWand();
if (castItem != null && (castItem.SpellDID ?? 0) == spell.Id)
baseCost = (uint)(castItem.ItemManaCost ?? 0);

uint mana_conversion_skill = caster.GetCreatureSkill(Skill.ManaConversion).Current;
uint difficulty = spell.PowerMod; // modified power difficulty

Expand All @@ -97,10 +104,10 @@ public uint CalculateManaUsage(Creature caster, Spell spell, WorldObject target
int numTargetItems = 1;
if (targetPlayer != null)
numTargetItems = targetPlayer.EquippedObjects.Count;
preCost = (uint)Math.Round((spell.BaseMana + (spell.ManaMod * numTargetItems)) * baseManaPercent);
preCost = (uint)Math.Round((baseCost + (spell.ManaMod * numTargetItems)) * baseManaPercent);
}
else
preCost = (uint)Math.Round(spell.BaseMana * baseManaPercent);
preCost = (uint)Math.Round(baseCost * baseManaPercent);

if (preCost < 1) preCost = 1;

Expand Down
15 changes: 15 additions & 0 deletions Source/ACE.Server/WorldObjects/Player_Inventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,21 @@ private WeenieError CheckWieldRequirement(WorldObject item)
return WeenieError.None;
}

private Skill CheckActivationRequirement(WorldObject item)
{
if (item.ItemDifficulty != null)
{
if (GetCreatureSkill(Skill.ArcaneLore).Current < item.ItemDifficulty.Value)
return Skill.ArcaneLore;
}

if (item.ItemSkillLimit != null && item.ItemSkillLevelLimit != null)
{
if (GetCreatureSkill((Skill)item.ItemSkillLimit.Value).Current < item.ItemSkillLevelLimit.Value)
return (Skill)item.ItemSkillLimit.Value;
}
return Skill.None;
}

// =========================================
// Game Action Handlers - Inventory Stacking
Expand Down
41 changes: 37 additions & 4 deletions Source/ACE.Server/WorldObjects/Player_Magic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -493,8 +493,15 @@ public void CreatePlayerSpell(WorldObject target, TargetCategory targetCategory,
else
player.IsBusy = true;

// if casting implement has spell built in,
// use spellcraft from the item, instead of player's magic skill?
var caster = GetEquippedWand();
var isWeaponSpell = IsWeaponSpell(spell);

// Grab player's skill level in the spell's Magic School
var magicSkill = player.GetCreatureSkill(spell.School).Current;
if (isWeaponSpell && caster.ItemSpellcraft != null)
magicSkill = (uint)caster.ItemSpellcraft;

if (targetCategory == TargetCategory.WorldObject)
{
Expand Down Expand Up @@ -548,7 +555,11 @@ public void CreatePlayerSpell(WorldObject target, TargetCategory targetCategory,
// Calculate mana usage
uint manaUsed = CalculateManaUsage(player, spell, target);

if (manaUsed > player.Mana.Current)
var currentMana = player.Mana.Current;
if (isWeaponSpell)
currentMana = (uint)(caster.ItemCurMana ?? 0);

if (manaUsed > currentMana)
{
player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, WeenieError.YouDontHaveEnoughManaToCast));
IsBusy = false; // delay?
Expand All @@ -557,7 +568,11 @@ public void CreatePlayerSpell(WorldObject target, TargetCategory targetCategory,

// begin spellcasting
Proficiency.OnSuccessUse(player, player.GetCreatureSkill(Skill.ManaConversion), spell.PowerMod);
player.UpdateVitalDelta(player.Mana, -(int)manaUsed);

if (!isWeaponSpell)
player.UpdateVitalDelta(player.Mana, -(int)manaUsed);
else
caster.ItemCurMana -= (int)manaUsed;

spell.Formula.GetPlayerFormula(player);

Expand Down Expand Up @@ -587,7 +602,11 @@ public void CreatePlayerSpell(WorldObject target, TargetCategory targetCategory,
// cast spell
spellChain.AddAction(this, () =>
{
var motionCastSpell = new Motion(MotionStance.Magic, spell.Formula.CastGesture, castSpeed);
var castGesture = spell.Formula.CastGesture;
if (isWeaponSpell && caster.UseUserAnimation != 0)
castGesture = caster.UseUserAnimation;

var motionCastSpell = new Motion(MotionStance.Magic, castGesture, castSpeed);
EnqueueBroadcastMotion(motionCastSpell);
});

Expand All @@ -596,7 +615,8 @@ public void CreatePlayerSpell(WorldObject target, TargetCategory targetCategory,

spellChain.AddAction(this, () =>
{
TryBurnComponents(spell);
if (!isWeaponSpell)
TryBurnComponents(spell);
});

var checkPKStatusVsTarget = CheckPKStatusVsTarget(player, target, spell);
Expand Down Expand Up @@ -1189,5 +1209,18 @@ public bool HasFoci(MagicSchool school)
var wcid = FociWCIDs[school];
return Inventory.Values.FirstOrDefault(i => i.WeenieClassId == wcid) != null;
}

/// <summary>
/// Returns TRUE if the currently equipped casting implement
/// has a built-in spell
/// </summary>
public bool IsWeaponSpell(Spell spell)
{
var caster = GetEquippedWand();
if (caster == null || caster.SpellDID == null)
return false;

return caster.SpellDID == spell.Id;
}
}
}
24 changes: 24 additions & 0 deletions Source/ACE.Server/WorldObjects/Player_Use.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,30 @@ public void HandleActionUseWithTarget(uint sourceObjectGuid, uint targetObjectGu
var invTarget = GetInventoryItem(targetObjectGuid);
var invWielded = GetEquippedItem(targetObjectGuid);

if (invSource == null)
{
// is this caster with a built-in spell?
var caster = GetEquippedItem(sourceObjectGuid);
if (caster != null && caster.SpellDID != null)
{
// check activation requirements
var skillFailed = CheckActivationRequirement(caster);
if (skillFailed != Skill.None)
{
Session.Network.EnqueueSend(new GameEventWeenieErrorWithString(Session, WeenieErrorWithString.Your_IsTooLowToUseItemMagic, skillFailed.ToSentence()));
SendUseDoneEvent(WeenieError.SkillTooLow);
return;
}
HandleActionCastTargetedSpell(targetObjectGuid, caster.SpellDID ?? 0);
return;
}
else
{
log.Warn($"{Name}.HandleActionUseWithTarget({sourceObjectGuid:X8}, {targetObjectGuid:X8}): couldn't find {sourceObjectGuid:X8}");
SendUseDoneEvent(WeenieError.None);
}
}

var worldTarget = (invTarget == null) ? CurrentLandblock?.GetObject(targetObjectGuid) : null;

if (invTarget != null)
Expand Down
2 changes: 1 addition & 1 deletion Source/ACE.Server/WorldObjects/WorldObject_Magic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ public static bool MagicDefenseCheck(uint casterMagicSkill, uint targetMagicDefe
magicSkill = caster.GetCreatureSkill(spell.School).Current;
else
// Retrieve casting item's spellcraft
magicSkill = (uint)ItemSpellcraft;
magicSkill = (uint)(ItemSpellcraft ?? 0);

var player = caster as Player;
var targetPlayer = target as Player;
Expand Down
18 changes: 15 additions & 3 deletions Source/ACE.Server/WorldObjects/WorldObject_Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1644,6 +1644,12 @@ public string Inscription
set { if (!value.HasValue) RemoveProperty(PropertyFloat.ManaRate); else SetProperty(PropertyFloat.ManaRate, value.Value); }
}

public int? ItemManaCost
{
get => GetProperty(PropertyInt.ItemManaCost);
set { if (!value.HasValue) RemoveProperty(PropertyInt.ItemManaCost); else SetProperty(PropertyInt.ItemManaCost, value.Value); }
}

public int? ItemDifficulty
{
get => GetProperty(PropertyInt.ItemDifficulty);
Expand All @@ -1656,6 +1662,12 @@ public string Inscription
set { if (!value.HasValue) RemoveProperty(PropertyInt.AppraisalItemSkill); else SetProperty(PropertyInt.AppraisalItemSkill, value.Value); }
}

public uint? ItemSkillLimit
{
get => GetProperty(PropertyDataId.ItemSkillLimit);
set { if (!value.HasValue) RemoveProperty(PropertyDataId.ItemSkillLimit); else SetProperty(PropertyDataId.ItemSkillLimit, value.Value); }
}

public int? ItemSkillLevelLimit
{
get => GetProperty(PropertyInt.ItemSkillLevelLimit);
Expand Down Expand Up @@ -1710,10 +1722,10 @@ public string Use
set { if (!value.HasValue) RemoveProperty(PropertyDataId.Spell); else SetProperty(PropertyDataId.Spell, value.Value); }
}

public int ItemSpellcraft
public int? ItemSpellcraft
{
get => GetProperty(PropertyInt.ItemSpellcraft) ?? 0;
set { if (value == 0) RemoveProperty(PropertyInt.ItemSpellcraft); else SetProperty(PropertyInt.ItemSpellcraft, value); }
get => GetProperty(PropertyInt.ItemSpellcraft);
set { if (value.HasValue) RemoveProperty(PropertyInt.ItemSpellcraft); else SetProperty(PropertyInt.ItemSpellcraft, value.Value); }
}

public int? BoostEnum
Expand Down