Charm Spell - All Type - Fails on Non Body Type NPCs

A place to submit .patch fixes for the DOL SVN

Moderator: Developer Team

Charm Spell - All Type - Fails on Non Body Type NPCs

Postby Crazys » Sat Oct 04, 2014 11:24 pm

On NPCS with no type selected AKA none still charm fails.
All should charm all not just npcs with a set type body.


Pulls the ((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.None failure check into the section that checks and bellow the can charm type is all check.
CharmSpellHandler.cs

Origional
Code: Select all
            /// <summary>
        /// Apply effect on target or do spell action if non duration spell
        /// </summary>
        /// <param name="target">target that gets the effect</param>
        /// <param name="effectiveness">factor from 0..1 (0%-100%)</param>
        public override void ApplyEffectOnTarget(GameLiving target, double effectiveness)
        {
           
           // This prevent most of type casting errors
           if(target is GameNPC == false) {
              MessageToCaster("This spell does not charm this type of monster!", eChatType.CT_SpellResisted);
                return;
           }
           
            // check only if brain wasn't changed at least once
            if (m_controlledBrain == null)
            {
                // Target is already controlled
              if(((GameNPC)target).Brain != null && ((GameNPC)target).Brain is IControlledBrain && (((IControlledBrain)((GameNPC)target).Brain).Owner as GamePlayer) != Caster)
               {
                   // TODO: proper message
                   MessageToCaster("Your target is not valid.", eChatType.CT_SpellResisted);
                   return;
               }
             
               // Already have a pet...
              if(Caster.ControlledBrain != null)
               {
                   MessageToCaster("You already have a charmed creature, release it first!", eChatType.CT_SpellResisted);
                   return;
               }
             
               // Body Type None (0) is used to make mobs un-charmable , Realm Guards or NPC cannot be charmed.
               if (target.Realm != 0 || ((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.None)
                {
                    MessageToCaster("This spell does not charm this type of monster!", eChatType.CT_SpellResisted);
                    return;
                }
               
               // If server properties prevent Named charm.
               if(ServerProperties.Properties.SPELL_CHARM_NAMED_CHECK != 0 && !target.Name[0].ToString().ToLower().Equals(target.Name[0].ToString()))
                {
                    MessageToCaster("This spell does not charm this type of monster!", eChatType.CT_SpellResisted);
                    return;
                }
                                  
               
                // Check if Body type applies
                if (m_spell.AmnesiaChance != (ushort)eCharmType.All)
                {
                   
                   bool charmable = false;
                   
                   // gets true only for charm-able mobs for this spell type
                   switch((eCharmType)m_spell.AmnesiaChance) {
                       
                      case eCharmType.HumanoidAnimalInsectMagicalUndead :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Undead)
                            charmable = true;
                         
                      goto case eCharmType.HumanoidAnimalInsectMagical;
                         
                      case eCharmType.HumanoidAnimalInsectMagical :
                          if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Magical)
                            charmable = true;
                          if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Plant)
                            charmable = true;
                          if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Elemental)
                            charmable = true;
                          
                        goto case eCharmType.HumanoidAnimalInsect;
                           
                        case eCharmType.HumanoidAnimalInsect :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Insect)
                            charmable = true;
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Reptile)
                            charmable = true;
                         
                      goto case eCharmType.HumanoidAnimal;

                       case eCharmType.HumanoidAnimal :
                           if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Animal)
                            charmable = true;
                           
                        goto case eCharmType.Humanoid;
                       
                      case eCharmType.Humanoid :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Humanoid)
                            charmable = true;
                         
                      break;
                      
                      case eCharmType.Animal :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Animal)
                            charmable = true;
                         
                      break;
                      
                      case eCharmType.Insect :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Insect)
                            charmable = true;
                         
                      break;
                      
                      case eCharmType.Reptile :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Reptile)
                            charmable = true;
                         
                      break;
                   }
                   
                   // The NPC type doesn't match spell charm types.
                   if(!charmable)
                   {
                      
                        MessageToCaster("This spell does not charm this type of monster!", eChatType.CT_SpellResisted);
                        return;
                   }

                }
               
            }
         
            // Spell.Value == Max Level this spell can charm, Spell.Damage == Max percent of the caster level this spell can charm
            if (target.Level > Spell.Value || target.Level > Caster.Level * Spell.Damage / 100)
            {
                MessageToCaster(target.GetName(0, true) + " is too strong for you to charm!", eChatType.CT_SpellResisted);
                return;
            }

            if (Caster is GamePlayer)
            {
               // base resists for all charm spells
                int resistChance = 100 - (85 + ((Caster.Level - target.Level) / 2));

                if (this.Spell.Pulse != 0) // not permanent
                {
                   
                    /*
                     * The Minstrel/Mentalist has an almost certain chance to charm/retain control of
                     * a creature his level or lower, although there is a small random chance that it
                     * could fail. The higher the level of the charmed creature compared to the
                     * Minstrel/Mentalist, the greater the chance the monster has of breaking the charm.
                     * Please note that your specialization level in the magic skill that contains the
                     * charm spell will modify your base chance of charming and retaining control.
                     * The higher your spec level, the greater your chance of controlling.
                     */
                   
                    int diffLevel = (int)(Caster.Level / 1.5 + Caster.GetModifiedSpecLevel(m_spellLine.Spec) / 3) - target.Level;
                   
                    if (diffLevel >= 0)
                    {
                       
                        resistChance = 10 - diffLevel * 3;
                        resistChance = Math.Max(resistChance, 1);
                    }
                    else
                    {
                       
                        resistChance = 10 + diffLevel * diffLevel * 3;
                        resistChance = Math.Min(resistChance, 99);
                    }

                }

                if (Util.Chance(resistChance))
                {
                   
                    MessageToCaster(target.GetName(0, true) + " resists the charm!", eChatType.CT_SpellResisted);
                    return;
                }
            }

            base.ApplyEffectOnTarget(target, effectiveness);
        }


