Skip to content

Commit

Permalink
Feat: Allow ProtectEffect from NPC (#488 on DOL) + Translations for I…
Browse files Browse the repository at this point in the history
…tem Bonus conditions in DetailDisplayHandler

- see Dawn-of-Light/DOLSharp#488
  • Loading branch information
DOL-Avalonia committed Nov 22, 2024
1 parent cc1ba5e commit 69d1e2d
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 86 deletions.
20 changes: 10 additions & 10 deletions GameServer/ai/brain/ControlledNpcBrain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class ControlledNpcBrain : StandardMobBrain, IControlledBrain
/// <summary>
/// Defines a logger for this class.
/// </summary>
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod()!.DeclaringType);

// note that a minimum distance is inforced in GameNPC
public static readonly short MIN_OWNER_FOLLOW_DIST = 50;
Expand Down Expand Up @@ -172,7 +172,7 @@ public virtual void Attack(GameObject target)
m_orderAttackTarget = target as GameLiving;
previousIsStealthed = false;
if (target is GamePlayer)
previousIsStealthed = (target as GamePlayer).IsStealthed;
previousIsStealthed = (target as GamePlayer)!.IsStealthed;
AttackMostWanted();
}

Expand Down Expand Up @@ -330,7 +330,7 @@ public override void Think()

//See if the pet is too far away, if so release it!
if (Owner is GamePlayer && IsMainPet && !GameMath.IsWithinRadius(Body, Owner, MAX_OWNER_FOLLOW_DIST))
(Owner as GamePlayer).CommandNpcRelease();
(Owner as GamePlayer)!.CommandNpcRelease();

// if pet is in agressive mode then check aggressive spells and attacks first
if (!Body.AttackState && AggressionState == eAggressionState.Aggressive)
Expand All @@ -350,15 +350,15 @@ public override void Think()
if (Body.TargetObject != null && Body.TargetObject is GamePlayer)
{
GamePlayer player = Body.TargetObject as GamePlayer;
if (Body.IsAttacking && player.IsStealthed && !previousIsStealthed)
if (Body.IsAttacking && player!.IsStealthed && !previousIsStealthed)
{
Body.StopAttack();
Body.StopCurrentSpellcast();
RemoveFromAggroList(player);
Body.TargetObject = null;
FollowOwner();
}
previousIsStealthed = player.IsStealthed;
previousIsStealthed = player!.IsStealthed;
}

// Always check offensive spells, or pets in melee will keep blindly melee attacking,
Expand Down Expand Up @@ -397,7 +397,7 @@ public override void CheckAbilities()
}
case Abilities.Protect:
{
new ProtectEffect().Start(Body.GetLivingOwner());
new ProtectEffect().Start(Body, Body.GetLivingOwner());
break;
}
case Abilities.ChargeAbility:
Expand Down Expand Up @@ -882,7 +882,7 @@ public override void AddToAggroList(GameLiving living, int aggroamount, bool che
base.AddToAggroList(living, aggroamount, checkLOS);
else
{
(npc_owner.Brain as StandardMobBrain).AddToAggroList(living, aggroamount);
(npc_owner.Brain as StandardMobBrain)!.AddToAggroList(living, aggroamount);
}
}

