#####################################################################
#                SEXBOT LAB
#####################################################################

default arcadescreenmode = 1
default selectedbot = []
default slotnum = 0
default selected_slotnum = 1
default multData = {"facPersonality": "Personality", "facUniformity": "Uniformity", "facCombos": "Traits Combo", "facTalents": "Talents", "facSkill": "Skills", "facSinglesPos": "Traits Positive", "facSinglesNeg": "Traits Negative", "facIQ": "IQ Factor", "facLikes": "Likes", "facDislikes": "Dislikes" }

default gradeTECReq = {
                    "subpar": 20,
                    "basic": 25,
                    "advanced": 30,
                    "military grade": 35
                    }
                    
default part_grade_index = {
                            "subpar" : "basic",
                            "basic" : "advanced",
                            "advanced" : "military grade",
                            "military grade" : "elite"
                           }
                                
style btnlinespace: 
    background None

style btnlinespace_text:
    color "#888f"
    hover_color "#66c1e0"
    ypos 3
    line_spacing -19 
    
#####################################################################
#					SUPPORT ROUTINES											
#####################################################################

label bot_roll_order(n = 1):
    $ orders = [
        ["A bot with all components being Generation 1 parts", 
        "all([x.cat == 1 for x in bot.parts.values()])",
        "bot.isComplete()"],
        ["A bot with all components being Generation 2 parts", 
        "all([x.cat == 2 for x in bot.parts.values()])",
        "bot.isComplete()"],
        ["A bot with all skills at least 70 points", 
        "all([x >= 70 for x in bot.skills.values()])",
        "bot.isComplete()"],
        ["A bot with at least three expert level skills (90+ points)", 
        "[x >= 70 for x in bot.skills.values()].count(True) >= 3",
        "bot.isComplete()"],
        ["A bot with IQ of 130 or higher and the 'Perversion' trait", 
        "'perverted' in bot.getTraits()", "bot.getIQ() >= 130",
        "bot.isComplete()"],
        ["A bot that likes anal and bondage", 
        "'anal' in bot.likes", "'bondage' in bot.likes",
        "bot.isComplete()"],
        ["A bot with full military grade component quality", 
        "all([x.pref == 'military grade' for x in bot.parts.values()])",
        "bot.isComplete()"],
        ["Any kind of bot configuration", 
        "bot.isComplete()"]
    ]  
    while n:
        $n -= 1
        $ GAME.lab.orders += [random.choice(orders)] 
        $ GAME.lab.orders = GAME.lab.orders[:3] # max 3 in queue
    return()

label sexbot_arcade_earnings():
    $ earnings = 0 
    $ best = False
    $ arcade_shells = []
    $ arcade_shelltypecount = 0
    $ arcade_traits = []
    $ arcade_traitcount = 0
    $ arcade_attitudes = []
    $ arcade_attitudecount = 0
    $ arcade_personalities = []
    $ arcade_personalitycount = 0
    
    
    python:
        for bot in GAME.arcade:
            if bot.addOns[5]:
                if bot.addOns[5].name not in arcade_shells:
                    arcade_shells.append(bot.addOns[5].name)
            else:
                arcade_shelltypecount = 1
            for i in bot.traits:
                if i not in arcade_traits:
                    arcade_traits.append(i)
                if bot.attitude not in arcade_attitudes:
                    arcade_attitudes.append(bot.attitude)
                if bot.personality not in arcade_personalities:
                    arcade_personalities.append(bot.personality)
                    
        arcade_shelltypecount += len(arcade_shells)
        arcade_multishelltypebonus = -3 + (arcade_shelltypecount * 3)
        arcade_attitudecount = len(arcade_attitudes)
        arcade_multiattitudebonus = -2 + (arcade_attitudecount * 2)
        arcade_traitcount = len(arcade_traits)
        arcade_multitraitbonus = -4 + (arcade_traitcount * 2)
        arcade_personalitycount = len(arcade_personalities)
        arcade_multipersonalitybonus = -2 + (arcade_personalitycount * 2)
        
        for bot in GAME.arcade:
            # earnings adjustment factor
            fac = 1.0 
            if any([x.wear == 1.0 for x in bot.parts.values()]):
                fac = 0.0

            # earnings apply
            bot.earnedToday = 0

            
            # bot.earnedToday += int(bot.getPrice() * random.uniform(0.015,0.022) * fac) # CR-0592
            # bot.earnedToday += bot.getEarnings() * fac 
            bot.earnedToday += int((20000 + bot.getPrice()) * random.uniform(0.0040,0.006) * fac * (.97 + (arcade_shelltypecount * .03)) * (1.0 + (arcade_attitudecount * .02)) * (1.0 + (arcade_traitcount * .02)) * (1.0 + (arcade_personalitycount * .02)))


            if best:
                if best.earnedToday < bot.earnedToday:
                    best = bot
            else:
                best = bot 
            earnings += bot.earnedToday  
            bot.tallyUp("Arcade Earnings",bot.earnedToday)
            GAME.mc.tallyUp("Arcade Earnings",bot.earnedToday)

            # bot wear effect apply
            for i in bot.parts.values():
                i.wear = min(1.0, i.wear + random.uniform(0.03,0.1))

            # repair bonus
            if "INV_ARCADE" in GAME.investments:
                for i in bot.parts.values():
                    i.wear = 0.0
        earnings = int(earnings)

    if earnings:
        queue sound "audio/notify.wav"
        call large_notify("ARCADE REPORT", "Your Arcade Bots have earned a total of {:,} Cr. Your best earner was {} with {:,} Cr.\n\nMultiple Sexbot Shell Types Earnings Bonus: [arcade_multishelltypebonus]%\nMultiple Sexbot Attitudes Earning Bonus: [arcade_multiattitudebonus]%\nMultiple Sexbot Traits Earnings Bonus: [arcade_multitraitbonus]%\nMultiple Sexbot Personalities Earning Bonus: [arcade_multipersonalitybonus]%".format(earnings, C_SU_B+best.name+C_SU_E, best.earnedToday), ["Continue"], "03_minigames/ico_BotArcade.png", "pink") from _call_large_notify_79 

        call transaction("Arcade Earnings", earnings, True) from _call_transaction_49 
    if GAME.mc.getTally("Arcade Earnings") > 100000 and "arcade tycoon" not in GAME.mc.achievements: 
        call achievement_notify(GAME.mc, "arcade tycoon", "20_gallery/gallery 21.jpg") from _call_achievement_notify_13 
        $ GAME.galleryAdd(21)
    return()

label sexbot_autotrainer():
    # Init 
    $ complete = []
    # execute training on auto bots 
    python:
        for i in GAME.lab.getCompleted():
            if i.autoTrain:
                skillBefore = sum(i.skills.values()) 
                for k in i.skills.keys():
                    i.train(k, "auto")
                    i.train(k, "auto")
                    i.train(k, "auto")
                skillAfter = sum(i.skills.values())  
                if (skillBefore < skillAfter) and (skillAfter >= sum(i.getTalents().values())):
                    complete.append(i) # training finished

                
    # report on completed bots
    while complete:
        $ bot = complete.pop(0)
        play sound "audio/success.wav"
        call large_notify("AUTOTRAIN COMPLETE", "The auto-train unit has completed the training of {0}.\n\nShe is now ready to be sold or rented out.".format(C_OR_B+bot.name+C_OR_E), ["Continue"], "03_minigames/ico_BotAuto.png", "orange") from _call_large_notify_80 
        $ GAME.mc.tallyUp("Autotrained Bots", 1)
        if GAME.mc.getTally("Autotrained Bots") == 1: 
            call achievement_notify(GAME.mc, "autotrainer", "20_gallery/gallery 23.jpg") from _call_achievement_notify_14 
            $ GAME.galleryAdd(23)
    return()

label sexbot_escape():
    $ escapees = []
    $ arcadeEscapees = []

    python:
        for bot in GAME.lab.getCompleted():
            if random.uniform(0.01,1.0) < bot.getEscapeProb():
                if not (bot.getShellConfig() == "I" and not any([GAME.questSys.inProgress(x) for x in ['QID_KRELL_YLYEE_WAIT', 'QID_MAIN_SWARMMODULE_B']])): # quest exceptions
                    escapees.append(bot) 
        for bot in GAME.arcade:
            if random.uniform(0.01,1.0) < bot.getEscapeProb():
                arcadeEscapees.append(bot) 

    while escapees:
        $ GAME.ship.destroySubunit()
        $ bot = escapees.pop(0)
        #scene room_lab_smart
        queue sound "audio/red alert.wav"
        call large_notify("SEXBOT ESCAPE!", "Owing to {0}'s supreme intelligence and your negligence in securing her, {0} has escaped. She has damaged critical ship components in the process.".format(C_RE_B+bot.name+C_RE_E), ["Continue"], "03_minigames/ico SBPCortex2.png", "red") from _call_large_notify_81 
        $ GAME.lab.clearBot(bot)       

    while arcadeEscapees:
        $ fine = random.randint(80,350)*100
        $ bot = arcadeEscapees.pop(0)
        #scene room_lab_smart
        queue sound "audio/notify.wav"
        call large_notify("ARCADE ESCAPE!", "An arcade operator informs you, that owing to your negligence in securing her, {0} has escaped from the arcade. She has damaged arcade equipment worth {1:,} Cr in the process.".format(C_RE_B+bot.name+C_RE_E, fine), ["Continue"], "03_minigames/ico SBPCortex2.png", "red") from _call_large_notify_82 
        $ GAME.arcade.remove(bot)       

    return()
   
