TheGodfather

I wanted to make it so players can Provo onto themselves.

Code:
#region Header
// **********
// ServUO - Provocation.cs
// **********
#endregion

#region References
using System;

using Server.Engines.XmlSpawner2;
using Server.Items;
using Server.Mobiles;
using Server.Targeting;
#endregion

namespace Server.SkillHandlers
{
    public class Provocation
    {
        public static void Initialize()
        {
            SkillInfo.Table[(int)SkillName.Provocation].Callback = OnUse;
        }

        public static TimeSpan OnUse(Mobile m)
        {
            m.RevealingAction();

            BaseInstrument.PickInstrument(m, OnPickedInstrument);

            return TimeSpan.FromSeconds(1.0); // Cannot use another skill for 1 second
        }

        public static void OnPickedInstrument(Mobile from, BaseInstrument instrument)
        {
            from.RevealingAction();
            from.SendLocalizedMessage(501587); // Whom do you wish to incite?
            from.Target = new InternalFirstTarget(from, instrument);
        }

        public class InternalFirstTarget : Target
        {
            private readonly BaseInstrument m_Instrument;

            public InternalFirstTarget(Mobile from, BaseInstrument instrument)
                : base(BaseInstrument.GetBardRange(from, SkillName.Provocation), false, TargetFlags.None)
            {
                m_Instrument = instrument;
            }

            protected override void OnTarget(Mobile from, object targeted)
            {
                from.RevealingAction();

                if (targeted is BaseCreature && from.CanBeHarmful((Mobile)targeted, false))
                {
                    BaseCreature creature = (BaseCreature)targeted;

                    if (!m_Instrument.IsChildOf(from.Backpack))
                    {
                        from.SendLocalizedMessage(1062488); // The instrument you are trying to play is no longer in your backpack!
                    }
                    else if (from is PlayerMobile && creature.Controlled)
                    {
                        from.SendLocalizedMessage(501590); // They are too loyal to their master to be provoked.
                    }
                    else if (creature.IsParagon && BaseInstrument.GetBaseDifficulty(creature) >= 160.0)
                    {
                        from.SendLocalizedMessage(1049446); // You have no chance of provoking those creatures.
                    }
                    else
                    {
                        from.RevealingAction();
                        m_Instrument.PlayInstrumentWell(from);
                        from.SendLocalizedMessage(1008085);
                            // You play your music and your target becomes angered.  Whom do you wish them to attack?
                        from.Target = new InternalSecondTarget(from, m_Instrument, creature);
                    }
                }
                else
                {
                    from.SendLocalizedMessage(501589); // You can't incite that!
                }
            }
        }

        public class InternalSecondTarget : Target
        {
            private readonly BaseCreature m_Creature;
            private readonly BaseInstrument m_Instrument;

            public InternalSecondTarget(Mobile from, BaseInstrument instrument, BaseCreature creature)
                : base(BaseInstrument.GetBardRange(from, SkillName.Provocation), false, TargetFlags.None)
            {
                m_Instrument = instrument;
                m_Creature = creature;
            }

            protected override void OnTarget(Mobile from, object targeted)
            {
                from.RevealingAction();

                if (targeted is BaseCreature || (from is BaseCreature && ((BaseCreature)from).CanProvoke))
                {
                    BaseCreature creature = targeted as BaseCreature;
                    Mobile target = targeted as Mobile;

                    if (!m_Instrument.IsChildOf(from.Backpack))
                    {
                        from.SendLocalizedMessage(1062488); // The instrument you are trying to play is no longer in your backpack!
                    }
                    else if (m_Creature.Unprovokable)
                    {
                        from.SendLocalizedMessage(1049446); // You have no chance of provoking those creatures.
                    }
                    else if (creature != null && creature.Unprovokable && !(creature is DemonKnight))
                    {
                        from.SendLocalizedMessage(1049446); // You have no chance of provoking those creatures.
                    }
                    else if (m_Creature.Map != target.Map ||
                             !m_Creature.InRange(target, BaseInstrument.GetBardRange(from, SkillName.Provocation)))
                    {
                        from.SendLocalizedMessage(1049450);
                            // The creatures you are trying to provoke are too far away from each other for your music to have an effect.
                    }
                    else if (m_Creature != target)
                    {
                        from.NextSkillTime = Core.TickCount + 10000;

                        double diff = ((m_Instrument.GetDifficultyFor(m_Creature) + m_Instrument.GetDifficultyFor(target)) * 0.5) - 5.0;
                        double music = from.Skills[SkillName.Musicianship].Value;

                        diff += (XmlMobFactions.GetScaledFaction(from, m_Creature, -25, 25, -0.001) +
                                 XmlMobFactions.GetScaledFaction(from, target, -25, 25, -0.001)) * 0.5;

                        if (music > 100.0)
                        {
                            diff -= (music - 100.0) * 0.5;
                        }

                        if (from.CanBeHarmful(m_Creature, true) && from.CanBeHarmful(target, true))
                        {
                            if (!BaseInstrument.CheckMusicianship(from))
                            {
                                from.NextSkillTime = Core.TickCount + 5000;
                                from.SendLocalizedMessage(500612); // You play poorly, and there is no effect.
                                m_Instrument.PlayInstrumentBadly(from);
                                m_Instrument.ConsumeUse(from);
                            }
                            else
                            {
                                //from.DoHarmful( m_Creature );
                                //from.DoHarmful( creature );
                                if (!from.CheckTargetSkill(SkillName.Provocation, target, diff - 25.0, diff + 25.0))
                                {
                                    from.NextSkillTime = Core.TickCount + 5000;
                                    from.SendLocalizedMessage(501599); // Your music fails to incite enough anger.
                                    m_Instrument.PlayInstrumentBadly(from);
                                    m_Instrument.ConsumeUse(from);
                                }
                                else
                                {
                                    from.SendLocalizedMessage(501602); // Your music succeeds, as you start a fight.
                                    m_Instrument.PlayInstrumentWell(from);
                                    m_Instrument.ConsumeUse(from);
                                    m_Creature.Provoke(from, target, true);
                                }
                            }
                        }
                    }
                    else
                    {
                        from.SendLocalizedMessage(501593); // You can't tell someone to attack themselves!
                    }
                }
                else
                {
                    //from.SendLocalizedMessage(501589); // You can't incite that!
                }
            }
        }
    }
}

