public static void WebUpdateMonsterData(List <Monster> monsterData) { int monsterCount = monsterData.Count(); for (int i = 0; i < monsterCount; i++) { Monster monster = monsterData.ElementAt(i); if (monster.Name == "Kono Dio da!" || monster.Health.Max > 1999999) { continue; } monsterNames[i] = monster.Name; monsterSizes[i] = monster.Crown.ToString() + " Crown, Size: " + monster.Size; if (monster.Health.Current < 1) { monsterCurrentHealths[i] = "0"; } else { monsterCurrentHealths[i] = monster.Health.Current.ToString(); } if (monster.Health.Max < 1) { monsterMaxHealths[i] = "0"; } else { monsterMaxHealths[i] = monster.Health.Max.ToString(); } int partsCount = monster.Parts.Count(); int effectsCount = monster.StatusEffects.Count(); monsterPartsAndStatuses[i] = ""; for (int j = 0; j < partsCount; j++) { MonsterPart monsterPart = monster.Parts.ElementAt(j); monsterPartsAndStatuses[i] += monsterPart.Name + ": " + monsterPart.Health.Current + " / " + monsterPart.Health.Max + "<br />"; } monsterPartsAndStatuses[i] += "<br />"; for (int j = 0; j < effectsCount; j++) { MonsterStatusEffect statusEffect = monster.StatusEffects.ElementAt(j); if (0 < statusEffect.Duration.Fraction && statusEffect.Duration.Fraction < 1000 && statusEffect.Buildup.Fraction > 0) { monsterPartsAndStatuses[i] += statusEffect.Name + " Build: " + Math.Round(statusEffect.Buildup.Fraction) * 100 + "% / Dur " + Math.Round(statusEffect.Duration.Fraction) * 100 + "% <br />"; } } } }
private static void UpdateMonsterStatusEffects(Process process, Monster monster) { int maxIndex = ConfigHelper.MonsterData.Values.StatusEffects.Where(s => s.GroupId.Equals("StatusEffect")).Count() - 1; var statuses = monster.StatusEffects; if (statuses != null && statuses.Where(s => s.GroupId.Equals("StatusEffect")).Any()) { for (int i = 0; i < statuses.Count(); i++) { MonsterStatusEffect status = statuses[i]; if (status == null) { continue; } float currentBuildup = 0; float maxBuildup = MemoryHelper.Read <float>(process, status.Address + DataOffsets.MonsterStatusEffect.MaxBuildup); if (maxBuildup > 0) { currentBuildup = MemoryHelper.Read <float>(process, status.Address + DataOffsets.MonsterStatusEffect.CurrentBuildup); } float currentDuration = 0; float maxDuration = MemoryHelper.Read <float>(process, status.Address + DataOffsets.MonsterStatusEffect.MaxDuration); if (maxDuration > 0) { currentDuration = MemoryHelper.Read <float>(process, status.Address + DataOffsets.MonsterStatusEffect.CurrentDuration); } int timesActivatedCount = MemoryHelper.Read <int>(process, status.Address + DataOffsets.MonsterStatusEffect.TimesActivatedCount); if (maxBuildup > 0 || maxDuration > 0) { uint index = MemoryHelper.Read <uint>(process, status.Address + 0x198); if (index <= maxIndex) { var statusEffectConfig = ConfigHelper.MonsterData.Values.StatusEffects[index]; monster.UpdateAndGetStatusEffect(status.Address, (int)index, maxBuildup > 0 ? maxBuildup : 1, !statusEffectConfig.InvertBuildup ? currentBuildup : maxBuildup - currentBuildup, maxDuration, !statusEffectConfig.InvertDuration ? currentDuration : maxDuration - currentDuration, timesActivatedCount); } } } } else { ulong baseStatus = MemoryHelper.Read <ulong>(process, monster.Address + DataOffsets.Monster.MonsterStartOfStructOffset + 0x78); baseStatus = MemoryHelper.Read <ulong>(process, baseStatus + 0x57A8); ulong nani = baseStatus; while (nani != 0) { nani = MemoryHelper.Read <ulong>(process, nani + 0x10); if (nani != 0) { baseStatus = nani; } } ulong currentStatusPointer = baseStatus + 0x40; while (currentStatusPointer != 0x0) { var currentMonsterInStatus = MemoryHelper.Read <ulong>(process, currentStatusPointer + 0x188); if (currentMonsterInStatus == monster.Address + 0x40 && !monster.StatusEffects.Where(status => status.Address == currentStatusPointer).Any()) { float currentBuildup = 0; float maxBuildup = MemoryHelper.Read <float>(process, currentStatusPointer + DataOffsets.MonsterStatusEffect.MaxBuildup); if (maxBuildup > 0) { currentBuildup = MemoryHelper.Read <float>(process, currentStatusPointer + DataOffsets.MonsterStatusEffect.CurrentBuildup); } float currentDuration = 0; float maxDuration = MemoryHelper.Read <float>(process, currentStatusPointer + DataOffsets.MonsterStatusEffect.MaxDuration); if (maxDuration > 0) { currentDuration = MemoryHelper.Read <float>(process, currentStatusPointer + DataOffsets.MonsterStatusEffect.CurrentDuration); } int timesActivatedCount = MemoryHelper.Read <int>(process, currentStatusPointer + DataOffsets.MonsterStatusEffect.TimesActivatedCount); if (maxBuildup > 0 || maxDuration > 0) { uint index = MemoryHelper.Read <uint>(process, currentStatusPointer + 0x198); if (index <= maxIndex && !((index == 14 || index == 15) && monster.isElder)) // skip traps for elders { var statusEffectConfig = ConfigHelper.MonsterData.Values.StatusEffects[index]; monster.UpdateAndGetStatusEffect(currentStatusPointer, (int)index, maxBuildup > 0 ? maxBuildup : 1, !statusEffectConfig.InvertBuildup ? currentBuildup : maxBuildup - currentBuildup, maxDuration, !statusEffectConfig.InvertDuration ? currentDuration : maxDuration - currentDuration, timesActivatedCount); } } } currentStatusPointer = MemoryHelper.Read <ulong>(process, currentStatusPointer + 0x18); } } // Stamina ulong staminaAddress = monster.Address + DataOffsets.Monster.MonsterStaminaOffset; float maxStaminaBuildUp = MemoryHelper.Read <float>(process, staminaAddress + 0x4); float currentStaminaBuildUp = 0; if (maxStaminaBuildUp > 0) { currentStaminaBuildUp = MemoryHelper.Read <float>(process, staminaAddress); } float maxFatigueDuration = MemoryHelper.Read <float>(process, staminaAddress + 0xC); float currentFatigueDuration = 0; if (maxFatigueDuration > 0) { currentFatigueDuration = MemoryHelper.Read <float>(process, staminaAddress + 0x10); } int fatigueActivatedCount = MemoryHelper.Read <int>(process, staminaAddress + 0x14); MonsterStatusEffectConfig statusEffect = null; if (currentFatigueDuration > 0) { statusEffect = ConfigHelper.MonsterData.Values.StatusEffects.SingleOrDefault(s => s.GroupId.Equals("Fatigue")); } else { statusEffect = ConfigHelper.MonsterData.Values.StatusEffects.SingleOrDefault(s => s.GroupId.Equals("Stamina")); } if (maxStaminaBuildUp > 0 || currentFatigueDuration > 0) { monster.UpdateAndGetStatusEffect(staminaAddress, Array.IndexOf(ConfigHelper.MonsterData.Values.StatusEffects, statusEffect), maxStaminaBuildUp > 0 ? maxStaminaBuildUp : 1, !statusEffect.InvertBuildup ? currentStaminaBuildUp : maxStaminaBuildUp - currentStaminaBuildUp, maxFatigueDuration, !statusEffect.InvertDuration ? currentFatigueDuration : maxFatigueDuration - currentFatigueDuration, fatigueActivatedCount); } // Rage ulong rageAddress = monster.Address + DataOffsets.Monster.MonsterRageOffset; float maxRageBuildUp = MemoryHelper.Read <float>(process, rageAddress + 0x24); float currentRageBuildUp = 0; if (maxRageBuildUp > 0) { currentRageBuildUp = MemoryHelper.Read <float>(process, rageAddress); } float maxRageDuration = MemoryHelper.Read <float>(process, rageAddress + 0x10); float currentRageDuration = 0; if (maxRageDuration > 0) { currentRageDuration = MemoryHelper.Read <float>(process, rageAddress + 0xC); } int rageActivatedCount = MemoryHelper.Read <int>(process, rageAddress + 0x1C); var rageStatusEffect = ConfigHelper.MonsterData.Values.StatusEffects.SingleOrDefault(s => s.GroupId.Equals("Rage"));//[33]; // 33 is rage if (maxRageBuildUp > 0 || maxRageDuration > 0) { monster.UpdateAndGetStatusEffect(rageAddress, Array.IndexOf(ConfigHelper.MonsterData.Values.StatusEffects, rageStatusEffect), maxRageBuildUp > 0 ? maxRageBuildUp : 1, !rageStatusEffect.InvertBuildup ? currentRageBuildUp : maxRageBuildUp - currentRageBuildUp, maxRageDuration, !rageStatusEffect.InvertDuration ? currentRageDuration : maxRageDuration - currentRageDuration, rageActivatedCount); } }
public static void ApplyAttack(AttackInfo attack, MapleCharacter player, int maxDamagePerMonster, int attackCount) { //应用攻击 player.AntiCheatTracker.ResetHpRegen(); //player.resetAfkTimer(); player.AntiCheatTracker.CheckAttack(attack.Skill); ISkill theSkill = null; MapleStatEffect attackEffect = null; if (attack.Skill != 0) { theSkill = SkillFactory.GetSkill(attack.Skill); attackEffect = attack.GetAttackEffect(player, theSkill); if (attackEffect == null) { AutobanManager.Instance.Autoban(player.Client, $"使用了没有的技能ID:{attack.Skill}"); } else if (attack.Skill != 2301002) { if (player.IsAlive) { attackEffect.ApplyTo(player); } else { player.Client.Send(PacketCreator.EnableActions()); } } } if (!player.IsAlive) { player.AntiCheatTracker.RegisterOffense(CheatingOffense.AttackingWhileDead); return; } if (attackCount != attack.NumDamage && attack.Skill != 4211006 && attack.NumDamage != attackCount * 2) { player.AntiCheatTracker.RegisterOffense(CheatingOffense.MismatchingBulletcount, attack.NumDamage + "/" + attackCount); return; } var totDamage = 0; var map = player.Map; if (attack.Skill == 4211006) { // meso explosion long delay = 0; foreach (var oned in attack.AllDamage) { var mapobject = map.Mapobjects[oned.Item1]; if (mapobject != null && mapobject.GetType() == MapleMapObjectType.Item) { var mapitem = (MapleMapItem)mapobject; if (mapitem.Meso > 0) { lock (mapitem) { if (mapitem.IsPickedUp) { return; } TimerManager.Instance.RunOnceTask(() => { map.RemoveMapObject(mapitem); map.BroadcastMessage(PacketCreator.RemoveItemFromMap(mapitem.ObjectId, 4, 0), mapitem.Position); mapitem.IsPickedUp = true; }, delay); delay += 100; } } else if (mapitem.Meso == 0) { player.AntiCheatTracker.RegisterOffense(CheatingOffense.EtcExplosion); return; } } else if (mapobject != null && mapobject.GetType() != MapleMapObjectType.Monster) { player.AntiCheatTracker.RegisterOffense(CheatingOffense.ExplodingNonexistant); return; // etc explosion, exploding nonexistant things, etc. } } } foreach (var oned in attack.AllDamage) { var monster = map.GetMonsterByOid(oned.Item1); if (monster != null) { var totDamageToOneMonster = 0; foreach (var eachd in oned.Item2) { totDamageToOneMonster += eachd; } totDamage += totDamageToOneMonster; player.CheckMonsterAggro(monster); if (totDamageToOneMonster > attack.NumDamage + 1) { var dmgCheck = player.AntiCheatTracker.CheckDamage(totDamageToOneMonster); if (dmgCheck > 5 && totDamageToOneMonster < 99999 && monster.Id < 9500317 && monster.Id > 9500319) { player.AntiCheatTracker .RegisterOffense(CheatingOffense.SameDamage, dmgCheck + " times: " + totDamageToOneMonster); } } // �?测单次攻击�?�,这里不会�?! if (player.IsGm || player.Job == MapleJob.Ares && player.Level <= 10) { //log.info("这里不进行操�?"); } else { if (player.Level < 10) { if (totDamageToOneMonster > 10000) { AutobanManager.Instance.BroadcastMessage(player.Client, player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + ")"); //player.ban(player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + " (IP: " + player.Client.getSession().getRemoteAddress().toString().split(":")[0] + ")"); return; } } if (player.Level < 20) { if (totDamageToOneMonster > 20000) { AutobanManager.Instance.BroadcastMessage(player.Client, player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + ")"); //player.ban(player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + " (IP: " + player.Client.getSession().getRemoteAddress().toString().split(":")[0] + ")"); return; } } if (player.Level < 30) { if (totDamageToOneMonster > 30000) { AutobanManager.Instance.BroadcastMessage(player.Client, player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + ")"); //player.ban(player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + " (IP: " + player.Client.getSession().getRemoteAddress().toString().split(":")[0] + ")"); return; } } if (player.Level < 50) { if (totDamageToOneMonster > 50000) { AutobanManager.Instance.BroadcastMessage(player.Client, player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + ")"); //player.ban(player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + " (IP: " + player.Client.getSession().getRemoteAddress().toString().split(":")[0] + ")"); return; } } if (player.Level < 70) { if (totDamageToOneMonster > 150000) { AutobanManager.Instance.BroadcastMessage(player.Client, player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + ")"); //player.ban(player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + " (IP: " + player.Client.getSession().getRemoteAddress().toString().split(":")[0] + ")"); return; } } if (player.Level < 150) { if (totDamageToOneMonster > 350000) { AutobanManager.Instance.BroadcastMessage(player.Client, player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + ")"); //player.ban(player.Name + " 被系统封�?.(异常攻击伤害�?: " + totDamageToOneMonster + " 当前等级 " + player.Level + " (IP: " + player.Client.getSession().getRemoteAddress().toString().split(":")[0] + ")"); return; } } } CheckHighDamage(player, monster, attack, theSkill, attackEffect, totDamageToOneMonster, maxDamagePerMonster); var distance = player.Position.DistanceSquare(monster.Position); if (distance > 400000.0) { // 600^2, 550 is approximatly the range of ultis player.AntiCheatTracker.RegisterOffense(CheatingOffense.AttackFarawayMonster, Math.Sqrt(distance).ToString(CultureInfo.InvariantCulture)); } //遥远的�?�物袭击 if (attack.Skill == 5111004) { // 能量转换 var edrain = SkillFactory.GetSkill(5111004); var gainhp = (int) (totDamage * (double)edrain.GetEffect(player.GetSkillLevel(edrain)).X / 100.0); gainhp = Math.Min(monster.MaxHp, Math.Min(gainhp, player.MaxHp / 2)); player.Hp += (short)gainhp; } else if (attack.Skill == 15100004) { //光�?�拳 var edrain = SkillFactory.GetSkill(15100004); var gainhp = (int) (totDamage * (double)edrain.GetEffect(player.GetSkillLevel(edrain)).X / 100.0); gainhp = Math.Min(monster.MaxHp, Math.Min(gainhp, player.MaxHp / 2)); player.Hp += (short)gainhp; } if (!monster.ControllerHasAggro) { if (monster.GetController() == player) { monster.ControllerHasAggro = true; } else { monster.SwitchController(player, true); } } if (attack.Skill == 2301002 && !monster.Stats.IsUndead) { player.AntiCheatTracker.RegisterOffense(CheatingOffense.HealAttackingUndead); //医治攻击亡灵 return; } // Pickpocket if ((attack.Skill == 4001334 || attack.Skill == 4201005 || attack.Skill == 0 || attack.Skill == 4211002 || attack.Skill == 4211004) && player.GetBuffedValue(MapleBuffStat.Pickpocket) != null) { HandlePickPocket(player, monster, oned); } if (attack.Skill == 21100005) { // 生命吸收21100005 var drain = SkillFactory.GetSkill(21100005); var gainhp = (int) (totDamageToOneMonster * (double)drain.GetEffect(player.GetSkillLevel(drain)).X / 100.0); gainhp = Math.Min(monster.MaxHp, Math.Min(gainhp, player.MaxHp / 2)); player.Hp += (short)gainhp; } if (attack.Skill == 4101005) { // 生命吸收21100005 var drain = SkillFactory.GetSkill(4101005); var gainhp = (int) (totDamageToOneMonster * (double)drain.GetEffect(player.GetSkillLevel(drain)).X / 100.0); gainhp = Math.Min(monster.MaxHp, Math.Min(gainhp, player.MaxHp / 2)); player.Hp += (short)gainhp; } if (attack.Skill == 14101006) { // 吸血 var drain = SkillFactory.GetSkill(14101006); var gainhp = (int) (totDamageToOneMonster * (double)drain.GetEffect(player.GetSkillLevel(drain)).X / 100.0); gainhp = Math.Min(monster.MaxHp, Math.Min(gainhp, player.MaxHp / 2)); player.Hp += (short)gainhp; } if (player.GetBuffedValue(MapleBuffStat.Hamstring) != null) { var hamstring = SkillFactory.GetSkill(3121007); //降低速度的击�?�? if (hamstring.GetEffect(player.GetSkillLevel(hamstring)).MakeChanceResult()) { var monsterStatusEffect = new MonsterStatusEffect( new Dictionary <MonsterStatus, int> { { MonsterStatus.Speed, hamstring.GetEffect(player.GetSkillLevel(hamstring)).X } }, hamstring, false); monster.ApplyStatus(player, monsterStatusEffect, false, hamstring.GetEffect(player.GetSkillLevel(hamstring)).Y *1000); } } if (player.GetBuffedValue(MapleBuffStat.Blind) != null) { //刺眼�? var blind = SkillFactory.GetSkill(3221006); if (blind.GetEffect(player.GetSkillLevel(blind)).MakeChanceResult()) { var monsterStatusEffect = new MonsterStatusEffect( new Dictionary <MonsterStatus, int> { { MonsterStatus.Acc, blind.GetEffect(player.GetSkillLevel(blind)).X } } , blind, false); monster.ApplyStatus(player, monsterStatusEffect, false, blind.GetEffect(player.GetSkillLevel(blind)).Y *1000); } } if (player.Job == MapleJob.Whiteknight) { int[] charges = { 1211005, 1211006 }; //寒冰钝器 foreach (var charge in charges) { var chargeSkill = SkillFactory.GetSkill(charge); if (player.IsBuffFrom(MapleBuffStat.WkCharge, chargeSkill)) { var iceEffectiveness = monster.GetEffectiveness(Element.Ice); if (totDamageToOneMonster > 0 && iceEffectiveness == ElementalEffectiveness.Normal || iceEffectiveness == ElementalEffectiveness.Weak) { var chargeEffect = chargeSkill.GetEffect(player.GetSkillLevel(chargeSkill)); var monsterStatusEffect = new MonsterStatusEffect( new Dictionary <MonsterStatus, int> { { MonsterStatus.Freeze, 1 } }, chargeSkill, false); monster.ApplyStatus(player, monsterStatusEffect, false, chargeEffect.Y * 2000); } break; } } } var venomNl = SkillFactory.GetSkill(4120005); //武器用毒�? if (player.GetSkillLevel(venomNl) <= 0) { venomNl = SkillFactory.GetSkill(14110004); //武器用毒�? } var venomShadower = SkillFactory.GetSkill(4220005); if (player.GetSkillLevel(venomNl) > 0) { var venomEffect = venomNl.GetEffect(player.GetSkillLevel(venomNl)); for (var i = 0; i < attackCount; i++) { if (venomEffect.MakeChanceResult()) { if (monster.VenomMultiplier < 3) { monster.VenomMultiplier += 1; var monsterStatusEffect = new MonsterStatusEffect( new Dictionary <MonsterStatus, int> { { MonsterStatus.Poison, 1 } }, venomNl, false); monster.ApplyStatus(player, monsterStatusEffect, false, venomEffect.Duration, true); } } } } else if (player.GetSkillLevel(venomShadower) > 0) { var venomEffect = venomShadower.GetEffect(player.GetSkillLevel(venomShadower)); for (var i = 0; i < attackCount; i++) { if (venomEffect.MakeChanceResult()) { if (monster.VenomMultiplier < 3) { monster.VenomMultiplier += 1; var monsterStatusEffect = new MonsterStatusEffect( new Dictionary <MonsterStatus, int> { { MonsterStatus.Poison, 1 } }, venomShadower, false); monster.ApplyStatus(player, monsterStatusEffect, false, venomEffect.Duration, true); } } } } if (totDamageToOneMonster > 0 && attackEffect != null && attackEffect.MonsterStatus.Any()) { if (attackEffect.MakeChanceResult()) { var monsterStatusEffect = new MonsterStatusEffect(attackEffect.MonsterStatus, theSkill, false); monster.ApplyStatus(player, monsterStatusEffect, attackEffect.IsPoison(), attackEffect.Duration); } } if (attack.IsHh && !monster.IsBoss) { map.DamageMonster(player, monster, monster.Hp - 1); } else if (attack.IsHh && monster.IsBoss) { var weaponItem = player.Inventorys[MapleInventoryType.Equipped.Value].Inventory[0xF5]; //装备 MapleItemInformationProvider.Instance.GetWeaponType(weaponItem.ItemId); } else { map.DamageMonster(player, monster, totDamageToOneMonster); } } } if (totDamage > 1) { player.AntiCheatTracker.SetAttacksWithoutHit(player.AntiCheatTracker.GetAttacksWithoutHit() + 1); int offenseLimit; if (attack.Skill != 3121004) { //暴风箭雨 offenseLimit = 100; } else { offenseLimit = 300; } if (player.AntiCheatTracker.GetAttacksWithoutHit() > offenseLimit) { player.AntiCheatTracker .RegisterOffense(CheatingOffense.AttackWithoutGettingHit, player.AntiCheatTracker.GetAttacksWithoutHit().ToString()); } //没有受到撞击攻击 //if (player.hasEnergyCharge()) //{ // player.increaseEnergyCharge(attack.numAttacked); //} } }