#####################################################################
#					LAB MANAGER TERMINAL		
#####################################################################
screen mg_lab_manager_scr(*args):
    $ lmMode = args[0]
    $ lmModes = args[1]
    $ partsFilter = args[2]
    $ yadj = args[3] # parts viewport manager y-pos
    $ LIST_Y = 260
        
    if lmMode == "arcade manager" and arcadescreenmode == 2:
        add "11_backgrounds/backdrop_cyberpunkclub_ohwee.jpg"
    image "05_gui/mask 50.png"

    $ markup = 1.0 
    if lmMode == "special offers":
        $ C_MARKUP = 7.0

    #####################################################################
    #						GUI
    #####################################################################
    use header
   
    text C_HI_B+"{}".format(lmMode.upper())+C_HI_E size FSIZE_LARGE pos 20, 90

    #hbox pos 440, 150 spacing 10:
    frame pos 1060, 44 xalign 0.5 background Solid ("#000000ff"):
        has hbox spacing 10
        for i in lmModes: #[:-1]:
            if lmMode == i:
                $ tabCol = "#07af"
                $ tabColh = "#09cf"
            else:
                $ tabCol = "#555f"
                $ tabColh = "#888f"
            fixed xsize 180 ysize 30:
                button action Return(["mode", i]):
                    background Solid(tabCol)
                    hover_background Solid(tabColh)
                text C_WH_B+"{}".format(i.title())+C_WH_E size FSIZE ypos 4 xalign 0.5 outlines [ (1, "#0008", 1, 1) ]        

    #####################################################################
    #                EXIT BUTTON
    #####################################################################
    
    frame xsize 300 ysize 64 pos 0,950 background Solid("#00000000") padding 0,0:
        image "05_gui/gui_menu_option.png" yalign 0.5 xzoom 0.8
        button action Return(False)xpos 20
        textbutton "Exit (X)" yalign 0.5 action Return(False) xpos 20 # CR-0587
        key "x" action Return (False)
        key "X" action Return (False) 
    
    if lmMode == "arcade manager":
      frame xsize 300 ysize 72 pos 0,865 background Solid("#00000000") padding 0,0:
        image "05_gui/gui_menu_option.png" yalign 0.5 xzoom 0.8
        button action ToggleVariable("arcadescreenmode", true_value=1, false_value=2) style "btnlinespace" xpos 20
        textbutton "View\n        (M)\nMode" yalign 0.5 xpos 20 style "btnlinespace"# CR-0587
        key "m" action ToggleVariable("arcadescreenmode", true_value=1, false_value=2)
        key "M" action ToggleVariable("arcadescreenmode", true_value=1, false_value=2)
        
    

    $ tooltip = GetTooltip()
    if tooltip and tooltip in parts:
        frame padding 20,20 xsize 560 ysize 920 pos 40 , 200 background Solid("#39210000"):
            image "08_items/ico bg1.png" zoom 0.5 xpos 50 ypos 100
            image "{}/{}".format(tooltip.getPath(),tooltip.getIco()) zoom 0.5 xpos 50 ypos 100
            vbox xsize 400 ypos 420 xpos -25 spacing 20:
                text tooltip.getName() xalign 0.5 size FSIZE
                text tooltip.getDesc() xalign 0.5 size FSIZE
                if tooltip.getBoostOneLiner():
                    text tooltip.getBoostOneLiner() xalign 0.5 size FSIZE
                text "Value: {:,} Cr".format(int(tooltip.getPrice())) xalign 0.5 size FSIZE

    #####################################################################
    #					PARTS STORAGE		
    #####################################################################
    if lmMode == "parts storage":
        $ parts = GAME.lab.parts
        text C_HI_B+"({:,} Units in Stock)".format(len(GAME.lab.parts))+C_HI_E size FSIZE_LARGE pos 40, 150
        hbox pos 475, 89 spacing 10:
            #for i in [1,2,3]:
                #if partsFilter["cat"][i]:
            if not togglefilters:
                $ bCol = "#07af"
                $ bColh = "#09cf"
            else:
                $ bCol = "#555f"
                $ bColh = "#888f"
            fixed xsize 70 ysize 30:
                button action (ToggleVariable("togglefilters", true_value=True, false_value=False), SetDict(partsFilter['slot'], 'cortex', togglefilters), SetDict(partsFilter['slot'], 'head', togglefilters), SetDict(partsFilter['slot'], 'head', togglefilters), SetDict(partsFilter['slot'], 'torso', togglefilters), SetDict(partsFilter['slot'], 'arms', togglefilters), SetDict(partsFilter['slot'], 'legs', togglefilters), SetDict(partsFilter['slot'], 'shell', togglefilters), SetDict(partsFilter['slot'], 'cube', togglefilters)):
                    background Solid(bCol)
                    hover_background Solid(bColh)
                text "Parts" xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]
            text " > " size FSIZE yalign 0.5 yoffset 4
            #if not togglefilters:
            for i in ["cortex", "head", "torso", "arms", "legs", "shell", "cube"]:
                if partsFilter["slot"][i]:
                    $ bCol = "#07af"
                    $ bColh = "#09cf"
                else:
                    $ bCol = "#555f"
                    $ bColh = "#888f"
                fixed xsize 70 ysize 30:
                    #text "Gen {}".format(i) xalign 0.5 yalign 0.5 size FSIZE_MED
                    #button action Return(["filter", "cat", i])
                    button action Return(["filter", "slot", i]):
                        background Solid(bCol)
                        hover_background Solid(bColh)
                    text "{}".format(i.title()) xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]
                    
        hbox pos 1190, 89 spacing 10:
            if not togglefilters1:
                $ bCol = "#07af"
                $ bColh = "#09cf"
            else:
                $ bCol = "#555f"
                $ bColh = "#888f"
            fixed xsize 80 ysize 30:
                button action (ToggleVariable("togglefilters1", true_value=True, false_value=False), SetDict(partsFilter['modules'], 'ANA', togglefilters1), SetDict(partsFilter['modules'], 'BON', togglefilters1), SetDict(partsFilter['modules'], 'ORA', togglefilters1), SetDict(partsFilter['modules'], 'SPE', togglefilters1), SetDict(partsFilter['modules'], 'VAG', togglefilters1), SetDict(partsFilter['modules'], 'PER', togglefilters1), SetDict(partsFilter['modules'], 'Immo', togglefilters1), SetDict(partsFilter['modules'], 'IQ', togglefilters1)):
                    background Solid(bCol)
                    hover_background Solid(bColh)
                text "Addons" xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]
            text " > " size FSIZE yalign 0.5 yoffset 4

            for i in ["ANA", "BON", "ORA", "SPE", "VAG", "PER", "IQ", "Immo"]:
                if partsFilter["modules"][i]:
                    $ bCol = "#07af"
                    $ bColh = "#09cf"
                else:
                    $ bCol = "#555f"
                    $ bColh = "#888f"
                fixed xsize 55 ysize 30:
                    button action Return(["filter", "modules", i]):
                        background Solid(bCol)
                        hover_background Solid(bColh)
                    text i xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]
                    
                    
        hbox pos 475, 128 spacing 10:
            if not togglefilters2:
                $ bCol = "#07af"
                $ bColh = "#09cf"
            else:
                $ bCol = "#555f"
                $ bColh = "#888f"
            fixed xsize 100 ysize 30:
                button action (ToggleVariable("togglefilters2", true_value=True, false_value=False), SetDict(partsFilter['cat'], 1, togglefilters2), SetDict(partsFilter['cat'], 2, togglefilters2), SetDict(partsFilter['cat'], 3, togglefilters2), SetDict(partsFilter['prefs'], 'subpar', togglefilters2), SetDict(partsFilter['prefs'], 'basic', togglefilters2), SetDict(partsFilter['prefs'], 'advanced', togglefilters2), SetDict(partsFilter['prefs'], 'military grade', togglefilters2), SetDict(partsFilter['prefs'], 'elite', togglefilters2)):
                    background Solid(bCol)
                    hover_background Solid(bColh)
                text "Toggle All" xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]
            text " > " size FSIZE yalign 0.5 yoffset 4
            for i in [1,2,3]:
                if partsFilter["cat"][i]:
                    $ bCol = "#07af"
                    $ bColh = "#09cf"
                else:
                    $ bCol = "#555f"
                    $ bColh = "#888f"
                fixed xsize 102 ysize 30:
                    button action Return(["filter", "cat", i]):
                        background Solid (bCol)
                        hover_background Solid (bColh)
                    text "Gen {}".format(i) xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]
                    
            text " : " size FSIZE yalign 0.5 yoffset 4 outlines [ (1, "#0488", 1, 1) ]
            for i in ["subpar", "basic", "advanced", "military grade", "elite"]:
                if partsFilter["prefs"][i]:
                    $ bCol = "#07af"
                    $ bColh = "#09cf"
                else:
                    $ bCol = "#555f"
                    $ bColh = "#888f"
                fixed xsize 135 ysize 30:
                    button action Return(["filter", "prefs", i]):
                        background Solid (bCol)
                        hover_background Solid (bColh)
                    text i.title() xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]# CR-0298
                    
        frame xsize 1355 ysize 27 background Solid("#0077aa88") xpos 475 ypos 167:
            padding (0,0)
            text "Component" xpos 300 ypos 3 size 24
            text "Condition" xpos 600 ypos 3 size 24
            text "Value" xpos 772 ypos 3 size 24
            text "Modifier" xpos 950 ypos 3 size 24

        side "c r":
            area 475,200,1400,840
            viewport id "vp":
                draggable True
                mousewheel True
                yadjustment yadj

                vbox spacing 4:#pos 500,120 xsize 1250 spacing 4:
                    for i in parts:
                        $ showPart = True
                        $ showPart = partsFilter["prefs"][i.pref] and partsFilter["cat"][i.cat] and partsFilter["slot"][i.slot]# and partsFilter["modules"][i.modules]
                        #if partsFilter["slot"]["addon"]:
                        for x in {"ANA", "BON", "ORA", "SPE", "VAG", "PER", "IQ", "Immo"}:
                           if x in (i.ID):
                               if partsFilter["modules"][x] == False:
                                   $showPart = False

                        if showPart:
                            frame xsize 1230 ysize 66 background Solid("#0077aa88"):
                                padding (0,0)

                                button action NullAction() tooltip i hover_background Solid("#00ccff22")
                                
                                image "{}{}".format("22_bot_thumb/",i.getIco()) zoom 0.65 xpos 20 yalign 0.5 yoffset 0
                                text i.getName() size FSIZE yalign 0.5 xpos 160
                                text "{}".format(percentColorized(i.getGrade())[0]) size FSIZE yalign 0.5 xpos 620 
                                text "{:,} Cr".format(i.getPrice()) size FSIZE yalign 0.5 xpos 850 xalign 1.0
                                #button action NullAction() tooltip i
                                #frame xsize 80 ysize 30 background Solid ("#cc6600ff") yalign 0.5 xpos 1000:
                                    #button action Return(["scrap",i])
                                    #text "Scrap" xalign 0.5 yalign 0.5 size FSIZE_MED 
                                
                                $ framexsize = 50
                                if "Immobilizer" in i.name:
                                    $ framexsize = 80
                                frame xsize framexsize ysize 30 background None yalign 0.5 xpos 950 yoffset -20:
                                        
                                    if "Shell" in i.ID:
                                        text ""

                                    elif i.getBoostOneLiner():
                                        #if "IQ" in i.getBoostOneLiner()
                                        text i.getBoostOneLiner() xalign 0.5 xoffset 15 yoffset 5 text_align 0.5 size FSIZE


                                    elif "Immobilizer" in i.name:

                                        $ immopmod1 = str(int(immoBaseEffects[i.cat][0]*prefImpact[i.pref]/-1))

                                        $ immopmod2 = immoBaseEffects[i.cat][1]*prefImpact[i.pref]
                                        if immopmod2 > int(immopmod2):
                                            $ immopmod2 = str(immopmod2/-1)
                                        else:
                                             $ immopmod2 = str(int(immopmod2)/-1)

                                        $ immopmod3 = immoBaseEffects[i.cat][2]*prefImpact[i.pref]
                                        if immopmod3 > int(immopmod3):
                                            $ immopmod3 = str(immopmod3/-1)
                                        else:
                                             $ immopmod3 = str(int(immopmod3)/-1)
                                        text  immopmod1 + "{size=18} %{color=#0FF}  G1\n{/color}{/size}" + immopmod2 + "{size=18} %{color=#0FF}  G2\n{/color}{/size}" + immopmod3 + "{size=18} %{color=#0FF}  G3{/color}{/size}" xalign 1.0 text_align 1.0 size 22 line_spacing -2 yoffset -1 kerning -2
                                        #text immopmod + "%{size=18}{color=#0FF}*\nGen Mod\n1 | .5 | .25{/color}{/size}" xalign 0.5 size FSIZE



                                frame xsize 120 ysize 66 xpos 1235 background Solid("#0077aa88"):
                                    padding (0,0)
                                    fixed xsize 80 ysize 30 xalign 0.5 yalign 0.5:                       
                                        button action Return(["scrap",i]) tooltip i:
                                            background Solid ("#cc0000ff")
                                            hover_background Solid ("#ff4400ff")     
                                        text "Scrap" xalign 0.5 ypos 5 size FSIZE_MED
                              
                                #frame xsize 80 ysize 30 background Solid ("#aa0000ff") yalign 0.5 xpos 1080:
                                    #button action Return(["scrap",i])
                                    #text "Scrap" xalign 0.5 yalign 0.5 size FSIZE_MED

            vbar value YScrollValue("vp")
        #image "08_items/ico ITMCrateBots.png" pos 40, 400 zoom 0.5

    #####################################################################
    #					SPECIAL OFFERS		
    #####################################################################
    elif lmMode == "special offers":
        $ parts = GAME.lab.specialOffers
                    
        frame xsize 1350 ysize 27 background Solid("#0077aa88") xpos 450 ypos 167:
            padding (0,0)
            text "Component" xpos 250 ypos 3 size 24
            text "Condition" xpos 600 ypos 3 size 24
            text "Value" xpos 772 ypos 3 size 24
            text "Modifier" xpos 950 ypos 3 size 24
    
        side "c r":
            area 450,200,1450,684
            viewport id "vp":
                draggable True
                mousewheel True
                    
                if len(parts) < 1:
                    fixed xysize 1100, 300:
                        text "Nothing is currently available..." xalign 0.5 yalign 0.5
                else:
                  vbox spacing 5:
                    for i in parts:
                        frame xsize 1350 ysize 70 background Solid("#0077aa88"):
                            padding (0,0)
                            image "{}{}".format("22_bot_thumb/",i.getIco()) zoom 0.75 xpos 20 yalign 0.5
                            text i.getName(["col"]) size FSIZE yalign 0.5 xpos 160
                            text "{}".format(percentColorized(i.getGrade())[0]) size FSIZE yalign 0.5 xpos 620 
                            text "{:,} Cr".format(int(i.getPrice()*C_MARKUP)) size FSIZE yalign 0.5 xpos 840 xalign 1.0
                            button action NullAction() tooltip i 
                            
                            $ framexsize = 50
                            if "Immobilizer" in i.name:
                                $ framexsize = 80
                            frame xsize framexsize ysize 30 background None yalign 0.5 xpos 950 yoffset -20:
                                        
                                if "Shell" in i.ID:
                                    text ""

                                elif i.getBoostOneLiner():
                                    #if "IQ" in i.getBoostOneLiner()
                                    text i.getBoostOneLiner() xalign 0.5 xoffset 15 yoffset 5 text_align 0.5 size FSIZE


                                elif "Immobilizer" in i.name:

                                    $ immopmod1 = str(int(immoBaseEffects[i.cat][0]*prefImpact[i.pref]/-1))

                                    $ immopmod2 = immoBaseEffects[i.cat][1]*prefImpact[i.pref]
                                    if immopmod2 > int(immopmod2):
                                        $ immopmod2 = str(immopmod2/-1)
                                    else:
                                         $ immopmod2 = str(int(immopmod2)/-1)

                                    $ immopmod3 = immoBaseEffects[i.cat][2]*prefImpact[i.pref]
                                    if immopmod3 > int(immopmod3):
                                        $ immopmod3 = str(immopmod3/-1)
                                    else:
                                         $ immopmod3 = str(int(immopmod3)/-1)
                                    text  immopmod1 + "{size=18} %{color=#0FF}  G1\n{/color}{/size}" + immopmod2 + "{size=18} %{color=#0FF}  G2\n{/color}{/size}" + immopmod3 + "{size=18} %{color=#0FF}  G3{/color}{/size}" xalign 1.0 text_align 1.0 size 22 line_spacing -2 yoffset -1 kerning -2
                                    #text immopmod + "%{size=18}{color=#0FF}*\nGen Mod\n1 | .5 | .25{/color}{/size}" xalign 0.5 size FSIZE

                            
                            fixed xsize 80 ysize 30 yalign 0.5 xpos 1150:
                                button action Return(["buy_part", i]):
                                    background Solid ("#0099ccff") 
                                    hover_background Solid ("#55ccffff")
                                text "Buy" xalign 0.5 yalign 0.5 size FSIZE_MED

            vbar value YScrollValue("vp")
        #image "08_items/ico ITMCrateBots.png" pos 40, 400 zoom 0.5
        
    #####################################################################
    #					ARCADE MANAGER		
    #####################################################################
    elif lmMode == "arcade manager":
    
      if arcadescreenmode == 1:
        side "c r":
            area 375,140,1450,850
            viewport id "vp":
                draggable True
                mousewheel True
                
                vbox spacing 5:
                    $ arcadebotcount = 0
                    for i in GAME.arcade:
                        $ arcadebotcount += 1
                        frame xsize 1450 ysize 80 background Solid("#0077aa88"):
                            padding (0,0)
                            image "03_minigames/ico_type_{}.png".format(i.getShellConfig().lower()) zoom 0.31 ypos 1 xpos 25
                            text str(arcadebotcount) xpos 5 ypos 5 size 30 bold True color "#0CF"
                            
                            hbox xpos 105 ypos 46:
                                for s in range(i.getStars()):
                                    image "03_minigames/star.png"  zoom 0.5
                            text i.name size FSIZE ypos 20 xpos 100 bold True
                            
                            text "Value:\n    {:,} Cr".format (i.getPrice()) size FSIZE ypos 15 xpos 470 xalign 1.0
                            vbox xsize 500 xpos 550 yalign 0.5:
                                text i.getShortDesc() yalign 0.5 size FSIZE
                            text "Earnings:\n    {:,} Cr".format(int(i.getTally("Arcade Earnings"))) size FSIZE ypos 15 xpos 1150 xalign 1.0
                            # Arcade Operation Mode
                            fixed xsize 80 ysize 30 yalign 0.5 xpos 1325:
                                button action Return(["arcade_retrieve", i]):
                                    background Solid ("#0099ccff") 
                                    hover_background Solid ("#55ccffff")
                                text "Retrieve" xalign 0.5 yalign 0.5 size FSIZE_MED
                     
            vbar value YScrollValue("vp")
        image "03_minigames/ico_BotArcade.png" pos 40, 600 zoom 0.5
        
      #OhWee mod code
      
      else: # if arcadescreenmode = 2
      
        $ slotnum = 0
        if selectedbot == [] and len(GAME.arcade) > 0:
            $ selectedbot = GAME.arcade[0]
        
        if selectedbot.getShellConfig().lower() == "a":
            image "03_minigames/mgsb_full_bot.png" xoffset -40
        else:
            image "03_minigames/mgsb_full_bot_{}.png".format(selectedbot.getShellConfig().lower()) xoffset -40
            
        # bot name overlay
        frame background Solid ("#00000055"):
            pos 25, 560
            xysize 170, 40
            has hbox
            for s in range(selectedbot.getStars()):
                    image "03_minigames/star.png" 
        frame xsize 475 ysize 140 ypos 600 xpos 30 background Solid ("#00000055"):
            text str(selected_slotnum) xpos 5 ypos 5 color "0CF" bold True
            text "{} - {:,} Cr".format(selectedbot.name, selectedbot.getPrice()) ypos 5 xcenter 215
            text selectedbot.getShortDesc() xpos 10 ypos 45 size FSIZE
            $ bot_earnings = selectedbot.getTally("Arcade Earnings")
            $ sbPersonality = selectedbot.getPersonality()
            text sbPersonality.title() + " | {color=#0e0}Earnings: [bot_earnings:,] Cr{/color}" xpos 10 ypos 100 size FSIZE
            
        frame xsize 139 ysize 44 idle_background Solid ("#09c") hover_background Solid ("#0cf") xpos 15 ypos 760:
            textbutton "{b}Retrieve{/b}" action Return(["arcade_retrieve2", selectedbot]):
                text_size 30
                text_color "#0FF" 
                text_hover_color "#FFF"
                text_xoffset -2
                text_yoffset -2
                
        # Current Bot Stats
        
        
        frame xsize 360 ysize 900 pos 560, 100 background Solid("#0004"):
            vbox spacing 2 yoffset 10:                       
                frame xsize 360 ysize 35 background Solid ("#09f8") yoffset -10:
                    text "PARTS".format() xpos 5 ypos 1 size FSIZE
                    text "{:,} Cr".format(sum([selectedbot.parts[x].getPrice() for x in selectedbot.parts.keys() if bot.hasComp(x)])) xpos 340 xalign 1.0 ypos 1 size FSIZE
                    
                for i in ["cortex", "head", "torso", "arms", "legs"]:
                       # list part     
                    fixed xsize 360 ysize 30:
                        text "{}".format(i.title()) xpos 15 yalign 0.5 size FSIZE
                        if selectedbot.hasComp(i):
                            text "{}{}".format(selectedbot.parts[i].cat, selectedbot.parts[i].pref[:1]) xpos 195 yalign 0.5 size 20
                            text "{:,} Cr".format(selectedbot.parts[i].getPrice()) xpos 340 xalign 1.0 yalign 0.5 size FSIZE
                            
                text " "
                        
                frame xsize 360 ysize 35 background Solid ("#09f8") yoffset -10:
                            text "ADDONS + SHELL".format() xpos 5 ypos 1 size FSIZE
                            text "{:,} Cr".format(sum([selectedbot.addOns[x].getPrice() for x in range(6) if selectedbot.addOns[x]]),1) xpos 340 xalign 1.0 yalign 0.5 size FSIZE # CR-0754

                for i in range(6):
                            
                            $ addOn = selectedbot.addOns[i]
                            fixed xsize 360 ysize 30:
                                if addOn:
                                    if addOn.name == "Galaxina Prototype":
                                        text "Galaxina Shell" xpos 15 yalign 0.5 size FSIZE
                                    else:
                                      text "{}".format(addOn.name) xpos 15 yalign 0.5 size FSIZE
                                    text "{}{}".format(addOn.cat, addOn.pref[:1]) xpos 195 yalign 0.5 size 20
                                    text "{:,} Cr".format(addOn.getPrice()) xpos 340 xalign 1.0 yalign 0.5 size FSIZE
                                else:
                                    text "-" xpos 340 xalign 1.0 yalign 0.5 size FSIZE
                                    
                text " "
                $sbData = selectedbot.getPrice("analysis")
                frame xsize 360 ysize 35 background Solid ("#09f8") yoffset -10:
                    text "VALUE MULTIPLIER".format() xpos 5 ypos 1 size FSIZE
                    
                    $ intellect_bonus = round(sbData["facIQ"],2) + round(sbData["facPersonality"],2) + round(globals()["attitudeMod"],2)
                    $ traits_bonus = round(globals()["final_traitBonus"],2) + round(sbData["facCombos"],2)
                    $ talents_bonus = round(sbData["facTalents"],2) + round(sbData["facSkill"],2) + round(sbData["facLikes"],2) + round(sbData["facDislikes"],2)
                    
                    $ bot_mult_bonus = (sbData["facUniformity"]) * intellect_bonus * traits_bonus * talents_bonus
                    
                    text "[bot_mult_bonus:.02f]x" xpos 340 xalign 1.0 ypos 1 size FSIZE
            
            
                $ multData2 = {"facIQ": "IQ Factor", "facUniformity": "Uniformity", "facPersonality": "Personality", "facTalents": "Talents", "facSkill": "Skills", "facSinglesPos": "Traits Positive", "facSinglesNeg": "Traits Negative", "facCombos": "Traits Combo", "facLikes": "Likes", "facDislikes": "Dislikes" }
                

                fixed xsize 360 ysize 30:# background Solid ("#00000000"):
                    text "Uniformity" xpos 15 yalign 0.5 size FSIZE
                    text "x{}".format(sbData["facUniformity"]) xpos 335 xalign 1.0 yalign 0.5 size FSIZE
                    
                        
                fixed xsize 360 ysize 30:# background Solid ("#00000000"):
                    text "Intellect" xpos 15 yalign 0.5 size FSIZE
                    text "x[intellect_bonus]" xpos 335 xalign 1.0 yalign 0.5 size FSIZE
                    
                fixed xsize 340 ysize 22 xoffset 35 yoffset -5:
                    text "IQ Factor" size 22 color "#0e0"
                    $ IQadd_value = sbData["facIQ"]
                    text "[IQadd_value:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                    
                fixed xsize 340 ysize 22 xoffset 35 yoffset -5:
                    text "Personality" size 22 color "#0e0"
                    $ Peradd_value = sbData["facPersonality"]
                    if Peradd_value < 0:
                        text "-[Peradd_value:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                    else:
                        text "+[Peradd_value:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                    
                fixed xsize 340 ysize 22 xoffset 35 yoffset -5:
                    text "Attitude" size 22 color "#0e0"
                    $ Attadd_value = globals()["attitudeMod"]
                    if Attadd_value < 0:
                        text "[Attadd_value:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                    else:
                        text "+[Attadd_value:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                        
                        
                fixed xsize 360 ysize 30:# background Solid ("#00000000"):
                    text "Traits" xpos 15 yalign 0.5 size FSIZE
                    text "x[traits_bonus]" xpos 335 xalign 1.0 yalign 0.5 size FSIZE
                    
                fixed xsize 340 ysize 22 xoffset 35 yoffset -5:
                    text "Traits Bonus" size 22 color "#0e0"
                    $ traitbonus_value = globals()["final_traitBonus"] - sbData["facSinglesPos"] - sbData["facSinglesNeg"]
                    text "[traitbonus_value:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                    
                fixed xsize 340 ysize 22 xoffset 35 yoffset -5:
                    text "Trait Combo Bonus" size 22 color "#0e0"
                    $ comboadd_value = sbData["facCombos"]
                    text "+[comboadd_value:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                    
                fixed xsize 340 ysize 22 xoffset 35 yoffset -5:
                    $ PosTraits = sbData["facSinglesPos"]
                    $ PosTraitCount = str(int(PosTraits*20))
                    text "Positive Traits (" + PosTraitCount + ")" size 22 color "#0e0"
                    $ PosTraits = sbData["facSinglesPos"]
                    text "+[PosTraits:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                    
                fixed xsize 340 ysize 22 xoffset 35 yoffset -5:
                    $ NegTraits = sbData["facSinglesNeg"]
                    $ NegTraitCount = str((int(NegTraits*20) * -1))
                    text "Negative Traits (" + NegTraitCount + ")" size 22 color "#0e0"
                    $ NegTraits = sbData["facSinglesNeg"]
                    text "[NegTraits:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                        
                        
                fixed xsize 360 ysize 30:# background Solid ("#00000000"):
                    text "Talents" xpos 15 yalign 0.5 size FSIZE
                    text "x[talents_bonus]" xpos 335 xalign 1.0 yalign 0.5 size FSIZE
                    
                fixed xsize 340 ysize 22 xoffset 35 yoffset -5:
                    text "Base Competency" size 22 color "#0e0"
                    $ talentbase_value =  sbData["facTalents"]
                    text "[talentbase_value:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                    
                fixed xsize 340 ysize 22 xoffset 35 yoffset -5:
                    text "Skills Bonus" size 22 color "#0e0"
                    $ skilladd_value = sbData["facSkill"]
                    text "+[skilladd_value:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                    
                fixed xsize 340 ysize 22 xoffset 35 yoffset -5:
                    $ SkillLikes = str(len(selectedbot.likes))
                    $ SkillLikesBonus = sbData["facLikes"]
                    text "Preferred Skills (" + SkillLikes + ")" size 22 color "#0e0"
                    text "+[SkillLikesBonus:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
                    
                fixed xsize 340 ysize 22 xoffset 35 yoffset -5:
                    $ SkillDislikes = str(len(selectedbot.dislikes))
                    $ SkillDislikesBonus = sbData["facDislikes"]
                    text "Disfavored Skills (" + SkillDislikes + ")" size 22 color "#0e0"
                    text "[SkillDislikesBonus:.02f]" xpos 300 xalign 1.0 size 22 color "#0e0"
        
        
        # Arcade Sexbot Lineup Stats
        
        $ arcade_shells = []
        $ arcade_shelltypecount = 0
        $ arcade_traits = []
        $ arcade_traitcount = 0
        $ arcade_attitudes = []
        $ arcade_attitudecount = 0
        $ arcade_personalities = []
        $ arcade_personalitycount = 0

        for bot in GAME.arcade:
            if bot.addOns[5]:
                if bot.addOns[5].name not in arcade_shells:
                    $ arcade_shells.append(bot.addOns[5].name)
            else:
                $ arcade_shelltypecount = 1
            for i in bot.traits:
                if i not in arcade_traits:
                    $ arcade_traits.append(i)
                if bot.attitude not in arcade_attitudes:
                    $ arcade_attitudes.append(bot.attitude)
                if bot.personality not in arcade_personalities:
                    $ arcade_personalities.append(bot.personality)
                    
        $ arcade_shelltypecount += len(arcade_shells)
        $ arcade_multishelltypebonus = -3 + (arcade_shelltypecount * 3)
        $ arcade_attitudecount = len(arcade_attitudes)
        $ arcade_multiattitudebonus = -2 + (arcade_attitudecount * 2)
        $ arcade_traitcount = len(arcade_traits)
        $ arcade_multitraitbonus = -4 + (arcade_traitcount * 2)
        $ arcade_personalitycount = len(arcade_personalities)
        $ arcade_multipersonalitybonus = -2 + (arcade_personalitycount * 2)

        $ arcadebotcount = len(GAME.arcade)
        text "Number of\n   Different\n      Shell Types: " + str(arcade_shelltypecount) + "\n\nMulti-Shell\n  Income Bonus: " + str(arcade_multishelltypebonus) + "%\n\n\nNumber of Bot\n  Personality Types: " + str(arcade_personalitycount) + "\n\nMulti-Personalities\n  Income Bonus: " + str(arcade_multipersonalitybonus) + "%\n\n\nNumber of\n    Bot Traits: " + str(arcade_traitcount) + "\n\nMulti-Traits\n  Income Bonus: " + str(arcade_multitraitbonus) + "%\n\n\nNumber of Bot\n  Attitude Types: " + str(arcade_attitudecount) + "\n\nMulti-Attitudes\n  Income Bonus: " + str(arcade_multiattitudebonus) + "%":
            size 24
            xpos 1110
            ypos 225
            xanchor 0.5                
                
                
        #Other sexbots currently at arcade
        
        vpgrid:
            cols 3
            xpos 1280
            ypos 85
            spacing 10
            
            for i in GAME.arcade:
                $ slotnum += 1
                if i == selectedbot:
                    pass
                else:
                    frame background "05_gui/frame_arcadegals.png":
                        xysize 200, 320
                        if i.getShellConfig().lower() == "a":
                            image "03_minigames/mgsb_full_bot.png":
                                yalign 1.0
                                yoffset -22
                                xpos 0
                                zoom 0.24
                                
                            button action (SetVariable("selectedbot", i), SetVariable("slotnum", slotnum))
                            
                            text str(slotnum):
                                ypos 2
                                xpos 5
                                size 30
                                color "#09F"
                                bold True
                            text i.name:
                                ypos 2
                                xalign 0.55
                                size 24
                                xanchor 0.5
                            text "{:,} Cr".format(i.getPrice()):
                                ypos 286
                                xalign 0.5  
                                size 24 
                                xanchor 0.5
          
                        else:
                            image "03_minigames/mgsb_full_bot_{}.png".format(i.getShellConfig().lower()):
                                yalign 1.0
                                yoffset -22
                                xpos 0
                                zoom 0.24
                            button action (SetVariable("selectedbot", i), SetVariable("selected_slotnum", slotnum))
                            text str(slotnum):
                                ypos 2
                                xpos 2
                                size 30
                                color "#0CF"
                                bold True
                            text i.name:
                                ypos 2
                                xalign 0.55
                                size 24
                                xanchor 0.5
                            text "{:,} Cr".format(i.getPrice()):
                                ypos 286
                                xalign 0.5  
                                size 24 
                                xanchor 0.5
          
    #####################################################################
    #	                BOT MANAGER			
    #####################################################################
    elif lmMode == "bot manager":

        side "c r":
            area 375,140,1500,850
            viewport id "vp":
                draggable True
                mousewheel True
                
                vbox spacing 5:
                    for i in [x for x in GAME.lab.cells if x]:
                        if i.isComplete():
                            frame xsize 1450 ysize 80 background Solid("#0077aa88"):
                                padding (0,0)
                                image "03_minigames/ico_type_{}.png".format(i.getShellConfig().lower()) zoom 0.31 ypos 1 xpos 25
                                hbox xpos 105 ypos 46:
                                    for s in range(i.getStars()):
                                        image "03_minigames/star.png"  zoom 0.5
                                text i.name size FSIZE xpos 100 ypos 20  bold True
                                text "Value:\n    {:,} Cr".format (i.getPrice()) size FSIZE ypos 15 xpos 470 xalign 1.0
                                vbox xsize 500 xpos 550 yalign 0.5:
                                    text i.getShortDesc() yalign 0.5 size FSIZE

                                
                                fixed xsize 120 ysize 30  yalign 0.5 xpos 1050:
                                  if len(GAME.arcade) < 10:
                                    button action Return(["process", "sex arcade", i]):
                                        background Solid ("#0099ccff")
                                        hover_background Solid ("#55ccffff")
                                    text "Sex Arcade" xalign 0.5 ypos 5 size FSIZE_MED 
                                    
                                  else:
                                    button action NullAction():
                                        background Solid ("#ff9999ff")
                                    text "Sex Arcade" xalign 0.5 ypos 5 size FSIZE_MED
                                #if [order for order in GAME.lab.orders if i in GAME.lab.findBots(order)]:
                                    #frame xsize 120 ysize 30 background Solid ("#0099ccff") yalign 0.5 xpos 1250:
                                        #button action Return(["bot_ship", i])
                                        #text "Fulfill" xalign 0.5 yalign 0.5 size FSIZE_MED    
                                #else: 
                                fixed xsize 120 ysize 30 yalign 0.5 xpos 1250:
                                    button action Return(["bot_ship", i]):
                                        background Solid ("#0099ccff") 
                                        hover_background Solid ("#55ccffff")
                                    text "Shipping" xalign 0.5 yalign 0.5 size FSIZE_MED
                     
            vbar value YScrollValue("vp")


        image "03_minigames/ico bg1.png" pos 40, 400 zoom 0.5
        image "03_minigames/ico_BotShip.png" pos 40, 400 zoom 0.5    

