diff --git a/assets/bHaptics/Interaction/Head/Steam.tact b/assets/bHaptics/Interaction/Head/Steam.tact new file mode 100644 index 0000000..353928d --- /dev/null +++ b/assets/bHaptics/Interaction/Head/Steam.tact @@ -0,0 +1 @@ +{"project":{"createdAt":1616725262848,"description":"","layout":{"layouts":{"Head":[{"index":0,"x":0,"y":0.5},{"index":1,"x":0.2,"y":0.5},{"index":2,"x":0.4,"y":0.5},{"index":3,"x":0.6,"y":0.5},{"index":4,"x":0.8,"y":0.5},{"index":5,"x":1,"y":0.5}]},"name":"Tactal","type":"Tactal"},"mediaFileDuration":1,"name":"Steam","tracks":[{"effects":[{"modes":{"Head":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":200,"playbackType":"NONE","pointList":[{"index":1,"intensity":0.5},{"index":2,"intensity":0.5},{"index":3,"intensity":0.5},{"index":4,"intensity":0.5}],"startTime":0},{"endTime":400,"playbackType":"NONE","pointList":[{"index":2,"intensity":0.5},{"index":4,"intensity":0.5}],"startTime":200},{"endTime":600,"playbackType":"NONE","pointList":[{"index":1,"intensity":0.5},{"index":3,"intensity":0.5}],"startTime":400},{"endTime":800,"playbackType":"NONE","pointList":[{"index":1,"intensity":0.5},{"index":2,"intensity":0.5},{"index":3,"intensity":0.5},{"index":4,"intensity":0.5}],"startTime":600}]},"mode":"DOT_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_SPEED","playbackType":"NONE","visible":true,"pointList":[]}]}}},"name":"Effect 1","offsetTime":800,"startTime":101}],"enable":true},{"effects":[{"modes":{"Head":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":1000,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_SPEED","playbackType":"FADE_OUT","pointList":[{"intensity":0.6,"time":0,"x":0.51,"y":0.5},{"intensity":0.6,"time":1000,"x":0,"y":0.5}],"visible":true},{"movingPattern":"CONST_SPEED","playbackType":"FADE_OUT","pointList":[{"intensity":0.6,"time":0,"x":0.51,"y":0.5},{"intensity":0.6,"time":1000,"x":1,"y":0.5}],"visible":true}]}}},"name":"Effect 1 copy 5","offsetTime":1000,"startTime":0}],"enable":true}],"updatedAt":1616726002365,"id":"-MWgKRBAGBbUKHWvEE50"},"durationMillis":0,"intervalMillis":20,"size":20} \ No newline at end of file diff --git a/assets/bHaptics/Interaction/Vest/Steam.tact b/assets/bHaptics/Interaction/Vest/Steam.tact new file mode 100644 index 0000000..a560065 --- /dev/null +++ b/assets/bHaptics/Interaction/Vest/Steam.tact @@ -0,0 +1 @@ +{"project":{"createdAt":1616723439806,"description":"","id":"-MWgDU69UiPwMXghacZX","layout":{"layouts":{"VestBack":[{"index":0,"x":0,"y":0},{"index":1,"x":0.333,"y":0},{"index":2,"x":0.667,"y":0},{"index":3,"x":1,"y":0},{"index":4,"x":0,"y":0.25},{"index":5,"x":0.333,"y":0.25},{"index":6,"x":0.667,"y":0.25},{"index":7,"x":1,"y":0.25},{"index":8,"x":0,"y":0.5},{"index":9,"x":0.333,"y":0.5},{"index":10,"x":0.667,"y":0.5},{"index":11,"x":1,"y":0.5},{"index":12,"x":0,"y":0.75},{"index":13,"x":0.333,"y":0.75},{"index":14,"x":0.667,"y":0.75},{"index":15,"x":1,"y":0.75},{"index":16,"x":0,"y":1},{"index":17,"x":0.333,"y":1},{"index":18,"x":0.667,"y":1},{"index":19,"x":1,"y":1}],"VestFront":[{"index":0,"x":0,"y":0},{"index":1,"x":0.333,"y":0},{"index":2,"x":0.667,"y":0},{"index":3,"x":1,"y":0},{"index":4,"x":0,"y":0.25},{"index":5,"x":0.333,"y":0.25},{"index":6,"x":0.667,"y":0.25},{"index":7,"x":1,"y":0.25},{"index":8,"x":0,"y":0.5},{"index":9,"x":0.333,"y":0.5},{"index":10,"x":0.667,"y":0.5},{"index":11,"x":1,"y":0.5},{"index":12,"x":0,"y":0.75},{"index":13,"x":0.333,"y":0.75},{"index":14,"x":0.667,"y":0.75},{"index":15,"x":1,"y":0.75},{"index":16,"x":0,"y":1},{"index":17,"x":0.333,"y":1},{"index":18,"x":0.667,"y":1},{"index":19,"x":1,"y":1}]},"name":"Tactot","type":"Tactot"},"mediaFileDuration":1,"name":"Steam","tracks":[{"effects":[{"modes":{"VestBack":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":480,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"NONE","pointList":[{"intensity":0.1,"time":0,"x":0,"y":0.14},{"intensity":0.1,"time":240,"x":0,"y":0.14},{"intensity":0.1,"time":480,"x":0.17,"y":0.22999999999999998}],"visible":true}]}},"VestFront":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":480,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"DOT_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"FADE_OUT","pointList":[{"intensity":0.4,"time":0,"x":0.68,"y":1},{"intensity":0.4,"time":240,"x":0,"y":0.86},{"intensity":0.4,"time":480,"x":0,"y":0.86}],"visible":true}]}}},"name":"Effect 1","offsetTime":480,"startTime":0},{"modes":{"VestBack":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":480,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"NONE","pointList":[{"intensity":0.1,"time":0,"x":0.01,"y":0.64},{"intensity":0.1,"time":240,"x":0.02,"y":0.64},{"intensity":0.1,"time":480,"x":0.33,"y":0.75}],"visible":true}]}},"VestFront":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":480,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"FADE_OUT","pointList":[{"intensity":0.2,"time":0,"x":0.67,"y":0.5},{"intensity":0.2,"time":240,"x":0.02,"y":0.6599999999999999},{"intensity":0.2,"time":480,"x":0.02,"y":0.6599999999999999}],"visible":true}]}}},"name":"Effect 1 copy 2","offsetTime":480,"startTime":271,"trackIndex":0},{"modes":{"VestBack":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":299,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"NONE","pointList":[{"intensity":0.1,"time":0,"x":0.99,"y":0.64},{"intensity":0.1,"time":149,"x":0.98,"y":0.64},{"intensity":0.1,"time":299,"x":0.6699999999999999,"y":0.75}],"visible":true}]}},"VestFront":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":299,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"FADE_OUT","pointList":[{"intensity":0.2,"time":0,"x":0.32999999999999996,"y":0.5},{"intensity":0.2,"time":149,"x":0.98,"y":0.6599999999999999},{"intensity":0.2,"time":299,"x":0.98,"y":0.6599999999999999}],"visible":true}]}}},"name":"Effect 1 copy 6","offsetTime":299,"startTime":699,"trackIndex":1},{"modes":{"VestBack":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":800,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_SPEED","playbackType":"NONE","visible":true,"pointList":[]}]}},"VestFront":{"dotMode":{"dotConnected":true,"feedback":[{"endTime":266,"playbackType":"NONE","pointList":[{"index":5,"intensity":0.2},{"index":6,"intensity":0.2},{"index":10,"intensity":0.2},{"index":13,"intensity":0.2}],"startTime":0},{"endTime":533,"playbackType":"NONE","pointList":[{"index":5,"intensity":0.2},{"index":9,"intensity":0.2},{"index":14,"intensity":0.2}],"startTime":266},{"endTime":800,"playbackType":"NONE","pointList":[{"index":6,"intensity":0.2},{"index":10,"intensity":0.2},{"index":9,"intensity":0.2},{"index":13,"intensity":0.2}],"startTime":533},{"endTime":800,"playbackType":"NONE","pointList":[{"index":5,"intensity":0.2},{"index":10,"intensity":0.2}],"startTime":800}]},"mode":"DOT_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_SPEED","playbackType":"NONE","visible":true,"pointList":[]}]}}},"name":"Effect 8","offsetTime":800,"startTime":100}],"enable":true},{"effects":[{"modes":{"VestBack":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":480,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"NONE","pointList":[{"intensity":0.1,"time":0,"x":1,"y":0.14},{"intensity":0.1,"time":240,"x":1,"y":0.14},{"intensity":0.1,"time":480,"x":0.83,"y":0.22999999999999998}],"visible":true}]}},"VestFront":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":480,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"FADE_OUT","pointList":[{"intensity":0.2,"time":0,"x":0.31999999999999995,"y":0},{"intensity":0.2,"time":240,"x":1,"y":0.14},{"intensity":0.2,"time":480,"x":1,"y":0.14}],"visible":true}]}}},"name":"Effect 1 copy 1","offsetTime":480,"startTime":518,"trackIndex":0},{"modes":{"VestBack":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":480,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"NONE","pointList":[{"intensity":0.1,"time":0,"x":0.99,"y":0.64},{"intensity":0.1,"time":240,"x":0.98,"y":0.64},{"intensity":0.1,"time":480,"x":0.6699999999999999,"y":0.75}],"visible":true}]}},"VestFront":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":480,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"FADE_OUT","pointList":[{"intensity":0.2,"time":0,"x":0.32999999999999996,"y":0.5},{"intensity":0.2,"time":240,"x":0.98,"y":0.6599999999999999},{"intensity":0.2,"time":480,"x":0.98,"y":0.6599999999999999}],"visible":true}]}}},"name":"Effect 1 copy 3","offsetTime":480,"startTime":163,"trackIndex":0},{"modes":{"VestBack":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":480,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"NONE","pointList":[{"intensity":0.1,"time":0,"x":0,"y":0.14},{"intensity":0.1,"time":240,"x":0,"y":0.14},{"intensity":0.1,"time":480,"x":0.17,"y":0.22999999999999998}],"visible":true}]}},"VestFront":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":480,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"FADE_OUT","pointList":[{"intensity":0.2,"time":0,"x":0.68,"y":0},{"intensity":0.2,"time":240,"x":0,"y":0.14},{"intensity":0.2,"time":480,"x":0,"y":0.14}],"visible":true}]}}},"name":"Effect 1 copy 4","offsetTime":480,"startTime":431,"trackIndex":0},{"modes":{"VestBack":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":274,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"NONE","pointList":[{"intensity":0.1,"time":0,"x":0.01,"y":0.64},{"intensity":0.1,"time":137,"x":0.02,"y":0.64},{"intensity":0.1,"time":274,"x":0.33,"y":0.75}],"visible":true}]}},"VestFront":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":274,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"FADE_OUT","pointList":[{"intensity":0.2,"time":0,"x":0.67,"y":0.5},{"intensity":0.2,"time":137,"x":0.02,"y":0.6599999999999999},{"intensity":0.2,"time":274,"x":0.02,"y":0.6599999999999999}],"visible":true}]}}},"name":"Effect 1 copy 5","offsetTime":274,"startTime":0,"trackIndex":0},{"modes":{"VestBack":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":614,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"NONE","pointList":[{"intensity":0.1,"time":0,"x":1,"y":0.38},{"intensity":0.1,"time":307,"x":1,"y":0.39},{"intensity":0.1,"time":614,"x":0.67,"y":0.49}],"visible":true}]}},"VestFront":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":614,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_TDM","playbackType":"FADE_OUT","pointList":[{"intensity":0.2,"time":0,"x":0.34,"y":0.25},{"intensity":0.2,"time":307,"x":0.98,"y":0.38},{"intensity":0.2,"time":614,"x":0.98,"y":0.38}],"visible":true}]}}},"name":"Effect 1 copy 7","offsetTime":614,"startTime":207,"trackIndex":0},{"modes":{"VestBack":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":800,"playbackType":"NONE","startTime":0,"pointList":[]}]},"mode":"PATH_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_SPEED","playbackType":"NONE","visible":true,"pointList":[]}]}},"VestFront":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":800,"playbackType":"FADE_IN_OUT","pointList":[{"index":1,"intensity":0.5},{"index":2,"intensity":0.5}],"startTime":0}]},"mode":"DOT_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_SPEED","playbackType":"NONE","visible":true,"pointList":[]}]}}},"name":"Effect 8 copy 1","offsetTime":800,"startTime":100,"trackIndex":0}],"enable":true}],"updatedAt":1616725869167},"durationMillis":0,"intervalMillis":20,"size":20} \ No newline at end of file diff --git a/java/com/drbeef/doom3quest/bhaptics/bHaptics.java b/java/com/drbeef/doom3quest/bhaptics/bHaptics.java index d29469d..928a57c 100644 --- a/java/com/drbeef/doom3quest/bhaptics/bHaptics.java +++ b/java/com/drbeef/doom3quest/bhaptics/bHaptics.java @@ -92,7 +92,7 @@ public class bHaptics { private static Map> eventToEffectKeyMap = new HashMap<>(); - private static Map repeatingHaptics = new HashMap<>(); + private static Map> repeatingHaptics = new HashMap<>(); public static void initialise() { @@ -162,11 +162,22 @@ public class bHaptics { registerFromAsset(context, "bHaptics/Interaction/Vest/Spark.tact", "spark", "environment"); registerFromAsset(context, "bHaptics/Interaction/Head/Spark.tact", PositionType.Head, "spark", "environment", 0.5f, 0.5f); - //Directional based place holder for looping steam pattern - registerFromAsset(context, "bHaptics/Interaction/Vest/Spark.tact", PositionType.Vest, "steam_loop", "environment", 0.5f, 0.25f); - eventToEffectKeyMap.get("steam_loop").elementAt(0).directional = true; + //Directional based looping steam pattern + registerFromAsset(context, "bHaptics/Interaction/Vest/Steam.tact", PositionType.Vest, "steam_loop", "environment", 0.5f, 1.0f); + registerFromAsset(context, "bHaptics/Interaction/Head/Steam.tact", PositionType.Head, "steam_loop", "environment", 0.5f, 1.0f); + eventToEffectKeyMap.get("steam_loop").forEach((haptic) -> { + haptic.directional = true; + }); - registerFromAsset(context, "bHaptics/Interaction/Vest/Spark.tact", "steam_blast", "environment"); + //Directional based looping flames pattern (use steam, but stronger) + registerFromAsset(context, "bHaptics/Interaction/Vest/Steam.tact", PositionType.Vest, "flame_loop", "environment", 1.0f, 1.0f); + registerFromAsset(context, "bHaptics/Interaction/Head/Steam.tact", PositionType.Head, "flame_loop", "environment", 1.0f, 1.0f); + eventToEffectKeyMap.get("flame_loop").forEach((haptic) -> { + haptic.directional = true; + }); + + //Re use the spark for the steam blast + registerFromAsset(context, "bHaptics/Interaction/Vest/Spark.tact", PositionType.Vest, "steam_blast", "environment", 1.0f, 0.25f); registerFromAsset(context, "bHaptics/Interaction/Vest/Body_PDA_Open.tact", "pda_open", "pda"); registerFromAsset(context, "bHaptics/Interaction/Vest/Body_PDA_Open.tact", "pda_close", "pda"); @@ -201,15 +212,15 @@ public class bHaptics { registerFromAsset(context, "bHaptics/Weapon/Arms/ReloadFinish_Mirror.tact", PositionType.ForearmL, "weapon_reload_finish", "weapon"); //Chainsaw Idle - registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV2.tact", PositionType.Right, "chainsaw_idle", "weapon"); + registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV1.tact", PositionType.Right, "chainsaw_idle", "weapon"); registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV2.tact", PositionType.ForearmR, "chainsaw_idle", "weapon"); - registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV2_Mirror.tact", PositionType.Left, "chainsaw_idle", "weapon"); + registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV1_Mirror.tact", PositionType.Left, "chainsaw_idle", "weapon"); registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV2_Mirror.tact", PositionType.ForearmL, "chainsaw_idle", "weapon"); //Chainsaw Fire - registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV1.tact", PositionType.Right, "chainsaw_fire", "weapon_fire"); + registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV2.tact", PositionType.Right, "chainsaw_fire", "weapon_fire"); registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV1.tact", PositionType.ForearmR, "chainsaw_fire", "weapon_fire"); - registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV1_Mirror.tact", PositionType.Left, "chainsaw_fire", "weapon_fire"); + registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV2_Mirror.tact", PositionType.Left, "chainsaw_fire", "weapon_fire"); registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV1_Mirror.tact", PositionType.ForearmL, "chainsaw_fire", "weapon_fire"); //Fist @@ -406,22 +417,28 @@ public class bHaptics { } } - public static void beginFrame() + public static void beginFrame() {} + + public static void endFrame() { - Vector toRemove = new Vector<>(); if (enabled && hasPairedDevice) { - repeatingHaptics.forEach((key, haptic) -> { - if (haptic.level == 0) { - if (player.isPlaying(haptic.altKey)) - { - player.turnOff(haptic.altKey); + repeatingHaptics.forEach((key, haptics) -> { + haptics.forEach((haptic) -> { + if (haptic.level < 10) { + if (player.isPlaying(haptic.altKey)) { + player.turnOff(haptic.altKey); + } + } else if (!player.isPlaying(haptic.altKey)) { + //If a repeating haptic isn't playing, start it again with last known values + float flIntensity = ((haptic.level / 100.0F) * haptic.intensity); + + if (haptic.type != PositionType.Head || + //If the haptic is head based, then only play if it is within a certain FOV + (haptic.rotation >= -360 && haptic.rotation <= -315) || (haptic.rotation >= 0 && haptic.rotation <= 45)) { + player.submitRegistered(haptic.key, haptic.altKey, flIntensity, haptic.duration, haptic.rotation, 0); + } } - } - else if (!player.isPlaying(haptic.altKey)) { - //If a repeating haptic isn't playing, start it again with last known values - float flIntensity = ((haptic.level / 100.0F) * haptic.intensity); - player.submitRegistered(haptic.key, haptic.altKey, flIntensity, haptic.duration, haptic.rotation, 0); - } + }); }); } else @@ -430,8 +447,6 @@ public class bHaptics { } } - public static void endFrame() {} - /* position values: 0 - Will play on vest and both arms if tactosy tact files present for both @@ -558,7 +573,18 @@ public class bHaptics { } repeatingHaptic.level = intensity; - repeatingHaptics.put(key, repeatingHaptic); + + if (!repeatingHaptics.containsKey(key)) + { + Vector v = new Vector<>(); + v.add(repeatingHaptic); + repeatingHaptics.put(key, v); + } + else + { + Vector v = repeatingHaptics.get(key); + v.add(repeatingHaptic); + } } else { player.submitRegistered(haptic.key, haptic.altKey, flIntensity, flDuration, flAngle, yHeight); @@ -637,6 +663,10 @@ public class bHaptics { { key = "spark"; } + else if (key.contains("flames") || key.contains("propane") || key.contains("burning")) + { + key = "flame_loop"; + } else if (key.contains("steam")) { if (key.contains("blast") || key.contains("shot") || key.contains("chuff")) { @@ -667,8 +697,9 @@ public class bHaptics { if (repeatingHaptics.containsKey(key)) { - Haptic haptic = repeatingHaptics.get(key); - player.turnOff(haptic.altKey); + repeatingHaptics.get(key).forEach((haptic) -> { + player.turnOff(haptic.altKey); + }); repeatingHaptics.remove(key); } @@ -683,12 +714,13 @@ public class bHaptics { if (repeatingHaptics.containsKey(key)) { - Haptic haptic = repeatingHaptics.get(key); - if (haptic.directional) { - haptic.rotation = angle; - } + repeatingHaptics.get(key).forEach((haptic) -> { + if (haptic.directional) { + haptic.rotation = angle; + } - haptic.level = intensity; + haptic.level = intensity; + }); } } }