private static void HandleRegionSkill(GameSession session, SkillCast skillCast) { foreach (SkillMotion skillMotion in skillCast.GetSkillMotions()) { foreach (SkillAttack skillAttack in skillMotion.SkillAttacks) { if (skillAttack.SkillConditions?.Count > 0) { foreach (SkillCondition skillCondition in skillAttack.SkillConditions) { SkillCast splashSkill = new(skillCondition.SkillId, skillCondition.SkillLevel, GuidGenerator.Long(), session.ServerTick, skillCast) { CasterObjectId = session.Player.FieldPlayer.ObjectId, SkillAttack = skillAttack, EffectCoords = skillCast.EffectCoords, SkillObjectId = skillCast.SkillObjectId }; if (!splashSkill.MetadataExists) { return; } if (!skillCondition.ImmediateActive) { if (splashSkill.IsRecoveryFromBuff()) { HandleRegionHeal(session, splashSkill); continue; } HandleRegionDamage(session, splashSkill); continue; } // go to another skill condition?? might cause infinite loop // HandleRegionSkill(session, splashSkill); } continue; } skillCast.SkillAttack = skillAttack; if (!skillCast.MetadataExists) { return; } if (skillCast.IsRecoveryFromBuff()) { HandleRegionHeal(session, skillCast); continue; } HandleRegionDamage(session, skillCast); } } }
private static void HandleRegionSkills(GameSession session, PacketReader packet) { long skillSn = packet.ReadLong(); byte mode = packet.ReadByte(); int unknown = packet.ReadInt(); int attackIndex = packet.ReadInt(); CoordF position = packet.Read <CoordF>(); CoordF rotation = packet.Read <CoordF>(); // What are these values used? Check client vs server? // TODO: Verify rest of skills to proc correctly. // TODO: Send status correctly when Region attacks are proc. SkillCast parentSkill = session.Player.FieldPlayer.SkillCast; if (parentSkill is null || parentSkill.SkillSn != skillSn) { return; } SkillAttack skillAttack = parentSkill.GetSkillMotions().FirstOrDefault()?.SkillAttacks.FirstOrDefault(); if (skillAttack is null) { return; } if (skillAttack.CubeMagicPathId == 0 && skillAttack.MagicPathId == 0) { return; } SkillCondition skillCondition = skillAttack.SkillConditions.FirstOrDefault(x => x.IsSplash); if (skillCondition is null) { return; } SkillCast skillCast = new(skillCondition.SkillId, skillCondition.SkillLevel, GuidGenerator.Long(), session.ServerTick, parentSkill) { CasterObjectId = session.Player.FieldPlayer.ObjectId, SkillAttack = skillAttack, Duration = skillCondition.FireCount * 1000, Interval = skillCondition.Interval }; RegionSkillHandler.HandleEffect(session, skillCast, attackIndex); } #endregion }