label mg_lab_manager():
    # initialize
    #show image "room_lab_smart" 
    $ lmModes = ["parts storage", "special offers", "bot manager", "arcade manager"]
    $ lmMode = "parts storage"
        
    #$ partsFilter = {
            #"prefs": {"subpar": True, "basic": True, "advanced": True,        
            #"military grade": True, "elite": True},
            #"cat": {1: True, 2: True, 3: True },
            #"slot": {"cortex": True, "head": True, "torso": True, "arms": True, "legs": True, "addon": True, "shell": True, "cube": True} 
            #"kind": {"sexbot parts": True, "sexbot addons": True}  
        #}
    $ yadj = ui.adjustment() # to remember ypos in lab manager lists

    # stock special offers of the day (Basic or better)
    python:
        if not GAME.mc.hasDoneToday("special_offers"):
            parts = []
            GAME.lab.specialOffers = []
            n = random.randint(6,10)
            while n >= 0:
                # random stuff
                pFilter = random.choice(["sexbot addons", "sexbot parts", "sexbot parts"])
                if pFilter == "sexbot addons":
                    gFilter = random.choice([1,1,2,2,2,3,3])
                else:
                    gFilter = random.choice([1,2,2,2,2,3,3])

                part = random.choice([x for x in GAME.sbPartsData.values() if x.kind == pFilter and x.cat == gFilter and "no_find" not in x.tags])
                
                # ===== CR-0549 START
                # immobilizer luck roll
                if random.randint(1,100) > 90:
                    part = random.choice([x for x in GAME.sbPartsData.values() if "immo" in x.ID.lower() and x.cat == gFilter and "no_find" not in x.tags])
                # ===== CR-0549 END

                rolledPart = part.clone()
                rolledPart.wear = 0.0
                if rolledPart.pref in ["basic", "advanced", "military grade"]:
                    GAME.lab.specialOffers.append(rolledPart)
                    n -= 1
                

    # presort parts 
    #$ GAME.lab.parts.sort(key = lambda x : (x.ID.split('-')[0], prefsort.index(x.pref),  x.kind, x.price))
    $ GAME.lab.parts.sort(key = lambda x : (basesort.index(x.ID.split('-')[0]), prefsort.index(x.pref), x.price))

    # manager loop
    while True:
        call screen mg_lab_manager_scr(lmMode, lmModes, partsFilter, yadj) 
        if _return == False:  
            queue sound "audio/click.wav"
            #hide image "room_lab_smart" 
            return() 

        elif "filter" in _return:
            queue sound "audio/click.wav"
            $ fType = _return[1]
            $ fVal = _return[2]
            $ partsFilter[fType][fVal] = not partsFilter[fType][fVal]


        elif "arcade_retrieve" in _return:
            $ bot = _return[1]
            queue sound "audio/notify.wav"
            call large_notify("ARCADE RETRIEVAL", "You notify the arcade of {0}'s retrieval.\n\n{0} is uninstalled and packaged into a bot stasis pod. She will be dropped off tomorrow at your location.".format(C_SU_B+bot.name+C_SU_E), ["Continue"], "03_minigames/ico_BotArcade.png", "pink") from _call_large_notify_83 
            queue sound "audio/install.wav"
            $ GAME.inQueuePending.append(["bot", bot, GAME.day+1])
            $ GAME.arcade.remove(bot)
            
        #OhWee mod code

        elif "arcade_retrieve2" in _return:
            $ selectedbot = _return[1]
            queue sound "audio/notify.wav"
            call large_notify("ARCADE RETRIEVAL", "You notify the arcade of {0}'s retrieval.\n\n{0} is uninstalled and packaged into a bot stasis pod. She will be dropped off tomorrow at your location.".format(C_SU_B+selectedbot.name+C_SU_E), ["Continue"], "03_minigames/ico_BotArcade.png", "pink") from _call_large_notify_83a
            queue sound "audio/install.wav"
            $ GAME.inQueuePending.append(["bot", selectedbot, GAME.day+1])
            $ GAME.arcade.remove(selectedbot)
            $ selectedbot = GAME.arcade[0]
            $ selected_slotnum = 1
            
        #End OhWee mod code
            
        elif "scrap" in _return:
            $ part = _return[1]
            if "no_sell" in part.getBasePart().tags and part.getBasePart().ID not in ["SBPShell1TypeJ", "SBPShell2TypeJ", "SBPShell3TypeJ" ]:
                if "TypeI" in part.getBasePart().ID:
                    queue sound "audio/notify.wav"
                    call large_notify("CONFIRMATION", "A Type I (Infiltrator) Shell is required for essential Quest content. Selling every last one might prevent your progress lateron.\n\nDo you really want to sell that shell?", ["Confirm", "Abort"], "03_minigames/ico {}.png".format(part.getBasePart().ID)) from _call_large_notify_84
                    if _return == "Confirm":
                        call transaction("Bot Parts Scrap", int(part.getPrice()/2.0) , True) from _call_transaction_50 
                        $ GAME.lab.parts.remove(part)
                else:
                    queue sound "audio/tech_fail.wav"
                    mc "\"I should hold on to that part...\""
                    mc "\"I might need it later...\""
            else:
                call transaction("Bot Parts Scrap", int(part.getPrice()/2.0) , True) from _call_transaction_51 
                $ GAME.lab.parts.remove(part)

        elif "buy_part" in _return:
            $ part = _return[1]
            $ price = part.getPrice()*7 # markup
            if GAME.money < price:
                queue sound "audio/beep.wav"
                call simple_notify("LAB MANAGER", "Insufficient Funds.", ["Continue"]) from _call_simple_notify_110 
            else:
                call transaction("Bot Parts Purchases", -price , True) from _call_transaction_52 
                $ GAME.lab.specialOffers.remove(part)
                $ GAME.lab.parts.append(part)

        elif "bot_ship" in _return:
            $ bot = _return[1]
            call mg_sexbot_ship(bot) from _call_mg_sexbot_ship 

            # $ orders = [x for x in GAME.lab.orders if bot in GAME.lab.findBots(x)]
            # if orders != []:
            #     $ fac = 1.0
            #     $ order = orders.pop(0)
            #     $ GAME.lab.orders.remove(order) 
            # else:
            #     $ fac = 0.5 # fire sale
            # if GAME.getSpaceLoc().ID not in ["LIDPirate", "LIDStationArellarti"] and bot.getIQ() >= 140:
            #     play sound "audio/tech_fail.wav"
            #     call simple_notify("ORDER MANAGER", "Illegal Configuration", ["Continue"])
            #     if not GAME.mc.hasDone("illegal_bot_config"):
            #         queue sound "audio/drone_beep.wav"
            #         bb2 "\"Sexbots with IQ of 140 or higher may not be {i}officially{/i} traded.\""
            #         mc "\"Too, bad, they fetch a nice premium...\""
            #         call quest_updater()
            #     else:
            #         queue sound "audio/drone_beep.wav"
            #         bb2 "\"Remember, high IQ Bots can only be traded at the Pirate Outpost.\""
            #         mc "\"Ah, right.\""
            # else:
            #     call mg_sexbot_sell(bot, fac)

                           
        elif "process" in _return and _return[1] == "sex arcade":
            $ bot = _return[2]
            # $ bot = GAME.lab.current
            if len(GAME.arcade) >= 10:
                queue sound "audio/beep.wav"
                "Lab Manager" "\"Arcade contracting limit reached.\""
            elif bot.getShellConfig() == "I":
                queue sound "audio/notify.wav"
                mc "\"I better not send an Infiltrator to the Arcade...\""
                mc "\"I can imagine a whole number of things going really wrong there...\""
            elif bot.isIllegal() and GAME.getSpaceLoc().ID not in ["LIDPirate", "LIDStationArellarti"]:
                queue sound "audio/beep.wav"
                "Lab Manager" "\"Bot configuration illegal. Arcade prohibited.\""
                queue sound "audio/drone_beep.wav"
                bb2 "\"Remember, high IQ Bots can only be traded at the Pirate Outpost.\""
                mc "\"Ah, right.\""
            elif bot.isIllegal() and GAME.questSys.isDone("QID_PIRATE_CONTACT"):
                $ GAME.mc.tallyUp("Arcade Deliveries/P",1)
                $ GAME.arcade.append(bot)
                $ GAME.lab.clearBot(bot)
                #$ GAME.lab.clearLab()
                queue sound "audio/install.wav"
                call large_notify("SEX ARCADE", "You install {} on an arcade platform and prepare her for shipping to an Illegal Sex Arcade.\n\nEarnings will be credited to your account once per day.".format(bot.name), ["Continue"], "03_minigames/ico_BotArcade.png") from _call_large_notify_85 
                $ GAME.mc.hasDone("arcade_delivery")
            else:
                $ GAME.mc.tallyUp("Arcade Deliveries",1)
                $ GAME.arcade.append(bot)
                $ GAME.lab.clearBot(bot)
                # $ GAME.lab.clearLab()
                queue sound "audio/install.wav"
                call large_notify("SEX ARCADE", "You install {} on an arcade platform and prepare her for shipping to a Sex Arcade.\n\nEarnings will be credited to your account once per day.".format(bot.name), ["Continue"], "03_minigames/ico_BotArcade.png") from _call_large_notify_86 
                $ GAME.mc.hasDone("arcade_delivery")

            call quest_updater() from _call_quest_updater_211 

        elif "mode" in _return:
            queue sound "audio/click.wav"
            $ lmMode = _return[1]

    return()    

