Initial Beta of Bashmatic
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Charles Click 2024-06-17 01:36:51 -04:00
parent b5e14f3f22
commit f49d426ccf
Signed by: roryejinn
GPG Key ID: EDECB89DEDB998C0
16 changed files with 2651 additions and 226 deletions

42
.woodpecker.yaml Normal file
View File

@ -0,0 +1,42 @@
steps:
- name: build-release
image: alpine
when:
- event: tag
commands:
- apk add openjdk21
- apk add wget
- apk add tar
- wget https://github.com/demonnic/muddler/releases/download/0.13/muddle-shadow-0.13.tar
- tar -xvf muddle-shadow-0.13.tar
- mv muddle-shadow-0.13/lib/muddle-0.13-all.jar muddle.jar
- java -jar muddle.jar
- name: deploy-build
image: alpine
when:
- event: tag
environment:
GITEATKN:
from_secret: GITEA_TOKEN
GOTOKEN:
from_secret: GOTIFY_TOKEN
depends_on: build-release
commands:
- apk add tea
- apk add wget
- tea login add --name=temp --url=https://git.vertinext.com/ --token=$GITEATKN
- tea releases create --asset "build/Bashmatic.mpackage" --asset "build/Bashmatic.xml" --tag ${CI_COMMIT_TAG} --title "Latest Compiled Release" --note "Use .mpackage for Mudlet and .xml for Mushclient"
- wget "https://gotify.vertinext.com/message?token=$GOTOKEN" --post-data "title=${CI} - ${CI_REPO_NAME}&message=New release ${CI_COMMIT_TAG} built and deployed.&priority=0" -O /dev/null
- name: notify-on-branch-push
image: alpine
when:
- event: [push, pull_request, tag, release]
- status: [success, failure]
environment:
GOTOKEN:
from_secret: GOTIFY_TOKEN
commands:
- apk add wget
- wget "https://gotify.vertinext.com/message?token=$GOTOKEN" --post-data "title=${CI} - ${CI_REPO_NAME}&message=New ${CI_PIPELINE_EVENT} to ${CI_REPO_NAME}/${CI_COMMIT_BRANCH}.&priority=0" -O /dev/null

View File