Trying to find what to change in this file... a bit dense lol
 
You want to be able to provocate yourself with a creature and/or a creature to yourself?

From what i see in InternalSecondTarget in OnTarget,
Code:
if (targeted is BaseCreature || (from is BaseCreature && ((BaseCreature)from).CanProvoke))
Is problematic.

The whole code would need to be reviewed and tested if you want to allow players as provocated creature targets.
I would suggest making two different conditions to meet the BaseCreature and PlayerMobile criteria, since both do not really affect the other.

If you have enough confidence to try it, do not hesitate to ask for help.
If you don't really know where to start , i can take some time to come up with something.
[doublepost=1474767468][/doublepost]I didn't test it, it compiled though.

Code:
public class InternalSecondTarget : Target
{
    private readonly BaseCreature m_Creature;
    private readonly BaseInstrument m_Instrument;

    public InternalSecondTarget(Mobile from, BaseInstrument instrument, BaseCreature creature) : base(BaseInstrument.GetBardRange(from, SkillName.Provocation), false, TargetFlags.None)
    {
        m_Instrument = instrument;
        m_Creature = creature;
    }

    protected override void OnTarget(Mobile from, object targeted)
    {
        from.RevealingAction();

        BaseCreature targCreature = targeted as BaseCreature;
        PlayerMobile targPlayer = targeted as PlayerMobile;
       
        // Note: the messages will now be in the "wrong" order (if we consider vanilla), as the checks are not done the same way as before.
        // Not one or the other, so it is not worth to continue checking.
        if (targCreature == null && targPlayer == null)
        {
            from.SendLocalizedMessage(501589); // You can't incite that!
            return;
        }
        else if (m_Creature == targeted) // should work.
        {
            from.SendLocalizedMessage(501593); // You can't tell someone to attack themselves!
            return;
        }
        else if (!m_Instrument.IsChildOf(from.Backpack))
        {
            from.SendLocalizedMessage(1062488); // The instrument you are trying to play is no longer in your backpack!
            return;
        }
        else
        {
            Mobile target = targeted as Mobile;

            // The target is a creature, or the provocator is a creature that can provocate.
            if (targCreature != null || (from is BaseCreature && ((BaseCreature)from).CanProvoke))
            {
                if (m_Creature.Unprovokable)
                {
                    from.SendLocalizedMessage(1049446); // You have no chance of provoking those creatures.
                }
                else if (targCreature != null && targCreature.Unprovokable && !(targCreature is DemonKnight))
                {
                    from.SendLocalizedMessage(1049446); // You have no chance of provoking those creatures.
                }
                else if (m_Creature.Map != target.Map || !m_Creature.InRange(target, BaseInstrument.GetBardRange(from, SkillName.Provocation)))
                {
                    from.SendLocalizedMessage(1049450); // The creatures you are trying to provoke are too far away from each other for your music to have an effect.
                }
                else
                {
                    DoProvoc(from, targPlayer);
                }
            }
            else if (targPlayer != null)
            {
                DoProvoc(from, targPlayer);
            }
        }
    }
   
