// Actor variables var CurrentActor; var Actor = []; var ActorNamesText = null; var ActorName = 0; var ActorLove = 1; var ActorSubmission = 2; var ActorInventory = 3; var ActorOrgasmCount = 4; var ActorBondageCount = 5; var ActorLastBondageChapter = 6; var ActorCloth = 7; var ActorPose = 8; var ActorHideName = 9; var ActorOwner = 10; // Make sure the current actor is loaded (create it if not) function ActorLoad(ActorToLoad, ActorLeaveScreen) { // Keep the actor leave screen LeaveIcon = "Leave"; LeaveScreen = ActorLeaveScreen; // Sets if the actor is the player lover, submissive or Mistress CurrentActor = ActorToLoad; if (ActorToLoad == "") return; Common_ActorIsLover = (CurrentActor == Common_PlayerLover); Common_ActorIsOwner = (CurrentActor == Common_PlayerOwner); Common_ActorIsOwned = (ActorGetValue(ActorOwner) == "Player"); // Load the actor if it's not already loaded for (var L = 0; L < Actor.length; L++) if (Actor[L][ActorName] == ActorToLoad) return; Actor[Actor.length] = [ActorToLoad, 0, 0, [], 0, 0, "", "Clothed", "", false, ""]; } // Return a value from the current actor data function ActorGetValue(ValueType) { for (var L = 0; L < Actor.length; L++) if (CurrentActor == Actor[L][ActorName]) return Actor[L][ValueType]; } // Return a value from a specific actor data function ActorSpecificGetValue(SpecificActorName, ValueType) { for (var L = 0; L < Actor.length; L++) if (SpecificActorName == Actor[L][ActorName]) return Actor[L][ValueType]; } // Return the current actor's localized name function ActorGetDisplayName() { if (ActorNamesText == null) ReadCSV("ActorNamesText", "C999_Common", "ActorNames", "Text", GetWorkingLanguageForChapter("C999_Common")); if (ActorGetValue(ActorHideName)) return GetCSVText(ActorNamesText, "Unknown"); return GetCSVText(ActorNamesText, CurrentActor); } // Change positively or negatively the current actor attitude toward the player function ActorChangeAttitude(LoveAttitude, SubAttitude) { // If we need to make a change to the attitude, we apply it if ((LoveAttitude != 0) || (SubAttitude != 0)) for (var L = 0; L < Actor.length; L++) if (CurrentActor == Actor[L][ActorName]) { Actor[L][ActorLove] = Actor[L][ActorLove] + parseInt(LoveAttitude); Actor[L][ActorSubmission] = Actor[L][ActorSubmission] + parseInt(SubAttitude); if (Actor[L][ActorLove] > 99) Actor[L][ActorLove] = 99; if (Actor[L][ActorLove] < -99) Actor[L][ActorLove] = -99; if (Actor[L][ActorSubmission] > 99) Actor[L][ActorSubmission] = 99; if (Actor[L][ActorSubmission] < -99) Actor[L][ActorSubmission] = -99; } } // Change positively or negatively a specific actor attitude toward the player function ActorSpecificChangeAttitude(SpecificActorName, LoveAttitude, SubAttitude) { // If we need to make a change to the attitude, we apply it if ((LoveAttitude != 0) || (SubAttitude != 0)) for (var L = 0; L < Actor.length; L++) if (SpecificActorName == Actor[L][ActorName]) { Actor[L][ActorLove] = Actor[L][ActorLove] + parseInt(LoveAttitude); Actor[L][ActorSubmission] = Actor[L][ActorSubmission] + parseInt(SubAttitude); } } // Add an orgasm to the actor count and logs the event function ActorAddOrgasm() { for (var L = 0; L < Actor.length; L++) if (CurrentActor == Actor[L][ActorName]) Actor[L][ActorOrgasmCount]++; GameLogAdd("Orgasm"); } // Validates that a specific interaction stage is available for the player function ActorInteractionAvailable(LoveReq, SubReq, VarReq, InText, ForIntro) { // Make sure the love / sub level is match (both positive and negative) VarReq = VarReq.trim(); InText = InText.trim(); if ((parseInt(LoveReq) > 0) && (parseInt(ActorGetValue(ActorLove)) < parseInt(LoveReq))) return false; if ((parseInt(SubReq) > 0) && (parseInt(ActorGetValue(ActorSubmission)) < parseInt(SubReq))) return false; if ((parseInt(LoveReq) < 0) && (parseInt(ActorGetValue(ActorLove)) > parseInt(LoveReq))) return false; if ((parseInt(SubReq) < 0) && (parseInt(ActorGetValue(ActorSubmission)) > parseInt(SubReq))) return false; // Checks if there's a custom script variable or a common variable to process if(VarReq != ""){ let negate = VarReq.substring(0,1) == "!"; if(negate) VarReq = VarReq.substring(1); // whether to check global variable starting with Common_ or script variable starting with chapter and screen name let variableToCheck = (VarReq.substring(0,7) == "Common_" ? VarReq : CurrentChapter + "_" + CurrentScreen + "_" + VarReq); if(!!window[variableToCheck] === negate) return false; } // Check if the player is gagged, only interactions that starts with '(', '(' or '@' are allowed var nonSpeechActionsStart = [ "(", "(", // Full-width bracket used in CJK languages "@", ]; if ((nonSpeechActionsStart.indexOf(InText.substr(0, 1)) < 0) && Common_PlayerGagged && !ForIntro) return false; // Since nothing blocks, we allow it return true; } // Add inventory to the current actor function ActorAddInventory(NewInventory) { // Find the current actor and adds the inventory if it's not already the case for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == CurrentActor) if (Actor[A][ActorInventory].indexOf(NewInventory) == -1) { Actor[A][ActorInventory].push(NewInventory); if (Actor[A][ActorLastBondageChapter] != CurrentChapter) { Actor[A][ActorLastBondageChapter] = CurrentChapter; Actor[A][ActorBondageCount]++; GameLogAdd("Bondage"); } } } // Add 1 to the bondage count of a specific actor function ActorSpecificAddBondage(SpecificActor) { for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == SpecificActor) { Actor[A][ActorBondageCount]++; GameLogSpecificAdd(CurrentChapter, SpecificActor, "Bondage"); } } // Returns the number of times that all actors were tied up during any chapter function ActorGetTotalBondageCount() { var total = 0; for (var A = 0; A < Actor.length; A++) total = total + Actor[A][ActorBondageCount]; return total; } // Remove inventory from the current actor function ActorRemoveInventory(RemInventory) { // Find the current actor and adds the inventory if it's not already the case for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == CurrentActor) if (Actor[A][ActorInventory].indexOf(RemInventory) >= 0) Actor[A][ActorInventory].splice(Actor[A][ActorInventory].indexOf(RemInventory), 1); } // Returns true if the current actor has the queried inventory function ActorHasInventory(QueryInventory) { // Cycles to find the correct actor and checks if the inventory is in the list for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == CurrentActor) if (Actor[A][ActorInventory].indexOf(QueryInventory) >= 0) return true; return false; } // Sets the clothes for the current actor function ActorSetCloth(NewCloth) { for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == CurrentActor) Actor[A][ActorCloth] = NewCloth; } // Sets the owner for the current actor (collar the actor) function ActorSetOwner(NewOwner) { for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == CurrentActor) { Actor[A][ActorOwner] = NewOwner; ActorAddInventory("Collar"); GameLogAdd("CollaredBy" + NewOwner); if (NewOwner == "Player") Common_ActorIsOwned = true; } } // Sets the clothes for a specific actor function ActorSpecificSetCloth(SpecificActor, NewCloth) { for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == SpecificActor) Actor[A][ActorCloth] = NewCloth; } // Set the pose for the current actor function ActorSetPose(NewPose) { for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == CurrentActor) Actor[A][ActorPose] = NewPose; } // Sets the pose for a specified actor (also works for the player if needed) function ActorSpecificSetPose(SpecificActor, NewPose) { if (SpecificActor == "Player") { Common_PlayerPose = NewPose; } else { for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == SpecificActor) Actor[A][ActorPose] = NewPose; } } // Returns TRUE if the actor (or player) is in visible bondage function ActorSpecificInBondage(SpecificActor) { if (SpecificActor == "Player") { return (Common_PlayerRestrained || Common_PlayerGagged); } else { for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == SpecificActor) return (ActorSpecificHasInventory(SpecificActor, "Rope") || ActorSpecificHasInventory(SpecificActor, "TwoRopes") || ActorSpecificHasInventory(SpecificActor, "ThreeRopes") || ActorSpecificHasInventory(SpecificActor, "Armbinder") || ActorSpecificHasInventory(SpecificActor, "Cuffs") || ActorSpecificHasInventory(SpecificActor, "Manacles") || ActorSpecificHasInventory(SpecificActor, "BallGag") || ActorSpecificHasInventory(SpecificActor, "TapeGag") || ActorSpecificHasInventory(SpecificActor, "ClothGag") || ActorSpecificHasInventory(SpecificActor, "PantieGag") || ActorSpecificHasInventory(SpecificActor, "SockGag")); } } // Returns TRUE if a specific actor (or player) is restrained function ActorSpecificIsRestrained(SpecificActor) { if (SpecificActor == "Player") { return Common_PlayerRestrained; } else { for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == SpecificActor) return (ActorSpecificHasInventory(SpecificActor, "Rope") || ActorSpecificHasInventory(SpecificActor, "TwoRopes") || ActorSpecificHasInventory(SpecificActor, "ThreeRopes") || ActorSpecificHasInventory(SpecificActor, "Armbinder") || ActorSpecificHasInventory(SpecificActor, "Cuffs") || ActorSpecificHasInventory(SpecificActor, "Manacles")); } } // Returns TRUE if a specific actor (or player) is restrained function ActorSpecificIsGagged(SpecificActor) { if (SpecificActor == "Player") { return Common_PlayerGagged; } else { for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == SpecificActor) return (ActorSpecificHasInventory(SpecificActor, "BallGag") || ActorSpecificHasInventory(SpecificActor, "TapeGag") || ActorSpecificHasInventory(SpecificActor, "ClothGag")); } } // Returns true if the actor is restrained (if there's no actor, we return the player status) function ActorIsRestrained() { if (CurrentActor == "") return Common_PlayerRestrained; else return (ActorHasInventory("Rope") || ActorHasInventory("TwoRopes") || ActorHasInventory("ThreeRopes") || ActorHasInventory("Armbinder") || ActorHasInventory("Cuffs") || ActorHasInventory("Manacles")); } // Returns true if the actor is gagged (if there's no actor, we return the player status) function ActorIsGagged() { if (CurrentActor == "") return Common_PlayerGagged; else return (ActorHasInventory("BallGag") || ActorHasInventory("TapeGag") || ActorHasInventory("ClothGag") || ActorHasInventory("PantieGag") || ActorHasInventory("SockGag")); } // Returns true if the actor is chaste (if there's no actor, we return the player status) function ActorIsChaste() { if (CurrentActor == "") return Common_PlayerChaste; else return (ActorHasInventory("ChastityBelt")); } // Unties the actor and returns the rope to the player function ActorUntie() { if (ActorHasInventory("ThreeRopes")) { PlayerAddInventory("Rope", 1); ActorRemoveInventory("ThreeRopes"); } if (ActorHasInventory("TwoRopes")) { PlayerAddInventory("Rope", 1); ActorRemoveInventory("TwoRopes"); } if (ActorHasInventory("Rope")) { PlayerAddInventory("Rope", 1); ActorRemoveInventory("Rope"); } if (ActorHasInventory("Armbinder")) { PlayerAddInventory("Armbinder", 1); ActorRemoveInventory("Armbinder"); } } // Ungag the actor and returns the item if possible function ActorUngag() { if (ActorHasInventory("BallGag")) { ActorRemoveInventory("BallGag"); PlayerAddInventory("BallGag", 1); } if (ActorHasInventory("ClothGag")) { ActorRemoveInventory("ClothGag"); PlayerAddInventory("ClothGag", 1); } if (ActorHasInventory("TapeGag")) ActorRemoveInventory("TapeGag"); if (ActorHasInventory("PantieGag")) { ActorRemoveInventory("PantieGag"); PlayerAddInventory("PantieGag", 1); } if (ActorHasInventory("SockGag")) { ActorRemoveInventory("SockGag"); PlayerAddInventory("SockGag", 1); } } // Remove the blindfold from the actor and return it to the player function ActorUnblindfold() { if (ActorHasInventory("Blindfold")) { ActorRemoveInventory("Blindfold"); PlayerAddInventory("Blindfold", 1); } } // Tries to apply a restrain on the current actor function ActorApplyRestrain(RestrainName) { // The rope can be applied twice, the item becomes "TwoRopes" if ((RestrainName == "Rope") && ActorHasInventory("Rope") && !ActorHasInventory("TwoRopes") && PlayerHasInventory("Rope")) RestrainName = "TwoRopes"; if ((RestrainName == "Rope") && ActorHasInventory("Rope") && ActorHasInventory("TwoRopes") && !ActorHasInventory("ThreeRopes") && PlayerHasInventory("Rope") && (PlayerGetSkillLevel("RopeMastery") >= 1)) RestrainName = "ThreeRopes"; // If there's no text or the player is restrained, we assume we cannot apply the restrain var RestrainText = GetText(RestrainName); if ((RestrainText.substr(0, 20) != "MISSING TEXT FOR TAG") && (RestrainText != "") && !Common_PlayerRestrained && (PlayerHasInventory(RestrainName) || RestrainName == "TwoRopes" || RestrainName == "ThreeRopes") && !ActorHasInventory(RestrainName)) { // Third rope if (RestrainName == "ThreeRopes") { PlayerRemoveInventory("Rope", 1); ActorAddInventory("ThreeRopes"); CurrentTime = CurrentTime + 60000; } // Second rope if (RestrainName == "TwoRopes") { PlayerRemoveInventory("Rope", 1); ActorAddInventory("TwoRopes"); CurrentTime = CurrentTime + 60000; } // Regular restraints if ((RestrainName == "Rope") || (RestrainName == "Cuffs") || (RestrainName == "Armbinder")) { if (!ActorIsRestrained()) { PlayerRemoveInventory(RestrainName, 1); ActorAddInventory(RestrainName); CurrentTime = CurrentTime + 60000; } else return; } // Collar (only available in the Kinbaku club for now) if ((RestrainName == "Collar") && (CurrentChapter == "C101_KinbakuClub")) { PlayerRemoveInventory("Collar", 1); ActorAddInventory("Collar"); CurrentTime = CurrentTime + 60000; } // Regular gags (gags can be swapped) if ((RestrainName == "BallGag") || (RestrainName == "TapeGag") || (RestrainName == "ClothGag")) { ActorUngag(); PlayerRemoveInventory(RestrainName, 1); ActorAddInventory(RestrainName); CurrentTime = CurrentTime + 60000; } // Mouth filling before regular gags (only available in the Kinbaku club for now) if (((RestrainName == "PantieGag") || (RestrainName == "SockGag")) && !(ActorHasInventory("BallGag") || ActorHasInventory("ClothGag") || ActorHasInventory("TapeGag")) && (CurrentChapter == "C101_KinbakuClub")) { PlayerRemoveInventory(RestrainName, 1); ActorAddInventory(RestrainName); CurrentTime = CurrentTime + 60000; } // Blindfold (only available in the Kinbaku club for now) if ((RestrainName == "Blindfold") && (CurrentChapter == "C101_KinbakuClub")) { PlayerRemoveInventory("Blindfold", 1); ActorAddInventory("Blindfold"); CurrentTime = CurrentTime + 60000; } // Vaginal items (cannot be used if the actor is chaste) if ((RestrainName == "ChastityBelt") || (RestrainName == "VibratingEgg")) { if (!ActorIsChaste()) { PlayerRemoveInventory(RestrainName, 1); ActorAddInventory(RestrainName); CurrentTime = CurrentTime + 60000; } else return; } // Anal items (cannot be used if the actor is chaste) (only available in the Kinbaku club for now) if ((RestrainName == "ChastityBelt") || (RestrainName == "ButtPlug")) { if (!ActorIsChaste()) { PlayerRemoveInventory(RestrainName, 1); ActorAddInventory(RestrainName); CurrentTime = CurrentTime + 60000; } else return; } // Cuffs key if (RestrainName == "CuffsKey") { if (ActorHasInventory("Cuffs")) { ActorRemoveInventory("Cuffs"); PlayerAddInventory("Cuffs", 1); CurrentTime = CurrentTime + 60000; } else return; } // Show the text on the screen and jumps 1 minute OverridenIntroText = RestrainText; } } // Returns true if the queried actor has the queried inventory function ActorSpecificHasInventory(QueryActor, QueryInventory) { // Cycles to find the correct actor and checks if the inventory is in the list for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == QueryActor) if (Actor[A][ActorInventory].indexOf(QueryInventory) >= 0) return true; return false; } // Clear all inventory from an actor (expect the egg, plug, chastitybelt and collar) function ActorSpecificClearInventory(QueryActor, Recover) { for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == QueryActor) { var HadEgg = ActorSpecificHasInventory(QueryActor, "VibratingEgg"); var HadPlug = ActorSpecificHasInventory(QueryActor, "ButtPlug"); var HadCollar = ActorSpecificHasInventory(QueryActor, "Collar"); var HadBelt = ActorSpecificHasInventory(QueryActor, "ChastityBelt"); while (Actor[A][ActorInventory].length > 0) { if ((Actor[A][ActorInventory][0] != "VibratingEgg") && (Actor[A][ActorInventory][0] != "ButtPlug") && (Actor[A][ActorInventory][0] != "TwoRopes") && (Actor[A][ActorInventory][0] != "ThreeRopes") && (Actor[A][ActorInventory][0] != "Collar") && (Actor[A][ActorInventory][0] != "ChastityBelt") && (Actor[A][ActorInventory][0] != "TapeGag") && Recover) PlayerAddInventory(Actor[A][ActorInventory][0], 1); if ((Actor[A][ActorInventory][0] == "ThreeRopes") && Recover) PlayerAddInventory("Rope", 1); if ((Actor[A][ActorInventory][0] == "TwoRopes") && Recover) PlayerAddInventory("Rope", 1); Actor[A][ActorInventory].splice(0, 1); } if (HadEgg) Actor[A][ActorInventory].push("VibratingEgg"); if (HadPlug) Actor[A][ActorInventory].push("ButtPlug"); if (HadCollar) Actor[A][ActorInventory].push("Collar"); if (HadBelt) Actor[A][ActorInventory].push("ChastityBelt"); } } // Returns the actor image file to use function ActorSpecificGetImage(QueryActor) { // The image file name is constructed from the inventory var ActorImage = QueryActor; if (ActorSpecificHasInventory(QueryActor, "Cuffs")) ActorImage = ActorImage + "_Cuffs"; if (ActorSpecificHasInventory(QueryActor, "Rope")) ActorImage = ActorImage + "_Rope"; if (ActorSpecificHasInventory(QueryActor, "Armbinder")) ActorImage = ActorImage + "_Armbinder"; if (ActorSpecificHasInventory(QueryActor, "BallGag")) ActorImage = ActorImage + "_BallGag"; if (ActorSpecificHasInventory(QueryActor, "TapeGag")) ActorImage = ActorImage + "_TapeGag"; return ActorImage; } // Change specific actor actors name on screen function ActorSpecificConcealment(SpecificActor, Hidden) { for (var A = 0; A < Actor.length; A++) if (Actor[A][ActorName] == SpecificActor) Actor[A][ActorHideName] = Hidden; }