@ -2,15 +2,15 @@
Bashmatic is a generic script package for mudlet. Many muds have a character visit areas and attack various denizens to gain experience to level up. This process is colloquially called bashing. Bashmatic is a very generic script package that automates this process. Bashmatic is a generic script package for mudlet. Many muds have a character visit areas and attack various denizens to gain experience to level up. This process is colloquially called bashing. Bashmatic is a very generic script package that automates this process.
# What does it support? # What does it support?
Again, it's very generic. Because of that it supports pretty much anywhere that you can bash using a one line command to do so. However, because of the generic nature of the script it also doesn't support more advanced features games might have. It does however support sending commands to the game before and after fights. It also supports grouping bashing targets by areas if you use the mudlet mapper or your game supports gmcp. It also supports finding enemies by gmcp or general input scraping. So overall: Again, it's very generic. Because of that it supports pretty much anywhere that you can bash using a one line command to do so. However, because of the generic nature of the script it also doesn't support more advanced features games might have. It does however support sending commands to the game before and after fights. It also supports grouping bashing targets by areas if you use the mudlet mapper. Overall it supports:
* Supports sending a customized pre-bashing command * Supports sending a customized pre-bashing command
* Supports sending a customized bashing command * Supports sending a customized bashing command
* Supports sending a customized post-bashing command * Supports sending a customized post-bashing command
* Supports specifying a custom mob death phrase * Supports specifying a custom mob death trigger phrase per game
* Supports grouping bashing targets by area * Supports grouping bashing targets by area
* Supports detecting areas using the mudlet mapper or by GMCP * Supports detecting areas using the mudlet mapper
* Supports detecting enemies by GMCP or general input scraping * Supports detecting enemies by creating temp triggers based on target names
* Provides a function `bmDisable()` that will disable the basher so you can rig a flee/wimpy trigger/alias * Provides a function `bmDisable()` that will disable the basher so you can rig a flee/wimpy trigger/alias
# Can I use this on my mud? # Can I use this on my mud?
@ -22,25 +22,24 @@ A few but none that are too bad.
## Switching To Area Group Mode ## Switching To Area Group Mode
By default, Bashmatic does not group by areas. This means if you switch the target grouping mode to areas you will erase your target list. This is by necessity. If area grouping is turned off, no area data is stored for targets. When you turn on area grouping, we have no way of finding out what area they should be in. So you'll have to readd them to get them in the right area. This is not true of the other way. If you are grouping by area and turn that off, then we will simply collate all targets into a giant list. You can then clear your target list using `bm clear` if you want. By default, Bashmatic does not group by areas. This means if you switch the target grouping mode to areas you will erase your target list. This is by necessity. If area grouping is turned off, no area data is stored for targets. When you turn on area grouping, we have no way of finding out what area they should be in. So you'll have to readd them to get them in the right area. This is not true of the other way. If you are grouping by area and turn that off, then we will simply collate all targets into a giant list. You can then clear your target list using `bm clear` if you want.
## GMCP Usage
GMCP requires you to tell the script where the variables are located. This isn't hard. You can type `lua gmcp` into mudlet to get back a listing of the gmcp data your mud sends out. If the list of enemies on your mud was at `Room.Info.Enemies` you could give me that information using `bm config egmcp=Room.Info.Enemies`
## Grouping Targets By Areas ## Grouping Targets By Areas
If grouping by GMCP areas, also see above. We can group targets by areas if you prefer as long as we can tell which area we are in. This can happen by mudlet returning an area through `GetRoomAreaName(GetRoomArea(GetPlayerRoom())`. This requires you to have a map made in mudlet. Functionally, the real benefit to this is that we can reduce the number of tmeporary triggers made since we can only make ones related to the current area. However, unless you have thousands upon thousands of targets built into your list you probably won't notice the difference.
We can group targets by areas if you prefer as long as we can tell which area we are in. This can happen by the mud sending the area name by GMCP or by mudlet returning an area through `GetRoomArea(GetPlayerRoom())`. This can be useful for keeping your target lists manageable assuming you want to be able to look at them.
## Auto target switching ## Auto target switching
Bashmatic doesn't technically support auto-target switching, but we have a jury rigged solution. Upon detecting an enemy's death we will look at the room again. Bashmatic doesn't technically support auto-target switching, but we have a jury rigged solution. Upon detecting an enemy's death we will look at the room again.
## Before, During, and After Bashing commands ## Before, During, and After Bashing commands
You should know that the only time we append the target name is bashing start command. Before, During, and After bashing commands do not receive the target name. You should know that the only time we append the target name is bashing start command. Before, During, and After bashing commands do not receive the target name. We also kill all triggers related to finding targets once we start bashing a target.
# Required Setup # Required Setup
At the very least, you'll need to setup a bashing command. This can be as simply as just `kill` and we'll fill in the target. And you'll need some kind of death trigger. On a lot of muds this could just be the word `died`. A lot of muds just use some variation of the phrase `has died` and this script will match `.*word.*`. Then at least one target added using bm add target. So `bm add bunny` maybe. At the very least, you'll need to setup a bashing command. This can be as simple as just `kill` and we'll fill in the target so it late becomes `kill target`. And you'll need some kind of phrase that allows us to determine a mob has died: The death trigger phrase. On a lot of muds this could just be the word `died` or `has been slain` or `have slain` or some other combination. A lot of muds just use some variation of the phrase `has died` and this script will match `.*word.*`. Then at least one target added using bma target. So `bma bunny` maybe.
* A bash command, Possibly just: `kill` * A bash command, Possibly just: `kill`
* A death trigger, Possibly just: `died` * A death trigger, Possibly just: `died`
* At least one target, Possibly just: `bm add bunny` * At least one target, Possibly just: `bma bunny`
# How does this work? # How does this work?
It depends. Under the hood, it's much more efficient if we can get enemy data from GMCP. Using GMCP, we can simply scan GMCP data for changes to enemy data and react to that. Without GMCP, we create temporary triggers and react to those as they fire. In general, we create temporary triggers that only fire once that look for matches against the targets given. So for our bunny example, we would create a temp trigger that will only ever fire once against the word bunny. This is not perfect, for obvious reasons. If the room description contains the word bunny or if someone is wearing an item with the word bunny in it, we're going to react to that word. Still, it's a simple enough solution that works most of the time for most situations especially given that the system has to be manually turned on and is likely to only even be turned on in situations where we are less likely to run into those odd situations. IE: If you turn on the autobasher, the bunny you run into is most likely to be the one you want to kill for gaining experience, not the random guy with his bunny cloak. Even if it does mess up, just kill something normally once and it will reset. Or simply toggle it off and on. You'll be ready to go again.
# In Game Help
There is extensive and easy to understand help built in. Once installed in mudlet, see `bm help` and `bmc` for an indepth explanation of settings and features.

View File

@ -1,17 +1,16 @@
if not bashmatic.configs.death.event then if not bashmatic.death.event then
cecho("<firebrick>BASHMATIC: You must configure the death trigger first. Please see bm help for more info.") cecho("<firebrick>BASHMATIC: You must configure the death trigger first. Please see bm help for more info.")
else else
if bashmatic.configs.enemies.detection == "inline" then if bashmatic.enemies.group then
-- using trigger detection -- grouping enemies by area
local area = nil local area = GetRoomAreaName(GetRoomArea(GetPlayerRoom())) or nil
if bashmatic.configs.areas.detection == "mapper" then area = GetRoomAreaName(GetRoomArea(GetPlayerRoom())) end if area == nil then
if bashmatic.configs.areas.detection == "gmcp" and bashmatic.configs.areas.data ~= nil then area = bashmatic.configs.areas.data end cecho("<firebrick>BASHMATIC: We tried to add that enemy but got a bad area.\nGot: " .. area .. "<reset>")
inlineAddTarget(matches[2], area)
elseif bashmatic.configs.enemies.detection == "gmcp" then
-- using gmcp detection
cecho("<firebrick>BASHMATIC: GMCP not implemented yet.")
else else
-- well this is broken inlineAddTarget(matches[2], area)
cecho("<firebrick>BASHMATIC: Invalid enemy detection method.<reset>") end
else
-- not grouping by area
inlineAddTarget(matches[2], nil)
end end
end end