New
Code: Select all
        /// <summary>
        /// Apply effect on target or do spell action if non duration spell
        /// </summary>
        /// <param name="target">target that gets the effect</param>
        /// <param name="effectiveness">factor from 0..1 (0%-100%)</param>
        public override void ApplyEffectOnTarget(GameLiving target, double effectiveness)
        {
           
           // This prevent most of type casting errors
           if(target is GameNPC == false) {
              MessageToCaster("This spell does not charm this type of monster!", eChatType.CT_SpellResisted);
                return;
           }
           
            // check only if brain wasn't changed at least once
            if (m_controlledBrain == null)
            {
                // Target is already controlled
              if(((GameNPC)target).Brain != null && ((GameNPC)target).Brain is IControlledBrain && (((IControlledBrain)((GameNPC)target).Brain).Owner as GamePlayer) != Caster)
               {
                   // TODO: proper message
                   MessageToCaster("Your target is not valid.", eChatType.CT_SpellResisted);
                   return;
               }
             
               // Already have a pet...
              if(Caster.ControlledBrain != null)
               {
                   MessageToCaster("You already have a charmed creature, release it first!", eChatType.CT_SpellResisted);
                   return;
               }
             
               // Body Type None (0) is used to make mobs un-charmable , Realm Guards or NPC cannot be charmed.
                if (target.Realm != 0)
                {
                    MessageToCaster("This spell does not charm this type of monster!", eChatType.CT_SpellResisted);
                    return;
                }
               
               // If server properties prevent Named charm.
               if(ServerProperties.Properties.SPELL_CHARM_NAMED_CHECK != 0 && !target.Name[0].ToString().ToLower().Equals(target.Name[0].ToString()))
                {
                    MessageToCaster("This spell does not charm this type of monster!", eChatType.CT_SpellResisted);
                    return;
                }
                                  
               
                // Check if Body type applies
                if (m_spell.AmnesiaChance != (ushort)eCharmType.All)
                {
                   if (((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.None)
                   {
                    MessageToCaster("This spell does not charm this type of monster!", eChatType.CT_SpellResisted);
                    return;
                    }
                   bool charmable = false;
                      
                   // gets true only for charm-able mobs for this spell type
                   switch((eCharmType)m_spell.AmnesiaChance) {
                       
                      case eCharmType.HumanoidAnimalInsectMagicalUndead :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Undead)
                            charmable = true;
                         
                      goto case eCharmType.HumanoidAnimalInsectMagical;
                         
                      case eCharmType.HumanoidAnimalInsectMagical :
                          if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Magical)
                            charmable = true;
                          if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Plant)
                            charmable = true;
                          if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Elemental)
                            charmable = true;
                          
                        goto case eCharmType.HumanoidAnimalInsect;
                           
                        case eCharmType.HumanoidAnimalInsect :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Insect)
                            charmable = true;
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Reptile)
                            charmable = true;
                         
                      goto case eCharmType.HumanoidAnimal;

                       case eCharmType.HumanoidAnimal :
                           if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Animal)
                            charmable = true;
                           
                        goto case eCharmType.Humanoid;
                       
                      case eCharmType.Humanoid :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Humanoid)
                            charmable = true;
                         
                      break;
                      
                      case eCharmType.Animal :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Animal)
                            charmable = true;
                         
                      break;
                      
                      case eCharmType.Insect :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Insect)
                            charmable = true;
                         
                      break;
                      
                      case eCharmType.Reptile :
                         if(((GameNPC)target).BodyType == (ushort)NpcTemplateMgr.eBodyType.Reptile)
                            charmable = true;
                         
                      break;
                   }
                   
                   // The NPC type doesn't match spell charm types.
                   if(!charmable)
                   {
                      
                        MessageToCaster("This spell does not charm this type of monster!", eChatType.CT_SpellResisted);
                        return;
                   }

                }
               
            }
         
            // Spell.Value == Max Level this spell can charm, Spell.Damage == Max percent of the caster level this spell can charm
            if (target.Level > Spell.Value || target.Level > Caster.Level * Spell.Damage / 100)
            {
                MessageToCaster(target.GetName(0, true) + " is too strong for you to charm!", eChatType.CT_SpellResisted);
                return;
            }

            if (Caster is GamePlayer)
            {
               // base resists for all charm spells
                int resistChance = 100 - (85 + ((Caster.Level - target.Level) / 2));

                if (this.Spell.Pulse != 0) // not permanent
                {
                   
                    /*
                     * The Minstrel/Mentalist has an almost certain chance to charm/retain control of
                     * a creature his level or lower, although there is a small random chance that it
                     * could fail. The higher the level of the charmed creature compared to the
                     * Minstrel/Mentalist, the greater the chance the monster has of breaking the charm.
                     * Please note that your specialization level in the magic skill that contains the
                     * charm spell will modify your base chance of charming and retaining control.
                     * The higher your spec level, the greater your chance of controlling.
                     */
                   
                    int diffLevel = (int)(Caster.Level / 1.5 + Caster.GetModifiedSpecLevel(m_spellLine.Spec) / 3) - target.Level;
                   
                    if (diffLevel >= 0)
                    {
                       
                        resistChance = 10 - diffLevel * 3;
                        resistChance = Math.Max(resistChance, 1);
                    }
                    else
                    {
                       
                        resistChance = 10 + diffLevel * diffLevel * 3;
                        resistChance = Math.Min(resistChance, 99);
                    }

                }

                if (Util.Chance(resistChance))
                {
                   
                    MessageToCaster(target.GetName(0, true) + " resists the charm!", eChatType.CT_SpellResisted);
                    return;
                }
            }

            base.ApplyEffectOnTarget(target, effectiveness);
        }
