public bool CastSpell(GameObject target = null) { if (!m_Spell) { return(false); } GameObject actual_target = m_Spell.m_CastType == SpellCastType.FireAndForget ? target : m_Owner; //if the spell is not on CD or it has charges if ((!m_IsSpellOnCD || m_RemainingCharges > 0) && !m_IsConcentrating && !m_Spell.m_UseAllAvailableCharges) { m_IsConcentrating = m_Spell.m_CastType == SpellCastType.Concentration; m_InstantiatedSpell = m_Spell.CastSpell(m_Owner, actual_target, m_SpawnPoint.position, m_SpawnParent.rotation); m_RemainingCharges--; // only update cooldown if it's not already on cooldown // i.e when there's no charges left if (!m_IsSpellOnCD) { m_RemainingCD = m_Spell.m_SpellCooldown; } m_IsSpellOnCD = true; return(true); } else if (m_Spell.m_UseAllAvailableCharges && !m_UsingCharges && m_RemainingCharges > 0) { m_IsConcentrating = m_Spell.m_CastType == SpellCastType.Concentration; m_RemainingCD = m_Spell.m_SpellCooldown; m_IsSpellOnCD = true; float delay = 0.05f; float ttl = delay * m_RemainingCharges * 1.1f; GameplayStatics.Delay(delay * m_RemainingCD * 1.1f, () => m_UsingCharges = true, () => m_UsingCharges = false); GameplayStatics.AddTimer(m_Owner, ttl, delay, () => { if (m_RemainingCharges > 0) { m_InstantiatedSpell = m_Spell.CastSpell(m_Owner, actual_target, m_SpawnPoint.position, m_SpawnParent.rotation); m_RemainingCharges--; } }); return(true); } else if (m_IsConcentrating) { m_Spell.StopConcentration(m_InstantiatedSpell); m_IsConcentrating = false; } return(false); }