View File

@ -1,10 +1,20 @@
if table.size(bashmatic.hunting.events) > 0 then killBashingTriggers()
for _, tid in ipairs(bashmatic.hunting.events) do
killTrigger(tid)
end
end
toggleBashing(false) toggleBashing(false)
bmDisable() bmDisable()
bashmatic.hunting.events = {}
bashmatic.hunting.targets = {} if Bashmatic.enemies.group then
cecho("<firebrick>BASHMATIC: Cleared target list.<reset>") local area = GetRoomAreaName(GetRoomArea(GetPlayerRoom())) or nil
if area == nil then
cecho("<firebrick>Bashmatic: Attempted to clear area targets but got a bad area.\nGot: " .. area .. "<reset>")
return
end
if not table.contains(Bashmatic.enemies.targets, area) then
cecho("<firebrick>Bashmatic: You don't have any enemies for the area " .. area .. "<reset>")
return
end
Bashmatic.enemies.targets.area = nil
cecho("<DarkSlateBlue>Bashmatic: Cleared target list for area " .. area .. "<reset>")
else
Bashmatic.enemies.targets = {}
cecho("<DarkSlateBlue>Bashmatic: Cleared target list.<reset>")
end

View File

@ -3,22 +3,12 @@ cecho("<Slategrey>---------------------------------")
cecho("<DarkSlateBlue>See bm help for information on configuration.") cecho("<DarkSlateBlue>See bm help for information on configuration.")
cecho("<DarkSlateBlue>") cecho("<DarkSlateBlue>")
cecho("<MediumPurple>\nBattle Commands:") cecho("<MediumPurple>\nBattle Commands:")
cecho("<DarkSlateBlue>-- Start : " .. bashmatic.commands.start or "None") cecho("<DarkSlateBlue>-- Start : " .. Bashmatic.commands.start or "None")
cecho("<DarkSlateBlue>-- Before: " .. bashmatic.commands.before or "None") cecho("<DarkSlateBlue>-- Before: " .. Bashmatic.commands.before or "None")
cecho("<DarkSlateBlue>-- During: " .. bashmatic.commands.during or "None" .. "(Every " .. bashmatic.commands.duringTime .. "s)") cecho("<DarkSlateBlue>-- During: " .. Bashmatic.commands.during or "None" .. "(Every " .. Bashmatic.commands.duringTime .. "s)")
cecho("<DarkSlateBlue>-- After : " .. bashmatic.commands.after or "None") cecho("<DarkSlateBlue>-- After : " .. Bashmatic.commands.after or "None")
cecho("<MediumPurple>\n\nDeath Trigger:") cecho("<MediumPurple>\n\nDeath Trigger:")
cecho("<DarkSlateBlue>-- Phrase : " .. bashmatic.death.phrase or "None") cecho("<DarkSlateBlue>-- Phrase : " .. Bashmatic.death.phrase or "None")
cecho("<DarkSlateBlue>-- Activated?: " .. bashmatic.death.event or "No") cecho("<DarkSlateBlue>-- Activated?: " .. Bashmatic.death.event or "No")
cecho("<MediumPurple>\n\nDetection:") cecho("<MediumPurple>\n\nEnemies:")
cecho("<DarkSlateBlue>-- Detecting enemies using " .. bashmatic.configs.enemies.detection) cecho("<DarkSlateBlue>-- Grouping by Areas: " .. Bashmatic.enemies.group or "No")
if bashmatic.configs.areas.detection == nil then
cecho("<DarkSlateBlue>-- Not currently grouping enemies by areas.")
else
cecho("<DarkSlateBlue>-- Currently grouping enemies by areas using " .. bashmatic.configs.areas.detection)
end
if bashmatic.configs.enemies.detection == "gmcp" or bashmatic.configs.areas.detection == "gmcp" then
cecho("<MediumPurple>\n\nGMCP Detection Settings:")
if bashmatic.configs.enemies.detection == "gmcp" then cecho("<DarkSlateBlue>-- Enemy data located at " .. bashmatic.configs.enemies.location) end
if bashmatic.configs.areas.detection == "gmcp" then cecho("<DarkSlateBlue>-- Area data located at " .. bashmatic.configs.areas.location) end
end

View File