Attachments
CharmSpellHandler.patch
(12.48 KiB) Downloaded 9 times
Crazys
Contributor
 
Posts: 346
Joined: Tue Nov 07, 2006 10:18 pm

Re: Charm Spell - All Type - Fails on Non Body Type NPCs

Postby Leodagan » Sun Oct 05, 2014 6:40 am

As the comment says in code : this is working as intended.

The Body Type None is here for protecting Special Mobs, or Quest Mob or anything that an Admin don't want to be charmed, by just removing it's body type (which is a value never used elsewhere than charm check !!)

If you want to change a common behavior you have to throw a "Switch" in there ;)

take example on how "SPELL_CHARM_NAMED_CHECK" is working, create a new property like "SPELL_CHARM_BODYTYPENONE_CHECK" with default value being true (to keep previous behavior by default) and use it to decide wether you use new or old behavior :)

The check you moved inside the "Type Switch" code part is useless, the type switch will never get true for a specific typed charm spell on a bodyType None Check !

...And you duplicated some code found in the same method, making a copy of code should always trigger alarm in your head "what am I doing wrong", writing code is mostly finding one solution to multiple problems, if you write code that use multiple solutions for one problem you have to think of where you messed up :D
User avatar
Leodagan
Developer
 
Posts: 1350
Joined: Tue May 01, 2012 9:30 am
Location: Lyon

