Skip to content

📡自定义MM技能机制

ScriptMechanic下

类型

技能类型描述需要重写的方法
SKILL普通技能见下例子
AURA光环技能见自定义MM光环

示例

yaml
- test-message{message=AttributeMM牛逼}
javascript
//原始版本属性伤害,不兼容取消攻击事件、光环、AttributePlus蓄力、AttributePlus抛射物设置
//使用DamageApOld{clear=true;type=xx;属性=xx}使用
var mechanicName = "damage-ap-old|damageapold|attr-damage|attrdamage"
/*
  技能类型
  SKILL 一般技能 重写cast...方法 *不写默认为此类型
    如果技能中选择器为实体时 castAtEntity(utils, data, skillMetadata, abstractEntity)
    如果技能中选择器为坐标时 castAtLocation(utils, data, skillMetadata, abstractLocation)
    如果技能中未使用选择器时 cast(utils, data, skillMetadata)
  AURA 光环 重写auraStart(utils, data, tracker, skillMetadata, abstractEntity, skill, cancel)方法
 */
var mechanicType = "SKILL"

var baseAttributeBlackList

/**
 * 加载时运行
 *
 * @param utils 脚本工具
 * @param data 脚本数据
 * @param manager MythicMobs5独有的 在4.x版本中 manager是一个字符串"manager"
 * @param line 技能配置
 * @param lineParse 解析器 其实就是MythicConfigLine
 */
function onLoad(utils, data, manager, line, lineParse) {
    baseAttributeBlackList = utils.getConfig().getStringList("BaseAttributeBlackList.def")
    
    var attributeList = AttributePlus.attributeManager.attributeNameList
    var attributesHashMap = new Packages.java.util.HashMap()
    for (var i in attributeList.keySet().toArray()) {
        var attributeName = attributeList.keySet().toArray()[i]
        if (!attributeName.equals("type") && !attributeName.equals("clear")) {
            var attributeValue = lineParse.getString(attributeName, null)
            if (attributeValue != null) {
                attributesHashMap.put(attributeName, attributeValue)
            }
        }
    }
    data.set("attributesHashMap", attributesHashMap)
    //只有type和clear 其他自行添加
    data.set("type", lineParse.getString("type", null));
    data.set("clear", lineParse.getBoolean("clear", true));
}


/**
 * 释放技能
 *
 * @param utils 脚本工具
 * @param data 脚本数据
 * @param skillMetadata 技能元数据
 * @param abstractEntity 抽象目标
 */
function castAtEntity(utils, data, skillMetadata, abstractEntity) {
    //使用MythicMobs-5.x时候需要返回SkillResult
    //if (!skillMetadata.getCaster().getEntity().isLiving() && !abstractEntity.isLiving() && abstractEntity.isDead()) return SkillResult.ERROR
    if (!skillMetadata.getCaster().getEntity().isLiving() && !abstractEntity.isLiving() && abstractEntity.isDead()) return false

    var type = data.get("type")
    var clear = data.get("clear")

    //获取释放者和目标
    var caster = skillMetadata.getCaster().getEntity().getBukkitEntity()
    var target = abstractEntity.getBukkitEntity()
    //处理技能属性
    var attributesHashMap = data.get("attributesHashMap")
    var skillAttributesList = new ArrayList()
    for (var i in attributesHashMap.keySet().toArray()) {
        var attributeName = attributesHashMap.keySet().toArray()[i]
        var attributeValue = parse(attributesHashMap.get(attributeName), caster, target, skillMetadata, abstractEntity)
        skillAttributesList.add(attributeName + ":" + attributeValue)
    }
    var skillAttributeSource = AttributeAPI.getAttributeSource(skillAttributesList);

    //处理基础属性
    var defAttributesHashMap = new Packages.java.util.HashMap()
    if (clear) {
        var attributeList = AttributePlus.attributeManager.attributeNameList
        for (var i in attributeList.keySet().toArray()) {
            var attributeName = attributeList.keySet().toArray()[i]
            if (!baseAttributeBlackList.contains(attributeName)) {
                var attributeValue = AttributeAPI.getAttrData(caster).getAttributeValue(attributeName)
                if (attributeValue[0].doubleValue() > 0.0) {
                    defAttributesHashMap.put(attributeName, attributeValue)
                }
            }
        }
    }
    var defAttributeSource = new Packages.org.serverct.ersha.attribute.data.AttributeSource(defAttributesHashMap)
    /*
    * 接下来是处理属性攻击的代码
    * 原理就是通过操作攻击者的属性源来控制攻击者的属性值
    * 将攻击者的属性值变为想要的属性值 然后通过造成伤害被AttributePlus检测并接管
    * 最后将属性源扣除使触发者变为正常属性
    *
    * 兼容性巨差 问题巨多 几乎除了属性值之外的都不可控
    * 这是一个非常落后的方法 非必要不要使用这个方法
    * 自行想办法解决伤害递归、伤害被取消、蓄力、抛射物问题
    * 如果玩家出现属性源无法取消的问题自行清除APMMDEF和APMMSKILL属性源或重新进游戏
    *
    * 尽量使用最新版的DamageAp
    */
    //处理属性
    var attrData = AttributeAPI.getAttrData(caster)
    AttributeAPI.addSourceAttribute(attrData, "APMMDEF", defAttributeSource)
    AttributeAPI.addSourceAttribute(attrData, "APMMSKILL", skillAttributeSource)
    //取消目标不可攻击状态
    target.setNoDamageTicks(0);
    //处理API内容
    Packages.me.monsterxz.attributemm.API.type = type
    //让AttributePlus处理攻击
    target.damage(0.0, caster)
    //将API内容处理回来
    Packages.me.monsterxz.attributemm.API.type = null
    //将属性处理回来
    AttributeAPI.takeSourceAttribute(attrData, "APMMDEF")
    AttributeAPI.takeSourceAttribute(attrData, "APMMSKILL")

    //使用MythicMobs-5.x时候需要返回SkillResult
    //return SkillResult.SUCCESS;
    return true
}


var PlaceholderString = Packages.io.lumine.xikage.mythicmobs.skills.placeholders.parsers.PlaceholderString //MythicMobs-4.x
//var PlaceholderString =io.lumine.mythic.api.skills.placeholders.PlaceholderString //MythicMobs-5.x

function parse(string, attacker, entity, skillMetadata, abstractEntity) {
    if (string == null) {
        return null;
    }
    if (string.contains("$") || string.contains("%")) {
        string = PlaceholderUtils.parsePapiAndMp(attacker, entity, string);
    }
    if (string.contains("<") && string.contains(">")) {
        string = PlaceholderString.of(string).get(skillMetadata, abstractEntity);
    }
    string = Packages.java.lang.String.format("%.2f", CalculatorUtils.eval(string));
    return string
}

function castAtLocation(utils, data, skillMetadata, abstractLocation) {
    //使用MythicMobs-5.x时候需要返回SkillResult
    //return SkillResult.SUCCESS;
    return true

}

function cast(utils, data, skillMetadata) {
    //使用MythicMobs-5.x时候需要返回SkillResult
    //return SkillResult.SUCCESS;
    return true

}