예제 #1
0
        public override async Task Execute(IFieldObjUser user, string[] args)
        {
            await user.Message("Available command aliases:");

            await Task.WhenAll(_processor.Commands
                               .Where(c => c.Aliases.Count > 0)
                               .Select(c => user.Message($"{c.Name} - {string.Join(", ", c.Aliases)}")));
        }
예제 #2
0
        public override async Task Execute(IFieldObjUser user, string[] args)
        {
            var def = new CommandLineArgumentsDefinition(typeof(TArgs))
            {
                ExeName = Name
            };

            try
            {
                var parsed = Args.Parse <TArgs>(args);

                await Execute(user, parsed);
            }
            catch (ArgException e)
            {
                await user.Message(e.Message);

                await user.Message($"Usage: {def.UsageSummary}");
            }
        }
예제 #3
0
        public override async Task Execute(IFieldObjUser user, NPCShopCommandArgs args)
        {
            var template = await _templates.Retrieve(args.TemplateID);

            if (template == null)
            {
                await user.Message($"The specified NPC Shop: {args.TemplateID}, does not exist.");

                return;
            }

            var shop = new ShopDialog(template.ID, template);

            await user.Dialog(shop);
        }
예제 #4
0
        protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet)
        {
            var npc = user.Field.GetPool(FieldObjType.NPC).GetObject <IFieldObjNPC>(packet.ReadInt());

            if (npc == null)
            {
                return;
            }
            if (!user.Watching.Any(w => w == npc.FieldSplit))
            {
                return;
            }

            var scriptName = npc.Info.Script;

            if (string.IsNullOrWhiteSpace(scriptName))
            {
                return;
            }

            try
            {
                var script = await stageUser.Stage.ScriptEngine.CreateFromFile(scriptName);

                var context      = new ConversationContext(user);
                var conversation = new ScriptedConversation(
                    context,
                    new BasicSpeaker(context, templateID: npc.Info.ID),
                    new BasicSpeaker(context, flags: ConversationSpeakerFlags.NPCReplacedByUser),
                    script
                    );

                await user.Converse(conversation);
            }
            catch (FileNotFoundException)
            {
                await user.Message($"The '{scriptName}' script does not exist.");
            }
        }
예제 #5
0
        public override async Task Execute(IFieldObjUser user, StatCommandArgs args)
        {
            switch (args.Type)
            {
            case ModifyStatType.Skin:
            case ModifyStatType.Face:
            case ModifyStatType.Hair:
                await user.Prompt(target =>
                                  target.AskAvatar("Is this style okay?", new[] { args.Value })
                                  );

                break;

            case ModifyStatType.SP:
                if (GameConstants.IsExtendSPJob(user.Character.Job))
                {
                    var jobLevel = await user.Prompt(s => s.AskNumber("Which job level would you like to set?", min: 0, max: 10));

                    await user.ModifyStats(s => s.SetExtendSP((byte)jobLevel, (byte)args.Value));

                    await user.Message($"Successfully set extend SP (job level: {jobLevel}) to {args.Value}");

                    return;
                }
                break;
            }
            // TODO: pet

            await user.ModifyStats(s =>
            {
                switch (args.Type)
                {
                case ModifyStatType.Skin:
                    s.Skin = (byte)args.Value;
                    break;

                case ModifyStatType.Face:
                    s.Face = args.Value;
                    break;

                case ModifyStatType.Hair:
                    s.Hair = args.Value;
                    break;

                case ModifyStatType.Pet:
                case ModifyStatType.Pet2:
                case ModifyStatType.Pet3:
                    break;

                case ModifyStatType.Level:
                    s.Level = (byte)args.Value;
                    break;

                case ModifyStatType.Job:
                    s.Job = (short)args.Value;
                    break;

                case ModifyStatType.STR:
                    s.STR = (short)args.Value;
                    break;

                case ModifyStatType.DEX:
                    s.DEX = (short)args.Value;
                    break;

                case ModifyStatType.INT:
                    s.INT = (short)args.Value;
                    break;

                case ModifyStatType.LUK:
                    s.LUK = (short)args.Value;
                    break;

                case ModifyStatType.HP:
                    s.HP = args.Value;
                    break;

                case ModifyStatType.MaxHP:
                    s.MaxHP = args.Value;
                    break;

                case ModifyStatType.MP:
                    s.MP = args.Value;
                    break;

                case ModifyStatType.MaxMP:
                    s.MaxMP = args.Value;
                    break;

                case ModifyStatType.AP:
                    s.AP = (short)args.Value;
                    break;

                case ModifyStatType.SP:
                    s.SP = (short)args.Value;
                    break;

                case ModifyStatType.EXP:
                    s.EXP = args.Value;
                    break;

                case ModifyStatType.POP:
                    s.POP = (short)args.Value;
                    break;

                case ModifyStatType.Money:
                    s.Money = args.Value;
                    break;

                case ModifyStatType.TempEXP:
                    s.TempEXP = args.Value;
                    break;
                }
            });

            await user.Message($"Successfully set {args.Type} to {args.Value}");
        }