Re: Charm Spell - All Type - Fails on Non Body Type NPCs

Postby Crazys » Sun Oct 05, 2014 7:17 am

I disagree with the formatting as this is completely against all old dbs. You wpuld have to put a body on npcs in the game!!! Would it notmake more sense to have noncharmable as a flag? On the game npc that way they can still have a body?
Crazys
Contributor
 
Posts: 346
Joined: Tue Nov 07, 2006 10:18 pm

Re: Charm Spell - All Type - Fails on Non Body Type NPCs

Postby Leodagan » Sun Oct 05, 2014 9:05 am

Why would old DB need a bodyType in game ?

I checked all code BodyType is not used anywhere else than charm spell handler, most Quest script hardcoded NPC are setting the BodyType to 0 triggering the charm "protection"...

BodyType isn't sent to client so it's not needed for any Packet Handling, are you sure you aren't mistaking BodyType with "Race", Race is a GameNPC field that allow to set the NPC Type with templated resists (like undead weak to spirit, or animals weak to fire strong to cold...)

The BodyType field of a GameNPC have no other purpose than charm check, why would you want an other bool field only targeted at charm check ? If you want to use BodyType(0) for any "other" purpose then you can hardcode the "ushort.MaxValue" as non-charmable :)
User avatar
Leodagan
Developer
 
Posts: 1350
Joined: Tue May 01, 2012 9:30 am
Location: Lyon

Re: Charm Spell - All Type - Fails on Non Body Type NPCs

Postby Crazys » Sun Oct 05, 2014 3:17 pm

Leodagan wrote:Why would old DB need a bodyType in game ?

I checked all code BodyType is not used anywhere else than charm spell handler, most Quest script hardcoded NPC are setting the BodyType to 0 triggering the charm "protection"...

BodyType isn't sent to client so it's not needed for any Packet Handling, are you sure you aren't mistaking BodyType with "Race", Race is a GameNPC field that allow to set the NPC Type with templated resists (like undead weak to spirit, or animals weak to fire strong to cold...)

The BodyType field of a GameNPC have no other purpose than charm check, why would you want an other bool field only targeted at charm check ? If you want to use BodyType(0) for any "other" purpose then you can hardcode the "ushort.MaxValue" as non-charmable :)


Shrug as far as ik concerned we can kill the thread. I was attempting to help out new servers as any new mob has no body so it cant be xharmed as well as the entire world for tye publicly nade dbs. So unless you modify every npc in the game charm always fails. Just seems over the top.where adding a type non charm or non charm flag I personally felt would be a better option.
Crazys
Contributor
 
Posts: 346
Joined: Tue Nov 07, 2006 10:18 pm

Re: Charm Spell - All Type - Fails on Non Body Type NPCs

Postby Leodagan » Sun Oct 05, 2014 3:43 pm

Oh ok I see...

Then it would be better to update the /mob command to set the BodyType flag to something as soon as someone remove the "Peace" flag :)

Removing Peace flag is something mostly done at first after having a npc created... (well you may have a better idea around this ?)

But if you want to edit your database "widely" it's pretty easy to make an "UPDATE" sql statement only targeted at field without npc type...

UPDATE mob SET BodyType = 1 WHERE BodyType IS NULL;

Or any other WHERE clause if you want to target some specific npc...
User avatar
Leodagan
Developer
 
Posts: 1350
Joined: Tue May 01, 2012 9:30 am
Location: Lyon


Return to DOL Code Contributions

Who is online

Users browsing this forum: No registered users and 1 guest