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)}"))); }
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}"); } }
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); }
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."); } }
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}"); }
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}"))); }
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); })); }