Energy sword now has innate sweeping edge mechanics

Fixes #54
This commit is contained in:
DBotThePony 2022-10-01 20:39:57 +07:00
parent 644e287ece
commit c4d683fe7b
Signed by: DBot
GPG Key ID: DCC23B5715498507
3 changed files with 120 additions and 20 deletions

View File

@ -446,6 +446,8 @@ private fun items(provider: MatteryLanguageProvider) {
add(MItems.ENERGY_SWORD, "Powered Cake Slicer") add(MItems.ENERGY_SWORD, "Powered Cake Slicer")
add(MItems.ENERGY_SWORD, "desc", "Needs power to operate") add(MItems.ENERGY_SWORD, "desc", "Needs power to operate")
add(MItems.ENERGY_SWORD, "desc2", "Deals extra damage to androids when powered") add(MItems.ENERGY_SWORD, "desc2", "Deals extra damage to androids when powered")
add(MItems.ENERGY_SWORD, "desc3", "Always strikes surrounding enemies with full damage if empowered")
add(MItems.ENERGY_SWORD, "desc4", "Does not benefit from Sweeping Edge enchantment")
add(MItems.PORTABLE_CONDENSATION_DRIVE, "Portable Condensation Drive") add(MItems.PORTABLE_CONDENSATION_DRIVE, "Portable Condensation Drive")
add(MItems.PORTABLE_DENSE_CONDENSATION_DRIVE, "Portable Dense Condensation Drive") add(MItems.PORTABLE_DENSE_CONDENSATION_DRIVE, "Portable Dense Condensation Drive")

View File

@ -39,6 +39,18 @@ import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.core.orNull import ru.dbotthepony.mc.otm.core.orNull
import ru.dbotthepony.mc.otm.registry.EMPDamageSource import ru.dbotthepony.mc.otm.registry.EMPDamageSource
/**
* This is called from [net.minecraft.world.item.enchantment.EnchantmentHelper.getSweepingDamageRatio]
* by coremod patch
*/
fun getSweepingDamageRatioHook(ply: LivingEntity): Float? {
if (ply.mainHandItem.item is EnergySwordItem && ply.mainHandItem.matteryEnergy?.extractEnergyInnerExact(EnergySwordItem.ENERGY_PER_SWING, true)?.isPositive == true) {
return 1f
}
return null
}
class EnergySwordItem : Item(Properties().stacksTo(1).rarity(Rarity.RARE).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) { class EnergySwordItem : Item(Properties().stacksTo(1).rarity(Rarity.RARE).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
val chargedAttributes: Multimap<Attribute, AttributeModifier> val chargedAttributes: Multimap<Attribute, AttributeModifier>
val dischargedAttributes: Multimap<Attribute, AttributeModifier> val dischargedAttributes: Multimap<Attribute, AttributeModifier>
@ -83,6 +95,12 @@ class EnergySwordItem : Item(Properties().stacksTo(1).rarity(Rarity.RARE).tab(Ov
override fun hurtEnemy(itemStack: ItemStack, victim: LivingEntity, attacker: LivingEntity): Boolean { override fun hurtEnemy(itemStack: ItemStack, victim: LivingEntity, attacker: LivingEntity): Boolean {
if (attacker is Player && attacker.isCreative) { if (attacker is Player && attacker.isCreative) {
victim.matteryPlayer?.let {
if (it.isAndroid) {
victim.hurt(EMPDamageSource(attacker), 8f)
}
}
return true return true
} }
@ -124,6 +142,8 @@ class EnergySwordItem : Item(Properties().stacksTo(1).rarity(Rarity.RARE).tab(Ov
p_41423_.add(DESCRIPTION) p_41423_.add(DESCRIPTION)
p_41423_.add(DESCRIPTION2) p_41423_.add(DESCRIPTION2)
p_41423_.add(DESCRIPTION3)
p_41423_.add(DESCRIPTION4)
} }
override fun mineBlock( override fun mineBlock(
@ -179,13 +199,15 @@ class EnergySwordItem : Item(Properties().stacksTo(1).rarity(Rarity.RARE).tab(Ov
} }
companion object { companion object {
private val MAX_ENERGY = ImpreciseFraction(500_000) val MAX_ENERGY = ImpreciseFraction(500_000)
private val ENERGY_ZAP = ImpreciseFraction(4_000) val ENERGY_ZAP = ImpreciseFraction(4_000)
private val ENERGY_PER_SWING = ImpreciseFraction(2_000) val ENERGY_PER_SWING = ImpreciseFraction(2_000)
private val COBWEB_POWER_COST = ImpreciseFraction(2_500) val COBWEB_POWER_COST = ImpreciseFraction(2_500)
private val PLANT_POWER_COST = ImpreciseFraction(500) val PLANT_POWER_COST = ImpreciseFraction(500)
private val DESCRIPTION = TranslatableComponent("item.overdrive_that_matters.energy_sword.desc").withStyle(ChatFormatting.DARK_GRAY) private val DESCRIPTION = TranslatableComponent("item.overdrive_that_matters.energy_sword.desc").withStyle(ChatFormatting.DARK_GRAY)
private val DESCRIPTION2 = TranslatableComponent("item.overdrive_that_matters.energy_sword.desc2").withStyle(ChatFormatting.DARK_GRAY) private val DESCRIPTION2 = TranslatableComponent("item.overdrive_that_matters.energy_sword.desc2").withStyle(ChatFormatting.DARK_GRAY)
private val DESCRIPTION3 = TranslatableComponent("item.overdrive_that_matters.energy_sword.desc3").withStyle(ChatFormatting.DARK_GRAY)
private val DESCRIPTION4 = TranslatableComponent("item.overdrive_that_matters.energy_sword.desc4").withStyle(ChatFormatting.DARK_GRAY)
} }
} }

View File

@ -4,6 +4,10 @@ var AbstractInsnNode = Java.type('org.objectweb.asm.tree.AbstractInsnNode')
var Opcodes = Java.type('org.objectweb.asm.Opcodes') var Opcodes = Java.type('org.objectweb.asm.Opcodes')
var VarInsnNode = Java.type('org.objectweb.asm.tree.VarInsnNode') var VarInsnNode = Java.type('org.objectweb.asm.tree.VarInsnNode')
var MethodInsnNode = Java.type('org.objectweb.asm.tree.MethodInsnNode') var MethodInsnNode = Java.type('org.objectweb.asm.tree.MethodInsnNode')
var JumpInsnNode = Java.type('org.objectweb.asm.tree.JumpInsnNode')
var LabelNode = Java.type('org.objectweb.asm.tree.LabelNode')
var InsnNode = Java.type('org.objectweb.asm.tree.InsnNode')
var Label = Java.type('org.objectweb.asm.Label')
var opcodesRemapped = { var opcodesRemapped = {
'aaload': 50, 'aaload': 50,
@ -510,21 +514,21 @@ function initializeCoreMod() {
'transformer': function(node) { 'transformer': function(node) {
// If item is not "damaged": // If item is not "damaged":
// 113: invokevirtual #144 // Method addResource:(ILnet/minecraft/world/item/ItemStack;)I // 113: invokevirtual #144 // Method addResource:(ILnet/minecraft/world/item/ItemStack;)I
// 116: invokevirtual #158 // Method net/minecraft/world/item/ItemStack.setCount:(I)V // 116: invokevirtual #158 // Method net/minecraft/world/item/ItemStack.setCount:(I)V
// 119: aload_2 // 119: aload_2
// 120: invokevirtual #57 // Method net/minecraft/world/item/ItemStack.isEmpty:()Z // 120: invokevirtual #57 // Method net/minecraft/world/item/ItemStack.isEmpty:()Z
// 123: ifne 134 // 123: ifne 134
// 126: aload_2 // 126: aload_2
// 127: invokevirtual #68 // Method net/minecraft/world/item/ItemStack.getCount:()I // 127: invokevirtual #68 // Method net/minecraft/world/item/ItemStack.getCount:()I
// 130: iload_3 // 130: iload_3
// 131: if_icmplt 87 // 131: if_icmplt 87
// <-- our target // <-- our target
// 134: aload_2 // 134: aload_2
// 135: invokevirtual #68 // Method net/minecraft/world/item/ItemStack.getCount:()I // 135: invokevirtual #68 // Method net/minecraft/world/item/ItemStack.getCount:()I
// 138: iload_3 // 138: iload_3
// 139: if_icmpne 162 // 139: if_icmpne 162
// 142: aload_0 // 142: aload_0
// If item returned that it is damaged: // If item returned that it is damaged:
// 10: invokevirtual #97 // Method net/minecraft/world/item/ItemStack.isDamaged:()Z // 10: invokevirtual #97 // Method net/minecraft/world/item/ItemStack.isDamaged:()Z
@ -593,6 +597,78 @@ function initializeCoreMod() {
return node return node
} }
},
'EnchantmentHelper#getSweepingDamageRatio patch for energy sword': {
'target': {
'type': 'METHOD',
'class': 'net.minecraft.world.item.enchantment.EnchantmentHelper',
'methodName': ASMAPI.mapMethod('m_44821_'), // getSweepingDamageRatio
'methodDesc': '(Lnet/minecraft/world/entity/LivingEntity;)F'
},
'transformer': function(node) {
// 0: getstatic #237 // Field net/minecraft/world/item/enchantment/Enchantments.SWEEPING_EDGE:Lnet/minecraft/world/item/enchantment/Enchantment;
// 3: aload_0
// 4: invokestatic #243 // Method getEnchantmentLevel:(Lnet/minecraft/world/item/enchantment/Enchantment;Lnet/minecraft/world/entity/LivingEntity;)I
// 7: istore_1
// 8: iload_1
// 9: ifle 19
// 12: iload_1
// 13: invokestatic #246 // Method net/minecraft/world/item/enchantment/SweepingEdgeEnchantment.getSweepingDamageRatio:(I)F
// 16: goto 20
// 19: fconst_0
// 20: freturn
var instructions = node.instructions
var last = new VarInsnNode(opcodesRemapped.aload, 0)
instructions.insert(last) // load player onto stack
var next = new MethodInsnNode(
opcodesRemapped.invokestatic,
'ru/dbotthepony/mc/otm/item/EnergySwordItemKt',
'getSweepingDamageRatioHook',
'(Lnet/minecraft/world/entity/LivingEntity;)Ljava/lang/Float;',
false
) // call hook
instructions.insert(last, next)
last = next
var label = new Label()
var labelNode = new LabelNode(label)
// add label to jump to if our hook returns null
instructions.insert(last, labelNode)
// duplicate our value, so `ifnull` can safely pop it from stack
next = new InsnNode(opcodesRemapped.dup)
instructions.insert(last, next)
last = next
// jump to original code if we returned null
next = new JumpInsnNode(opcodesRemapped.ifnull, labelNode)
instructions.insert(last, next)
last = next
// unbox float
next = new MethodInsnNode(
opcodesRemapped.invokevirtual,
'java/lang/Float',
'floatValue',
'()F',
false
)
instructions.insert(last, next)
last = next
// return float
next = new InsnNode(opcodesRemapped.freturn)
instructions.insert(last, next)
last = next
}
} }
} }
} }