// ==UserScript== // @name The West Duel Cloth Calc // @author Mr. Perseus // @namespace tw-perseus // @description Calculates the Duel skill values of your opponents. // @include https://*.the-west.*/game.php* // @include http://*.the-west.*/game.php* // @include https://*.tw.innogames.*/game.php* // @include http://*.tw.innogames.*/game.php* // @version 1.0.1 // @grant none // @downloadURL none // ==/UserScript== (function (fn) { const script = document.createElement('script'); script.setAttribute('type', 'application/javascript'); script.textContent = `(${fn})();`; document.body.appendChild(script); document.body.removeChild(script); })(() => { $(document).ready(() => { const TWDCC = { version: '1.0.1', serverUrl: window.location.hostname.split(/[.0-9]+/)[0], }; TWDCC.Updater = { init() { setTimeout(TWDCC.Updater.load, 5000); }, load() { $.getScript( 'https://rawcdn.githack.com/mr-perseus/tw-js-library/master/script-updater.js', () => { if (scriptUpdater.TWDCC > TWDCC.version) { const updateMessage = new west.gui.Dialog( 'Update: The West Duel Cloth Calc', `Update Available

v${scriptUpdater.TWDCC}:
${scriptUpdater.TWDCCNew}
`, west.gui.Dialog.SYS_WARNING, ) .addButton('Update', () => { updateMessage.hide(); window.location.href = 'https://greasyfork.org/scripts/210874-the-west-duel-cloth-calc/code/The%20West%20Duel%20Cloth%20Calc.user.js'; }) .addButton('cancel') .show(); } }, ); }, }; TWDCC.DuelClothCalc = { init() { PlayerProfileMain.backup_twdcc_setWear = PlayerProfileMain.setWear; PlayerProfileMain.setWear = function () { PlayerProfileMain.backup_twdcc_setWear.apply( this, arguments, ); const playerLevel = this.resp.level; let weaponId = 0; const itemKeys = []; Object.keys(this.resp.wear).forEach((key) => { if ( this.resp.wear[key] && (key === 'animal' || key === 'yield' /* Product */ || key === 'head' || key === 'body' || key === 'pants' || key === 'foot' || key === 'neck' || key === 'belt' || key === 'right_arm' || key === 'left_arm') ) { if (key === 'right_arm') { weaponId = this.resp.wear[key]; } itemKeys.push(this.resp.wear[key]); } }); const values = TWDCC.DuelClothCalc.getSkillValuesFromItemKeys( playerLevel, itemKeys, ); const popupData = TWDCC.DuelClothCalc.getPopupData(values); const duelistPopup = TWDCC.DuelClothCalc.generateNpcPopup( popupData, weaponId, this.resp, ); const jqueryAvatar = this.window.find('div.profileavatar'); jqueryAvatar.attr('title', duelistPopup); const overlayClass = this.window.find('div.overlay'); overlayClass.removeClass('overlay'); }; }, getSkillValuesFromItemKeys(playerLevel, itemKeys) { const itemObjects = TWDCC.DuelClothCalc.getItemObjects(itemKeys); const sets = TWDCC.DuelClothCalc.getSetsNumbers(itemObjects); const setObjects = TWDCC.DuelClothCalc.getSetData(sets); return TWDCC.DuelClothCalc.calculateValues( itemObjects, playerLevel, sets, setObjects, ); }, getItemObjects(itemKeys) { const itemObjects = []; itemKeys.forEach((key) => itemObjects.push(ItemManager.get(key)), ); return itemObjects; }, calculateValues(itemObjects, playerLevel, sets, setObjects) { const values = { strength: 0, flexibility: 0, dexterity: 0, charisma: 0, /* Strength */ build: 0, punch: 0, tough: 0, endurance: 0, health: 0, /* flexibility */ ride: 0, reflex: 0, dodge: 0, hide: 0, swim: 0, /* Dexterity */ aim: 0, shot: 0, pitfall: 0, // eslint-disable-next-line camelcase finger_dexterity: 0, repair: 0, /* charisma */ leadership: 0, tactic: 0, trade: 0, animal: 0, appearance: 0, }; itemObjects.forEach((itemObject) => { const newValuesBonus = TWDCC.DuelClothCalc.getBonusObjectValues( itemObject.bonus.item, ); TWDCC.DuelClothCalc.factorizeValues( newValuesBonus, playerLevel, itemObject.item_level, ); TWDCC.DuelClothCalc.addToValues(values, newValuesBonus); const newValuesSimple = TWDCC.DuelClothCalc.getSimpleObjectValues(itemObject); TWDCC.DuelClothCalc.addToValues(values, newValuesSimple); }); TWDCC.DuelClothCalc.addSetsToValues( sets, values, playerLevel, setObjects, ); return values; }, factorizeValues(values, playerLevel, itemLevel) { const itemPercent = itemLevel ? 1 + itemLevel / 10 : 1; Object.keys(values).forEach((key) => { const ceilValue = Math.ceil(values[key] * playerLevel); values[key] = Math.round(ceilValue * itemPercent); if (values[key] === ceilValue && itemPercent !== 1) { values[key] += 1; } }); }, addToValues(values, newValues) { Object.keys(newValues).forEach((key) => { values[key] = values[key] ? values[key] + newValues[key] : newValues[key]; }); }, getBonusObjectValues(item) { const values = {}; item.forEach((valueObj) => { if ( valueObj.type === 'character' && valueObj.key === 'level' /* valueObj.roundingMethod === "ceil" && */ && (valueObj.bonus.type === 'skill' || valueObj.bonus.type === 'attribute') ) { values[valueObj.bonus.name] = valueObj.bonus.value; } }); return values; }, getSimpleSetObjectValues(setObject) { const values = {}; setObject.forEach((key) => { if (key.type === 'attribute' || key.type === 'skill') { values[key.name] = key.value; } }); return values; }, getSimpleObjectValues(itemObject) { const values = {}; Object.keys(itemObject.bonus.skills).forEach((key) => { values[key] = itemObject.bonus.skills[key]; }); Object.keys(itemObject.bonus.attributes).forEach((key) => { values[key] = itemObject.bonus.attributes[key]; }); return values; }, addSetsToValues(sets, values, playerLevel, setObjects) { Object.keys(sets).forEach((key) => { const setData = setObjects[key]; if (setData && setData.bonus[sets[key]]) { const valuesSetBonus = {}; const valuesSetSimple = {}; for (let index = 2; index <= sets[key]; index += 1) { const valuesSetBonusLevel = TWDCC.DuelClothCalc.getBonusObjectValues( setData.bonus[index], ); TWDCC.DuelClothCalc.addToValues( valuesSetBonus, valuesSetBonusLevel, ); const valuesSetSimpleLevel = TWDCC.DuelClothCalc.getSimpleSetObjectValues( setData.bonus[index], ); TWDCC.DuelClothCalc.addToValues( valuesSetSimple, valuesSetSimpleLevel, ); } TWDCC.DuelClothCalc.factorizeValues( valuesSetBonus, playerLevel, ); TWDCC.DuelClothCalc.addToValues(values, valuesSetBonus); TWDCC.DuelClothCalc.addToValues( values, valuesSetSimple, ); } }); }, getPopupData(values) { return { shot: values.dexterity + values.shot, punch: values.strength + values.punch, aim: values.dexterity + values.aim, appearance: values.charisma + values.appearance, tactic: values.charisma + values.tactic, reflex: values.flexibility + values.reflex, dodge: values.flexibility + values.dodge, tough: values.strength + values.tough, health: values.strength + values.health, }; }, getSetsNumbers(itemObjects) { const sets = {}; itemObjects.forEach((itemObject) => { if (itemObject.set) { if ( Object.prototype.hasOwnProperty.call( sets, itemObject.set, ) ) { sets[itemObject.set] += 1; } else { sets[itemObject.set] = 1; } } }); return sets; }, getSetData(sets) { const setObjects = []; Object.keys(sets).forEach((key) => { setObjects[key] = west.storage.ItemSetManager.get(key); }); return setObjects; }, generateNpcPopup(npcData, weaponId, character) { let weapon; let damage; if (weaponId) { weapon = ItemManager.get(weaponId); damage = weapon.getDamage(character); } // noinspection HtmlRequiredAltAttribute return ( `${ weapon ? '' : '' }` + `` + `` + `` + `` + `` + `` + `${ weapon ? `` : '' }
' + "The opponent's skill bonus" + '
 
${ npcData.shot || 0 }${npcData.punch || 0}${ npcData.aim || 0 }${ npcData.appearance || 0 }
${ npcData.tactic || 0 }${npcData.reflex || 0}${ npcData.dodge || 0 }${ npcData.tough || 0 }${ npcData.health || 0 }

${weapon.name}
(` + 'Damage' + `: ${damage.min} - ${damage.max})
` ); }, }; try { TWDCC.Updater.init(); TWDCC.DuelClothCalc.init(); } catch (err) { console.error('TWDCC ERROR', err); } }); });