public void ModifyHP(short value, bool sendPacket = true) { var startValue = PrimaryStats.HP; if ((PrimaryStats.HP + value) < 0) { PrimaryStats.HP = 0; } else if ((PrimaryStats.HP + value) > PrimaryStats.GetMaxHP(false)) { PrimaryStats.HP = PrimaryStats.GetMaxHP(false); } else { PrimaryStats.HP = (short)(PrimaryStats.HP + value); } if (sendPacket) { CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Hp, PrimaryStats.HP); } if (startValue == PrimaryStats.HP) { // Doesn't matter return; } ModifiedHP(); }
public void ModifyMP(short value, bool sendPacket = true) { if ((PrimaryStats.MP + value) < 0) { PrimaryStats.MP = 0; } else if ((PrimaryStats.MP + value) > PrimaryStats.GetMaxMP(false)) { PrimaryStats.MP = PrimaryStats.GetMaxMP(false); } else { PrimaryStats.MP = (short)(PrimaryStats.MP + value); } if (sendPacket) { CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Mp, PrimaryStats.MP); /*if (this.PartyID != -1) * { * MapPacket.UpdatePartyMemberMP(this); * MapPacket.ReceivePartyMemberMP(this); * }*/ } }
public int AddMesos(int value, bool isSelf = false) { var newMesos = 0; if (value < 0) { if ((Inventory.Mesos - value) < 0) { newMesos = 0; } else { newMesos = Inventory.Mesos + value; // neg - neg = pos } } else { if (((long)Inventory.Mesos + value) > Int32.MaxValue) { newMesos = Int32.MaxValue; } else { newMesos = Inventory.Mesos + value; } } var mesosDiff = newMesos - Inventory.Mesos; Inventory.Mesos = newMesos; CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Mesos, Inventory.Mesos, isSelf); return(mesosDiff); }
public void SetFame(short value) { _characterLog.Info(new StatChangeLogRecord { value = value, type = "fame", add = false }); PrimaryStats.Fame = value; CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Fame, value); }
public void ModifyMaxHP(short value) { _characterLog.Info(new StatChangeLogRecord { value = value, type = "maxhp", add = true }); PrimaryStats.MaxHP = (short)(((PrimaryStats.MaxHP + value) > Constants.MaxMaxHp) ? Constants.MaxMaxHp : (PrimaryStats.MaxHP + value)); CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.MaxHp, PrimaryStats.MaxHP); }
public void SetSP(short value) { _characterLog.Info(new StatChangeLogRecord { value = value, type = "sp", add = false }); PrimaryStats.SP = value; CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Sp, PrimaryStats.SP); }
public void SetMesos(int value, bool isSelf = false) { if (value < 0) { value = 0; } Inventory.Mesos = value; CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Mesos, Inventory.Mesos, isSelf); }
public void SetHair(int id) { _characterLog.Info(new StatChangeLogRecord { value = id, type = "hair", add = false }); Hair = id; CharacterStatsPacket.SendStatChange(this, (int)CharacterStatsPacket.StatFlags.Hair, id); MapPacket.SendAvatarModified(this, MapPacket.AvatarModFlag.Equips);//Because hair is a equip I guess }
public void SetFace(int id) { _characterLog.Info(new StatChangeLogRecord { value = id, type = "face", add = false }); Face = id; CharacterStatsPacket.SendStatChange(this, (int)CharacterStatsPacket.StatFlags.Eyes, id); MapPacket.SendAvatarModified(this, MapPacket.AvatarModFlag.Face); }
public void SetSkin(byte id) { _characterLog.Info(new StatChangeLogRecord { value = id, type = "skin", add = false }); Skin = id; CharacterStatsPacket.SendStatChange(this, (byte)CharacterStatsPacket.StatFlags.Skin, id); MapPacket.SendAvatarModified(this, MapPacket.AvatarModFlag.Skin); }
public void SetLuk(short value) { _characterLog.Info(new StatChangeLogRecord { value = value, type = "luk", add = false }); PrimaryStats.Luk = value; CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Luk, PrimaryStats.Luk); this.FlushDamageLog(); }
public void SetJob(short value) { _characterLog.Info(new StatChangeLogRecord { value = value, type = "job", add = false }); PrimaryStats.Job = value; CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Job, value); this.FlushDamageLog(); Server.Instance.CenterConnection.UpdatePlayerJobLevel(this); }
public void SetLevel(byte value) { _characterLog.Info(new StatChangeLogRecord { value = value, type = "level", add = false }); PrimaryStats.Level = value; CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Level, value); MapPacket.SendPlayerLevelupAnim(this); this.FlushDamageLog(); Server.Instance.CenterConnection.UpdatePlayerJobLevel(this); }
public void AddSP(short value) { _characterLog.Info(new StatChangeLogRecord { value = value, type = "sp", add = true }); if (value + PrimaryStats.SP > Int16.MaxValue) { PrimaryStats.SP = Int16.MaxValue; } else { PrimaryStats.SP += value; } CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Sp, PrimaryStats.SP); }
public void SetHPAndMaxHP(short value, bool sendPacket = true) { if (value <= 0) { value = 1; } SetMaxHP(value); PrimaryStats.HP = value; if (sendPacket == true) { CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Hp, value); } }
public void AddAP(short value, bool isSelf = false) { _characterLog.Info(new StatChangeLogRecord { value = value, type = "ap", add = true }); if (value + PrimaryStats.AP > Int16.MaxValue) { PrimaryStats.AP = Int16.MaxValue; } else { PrimaryStats.AP += value; } CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Ap, PrimaryStats.AP, isSelf); }
public void SetMPAndMaxMP(short value, bool isBySelf = false, bool sendPacket = true) { if (value < 0) { value = 0; } SetMaxMP(value); PrimaryStats.MP = value; if (sendPacket == true) { CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Mp, value, isBySelf); } }
public void SetMaxMP(short value) { _characterLog.Info(new StatChangeLogRecord { value = value, type = "maxmp", add = false }); if (value > Constants.MaxMaxMp) { value = Constants.MaxMaxMp; } else if (value < Constants.MinMaxMp) { value = Constants.MinMaxMp; } PrimaryStats.MaxMP = value; CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.MaxMp, value); }
public void AddLuk(short value) { _characterLog.Info(new StatChangeLogRecord { value = value, type = "luk", add = true }); if (value + PrimaryStats.Luk > Int16.MaxValue) { PrimaryStats.Luk = Int16.MaxValue; } else { PrimaryStats.Luk += value; } CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Luk, PrimaryStats.Luk); this.FlushDamageLog(); }
public static void HandlePickupDrop(Character chr, Packet packet) { // 5F 18 FF 12 01 00 00 00 00 packet.Skip(4); // pos? int dropid = packet.ReadInt(); if (chr.AssertForHack(chr.Room != null, "Trying to loot a drop while in a 'room'") || !chr.Field.DropPool.Drops.TryGetValue(dropid, out Drop drop) || !drop.CanTakeDrop(chr)) { InventoryPacket.NoChange(chr); return; } var dropLootRange = drop.Pt2 - chr.Position; chr.AssertForHack(dropLootRange > 200, "Possible drop VAC! Distance: " + dropLootRange, dropLootRange > 250); bool SentDropNotice = false; Reward reward = drop.Reward; int dropNoticeItemIdOrMesos = reward.Drop; short pickupAmount = reward.Amount; if (reward.Mesos) { // Party meso distribution if (drop.SourceID != 0 && chr.PartyID != 0 && drop.OwnPartyID == chr.PartyID) { var PartyData = chr.Field.GetInParty(chr.PartyID); var Count = PartyData.Count(); if (Count > 1) { SentDropNotice = true; var Base = drop.Reward.Drop * 0.8 / Count + 0.5; Base = Math.Floor(Base); if (Base <= 0.0) { Base = 0.0; } var Bonus = Convert.ToInt32(drop.Reward.Drop - Count * Base); if (Bonus < 0) { Bonus = 0; } drop.Reward.Drop = Convert.ToInt32(Base); foreach (var BonusUser in PartyData) { int mesosGiven = reward.Drop; if (chr.ID == BonusUser.ID) { mesosGiven += Bonus; } // Now figure out what we really gave the user mesosGiven = BonusUser.AddMesos(mesosGiven, true); Common.Tracking.MesosTransfer.PlayerLootMesos(drop.SourceID, chr.ID, mesosGiven, "Party " + chr.PartyID + ", " + chr.MapID + ", " + drop.GetHashCode()); CharacterStatsPacket.SendGainDrop(BonusUser, true, mesosGiven, 0); } } } if (!SentDropNotice) { dropNoticeItemIdOrMesos = chr.AddMesos(reward.Drop, true); Common.Tracking.MesosTransfer.PlayerLootMesos( drop.SourceID, chr.ID, dropNoticeItemIdOrMesos, chr.MapID + ", " + drop.GetHashCode() ); } } else if (Constants.isStar(reward.ItemID)) { if (!chr.Inventory.HasSlotsFreeForItem(reward.ItemID, reward.Amount, Constants.isStackable(reward.ItemID))) { CannotLoot(chr, -1); InventoryPacket.NoChange(chr); return; } var rewardItem = drop.Reward.GetData(); chr.Inventory.AddItem2(rewardItem); ItemTransfer.ItemPickedUp(chr.ID, chr.MapID, reward.ItemID, reward.Amount, chr.MapID + ", " + drop.GetHashCode(), rewardItem); } else if (chr.Inventory.AddItem2(drop.Reward.GetData()) == drop.Reward.Amount) { CannotLoot(chr, -1); InventoryPacket.NoChange(chr); // ._. stupid nexon return; } else { if (Constants.isEquip(drop.Reward.ItemID)) { ItemTransfer.ItemPickedUp(chr.ID, chr.MapID, reward.ItemID, reward.Amount, chr.MapID + ", " + drop.GetHashCode(), drop.Reward.GetData()); } } if (!SentDropNotice) { CharacterStatsPacket.SendGainDrop(chr, reward.Mesos, dropNoticeItemIdOrMesos, pickupAmount); } chr.Field.DropPool.RemoveDrop(drop, RewardLeaveType.FreeForAll, chr.ID); }
public override void AC_OnPacketInbound(Packet packet) { ClientMessages header = 0; try { header = (ClientMessages)packet.ReadByte(); if (!Loaded || Player?.Character == null) { switch (header) { case ClientMessages.MIGRATE_IN: OnPlayerLoad(packet); break; //updated } } // Block packets as we are migrating else if (Server.Instance.InMigration == false || Server.Instance.IsNewServerInMigration) { var character = Player.Character; if (logPackets.Contains(header)) { PacketLog.ReceivedPacket(packet, (byte)header, Server.Instance.Name, IP); } switch (header) { case ClientMessages.ENTER_PORTAL: MapPacket.OnEnterPortal(packet, character); break; case ClientMessages.CHANGE_CHANNEL: OnChangeChannel(character, packet); break; case ClientMessages.ENTER_CASH_SHOP: OnEnterCashShop(character); break; case ClientMessages.MOVE_PLAYER: MapPacket.HandleMove(character, packet); break; case ClientMessages.SIT_REQUEST: MapPacket.HandleSitChair(character, packet); break; case ClientMessages.ENTER_TOWN_PORTAL: MapPacket.HandleDoorUse(character, packet); break; case ClientMessages.CLOSE_RANGE_ATTACK: AttackPacket.HandleMeleeAttack(character, packet); break; case ClientMessages.RANGED_ATTACK: AttackPacket.HandleRangedAttack(character, packet); break; case ClientMessages.MAGIC_ATTACK: AttackPacket.HandleMagicAttack(character, packet); break; case ClientMessages.TAKE_DAMAGE: CharacterStatsPacket.HandleCharacterDamage(character, packet); break; case ClientMessages.CHAT: MessagePacket.HandleChat(character, packet); break; case ClientMessages.GROUP_MESSAGE: MessagePacket.HandleSpecialChat(character, packet); break; case ClientMessages.WHISPER: MessagePacket.HandleCommand(character, packet); break; case ClientMessages.EMOTE: MapPacket.SendEmotion(character, packet.ReadInt()); break; case ClientMessages.NPC_TALK: MapPacket.HandleNPCChat(character, packet); break; case ClientMessages.NPC_TALK_MORE: NpcPacket.HandleNPCChat(character, packet); break; case ClientMessages.SHOP_ACTION: NpcPacket.HandleNPCShop(character, packet); break; case ClientMessages.STORAGE_ACTION: StoragePacket.HandleStorage(character, packet); break; case ClientMessages.ITEM_MOVE: InventoryPacket.HandleInventoryPacket(character, packet); break; case ClientMessages.ITEM_USE: InventoryPacket.HandleUseItemPacket(character, packet); break; case ClientMessages.SUMMON_BAG_USE: InventoryPacket.HandleUseSummonSack(character, packet); break; case ClientMessages.CASH_ITEM_USE: CashPacket.HandleCashItem(character, packet); break; case ClientMessages.RETURN_SCROLL_USE: InventoryPacket.HandleUseReturnScroll(character, packet); break; case ClientMessages.SCROLL_USE: InventoryPacket.HandleScrollItem(character, packet); break; case ClientMessages.DISTRIBUTE_AP: CharacterStatsPacket.HandleStats(character, packet); break; case ClientMessages.HEAL_OVER_TIME: CharacterStatsPacket.HandleHeal(character, packet); break; case ClientMessages.DISTRIBUTE_SP: SkillPacket.HandleAddSkillLevel(character, packet); break; case ClientMessages.PREPARE_SKILL: SkillPacket.HandlePrepareSkill(character, packet); break; case ClientMessages.GIVE_BUFF: SkillPacket.HandleUseSkill(character, packet); break; case ClientMessages.CANCEL_BUFF: SkillPacket.HandleStopSkill(character, packet); break; case ClientMessages.DROP_MESOS: DropPacket.HandleDropMesos(character, packet.ReadInt()); break; case ClientMessages.GIVE_FAME: FamePacket.HandleFame(character, packet); break; case ClientMessages.CHAR_INFO_REQUEST: MapPacket.SendPlayerInfo(character, packet); break; case ClientMessages.SPAWN_PET: PetsPacket.HandleSpawnPet(character, packet.ReadShort()); break; case ClientMessages.SUMMON_MOVE: MapPacket.HandleSummonMove(character, packet); break; case ClientMessages.SUMMON_ATTACK: AttackPacket.HandleSummonAttack(character, packet); break; case ClientMessages.SUMMON_DAMAGED: MapPacket.HandleSummonDamage(character, packet); break; case ClientMessages.MOB_MOVE: MobPacket.HandleMobControl(character, packet); break; case ClientMessages.NPC_ANIMATE: MapPacket.HandleNPCAnimation(character, packet); break; case ClientMessages.PET_MOVE: PetsPacket.HandleMovePet(character, packet); break; case ClientMessages.PET_INTERACTION: PetsPacket.HandleInteraction(character, packet); break; case ClientMessages.PET_ACTION: PetsPacket.HandlePetAction(character, packet); break; case ClientMessages.FIELD_CONTIMOVE_STATE: MapPacket.OnContiMoveState(character, packet); break; case ClientMessages.DROP_PICK_UP: DropPacket.HandlePickupDrop(character, packet); break; case ClientMessages.MESSENGER: MessengerHandler.HandleMessenger(character, packet); break; case ClientMessages.MINI_ROOM_OPERATION: MiniRoomPacket.HandlePacket(character, packet); break; case ClientMessages.FRIEND_OPERATION: BuddyHandler.HandleBuddy(character, packet); break; case ClientMessages.PARTY_OPERATION: PartyHandler.HandleParty(character, packet); break; case ClientMessages.DENY_PARTY_REQUEST: PartyHandler.HandleDecline(character, packet); break; case ClientMessages.REACTOR_HIT: ReactorPacket.HandleReactorHit(character, packet); break; case ClientMessages.REPORT_USER: MiscPacket.ReportPlayer(character, packet); break; //this is a garbage opcode that i use when doing janky client packet workarounds. This is where packets go to die. case ClientMessages.JUNK: Program.MainForm.LogDebug("received junk packet"); break; // eh.. ignore? // Happens when one of the following buffs are set: // Stun, Poison, Seal, Darkness, Weakness, Curse // Maybe patch out of the client case ClientMessages.CHARACTER_IS_DEBUFFED: break; // TODO: Implement??? case ClientMessages.MOB_APPLY_CONTROL: break; case ClientMessages.CLIENT_HASH: break; case ClientMessages.PONG: // Make sure we update the player online thing RedisBackend.Instance.SetPlayerOnline( character.UserID, Server.Instance.GetOnlineId() ); // Cleanup expired items character.Inventory.CheckExpired(); break; default: if (character.Field.HandlePacket(character, packet, header) == false) { Program.MainForm.LogAppend( "[{0}] Unknown packet received! " + packet, header ); } break; } } } catch (Exception ex) { Program.MainForm.LogAppend($"---- ERROR ----\r\n{ex}"); Program.MainForm.LogAppend($"Packet: {packet}"); FileWriter.WriteLine(@"etclog\ExceptionCatcher.log", "[Game Server " + Server.Instance.ID + "][" + DateTime.Now + "] Exception caught: " + ex, true); //Disconnect(); } #if DEBUG if (packet.Length != packet.Position) { var packetStr = packet.ToString(); packetStr = packetStr.Substring(0, packet.Position * 3 - 1) + "-x-" + packetStr.Substring(packet.Position * 3); log.Debug($"Did not read full message in packet: {header} {packetStr}"); } #endif }
public void OnVarset(Character Sent, string Var, object Value, object Value2 = null, object Value3 = null) { if (this != Sent && Sent.IsGM && !Sent.IsAdmin) //Todo Admin levels { MessagePacket.SendNotice("You don't have the premission to edit other players stats!", Sent); //$"{Sent.Name} tried to edit another players stats without premission" } else { try { MapPacket.AvatarModFlag AvatarMod = 0; CharacterStatsPacket.StatFlags dwFlag = 0; switch (Var.ToLower()) { case "hp": dwFlag |= CharacterStatsPacket.StatFlags.Hp; PrimaryStats.HP = Convert.ToInt16(Value); break; case "mp": dwFlag |= CharacterStatsPacket.StatFlags.Mp; PrimaryStats.MP = Convert.ToInt16(Value); break; case "exp": dwFlag |= CharacterStatsPacket.StatFlags.Exp; PrimaryStats.EXP = Convert.ToInt32(Value); break; case "maxhp": dwFlag |= CharacterStatsPacket.StatFlags.MaxHp; if (Value.ToString() == "0") { Value = "1"; } PrimaryStats.MaxHP = Convert.ToInt16(Value); break; case "maxmp": dwFlag |= CharacterStatsPacket.StatFlags.MaxMp; if (Value.ToString() == "0") { Value = "1"; } PrimaryStats.MaxMP = Convert.ToInt16(Value); break; case "ap": dwFlag |= CharacterStatsPacket.StatFlags.Ap; PrimaryStats.AP = Convert.ToInt16(Value); break; case "sp": dwFlag |= CharacterStatsPacket.StatFlags.Sp; PrimaryStats.SP = Convert.ToInt16(Value); break; case "str": dwFlag |= CharacterStatsPacket.StatFlags.Str; PrimaryStats.Str = Convert.ToInt16(Value); break; case "dex": dwFlag |= CharacterStatsPacket.StatFlags.Dex; PrimaryStats.Dex = Convert.ToInt16(Value); break; case "int": dwFlag |= CharacterStatsPacket.StatFlags.Int; PrimaryStats.Int = Convert.ToInt16(Value); break; case "luk": dwFlag |= CharacterStatsPacket.StatFlags.Luk; PrimaryStats.Luk = Convert.ToInt16(Value); break; case "fame": case "pop": dwFlag |= CharacterStatsPacket.StatFlags.Fame; PrimaryStats.Fame = Convert.ToInt16(Value); break; case "mesos": dwFlag |= CharacterStatsPacket.StatFlags.Mesos; Inventory.Mesos = Convert.ToInt32(Value); break; case "job": { var Job = Convert.ToInt16(Value); if (DataProvider.HasJob(Job) || Job == 0) { dwFlag |= CharacterStatsPacket.StatFlags.Job; PrimaryStats.Job = Job; } else { MessagePacket.SendNotice($"Job {Job} does not exist.", Sent); } break; } case "skill": { var SkillID = Convert.ToInt32(Value); if (DataProvider.Skills.TryGetValue(SkillID, out var Skill)) { if (Value2 == null) { Value2 = Skill.MaxLevel; } Skills.SetSkillPoint(SkillID, Convert.ToByte(Value2), true); } else { MessagePacket.SendNotice($"Skill {SkillID} does not exist.", Sent); } break; } case "level": dwFlag |= CharacterStatsPacket.StatFlags.Level; Level = Convert.ToByte(Value); MapPacket.SendPlayerLevelupAnim(this); break; case "skin": { var SkinID = Convert.ToByte(Value); if (SkinID >= 0 && SkinID < 6) { AvatarMod |= MapPacket.AvatarModFlag.Skin; dwFlag |= CharacterStatsPacket.StatFlags.Skin; Skin = SkinID; } else { MessagePacket.SendNotice($"Skin {SkinID} does not exist.", Sent); } break; } case "face": { var FaceID = Convert.ToInt32(Value); if (DataProvider.Equips.ContainsKey(FaceID)) { AvatarMod |= MapPacket.AvatarModFlag.Face; dwFlag |= CharacterStatsPacket.StatFlags.Eyes; Face = FaceID; } else { MessagePacket.SendNotice($"Face {FaceID} does not exist.", Sent); } break; } case "hair": { var HairID = Convert.ToInt32(Value); if (DataProvider.Equips.ContainsKey(HairID)) { AvatarMod |= MapPacket.AvatarModFlag.Equips; dwFlag |= CharacterStatsPacket.StatFlags.Hair; Hair = HairID; } else { MessagePacket.SendNotice($"Hair {HairID} does not exist.", Sent); } break; } case "gender": { Gender = ParseGenderString(Value.ToString()); Server.Instance.CharacterDatabase.RunQuery( "UPDATE characters SET gender = @gender WHERE id = @id", "@gender", Gender, "@id", ID ); MessagePacket.SendNotice($"Gender set to {(Gender == 0 ? "male" : (Gender == 2 ? "Unisex" : "female"))}. Please relog.", this); break; } case "accgender": { var gender = ParseGenderString(Value.ToString()); Server.Instance.CharacterDatabase.RunQuery( "UPDATE users SET gender = @gender WHERE ID = @id", "@gender", gender, "@id", UserID ); MessagePacket.SendNotice($"Account gender set to {(gender == 0 ? "male" : (gender == 2 ? "Unisex" : "female"))}", this); break; } case "map": case "field": { var FieldID = Convert.ToInt32(Value); if (DataProvider.Maps.ContainsKey(FieldID)) { ChangeMap(FieldID); } else { MessagePacket.SendText(MessagePacket.MessageTypes.RedText, "Map not found.", this, MessagePacket.MessageMode.ToPlayer); } break; } default: MessagePacket.SendNotice($"{Var} is not a valid Variable!", Sent); return; } if (dwFlag != 0) { CharacterStatsPacket.SendUpdateStat(this, true, dwFlag); } if (AvatarMod != 0) { MapPacket.SendAvatarModified(this, AvatarMod); } } catch (Exception ex) { MessagePacket.SendNotice(ex.Message, Sent); } } }
public void SetEXP(int value) { PrimaryStats.EXP = value; CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Exp, value); }
public void AddEXP(uint value, bool IsLastHit = false, bool Quest = false) { if (value == 0 || PrimaryStats.Level >= 200 || PrimaryStats.HP <= 0) { return; } var amount = (int)(value > Int32.MaxValue ? Int32.MaxValue : value); var amnt = (uint)(PrimaryStats.EXP + amount); CharacterStatsPacket.SendGainEXP(this, amount, IsLastHit, Quest); var level = PrimaryStats.Level; var save = false; var expRequired = Constants.GetLevelEXP(PrimaryStats.Level); if (amnt >= expRequired) { short apgain = 0; short spgain = 0; short mpgain = 0; short hpgain = 0; var job = (short)(PrimaryStats.Job / 100); var intt = PrimaryStats.GetIntAddition(true); amnt -= (uint)expRequired; level++; // Update EXP required... expRequired = Constants.GetLevelEXP(level); apgain += Constants.ApPerLevel; hpgain += RNG.Range.generate( Constants.HpMpFormulaArguments[job, 0, (int)Constants.HpMpFormulaFields.HPMin], Constants.HpMpFormulaArguments[job, 0, (int)Constants.HpMpFormulaFields.HPMax], true ); mpgain += RNG.Range.generate( Constants.HpMpFormulaArguments[job, 0, (int)Constants.HpMpFormulaFields.MPMin], Constants.HpMpFormulaArguments[job, 0, (int)Constants.HpMpFormulaFields.MPMax], true ); // Additional buffing through INT stats mpgain += (short)( intt * Constants.HpMpFormulaArguments[job, 0, (int)Constants.HpMpFormulaFields.MPIntStatMultiplier] / 200 ); var improvedMaxHpIncreaseLvl = Skills.GetSkillLevel(Constants.Swordsman.Skills.ImprovedMaxHpIncrease); if (improvedMaxHpIncreaseLvl > 0) { hpgain += CharacterSkills.GetSkillLevelData(Constants.Swordsman.Skills.ImprovedMaxHpIncrease, improvedMaxHpIncreaseLvl).XValue; } var improvedMaxMpIncreaseLvl = Skills.GetSkillLevel(Constants.Magician.Skills.ImprovedMaxMpIncrease); if (improvedMaxMpIncreaseLvl > 0) { mpgain += CharacterSkills.GetSkillLevelData(Constants.Magician.Skills.ImprovedMaxMpIncrease, improvedMaxMpIncreaseLvl).XValue; } if (PrimaryStats.Job != 0) { spgain = Constants.SpPerLevel; } if (level >= 200) { amnt = 0; // TODO: Announce max level! } // Overflow? lets reduce it if (amnt >= expRequired) { amnt = (uint)(expRequired - 1); } _levelLog.Info(new LevelLogRecord { level = level, posX = Position.X, posY = Position.Y, }); ModifyMaxHP(hpgain); ModifyMaxMP(mpgain); SetLevel(level); AddAP(apgain); AddSP(spgain); ModifyHP(PrimaryStats.GetMaxHP(false)); ModifyMP(PrimaryStats.GetMaxMP(false)); save = true; } PrimaryStats.EXP = (int)amnt; // Calculate savepoints var stepOfSave = CalculateSaveStep(); var curDateTime = MasterThread.CurrentDate; if (!save) { if (lastSaveStep != stepOfSave) { var levelTimeSpan = curDateTime - LastSavepoint; if (levelTimeSpan.TotalSeconds >= 30) { _characterLog.Debug( $"Saving because user reached save threshold. Current {stepOfSave} last {lastSaveStep}"); save = true; LastSavepoint = curDateTime; } else { AssertForHack( levelTimeSpan.TotalSeconds < 20, $"Getting fast EXP ({levelTimeSpan.TotalSeconds} seconds since last savepoint)", levelTimeSpan.TotalSeconds < 15 ); } _characterLog.Debug( new SavepointLogRecord { level = PrimaryStats.Level, posX = Position.X, posY = Position.Y, totalMillisBetween = (int)levelTimeSpan.TotalMilliseconds, blocked = save == false } ); lastSaveStep = stepOfSave; } } else { lastSaveStep = stepOfSave; } if (save) { LastSavepoint = curDateTime; Save(); } CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Exp, PrimaryStats.EXP); }
public void DamageMP(short amount) { PrimaryStats.MP = (short)(amount > PrimaryStats.MP ? 0 : PrimaryStats.MP - amount); CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Mp, PrimaryStats.MP, false); }