~~ ~~ lockandkey.af - Portal Bot with Stipend & Partial Bella Services ~~ ~~ A portal summoning bot that: ~~ - Listens for tells containing "primary" or "secondary" to summon portals ~~ - Collects stipend on timer (with backoff) ~~ - Runs partial bella (jaw turn-in only, no kill bella) ~~ - Returns home via ah_recall after services ~~ ~~ Portal Spells: ~~ Summon Primary Portal I = spell 157 ~~ Summon Secondary Portal I = spell 2648 ~~ ~~ { ~~ FOR AUTO-COMPLETION ASSISTANCE: testvar getvar setvar touchvar clearallvars clearvar getcharintprop getchardoubleprop getcharquadprop getcharboolprop getcharstringprop getisspellknown getcancastspell_hunt getcancastspell_buff getcharvital_base getcharvital_current getcharvital_buffedmax getcharskill_traininglevel getcharskill_base getcharskill_buffed getplayerlandcell getplayercoordinates coordinategetns coordinategetwe coordinategetz coordinatetostring coordinateparse coordinatedistancewithz coordinatedistanceflat wobjectgetphysicscoordinates wobjectgetname wobjectgetobjectclass wobjectgettemplatetype wobjectgetisdooropen wobjectfindnearestmonster wobjectfindnearestdoor wobjectfindnearestbyobjectclass wobjectfindininventorybytemplatetype wobjectfindininventorybyname wobjectfindininventorybynamerx wobjectgetselection wobjectgetplayer wobjectfindnearestbynameandobjectclass actiontryselect actiontryuseitem actiontryapplyitem actiontrygiveitem actiontryequipanywand actiontrycastbyid actiontrycastbyidontarget chatbox chatboxpaste statushud statushudcolored uigetcontrol uisetlabel isfalse istrue iif randint cstr strlen getobjectinternaltype cstrf stopwatchcreate stopwatchstart stopwatchstop stopwatchelapsedseconds cnumber floor ceiling round abs getworldname getitemcountininventorybyname getheading getitemcountininventorybynamerx getheadingto actiontrygiveprofile vitae getfellowshipstatus getfellowshipname getfellowshipisopen getfellowshipisleader getfellowshipleaderid getfellowshipcanrecruit getfellowid getfellowshipcount getfellowshiplocked getfellowname getfellowshipisfull sin cos tan sqrt asin acos atan atan2 sinh cosh tanh vtsetmetastate getregexmatch echo chr ord wobjectgetid wobjectgethealth wobjectfindbyid wobjectgetintprop wobjectfindnearestbytemplatetype wobjectgetopencontainer testquestflag getquestktprogress isrefreshingquests getquestktrequired getqueststatus getisday getgamehour getgamehourname getisnight getgameday getgameticks getminutesuntilday getgamemonth getplayerlandblock wobjectisvalid getitemcountbytemplatetype ifthen ~~ } STATE: {Default} ~~ Init variables then transition to service check IF: Not Expr {testvar[bellaStartAttempts]} DO: DoExpr {setvar[bellaStartAttempts, 0]} IF: Not Expr {testvar[bellaMpPrimaryAttempts]} DO: DoExpr {setvar[bellaMpPrimaryAttempts, 0]} IF: Not Expr {testvar[bellaTurnInAttempts]} DO: DoExpr {setvar[bellaTurnInAttempts, 0]} IF: Not Expr {testvar[bellaJawRunRecoverAttempts]} DO: DoExpr {setvar[bellaJawRunRecoverAttempts, 0]} IF: Not Expr {testvar[bellaBackoffSeconds]} DO: DoExpr {setvar[bellaBackoffSeconds, 86400]} IF: Not Expr {testvar[stipendBackoffSeconds]} DO: DoExpr {setvar[stipendBackoffSeconds, 86400]} IF: Not Expr {testvar[disableBellaServices]} DO: DoExpr {setvar[disableBellaServices, 0]} IF: Not Expr {testvar[serviceCheckInterval]} DO: DoExpr {setvar[serviceCheckInterval, 43200]} IF: Not Expr {testvar[serviceClock]} DO: DoAll DoExpr {setvar[serviceClock,stopwatchcreate[]]} DoExpr {stopwatchstart[getvar[serviceClock]]} IF: Always DO: DoAll Chat {/ub opt set VTank.PatchExpressionEngine true} Chat {/vt opt set enablecombat false} Chat {/vt opt set enablelooting false} Chat {/vt opt set enablenav false} Chat {/vt opt set enablebuffing true} SetState {service_quest_refresh} ~~ } STATE: {idle} ~~ Main loop: listen for portal tells, check service timer, handle buffs IF: Death DO: SetState {death} IF: NeedToBuff DO: SetState {buffing} ~~ Listen for tells containing "primary" IF: ChatCapture {(^(\[[A-z]+?\] |)You|.*\[^\<]*)\>.+\<\\Tell\>) .*, ".*primary.*"$} {} DO: SetState {summon_primary} ~~ Listen for tells containing "secondary" IF: ChatCapture {(^(\[[A-z]+?\] |)You|.*\[^\<]*)\>.+\<\\Tell\>) .*, ".*secondary.*"$} {} DO: SetState {summon_secondary} ~~ Periodic service check IF: All Expr {testvar[serviceClock]} Expr {stopwatchelapsedseconds[getvar[serviceClock]]>=getvar[serviceCheckInterval]} DO: SetState {service_quest_refresh} IF: Always DO: None STATE: {summon_primary} ~~ Face 180, equip wand, cast Summon Primary Portal I (157) with retries IF: Death DO: SetState {death} IF: Always DO: DoAll Chat {/vt opt set enablecombat false} Chat {/ub face 180} DoExpr {actiontryequipanywand[]} IF: SecsInStateGE 4 DO: DoExpr {actiontrycastbyid[157]} IF: SecsInStateGE 7 DO: DoExpr {actiontrycastbyid[157]} IF: SecsInStateGE 10 DO: DoExpr {actiontrycastbyid[157]} IF: SecsInStateGE 17 DO: SetState {idle} STATE: {summon_secondary} ~~ Face 90, equip wand, cast Summon Secondary Portal I (2648) with retries IF: Death DO: SetState {death} IF: Always DO: DoAll Chat {/vt opt set enablecombat false} Chat {/ub face 90} DoExpr {actiontryequipanywand[]} IF: SecsInStateGE 4 DO: DoExpr {actiontrycastbyid[2648]} IF: SecsInStateGE 7 DO: DoExpr {actiontrycastbyid[2648]} IF: SecsInStateGE 10 DO: DoExpr {actiontrycastbyid[2648]} IF: SecsInStateGE 17 DO: SetState {idle} STATE: {buffing} ~~ Wait for buffs to complete, then return to idle IF: Death DO: SetState {death} IF: Not NeedToBuff DO: SetState {idle} IF: SecsInStateGE 120 DO: SetState {idle} STATE: {service_quest_refresh} ~~ Request quest status refresh, wait for completion IF: Death DO: SetState {death} IF: Always DO: DoAll Chat {/myquests} DoExpr {touchvar[questsRequested]} IF: All Expr {testvar[questsRequested]} Expr {isrefreshingquests[]==0} SecsInStateGE 2 DO: SetState {service_pending_eval} IF: SecsInStateGE 8 DO: SetState {service_pending_eval} STATE: {service_pending_eval} ~~ Check if bella jaw quest is ready (no augment application for portal bot) IF: Always DO: SetState {service_decide} STATE: {service_decide} ~~ Decide which services to run: stipend, partial bella, or return to idle ~~ Reset bella backoff if timer expired IF: All Expr {getvar[disableBellaServices]==1} Expr {testvar[bellaBackoffClock]} Expr {stopwatchelapsedseconds[getvar[bellaBackoffClock]]>=getvar[bellaBackoffSeconds]} DO: DoAll DoExpr {setvar[disableBellaServices, 0]} DoExpr {setvar[bellaStartAttempts, 0]} DoExpr {setvar[bellaMpPrimaryAttempts, 0]} DoExpr {setvar[bellaTurnInAttempts, 0]} DoExpr {setvar[bellaJawRunRecoverAttempts, 0]} DoExpr {clearvar[bellaBackoffClock]} ~~ Stipend: first run (no backoff clock) IF: All Expr {getqueststatus[`stipendtimer_0812`]==1} Not Expr {testvar[stipendBackoffClock]} DO: SetState {service_stipend} ~~ Stipend: backoff expired IF: All Expr {getqueststatus[`stipendtimer_0812`]==1} Expr {testvar[stipendBackoffClock]} Expr {stopwatchelapsedseconds[getvar[stipendBackoffClock]]>=getvar[stipendBackoffSeconds]} DO: DoAll DoExpr {clearvar[stipendBackoffClock]} SetState {service_stipend} ~~ Partial bella: jaw quest ready + services not disabled IF: All Expr {getvar[disableBellaServices]!=1} Expr {getqueststatus[`insatiableeaterjaw`]==1} DO: SetState {service_bella_start} ~~ Nothing to do, return to idle IF: Always DO: DoAll DoExpr {setvar[serviceClock,stopwatchcreate[]]} DoExpr {stopwatchstart[getvar[serviceClock]]} SetState {idle} STATE: {service_stipend} ~~ Run stipend collection nav, start backoff clock IF: Death DO: SetState {death} IF: Always DO: SetWatchdog 3 600 {service_reset_main} IF: Always DO: DoAll Chat {/vt opt set enablecombat false} Chat {/vt opt set enablelooting false} Chat {/vt opt set enablenav true} DoExpr {setvar[stipendBackoffClock, stopwatchcreate[]]} DoExpr {stopwatchstart[getvar[stipendBackoffClock]]} DoExpr {touchvar[stipendNavLoaded]} EmbedNav nav0__stipend_nav {stipend.nav} IF: All Expr {testvar[stipendNavLoaded]} NavEmpty SecsInStateGE 2 DO: SetState {service_reset_main} STATE: {service_bella_start} ~~ Enter marketplace for bella jaw run IF: Death DO: SetState {death} IF: Always DO: DoExpr {setvar[bellaStartAttempts,getvar[bellaStartAttempts]+1]} IF: Expr {getvar[bellaStartAttempts]>=3} DO: SetState {service_bella_backoff} IF: Always DO: DoAll Chat {/vt opt set enablecombat false} Chat {/vt opt set enablelooting false} Chat {/vt opt set enablenav false} Chat {/vt opt set enablebuffing true} IF: SecsInStateGE 2 DO: DoAll Chat {/a [bella] starting marketplace entry} Chat {/vt opt set enablenav false} Chat {/mp} IF: ExitPortal DO: DoAll DoExpr {setvar[bellaStartAttempts, 0]} SetState {service_bella_mp_primary} IF: SecsInStateGE 120 DO: SetState {service_bella_start} STATE: {service_bella_mp_primary} ~~ Navigate through marketplace primary path to jaw dungeon portal IF: Death DO: SetState {death} IF: Always DO: DoExpr {setvar[bellaMpPrimaryAttempts,getvar[bellaMpPrimaryAttempts]+1]} IF: Expr {getvar[bellaMpPrimaryAttempts]>=3} DO: SetState {service_bella_backoff} IF: Always DO: DoAll Chat {/vt opt set enablebuffing true} Chat {/vt opt set enablenav true} Chat {/vt opt set enablecombat false} Chat {/vt opt set enablelooting false} Chat {/vt opt set NavPriorityBoost false} Chat {/vt opt set navclosestoprange 0.008} IF: Expr {getplayerlandblock[]==23855104} DO: Chat {/vt nav load mp_primary} IF: All Expr {getplayerlandblock[]!=23855104} SecsInStateGE 30 DO: DoAll Chat {/a [bella] wrong mp_primary landblock, restarting marketplace entry} SetState {service_bella_start} IF: ExitPortal DO: DoAll Chat {/vt opt set enablenav false} DoExpr {setvar[bellaMpPrimaryAttempts, 0]} SetState {service_bella_jaw_run} IF: SecsInStateGE 60 DO: DoAll Chat {/a [bella] mp_primary timed out, restarting marketplace entry} SetState {service_bella_start} STATE: {service_bella_jaw_run} ~~ Run jaw dungeon nav IF: Death DO: SetState {death} IF: Expr {getplayerlandblock[]==9830400} DO: DoAll Chat {/vt opt set enablenav true} Chat {/vt nav load jaw_1} IF: All Expr {getplayerlandblock[]!=9830400} SecsInStateGE 30 DO: DoAll Chat {/a [bella] wrong jaw_run landblock, restarting marketplace entry} SetState {service_bella_start} IF: All Expr {getplayerlandblock[]==9830400} SecsInStateGE 30 NavEmpty DO: DoAll DoExpr {setvar[bellaStartAttempts, 0]} DoExpr {setvar[bellaJawRunRecoverAttempts, 0]} Chat {/vt nav load jaw_1_hunt} Chat {/vt opt set enablecombat true} Chat {/vt opt set enablelooting true} Chat {/vt opt set lootonlyrarecorpses false} SetState {service_bella_jaw_hunt} IF: All SecsInStateGE 300 Expr {getvar[bellaJawRunRecoverAttempts]<3} DO: DoAll DoExpr {chatbox[`/a [bella] jaw_run stuck, recall retry `+cstr[getvar[bellaJawRunRecoverAttempts]+1]+`/3`]} DoExpr {setvar[bellaJawRunRecoverAttempts,getvar[bellaJawRunRecoverAttempts]+1]} Chat {/vt nav load nav_portal_recall} SetState {service_bella_jaw_run_recover} IF: All SecsInStateGE 300 Expr {getvar[bellaJawRunRecoverAttempts]>=3} DO: SetState {service_bella_backoff} STATE: {service_bella_jaw_run_recover} ~~ Recovery wait for jaw run stuck IF: Death DO: SetState {death} IF: SecsInStateGE 20 DO: SetState {service_bella_jaw_run} STATE: {service_bella_jaw_hunt} ~~ Hunt for jaw drop IF: Death DO: SetState {death} IF: ExitPortal DO: DoAll Chat {/vt opt set enablenav true} SetState {service_bella_turn_in_jaw} IF: ItemCountGE 1 {Insatiable Eater Jaw} DO: DoAll Chat {/vt opt set enablecombat false} Chat {/vt nav load to_fiun} IF: SecsInStateGE 1200 DO: SetState {service_bella_start} STATE: {service_bella_turn_in_jaw} ~~ Turn in jaw to Fiun NPC, then return home (partial bella - no mp_trans/secondary/kill) IF: Death DO: SetState {death} ~~ Jaw accepted: return home instead of continuing to mp_secondary IF: ChatMatch {^.*One who obtains such as this is truly worthy of that which we would teach\. The highest peak of the deadliest isle contains that which you seek.*$} DO: DoAll Chat {/a [bella] jaw turned in, returning home (partial bella)} DoExpr {setvar[bellaTurnInAttempts, 0]} SetState {service_reset_main} IF: All SecsInStateGE 300 ItemCountGE 1 {Insatiable Eater Jaw} Expr {getvar[bellaTurnInAttempts]<3} DO: DoAll DoExpr {chatbox[`/a [bella] jaw turn-in timed out, retry `+cstr[getvar[bellaTurnInAttempts]+1]+`/3`]} DoExpr {setvar[bellaTurnInAttempts,getvar[bellaTurnInAttempts]+1]} Chat {/vt nav load to_fiun} SetState {service_bella_turn_in_jaw} IF: All SecsInStateGE 300 ItemCountGE 1 {Insatiable Eater Jaw} Expr {getvar[bellaTurnInAttempts]>=3} DO: SetState {service_bella_backoff} ~~ Jaw already gone (consumed by NPC), just go home IF: SecsInStateGE 300 DO: DoAll DoExpr {setvar[bellaTurnInAttempts, 0]} SetState {service_reset_main} STATE: {service_bella_backoff} ~~ Disable bella services for 24h, return home IF: Always DO: DoAll Chat {/a [bella] backoff tripped, disabling bella services for 24h} Chat {/vt opt set enablecombat false} Chat {/vt opt set enablenav true} DoExpr {setvar[disableBellaServices, 1]} DoExpr {setvar[bellaStartAttempts, 0]} DoExpr {setvar[bellaMpPrimaryAttempts, 0]} DoExpr {setvar[bellaTurnInAttempts, 0]} DoExpr {setvar[bellaJawRunRecoverAttempts, 0]} DoExpr {setvar[bellaBackoffClock,stopwatchcreate[]]} DoExpr {stopwatchstart[getvar[bellaBackoffClock]]} SetState {service_reset_main} STATE: {service_reset_main} ~~ Clear service vars, load ah_recall to return home, then go to idle IF: Death DO: SetState {death} IF: Always DO: SetWatchdog 3 600 {service_reset_main_stuck} IF: Always DO: DoAll DoExpr {clearvar[questsRequested]} DoExpr {clearvar[stipendNavLoaded]} Chat {/vt opt set enablecombat false} Chat {/vt opt set enablelooting false} Chat {/vt opt set enablenav true} Chat {/vt opt set enablebuffing true} DoExpr {setvar[serviceClock,stopwatchcreate[]]} DoExpr {stopwatchstart[getvar[serviceClock]]} DoExpr {touchvar[resetNavLoaded]} Chat {/vt nav load ah_recall} IF: All Expr {testvar[resetNavLoaded]} NavEmpty SecsInStateGE 2 DO: DoAll DoExpr {clearvar[resetNavLoaded]} ClearWatchdog Chat {/vt opt set enablenav false} SetState {idle} STATE: {service_reset_main_stuck} ~~ Fallback if ah_recall nav gets stuck IF: Always DO: DoAll Chat {/ah} SetState {service_reset_main_wait} STATE: {service_reset_main_wait} ~~ Wait for /ah recall, then retry reset IF: Death DO: SetState {death} IF: ExitPortal DO: SetState {service_reset_main} IF: SecsInStateGE 30 DO: SetState {service_reset_main} STATE: {death} ~~ Death recovery: wait for portal exit, recall home IF: Always DO: DoAll Chat {/vt opt set enablecombat false} Chat {/vt opt set enablelooting false} IF: ExitPortal DO: DoAll Chat {/ah} SetState {death_wait_recall} IF: SecsInStateGE 30 DO: DoAll Chat {/ah} SetState {death_wait_recall} STATE: {death_wait_recall} ~~ Wait for /ah recall portal exit, then return to idle IF: Death DO: SetState {death} IF: ExitPortal DO: SetState {idle} IF: SecsInStateGE 60 DO: SetState {idle} ~~========================= ONLY NAVS APPEAR BELOW THIS LINE =========================~~ NAV: nav0__stipend_nav once pau 47.1262349446615 26.1864453474681 0.225020837783813 2000 cht -101.597905190786 -96.6216093699137 2.08333134651184E-05 {/ah} pau 47.1262349446615 26.1864453474681 0.225020837783813 15000 pnt 59.3590666453044 -28.7057823816935 0.0500208298365275 ptl -101.597905190786 -96.6216093699137 2.08333134651184E-05 59.3936458587647 -28.7256083488464 0.0508250035345554 14 {Portal to Town Network} pnt -101.615851815542 -96.6388638178507 2.08333134651184E-05 pnt -101.657751337687 -96.5832635879517 2.08333134651184E-05 pnt -101.658352184296 -96.5325949986776 2.08333134651184E-05 ptl -101.597905190786 -96.6216093699137 2.08333134651184E-05 -101.588099161784 -96.5166525046031 -0.000262499845121056 14 {Portal to Arwic} pnt 56.6498762130737 33.416518386205 0.175020837783813 pnt 56.655900033315 33.5368880271912 0.175020837783813 pnt 56.7470087051392 33.5495386441549 0.175020837783813 pnt 56.7795230229696 33.6337207794189 0.175020837783813 tlk -101.597905190786 -96.6216093699137 2.08333134651184E-05 56.7816291809082 33.6455291748047 0.175020843744278 37 {Monroe}