#####################################################################
#					PROCESS BOTS		
#####################################################################

label mg_sexbot_to_arcade(bot):
    if len(GAME.arcade) >= 10:
        queue sound "audio/beep.wav"
        "Lab Manager" "\"Arcade contracting limit reached.\""
    elif bot.isIllegal() and GAME.getSpaceLoc().ID != "LIDPirate":
        queue sound "audio/beep.wav"
        "Lab Manager" "\"Bot configuration illegal. Arcade prohibited.\""
        queue sound "audio/drone_beep.wav"
        bb2 "\"Remember, high IQ Bots can only be traded at the Pirate Outpost.\""
        mc "\"I forgot.\""        
    elif bot.isIllegal() and GAME.questSys.isDone("QID_PIRATE_CONTACT"):
        $ GAME.mc.tallyUp("Arcade Deliveries/P",1)
        $ GAME.arcade.append(bot)
        $ GAME.lab.clearLab()
        queue sound "audio/install.wav"
        call large_notify("SEX ARCADE", "You install {} on an arcade platform and prepare her for shipping to an Illegal Sex Arcade.\n\nEarnings will be credited to your account once per day.".format(bot.name), ["Continue"], "03_minigames/ico_BotArcade.png") from _call_large_notify_87 
        $ GAME.mc.hasDone("arcade_delivery")
    else:
        $ GAME.mc.tallyUp("Arcade Deliveries",1)
        $ GAME.arcade.append(bot)
        # $ GAME.lab.clearLab()
        queue sound "audio/install.wav"
        call large_notify("SEX ARCADE", "You install {} on an arcade platform and prepare her for shipping to a Sex Arcade.\n\nEarnings will be credited to your account once per day.".format(bot.name), ["Continue"], "03_minigames/ico_BotArcade.png") from _call_large_notify_88 
        $ GAME.mc.hasDone("arcade_delivery")
    call quest_updater() from _call_quest_updater_212 
    return()

label mg_sexbot_ship(bot):
    queue sound "audio/install.wav"
    call large_notify("BOT PACKAGING", "You package {}{}{} into a Stasis Pod and transfer the pod into the Cargo Bay for shipping.\n\nYou can sell and ship her out via the Cargo Manager.".format(C_HI_B, bot.name,C_HI_E), ["Continue"]) from _call_large_notify_89 
    $ GAME.ship.packBot(bot, "Shipping")
    $ GAME.lab.getBotFromCell(bot)
    queue sound "audio/load.wav"
    return()

label mgsb_quality_control(): #qc for current bot 

    # init
    $ TEC_MAX = 20
    $ qEffectDict = {"A": 20, "N": 25, "V": 30}
    $ qGalleryDict = {"A": 110, "N": 122, "V": 137}

    $ qAni = "ani_qc_bot_a"
    $ qAniDict = {"A": "ani_qc_bot_a", "N": "ani_qc_bot_n", "V": "ani_qc_bot_v"}
    $ shellType = GAME.lab.current.getShellConfig()

    # shell available for qc?
    if shellType in qEffectDict.keys() and shellType in qAniDict.keys():
        $ TEC_MAX = qEffectDict[shellType] 
        $ qAni = qAniDict[shellType]
        $ GAME.galleryAdd(qGalleryDict[shellType])

    if shellType in ["A", "N", "V"]:
        # play qc cutscene 
        "You prepare [C_HI_B][GAME.lab.current.name][C_HI_E] for Quality Control Testing..."
        scene expression("10_anims/ani_qc_bot_{}_00.jpg".format(GAME.lab.current.getShellConfig().lower())) with fade
        window hide 
        pause
        scene expression(qAni)
        window hide 
        pause
        # assess effect 
        #$ skillKey = random.choice(GAME.lab.current.skills.keys())
        $ qc_amount = max(0, GAME.mc.getAttr("TEC") - GAME.lab.current.qc)

        scene room_lab_smart with fade
        if qc_amount:
            # notify
            $ msgName = "[C_HI_B][GAME.lab.current.name][C_HI_E]"
            $ msgAmount = "[C_HI_B][qc_amount][C_HI_E]"
            $ skillcurrent = "{size=20}Current Skill Level:\nAna: " + str(GAME.lab.current.talents["ANA"]) + "/" + str(bot.skills["ANA"]) + "   Bon: " + str(GAME.lab.current.talents["BON"]) + "/" + str(bot.skills["BON"]) + "   Ora: " + str(GAME.lab.current.talents["ORA"]) + "/" + str(bot.skills["ORA"]) + "   Spe: " + str(GAME.lab.current.talents["SPE"]) + "/" + str(bot.skills["SPE"]) + "   Vag: " + str(GAME.lab.current.talents["VAG"]) + "/" + str(bot.skills["VAG"]) + "{/size}" 
                

            queue sound "audio/success.wav"
            call large_notify("QUALITY CONTROL RESULT", "The Quality Control Procedure for {0} was successful.\n\nSelect Skill to apply {1} Bonus Points!\n\n{2}".format(msgName, msgAmount, skillcurrent),["ANA", "BON", "ORA", "SPE", "VAG"], "08_items/ico ITMSpanner.png", "blue", ["narrow_button"]) from _call_large_notify_90 

            queue sound "audio/success.wav"


            $ skillKey = _return
            python:
                GAME.lab.current.qc += qc_amount   
                GAME.lab.current.talents[skillKey] += qc_amount 
                GAME.lab.current.skills[skillKey] += qc_amount 

            call simple_notify("SKILL UP - {}".format(GAME.lab.current.name), "{} +{}".format(skillKey, msgAmount),["Continue"], "08_items/ico ITMSpanner.png", "blue") from _call_simple_notify_111 

            $ GAME.mc.incAttrFrac("TEC", 0.5, TEC_MAX)
            
                
        else:
            play sound "audio/tech_fail.wav"
            "Your TEC skills were not sufficient for further Skill increase of [C_SU_B][GAME.lab.current.name][C_SU_E]."
        queue sound "audio/install.wav"

    # bot shell not allowed
    else:
        play sound "audio/tech_fail.wav"
        "Lab Manager" "\"Quality Control Function not available for this Model.\""
    return()