예제 #6
0
        public override async Task Execute(IFieldObjUser user, string[] args)
        {
            await user.Message("Available commands:");

            await Task.WhenAll(_processor.Commands.Select(c => user.Message($"{c.Name} - {c.Description}")));
        }
예제 #7
0
        protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet)
        {
            var clientAttackInfo = packet.Read(new ClientAttackInfo());

            var skill       = (Skill)clientAttackInfo.SkillID;
            var skillLevel  = clientAttackInfo.SkillID > 0 ? user.Character.GetSkillLevel(clientAttackInfo.SkillID) : 0;
            var damageType  = Type == AttackType.Magic ? DamageType.Magic : DamageType.Physical;
            var damageApply = new List <Tuple <IFieldObjMob, int> >();

            if (Type == AttackType.Melee)
            {
                // TODO bmage blows
            }

            if (Type == AttackType.Body)
            {
                // TODO teleport mastery
            }

            var operation = (PacketSendOperations)((int)PacketSendOperations.UserMeleeAttack + (int)Type);
            var response  = new UnstructuredOutgoingPacket(operation);

            response.WriteInt(user.ID);
            response.WriteByte((byte)(clientAttackInfo.DamagePerMob | 16 * clientAttackInfo.MobCount));
            response.WriteByte(user.Character.Level);

            response.WriteByte((byte)skillLevel);
            if (skillLevel > 0)
            {
                response.WriteInt(clientAttackInfo.SkillID);
            }

            response.WriteByte((byte)(
                                   1 * Convert.ToByte(clientAttackInfo.IsFinalAfterSlashBlast) |
                                   8 * Convert.ToByte(clientAttackInfo.IsShadowPartner) |
                                   16 * 0 |
                                   32 * Convert.ToByte(clientAttackInfo.IsSerialAttack)
                                   ));
            response.WriteShort((short)(
                                    clientAttackInfo.Action & 0x7FFF |
                                    Convert.ToByte(clientAttackInfo.IsFacingLeft) << 15)
                                );

            if (clientAttackInfo.Action <= 0x110)
            {
                response.WriteByte(0); // nMastery
                response.WriteByte(0); // v82
                response.WriteInt(0);  // bMovingShoot

                clientAttackInfo.Mobs.ForEach(m =>
                {
                    var critical    = new bool[clientAttackInfo.DamagePerMob];
                    var damage      = new int[clientAttackInfo.DamagePerMob];
                    var totalDamage = m.Damage.Sum();
                    var mob         = user.Field.GetObject <IFieldObjMob>(m.MobID);

                    response.WriteInt(m.MobID);
                    response.WriteByte(m.HitAction);

                    if (mob != null)
                    {
                        var equipInventory   = user.Character.Inventories[ItemInventoryType.Equip];
                        var serverAttackInfo = new AttackInfo(user, mob)
                        {
                            WeaponID = equipInventory.Items.ContainsKey((short)BodyPart.Weapon)
                                ? equipInventory.Items[(short)BodyPart.Weapon].TemplateID
                                : 0,
                            BulletID   = 0,
                            SkillID    = clientAttackInfo.SkillID,
                            SkillLevel = skillLevel
                        };

                        var calculatedDamage = damageType == DamageType.Physical
                            ? user.Damage.CalculateCharacterPDamage(serverAttackInfo)
                            : user.Damage.CalculateCharacterMDamage(serverAttackInfo);
                        var calculatedTotalDamage = calculatedDamage.Select(d => d.Damage).Sum();

                        // TODO cheatdetector?
                        if (clientAttackInfo.DamagePerMob != calculatedDamage.Length)
                        {
                            user.Message($"Attack count mismatch: {clientAttackInfo.DamagePerMob} : {calculatedDamage.Length}");
                            return;
                        }
                        if (totalDamage != calculatedTotalDamage)
                        {
                            user.Message($"Client damage: {string.Join(" + ", m.Damage.Select(m => $"{m}"))} = {totalDamage}");
                            user.Message($"Server damage: {string.Join(" + ", calculatedDamage.Select(m => $"{m.Damage}"))} = {calculatedTotalDamage}");
                        }

                        damageApply.Add(Tuple.Create(mob, calculatedTotalDamage));

                        for (var i = 0; i < clientAttackInfo.DamagePerMob; i++)
                        {
                            critical[i] = calculatedDamage[i].IsCritical;
                            damage[i]   = calculatedDamage[i].Damage;
                        }
                    }
                    else
                    {
                        user.Damage.SkipCalculationForCharacterDamage();
                    }

                    for (var i = 0; i < clientAttackInfo.DamagePerMob; i++)
                    {
                        response.WriteBool(critical[i]);
                        response.WriteInt(damage[i]);
                    }
                });
            }

            // TODO Keydown

            await user.FieldSplit.Dispatch(user, response);

            await Task.WhenAll(damageApply.Select(async a =>
            {
                var(mob, damage) = a;

                mob.Controller = user;
                await mob.Damage(user, damage);
            }));
        }