What player is a modified version of buttplug?
Thank you for sharing the extra details; they were really helpful.
I managed to implement EDI successfully into my latest game integration. Iāve also included some infos and comments in the code, for those who are interested.
True to its name, using EDI was rather straightforward and the extra features it offers, are great.
I do have a few remarks and possible requests based on what I noticed tho:
-
It appears that when the āReload Galleryā option is used (more than once), the program stops responding or crashes.
-
It would be great to have some logging functionality. For instance, in FunscriptPlayer, there was at least a āStatusā message that showed the name that the injected code was able to pull, or whether it was detecting anything at all. I have now integrated a local logging for the detected gallery names and EDI-Server requests, but it would be nice to have something like this natively integrated, maybe in the Swagger UI.
-
Another small idea is to have a different ādefinitions.csvā file for each gallery variant. The way I see it, EDI offers three main scripting approaches for the gallery:
a. Combining all scenes into a single video and making a long script.
b. Dividing the script into multiple parts (like one for each game stage).
c. Making several smaller scripts for each animation.
Since different users might prefer different scripting methods for the same game, having separate .csv files for each variant ensures all versions can be used.
There are many games that already have most of their animations as separate video files. So I was able to create an automation script that generates the .csv file and allows for each case to be easily generated as well. -
Probably an issue with the transmission limitation, but if a bluetooth connection is used and the script is too detailed, it will cause big delays on the EDI itself, where even the processing of the http calls (start/stop, ect.) will lag behind and are perform later than they should.
-
The āpauseā function stops the device, but actually continues playing the script in the background, essentially skipping parts of it, instead of completely staying idle. Iām not sure if thatās intentional.
The current issue with this is, if the pause duration lasts longer than the actual script duration for that part, EDI will crash. Iām guessing since the pause only stops the playback and not the script seeking, when it tries to resume, it calls a seek time that doesnāt exist and the program doesnāt like that.
Regardless, the function itself can be useful in some cases, but would need to be fixed, and having an option to completely halt the script temporarily and then seamlessly resume where it left off, would be great as well (especially for game pausing, etc.).
Thanks again for this awesome tool. Iām looking forward to hopefully seeing more game integrations with it soon
So after several hours (and days) I have figured out how to make these however my time is extremely limited until later in like two months when all the projects are done.
While looking over some old games and whatnot, figuring out how to get these and call to these animations I was kinda confused about some things. Most games people have done are limited to one set of animations because one outfit so to speak however 2 of them i started to record and splice, they have several outfits and/or Live2D and I have no idea what the animation calls out toā¦ Iāve given up on The Evil Guards of the Merchant City (RJ335038) as I think its too complex for me atm since it has a variety of shapes, sizes, outfit and started on a small RPGM game Iāve been able to figure out thats only had some small sets of animations and think thats going well. Was thinking about renpāy games since iāve been providing alot of art/skin edits and that seems simple enough. (i think)
Anyhow, is there any advice on handling record/scripting and calling out to multiple outfits? do script one and be done or record one and I suppose call out to the other variants with a copy of the same .funscript?
I would also like to know as I planned on taking a shot at doing āThe Dead End ~The Maidens and the Cursed Labyrinth~ ALL IN ONE EDITION (RJ284359)ā.
Anyway to use this to connect to genesis order? I found the .js file for Lovense integration in the Genesis Order files.
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:
Thanks for the explanation! Iāll prob pick it back up another time because that game has more content then I think I can manage. As for now im reverting back to something simple/smallerā¦ Some games with a video folder or sprite sheet make it quite easy, so far that I ended up looking back at an old game and viola, I was able to get like one part of it to work, opposed to games that have split pieces, parts, hairs etc because Im still learning on what to label some animations. My whole endgame is to learn L2D ones, they seem more complex but offer more options
Im more of a video/reverse engineering kinda learning person so most of my learning, fun-scripting has been learned from previous samples/work. Once im confident enough and my SR6 finally gets to me I can take bigger/more fun projects and share (self conscious of my own work heh)
Again thanks for the explanation!
Iāve had this issue with a few games using EDI. Appreciate the work thatās gone into this, but when I load a game with this integration, it works but after about like 12 seconds itāll just crash, or quit out with no error, and I have to restart it, making it kinda completely broken for me unfortunately.
Any idea what could be causing this? Using .net 6 ādotnet-sdk-6.0.415-win-x64ā on Windows 10. On a fresh install too, was having this issue before on my old machine as well.
Can I ask a stupid question!
On the settings for this I assume to setup I simply add my handy key into that box and leave the iniface url as ws://localhost:12345 ?
I cant seem to connect / see no devices?
If I start a game with it open - i can see its getting commands passed to EDI but my handy does nothing
Thank you and apologies for the noob question
@easycarry did you get this resolved? Iām having the same issue, but mine just closes after a minute of use.
I logged on this morning thought would have another go and mine has started doing the same just closing after a minute.
looking in log seems like .net isnt happy saying request address is not valid. Just starting to troubleshoot so will update if I find anything.
tried re-downloading with the demo files - it opened and didnt auto close.
i added handy key - nothing happened tried reconnect nothing. If i go into swagger via the link it would pass a command.
closed the app - just re-launched and back to it auto closing again after a minute
Okay found my issue! NordVPN must be killing it or conflicting!
I just disconnected my vpn and straight away
@easycarry \ @cloudviiv I dont know if either of you have vpn or anything filtering your traffic in anyway but the crashes and it detecting my handy all okay when disconnected vpn connection.
adding a rule in to work around that.
So after testing I found that my problem occurs when I attach multiple devices to edi (specifically my SR6 & diamo). Itās as if itās crashed due to too much info or something. Whenever I use my SR6 alone though it works just fine.
hello i am working on this.
hey thanks for the feedback, try this new version let me know if it worked well for you
Thanks for your continuous development!
Could you provide some more details regarding the latest features?
Iām especially interested in the points āHandy bluetooth PrecisiĆ³nā, āCommand Delay in Config,ā and āAdd ready colum in devices gridā.
How do these options work exactly?
Also, I noticed that the .zip variant without the videos still has the older EDI version. Maybe you can update that one as well.
i Basically refactor the command sending logic so that they do not overlap. and are always managed from individual threads.
in the edi config
ābuttplugā: {
āUrlā: āws://localhost:12345ā,
āCommandDelayā: 50
},
The vibrators and osilators send commands every 50ml while the handy sends one command at a time and if the command lasts less than 50mliseconds it skips it. It also adjusts command timings so that they are always sent with the correct milliseconds based on the current millisecond so you never get out of sync.
yes, I have to update those links and update the tutorial too.
since now you can get the definitions from the funscript chapters
Hey, just to mention - downloaded the new version - initial tests seem fine. It caused Avast to go nuts in wanting to block it have added an exception and still have the one in nordvpn. Seems to work fine in an initial try out