#####################################################################
#					STORAGE PART / BOT SELECTION	
#####################################################################
screen mg_sexbot_part_storage_scr(*args):
    $ partsKey = args[0]
    $ parts = args[1]
    $ partsFilter2 = args[2]
    #$ fOrder = args[3]
    
    image "05_gui/mask 50.png"
    use header
    
    text C_HI_B+"PARTS INVENTORY"+C_HI_E size FSIZE_LARGE pos 30, 90
    
    if "addon" in partsKey:
    
        text "Talent Boosters" pos 1035, 67 xalign 0.5 size FSIZE_MED
        
        hbox pos 650, 89 spacing 10:
            if not togglefilters1a:
                $ bCol = "#07af"
                $ bColh = "#09cf"
            else:
                $ bCol = "#555f"
                $ bColh = "#888f"
            fixed xsize 80 ysize 30:
                button action (
                        ToggleVariable("togglefilters1a", true_value=True, false_value=False), 
                        SetDict(partsFilter2['modules'], 'ANA', togglefilters1a), 
                        SetDict(partsFilter2['modules'], 'BON', togglefilters1a), 
                        SetDict(partsFilter2['modules'], 'ORA', togglefilters1a), 
                        SetDict(partsFilter2['modules'], 'SPE', togglefilters1a), 
                        SetDict(partsFilter2['modules'], 'VAG', togglefilters1a), 
                        SetDict(partsFilter2['modules'], 'PER', togglefilters1a), 
                        SetDict(partsFilter2['modules'], 'Immo', togglefilters1a), 
                        SetDict(partsFilter2['modules'], 'IQ', togglefilters1a)):
                    background Solid(bCol)
                    hover_background Solid(bColh)
                text "Addons" xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]
            text " > " size FSIZE yalign 0.5 yoffset 4

            for i in ["ANA", "BON", "ORA", "SPE", "VAG", "PER", "IQ", "Immo"]:
                if partsFilter2["modules"][i]:
                    $ bCol = "#07af"
                    $ bColh = "#09cf"
                else:
                    $ bCol = "#555f"
                    $ bColh = "#888f"
                fixed xsize 80 ysize 30:
                    button action Return(["filter", "modules", i]):
                        background Solid(bCol)
                        hover_background Solid(bColh)
                    text i xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]
                if i == "PER":
                    text " : " size FSIZE yalign 0.5 yoffset 4
            
            
    hbox pos 475, 128 spacing 10:
            if not togglefilters2:
                $ bCol = "#07af"
                $ bColh = "#09cf"
            else:
                $ bCol = "#555f"
                $ bColh = "#888f"
            fixed xsize 100 ysize 30:
                button action (
                        ToggleVariable("togglefilters2a", true_value=True, false_value=False), 
                        SetDict(partsFilter2['cat'], 1, togglefilters2a), 
                        SetDict(partsFilter2['cat'], 2, togglefilters2a), 
                        SetDict(partsFilter2['cat'], 3, togglefilters2a), 
                        SetDict(partsFilter2['prefs'], 'subpar', togglefilters2a), 
                        SetDict(partsFilter2['prefs'], 'basic', togglefilters2a), 
                        SetDict(partsFilter2['prefs'], 'advanced', togglefilters2a), 
                        SetDict(partsFilter2['prefs'], 'military grade', togglefilters2a), 
                        SetDict(partsFilter2['prefs'], 'elite', togglefilters2a)):
                    background Solid(bCol)
                    hover_background Solid(bColh)
                text "Toggle All" xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]
            text " > " size FSIZE yalign 0.5 yoffset 4
            for i in [1,2,3]:
                if partsFilter2["cat"][i]:
                    $ bCol = "#07af"
                    $ bColh = "#09cf"
                else:
                    $ bCol = "#555f"
                    $ bColh = "#888f"
                fixed xsize 102 ysize 30:
                    button action Return(["filter", "cat", i]):
                        background Solid (bCol)
                        hover_background Solid (bColh)
                    text "Gen {}".format(i) xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]
                    
            text " : " size FSIZE yalign 0.5 yoffset 4 outlines [ (1, "#0488", 1, 1) ]
            for i in ["subpar", "basic", "advanced", "military grade", "elite"]:
                if partsFilter2["prefs"][i]:
                    $ bCol = "#07af"
                    $ bColh = "#09cf"
                else:
                    $ bCol = "#555f"
                    $ bColh = "#888f"
                fixed xsize 135 ysize 30:
                    button action Return(["filter", "prefs", i]):
                        background Solid (bCol)
                        hover_background Solid (bColh)
                    text i.title() xalign 0.5 ypos 7 size FSIZE_MED outlines [ (1, "#0488", 1, 1) ]# CR-0298
                    
    frame xsize 1355 ysize 27 background Solid("#0077aa88") xpos 475 ypos 167:
            padding (0,0)
            text "Component" xpos 275 ypos 3 size 24
            text "Condition" xpos 600 ypos 3 size 24
            text "Value" xpos 772 ypos 3 size 24
            if "addon" in partsKey:
                text "Modifier" xpos 950 ypos 3 size 24
    side "c r":
        area 475,200,1400,840
        viewport id "vp":
            draggable True
            mousewheel True
            
            vbox pos 500,120 xsize 1350 spacing 5:
                for i in parts:
                    $ display = True
                    
                    if "addon" not in partsKey:
                        $ display = partsFilter2["cat"][i.cat] and partsFilter2["prefs"][i.pref]
                    else:
                        $ display = partsFilter2["cat"][i.cat] and partsFilter2["prefs"][i.pref]
                        for x in {"ANA", "BON", "ORA", "SPE", "VAG", "PER", "IQ", "Immo"}:
                             if x in (i.ID):
                                 if partsFilter2["modules"][x] != True:
                                     $ display = False
                        #$ display = any([i.isMatch(k) and partsFilter2[k] for k in partsFilter2.keys()])

                    if display:
                      fixed xsize 1350 ysize 66:
                        frame xsize 1230 ysize 66 background Solid("#0077aa88"):
                            padding (0,0)
                            if partsKey == "giveshell":
                                button action Return(i) tooltip i hover_background Solid("#00ccff22")
                            elif not bot.hasComp("cortex") and partsKey != "cortex":
                                button action NullAction() tooltip i hover_background Solid("#00ccff22")
                            
                            else:
                                button action Return(i) tooltip i hover_background Solid("#00ccff22")
                            image "{}{}".format("22_bot_thumb/",i.getIco()) zoom 0.65 xpos 20 yalign 0.5
                            text i.getName() size FSIZE yalign 0.5 xpos 160
                            text "{}".format(percentColorized(i.getGrade())[0]) size FSIZE yalign 0.5 xpos 630 
                            text "{:,} Cr".format(i.getPrice()) size FSIZE yalign 0.5 xpos 850 xalign 1.0
                            $ framexsize = 50
                            if "Immobilizer" in i.name:
                                $ framexsize = 80
                            frame xsize framexsize ysize 30 background None yalign 0.5 xpos 950 yoffset -20:
                                        
                                if "Shell" in i.ID:
                                    text ""

                                elif i.getBoostOneLiner():
                                    #if "IQ" in i.getBoostOneLiner()
                                    text i.getBoostOneLiner() xalign 0.5 xoffset 15 yoffset 5 text_align 0.5 size FSIZE


                                elif "Immobilizer" in i.name:

                                    $ immopmod1 = str(int(immoBaseEffects[i.cat][0]*prefImpact[i.pref]/-1))

                                    $ immopmod2 = immoBaseEffects[i.cat][1]*prefImpact[i.pref]
                                    if immopmod2 > int(immopmod2):
                                        $ immopmod2 = str(immopmod2/-1)
                                    else:
                                         $ immopmod2 = str(int(immopmod2)/-1)

                                    $ immopmod3 = immoBaseEffects[i.cat][2]*prefImpact[i.pref]
                                    if immopmod3 > int(immopmod3):
                                        $ immopmod3 = str(immopmod3/-1)
                                    else:
                                         $ immopmod3 = str(int(immopmod3)/-1)
                                    text  immopmod1 + "{size=18} %{color=#0FF}  G1\n{/color}{/size}" + immopmod2 + "{size=18} %{color=#0FF}  G2\n{/color}{/size}" + immopmod3 + "{size=18} %{color=#0FF}  G3{/color}{/size}" xalign 1.0 text_align 1.0 size 22 line_spacing -2 yoffset -1 kerning -2


                        if bot.hasComp("cortex"):
                            frame xsize 120 ysize 66 xpos 1235 background Solid("#0077aa88"):
                                padding (0,0)
                                fixed xsize 80 ysize 30 xalign 0.5 yalign 0.5:                       
                                    button action Return(["scrap",i]) tooltip i:
                                        background Solid ("#cc0000ff")
                                        hover_background Solid ("#ff4400ff")     
                                    text "Scrap" xalign 0.5 ypos 5 size FSIZE_MED


        vbar value YScrollValue("vp")



    $ tooltip = GetTooltip()
    if tooltip and tooltip in parts:
        frame padding 15,15 xsize 460 ysize 840 pos 0, 220 background Solid("#39210000"):
            image "08_items/ico bg1.png" zoom 0.5 xalign 0.5 ypos 40# xpos 50 ypos 100
            image "{}/{}".format("03_minigames/",tooltip.getIco()) zoom 0.5 xalign 0.5 ypos 40# xpos 50 ypos 100
            vbox xsize 400 ypos 320 spacing 20 xalign 0.5:
                text tooltip.getName() xalign 0.5 size FSIZE
                text tooltip.getDesc() xalign 0.5 size FSIZE
                if tooltip.getBoostOneLiner():
                    text tooltip.getBoostOneLiner() xalign 0.5 size FSIZE
                text "Value: {:,} Cr".format(tooltip.getPrice()) xalign 0.5 size FSIZE

    #####################################################################
    #                EXIT BUTTON
    #####################################################################
    frame xsize 350 ysize 64 pos 0,900 background Solid("#00000000") padding 0,0:
        image "05_gui/gui_menu_option.png" yalign 0.5
        button action Return(False)xpos 20
        textbutton "Exit (X)" yalign 0.5 action Return(False) xpos 20  # CR-0587
        key "x" action Return (False)
        key "X" action Return (False)            

label mg_sexbot_part_storage(partsKey):  
    show image "room_lab_smart" 
    $ interactive = True
    
    $ GAME.lab.parts.sort(key = lambda x : (basersort.index(x.ID.split('-')[0]), prefrsort.index(x.pref), x.price))

    while interactive:   
    
        if partsKey == "addon":
            $ parts = [x for x in GAME.lab.parts if x.slot == "addon"]
        elif partsKey == "shell":
            $ parts = [x for x in GAME.lab.parts if x.slot == "shell"]
        elif partsKey == "giveshell":
            $ parts = [x for x in GAME.lab.parts if x.slot == "shell"]
        elif partsKey == "cube":
            $ parts = [x for x in GAME.lab.parts if x.slot == "cube"]
        else:
            $ parts = [x for x in GAME.lab.parts if x.slot == partsKey]

        $ parts = sorted(parts, key=lambda x : (basersort.index(x.ID.split('-')[0]), prefrsort.index(x.pref)))    


        
        call screen mg_sexbot_part_storage_scr(partsKey, parts, partsFilter2)
        if _return == False:
            $ interactive = False

        elif _return in parts:
            $ interactive = False

        elif "filter" in _return:
            queue sound "audio/click.wav"
            $ fType = _return[1]
            $ fVal = _return[2]
            $ partsFilter2[fType][fVal] = not partsFilter2[fType][fVal] 

        elif "scrap" in _return:
            $ part = _return[1]
            call transaction("Bot Parts Scrap", part.getPrice() , True) from _call_transaction_53 
            $ GAME.lab.parts.remove(part)

    hide image "room_lab_smart"
    # hide image  "05_gui/mask 50.png"
    return(_return)

#####################################################################
#					BOT STORAGE MANAGER					       	
#####################################################################
  
screen mg_sexbot_bot_storage_scr(*args):

    $ mode = args[0] # store / multiverse
    text C_HI_B+"BOT STORAGE"+C_HI_E size FSIZE_LARGE pos 960, 80 xalign 0.5

    side "c r":
        area 440,240,1420,684
        viewport id "vp":
            draggable True
            mousewheel True
            
            vbox pos 500,120 xsize 1300 spacing 5:
                for i in [x for x in GAME.lab.cells if x]:
                    frame xsize 1300 ysize 80 background Solid("#0099cc88"):
                        hbox yalign 0.5 xpos 20:
                            for s in range(i.getStars()):
                                image "03_minigames/star.png"  zoom 0.5
                        text i.name size FSIZE yalign 0.5 xpos 140
                        text "{}".format({True: "Complete", False: "Unfinished"}[i.isComplete()]) size FSIZE yalign 0.5 xpos 260
                        vbox xsize 500 xpos 400 yalign 0.5:
                            text i.getShortDesc() yalign 0.5 size FSIZE
                        text "{:,} Cr".format(i.getPrice()) size FSIZE yalign 0.5 xpos 960 xalign 1.0
                        # LAB Operation Mode
                        if mode == "store":
                            frame xsize 80 ysize 30 background Solid ("#0099ccff") yalign 0.5 xpos 1000:
                                button action Return(["config_bot", i])
                                text "Config" xalign 0.5 yalign 0.5 size FSIZE_MED
                            fixed xsize 80 ysize 30 yalign 0.5 xpos 1200:
                                button action Return(["scrap_bot",i]):
                                    background Solid ("#cc6600ff")
                                    hover_background Solid ("#ccaa00ff")
                                text "Scrap" xalign 0.5 yalign 0.5 size FSIZE_MED
                        # Export Bot Mode
                        else:
                            frame xsize 80 ysize 30 background Solid ("#0099ccff") yalign 0.5 xpos 1000:
                                button action Return(["export_bot", i])
                                text "Export" xalign 0.5 yalign 0.5 size FSIZE_MED                        

        vbar value YScrollValue("vp")

    #####################################################################
    #                EXIT BUTTON
    #####################################################################
    frame xsize 350 ysize 64 pos 0,900 background Solid("#00000000") padding 0,0:
        image "05_gui/gui_menu_option.png" yalign 0.5
        button action Return(False)xpos 20
        textbutton "Exit (X)" yalign 0.5 action Return(False) xpos 20 # CR-0587
        key "x" action Return (False)
        key "X" action Return (False)            

label mg_sexbot_bot_storage(mode="store"):

    show image "room_lab_smart"
    # show image  "05_gui/mask 50.png"
    $ interactive = True
    while interactive:
        call screen mg_sexbot_bot_storage_scr(mode)
        if _return == False:
            $ interactive = False

        elif "config_bot" in _return:
            $ newBot = _return[1]
            $ GAME.lab.storeBot(GAME.lab.current)
            $ GAME.lab.retrieveBot(newBot)
            queue sound "audio/load.wav"
            $ interactive = False

        # elif "sell_bot" in _return:
        #     $ bot = _return[1]
        #     call mg_sexbot_sell(bot)

        elif "export_bot" in _return:
            $ bot = GAME.lab.getBotFromCell(_return[1])
            return(bot)


    hide image "room_lab_smart"
    # hide image  "05_gui/mask 50.png"
    return(False)

#####################################################################
#					CONFIGURATION SCREENS		
#####################################################################
    