@ -2,24 +2,49 @@ local which = matches[2]:lower()
if which == "phrase" then if which == "phrase" then
-- death phrase -- death phrase
if Bashmatic.death.event ~= nil then
killTrigger(Bashmatic.death.event)
end
Bashmatic.death.phrase = matches[2]
Bashmatic.death.event = tempTrigger(Bashmatic.death.phrase,handleMobDeath)
cecho("<DarkSlateBlue>Bashmatic: Reset the death event trigger phrase to " .. matches[2] .. ".<reset>")
elseif which == "start" then elseif which == "start" then
-- starting battle command -- starting battle command
Bashmatic.commands.start = matches[2]
cecho("<DarkSlateBlue>Bashmatic: Set battle start command to " .. matches[2] .. " target.<reset>")
elseif which == "before" then elseif which == "before" then
-- before battle command -- before battle command
Bashmatic.commands.before = matches[2]
cecho("<DarkSlateBlue>Bashmatic: Will send " .. matches[2] .. " before battle start.<reset>")
elseif which == "during" then elseif which == "during" then
-- during battle command -- during battle command
Bashmatic.comands.during = matches[2]
cecho("<DarkSlateBlue>Bashmatic: Will send " .. matches[2] .. " during battle every " .. Bashmatic.commands.duringTime .. " seconds.<reset>")
elseif which == "duringTime" then elseif which == "duringTime" then
-- during battle command time frame -- during battle command time frame
Bashmatic.commands.duringTime = tonumber(mathces[2])
cecho("<DarkSlateBlue>Bashmatic: Will send " .. Bashmatic.commands.during .. " during battle every " .. tonumber(matches[2]) .. " seconds.<reset>")
elseif which == "after" then elseif which == "after" then
-- after battle command -- after battle command
elseif which == "enemy" then Bashmatic.commands.after = matches[2]
-- enemy detection method cecho("<DarkSlateBlue>Bashmatic: Will send " .. matches[2] .. " after combat.<reset>")
elseif which == "egmcp" then elseif which == "group" then
-- enemy gmcp path -- group by area
elseif which == "area" then if #getRooms() == 0 then
-- area detection method Bashmatic.enemies.group = false
elseif which == "agmcp" then cecho("<firebrick>Bashmatic: No map detected. Did you make one? You need at least one room to use this feature.<reset>")
-- area gmcp path else
Bashmatic.enemies.group = not Bashmatic.enemies.group
if Bashmatic.enemies.group then
-- we've just turned on enemy grouping
Bashmatic.enemies.targets = {}
cecho("<DarkSlateBlue>Bashmatic: Now grouping enemies by areas. Cleared previous enemies.<reset>")
else
-- we've just turned off enemy grouping
squashTargetGroups()
cecho("<DarkSlateBlue>Bashmatic: No longer grouping enemies by areas. Squashed previous enemies into one large table.\nYou can bm clear to erase them.<reset>")
end
end
else else
cecho("<firebrick>BASHMATIC: Unrecognized option " .. matches[2] .. ". See bm help for a list of options.") cecho("<firebrick>Bashmatic: Unrecognized option " .. matches[2] .. ". See bm help for a list of options.")
end end

View File

@ -0,0 +1,28 @@
local ourIndex = tonumber(matches[2])
if Bashmatic.enemies.group then
local area = GetRoomAreaName(GetRoomArea(GetPlayerRoom())) or nil
if area == nil then
cecho("<firebrick>Bashmatic: Attempted to clear area targets but got a bad area.\nGot: " .. area .. "<reset>")
return
end
if not table.contains(Bashmatic.enemies.targets, area) then
cecho("<firebrick>Bashmatic: You don't have any enemies for the area " .. area .. "<reset>")
return
end
local size = table.size(Bashmatic.enemies.targets.area)
if ourIndex > size then
cecho("<firebrick>Bashmatic: Index out of range for this area. There are only " .. size .. " targets stored.<reset>")
return
end
table.remove(Bashmatic.enemies.targets.area, ourIndex)
cecho("<DarkSlateBlue>Bashmatic: Removed target from the area list.<reset>")
else
local size = table.size(Bashmatic.enemies.targets)
if ourIndex > size then
cecho("<firebrick>Bashmatic: Index out of range. There are only " .. size .. " targets stored.<reset>")
return
end
table.remove(Bashmatic.enemies.targets, ourIndex)
cecho("<DarkSlateBlue>Bashmatic: Removed target from the list.<reset")
end

View File