Expand Down Expand Up @@ -1001,7 +1001,7 @@ owner_npc.TargetObject is GameLiving &&
{
foreach (IGameEffect effect in Body.EffectList)
{
if (effect is GameSpellEffect && (effect as GameSpellEffect).SpellHandler is SpeedEnhancementSpellHandler)
if (effect is GameSpellEffect && (effect as GameSpellEffect)!.SpellHandler is SpeedEnhancementSpellHandler)
{
effects.Add(effect as GameSpellEffect);
}
Expand All @@ -1012,7 +1012,7 @@ owner_npc.TargetObject is GameLiving &&
{
foreach (IGameEffect effect in Owner.EffectList)
{
if (effect is GameSpellEffect && (effect as GameSpellEffect).SpellHandler is SpeedEnhancementSpellHandler)
if (effect is GameSpellEffect && (effect as GameSpellEffect)!.SpellHandler is SpeedEnhancementSpellHandler)
{
effects.Add(effect as GameSpellEffect);
}
Expand Down Expand Up @@ -1066,7 +1066,7 @@ protected virtual void OnOwnerAttacked(DOLEvent e, object sender, EventArgs argu

AttackedByEnemyEventArgs args = arguments as AttackedByEnemyEventArgs;
if (args == null) return;
if (args.AttackData.Target is GamePlayer && (args.AttackData.Target as GamePlayer).ControlledBrain != this)
if (args.AttackData.Target is GamePlayer && (args.AttackData.Target as GamePlayer)!.ControlledBrain != this)
return;
// react only on these attack results
switch (args.AttackData.AttackResult)
Expand Down
6 changes: 3 additions & 3 deletions GameServer/ai/brain/StandardMobBrain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -625,9 +625,9 @@ public virtual void AddToAggroList(GameLiving living, int aggroamount, bool Chec
if (protectAmount > 0)
{
aggroamount -= protectAmount;
protect.ProtectSource.Out.SendMessage(LanguageMgr.GetTranslation(protect.ProtectSource.Client.Account.Language, "AI.Brain.StandardMobBrain.YouProtDist", player.GetName(0, false),
Body.GetName(0, false, protect.ProtectSource.Client.Account.Language, Body)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
//player.Out.SendMessage("You are protected by " + protect.ProtectSource.GetName(0, false) + " from " + Body.GetName(0, false) + ".", eChatType.CT_System, eChatLoc.CL_SystemWindow);
if (protect.ProtectSource is GamePlayer playerSource)
playerSource.Out.SendMessage(LanguageMgr.GetTranslation(playerSource.Client.Account.Language, "AI.Brain.StandardMobBrain.YouProtDist", player.GetName(0, false),
Body.GetName(0, false, playerSource.Client.Account.Language, Body)), eChatType.CT_System, eChatLoc.CL_SystemWindow);

lock ((m_aggroTable as ICollection).SyncRoot)
{
Expand Down
121 changes: 57 additions & 64 deletions GameServer/effects/ProtectEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,15 @@ namespace DOL.GS.Effects
public class ProtectEffect : StaticEffect, IGameEffect
{
/// <summary>
/// The player protecting the target
/// The individual protecting the target
/// </summary>
GamePlayer m_protectSource;
public GameLiving ProtectSource { get; private set; }

/// <summary>
/// Gets the player protecting the target
/// The individual being protected
/// </summary>
public GamePlayer ProtectSource
{
get { return m_protectSource; }
set { m_protectSource = value; }
}

/// <summary>
/// Reference to gameplayer that is protecting this player
/// </summary>
GamePlayer m_protectTarget = null;

/// <summary>
/// Gets the protected player
/// </summary>
public GamePlayer ProtectTarget
{
get { return m_protectTarget; }
set { m_protectTarget = value; }
}

private Group m_playerGroup;
public GameLiving ProtectTarget { get; private set; }
private Group m_playerGroup = null;

/// <summary>
/// Creates a new protect effect
Expand All @@ -71,34 +52,37 @@ public ProtectEffect()
/// <summary>
/// Start the guarding on player
/// </summary>
public void Start(GamePlayer protectSource, GamePlayer protectTarget)
public void Start(GameLiving source, GameLiving target)
{
if (protectSource == null || protectTarget == null)
if (source == null || target == null)
return;

m_owner = protectSource;
m_playerGroup = protectSource.Group;
m_owner = source;
ProtectSource = source;
ProtectTarget = target;

if (m_playerGroup != protectTarget.Group)
return;

m_protectSource = protectSource;
m_protectTarget = protectTarget;

GameEventMgr.AddHandler(m_playerGroup, GroupEvent.MemberDisbanded, new DOLEventHandler(GroupDisbandCallback));
if (target.Group != null && target.Group == source.Group)
{
m_playerGroup = source.Group;
GameEventMgr.AddHandler(m_playerGroup, GroupEvent.MemberDisbanded, new DOLEventHandler(GroupDisbandCallback));
}

m_protectSource.EffectList.Add(this);
m_protectTarget.EffectList.Add(this);
source.EffectList.Add(this);
target.EffectList.Add(this);

if (!protectSource.IsWithinRadius(protectTarget, ProtectAbilityHandler.PROTECT_DISTANCE))
if (!source.IsWithinRadius(target, ProtectAbilityHandler.PROTECT_DISTANCE))
{
protectSource.Out.SendMessage(LanguageMgr.GetTranslation(protectSource.Client, "Effects.ProtectEffect.YouProtectingYBut", protectTarget.GetName(0, false)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
protectTarget.Out.SendMessage(LanguageMgr.GetTranslation(protectTarget.Client, "Effects.ProtectEffect.XProtectingYouBut", protectSource.GetName(0, true)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
if (source is GamePlayer playerSource)
playerSource.Out.SendMessage(LanguageMgr.GetTranslation(playerSource.Client, "Effects.ProtectEffect.YouProtectingYBut", target.GetName(0, false)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
if (target is GamePlayer playerTarget)
playerTarget.Out.SendMessage(LanguageMgr.GetTranslation(playerTarget.Client, "Effects.ProtectEffect.XProtectingYouBut", source.GetName(0, true)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
}
else
{
protectSource.Out.SendMessage(LanguageMgr.GetTranslation(protectSource.Client, "Effects.ProtectEffect.YouProtectingY", protectTarget.GetName(0, false)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
protectTarget.Out.SendMessage(LanguageMgr.GetTranslation(protectTarget.Client, "Effects.ProtectEffect.XProtectingYou", protectSource.GetName(0, true)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
if (source is GamePlayer playerSource)
playerSource.Out.SendMessage(LanguageMgr.GetTranslation(playerSource.Client, "Effects.ProtectEffect.YouProtectingY", target.GetName(0, false)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
if (target is GamePlayer playerTarget)
playerTarget.Out.SendMessage(LanguageMgr.GetTranslation(playerTarget.Client, "Effects.ProtectEffect.XProtectingYou", source.GetName(0, true)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
}
}

Expand All @@ -110,41 +94,42 @@ public void Start(GamePlayer protectSource, GamePlayer protectTarget)
/// <param name="args"></param>
protected void GroupDisbandCallback(DOLEvent e, object sender, EventArgs args)
{
MemberDisbandedEventArgs eArgs = args as MemberDisbandedEventArgs;
if (eArgs == null) return;
if (eArgs.Member == ProtectTarget || eArgs.Member == ProtectSource)
{
if (args is MemberDisbandedEventArgs eArgs && (eArgs.Member == ProtectTarget || eArgs.Member == ProtectSource))
Cancel(false);
}
}

/// <summary>
/// Called when effect must be canceled
/// </summary>
public override void Cancel(bool playerCancel, bool force = false)
{
GameEventMgr.RemoveHandler(m_playerGroup, GroupEvent.MemberDisbanded, new DOLEventHandler(GroupDisbandCallback));
if (m_playerGroup != null)
GameEventMgr.RemoveHandler(m_playerGroup, GroupEvent.MemberDisbanded, new DOLEventHandler(GroupDisbandCallback));
// intercept handling is done by the active part
m_protectSource.EffectList.Remove(this);
m_protectTarget.EffectList.Remove(this);

m_protectSource.Out.SendMessage(LanguageMgr.GetTranslation(m_protectSource.Client, "Effects.ProtectEffect.YouNoProtectY", m_protectTarget.GetName(0, false)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
m_protectTarget.Out.SendMessage(LanguageMgr.GetTranslation(m_protectTarget.Client, "Effects.ProtectEffect.XNoProtectYou", m_protectSource.GetName(0, true)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
ProtectSource.EffectList.Remove(this);
ProtectTarget.EffectList.Remove(this);

m_playerGroup = null;
if (ProtectSource is GamePlayer playerSource)
playerSource.Out.SendMessage(LanguageMgr.GetTranslation(playerSource.Client, "Effects.ProtectEffect.YouNoProtectY", ProtectTarget.GetName(0, false)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
if (ProtectTarget is GamePlayer playerTarget)
playerTarget.Out.SendMessage(LanguageMgr.GetTranslation(playerTarget.Client, "Effects.ProtectEffect.XNoProtectYou", ProtectSource.GetName(0, true)), eChatType.CT_System, eChatLoc.CL_SystemWindow);
}

/// <summary>
/// Name of the effect
/// </summary>
public override string Name
{

get
{
if (m_protectSource != null && m_protectTarget != null)
return LanguageMgr.GetTranslation(((GamePlayer)Owner).Client, "Effects.ProtectEffect.ProtectByName", m_protectTarget.GetName(0, false), m_protectSource.GetName(0, false));
return LanguageMgr.GetTranslation(((GamePlayer)Owner).Client, "Effects.ProtectEffect.Name");
string language;
if (ProtectTarget is GamePlayer playerTarget)
language = playerTarget.Client.Account.Language;
else if (ProtectSource is GamePlayer playerSource)
language = playerSource.Client.Account.Language;
else
language = LanguageMgr.DefaultLanguage;
return LanguageMgr.GetTranslation(language, "Effects.ProtectEffect.ProtectByName", ProtectTarget.GetName(0, false), ProtectSource.GetName(0, false));
}
}

Expand All @@ -171,12 +156,20 @@ public override IList<string> DelveInfo
{
get
{
var delveInfoList = new List<string>(4);
delveInfoList.Add(LanguageMgr.GetTranslation(((GamePlayer)Owner).Client, "Effects.ProtectEffect.InfoEffect"));
delveInfoList.Add(" ");
delveInfoList.Add(LanguageMgr.GetTranslation(((GamePlayer)Owner).Client, "Effects.ProtectEffect.XProtectingY", ProtectSource.GetName(0, true), ProtectTarget.GetName(0, false)));

return delveInfoList;
string language;
if (ProtectTarget is GamePlayer playerTarget)
language = playerTarget.Client.Account.Language;
else if (ProtectSource is GamePlayer playerSource)
language = playerSource.Client.Account.Language;
else
language = LanguageMgr.DefaultLanguage;

return new List<string>(4)
{
LanguageMgr.GetTranslation(language, "Effects.ProtectEffect.InfoEffect"),
" ",
LanguageMgr.GetTranslation(language, "Effects.ProtectEffect.XProtectingY", ProtectSource.GetName(0, true), ProtectTarget.GetName(0, false))
};
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion GameServer/language/EN/Packets.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,10 @@ DetailDisplayHandler.WriteMagicalBonuses.StrikeArmor: - Spell has a chance of ca
DetailDisplayHandler.WriteMagicalBonuses.StrikeEnemy: - Spell has a chance of casting when this weapon strikes an enemy.
DetailDisplayHandler.WriteMagicalBonuses.UsedItem: - Spell has a chance of casting when this item is used.
DetailDisplayHandler.WriteMagicalBonuses.UseItem1: Can use item every: {0}
DetailDisplayHandler.WriteMagicalBonuses.UseItem2: Can use item every: 3:00 min.
DetailDisplayHandler.WriteMagicalBonuses.UseItem2: Can use item every: {0}:{1} min.
DetailDisplayHandler.WriteMagicalBonuses.UseItem3: Can use again in: {0}.
DetailDisplayHandler.WriteBonusConditions.Title: Bonus Requirements:
DetailDisplayHandler.WriteBonusConditions.Renaissance: Must be "Reborn"
DetailDisplayHandler.WritePoisonInfo.Charges: - {0} Charges
DetailDisplayHandler.WritePoisonInfo.Level: - {0} Level
DetailDisplayHandler.WritePoisonInfo.LevelRequired: Level Requirement:
Expand Down
8 changes: 5 additions & 3 deletions GameServer/language/FR/Packets.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,11 @@ DetailDisplayHandler.WriteMagicalBonuses.MaxCharges: - {0} Max
DetailDisplayHandler.WriteMagicalBonuses.StrikeArmor: - Le sort a une chance d'être lancé quand un ennemi touche cette armure.
DetailDisplayHandler.WriteMagicalBonuses.StrikeEnemy: - Le sort a une chance d'être lancé quand cette arme touche un ennemi.
DetailDisplayHandler.WriteMagicalBonuses.UsedItem: - Le sort a une chance d'être lancé quand l'objet est utilisé.
DetailDisplayHandler.WriteMagicalBonuses.UseItem.second: Peut être utilisé toutes les : {0} secondes.
DetailDisplayHandler.WriteMagicalBonuses.UseItem.minute: Peut être utilisé toutes les : {0}:{1} min.
DetailDisplayHandler.WriteMagicalBonuses.UseItem.in: Peut être réutilisé dans : {0}.
DetailDisplayHandler.WriteMagicalBonuses.UseItem1: Peut être utilisé toutes les : {0} secondes.
DetailDisplayHandler.WriteMagicalBonuses.UseItem2: Peut être utilisé toutes les : {0}:{1} min.
DetailDisplayHandler.WriteMagicalBonuses.UseItem3: Peut être réutilisé dans : {0}.
DetailDisplayHandler.WriteBonusConditions.Title: Conditions de Bonus:
DetailDisplayHandler.WriteBonusConditions.Renaissance: Doit être "Renaissance"
DetailDisplayHandler.WritePoisonInfo.Charges: - {0} Charges
DetailDisplayHandler.WritePoisonInfo.Level: - {0} Niveau
DetailDisplayHandler.WritePoisonInfo.LevelRequired: Niveau requis :
Expand Down
4 changes: 2 additions & 2 deletions GameServer/language/FR/spells/SpellHandler.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ SpellHandler.YouMiss: Vous ratez votre cible !
SpellHandler.TargetMissed: {0} a raté sa cible !
SpellHandler.EngageCannotBeUsed: {0} a été attaqué récemment et vous ne pouvez pas engager.
SpellHandler.NotEnoughEndurance: Vous vous concentrez pour bloquer le coup !
SpellHandler.PvPOnly: Ne peut seulement être utilisé contre des joueurs ou des familiers contrôlés par des joueurs.
SpellHandler.PvPOnly: Utilisable uniquement contre des joueurs ou des familiers contrôlés par des joueurs.

SpellHandler.CheckLOSYouToPet.NotInView: Votre familier n'est pas en vue.
SpellHandler.CheckLOSPlayerToTarget.LoSInterrupt: Interruption de la ligne de vue dans CheckLOSPlayerToTarget
Expand Down Expand Up @@ -194,7 +194,7 @@ SpellHandler.PowerDrain.NoAbsorb: Vous ne pouvez pas absorber davantage de Mana
SpellHandler.PowerDrain.SpellHit: {0} vous siphonne {1} Mana.
SpellHandler.PowerDrain.StealSuccess: Vous siphonnez {1} Mana de {0}!
SpellHandler.PowerDrain.StealOverflow: Vous siphonnez {1} Mana de {0}! ({2} surplus)
SpellHandler.PowerDrain.Description: Verouille votre cible et vous-même en place et lui siphonne {0}% base Mana toutes les {1}s pour {2} secondes. Pendant la duration du grappin, ni vous ni votre cible ne pouvez être touché par des attaques en mélée.
SpellHandler.PowerDrain.Description: Verouille sur place votre cible et vous-même, aspirant {0}% de sa Mana de base toutes les {1}s pour {2} secondes. Pendant la durée de cet effet, ni vous ni votre cible ne pouvez subir de dégâts de mêlée.

SpellHandler.PrimerSpell.EffectExpired: Votre effet de sort de modification a expiré.
SpellHandler.PrimerSpell.MovementBreaksEffect: Vous bougez et rompez votre sort de modification.
Expand Down
Loading

0 comments on commit 69d1e2d

Please sign in to comment.