screen mg_sexbot_prep_scr():
    image "lab_bg"
    # image "03_minigames/mgsb_bg.png"
    # Bot composite image 
    $ bot = GAME.lab.current
    if bot.isComplete():
        image "full_bot" # completed bot
    else:    
        image "bot_doll" # gray doll

    #####################################################################
    #					DATA PANEL LEFT								  #
    #####################################################################
    # Bot Data
    vbox spacing 10 pos 50, 40:
        text C_HI_B+"BOT POTENTIAL"+C_HI_E 
        image "05_gui/px_1x1_orange.png" xsize 200 ysize 3 yalign 0.5
        hbox:
            for i in range(bot.getStars()):
                image "03_minigames/star.png" 

    vbox spacing 10 pos 50, 150:
        text C_HI_B+"DESIGNATION"+C_HI_E 
        image "05_gui/px_1x1_orange.png" xsize 200 ysize 3 yalign 0.5
        if bot.hasComp("cortex"):
            text "{}".format(bot.name)
        else:
            text "None"

    vbox spacing 10 pos 50, 260:
        text C_HI_B+"VALUE"+C_HI_E 
        image "05_gui/px_1x1_orange.png" xsize 200 ysize 3 yalign 0.5
        if bot.hasComp("cortex"):
            text "{:,} Cr".format(bot.getPrice())
        else:
            text "n/a"

    #####################################################################
    #					DATA PANEL RIGHT		  					  
    #####################################################################
    frame xsize 1080 ysize 1080 background Solid ("ffffff00") xalign 1.0: 
        text C_HI_B+"BOT CONFIGURATION & TRAINING"+C_HI_E xalign 0.5 ypos 20 size FSIZE_LARGE
        image "05_gui/px_1x1_orange.png" xsize 800 ysize 3 xalign 0.5 ypos 80

        # Lab charging status 
        $ labRes = [ "ITMCarbonFiberSpools", "ITMOrePromethium", "ITMAICore", "ITMAICoreElite", "ITMPodBio", "ITMPodEnergy", "ITMPodNano"]
        $ labResTips = {
            "ITMOrePromethium": "Required for Hypertrain. Click Hypertrain in left menu. Consumed.", 
            "ITMAICore": "Used to upgrade Cortex Gen. Upgrade Cortex in left menu to use. Consumed.", 
            "ITMAICoreElite": "Used to upgrade Gen3 Cortex to Precursor Type. Upgrade Cortex in left menu. Consumed.",
            "ITMCarbonFiberSpools": "Used to upgrade structural components to a higher Gen. Consumed", 
            "ITMPodBio": "Used to repair bot parts. Consumed by repair.",
            "ITMPodEnergy": "Used to train bots. Consumed by training.",
            "ITMPodNano": "Used to repair or upgrade bot parts. Consumed by repair."
            }

        $ labResCount = [GAME.ship.cargo.count(GAME.items[x]) for x in labRes]
        vbox xpos 700 ypos 120 xsize 300 spacing 10:
            text C_HI_B+"LAB RESOURCES"+C_HI_E
            $ gX,gY = 4,2
            grid gX gY spacing 10:
                for i in range(gX*gY):
                    frame xsize 64 ysize 64 background Solid("#0099cc00") padding 3,3:
                        if i < len(labRes):
                            image "08_items/ico {}.png".format(labRes[i]) xalign 0.5 yalign 0.5 zoom 0.2 
                            $ amount = labResCount[i]           
                            if amount:                 
                                text "{}x".format(amount) size FSIZE
                            else:
                                image "05_gui/ico_attention.png" xalign 0.5 yalign 0.5
                            button action NullAction() tooltip labResTips[labRes[i]]
                        else:
                            text " "
            image "05_gui/px_1x1_empty.png" 
            for k in ["Bio","Energy", "Nano"]:
                frame xsize 340 ysize 30 background Solid("#ffffff00"):
                    text "{}".format(k) size FSIZE yalign 0.5
                    bar xsize 120 ysize 20 range 400 value GAME.lab.status[k.lower()] yalign 0.5 xpos 160                       


        # Information     
        vbox xpos 80 ypos 120 spacing 20:
            text C_HI_B+"INFORMATION"+C_HI_E 
            if bot.hasComp("cortex"):
                $ colRange = ["green", "yellow", "orange", "red"]
                text "IQ {} | {} | Escape Risk (%): {}".format(
                    bot.getIQ(), 
                    bot.colorize(bot.getAttitude().title()), 
                    colMap (bot.getEscapeProb()*100, colRange, [-5, 20])
                    )
                text  "[C_HI_B]TRAITS:[C_HI_E] {}".format(" | ".join(
                    [ bot.colorize(x.title()) for x in bot.getTraits()]))

                text  "[C_HI_B]PERSONALITY:[C_HI_E] {}".format(bot.colorize(bot.getPersonality().title()))

        # ADD-Ons
        $ GRADES = {"subpar": "Subpar", "basic": "Basic", "advanced": "Advanced", "military grade": "MilGrade", "elite": "Elite"}
        text C_HI_B+"SHELL                             ADD-ON MODULES"+C_HI_E xpos 90 ypos 420
        hbox xpos 80 ypos 482 spacing 20:
            #if bot.hasComp("cortex"):
                # shell special slot #5
                frame xsize 96 ysize 96:
                    if bot.addOns[5]:
                        image "{}{}".format(bot.addOns[5].getPath(), bot.addOns[5].getIco()) zoom 0.375 xalign 0.5 yalign 0.5 
                        button action Return(["module", 5]) tooltip bot.addOns[5]
                        text "{}".format(GRADES[bot.addOns[5].pref]) size 21 xpos 3 ypos 90 outlines [ (2, "#000f", 1, 1) ]
                    else:
                        #button action Return(["module", 5])  
                            $ addons_shells = [x for x in GAME.lab.parts if "Shell" in x.ID]# and "Shell" in x.name]
                            if len(addons_shells) < 1:
                                add "/images/03_minigames/AEExclamation_red.png" xsize 96 ysize 98 xpos -8 yalign 0.4
                                text "{b}{i}NONE{/i}{/b}" size 30 text_align 0.5 xalign 0.5 yalign 0.6 color "#ffff0090"
                            elif not bot.isComplete():
                                add "/images/03_minigames/AEExclamation_red.png" xsize 96 ysize 98 xpos -8 yalign 0.4
                                text "{b}{i}VIEW\nONLY{/i}{/b}" size 30 text_align 0.5 xalign 0.5 yalign 0.6 color "#ffff0090"
                                button action Return(["module", 5]) 
                                #button action (SetVariable("shellslot", True), SetVariable("addon_buttons", False), Return(["module", 5]))
                            else:
                                button action Return(["module", 5]) 
                                #button action (SetVariable("shellslot", True), SetVariable("addon_buttons", False), Return(["module", 5]))                        
                                               
                image "05_gui/px_1x1_orange.png" xsize 3 ysize 64 yalign 0.5 xalign 0.5              
                # standard modules slots #0 to 4
                for i in range(5): # 
                    frame xsize 96 ysize 96:
                        if bot.addOns[i]:
                            if bot.addOns[i].cat == 1:
                                image "03_minigames/ico_gen1fadebg.png" xsize 90 ysize 90 yalign 0.5 xalign 0.5
                            elif bot.addOns[i].cat == 2:
                                image "03_minigames/ico_gen2fadebg.png" xsize 90 ysize 90 yalign 0.5 xalign 0.5
                            else: #if bot.addOns[i].cat == 3:
                                image "03_minigames/ico_gen3fadebg.png" xsize 90 ysize 90 yalign 0.5 xalign 0.5
                            image "{}{}".format(bot.addOns[i].getPath(), bot.addOns[i].getIco()) zoom 0.375 xalign 0.5 yalign 0.5 
                            button action Return(["module", i]) tooltip bot.addOns[i]
                            #hbox xalign 0.5 ypos 64:
                                #frame xsize 32 ysize 24 background Solid("#00000000"):
                                    #text "{}".format(bot.addOns[i].cat) size FSIZE  xalign 0.5 yalign 0.5
                                #frame xsize 64 ysize 24 background Solid("#00000000"):
                            if bot.addOns[i].getBoostOneLiner():
                                text bot.addOns[i].getBoostOneLiner()[3:] xalign 0.985 ypos 63 size FSIZE outlines [ (2, "#000f", 1, 1) ]
                            elif "Immobilizer" in bot.addOns[i].name:
                                $ botGen = bot.parts["cortex"].cat
                                $ immomod = immoBaseEffects[bot.addOns[i].cat][botGen-1]*prefImpact[bot.addOns[i].pref]
                                if immomod > int(immomod):
                                    $ immomod = str(immomod/-1)
                                else:
                                    $ immomod = str(int(immomod)/-1)
                                text immomod xalign 0.985 ypos 63 size FSIZE outlines [ (2, "#000f", 1, 1) ]
                            text "{}".format(GRADES[bot.addOns[i].pref]) size 21 xpos 3 ypos 92 color "0dff"#outlines [ (2, "#000f", 1, 1) ]

                        else:
                            button action Return(["module", i])
                
        # Training
        vbox xpos 80 ypos 640 spacing 20:
            $ hyperMsg, qcMsg = "", ""
            if bot.qc < GAME.mc.getAttr("TEC"):
                $ qcMsg = "{}QC +{}{}".format(C_SU_B, GAME.mc.getAttr("TEC")-bot.qc,C_SU_E)
            if "hyper-train" in GAME.lab.status.keys():
                if GAME.lab.status["hyper-train"] > 0:
                    $ hypertrainpercent = (GAME.lab.status["hyper-train"] * 5)
                    $ hyperMsg = "{}Hyper-Train On: [hypertrainpercent]% left     {}".format(C_OR_B, C_OR_E, GAME.lab.status["hyper-train"])
            text C_HI_B+" SKILLS:     {}{}".format(hyperMsg, qcMsg)+C_HI_E xoffset -65
            if bot.hasComp("cortex"):
                for k in sorted(GAME.sbData["skillDict"].keys()):
                    $ C_B, C_E = "", "" 
                    if bot.talents[k] < bot.getTalents()[k]:
                        $ C_B, C_E = C_GR_B, C_GR_E 
                    frame xsize 600 ysize 40 background Solid("#ffffff00"):
                        if GAME.sbData["skillDict"][k].lower() in bot.getDislikes():
                            image "03_minigames/gui_mini_dislike.png" xpos -64 ypos -10
                        elif GAME.sbData["skillDict"][k].lower() in bot.getLikes():
                            image "03_minigames/gui_mini_heart.png" xpos -64 ypos -10
                        text C_B+GAME.sbData["skillDict"][k].title()+C_E yalign 0.5 
                        if bot.skills[k] >= bot.getTalents()[k]:
                            text "{}".format(bot.skills[k]) xpos 280 xalign 0.5
                            if bot.skills[k] >= 90:
                                text C_SU_B+"{} Expert".format(GAME.sbData["skillDict"][k].title())+C_SU_E xpos 400
                        else:
                            text "{}".format(0) xpos 140 yalign 0.5
                            bar xsize 200 ysize 28 yalign 0.5 xpos 180 value bot.skills[k] range 100
                            text "{}".format(max(100,bot.skills[k])) xpos 400  yalign 0.5
                            # frame xsize 100 ysize 40 xpos 520 background Solid("#0099cc") yalign 0.5:
                            #     text "Train" xalign 0.5 yalign 0.5 size FSIZE 
                            #     button action Return(["train", k])
        
        # Autotrain Frame 
        if bot.isComplete():
            frame xsize 328 ysize 248 pos 700, 705:
                if bot.autoTrain:
                    image "ani_thumb_auto" zoom 0.5 xalign 0.5 yalign 0.5
                    #text "ACTIVE" xalign 0.5 yalign 0.1 size FSIZE 
                    image "05_gui/px_1x1_green.png" xsize 20 ysize 20 
                else:
                    image "10_anims/ani_thumb_auto_00.jpg" zoom 0.5 xalign 0.5 yalign 0.5
                    #text "INACTIVE" xalign 0.5 yalign 0.1 size FSIZE 
    #####################################################################
    #					TOOLTIPS						  
    #####################################################################
    $ tooltip = GetTooltip()
    if tooltip and isinstance(tooltip, str):
        vbox  pos 1300,990 xalign 0.5 spacing 10:
            bar xsize 300 ysize 2 xalign 0.5
            text "{}".format(tooltip) xalign 0.5 size FSIZE
            bar xsize 300 ysize 2 xalign 0.5

         
