This was made to demonstrate using actionscript programming with conventional clothing modding
this is a loader mod, but can be used in vanilla with no noticeable difference. The download includes the source fla project for further reference.
mod does not change skin color, alternate color used to demonstrate features
The buttplug occasionally moves outward to make it look like she is trying to push it out of her anus, follows the anklecuffs colorslider.
The skin on the stretched anus part follows the skin hsl and also adjusts to skin tone selection.
The position and angle of the buttplug changes based on her leg angles, so this provides a good target if looking to get anal animtools positions looking good (i know some positions included with animtools have sloppy angles)
for moreclothing stuff, this is a body mod, example:
flexingbuttplug11.swf=Flexing Buttplug:Body>Body3
heres the code for setting up the mod to be able to reference the top level 'g' object in SDT while covering the various ways the mod can be loaded:
this is a loader mod, but can be used in vanilla with no noticeable difference. The download includes the source fla project for further reference.
mod does not change skin color, alternate color used to demonstrate features
The buttplug occasionally moves outward to make it look like she is trying to push it out of her anus, follows the anklecuffs colorslider.
The skin on the stretched anus part follows the skin hsl and also adjusts to skin tone selection.
The position and angle of the buttplug changes based on her leg angles, so this provides a good target if looking to get anal animtools positions looking good (i know some positions included with animtools have sloppy angles)
for moreclothing stuff, this is a body mod, example:
flexingbuttplug11.swf=Flexing Buttplug:Body>Body3
heres the code for setting up the mod to be able to reference the top level 'g' object in SDT while covering the various ways the mod can be loaded:
Code:
import SDTMods.*;
import flash.display.Loader;
import flash.system.ApplicationDomain;
import flash.geom.ColorTransform;
var loader, g, lProxy;
var loadermode:Boolean = false;
var registeredinmoreclothing:Boolean = false;
//my variables
var counter:Number = 0;
var timer:int = 0;
var timer2:int = 0;
var speed:Number = 3;
var delay:Number = 10;
var delay2:Number = 0;
var scale:Number = 0;
//charData = "";
modName = "Flexing Buttplug";
modCreator = "sby";
registerMod(bottoms);
//Choose a modpiece to be used in evaluation code to determine if the mod has been cleared. this should probably be one of the mods that makes use of any custom code added in proxies/listeners
//when loaded through a char folder, that individual mod piece could be cleared from using the clothing menu. if you have multiple pieces of clothing using different listeners, it might be better to have multiple evaluation functions with separate reset functions.
var evaluationModpiece = bottoms.backside;
var evaluationParent = evaluationModpiece.parent;
var myAppDomain = ApplicationDomain.currentDomain; //depending on how the mod is loaded, this may not be the sdt application domain
if(myAppDomain.hasDefinition("g")) //this occurs twice with loader characterfolder processing, and in vanilla SDT
{
g = myAppDomain.getDefinition("g");
var variablewaspublic:Boolean = false;
try
{
g.her.breathingFactor; //this is private in vanilla, will cause an error to be thrown
variablewaspublic = true;
}
catch(e) {
variablewaspublic = false;
}
if(variablewaspublic) //if the tested variable was publically accessable, then that means we are in the loader
{ //charfolder load in loader
loader = g.inGameMenu.helpMenu.getChildAt(0).loader; //this is a reference to the loader object placed on the helpMenu aka the loader menu in-game
lProxy = loader.lDOM.getDefinition("Modules.lProxy");
loadermode = true;
finishinit();
}
else
{ //swf load in vanilla
loadermode = false;
finishinit();
}
}
function initl(l){
loader = l;
g = l.g;
lProxy = loader.lDOM.getDefinition("Modules.lProxy");
loadermode = true;
finishinit();
loader.unloadMod();
}
function finishinit()
{
if(loadermode)
{
if(loader.moreclothing && loader.moreclothing.modactive)
{
registeredinmoreclothing = true; //assume if this mod is loaded while moreclothing is processing mods, that we have been added to moreclothing
}
}
if(loadermode && !registeredinmoreclothing) loader.registerUnloadFunction(myResetFunction);
//add supplemental setup code here,
//use checks of 'if(loadermode)' to seperate out things that can only be done in the loader
//the vanilla game object 'g' is available at this point, where you can then get other things like g.her and g.him
//if using the loader, references to the top level loader object 'loader', and the loader proxy class 'lProxy' are available at this point
bottoms.addEventListener(Event.ENTER_FRAME, frameRefresh);
//you will want the function 'evaluateModStatus' called in something you register for the purpose of code cleanup, in this case it is done under this framerefresh.
}
function frameRefresh(e)
{
if(!bottoms.backside.visible || bottoms.backside.parent == null || !bottoms.backside.parent.visible || g.gamePaused)
{
//mod cleared, or moreclothing has it hidden
}
else
{
if(g.characterControl.currentSkin == 0)
{
bottoms.backside.plug.myplug2.myoverlay.alpha = 0.3;
}else
if(g.characterControl.currentSkin == 1)
{
bottoms.backside.plug.myplug2.myoverlay.alpha = 0.5;
}else
if(g.characterControl.currentSkin == 2)
{
bottoms.backside.plug.myplug2.myoverlay.alpha = 0.2;
}else
if(g.characterControl.currentSkin == 3)
{
bottoms.backside.plug.myplug2.myoverlay.alpha = 0;
}
bottoms.backside.plug.myplug2.myskin.filter = g.her.torso.back.filters;
if(loadermode)
{
bottoms.backside.plug.rotation = -27 + g.her.torsoIK.m2Ang * 65 / Math.PI;
}
else
{
bottoms.backside.plug.rotation = -16; //g.her.torsoIK.m2Ang not avaliable in vanilla, use static value
}
if(timer > delay)
{
if(counter < 90 || timer2 <= 0)
{
counter = Math.min(180, counter + speed);
}
bottoms.backside.plug.myplug2.x = Math.sin(counter * Math.PI / 180) * -20 * scale;
if(counter >= 90)
{
timer2 = Math.max(0, timer2 - 1);
if(counter == 180)
{
counter = 0;
delay = 50 + Math.random() * 210;
speed = 1 + Math.random() * 2.5;
timer = 0;
timer2 = -30 + Math.random() * 70;
scale = 0.5 + Math.random() * 1.7 ;
}
}
}
else
{
timer++;
}
var rgbFill1ToUse;
var rgbFill2ToUse;
if(loadermode)
{ //if in loader, can be very efficient and grab it directly
//if want to use rgb picker 1:
//rgbFill1ToUse = g.characterControl.ankleCuffsControl.rgb1;
//if want to use rgb picker 2:
rgbFill2ToUse = g.characterControl.ankleCuffsControl.rgb2;
}
else
{
var fills = g.characterControl.ankleCuffsControl.getDataString().split(",");
//if want to use rgb picker 1:
/*
if(fills.length >= 5) //Check for rgbFill1
{
rgbFill1ToUse = {r:fills[1], g:fills[2], b:fills[3], a:fills[4]};
}
else
{
rgbFill1ToUse = {r:0, g:0, b:0, a:1}; //default to black
}
*/
//if want to use rgb picker 2:
if(fills.length >= 9) //Check for rgbFill2
{
rgbFill2ToUse = {r:fills[5], g:fills[6], b:fills[7], a:fills[8]};
}
else
{
rgbFill2ToUse = {r:0, g:0, b:0, a:1}; //default to black
}
}
//here is an example follow color slider piece of code
//var mycolor1 = new ColorTransform(1, 1, 1, rgbFill1ToUse.a, rgbFill1ToUse.r, rgbFill1ToUse.g, rgbFill1ToUse.b);
var mycolor2 = new ColorTransform(1, 1, 1, rgbFill2ToUse.a, rgbFill2ToUse.r, rgbFill2ToUse.g, rgbFill2ToUse.b);
tryToSetFill(bottoms.backside.plug.myplug2, "rgbFill", mycolor2);
}
evaluateModStatus();
}
function myResetFunction()
{
//add reset code here that removes any loader specific add-ins,functions,proxies created
if(loadermode)
{
}
//add reset code here that removes vanilla compatible stuff such as listeners that were created
bottoms.removeEventListener(Event.ENTER_FRAME, frameRefresh);
}
function evaluateModStatus() //if the mod has some sort of listener code registered, this should be called so vanilla sdt can also clear up uneeded code, as well as cleanup for extra stuff processed in loader char folders.
{
//this checks if the mod is still placed on something //this check is to weed out the duplicate instances of the mod that are never placed when using loader char folders, as the modtype container is still the modpiece's parent
if((evaluationModpiece.parent == null && !registeredinmoreclothing ) || evaluationModpiece.parent == evaluationParent)
{
myResetFunction();
}
}
function tryToSetFill(param1:MovieClip, param2:String, param3:ColorTransform) : void
{
if (param1)
{
tryToSetFillChildren(param1, param2, param3);
}
return;
}// end function
function tryToSetFillChildren(param1:MovieClip, param2:String, param3:ColorTransform) : void
{
var _loc_4:* = param1.numChildren;
var _loc_5:* = 0;
while (_loc_5 < _loc_4)
{
if (param1.getChildAt(_loc_5).name == param2)
{
param1.getChildAt(_loc_5).transform.colorTransform = param3;
}
if (param1.getChildAt(_loc_5) is DisplayObjectContainer)
{
tryToSetFillChildren(param1.getChildAt(_loc_5) as MovieClip, param2, param3);
}
_loc_5 = _loc_5 + 1;
}
return;
}// end function