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;
        }

        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
                            if (TargetUnit.TakeDamage(DamageFlags, Unit, Damage) > 0)
                            {
                                TargetUnit.DoUpdateInfo = true;
                                TargetUnit.DoUpdateView = true;
                            }

                            // 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.AddSpellEffects(sp);
                                }
                            }
                        }

                        fproj.Dispose();
                        MapLogic.Instance.Objects.Remove(fproj);
                    });
                }
                else
                {
                    if (TargetUnit.TakeDamage(DamageFlags, Unit, Damage) > 0)
                    {
                        TargetUnit.DoUpdateInfo = true;
                        TargetUnit.DoUpdateView = true;
                    }
                }
            }
            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.AddSpellEffects(sp);
                    }
                }
                else
                {
                    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.AddSpellEffects(sp);
                        }
                    }
                }
            }

            DamageDone = true;
        }

        if (Speed * Timer >= Unit.Charge + Unit.Relax)
        {
            return(false); // end of attack
        }
        Timer++;
        return(true);
    }
Exemplo n.º 2
0
        public override bool Process()
        {
            if (NetworkManager.IsClient)
            {
                return(false);
            }

            // 5x5, but remove corners
            for (int y = TargetY - 2; y <= TargetY + 2; y++)
            {
                for (int x = TargetX - 2; x <= TargetX + 2; x++)
                {
                    // check for corner tiles :)
                    if ((x == TargetX - 2 || x == TargetX + 2) && (y == TargetY - 2 || y == TargetY + 2))
                    {
                        continue;
                    }
                    if (x < 0 || y < 0 ||
                        x >= MapLogic.Instance.Width ||
                        y >= MapLogic.Instance.Height)
                    {
                        continue;
                    }

                    // check if there are FIRE effects on this cell, don't spawn fog
                    bool spawnblocked = false;
                    foreach (MapObject mo in MapLogic.Instance.Nodes[x, y].Objects)
                    {
                        if (!(mo is MapProjectile))
                        {
                            continue;
                        }

                        MapProjectile mp = (MapProjectile)mo;
                        if (mp.Class == null || mp.Class.ID != (int)AllodsProjectile.PoisonCloud)
                        {
                            continue;
                        }

                        // don't remove if on edge of fire wall
                        if (new Vector2(mp.ProjectileX - x + 0.5f, mp.ProjectileY - y + 0.5f).magnitude > 0.8f)
                        {
                            continue;
                        }

                        spawnblocked = true;
                        break;
                    }

                    if (spawnblocked)
                    {
                        continue;
                    }

                    Server.SpawnProjectileEOT(AllodsProjectile.PoisonCloud, Spell.User, x + 0.5f, y + 0.5f, 0, (int)(MapLogic.TICRATE * Spell.GetDuration()), 40, 0, 0, 16, proj =>
                    {
                        DamageFlags spdf = SphereToDamageFlags(Spell);
                        // get projectile cells
                        int axFrom = Mathf.Max(0, Mathf.FloorToInt(proj.ProjectileX));
                        int axTo   = Mathf.Min(MapLogic.Instance.Width - 1, Mathf.CeilToInt(proj.ProjectileX));
                        int ayFrom = Mathf.Max(0, Mathf.FloorToInt(proj.ProjectileY));
                        int ayTo   = Mathf.Min(MapLogic.Instance.Height - 1, Mathf.CeilToInt(proj.ProjectileY));
                        for (int py = ayFrom; py <= ayTo; py++)
                        {
                            for (int px = axFrom; px <= axTo; px++)
                            {
                                // check how much projectile is on this cell
                                float pdst = 1f - Mathf.Min(1f, new Vector2(px + 0.5f - proj.ProjectileX, py + 0.5f - proj.ProjectileY).magnitude);
                                // 0..1 effect power
                                MapNode node = MapLogic.Instance.Nodes[px, py];
                                for (int i = 0; i < node.Objects.Count; i++)
                                {
                                    MapObject mo = node.Objects[i];
                                    if (!(mo is MapUnit))
                                    {
                                        continue;
                                    }
                                    MapUnit mov = (MapUnit)mo;
                                    int dmg     = (int)(Spell.GetIndirectPower() * pdst);
                                    if (dmg <= 0)
                                    {
                                        continue;                                                                       // don't add null effects
                                    }
                                    SpellEffects.Effect eff = new SpellEffects.Poison(this, dmg, MapLogic.TICRATE * 8); // originally 8 seconds
                                    mov.AddSpellEffects(eff);
                                }
                            }
                        }
                    });
                }
            }

            return(false);
        }
Exemplo n.º 3
0
        public override bool Process()
        {
            if (NetworkManager.IsClient)
            {
                return(false);
            }

            // 11x11, but remove corners
            for (int y = TargetY - 5; y <= TargetY + 5; y++)
            {
                for (int x = TargetX - 5; x <= TargetX + 5; x++)
                {
                    // check for corner tiles :)
                    if (new Vector2(x - TargetX, y - TargetY).magnitude > 5.5f)
                    {
                        continue;
                    }
                    if (x < 0 || y < 0 ||
                        x >= MapLogic.Instance.Width ||
                        y >= MapLogic.Instance.Height)
                    {
                        continue;
                    }

                    // remove light effects
                    MapNode node = MapLogic.Instance.Nodes[x, y];
                    for (int i = 0; i < node.Objects.Count; i++)
                    {
                        MapObject mo = node.Objects[i];
                        if (mo is MapProjectile &&
                            ((((MapProjectile)mo).ClassID == AllodsProjectile.SpecDarkness) || (((MapProjectile)mo).ClassID == AllodsProjectile.SpecLight)))
                        {
                            mo.Dispose();
                            i--;
                            continue;
                        }
                    }

                    float power      = Spell.GetScanRange();
                    int   lightlevel = (int)(-(power * 32));

                    Server.SpawnProjectileEOT(AllodsProjectile.SpecDarkness, Spell.User, x + 0.5f, y + 0.5f, 0, (int)(MapLogic.TICRATE * Spell.GetDuration()), MapLogic.TICRATE / 2, 0, 0, 16, proj =>
                    {
                        MapNode pnode = MapLogic.Instance.Nodes[proj.X, proj.Y];
                        for (int i = 0; i < pnode.Objects.Count; i++)
                        {
                            MapObject mo = pnode.Objects[i];
                            if (!(mo is MapUnit))
                            {
                                continue;
                            }

                            MapUnit mov = (MapUnit)mo;
                            // don't affect AI units
                            if (mov.Player == null || mov.Player.DoFullAI)
                            {
                                continue;
                            }

                            SpellEffects.Effect eff = new SpellEffects.Darkness(MapLogic.TICRATE / 2, Spell.GetScanRange()); // 1 second
                            mov.AddSpellEffects(eff);
                        }
                    }, lightlevel);
                }
            }

            return(false);
        }