Exemplo n.º 1
0
    public bool Process()
    {
        if (Timer == 0)
        {
            Unit.VState       = UnitVisualState.Attacking;
            Unit.AttackFrame  = 0;
            Unit.AttackTime   = 0;
            Unit.DoUpdateView = true;
            Speed             = 0.5f;

            // disable invisibility on attack, but only if target is not self
            if (TargetUnit != Unit)
            {
                List <SpellEffects.Invisibility> invis = Unit.GetSpellEffects <SpellEffects.Invisibility>();
                foreach (SpellEffects.Invisibility inv in invis)
                {
                    Unit.RemoveSpellEffect(inv);
                }
            }
        }

        if (Unit.Class.AttackPhases > 1)
        {
            if (Speed * Unit.AttackTime >= Unit.Class.AttackFrames[Unit.AttackFrame].Time)
            {
                //Unit.AttackFrame = ++Unit.AttackFrame % Unit.Class.AttackPhases;
                Unit.AttackFrame++;
                if (Unit.AttackFrame >= Unit.Class.AttackPhases)
                {
                    Unit.AttackFrame = Unit.Class.AttackPhases - 1;
                }
                Unit.AttackTime   = -1;
                Unit.DoUpdateView = true;
            }

            Unit.AttackTime++;
        }
        else
        {
            Unit.AttackFrame = 0;
            Unit.AttackTime  = 0;
        }

        if (Speed * Timer >= Unit.Charge && !NetworkManager.IsClient && !DamageDone)
        {
            // do damage here!
            // check if we need to fire a projectile (range)
            AllodsProjectile proj = AllodsProjectile.None; // default :D

            // check for castspell in weapon.
            // check for weapon.
            List <Spell> castspells   = new List <Spell>();
            bool         procoverride = false;
            if (Unit.GetObjectType() == MapObjectType.Human)
            {
                Item weapon = ((MapHuman)Unit).GetItemFromBody(MapUnit.BodySlot.Weapon);
                // if weapon is a staff, then castspell is called immediately.
                // otherwise castspell is only applied when the projectile hits.
                if (weapon != null && weapon.IsValid)
                {
                    foreach (ItemEffect eff in weapon.Effects)
                    {
                        if (eff.Type1 == ItemEffect.Effects.CastSpell)
                        {
                            Spell sp = new Spell(eff.Value1);
                            sp.Skill = eff.Value2;
                            sp.User  = Unit;
                            sp.Item  = weapon;
                            castspells.Add(sp);
                        }
                    }

                    if (weapon.Class.Option.Name == "Staff" || weapon.Class.Option.Name == "Shaman Staff")
                    {
                        procoverride = true;
                    }
                }
            }

            if (Unit.Interaction.GetAttackRange() > 1)
            {
                // send this projectile to clients too
                // make projectile specified in the unit class.
                proj = (AllodsProjectile)Unit.Class.Projectile;
            }

            if (!procoverride && Spell == null)
            {
                if (proj != AllodsProjectile.None)
                {
                    // following offsets are based on unit's width, height and center
                    float cX = Unit.X + Unit.Width * 0.5f + Unit.FracX;
                    float cY = Unit.Y + Unit.Height * 0.5f + Unit.FracY;

                    float tX = TargetUnit.X + TargetUnit.Width * 0.5f + TargetUnit.FracX;
                    float tY = TargetUnit.Y + TargetUnit.Height * 0.5f + TargetUnit.FracY;

                    Vector2 dir = new Vector2(tX - cX, tY - cY).normalized *((Unit.Width + Unit.Height) / 2) / 1.5f;
                    cX += dir.x;
                    cY += dir.y;

                    Server.SpawnProjectileDirectional(proj, Unit, cX, cY, 0,
                                                      tX, tY, 0,
                                                      10,
                                                      (MapProjectile fproj) =>
                    {
                        if (fproj.ProjectileX >= TargetUnit.X + TargetUnit.FracX &&
                            fproj.ProjectileY >= TargetUnit.Y + TargetUnit.FracY &&
                            fproj.ProjectileX < TargetUnit.X + TargetUnit.FracX + TargetUnit.Width &&
                            fproj.ProjectileY < TargetUnit.Y + TargetUnit.FracY + TargetUnit.Height)
                        {
                            //Debug.LogFormat("projectile hit!");
                            // done, make damage
                            TargetUnit.TakeDamage(DamageFlags, Unit, Damage);

                            // and cast spell
                            foreach (Spell spell in castspells)
                            {
                                Spells.SpellProc sp = spell.Cast(TargetUnit.X + TargetUnit.Width / 2, TargetUnit.Y + TargetUnit.Height / 2, TargetUnit);
                                if (sp != null)
                                {
                                    Unit.AddSpellProcessors(sp);
                                }
                            }
                        }

                        fproj.Dispose();
                    });
                }
                else
                {
                    TargetUnit.TakeDamage(DamageFlags, Unit, Damage);
                }
            }
            else
            {
                // cast spells directly
                // just do something atm.
                // todo: check spells that can be only casted on self (distance 0).
                if (Spell != null)
                {
                    Spells.SpellProc sp;
                    if (TargetUnit != null)
                    {
                        sp = Spell.Cast(TargetUnit.X + TargetUnit.Width / 2, TargetUnit.Y + TargetUnit.Height / 2, TargetUnit);
                    }
                    else
                    {
                        sp = Spell.Cast(TargetX, TargetY, null);
                    }
                    if (sp != null)
                    {
                        Unit.AddSpellProcessors(sp);
                    }
                    castspells.Clear();
                }
            }

            foreach (Spell spell in castspells)
            {
                Spells.SpellProc sp = spell.Cast(TargetUnit.X + TargetUnit.Width / 2, TargetUnit.Y + TargetUnit.Height / 2, TargetUnit);
                if (sp != null)
                {
                    Unit.AddSpellProcessors(sp);
                }
            }

            DamageDone = true;
        }

        if (Speed * Timer >= Unit.Charge + Unit.Relax)
        {
            return(false); // end of attack
        }
        Timer++;
        return(true);
    }