    private void DoProvoc(Mobile from, Mobile target)
    {
        from.NextSkillTime = Core.TickCount + 10000;

        double diff = ((m_Instrument.GetDifficultyFor(m_Creature) + m_Instrument.GetDifficultyFor(target)) * 0.5) - 5.0;
        double music = from.Skills[SkillName.Musicianship].Value;

        // NOTE: This could fail, since idk what
        diff += (XmlMobFactions.GetScaledFaction(from, m_Creature, -25, 25, -0.001) + XmlMobFactions.GetScaledFaction(from, target, -25, 25, -0.001)) * 0.5;

        if (music > 100.0)
        {
            diff -= (music - 100.0) * 0.5;
        }

        if (from.CanBeHarmful(m_Creature, true) && from.CanBeHarmful(target, true))
        {
            if (!BaseInstrument.CheckMusicianship(from))
            {
                from.NextSkillTime = Core.TickCount + 5000;
                from.SendLocalizedMessage(500612); // You play poorly, and there is no effect.
                m_Instrument.PlayInstrumentBadly(from);
                m_Instrument.ConsumeUse(from);
            }
            else
            {
                //from.DoHarmful( m_Creature );
                //from.DoHarmful( target );
                if (!from.CheckTargetSkill(SkillName.Provocation, target, diff - 25.0, diff + 25.0))
                {
                    from.NextSkillTime = Core.TickCount + 5000;
                    from.SendLocalizedMessage(501599); // Your music fails to incite enough anger.
                    m_Instrument.PlayInstrumentBadly(from);
                    m_Instrument.ConsumeUse(from);
                }
                else
                {
                    from.SendLocalizedMessage(501602); // Your music succeeds, as you start a fight.
                    m_Instrument.PlayInstrumentWell(from);
                    m_Instrument.ConsumeUse(from);
                    m_Creature.Provoke(from, target, true);
                }
            }
        }
    }
}

There could be a problem with the XML related line with the "diff +=", but other than that i expect it to have the behavior you want.
 
seems to work!
[doublepost=1474911740][/doublepost]Ok this causes this error

Code:
Exception:
System.NullReferenceException: Object reference not set to an instance of an object.
   at Server.Items.BaseInstrument.GetBaseDifficulty(Mobile targ)
   at Server.Items.BaseInstrument.GetDifficultyFor(Mobile targ)
   at Server.SkillHandlers.Provocation.InternalSecondTarget.DoProvoc(Mobile from, Mobile target)
   at Server.Targeting.Target.Invoke(Mobile from, Object targeted) in c:\Program Files (x86)\ServUO3\ServUO-master\Server\Targeting\Target.cs:line 269
   at Server.Network.PacketHandlers.TargetResponse(NetState state, PacketReader pvSrc) in c:\Program Files (x86)\ServUO3\ServUO-master\Server\Network\PacketHandlers.cs:line 1323
   at Server.Network.MessagePump.HandleReceive(NetState ns) in c:\Program Files (x86)\ServUO3\ServUO-master\Server\Network\MessagePump.cs:line 303
   at Server.Network.MessagePump.Slice() in c:\Program Files (x86)\ServUO3\ServUO-master\Server\Network\MessagePump.cs:line 121
   at Server.Core.Main(String[] args) in c:\Program Files (x86)\ServUO3\ServUO-master\Server\Main.cs:line 577
[doublepost=1474912268][/doublepost]It happens when you provoke another create on another creature.
 
Last edited by a moderator:
  • else
  • {
  • DoProvoc(from, targPlayer);
  • }
  • }
  • else if (targPlayer != null)
  • {
  • DoProvoc(from, targPlayer);
  • }
Obviously Po0ka slipped in a deliberate mistake there to catch us out ;) For the next person who gets here like me, wondering if anyone else has done this, change the first targPlayer to targCreature.

Also for RunUO you don't want the XmlFactions line. This is dealt with by the slayer factions elsewhere.

Finally, I had to change the GetBaseDifficulty method in BaseInstrument.cs to add a return for when targ is PlayerMobile as follows:


Code:
 public static double GetBaseDifficulty( Mobile targ )
 {
 /* Difficulty TODO: Add another 100 points for each of the following abilities:
 - Radiation or Aura Damage (Heat, Cold etc.)
 - Summoning Undead
 */
 double val = (targ.HitsMax * 1.6) + targ.StamMax + targ.ManaMax;
 val += targ.SkillsTotal / 10;
 if ( val > 700 )
 val = 700 + (int)((val - 700) * (3.0 / 11));
// David: Provocation now works on players 
 if ( targ is PlayerMobile )
 {
 val /= 10;
 return val;
 }
 BaseCreature bc = targ as BaseCreature;
 if ( IsMageryCreature( bc ) )
 val += 100;
 if ( IsFireBreathingCreature( bc ) )
 val += 100;
 if ( IsPoisonImmune( bc ) )
 val += 100;
 if ( targ is VampireBat || targ is VampireBatFamiliar )
 val += 100;
 val += GetPoisonLevel( bc ) * 20;
 val /= 10;
 if ( bc != null && bc.IsParagon )
 val += 40.0;
 if ( Core.SE && val > 160.0 )
 val = 160.0;
 return val;
 }

You could get smart in there and check against the target player's provocation or peacemaking skill if you wanted as well. I suppose it should be harder for a bard to provoke a pet onto someone who had GM peacemaking skill so I will likely add that to my shard.

Thanks everyone.

David
 

Active Shards

Donations

Total amount
$0.00
Goal
$1,000.00
Back