/// <summary> /// Sends Age Increase Packet /// </summary> /// <param name="client"></param> /// <param name="creature"></param> /// <param name="age"></param> public static void AgeIncrease(WorldClient client, MabiPC player, ushort age) { var p = new MabiPacket(Op.AgeIncrease, player.Id); p.PutShort(age); client.Send(p); }
/// <summary> /// Fixed dye complete /// </summary> /// <param name="client"></param> /// <param name="creature"></param> /// <param name="skillId"></param> /// <param name="part"></param> public static void DyeSkillComplete(Client client, MabiCreature creature, SkillConst skillId, uint part) { var packet = new MabiPacket(Op.SkillComplete, creature.Id); packet.PutShort((ushort)skillId); packet.PutInt(part); client.Send(packet); }
/// <summary> /// Sends ItemAmount to creature's client. /// </summary> /// <param name="creature"></param> /// <param name="item"></param> public static void ItemAmount(MabiCreature creature, MabiItem item) { var packet = new MabiPacket(Op.ItemAmount, creature.Id); packet.PutLong(item.Id); packet.PutShort(item.Info.Amount); packet.PutByte(2); // ? (related to the 2 in move item?) creature.Client.Send(packet); }
/// <summary> /// Broadcasts Phoenix Feather above dead creature effect in creature's range. /// </summary> /// <param name="client"></param> /// <param name="creature"></param> public static void DeadFeather(MabiCreature creature, DeadMenuOptions options) { var bits = (uint)options; var flags = new List<uint>(); // Break down options bit by bit, and add them to flags if set. for (uint i = 1; bits != 0; ++i, bits >>= 1) { if ((bits & 1) != 0) flags.Add(i); } var packet = new MabiPacket(Op.DeadFeather, creature.Id); packet.PutShort((ushort)flags.Count); foreach (var f in flags) packet.PutInt(f); packet.PutByte(0); WorldManager.Instance.Broadcast(packet, SendTargets.Range, creature); }
public static void OpenNPCShop(WorldClient client, MabiShop shop) { var packet = new MabiPacket(Op.OpenNPCShop, client.Character.Id); packet.PutString("shopname"); packet.PutByte(0); packet.PutByte(0); packet.PutInt(0); packet.PutByte((byte)shop.Tabs.Count); for (var i = 0; i < shop.Tabs.Count; ++i) { packet.PutString("[{0}]{1}", i, shop.Tabs[i].Name); // [160200] ? { packet.PutByte(0); } packet.PutShort((ushort)shop.Tabs[i].Items.Count); foreach (var item in shop.Tabs[i].Items) packet.AddItemInfo(item, ItemPacketType.Private); } client.Send(packet); }
/// <summary> /// Broadcasts motion use. Also sends MotionCancel, if cancel is true. /// </summary> public static void UseMotion(MabiCreature creature, uint category, uint type, bool loop = false, bool cancel = false) { if (cancel) { // Cancel motion var cancelPacket = new MabiPacket(Op.MotionCancel, creature.Id); cancelPacket.PutByte(0); WorldManager.Instance.Broadcast(cancelPacket, SendTargets.Range, creature); } // Do motion var doPacket = new MabiPacket(Op.UseMotion, creature.Id); doPacket.PutInt(category); doPacket.PutInt(type); doPacket.PutByte(loop); doPacket.PutShort(0); WorldManager.Instance.Broadcast(doPacket, SendTargets.Range, creature); }
/// <summary> /// Normal skill prepare response, skillId None means fail. /// </summary> /// <param name="client"></param> /// <param name="creature"></param> /// <param name="skillId"></param> /// <param name="castTime"></param> public static void SkillPrepare(Client client, MabiCreature creature, SkillConst skillId, uint castTime) { var packet = new MabiPacket(Op.SkillPrepare, creature.Id); packet.PutShort((ushort)skillId); if (skillId != SkillConst.None) packet.PutInt(castTime); client.Send(packet); }
public static void SkillStackSet(Client client, MabiCreature creature, SkillConst skillId, byte stack) { var packet = new MabiPacket(Op.SkillStackSet, creature.Id); packet.PutBytes(creature.ActiveSkillStacks, 1); packet.PutShort((ushort)creature.ActiveSkillId); client.Send(packet); }
/// <summary> /// Broadcasts RankUp animation in range of creature. /// Only includes skillId if it is > 0. /// </summary> /// <param name="creature"></param> /// <param name="skillId"></param> public static void RankUp(MabiCreature creature, ushort skillId = 0) { var packet = new MabiPacket(Op.RankUp, creature.Id); if (skillId > 0) packet.PutShort(skillId); packet.PutShort(1); WorldManager.Instance.Broadcast(packet, SendTargets.Range, creature); }
public static void CutsceneStart(WorldClient client, MabiCutscene cutscene) { var p = new MabiPacket(Op.CutsceneStart, Id.World); p.PutLongs(client.Character.Id, cutscene.Leader.Id); p.PutString(cutscene.Name); p.PutSInt(cutscene.Actors.Count); foreach (var a in cutscene.Actors) { p.PutString(a.Item1); p.PutShort((ushort)a.Item2.Length); p.PutBin(a.Item2); } p.PutInt(1); p.PutLong(client.Character.Id); client.Send(p); }
public override SkillResults Prepare(MabiCreature creature, MabiSkill skill, MabiPacket packet, uint castTime) { var rnd = RandomProvider.Get(); // Check for instrument if (creature.RightHand == null || creature.RightHand.Type != ItemType.Instrument) return SkillResults.Failure; // Spawn chair for Cello if (creature.RightHand.DataInfo.Instrument == InstrumentType.Cello) { var pos = creature.GetPosition(); // Chair prop var prop = new MabiProp((!creature.IsGiant ? CelloChair : GiantCelloChair), creature.Region, pos.X, pos.Y, MabiMath.DirToRad(creature.Direction)); prop.State = "stand"; WorldManager.Instance.AddProp(prop); // Move char Send.AssignChair(creature, prop.Id, 1); // Update chair prop.ExtraData = string.Format("<xml OWNER='{0}' SITCHAR='{0}'/>", creature.Id); Send.PropUpdate(prop); creature.Temp.SittingProp = prop; } // Score scrolls go into the magazine pocket and need a SCORE tag. // XXX: Is it possbile to play random with a low durability scroll? bool hasScroll = (creature.Magazine != null && creature.Magazine.Tags.Has("SCORE") && creature.Magazine.OptionInfo.Durability >= DurabilityUse); // Random score if no usable scroll was found. uint rndScore = (!hasScroll ? (uint)rnd.Next(RandomScoreMin, RandomScoreMax + 1) : 0); // Quality seems to go from 0 (worst) to 3 (best). // Should be generated based on skills + random. var quality = (PlayingQuality)rnd.Next((int)PlayingQuality.VeryBad, (int)PlayingQuality.VeryGood + 1); // Up quality by chance, based on Musical Knowledge var knowledge = creature.Skills.Get(SkillConst.MusicalKnowledge); if (knowledge != null && rnd.Next(0, 100) < knowledge.RankInfo.Var2) quality++; if (quality > PlayingQuality.VeryGood) quality = PlayingQuality.VeryGood; // Save quality before checking perfect play option, // we want proper skill training. creature.Temp.PlayingInstrumentQuality = quality; if (WorldConf.PerfectPlay) { quality = PlayingQuality.VeryGood; Send.ServerMessage(creature.Client, creature, Localization.Get("skills.perfect_play")); // Regardless of the result, perfect play will let your performance sound perfect. } // Reduce scroll's durability. if (hasScroll) { creature.Magazine.ReduceDurability(DurabilityUse); creature.Client.Send( new MabiPacket(Op.ItemDurabilityUpdate, creature.Id) .PutLong(creature.Magazine.Id) .PutInt(creature.Magazine.OptionInfo.Durability) ); } // Music effect { var effect = hasScroll ? PacketCreator.PlayEffect(creature, creature.RightHand.DataInfo.Instrument, quality, creature.Magazine.Tags["SCORE"]) : PacketCreator.PlayEffect(creature, creature.RightHand.DataInfo.Instrument, quality, rndScore); WorldManager.Instance.Broadcast(effect, SendTargets.Range, creature); } // Use skill { var use = new MabiPacket(Op.SkillUse, creature.Id); use.PutShort(skill.Info.Id); use.PutLong(0); use.PutByte(hasScroll); if (!hasScroll) use.PutInt(rndScore); else use.PutString(creature.Magazine.Tags["SCORE"]); use.PutByte((byte)creature.RightHand.DataInfo.Instrument); use.PutByte(1); use.PutByte(0); creature.Client.Send(use); creature.ActiveSkillId = skill.Id; } // Change motion for Battle Mandolin (no idea if this official, but I like it =P) [exec] //if (creature.RightHand.Info.Class == 40367) // WorldManager.Instance.CreatureUseMotion(creature, 88, 2, true); return SkillResults.Okay; }
/// <summary> /// Fixed dye use complete. /// </summary> /// <param name="client"></param> /// <param name="creature"></param> /// <param name="skillId"></param> /// <param name="part"></param> /// <param name="unk"></param> public static void SkillUseDye(Client client, MabiCreature creature, SkillConst skillId, uint part, byte unk) { var packet = new MabiPacket(Op.SkillUse, creature.Id); packet.PutShort((ushort)skillId); packet.PutInt(part); packet.PutByte(unk); client.Send(packet); }
/// <summary> /// Skill use with a delay? /// </summary> /// <param name="client"></param> /// <param name="creature"></param> /// <param name="skillId"></param> /// <param name="ms"></param> /// <param name="unk"></param> public static void SkillUse(Client client, MabiCreature creature, SkillConst skillId, uint ms, uint unk) { var packet = new MabiPacket(Op.SkillUse, creature.Id); packet.PutShort((ushort)skillId); packet.PutInts(ms, unk); client.Send(packet); }
public static void SkillUse(Client client, MabiCreature creature, SkillConst skillId, ulong targetId, uint unk1, uint unk2) { var packet = new MabiPacket(Op.SkillUse, creature.Id); packet.PutShort((ushort)skillId); if (skillId != SkillConst.None) { packet.PutLong(targetId); packet.PutInt(unk1); packet.PutInt(unk2); } client.Send(packet); }
public static void SkillUse(Client client, MabiCreature creature, SkillConst skillId, ulong targetId) { var packet = new MabiPacket(Op.SkillUse, creature.Id); packet.PutShort((ushort)skillId); packet.PutLong(targetId); client.Send(packet); }
/// <summary> /// Sends SkillStop to creature's client. /// </summary> /// <param name="creature"></param> /// <param name="skillId"></param> /// <param name="parameter"></param> public static void SkillStop(MabiCreature creature, SkillConst skillId, string parameter) { var packet = new MabiPacket(Op.SkillStop, creature.Id); packet.PutShort((ushort)skillId); packet.PutString(parameter); creature.Client.Send(packet); }
/// <summary> /// Updates the stack amount (how many uses left). /// </summary> /// <param name="creature"></param> /// <param name="skillId"></param> /// <param name="remaining"></param> /// <param name="max"></param> public static void SkillStackUpdate(Client client, MabiCreature creature, SkillConst skillId, byte remaining) { var packet = new MabiPacket(Op.SkillStackUpdate, creature.Id); packet.PutBytes(remaining, 1, 0); packet.PutShort((ushort)skillId); client.Send(packet); }
public static void EntitiesAppear(Client client, IEnumerable<MabiEntity> entities) { var packet = new MabiPacket(Op.EntitiesAppear, Id.Broadcast); packet.PutShort((ushort)entities.Count()); foreach (var entity in entities) { var data = new MabiPacket(0, 0); data.AddPublicEntityInfo(entity); var dataBytes = data.Build(false); packet.PutShort(entity.DataType); packet.PutInt((uint)dataBytes.Length); packet.PutBin(dataBytes); } client.Send(packet); }
/// <summary> /// Default skill ready packet, with or without string parameters. /// </summary> /// <param name="client"></param> /// <param name="creature"></param> /// <param name="skillId"></param> /// <param name="parameters"></param> public static void SkillReady(Client client, MabiCreature creature, SkillConst skillId, string parameters = "") { var packet = new MabiPacket(Op.SkillReady, creature.Id); packet.PutShort((ushort)skillId); if (!string.IsNullOrWhiteSpace(parameters) && parameters.Length > 0) packet.PutString(parameters); client.Send(packet); }
/// <summary> /// Returns a packet with the base information for every action /// </summary> /// <param name="actionId"></param> /// <returns></returns> public virtual MabiPacket GetPacket(uint actionId) { var result = new MabiPacket(Op.CombatAction, this.Creature.Id); result.PutInt(actionId); result.PutLong(this.Creature.Id); result.PutByte((byte)this.Type); result.PutShort(this.StunTime); result.PutShort((ushort)this.SkillId); result.PutShort(0); return result; }
public static MabiPacket ItemAmount(MabiCreature creature, MabiItem item) { var p = new MabiPacket(Op.ItemAmount, creature.Id); p.PutLong(item.Id); p.PutShort(item.Info.Amount); p.PutByte(2); return p; }
private MabiPacket GetPacket(MabiCreature creature, MabiSkill skill, bool transforming) { // TODO: Add actual transform level from rank info. // intVal1 = look, intVal2 = titleId var p = new MabiPacket(0xA41C, creature.Id); p.PutByte((byte)(transforming ? this.TransformId : (byte)0)); p.PutShort((ushort)(transforming ? 15 : 0)); p.PutShort((ushort)(transforming ? ((skill.Info.Rank + 1) / 4) : 0)); p.PutByte(1); return p; }
public static void NewKeyword(WorldClient client, ushort keywordId) { var pp = new MabiPacket(Op.NewKeyword, client.Character.Id); pp.PutShort(keywordId); client.Send(pp); }
/// <summary> /// Playing instrument effect (sound and motion) for creature, /// based on the given score id (client:score.xml). /// </summary> /// <param name="creature"></param> /// <param name="instrument"></param> /// <param name="quality"></param> /// <param name="score"></param> /// <returns></returns> public static MabiPacket PlayEffect(MabiCreature creature, InstrumentType instrument, PlayingQuality quality, uint score) { var p = new MabiPacket(Op.Effect, creature.Id); p.PutInt(Effect.PlayMusic); p.PutByte(false); p.PutInt(score); p.PutInt(0); p.PutShort(0); p.PutInt(14113); p.PutByte((byte)quality); p.PutByte((byte)instrument); p.PutByte(0); p.PutByte(0); p.PutByte(1); return p; }
/// <summary> /// Sends list of disappearing entites to client. /// </summary> /// <param name="client"></param> /// <param name="entities"></param> public static void EntitiesDisappear(Client client, IEnumerable<MabiEntity> entities) { var packet = new MabiPacket(Op.EntitiesDisappear, Id.Broadcast); packet.PutShort((ushort)entities.Count()); foreach (var entity in entities) { packet.PutShort(entity.DataType); packet.PutLong(entity.Id); } client.Send(packet); }
/// <summary> /// Skill ready packet with 2 ulong parameters for ids (e.g. dyeing). /// </summary> /// <param name="client"></param> /// <param name="creature"></param> /// <param name="skillId"></param> /// <param name="id1"></param> /// <param name="id2"></param> public static void SkillReady(Client client, MabiCreature creature, SkillConst skillId, ulong id1, ulong id2) { var packet = new MabiPacket(Op.SkillReady, creature.Id); packet.PutShort((ushort)skillId); packet.PutLongs(id1, id2); client.Send(packet); }
/// <summary> /// Playing instrument effect (sound and motion) for creature, /// based on the given MML code. /// </summary> /// <param name="creature"></param> /// <param name="instrument"></param> /// <param name="quality"></param> /// <param name="compressedMML"></param> /// <returns></returns> public static MabiPacket PlayEffect(MabiCreature creature, InstrumentType instrument, PlayingQuality quality, string compressedMML) { var p = new MabiPacket(Op.Effect, creature.Id); p.PutInt(Effect.PlayMusic); p.PutByte(true); // has scroll p.PutString(compressedMML); p.PutInt(0); p.PutShort(0); p.PutInt(14113); // ? p.PutByte((byte)quality); p.PutByte((byte)instrument); p.PutByte(0); p.PutByte(0); p.PutByte(1); // loops return p; }
/// <summary> /// Broadcasts update packet for Title and OptionTitle. /// </summary> /// <param name="creature"></param> public static void TitleUpdate(MabiCreature creature) { var packet = new MabiPacket(Op.TitleUpdate, creature.Id); packet.PutShort(creature.Title); packet.PutShort(creature.OptionTitle); WorldManager.Instance.Broadcast(packet, SendTargets.Range, creature); }
public static MabiPacket StatUpdate(MabiCreature creature, StatUpdateType type, params Stat[] stats) { var packet = new MabiPacket((type & StatUpdateType.Public) != 0 ? Op.StatUpdatePublic : Op.StatUpdatePrivate, creature.Id); packet.PutByte((byte)type); // Stats packet.PutSInt(stats.Length); foreach (var stat in stats) { packet.PutInt((uint)stat); switch (stat) { case Stat.Height: packet.PutFloat(creature.Height); break; case Stat.Weight: packet.PutFloat(creature.Weight); break; case Stat.Upper: packet.PutFloat(creature.Upper); break; case Stat.Lower: packet.PutFloat(creature.Lower); break; case Stat.CombatPower: packet.PutFloat(creature.CombatPower); break; case Stat.Level: packet.PutShort(creature.Level); break; case Stat.AbilityPoints: packet.PutShort(creature.AbilityPoints); break; case Stat.Experience: packet.PutLong(MabiData.ExpDb.CalculateRemaining(creature.Level, creature.Experience) * 1000); break; case Stat.Life: packet.PutFloat(creature.Life); break; case Stat.LifeMax: packet.PutFloat(creature.LifeMaxBaseTotal); break; case Stat.LifeMaxMod: packet.PutFloat(creature.StatMods.GetMod(Stat.LifeMaxMod)); break; case Stat.LifeInjured: packet.PutFloat(creature.LifeInjured); break; case Stat.Mana: packet.PutFloat(creature.Mana); break; case Stat.ManaMax: packet.PutFloat(creature.ManaMaxBaseTotal); break; case Stat.ManaMaxMod: packet.PutFloat(creature.StatMods.GetMod(Stat.ManaMaxMod)); break; case Stat.Stamina: packet.PutFloat(creature.Stamina); break; case Stat.Food: packet.PutFloat(creature.StaminaHunger); break; case Stat.StaminaMax: packet.PutFloat(creature.StaminaMaxBaseTotal); break; case Stat.StaminaMaxMod: packet.PutFloat(creature.StatMods.GetMod(Stat.StaminaMaxMod)); break; case Stat.StrMod: packet.PutFloat(creature.StatMods.GetMod(Stat.StrMod)); break; case Stat.DexMod: packet.PutFloat(creature.StatMods.GetMod(Stat.DexMod)); break; case Stat.IntMod: packet.PutFloat(creature.StatMods.GetMod(Stat.IntMod)); break; case Stat.LuckMod: packet.PutFloat(creature.StatMods.GetMod(Stat.LuckMod)); break; case Stat.WillMod: packet.PutFloat(creature.StatMods.GetMod(Stat.WillMod)); break; case Stat.Str: packet.PutFloat(creature.StrBaseTotal); break; case Stat.Int: packet.PutFloat(creature.IntBaseTotal); break; case Stat.Dex: packet.PutFloat(creature.DexBaseTotal); break; case Stat.Will: packet.PutFloat(creature.WillBaseTotal); break; case Stat.Luck: packet.PutFloat(creature.LuckBaseTotal); break; case Stat.DefenseBaseMod: packet.PutShort((ushort)creature.DefensePassive); break; case Stat.ProtectBaseMod: packet.PutFloat(creature.ProtectionPassive * 100); break; case Stat.DefenseMod: packet.PutShort((ushort)creature.StatMods.GetMod(Stat.DefenseMod)); break; case Stat.ProtectMod: packet.PutFloat(creature.StatMods.GetMod(Stat.ProtectMod)); break; // Client might crash with a mismatching value, // take a chance and put an int by default. default: packet.PutInt(1); break; } } // (New?) Stat regens packet.PutSInt(creature.StatRegens.Count); foreach (var mod in creature.StatRegens) mod.AddToPacket(packet); // Stat mod ids to remove? packet.PutInt(0); packet.PutInt(0); // ? if (type == StatUpdateType.Public) { packet.PutInt(0); // ? // Stat mod ids to remove? packet.PutInt(0); packet.PutInt(0); // ? } return packet; }
/// <summary> /// Skill complete with an additional id parameter, and 2 unknown ints. /// </summary> /// <param name="client"></param> /// <param name="creature"></param> /// <param name="skillId"></param> /// <param name="id"></param> /// <param name="unk1"></param> /// <param name="unk2"></param> public static void SkillComplete(Client client, MabiCreature creature, SkillConst skillId, ulong id, uint unk1, uint unk2) { var packet = new MabiPacket(Op.SkillComplete, creature.Id); packet.PutShort((ushort)skillId); packet.PutLong(id); packet.PutInts(unk1, unk2); client.Send(packet); }