from JJMumbleBot.lib.plugin_template import PluginBase from JJMumbleBot.lib.utils.plugin_utils import PluginUtilityService from JJMumbleBot.lib.utils.logging_utils import log from JJMumbleBot.lib.utils.print_utils import PrintMode from JJMumbleBot.settings import global_settings as gs from JJMumbleBot.lib.resources.strings import * import os import random import sqlite3 class Plugin(PluginBase): def __init__(self): super().__init__() from json import loads self.plugin_name = os.path.basename(__file__).rsplit('.')[0] self.metadata = PluginUtilityService.process_metadata(f'plugins/extensions/{self.plugin_name}') self.plugin_cmds = loads(self.metadata.get(C_PLUGIN_INFO, P_PLUGIN_CMDS)) init_db = sqlite3.connect('init.db') init = init_db.cursor() init.execute("CREATE TABLE IF NOT EXISTS v1 (content string, name string UNIQUE)") init.execute("CREATE TABLE IF NOT EXISTS v2 (content string, name string UNIQUE)") init.execute("CREATE TABLE IF NOT EXISTS v3 (content string, name string UNIQUE)") init_db.commit() init_db.close() self.is_running = True log( INFO, f"{self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]} v{self.metadata[C_PLUGIN_INFO][P_PLUGIN_VERS]} Plugin Initialized.", origin=L_STARTUP, print_mode=PrintMode.REG_PRINT.value ) def quit(self): self.is_running = False log( INFO, f"Exiting {self.plugin_name} plugin...", origin=L_SHUTDOWN, print_mode=PrintMode.REG_PRINT.value ) def stop(self): if self.is_running: self.quit() def start(self): if not self.is_running: self.__init__() def cmd_volley(self, data): all_data = data.message.strip().split() try: v = int(all_data[1]) if (v == 1): volley = "v1" elif (v == 2): volley = "v2" elif (v == 3): volley = "v3" else: gs.gui_service.quick_gui("Format: !volley # script actions", text_type='header', box_align='left') return script = str(all_data[2:]) init_db = sqlite3.connect('init.db') cur = init_db.cursor() cur.execute("INSERT INTO " + volley + " values (?,?) ON CONFLICT(name) DO UPDATE SET content=\"" + script + "\"", (str(script),str(gs.mumble_inst.users[data.actor]['name']))) init_db.commit() init_db.close() gs.gui_service.quick_gui(str(gs.mumble_inst.users[data.actor]['name']) + " has scripted volley " + str(v), text_type='header', box_align='left') return except IndexError: gs.gui_service.quick_gui("Format: !volley # script_actions", text_type='header', box_align='left') return def cmd_npcvolley(self, data): all_data = data.message.strip().split() try: v = int(all_data[1]) if (v == 1): volley = "v1" elif (v == 2): volley = "v2" elif (v == 3): volley = "v3" else: gs.gui_service.quick_gui("Format: !npcvolley # name script_actions", text_type='header', box_align='left') return script = str(all_data[3:]) init_db = sqlite3.connect('init.db') cur = init_db.cursor() cur.execute("INSERT INTO " + volley + " values (?,?) ON CONFLICT(name) DO UPDATE SET content=\"" + script + "\"", (str(script),str(all_data[2]))) init_db.commit() init_db.close() gs.gui_service.quick_gui(str(gs.mumble_inst.users[data.actor]['name']) + " has scripted volley " + str(v), text_type='header', box_align='left') return except IndexError: gs.gui_service.quick_gui("Format: !volley # name script_actions", text_type='header', box_align='left') return def reveal_actions(self,volleynum): volley = "v" + str(volleynum) init_db = sqlite3.connect('init.db') cur = init_db.cursor() cur.execute("SELECT * from " + volley + " ORDER BY name DESC") ret_text = "Volley " + str(volleynum) + "
" for row in cur: ret_text += str(row[1]) + ": " + row[0] + "
" init_db.close() gs.gui_service.quick_gui(ret_text, text_type='header', box_align='left') return def cmd_revealv1(self, data): self.reveal_actions(1) return def cmd_revealv2(self, data): self.reveal_actions(2) return def cmd_revealv3(self, data): self.reveal_actions(3) return def whoscript(self,volleynum): volley = "v" + str(volleynum) init_db = sqlite3.connect('init.db') cur = init_db.cursor() cur.execute("SELECT * from " + volley + " ORDER BY name DESC") ret_text = "Volley " + str(volleynum) + "
" for row in cur: ret_text += str(row[1]) + "
" init_db.close() gs.gui_service.quick_gui(ret_text, text_type='header', box_align='left') return def cmd_scriptedv1(self, data): self.whoscript(1) return def cmd_scriptedv2(self, data): self.whoscript(2) return def cmd_scriptedv3(self, data): self.whoscript(3) return def cmd_scripted(self, data): self.whoscript(1) self.whoscript(2) self.whoscript(3) return def clear_volley(self, volleynum): self.del_volley(volleynum, "ThisNonceWillNeverBeUsedAsAName"); def del_volley(self, volleynum, name): volley = "v" + str(volleynum) init_db = sqlite3.connect('init.db') init = init_db.cursor() if (name == "ThisNonceWillNeverBeUsedAsAName"): init.execute("DROP TABLE " + volley) init_db.commit() init.execute("CREATE TABLE IF NOT EXISTS " + volley + " (content string, name string UNIQUE)") gs.gui_service.quick_gui("Purged all for " + volley, text_type='header', box_align='left') else: dbname = "\'" + name + "\'" init.execute("DELETE FROM " + volley + " where name LIKE " + dbname); gs.gui_service.quick_gui("Removed " + name + " from volley " + volley, text_type='header', box_align='left') init_db.commit() init_db.close() def cmd_clearv1(self, data): self.clear_volley(1) return def cmd_clearv2(self, data): self.clear_volley(2) return def cmd_clearv3(self, data): self.clear_volley(3) return def cmd_unscript(self,data): all_data = data.message.strip().split() if(len(all_data) == 2): self.del_volley(1,all_data[1]) self.del_volley(2,all_data[1]) self.del_volley(3,all_data[1]) else: self.del_volley(int(all_data[2]),all_data[1]) return def cmd_bw(self, data): all_data = data.message.strip().split() try: shade = all_data[1][0] if shade == "B" or shade == "b": size = 4 number_of_dice = int(all_data[1][1:]) elif shade == "G" or shade == "g": size = 3 number_of_dice = int(all_data[1][1:]) elif shade == "W" or shade == "w": size = 2 number_of_dice = int(all_data[1][1:]) else: number_of_dice = int(all_data[1]) size = 4 astrodice = 0 if len(all_data) > 2: if all_data[2] == "a" or all_data[2] == "A": astrodice = 1 elif all_data[2] == "aa" or all_data[2] == "AA": astrodice = 2 ret_text = "
Die Pool:
" successes = 0 ones = 0 for i in range(number_of_dice): random.seed(int.from_bytes(os.urandom(8), byteorder="big")) this_die = random.randint(1,6) if i == 0: ret_text += f"{this_die}" else: ret_text += f", {this_die}" if this_die >= size: successes = successes + 1 if this_die == 1: ones = ones + 1 if astrodice > 0: ret_text += f"
Astrology:
" astrosplosions = 0; for i in range(astrodice): this_die = random.randint(1,6) if i == 0: ret_text += f"{this_die}" else: ret_text += f", {this_die}" if this_die >= size: successes = successes + 1 if this_die == 6: astrosplosions = astrosplosions + 1 if this_die == 1: new_die = random.randint(1,6) ret_text += f", {new_die}" if new_die < size: successes = successes - 1 i = 0 while i < astrosplosions: if i == 0: ret_text += f", {this_die}, " else: ret_text += f", {this_die}" if this_die >= size: successes = successes + 1 if this_die == 1: ones = ones + 1 if this_die == 6: astrosplosions += 1 i = i + 1 ret_text += f"
Successes: {successes} , Ones: {ones}" gs.gui_service.quick_gui(ret_text, text_type='header', box_align='left') return except IndexError: gs.gui_service.quick_gui("Format: !bw # [a][a]", text_type='header', box_align='left') return def cmd_bwo(self, data): all_data = data.message.strip().split() try: shade = all_data[1][0] if shade == "B" or shade == "b": size = 4 number_of_dice = int(all_data[1][1:]) elif shade == "G" or shade == "g": size = 3 number_of_dice = int(all_data[1][1:]) elif shade == "W" or shade == "w": size = 2 number_of_dice = int(all_data[1][1:]) else: number_of_dice = int(all_data[1]) size = 4 astrodice = 0 if len(all_data) > 2: if all_data[2] == "a" or all_data[2] == "A": astrodice = 1 elif all_data[2] == "aa" or all_data[2] == "AA": astrodice = 2 ret_text = "
Die Pool:
" successes = 0 ones = 0 explosions = 0 i = 0 while i < number_of_dice: random.seed(int.from_bytes(os.urandom(8), byteorder="big")) this_die = random.randint(1,6) if i == 0: ret_text += f"{this_die}" else: ret_text += f", {this_die}" if this_die >= size: successes = successes + 1 if this_die == 1: ones = ones + 1 if this_die == 6: number_of_dice += 1 explosions = explosions + 1 i = i + 1 if astrodice > 0: ret_text += f"
Astrology:
" astrosplosions = 0; for i in range(astrodice): this_die = random.randint(1,6) if i == 0: ret_text += f"{this_die}" else: ret_text += f", {this_die}" if this_die >= size: successes = successes + 1 if this_die == 6: astrosplosions = astrosplosions + 1 if this_die == 1: new_die = random.randint(1,6) ret_text += f", {new_die}" if new_die < size: successes = successes - 1 i = 0 while i < astrosplosions: if i == 0: ret_text += f", {this_die}, " else: ret_text += f", {this_die}" if this_die >= size: successes = successes + 1 if this_die == 1: ones = ones + 1 if this_die == 6: astrosplosions += 1 ret_text += f"
Successes: {successes} , Ones: {ones} , Explosions: {explosions}" gs.gui_service.quick_gui(ret_text, text_type='header', box_align='left') return except IndexError: gs.gui_service.quick_gui("!bwo # [a][a]", text_type='header', box_align='left') return def cmd_advancement(self, data): gs.gui_service.quick_gui("
Routine Difficult Challenging
1D Ob1 * Ob 1* Ob 2+
2D Ob1 Ob 2 Ob 3+
3D Ob1-2 Ob 3 Ob 4+
4D Ob1-2 Ob 3-4 Ob 5+
5D Ob1-3 Ob 4-5 Ob 6+
6D Ob1-4 Ob 5-6 Ob 7+
7D Ob1-4 Ob 5-7 Ob 8+
8D Ob1-5 Ob 6-8 Ob 9+
9D Ob1-6 Ob 7-9 Ob 10+
10D Ob1-7 Ob 8-10 Ob 11+
11D Ob1-8 Ob 9-11 Ob 12+
12D Ob1-9 Ob 10-12 Ob 13+
13D Ob1-10 Ob 11-13 Ob 14+
14D Ob1-11 Ob 12-14 Ob 15+
15D Ob1-12 Ob 13-15 Ob 16+
16D Ob1-13 Ob 14-16 Ob 17+
17D Ob1-14 Ob 15-17 Ob 18+
18D Ob1-15 Ob 16-18 Ob 19+
", text_type='header', box_align='left') return def cmd_prayers(self, data): gs.gui_service.quick_gui("
ObEffect
2Boon: Open end any one ability for the rest of the scene.
3Blessing: Add +1D to one health, steel, stat, or skill test (duration Intent)
3Curse: Add +1 Ob to a single Ability for a single target, for a scene.
4Aid: Add +1D plus an additional +1D per margain of success (maximum +3D) to any stat, skill, health, or steel test. You may cast this at the beginning of the scene and save it until needed, but must pick the stat/skill/whatever at casting time.
4-6Hinderance: Immobalize a foe for a number of Fight actions equal to half your Faith. Base Ob is 4 and +1 per additional Foe.
5Guidance: You can find the correct path. Literally or metaphorically.
5Minor Miracle: When it is dark, we pray for light. When sorcerers chant, we pray their spells be broken. When the Blade is snapped, we pray that it be made whole. When blood ebbs from the wound, we pray that it be closed.
5Purification: With the touch of a hand, drive out rot and lesser Evil Spirirts (Strength/Will B5 or lower).
6Consecration: A lengthy prayer. Bar Spirits and Daemons whose Will is less than the user\'s Faith.
7Inspiration: Reveal what the priest wishes to know to them. Also often what they did not intend to learn.
8Intercession: Bring the devotee from danger. Or bring the danger from the devotee.
10Miracle: When all hope is lost, when the cataclysm has come, we pray for the divine to manifest and save us. This is the big one - the column of scouring fire, the parting of the seas, the raging storm that destroys the fleet.
", text_type='header', box_align='left') return def cmd_secondsight(self, data): gs.gui_service.quick_gui("
Ob 1high power magic (major miracles, Mjolnir, the Burning Wheel, Ob 10 spells, Strength 10 spirits, etc.)
Ob 5moderately-powered magic (minor miracles, Ob 5 spells, a risen corpse, the Belt of Flying, Dragon Slaying Sword, Spirit Weapons, Strength 5-spirits)
Ob 8low power magic (Red Spectacles, Bless/Curse, Ob 2 spells, Strength 2 spirits etc.)
", text_type='header', box_align='left') return def cmd_touchofages(self, data): gs.gui_service.quick_gui("
Ob 1Type/name of object
Ob 2Age of object
Ob 3Length of the time the object has been in its current location
Ob 4Recent events surrounding the object that left physical evidence
Ob 5Recent events that left no physical mark
Ob 6Past events that left their mark
Ob 7Past events that left no mark
", text_type='header', box_align='left') return def cmd_aurareading(self, data): gs.gui_service.quick_gui("
Detecting if the subject is alive, dead, from this plane or anotherOb 1
Reading an aura traitOb 1
Reading moodOb 2
Seeing a character traitOb 3
Seeing a die or call-on traitOb 4
Sensing a person's intentOb 4
Seeing an InstinctOb 6
Seeing a BeliefOb 7
Seeing a character's pastOb 8
Seeing a character's futureOb 9
Reading an object to see if it is magical or mundaneOb 1
Reading a school of magicOb 2
Deciphering a facet of a spell or enchantmentOb 3
Naming a spell as it is being castOb 6
Detecting the presence and nature of a spiritOb 10 - strength
", text_type='header', box_align='left') return def cmd_sessionend(self, data): gs.gui_service.quick_gui("
Name Earns/Type Description
Belief 1 Fate Driving the game forward with a Belief
Instinct 1 Fate Playing an Instinct makes the character's life difficult
Trait 1 Fate Invoking a trait that sends the story in an unforeseen direction
Humour 1 Fate For an in-character game-stopper
Right Skill, Right Time 1 Fate For having a skill to make the story go
Embodiment 1 Persona For really good or distinctive roleplaying
Moldbreaker 1 Persona For going beyond the bounds of the character
Workhorse 1 Persona For doing all the work of the scenario
MVP 1 Persona For being the crucial element of success
Personal Goals 1 Persona Revenge, triumph, seduction, victory
Greater Goals 1 Deeds Accomplishing goals bigger than you!
Beyond the Call 1 Deeds Helping, no matter the cost
", text_type='header', box_align='left') def cmd_obs(self, data): gs.gui_service.quick_gui("
Ob 1A simple act done with litttle thought
Ob 2An act performed routinely at your job
Ob 3An act you can accomplish if you concentrate
Ob 4A risky act
Ob 5An act that requires expertise
Ob 6An act that requires a heroic effort
Ob 7An improbable feat
Ob 8An act requiring preternatural ability or a lot of help
Ob 9An act deemed nearly impossible
Ob 10A miracle
", text_type='header', box_align='left')