Initial showing of the bot window
This commit is contained in:
parent
7be649b56b
commit
45ded91030
@ -69,7 +69,6 @@ add_library(ISXMr SHARED ${SOURCE_DIR}/ISXMr.cpp
|
||||
src/isxeq2/Actor.cpp
|
||||
src/isxeq2/Actor.h
|
||||
src/isxeq2/LSObject.h
|
||||
src/WriteUIFileToDisk.cpp
|
||||
src/isxeq2/Point3f.h
|
||||
src/isxeq2/Ability.cpp
|
||||
src/isxeq2/Ability.h
|
||||
@ -78,12 +77,12 @@ add_library(ISXMr SHARED ${SOURCE_DIR}/ISXMr.cpp
|
||||
src/isxeq2/CharacterClass.h
|
||||
src/isxeq2/AbilityEffect.h
|
||||
src/Logger.h
|
||||
src/Commands/ExecutableCommand.h
|
||||
src/Commands/ExportCommand.cpp
|
||||
src/Commands/ExportCommand.h
|
||||
src/Tasks/ExecutableTask.h
|
||||
src/Tasks/ExportAbilitiesTask.cpp
|
||||
src/Tasks/ExportAbilitiesTask.h
|
||||
src/isxeq2/ExtensionTLOs.h
|
||||
src/Commands/CommandExecutor.cpp
|
||||
src/Commands/CommandExecutor.h
|
||||
src/Tasks/TaskExecutor.cpp
|
||||
src/Tasks/TaskExecutor.h
|
||||
src/BotSettings/ExportedAbility.h
|
||||
includes/argh/argh.h
|
||||
src/isxeq2/EQ2.h
|
||||
@ -94,6 +93,10 @@ add_library(ISXMr SHARED ${SOURCE_DIR}/ISXMr.cpp
|
||||
src/Api/MrBotApi.h
|
||||
includes/json_struct/json_struct.h
|
||||
includes/json_struct/json_struct_diff.h
|
||||
src/Tasks/BotTask.cpp
|
||||
src/Tasks/BotTask.h
|
||||
src/ScopedEnumBitwiseOperators.h
|
||||
lgui2/UpdateUIPackageFile.h
|
||||
)
|
||||
|
||||
IF (WIN32)
|
||||
|
||||
687
lgui2/bot_cast_stack.json
Normal file
687
lgui2/bot_cast_stack.json
Normal file
@ -0,0 +1,687 @@
|
||||
{
|
||||
"$schema": "http://www.lavishsoft.com/schema/lgui2Package.json",
|
||||
"skin": "MRSkin",
|
||||
"templates": {
|
||||
"settings.abilityListEntry": {
|
||||
"jsonTemplate": "listboxitem",
|
||||
"padding": 2,
|
||||
"content": {
|
||||
"type": "stackpanel",
|
||||
"orientation": "vertical",
|
||||
"-contentContainer": {
|
||||
"jsonTemplate": "listbox.contentContainerFitWidth"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"horizontalAlignment": "stretch",
|
||||
"textBinding": {
|
||||
"pullFormat": "${_CONTEXTITEMDATA_.Get[name]}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"settings.castStack": {
|
||||
"orientation": "vertical",
|
||||
"children": [
|
||||
{
|
||||
"type": "panel",
|
||||
"visibility": "hidden",
|
||||
"name": "CastStackController.events"
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"heightFactor": 0.9,
|
||||
"widthFactor": 1,
|
||||
"horizontalAlignment": "left",
|
||||
"children": [
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "vertical",
|
||||
"widthFactor": 0.3,
|
||||
"margin": [
|
||||
0,
|
||||
0,
|
||||
5,
|
||||
0
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "Ability List",
|
||||
"widthFactor": 1,
|
||||
"horizontalAlignment": "left"
|
||||
},
|
||||
{
|
||||
"type": "listbox",
|
||||
"name": "abilityList",
|
||||
"heightFactor": 0.9,
|
||||
"itemsBinding": {
|
||||
"pullFormat": "${CastStackController.abilityListItems}",
|
||||
"pullOnce": true
|
||||
},
|
||||
"itemViewGenerators": {
|
||||
"default": {
|
||||
"type": "template",
|
||||
"template": "settings.abilityListEntry"
|
||||
}
|
||||
},
|
||||
"selectedItemBinding": {
|
||||
"pullFormat": "${CastStackController.currentSelectedAvailableAbilityIndex}",
|
||||
"pushFormat": [
|
||||
"CastStackController:SetCurrentAbility[\"",
|
||||
"\"]"
|
||||
]
|
||||
},
|
||||
"-contentContainer": {
|
||||
"jsonTemplate": "listbox.contentContainerFitWidth"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"name": "castStack.addAbility",
|
||||
"content": "Add Ability",
|
||||
"horizontalAlignment": "stretch",
|
||||
"eventHandlers": {
|
||||
"onRelease": [
|
||||
"method",
|
||||
"CastStackController",
|
||||
"AddAbility"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "vertical",
|
||||
"widthFactor": 0.3,
|
||||
"heightFactor": 1,
|
||||
"verticalAlignment": "top",
|
||||
"margin": [
|
||||
0,
|
||||
0,
|
||||
5,
|
||||
0
|
||||
],
|
||||
"padding": [
|
||||
0,
|
||||
16,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"margin": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "Type",
|
||||
"width": 60
|
||||
},
|
||||
{
|
||||
"type": "combobox",
|
||||
"name": "castStack.ability.type",
|
||||
"horizontalAlignment": "stretch",
|
||||
"items": [
|
||||
"Combat",
|
||||
"CA",
|
||||
"NamedCA",
|
||||
"Heal",
|
||||
"PowerHeal",
|
||||
"Debuff",
|
||||
"NamedDebuff",
|
||||
"NonCombatBuff",
|
||||
"Cure",
|
||||
"Buff"
|
||||
],
|
||||
"selectedItemBinding": {
|
||||
"pullFormat": "${CastStackController.newCastStackItem.Get[type]}",
|
||||
"autoPull": false,
|
||||
"pullHook": {
|
||||
"elementName": "CastStackController.events",
|
||||
"flags": "global",
|
||||
"event": "onNewCastStackItemChanged"
|
||||
}
|
||||
},
|
||||
"eventHandlers": {
|
||||
"onSelectionChanged": {
|
||||
"type": "method",
|
||||
"object": "CastStackController",
|
||||
"method": "OnCastStackAbilityComboChange"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"margin": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "Target",
|
||||
"width": 60
|
||||
},
|
||||
{
|
||||
"type": "combobox",
|
||||
"name": "castStack.ability.target",
|
||||
"horizontalAlignment": "stretch",
|
||||
"itemsBinding": {
|
||||
"pullFormat": "${CastStackController.GetTargetOptions}",
|
||||
"pullOnce": true
|
||||
},
|
||||
"selectedItemBinding": {
|
||||
"pullFormat": "${CastStackController.newCastStackItem.Get[target]}",
|
||||
"autoPull": false,
|
||||
"pullHook": {
|
||||
"elementName": "CastStackController.events",
|
||||
"flags": "global",
|
||||
"event": "onNewCastStackItemChanged"
|
||||
}
|
||||
},
|
||||
"eventHandlers": {
|
||||
"onSelectionChanged": {
|
||||
"type": "method",
|
||||
"object": "CastStackController",
|
||||
"method": "OnCastStackAbilityComboChange"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"margin": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "# targets",
|
||||
"width": 60
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.ability.targetCount",
|
||||
"horizontalAlignment": "stretch",
|
||||
"textBinding": {
|
||||
"pullFormat": "${CastStackController.SafeGetNewCastStackItemProperty[targetCount]}",
|
||||
"autoPull": false,
|
||||
"pullHook": {
|
||||
"elementName": "CastStackController.events",
|
||||
"flags": "global",
|
||||
"event": "onNewCastStackItemChanged"
|
||||
},
|
||||
"pushFormat": [
|
||||
"CastStackController:SafeSetNewCastStackItemProperty[\"targetCount\",\"",
|
||||
"\"]"
|
||||
],
|
||||
"autoPush": false
|
||||
},
|
||||
"hooks": {
|
||||
"onLostFocus": {
|
||||
"flags": "self",
|
||||
"event": "lostKeyboardFocus",
|
||||
"eventHandler": {
|
||||
"type": "forward",
|
||||
"event": "pushTextBinding",
|
||||
"flags": "self"
|
||||
}
|
||||
},
|
||||
"onLostMouseFocus": {
|
||||
"flags": "self",
|
||||
"event": "lostMouseFocus",
|
||||
"eventHandler": {
|
||||
"type": "forward",
|
||||
"event": "pushTextBinding",
|
||||
"flags": "self"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "HP/MP %",
|
||||
"width": 60
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.percent",
|
||||
"horizontalAlignment": "stretch",
|
||||
"textBinding": {
|
||||
"pullFormat": "${CastStackController.SafeGetNewCastStackItemProperty[percent]}",
|
||||
"autoPull": false,
|
||||
"pullHook": {
|
||||
"elementName": "CastStackController.events",
|
||||
"flags": "global",
|
||||
"event": "onNewCastStackItemChanged"
|
||||
},
|
||||
"pushFormat": [
|
||||
"CastStackController:SafeSetNewCastStackItemProperty[\"percent\",\"",
|
||||
"\"]"
|
||||
],
|
||||
"autoPush": false
|
||||
},
|
||||
"hooks": {
|
||||
"onLostFocus": {
|
||||
"flags": "self",
|
||||
"event": "lostKeyboardFocus",
|
||||
"eventHandler": {
|
||||
"type": "forward",
|
||||
"event": "pushTextBinding",
|
||||
"flags": "self"
|
||||
}
|
||||
},
|
||||
"onLostMouseFocus": {
|
||||
"flags": "self",
|
||||
"event": "lostMouseFocus",
|
||||
"eventHandler": {
|
||||
"type": "forward",
|
||||
"event": "pushTextBinding",
|
||||
"flags": "self"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "checkbox",
|
||||
"name": "castStack.ignoreDuration",
|
||||
"content": "Ignore Duration",
|
||||
"horizontalAlignment": "stretch",
|
||||
"margin": [
|
||||
2,
|
||||
10,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "checkbox",
|
||||
"name": "castStack.ignoreEncounterNukes",
|
||||
"content": "Ignore Encounter Nukes",
|
||||
"horizontalAlignment": "stretch"
|
||||
},
|
||||
{
|
||||
"type": "checkbox",
|
||||
"name": "castStack.ignoreAENukes",
|
||||
"content": "Ignore AE Nukes",
|
||||
"horizontalAlignment": "stretch"
|
||||
},
|
||||
{
|
||||
"type": "checkbox",
|
||||
"name": "castStack.maxIncrements",
|
||||
"content": "Max Increments",
|
||||
"horizontalAlignment": "stretch"
|
||||
},
|
||||
{
|
||||
"type": "checkbox",
|
||||
"name": "castStack.namedOnly",
|
||||
"content": "Named Only",
|
||||
"horizontalAlignment": "stretch"
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"horizontalAlignment": "stretch",
|
||||
"margin": [
|
||||
0,
|
||||
10,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "Fervor",
|
||||
"width": 70
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.fervorRangeMin",
|
||||
"width": 30
|
||||
},
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "-",
|
||||
"font": {
|
||||
"bold": true,
|
||||
"height": 24
|
||||
},
|
||||
"margin": [
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"width": 10
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.fervorRangeMax",
|
||||
"width": 30
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"horizontalAlignment": "stretch",
|
||||
"margin": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "Dissonance",
|
||||
"width": 70
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.dissonanceRangeMin",
|
||||
"width": 30
|
||||
},
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "-",
|
||||
"font": {
|
||||
"bold": true,
|
||||
"height": 24
|
||||
},
|
||||
"margin": [
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"width": 10
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.dissonanceRangeMax",
|
||||
"width": 30
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"horizontalAlignment": "stretch",
|
||||
"margin": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "My HP",
|
||||
"width": 70
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.myHpRangeMin",
|
||||
"width": 30
|
||||
},
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "-",
|
||||
"font": {
|
||||
"bold": true,
|
||||
"height": 24
|
||||
},
|
||||
"margin": [
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"width": 10
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.myHpRangeMax",
|
||||
"width": 30
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"horizontalAlignment": "stretch",
|
||||
"margin": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "My Power",
|
||||
"width": 70
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.myPowerRangeMin",
|
||||
"width": 30
|
||||
},
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "-",
|
||||
"font": {
|
||||
"bold": true,
|
||||
"height": 24
|
||||
},
|
||||
"margin": [
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"width": 10
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.myPowerRangeMax",
|
||||
"width": 30
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"horizontalAlignment": "stretch",
|
||||
"margin": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "NPC HP",
|
||||
"width": 70
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.npcHpRangeMin",
|
||||
"width": 30
|
||||
},
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "-",
|
||||
"font": {
|
||||
"bold": true,
|
||||
"height": 24
|
||||
},
|
||||
"margin": [
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"width": 10
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.npcHpRangeMax",
|
||||
"width": 30
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"horizontalAlignment": "stretch",
|
||||
"margin": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "Aggro",
|
||||
"width": 70
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.aggroRangeMin",
|
||||
"width": 30
|
||||
},
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "-",
|
||||
"font": {
|
||||
"bold": true,
|
||||
"height": 24
|
||||
},
|
||||
"margin": [
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"width": 10
|
||||
},
|
||||
{
|
||||
"type": "textbox",
|
||||
"name": "castStack.aggroRangeMax",
|
||||
"width": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "vertical",
|
||||
"widthFactor": 1,
|
||||
"heightFactor": 1,
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "Cast Order",
|
||||
"widthFactor": 1,
|
||||
"horizontalAlignment": "left"
|
||||
},
|
||||
{
|
||||
"type": "listbox",
|
||||
"name": "castStack.castOrder",
|
||||
"horizontalAlignment": "stretch",
|
||||
"heightFactor": 0.9,
|
||||
"itemsBinding": {
|
||||
"pullFormat": "${CastStackController.profile.Get[castStack].Keys}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"name": "castStack.castOrder.edit",
|
||||
"content": "Edit Entry",
|
||||
"horizontalAlignment": "stretch",
|
||||
"eventHandlers": {
|
||||
"onRelease": [
|
||||
"method",
|
||||
"CastStackController",
|
||||
"EditEntry"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "horizontal",
|
||||
"verticalAlignment": "stretch",
|
||||
"horizontalAlignment": "stretch",
|
||||
"children": [
|
||||
{
|
||||
"type": "stackpanel",
|
||||
"orientation": "vertical",
|
||||
"verticalAlignment": "stretch",
|
||||
"horizontalAlignment": "left",
|
||||
"children": [
|
||||
{
|
||||
"type": "button",
|
||||
"name": "castStack.loadProfile",
|
||||
"content": "Load Profile",
|
||||
"horizontalAlignment": "left"
|
||||
},
|
||||
{
|
||||
"type": "combobox",
|
||||
"name": "castStack.profileList",
|
||||
"horizontalAlignment": "left",
|
||||
"itemsBinding": {
|
||||
"pullFormat": "${CastStackController.ProfileList}",
|
||||
"autoPull": true,
|
||||
"pullHook": {
|
||||
"elementName": "CastStackController.events",
|
||||
"flags": "global",
|
||||
"event": "onProfileListChanged"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
174
lgui2/bot_window.json
Normal file
174
lgui2/bot_window.json
Normal file
@ -0,0 +1,174 @@
|
||||
{
|
||||
"$schema": "http://www.lavishsoft.com/schema/lgui2Package.json",
|
||||
"includes": [
|
||||
"bot_cast_stack.json"
|
||||
],
|
||||
"skin": {
|
||||
"name": "MRSkin",
|
||||
"brushes": {
|
||||
"window.titleBar.backgroundBrush": {
|
||||
"color": "#211C18"
|
||||
}
|
||||
},
|
||||
"templates": {
|
||||
"window.title": {
|
||||
"verticalAlignment": "center",
|
||||
"margin": [
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
"button": {
|
||||
"jsonTemplate": "default:button",
|
||||
"margin": [
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
"color": "#f4f3ee"
|
||||
},
|
||||
"checkbox": {
|
||||
"jsonTemplate": "default:checkbox",
|
||||
"margin": [
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
},
|
||||
"window": {
|
||||
"jsonTemplate": "default:window",
|
||||
"backgroundBrush": {
|
||||
"color": "#463f3a"
|
||||
},
|
||||
"color": "#f4f3ee",
|
||||
"font": {
|
||||
"face": "Segoe UI",
|
||||
"height": 16
|
||||
}
|
||||
},
|
||||
"listbox.contentContainerFitWidth": {
|
||||
"jsonTemplate": "listbox.contentContainer",
|
||||
"horizontalScroll": "fit"
|
||||
}
|
||||
}
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"type": "window",
|
||||
"skin": "MRSkin",
|
||||
"title": "MR Bot",
|
||||
"name": "mr.bot.miniwindow",
|
||||
"borderThickness": 2,
|
||||
"hideOnClose": false,
|
||||
"minSize": {
|
||||
"width": 100,
|
||||
"height": 50
|
||||
},
|
||||
"maxSize": {
|
||||
"width": 150,
|
||||
"height": 125
|
||||
},
|
||||
"eventHandlers": {
|
||||
"onCloseButtonClick": [
|
||||
"method",
|
||||
"BotController",
|
||||
"OnClose"
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"type": "stackpanel",
|
||||
"uniform": true,
|
||||
"heightFactor": 1,
|
||||
"children": [
|
||||
{
|
||||
"type": "button",
|
||||
"content": "${BotController.StartButtonText}",
|
||||
"horizontalAlignment": "stretch",
|
||||
"eventHandlers": {
|
||||
"onRelease": [
|
||||
"method",
|
||||
"BotController",
|
||||
"ToggleBot"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"content": "${BotController.SettingsButtonText}",
|
||||
"horizontalAlignment": "stretch",
|
||||
"eventHandlers": {
|
||||
"onRelease": [
|
||||
"method",
|
||||
"BotController",
|
||||
"ToggleSettings"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "window",
|
||||
"skin": "MRSkin",
|
||||
"title": "MR Bot Settings",
|
||||
"name": "mr.bot.settings",
|
||||
"borderThickness": 2,
|
||||
"hideOnClose": true,
|
||||
"visibility": "hidden",
|
||||
"minSize": {
|
||||
"width": 450,
|
||||
"height": 200
|
||||
},
|
||||
"maxSize": {
|
||||
"height": 600,
|
||||
"width": 800
|
||||
},
|
||||
"eventHandlers": {
|
||||
"onCloseButtonClick": [
|
||||
"method",
|
||||
"BotController",
|
||||
"OnCloseSettings"
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"type": "tabcontrol",
|
||||
"heightFactor": 1,
|
||||
"horizontalAlignment": "stretch",
|
||||
"verticalAlignment": "stretch",
|
||||
"tabs": [
|
||||
{
|
||||
"type": "tab",
|
||||
"header": "Cast Stack",
|
||||
"name": "mr.bot.settings.castStack",
|
||||
"content": {
|
||||
"jsonTemplate": "settings.castStack",
|
||||
"type": "stackpanel"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "tab",
|
||||
"header": "General",
|
||||
"content": {
|
||||
"type": "dockpanel",
|
||||
"_dock": "top",
|
||||
"padding": 2,
|
||||
"horizontalAlignment": "stretch",
|
||||
"children": [
|
||||
{
|
||||
"type": "textblock",
|
||||
"text": "General Settings",
|
||||
"horizontalAlignment": "center",
|
||||
"verticalAlignment": "center"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
29
scripts/bot_controller.iss
Normal file
29
scripts/bot_controller.iss
Normal file
@ -0,0 +1,29 @@
|
||||
objectdef MRBotController
|
||||
{
|
||||
variable string test = "just a test"
|
||||
method Initialize()
|
||||
{
|
||||
LGUI2:LoadPackageFile["${LavishScript.HomeDirectory}/scripts/mr/ui/bot_window.json"]
|
||||
}
|
||||
|
||||
method Shutdown()
|
||||
{
|
||||
LGUI2:UnloadPackageFile["${LavishScript.HomeDirectory}/scripts/mr/ui/bot_window.json"]
|
||||
}
|
||||
|
||||
method OnClose()
|
||||
{
|
||||
Event[MRBot_OnCloseButtonClicked]:Execute
|
||||
}
|
||||
}
|
||||
|
||||
variable(global) MRBotController BotController
|
||||
; variable(global) MRSettingsController SettingsController
|
||||
|
||||
function main()
|
||||
{
|
||||
while 1
|
||||
{
|
||||
wait 5
|
||||
}
|
||||
}
|
||||
25
scripts/cast_stack_controller.iss
Normal file
25
scripts/cast_stack_controller.iss
Normal file
@ -0,0 +1,25 @@
|
||||
objectdef MRCastStackController
|
||||
{
|
||||
method Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
method Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
method OnClose()
|
||||
{
|
||||
Event[OnCloseButtonClicked]:Execute
|
||||
}
|
||||
}
|
||||
|
||||
variable(global) MRCastStackController CastStackController
|
||||
|
||||
function main()
|
||||
{
|
||||
while 1
|
||||
{
|
||||
wait 5
|
||||
}
|
||||
}
|
||||
@ -3,15 +3,13 @@
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//#include <nlohmann/json.hpp>
|
||||
//#include <picojson/picojson.h>
|
||||
#include <json_struct/json_struct.h>
|
||||
|
||||
using namespace std;
|
||||
//using json = nlohmann::json;
|
||||
#include "ScopedEnumBitwiseOperators.h"
|
||||
|
||||
enum AbilityTypeFlags {
|
||||
using namespace std;
|
||||
|
||||
enum class AbilityTypeFlags {
|
||||
Debuff = 1,
|
||||
Buff = 2,
|
||||
AE = 4,
|
||||
@ -32,13 +30,16 @@ enum AbilityTypeFlags {
|
||||
Self = 131072,
|
||||
};
|
||||
|
||||
enum AbilityRequirementsFlags {
|
||||
enum class AbilityRequirementsFlags {
|
||||
NoEpic = 1,
|
||||
Flanking = 2,
|
||||
Stealth = 4,
|
||||
Ranged = 8,
|
||||
};
|
||||
|
||||
JS_ENUM_DECLARE_VALUE_PARSER(AbilityTypeFlags);
|
||||
JS_ENUM_DECLARE_VALUE_PARSER(AbilityRequirementsFlags);
|
||||
|
||||
struct ExportedAbility {
|
||||
unsigned long Id;
|
||||
string Name;
|
||||
@ -75,8 +76,8 @@ struct ExportedAbility {
|
||||
float MaxRange;
|
||||
unsigned int Damage;
|
||||
vector<string> Effects;
|
||||
unsigned long TypeFlags;
|
||||
unsigned short RequirementsFlags;
|
||||
AbilityTypeFlags TypeFlags;
|
||||
AbilityRequirementsFlags RequirementsFlags;
|
||||
|
||||
JS_OBJ(Id, Name, Description, Tier, Level, HealthCost, PowerCost, DissonanceCost, SavageryCost, ConcentrationCost,
|
||||
MainIconID, HOIconID, CastingTime, RecoveryTime, RecastTime, MaxDuration, NumClasses, NumEffects,
|
||||
|
||||
@ -4,35 +4,46 @@
|
||||
|
||||
#include "ISXMr.h"
|
||||
#include "Logger.h"
|
||||
#include "Commands/ExportCommand.h"
|
||||
#include "Tasks/BotTask.h"
|
||||
#include "Tasks/ExportAbilitiesTask.h"
|
||||
|
||||
enum CommandType {
|
||||
Export,
|
||||
Test,
|
||||
NotDefined
|
||||
};
|
||||
|
||||
CommandType GetCommandType(const std::string &command) {
|
||||
TaskTypeEnum GetTaskType(const std::string &command) {
|
||||
if (command == "export" || command == "e") {
|
||||
return CommandType::Export;
|
||||
} else if (command == "test" || command == "t") {
|
||||
return CommandType::Test;
|
||||
return TaskTypeEnum::Export;
|
||||
}
|
||||
return CommandType::NotDefined;
|
||||
if (command == "test" || command == "t") {
|
||||
return TaskTypeEnum::Test;
|
||||
}
|
||||
if (command == "bot" || command == "b") {
|
||||
return TaskTypeEnum::Bot;
|
||||
}
|
||||
return TaskTypeEnum::NotDefined;
|
||||
}
|
||||
|
||||
|
||||
int CMD_Mr(int argc, char *argv[]) {
|
||||
const argh::parser cmdl(argv);
|
||||
switch (const auto commandType = GetCommandType(cmdl[1])) {
|
||||
case CommandType::Export:
|
||||
executor.AddTask(std::make_shared<ExportCommand>());
|
||||
const auto taskType = GetTaskType(cmdl[1]);
|
||||
|
||||
if (executor.IsTaskTypeRunning(taskType)) {
|
||||
logw << "Task of type " << cmdl[1] << " is already running" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (taskType) {
|
||||
case TaskTypeEnum::Export:
|
||||
executor.AddTask(std::make_shared<ExportAbilitiesTask>());
|
||||
break;
|
||||
case CommandType::Test:
|
||||
case TaskTypeEnum::Bot:
|
||||
executor.AddTask(BotTask::Instance());
|
||||
break;
|
||||
case TaskTypeEnum::Test:
|
||||
log << LogLevel::Info << "Test command" << std::endl;
|
||||
break;
|
||||
default:
|
||||
logw << "USAGE: mr [e|export]: Export abilities" << std::endl;
|
||||
logw << "USAGE: mr [e|export]: Export abilities\n"
|
||||
<< " mr [b|bot]: Run the combat bot" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
#ifndef COMMANDEXECUTOR_H
|
||||
#define COMMANDEXECUTOR_H
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
#include "ExecutableCommand.h"
|
||||
|
||||
|
||||
class CommandExecutor {
|
||||
public:
|
||||
CommandExecutor(): stop(false) {
|
||||
}
|
||||
|
||||
void Shutdown();
|
||||
|
||||
void AddTask(std::shared_ptr<ExecutableCommand> command);
|
||||
|
||||
void RemoveFinishedTasks();
|
||||
|
||||
private:
|
||||
struct Task {
|
||||
std::shared_ptr<ExecutableCommand> command;
|
||||
std::future<void> future;
|
||||
};
|
||||
|
||||
std::vector<Task> tasks;
|
||||
mutable std::mutex queueMutex;
|
||||
std::atomic<bool> stop;
|
||||
};
|
||||
|
||||
|
||||
#endif //COMMANDEXECUTOR_H
|
||||
@ -1,36 +0,0 @@
|
||||
#ifndef BASECOMMAND_H
|
||||
#define BASECOMMAND_H
|
||||
|
||||
class ExecutableCommand {
|
||||
public:
|
||||
ExecutableCommand() : finished(false) {
|
||||
}
|
||||
|
||||
virtual ~ExecutableCommand() = default;
|
||||
|
||||
virtual void Execute() = 0;
|
||||
|
||||
void RequestStop() {
|
||||
stopRequested = true;
|
||||
}
|
||||
|
||||
bool IsStopRequested() const {
|
||||
return stopRequested;
|
||||
}
|
||||
|
||||
bool IsFinished() const {
|
||||
return finished;
|
||||
}
|
||||
|
||||
protected:
|
||||
void MarkFinished() {
|
||||
finished = true;
|
||||
}
|
||||
|
||||
bool stopRequested = false;
|
||||
|
||||
private:
|
||||
bool finished;
|
||||
};
|
||||
|
||||
#endif //BASECOMMAND_H
|
||||
@ -1,16 +0,0 @@
|
||||
//
|
||||
// Created by marob on 12/27/2023.
|
||||
//
|
||||
|
||||
#ifndef EXPORT_H
|
||||
#define EXPORT_H
|
||||
#include "ExecutableCommand.h"
|
||||
|
||||
|
||||
class ExportCommand final : public ExecutableCommand {
|
||||
public:
|
||||
void Execute() override;
|
||||
};
|
||||
|
||||
|
||||
#endif //EXPORT_H
|
||||
@ -22,7 +22,7 @@
|
||||
#include "isxeq2/Character.h"
|
||||
#include "../lgui2/test.json.h"
|
||||
#include "../scripts/bot.iss.h"
|
||||
#include "Commands/CommandExecutor.h"
|
||||
#include "Tasks/TaskExecutor.h"
|
||||
#pragma comment(lib,"isxdk.lib")
|
||||
// The mandatory pre-setup function. Our name is "ISXMr", and the class is ISXMr.
|
||||
// This sets up a "ModulePath" variable which contains the path to this module in case we want it,
|
||||
@ -85,23 +85,23 @@ bool ISXMr::Initialize(ISInterface *p_ISInterface) {
|
||||
* Most of the functionality in Initialize is completely optional and could be removed or
|
||||
* changed if so desired. The defaults are simply a suggestion that can be easily followed.
|
||||
*/
|
||||
constexpr size_t innerspacePathBufferLength = 255;
|
||||
char innerspacePathBuffer[innerspacePathBufferLength];
|
||||
const std::filesystem::path innerspacePath = p_ISInterface->GetInnerSpacePath(
|
||||
innerspacePathBuffer, innerspacePathBufferLength);
|
||||
std::filesystem::path fullPath = innerspacePath / R"(scripts\mr\ui\test.json)";
|
||||
|
||||
if (fullPath.has_parent_path() && !std::filesystem::exists(fullPath.parent_path())) {
|
||||
std::filesystem::create_directories(fullPath.parent_path());
|
||||
}
|
||||
|
||||
std::ofstream file(fullPath, std::ios::binary);
|
||||
if (!file) {
|
||||
std::cerr << "Error opening file for writing: " << fullPath << std::endl;
|
||||
}
|
||||
|
||||
file.write(reinterpret_cast<const char *>(test_json), test_json_len);
|
||||
file.close();
|
||||
// constexpr size_t innerspacePathBufferLength = 255;
|
||||
// char innerspacePathBuffer[innerspacePathBufferLength];
|
||||
// const std::filesystem::path innerspacePath = p_ISInterface->GetInnerSpacePath(
|
||||
// innerspacePathBuffer, innerspacePathBufferLength);
|
||||
// std::filesystem::path fullPath = innerspacePath / R"(scripts\mr\ui\test.json)";
|
||||
//
|
||||
// if (fullPath.has_parent_path() && !std::filesystem::exists(fullPath.parent_path())) {
|
||||
// std::filesystem::create_directories(fullPath.parent_path());
|
||||
// }
|
||||
//
|
||||
// std::ofstream file(fullPath, std::ios::binary);
|
||||
// if (!file) {
|
||||
// std::cerr << "Error opening file for writing: " << fullPath << std::endl;
|
||||
// }
|
||||
//
|
||||
// file.write(reinterpret_cast<const char *>(test_json), test_json_len);
|
||||
// file.close();
|
||||
|
||||
|
||||
//__try // exception handling. See __except below.
|
||||
@ -141,7 +141,7 @@ bool ISXMr::Initialize(ISInterface *p_ISInterface) {
|
||||
// Register any text triggers built into ISXMr
|
||||
RegisterTriggers();
|
||||
|
||||
pISInterface->RunScriptFromBuffer("mrbot", reinterpret_cast<const char *>(bot_iss), bot_iss_len);
|
||||
// pISInterface->RunScriptFromBuffer("mrbot", reinterpret_cast<const char *>(bot_iss), bot_iss_len);
|
||||
printf("ISXMr version %s Loaded", Mr_Version);
|
||||
return true;
|
||||
}
|
||||
@ -315,11 +315,11 @@ void __cdecl OnCloseButtonClicked(int argc, char *argv[], PLSOBJECT lsObj) {
|
||||
}
|
||||
|
||||
void ISXMr::RegisterEvents() {
|
||||
onGetTargetEventId = pISInterface->RegisterEvent("OnGetTarget");
|
||||
pISInterface->AttachEventTarget(onGetTargetEventId, OnGetTargetEvent);
|
||||
|
||||
onCloseButtonClickedEventId = pISInterface->RegisterEvent("OnCloseButtonClicked");
|
||||
pISInterface->AttachEventTarget(onCloseButtonClickedEventId, OnCloseButtonClicked);
|
||||
// onGetTargetEventId = pISInterface->RegisterEvent("OnGetTarget");
|
||||
// pISInterface->AttachEventTarget(onGetTargetEventId, OnGetTargetEvent);
|
||||
//
|
||||
// onCloseButtonClickedEventId = pISInterface->RegisterEvent("OnCloseButtonClicked");
|
||||
// pISInterface->AttachEventTarget(onCloseButtonClickedEventId, OnCloseButtonClicked);
|
||||
}
|
||||
|
||||
void ISXMr::DisconnectServices() {
|
||||
@ -382,14 +382,14 @@ void ISXMr::UnRegisterServices() {
|
||||
}
|
||||
|
||||
void ISXMr::UnRegisterEvents() {
|
||||
pISInterface->DetachEventTarget(onGetTargetEventId, OnGetTargetEvent);
|
||||
pISInterface->UnregisterEvent(onGetTargetEventId);
|
||||
|
||||
pISInterface->DetachEventTarget(onCloseButtonClickedEventId, OnCloseButtonClicked);
|
||||
pISInterface->UnregisterEvent(onCloseButtonClickedEventId);
|
||||
// pISInterface->DetachEventTarget(onGetTargetEventId, OnGetTargetEvent);
|
||||
// pISInterface->UnregisterEvent(onGetTargetEventId);
|
||||
//
|
||||
// pISInterface->DetachEventTarget(onCloseButtonClickedEventId, OnCloseButtonClicked);
|
||||
// pISInterface->UnregisterEvent(onCloseButtonClickedEventId);
|
||||
}
|
||||
|
||||
CommandExecutor executor;
|
||||
TaskExecutor executor;
|
||||
|
||||
std::chrono::milliseconds interval(100);;
|
||||
std::chrono::steady_clock::time_point nextCleanup = std::chrono::steady_clock::now() + interval;
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include <ISXDK.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "Commands/CommandExecutor.h"
|
||||
#include "Tasks/TaskExecutor.h"
|
||||
|
||||
|
||||
class ISXMr :
|
||||
@ -56,7 +56,7 @@ extern HISXSERVICE hHTTPService;
|
||||
extern HISXSERVICE hTriggerService;
|
||||
extern HISXSERVICE hSystemService;
|
||||
|
||||
extern CommandExecutor executor;;
|
||||
extern TaskExecutor executor;;
|
||||
|
||||
extern ISXMr *pExtension;
|
||||
#define printf pISInterface->Printf
|
||||
|
||||
@ -75,7 +75,7 @@ private:
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
const auto now_c = std::chrono::system_clock::to_time_t(now);
|
||||
|
||||
std::tm now_tm;
|
||||
std::tm now_tm = {};
|
||||
localtime_s(&now_tm, &now_c); // Thread-safe on Windows
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
59
src/ScopedEnumBitwiseOperators.h
Normal file
59
src/ScopedEnumBitwiseOperators.h
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
#ifndef SCOPEDENUMBITWISEOPERATORS_H
|
||||
#define SCOPEDENUMBITWISEOPERATORS_H
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
template<typename Enum>
|
||||
std::enable_if_t<std::is_enum_v<Enum>, Enum>
|
||||
operator^(Enum lhs, Enum rhs) {
|
||||
using underlying = std::underlying_type_t<Enum>;
|
||||
return static_cast<Enum>(static_cast<underlying>(lhs) ^ static_cast<underlying>(rhs));
|
||||
}
|
||||
|
||||
template<typename Enum>
|
||||
std::enable_if_t<std::is_enum_v<Enum>, Enum>
|
||||
operator|(Enum lhs, Enum rhs) {
|
||||
using underlying = std::underlying_type_t<Enum>;
|
||||
return static_cast<Enum>(static_cast<underlying>(lhs) | static_cast<underlying>(rhs));
|
||||
}
|
||||
|
||||
template<typename Enum>
|
||||
std::enable_if_t<std::is_enum_v<Enum>, Enum>
|
||||
operator&(Enum lhs, Enum rhs) {
|
||||
using underlying = std::underlying_type_t<Enum>;
|
||||
return static_cast<Enum>(static_cast<underlying>(lhs) & static_cast<underlying>(rhs));
|
||||
}
|
||||
|
||||
template<typename Enum>
|
||||
std::enable_if_t<std::is_enum_v<Enum>, Enum>
|
||||
operator~(Enum rhs) {
|
||||
using underlying = std::underlying_type_t<Enum>;
|
||||
return static_cast<Enum>(~static_cast<underlying>(rhs));
|
||||
}
|
||||
|
||||
template<typename Enum>
|
||||
std::enable_if_t<std::is_enum_v<Enum>, Enum>
|
||||
operator|=(Enum &lhs, Enum rhs) {
|
||||
using underlying = std::underlying_type_t<Enum>;
|
||||
lhs = static_cast<Enum>(static_cast<underlying>(lhs) | static_cast<underlying>(rhs));
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename Enum>
|
||||
std::enable_if_t<std::is_enum_v<Enum>, Enum>
|
||||
operator&=(Enum &lhs, Enum rhs) {
|
||||
using underlying = std::underlying_type_t<Enum>;
|
||||
lhs = static_cast<Enum>(static_cast<underlying>(lhs) & static_cast<underlying>(rhs));
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename Enum>
|
||||
std::enable_if_t<std::is_enum_v<Enum>, Enum>
|
||||
operator^=(Enum &lhs, Enum rhs) {
|
||||
using underlying = std::underlying_type_t<Enum>;
|
||||
lhs = static_cast<Enum>(static_cast<underlying>(lhs) ^ static_cast<underlying>(rhs));
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#endif //SCOPEDENUMBITWISEOPERATORS_H
|
||||
77
src/Tasks/BotTask.cpp
Normal file
77
src/Tasks/BotTask.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include "BotTask.h"
|
||||
#include "ISXMr.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include "../../lgui2/UpdateUIPackageFile.h"
|
||||
#include "../../lgui2/bot_window.json.h"
|
||||
#include "../../lgui2/bot_cast_stack.json.h"
|
||||
#include "../../scripts/bot_controller.iss.h"
|
||||
|
||||
|
||||
std::weak_ptr<BotTask> BotTask::instance;
|
||||
|
||||
std::shared_ptr<BotTask> BotTask::Instance() {
|
||||
auto existingInstance = instance.lock();
|
||||
if (!existingInstance) {
|
||||
existingInstance = std::shared_ptr<BotTask>(new BotTask());
|
||||
instance = existingInstance;
|
||||
}
|
||||
|
||||
return existingInstance;
|
||||
}
|
||||
|
||||
BotTask::BotTask() {
|
||||
UpdateUIPackageFile(
|
||||
"bot_window.json",
|
||||
reinterpret_cast<const char *>(bot_window_json),
|
||||
bot_window_json_len,
|
||||
bot_window_json_last_modified
|
||||
);
|
||||
|
||||
UpdateUIPackageFile(
|
||||
"bot_cast_stack.json",
|
||||
reinterpret_cast<const char *>(bot_cast_stack_json),
|
||||
bot_cast_stack_json_len,
|
||||
bot_cast_stack_json_last_modified
|
||||
);
|
||||
|
||||
pISInterface->RunScriptFromBuffer(
|
||||
ScriptName.c_str(),
|
||||
reinterpret_cast<const char *>(bot_controller_iss),
|
||||
bot_controller_iss_len
|
||||
);
|
||||
|
||||
botController = make_shared<LSObject>(LSObject::FromDataParse("${BotController}"));
|
||||
this->onCloseButtonClickedEventId = pISInterface->RegisterEvent(OnClosedEventName.c_str());
|
||||
pISInterface->AttachEventTarget(this->onCloseButtonClickedEventId,
|
||||
&BotTask::OnCloseEventHandler);
|
||||
}
|
||||
|
||||
void __cdecl BotTask::OnCloseEventHandler(int argc, char *argv[], PLSOBJECT plsObject) {
|
||||
Instance()->Close();
|
||||
}
|
||||
|
||||
|
||||
BotTask::~BotTask() {
|
||||
const std::string bufferScriptName = "Buffer:" + ScriptName;
|
||||
pISInterface->EndScript(bufferScriptName.c_str());
|
||||
pISInterface->DetachEventTarget(this->onCloseButtonClickedEventId, &BotTask::OnCloseEventHandler);
|
||||
pISInterface->UnregisterEvent(this->onCloseButtonClickedEventId);
|
||||
}
|
||||
|
||||
void BotTask::Execute() {
|
||||
while (!this->stopRequested && !this->IsFinished()) {
|
||||
// sleep for 100 ms
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
|
||||
void BotTask::Close() {
|
||||
this->MarkFinished();
|
||||
}
|
||||
|
||||
TaskTypeEnum BotTask::TaskType() const {
|
||||
return TaskTypeEnum::Bot;
|
||||
}
|
||||
37
src/Tasks/BotTask.h
Normal file
37
src/Tasks/BotTask.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef BOTTASK_H
|
||||
#define BOTTASK_H
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "ExecutableTask.h"
|
||||
#include "isxeq2/LSObject.h"
|
||||
|
||||
class BotTask final : public ExecutableTask, public std::enable_shared_from_this<BotTask> {
|
||||
public:
|
||||
static std::shared_ptr<BotTask> Instance();
|
||||
|
||||
~BotTask() override;
|
||||
|
||||
void Execute() override;
|
||||
|
||||
void Close();
|
||||
|
||||
[[nodiscard]] TaskTypeEnum TaskType() const override;
|
||||
|
||||
private:
|
||||
BotTask();
|
||||
|
||||
static std::weak_ptr<BotTask> instance;
|
||||
|
||||
const std::string ScriptName = "MRBot";
|
||||
const std::string OnClosedEventName = "MRBot_OnCloseButtonClicked";
|
||||
|
||||
std::shared_ptr<LSObject> botController;
|
||||
std::shared_ptr<LSObject> settingsController;
|
||||
|
||||
u_int onCloseButtonClickedEventId = 0;
|
||||
|
||||
static void __cdecl OnCloseEventHandler(int argc, char *argv[], PLSOBJECT plsObject);
|
||||
};
|
||||
|
||||
#endif //BOTTASK_H
|
||||
46
src/Tasks/ExecutableTask.h
Normal file
46
src/Tasks/ExecutableTask.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef BASETASK_H
|
||||
#define BASETASK_H
|
||||
|
||||
enum class TaskTypeEnum {
|
||||
Export,
|
||||
Bot,
|
||||
Test,
|
||||
NotDefined
|
||||
};
|
||||
|
||||
class ExecutableTask {
|
||||
public:
|
||||
ExecutableTask() : finished(false) {
|
||||
}
|
||||
|
||||
virtual ~ExecutableTask() = default;
|
||||
|
||||
virtual void Execute() = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual TaskTypeEnum TaskType() const = 0;
|
||||
|
||||
void RequestStop() {
|
||||
stopRequested = true;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsStopRequested() const {
|
||||
return stopRequested;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsFinished() const {
|
||||
return finished;
|
||||
}
|
||||
|
||||
protected:
|
||||
void MarkFinished() {
|
||||
finished = true;
|
||||
}
|
||||
|
||||
bool stopRequested = false;
|
||||
|
||||
private:
|
||||
bool finished;
|
||||
};
|
||||
|
||||
#endif //BASETASK_H
|
||||
@ -5,7 +5,7 @@
|
||||
#include<json_struct/json_struct.h>
|
||||
|
||||
#include "ISXMr.h"
|
||||
#include "ExportCommand.h"
|
||||
#include "ExportAbilitiesTask.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
@ -23,7 +23,7 @@ AbilityInfo GetAbilityInfo(const int idx) {
|
||||
return ability.GetAbilityInfo();
|
||||
}
|
||||
|
||||
void ExportCommand::Execute() {
|
||||
void ExportAbilitiesTask::Execute() {
|
||||
try {
|
||||
log << "Exporting abilities" << endl;
|
||||
const auto numAbilities = ExtensionTLOs::Me().NumAbilities();
|
||||
15
src/Tasks/ExportAbilitiesTask.h
Normal file
15
src/Tasks/ExportAbilitiesTask.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef EXPORTABILITIESTASK_H
|
||||
#define EXPORTABILITIESTASK_H
|
||||
#include "ExecutableTask.h"
|
||||
|
||||
class ExportAbilitiesTask final : public ExecutableTask {
|
||||
public:
|
||||
void Execute() override;
|
||||
|
||||
[[nodiscard]] TaskTypeEnum TaskType() const override {
|
||||
return TaskTypeEnum::Export;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif //EXPORTABILITIESTASK_H
|
||||
@ -1,9 +1,9 @@
|
||||
#include "CommandExecutor.h"
|
||||
#include "TaskExecutor.h"
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
|
||||
void CommandExecutor::Shutdown() {
|
||||
void TaskExecutor::Shutdown() {
|
||||
stop = true;
|
||||
for (auto &[command, future]: tasks) {
|
||||
if (future.valid()) {
|
||||
@ -22,7 +22,7 @@ void CommandExecutor::Shutdown() {
|
||||
}
|
||||
|
||||
|
||||
void CommandExecutor::AddTask(std::shared_ptr<ExecutableCommand> command) {
|
||||
void TaskExecutor::AddTask(std::shared_ptr<ExecutableTask> command) {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
std::future<void> future = std::async(std::launch::async, [command]() {
|
||||
try {
|
||||
@ -34,7 +34,15 @@ void CommandExecutor::AddTask(std::shared_ptr<ExecutableCommand> command) {
|
||||
tasks.push_back({command, std::move(future)});
|
||||
}
|
||||
|
||||
void CommandExecutor::RemoveFinishedTasks() {
|
||||
bool TaskExecutor::IsTaskTypeRunning(TaskTypeEnum taskType) const {
|
||||
std::lock_guard lock(queueMutex);
|
||||
return std::ranges::any_of(tasks, [taskType](const Task &task) {
|
||||
return task.task->TaskType() == taskType;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void TaskExecutor::RemoveFinishedTasks() {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
std::erase_if(tasks, [](Task &task) {
|
||||
if (task.future.valid() && task.future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
|
||||
42
src/Tasks/TaskExecutor.h
Normal file
42
src/Tasks/TaskExecutor.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef TASKEXECUTOR_H
|
||||
#define TASKEXECUTOR_H
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
#include "ExecutableTask.h"
|
||||
|
||||
enum TaskType {
|
||||
Export,
|
||||
Bot,
|
||||
Test,
|
||||
NotDefined
|
||||
};
|
||||
|
||||
class TaskExecutor {
|
||||
public:
|
||||
TaskExecutor(): stop(false) {
|
||||
}
|
||||
|
||||
void Shutdown();
|
||||
|
||||
void AddTask(std::shared_ptr<ExecutableTask> command);
|
||||
|
||||
bool IsTaskTypeRunning(TaskTypeEnum taskType) const;
|
||||
|
||||
void RemoveFinishedTasks();
|
||||
|
||||
private:
|
||||
struct Task {
|
||||
std::shared_ptr<ExecutableTask> task;
|
||||
std::future<void> future;
|
||||
};
|
||||
|
||||
std::vector<Task> tasks;
|
||||
mutable std::mutex queueMutex;
|
||||
std::atomic<bool> stop;
|
||||
};
|
||||
|
||||
|
||||
#endif //TASKEXECUTOR_H
|
||||
@ -1,37 +0,0 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
std::chrono::system_clock::time_point ParseEmbeddedTimestamp(const std::string& timestamp) {
|
||||
std::tm tm = {};
|
||||
std::istringstream ss(timestamp);
|
||||
ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
|
||||
return std::chrono::system_clock::from_time_t(std::mktime(&tm));
|
||||
}
|
||||
|
||||
void WriteUIFileToDiskIfChanged(
|
||||
const std::string& filePath,
|
||||
const unsigned char* data,
|
||||
const size_t length,
|
||||
const std::string& lastModified) {
|
||||
|
||||
auto embeddedTimestamp = ParseEmbeddedTimestamp(lastModified);
|
||||
|
||||
if (std::filesystem::exists(filePath)) {
|
||||
const auto lastWriteTime = std::filesystem::last_write_time(filePath);
|
||||
|
||||
// Convert file_time_type to system_clock::time_point
|
||||
const auto lastWriteTimeTp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
|
||||
lastWriteTime - std::filesystem::file_time_type::clock::now() + std::chrono::system_clock::now()
|
||||
);
|
||||
|
||||
if (lastWriteTimeTp < embeddedTimestamp) {
|
||||
std::ofstream file(filePath, std::ios::binary);
|
||||
file.write(reinterpret_cast<const char*>(data), length);
|
||||
}
|
||||
} else {
|
||||
std::ofstream file(filePath, std::ios::binary);
|
||||
file.write(reinterpret_cast<const char*>(data), length);
|
||||
}
|
||||
}
|
||||
@ -76,23 +76,23 @@ ExportedAbility Ability::ToExportedAbility() const {
|
||||
}
|
||||
|
||||
if (RequiresStealth(exportedAbility.Effects)) {
|
||||
exportedAbility.RequirementsFlags |= Stealth;
|
||||
exportedAbility.RequirementsFlags |= AbilityRequirementsFlags::Stealth;
|
||||
}
|
||||
|
||||
if (RequiresFlanking(exportedAbility.Effects)) {
|
||||
exportedAbility.RequirementsFlags |= Flanking;
|
||||
exportedAbility.RequirementsFlags |= AbilityRequirementsFlags::Flanking;
|
||||
}
|
||||
|
||||
if (RequiresNonEpic(exportedAbility.Effects)) {
|
||||
exportedAbility.RequirementsFlags |= NoEpic;
|
||||
exportedAbility.RequirementsFlags |= AbilityRequirementsFlags::NoEpic;
|
||||
}
|
||||
|
||||
if (IsStun(exportedAbility.Effects)) {
|
||||
exportedAbility.TypeFlags |= Stun;
|
||||
exportedAbility.TypeFlags |= AbilityTypeFlags::Stun;
|
||||
}
|
||||
|
||||
if (IsInterrupt(exportedAbility.Effects)) {
|
||||
exportedAbility.TypeFlags |= Interrupt;
|
||||
exportedAbility.TypeFlags |= AbilityTypeFlags::Interrupt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ public:
|
||||
// Use a fold expression to convert each argument to a string
|
||||
const std::vector<std::string> arguments = {toString(args)...};
|
||||
|
||||
const int argc = arguments.size();
|
||||
const size_t argc = arguments.size();
|
||||
std::vector<char *> argv;
|
||||
|
||||
for (auto &arg: arguments) {
|
||||
@ -49,7 +49,7 @@ public:
|
||||
if (const auto result = this->lsObject->Type->GetMemberEx(
|
||||
this->lsObject->GetObjectData(),
|
||||
const_cast<char *>(memberName.c_str()),
|
||||
argc,
|
||||
static_cast<int>(argc),
|
||||
argv.data(),
|
||||
response
|
||||
); !result) {
|
||||
@ -75,7 +75,7 @@ public:
|
||||
// Use a fold expression to convert each argument to a string
|
||||
const std::vector<std::string> arguments = {toString(args)...};
|
||||
|
||||
const int argc = arguments.size();
|
||||
const size_t argc = arguments.size();
|
||||
std::vector<char *> argv;
|
||||
|
||||
for (auto &arg: arguments) {
|
||||
@ -85,14 +85,22 @@ public:
|
||||
this->lsObject->Type->GetMethodEx(
|
||||
this->lsObject->GetObjectData(),
|
||||
const_cast<char *>(methodName.c_str()),
|
||||
argc,
|
||||
static_cast<int>(argc),
|
||||
argv.data());
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
[[nodiscard]] bool IsValid() const {
|
||||
return this->lsObject.has_value();
|
||||
}
|
||||
|
||||
static LSObject FromDataParse(const std::string &dataToParse) {
|
||||
if (LSOBJECT rawObject; pISInterface->DataParse(dataToParse.c_str(), rawObject)) {
|
||||
return LSObject(rawObject);
|
||||
}
|
||||
|
||||
return LSObject(nullopt);
|
||||
}
|
||||
|
||||
private:
|
||||
optional<LSOBJECT> lsObject;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user