@ -4,35 +4,33 @@ Let's Bash some Mobs!
Basic Setup Basic Setup
----------- -----------
Bare Minimum, you need to setup a death trigger, a starting battle command, and at least one target. Set up the death trigger by doing bm config phrase=your game's death phrase. Then setup a starting command with bm config start=kill. Then go find a target and bm add target. Then type bm and you're all set to auto bash them. Altogether again then that was. Bare Minimum, you need to setup a death trigger, a starting battle command, and at least one target. Set up the death trigger by doing bm config phrase=your game's death phrase or word. Then setup a starting command with bm config start=kill command. Then go find a target and bm add target. Then type bm and you're all set to auto bash them. Altogether again then that was.
1) bm config phrase=death phrase 1) bmc phrase=death phrase or keyword
2) bm config start=kill command 2) bmc start=kill command (target added automatically)
3) bm add target 3) bma target
4) bm - this will toggle the system on 4) bm - this will toggle the system on
All config options All config options
------------------ ------------------
Toggle all of these using bm config option=value Toggle all of these using bm config option=value
bm config phrase - sets the phrase that should trigger resolution for the death of our target. bmc phrase - sets the phrase that should trigger resolution for the death of our target.
bm config start - sets the command used to start combat. The target name is added here. bmc start - sets the command used to start combat. The target name is added here.
bm config before - commands to execute before we start combat. bmc before - commands to execute before we start combat.
bm config during - commands to execute during combat. bmc during - commands to execute during combat.
bm config duringTime - time delay between during command execution. Default 2 seconds. Wants a number. bmc duringTime - time delay between during command execution. Default 2 seconds. Wants a number.
bm config after - commands to execute after the death trigger fires. bmc after - commands to execute after the death trigger fires.
bm config enemy - Set to one of inline or gmcp to determine how we grab enemy data. bmc group - set to yes or no to toggle grouping enemies by mudlet mapper areas on or off
bm config egmcp - if using gmcp to grab enemy data, use this to set the gmcp path for enemy data.
bm config area - if wanting to group by areas, set this to mapper or gmcp to set how we get area information.
bm config agmcp - if using gmcp for areas, use this to set the gmcp path for area data.
Aliases Available Aliases Available
----------------- -----------------
bm add <target> - add a new target to the hunt list bma <target> - add a new target to the hunt list
bmc - show the current configuration bmc - show the current configuration
bm config option=value - change the configuration bmc option=value - change the configuration
bmt - List all current targets bmt - List all current targets (if grouped by areas this will be for the current area)
bm - toggle the bashing system on and off bm - toggle the bashing system on and off
bm clear - clear all targets bm clear - clear all targets (All Targets. For All Areas.)
bmd # - Delete the target with the given ID from bmt
bm help - this screen bm help - this screen
<reset>]]) <reset>]])

View File

@ -0,0 +1,40 @@
if Bashmatic.enemies.group then
-- grouped by areas
local area = GetRoomAreaName(GetRoomArea(GetPlayerRoom())) or nil
if area == nil then
cecho("<firebrick>Bashmatic: We got an invalid area.\nWe Got: " .. area .. "<reset>")
return
end
if not table.contains(Bashmatic.enemies.targets, area) then
cecho("<firebrick>Bashmatic: No enemies added from the area " .. area .. "<reset>")
return
end
local size = table.size(Bashmatic.enemies.targets.area)
if size == 0 then
cecho("<firebrick>Bashmatic: No enemies added from the area " .. area .. "<reset>")
return
end
if size <= 15 then
-- fits on one page
displayAreaTargetList(area, 1, size, nil, nil)
else
-- paginator
local pages = math.floor(size/15)+1
displayAreaTargetList(area, 1, 15, 1, pages)
end
else
-- not grouped by area
local size = table.size(Bashmatic.enemies.targets)
if size == 0 then
cecho("<firebrick>Bashmatic: No enemies added.<reset>")
return
end
if size <= 15 then
-- fits on one page
displayTargetList(1, size, nil, nil)
else
-- paginator
local pages = math.floor(size/15)+1
displayTargetList(1, 15, 1, pages)
end
end

View File

@ -0,0 +1,54 @@
if Bashmatic.enemies.group then
-- grouped by areas
local area = GetRoomAreaName(GetRoomArea(GetPlayerRoom())) or nil
if area == nil then
cecho("<firebrick>Bashmatic: We got an invalid area.\nWe Got: " .. area .. "<reset>")
return
end
if not table.contains(Bashmatic.enemies.targets, area) then
cecho("<firebrick>Bashmatic: No enemies added from the area " .. area .. "<reset>")
return
end
local size = table.size(Bashmatic.enemies.targets.area)
if size == 0 then
cecho("<firebrick>Bashmatic: No enemies added from the area " .. area .. "<reset>")
return
end
if size <= 15 then
-- fits on one page
displayAreaTargetList(area, 1, size, nil, nil)
else
-- paginator
local pages = math.floor(size/15)+1
if tonumber(matches[2]) > pages then
cecho("<firebrick>Bashmatic: There aren't that many pages. There are only " .. pages .. " pages.<reset>")
return
end
local startIndex = ((tonumber(matches[2]) - 1)*15)+1
local endIndex = startIndex + 14
if endIndex > size then endIndex = size end
displayAreaTargetList(area, startIndex, endIndex, tonumber(matches[2]), pages)
end
else
-- not grouped by area
local size = table.size(Bashmatic.enemies.targets)
if size == 0 then
cecho("<firebrick>Bashmatic: No enemies added.<reset>")
return
end
if size <= 15 then
-- fits on one page
displayTargetList(1, size, nil, nil)
else
-- paginator
local pages = math.floor(size/15)+1
if tonumber(matches[2]) > pages then
cecho("<firebrick>Bashmatic: There aren't that many pages. There are only " .. pages .. " pages.<reset>")
return
end
local startIndex = ((tonumber(matches[2]) - 1)*15)+1
local endIndex = startIndex + 14
if endIndex > size then endIndex = size end
displayTargetList(startIndex, endIndex, tonumber(matches[2]), pages)
end
end

