Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MOD] Craft Price Estimation+ Zaap Search fixed + [MOD] Monstes spells #263

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -88,3 +88,6 @@ release
dist-ssr
*.local
.vscode/settings.json

# Webstorm
.idea
2 changes: 2 additions & 0 deletions packages/i18n/en/index.ts
Original file line number Diff line number Diff line change
@@ -120,6 +120,8 @@ const en: BaseTranslation = {
interface: 'Interface',
sound: 'Sound',
gameData: 'Game data',
debug: 'Debug',
activateDebugLogs: 'Activate the debug logs. Warning: this may worsen the performance',
language: 'Language',
resolution: 'Resolution',
fullScreen: 'Full screen',
2 changes: 2 additions & 0 deletions packages/i18n/es/index.ts
Original file line number Diff line number Diff line change
@@ -121,6 +121,8 @@ const es: Translation = {
interface: 'Interfaz',
sound: 'Sonido',
gameData: 'Datos del juego',
debug: 'Debug',
activateDebugLogs: 'Activa los logs de debug. Atencion: Esto puede empeorar el rendimiento',
language: 'Lenguaje',
resolution: 'Resolución',
fullScreen: 'Pantalla completa',
2 changes: 2 additions & 0 deletions packages/i18n/fr/index.ts
Original file line number Diff line number Diff line change
@@ -121,6 +121,8 @@ const fr: Translation = {
interface: 'Interface',
sound: 'Son',
gameData: 'Données du jeu',
debug: 'Debug',
activateDebugLogs: 'Activer les journaux de débogage. Attention : Cela peut nuire à la performance du système.',
language: 'Langue',
resolution: 'Résolution',
fullScreen: 'Activer le mode plein écran',
16 changes: 16 additions & 0 deletions packages/i18n/i18n-types.ts
Original file line number Diff line number Diff line change
@@ -365,6 +365,14 @@ type RootTranslation = {
* Game data
*/
gameData: string
/**
* Debug
*/
debug: string
/**
* Activate the debug logs. Warning: this may worsen the performance
*/
activateDebugLogs: string
/**
* Language
*/
@@ -1439,6 +1447,14 @@ export type TranslationFunctions = {
* Game data
*/
gameData: () => LocalizedString
/**
* Debug
*/
debug: () => LocalizedString
/**
* Activate the debug logs. Warning: this may worsen the performance
*/
activateDebugLogs: () => LocalizedString
/**
* Language
*/
77 changes: 77 additions & 0 deletions packages/renderer/src/mods/debug message helper/debug messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Mod } from '@/mods/mod'
import { DofusWindow } from '@/dofus-window'
import { RootStore } from '@/store'
import { TranslationFunctions } from '@lindo/i18n'
import { EventManager } from '@/mods/helpers'
import { IObjectDidChange, Lambda, observe } from 'mobx'

interface ValueDidChange {
value: boolean
oldValue: boolean
}

export class DebugMessagesMod extends Mod {
private readonly eventManager = new EventManager()
private readonly _disposers: Array<Lambda> = []

constructor(wGame: DofusWindow, rootStore: RootStore, LL: TranslationFunctions) {
super(wGame, rootStore, LL)
console.log('- enabled debug messages')
const disposer = observe(this.rootStore.optionStore.window, (change: IObjectDidChange<ValueDidChange>) => {
if (change.name !== 'debugLogs') return
if (change.type !== 'update') return
if (change?.newValue?.value) this.startEvents()
else this.removeEvents()
})
this._disposers.push(disposer)
if (this.rootStore.optionStore.window.debugLogs) this.load()
}

private load() {
this.startEvents()
}

private startEvents() {
console.log('- starting debug events')
this.eventManager.on(this.wGame.dofus.connectionManager, 'send', this.onSend)
this.eventManager.on(this.wGame.dofus.connectionManager, 'data', this.onReceive)
this.eventManager.on(this.wGame.dofus.connectionManager, 'messageSequence', this.onMsgSeq)
}

onSend = (msg: any) => {
if (msg.call === 'sendMessage') {
console.debug('%c-> ' + msg.data.data.type, 'background-color: orange; color:black', msg.data.data.data)
} else {
console.debug('%c-> ' + msg.data.call, 'background-color: red; color:white', msg.data.data)
}
}

onReceive = (msg: any) => {
const msgCopy = { ...msg }
const type = msg._messageType
delete msgCopy._messageType
console.debug('%c<- ' + type, 'background-color: green;color: white', msgCopy)
}

onMsgSeq = (msg: any) => {
msg.sequence.forEach((s: any) => {
const msgCopy = { ...s }
delete msgCopy._messageType
console.debug('%cSEQ ' + s._messageType, 'background-color: yellow;color:black;', msgCopy)
})
}

destroy(): void {
this.removeEvents()
for (const disposer of this._disposers) {
disposer()
}
}

private removeEvents() {
console.log('- removing debug events')
this.eventManager.removeListener(this.wGame.dofus.connectionManager, 'send', this.onSend)
this.eventManager.removeListener(this.wGame.dofus.connectionManager, 'data', this.onReceive)
this.eventManager.removeListener(this.wGame.dofus.connectionManager, 'messageSequence', this.onMsgSeq)
}
}
1 change: 1 addition & 0 deletions packages/renderer/src/mods/debug message helper/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './debug messages'
6 changes: 6 additions & 0 deletions packages/renderer/src/mods/index.ts
Original file line number Diff line number Diff line change
@@ -15,6 +15,9 @@ import { ShortcutsMod } from './shortcuts'
import { ShowResourcesMod } from './show-resources'
import { VerticalTimelineMod } from './vertical-timeline'
import { ZaapSearchFilterMod } from './zaap-search-filter'
import { RecipePrice } from './recipe-price'
import { OffensiveMonsters } from '@/mods/ofensive monsters'
import { DebugMessagesMod } from '@/mods/debug message helper'

export * from './shortcuts'
export * from './notifications'
@@ -46,5 +49,8 @@ export const MODS = [
RuneListerMod,
ShowResourcesMod,
ZaapSearchFilterMod,
RecipePrice,
OffensiveMonsters,
DebugMessagesMod,
...GENERAL_MODS
] as const
1 change: 1 addition & 0 deletions packages/renderer/src/mods/ofensive monsters/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './offensive-monsters'
256 changes: 256 additions & 0 deletions packages/renderer/src/mods/ofensive monsters/offensive-monsters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
/* eslint-disable */
import { Mod } from '@/mods/mod'
import { DofusWindow } from '@/dofus-window'
import { RootStore } from '@/store'
import { TranslationFunctions } from '@lindo/i18n'
//Thanks Moune
export class OffensiveMonsters extends Mod {
private manager: any
private grimoireWindow: any
private oldAddMonster: any
private damageInfo: any
private spellWindow: any
private mobSpells: any

constructor(wGame: DofusWindow, rootStore: RootStore, LL: TranslationFunctions) {
super(wGame, rootStore, LL)
window.lindoAPI.logger.info('- enable Offensive Monsters')()
this.manager = this.findSingleton('getWindow') as any
this.grimoireWindow = this.manager.getWindow('grimoire')
setTimeout(() => {

this.initSpellUi()

this.initWindow()

this.injectButton()
}, 300)
}

findSingleton(singleton: string): any {
const ret = this.wGame.findSingleton(singleton, this.wGame) as any
if (Array.isArray(ret))
return ret
return ret?.exports
}

destroy(): void {

if (this.oldAddMonster) {
const x = (this.findSingleton('addMonster') as any)
x.prototype.addMonster = this.oldAddMonster
this.oldAddMonster = null
}
}

initWindow() {
this.createWindow('mouneSpellMobs', 'Hechizos del monstruo')
this.spellWindow = this.manager.getWindow('mouneSpellMobs')
this.damageInfo = this.spellWindow.windowBody.createChild('div')
this.damageInfo.setText('Dommages x nani')
this.damageInfo.rootElement.style.cssText = `
text-align: center;
margin-bottom: 10px;
color: navajowhite;
font-size: 20px;
`
this.spellWindow.windowBody.appendChild(this.mobSpells)
}

initSpellUi() {
const constr = this.findSingleton('_loadAllSpells') as any
// eslint-disable-next-line new-cap
this.mobSpells = new constr()
this.mobSpells.emit('open')
this.mobSpells.emit('opened')
this.mobSpells._spellsStatus = {}
this.mobSpells._spellCache = {}
this.mobSpells.spells = {}
const r = (this.findSingleton('createSpells') as any[])[1].exports.prototype
this.mobSpells._loadAllSpells = constr.prototype._loadAllSpells.bind(this.mobSpells)

this.mobSpells._createSpells = r.createSpells.bind(this.mobSpells)
this.mobSpells.addSpells = (this.findSingleton('addSpells') as any).prototype.addSpells.bind(
this.mobSpells
)
}

addSpells(ids: any) {
this.mobSpells._createSpells(ids, () => {
const w = (this.findSingleton('getWindow') as any)
w.switch('mouneSpellMobs')
this.mobSpells._loadAllSpells(this.mobSpells._spellCache)
})
}

finishSpells(ids: any) {
this.mobSpells._spellCache = {}
this.addSpells(ids)
}

injectButton() {
function n(e: any, t: any, i: any) {
;(void 0 === i.min[e] || i.min[e] > t[e]) && (i.min[e] = t[e]),
(void 0 === i.max[e] || i.max[e] < t[e]) && (i.max[e] = t[e])
}

function o(e: any) {
for (var t: any = {
min: {},
max: {}
},
i = [
'level',
'lifePoints',
'actionPoints',
'movementPoints',
'earthResistance',
'airResistance',
'fireResistance',
'waterResistance',
'neutralResistance'
],
o = i.length,
s = 0,
a = e.length;
s < a;
s += 1
)
for (let r = e[s], l = 0; l < o; l += 1) {
const c = i[l]
n(c, r, t)
}
return t
}

const module = this
const buttonCreator = this.findSingleton('DofusButton') as any
const m = (this.findSingleton('getWuiName') as any)[2].exports
const b = (this.findSingleton('getText') as any)[0].exports.getText
const y = this.findSingleton('createMapLocation') as any
this.oldAddMonster = (this.findSingleton('addMonster') as any).prototype.addMonster
;(this.findSingleton('addMonster') as any).prototype.addMonster = function(e: any, t: any) {
// eslint-disable-next-line new-cap
const i = new m('div', {
className: 'infos'
})
const n = i.createChild('div', {
className: 'gfx'
})
n.setStyle('backgroundImage', t)
const s = i.createChild('div', {
className: 'infosGroupRight'
})
const a = s.createChild('div', {
className: 'cf'
})
const r = ['name']
e.isBoss && r.push('boss'), e.isMiniBoss && r.push('miniBoss'), e.isQuestMonster && r.push('questMonster')
const l = true
let c = e.nameId
// eslint-disable-next-line no-unused-expressions
l && (c += ' (' + e.id + ')'),
a.createChild('div', {
className: r,
text: c
})
const u = o(e.grades)
const d = u.min.level
const h = u.max.level
let p = b('ui.common.short.level') + ' ' + d
// eslint-disable-next-line no-unused-expressions
d !== h && (p += ' ' + b('ui.chat.to') + ' ' + h),
a.createChild('div', {
className: 'level',
text: p
})

s.appendChild(y.createMapLocation(e.subareas, this.subAreas, e.favoriteSubareaId))
const f = this.monsterList.addItem(
{
id: e.id,
element: i,
data: e
},
{
noRefresh: !0
}
)
// eslint-disable-next-line new-cap
const spellButton = new buttonCreator({
tooltip: 'Ver hechizos de los monstruos',
addIcon: true
})
spellButton.rootElement.style.cssText = `
pointer: cursor;
background-image: url(../game/assets/ui/banner/menuIconSpell.png);
background-size: contain;
background-repeat: no-repeat;
width: 30px;
height: 30px;
display: flex;
flex-direction: row;
`
f.addClassNames('monster'),
(f.monsterData = e),
(f.gradeMinMaxInfo = u),
s._childrenList[1].insertChildBefore(spellButton, s._childrenList[1]._childrenList[1])
spellButton.on('tap', () => {
const minWisdom = 1 + e.grades[0].wisdom / 100
const len = e.grades.length
const maxWisdom = 1 + e.grades[len - 1].wisdom / 100
if (minWisdom == maxWisdom) {
module.damageInfo.setText(`Daños x ${minWisdom}`)
} else {
module.damageInfo.setText(`Daños x ${minWisdom} a x ${maxWisdom}`)
}
module.mobSpells.spells = {}
module.finishSpells(e.spells)
})
}
}

createWindow(id: any, name: any) {
const windowMaker = (this.findSingleton('startWaitingForContent') as any[])[0].exports
const superClass = (this.findSingleton('inherits') as any)[0].exports.inherits

function myWindow(this: any) {
windowMaker.call(this, {
className: id,
title: name,
plusButton: true,
minusButton: true,
positionInfo: {
left: 'c',
top: 'c',
width: '60%',
height: '70%',
isDefault: true
}
})
this.status = {
lastOpenCoords: {},
lastWindowInfo: {
x: null,
y: null,
w: null,
h: null
},
initialSizeAndPosition: {
left: 'c',
bottom: '3%',
width: '50%',
height: '90%'
}
}
this.plusButton.hide()
this.minusButton.hide()
}


superClass(myWindow, windowMaker)

// @ts-ignore
this.manager.addWindow(id, new myWindow)
}
}
1 change: 1 addition & 0 deletions packages/renderer/src/mods/recipe-price/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './recipe-price'
76 changes: 76 additions & 0 deletions packages/renderer/src/mods/recipe-price/recipe-price.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* eslint-disable prefer-rest-params */
import { Mod } from '@/mods/mod'
import { DofusWindow } from '@/dofus-window'
import { RootStore } from '@/store'
import { TranslationFunctions } from '@lindo/i18n'

export class RecipePrice extends Mod {
constructor(wGame: DofusWindow, rootStore: RootStore, LL: TranslationFunctions) {
super(wGame, rootStore, LL)
window.lindoAPI.logger.info('- enable Recipe Prices helper')()
const itemRecipes = this.getWindowById('itemRecipes')
this.hookFunction(itemRecipes, '_displayItem', () => {
setTimeout(() => {
const itemRecipes = this.getWindowById('itemRecipes') as any
const singleton = this.wGame.findSingleton('getAveragePrice', this.wGame) as any
const func = singleton.exports.getAveragePrice
const recipe = itemRecipes?.recipeBox?.rawRecipe
const slots = itemRecipes?.itemBox?.item?.recipeSlots
let res = 0
let resCost = func(itemRecipes?.recipeBox?.rawRecipe?.resultId)
for (let i = recipe?.ingredientIds?.length - 1; i >= 0; i--) {
const id = recipe.ingredientIds[i]
const cost = func(id)
const quantity = recipe.quantities[i]
if (cost >= 0) res += cost * quantity
}
if (slots === 0) {
res = 0
resCost = 0
}
this.injectCost(res, resCost)
}, 100)
})
}

destroy(): void {
console.log('destroyed')
}

private getKamaDiv() {
return "<div style='background: url(./assets/ui/icons/kama.png) no-repeat;width: 20px;display: inline-block;height: 16px;background-size: 18px;'></div>"
}

private injectCost(cost: number, resultCost: number) {
const el = this.wGame.document.querySelector('.itemRecipeBox .title')
if (!el) {
throw new Error('')
}
let text = el.innerHTML
const ind = text.indexOf('<element')
if (ind >= 0) text = el.innerHTML.substring(0, ind)
if (cost > 0)
el.innerHTML = `${text}<element style='color:${
cost < resultCost ? 'green' : 'red'
}'> [${cost}]${this.getKamaDiv()}</element> - <element style='color: yellow'>[${resultCost}]${this.getKamaDiv()}</element>`
else el.innerHTML = text
}

private hookFunction(object: any, functionName: string, callback: any) {
;(function (originalFunction) {
object[functionName] = function () {
const returnValue = originalFunction.apply(this, arguments)
callback.apply(this, [returnValue, originalFunction, arguments])
return returnValue
}
})(object[functionName])
}

private getWindowById(id: string) {
const window = this.wGame.gui.windowsContainer.getChildren().find((e) => e.id === id)
if (!window) {
throw new Error(`Can't find the window id ${id}`)
}
return window
}
}
30 changes: 15 additions & 15 deletions packages/renderer/src/mods/zaap-search-filter/zaap-search-filter.ts
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ export class ZaapSearchFilterMod extends Mod {
currentZaap.style.display = 'none'

if (currentZaap.innerText.toLowerCase().includes(zaapWanted)) {
currentZaap.style.display = 'block'
currentZaap.style.display = ''
}
}
})
@@ -156,11 +156,11 @@ export class ZaapSearchFilterMod extends Mod {
if (unfav !== 0) {
favorites.splice(unfav, 1)
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/greyStar.png">
<img width='25' height='24' src='./assets/ui/icons/greyStar.png'>
`
} else {
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/goldenStar.png">
<img width='25' height='24' src='./assets/ui/icons/goldenStar.png'>
`
favorites.push(zaap)
}
@@ -183,11 +183,11 @@ export class ZaapSearchFilterMod extends Mod {

if (found) {
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/goldenStar.png">
<img width='25' height='24' src='./assets/ui/icons/goldenStar.png'>
`
} else {
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/greyStar.png">
<img width='25' height='24' src='./assets/ui/icons/greyStar.png'>
`
}

@@ -242,7 +242,7 @@ export class ZaapSearchFilterMod extends Mod {

currentZaap.style.display = 'none'
if (currentZaap.innerText.toLowerCase().includes(zaapWanted)) {
currentZaap.style.display = 'block'
currentZaap.style.display = ''
}
}
})
@@ -321,11 +321,11 @@ export class ZaapSearchFilterMod extends Mod {
if (unfav !== 0) {
favorites.splice(unfav, 1)
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/greyStar.png">
<img width='25' height='24' src='./assets/ui/icons/greyStar.png'>
`
} else {
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/goldenStar.png">
<img width='25' height='24' src='./assets/ui/icons/goldenStar.png'>
`
favorites.push(zaap)
}
@@ -348,11 +348,11 @@ export class ZaapSearchFilterMod extends Mod {

if (found) {
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/goldenStar.png">
<img width='25' height='24' src='./assets/ui/icons/goldenStar.png'>
`
} else {
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/greyStar.png">
<img width='25' height='24' src='./assets/ui/icons/greyStar.png'>
`
}

@@ -407,7 +407,7 @@ export class ZaapSearchFilterMod extends Mod {

currentZaap.style.display = 'none'
if (currentZaap.innerText.toLowerCase().includes(zaapWanted)) {
currentZaap.style.display = 'block'
currentZaap.style.display = ''
}
}
})
@@ -487,11 +487,11 @@ export class ZaapSearchFilterMod extends Mod {
if (unfav !== 0) {
favorites.splice(unfav, 1)
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/greyStar.png">
<img width='25' height='24' src='./assets/ui/icons/greyStar.png'>
`
} else {
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/goldenStar.png">
<img width='25' height='24' src='./assets/ui/icons/goldenStar.png'>
`
favorites.push(zaap)
}
@@ -514,11 +514,11 @@ export class ZaapSearchFilterMod extends Mod {

if (found) {
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/goldenStar.png">
<img width='25' height='24' src='./assets/ui/icons/goldenStar.png'>
`
} else {
divButton.innerHTML = `
<img width="25" height="24" src="./assets/ui/icons/greyStar.png">
<img width='25' height='24' src='./assets/ui/icons/greyStar.png'>
`
}

Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ export const GameScreen = memo(({ game }: GameScreenProps) => {
})

if (results.length > 1) {
window.lindoAPI.logger.error(
window.lindoAPI?.logger?.error(
`[MG] Singleton searcher found multiple results for key "${searchKey}". Returning all of them.`
)()
return results
Original file line number Diff line number Diff line change
@@ -143,6 +143,17 @@ export const OptionGeneral = () => {
</Button>
)}
</Stack>
<Typography variant='h5' component='h2' gutterBottom>
{LL.option.general.debug()}
</Typography>
<FormControl fullWidth>
<FormControlLabel
control={<Checkbox />}
label={LL.option.general.activateDebugLogs()}
checked={optionStore.window.debugLogs}
onChange={(_, checked) => optionStore.window.setDebugLogs(checked)}
/>
</FormControl>
</Box>
</>
)}
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ export const WindowOptionModel = types
.model('WindowOption')
.props({
fullScreen: types.optional(types.boolean, false),
debugLogs: types.optional(types.boolean, false),
resolution: types.optional(types.frozen<Resolution>(), {
width: 1280,
height: 720
@@ -25,6 +26,9 @@ export const WindowOptionModel = types
}
}))
.actions((self) => ({
setDebugLogs(value: boolean) {
self.debugLogs = value
},
setFullScreen(value: boolean) {
self.fullScreen = value
},