Skip to content

Commit

Permalink
initial release of NPC animation notifier
Browse files Browse the repository at this point in the history
  • Loading branch information
usa-usa-usa-usa committed Sep 7, 2024
1 parent 5930d99 commit 88dd1a3
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 83 deletions.
58 changes: 56 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,56 @@
# Example
An example greeter plugin
# NPC Animation Notifier Plugin
The **NPC Animation Notifier Plugin** allows users to configure notifications for specific NPC animations in RuneLite. By specifying NPC IDs, animation IDs, and custom names, the plugin will alert you whenever the selected NPCs perform the defined animations.


## Configuring the Plugin

You need to configure the plugin by specifying the NPC ID, animation ID, and a custom name for each animation you want to track.

Within the plugin settings, enter NPC and animation details in the following format (each on a new line):
- **NPC_ID**: The ID of the NPC you want to monitor.
- **Animation_ID**: The ID of the specific animation performed by the NPC.
- **Custom_Animation_Name**: A custom name for the animation (required). This name will be shown in notifications instead of the animation ID.

**Example**

<NPC_ID>,<Animation_ID>,<Custom_Animation_Name>

NOTE: All three fields (NPC ID, Animation ID, and Custom Animation Name) are required for each entry.
If any field is missing, the plugin will not function properly for that entry.

Example:

8615,9111,Hydra Switch
8619,9112,Hydra Switch
8620,9113,Hydra Switch


## Finding NPC and Animation IDs

To find NPC IDs and Animation IDs, I recommend using the **Identificator Plugin** from the Plugin Hub:

