commit 3c214ca0065a8dfdfda65ebf54c81cf581606c78 Author: Justin Visser Date: Tue Mar 18 13:15:16 2025 +0100 Initial revision degrime script diff --git a/degrime.simba b/degrime.simba new file mode 100644 index 0000000..92a4382 --- /dev/null +++ b/degrime.simba @@ -0,0 +1,668 @@ +{$DEFINE SCRIPT_ID := 'degrime-002'} +{$DEFINE SCRIPT_REVISION := '1'} +{$IFDEF WINDOWS}{$DEFINE SCRIPT_GUI}{$ENDIF} +{$I SRL-T/osr.simba} +{$I WaspLib/osr.simba} + +{------------------------------------------------------------------------- + Constants for timing and wait values used throughout the script. +-------------------------------------------------------------------------} +const + // General wait constants + cInterfaceCloseDelay = 300; // Delay after closing interfaces + cWaitUntilDelay = 65; // Poll delay for WaitUntil calls + cRandomAdjustment = 1000; // Maximum random adjustment + + // Magic interface retry and castable wait times + cMagicInterfaceRetryDelay = 500; // Delay to retry opening magic interface + cCastableWaitMin = 400; // Minimum wait time for checking castability + cCastableWaitExpected = 500; // Expected wait time for checking castability + cCastableWaitMax = 600; // Maximum wait time for checking castability + cSkewParam = 3; // Skew parameter for all srl.SkewedRand calls + + // Wait times in the cast animation (WaitCast procedure) + cUnfocusedWaitMin = 5000; // Minimum wait time when unfocused + cUnfocusedWaitExpected = 7000; // Expected wait time when unfocused + cUnfocusedWaitMax = 15000; // Maximum wait time when unfocused + cFocusedWaitMin = 2400; // Minimum wait time when focused + cFocusedWaitExpected = 2600; // Expected wait time when focused + cFocusedWaitMax = 2700; // Maximum wait time when focused + + // Wait times for bank deposit and withdrawal actions + cDepositWaitMin = 450; // Minimum wait time for deposit + cDepositWaitExpected = 550; // Expected wait time for deposit + cDepositWaitMax = 650; // Maximum wait time for deposit + cWithdrawWaitMin = 300; // Minimum wait time for withdrawal + cWithdrawWaitExpected = 400; // Expected wait time for withdrawal + cWithdrawWaitMax = 550; // Maximum wait time for withdrawal + cBankOpenWaitMin = 300; // Minimum wait time for bank open + cBankOpenWaitExpected = 400; // Expected wait time for bank open + cBankOpenWaitMax = 550; // Maximum wait time for bank open + cPostBankCloseDelay = 500; // Delay after closing bank + + // Delay for main loop iterations in Run procedure + cLoopDelayMin = 300; // Minimum loop delay + cLoopDelayExpected = 400; // Expected loop delay + cLoopDelayMax = 500; // Maximum loop delay + + // Focus duration constants (for focus-loss simulation) + cFocusSkewMin = 2; // Minimum skew for focus duration calculation + cFocusSkewMax = 4; // Maximum skew for focus duration calculation + cFocusSwitchChance = 1; // Early switch chance threshold (in 0..cFocusRandomRange scale) + cFocusRandomRange = 1000; // Random range used for early focus switch check + cFocusedDurationExpected = 15 * 60 * 1000; // Expected focused duration (15 minutes in ms) + cFocusedDurationMin = 0; // Minimum focused duration for srl.SkewedRand call + cFocusedDurationMax = 20 * 60 * 1000; // Maximum focused duration (20 minutes in ms) + cUnfocusedDurationExpected = 4 * 60 * 1000; // Expected unfocused duration (4 minutes in ms) + cUnfocusedDurationMin = 0; // Minimum unfocused duration for srl.SkewedRand call + cUnfocusedDurationMax = 8 * 60 * 1000; // Maximum unfocused duration (8 minutes in ms) + + // Time conversion constant + cMsPerHour = 3600000; // Milliseconds per hour + +{------------------------------------------------------------------------- + End of constants +-------------------------------------------------------------------------} + +{------------------------------------------------------------------------- + Shared Helper Functions +-------------------------------------------------------------------------} + +{ Returns a wait time using the skewed random function with given expected, min, and max values. } +function GetWaitTime(expected, minVal, maxVal: Integer): Integer; +begin + Result := srl.SkewedRand(expected, minVal, maxVal, cSkewParam); +end; + +{ Waits until the bank is open. + If the bank is not open, it walks to the bank and waits until open. } +procedure WaitForBankOpen(); +begin + if not Bank.IsOpen() then + begin + Bank.WalkOpen(); + WaitUntil(Bank.IsOpen(), cWaitUntilDelay, GetWaitTime(cBankOpenWaitExpected, cBankOpenWaitMin, cBankOpenWaitMax)); + end; +end; + +{ Deposits a bank item and waits until the specified item is no longer in the inventory. } +procedure DepositItemWithWait(bankItem: TRSBankItem; itemName: string); +begin + Bank.DepositItem(bankItem, True); + WaitUntil(not Inventory.ContainsItem(itemName), cWaitUntilDelay, + GetWaitTime(cDepositWaitExpected, cDepositWaitMin, cDepositWaitMax)); +end; + +{ Withdraws a bank item and waits until the specified item is present in the inventory. } +procedure WithdrawItemWithWait(bankItem: TRSBankItem; itemName: string); +begin + Bank.WithdrawItem(bankItem, True); + WaitUntil(Inventory.ContainsItem(itemName), cWaitUntilDelay, + GetWaitTime(cWithdrawWaitExpected, cWithdrawWaitMin, cWithdrawWaitMax)); +end; + +{ Checks if the required runes (or rune pouches) are available.} +function HasRequiredRunes(): Boolean; +begin + Result := ((Inventory.CountItem('Earth rune') >= 4) and (Inventory.CountItem('Nature rune') >= 2)) + or Inventory.ContainsItem('Rune pouch') + or Inventory.ContainsItem('Divine rune pouch'); +end; + +{------------------------------------------------------------------------- + End of shared helpers +-------------------------------------------------------------------------} + +type + // State machine reflecting in-game flow. + TDegrimeState = ( + DS_INVENTORY_CHECK, + DS_CHECK_CASTABLE, + DS_CAST_WAIT, + DS_BANK, + DS_TERMINATE + ); + + // Enumeration for the herbs. + THerbs = ( + herbHuasca, + herbTarromin, + herbHarralander, + herbMarrentill, + herbGuamLeaf, + herbIritLeaf, + herbAvantoe, + herbDwarfWeed, + herbLantadyme, + herbToadflax, + herbCadantine, + herbKwuarm, + herbTorstol, + herbRanarrWeed, + herbSnapdragon + ); + +const + // Mapping from enum to the full "Grimy ..." herb name. + HerbNames: array[THerbs] of string = [ + 'Grimy Huasca', + 'Grimy Tarromin', + 'Grimy Harralander', + 'Grimy Marrentill', + 'Grimy Guam Leaf', + 'Grimy Irit Leaf', + 'Grimy Avantoe', + 'Grimy Dwarf Weed', + 'Grimy Lantadyme', + 'Grimy Toadflax', + 'Grimy Cadantine', + 'Grimy Kwuarm', + 'Grimy Torstol', + 'Grimy Ranarr Weed', + 'Grimy Snapdragon' + ]; + + // Mapping from enum to the clean herb name. + CleanHerbNames: array[THerbs] of string = [ + 'Huasca', + 'Tarromin', + 'Harralander', + 'Marrentill', + 'Guam Leaf', + 'Irit Leaf', + 'Avantoe', + 'Dwarf Weed', + 'Lantadyme', + 'Toadflax', + 'Cadantine', + 'Kwuarm', + 'Torstol', + 'Ranarr Weed', + 'Snapdragon' + ]; + +var + GlobalCurrentHerb: THerbs = herbIritLeaf; + SimulateFocusLoss: Boolean = False; // Global flag to enable focus-loss simulation + +type + // Type for focus state. + TFocusState = (fsFocused, fsUnfocused); + + // Main script record – inherits from TBaseBankScript. + TDegrimeScript = record(TBaseBankScript) + State: TDegrimeState; + CastCount: UInt32; + CastRetries: Integer; + CurrentHerb: THerbs; + CleanHerbBank: TRSBankItem; + GrimyHerbBank: TRSBankItem; + StartXP: Integer; + FocusState: TFocusState; + FocusTimer: Int64; + end; + +{------------------------------------------------------------------------- + Setup: Configure antiban settings. +-------------------------------------------------------------------------} +procedure TAntiban.Setup(); override; +begin + Antiban.Skills := [ERSSkill.TOTAL, ERSSKILL.MAGIC]; + Antiban.MinZoom := 63; + Antiban.MaxZoom := 83; + inherited; +end; + +{------------------------------------------------------------------------- + Helper Methods for Script Flow +-------------------------------------------------------------------------} + +{ DS_INIT: Initialization – close interfaces, set bank region, and initialize focus timer. } +procedure TDegrimeScript.Init(maxActions: UInt32; maxTime: UInt64); override; +begin + inherited; + RSInterface.Close(); + Wait(cInterfaceCloseDelay); + Self.RSW.SetupNamedRegion(); + + // Initialize herb selection and bank items. + Self.CurrentHerb := GlobalCurrentHerb; + Self.CleanHerbBank := TRSBankItem.Setup(CleanHerbNames[Self.CurrentHerb], Bank.QUANTITY_ALL, True); + Self.GrimyHerbBank := TRSBankItem.Setup(HerbNames[Self.CurrentHerb], Bank.QUANTITY_ALL, False); + Self.CastCount := 0; + Self.CastRetries := 0; + + // Initialize XP reporting and focus simulation if enabled. + Self.StartXP := XPBar.Read(); + if SimulateFocusLoss then + begin + Self.FocusState := fsFocused; + Self.FocusTimer := GetTimeRunning() + + GetWaitTime(cFocusedDurationExpected, cFocusedDurationMin, cFocusedDurationMax) + + Random(-cRandomAdjustment, cRandomAdjustment); + end + else + begin + Self.FocusState := fsFocused; + Self.FocusTimer := 0; + end; + Self.State := DS_INVENTORY_CHECK; +end; + +{ DS_INVENTORY_CHECK: Verify that the inventory contains the grimy herb and required runes. } +procedure TDegrimeScript.InventoryCheck(); +begin + Self.SetAction('Checking inventory for ' + HerbNames[Self.CurrentHerb] + ' and required runes.'); + if Inventory.Count() = 0 then + begin + Self.SetAction('Inventory is empty. Terminating.'); + Self.State := DS_TERMINATE; + Exit; + end; + if not Inventory.ContainsItem(HerbNames[Self.CurrentHerb]) then + begin + Self.SetAction('No grimy herb in inventory. Switching to bank.'); + Self.State := DS_BANK; + Exit; + end; + if not HasRequiredRunes() then + begin + Self.SetAction('Missing required runes/pouch in inventory. Switching to bank.'); + Self.State := DS_BANK; + end + else + Self.State := DS_CHECK_CASTABLE; +end; + +{ DS_CHECK_CASTABLE: Open magic interface and verify the Degrime spell is castable. } +procedure TDegrimeScript.CheckCastable(); +var + waitTime: Integer; +begin + if not Magic.Open() then + begin + Self.SetAction('Magic interface failed to open. Retrying...'); + Wait(cMagicInterfaceRetryDelay); + if not Magic.Open() then + begin + Self.SetAction('Unable to open magic interface. Terminating.'); + Self.State := DS_TERMINATE; + Exit; + end; + end; + waitTime := GetWaitTime(cCastableWaitExpected, cCastableWaitMin, cCastableWaitMax); + Wait(waitTime); + if Magic.CanActivate(ERSSpell.Degrime) then + begin + Self.SetAction('Spell is castable.'); + Self.State := DS_CAST_WAIT; + end + else + begin + Self.SetAction('Spell unavailable. Terminating.'); + Self.State := DS_TERMINATE; + end; +end; + +{ DS_CAST_WAIT: Attempts to cast the spell and waits the appropriate amount of time to take the next action} +procedure TDegrimeScript.CastAndWait(); +var + waitTime: Integer; +begin + Self.CheckCastable(); + if Self.State = DS_TERMINATE then Exit; + if Magic.CanActivate(ERSSpell.Degrime) then + begin + Self.SetAction('Casting Degrime spell.'); + Inc(Self.CastCount); + Magic.CastSpell(ERSSpell.Degrime); + end + else + begin + Self.State := DS_TERMINATE; + Exit; + end; + + if SimulateFocusLoss then + Self.SwitchFocusState(); + + if SimulateFocusLoss and (Self.FocusState = fsUnfocused) then + begin + waitTime := GetWaitTime(cUnfocusedWaitExpected, cUnfocusedWaitMin, cUnfocusedWaitMax) + + Random(-cRandomAdjustment, cRandomAdjustment); + Self.SetAction('Unfocused: waiting for cast animation (' + ToStr(waitTime) + ' ms).'); + end + else + begin + waitTime := GetWaitTime(cFocusedWaitExpected, cFocusedWaitMin, cFocusedWaitMax); + Self.SetAction('Waiting for cast animation (' + ToStr(waitTime) + ' ms).'); + end; + Bank.Hover(); + Wait(waitTime); + Self.Report(); + Self.State := DS_BANK; +end; + +{ Deposits clean herbs using the shared helper function. } +procedure TDegrimeScript.DepositCleanHerbs(); +begin + Self.SetAction('Depositing clean herbs.'); + DepositItemWithWait(Self.CleanHerbBank, CleanHerbNames[Self.CurrentHerb]); +end; + +{ Withdraws grimy herbs using the shared helper function. } +procedure TDegrimeScript.WithdrawGrimyHerbs(); +begin + if Inventory.ContainsItem(CleanHerbNames[Self.CurrentHerb]) then + begin + Self.SetAction('Deposit might have failed, retry'); + DepositCleanHerbs(); + end; + if Bank.ContainsItem(HerbNames[Self.CurrentHerb]) then + begin + Self.SetAction('Withdrawing grimy herbs.'); + WithdrawItemWithWait(Self.GrimyHerbBank, HerbNames[Self.CurrentHerb]); + end + else + begin + if (not Inventory.ContainsItem(CleanHerbNames[Self.CurrentHerb])) then + begin + Self.SetAction('No grimy herbs left in bank. Terminating.'); + Self.State := DS_TERMINATE; + end + else + begin + Self.SetAction('Deposit might have failed, retry'); + DepositCleanHerbs(); + end + end; +end; + +{ DS_BANK: Handle bank interactions (deposit/withdraw). } +procedure TDegrimeScript.BankInteraction(); +var + runesOk: Boolean; +begin + Self.SetAction('Performing bank interaction.'); + WaitForBankOpen(); + + runesOk := ((Inventory.CountItem('Earth rune') >= 4) and (Inventory.CountItem('Nature rune') >= 2)) + or Inventory.ContainsItem('Rune pouch') + or Inventory.ContainsItem('Divine rune pouch'); + + { Case 1: Inventory contains grimy herbs. } + if Inventory.ContainsItem(HerbNames[Self.CurrentHerb]) then + begin + if runesOk then + begin + Self.SetAction('Grimy herb present with required runes. Closing bank.'); + Bank.Close(); + Wait(cPostBankCloseDelay); + Self.State := DS_CHECK_CASTABLE; + end + else + begin + Self.SetAction('Grimy herb present but missing required runes. Terminating.'); + Self.State := DS_TERMINATE; + end; + Exit; + end + { Case 2: Inventory contains clean herbs. } + else if Inventory.ContainsItem(CleanHerbNames[Self.CurrentHerb]) then + begin + DepositCleanHerbs(); + WithdrawGrimyHerbs(); + if Self.State <> DS_TERMINATE then + Self.State := DS_CHECK_CASTABLE; + Exit; + end + { Case 3: Inventory is empty. } + else if Inventory.Count() = 0 then + begin + Self.SetAction('Inventory is empty. Terminating.'); + Self.State := DS_TERMINATE; + Exit; + end + { Case 4: Fallback unexpected state. } + else + begin + if runesOk and Bank.ContainsItem(HerbNames[Self.CurrentHerb]) then + begin + WithdrawGrimyHerbs(); + if Self.State <> DS_TERMINATE then + Self.State := DS_CHECK_CASTABLE; + end + else + begin + Self.SetAction('Missing required runes/pouch or herbs. Terminating.'); + Self.State := DS_TERMINATE; + end; + end; +end; + +{------------------------------------------------------------------------- + Focus-State Functionality +-------------------------------------------------------------------------} + +{ SwitchFocusState: + Determines when to switch between focused and unfocused modes using + predefined durations and a chance for an early switch. + (inspired by BigAussie AIO Lunar Spells) +} +procedure TDegrimeScript.SwitchFocusState(); +var + skewness: Integer; + focusedDuration, unfocusedDuration: Integer; +begin + skewness := Random(cFocusSkewMin, cFocusSkewMax); + focusedDuration := GetWaitTime(cFocusedDurationExpected, cFocusedDurationMin, cFocusedDurationMax) + + Random(-cRandomAdjustment, cRandomAdjustment); + unfocusedDuration := GetWaitTime(cUnfocusedDurationExpected, cUnfocusedDurationMin, cUnfocusedDurationMax) + + Random(-cRandomAdjustment, cRandomAdjustment); + if GetTimeRunning() >= Self.FocusTimer then + begin + if Self.FocusState = fsFocused then + begin + Self.FocusState := fsUnfocused; + Self.SetAction('Switched to Unfocused mode for ' + ToStr(unfocusedDuration) + ' ms.'); + Self.FocusTimer := GetTimeRunning() + unfocusedDuration; + end + else + begin + Self.FocusState := fsFocused; + Self.SetAction('Switched to Focused mode for ' + ToStr(focusedDuration) + ' ms.'); + Self.FocusTimer := GetTimeRunning() + focusedDuration; + end; + end + else + begin + if Random(cFocusRandomRange) < cFocusSwitchChance then + begin + if Self.FocusState = fsFocused then + begin + Self.FocusState := fsUnfocused; + Self.SetAction('Early switch to Unfocused mode.'); + Self.FocusTimer := GetTimeRunning() + unfocusedDuration; + end + else + begin + Self.FocusState := fsFocused; + Self.SetAction('Early switch to Focused mode.'); + Self.FocusTimer := GetTimeRunning() + focusedDuration; + end; + end; + end; +end; + +{------------------------------------------------------------------------- + Reporting Functionality +-------------------------------------------------------------------------} + +{ Report: Logs total casts, runtime, and XP splits for magic and herblore. +} +procedure TDegrimeScript.Report(); +const + ReportWidth = 60; +var + currentXP, totalGainedXP, magicExp, herbloreExp: Integer; + castsPerHour, magicExpPerHour, herbloreExpPerHour: Integer; + runtimeStr, focusStateStr, header, titleLine: string; + timeInHours, leftPadding: Double; +begin + currentXP := XPBar.Read(); + totalGainedXP := currentXP - Self.StartXP; + magicExp := 83 * Self.CastCount; + herbloreExp := totalGainedXP - magicExp; + timeInHours := GetTimeRunning() / cMsPerHour; + + castsPerHour := Round(Self.CastCount / timeInHours); + magicExpPerHour := Round(magicExp / timeInHours); + herbloreExpPerHour := Round(herbloreExp / timeInHours); + runtimeStr := SRL.MsToTime(GetTimeRunning, Time_Short); + + if Self.FocusState = fsFocused then + focusStateStr := 'Focused' + else + focusStateStr := 'Unfocused'; + + header := StringOfChar('=', ReportWidth); + titleLine := 'Degrime Cast Report'; + leftPadding := (ReportWidth - Length(titleLine)) / 2; + + WriteLn(header); + WriteLn(StringOfChar(' ', Trunc(leftPadding)) + titleLine); + WriteLn(header); + WriteLn(Format('%-16s %10s %-18s %10s', ['Casts:', ToStr(Self.CastCount), 'Casts/Hour:', ToStr(castsPerHour)])); + WriteLn(Format('%-16s %10s %-18s %10s', ['Magic Exp:', ToStr(magicExp), 'Magic Exp/Hour:', ToStr(magicExpPerHour)])); + WriteLn(Format('%-16s %10s %-18s %10s', ['Herblore Exp:', ToStr(herbloreExp), 'Herblore Exp/Hour:', ToStr(herbloreExpPerHour)])); + WriteLn(Format('%-16s %10s %-18s %10s', ['Runtime:', runtimeStr, 'Focus State:', focusStateStr])); + WriteLn(header); +end; + +{Override the standard PrintReport as I won't be using it} +procedure TDegrimeScript.PrintReport(); override; +begin + Self.PreviousAction := Self.Action; +end; + +{------------------------------------------------------------------------- + Main Run Loop +-------------------------------------------------------------------------} + +procedure TDegrimeScript.Run(maxActions: UInt32; maxTime: UInt64); +var + loopDelay: Integer; +begin + Self.Init(maxActions, maxTime); + while not Self.ShouldStop() do + begin + case Self.State of + DS_INVENTORY_CHECK: Self.InventoryCheck(); + DS_CHECK_CASTABLE: Self.CheckCastable(); + DS_CAST_WAIT: Self.CastAndWait(); + DS_BANK: Self.BankInteraction(); + DS_TERMINATE: Break; + end; + Self.DoAntiban(); + loopDelay := GetWaitTime(cLoopDelayExpected, cLoopDelayMin, cLoopDelayMax); + Wait(loopDelay); + end; + Self.SetAction('Script terminated. Total casts: ' + ToStr(Self.CastCount)); +end; + +{$IFDEF SCRIPT_GUI} +type + TDegrimeConfig = record(TScriptForm) + HerbSelector: TLabeledCombobox; + BankCheckbox: TLabeledCheckbox; + FocusLossCheckbox: TLabeledCheckbox; + end; + +procedure TDegrimeConfig.StartScript(sender: TObject); override; +begin + case Self.HerbSelector.GetItemIndex() of + 0: GlobalCurrentHerb := herbHuasca; + 1: GlobalCurrentHerb := herbTarromin; + 2: GlobalCurrentHerb := herbHarralander; + 3: GlobalCurrentHerb := herbMarrentill; + 4: GlobalCurrentHerb := herbGuamLeaf; + 5: GlobalCurrentHerb := herbIritLeaf; + 6: GlobalCurrentHerb := herbAvantoe; + 7: GlobalCurrentHerb := herbDwarfWeed; + 8: GlobalCurrentHerb := herbLantadyme; + 9: GlobalCurrentHerb := herbToadflax; + 10: GlobalCurrentHerb := herbCadantine; + 11: GlobalCurrentHerb := herbKwuarm; + 12: GlobalCurrentHerb := herbTorstol; + 13: GlobalCurrentHerb := herbRanarrWeed; + 14: GlobalCurrentHerb := herbSnapdragon; + else + GlobalCurrentHerb := herbMarrentill; + end; + SimulateFocusLoss := Self.FocusLossCheckbox.IsChecked(); + inherited; +end; + +procedure TDegrimeConfig.Run(); override; +var + tab: TTabSheet; +begin + Self.Setup('Degrime Script Config'); + Self.Start.SetOnClick(@Self.StartScript); + Self.AddTab('Script Settings'); + tab := Self.Tabs[High(Self.Tabs)]; + with Self.HerbSelector do + begin + Create(tab); + SetCaption('Select Herb:'); + SetLeft(20); + SetTop(50); + Combobox.SetStyle(csDropDownList); + Combobox.GetItems.Add('Grimy Huasca'); + Combobox.GetItems.Add('Grimy Tarromin'); + Combobox.GetItems.Add('Grimy Harralander'); + Combobox.GetItems.Add('Grimy Marrentill'); + Combobox.GetItems.Add('Grimy Guam Leaf'); + Combobox.GetItems.Add('Grimy Irit Leaf'); + Combobox.GetItems.Add('Grimy Avantoe'); + Combobox.GetItems.Add('Grimy Dwarf Weed'); + Combobox.GetItems.Add('Grimy Lantadyme'); + Combobox.GetItems.Add('Grimy Toadflax'); + Combobox.GetItems.Add('Grimy Cadantine'); + Combobox.GetItems.Add('Grimy Kwuarm'); + Combobox.GetItems.Add('Grimy Torstol'); + Combobox.GetItems.Add('Grimy Ranarr Weed'); + Combobox.GetItems.Add('Grimy Snapdragon'); + Combobox.SetItemIndex(5); // Default herb selection. + end; + with Self.FocusLossCheckbox do + begin + Create(tab); + SetCaption('Simulate Losing Focus'); + SetLeft(20); + SetTop(Self.HerbSelector.GetBottom() + 20); + SetHint('Enable to occasionally switch focus state and cast with slower timers.'); + end; + Self.CreateBankSettings(); + Self.CreateAntibanManager(); + Self.CreateWaspLibSettings(); + Self.CreateAPISettings(); + inherited; +end; + +var + DegrimeConfig: TDegrimeConfig; +{$ENDIF} + +var + DegrimeScript: TDegrimeScript; + +{$IFNDEF SCRIPT_CHAIN} +begin + {$IFDEF SCRIPT_GUI} + DegrimeConfig.Run(); + {$ENDIF} + DegrimeScript.Run(WLSettings.MaxActions, WLSettings.MaxTime); +end. +{$ENDIF} +