FaceMelter

Member
ServUO Version
Publish Unknown
Ultima Expansion
None
Is there a way to follow up the use of spell.Cast() with current target via script? Here's an example of what I've tried so far:
int m_SpellID = this.SpellSelect; Spell spell = SpellRegistry.NewSpell( m_SpellID, attacker, this ); if ( spell != null ) { spell.Cast(); attacker.Target = new InternalTarget( defender ); } else { attacker.SendLocalizedMessage( 502345 ); // This spell has been temporarily disabled. }
When I first added this, I didn't have the internal targeting. This functioned. The spell was cast and the player is displayed a targeting cursor.
I'd like the spell target to automatically cast on the defender (a mobile that's previously defined).
After adding the InternalTarget line above, I get a namespace error (missing an assembly reference?). Normally this means that I forgot to include the right System or Server reference. Here's what I have:
using System; using System.Text; using System.Collections; using Server.Network; using Server.Targeting; using Server.Mobiles; using Server.Spells; using Server.Engines.Craft; using System.Collections.Generic; using Server.Misc;
Is there some other reference besides Server.Targeting? I've never messed with InternalTarget or Targeting in general before, so perhaps I'm missing something or using the incorrect Targeting here. I've looked at how this is used in other scripts, but I've misunderstood something here. (This is located in the OnHit section of BaseWeapon.)

Thanks for any advice that can point me in the right direction!
 
You can't invoke InternalTarget because it's private method, your namespace just can't see this method in list. You can just try to change this method to "public" to make it visible. But don't do that!
It will incorrect from the point of view of the principles of programming and OOP, as well as your task. Because method spell.Cast(); -> going to invoke CastTimer -> which going to call by delay OnCast() method. OnCast already contains "InternalTarget;" which you wanted to use.
C#:
        public override void OnCast()
        {
            Caster.Target = new InternalTarget( this );
        }
 
I wasn't sure if InternalTarget was the correct way to go, it was just what I saw. I tried to add the above override to BaseWeapon, but received:

'Server.Items.BaseWeapon.OnCast()': no suitable method found to override

Meaning that BaseWeapon has no defalut OnCast() method to override... which makes sense. So that's not an option.

Looking at how it's normally done in BaseWeapon, it looks like OnHit spells are "faked".

They do a combination of displaying particles (animation of a spell) and then performing DoHarmful() to do the damage.

Because I'm trying to do this using spells via the spell registry, do I need to change how OnCast works for spells to make it work within BaseWeapon? Or is there another method to cast on current target directly?
 
Looking at how it's normally done in BaseWeapon, it looks like OnHit spells are "faked".
Yes, you're right. It's like pseudo casts, just damage + effects.

If you want to immediately apply casting for weapons, you will need to perform a number of manipulations with the definition of spell parameters.

You can directly define a list of spells and then you will have the opportunity to use methods like:
public void Target(Damageable m)

But in your example, you want to create spells by Spell_ID, in which case you will need to use reflexive methods to call private InternalTarget methods. In this case, ServUO already has a solution called OnCastInstantTarget(). But to implement it, you will need to set a number of parameters, without which you will fizzle these spells, mana will be taken away from you and weapons will fall out of your hands. Obviously, it is for this reason that Hit Properties were implemented as separate entities for easier use.
The solution to your question will look something like this:

C#:
        public override bool AllowEquipedCast(Mobile from)
        {
            return true;
        }

        public override void OnHit(Mobile attacker, IDamageable damageable, double damageBonus)
        {
            base.OnHit(attacker, damageable, damageBonus);

            int m_SpellID = Utility.RandomBool() ? 29 : 50; // lightning or flamestrike
            Spell spell = SpellRegistry.NewSpell(m_SpellID, attacker, null);

            if (spell != null)
            {
                spell.State = SpellState.Sequencing;
                attacker.Spell = spell;
                spell.InstantTarget = damageable;
                spell.OnCastInstantTarget();
            }
        }
 
Since I'm using an older RunUO base, I don't have InstantTarget, but I have been looking at that and what you've posted trying to understand what I'm looking at.

I know that by tying it directly to the spell registry I'm creating problems for myself, but this is just one small part of a larger spell system rewrite. I'll keep taking a crack at this and see how far I can get.

I'm doing my best to follow how the spell system get's to the spell.cast part, but holy moly it's a ton of checks before it gets there. I'm also confused when I see things like OnCast being an entirely empty method. But I'll get there eventually.''

Thanks again for helping me get some more perspective!
 
Yes, you're right. It's like pseudo casts, just damage + effects.

If you want to immediately apply casting for weapons, you will need to perform a number of manipulations with the definition of spell parameters.

You can directly define a list of spells and then you will have the opportunity to use methods like:
public void Target(Damageable m)

But in your example, you want to create spells by Spell_ID, in which case you will need to use reflexive methods to call private InternalTarget methods. In this case, ServUO already has a solution called OnCastInstantTarget(). But to implement it, you will need to set a number of parameters, without which you will fizzle these spells, mana will be taken away from you and weapons will fall out of your hands. Obviously, it is for this reason that Hit Properties were implemented as separate entities for easier use.
The solution to your question will look something like this:

C#:
        public override bool AllowEquipedCast(Mobile from)
        {
            return true;
        }

        public override void OnHit(Mobile attacker, IDamageable damageable, double damageBonus)
        {
            base.OnHit(attacker, damageable, damageBonus);

            int m_SpellID = Utility.RandomBool() ? 29 : 50; // lightning or flamestrike
            Spell spell = SpellRegistry.NewSpell(m_SpellID, attacker, null);

            if (spell != null)
            {
                spell.State = SpellState.Sequencing;
                attacker.Spell = spell;
                spell.InstantTarget = damageable;
                spell.OnCastInstantTarget();
            }
        }
It took me a while to learn how the version of RunUO I'm using does spell effects, and while I never got a version that works using spell.Cast, I was able to rewrite a version that does it the "fake" way that we discussed using a damage call and invoking particles. Just wanted to thank you Juzzver for helping me out!

This doesn't work for the current ServUO, only on the custom RunUO server I'm using:
DoMagicArrow:
public virtual void DoMagicArrow( Mobile attacker, Mobile defender )
        {
            if ( !attacker.CanBeHarmful( defender, false ) )
                return;

            attacker.DoHarmful( defender );

            attacker.MovingParticles( defender, 0x36E4, 5, 0, false, true, 3006, 4006, 0 );
            attacker.PlaySound( 0x1E5 );
        }

I add the damage later on in the sequence. I still want to figure out how to make a spell cast without all of the checks, but I'll keep digging. I have had some success with spells that auto target like Magic Reflection, perhaps I just need to make modified versions of the spells that mimic those types for use. So far I've made a shield that has a chance to automatically cast Magic Reflection, so I'll take that as progress!
 

Active Shards

Donations

Total amount
$0.00
Goal
$1,000.00
Back