- [Identificator Plugin on RuneLite](https://runelite.net/plugin-hub/show/identificator)

This plugin helps you identify NPCs and animations by hovering over the NPCs in-game and displaying their IDs.

## Handling Input Errors

If you malform the input in the configuration, the plugin will **ignore** the invalid entries and continue to process correctly formatted ones. Here's how errors are handled:

- **Missing fields**: If any of the NPC ID, Animation ID, or Custom Animation Name is missing from an entry, that line will be ignored.
- **Invalid numbers**: If an NPC ID or Animation ID is not a valid integer, that entry will also be ignored.
- **Empty or incomplete lines**: These will be skipped by the plugin without affecting other valid entries.

Make sure that each entry follows the correct format to avoid missing notifications.

## Frequently Asked Questions (FAQ)

### Q: What happens if I leave out the NPC ID, Animation ID, or Custom Animation Name?
A: The plugin will ignore any entries that do not contain all three fields. You must enter all three values for each line.

### Q: How do I find the NPC and Animation IDs?
A: You can use the **Identificator Plugin** to easily find NPC and Animation IDs by hovering over NPCs in-game.

### Q: Can I track multiple animations for a single NPC?
A: Yes! You can add multiple lines with the same NPC ID and different Animation IDs if you want to track several animations for the same NPC.

2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies {
testImplementation group: 'net.runelite', name:'jshell', version: runeLiteVersion
}

group = 'com.example'
group = 'com.hydrahelper'
version = '1.0-SNAPSHOT'

tasks.withType(JavaCompile) {
Expand Down
Binary file added icon.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 6 additions & 5 deletions runelite-plugin.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
displayName=Example
author=Nobody
description=An example greeter plugin
tags=
plugins=com.example.ExamplePlugin
displayName=NPC Animation Notifier
author=usa-usa-usa-usa
support=https://github.com/usa-usa-usa-usa/usas-plugins/tree/NPCAnimationNotifier
description=Get chat notifications when NPCs perform an animation
tags=NPC, animation, notification, helper
plugins=com.npcanimationnotifier.NPCAnimationNotifierPlugin
19 changes: 0 additions & 19 deletions src/main/java/com/example/ExampleConfig.java

This file was deleted.

53 changes: 0 additions & 53 deletions src/main/java/com/example/ExamplePlugin.java

This file was deleted.

42 changes: 42 additions & 0 deletions src/main/java/com/npcanimationnotifier/AnimationData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.npcanimationnotifier;


public class AnimationData
{
private final int animationId;
private final String animationName;

private final int npcId;

public AnimationData(int npcId, int animationId, String animationName)
{
this.npcId = npcId;
this.animationId = animationId;
this.animationName = animationName;
}

public int getAnimationId()
{
return animationId;
}

public String getAnimationName()
{
return animationName;
}

public int getNpcId()
{
return npcId;
}

@Override
public String toString()
{
return "AnimationData{" +
"npcId=" + npcId +
", animationId=" + animationId +
", animationName='" + animationName + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.npcanimationnotifier;

import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;

@ConfigGroup("npcAnimationNotifier")
public interface NPCAnimationNotifierConfig extends Config
{
@ConfigItem(
keyName = "npcAnimationDefinition",
name = "NPC Animations",
description = "Enter NPC ID, Animation ID, and Animation Name (you name it yourself)<br>Separated by a comma - ex. '1234,9999,The Griddy'<br> Add a new line for each new NPC"
)
default String npcAnimationDefinition()
{
return "";
}
}
130 changes: 130 additions & 0 deletions src/main/java/com/npcanimationnotifier/NPCAnimationNotifierPlugin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.npcanimationnotifier;

import javax.inject.Inject;
import com.google.inject.Provides;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.*;
import net.runelite.api.events.GameTick;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.Notifier;

import java.util.*;
import java.util.stream.StreamSupport;

@Slf4j
@PluginDescriptor(
name = "NPC Animation Notifier"
)
public class NPCAnimationNotifierPlugin extends Plugin
{
private List<AnimationData> npcAnimationList;
private int currentAnimation;
private int previousAnimation;

@Inject
private Client client;

@Inject
private Notifier notifier;

@Inject
private NPCAnimationNotifierConfig config;


@Override
protected void startUp() throws Exception
{
log.info("Loading animation map");
loadNpcAnimationMap();
}

@Override
protected void shutDown() throws Exception
{
log.info("Clearing animation map");
npcAnimationList.clear();
}

@Provides
NPCAnimationNotifierConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(NPCAnimationNotifierConfig.class);
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (event.getKey().equals("npcAnimationDefinition"))
{
log.info("Animation definition changed");
loadNpcAnimationMap();
}
}

@Subscribe
public void onGameTick(GameTick event)
{
WorldView worldView = client.getTopLevelWorldView();

StreamSupport.stream(worldView.npcs().spliterator(), false)
.filter(npc -> npc != null)
.forEach(npc -> {
npcAnimationList.stream()
.filter(data -> data.getNpcId() == npc.getId())
.forEach(data -> handleNpc(npc, data));
});
}

private void handleNpc(NPC npc, AnimationData animationData)
{
previousAnimation = currentAnimation;
currentAnimation = npc.getAnimation();

if (currentAnimation == animationData.getAnimationId() && currentAnimation != previousAnimation)
{
String logMessage = String.format("%s[%d] is performing animation %s[%s]!", npc.getName(), npc.getId(), animationData.getAnimationName(), animationData.getAnimationId());
String notifyMessage = String.format("%s is performing %s!", npc.getName(), animationData.getAnimationName());

log.info(logMessage);
notifier.notify(notifyMessage);
}
}

private void loadNpcAnimationMap()
{
String configInput = config.npcAnimationDefinition();
npcAnimationList = parseNpcAnimationPairs(configInput);
}

private List<AnimationData> parseNpcAnimationPairs(String configInput)
{
List<AnimationData> npcAnimationList = new ArrayList<>();

String[] rows = configInput.split("\n");

for (String row : rows)
{
String[] parts = row.split(",");
if (parts.length >= 3)
{
try
{
int npcId = Integer.parseInt(parts[0].trim());
int animationId = Integer.parseInt(parts[1].trim());
String animationName = parts[2].trim();

npcAnimationList.add(new AnimationData(npcId, animationId, animationName));
}
catch (NumberFormatException e)
{
log.error("Invalid NPC or Animation ID format: {}", row, e);
}
}
}

return npcAnimationList;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.example;
package com.npcanimationnotifier;

import net.runelite.client.RuneLite;
import net.runelite.client.externalplugins.ExternalPluginManager;

public class ExamplePluginTest
public class NPCAnimationNotifierPluginTest
{
public static void main(String[] args) throws Exception
{
ExternalPluginManager.loadBuiltin(ExamplePlugin.class);
ExternalPluginManager.loadBuiltin(NPCAnimationNotifierPlugin.class);
RuneLite.main(args);
}
}

0 comments on commit 88dd1a3

Please sign in to comment.