Jump to content
MakeWebGames

Magictallguy

Administrators
  • Posts

    2,124
  • Joined

  • Last visited

  • Days Won

    144

Magictallguy last won the day on September 22

Magictallguy had the most liked content!

About Magictallguy

  • Birthday 08/07/1991

Personal Information

  • Location
    Bolton, UK
  • Occupation
    Freelance Website Developer
  • Website
    https://orsokuma.com

Recent Profile Visitors

22,029 profile views

Magictallguy's Achievements

Collaborator

Collaborator (7/14)

  • Well Followed Rare
  • Conversation Starter Rare
  • Reacting Well Rare
  • Very Popular Rare
  • First Post Rare

Recent Badges

478

Reputation

  1. I didn't add any >100 formatting, but that'd be easy enough. Hell, I might even update to use a checkbox for it so users can see the direct value if they need to, or just a "yup, this is guaranteed" output. Go sick 😄
  2. I really like the ability to visualise how the crime formulae may result; so I took your idea and added the ability to select from an existing crime, or assume the default formula ((WILL*0.8)/2.5)+(LEVEL/4) and calculate as desired. I also stripped the jQuery dependence; pure vanilla JS, woo! Fair note to our more sensitive-eyed programmers; there's no dark mode by default. Note: Written in a PHP8.4 environment. Older versions may need to change the match() call to a switch() equivalent crime-formula.php <?php declare(strict_types=1); $_GET['action'] ??= null; $_GET['id'] = array_key_exists('id', $_GET) && is_numeric($_GET['id']) && (int)$_GET['id'] > 0 ? (int)$_GET['id'] : null; class CrimeFormula { private static ?self $inst = null; private ?database $db; private ?array $settings; /** * @param database $db * @param array $settings */ public function __construct(database $db, array $settings) { $this->db = $db; $this->settings = $settings; $this->run(); } /** * @return void */ private function run(): void { $response = match ($_GET['action']) { 'get-crime-by-id' => $this->getCrimeById($_GET['id']), default => [ 'type' => 'error', 'message' => 'No action given', ], }; if ($this->isAjax()) { header('Content-type: application/json'); echo json_encode($response); exit; } if (array_key_exists('location', $response)) { header('Location: ' . $response['location']); exit; } echo $this->template('crime-select', [ '%id%' => $_GET['id'], '%menu.opts:crimes%' => $this->renderMenuOptsCrimes($_GET['id']), ]); } /** * @param int|null $id * * @return array|null */ private function getCrimeById(?int $id): ?array { if (empty($id)) { return null; } $get_crime = $this->db->query( 'SELECT * FROM crimes WHERE crimeID = ' . $id . ' LIMIT 1', ); $row = $this->db->fetch_row($get_crime); $this->db->free_result($get_crime); return $row ?? null; } /** * @return bool */ private function isAjax(): bool { return array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'; } /** * @param string $fileName * @param array $replacements * * @return string|null */ private function template(string $fileName, array $replacements = []): ?string { $path = str_replace('/', DIRECTORY_SEPARATOR, __DIR__ . '/' . $fileName . '.html'); if (!file_exists($path)) { return null; } $content = file_get_contents($path); return strtr($content, $replacements); } /** * @param int|null $selected * * @return string */ private function renderMenuOptsCrimes(?int $selected = null): string { $ret = ''; $rows = $this->db->query( 'SELECT crimeID, crimeNAME, crimeBRAVE FROM crimes ORDER BY crimeBRAVE', ); while ($row = $this->db->fetch_row($rows)) { $ret .= sprintf( '<option value="%u" %s>%s [%s brave]</option>%s', $row['crimeID'], (int)$row['crimeID'] === $selected ? 'selected' : '', stripslashes(htmlspecialchars($row['crimeNAME'])), number_format((int)$row['crimeBRAVE']), PHP_EOL, ); } $this->db->free_result($rows); return $ret; } /** * @param database $db * @param array $settings * * @return self|null */ public static function getInstance(database $db, array $settings): ?self { if (self::$inst === null) { self::$inst = new self($db, $settings); } return self::$inst; } } global $db, $set; require_once __DIR__ . '/globals_nonauth.php'; $module = CrimeFormula::getInstance($db, $set); crime-select.html <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Crime Formula Tests</title> </head> <body> <div class="container" style="margin: 0 auto;"> <form id="crime-selection-form" method="get"> <div class="row py-2"> <div class="col"> <div class="form-group"> <label for="crime">Select Crime</label> <select name="crime" id="crime" class="form-control"> <option value="0" selected>--- None ---</option> %menu.opts:crimes% </select> </div> </div> </div> <div class="row py-2"> <div class="col-lg-6 col-md"> <div class="form-group"> <label for="level">Level</label> <input type="number" name="level" id="level" class="form-control" value="1" step="1"> </div> </div> <div class="col-lg-6 col-md"> <div class="form-group"> <label for="will">Will</label> <input type="number" name="will" id="will" class="form-control" value="100" step="1"> </div> </div> </div> </form> </div> <div class="container"> <span class="d-block m-1" id="crime-formula-raw"></span> <span class="d-block m-1" id="crime-formula-formatted"></span> <span class="d-block m-1" id="crime-response"></span> </div> <script> const apiCall = (path) => { return fetch(path, { headers: { 'credentials': 'same-origin', 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json' }, signal: AbortSignal.timeout(5000) }); }; const getCrime = (id, callback) => { apiCall(`crime-formula.php?action=get-crime-by-id&id=${id}`) .then(response => response.json()) .then(data => callback(data)); }; const responseElem = document.getElementById("crime-response"); const formulaRawElem = document.getElementById("crime-formula-raw"); const formulaFormattedElem = document.getElementById("crime-formula-formatted"); const updateCrimeInfo = (formula, will, level) => { let formulaFormatted = formula.replace('WILL', will).replace('LEVEL', level); formulaRawElem.innerText = formula; formulaFormattedElem.innerText = formulaFormatted; /* Dirty. Don't do this if you can avoid it. And certainly *never* trust user input with it. */ let amnt = eval(formulaFormatted); responseElem.innerText = amnt.toLocaleString(undefined, {maximumFractionDigits: 3}) + "%"; }; const getCrimeFullEvent = (e) => { e.stopPropagation(); e.preventDefault(); if ([undefined, null].includes(responseElem) || [undefined, null].includes(formulaRawElem) || [undefined, null].includes(formulaFormattedElem)) { console.error("Form element missing: crime-response/crime-formula-raw/crime-formula-formatted"); return; } let will = document.getElementById("will").value; let level = document.getElementById("level").value; let id = document.getElementById("crime").value; if ([undefined, null].includes(will)) { will = 100; } if ([undefined, null].includes(level)) { level = 1; } if ([undefined, null].includes(id)) { id = 0; } let formula = '((WILL*0.8)/2.5)+(LEVEL/4)'; if (id > 0) { getCrime(id, (data) => { if ([undefined, null].includes(data)) { console.error("Blank crime data response"); return false; } if (data.hasOwnProperty("type") && data.type !== "success") { console.error(data); return false; } updateCrimeInfo(data.crimePERCFORM, will, level); return true; }); } else { updateCrimeInfo(formula, will, level); } }; window.addEventListener("DOMContentLoaded", () => { const formElem = document.getElementById("crime-selection-form"); if ([undefined, null].includes(formElem)) { console.error("Form element missing: crime-selection-form"); return; } formElem.addEventListener("keyup", (e) => getCrimeFullEvent(e)); formElem.addEventListener("mouseup", (e) => getCrimeFullEvent(e)); }); </script> </body> </html> 2025-09-22 18-58-18.mp4
  3. For anyone wanting to take this on, you're lookin' at CrateJS to re-wrap
  4. Note: In higher-traffic areas, this may introduce race conditions. In that scenario, I'd recommend using the database (the one your project is already using) to track this information; amongst other things, most RDBMS support query queuing as default. For low-traffic areas and areas where you don't foresee an upsurge in activity (refer to your metrics), then this file-based approach may be perfectly sufficient for your needs
  5. Technically, yes! It is certainly possible to run multiple sites that reference a single database. More often than not, though, the question is "why"? If, for example, I was to start a mafia-style game with MCC then I decided I wanted a sci-fi style game with gRPG; I could do the leg-work and make them compatible. That being said, what of the players? Someone playing a mafia-style game with [x] currency will likely be confused by having [y] currency in the sci-fi game. I'm a firm believer of "fit for purpose"; each project gets their own database(s) as necessary. If you want to make a merge of the open-source engines, you go right ahead 😄
  6. These can be added into the Dockerfile as RUN directives
  7. Summer! Life generally tends to get louder in the summer. People are out (and away from their keyboards) more often. We're still just a message away though. As for gRPG, I've already framed a structure for the multi-PHP-version supports and have begun tweaking the various branches
  8. Minor control issue; W responds (piece rotation), but ASD do not. All arrow keys work.
  9. Hmm, could Cloudflare be doing the derp on an old resource? @Dayo
  10. Adding a mobile screeny for the light theme to confirm This is very likely a caching issue - we're on CSS build 8 now
  11. Looks like your browser simply failed to grab the site's CSS properly. Clear the cache and try again 🙂 Chiming in with mobile screenshot too! Samsung Galaxy S23
  12. I have not as I wasn't thinking of backwards compatibility. This change is part of a rolling set of changes I intend to make to suit more recent technologies. As for the claim that "nobody" has PHP 8.4 yet; SiteEU, WebWiz, HawkHost, Kinsta, SwitchWeb, NameCheap, GoDaddy, Google Cloud Hosting and AWS absolutely do support it. Honourable mention to cPanel's EasyApache which added PHP 8.4 support in December just gone. Again, I will add backward compatibility for PHP 8.0. Might send up a couple of branched releases so people can select their desired version.
  13. You changed setenv to getenv? Of course that wouldn't work
  14. Back when I was on Windows, I loved mLocati's PowerShell PHP Manager - you may wish to consider looking into it. Its primary purpose is to provide an easy way to install multiple PHP versions and choose whichever one the system considers active. As for your host, perhaps a request to their support might be fruitful.
  15. PHP 8.4 required. I'll push an 8.0-friendly version shortly
×
×
  • Create New...