First Release Version. Version 1.1
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
aa1c31fffd
commit
33960f8ed9
@ -3,12 +3,12 @@ steps:
|
|||||||
image: git.vertinext.com/roryejinn/alpine_muddler
|
image: git.vertinext.com/roryejinn/alpine_muddler
|
||||||
when:
|
when:
|
||||||
- path:
|
- path:
|
||||||
include: [ 'Fighter/*' ]
|
include: [ 'src/*' ]
|
||||||
event: [push, pull_request]
|
event: [push, pull_request]
|
||||||
environment:
|
environment:
|
||||||
GITEATKN:
|
GITEATKN:
|
||||||
from_secret: GITEA_TOKEN
|
from_secret: GITEA_TOKEN
|
||||||
VERSION: 1.0.5
|
VERSION: 1.1
|
||||||
commands:
|
commands:
|
||||||
- apk add tea
|
- apk add tea
|
||||||
- java -jar /muddle/muddle.jar
|
- java -jar /muddle/muddle.jar
|
||||||
|
14
README.md
14
README.md
@ -3,26 +3,28 @@ Fighter is a simple, alias based PVP system for Achaea. The Fighter Engine is of
|
|||||||
|
|
||||||
## Fighter Engine
|
## Fighter Engine
|
||||||
### Base Components
|
### Base Components
|
||||||
The Fighter Engine consists of all code in the aliases folder (automatFight, callAction) and the primary engine script (fighter.lua) under scripts. These components have no other plugin requirements. They only require Mudlet OR that gmcp data is exposed via a variable named gmcp. Even then, that sole requirement only comes up under the callAction script and is easy to remove if unwanted.
|
The Fighter Engine consists of all code in the aliases folder (callAction) and the primary engine script (fighter.lua) under scripts. These components have no other plugin requirements. They only require Mudlet OR that gmcp data is exposed via a variable named gmcp. Even then, that sole requirement only comes up under the callAction script and is easy to remove if unwanted.
|
||||||
|
|
||||||
### Example PVP Scripts
|
### Example PVP Scripts
|
||||||
alchemist.lua and psion.lua are two example PVP scripts that demonstrate how to create a PVP decision engine that works with the Fighter Engine. These two example scripts are available for Legacy and Orion depending on which curing system you use. Additionally, this implementation relies on AK 8.5 and Romaen's Limb Tracker 1.3. Other versions of Romaen's Limb Tracker will probably work as long as they don't change how limb damage is accessed (IE: limbs[target].hits[limb]). AK on the other hand is a large, varied script and I can't guarantee any compatibility with other versions.
|
alchemist.lua and psion.lua are two example PVP scripts that demonstrate how to create a PVP decision engine that works with the Fighter Engine. These two example scripts are available for Legacy and Orion depending on which curing system you use. Additionally, this implementation relies on AK 8.5 and Romaen's Limb Tracker 1.3. Other versions of Romaen's Limb Tracker will probably work as long as they don't change how limb damage is accessed (IE: limbs[target].hits[limb]). AK on the other hand is a large, varied script and I can't guarantee any compatibility with other versions.
|
||||||
|
|
||||||
Additionally, each script demonstrates different use cases and implementations. Psion relies heavily on limb damage and shows how you might change your actions based on that. On the other hand, the alchemist example demonstrates how one might handle multiple balance timers.
|
Additionally, each script demonstrates different use cases and implementations. Psion relies heavily on limb damage and shows how you might change your actions based on that. On the other hand, the alchemist example demonstrates how one might handle multiple balance timers.
|
||||||
|
|
||||||
|
#### Getting The Requirements
|
||||||
|
* AK 8.5: https://github.com/AranosBanazir/Legacy/blob/main/AK.xml
|
||||||
|
* Romaen's Limb Tracker: https://github.com/27theo/limb/releases/tag/v1.3
|
||||||
|
|
||||||
## Creating Your Own Class Engines
|
## Creating Your Own Class Engines
|
||||||
While I've included an example alchemist and psion class engine, you might not have the same priorities as me. You might also want to add other classes. It is easy to do so.
|
While I've included an example alchemist and psion class engine, you might not have the same priorities as me. You might also want to add other classes. It is easy to do so.
|
||||||
|
|
||||||
### Step 1 - Write Your Class Engine
|
### Step 1 - Write Your Class Engine
|
||||||
Create a new script with a name that helps you identify it. In that script, you will write your entire Class Engine. This file is responsible for deciding what actions to take, managing affliction reporting, sending the commands to the game, storing and managing data specific to the classes implementation, and managing any created temporary objects such as timers, triggers or aliases. Your Class Engine has to follow four rules but can otherwise be written however you want.
|
Create a new script with a name that helps you identify it. In that script, you will write your entire Class Engine. This file is responsible for deciding what actions to take, managing affliction reporting, sending the commands to the game, storing and managing data specific to the classes implementation, and managing any created temporary objects such as timers, triggers or aliases. Your Class Engine has to follow three rules but can otherwise be written however you want.
|
||||||
|
|
||||||
1) You must have a decideAction() function. decideAction() is the primary function called by the Fighter Engine to generate a pvp command string.
|
1) You must have a decideAction() function. decideAction() is the primary function called by the Fighter Engine to generate a pvp command string.
|
||||||
|
|
||||||
2) You must have an isReady() function. isReady() is responsible for making automation work. The isReady function should determine when a new action should be taken and then kill the temporary event handler spawned by decideAction and recall decideAction to generate a new command.
|
2) When designing your Class Engine, enclose everything in a single table which will act like a class. You can see an example of this in both example scripts where functions are held within a table. This makes it easier for Fighter to manipulate the implementations and call the Class Engines.
|
||||||
|
|
||||||
3) When designing your Class Engine, enclose everything in a single table which will act like a class. You can see an example of this in both example scripts where functions are held within a table. This makes it easier for Fighter to manipulate the implementations and call the Class Engines.
|
3) Every Class Engine should be written in such a way that when fighter.Setup() is called it is able to rebuild itself. fighter.Setup() is designed as a basic hot reload function and will recreate Fighter and all sub-components each time. This allows you to force Mudlet to update any changes you make to the Fighter Engine or Class Engines.
|
||||||
|
|
||||||
4) Every Class Engine should be written in such a way that when fighter.Setup() is called it is able to rebuild itself. fighter.Setup() is designed as a basic hot reload function and will recreate Fighter and all sub-components each time. This allows you to force Mudlet to update any changes you make to the Fighter Engine or Class Engines.
|
|
||||||
|
|
||||||
### Step 2 - Add it to fighter.lua
|
### Step 2 - Add it to fighter.lua
|
||||||
Open up fighter.lua and at the top you'll see two tables that we need to modify slightly for your new Class Engine to work.
|
Open up fighter.lua and at the top you'll see two tables that we need to modify slightly for your new Class Engine to work.
|
||||||
|
2
mfile
2
mfile
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"package": "Fighter",
|
"package": "Fighter",
|
||||||
"description": "A simple, modular, alias based pvp engine written in Lua for Achaea.",
|
"description": "A simple, modular, alias based pvp engine written in Lua for Achaea.",
|
||||||
"version": "1.0.5"
|
"version": "1.1"
|
||||||
}
|
}
|
@ -5,8 +5,8 @@
|
|||||||
"regex": "^fight$"
|
"regex": "^fight$"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "automateFight",
|
"name": "showHelp",
|
||||||
"isActive": "yes",
|
"isActive": "yes",
|
||||||
"regex": "^autofight$"
|
"regex": "^fighthelp$"
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -1,7 +0,0 @@
|
|||||||
if fighter.automate then
|
|
||||||
cecho("\n<firebrick>COMBAT NOTICE: Will no longer automate sending the next pvp command. Please use the pvp alias when you want to send a command string.")
|
|
||||||
fighter.automate = false
|
|
||||||
else
|
|
||||||
cecho("\n<firebrick>COMBAT NOTICE: Will automate sending the next pvp command.")
|
|
||||||
fighter.automate = true
|
|
||||||
end
|
|
1
src/aliases/showHelp.lua
Normal file
1
src/aliases/showHelp.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
fighter.generateHelp()
|
48
src/resources/MDK/LICENSE.lua
Normal file
48
src/resources/MDK/LICENSE.lua
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
--[===[
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2020 Damian Monogue
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
--]===]
|
||||||
|
|
||||||
|
-- schema validation provided by schema.lua, license below
|
||||||
|
--[[
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Sebastian Schoener
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
]]
|
91
src/resources/MDK/README.md
Normal file
91
src/resources/MDK/README.md
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# the demonnic MDK and You
|
||||||
|
|
||||||
|
This is a collection of Lua 'classes' and modules I wrote for Mudlet. It is largely targeted at scripters, and comes packaged in two ways depending on how you intend to use/distribute your work. Please see [Installation](#installation) for more details
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
The [MDK wiki](https://github.com/demonnic/MDK/wiki) contains an entry for each module or class, as well as examples.
|
||||||
|
|
||||||
|
Starting with alpha2 of the MDK, the ldocs generated from code are included in the zipped releases. The current release's ldocs can always be viewed at <https://demonnic.github.io/mdk/current/>
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
How you 'install' the MDK depends on how you intend to use it.
|
||||||
|
|
||||||
|
### I just want to install the MDK for my own personal use
|
||||||
|
|
||||||
|
You just want to get your hands on the goods, and aren't looking to use any MDK items in an exported package for sharing or anything like that.
|
||||||
|
Well, you are who the mdk mpackage is for! Download the MDK.mpackage from your desired release on the [Releases](https://github.com/demonnic/MDK/releases) page and install it in the package manager. The examples in the [wiki](https://demonnic.github.io/mdk/current/) are written with this in mind, and you would require the items you need as `local EMCO = require("MDK.emco")`
|
||||||
|
|
||||||
|
### I am a package author looking to include/use one of the MDK modules or classes in my package
|
||||||
|
|
||||||
|
You should download the `demonnic-MDK-<version>.zip` file for your desired release on the [Releases](https://github.com/demonnic/MDK/releases) page.
|
||||||
|
Inside are the individual .lua files for the modules and classes described in the [wiki](https://demonnic.github.io/mdk/current/) and [API docs](https://demonnic.github.io/mdk/current/).
|
||||||
|
You can include all of them if you wish, or only the ones you actually make use of. I ask that you include the LICENSE.lua or LICENSE-MDK.lua file (depending on the release) file in addition.
|
||||||
|
They should go in the root of your package, so that when your package is installed the files can be found at `getMudletHomeDir() .. "/<packagename>/emco.lua"`. You would then use `local EMCO = require("<mypackagename>.emco")`
|
||||||
|
So for example if your package name is "MySuperCoolPackage" and it installs to `getMudletHomeDir() .. "/MySuperCoolPackage/"` then you use `local EMCO = require("MySuperCoolPackage.emco")` and the emco.lua file should be at `getMudletHomeDir() .. "/MySuperCoolPackage/emco.lua"`
|
||||||
|
|
||||||
|
## Files (Modules/Classes)
|
||||||
|
|
||||||
|
These files contain the modules in the MDK. You only need to include those files which you intend to use, except as noted in the descriptions below.
|
||||||
|
If you include any of the modules from the MDK, you should also include LICENSE.lua or LICENSE-MDK.lua. It contains the licenses for my modules and for luaunit and lua-schema which are not my original works.
|
||||||
|
You should maybe also include demontools.lua, as it notes below several other of the MDK modules make use of items within it.
|
||||||
|
|
||||||
|
* aliasmgr.ua
|
||||||
|
* Object to manage tempAliases programmatically. <https://github.com/demonnic/MDK/wiki/AliasMgr>
|
||||||
|
|
||||||
|
* chyron.lua
|
||||||
|
* Label which moves a message across its face from right to left, like a stock ticker or the news chyrons. Documentation at <https://github.com/demonnic/MDK/wiki/Chyron>
|
||||||
|
|
||||||
|
* demontools.lua
|
||||||
|
* Collection of miscellaneous useful functions. You should include this file if you use the MDK, as several other modules make use of it. Include functions for converting c/d/hecho, html, and ansi colored strings between each other, mkdir_p, and some others. <https://github.com/demonnic/MDK/wiki/DemonTools>
|
||||||
|
|
||||||
|
* emco.lua
|
||||||
|
* EMCO. Documentation at <https://github.com/demonnic/MDK/wiki/EMCO> Will make use of LoggingConsole if loggingconsole.lua and demontools.lua are included
|
||||||
|
|
||||||
|
* figlet.lua
|
||||||
|
* Creates FIGlets from strings
|
||||||
|
* Reference package with multiple fonts and color gradients at <https://github.com/demonnic/figinator>
|
||||||
|
|
||||||
|
* ftext.lua
|
||||||
|
* basic fText. Documentation at <https://github.com/demonnic/MDK/wiki/fText>
|
||||||
|
* now includes TextFormatter and TableMaker as ftext.TextFormatter and ftext.TableMaker
|
||||||
|
|
||||||
|
* gradientmaker.lua
|
||||||
|
* Functions for creating color gradients for use with c/d/hecho. Documentation at <https://github.com/demonnic/MDK/wiki/GradientMaker>
|
||||||
|
|
||||||
|
* loggingconsole.lua
|
||||||
|
* Self logging extension to the mini console. Works just like a Geyser.MiniConsole but adds a templated path and fileName constraint, as well as logFormat so it can log what is echod or appended to it. Requires demontools.lua in order to work.
|
||||||
|
|
||||||
|
* loginator.lua
|
||||||
|
* Creates objects for logging messages to disk. <https://github.com/demonnic/MDK/wiki/Loginator>
|
||||||
|
|
||||||
|
* mastermindsolver.lua
|
||||||
|
* A class which will help you solve Master Mind puzzles. <https://github.com/demonnic/MDK/wiki/MasterMindSolver>
|
||||||
|
|
||||||
|
* revisionator.lua
|
||||||
|
* A class which aims to make upgrading between package versions easier by storing and running patch functions. <https://github.com/demonnic/MDK/wiki/Revisionator>
|
||||||
|
|
||||||
|
* sortbox.lua
|
||||||
|
* SortBox, an alternative to H/VBox which can be either, and also provides options for sorting its contents. Overview at <https://github.com/demonnic/MDK/wiki/SortBox>
|
||||||
|
|
||||||
|
* spinbox.lua
|
||||||
|
* SpinBox, a Geyser element for adjusting numbers with your mouse. Overview at <https://github.com/demonnic/MDK/wiki/SpinBox>
|
||||||
|
|
||||||
|
* sug.lua
|
||||||
|
* Self Updating Gauges, will watch a set of variables and update itself on a timer based on what values those variables hold. Documentation at <https://github.com/demonnic/MDK/wiki/SelfUpdatingGauge>
|
||||||
|
|
||||||
|
* textgauge.lua
|
||||||
|
* TextGauges, what it says on the tin. Documentation at <https://github.com/demonnic/MDK/wiki/TextGauge>
|
||||||
|
|
||||||
|
* timergauge.lua
|
||||||
|
* TimerGauge, an extension of Geyser.Gauge which serves as an animated countdown timer. Overview at <https://github.com/demonnic/MDK/wiki/TimerGauge>
|
||||||
|
|
||||||
|
## Others people's work I depend upon
|
||||||
|
|
||||||
|
* schema.lua
|
||||||
|
* lua-schema, for defining table schema. Documentation at <https://github.com/sschoener/lua-schema>
|
||||||
|
* will be used by Archon for ensuring configuration tables are as they should be.
|
||||||
|
|
||||||
|
* LICENSE.lua
|
||||||
|
* Contains the license information for MDK, as well as lua-schema and luaunit which have been included.
|
1697
src/resources/MDK/ftext.lua
Normal file
1697
src/resources/MDK/ftext.lua
Normal file
File diff suppressed because it is too large
Load Diff
447
src/resources/MDK/ftext_spec.lua
Normal file
447
src/resources/MDK/ftext_spec.lua
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
local ftext = require("MDK.ftext")
|
||||||
|
|
||||||
|
describe("ftext:", function()
|
||||||
|
describe("ftext.fText:", function()
|
||||||
|
local fText = ftext.fText
|
||||||
|
|
||||||
|
it("Should properly center text", function()
|
||||||
|
local expected = " some text "
|
||||||
|
local actual = fText("some text", {width = 20})
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(20, actual:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should properly pad left aligned text", function()
|
||||||
|
local expected = "some text "
|
||||||
|
local actual = fText("some text", {width = 20, alignment = "left"})
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(20, actual:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should properly pad right aligned text", function()
|
||||||
|
local expected = " some text"
|
||||||
|
local actual = fText("some text", {width = 20, alignment = "right"})
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(20, actual:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should wrap lines to the correct length", function()
|
||||||
|
local str = "This is a test of the emergency broadcast system. This is only a test"
|
||||||
|
local options = {width = 10, alignment = "centered"}
|
||||||
|
local actual = fText(str, options)
|
||||||
|
for _, line in ipairs(actual:split("\n")) do
|
||||||
|
assert.equals(line:len(), 10)
|
||||||
|
end
|
||||||
|
options.width = 15
|
||||||
|
actual = fText(str, options)
|
||||||
|
for _, line in ipairs(actual:split("\n")) do
|
||||||
|
assert.equals(line:len(), 15)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("non-space spacer character:", function()
|
||||||
|
local str = "some text"
|
||||||
|
local options = {width = "20", alignment = "left", spacer = "="}
|
||||||
|
it("Should work with left align", function()
|
||||||
|
local expected = "some text =========="
|
||||||
|
local actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(20, actual:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should work with right align", function()
|
||||||
|
local expected = "========== some text"
|
||||||
|
options.alignment = "right"
|
||||||
|
local actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(20, actual:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should work with center align", function()
|
||||||
|
local expected = ("==== some text =====")
|
||||||
|
options.alignment = "center"
|
||||||
|
local actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(20, actual:len())
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("nogap option:", function()
|
||||||
|
local str = "some text"
|
||||||
|
local options = {width = "20", alignment = "left", spacer = "=", nogap = true}
|
||||||
|
|
||||||
|
it("Should work with left align", function()
|
||||||
|
local expected = "some text==========="
|
||||||
|
local actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(20, actual:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should work with right align", function()
|
||||||
|
local expected = "===========some text"
|
||||||
|
options.alignment = "right"
|
||||||
|
local actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(20, actual:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should work with center align", function()
|
||||||
|
local expected = "=====some text======"
|
||||||
|
options.alignment = "center"
|
||||||
|
local actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(20, actual:len())
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("cap functionality", function()
|
||||||
|
local str = "some text"
|
||||||
|
local options = {width = 20, spacer = "=", cap = "|"}
|
||||||
|
|
||||||
|
it("Should place the spacer outside the cap by default", function()
|
||||||
|
local expected = "===| some text |===="
|
||||||
|
local actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(20, actual:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should place it inside the cap if inside option is true", function()
|
||||||
|
local expected = "|=== some text ====|"
|
||||||
|
options.inside = true
|
||||||
|
local actual = fText(str, options)
|
||||||
|
options.inside = nil
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(20, actual:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should mirror certain characters with their opposites", function()
|
||||||
|
local expected = "===[ some text ]===="
|
||||||
|
options.mirror = true
|
||||||
|
options.cap = "["
|
||||||
|
local actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
options.inside = true
|
||||||
|
expected = "[=== some text ====]"
|
||||||
|
actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
options.inside = nil
|
||||||
|
options.cap = "<"
|
||||||
|
expected = "===< some text >===="
|
||||||
|
actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
options.cap = "{"
|
||||||
|
expected = "==={ some text }===="
|
||||||
|
actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
options.cap = "("
|
||||||
|
expected = "===( some text )===="
|
||||||
|
actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
options.cap = "|"
|
||||||
|
expected = "===| some text |===="
|
||||||
|
actual = fText(str, options)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("ftext.cfText", function()
|
||||||
|
local cfText = ftext.cfText
|
||||||
|
local str = "some text"
|
||||||
|
local options = {
|
||||||
|
width = 20,
|
||||||
|
spacer = "=",
|
||||||
|
cap = "[",
|
||||||
|
inside = true,
|
||||||
|
mirror = true,
|
||||||
|
capColor = "<purple>",
|
||||||
|
spacerColor = "<green>",
|
||||||
|
textColor = "<red>",
|
||||||
|
}
|
||||||
|
it("Should handle cecho colored text", function()
|
||||||
|
local expectedStripped = "[=== some text ====]"
|
||||||
|
local expected = "<purple>[<reset><green>===<reset><red> some text <reset><green>====<reset><purple>]<reset>"
|
||||||
|
local actual = cfText(str, options)
|
||||||
|
local actualStripped = cecho2string(actual)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(expectedStripped, actualStripped)
|
||||||
|
assert.equals(20, actualStripped:len())
|
||||||
|
expectedStripped = "===[ some text ]===="
|
||||||
|
expected = "<green>===<reset><purple>[<reset><red> some text <reset><purple>]<reset><green>====<reset>"
|
||||||
|
options.inside = false
|
||||||
|
actual = cfText(str, options)
|
||||||
|
actualStripped = cecho2string(actual)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(expectedStripped, actualStripped)
|
||||||
|
assert.equals(20, actualStripped:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should wrap cecho lines to the correct length", function()
|
||||||
|
local str = "This is a test of the emergency broadcast system. This is only a test"
|
||||||
|
local options = {width = 10, alignment = "centered"}
|
||||||
|
local actual = cfText(str, options)
|
||||||
|
for _, line in ipairs(actual:split("\n")) do
|
||||||
|
assert.equals(cecho2string(line):len(), 10)
|
||||||
|
end
|
||||||
|
options.width = 15
|
||||||
|
actual = cfText(str, options)
|
||||||
|
for _, line in ipairs(actual:split("\n")) do
|
||||||
|
assert.equals(cecho2string(line):len(), 15)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("ftext.dfText", function()
|
||||||
|
local dfText = ftext.dfText
|
||||||
|
local str = "some text"
|
||||||
|
local options = {
|
||||||
|
width = 20,
|
||||||
|
spacer = "=",
|
||||||
|
cap = "[",
|
||||||
|
inside = true,
|
||||||
|
mirror = true,
|
||||||
|
capColor = "<160,32,240>",
|
||||||
|
spacerColor = "<0,255,0>",
|
||||||
|
textColor = "<255,0,0>",
|
||||||
|
}
|
||||||
|
it("Should handle decho colored text", function()
|
||||||
|
local expectedStripped = "[=== some text ====]"
|
||||||
|
local expected = "<160,32,240>[<r><0,255,0>===<r><255,0,0> some text <r><0,255,0>====<r><160,32,240>]<r>"
|
||||||
|
local actual = dfText(str, options)
|
||||||
|
local actualStripped = decho2string(actual)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(expectedStripped, actualStripped)
|
||||||
|
assert.equals(20, actualStripped:len())
|
||||||
|
expectedStripped = "===[ some text ]===="
|
||||||
|
expected = "<0,255,0>===<r><160,32,240>[<r><255,0,0> some text <r><160,32,240>]<r><0,255,0>====<r>"
|
||||||
|
options.inside = false
|
||||||
|
actual = dfText(str, options)
|
||||||
|
actualStripped = decho2string(actual)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(expectedStripped, actualStripped)
|
||||||
|
assert.equals(20, actualStripped:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should wrap decho lines to the correct length", function()
|
||||||
|
local str = "This is a test of the emergency broadcast system. This is only a test"
|
||||||
|
local options = {width = 10, alignment = "centered"}
|
||||||
|
local actual = dfText(str, options)
|
||||||
|
for _, line in ipairs(actual:split("\n")) do
|
||||||
|
assert.equals(decho2string(line):len(), 10)
|
||||||
|
end
|
||||||
|
options.width = 15
|
||||||
|
actual = dfText(str, options)
|
||||||
|
for _, line in ipairs(actual:split("\n")) do
|
||||||
|
assert.equals(decho2string(line):len(), 15)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("ftext.hfText", function()
|
||||||
|
local hfText = ftext.hfText
|
||||||
|
local str = "some text"
|
||||||
|
local options = {
|
||||||
|
width = 20,
|
||||||
|
spacer = "=",
|
||||||
|
cap = "[",
|
||||||
|
inside = true,
|
||||||
|
mirror = true,
|
||||||
|
capColor = "#a020f0",
|
||||||
|
spacerColor = "#00ff00",
|
||||||
|
textColor = "#ff0000",
|
||||||
|
}
|
||||||
|
it("Should handle hecho colored text", function()
|
||||||
|
local expectedStripped = "[=== some text ====]"
|
||||||
|
local expected = "#a020f0[#r#00ff00===#r#ff0000 some text #r#00ff00====#r#a020f0]#r"
|
||||||
|
local actual = hfText(str, options)
|
||||||
|
local actualStripped = hecho2string(actual)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(expectedStripped, actualStripped)
|
||||||
|
assert.equals(20, actualStripped:len())
|
||||||
|
expectedStripped = "===[ some text ]===="
|
||||||
|
expected = "#00ff00===#r#a020f0[#r#ff0000 some text #r#a020f0]#r#00ff00====#r"
|
||||||
|
options.inside = false
|
||||||
|
actual = hfText(str, options)
|
||||||
|
actualStripped = hecho2string(actual)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(expectedStripped, actualStripped)
|
||||||
|
assert.equals(20, actualStripped:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should wrap hecho lines to the correct length", function()
|
||||||
|
local str = "This is a test of the emergency broadcast system. This is only a test"
|
||||||
|
local options = {width = 10, alignment = "centered"}
|
||||||
|
local actual = hfText(str, options)
|
||||||
|
for _, line in ipairs(actual:split("\n")) do
|
||||||
|
assert.equals(hecho2string(line):len(), 10)
|
||||||
|
end
|
||||||
|
options.width = 15
|
||||||
|
actual = hfText(str, options)
|
||||||
|
for _, line in ipairs(actual:split("\n")) do
|
||||||
|
assert.equals(hecho2string(line):len(), 15)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("ftext.TextFormatter", function()
|
||||||
|
local tf = ftext.TextFormatter
|
||||||
|
local str = "some text"
|
||||||
|
local formatter
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
formatter = tf:new({width = 20})
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should let you change width using :setWidth", function()
|
||||||
|
formatter:setWidth(80)
|
||||||
|
local expected =
|
||||||
|
"<white><reset><white> <reset><white> some text <reset><white> <reset><white><reset>"
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(80, cecho2string(actual):len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should format for cecho by default", function()
|
||||||
|
local expected = "<white><reset><white> <reset><white> some text <reset><white> <reset><white><reset>"
|
||||||
|
local expectedStripped = " some text "
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
local actualStripped = cecho2string(actual)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
assert.equals(expectedStripped, actualStripped)
|
||||||
|
assert.equals(20, actualStripped:len())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should produce the same line as cfText given the same options", function()
|
||||||
|
local expected = ftext.cfText(str, formatter.options)
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should let you change type using :setType", function()
|
||||||
|
formatter:setType("h")
|
||||||
|
local expected = ftext.hfText(str, formatter.options)
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
formatter:setType("d")
|
||||||
|
expected = ftext.dfText(str, formatter.options)
|
||||||
|
actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
formatter:setType("")
|
||||||
|
expected = ftext.fText(str, formatter.options)
|
||||||
|
actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should default to word wrapping, and let you change it with :setWrap", function()
|
||||||
|
formatter:setWidth(10)
|
||||||
|
local expected =
|
||||||
|
"<white><reset><white> <reset><white> some <reset><white> <reset><white><reset>\n<white><reset><white> <reset><white> text <reset><white> <reset><white><reset>"
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
expected = "<white><reset><white><reset><white> some text <reset><white><reset><white><reset>"
|
||||||
|
formatter:setWrap(false)
|
||||||
|
actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should allow you to change the cap using :setCap", function()
|
||||||
|
formatter:setCap('|')
|
||||||
|
local expected = "<white>|<reset><white> <reset><white> some text <reset><white> <reset><white>|<reset>"
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should allow you to change the capColor using :setCapColor", function()
|
||||||
|
formatter:setCapColor('<red>')
|
||||||
|
local expected = "<red><reset><white> <reset><white> some text <reset><white> <reset><red><reset>"
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should allow you to change the spacer color using :setSpacerColor", function()
|
||||||
|
formatter:setSpacerColor("<red>")
|
||||||
|
local expected = "<white><reset><red> <reset><white> some text <reset><red> <reset><white><reset>"
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should allow you to change the text color using :setTextColor", function()
|
||||||
|
formatter:setTextColor("<red>")
|
||||||
|
local expected = "<white><reset><white> <reset><red> some text <reset><white> <reset><white><reset>"
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should allow you to change the spacer using :setSpacer", function()
|
||||||
|
formatter:setSpacer("=")
|
||||||
|
-- local expected = "<white><reset><white> <reset><white> some text <reset><white> <reset><white><reset>"
|
||||||
|
local expected = "<white><reset><white>====<reset><white> some text <reset><white>=====<reset><white><reset>"
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should allow you to set the alignment using :setAlignment", function()
|
||||||
|
formatter:setAlignment("left")
|
||||||
|
local expected = "<white><reset><white><reset><white>some text <reset><white> <reset><white><reset>"
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
formatter:setAlignment("right")
|
||||||
|
expected = "<white><reset><white> <reset><white> some text<reset><white><reset><white><reset>"
|
||||||
|
actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should allow you to change the 'inside' option using :setInside", function()
|
||||||
|
formatter:setInside(false)
|
||||||
|
local expected = "<white> <reset><white><reset><white> some text <reset><white><reset><white> <reset>"
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should allow you to change the mirror option using :setMirror", function()
|
||||||
|
formatter:setCap('<')
|
||||||
|
formatter:setMirror(true)
|
||||||
|
local expected = "<white><<reset><white> <reset><white> some text <reset><white> <reset><white>><reset>"
|
||||||
|
local actual = formatter:format(str)
|
||||||
|
assert.equal(expected, actual)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("ftext.TableMaker", function()
|
||||||
|
local TableMaker = ftext.TableMaker
|
||||||
|
local tm
|
||||||
|
before_each(function()
|
||||||
|
tm = TableMaker:new()
|
||||||
|
tm:addColumn({name = "col1", width = 15, textColor = "<red>"})
|
||||||
|
tm:addColumn({name = "col2", width = 15, textColor = "<blue>"})
|
||||||
|
tm:addColumn({name = "col3", width = 15, textColor = "<green>"})
|
||||||
|
tm:addRow({"some text", "more text", "other text"})
|
||||||
|
tm:addRow({"little text", "bigger text", "text"})
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Should assemble a formatted table given default options", function()
|
||||||
|
local expected = [[<white>*************************************************<reset>
|
||||||
|
<white>*<reset><white><reset><white> <reset><red> col1 <reset><white> <reset><white><reset><white>|<reset><white><reset><white> <reset><blue> col2 <reset><white> <reset><white><reset><white>|<reset><white><reset><white> <reset><green> col3 <reset><white> <reset><white><reset><white>*<reset>
|
||||||
|
<white>*<reset><white>---------------<reset><white>|<reset><white>---------------<reset><white>|<reset><white>---------------<reset><white>*<reset>
|
||||||
|
<white>*<reset><white><reset><white> <reset><red> some text <reset><white> <reset><white><reset><white>|<reset><white><reset><white> <reset><blue> more text <reset><white> <reset><white><reset><white>|<reset><white><reset><white> <reset><green> other text <reset><white> <reset><white><reset><white>*<reset>
|
||||||
|
<white>*<reset><white>---------------<reset><white>|<reset><white>---------------<reset><white>|<reset><white>---------------<reset><white>*<reset>
|
||||||
|
<white>*<reset><white><reset><white> <reset><red> little text <reset><white> <reset><white><reset><white>|<reset><white><reset><white> <reset><blue> bigger text <reset><white> <reset><white><reset><white>|<reset><white><reset><white> <reset><green> text <reset><white> <reset><white><reset><white>*<reset>
|
||||||
|
<white>*************************************************<reset>
|
||||||
|
]]
|
||||||
|
local actual = tm:assemble()
|
||||||
|
assert.equals(expected, actual)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("TableMaker:getCell should return the text and formatter for a specific cell", function()
|
||||||
|
local expectedText = "more text"
|
||||||
|
local expectedFormatter = tm.columns[2]
|
||||||
|
local actualText, actualFormatter = tm:getCell(1, 2)
|
||||||
|
assert.equals(expectedText, actualText)
|
||||||
|
assert.equals(expectedFormatter, actualFormatter)
|
||||||
|
local expectedFormatted = "<white><reset><white> <reset><blue> more text <reset><white> <reset><white><reset>"
|
||||||
|
local actualFormatted = actualFormatter:format(actualText)
|
||||||
|
assert.equals(expectedFormatted, actualFormatted)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end)
|
1
src/resources/MDK/mdkversion.txt
Normal file
1
src/resources/MDK/mdkversion.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
2.10.0
|
@ -1,10 +1,10 @@
|
|||||||
-- The alchemist implementation variables
|
-- The alchemist implementation variables
|
||||||
alchemist = alchemist or {}
|
alchemist = alchemist or {}
|
||||||
alchemist.pid = nil
|
|
||||||
alchemist.specialty = nil
|
alchemist.specialty = nil
|
||||||
alchemist.balances = alchemist.balances or {}
|
alchemist.balances = alchemist.balances or {}
|
||||||
alchemist.balances.homunculus = true
|
alchemist.balances.homunculus = true
|
||||||
alchemist.balances.humor = true
|
alchemist.balances.humor = true
|
||||||
|
alchemist.humors = alchemist.humors or {}
|
||||||
alchemist.humors.table = {
|
alchemist.humors.table = {
|
||||||
"Sanguine",
|
"Sanguine",
|
||||||
"Sanguine",
|
"Sanguine",
|
||||||
@ -22,12 +22,12 @@ alchemist.inundate = false
|
|||||||
-- NOTE: This script was written for a Sublimation user and primarily pushes keeping class specific weaknesses and using bleeding/aurify as a killpath
|
-- NOTE: This script was written for a Sublimation user and primarily pushes keeping class specific weaknesses and using bleeding/aurify as a killpath
|
||||||
function alchemist.decideAction()
|
function alchemist.decideAction()
|
||||||
if gmcp.Char.Status.class ~= "Alchemist" then
|
if gmcp.Char.Status.class ~= "Alchemist" then
|
||||||
cecho("\n<firebrick>(BadPVP): Called Alchemist decision engine when not a Alchemist.")
|
cecho("\n<firebrick>COMBAT NOTICE: Called Alchemist decision engine when not a Alchemist.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not target or target == nil then
|
if not target or target == nil or target == "None" or target == "Dude" then
|
||||||
cecho("\n<firebrick>(BadPVP): Called decision engine without a target.")
|
cecho("\n<firebrick>COMBAT NOTICE: Called decision engine without a target.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -40,10 +40,10 @@ function alchemist.decideAction()
|
|||||||
local affsReport = {}
|
local affsReport = {}
|
||||||
local enemyClass = nil
|
local enemyClass = nil
|
||||||
local humors = {
|
local humors = {
|
||||||
choleric = ak.alchemist.humour.choleric or 0,
|
Choleric = ak.alchemist.humour.choleric or 0,
|
||||||
melancholic = ak.alchemist.humour.melancholic or 0,
|
Melancholic = ak.alchemist.humour.melancholic or 0,
|
||||||
phlegmatic = ak.alcehmist.humour.phlegmatic or 0,
|
Phlegmatic = ak.alchemist.humour.phlegmatic or 0,
|
||||||
sanguine = ak.alchemist.humour.sanguine or 0
|
Sanguine = ak.alchemist.humour.sanguine or 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if table.contains(Legacy.CT.Enemies, target) then
|
if table.contains(Legacy.CT.Enemies, target) then
|
||||||
@ -77,12 +77,12 @@ function alchemist.decideAction()
|
|||||||
table.insert(commandString, "homunculus corrupt " .. target)
|
table.insert(commandString, "homunculus corrupt " .. target)
|
||||||
table.insert(affsReport, "homunculus corruption")
|
table.insert(affsReport, "homunculus corruption")
|
||||||
alchemist.balances.homunculus = false
|
alchemist.balances.homunculus = false
|
||||||
alchemist.hopid = tempTimer(12, alchemist.resetBalance("homunculus"))
|
tempTimer(12, function() alchemist.resetBalance("homunculus") end)
|
||||||
else
|
else
|
||||||
-- Just attack
|
-- Just attack
|
||||||
table.insert(commandString, "homunculus attack " .. target)
|
table.insert(commandString, "homunculus attack " .. target)
|
||||||
alchemist.balances.homunculus = false
|
alchemist.balances.homunculus = false
|
||||||
alchemist.hopid = tempTimer(3, alchemist.resetBalance("homunculus"))
|
tempTimer(3, function() alchemist.resetBalance("homunculus") end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -90,20 +90,20 @@ function alchemist.decideAction()
|
|||||||
-- temper target humour (1.7 seconds Humor)
|
-- temper target humour (1.7 seconds Humor)
|
||||||
-- inundate target humor (1.7 seconds humor)
|
-- inundate target humor (1.7 seconds humor)
|
||||||
-- This will rotate through the alchemist.humors.table and temper those humors in order until it is time to inundate
|
-- This will rotate through the alchemist.humors.table and temper those humors in order until it is time to inundate
|
||||||
if humors.sanguine > 2 then
|
if humors.Sanguine > 2 then
|
||||||
-- push inundate at 3+ sanguine to push bleeding
|
-- push inundate at 3+ sanguine to push bleeding
|
||||||
table.insert(commandString, "inundate " .. target .. " sanguine")
|
table.insert(commandString, "inundate " .. target .. " sanguine")
|
||||||
table.insert(affsReport, "bleeding")
|
table.insert(affsReport, "bleeding")
|
||||||
alchemist.hupid = tempTimer(1.7, alchemist.resetBalance("humor"))
|
tempTimer(1.7, function() alchemist.resetBalance("humor") end)
|
||||||
alchemist.inundate = true
|
alchemist.inundate = true
|
||||||
elseif humors.phlegmatic >= 4 then
|
elseif humors.Phlegmatic >= 4 then
|
||||||
-- For some reason, they allowed us to push phlegmatic very high so inundate this for extra affs
|
-- For some reason, they allowed us to push phlegmatic very high so inundate this for extra affs
|
||||||
table.insert(commandString, "inundate " .. target .. " phlegmatic")
|
table.insert(commandString, "inundate " .. target .. " phlegmatic")
|
||||||
table.insert(affsReport, "lethargy")
|
table.insert(affsReport, "lethargy")
|
||||||
if humors.phlegmatic >= 4 then table.insert(affsReport, "anorexia") end
|
if humors.Phlegmatic >= 4 then table.insert(affsReport, "anorexia") end
|
||||||
if humors.phlegmatic >= 6 then table.insert(affsReport, "slickness") end
|
if humors.Phlegmatic >= 6 then table.insert(affsReport, "slickness") end
|
||||||
if humors.phlegmatic >= 8 then table.insert(affsReport, "weariness") end
|
if humors.Phlegmatic >= 8 then table.insert(affsReport, "weariness") end
|
||||||
alchemist.hupid = tempTimer(1.7, alchemist.resetBalance("humor"))
|
tempTimer(1.7, function() alchemist.resetBalance("humor") end)
|
||||||
else
|
else
|
||||||
-- Temper whatever humor we have
|
-- Temper whatever humor we have
|
||||||
local ourHumor = alchemist.humors.table[alchemist.humors.index]
|
local ourHumor = alchemist.humors.table[alchemist.humors.index]
|
||||||
@ -111,12 +111,12 @@ function alchemist.decideAction()
|
|||||||
table.insert(affsReport, "tempered" .. ourHumor .. "(" .. tostring(humors[ourHumor] + 1) .. ")")
|
table.insert(affsReport, "tempered" .. ourHumor .. "(" .. tostring(humors[ourHumor] + 1) .. ")")
|
||||||
alchemist.humors.index = alchemist.humors.index + 1
|
alchemist.humors.index = alchemist.humors.index + 1
|
||||||
if alchemist.humors.index > #alchemist.humors.table then alchemist.humors.index = 1 end
|
if alchemist.humors.index > #alchemist.humors.table then alchemist.humors.index = 1 end
|
||||||
alchemist.hupid = tempTimer(1.7, alchemist.resetBalance("humor"))
|
tempTimer(1.7, function() alchemist.resetBalance("humor") end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Educe
|
-- Educe
|
||||||
local hpPercent = ((gmcp.Char.Vitals.hp / gmcp.Char.Vitals.maxhp) * 100)
|
local hpPercent = ((gmcp.Char.Vitals.hp / gmcp.Char.Vitals.maxhp) * 100)
|
||||||
if alchemist.wrackCount ~= 0 and alchemist.wrackcount % 3 ~= 0 then
|
if alchemist.wrackCount ~= 0 and alchemist.wrackCount % 3 ~= 0 then
|
||||||
-- Educe here as we aren't truewracking
|
-- Educe here as we aren't truewracking
|
||||||
if ak.defs.shield then
|
if ak.defs.shield then
|
||||||
-- Break Shield
|
-- Break Shield
|
||||||
@ -161,9 +161,6 @@ function alchemist.decideAction()
|
|||||||
send("queue addclearfull eqbal murder")
|
send("queue addclearfull eqbal murder")
|
||||||
send("pt " .. target .. " hit with " .. table.concat(affsReport, " "))
|
send("pt " .. target .. " hit with " .. table.concat(affsReport, " "))
|
||||||
|
|
||||||
if fighter.automate then
|
|
||||||
alchemist.pid = registerAnonymousEventHandler("gmcp.Char.Vitals", "alchemist.isReady")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Functioned used to reset special class balances for Alchemist
|
-- Functioned used to reset special class balances for Alchemist
|
||||||
@ -171,14 +168,11 @@ function alchemist.resetBalance(which)
|
|||||||
if which == "homunculus" then
|
if which == "homunculus" then
|
||||||
alchemist.balances.homunculus = true
|
alchemist.balances.homunculus = true
|
||||||
cecho("\n<firebrick>COMBAT NOTICE: Homunculus balance restored.")
|
cecho("\n<firebrick>COMBAT NOTICE: Homunculus balance restored.")
|
||||||
killTimer(alchemist.hopid)
|
|
||||||
elseif which == "humor" then
|
elseif which == "humor" then
|
||||||
alchemist.balances.humor = true
|
alchemist.balances.humor = true
|
||||||
cecho("\n<firebrick>COMBAT NOTICE: Humor balance restored.")
|
cecho("\n<firebrick>COMBAT NOTICE: Humor balance restored.")
|
||||||
killTimer(alchemist.hupid)
|
|
||||||
else
|
else
|
||||||
cecho("\n<firebrick>COMBAT NOTICE: We were asked to reset the Alchemist balance " ..
|
cecho("\n<firebrick>COMBAT NOTICE: We were asked to reset the Alchemist balance " .. which .. " but that isn't a valid balance.")
|
||||||
which .. " but that isn't a valid balance.")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -198,22 +192,9 @@ function alchemist.setSpecialty()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if ourSpecialty == nil then
|
if ourSpecialty == nil then
|
||||||
cecho(
|
cecho("\n<firebrick>COMBAT NOTICE: No alchemy specialty found. If you have not yet embraced your class or you are not currently an Alchemist this is normal. Otherwise, this is an error.")
|
||||||
"\n<firebrick>COMBAT NOTICE: No alchemy specialty found. If you have not yet embraced your class or you are not currently an Alchemist this is normal. Otherwise, this is an error.")
|
|
||||||
else
|
else
|
||||||
alchemist.specialty = ourSpecialty
|
alchemist.specialty = ourSpecialty
|
||||||
cecho("\n<firebrick>COMBAT NOTICE: Set alchemy specialty to " .. ourSpecialty)
|
cecho("\n<firebrick>COMBAT NOTICE: Set alchemy specialty to " .. ourSpecialty)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- This function is responsible for automating the combat system
|
|
||||||
-- This is an example of one that handles multiple balance timers
|
|
||||||
function alchemist.isReady()
|
|
||||||
-- Skip if we are still off balance
|
|
||||||
if (gmcp.Char.Vitals.eq == 0) or (gmcp.Char.Vitals.bal == 0) then return end
|
|
||||||
-- We want to make sure we at least have humor balance (Which we should generally)
|
|
||||||
if not alchemist.balances.humor then return end
|
|
||||||
|
|
||||||
killAnonymousEventHandler(alchemist.pid)
|
|
||||||
alchemist.decideAction()
|
|
||||||
end
|
|
||||||
|
@ -2,7 +2,6 @@ fighter = fighter or {}
|
|||||||
|
|
||||||
function fighter.Setup()
|
function fighter.Setup()
|
||||||
fighter.classes = {}
|
fighter.classes = {}
|
||||||
fighter.automate = false
|
|
||||||
|
|
||||||
-- To add a new class, put the name here
|
-- To add a new class, put the name here
|
||||||
fighter.classes.implemented = {
|
fighter.classes.implemented = {
|
||||||
@ -63,5 +62,68 @@ function fighter.Setup()
|
|||||||
-- This will set the variable alchemist.specialty to Sublimation or Formulation depending
|
-- This will set the variable alchemist.specialty to Sublimation or Formulation depending
|
||||||
alchemist.setSpecialty()
|
alchemist.setSpecialty()
|
||||||
end
|
end
|
||||||
|
|
||||||
registerAnonymousEventHandler("sysLoadEvent", "fighter.Setup")
|
registerAnonymousEventHandler("sysLoadEvent", "fighter.Setup")
|
||||||
|
|
||||||
|
function fighter.verifyInstall(_, name)
|
||||||
|
if name ~= "fighter" then return end
|
||||||
|
fighter.Setup()
|
||||||
|
end
|
||||||
|
registerAnonymousEventHandler("sysInstall", "fighter.verifyInstall")
|
||||||
|
|
||||||
|
function fighter.verifyUninstall(_, name)
|
||||||
|
if name ~= "fighter" then return end
|
||||||
|
fighter = nil
|
||||||
|
alchemist = nil
|
||||||
|
psion = nil
|
||||||
|
end
|
||||||
|
registerAnonymousEventHandler("sysUninstall", "fighter.verifyUninstall")
|
||||||
|
|
||||||
|
function fighter.generateHelp()
|
||||||
|
local tablemaker = require("Fighter.MDK.ftext").TableMaker
|
||||||
|
local formatter = require ("Fighter.MDK.ftext").TextFormatter
|
||||||
|
|
||||||
|
headerFormat = formatter:new({
|
||||||
|
width = 80,
|
||||||
|
cap = "<|",
|
||||||
|
capColor = "<DarkSlateBlue>",
|
||||||
|
textColor = "<white>",
|
||||||
|
spacerColor = "<steel_blue>",
|
||||||
|
inside = false,
|
||||||
|
spacer = " ",
|
||||||
|
alignment = "center",
|
||||||
|
mirror = true
|
||||||
|
})
|
||||||
|
|
||||||
|
helpTable = tablemaker:new({
|
||||||
|
title = "Fighter Help",
|
||||||
|
printTitle = false,
|
||||||
|
printHeaders = true,
|
||||||
|
frameColor = "<steel_blue>",
|
||||||
|
separateRows = false,
|
||||||
|
forceHeaderSeparator = true
|
||||||
|
})
|
||||||
|
helpTable:addColumn({
|
||||||
|
name = "Command",
|
||||||
|
width = 30,
|
||||||
|
textColor = "<DarkSlateBlue>"
|
||||||
|
})
|
||||||
|
helpTable:addColumn({
|
||||||
|
name = "Description",
|
||||||
|
width = 50,
|
||||||
|
textColor = "<DarkSlateGrey>"
|
||||||
|
})
|
||||||
|
--pvp
|
||||||
|
helpTable:addRow({
|
||||||
|
"fight",
|
||||||
|
"Generate your next pvp action."
|
||||||
|
})
|
||||||
|
--pvpnt
|
||||||
|
helpTable:addRow({
|
||||||
|
"<LightSlateBlue>fighthelp",
|
||||||
|
"<LightSlateGrey>Display this menu."
|
||||||
|
})
|
||||||
|
|
||||||
|
cecho(headerFormat:format("Fighter Help Docs"))
|
||||||
|
cecho(helpTable:assemble())
|
||||||
|
|
||||||
|
end
|
@ -1,18 +1,17 @@
|
|||||||
-- Psion Implementation Variables
|
-- Psion Implementation Variables
|
||||||
psion = psion or {}
|
psion = psion or {}
|
||||||
psion.timeToFlurry = false
|
psion.timeToFlurry = false
|
||||||
psion.pid = nil
|
|
||||||
|
|
||||||
-- The primary function to build pvp actions for the psion class
|
-- The primary function to build pvp actions for the psion class
|
||||||
-- NOTE: This script primarily pushes for keeping specific class weaknesses applied and stacking unweaved body/mind until it can be inverted to spirit and flurried against
|
-- NOTE: This script primarily pushes for keeping specific class weaknesses applied and stacking unweaved body/mind until it can be inverted to spirit and flurried against
|
||||||
function psion.decideAction()
|
function psion.decideAction()
|
||||||
if gmcp.Char.Status.class ~= "Psion" then
|
if gmcp.Char.Status.class ~= "Psion" then
|
||||||
cecho("\n<firebrick>(BadPVP): Called Psion decision engine when not a Psion.")
|
cecho("\n<firebrick>COMBAT NOTICE: Called Psion decision engine when not a Psion.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not target or target == nil then
|
if not target or target == nil or target == "None" or target == "Dude" then
|
||||||
cecho("\n<firebrick>(BadPVP): Called decision engine without a target.")
|
cecho("\n<firebrick>COMBAT NOTICE: Called decision engine without a target.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -187,11 +186,3 @@ function psion.decideAction()
|
|||||||
psion.pid = registerAnonymousEventHandler("gmcp.Char.Vitals", "psion.isReady")
|
psion.pid = registerAnonymousEventHandler("gmcp.Char.Vitals", "psion.isReady")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- This function is responsible for automating the combat system
|
|
||||||
function psion.isReady()
|
|
||||||
if (gmcp.Char.Vitals.eq == 0) or (gmcp.Char.Vitals.bal == 0) then return end
|
|
||||||
|
|
||||||
killAnonymousEventHandler(psion.pid)
|
|
||||||
psion.decideAction()
|
|
||||||
end
|
|
||||||
|
Loading…
Reference in New Issue
Block a user