Sjshovan
6 years ago
commit
dce7b5be54
5 changed files with 731 additions and 0 deletions
@ -0,0 +1,25 @@ |
|||||||
|
Copyright © 2018, Sjshovan (Apogee) |
||||||
|
All rights reserved. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without |
||||||
|
modification, are permitted provided that the following conditions are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright |
||||||
|
notice, this list of conditions and the following disclaimer. |
||||||
|
* Redistributions in binary form must reproduce the above copyright |
||||||
|
notice, this list of conditions and the following disclaimer in the |
||||||
|
documentation and/or other materials provided with the distribution. |
||||||
|
* Neither the name of Mount Muzzle nor the |
||||||
|
names of its contributors may be used to endorse or promote products |
||||||
|
derived from this software without specific prior written permission. |
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||||
|
DISCLAIMED. IN NO EVENT SHALL Sjshovan (Apogee) BE LIABLE FOR ANY |
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
@ -0,0 +1,196 @@ |
|||||||
|
**Author:** [Sjshovan (Apogee)](https://github.com/Ap0gee) |
||||||
|
**Version:** v0.9.0 |
||||||
|
|
||||||
|
|
||||||
|
# Mount Muzzle |
||||||
|
|
||||||
|
> An Ashita v3 addon that allows the user to change or remove the default mount music in Final Fantasy 11 Online. |
||||||
|
|
||||||
|
|
||||||
|
### Table of Contents |
||||||
|
|
||||||
|
- [Prerequisites](#prerequisites) |
||||||
|
- [Installation](#installation) |
||||||
|
- [Aliases](#aliases) |
||||||
|
- [Usage](#usage) |
||||||
|
- [Commands](#commands) |
||||||
|
- [Support](#support) |
||||||
|
- [Change Log](#change-log) |
||||||
|
- [Known Issues](#known-issues) |
||||||
|
- [TODOs](#todos) |
||||||
|
- [License](#license) |
||||||
|
|
||||||
|
___ |
||||||
|
### Prerequisites |
||||||
|
1. [Final Fantasy 11 Online](http://www.playonline.com/ff11us/index.shtml) |
||||||
|
2. [Ashita v3](https://www.ashitaxi.com/) |
||||||
|
|
||||||
|
___ |
||||||
|
### Installation |
||||||
|
|
||||||
|
**Ashita:** |
||||||
|
1. Navigate to the `Addons` section on the left. |
||||||
|
2. Locate the `MountMuzzle` addon. |
||||||
|
3. Click the flashing download button near the upper-right corner. |
||||||
|
|
||||||
|
**Manual:** |
||||||
|
1. Navigate to <https://github.com/Ap0gee/Ashita-MountMuzzle>. |
||||||
|
2. Click on `Releases`. |
||||||
|
3. Click on the `Source code (zip)` link within the latest release to download. |
||||||
|
4. Extract the zipped folder to `Ashita_v3/addons/`. |
||||||
|
5. Rename the folder to remove the version tag (`-v0.9.0`). The folder should be named `MountMuzzle`. |
||||||
|
|
||||||
|
**Autoloading:** |
||||||
|
|
||||||
|
By default you will need to manually load this addon each time you restart the game. |
||||||
|
To autoload MountMuzzle so that it is always ready for use upon entering the game, follow these steps: |
||||||
|
|
||||||
|
1. Navigate to the `Ashita_v3/scripts/` directory. |
||||||
|
2. Open the `Default.txt` file. |
||||||
|
3. Locate the `Load Common Addons` section. |
||||||
|
4. add the following line: `/addon load mountmuzzle`. |
||||||
|
|
||||||
|
___ |
||||||
|
### Aliases |
||||||
|
The following aliases are available to Mount Muzzle commands: |
||||||
|
|
||||||
|
**mountmuzzle:** muzzle | mm |
||||||
|
**list:** l |
||||||
|
**set:** s |
||||||
|
**get:** g |
||||||
|
**default:** d |
||||||
|
**unload:** u |
||||||
|
**reload:** r |
||||||
|
**about:** a |
||||||
|
**silent:** s |
||||||
|
**mount:** m |
||||||
|
**chocobo:** c |
||||||
|
**zone:** z |
||||||
|
**help:** h |
||||||
|
|
||||||
|
___ |
||||||
|
### Usage |
||||||
|
|
||||||
|
Manually load the addon by using the following command: |
||||||
|
|
||||||
|
/addon load mountmuzzle |
||||||
|
|
||||||
|
___ |
||||||
|
### Commands |
||||||
|
|
||||||
|
**help** |
||||||
|
|
||||||
|
Displays available Mount Muzzle commands. Below are the equivalent ways of calling the command: |
||||||
|
|
||||||
|
/mountmuzzle help |
||||||
|
/muzzle help |
||||||
|
/mm help |
||||||
|
/mountmuzzle h |
||||||
|
/muzzle h |
||||||
|
/mm h |
||||||
|
|
||||||
|
**list** |
||||||
|
|
||||||
|
Displays the available muzzle types. Below are the equivalent ways of calling the command: |
||||||
|
|
||||||
|
/mountmuzzle list |
||||||
|
/muzzle list |
||||||
|
/mm list |
||||||
|
/mm l |
||||||
|
|
||||||
|
**set _\<muzzle>_** |
||||||
|
|
||||||
|
Sets the current muzzle to the given muzzle type. This command takes a single argument represented by `<muzzle>`. Below are the equivalent ways of calling the command: |
||||||
|
|
||||||
|
/mountmuzzle set <muzzle> |
||||||
|
/muzzle set <muzzle> |
||||||
|
/mm set <muzzle> |
||||||
|
/mm s <muzzle> |
||||||
|
|
||||||
|
Here are some usage examples for the **set _\<muzzle>_** command: `mm set silent` and `muzzle set zone` etc... |
||||||
|
|
||||||
|
**get** |
||||||
|
|
||||||
|
Displays the current muzzle that is set. Below are the equivalent ways of calling the command: |
||||||
|
|
||||||
|
/mountmuzzle get |
||||||
|
/muzzle get |
||||||
|
/mm get |
||||||
|
/mm g |
||||||
|
|
||||||
|
**default** |
||||||
|
|
||||||
|
Sets the current muzzle to the default muzzle type: `Silent`. Below are the equivalent ways of calling the command: |
||||||
|
|
||||||
|
/mountmuzzle default |
||||||
|
/muzzle default |
||||||
|
/mm default |
||||||
|
/mm d |
||||||
|
|
||||||
|
**unload** |
||||||
|
|
||||||
|
Unloads the Mount Muzzle addon. Below are the equivalent ways of calling the command: |
||||||
|
|
||||||
|
/mountmuzzle unload |
||||||
|
/muzzle unload |
||||||
|
/mm unload |
||||||
|
/mm u |
||||||
|
|
||||||
|
**reload** |
||||||
|
|
||||||
|
Reloads the Mount Muzzle addon. Below are the equivalent ways of calling the command: |
||||||
|
|
||||||
|
/mountmuzzle reload |
||||||
|
/muzzle reload |
||||||
|
/mm reload |
||||||
|
/mm r |
||||||
|
|
||||||
|
**about** |
||||||
|
|
||||||
|
Displays information about the Mount Muzzle addon. Below are the equivalent ways of calling the command: |
||||||
|
|
||||||
|
/mountmuzzle about |
||||||
|
/muzzle about |
||||||
|
/mm about |
||||||
|
/mm a |
||||||
|
|
||||||
|
___ |
||||||
|
### Support |
||||||
|
**Having Issues with this addon?** |
||||||
|
* Please let me know [here](https://github.com/Ap0gee/Ashita-MountMuzzle/issues/new). |
||||||
|
|
||||||
|
**Have something to say?** |
||||||
|
* Send me some feedback here: <sjshovan@gmail.com> |
||||||
|
|
||||||
|
**Want to stay in the loop with my work?** |
||||||
|
* You can follow me at: <https://twitter.com/Sjshovan> |
||||||
|
|
||||||
|
**Want to show your love and help me make more awesome stuff?** |
||||||
|
* You can do so here: <https://www.paypal.me/Sjshovan> |
||||||
|
|
||||||
|
___ |
||||||
|
### Change Log |
||||||
|
|
||||||
|
**v0.9.0** - 12/4/2018 |
||||||
|
- Initial release |
||||||
|
|
||||||
|
___ |
||||||
|
### Known Issues |
||||||
|
|
||||||
|
- **Issue:** If Mount Muzzle is selected to automatically load and the player is mounted upon login, there is a significant delay before the chosen music will begin to play. |
||||||
|
- **Issue:** Upon changing zones the default music can be heard for a moment before the chosen music begins to play. |
||||||
|
- **Issue:** Unable to correctly set mount music to original if Mount Muzzle is unloaded while mounted. |
||||||
|
|
||||||
|
___ |
||||||
|
### TODOs |
||||||
|
|
||||||
|
- **TODO:** Investigate alternative methods for music change as packet injection/swap allows the player to hear the default music upon zone change and login, regardless of chosen music. |
||||||
|
- **TODO:** Investigate methods for determining which mount type the player is on when loading/unloading Mount Muzzle. |
||||||
|
___ |
||||||
|
|
||||||
|
### License |
||||||
|
|
||||||
|
Copyright © 2018, [Sjshovan (Apogee)](https://github.com/Ap0gee). |
||||||
|
Released under the [BSD License](LICENSE). |
||||||
|
|
||||||
|
*** |
@ -0,0 +1,120 @@ |
|||||||
|
--[[ |
||||||
|
Copyright © 2018, Sjshovan (Apogee) |
||||||
|
All rights reserved. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without |
||||||
|
modification, are permitted provided that the following conditions are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright |
||||||
|
notice, this list of conditions and the following disclaimer. |
||||||
|
* Redistributions in binary form must reproduce the above copyright |
||||||
|
notice, this list of conditions and the following disclaimer in the |
||||||
|
documentation and/or other materials provided with the distribution. |
||||||
|
* Neither the name of Mount Muzzle nor the |
||||||
|
names of its contributors may be used to endorse or promote products |
||||||
|
derived from this software without specific prior written permission. |
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||||
|
DISCLAIMED. IN NO EVENT SHALL Sjshovan (Apogee) BE LIABLE FOR ANY |
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
--]] |
||||||
|
|
||||||
|
packets = { |
||||||
|
inbound = { |
||||||
|
music_change = { |
||||||
|
id = 0x05F, |
||||||
|
offsets = { |
||||||
|
type = 0x06 |
||||||
|
} |
||||||
|
}, |
||||||
|
zone_update = { |
||||||
|
id = 0x00A |
||||||
|
} |
||||||
|
}, |
||||||
|
outbound = { |
||||||
|
action = { |
||||||
|
id = 0x1A, |
||||||
|
categories = { |
||||||
|
mount = 0x1A, |
||||||
|
unmount = 0x12 |
||||||
|
}, |
||||||
|
} |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
player = { |
||||||
|
statuses = { |
||||||
|
types = { |
||||||
|
mount = 1072 |
||||||
|
}, |
||||||
|
mounted = { |
||||||
|
chocobo = 5, |
||||||
|
mount = 85 |
||||||
|
} |
||||||
|
}, |
||||||
|
buffs = { |
||||||
|
reiveMark = 511, |
||||||
|
mounted = 252 |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
music = { |
||||||
|
songs = { |
||||||
|
silent = 0x5B, |
||||||
|
mount = 0x54, |
||||||
|
chocobo = 0xD4, |
||||||
|
zone = 0x00, |
||||||
|
}, |
||||||
|
types = { |
||||||
|
mount = 84, |
||||||
|
idle_day = 0, |
||||||
|
idle_night = 1 |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
colors = { |
||||||
|
primary = "\31\200%s", |
||||||
|
secondary = "\31\207%s", |
||||||
|
info = "\31\1%s", |
||||||
|
warn = "\31\140%s", |
||||||
|
danger = "\31\167%s", |
||||||
|
success = "\31\158%s" |
||||||
|
} |
||||||
|
|
||||||
|
muzzles = { |
||||||
|
silent = { |
||||||
|
name = 'silent', |
||||||
|
song = music.songs.silent, |
||||||
|
description = 'No Music (Default)' |
||||||
|
}, |
||||||
|
mount = { |
||||||
|
name = 'mount', |
||||||
|
song = music.songs.mount, |
||||||
|
description = 'Mount Music' |
||||||
|
}, |
||||||
|
chocobo = { |
||||||
|
name = 'chocobo', |
||||||
|
song = music.songs.chocobo, |
||||||
|
description = 'Chocobo Music' |
||||||
|
}, |
||||||
|
zone = { |
||||||
|
name = 'zone', |
||||||
|
song = music.songs.zone, |
||||||
|
description = 'Current Zone Music' |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
packets = packets, |
||||||
|
player = player, |
||||||
|
music = music, |
||||||
|
colors = colors, |
||||||
|
muzzles = muzzles |
||||||
|
} |
@ -0,0 +1,99 @@ |
|||||||
|
--[[ |
||||||
|
Copyright © 2018, Sjshovan (Apogee) |
||||||
|
All rights reserved. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without |
||||||
|
modification, are permitted provided that the following conditions are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright |
||||||
|
notice, this list of conditions and the following disclaimer. |
||||||
|
* Redistributions in binary form must reproduce the above copyright |
||||||
|
notice, this list of conditions and the following disclaimer in the |
||||||
|
documentation and/or other materials provided with the distribution. |
||||||
|
* Neither the name of Mount Muzzle nor the |
||||||
|
names of its contributors may be used to endorse or promote products |
||||||
|
derived from this software without specific prior written permission. |
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||||
|
DISCLAIMED. IN NO EVENT SHALL Sjshovan (Apogee) BE LIABLE FOR ANY |
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
--]] |
||||||
|
|
||||||
|
local colors = require("constants").colors |
||||||
|
|
||||||
|
function buildHelpCommandEntry(command, description) |
||||||
|
local short_name = strColor("mm", colors.primary) |
||||||
|
local command = strColor(command, colors.secondary) |
||||||
|
local sep = strColor("=>", colors.primary) |
||||||
|
local description = strColor(description, colors.info) |
||||||
|
|
||||||
|
return string.format("%s %s %s %s", short_name, command, sep, description) |
||||||
|
end |
||||||
|
|
||||||
|
function buildHelpTypeEntry(name, description) |
||||||
|
local name = strColor(name, colors.secondary) |
||||||
|
local sep = strColor("=>", colors.primary) |
||||||
|
local description = strColor(description, colors.info) |
||||||
|
|
||||||
|
return string.format("%s %s %s", name, sep, description) |
||||||
|
end |
||||||
|
|
||||||
|
function buildHelpTitle(context) |
||||||
|
local context = strColor(context, colors.danger) |
||||||
|
|
||||||
|
return string.format("%s Help: %s", _addon.name, context) |
||||||
|
end |
||||||
|
|
||||||
|
function buildHelpSeperator(character, count) |
||||||
|
local sep = '' |
||||||
|
|
||||||
|
for i = 1, count do |
||||||
|
sep = sep .. character |
||||||
|
end |
||||||
|
|
||||||
|
return strColor(sep, colors.warn) |
||||||
|
end |
||||||
|
|
||||||
|
function buildCommandResponse(message, success) |
||||||
|
local response_color = colors.success |
||||||
|
local response_type = 'Success' |
||||||
|
|
||||||
|
if not success then |
||||||
|
response_type = 'Error' |
||||||
|
response_color = colors.danger |
||||||
|
end |
||||||
|
|
||||||
|
return string.format("%s: %s", |
||||||
|
strColor(response_type, response_color), strColor(message, colors.info) |
||||||
|
) |
||||||
|
end |
||||||
|
|
||||||
|
function displayResponse(response, color) |
||||||
|
color = color or colors.info |
||||||
|
print(strColor(response, color)) |
||||||
|
end |
||||||
|
|
||||||
|
function strColor(str, color) |
||||||
|
return string.format(color, str) |
||||||
|
end |
||||||
|
|
||||||
|
function ucFirst(str) |
||||||
|
return str:gsub("^%l", string.upper) |
||||||
|
end |
||||||
|
|
||||||
|
function tableContains(tab, val) |
||||||
|
for index, value in pairs(tab) do |
||||||
|
if value == val then |
||||||
|
return true |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
return false |
||||||
|
end |
@ -0,0 +1,291 @@ |
|||||||
|
--[[ |
||||||
|
Copyright © 2018, Sjshovan (Apogee) |
||||||
|
All rights reserved. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without |
||||||
|
modification, are permitted provided that the following conditions are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright |
||||||
|
notice, this list of conditions and the following disclaimer. |
||||||
|
* Redistributions in binary form must reproduce the above copyright |
||||||
|
notice, this list of conditions and the following disclaimer in the |
||||||
|
documentation and/or other materials provided with the distribution. |
||||||
|
* Neither the name of Mount Muzzle nor the |
||||||
|
names of its contributors may be used to endorse or promote products |
||||||
|
derived from this software without specific prior written permission. |
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||||
|
DISCLAIMED. IN NO EVENT SHALL Sjshovan (Apogee) BE LIABLE FOR ANY |
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
--]] |
||||||
|
|
||||||
|
_addon.name = 'Mount Muzzle' |
||||||
|
_addon.description = 'Change or remove the default mount music.' |
||||||
|
_addon.author = 'Sjshovan (Apogee) [email protected]' |
||||||
|
_addon.version = '0.9.0' |
||||||
|
_addon.commands = {'/mountmuzzle', '/muzzle', '/mm'} |
||||||
|
|
||||||
|
require('constants') |
||||||
|
require('helpers') |
||||||
|
|
||||||
|
require 'common' |
||||||
|
|
||||||
|
local default_settings = { |
||||||
|
muzzle = "silent" |
||||||
|
} |
||||||
|
|
||||||
|
local settings = default_settings; |
||||||
|
|
||||||
|
local defaults = { |
||||||
|
muzzle = muzzles.silent.name |
||||||
|
} |
||||||
|
|
||||||
|
local needs_inject = false |
||||||
|
|
||||||
|
local help = { |
||||||
|
commands = { |
||||||
|
buildHelpSeperator('=', 26), |
||||||
|
buildHelpTitle('Commands'), |
||||||
|
buildHelpSeperator('=', 26), |
||||||
|
buildHelpCommandEntry('list', 'Display the available muzzle types.'), |
||||||
|
buildHelpCommandEntry('set <muzzle>', 'Set the current muzzle to the given muzzle type.'), |
||||||
|
buildHelpCommandEntry('get', 'Display the current muzzle.'), |
||||||
|
buildHelpCommandEntry('default', 'Set the current muzzle to the default (Silent).'), |
||||||
|
buildHelpCommandEntry('unload', 'Unload Mount Muzzle.'), |
||||||
|
buildHelpCommandEntry('reload', 'Reload Mount Muzzle.'), |
||||||
|
buildHelpCommandEntry('about', 'Display information about Mount Muzzle.'), |
||||||
|
buildHelpCommandEntry('help', 'Display Mount Muzzle commands.'), |
||||||
|
buildHelpSeperator('=', 26), |
||||||
|
}, |
||||||
|
types = { |
||||||
|
buildHelpSeperator('=', 23), |
||||||
|
buildHelpTitle('Types'), |
||||||
|
buildHelpSeperator('=', 23), |
||||||
|
buildHelpTypeEntry(muzzles.silent.name, muzzles.silent.description), |
||||||
|
buildHelpTypeEntry(muzzles.mount.name, muzzles.mount.description), |
||||||
|
buildHelpTypeEntry(muzzles.chocobo.name, muzzles.chocobo.description), |
||||||
|
buildHelpTypeEntry(muzzles.zone.name, muzzles.zone.description), |
||||||
|
buildHelpSeperator('=', 23), |
||||||
|
}, |
||||||
|
about = { |
||||||
|
buildHelpSeperator('=', 23), |
||||||
|
buildHelpTitle('About'), |
||||||
|
buildHelpSeperator('=', 23), |
||||||
|
buildHelpTypeEntry('Name', _addon.name), |
||||||
|
buildHelpTypeEntry('Description', _addon.description), |
||||||
|
buildHelpTypeEntry('Author', _addon.author), |
||||||
|
buildHelpTypeEntry('Version', _addon.version), |
||||||
|
buildHelpSeperator('=', 23), |
||||||
|
}, |
||||||
|
aliases = { |
||||||
|
muzzles = { |
||||||
|
s = muzzles.silent.name, |
||||||
|
m = muzzles.mount.name, |
||||||
|
c = muzzles.chocobo.name, |
||||||
|
z = muzzles.zone.name |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function display_help(table_help) |
||||||
|
for index, command in pairs(table_help) do |
||||||
|
displayResponse(command) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
function getMuzzle() |
||||||
|
return settings.muzzle |
||||||
|
end |
||||||
|
|
||||||
|
function getPlayerBuffs() |
||||||
|
return AshitaCore:GetDataManager():GetPlayer():GetBuffs() |
||||||
|
end |
||||||
|
|
||||||
|
function resolveCurrentMuzzle() |
||||||
|
local current_muzzle = getMuzzle() |
||||||
|
|
||||||
|
if not muzzleValid(current_muzzle) then |
||||||
|
current_muzzle = muzzles.silent.name |
||||||
|
setMuzzle(current_muzzle) |
||||||
|
displayResponse( |
||||||
|
string.format( |
||||||
|
'Note: Muzzle found in settings was not valid and is now set to the default (%s\30\1).', |
||||||
|
strColor('Silent', colors.secondary) |
||||||
|
), |
||||||
|
colors.warn |
||||||
|
) |
||||||
|
end |
||||||
|
|
||||||
|
return muzzles[current_muzzle] |
||||||
|
end |
||||||
|
|
||||||
|
function setMuzzle(muzzle) |
||||||
|
settings.muzzle = muzzle |
||||||
|
ashita.settings.save(_addon.path .. '/settings/settings.json', settings); |
||||||
|
end |
||||||
|
|
||||||
|
function playerInReive() |
||||||
|
return tableContains(getPlayerBuffs(), player.buffs.reiveMark) |
||||||
|
end |
||||||
|
|
||||||
|
function playerIsMounted() |
||||||
|
local entity = AshitaCore:GetDataManager():GetEntity() |
||||||
|
|
||||||
|
if entity then |
||||||
|
return tableContains( |
||||||
|
player.statuses.mounted, entity:GetStatus(player.statuses.types.mount) |
||||||
|
) or tableContains( |
||||||
|
getPlayerBuffs(), player.buffs.mounted |
||||||
|
) |
||||||
|
end |
||||||
|
|
||||||
|
return false |
||||||
|
end |
||||||
|
|
||||||
|
function muzzleValid(muzzle) |
||||||
|
return muzzles[muzzle] ~= nil |
||||||
|
end |
||||||
|
|
||||||
|
function injectMuzzleMusic() |
||||||
|
injectMusic(music.types.mount, resolveCurrentMuzzle().song) |
||||||
|
end |
||||||
|
|
||||||
|
function injectMusic(bgmType, songID) |
||||||
|
local bgm_packet = struct.pack("bbbbbbb", |
||||||
|
0x5F, 0x04, 0x00, 0x00, 0x04, 0x00, songID, 0x00 |
||||||
|
):totable(); |
||||||
|
AddIncomingPacket(packets.inbound.music_change.id, bgm_packet) |
||||||
|
end |
||||||
|
|
||||||
|
function requestInject() |
||||||
|
needs_inject = true |
||||||
|
end |
||||||
|
|
||||||
|
function handleInjectionNeeds() |
||||||
|
if needs_inject and playerIsMounted() then |
||||||
|
injectMuzzleMusic() |
||||||
|
needs_inject = false; |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
function tryInject() |
||||||
|
requestInject() |
||||||
|
handleInjectionNeeds() |
||||||
|
end |
||||||
|
|
||||||
|
ashita.register_event('load', function() |
||||||
|
settings = ashita.settings.load_merged( |
||||||
|
_addon.path .. '/settings/settings.json', settings |
||||||
|
) |
||||||
|
tryInject(); |
||||||
|
end) |
||||||
|
|
||||||
|
ashita.register_event('unload', function() |
||||||
|
injectMusic(music.types.mount, muzzles.zone.song) |
||||||
|
end) |
||||||
|
|
||||||
|
ashita.register_event('command', function(command, ntype) |
||||||
|
|
||||||
|
local command_args = command:lower():args() |
||||||
|
|
||||||
|
if not tableContains(_addon.commands, command_args[1]) then |
||||||
|
return false |
||||||
|
end |
||||||
|
|
||||||
|
local respond = false |
||||||
|
local response_message = '' |
||||||
|
local success = true |
||||||
|
|
||||||
|
if command_args[2] == 'list' or command_args[2] == 'l' then |
||||||
|
display_help(help.types) |
||||||
|
|
||||||
|
elseif command_args[2] == 'set' or command_args[2] == 's' then |
||||||
|
respond = true |
||||||
|
|
||||||
|
local muzzle = tostring(command_args[3]):lower() |
||||||
|
local from_alias = help.aliases.muzzles[muzzle] |
||||||
|
|
||||||
|
if (from_alias ~= nil) then |
||||||
|
muzzle = from_alias |
||||||
|
end |
||||||
|
|
||||||
|
if not muzzleValid(muzzle) then |
||||||
|
success = false |
||||||
|
response_message = 'Muzzle type not recognized.' |
||||||
|
else |
||||||
|
requestInject() |
||||||
|
setMuzzle(muzzle) |
||||||
|
response_message = string.format( |
||||||
|
'Updated current muzzle to %s.', |
||||||
|
strColor(ucFirst(muzzle), colors.secondary) |
||||||
|
) |
||||||
|
end |
||||||
|
|
||||||
|
elseif command_args[2] == 'get' or command_args[2] == 'g' then |
||||||
|
respond = true |
||||||
|
response_message = string.format( |
||||||
|
'Current muzzle is %s.', |
||||||
|
strColor(ucFirst(getMuzzle()), colors.secondary) |
||||||
|
) |
||||||
|
|
||||||
|
elseif command_args[2] == 'default' or command_args[2] == 'd' then |
||||||
|
respond = true |
||||||
|
requestInject() |
||||||
|
|
||||||
|
setMuzzle(muzzles.silent.name) |
||||||
|
response_message = string.format( |
||||||
|
'Updated current muzzle to the default (%s\30\1).', |
||||||
|
strColor('Silent', colors.secondary) |
||||||
|
) |
||||||
|
|
||||||
|
elseif command_args[2] == 'reload' or command_args[2] == 'r' then |
||||||
|
AshitaCore:GetChatManager():QueueCommand('/addon reload mountmuzzle', 1) |
||||||
|
|
||||||
|
elseif command_args[2] == 'unload' or command_args[2] == 'u' then |
||||||
|
respond = true |
||||||
|
response_message = 'Thank you for using Mount Muzzle. Goodbye.' |
||||||
|
AshitaCore:GetChatManager():QueueCommand('/addon unload mountmuzzle', 1) |
||||||
|
|
||||||
|
elseif command_args[2] == 'about' or command_args[2] == 'a' then |
||||||
|
display_help(help.about) |
||||||
|
|
||||||
|
elseif command_args[2] == 'help' or command_args[2] == 'h' then |
||||||
|
display_help(help.commands) |
||||||
|
|
||||||
|
else |
||||||
|
display_help(help.commands) |
||||||
|
|
||||||
|
end |
||||||
|
|
||||||
|
if respond then |
||||||
|
displayResponse( |
||||||
|
buildCommandResponse(response_message, success) |
||||||
|
) |
||||||
|
end |
||||||
|
|
||||||
|
handleInjectionNeeds() |
||||||
|
|
||||||
|
return false |
||||||
|
end) |
||||||
|
|
||||||
|
ashita.register_event('incoming_packet', function(id, size, packet, modified_packet, blocked_packet) |
||||||
|
if id == packets.inbound.music_change.id then |
||||||
|
local music_type = struct.unpack('H', packet, packets.inbound.music_change.offsets.type + 1) |
||||||
|
|
||||||
|
if music_type == music.types.mount then |
||||||
|
injectMusic(music.types.mount, resolveCurrentMuzzle().song) |
||||||
|
return true |
||||||
|
end |
||||||
|
|
||||||
|
tryInject() |
||||||
|
end |
||||||
|
|
||||||
|
return false |
||||||
|
end) |
Loading…
Reference in new issue