Most of these “outfits” you mentioned can be ignored. You just need to filter out the specifc animation part you want to call a script for.
In the game Milking Farm I filtered for specific strings, based on what the animations are named and am intercepting sprite animations, as well as CG Images. So you can check that plugin as reference.
Live2D animations can be a bit tricky. You can again ignore most variables (shapes, sizes, outfit) that are called alongside them and just focus on the model animation.
I’m still new to this myself, so there might be a better way, but I found that it’s possible to listen to certain events and then detect what Live2D animation is playing based on that.
For the game The Evil Guards of the Merchant City, this could look something like this:
(simple base example)
// Hook into common event execution
var _Game_Interpreter_setup = Game_Interpreter.prototype.setup;
Game_Interpreter.prototype.setup = function(list, eventId) {
_Game_Interpreter_setup.call(this, list, eventId);
this._eventId = eventId; // Store the current event ID
if (this.isOnCurrentMap()) {
for (var i = 0; i < list.length; i++) {
var command = list[i];
if (command.code === 117) { // Call Common Event
var commonEventId = command.parameters[0];
var commonEvent = $dataCommonEvents[commonEventId];
if (commonEvent) {
var eventName = commonEvent.name;
if (eventName.startsWith("※") || eventName.endsWith("✔")) {
logToFile('Event Name:' + eventName); //replace with your function
}
}
}
}
}
};
// Hook into sub events
var old_Game_Interpreter_prototype_pluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command, args) {
old_Game_Interpreter_prototype_pluginCommand.call(this, command, args);
var eventId = this._eventId; // Get the current event ID
var event = $gameMap.event(eventId); // Get the event object
//strings to filter for (might need to be adjusted); "CG" to check Live2D Model group
var regex = /^(CG|BJ|DS|NP|SA|\$v120|TJ|BS|Again).*$/;
if (event) {
if (regex.test(args[1]) || (/^FR$/.test(args))){
logToFile('Info:' + args); //replace with your function
}
}
};
Which is then able to detect what Live2D animation is playing, as well as the sub-scene/stage:
Where “SA” and similar variables indicate the stage
(in most cases it looks like 1=init, 2=SpeedNormal, 3=SpeedFast, 4=SpeedFastest, 5=Finish).
The annoying part in this case, is that you need to assign these names to the right animation.
I would suggest going into the unlocked in-game gallery, see what name is detected for each animation and then saving the script with the same name.
This one is actually simpler, since it uses video files in the “www\movies” folder.
Most of them can be filtered out / redirected, since they’re duplicates and would be using the same script.
You can just script these videos directly and then intercept them like this:
(code example)
player = new Player();
var MoviePicture_loadVideo = Sprite_Picture.prototype.loadVideo;
Sprite_Picture.prototype.loadVideo = function () {
MoviePicture_loadVideo.apply(this, arguments);
this._scriptName = this._pictureName
//.replace() Custom string adjustment
this._scriptRunning = true;
this._seeked = false;
this.bitmap._video.addEventListener(
'seeked',
function () {
if (this._scriptRunning) { //add custom name filter here as well
logToFile('start: ' + this._scriptName); //replace with your function
this._seeked = true;
}
}.bind(this))
}
const MoviePicture_updateVideo = Sprite_Picture.prototype.updateVideo;
Sprite_Picture.prototype.updateVideo = function () {
if (!this.isVideoPicture()) {
if (this._scriptRunning) {
this._scriptRunning = false;
logToFile('stop'); //replace with your function
}
}
MoviePicture_updateVideo.apply(this, arguments);
}
player.refresh();
To detect the video names played: