Ejemplo n.º 1
0
    private void PrepareTrainers(Creature challenger, Creature player)
    {
        var pos          = challenger.GetPosition();
        var playerNewPos = pos.GetRelative(MabiMath.ByteToRadian(challenger.Direction), BattleDistance);

        _challengerMonsterPos = playerNewPos.GetRelative(pos, -MonsterDistance);
        _playerMonsterPos     = pos.GetRelative(playerNewPos, -MonsterDistance);

        //challenger.Region.AddProp(new Prop(10, challenger.RegionId, _challengerMonsterPos.X, _challengerMonsterPos.Y, 0));
        //challenger.Region.AddProp(new Prop(10, challenger.RegionId, _playerMonsterPos.X, _playerMonsterPos.Y, 0));

        // Camera
        var packet = new Packet(Op.SetCamera, player.EntityId);

        packet.PutFloat(1000);                                                                                              // distance
        packet.PutFloat(0);
        packet.PutFloat(5);                                                                                                 // pitch
        packet.PutFloat(MabiMath.DirectionToRadian(pos.X - playerNewPos.X, pos.Y - playerNewPos.Y) * (180 / Math.PI) + 25); // yaw
        packet.PutFloat(0);
        player.Client.Send(packet);

        // Move and turn
        player.Jump(playerNewPos);
        player.TurnTo(pos);
        challenger.TurnTo(playerNewPos);
    }