View File

@ -1 +1,7 @@
bashmatic.configs.enabled = not bashmatic.configs.enabled Bashmatic.enabled = not Bashmatic.enabled
if Bashmatic.enabled and table.size(Bashmatic.hunting.events) == 0 and table.size(Bashmatic.enemies.targets) > 1 then
-- we just turned ourself on, we have targets, and no triggers are running
recreateTriggers()
cecho("<DarkSlateBlue>Bashmatic: Bashmatic turned on. Let's go bash some mobs.<reset>")
end

View File

@ -3,7 +3,7 @@
"isActive": "yes", "isActive": "yes",
"isFolder": "no", "isFolder": "no",
"name": "BM Addtarget", "name": "BM Addtarget",
"regex": "^bm add (.*)$", "regex": "^bma (.*)$",
"script": "" "script": ""
}, },
{ {
@ -17,7 +17,7 @@
"isActive": "yes", "isActive": "yes",
"isFolder": "no", "isFolder": "no",
"name": "BM Configset", "name": "BM Configset",
"regex": "^bm config (.*)=(.*)$", "regex": "^bmc (.*)=(.*)$",
"script": "" "script": ""
}, },
{ {
@ -27,6 +27,13 @@
"regex": "^bmt$", "regex": "^bmt$",
"script": "" "script": ""
}, },
{
"isActive": "yes",
"isFolder": "no",
"name": "BM Listtargets Pager",
"regex": "^bmt (\\d+)$",
"script": ""
},
{ {
"isActive": "yes", "isActive": "yes",
"isFolder": "no", "isFolder": "no",
@ -47,5 +54,12 @@
"name": "BM Help", "name": "BM Help",
"regex": "^bm help$", "regex": "^bm help$",
"script": "" "script": ""
},
{
"isActive": "yes",
"isFolder": "no",
"name": "BM Delete",
"regex": "^bmd (\\d+)",
"script": ""
} }
] ]

48
src/resources/LICENSE_MDK.lua Executable file
View 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.
]]

1697
src/resources/ftext.lua Executable file

File diff suppressed because it is too large Load Diff

447
src/resources/ftext_spec.lua Executable file
View 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)

View File

