Started by
summerkleger
on
Topic category: Help with Minecraft modding (Java Edition)
I'm making a mod that has spells, and I don't want to make an individual spell for every single effect. Is there a way to shoot an arrow with attributes on it? I just need to store data in the arrow itself.
In Aquatic Craft I have a weapon that fires a custom projectile, with its effect changing depending on the type of fish you're holding in your off-hand. And I do this by changing the "Air" value of the projectile, funnily enough.
Just in case of any differences between versions, I'm using 2023.4 for a 1.20.1 mod here...
I have a custom ranged weapon that fires a custom projectile, and the weapon has two different procedures on it. The first I'll call "values" and the second I'll call "fire". The trigger "When ranged item used" under the "Advanced properties" tab calls the "values" procedure while the "When right-clicked (entity pos.)" trigger calls the "fire" procedure.
I have the "values" procedure check to make sure that the player is holding the correct weapon in their main hand and an item tagged as ammo in their off-hand. Then, I set a local string variable to a positive integer depending on the type of ammo held. I have a series of 'if else if ...' statements for each type of ammo, setting the string variable to a different integer for each.
At the bottom of the procedure, I create a string with three parts:
data merge entity @e[type=aquaticcraft:projectile_aq_fish_launcher_projectile, limit=1, sort=nearest] {Air:
effectValueString
}
I then execute the string as a command at the x, y, z position of the Event/target entity. This gets the nearest of this type of custom projectile and changes its Air value to whatever you set it to. I believe the range is 0-300, but I haven't tested beyond that. I use a range from 1-60 myself. This procedure also triggers a custom cooldown to prevent the player from spamming it too quickly.
The "fire" procedure makes sure that the player is holding applicable ammo in their off-hand slot, checks to make sure the weapon isn't currently on cooldown, and then I use a "Shoot _ from entity: Event/target entity with speed: 2 inaccuracy: 0" block. The blank is an "Arrow of type ..." block set to your custom projectile. I then call the "values" procedure from the "fire" procedure.
To recap: I fire the weapon, it creates a projectile, I change the Air tag on the nearest projectile of the type I just created, and then it flies off...
Then, on the projectile itself, I have a procedure I'll call "hit", which is called under both the "When projectile hits block" and "When projectile hits living entity" triggers.
The "hit" procedure has a long series of if else if ... statements that "Get oxygen of Immediate source entity" and compare it, with math logic, to check its value. (If = 1, else if = 2, etc.) Then, since my effects are all explosive, I use "Explode at ..." and "For each entity as Entity iterator ..." blocks. At the very end of the procedure, I have a "Execute command / kill @s in the name of Immediate source entity" block, to prevent it from lingering if you fire the projectile at an entity immune to ranged attacks or get the projectile stuck some other way.
The tricky part in figuring this out was trying to get information from the projectile that MCreator could set on a projectile entity and then read later. I implemented this method before you could simply "Get nearest entity ..." for a projectile entity. Now you could probably just get the nearest projectile, give it a custom NBT tag, and then check that tag when it hits something. But I still wanted to talk you through my process.