
CustomEmotesAPI
API for adding emotes to survivors, reuploaded with permission
Last updated | 3 years ago |
Total downloads | 343 |
Total rating | 0 |
Categories | Libraries Client-side Server-side Emotes |
Dependency string | Temporary_Team_Name_Please_Ignore-CustomEmotesAPI-1.5.4 |
Dependants | 0 other packages depend on this package |
This mod requires the following mods to function

bbepis-BepInExPack
Unified BepInEx all-in-one modding pack - plugin framework, detour library
Preferred version: 5.4.1903
Rune580-Risk_Of_Options
A convenient API for adding BepInEx ConfigEntry's to a option menu
Preferred version: 2.3.0
README
IMPORTANT
-
Reuploaded to Thunderstore with permission from MetrosexualFruitcake.
-
This does nothing on without other mods. Please don't download this on it's own and complain to me unless you really want to.
-
Join the BadAssEmotes/EmotesAPI discord https://discord.gg/3kXkVkNDxs
-
If you are unsure how to do animations, go to Settings->ModSettings->CustomEmotesAPI. From here you can customize your emote wheels and see keybinds.
How to implement
First off, if you are at all confused about any of this, I made a repo with example implementations. https://github.com/ToastedOven/ExampleEmotePlugin Also BadAssEmotes exists if you want to look at a more complete mod. https://github.com/ToastedOven/BadAssEmotes
General Overview
Start here if you are lost
-
Create a humanoid animation in unity and import it into your plugin project.
-
In your project, Import the CustomEmotesAPI dll file and include
using EmotesAPI;
in your cs file. -
Place
CustomEmotesAPI.AddCustomAnimation(AnimationClip, false);
somewhere in your awake call. Where AnimationClip is the animation clip you imported from unity. -
If done correctly, this will load the animation into the list of available emotes. Feel free to change the bool to
true
and import a looping animation as well. -
You can also import custom survivors with
CustomEmotesAPI.ImportArmature(bodyPrefab, underskeleton)
Underskeleton is a copy of the bodyPrefab which is setup as a humanoid skeleton -
https://youtu.be/c_G3G4RzCFA a walkthrough of importing a bodyprefab into game. All vanilla survivors are already imported, this is for modded characters
AddCustomAnimation Params
AnimationClip[] animationClip //Default animation Can also use a non-array here if you just have one animation
bool looping //Whether or not animationClip loops
string[] _wwiseEventName = null //Events to post when animation starts consider using Volume_Emotes (0-100, default 50) in your wwise events
string[] _wwiseStopEvent = null //Events to post when animation stops, you should only need one stop event, but just in case of some edge case you get a full array. Make sure to set the same amount of stop events as start events.
HumanBodyBones[] rootBonesToIgnore = null //All bones specified and any child bones will be ignored by the animation
HumanBodyBones[] soloBonesToIgnore = null //All bones specified will be ignored by the animation
AnimationClip[] secondaryAnimation = null //Animation to play after the primary animation. Use this if you have a non-looping-into-looping animation. animationClip.Length must equal secondaryAnimation.Length or else you will have errors. Can also use a non-array here if you just have one animation
bool dimWhenClose = false //Create an audio dimming sphere around the emotee which will dim normal music when you approach them
bool stopWhenMove = false //Stops the animation if moving
bool stopWhenAttack = false //Stops the animation if attacking
bool visible = true //Dictates if emote will show up in the normal list.
bool syncAnim = false //Dictates if emote will sync the animation.
bool syncAudio = false //Dictates if emote will sync audio (requires wwise start and stop events)
int startPref = -1 //Determines which spot in the clip arrays a user will always play if they start a syncing animation, -1 is random -2 is sequential
int joinPref = -1 //Determines which spot in the clip arrays a user will always play if they join a syncing animation, -1 is random -2 is sequential
JoinSpot[] joinSpots = null //Places join spots will be created when animation is played
Regiserting World Props
-
Declare an int to keep track of your world prop's position
-
Call RegisterWorldProp as so: propInt = CustomEmotesAPI.RegisterWorldProp(propGameObject, new JoinSpot[] { propJoinSpot });
-
Spawn your world prop with if (NetworkServer.active) { gameObject = CustomEmotesAPI.SpawnWorldProp(propInt); }
-
Spawn your object for all clients with if (NetworkServer.active) { NetworkServer.Spawn(gameObject); }
Setting up Emote Spots
public struct JoinSpot
public string name;
public Vector3 position; //these should all be relative to whatever you plan to parent said JoinSpot to
public Vector3 rotation;
public Vector3 scale;
Emote Spot Joined
-
There are two events you can hook into for emote spots, emoteSpotJoined_Prop and emoteSpotJoined_Body. One for world props, the other for survivors and such.
-
Here's an example for joining a prop
private void CustomEmotesAPI_emoteSpotJoined_Prop(GameObject emoteSpot, BoneMapper joiner, BoneMapper host) { string emoteSpotName = emoteSpot.name; if (emoteSpotName.StartsWith("VengaBusDoor")) //checking if the emoteSpot is correct { joiner.PlayAnim("vengaBusSit", 0); //playing a sit animation Venga.JoinBus(joiner); //executing code on the prop's end with the joiner in mind. } }
-
Here's an example for joining another player
private void CustomEmotesAPI_emoteSpotJoined_Body(GameObject emoteSpot, BoneMapper joiner, BoneMapper host) { string emoteSpotName = emoteSpot.name; if (emoteSpotName == "StandingHereJoinSpot") { joiner.PlayAnim("StandingHere", 0); GameObject g = new GameObject(); g.name = "StandingHereProp"; joiner.props.Add(g); g.transform.SetParent(host.transform); Vector3 scal = host.transform.lossyScale; g.transform.localPosition = new Vector3(0, 0, .75f / scal.z); g.transform.localEulerAngles = new Vector3(0, 140, 0); g.transform.localScale = new Vector3(.8f, .8f, .8f); joiner.AssignParentGameObject(g, true, true, true); //public void AssignParentGameObject(GameObject youAreTheFather, bool lockPosition, bool lockRotation, bool lockScale, bool scaleAsBandit = true, bool disableCollider = true) emoteSpot.GetComponent<EmoteLocation>().SetEmoterAndHideLocation(joiner); // Basically just for hiding emote join spots. Primarily for if any given emote spot only supports one player at a time. } }
-
Just to reiterate, if you need any help with this, feel free to reach out to me on Discord.
Examples
- loops first anim, has a start and stop wwise event, dims audio when close
CustomEmotesAPI.AddCustomAnimation(loserAnimClip, true, "Loser", "LoserStop", dimWhenClose: true);
- doesn't loop first anim, secondary anim which loops
CustomEmotesAPI.AddCustomAnimation(spinStartAnimClip, false, secondaryAnimation: spinLoopAnimClip);
- Creates 2 HumanBodyBone lists for ignoring bones in the animation, doesn't loop first anim, has a start and stop wwise event, includes previously created HumanBodyBone lists
HumanBodyBones[] upperLegs = new HumanBodyBones[] { HumanBodyBones.LeftUpperLeg, HumanBodyBones.RightUpperLeg };
HumanBodyBones[] hips = new HumanBodyBones[] { HumanBodyBones.Hips };
CustomEmotesAPI.AddCustomAnimation(dabAnimClip, false, "Dab", "DabStop", upperLegs, hips);
- After subscribing to the CustomEmotesAPI.animChanged event, when you play one of your animations, call mapper.props.Add(propGameObject), set propGameObject's transform to mapper.transform.parent, then call mapper.ScaleProps() and mapper.SetAutoWalk(3, true). This will cause the prop that spawns to scale with the survivor and then cause you to auto walk slowly while the animation is playing.
If you're still lost, consider srolling up and cloning from the example repo or @ me on Discord @Metrosexual Fruitcake#6969
Changelog
-
Version 1.5.4: Fixed joinspots not always getting deleted, probably fixed audio passing between stages randomly.
-
Version 1.5.3: Actually did it, OOOOOPS
-
Version 1.5.2: Added a BlackListEmote function for mod devs. This is a temporary fix until Rune finishes the UI overhaul, but it prevents an emote from being in random.
-
Version 1.5.1: Updated visuals for JoinSpots
-
Version 1.5.0: Added ability to have emotes be sequential (player 1 gets emoteA, player 2 gets emoteB, player 3 gets emoteC, etc...) You can implement this by having your join/start pref be -2. Added world props as an option. Added join spots as an option when setting up an emote or world props. Added emote rigs for Jinx and Soldier.
-
Version 1.4.0: Fixed errors with upcoming mods. Removed Brass Contraption emote skeleton temporarily, will be readded when I suck less. Added support for auto-walking during animations (BoneMapper.SetAutoWalk()) and scaling of props based of bandit, aka scale your props with bandit for best results. (BoneMapper.ScaleProps()) not perfect but works most of the time. Added support for multiple audio events for an animation. This is unneeded if you don't sync your animation since you can just do the randomiztion in wwise. Probably fixed emote syncing.
-
Version 1.3.6: Fixed incompatibility with my own mod because I am a dumbass.
-
Version 1.3.5: Fixed issue with props being immediately deleted.
-
Version 1.3.4: Fixed some of the underlying code, now properly allowing enemy injections without any issue (probably). As part of this, you can now call PlayAnimation on a specific BoneMapper.
-
Version 1.3.3: Phoenix Wright and Scout (he already tposes around, I know he jank so dont @ me). Removed Dancer's experimental rig as it is now official supported by the mod creator. Added toggles for all experimental rigs under Mod Settings/BepinExConfig.
-
Version 1.3.2: Added a toggle for Aurelion Sol in Mod Settings. He is very bug but still works if you really want that.
-
Version 1.3.1: Added Dancer support. Fixed issue where a handfull of modded survivors wouldn't animate if they were a lobby player. Fixed conflict when Paladin has his cape turned on. Also added a fun toy for you animation creators, each BoneMapper now has a list of gameobjects called "props" which you can access, these are automatically cleared whenever an animation ends, so feel free to do with that as you will. I should really fix my documentation..........
-
Version 1.3.0: Fixed Artificer and Void Fiend not animating normally. Added the following emote skeletons: The House, Henry, Aurelion Sol (damn boi he ugly), Katarina, Miner
-
Version 1.2.3: The "Fine, I'll do it myself" update. Added emote skeletons for the following mods: Paladin, Enforcer/NemEnforcer, Chef, Holomancer, Sett, and Tracer. If any of these mod creators want to do it on their side, lemme know and I can remove it from here.
-
Version 1.2.2: Fixed animations with an intro and loop, not playing the loop. Ooooops
-
Version 1.2.1: Fixed default binds for the new buttons which I totally forgot about, please understand. Please rebind these if you downloaded 1.2.0
-
Version 1.2.0: Made a change to how animations are imported, you WILL need to update your mods. If you are a mod dev, you should only need to recompile and you'll be good.
-
Version 1.1.10: Changed the bone loading mode to accomidate certain models that add bones in ways not previously accounted for, this "should" be the last time this needs to be done.
-
Version 1.1.9: Fixed footIK for emotes, everything will now be 10% less floaty.
-
Version 1.1.8: Fixed a incompatibility with other mods that add bones inside of existing rigs.
-
Version 1.1.7: Fixed issue where audio syncs didn't get deleted if multiple people are performing the same emote when someone dies.
-
Version 1.1.6: Touched up commando's import model, it was the first one I ever did so his feet were kinda wack. Removed the auto rigging feature as I have already noticed serious potential problems it could cause in some survivors. It only worked on a couple of mods anyway.
-
Version 1.1.5: Fixed issue with resolution scaling causing you to be stuck in the emote picker wheel. Added a sfx slider which I encourage everyone importing emotes to use if you have sound. The RTPC value is Volume_Emotes and it ranges from 0 to 100, starting at 50
-
Version 1.1.4: Added advanced, experimental, rocket science, galaxy brain technology that will usually not work. But in some cases like with Sett, it will auto generate an animation rig if one isn't present. Fixed an issue with emotes getting desynced upon a player dying.
-
Version 1.1.3: Fixed crippling performance from last patch. Hopefully everything is sorted for real this time. Admittidly the method is a bit jank. My apolocheese
-
Version 1.1.2: Fixed the fix because I suck at coding :)
-
Version 1.1.1: Fixed incompatibility issue with AutoSprintMod.
-
Version 1.1.0: Fixed issue with less than perfect connections causing the emotewheel to lock up. Added the ability to sync audio and animation position of emotes. This changes how you import anim files. If anyone is currently working on an animation pack, you need to download the latest version and use it as a reference for your project.
-
Version 1.0.1: Fixed error with armature importing. You shouldn't have to change anything on your end.
-
Version 1.0.0: Initial Release