@ -1,207 +1,235 @@
bashmatic = bashmatic or nil local ourTables = require("Bashmatic.ftext").TableMaker
Bashmatic = Bashmatic or {
["commands"] = {
start = nil,
before = nil,
during = nil,
duringTime = nil,
after = nil
},
["death"] = {
phrase = nil,
event = nil
},
["enemies"] = {
group = false,
targets = {}
},
["enabled"] = false,
["bashing"] = false,
["hunting"] = {
events = {}
}
}
function handleInstall(_, name) function handleInstall(_, name)
if name:lower() == "bashmatic" then if name:lower() == "Bashmatic" then
if bashmatic == nil then cecho("<MediumPurple>Bashmatic: Welcome to Bashmatic. See bm help to get started.")
-- it's empty
bashmatic = {}
bashmatic.commands = {
"start" = nil,
"before" = nil,
"during" = nil,
"duringTime" = 2,
"after" = nil
}
bashmatic.death = {
"phrase" = nil,
"event" = nil
}
bashmatic.configs = {
"enemies" = {
"detection" = "inline",
"location" = nil,
"data" = nil
},
"areas" = {
"detection" = nil,
"location" = nil,
"data" = nil
}
}
bashmatic.enabled = false
bashmatic.bashing = false
bashmatic.hunting = {
"targets" = {},
"events" = {}
}
else
-- it's not empty, verify install
local corruptions = 0
if not table.contains(bashmatic, "commands") then
bashmatic.commands = {
"start" = nil,
"before" = nil,
"during" = nil,
"duringTime" = 2,
"after" = nil
}
cecho("<firebrick>BASHMATIC: Potentially corrupt install. Tried to repair bashing commands.<reset>")
corruptions += 1
end
if not table.contains(bashmatic, "death") then
bashmatic.death = {
"phrase" = nil,
"event" = nil
}
cecho("<firebrick>BASHMATIC: Potentially corrupt install. Tried to repair death trigger.<reset>")
corruptions += 1
end
if not table.contains(bashmatic, "configs") then
bashmatic.configs = {
"enemies"{
"detection" = "inline",
"location" = nil,
"data" = nil
},
"areas" = {
"detection" = nil,
"location" = nil,
"data" = nil
}
}
cecho("<firebrick>BASHMATIC: Potentially corrupt install. Tried to repair configuration.<reset>")
corruptions += 1
end
if not table.contains(bashmatic, "enabled") then
bashmatic.enabled = false
cecho("<firebrick>BASHMATIC: Potentially corrupt install. Tried to repair status settings.<reset>")
corruptions += 1
end
if not table.contains(bashmatic, "bashing") then
bashmatic.bashing = false
cecho("<firebrick>BASHMATIC: Potentially corrupt install. Tried to repair status settings.<reset>")
corruptions += 1
end
if not table.contains(bashmatic, "hunting") then
bashmatic.hunting = {
"targets" = {},
"events" = {}
}
cecho("<firebrick>BASHMATIC: Potentially corrupt install. Tried to repair target listings.<reset>")
corruptions += 1
end
if corruptions >= 2 then
cecho("<firebrick>BASHMATIC: Multiple corruptions fixed. You should probably uninstall and reinstall Bashmatic.<reset>")
end
end
end end
end end
registerAnonymousEventHandler("sysInstallPackage", handleInstall) registerAnonymousEventHandler("sysInstallPackage", handleInstall)
function handleShutdown() function handleShutdown()
if bashmatic.configs.death.event ~= nil then killTrigger(bashmatic.configs.death.event) end if Bashmatic.death.event ~= nil then killTrigger(Bashmatic.death.event) end
bashmatic.configs.death.event = nil killBashingTriggers()
bmDisable()
toggleBashing(false)
Bashmatic.death.event = nil
table.save(getMudletHomeDir() .. "/bashmatic.lua", bashmatic) table.save(getMudletHomeDir() .. "/Bashmatic.lua", Bashmatic)
end end
registerAnonymousEventHandler("sysExitEvent", handleShutdown) registerAnonymousEventHandler("sysExitEvent", handleShutdown)
function handleLoadEvent() function handleLoadEvent()
if io.exists(getMudletHomeDir() .. "/bashmatic.lua") then if io.exists(getMudletHomeDir() .. "/Bashmatic.lua") then
table.load(getMudletHomeDir() .. "/bashmatic.lua", bashmatic) table.load(getMudletHomeDir() .. "/Bashmatic.lua", Bashmatic)
end end
if bashmatic.configs.death.phrase ~= nil then if Bashmatic.death.phrase ~= nil then
bashmatic.configs.death.event = tempTrigger(bashmatic.configs.death.phrase,handleMobDeath) Bashmatic.death.event = tempTrigger(Bashmatic.death.phrase,handleMobDeath)
end end
cecho("<DarkSlateBlue>BASHMATIC: Loaded settings. Let's bash some mobs.") cecho("<DarkSlateBlue>Bashmatic: Loaded settings. Let's bash some mobs.")
end end
registerAnonymousEventHandler("sysLoadEvent", handleLoadEvent) registerAnonymousEventHandler("sysLoadEvent", handleLoadEvent)
function bmDisable() function bmDisable()
bashmatic.enabled = false Bashmatic.enabled = false
end end
function toggleBashing(status) function toggleBashing(status)
bashmatic.bashing = status Bashmatic.bashing = status
end end
function handleMobDeath() function handleMobDeath()
if bashmatic.configs.commands.after then if Bashmatic.commands.after then
send(bashmatic.configs.commands.after) send(Bashmatic.commands.after)
end end
toggleBashing(false) toggleBashing(false)
if bashmatic.configs.enabled then if Bashmatic.enabled then
if table.size(Bashmatic.hunting.events) > 0 then
-- active triggers
send("look") send("look")
else
-- recreate triggers and then look
recreateTriggers()
send("look")
end
end end
end end
function handleDuringTick() function handleDuringTick()
send(bashmatic.configs.commands.during) send(Bashmatic.commands.during)
if bashmatic.configs.bashing then tempTimer(bashmatic.configs.commands.duringTime,handleDuringTick) end if Bashmatic.bashing then tempTimer(Bashmatic.commands.duringTime,handleDuringTick) end
end end
-- Functions for handling inline matching -- Functions for handling inline matching
function handleBashingMatches(match) function handleBashingMatches(match)
if not bashmatic.configs.enabled then if not Bashmatic.enabled or Bashmatic.bashing then
-- bashing is disabled, so clear the triggers -- bashing is disabled or we're currently bashing something, so clear the triggers
for _, tid in ipairs(bashmatic.hunting.events) do killBashingTriggers()
killTrigger(tid)
end
bashmatic.hunting.events = {}
else else
if bashmatic.configs.bashing then if Bashmatic.commands.before then send(Bashmatic.commands.before) end
-- we're currently bashing something, so reup the trigger and wait send(Bashmatic.commands.start .. match)
bmCreateTrigger(match) if Bashmatic.commands.during then tempTimer(Bashmatic.commands.duringTime,handleDuringTick) end
else
if bashmatic.configs.commands.before then send(bashmatic.configs.commands.before) end
send(bashmatic.configs.commands.start .. match)
if bashmatic.configs.commands.during then tempTimer(bashmatic.configs.commands.duringTime,handleDuringTick) end
end
end end
end end
function bmCreateTrigger(keyword) function bmCreateTrigger(keyword)
table.insert(bashmatic.hunting.events, tempTrigger(keyword, handleBashingMatches(keyword), 1)) table.insert(Bashmatic.hunting.events, tempTrigger(keyword, handleBashingMatches(keyword), 1))
end end
-- Functions for handling GMCP matching
-- Functions for handling adding targets -- Functions for handling adding targets
function inlineAddTarget(target, area) function inlineAddTarget(target, area)
if area == nil then if area == nil then
cecho("<DarkSlateBlue>BASHMATIC: Added " .. matches[2] .. " to hunting targets.<reset>") cecho("<DarkSlateBlue>Bashmatic: Added " .. target .. " to hunting targets.<reset>")
if not table.contains(bashmatic.hunting.targets, matches[2]) then if not table.contains(Bashmatic.enemies.targets, target) then
table.insert(bashmatic.hunting.targets, matches[2]) table.insert(Bashmatic.enemies.targets, target)
end end
end end
if area ~= nil then if area ~= nil then
cecho("<DarkSlateBlue>BASHMATIC: Added " .. matches[2] .. " to hunting targets in " .. area .. ".<reset>") cecho("<DarkSlateBlue>Bashmatic: Added " .. target .. " to hunting targets in " .. area .. ".<reset>")
if table.contains(bashmatic.hunting.targets, area) then if table.contains(Bashmatic.enemies.targets, area) then
table.insert(bashmatic.hunting.targets.area, matches[2]) table.insert(Bashmatic.enemies.targets.area, target)
else else
bashmatic.hunting.targets.area = {} Bashmatic.enemies.targets.area = {}
table.insert(bashmatic.hunting.targets.area, matches[2]) table.insert(Bashmatic.enemies.targets.area, target)
end end
end end
if not bashmatic.configs.bashing then if not Bashmatic.bashing and Bashmatic.enabled then
if bashmatic.configs.enabled then bmCreateTrigger(target)
bmCreateTrigger(matches[2]) end
end
function recreateTriggers()
if Bashmatic.enemies.group then
-- Grouping enemies by areas
local thisArea = GetRoomAreaName(GetRoomArea(GetPlayerRoom())) or nil
if thisArea == nil then
cecho("<firebrick>Bashmatic: We attempted to locate your area but failed.\nGot: " .. thisArea .. "<reset>")
return
end
if not table.contains(Bashmatic.enemies.targets, thisArea) then
cecho("<firebrick>Bashmatic: You haven't added any enemies for the area " .. thisArea .. "<reset>")
return
end
for _, keyword in ipairs(Bashmatic.enemies.targets.thisArea) do
bmCreateTrigger(keyword)
end
else
-- Not grouping enemies by areas
for _, keyword in ipairs(Bashmatic.enemies.targets) do
bmCreateTrigger(keyword)
end end
end end
end end
function killBashingTriggers()
if table.size(Bashmatic.hunting.events) > 0 then
for _, tid in ipairs(Bashmatic.hunting.events) do
killTrigger(tid)
end
end
Bashmatic.hunting.events = {}
end
function displayTargetList(start, endi, page, pages)
local thisTable = ourTables:new({
title = "Bashmatic Target List",
printTitle = true,
titleColor = "<MediumPurple>",
printHeaders = false,
separateRows = false
})
thisTable:addColumn({
name = "Index",
width = 8,
textColor = "<firebrick>"
})
thisTable:addColumn({
name = "Target",
width = 72,
textColor = "<Slategrey>"
})
for i=start,i<=endi,1 do
thisTable:addRow({
i,
Bashmatic.enemies.targets[i]
})
end
cecho(thisTable:assemble())
if page ~= nil then
cecho("<DarkSlateBlue>Displaying " .. start .. " to " .. endi .. " (Page " .. page .. " of " .. pages .. ")<reset>")
end
end
function displayAreaTargetList(area, start, endi, page, pages)
local thisTable = ourTables:new({
title = "Bashmatic Target List",
printTitle = true,
titleColor = "<MediumPurple>",
printHeaders = false,
separateRows = false
})
thisTable:addColumn({
name = "Index",
width = 8,
textColor = "<firebrick>"
})
thisTable:addColumn({
name = "Target",
width = 72,
textColor = "<Slategrey>"
})
for i=start,i<=endi,1 do
thisTable:addRow({
i,
Bashmatic.enemies.targets.area[i]
})
end
cecho("<MediumPurple>Target Listing for area " .. area .. "<reset>")
if page ~= nil then
cecho("<DarkSlateBlue>Displaying " .. start .. " to " .. endi .. " (Page " .. page .. " of " .. pages .. ")<reset>")
end
end
function squashTargetGroups()
local finalTable = {}
for _, area in ipairs(Bashmatic.enemies.targets) do
if table.size(Bashmatic.enemies.targets.area) > 0 then
for _, enemy in ipairs(Bashmatic.enemies.targets.area) do
table.insert(finalTable,enemy)
end
end
end
Bashmatic.enemies.targets = finalTable
end