public virtual bool CastSpellOnCell(ushort spellid, short cellid, int targetId = 0)
        {
            SpellLevelRecord spellLevl = GetSpellLevel(spellid);

            if (!IsPlaying)
            {
                OnSpellCastFailed(CastFailedReason.NOT_PLAYING, spellLevl);
                return(false);
            }
            if (Fight.Ended)
            {
                OnSpellCastFailed(CastFailedReason.FIGHT_ENDED, spellLevl);
                return(false);
            }

            if (!ValidState(spellLevl))
            {
                OnSpellCastFailed(CastFailedReason.FORBIDDEN_STATE, spellLevl);
                return(false);
            }
            if (spellLevl.ApCost > FighterStats.Stats.ActionPoints)
            {
                OnSpellCastFailed(CastFailedReason.AP_COST, spellLevl);
                return(false);
            }
            if ((SpellIdEnum)spellid == SpellIdEnum.Punch)
            {
                UsingWeapon = true;
                bool result = UseWeapon(cellid);
                UsingWeapon = false;
                return(result);
            }
            if (targetId == 0)
            {
                var target = Fight.GetFighter(cellid);
                if (target != null)
                {
                    targetId = target.ContextualId;
                }
            }
            if (!SpellHistory.CanCast(spellLevl, targetId))
            {
                OnSpellCastFailed(CastFailedReason.CAST_LIMIT, spellLevl);
                return(false);
            }

            this.Fight.TryStartSequence(this.ContextualId, 1);
            FightSpellCastCriticalEnum critical = RollCriticalDice(spellLevl);

            short[] portals = new short[0];// WHAT THE F**K

            this.Fight.Send(new GameActionFightSpellCastMessage(0, ContextualId, targetId, cellid, (sbyte)critical, false, spellid, spellLevl.Grade, portals));
            this.SpellHistory.Add(spellLevl, targetId);

            #region EffectHandler

            if (CustomSpellEffectsProvider.Exist(spellid))
            {
                Fight.TryStartSequence(ContextualId, 1);
                CustomSpellEffectsProvider.Handle(spellid, spellLevl.Effects, this);
                Fight.TryEndSequence(1, 0);
            }
            else
            {
                HandleSpellEffects(spellLevl, cellid, critical);
            }
            #endregion

            FighterStats.Stats.ActionPoints -= spellLevl.ApCost;
            GameActionFightPointsVariation(ActionsEnum.ACTION_CHARACTER_ACTION_POINTS_USE, (short)-spellLevl.ApCost);
            if (CharacterRecord.GetCharacterRecordById(this.ContextualId) != null && CharacterRecord.GetCharacterRecordById(this.ContextualId).GodMod)
            {
                FighterStats.Stats.ActionPoints += spellLevl.ApCost;
                GameActionFightPointsVariation(ActionsEnum.ACTION_CHARACTER_ACTION_POINTS_WIN, (short)spellLevl.ApCost);
            }
            Fight.CheckFightEnd();

            if (Fight.Ended)
            {
                return(true);
            }
            RefreshStats();
            OnSpellCasted(spellLevl);
            this.Fight.TryEndSequence(1, 100);
            ApplyFighterEvent(FighterEventType.AFTER_USED_AP, spellLevl.ApCost);
            return(true);
        }