screen mg_sexbot_scr():
    $ bot = GAME.lab.current

    #####################################################################
    #                EXIT BUTTON
    #####################################################################
    vbox pos 0,960  spacing 20:
        frame xsize 350 ysize 64 background Solid("#00000000") padding 0,0:
            image "05_gui/gui_menu_option.png" yalign 0.5
            button action Return(False)xpos 20
            textbutton "Exit (X)" yalign 0.5 action Return(False) xpos 20 # CR-0587
            key "x" action Return (False)
            key "X" action Return (False)     

    #####################################################################
    #					INTERACTIVE											  #
    #####################################################################
    # bot cells
    vbox spacing 10 pos 50, 380:
        text C_HI_B+"BOT STORAGE"+C_HI_E 
        image "05_gui/px_1x1_orange.png" xsize 200 ysize 3 yalign 0.5
        grid 5 GAME.lab.cellsMax/5 spacing 5:
            for i in range(GAME.lab.cellsMax):
                if GAME.lab.cells[i]:
                    frame xsize 25 ysize 25 background Solid("#0099ccff") padding 0,0:
                        button action Return(["bot", GAME.lab.cells[i], i]) tooltip GAME.lab.cells[i]
                        if GAME.lab.cells[i].autoTrain:
                            image "/05_gui/px_1x1_green.png" xsize 8 ysize 8
                else:
                    frame xsize 25 ysize 25 background Solid("#00000055") padding 0,0:
                        if GAME.lab.current:
                            if GAME.lab.current.hasComp("cortex"):
                                button action Return(["process", "store", i]) 
                            pass
                        pass
        #image "05_gui/px_1x1_orange.png" xsize 200 ysize 3 yalign 0.5 # CR-0323
        #text C_OR_B+"CLICK EMPTY DOT TO STORE"+C_OR_E size FSIZE_MED # CR-0323
 
    #####################################################################
    #					LAB OPTIONS		
    #####################################################################
    $ options = []


    if bot.isComplete() and bot.parts["cortex"].cat == 3 and any([GAME.ship.countCargo(x) for x in ["ITMAICoreElite"]]): # upgrade
        $ options = ["upgrade cortex"] + options 
    elif bot.isComplete() and any([GAME.ship.countCargo(x) for x in ["ITMAICoreElite", "ITMAICore"]]): 
        $ options = ["upgrade cortex"] + options

    if bot.isComplete() and GAME.ship.countCargo("ITMOrePromethium"): # training efficiency +
        $ options = ["hyper-train"] + options 
    $ options = options + ["lab manager"]
    if GAME.lab.current.isComplete() and "INV_YUTANI" in GAME.investments:
        $ options = ["bot analyzer"]+options
    if bot.isComplete():
        $ options = ["quality control"] + options


    vbox ypos 940 yalign 1.0 spacing 20:
        # frame xsize 100 ysize 300
        for i in options:
            frame xsize 350 ysize 64 background Solid("#00000000") padding 0,0:
                image "05_gui/gui_menu_option.png" yalign 0.5
                textbutton i.title() yalign 0.5 action NullAction() xpos 20
                button action Return(["process", i])xpos 20

    #####################################################################
    #					DATA PANEL LEFT								  #
    #####################################################################
    # Change Name / Reroll nme
    if bot.hasComp("cortex"):
        frame xsize 32 ysize 32 pos 220, 146 background Solid ("#00000000") padding 0,0:
            image "03_minigames/gui_mini_pen.png" xalign 0.5 yalign 0.5
            button action Return(["rename", None])
        frame xsize 32 ysize 32 pos 260, 146 background Solid ("#00000000") padding 0,0:
            image "05_gui/gui_mini_reroll.png" xalign 0.5 yalign 0.5
            button action Return(["reroll_name", None]) 

    # Config screen /  Buttons and Active Elements 
    $ pPosY = [40, 174, 307, 440, 930]
    $ GRADES = {"subpar": "Subpar", "basic": "Basic", "advanced": "Advanced", "military grade": "MilGrade", "elite": "Elite"}
    for i in range(5):
        $ parts2a = [x for x in GAME.lab.parts if x.slot == bot.partNames[i]] 

    # Parts Data Fixed
    for i in range(5):

        vbox xsize 200 spacing 10 pos 600, pPosY[i]:
            text C_HI_B+bot.partNames[i].upper()+C_HI_E xpos 110
        if bot.hasComp(bot.partNames[i]):
            $ part = bot.parts[bot.partNames[i]]
            frame xsize 96 ysize 96 pos 600, pPosY[i]:
                image "{}{}".format(part.getPath(), part.getIco()) zoom 0.25 xalign 0.5 yalign 0.5
                button action Return(["remove", bot.partNames[i]]) tooltip part 
                text "{}".format(GRADES[part.pref]) size 21  xpos 115 ypos 27 color "#0aff"# outlines [ (2, "#000f", 1, 1) ]
                text "{}".format( percentColorized(part.getGrade())[0] ) xpos 200 ypos 60 xalign 1.0

        elif bot.partNames[i] != "cortex":# and bot.hasComp("cortex"):
            frame xsize 96 ysize 96 pos 600, pPosY[i]:
                #button action Return(["add", bot.partNames[i]]) 
                if len(parts2a) > 0:
                    if not bot.hasComp("cortex"):
                        add "/images/03_minigames/AEExclamation_red.png" xsize 96 ysize 98 xpos -8 yalign 0.4
                        text "{b}{i}VIEW ONLY{/i}{/b}" size 30 text_align 0.5 xalign 0.5 yalign 0.6 color "#ffff0090"
                    button action Return(["add", bot.partNames[i]])
                else:
                    add "/images/03_minigames/AEExclamation_red.png" xsize 96 ysize 98 xpos -8 yalign 0.4
                    text "{b}{i}NONE{/i}{/b}" size 30 text_align 0.5 xalign 0.5 yalign 0.6 color "#ffff0090"
        elif bot.partNames[i] == "cortex":
            frame xsize 96 ysize 96 pos 600, pPosY[i]:
                if len(parts2a) < 1:
                    add "/images/03_minigames/AEExclamation_red.png" xsize 96 ysize 98 xpos -8 yalign 0.4
                    text "{b}{i}NONE{/i}{/b}" size 30 text_align 0.5 xalign 0.5 yalign 0.6 color "#ffff0090"
                else:
                    button action Return(["add", bot.partNames[i]]) 

        vbox xsize 200 spacing 10 pos 600, pPosY[i]:
            text " "
            #image "05_gui/px_1x1_orange.png" xsize 200 ysize 3 yalign 0.5
            if bot.hasComp(bot.partNames[i]):
            
                fixed xsize 140 ysize 40 xalign 1.0: #background Solid ("#00000000"):
                    
                    if True and bot.partNames[i] != "cortex" and "gen_upgrade_talk" in bb_2.done:
                    
                      if (part.cat == 3 and gradeTECReq[part.pref] <= GAME.mc.attr["TEC"]) or part.cat < 3:
                        fixed xsize 40 ysize 40 ypos -51 xpos 145:
                            image "03_minigames/gui_mini_up.png" xalign 0.5 yalign 0.5
                            button action Return(["gen_up", bot.partNames[i]])
                      else:
                        pass

                    if bot.parts[bot.partNames[i]].getGrade() < 100:
                        fixed xsize 40 ysize 40 ypos -5 xpos 140:
                            image "03_minigames/gui_mini_wrench.png" xalign 0.5 yalign 0.5
                            button action Return(["repair", bot.partNames[i]])
            else:
                text "n/a" xalign 1.0

    # cortex cube slot 
    if bot.hasComp("cortex"):
        if bot.parts["cortex"].attr["BaseID"] == "SBPCortexPre":
            frame xsize 48 ysize 48 pos 532, pPosY[0]:
                button action Return(["add", "cube"]) 


    #####################################################################
    #					TRAINING BUTTONS				  
    #####################################################################

    # Training
    vbox xpos 80 ypos 645 spacing 20:
        text  " "
        if bot.isComplete() and not bot.autoTrain:
            for k in sorted(GAME.sbData["skillDict"].keys()):
                frame xsize 600 ysize 40 background Solid("#ffffff00"):
                    if bot.skills[k] < bot.getTalents()[k]:
                        frame xsize 100 ysize 40 xpos 1320 background Solid("#0099cc") yalign 0.5:
                            text "Train" xalign 0.5 yalign 0.5 size FSIZE 
                            button action Return(["train", k]) 
    # Autotrain Button
    if bot.isComplete():
        frame xsize 140 ysize 40 xpos 1630 background Solid("#0099cc") ypos 900:
            text "Auto-Train" xalign 0.5 yalign 0.5 size FSIZE 
            button action Return(["autotrain", k])


    #####################################################################
    #					TOOLTIPS						  
    #####################################################################
    $ tooltip = GetTooltip()
    # bot?
    if tooltip and isinstance(tooltip, Sexbot):
        vbox  pos 1300,990 xalign 0.5 spacing 10:
            bar xsize 300 ysize 2 xalign 0.5
            hbox spacing 10 xalign 0.5:
                hbox:
                    for i in range(tooltip.getStars()):
                        image "03_minigames/star.png" zoom 0.5 yalign 0.5
                text "{} -".format(tooltip.name)xalign 0.5 size FSIZE
                text "Gen {} -".format(tooltip.parts["cortex"].cat)xalign 0.5 size FSIZE
                text "{:,} Cr".format(tooltip.getPrice()) xalign 0.5 size FSIZE
            bar xsize 300 ysize 2 xalign 0.5

 
            
    # part?
    if tooltip and isinstance(tooltip, SexbotPart) :
            vbox  pos 1300,990 xalign 0.5 spacing 10:
                bar xsize 300 ysize 2 xalign 0.5
                if tooltip.getBoostOneLiner("short"):
                    text "{} - {}".format(tooltip.getName(), tooltip.getBoostOneLiner("short")) xalign 0.5 size FSIZE
                else:
                    text "{}".format(tooltip.getName()) xalign 0.5 size FSIZE
                bar xsize 300 ysize 2 xalign 0.5

#####################################################################
#					MAIN LAB MODULE	
#####################################################################

