Magic

Magic

190k Downloads

Custom Team Provider for Spell Targeting

JoepOvermars opened this issue ยท 14 comments

commented

Hello, i have a question as the title says, how can i cancel a spell from being fired
i tried event.getSpell().cancel(), event.getSpell().getCurrentCast().setResult(SpellResult.CANCELLED), and many more that contains cancel, but no one seems to cancel the spell from being fired
So, is there any way to cancel the spell using the CastEvent?

commented

Ah, ok. That was kind of a hacky suggestion, anyway, I was hoping it would force targeting to happen early.

Well pretty much what you're trying to do isn't going to work out real well. :(

It's kind of an ambiguous thing- not all spells target where the player is looking. Some perform local area of effects, some throw or shoot a projectile.. it's hard to tell where an arrow will land based on where player is looking, for instance.

The way spells normally perform these kind of checks is on the receiving end, when it tries to change blocks it checks for build/break permission at that location, or when it tries to damage an entity it checks for pvp permission. There's not really any sense of trying to preemptively prevent a spell because it may land in a location.

I'd like to help, there's probably some way to do what you're after. Is this a custom arena system, or is it a public plugin I could integrate with for build/pvp permissions?

commented

Once the CastEvent fires the spell has already been cast, it's too late to cancel it.

You can cancel PreCastEvent, though:

https://github.com/elBukkit/MagicPlugin/blob/master/MagicAPI/src/main/java/com/elmakers/mine/bukkit/api/event/PreCastEvent.java

commented

I only need to cancel it if one of the targets is on a specific arena, and in the PreCastEvent the e.getSpell().getCurrentCast().getTargetedEntities() returns an empty collection, could it be possible to cancel the hit inside of this event? or should I use a damageEvent to fix this?

commented

I think you the best you can do is cancel it if the caster is in the area.

Targeted entities returns entities actually hit by a spell, once that is determined the spell is pretty much done casting (projectiles in flight, effects happen, etc).

If you want to cancel a spell based on where the player is looking you could try calling spell.getTargetLocation, I think that will perform targeting for you and return the location where the player is looking.

commented

e.getSpell().getCurrentCast().getTargetLocation() returns null in the PreCastEvent, so that will also not work

commented

I see, I think we can work something out!

There is a friendly fire system that works with a few arena plugins. If you were able to register yourself as a provider for FF checks would that work for you?

So basically anytime a spell was going to target another player, your plugin would be asked if that was OK.

You would just have to implement and register an interface rather that handling an event.

Does that sound workable?

commented

I dont really get what you mean, could you give an example?

commented

It is a custom duelling plugin, i don't want the players to hit their teammates, so the way you are suggesting would probably not work, i think

commented

So let's say your plugin implements an interface

interface TeamProvider {
  boolean isFriendly(Entity attacker, Entity entity);
}

This lets you say when an attacker is "friendly" (on the same team) with another entity.

You then register your team provider with Magic, and then spells will use your rules when casting.

Doing it this way lets you tie into flags built in to the plugin like "bypass_friendly_fire" and "only_friendly" so you can make support spells that can be cast on teammates, or can only be cast on teammates.

commented

Do you still want a TeamProvider interface? Do you need something else to accomplish what you're after?

commented

I still want the TeamProvider interface, as this is propably what will help me in this plugin but also in multiple other plugins

commented

TeamProvider added in most recent dev build. You'll need to listen for the LoadEvent:

https://github.com/elBukkit/MagicPlugin/blob/master/MagicAPI/src/main/java/com/elmakers/mine/bukkit/api/event/LoadEvent.java#L52

And register a TeamProvider that you implement. It is just a simple isFriendly method:

https://github.com/elBukkit/MagicPlugin/blob/master/MagicAPI/src/main/java/com/elmakers/mine/bukkit/api/entity/TeamProvider.java#L23

This will be called any time any entity targets another entity with a spell. Take care, they won't always be Players.

I'll leave this open for a bit, please let me know if all goes well or if you need changes or run into issues.

commented

I tested it for a while, and it all works fine for me, thank you for making this feature

commented

I'm glad that worked for you, thank you for letting me know!