Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9d14ab5
Initial Sadhu skill's implementations
felipecastagnarodecarvalho Jul 27, 2024
0f1cfaa
[WIP] Sadhu skills
felipecastagnarodecarvalho Jul 28, 2024
8a0803a
Merge branch 'master' of https://github.com/NoCode-NoLife/melia into …
felipecastagnarodecarvalho Jul 28, 2024
cdf1740
Adding the first sadhu Skill - Prakriti
felipecastagnarodecarvalho Jul 29, 2024
01a2f3a
Polishing Prakriti
felipecastagnarodecarvalho Jul 29, 2024
bd6a41f
Adding Anila skill
felipecastagnarodecarvalho Jul 29, 2024
3c5e170
Adding Possession skill (sadhu) + skill base class inheritance
felipecastagnarodecarvalho Jul 29, 2024
80ff162
Adding Enira sadhu skill
felipecastagnarodecarvalho Jul 30, 2024
5aa0295
Working on the sadhu arts that creates clones
felipecastagnarodecarvalho Jul 30, 2024
020d514
Small Update (Sadhu)
felipecastagnarodecarvalho Jul 30, 2024
cef4651
Merge branch 'master' into sadhu_skills
felipecastagnarodecarvalho Jul 30, 2024
70535a7
[WIP] Sadhu skills tweek
felipecastagnarodecarvalho Jul 30, 2024
e2203f0
Messing up with the IA (for dummies)
felipecastagnarodecarvalho Jul 31, 2024
d3fba4d
Minor changes Sadhu
felipecastagnarodecarvalho Aug 12, 2024
60bc776
Minor update sadhu
felipecastagnarodecarvalho Aug 13, 2024
507317e
Merging master
felipecastagnarodecarvalho Aug 13, 2024
10cda3d
Updating sadhu dummy AI
felipecastagnarodecarvalho Aug 13, 2024
f2b09d5
Merging master
felipecastagnarodecarvalho Aug 15, 2024
2c6492c
Sadhu skills - Working on the hability skills
felipecastagnarodecarvalho Aug 15, 2024
9ede990
Adding last two Sadhu skills
felipecastagnarodecarvalho Aug 16, 2024
e6f87ac
Updating skill file names
felipecastagnarodecarvalho Aug 22, 2024
888b8d5
Merging master
felipecastagnarodecarvalho Sep 13, 2024
d55e4af
Merge branch 'master' into sadhu_skills
felipecastagnarodecarvalho Sep 17, 2024
73e8c55
[WIP
felipecastagnarodecarvalho Sep 17, 2024
1a49524
Resolving review conversations
felipecastagnarodecarvalho Sep 18, 2024
08bde3b
Merging Upstream Master
felipecastagnarodecarvalho Mar 6, 2025
a0075b3
[WIP] Fixing review issues
felipecastagnarodecarvalho Mar 7, 2025
86338ef
Fixing remaining review issues
felipecastagnarodecarvalho Mar 8, 2025
3c9ed92
Initial fixes for review
felipecastagnarodecarvalho Jun 21, 2025
579e41d
Merge branch 'master' of https://github.com/NoCode-NoLife/Melia into …
felipecastagnarodecarvalho Jun 21, 2025
9c4d791
Updating sadhu skills (2) - commiting before pulling from master
felipecastagnarodecarvalho Jul 14, 2025
adadead
Merge branch 'master' of https://github.com/NoCode-NoLife/Melia into …
felipecastagnarodecarvalho Jul 14, 2025
845a5f0
Ready for a new review - sadhu updates
felipecastagnarodecarvalho Jul 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Shared/Data/Database/PacketStrings.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Newtonsoft.Json.Linq;
using Yggdrasil.Data.JSON;

Expand All @@ -16,6 +17,17 @@ public class PacketStringData
/// </summary>
public class PacketStringDb : DatabaseJsonIndexed<string, PacketStringData>
{
/// <summary>
/// Tries to find a Packet string data for a given id.
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool TryFind(int id, out PacketStringData data)
{
data = this.Entries.Values.FirstOrDefault(a => a.Id == id);
return data != null;
}

/// <summary>
/// Reads given entry and adds it to the database.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Shared/Data/Database/SkillTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class SkillTreeDb : DatabaseJson<SkillTreeData>
/// level.
/// </summary>
/// <param name="jobId"></param>
/// <param name="circle"></param>
/// <param name="jobLevel"></param>
/// <returns></returns>
public SkillTreeData[] FindSkills(JobId jobId, int jobLevel)
{
Expand Down
1 change: 1 addition & 0 deletions src/Shared/Game/Const/HitType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ public enum HitType : short
KnockBack = 3,
KnockDown = 4,
Type18 = 18,
Type33 = 33,
}
}
3 changes: 3 additions & 0 deletions src/Shared/Network/NormalOp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public static class Zone
public const int PlayEffect = 0x16;
public const int PlayForceEffect = 0x17;
public const int UpdateSkillEffect = 0x1F;
public const int UpdateModelColor = 0x20;
public const int FadeOut = 0x38;
public const int BarrackSlotCount = 0x3C;
public const int AttackCancel = 0x41;
Expand Down Expand Up @@ -69,6 +70,8 @@ public static class Zone
public const int PlayTextEffect = 0xE3;
public const int Unknown_E4 = 0xE7;
public const int Unknown_EF = 0xF2;
public const int EnableUseSkillWhileOutOfBody = 0x10B;
public const int EndOutOfBodyBuff = 0x10C;
public const int ChannelTraffic = 0x12D;
public const int SetGreetingMessage = 0x136;
public const int Unk13E = 0x13E;
Expand Down
153 changes: 153 additions & 0 deletions src/ZoneServer/Buffs/Handlers/Clerics/Sadhu/OOBE_Anila_Buff.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
using System;
using Melia.Shared.Game.Const;
using Melia.Zone.Buffs.Base;
using Melia.Zone.Network;
using Melia.Zone.Skills.Combat;
using Melia.Zone.Skills;
using Melia.Zone.Skills.SplashAreas;
using Melia.Zone.World.Actors;
using Melia.Zone.World.Actors.Characters;
using Melia.Zone.World.Actors.Pads;
using Melia.Zone.World.Actors.Monsters;
using static Melia.Zone.Skills.SkillUseFunctions;
using Melia.Shared.World;

namespace Melia.Zone.Buffs.Handlers.Clerics.Sadhu
{
/// <summary>
/// Handler for the Out Of Body Experience (OOBE) Anila Buff
/// which makes the character go back to original position after a while
/// and leave an effect that damages enemies on hit by a wave effect.
/// </summary>
[BuffHandler(BuffId.OOBE_Anila_Buff)]
public class OOBE_Anila_Buff : Sadhu_BuffHandler_Base
{
/// <summary>
/// Starts buff, adding an event handler for
/// the death of the dummy character.
/// </summary>
/// <param name="buff"></param>
/// <param name="activationType"></param>
public override void OnActivate(Buff buff, ActivationType activationType)
{
var caster = buff.Caster;

AddPropertyModifier(buff, caster, PropertyName.MSPD_BM, (int)buff.NumArg1);

// Don't continue if the caster is not a Character
if (caster is not Character casterCharacter)
return;

var dummyCharacter = casterCharacter.Map.GetCharacter((int)buff.NumArg2);

if (dummyCharacter != null)
dummyCharacter.Died += this.OnDummyDied;
}

/// <summary>
/// Executes the buff handler's end behavior.
/// Does not actually end or remove the buff.
/// </summary>
/// <param name="buff"></param>
public override void OnEnd(Buff buff)
{
var caster = buff.Caster;

RemovePropertyModifier(buff, caster, PropertyName.MSPD_BM);

// Ignore if the caster is not a Character
if (caster is not Character casterCharacter)
return;

// It spawns an clone character in form of a spirit that is controlled by AI.
// So we need to identify the Source character that will be used on the buff ending.
var characterSkillHandling = casterCharacter is DummyCharacter dummyCharacter && dummyCharacter.Owner.IsAbilityActive(AbilityId.Sadhu35)
? dummyCharacter.Owner
: caster;

// Don't continue if the caster doesn't have the skill.
if (!characterSkillHandling.TryGetSkill(SkillId.Sadhu_Anila, out var skill))
return;

characterSkillHandling.SetAttackState(true);

// Creates the Pad that will handles the buff ending effect that damages enemies that touches it.
var pad = new Pad(PadName.Sadhu_Anila_Effect_Pad, characterSkillHandling, skill, new Square(caster.Position, caster.Direction, 50, 65));

pad.Position = new Position(pad.Trigger.Area.Center.X, caster.Position.Y, pad.Trigger.Area.Center.Y);
pad.Trigger.MaxActorCount = 7;
pad.Trigger.LifeTime = TimeSpan.FromSeconds(10);
pad.Trigger.Subscribe(TriggerType.Enter, this.OnCollisionEnter);

caster.Map.AddPad(pad);

// [Arts] Spirit Expert: Wandering Soul - AI Controlled Spirit
if (casterCharacter is DummyCharacter dummyCharacter2 && dummyCharacter2.Owner.IsAbilityActive(AbilityId.Sadhu35))
{
Send.ZC_SKILL_READY(dummyCharacter2.Owner, caster, skill, caster.Position, caster.Position);
Send.ZC_NORMAL.UpdateSkillEffect(dummyCharacter2.Owner, caster.Handle, caster.Position, caster.Direction, Position.Zero);
Send.ZC_SKILL_MELEE_GROUND(dummyCharacter2.Owner, caster, skill, caster.Position, ForceId.GetNew(), null);
}
else // Spirit was controlled by the player
{
skill.IncreaseOverheat();
}

// [Arts] Spirit Expert: Wandering Soul: AI Controlled Spirit
// Removes the clone character (spirit) from the map.
if (casterCharacter is DummyCharacter dummyCharacter3 && dummyCharacter3.Owner.IsAbilityActive(AbilityId.Sadhu35))
{
this.RemoveSpritCloneCharacter(dummyCharacter3);
return;
}

Send.ZC_NORMAL.EndOutOfBodyBuff(casterCharacter, BuffId.OOBE_Anila_Buff);
Send.ZC_NORMAL.UpdateModelColor(casterCharacter, 255, 255, 255, 255, 0.01f);
Send.ZC_PLAY_SOUND(casterCharacter, "skl_eff_yuchae_end_2");

this.ReturnToBody(casterCharacter, (int)buff.NumArg2);
}

/// <summary>
/// Called when an actor enters the skill's pad area.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void OnCollisionEnter(object sender, PadTriggerActorArgs args)
{
var pad = args.Trigger;
var creator = args.Creator;
var target = args.Initiator;

if (pad.Trigger.AtCapacity)
return;

if (!creator.CanAttack(target))
return;

this.Attack(pad.Skill, creator, target);
}

/// <summary>
/// Pad's attack handler.
/// </summary>
/// <param name="skill"></param>
/// <param name="caster"></param>
/// <param name="target"></param>
private void Attack(Skill skill, ICombatEntity caster, ICombatEntity target)
{
var dealsDamageCharacter = caster is DummyCharacter dummyCharacter && dummyCharacter.Owner.IsAbilityActive(AbilityId.Sadhu35)
? dummyCharacter.Owner
: caster;

var modifier = SkillModifier.MultiHit(3);
var skillHitResult = SCR_SkillHit(dealsDamageCharacter, target, skill, modifier);

target.TakeDamage(skillHitResult.Damage, dealsDamageCharacter);

var hit = new HitInfo(dealsDamageCharacter, target, skill, skillHitResult, TimeSpan.FromMilliseconds(200));

Send.ZC_HIT_INFO(dealsDamageCharacter, target, hit);
}
}
}
Loading