Ejemplo n.º 2
0
        public void GetRelative()
        {
            var pos1 = new Position(100, 100);
            var pos2 = new Position(100, 200);

            Assert.Equal(new Position(100, 250), pos1.GetRelative(pos2, 50));
            Assert.Equal(new Position(100, 150), pos1.GetRelative(pos2, -50));
            Assert.Equal(new Position(100, -50), pos1.GetRelative(pos2, -250));

            var pos3 = new Position(50, 100);

            Assert.Equal(new Position(0, 100), pos1.GetRelative(pos3, 50));
            Assert.Equal(new Position(100, 100), pos1.GetRelative(pos3, -50));
            Assert.Equal(new Position(300, 100), pos1.GetRelative(pos3, -250));

            var up    = MabiMath.DegreeToRadian(90);
            var down  = MabiMath.DegreeToRadian(270);
            var left  = MabiMath.DegreeToRadian(180);
            var right = MabiMath.DegreeToRadian(0);

            Assert.Equal(new Position(100, 200), pos1.GetRelative(up, 100));
            Assert.Equal(new Position(100, 0), pos1.GetRelative(down, 100));
            Assert.Equal(new Position(0, 100), pos1.GetRelative(left, 100));
            Assert.Equal(new Position(200, 100), pos1.GetRelative(right, 100));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Sets up shop, spawning the prop.
        /// </summary>
        /// <param name="title"></param>
        /// <param name="description"></param>
        public bool SetUp(string title, string description)
        {
            if (!this.IsReadyForBusiness)
            {
                return(false);
            }

            this.Title       = title;
            this.Description = description;

            var rnd       = RandomProvider.Get();
            var pos       = this.Owner.GetPosition();
            var location  = new Location(this.Owner.RegionId, GetPlacementPosition(pos, this.Owner.Direction));
            var direction = MabiMath.ByteToRadian(this.Owner.Direction);

            // Spawn prop
            var propId = GetShopPropId(this.Bag);

            this.Prop             = new Prop(propId, location.RegionId, location.X, location.Y, (float)direction);
            this.Prop.Info.Color1 = this.Bag.Info.Color1;
            this.Prop.Info.Color2 = this.Bag.Info.Color2;
            this.Prop.Info.Color3 = this.Bag.Info.Color3;
            this.Prop.Extensions.AddSilent(new ConfirmationPropExtension("default", "이 개인상점을 여시겠습니까?", "개인상점 열기"));
            this.Region.AddProp(this.Prop);

            // Move that body
            Send.UseMotion(this.Owner, 11, 4);

            // Update prop with owner and title
            this.Prop.Xml.SetAttributeValue("PSPID", this.Owner.EntityId);
            this.Prop.Xml.SetAttributeValue("PSTTL", title);
            Send.PropUpdate(this.Prop);

            return(true);
        }
Ejemplo n.º 4
0
    protected override IEnumerable Idle()
    {
        var challenger = Creature;

        if (challenger.Vars.Temp["inTrainerBattleWith"] != null)
        {
            Return();
        }

        var dir = MabiMath.ByteToRadian(challenger.Direction) - Math.PI;         // opposite direction...?
        var pos = challenger.GetPosition();

        var players = challenger.Region.GetCreatures(a => a.IsPlayer && a.GetPosition().InCone(pos, dir, 1000, 45));

        if (players.Count != 1)
        {
            Return();
        }

        var opponent = players.First();

        if (_fought.Contains(opponent.EntityId))
        {
            Return();
        }

        _fought.Add(opponent.EntityId);

        TrainerBaseScript.StartBattle(challenger, opponent);
    }
Ejemplo n.º 5
0
        /// <summary>
        /// Spawns treasure chests in treasure room.
        /// </summary>
        private void SpawnTreasureChests()
        {
            var region = this.Regions.Last();
            var rnd    = RandomProvider.Get();

            for (int i = 0; i < _treasureChests.Count; ++i)
            {
                var pos = new Generation.Position(this.Generator.Floors.Last().MazeGenerator.EndPos);

                pos.X *= Dungeon.TileSize;
                pos.Y *= Dungeon.TileSize;

                pos.X += Dungeon.TileSize / 2;
                pos.Y += (int)(Dungeon.TileSize * 2.5f);

                var placement = _treasurePlacementProvider.GetPosition();

                pos.X += placement[0];
                pos.Y += placement[1];
                var rotation = MabiMath.DegreeToRadian(placement[2]);

                var prop = _treasureChests[i];
                prop.RegionId       = region.Id;
                prop.Info.X         = pos.X;
                prop.Info.Y         = pos.Y;
                prop.Info.Direction = rotation;
                region.AddProp(prop);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Reduces hunger by amount and handles weight gain/loss
        /// and stat bonuses.
        /// </summary>
        /// <remarks>
        /// Body and stat changes are applied inside Creature,
        /// on MabiTick (every 5 minutes).
        /// </remarks>
        protected void Feed(Creature creature, double hunger, double weight = 0, double upper = 0, double lower = 0, double str = 0, double int_ = 0, double dex = 0, double will = 0, double luck = 0, double life = 0, double mana = 0, double stm = 0)
        {
            // Saturday: Food effects are increased. (2x weight, hunger; effects are long term)
            // +100%? Seems a lot, but that's what the Wiki says.
            if (ErinnTime.Now.Month == ErinnMonth.Samhain)
            {
                hunger *= 2;
                weight *= 2;
                upper  *= 2;
                lower  *= 2;
            }

            // Hunger
            var diff = creature.Hunger;

            creature.Hunger -= (float)hunger;
            diff            -= creature.Hunger;

            // Weight (multiplicators guessed, based on packets)
            // Only increase weight if you eat above 0% Hunger?
            if (diff < hunger)
            {
                creature.Temp.WeightFoodChange += (float)weight * (weight >= 0 ? WeightChangePlus : WeightChangeMinus);
                creature.Temp.UpperFoodChange  += (float)upper * (upper >= 0 ? WeightChangePlus : WeightChangeMinus);
                creature.Temp.LowerFoodChange  += (float)lower * (lower >= 0 ? WeightChangePlus : WeightChangeMinus);
            }

            // Stats
            creature.Temp.StrFoodChange  += MabiMath.FoodStatBonus(str, hunger, diff, creature.Age);
            creature.Temp.IntFoodChange  += MabiMath.FoodStatBonus(int_, hunger, diff, creature.Age);
            creature.Temp.DexFoodChange  += MabiMath.FoodStatBonus(dex, hunger, diff, creature.Age);
            creature.Temp.WillFoodChange += MabiMath.FoodStatBonus(will, hunger, diff, creature.Age);
            creature.Temp.LuckFoodChange += MabiMath.FoodStatBonus(luck, hunger, diff, creature.Age);
        }
Ejemplo n.º 7
0
        public void InCone()
        {
            var centerPos = new Position(0, 0);
            var topPos    = new Position(0, 500);
            var bottomPos = new Position(0, -500);
            var leftPos   = new Position(-500, 0);
            var rightPos  = new Position(500, 0);

            var up    = MabiMath.DegreeToRadian(90);
            var down  = MabiMath.DegreeToRadian(270);
            var left  = MabiMath.DegreeToRadian(180);
            var right = MabiMath.DegreeToRadian(0);

            Assert.Equal(true, topPos.InCone(centerPos, up, 600, MabiMath.DegreeToRadian(10)));
            Assert.Equal(true, bottomPos.InCone(centerPos, down, 600, MabiMath.DegreeToRadian(10)));
            Assert.Equal(true, leftPos.InCone(centerPos, left, 600, MabiMath.DegreeToRadian(10)));
            Assert.Equal(true, rightPos.InCone(centerPos, right, 600, MabiMath.DegreeToRadian(10)));

            Assert.Equal(true, topPos.InCone(centerPos, up, 500, MabiMath.DegreeToRadian(10)));
            Assert.Equal(false, topPos.InCone(centerPos, up, 500, MabiMath.DegreeToRadian(180)));
            Assert.Equal(true, topPos.InCone(centerPos, up, 600, MabiMath.DegreeToRadian(180)));
            Assert.Equal(true, topPos.InCone(centerPos, up, 1000, MabiMath.DegreeToRadian(180)));

            Assert.Equal(true, topPos.InCone(centerPos, up, 1000, MabiMath.DegreeToRadian(190)));
            Assert.Equal(true, topPos.InCone(centerPos, up, 1000, MabiMath.DegreeToRadian(-190)));
            Assert.Equal(true, topPos.InCone(centerPos, up, 1000, MabiMath.DegreeToRadian(9999)));
            Assert.Equal(true, topPos.InCone(centerPos, up, 1000, MabiMath.DegreeToRadian(-9999)));

            Assert.Equal(false, topPos.InCone(centerPos, MabiMath.DegreeToRadian(45), 2000, MabiMath.DegreeToRadian(45)));
            Assert.Equal(true, topPos.InCone(centerPos, MabiMath.DegreeToRadian(68), 2000, MabiMath.DegreeToRadian(45)));
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Returns position for the shop, based on given position and direction.
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        private static Position GetPlacementPosition(Position pos, byte direction)
        {
            var radians = MabiMath.ByteToRadian(direction);
            var x       = pos.X + 50 * Math.Cos(radians);
            var y       = pos.Y + 50 * Math.Sin(radians);

            return(new Position((int)x, (int)y));
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Completes skill, placing the campfire.
        /// </summary>
        /// <param name="creature"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void Complete(Creature creature, Skill skill, Packet packet)
        {
            var positionId = packet.GetLong();
            var unkInt1    = packet.GetInt();
            var unkInt2    = packet.GetInt();

            // Handle items
            if (skill.Info.Id == SkillId.Campfire)
            {
                // Check Firewood, the client should stop the player long before Complete.
                if (creature.Inventory.Count(creature.Temp.FirewoodItemId) < FirewoodCost)
                {
                    throw new ModerateViolation("Used Campfire without Firewood.");
                }

                // Remove Firewood
                creature.Inventory.Remove(creature.Temp.FirewoodItemId, FirewoodCost);
            }
            else
            {
                // Check kit
                var item = creature.Inventory.GetItem(creature.Temp.CampfireKitItemEntityId);
                if (item == null)
                {
                    throw new ModerateViolation("Used CampfireKit with invalid kit.");
                }

                // Reduce kit
                creature.Inventory.Decrement(item);
            }

            // Set up Campfire
            var pos    = new Position(positionId);
            var effect = (skill.Info.Rank < SkillRank.RB ? "campfire_01" : "campfire_02");
            var prop   = new Prop(PropId, creature.RegionId, pos.X, pos.Y, MabiMath.ByteToRadian(creature.Direction), 1);           // Logs

            prop.State = "single";
            prop.Xml.SetAttributeValue("EFFECT", effect);                                                       // Fire effect
            prop.DisappearTime = DateTime.Now.AddMinutes(this.GetDuration(skill.Info.Rank, creature.RegionId)); // Disappear after x minutes

            // Temp data for Rest
            prop.Temp.CampfireSkillRank = skill.RankData;
            if (skill.Info.Id == SkillId.Campfire)
            {
                prop.Temp.CampfireFirewood = AuraData.ItemDb.Find(creature.Temp.FirewoodItemId);
            }

            creature.Region.AddProp(prop);

            // Complete
            Send.SkillComplete(creature, skill.Info.Id, positionId, unkInt1, unkInt2);
        }
Ejemplo n.º 10
0
    public override void OnPuzzleCreate(Puzzle puzzle)
    {
        var lockedPlace = puzzle.GetPlace("LockedPlace");
        var key         = puzzle.LockPlace(lockedPlace, "Boss");

        var chest = new Chest(puzzle, "KeyChest");

        lockedPlace.AddProp(chest, Placement.Center);

        chest.Info.Direction = MabiMath.DegreeToRadian(90);
        chest.Add(Item.Create(GoddessPass));
        chest.Add(key);
    }
Ejemplo n.º 11
0
        public void GetDirection()
        {
            var up    = MabiMath.DegreeToRadian(90);
            var down  = MabiMath.DegreeToRadian(270);
            var left  = MabiMath.DegreeToRadian(180);
            var right = MabiMath.DegreeToRadian(0);

            var pos = new Position(100, 100);

            Assert.Equal(up, pos.GetDirection(new Position(100, 200)));
            Assert.Equal(down, pos.GetDirection(new Position(100, 0)));
            Assert.Equal(left, pos.GetDirection(new Position(0, 100)));
            Assert.Equal(right, pos.GetDirection(new Position(200, 100)));
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Returns the radian rotation for the given dungeon direction.
        /// </summary>
        /// <remarks>
        /// TODO: Move somewhere? Direction maybe? Or an extension?
        /// </remarks>
        /// <param name="direction"></param>
        /// <returns></returns>
        private static float Rotation(int direction)
        {
            switch (direction)
            {
            case Direction.Up: return(MabiMath.DirectionToRadian(0, -1));

            case Direction.Down: return(MabiMath.DirectionToRadian(0, 1));

            case Direction.Left: return(MabiMath.DirectionToRadian(1, 0));

            case Direction.Right: return(MabiMath.DirectionToRadian(-1, 0));
            }

            throw new ArgumentException("Invalid direction '" + direction + "'.");
        }
Ejemplo n.º 13
0
    private void SpawnGate(Dungeon dungeon)
    {
        var region      = dungeon.Regions.Last();
        var endLocation = dungeon.GetEndRoomCenter();
        var direction   = MabiMath.DirectionToRadian(0, -1);

        var gate = new Prop(GatePropId, endLocation.RegionId, endLocation.X, endLocation.Y, direction);

        gate.Info.Color2 = 0xffffffff;
        gate.Behavior    = OnTouchGate;
        region.AddProp(gate);

        var portal = new Prop(GatePortalPropId, endLocation.RegionId, endLocation.X, endLocation.Y, direction);

        portal.Behavior = OnTouchPortal;
        region.AddProp(portal);
    }
Ejemplo n.º 14
0
    private void OnCharacterSelected(long entityId)
    {
        selectedCharacter = characters.FirstOrDefault(a => a.EntityId == entityId);
        if (selectedCharacter == null)
        {
            Debug.LogErrorFormat("Missing character '{0}'.", entityId);
            return;
        }

        UpdateChannels(selectedCharacter.Server);
        SelChannel.interactable = true;

        var server = selectedCharacter.Server;
        var name   = selectedCharacter.Name;
        var color  = MabiMath.GetNameColor(name).ToString("X6");

        TxtSelectedChar.text         = string.Format("<size=20>{0}</size>\n<color=#{2}>{1}</color>", server, name, color);
        Connection.SelectedCharacter = selectedCharacter;
    }
Ejemplo n.º 15
0
        /// <summary>
        /// Adds prop to puzzle in place.
        /// </summary>
        /// <param name="place"></param>
        /// <param name="prop"></param>
        /// <param name="positionType"></param>
        public void AddProp(PuzzlePlace place, DungeonProp prop, Placement positionType)
        {
            if (this.Region == null)
            {
                throw new PuzzleException("AddProp outside of OnPuzzleCreate.");
            }

            var pos = place.GetPosition(positionType);

            prop.RegionId = this.Region.Id;
            prop.Info.X   = pos[0];
            prop.Info.Y   = pos[1];
            prop.UpdateShapes();
            prop.Info.Direction = MabiMath.DegreeToRadian(pos[2]);
            prop.Behavior      += PuzzleEvent;

            this.Region.AddProp(prop);
            this.Props[prop.Name] = prop;
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Spawns monsters from internal list.
        /// </summary>
        public void Spawn()
        {
            var rnd = RandomProvider.Get();

            var region   = this.Puzzle.Region;
            var worldPos = this.Place.GetWorldPosition();

            foreach (var monster in _monsters)
            {
                var pos = this.Place.GetPosition(_spawnPosition);
                monster.Direction = MabiMath.DegreeToByte(pos[2]);
                monster.Spawn(region.Id, pos[0], pos[1]);

                if (monster.AI != null)
                {
                    monster.AI.Activate(1000);
                }
            }
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Creates new door prop.
        /// </summary>
        /// <param name="propId"></param>
        /// <param name="regionId"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="direction">Direction the door faces in, in degree.</param>
        /// <param name="doorType"></param>
        /// <param name="name"></param>
        /// <param name="state"></param>
        public Door(int propId, int regionId, int x, int y, int direction, DungeonBlockType doorType, string name, string state = "open")
            : base(propId, regionId, x, y, direction, 1, 0, state, "", "")
        {
            this.Name      = name;
            this.DoorType  = doorType;
            this.BlockBoss = false;
            this.Behavior  = this.DefaultBehavior;
            _isSwitchDoor  = false;
            _closedFrom    = new Position(x / Dungeon.TileSize, y / Dungeon.TileSize);

            // Set direction and adjust Y for boss doors
            if (doorType == DungeonBlockType.BossDoor)
            {
                this.Info.Direction = MabiMath.DirectionToRadian(0, 1);
                this.Info.Y        += Dungeon.TileSize + Dungeon.TileSize / 2;
            }
            else
            {
                this.Info.Direction = MabiMath.DegreeToRadian(direction);
            }
        }
Ejemplo n.º 18
0
    private void SpawnMonster(Creature challenger, int regionId, Position pos, Position turnPos)
    {
        var npc = (NPC)challenger;

        if (npc.AI != null)
        {
            npc.AI.Detach();
        }
        npc.Direction    = MabiMath.DirectionToByte(turnPos.X - pos.X, turnPos.Y - pos.Y);
        npc.LifeMaxBase /= LifeRatio;
        npc.Life         = npc.LifeMax;
        npc.State       |= CreatureStates.Spawned;
        npc.State       |= CreatureStates.GoodNpc;

        if (!npc.Skills.Has(SkillId.CombatMastery))
        {
            npc.Skills.Give(SkillId.CombatMastery, SkillRank.RF);
        }
        if (!npc.Skills.Has(SkillId.Smash))
        {
            npc.Skills.Give(SkillId.Smash, SkillRank.RF);
        }
        if (!npc.Skills.Has(SkillId.Defense))
        {
            npc.Skills.Give(SkillId.Defense, SkillRank.RF);
        }
        if (!npc.Skills.Has(SkillId.Counterattack))
        {
            npc.Skills.Give(SkillId.Counterattack, SkillRank.RF);
        }
        if (!npc.Skills.Has(SkillId.Icebolt))
        {
            npc.Skills.Give(SkillId.Icebolt, SkillRank.RF);
        }

        challenger.Warp(regionId, pos);
        challenger.TurnTo(turnPos);
        Send.SpawnEffect(SpawnEffect.Monster, regionId, pos.X, pos.Y, challenger, challenger);
    }
Ejemplo n.º 19
0
    public override void OnLoad()
    {
        SetName("_<mini>NPC</mini> Piano Player");
        SetRace(10001);
        SetFace(skin: 18, eye: 0, eyeColor: 49, lip: 48);
        SetLocation(52, 46224, 43756, 206);

        EquipItem(Pocket.Hair, 9200, 0x000000, 0, 0);
        EquipItem(Pocket.Face, 3900, 0, 0, 0);
        EquipItem(Pocket.Armor, 15001, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF);
        EquipItem(Pocket.Shoe, 220056, 0xFFFFFF, 0xFFFFFF, 0x000000);

        // Spawn piano
        var pos  = NPC.GetPosition();
        var prop = new MabiProp(44311, NPC.Region, pos.X, pos.Y, MabiMath.DirToRad(NPC.Direction));

        prop.State     = "stand";
        prop.ExtraData = string.Format("<xml OWNER='{0}' SITCHAR='{0}'/>", NPC.Id);
        SpawnProp(prop);

        // Sit
        NPC.Temp.SittingProp = prop;
        NPC.State           |= CreatureStates.SitDown;
    }
Ejemplo n.º 20
0
        /// <summary>
        /// Reduces hunger by amount and handles weight gain/loss
        /// and stat bonuses.
        /// </summary>
        /// <remarks>
        /// Body and stat changes are applied inside Creature,
        /// on MabiTick (every 5 minutes).
        /// </remarks>
        protected void Feed(Creature creature, double hunger, double weight = 0, double upper = 0, double lower = 0, double str = 0, double int_ = 0, double dex = 0, double will = 0, double luck = 0, double life = 0, double mana = 0, double stm = 0)
        {
            // Hunger
            var diff = creature.Hunger;

            creature.Hunger -= (float)hunger;
            diff            -= creature.Hunger;

            // Weight (multiplicators guessed, based on packets)
            // Only increase weight if you eat above 0% Hunger?
            if (diff < hunger)
            {
                creature.Temp.WeightFoodChange += (float)weight * (weight >= 0 ? WeightChangePlus : WeightChangeMinus);
                creature.Temp.UpperFoodChange  += (float)upper * (upper >= 0 ? WeightChangePlus : WeightChangeMinus);
                creature.Temp.LowerFoodChange  += (float)lower * (lower >= 0 ? WeightChangePlus : WeightChangeMinus);
            }

            // Stats
            creature.Temp.StrFoodChange  += MabiMath.FoodStatBonus(str, hunger, diff, creature.Age);
            creature.Temp.IntFoodChange  += MabiMath.FoodStatBonus(int_, hunger, diff, creature.Age);
            creature.Temp.DexFoodChange  += MabiMath.FoodStatBonus(dex, hunger, diff, creature.Age);
            creature.Temp.WillFoodChange += MabiMath.FoodStatBonus(will, hunger, diff, creature.Age);
            creature.Temp.LuckFoodChange += MabiMath.FoodStatBonus(luck, hunger, diff, creature.Age);
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Initiates floor, creating puzzles and props.
        /// </summary>
        /// <param name="iRegion"></param>
        public void InitFloorRegion(int iRegion)
        {
            this.CreatePuzzles(iRegion);

            var region    = this.Regions[iRegion];
            var floor     = this.Generator.Floors[iRegion - 1];
            var gen       = floor.MazeGenerator;
            var floorData = this.Data.Floors[iRegion - 1];

            var iPrevRegion = iRegion - 1;
            var iNextRegion = iRegion + 1;

            var startTile                  = gen.StartPos;
            var startPos                   = new Generation.Position(startTile.X * Dungeon.TileSize + Dungeon.TileSize / 2, startTile.Y * Dungeon.TileSize + Dungeon.TileSize / 2);
            var startRoomTrait             = floor.GetRoom(startTile);
            var startRoomIncomingDirection = startRoomTrait.GetIncomingDirection();

            var endTile          = gen.EndPos;
            var endPos           = new Generation.Position(endTile.X * Dungeon.TileSize + Dungeon.TileSize / 2, endTile.Y * Dungeon.TileSize + Dungeon.TileSize / 2);
            var endRoomTrait     = floor.GetRoom(endTile);
            var endRoomDirection = 0;

            for (int dir = 0; dir < 4; ++dir)
            {
                if (endRoomTrait.Links[dir] == LinkType.To)
                {
                    endRoomDirection = dir;
                    break;
                }
            }

            // Create upstairs prop
            var stairsBlock = this.Data.Style.Get(DungeonBlockType.StairsUp, startRoomIncomingDirection);
            var stairs      = new Prop(stairsBlock.PropId, region.Id, startPos.X, startPos.Y, MabiMath.DegreeToRadian(stairsBlock.Rotation), 1, 0, "single");

            stairs.Info.Color1 = floorData.Color1;
            stairs.Info.Color2 = floorData.Color1;
            stairs.Info.Color3 = floorData.Color3;
            region.AddProp(stairs);

            // Create portal prop leading to prev floor
            var portalBlock = this.Data.Style.Get(DungeonBlockType.PortalUp, startRoomIncomingDirection);
            var portal      = new Prop(portalBlock.PropId, region.Id, startPos.X, startPos.Y, MabiMath.DegreeToRadian(portalBlock.Rotation), 1, 0, "single", "_upstairs", Localization.Get("<mini>TO</mini> Upstairs"));

            portal.Info.Color1 = floorData.Color1;
            portal.Info.Color2 = floorData.Color1;
            portal.Info.Color3 = floorData.Color3;
            portal.Behavior    = (cr, pr) =>
            {
                // Indoor_RDungeon_EB marks the end position on the prev floor.
                var clientEvent = this.Regions[iPrevRegion].GetClientEvent("Indoor_RDungeon_EB");
                if (clientEvent == null)
                {
                    Log.Error("Event 'Indoor_RDungeon_EB' not found while trying to warp to '{0}'.", this.Regions[iPrevRegion].Name);
                    return;
                }

                // Warp to prev region
                var regionId = this.Regions[iPrevRegion].Id;
                var x        = (int)clientEvent.Data.X;
                var y        = (int)clientEvent.Data.Y;

                cr.Warp(regionId, x, y);
            };
            region.AddProp(portal);

            // Create save statue
            if (floorData.Statue)
            {
                var saveStatue = new Prop(this.Data.SaveStatuePropId, region.Id, startPos.X, startPos.Y, MabiMath.DegreeToRadian(stairsBlock.Rotation + 180), 1, 0, "single");
                saveStatue.Info.Color1 = floorData.Color1;
                saveStatue.Info.Color2 = floorData.Color1;
                saveStatue.Info.Color3 = floorData.Color3;
                saveStatue.Behavior    = (cr, pr) =>
                {
                    cr.DungeonSaveLocation = cr.GetLocation();
                    Send.Notice(cr, Localization.Get("You have memorized this location."));

                    // Scroll message
                    var msg = string.Format("You're currently on Floor {0} of {1}. ", iRegion, this.Data.EngName);
                    Send.Notice(cr, NoticeType.Top, ScrollMessageDuration, msg + this.GetPlayerListScrollMessage());
                };
                region.AddProp(saveStatue);
            }

            // Spawn boss or downstair props
            // TODO: There is one dungeon that has two boss rooms.
            if (floor.IsLastFloor)
            {
                // Create door to treasure room
                _bossExitDoor             = new Prop(this.Data.BossExitDoorId, region.Id, endPos.X, endPos.Y + Dungeon.TileSize / 2, Rotation(Direction.Up), 1, 0, "closed");
                _bossExitDoor.Info.Color1 = floorData.Color1;
                _bossExitDoor.Info.Color2 = floorData.Color1;
                _bossExitDoor.Info.Color3 = floorData.Color3;
                region.AddProp(_bossExitDoor);

                // Get or create boss door
                if (endRoomTrait.PuzzleDoors[Direction.Down] == null)
                {
                    Log.Warning("Dungeon.InitFloorRegion: No locked place in last section of '{0}'.", this.Name);

                    _bossDoor             = new Door(this.Data.BossDoorId, region.Id, endPos.X, endPos.Y - Dungeon.TileSize, Direction.Up, DungeonBlockType.BossDoor, "", "closed");
                    _bossDoor.Info.Color1 = floorData.Color1;
                    _bossDoor.Info.Color2 = floorData.Color1;
                    _bossDoor.Info.Color3 = floorData.Color3;
                    _bossDoor.Behavior    = (cr, pr) => { _bossDoor.Open(); };
                    _bossDoor.Behavior   += this.BossDoorBehavior;
                    _bossDoor.UpdateShapes();
                    endRoomTrait.SetPuzzleDoor(_bossDoor, Direction.Down);                     // making sure another open dummy door won't be added here
                    region.AddProp(_bossDoor);
                }
                else
                {
                    _bossDoor = endRoomTrait.PuzzleDoors[Direction.Down];
                    if (_bossDoor.State == "open")
                    {
                        Log.Warning("Dungeon.InitFloorRegion: Boss door was left open, closing. Dungeon: '{0}'.", this.Name);
                        _bossDoor.Close(endRoomTrait.X, endRoomTrait.Y);
                    }
                }

                // Create exit statue
                var exitStatue = new Prop(this.Data.LastStatuePropId, region.Id, endPos.X, endPos.Y + Dungeon.TileSize * 2, Rotation(Direction.Up), 1, 0, "single");
                exitStatue.Info.Color1 = floorData.Color1;
                exitStatue.Info.Color2 = floorData.Color1;
                exitStatue.Info.Color3 = floorData.Color3;
                exitStatue.Extensions.AddSilent(new ConfirmationPropExtension("GotoLobby", "_LT[code.standard.msg.dungeon_exit_notice_msg]", "_LT[code.standard.msg.dungeon_exit_notice_title]", "haskey(chest)"));
                exitStatue.Behavior = (cr, pr) =>
                {
                    ChannelServer.Instance.Events.OnPlayerClearedDungeon(cr, this);
                    cr.Warp(this.Data.Exit);
                };
                region.AddProp(exitStatue);
            }
            else
            {
                // Create downstairs prop
                var stairsDownBlock = this.Data.Style.Get(DungeonBlockType.StairsDown, endRoomDirection);
                var stairsDown      = new Prop(stairsDownBlock.PropId, region.Id, endPos.X, endPos.Y, MabiMath.DegreeToRadian(stairsDownBlock.Rotation), 1, 0, "single");
                stairsDown.Info.Color1 = floorData.Color1;
                stairsDown.Info.Color2 = floorData.Color1;
                stairsDown.Info.Color3 = floorData.Color3;
                region.AddProp(stairsDown);

                // Create portal leading to the next floor
                var portalDownBlock = this.Data.Style.Get(DungeonBlockType.PortalDown, endRoomDirection);
                var portalDown      = new Prop(portalDownBlock.PropId, region.Id, endPos.X, endPos.Y, MabiMath.DegreeToRadian(portalDownBlock.Rotation), 1, 0, "single", "_downstairs", Localization.Get("<mini>TO</mini> Downstairs"));
                portalDown.Info.Color1 = floorData.Color1;
                portalDown.Info.Color2 = floorData.Color1;
                portalDown.Info.Color3 = floorData.Color3;
                portalDown.Behavior    = (cr, pr) =>
                {
                    // Indoor_RDungeon_SB marks the start position on the next floor.
                    var clientEvent = this.Regions[iNextRegion].GetClientEvent("Indoor_RDungeon_SB");
                    if (clientEvent == null)
                    {
                        Log.Error("Event 'Indoor_RDungeon_SB' not found while trying to warp to '{0}'.", this.Regions[iNextRegion].Name);
                        return;
                    }

                    // Warp to next floor
                    var regionId = this.Regions[iNextRegion].Id;
                    var x        = (int)clientEvent.Data.X;
                    var y        = (int)clientEvent.Data.Y;

                    cr.Warp(regionId, x, y);
                };
                region.AddProp(portalDown);
            }

            // Place dummy doors
            for (int x = 0; x < floor.MazeGenerator.Width; ++x)
            {
                for (int y = 0; y < floor.MazeGenerator.Height; ++y)
                {
                    var room      = floor.MazeGenerator.GetRoom(x, y);
                    var roomTrait = floor.GetRoom(x, y);
                    var isRoom    = (roomTrait.RoomType >= RoomType.Start);

                    if (!room.Visited || !isRoom)
                    {
                        continue;
                    }

                    for (var dir = 0; dir < 4; ++dir)
                    {
                        // Skip stairs
                        if (roomTrait.RoomType == RoomType.Start && dir == startRoomIncomingDirection)
                        {
                            continue;
                        }
                        if (roomTrait.RoomType == RoomType.End && dir == endRoomDirection)
                        {
                            continue;
                        }

                        if (roomTrait.Links[dir] == LinkType.None)
                        {
                            continue;
                        }

                        if (roomTrait.PuzzleDoors[dir] == null)
                        {
                            var doorX = x * Dungeon.TileSize + Dungeon.TileSize / 2;
                            var doorY = y * Dungeon.TileSize + Dungeon.TileSize / 2;

                            var doorBlock = this.Data.Style.Get(DungeonBlockType.Door, dir);
                            var doorProp  = new Prop(doorBlock.PropId, region.Id, doorX, doorY, MabiMath.DegreeToRadian(doorBlock.Rotation), state: "open");
                            doorProp.Info.Color1 = floorData.Color1;
                            doorProp.Info.Color2 = floorData.Color2;
                            doorProp.Info.Color3 = floorData.Color3;
                            region.AddProp(doorProp);
                        }
                        else if (roomTrait.PuzzleDoors[dir].EntityId == 0)
                        {
                            // Add doors from failed puzzles
                            roomTrait.PuzzleDoors[dir].Info.Region = region.Id;
                            region.AddProp(roomTrait.PuzzleDoors[dir]);
                        }
                    }
                }
            }
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Creates sitting prop, fails silently if item or chair
        /// data doesn't exist.
        /// </summary>
        /// <param name="creature"></param>
        /// <param name="chairItemEntityId"></param>
        private void SetUpChair(Creature creature, long chairItemEntityId)
        {
            if (chairItemEntityId == 0)
            {
                return;
            }

            // Check item
            var item = creature.Inventory.GetItem(chairItemEntityId);

            if (item == null || item.Data.Type != ItemType.Misc)
            {
                return;
            }

            // Get chair data
            var chairData = AuraData.ChairDb.Find(item.Info.Id);

            if (chairData == null)
            {
                return;
            }

            var pos = creature.GetPosition();

            // Effect
            if (chairData.Effect != 0)
            {
                Send.Effect(creature, chairData.Effect, true);
            }

            // Chair prop
            var sittingProp = new Prop((!creature.IsGiant ? chairData.PropId : chairData.GiantPropId), creature.RegionId, pos.X, pos.Y, MabiMath.ByteToRadian(creature.Direction));

            sittingProp.Info.Color1 = item.Info.Color1;
            sittingProp.Info.Color2 = item.Info.Color2;
            sittingProp.Info.Color3 = item.Info.Color3;
            sittingProp.State       = "stand";
            creature.Region.AddProp(sittingProp);

            // Move char
            Send.AssignSittingProp(creature, sittingProp.EntityId, 1);

            // Update chair
            sittingProp.Xml.SetAttributeValue("OWNER", creature.EntityId);
            sittingProp.Xml.SetAttributeValue("SITCHAR", creature.EntityId);

            Send.PropUpdate(sittingProp);

            creature.Temp.CurrentChairData = chairData;
            creature.Temp.SittingProp      = sittingProp;
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Generates areas, incl (client) props and events.
        /// </summary>
        private void GenerateAreas()
        {
            this.Data = new RegionInfoData();

            var areaId = 2;
            var floor  = this.Floor;

            for (int x = 0; x < floor.MazeGenerator.Width; ++x)
            {
                for (int y = 0; y < floor.MazeGenerator.Height; ++y)
                {
                    var room      = floor.MazeGenerator.GetRoom(x, y);
                    var roomTrait = floor.GetRoom(x, y);

                    if (!room.Visited)
                    {
                        continue;
                    }

                    var isStart    = (roomTrait.RoomType == RoomType.Start);
                    var isEnd      = (roomTrait.RoomType == RoomType.End);
                    var isRoom     = (roomTrait.RoomType >= RoomType.Start);
                    var isBossRoom = (floor.HasBossRoom && isEnd);
                    var eventId    = 0L;

                    if (!isBossRoom)
                    {
                        var areaData = new AreaData();
                        areaData.Id   = areaId++;
                        areaData.Name = "Tile" + areaData.Id;

                        areaData.X1 = x * Dungeon.TileSize;
                        areaData.Y1 = y * Dungeon.TileSize;
                        areaData.X2 = x * Dungeon.TileSize + Dungeon.TileSize;
                        areaData.Y2 = y * Dungeon.TileSize + Dungeon.TileSize;

                        this.Data.Areas.Add(areaData);

                        var type = (isRoom ? DungeonBlockType.Room : DungeonBlockType.Alley);

                        var propEntityId = MabiId.ClientProps | ((long)this.Id << 32) | ((long)areaData.Id << 16) | 1;
                        var block        = this.Dungeon.Data.Style.Get(type, room.Directions);
                        var tileCenter   = new Point(x * Dungeon.TileSize + Dungeon.TileSize / 2, y * Dungeon.TileSize + Dungeon.TileSize / 2);

                        var prop = new Prop(propEntityId, block.PropId, this.Id, tileCenter.X, tileCenter.Y, MabiMath.DegreeToRadian(block.Rotation), 1, 0, "", "", "");
                        this.AddProp(prop);

                        // Debug
                        //foreach (var points in prop.Shapes)
                        //{
                        //	foreach (var point in points)
                        //	{
                        //		var pole = new Prop(30, this.Id, point.X, point.Y, 0, 1, 0, "", "", "");
                        //		pole.Shapes.Clear();
                        //		this.AddProp(pole);
                        //	}
                        //}

                        // TODO: This region/data stuff is a mess... create
                        //   proper classes, put them in the regions and be
                        //   done with it.

                        if (isStart || isEnd)
                        {
                            var xp = tileCenter.X;
                            var yp = tileCenter.Y;

                            if (roomTrait.DoorType[Direction.Up] >= 3000)
                            {
                                yp += 400;
                            }
                            else if (roomTrait.DoorType[Direction.Right] >= 3000)
                            {
                                xp += 400;
                            }
                            else if (roomTrait.DoorType[Direction.Down] >= 3000)
                            {
                                yp -= 400;
                            }
                            else if (roomTrait.DoorType[Direction.Left] >= 3000)
                            {
                                xp -= 400;
                            }

                            var eventData = new EventData();
                            eventData.Id   = MabiId.AreaEvents | ((long)this.Id << 32) | ((long)areaData.Id << 16) | eventId++;
                            eventData.Name = (isStart ? "Indoor_RDungeon_SB" : "Indoor_RDungeon_EB");
                            eventData.X    = xp;
                            eventData.Y    = yp;

                            var shape = new ShapeData();
                            shape.DirX1 = 1;
                            shape.DirY2 = 1;
                            shape.LenX  = 100;
                            shape.LenY  = 100;
                            shape.PosX  = xp;
                            shape.PosY  = yp;
                            eventData.Shapes.Add(shape);

                            areaData.Events.Add(eventData.Id, eventData);
                            _clientEvents.Add(eventData.Id, new ClientEvent(eventData, this.Data.Name, areaData.Name));
                        }
                    }
                    else
                    {
                        // Big main room
                        var areaData = new AreaData();
                        areaData.Id   = areaId++;
                        areaData.Name = "Tile" + areaData.Id;

                        areaData.X1 = x * Dungeon.TileSize - Dungeon.TileSize;
                        areaData.Y1 = y * Dungeon.TileSize;
                        areaData.X2 = x * Dungeon.TileSize + Dungeon.TileSize * 2;
                        areaData.Y2 = y * Dungeon.TileSize + Dungeon.TileSize * 2;

                        this.Data.Areas.Add(areaData);

                        var block        = this.Dungeon.Data.Style.Get(DungeonBlockType.BossRoom);
                        var propEntityId = MabiId.ClientProps | ((long)this.Id << 32) | ((long)areaData.Id << 16) | 1;
                        var tileCenter   = new Point(x * Dungeon.TileSize + Dungeon.TileSize / 2, y * Dungeon.TileSize + Dungeon.TileSize);

                        var prop = new Prop(propEntityId, block.PropId, this.Id, tileCenter.X, tileCenter.Y, MabiMath.DegreeToRadian(block.Rotation), 1, 0, "", "", "");
                        this.AddProp(prop);

                        // Debug
                        //foreach (var points in prop.Shapes)
                        //{
                        //	foreach (var point in points)
                        //	{
                        //		var pole = new Prop(30, this.Id, point.X, point.Y, 0, 1, 0, "", "", "");
                        //		pole.Shapes.Clear();
                        //		this.AddProp(pole);
                        //	}
                        //}

                        // Treasure room
                        areaData      = new AreaData();
                        areaData.Id   = areaId++;
                        areaData.Name = "Tile" + areaData.Id;

                        areaData.X1 = x * Dungeon.TileSize;
                        areaData.Y1 = y * Dungeon.TileSize + Dungeon.TileSize * 2;
                        areaData.X2 = x * Dungeon.TileSize + Dungeon.TileSize;
                        areaData.Y2 = y * Dungeon.TileSize + Dungeon.TileSize * 2 + Dungeon.TileSize;

                        this.Data.Areas.Add(areaData);
                    }
                }
            }
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Creates sitting prop, fails silently if item or chair
        /// data doesn't exist.
        /// </summary>
        /// <param name="creature"></param>
        /// <param name="chairItemEntityId"></param>
        private void SetUpChair(Creature creature, long chairItemEntityId)
        {
            if (chairItemEntityId == 0)
            {
                return;
            }

            // Check item
            var item = creature.Inventory.GetItem(chairItemEntityId);

            if (item == null || item.Data.Type != ItemType.Misc)
            {
                return;
            }

            // Get chair data
            var chairData = AuraData.ChairDb.Find(item.Info.Id);

            if (chairData == null)
            {
                return;
            }

            var pos = creature.GetPosition();

            // Effect
            if (chairData.Effect != 0)
            {
                Send.Effect(creature, chairData.Effect, true);
            }

            // Chair prop
            var sittingProp = new Prop((!creature.IsGiant ? chairData.PropId : chairData.GiantPropId), creature.RegionId, pos.X, pos.Y, MabiMath.ByteToRadian(creature.Direction));

            sittingProp.Info.Color1 = item.Info.Color1;
            sittingProp.Info.Color2 = item.Info.Color2;
            sittingProp.Info.Color3 = item.Info.Color3;
            sittingProp.State       = chairData.State;

            if (chairData.Stand != -1)
            {
                sittingProp.Xml.SetAttributeValue("PMPG", chairData.Stand);
                sittingProp.Xml.SetAttributeValue("PMPS", true);
            }

            sittingProp.Xml.SetAttributeValue("OWNER", creature.EntityId);
            sittingProp.Xml.SetAttributeValue("PMUIID", chairData.ItemId);

            creature.Region.AddProp(sittingProp);

            // State transition
            if (chairData.NextState != null)
            {
                Task.Delay(chairData.StateChangeDelay).ContinueWith(_ =>
                {
                    sittingProp.State = chairData.NextState;
                    Send.PropUpdate(sittingProp);
                });
            }

            this.SitOnProp(creature, sittingProp, chairData);
        }
Ejemplo n.º 25
0
    void Update()
    {
        // Go through all entities
        foreach (Transform entityTransform in EntityList)
        {
            // Get entity info component, ignore empty names
            var entityInfo = entityTransform.GetComponent <EntityInfo>();
            if (string.IsNullOrEmpty(entityInfo.Name))
            {
                continue;
            }

            // Get information for placement
            var nameTarget = entityTransform.FindChild("NameTarget");
            var pos        = mainCamera.WorldToScreenPoint(nameTarget.transform.position);

            // Create new name object if new entity
            Transform nameTransform;
            if (!nameTransforms.TryGetValue(entityTransform, out nameTransform))
            {
                // Get creature
                Entity creature;
                Connection.Entities.TryGetValue(entityInfo.Id, out creature);

                // Create object in list
                var newNameObj = (GameObject)GameObject.Instantiate(reference, pos, Quaternion.identity);
                nameTransform = newNameObj.transform;
                nameTransform.SetParent(me);

                // Set colored name
                var color       = MabiMath.GetNameColor(entityInfo.Name);
                var text        = nameTransform.GetComponent <Text>();
                var name        = entityInfo.Name;
                var displayName = string.Format("<color=#{0:X6}>{1}</color>", color, name);

                // NPC prefix
                if (entityInfo.IsConversationNpc)
                {
                    displayName = "<size=8>NPC</size> " + displayName;
                }

                text.text = displayName;

                // Save for automatic removal
                nameTransforms.Add(entityTransform, nameTransform);
            }

            var nameObject = nameTransform.gameObject;

            // If entity is visible, activate name object and move it into
            // position.
            if (pos.z > 0)
            {
                nameTransform.position = pos;
                if (!nameObject.activeSelf)
                {
                    nameObject.SetActive(true);
                }
            }
            // If entity is not visible deactivate the name.
            else if (nameObject.activeSelf)
            {
                nameObject.SetActive(false);
            }
        }

        // Check for removed entities
        var toRemove = new List <Transform>();

        foreach (var nameTransformX in nameTransforms)
        {
            // Remove name if entity transform became null (destroyed)
            var entityTransform = nameTransformX.Key;
            if (entityTransform == null)
            {
                var nameTransform = nameTransformX.Value;

                GameObject.Destroy(nameTransform.gameObject);
                toRemove.Add(entityTransform);
            }
        }

        // Remove destroyed entity's names from the list
        if (toRemove.Count != 0)
        {
            foreach (var key in toRemove)
            {
                nameTransforms.Remove(key);
            }
        }
    }
Ejemplo n.º 26
0
        /// <summary>
        /// Uses LightningRod
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void Use(Creature attacker, Skill skill, Packet packet)
        {
            // Set full charge variable
            attacker.Temp.LightningRodFullCharge = (DateTime.Now >= attacker.Temp.LightningRodPrepareTime.AddMilliseconds(skill.RankData.Var3));

            // Get direction for target Area
            var direction = Mabi.MabiMath.ByteToRadian(attacker.Direction);

            var attackerPos = attacker.GetPosition();

            // Calculate polygon points
            var r     = MabiMath.ByteToRadian(attacker.Direction);
            var poe   = attackerPos.GetRelative(r, 800);
            var pivot = new Point(poe.X, poe.Y);
            var p1    = new Point(pivot.X - SkillLength / 2, pivot.Y - SkillWidth / 2);
            var p2    = new Point(pivot.X - SkillLength / 2, pivot.Y + SkillWidth / 2);
            var p3    = new Point(pivot.X + SkillLength / 2, pivot.Y + SkillWidth / 2);
            var p4    = new Point(pivot.X + SkillLength / 2, pivot.Y - SkillWidth / 2);

            p1 = this.RotatePoint(p1, pivot, r);
            p2 = this.RotatePoint(p2, pivot, r);
            p3 = this.RotatePoint(p3, pivot, r);
            p4 = this.RotatePoint(p4, pivot, r);

            // TargetProp
            var lProp = new Prop(280, attacker.RegionId, poe.X, poe.Y, MabiMath.ByteToRadian(attacker.Direction), 1f, 0f, "single");

            attacker.Region.AddProp(lProp);

            // Prepare Combat Actions
            var cap = new CombatActionPack(attacker, skill.Info.Id);

            var targetAreaId = new Location(attacker.RegionId, poe).ToLocationId();

            var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, targetAreaId);

            aAction.Set(AttackerOptions.KnockBackHit1 | AttackerOptions.UseEffect);
            aAction.PropId = lProp.EntityId;
            cap.Add(aAction);

            // Get targets in Polygon - includes collission check
            var targets = attacker.Region.GetCreaturesInPolygon(p1, p2, p3, p4).Where(x => attacker.CanTarget(x) && !attacker.Region.Collisions.Any(attacker.GetPosition(), x.GetPosition())).ToList();

            var rnd = RandomProvider.Get();

            // Check crit
            var crit      = false;
            var critSkill = attacker.Skills.Get(SkillId.CriticalHit);

            if (critSkill != null && critSkill.Info.Rank > SkillRank.Novice)
            {
                var critChance = Math2.Clamp(0, 30, attacker.GetTotalCritChance(0));
                if (rnd.NextDouble() * 100 < critChance)
                {
                    crit = true;
                }
            }

            foreach (var target in targets)
            {
                var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, SkillId.CombatMastery);
                tAction.Set(TargetOptions.None);
                tAction.AttackerSkillId = skill.Info.Id;
                cap.Add(tAction);

                var damage = attacker.GetRndMagicDamage(skill, skill.RankData.Var1, skill.RankData.Var2);

                // Add damage if the skill is fully charged
                var dmgMultiplier = skill.RankData.Var4 / 100f;
                if (attacker.Temp.LightningRodFullCharge)
                {
                    damage += (damage * dmgMultiplier);
                }

                // Critical Hit
                if (crit)
                {
                    var bonus = critSkill.RankData.Var1 / 100f;
                    damage = damage + (damage * bonus);

                    tAction.Set(TargetOptions.Critical);
                }

                // MDef and MProt
                SkillHelper.HandleMagicDefenseProtection(target, ref damage);

                // Mana Deflector
                var delayReduction = ManaDeflector.Handle(attacker, target, ref damage, tAction);

                // Mana Shield
                ManaShield.Handle(target, ref damage, tAction);

                // Apply Damage
                target.TakeDamage(tAction.Damage = damage, attacker);

                // Stun Time
                tAction.Stun = TargetStun;

                // Death or Knockback
                if (target.IsDead)
                {
                    tAction.Set(TargetOptions.FinishingKnockDown);
                    attacker.Shove(target, KnockbackDistance);
                }
                else
                {
                    // Always knock down
                    if (target.Is(RaceStands.KnockDownable))
                    {
                        tAction.Set(TargetOptions.KnockDown);
                        attacker.Shove(target, KnockbackDistance);
                    }
                }
            }
            cap.Handle();

            Send.Effect(attacker, Effect.LightningRod, (int)LightningRodEffect.Attack, poe.X, poe.Y);

            Send.SkillUse(attacker, skill.Info.Id, targetAreaId, 0, 1);
            skill.Train(1);             // Use the Skill

            attacker.Region.RemoveProp(lProp);
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Uses LightningRod
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void Use(Creature attacker, Skill skill, Packet packet)
        {
            // Set full charge variable
            attacker.Temp.LightningRodFullCharge = (DateTime.Now >= attacker.Temp.LightningRodPrepareTime.AddMilliseconds(skill.RankData.Var3));

            // Get targets in skill area
            Position targetPropPos;
            var      targets = SkillHelper.GetTargetableCreaturesInSkillArea(attacker, SkillLength, SkillWidth, out targetPropPos);

            // TargetProp
            var lProp = new Prop(280, attacker.RegionId, targetPropPos.X, targetPropPos.Y, MabiMath.ByteToRadian(attacker.Direction), 1f, 0f, "single");

            attacker.Region.AddProp(lProp);

            // Prepare Combat Actions
            var cap = new CombatActionPack(attacker, skill.Info.Id);

            var targetAreaId = new Location(attacker.RegionId, targetPropPos).ToLocationId();

            var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, targetAreaId);

            aAction.Set(AttackerOptions.KnockBackHit1 | AttackerOptions.UseEffect);
            aAction.PropId = lProp.EntityId;
            cap.Add(aAction);

            var rnd = RandomProvider.Get();

            // Check crit
            var crit      = false;
            var critSkill = attacker.Skills.Get(SkillId.CriticalHit);

            if (critSkill != null && critSkill.Info.Rank > SkillRank.Novice)
            {
                var critChance = Math2.Clamp(0, 30, attacker.GetTotalCritChance(0));
                if (rnd.NextDouble() * 100 < critChance)
                {
                    crit = true;
                }
            }

            foreach (var target in targets)
            {
                var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, SkillId.CombatMastery);
                tAction.Set(TargetOptions.None);
                tAction.AttackerSkillId = skill.Info.Id;
                cap.Add(tAction);

                var damage = attacker.GetRndMagicDamage(skill, skill.RankData.Var1, skill.RankData.Var2);

                // Add damage if the skill is fully charged
                var dmgMultiplier = skill.RankData.Var4 / 100f;
                if (attacker.Temp.LightningRodFullCharge)
                {
                    damage += (damage * dmgMultiplier);
                }

                // Critical Hit
                if (crit)
                {
                    CriticalHit.Handle(attacker, 100, ref damage, tAction);
                }

                // Handle skills and reductions
                SkillHelper.HandleMagicDefenseProtection(target, ref damage);
                SkillHelper.HandleConditions(attacker, target, ref damage);
                var delayReduction = ManaDeflector.Handle(attacker, target, ref damage, tAction);
                ManaShield.Handle(target, ref damage, tAction);

                // Apply Damage
                target.TakeDamage(tAction.Damage = damage, attacker);

                // Stun Time
                tAction.Stun = TargetStun;

                // Death or Knockback
                if (target.IsDead)
                {
                    tAction.Set(TargetOptions.FinishingKnockDown);
                    attacker.Shove(target, KnockbackDistance);
                }
                else
                {
                    // Always knock down
                    if (target.Is(RaceStands.KnockDownable))
                    {
                        tAction.Set(TargetOptions.KnockDown);
                        attacker.Shove(target, KnockbackDistance);
                    }
                }
            }

            // Update current weapon
            SkillHelper.UpdateWeapon(attacker, targets.FirstOrDefault(), ProficiencyGainType.Melee, attacker.RightHand);

            cap.Handle();

            Send.Effect(attacker, Effect.LightningRod, LightningRodEffect.Attack, targetPropPos.X, targetPropPos.Y);

            Send.SkillUse(attacker, skill.Info.Id, targetAreaId, 0, 1);
            skill.Train(1);             // Use the Skill

            attacker.Region.RemoveProp(lProp);
        }
Ejemplo n.º 28
0
    public override void OnCreation(Dungeon dungeon)
    {
        var region       = dungeon.Regions.Last();
        var bossLocation = dungeon.GetBossRoomCenter();

        // Gargoyles
        region.AddProp(new Prop(29001, bossLocation.RegionId, bossLocation.X, bossLocation.Y, 0));
        region.AddProp(new Prop(29002, bossLocation.RegionId, bossLocation.X, bossLocation.Y, 0));
        region.AddProp(new Prop(29003, bossLocation.RegionId, bossLocation.X, bossLocation.Y, MabiMath.DegreeToRadian(90)));
        region.AddProp(new Prop(29004, bossLocation.RegionId, bossLocation.X, bossLocation.Y, MabiMath.DegreeToRadian(90)));
        region.AddProp(new Prop(29005, bossLocation.RegionId, bossLocation.X, bossLocation.Y, 0));
        region.AddProp(new Prop(29006, bossLocation.RegionId, bossLocation.X, bossLocation.Y, 0));
    }
Ejemplo n.º 29
0
        /// <summary>
        /// Spawns brownie for creature's personal shop.
        /// </summary>
        /// <param name="creature"></param>
        protected void SummonBrownie(Creature creature, Item item, string typeName)
        {
            var shop = creature.Temp.ActivePersonalShop;

            if (shop == null)
            {
                Send.MsgBox(creature, Localization.Get("The Personal Shop does not exist."));
                return;
            }

            // Get type
            var type = ChannelServer.Instance.ScriptManager.GetScriptType(typeName);

            if (type == null)
            {
                Log.Error("SpawnBrownie: Type '{0}' not found.", typeName);
                Send.MsgBox(creature, Localization.Get("Unable to summon brownie."));
                return;
            }

            // Check script type
            var obj       = Activator.CreateInstance(type);
            var npcScript = obj as NpcScript;

            if (npcScript == null)
            {
                Log.Error("SpawnBrownie: Type '{0}' is not an NpcScript.", typeName);
                Send.MsgBox(creature, Localization.Get("Unable to summon brownie."));
                return;
            }

            var loc   = shop.Prop.GetLocation();
            var angle = shop.Prop.Info.Direction + Math.PI / 2;
            var x     = loc.X + 50 * Math.Cos(angle);
            var y     = loc.Y + 50 * Math.Sin(angle);

            loc.X = (int)x;
            loc.Y = (int)y;

            var direction = MabiMath.RadianToByte(shop.Prop.Info.Direction);

            npcScript.Load();
            npcScript.NPC.Name += "@" + Interlocked.Increment(ref _brownieCopyId);
            npcScript.NPC.SetLocation(loc);
            npcScript.NPC.Direction  = direction;
            npcScript.NPC.ScriptType = type;

            shop.Region.AddCreature(npcScript.NPC);

            shop.SetOverseer(npcScript.NPC, item.EntityId);

            // Set expiration if it's not set yet
            if (item.OptionInfo.ExpireTime == 0)
            {
                // For some reason the client shows "365 days" more than it should...
                // reducing them for now.
                var seconds = (int)(DateTime.Now.AddHours(24).AddDays(-365) - new DateTime(1970, 1, 1)).TotalSeconds;

                item.OptionInfo.ExpireTime = seconds;
                Send.ItemUpdate(creature, item);
            }
        }
Ejemplo n.º 30
0
    public void AddMessage(string name, string message)
    {
        var color = MabiMath.GetNameColor(name);

        AddMessage(color, name, message);
    }