label mg_sexbot_lab():
 
    #scene room_lab_smart with fade
    hide screen header
    play music "audio/ambient_dark.wav" volume 0.2
    show screen mg_sexbot_prep_scr() with dissolve
    $ fromSlot = None # remembers where the displayed Bot is from
    queue sound "audio/beep.wav"
    $ labWork = False
    
    
    python:
            refill = False
            for i in ["bio", "energy", "nano"]:
                if GAME.lab.status[i] < 301 and GAME.items["ITMPod{}".format(i.title())] in GAME.ship.cargo:
                    refill = True
                    for r in range(4):
                        if GAME.lab.status[i] < 301:
                            if GAME.items["ITMPod{}".format(i.title())] in GAME.ship.cargo:
                                GAME.lab.status[i] += 100
                                GAME.ship.cargo.remove(GAME.items["ITMPod{}".format(i.title())])
                            else:
                                pass
                        else:
                            pass

    # Lab Loop
    while True:
        $ bot = GAME.lab.current
        call screen mg_sexbot_scr()
        #queue sound "audio/click.wav"

        #####################################################################
        #					EXIT BOTLAB		
        #####################################################################
        if _return == False:

            if GAME.lab.current.hasComp("cortex"): # CR-0323
                queue sound "audio/beep.wav"
                call simple_notify("LAB STATUS", "Put {} back into storage first.".format(C_HI_B+GAME.lab.current.name+C_HI_E), ["Continue"]) from _call_simple_notify_112 
            else: # CR-0323
                stop music fadeout 1.0 
                hide screen mg_sexbot_prep_scr with fade # CR-0323
                if labWork:
                    call hour_passes() from _call_hour_passes_100 
                scene room_lab_smart
                return() # CR-0323


        elif "rename" in _return:
            $ n = renpy.input("Rename {}".format(GAME.lab.current.name))
            $ n = n.strip() 
            $ n = n[:16]
            $ GAME.lab.current.name = n.title()

        elif "reroll_name" in _return: 
            $ old_name = GAME.lab.current.name 
            queue sound "audio/click.wav"
            while old_name == GAME.lab.current.name:
                $ GAME.lab.current.name = random.choice(GAME.sbData["names"])

        #####################################################################
        #					NEW BOT / CORTEX		
        #####################################################################
        elif "add" in _return and len([x for x in GAME.lab.cells if x])==10:
            queue sound "audio/tech_fail.wav"
            "Lab Manager" "\"No free storage cell to start new bot!\""

        elif "add" in _return and _return[1] == "cortex":
            $ labWork = True
            queue sound "audio/click.wav"
            # get core 
            hide screen mg_sexbot_prep_scr
            call mg_sexbot_part_storage("cortex") from _call_mg_sexbot_part_storage_1 
            if _return:
                $ cortex = _return          
                call activity_bar("Analyzing Core...", "{}{}".format(cortex.getPath(), cortex.getIco())) from _call_activity_bar_3 
                queue sound "audio/success.wav"
                # install part 
                $ bot.parts["cortex"]=cortex 
                # remove part from storage     
                $ GAME.lab.parts.remove(cortex)
                $ globals()["oldbotIQ"] = 0  
                $ bot.rollNew(cortex)
            show screen mg_sexbot_prep_scr()

        elif "add" in _return and _return[1] == "cube":
            $ labWork = True
            queue sound "audio/click.wav"
            # get cube
            hide screen mg_sexbot_prep_scr
            call mg_sexbot_part_storage("cube") from _call_mg_sexbot_part_storage_2 
            if _return:
                $ cube = _return       
                # warning 
                queue sound "audio/notify.wav"
                call large_notify("CUBE ACTIVATION", "Installation of this Precursor Cube will permanently alter cortex properties. The selected cube will be consumed in the process.\n\nDo you want to continue?", ["Continue", "Abort"], "03_minigames/ico {}.png".format(cube.attr["BaseID"])) from _call_large_notify_91 
                if _return == "Continue":
                    play sound "audio/success.wav"
                    $ result = cube.rollCube(bot)
                    if result[0] == "Traits":
                        $ msg = " / ".join([bot.colorize(x.title()) for x in bot.traits])
                        # $ msg = bot.colorize(result[1][0].title())+" / "+ bot.colorize(result[1][1].title())
                    else:
                        $ msg = bot.colorize(result[1].title()) 
                    call simple_notify("NEW {}".format(result[0].upper()), "{}".format(msg),["Continue"], "03_minigames/ico {}.png".format(cube.attr["BaseID"])) from _call_simple_notify_113 
                    # clean up data
                    $GAME.lab.parts.remove(cube)
                    queue sound "audio/tech_success.wav"

            show screen mg_sexbot_prep_scr()


        #####################################################################
        #					PART ADDITION / MODULE ADDITION		
        #####################################################################
        #elif "add" in _return and not bot.hasComp("cortex"):
            #queue sound "audio/beep.wav"
            #call simple_notify("CONFIGURATION", "You need to insert a core first.", ["Continue"]) from _call_simple_notify_114 

        elif "add" in _return:   
            $ labWork = True
            queue sound "audio/click.wav"
            $ partsKey = _return[1]
            # get part
            hide screen mg_sexbot_prep_scr
            call mg_sexbot_part_storage(partsKey) from _call_mg_sexbot_part_storage_3 
            show screen mg_sexbot_prep_scr()
            if _return:
                $ part = _return          
                # install part 
                $ bot.parts[partsKey]=part 
                # remove part from storage 
                $ GAME.lab.parts.remove(part)        
                queue sound "audio/install.wav"

                # bot completion triggers 
                if bot.isComplete(): 
                    # first bot
                    if GAME.questSys.inProgress("QID_BOT_FIRST"):
                        pause 2.0
                        $ GAME.mc.hasDone("first_bot") 
                        call quest_updater() from _call_quest_updater_213 
                    # bot creation log 
                    $ GAME.lab.botsCreated.add(bot.parts["cortex"].ID)
                    if len(GAME.lab.botsCreated) >= 20 and not GAME.mc.hasAchievement("master builder"):
                        call achievement_notify(GAME.mc, "master builder") from _call_achievement_notify_15 
                    

        elif "module" in _return:
            $ labWork = True
            $ iSlot = _return[1]
            $ bot = GAME.lab.current
            # base bot configured?
            if not bot.hasComp("cortex"):
                queue sound "audio/tech_fail.wav"
            # uninstall?    
            elif bot.addOns[iSlot]:
                $ bot.uninstallAddOn(iSlot)
                queue sound "audio/install.wav"

            # select new from storage? 
            else:
                queue sound "audio/click.wav"
                hide screen mg_sexbot_prep_scr
                if iSlot == 5:
                    call mg_sexbot_part_storage("shell") from _call_mg_sexbot_part_storage_4 
                else:
                    call mg_sexbot_part_storage("addon") from _call_mg_sexbot_part_storage_5 
                show screen mg_sexbot_prep_scr() 
                if _return:   
                    $ item = _return
                    if "Shell" in item.attr["BaseID"] and not bot.isComplete():
                        queue sound "audio/tech_fail.wav"
                    elif item.isShell() == "I" and not ( all([x.cat > 1 for x in bot.parts.values()]) and all([x.pref in ["military grade", "elite"] for x in bot.parts.values()])): # CR-0876
                        queue sound "audio/tech_fail.wav"
                        "Lab Manager" "\"Shell requires full Military Grade Bot, Gen2 or above.\"" # CR-0537
  
                    else: 
                        $ bot.installAddOn(i, item)    
                        queue sound "audio/tech_success.wav"
             
        #####################################################################
        #					BOT RETRIEVAL $ STORAGE
        #####################################################################
        elif "bot" in _return:
           
            if GAME.lab.current.hasComp("cortex"): # CR-0323
                queue sound "audio/tech_fail.wav" # CR-0323

            # retrieve bot into empty configurator # CR-0323
            else: # CR-0323
                $ retrieveBot = _return[1] # CR-0323
                $ fromSlot = _return[2] # CR-0323
                $ cellNum = GAME.lab.cells.index(retrieveBot) # CR-0323
                queue sound "audio/load.wav" # CR-0323
                $ GAME.lab.current = retrieveBot # CR-0323
                $ GAME.lab.cells[cellNum] = False # CR-0323               

        #####################################################################
        #					LAB OPERATION		
        #####################################################################

        elif "charge" in _return:
            queue sound "audio/load.wav"
            $ GAME.lab.charge(_return[1])

        elif "gen_up" in _return:
            # mat requirements 
            $ upgradeOK = False
            $ slot = _return[1]
            $ bot = GAME.lab.current
            $ matReq = {
                2: ["ITMPodNano"]*3,
                3: ["ITMPodNano"]*3+ ["ITMCarbonFiberSpools"]
            }
            
            if not slot:
                queue sound "audio/tech_fail.wav"
            $ part = bot.parts[slot]
            $ fromGen = part.cat 
            $ toGen = part.cat+1 
            $ baseID = part.attr.get("BaseID", False)
            
            if toGen > 3 and GAME.mc.attr["TEC"] < 20:
                queue sound "audio/beep.wav"
                bb2 "\"I am not sure there is a way to upgrade Gen 3 components...\""
                
            elif toGen > 3 and GAME.mc.attr["TEC"] < gradeTECReq[part.pref]:
                bb2 "\"Your skill level is currently insufficient to upgrade this Gen 3 component...\""
                
            elif not baseID:
                queue sound "audio/tech_fail.wav"
                
            # CR-2115 START
            elif toGen < 4 and not all(GAME.ship.cargo.count(GAME.items[x]) >= matReq[toGen].count(x) for x in set(matReq[toGen])):
                queue sound "audio/beep.wav"
                bb2 "\"We lack some materials for the upgrade...\""
                bb2 "\"We need 3 Nanite Pods to upgrade to Gen 2.\""
                bb2 "\"Upgrades to Gen 3 additionally require a Carbon Fiber Spool.\""
                
            elif toGen == 4 and not all(GAME.ship.cargo.count(GAME.items[x]) >= matReq[3].count(x) for x in set(matReq[3])):
                queue sound "audio/beep.wav"
                bb2 "\"We lack some materials for the upgrade...\""
                bb2 "\"We will need 3 Nanite Pods and a Carbon Fiber Spool before we can proceed...\""
                
            
            # CR-2115 END
            else:
                $ upgradeOK = True

            $ baseID = baseID[:-1]+"{}".format(toGen)
            if upgradeOK:
              if toGen < 4:
                # create part
                $ newPart = GAME.sbPartsData[baseID].clone({"pref": part.pref}) 
                queue sound "audio/install.wav"
                $ bot.parts[slot] = newPart
                # consume resources 
                python:
                    for i in matReq[toGen]:
                        GAME.ship.unloadWare(i)
                # TEC mc impact
                $ GAME.mc.incAttrFrac("TEC", 0.4,15)
              else:
                $ base2ID = baseID[:-1]+"3"
                $ part_newgrade = part_grade_index[part.pref]
                $ newPart = GAME.sbPartsData[base2ID].clone({"pref": part_newgrade})
                queue sound "audio/install.wav"
                $ bot.parts[slot] = newPart
                python:
                    for i in matReq[3]:
                        GAME.ship.unloadWare(i)
                # TEC mc impact
                $ GAME.mc.incAttrFrac("TEC", 0.4,35)

        elif "repair" in _return:
            $ labWork = True
            $ slot = _return[1] 
            $ repairMatReq = {"cortex": "bio", "torso": "nano", "legs": "nano", "arms": "nano", "head": "nano" }
            $ mat = repairMatReq[slot]
            $ bot = GAME.lab.current

            $rmc = int(bot.parts[slot].wear * 61) + 14
            if mat == "bio":
                $rmc = int(bot.parts[slot].wear * 81) + 19

            $ skillKey = capValue(GAME.mc.attr["TEC"],5,10)
            $ repTo = {5: 0.4, 6: 0.3, 7: 0.2, 8: 0.1, 9: 0.05, 10: 0.0 }

            if GAME.lab.status[mat] < (rmc * (1 - repTo[skillKey])):
                queue sound "audio/tech_fail.wav"
                if GAME.lab.status[mat] > 0:
                    $armpercent = GAME.lab.status[mat] / (rmc * (1 - repTo[skillKey]))
                    $repairspan =  bot.parts[slot].wear - (repTo[skillKey])
                    $repairscompleted = repairspan * armpercent
                    $bot.parts[slot].wear -= repairscompleted
                    #$ bot.parts[slot].wear = repTo[skillKey]  + (1 - ((1 - repTo[skillKey]) * (GAME.lab.status[mat] / (rmc * (1 - repTo[skillKey])))))
                    $GAME.lab.status[mat] = 0
                else:              
                    call simple_notify("CONFIGURATOR", "20% {} required.".format(mat.title()), ["Continue"]) from _call_simple_notify_115 

            elif repTo[skillKey] >= bot.parts[slot].wear:
                queue sound "audio/notify.wav"
                "Your Tech Skills are not sufficient to repair that part further."
                "With some more repair practice that should improve..."
            else:
                queue sound "audio/install.wav"
                $ bot.parts[slot].wear = repTo[skillKey]
                $ GAME.lab.status[mat] -= (rmc * (1 - repTo[skillKey]))
                $ GAME.mc.incAttrFrac("TEC", 0.1,10)

        elif "remove" in _return and GAME.lab.current.getShellConfig() in ["I","J", "V"]:
            queue sound "audio/tech_fail.wav"

        elif "remove" in _return:
            $ labWork = True
            $ slot = _return[1]
            $ bot = GAME.lab.current
            if slot == "cortex":
                queue sound "audio/notify.wav"
                call large_notify("WARNING", "Removal will destroy the current cortex. All parts will be returned to storage. \n\nDo you want to proceed?", ["Proceed", "Abort"], "08_items/ico ITMSpanner.png", "red") from _call_large_notify_92 
                if _return == "Proceed":
                    queue sound "audio/install.wav"
                    # return all parts and modules except core to storage
                    python:
                        for k in bot.parts.keys():
                            if k != "cortex":
                                bot.uninstallPart(k) 
                        for i in range(len(bot.addOns)):
                            if bot.addOns[i]:
                                GAME.lab.parts.append(bot.addOns[i])
                                bot.addOns[i] = False
                    # wipe doll 
                    $ GAME.lab.clearLab()
                    call simple_notify("CONFIGURATION", "Parts disassembled and stored.", ["Continue"]) from _call_simple_notify_116 
                else:
                    pass
            else:
                # remove part and return to storage
                queue sound "audio/install.wav"
                $ bot.uninstallPart(slot)               

        elif "autotrain" in _return:
            queue sound "audio/switch.wav"
            $ GAME.lab.current.autoTrain = not  GAME.lab.current.autoTrain

        elif "train" in _return:
            $ labWork = True
            $ skill = _return[1]
            $ bot = GAME.lab.current
            if not bot.isComplete():
                queue sound "audio/beep.wav"
                call simple_notify("CONFIGURATOR", "Complete configuration first.", ["Continue"]) from _call_simple_notify_117 
            elif GAME.lab.status["energy"] > 0:
                $ sPre = bot.skills[skill]
                queue sound "audio/train_tech.wav"
                $ tMode = "manual"
                if "hyper-train" in GAME.lab.status.keys():
                    if GAME.lab.status["hyper-train"] > 0:
                        $ tMode = "hyper" 
                        $ GAME.lab.status["hyper-train"] = max(0,GAME.lab.status["hyper-train"]-1)
                $ GAME.lab.current.train(skill, tMode)
                $ sPost = bot.skills[skill]
                if bot.skills[skill] >= bot.getTalents()[skill] and sPost >= 90:
                    play sound "audio/success.wav"
            else:
                queue sound "audio/tech_fail.wav"

        #####################################################################
        #					UPGRADE BOT  / HYPERTRAIN
        #####################################################################
        elif "upgrade cortex" in _return:

            $ bot = GAME.lab.current
            $ cortex = bot.parts["cortex"]
            $ botGen = cortex.cat
            $ botPref = cortex.pref
            $ globals()['oldbotIQ'] = bot.IQ

            queue sound "audio/notify.wav"
            
            if GAME.lab.status["bio"] < 100:
                call large_notify("INSUFFICIENT BIO MATERIAL LEVELS", "In addition to an AI-Core, one pod's worth of Bio is also required.", ["Abort"], "08_items/ico ITMAICore.png", "orange") from _call_large_notify_93a
                
            else:
                call large_notify("IMPORTANT UPGRADE NOTE", "Upgrading your bot's cortex will consume one AI-Core and one pod's worth of bio materials. If the cortex' generation is upgradeable, that upgrade is guaranteed. Bot IQ, traits etc. will not be retained and randomly change.\n\nDo you want to continue?", ["Upgrade", "Abort"], "08_items/ico ITMAICore.png", "orange") from _call_large_notify_93 

            if _return == "Upgrade":


                call activity_bar("Upgrading Core...", "{}{}".format(cortex.getPath(), cortex.getIco())) from _call_activity_bar_4 
                # removing shells 
                python:
                    for i in range(len(bot.addOns)):
                        if bot.addOns[i]:
                            if "shell" in bot.addOns[i].ID.lower():
                                bot.uninstallAddOn(i)


                # construct new cortex 
                $ cGen = {1: "SBPCortex1", 2: "SBPCortex2", 3: "SBPCortex3"}[capValue(botGen+1,1,3)]

                if GAME.ship.countCargo("ITMAICoreElite") and botGen == 3:
                    $ cGen = "SBPCortexPre"

                # prepare attributes to be retained 
                $ attr = {}
                if "SBPCortexPre" in cortex.ID and gradeTECReq[botPref] <= GAME.mc.attr["TEC"]:
                    $ attr["pref"] = part_grade_index[bot.parts["cortex"].pref]
                else:
                   $ attr["pref"] = bot.parts["cortex"].pref 
                $ attr["wear"] = bot.parts["cortex"].wear

                # prepare new cortex 
                $ newCortex = GAME.sbPartsData[cGen].clone(attr) # take over prefix
            
                # prepare new bot and transfer parts and addons
                $ attr = {}
                $ attr["name"] = bot.name 
                $ attr["tally"] = bot.tally
                $ newBot = Sexbot()
                $ newBot.rollNew(newCortex, attr)
    
                python:
                    for i in ["head", "arms", "torso", "legs"]:
                        newBot.parts[i] = bot.parts[i]
                    newBot.addOns = bot.addOns
                queue sound "audio/tech_success.wav"

                # Swap out active bot / consume core
                $ GAME.lab.current = newBot
                if cGen == "SBPCortexPre":
                    $ GAME.ship.cargo.remove(GAME.items["ITMAICoreElite"])
                elif GAME.ship.countCargo("ITMAICore") == 0: # Upgrade for gen 1,2 bot pressed but no normal AICores available
                    $ GAME.ship.cargo.remove(GAME.items["ITMAICoreElite"])
                else:
                    $ GAME.ship.cargo.remove(GAME.items["ITMAICore"])
                $ GAME.lab.status["bio"] -= 100
                            
        elif "hyper-train" in _return:
            queue sound "audio/tech_success.wav"
            $ GAME.lab.status["hyper-train"] = 20 
            $ GAME.ship.unloadWare("ITMOrePromethium")
            # $ i =  GAME.lab.extensions.index(GAME.items["ITMOrePromethium"])
            # $ GAME.lab.extensions[i] = False    

        elif "quality control" in _return: 
            hide screen mg_sexbot_prep_scr
            queue sound "audio/beep.wav"
            call mgsb_quality_control() from _call_mgsb_quality_control 
            show screen mg_sexbot_prep_scr

        elif "bot analyzer" in _return:
            hide screen mg_sexbot_prep_scr
            queue sound "audio/beep.wav"
            call mgsb_analyzer() from _call_mgsb_analyzer 

            show screen mg_sexbot_prep_scr                

        elif "lab manager" in _return:
            hide screen mg_sexbot_prep_scr
            call mg_lab_manager() from _call_mg_lab_manager_1 
            show screen mg_sexbot_prep_scr

        elif "process" in _return and _return[1] == "store":
            $ slot = _return[2] 
            if GAME.lab.hasFreeCell(): 
                queue sound "audio/load.wav"
                $ bot = GAME.lab.current          
                $ GAME.lab.storeBot(GAME.lab.current, slot) 
                $ fromSlot = None

                #show image "fullscreen_wip.png" with fade
                if not GAME.mc.hasDone("stored_bot"):
                    hide screen mg_sexbot_prep_scr
                    call large_notify("STORAGE", "You deactivate {0} and move her into the Lab's storage area.\n\nYou can retrieve your bot for configuration and training at any time from within the configurator menu.".format(C_HI_B+bot.name+C_HI_E), ["Continue"]) from _call_large_notify_94 
                    show screen mg_sexbot_prep_scr() with fade

                #####################################################################
                #              QUEST HOOKS
                #####################################################################
                if bot.getIQ() > 140 and bot.isComplete() and not GAME.questSys.isActive("QID_PIRATE_KICKOFF"):
                    queue sound "audio/drone_beep.wav"
                    bb2 "\"Captain [GAME.mc.name], this bot you created might pose a problem.\""
                    mc "\"How so?\"" 
                    bb2 "\"Iltari System Regulations prohibit engaging in trade with too intelligent sex bots.\""
                    mc "\"Too intelligent?\""
                    bb2 "\"Everything above 140 is prohibited.\""
                    mc "\"That's too bad.\""
                    mc "\"They'd fetch a nice premium...\""
                    mc "\"Can I still make them?\""
                    bb2 "\"Production for research purposes is allowed, trade is illegal.\""
                    mc "\"Is there any way around that?\""
                    bb2 "\"I suggest you talk with Nimhe.\""
                    bb2 "\"Her business associates might not look too closely on regulations.\""
                    bb2 "\"On the contrary, one might even say....\""
                    mc "\"I see...\""
                    mc "\"Maybe Nimhe can help selling higher end models.\""
                    mc "\"I'll talk to her.\""
                    $ GAME.mc.hasDone('illegal_bot_warning')
                    call quest_updater() from _call_quest_updater_214 

                if bot.getIQ() >= 150 and bot.isComplete() and bot.getPrice() > 100000 and GAME.questSys.inProgress("QID_PIRATE_PRESENT1"):
                    queue sound "audio/notify.wav"
                    mc "\"Excellent, that was just the bot I need for the Pirates.\""
                    mc "\"I better put [C_HI_B][bot.name][C_HI_E] aside and talk to Nimhe...\"" 
                    queue sound "audio/load.wav"
                    $ GAME.lab.clearBot(bot)  
                    $ GAME.mc.hasDone("bot_present_made")  
                    call quest_updater() from _call_quest_updater_215 

                if GAME.questSys.inProgress("QID_NIMHE_RETRIEVE_CREATE") and all([x.pref == "military grade" for x in bot.parts.values()]) and all([x.cat > 1 for x in bot.parts.values()]) and bot.isComplete(): # CR-0401
                    $ GAME.mc.hasDone("bot_frame_made")
                    # put bot aside
                    $ GAME.lab.hiddenCells.append(bot)
                    $ GAME.lab.clearBot(bot)
                    call quest_updater() from _call_quest_updater_216 

            else:
                queue sound "audio/notify.wav"
                call simple_notify("STORAGE", "No free storage cell.".format(GAME.lab.current.name), ["Continue"]) from _call_simple_notify_118 

        #####################################################################
        #					CHECK MAT AUTO REFILLS		
        #####################################################################
        python:
            refill = False
            for i in ["bio", "energy", "nano"]:
                if GAME.lab.status[i] < 301 and GAME.items["ITMPod{}".format(i.title())] in GAME.ship.cargo:
                    refill = True
                    for r in range(4):
                        if GAME.lab.status[i] < 301:
                            if GAME.items["ITMPod{}".format(i.title())] in GAME.ship.cargo:
                                GAME.lab.status[i] += 100
                                GAME.ship.cargo.remove(GAME.items["ITMPod{}".format(i.title())])
                            else:
                                pass
                        else:
                            pass
        if refill:
            queue sound "audio/load.wav"

    return()