Skip to content

Instantly share code, notes, and snippets.

@Sama34
Last active May 9, 2022 23:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sama34/4c8f563c272c394855f424695471dc54 to your computer and use it in GitHub Desktop.
Save Sama34/4c8f563c272c394855f424695471dc54 to your computer and use it in GitHub Desktop.
Dice Roller MyCode 1.2.0
<?php
/**
* Dice Roller MyCode
* Copyright 2017 Shinka, All Rights Reserved
*
* License: http://www.mybb.com/about/license
*
*/
global $alias, $patterns;
$patterns = array(
// [roll=low-high] | e.g. [roll=1-6]
'/\[roll=([\"\']?)(\d+)-(\d+)(([\+\-]\d+)?)\1\]/',
// [roll=(N)dS(+/-F)] | e.g. [roll=d6] | [roll=1d6] | [roll=1d6+10] | [roll=1d6-10]
'/\[roll=([\"\']?)(\d*)d(\d+)([\+\-]\d+)?\1\]/',
// [roll=weighed list] | e.g. [roll=2,2,1]
'/\[roll=([\"\']?)(\d+(,\d+)*)\1\]/',
// [roll=alias] | e.g. [roll=strength]
'/\[roll=([\"\']?)(\w+)\1\]/',
'/(\[quote=([\"\']|&quot;|).*?\2(.*?)\])(.*\[roll=[\dd\-\,]+\].*)(\[\/quote\])/',
// [code|php][roll=*][/code|php]
'/\[(code|php)\](.*?\[roll=[\dd\-\,]+\].*?)\[\/\1\](\r\n?|\n?)/'
);
// Disallow direct access to this file for security reasons
if (!defined("IN_MYBB")) {
die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined.");
}
// Require PluginLibrary.
if (!defined("PLUGINLIBRARY")) {
define("PLUGINLIBRARY", MYBB_ROOT."inc/plugins/pluginlibrary.php");
}
$plugins->add_hook("admin_config_plugins_begin", "diceroller_edit");
// Parse [roll=*] MyCode at postbit so PID is accessible
$plugins->add_hook("parse_message_me_mycode", "diceroller_setup");
function diceroller_info() {
global $mybb, $plugins_cache;
$info = array(
"name" => "Dice Roller MyCode",
"description" => "Rolls dice in a variety of exciting ways.",
"website" => "https://community.mybb.com/mods.php?action=view&pid=955",
"author" => "Shinka",
"authorsite" => "https://github.com/kalynrobinson/diceroller",
"version" => "1.2.0",
"guid" => "",
"compatibility" => "18*"
);
// Display edit and undo buttons on plugin description.
if (diceroller_is_installed() && $plugins_cache['active']['diceroller']) {
global $PL;
$PL or require_once PLUGINLIBRARY;
$editurl = $PL->url_append("index.php?module=config-plugins",
array("diceroller" => "edit",
"my_post_key" => $mybb->post_code));
$undourl = $PL->url_append("index.php",
array("module" => "config-plugins",
"diceroller" => "undo",
"my_post_key" => $mybb->post_code));
$editurl = "index.php?module=config-plugins&amp;diceroller=edit&amp;my_post_key=".$mybb->post_code;
$undourl = "index.php?module=config-plugins&amp;diceroller=undo&amp;my_post_key=".$mybb->post_code;
$info["description"] .= "<br /><a href=\"{$editurl}\">Make edits to class_parser.php</a>";
$info["description"] .= " | <a href=\"{$undourl}\">Undo edits to class_parser.php</a>";
}
return $info;
}
function diceroller_install() {
// Require PluginLibrary on install.
if (!file_exists(PLUGINLIBRARY)) {
flash_message("The selected plugin could not be installed because
<a href=\"http://mods.mybb.com/view/pluginlibrary\">PluginLibrary</a>
is missing.", "error");
admin_redirect("index.php?module=config-plugins");
}
}
function diceroller_uninstall() {
global $PL;
$PL or require_once PLUGINLIBRARY;
// Delete settings and templates from database.
$PL->settings_delete("diceroller");
$PL->templates_delete("diceroller");
}
function diceroller_is_installed() {
global $settings;
// Check if diceroller settings exist.
return isset($settings['diceroller_enable_sum']);
}
function diceroller_activate() {
global $PL, $mybb;
$PL or require_once PLUGINLIBRARY;
$PL->settings("diceroller",
"Dice Roller MyCode",
"Roll dice in a variety of exciting ways!",
array(
"enable_sum" => array(
"title" => "Display sum of NdS rolls?",
"description" => "When rolling multiple dice with NdS, should the sum of the results be displayed?",
"optionscode" => "yesno",
"value" => 1
),
"remove_dice" => array(
"title" => "Remove Dice from Pool",
"description" => "Remove value from dice pool so it cannot be landed
on again. List rolls or aliases you want to turn this setting on for,
separated by line breaks, e.g.
<br />carddraw
<br />1d20",
"optionscode" => "textarea",
"value" => "carddraw\n1d20"
),
"aliases" => array(
"title" => "Roll Aliases",
"description" => "A list of shorthand names and the rolls they
represent, using any of the supported syntax formats. Separate aliases
with line breaks, e.g.
<br />strength=1d6+5
<br />endurance=1-10
<br />agility=25,25,50",
"optionscode" => "textarea",
"value" => "strength=1d6+5\nendurance=1-4\nagility=25,25,50\ncarddraw=1-4"
),
"result_messages" => array(
"title" => "Result Messages",
"description" => "Display custom messages based on the result of a roll.
Output is based on sum of all rolls and offset.
Separate messages with commas and rolls with line breaks, e.g.
<br />1d20=Crit Fail, Fail, Success, Crit Success
<br />strength=Fumbled!, Missed!, Glancing Blow!, Direct Hit!, Perfect Strike!
<br />agility=You faceplanted!?, You tripped..., You have legs, Run like the wind!!!
<br />endurance=You're ded, Just a flesh wound, Alright!, Amazing!!!",
"optionscode" => "textarea",
"value" => "1d20=Crit Fail, Fail, Success, Crit Success\nstrength=Fumbled!, Missed!, Glancing Blow!, Direct Hit!, Perfect Strike!\nagility=You faceplanted!?, You tripped..., You have legs, Run like the wind!!!\nendurance=You're ded, Just a flesh wound, Alright!, Amazing!!!\ncarddraw=Awful luck!,Unlucky...,Lucky,Super lucky!!!!"
),
"result_ranges" => array(
"title" => "Result Ranges",
"description" => "Ranges in format <i>low</i>-<i>high</i> that
indicate when to display each custom message.
Separate messages with commas and rolls with line breaks, e.g.
<br />1d20=1-1,2-10,11-19,20-20 (rolling 1 will display \"Crit Fail\",
rolling between 2-10 will display \"Fail\", etc.)
<br />strength=1-5,6-10,11-15,16-20
<br />agility=1-25,26-50,51-75,76-100",
"optionscode" => "textarea",
"value" => "1d20=1-1,2-10,11-19,20-20\nstrength=6-6,7-7,8-9,10-10,11-11\nagility=1-1,2-2,3-3\nendurance=1-1,2-2,3-3,4-4\ncarddraw=1-1,2-2,3-3,4-4"
),
"resources" => array(
"title" => "Resources",
"description" => "Display resource item based on the result of a roll.
Output is based on each roll, not the sum, so 3d20 will output three
resource items. Separate items with commas and rolls with line breaks, e.g.
<br />1d20=Common Card,Uncommon Card,Rare Card,Super Rare Card!!!!",
"optionscode" => "textarea",
"value" => "carddraw=Common Card,Uncommon Card,Rare Card,Super Rare Card!!!!"
)
)
);
$PL->templates("diceroller",
"Diceroller MyCode",
array(
"" => '<div align="center">Rolling <strong>{$alias}</strong> {$dice}: {$rolls} {$offset} {$sum} {$results} {$resources}</div>',
"roll" => '{$roll} {$plus}',
"sum" => '= {$sum}',
"result" => '<br />{$result}',
"resource" => '<br />{$resource}',
)
);
}
function diceroller_deactivate() {
global $PL;
$PL or require_once PLUGINLIBRARY;
$PL->cache_delete("diceroller");
}
function diceroller_edit() {
global $mybb;
// Only perform edits if we were given the correct post key.
if ($mybb->input['my_post_key'] != $mybb->post_code) {
return;
}
global $PL;
$PL or require_once PLUGINLIBRARY;
if ($mybb->input['diceroller'] == 'edit') {
$result = $PL->edit_core("diceroller", "inc/class_parser.php",
array('search' => '$replace = "<blockquote',
'before' => "global \$plugins;\n\$message = \$plugins->run_hooks(\"parse_quote_message\", \$message);"),
true
);
} elseif ($mybb->input['diceroller'] == 'undo') {
$result = $PL->edit_core("diceroller", "inc/class_parser.php",
array(),
true
);
} else {
return;
}
if ($result === true) {
// redirect with success
flash_message("The file inc/class_parser.php was modified successfully.", "success");
admin_redirect("index.php?module=config-plugins");
} else {
// redirect with failure (could offer the result string for download instead)
flash_message("The file inc/class_parser.php could not be edited. Are the CHMOD settings correct?", "error");
admin_redirect("index.php?module=config-plugins");
}
}
/**
* Recursively drill down into the quote tags and then roll dice as
* it climbs back up.
*/
function diceroller_quote_callback($matches) {
global $patterns;
// Recursively drill down to innermost quote.
$inner = $matches[4];
$inner = preg_replace_callback("#\[quote=([\"']|&quot;|)(.*?)(?:\\1)(.*?)(?:[\"']|&quot;)?\](.*?)\[/quote\](\r\n?|\n?)#si", 'diceroller_quote_callback', $inner);
// Extract PID and use to seed.
$pid_pattern = '/pid=(?:&quot;|\"|\')?([0-9]+)[\"\']?(?:&quot;|\"|\')/';
preg_match($pid_pattern, $matches[3], $pid_matches);
if ((int)$pid_matches[1]) {
$pid = $pid_matches[1];
}
diceroller_parse($inner, $pid);
return str_replace($matches[4], $inner, $matches[0]);
}
/**
* Seed RNG using #post's PID and then parse [roll=*] tags.
*/
function diceroller_setup(&$message) {
global $post, $patterns, $parser;
if(!$post['pid'])
{
return;
}
if(!empty($parser->options['allow_mycode']))
{
$message = preg_replace_callback("#\[quote=([\"']|&quot;|)(.*?)(?:\\1)(.*?)(?:[\"']|&quot;)?\](.*?)\[/quote\](\r\n?|\n?)#si", 'diceroller_quote_callback', $message);
}
// Parse [roll=*] MyCode
$message = diceroller_parse($message, $post['pid']);
}
/**
* Parse [roll=*] tags.
*/
function diceroller_parse(&$message, $pid=1) {
global $mybb, $patterns, $templates;
// Seed RNG
srand($pid);
// Strip newlines.
// $message = str_replace("\n", "<br />", $message);
// Compute rolls and replace MyCode for each pattern
$message = preg_replace_callback($patterns[0], 'parse_lowhigh_callback', $message);
$message = preg_replace_callback($patterns[1], 'parse_nds_callback', $message);
$message = preg_replace_callback($patterns[2], 'parse_weighted_callback', $message);
$message = preg_replace_callback($patterns[3], 'parse_alias_callback', $message);
return $message;
}
/**
* Rolls dice for high-low format and evaluates templates.
*/
function parse_lowhigh_callback($matches) {
global $mybb, $templates, $alias;
$dosum = $mybb->settings['diceroller_enable_sum'];
// Extract information from matches
$low = $matches[2];
$high = $matches[3];
$offset = $matches[4];
$dice = $low . '-' . $high . $offset;
// Explode resources setting for given key
$key = $alias ? $alias : $dice;
$resourcesetting = get_setting_value('diceroller_resources', $key);
if ($resourcesetting) $resourcelist = explode(',', $resourcesetting);
$roll = rand(intval($low), intval($high));
// Calculate sum
if ($offset) {
if ($dosum) {
$sum = $roll + $offset;
}
}
// Get resource items
if ($resourcelist) {
$resource = $resourcelist[$roll-1];
eval('$resources .= "' . str_replace("\n", " ", $templates->get('diceroller_resource', true, false)) . '";');
}
// Get result messages
$key = $alias ? $alias : $dice;
$number = $sum ? $sum : $roll;
$resultlist = get_result_message($key, $number);
foreach ($resultlist as $result) {
eval('$results .= "' . str_replace("\n", " ", $templates->get('diceroller_result', true, false)) . '";');
}
// Evaluate templates
if ($sum != null) eval('$sum = "' . str_replace("\n", " ", $templates->get('diceroller_sum', true, false)) . '";');
eval('$rolls .= "' . str_replace("\n", " ", $templates->get('diceroller_roll', true, false)) . '";');
eval('$diceroller = "' . str_replace("\n", " ", $templates->get('diceroller', true, false)) . '";');
return $diceroller;
}
/**
* Rolls dice for NdS format and evaluates templates.
*/
function parse_nds_callback($matches) {
global $mybb, $templates, $alias;
$dosum = $mybb->settings['diceroller_enable_sum'];
// Extract information from matches
$number = $matches[2];
$sides = $matches[3];
$offset = $matches[4];
$dice = $number . 'd' . $sides . $offset;
// Explode resource setting
$key = $alias ? $alias : $dice;
$resourcesetting = get_setting_value('diceroller_resources', $key);
if ($resourcesetting) $resourcelist = explode(',', $resourcesetting);
$remove_dice = explode("\n", $mybb->settings['diceroller_remove_dice']);
// Default number to 1
if (!$number) $number = 1;
// Roll dice $number times
$rolled = array();
for ($i = 0; $i < $number; $i++) {
$roll = rand(1, intval($sides));
if ($remove_dice and $number <= $sides) {
while (in_array($roll, $rolled)) {
$roll = rand(1, intval($sides));
}
}
$rolled[] = $roll;
// Display plus sign if there are additional rolls
if ($i < $number-1) {
$plus = '+';
} else {
$plus = '';
}
// Get resource items
if ($resourcelist) {
$resource = $resourcelist[$roll-1];
eval('$resources .= "' . str_replace("\n", " ", $templates->get('diceroller_resource', true, false)) . '";');
}
eval('$rolls .= "' . str_replace("\n", " ", $templates->get('diceroller_roll', true, false)) . '";');
}
// Calculate sum
if ($dosum) {
if ($number > 1 or $offset) {
$sum = array_sum($rolled);
if ($offset) {
$sum += $offset;
}
}
}
// Get result messages
$num = $sum ? $sum : $rolled[0];
$resultlist = get_result_message($key, $num);
foreach ($resultlist as $result) {
eval('$results .= "' . str_replace("\n", " ", $templates->get('diceroller_result', true, false)) . '";');
}
// Evaluate templates
if ($sum != null) {
eval('$sum = "' . str_replace("\n", " ", $templates->get('diceroller_sum', true, false)) . '";');
}
eval('$diceroller = "' . str_replace("\n", " ", $templates->get('diceroller', true, false)) . '";');
return $diceroller;
}
/**
* Rolls dice for weighted format and evaluates templates.
*/
function parse_weighted_callback($matches) {
global $templates, $alias;
$dosum = $mybb->settings['diceroller_enable_sum'];
// Fetch information from matches and convert to array
$dice = $matches[2];
$weights = explode(',', $dice);
// Explode resource setting for given key
$key = $alias ? $alias : $dice;
$resourcesetting = get_setting_value('diceroller_resources', $key);
if ($resourcesetting) $resourcelist = explode(',', $resourcesetting);
// Roll weighted die
$roll = weighted_rng($weights);
// Get result messages
$key = $alias ? $alias : $dice;
$resultlist = get_result_message($key, $roll);
foreach ($resultlist as $result) {
eval('$results .= "' . str_replace("\n", " ", $templates->get('diceroller_result', true, false)) . '";');
}
// Get resource item
if ($resourcelist) {
$resource = $resourcelist[$roll-1];
eval('$resources .= "' . str_replace("\n", " ", $templates->get('diceroller_resource', true, false)) . '";');
}
// Evaluate templates
eval('$rolls .= "' . str_replace("\n", " ", $templates->get('diceroller_roll', true, false)) . '";');
eval('$diceroller = "' . str_replace("\n", " ", $templates->get('diceroller', true, false)) . '";');
return $diceroller;
}
/**
* Chooses random number from list of weights.
*/
function weighted_rng($weights) {
$rand = rand(1, (int) array_sum($weights));
foreach ($weights as $key => $value) {
$rand -= $value;
if ($rand <= 0) {
return $key + 1;
}
}
}
/**
* Rolls dice for alias format and evaluates templates.
*/
function parse_alias_callback($matches) {
global $mybb, $alias, $templates;
// Extract information from matches and settings
$alias = $matches[2];
$dice = get_setting_value('diceroller_aliases', $alias);
if (!$dice) {
$alias = null;
return "Alias does not exist.";
}
// Because the global $patterns won't work right here and I'm too lazy to
// figure out why
$alias_patterns = array(
// alias=low-high | e.g. alias=1-6
'/([\"\']?)(\d+)-(\d+)(([\+\-]\d+)?)\1/',
// alias=(N)dS(+/-F) | e.g. alias=d6 | alias=1d6 | alias=1d6+10 | alias=1d6-10
'/([\"\']?)(\d*)d(\d+)([\+\-]\d+)?\1/',
// alias=weighed list | e.g. alias==2,2,1
'/([\"\']?)(\d+(,\d+)*)\1/'
);
if (preg_match($alias_patterns[1], $dice)) {
$dice = preg_replace_callback($alias_patterns[1], 'parse_nds_callback', $dice);
} elseif (preg_match($alias_patterns[0], $dice)) {
$dice = preg_replace_callback($alias_patterns[0], 'parse_lowhigh_callback', $dice);
} elseif (preg_match($alias_patterns[2], $dice)) {
$dice = preg_replace_callback($alias_patterns[2], 'parse_weighted_callback', $dice);
}
// Reset global $alias
$alias = null;
return $dice;
}
/**
* Fetches value of setting $name and explodes into array delimited by '='.
*
* @param string $name Case-sensitive ame of the setting.
* @param boolean $inner_explode Whether the right hand side should also be exploded.
* @return array Array of items in the setting.
*/
function explode_settings($name) {
global $mybb;
$settings = $mybb->settings[$name];
$settings = explode("\n", $settings);
foreach ($settings as $key => $value) {
$explosion = explode('=', $value);
$settings[$explosion[0]] = $explosion[1];
unset($settings[$key]);
}
return $settings;
}
function explode_ranges($ranges) {
$ranges = str_replace(' ', '', trim($ranges));
$ranges = explode(",", $ranges);
foreach ($ranges as $key => $value) {
unset($ranges[$key]);
$explosion = explode('-', $value);
$ranges[] = array($explosion[0], $explosion[1]);
}
return $ranges;
}
/**
* Determines if $number is between $min and $max
*
* @param integer $number The number to test
* @param integer $min The minimum value in the range
* @param integer $max The maximum value in the range
* @return boolean Whether the number was in the range
*/
function in_range($number, $min, $max) {
if (is_numeric($number) && is_numeric($min) && is_numeric($max)) {
return ($number >= $min && $number <= $max);
}
return FALSE;
}
/**
* Checks if $value is a key in setting $name
*/
function get_setting_value($name, $value) {
$setting = explode_settings($name);
return isset($setting[$value])
? $setting[$value]
: null;
}
function get_result_message($key, $number) {
$result_messages = explode(',', get_setting_value('diceroller_result_messages', $key));
$result_ranges = get_setting_value('diceroller_result_ranges', $key);
$results = array();
if ($result_ranges) {
$result_ranges = explode_ranges($result_ranges);
$count = 0;
foreach ($result_ranges as $range) {
if (in_range($number, $range[0], $range[1])) {
$results[] = $result_messages[$count];
}
$count++;
}
}
return $results;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment