ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [타운스타] Autosell 오토셀 스크립트 사용방법
    게임/타운스타 2022. 2. 3. 21:21
    728x90
    반응형

    나의 타운스타 마을, 와인테크

    타운스타 오토셀 스크립트를 이용하면 재료가 모일때마다 자동으로 팔아줘서 게임하기가 수월해진다.

     

    1. 필수 설치 파일

    https://www.tampermonkey.net/

     

    Tampermonkey for Chrome

    Tampermonkey is a free browser extension and the most popular userscript manager. It's available for Chrome, Microsoft Edge, Safari, Opera Next, and Firefox. Even though some of the supported browsers have native userscript support, Tampermonkey will give

    www.tampermonkey.net

    위 사이트에서 스크립트를 실행해주는 프로그램을 설치하면 된다.

     

    나는 크롬을 사용중이어서 크롬의 Stable 버전을 설치했다.

    반응형

    2. 스크립트 다운로드

    https://gala-analytics.herokuapp.com/townstar

     

    Gala Analytics

     

    gala-analytics.herokuapp.com

    위 사이트에서 스크립트를 다운로드 받을 수 있다.

    나는 v2 버전을 사용중이다.

    코드의 맨 윗부분 유저스크립트에서, 한줄을 바꿔줘야한다.

    @match 부분에 // @match        *://*.sandbox-games.com/* 라고 넣어줘야 타운스타 내에서 스크립트가 동작한다.

     

    아래는 내가 사용중인 코드 전문이다.

    더보기

     

    // ==UserScript==
    // @name         Town Star Auto-Sell
    // @namespace    http://tampermonkey.net/
    // @version      2.3
    // @description  Automatically sell crafted items.
    // @author       Groove
    // @match        *://*.sandbox-games.com/*
    // @grant        none
    // @run-at       document-start
    // ==/UserScript==
    
    (function() {
        'use strict';
    	// keepAmt is the amount that you do not want to sell
    	// sellMin is the minimum amount needed before attempting to sell
    	//    setting a sellMin of 100 will ensure that the item is only sold in batches of 100 (e.g. via Freight Ship)
        const craftedItems = [
            //농작물
            {item: 'Pinot_Noir_Grapes', keepAmt: 3, sellMin: 0},
            //{item: 'Wheat', keepAmt: 0, sellMin: 0},
            {item: 'Gasoline', keepAmt: 3, sellMin: 0},
            {item: 'Wood', keepAmt: 10, sellMin: 0},
            {item: 'Oak_Wood', keepAmt: 3, sellMin: 0},
            {item: 'Lumber', keepAmt: 3, sellMin: 0},
            //공산품
            {item: 'Wine_Bottle', keepAmt: 3, sellMin: 0},
            {item: 'Energy', keepAmt: 3, sellMin: 0},
            {item: 'Pinot_Noir', keepAmt: 0, sellMin: 0},
            // 철광산
            {item: 'Silica', keepAmt: 6, sellMin: 0},
            {item: 'Limestone', keepAmt: 3, sellMin: 0},
            {item: 'Chromium', keepAmt: 3, sellMin: 0},
            {item: 'Iron', keepAmt: 3, sellMin: 0}
        ]
    
        new MutationObserver(function(mutations) {
            let airdropcollected = 0;
            if(document.getElementsByClassName('hud-jimmy-button')[0] && document.getElementsByClassName('hud-jimmy-button')[0].style.display != 'none'){
                document.getElementsByClassName('hud-jimmy-button')[0].click();
                document.getElementById('Deliver-Request').getElementsByClassName('yes')[0].click();
                document.getElementById('Deliver-Request').getElementsByClassName('close-button')[0].click();
            }
            if(document.getElementsByClassName('hud-airdrop-button')[0] && document.getElementsByClassName('hud-airdrop-button')[0].style.display != 'none'){
                if(airdropcollected == 0){
                    airdropcollected = 1;
                    document.getElementsByClassName('hud-airdrop-button')[0].click();
                    document.getElementsByClassName('air-drop')[0].getElementsByClassName('yes')[0].click();
                }
            }
            if (document.getElementById("playnow-container") && document.getElementById("playnow-container").style.visibility !== "hidden") {
                if(typeof Game == 'undefined' || (Game && Game.gameData == null)) {
                    window.location.reload();
                } else {
                    document.getElementById("playButton").click();
                    console.log(Date.now() + ' ---===ACTIVATING AUTO SELL===---');
                    ActivateAutoSell();
                }
            }
        }).observe(document, {childList: true, subtree: true});
    
        function GetAvailableTradeObject(capacity) {
            return Object.values(Game.town.objectDict).filter(tradeObj => tradeObj.logicType === 'Trade')
                .find(tradeObj =>
                      Game.unitsData[tradeObj.objData.UnitType].Capacity == capacity
                      && !Game.town.tradesList.find(activeTrade => activeTrade.source.x == tradeObj.townX && activeTrade.source.z == tradeObj.townZ)
                     )
        }
    
        function CloseWindows(elements, checkParent) {
            for (let i=0, n=elements.length; i < n; i++) {
                let el = checkParent ? elements[i].closest('.container') : elements[i];
                let elVis = el.currentStyle ? el.currentStyle.visibility : getComputedStyle(el, null).visibility;
                let elDis = el.currentStyle ? el.currentStyle.display : getComputedStyle(el, null).display;
                if (!(elVis === 'hidden' || elDis === 'none')) {
                    el.querySelector('.close-button') && el.querySelector('.close-button').click();
                }
            }
        }
    
        async function WaitForCompletion(selector) {
            while (document.querySelector(selector) !== null) {
                await new Promise( resolve => requestAnimationFrame(resolve) )
            }
            return document.querySelector(selector);
        }
    
        async function WaitForTradeLoad(targetTradeObj) {
            return await new Promise(resolve => {
                const waitForUpdate = setInterval(() => {
                    let tradeUiObj = Game.app.root.findByName('TradeUi').script.trade.townObject;
                    if (tradeUiObj && tradeUiObj.townX == targetTradeObj.townX && tradeUiObj.townZ == targetTradeObj.townZ && Game.app.root.findByName('TradeUi').script.trade.cityPaths[0].gasCost) {
                        resolve('Loaded');
                        clearInterval(waitForUpdate);
                    };
                }, 500);
            });
        }
    
        async function WaitForElement(selector) {
            while (document.querySelector(selector) === null) {
                await new Promise( resolve => requestAnimationFrame(resolve) )
            }
            await new Promise(resolve => setTimeout(resolve, 1000));
            return document.querySelector(selector);
        }
    
        async function CheckCrafts() {
            let allTradeObjects = Object.values(Game.town.objectDict).filter(tradeObj => tradeObj.logicType === 'Trade');
    
            for (let i=0, n=allTradeObjects.length; i < n; i++) {
                if (allTradeObjects[i].logicObject.tapToCollectEntity.enabled) {
                    allTradeObjects[i].logicObject.OnTapped();
                }
            }
            if (Game.town.GetStoredCrafts()['Gasoline'] >= 1) {
                for (let i=0, n=craftedItems.length; i < n; i++) {
                    if (Game.town.GetStoredCrafts()[craftedItems[i].item] >= craftedItems[i].keepAmt + 10) {
                        let targetTradeObj;
                        if (Game.town.GetStoredCrafts()[craftedItems[i].item] >= 100 + craftedItems[i].keepAmt) {
                            targetTradeObj = GetAvailableTradeObject(100);
                        }
                        if (!targetTradeObj && Game.town.GetStoredCrafts()[craftedItems[i].item] >= 50 + craftedItems[i].keepAmt && craftedItems[i].sellMin <= 50){
                            targetTradeObj = GetAvailableTradeObject(50);
                        }
                        if (!targetTradeObj && Game.town.GetStoredCrafts()[craftedItems[i].item] >= 10 + craftedItems[i].keepAmt && craftedItems[i].sellMin <= 10){
                            targetTradeObj = GetAvailableTradeObject(10);
                        }
                        if (targetTradeObj){
                            CloseWindows(document.querySelectorAll('body > .container > .player-confirm .dialog-cell'), false);
                            CloseWindows(document.querySelectorAll('.container > div:not(.hud):not(.player-confirm)'), true);
                            Game.town.selectObject(targetTradeObj);
                            Game.app.fire('SellClicked', {x: targetTradeObj.townX, z: targetTradeObj.townZ});
                            await WaitForCompletion('.LoadingOrders');
                            document.querySelector('#trade-craft-target [data-name="' + craftedItems[i].item + '"]').click();
                            await WaitForTradeLoad(targetTradeObj);
                            if (Game.town.GetStoredCrafts()['Gasoline'] >= Game.app.root.findByName('TradeUi').script.trade.cityPaths[0].gasCost) {
                                document.querySelector('#destination-target .destination .sell-button').click();
                                let tradeTimeout = setTimeout(function(){
    								document.querySelector('.trade-connection .no').click();
    							},10000);
                                await WaitForCompletion('.trade-connection .compass');
    							clearTimeout(tradeTimeout);
                            } else {
                                console.log('Whoops! You have run out of gas.');
                                document.querySelector('#autosell-status .bank').textContent = 'ALERT: Out of gas!'
                                document.querySelector('.container > .trade .close-button').click();
                            }
                        }
                    }
                }
            } else {
                console.log('Whoops! You have run out of gas.');
                document.querySelector('#autosell-status .bank').textContent = 'ALERT: Out of gas!'
            }
            setTimeout(CheckCrafts, 5000);
        }
    
        async function ActivateAutoSell() {
            let autoSellStatus = document.createElement('div');
            autoSellStatus.id = 'autosell-status';
            autoSellStatus.style.cssText = 'pointer-events: all; position: absolute; left: 50%; transform: translate(-50%, 0);';
            autoSellStatus.addEventListener( 'click', function(){this.children[0].textContent = 'Auto-Sell Active';})
            let autoSellContent = document.createElement('div');
            autoSellContent.classList.add('bank');
            autoSellContent.style.cssText = 'background-color: #fde7e3; padding-left: 10px; padding-right: 10px';
            autoSellContent.textContent = 'Auto-Sell Active';
            autoSellStatus.appendChild(autoSellContent);
            await WaitForElement('.hud');
            document.querySelector('.hud').prepend(autoSellStatus);
            CheckCrafts();
        }
    
    })();

    17번 라인의     const craftedItems = [ 부분에서,

    팔고싶은 아이템을 적으면 된다.

    예시로, {item: 'Wheat', keepAmt: 3, sellMin: 0} 의 의미는

    Wheat(밀)이 3개를 항상 유지하며, 팔수있을때 판다(sellMin:0) 라는 뜻이다.

    즉, 밀이 13개가 모이면 판매를 한다.

     

     

    3. 타운스타 실행

    타운스타를 실행하면 가운데 윗부분에 Auto-Sell Active라고 표시가 된다.

    혹은 크롬 브라우저 창에 아래 스크린샷과 같이 TamperMonkey의 빨간색 1을 발견할 수 있다.

     

     

    4. 평가

     

    매우 편하게 게임을 할 수 있다.

    특히 마을 건설 초반에 가솔린 테크가 완성되기 전에 돈을 모아야하는 시기가 있다.

    그때 지루하지않고 편하게 지나갈 수 있고

    중반쯤, 고급인력으로 대체할 때 돈이 많이 필요하게 된다.

    하룻밤 켜놓고 자면 다음날 돈이 많이 모여있어서 마을 완성을 바로 할 수 있게 된다.

    728x90
    반응형

    댓글

Designed by Tistory.