working with smarty[RESOLVED]

Need help with an engine or coding not on the list? Need help with a game or the website and forums here? Direct all questions here.
Post Reply
User avatar
Zak Zillion
Posts: 112
Joined: Thu Apr 07, 2011 12:55 am

working with smarty[RESOLVED]

Post by Zak Zillion »

Hey everyone, So I working with smarty to build a game (i'll be posting it in the Project Showoff Tier I later). This is my first time using smarty and it is giving me some trouble. Most of the game will be played through play.php, it is a text based MORPG were you move through the game and the db generates almost the whole page. Right now I am wanting the db to list all of the merchants and healers in the area through an array but smarty doesn't want to work with me for some reason. If someone could help me it would be awesome!

play.php

Code: Select all

<html
<head>
<link rel="stylesheet" type="text/css" href="main.css" />
<script type="text/javascript" src="df.js"></script>
</head>
<body>
<?php
//an animal is giving out a fake item


require 'smarty.php';
require 'weapon-stats.php';
require 'login-check.php';
$smarty = new smarty_connect;
require_once 'stats.php';
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
session_start();
/* $playerinfo = "SELECT * from users where username='$username'";
$playerinfo2 = mysql_query($playerinfo) or die("could not get player stats!");
$playerinfo3 = mysql_fetch_array($playerinfo2); */
$smarty->assign('level', getStat('lvl', $userID));
$smarty->assign('attack', getStat('atk', $userID));
$smarty->assign('magic', getStat('mag', $userID));
$smarty->assign('defence', getStat('def', $userID));
$smarty->assign('gold', getStat('gc', $userID));
$smarty->assign('setlvl', getStat('setlvl', $userID));
$setLVL = getStat('setlvl', $userID);

////////////////////MOVE/////////////////////

/*
$query  = sprintf("SELECT curarea FROM users WHERE username = '$name'", mysql_real_escape_string('$name'));
$result = mysql_query($query);
list($curarea) = mysql_fetch_row($result);
$smarty->assign('curarea', $curarea);

$query  = sprintf("SELECT lasarea FROM users WHERE username = '$name'", mysql_real_escape_string('$name'));
$result = mysql_query($query);
list($lasarea) = mysql_fetch_row($result);
$smarty->assign('lasarea', $lasarea); 

$smarty->assign('lasarea', '7'); 
$query = sprintf("UPDATE users SET lasarea = '$lasarea' WHERE id = '$userID'", mysql_real_escape_string('$userID'));
$smarty->assign('curarea','$area_id'); 
$query = sprintf("UPDATE users SET curarea = '$curarea' WHERE id = '$userID'", mysql_real_escape_string('$userID'));

////////////////////////////////////////////// */
if ($setLVL == 0) {
    // haven't set up the user's Level values yet - let's set those!
    setStat('setlvl', $userID, 1);
    setStat('level', $userID, 1);
    setStat('curexp', $userID, 0);
    setStat('nextlvl', $userID, 100);
} //$setLVL == 0
$smarty->assign('CurrentExperience', getStat('curexp', $userID));
$smarty->assign('NextLevel', getStat('nextlvl', $userID));
$setHP = getStat('sethp', $userID);
if ($setHP == 0) {
    // haven't set up the user's HP values yet - let's set those!
    setStat('curhp', $userID, 10);
    setStat('maxhp', $userID, 10);
    setStat('sethp', $userID, 1);
} //$setHP == 0
$smarty->assign('currentHP', getStat('curhp', $userID));
$smarty->assign('maximumHP', getStat('maxhp', $userID));
$smarty->assign('name', $_SESSION['username']);
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////

// our database settings
require 'database.php';
// monster stats
require 'monster-stats.php';

$area_id = $_REQUEST['area'];

$query  = sprintf("SELECT curarea FROM users WHERE id = '$userID'", mysql_real_escape_string('$userID'));
$result = mysql_query($query);
list($curarea) = mysql_fetch_row($result);
$smarty->assign('curarea', $curarea);
$smarty->assign('curarea', $area_id);
$query = sprintf("UPDATE users SET curarea = '$curarea' WHERE id = '$userID'", mysql_real_escape_string('$userID'));

$query  = sprintf("SELECT monsters FROM areas WHERE id = '$area_id' ORDER BY RAND() LIMIT 1", mysql_real_escape_string($area_id));
$result = mysql_query($query);
list($monsterarea) = mysql_fetch_row($result);
$smarty->assign('monsterarea', $monsterarea);

$query  = sprintf("SELECT monsters FROM areas WHERE id = '$area_id' ", mysql_real_escape_string($_POST['areamonster']));
$result = mysql_query($query);
list($areamonster) = mysql_fetch_row($result);
$smarty->assign('areamonster', $areamonster);

$query  = sprintf("SELECT north FROM areas WHERE id = '$area_id' ", mysql_real_escape_string($_POST['north']));
$result = mysql_query($query);
list($area_north) = mysql_fetch_row($result);
$smarty->assign('north', $area_north);

$query  = sprintf("SELECT south FROM areas WHERE id = '$area_id' ", mysql_real_escape_string($_POST['south']));
$result = mysql_query($query);
list($area_south) = mysql_fetch_row($result);
$smarty->assign('south', $area_south);

$query  = sprintf("SELECT west FROM areas WHERE id = '$area_id' ", mysql_real_escape_string($_POST['west']));
$result = mysql_query($query);
list($area_west) = mysql_fetch_row($result);
$smarty->assign('west', $area_west);

$query  = sprintf("SELECT east FROM areas WHERE id = '$area_id' ", mysql_real_escape_string($_POST['east']));
$result = mysql_query($query);
list($area_east) = mysql_fetch_row($result);
$smarty->assign('east', $area_east);

if ($_POST) {
    if ($_POST['action'] == 'Attack') {
        // to begin with, we'll retrieve our player and our monster stats 
        $query  = sprintf("SELECT id FROM users WHERE UPPER(username) = UPPER('%s')", mysql_real_escape_string($_SESSION['username']));
        $result = mysql_query($query);
        list($userID) = mysql_fetch_row($result);
        $player = array(
            name => $_SESSION['username'],
            attack => getStat('atk', $userID),
            defence => getStat('def', $userID),
            curhp => getStat('curhp', $userID)
        );
        $phand  = getStat('phand', $userID);
        $atk    = getWeaponStat('atk', $phand);
        $player['attack'] += $atk;
        // armor stats
        require 'armor-stats.php';
        $armor = array(
            'atorso',
            'ahead',
            'alegs',
            'aright',
            'aleft'
        );
        foreach ($armor as $key) {
            $id      = getStat($key, $userID);
            $defence = getArmorStat('defence', $id);
            $player['defence'] += $defence;
        } //$armor as $key
        
        $query  = sprintf("SELECT id FROM monsters WHERE name = '%s'", mysql_real_escape_string($_POST['monster']));
        $result = mysql_query($query);
        list($monsterID) = mysql_fetch_row($result);
        $monster = array(
            name => $_POST['monster'],
            attack => getMonsterStat('atk', $monsterID),
            defence => getMonsterStat('def', $monsterID),
            curhp => getMonsterStat('maxhp', $monsterID)
        );
        $combat  = array();
        $turns   = 0;
        while ($player['curhp'] > 0 && $monster['curhp'] > 0 && $turns <= 100) {
            if ($turns % 2 != 0) {
                $attacker =& $monster;
                $defender =& $player;
            } //$turns % 2 != 0
            else {
                $attacker =& $player;
                $defender =& $monster;
            }
            $damage = 0;
            if ($attacker['attack'] > $defender['defence']) {
                $damage = $attacker['attack'] - $defender['defence'];
            } //$attacker['attack'] > $defender['defence']
            $defender['curhp'] -= $damage;
            $combat[$turns] = array(
                attacker => $attacker['name'],
                defender => $defender['name'],
                damage => $damage
            );
            $turns++;
        } //$player['curhp'] > 0 && $monster['curhp'] > 0 && $turns <= 100
        setStat('curhp', $userID, $player['curhp']);
        if ($player['curhp'] > 0) {
            // player won
            setStat('gc', $userID, getStat('gc', $userID) + getMonsterStat('gc', $monsterID));
            $smarty->assign('won', 1);
            $smarty->assign('gold', getMonsterStat('gc', $monsterID));
            $rand   = rand(0, 100);
            $query  = sprintf("SELECT item_id FROM monster_items WHERE monster_id = %s ORDER BY RAND() LIMIT 1", mysql_real_escape_string($monsterID), mysql_real_escape_string($rand));
            $result = mysql_query($query);
            list($itemID) = mysql_fetch_row($result);
            $query  = sprintf("SELECT count(id) FROM user_items WHERE user_id = '%s' AND item_id = '%s'", mysql_real_escape_string($userID), mysql_real_escape_string($itemID));
            $result = mysql_query($query);
            list($count) = mysql_fetch_row($result);
            if ($count > 1) {
                // already has one of the item
                $query = sprintf("UPDATE user_items SET quantity = quantity ++ 1 WHERE user_id = '%s' AND item_id = '%s'", mysql_real_escape_string($userID), mysql_real_escape_string($itemID));
            } //$count > 1
            else {
                // has none - new row
                $query = sprintf("INSERT INTO user_items(quantity,user_id,item_id) VALUES (1,'%s','%s')", mysql_real_escape_string($userID), mysql_real_escape_string($itemID));
            }
            mysql_query($query);
            // retrieve the item name, so that we can display it
            $query  = sprintf("SELECT name FROM items WHERE id = %s", mysql_real_escape_string($itemID));
            $result = mysql_query($query);
            list($itemName) = mysql_fetch_row($result);
            $smarty->assign('item', $itemName);
            
            $monster_exp = getMonsterStat('exp', $monsterID);
            $smarty->assign('exp', $monster_exp);
            $nextlevel = getStat('nextlvl', $userID);
            $curexp    = getStat('curexp', $userID);
            $level     = getStat('Level', $userID);
            $curexp += $monster_exp;
            if ($curexp >= $nextlevel) {
                // level up!
                $nextlevel += $nextlevel * .3;
                $level += 1;
                $curexp = 0;
                $v      = 1;
            } //$curexp >= $nextlevel
            else {
                $v = 0;
            }
            $smarty->assign('v', $v);
            setStat('curexp', $userID, $curexp);
            setStat('nextlvl', $userID, $nextlevel);
            setStat('lvl', $userID, $level);
        } //$player['curhp'] > 0
        else {
            // monster won
            $smarty->assign('lost', 1);
        }
        $smarty->assign('combat', $combat);
    } //$_POST['action'] == 'Attack'
    else {
        // Running away! Send them back to the main page
        header('Location: index.php');
    }
} //$_POST
else {
    $area_id = $_REQUEST['area'];
    if ($areamonster = '1'); {
        $query  = sprintf("SELECT monster FROM area_monsters WHERE area = %s ORDER BY RAND() LIMIT 1", mysql_real_escape_string($area_id));
        $result = mysql_query($query);
        list($monster_id) = mysql_fetch_row($result);
        $smarty->assign('monster_id', $monster_id);
        
        $query  = sprintf("SELECT name FROM monsters WHERE id = '%s' ", mysql_real_escape_string($monster_id));
        $result = mysql_query($query);
        list($monster) = mysql_fetch_row($result);
        $smarty->assign('monster', $monster);
    }
}
$query  = sprintf("SELECT name FROM areas WHERE id = %s", mysql_real_escape_string($_REQUEST['area']));
$result = mysql_query($query);
list($area_name) = mysql_fetch_row($result);
$smarty->assign('area', $area_name);
$smarty->assign('area_id', $_REQUEST['area']);

$query  = sprintf("SELECT description FROM areas WHERE id = %s", mysql_real_escape_string($_REQUEST['area']));
$result = mysql_query($query);
list($area_description) = mysql_fetch_row($result);
$smarty->assign('description', $area_description);


///////////////////////////////////////////////

$query  = sprintf("SELECT is_admin FROM users WHERE id='$userID'", mysql_real_escape_string($userID));
$result = mysql_query($query);
list($is_admin) = mysql_fetch_row($result);
$smarty->assign('is_admin', $is_admin);


///////////////////Merchant//////////////////////

/*  $query  = sprintf("SELECT id FROM merchant WHERE id = '$userID' ", mysql_real_escape_string($_POST['userID']));
$result = mysql_query($query);
list($merchid) = mysql_fetch_row($result);
$smarty->assign("merchid", $merchid);

$query  = sprintf("SELECT name FROM merchant WHERE id = '$userID' ", mysql_real_escape_string($_POST['userID']));
$result = mysql_query($query);
list($merchname) = mysql_fetch_row($result);
$smarty->assign('merchname', $merchname);

$query  = sprintf("SELECT title FROM merchant WHERE id = '$userID' ", mysql_real_escape_string($_POST['userID']));
$result = mysql_query($query);
list($merchtitl) = mysql_fetch_row($result);
$smarty->assign('merchtitl', $merchtitl);

$query  = sprintf("SELECT description FROM merchant WHERE id = '$userID' ", mysql_real_escape_string($_POST['userID']));
$result = mysql_query($query);
list($merchdesc) = mysql_fetch_row($result);
$smarty->assign('merchdesc', $merchdesc);

$query  = sprintf("SELECT type FROM merchant WHERE id = '$userID' ", mysql_real_escape_string($_POST['userID']));
$result = mysql_query($query);
list($merchtype) = mysql_fetch_row($result);
$smarty->assign('merchtype', $merchtype);

$query  = sprintf("SELECT area FROM merchant WHERE id = '$userID' ", mysql_real_escape_string($_POST['userID']));
$result = mysql_query($query);
list($mercharea) = mysql_fetch_row($result);
$smarty->assign('mercharea', $mercharea);

$query  = sprintf("SELECT sellitem FROM merchant WHERE id = '$userID' ", mysql_real_escape_string($_POST['userID']));
$result = mysql_query($query);
list($merchsell) = mysql_fetch_row($result);
$smarty->assign('merchsell', $merchsell); */
////////////////////////////////////////////////////
/////////////////////Merchant Array/////////////////
$query  = sprintf("SELECT area FROM merchant WHERE id = '$userID' ", mysql_real_escape_string($_POST['userID']));
$result = mysql_query($query);
list($mercharea) = mysql_fetch_row($result);
$smarty->assign('mercharea', $mercharea);

$query  = sprintf("SELECT * FROM merchant WHERE id = '$userID' ", mysql_real_escape_string($_POST['userID']));
$result = mysql_query($query);
print_r(mysql_fetch_assoc($result));
$smarty->assign('m', array(
    'merchid'   => $merchant["id"],
    'merchname' => $merchant["name"],
    'merchtitl' => $merchant["title"],
    'merchdesc' => $merchant["description"],
    'merchtype' => $merchant["type"],
    'mercharea' => $merchant["area"],
    'merchsell' => $merchant["sellitem"]
));

$smarty->display('play.tpl');
?>
</body>
</html>
play.tpl

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>The Dark Flame: {$area}</title>
</head>
<body>
<div id='navbar'>
<ul>
<li><a href="play.php?area={$curarea}">Play<!--img src="images/play.png" alt="Move" width="100" height="40" /--></a></li>
<li><a href="inventory.php">Inventory<!--img src="images/inventory.png" alt="Inventory" width="100" height="40" /--></a></li>
<li><a href="character.php">Character<!--img src="images/character.png" alt="Character" width="100" height="40" /--></a></li>
<li><a href="logout.php">Logout<!--img src="images/logout.png" alt="Logout" width="100" height="40" /--></a></li>
</ul>
</div>
<div id=maindiv>
<h1 id="areat">{$area}</h1>
<p id="aread">{$description}</p>
{if $areamonster eq '1' && $combat eq ''}
<p>You've encountered a {$monster}!</p>
        	<form action='play.php?area={$area_id}' method='post'>
			<input type='submit' name='action' value='Attack' accesskey="c" /> or 
			<input type='submit' name='action' value='Run Away' accesskey="v" />
			<input type='hidden' name='monster' value='{$monster}' />
			</form>
	{else}
		<ol id='b'>
		{foreach from=$combat key=id item=i}
			<li>{$i.attacker} attacks {$i.defender} for {$i.damage} damage!</li>
		{/foreach}
		</ol>
		{if $won eq 1}
			<p>You killed {$smarty.post.monster}! You gained {$gold} gold, and {$exp} experience.</p>
			{if $v == '1'}
    <p>You gained a level!</p>
			{/if}
			<p>You found a {$item}!</p>
		{/if}
		{if $lost eq 1}
			<p>You were killed by {$smarty.post.monster}.</p>
            <p><a href="healer.php">I hope you can pay to be healed.</a></p>
		{/if}		

	{/if}
    {if $won eq '1' || $areamonster eq '0' }
    
<div id=movediv>
{if $north != ''}
			<p><a id='move' href='play.php?area={$north}' accesskey="w"><img src="images/north.png" alt="North" width="100" height="40" /></a></p>          
{/if}
{if $east != ''}
			<p><a id='move' href='play.php?area={$east}' accesskey="d"><img src="images/east.png" alt="North" width="100" height="40" /></a></p>
{/if}
{if $west != ''}
			<p><a id='move' href='play.php?area={$west}' accesskey="a"><img src="images/west copy.png" alt="North" width="100" height="40" /></a></p>
{/if}
{if $south != ''}
			<p><a id='move' href='play.php?area={$south}' accesskey="s"><img src="images/south.png" alt="North" width="100" height="40" /></a></p>
{/if}

<p><a id='move' href='index.php' accesskey="b">Back to Main</a></p>
            <ul class="b">
        <li>Level: {$level}</li>
        <li>Experience: {$CurrentExperience}</li>
        <li>Experience to Level: {$NextLevel}</li>
		<li>Attack: {$attack}</li>
		<li>Defence: {$defence}</li>
		<li>Magic: {$magic}</li>
		<li>Gold in hand: {$gold}</li>
{/if}
		<li>Current HP: {$currentHP}/{$maximumHP}</li></ul>
        </div>
        <div id="merchdiv">
        
       
        {if $won eq '1' || $areamonster eq '0' }
        {if $area_id == $mercharea}
        
        <p><a id='merchant' href='{$m.merchtype}.php?merchid={$m.merchid}'>{$m.merchname}</a> | </p>
        
        {/if}
        {/if}

        
    </div>
    

    
    {include  file='footer.tpl'}
    </div>
</body>
</html>
Last edited by Zak Zillion on Sun May 08, 2011 12:57 am, edited 1 time in total.
"Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius -- and a lot of courage -- to move in the opposite direction." - Albert Einstein

Old Project(s):
The Dark Flame
User avatar
Jackolantern
Posts: 10891
Joined: Wed Jul 01, 2009 11:00 pm

Re: working with smarty

Post by Jackolantern »

Sorry that there have been no responses on this so far, and sadly, I know little to nothing about Smarty as well. The general community consensus has been that it is typically overkill for the types of projects we do, since its main purpose is facilitating a non-destructive workflow between designers and developers on the same team, and well...we usually play both roles on our own projects. Have you tried asking in the Smarty forums? Surely you could get a fast answer there.
The indelible lord of tl;dr
User avatar
Zak Zillion
Posts: 112
Joined: Thu Apr 07, 2011 12:55 am

Re: working with smarty

Post by Zak Zillion »

Thank you for the response Jack, I have decided to convert back to just using PHP. I found that the syntax was was actually hindering me and it was annoying to not be able to see a page without saving it to the server, which would sometimes be down. So again thanks for the response and feel free to delete this topic.
"Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius -- and a lot of courage -- to move in the opposite direction." - Albert Einstein

Old Project(s):
The Dark Flame
User avatar
Jackolantern
Posts: 10891
Joined: Wed Jul 01, 2009 11:00 pm

Re: working with smarty

Post by Jackolantern »

I initially looked into Smarty as well, but decided not to use it. It really seems to be geared towards large team projects that are split into design and development departments with little cross-training.
The indelible lord of tl;dr
Kennydin
Posts: 39
Joined: Sat Oct 31, 2009 12:47 am

Re: working with smarty

Post by Kennydin »

I'd recommend using a framework such as CakePHP or Code Igniter if you're looking to develop your game in a slightly more modular way.
Smarty is, as Jack said, very dense as a framework (its more of a Template Engine). It can be actually very nice when you get the hang of it.

An easier alternative (and by no means thought lesser of) is a true MVC framwork.
If you're new to the whole MVC (Model View Controller) Architecture, I'd suggest using Code Igniter, its quite a simple framework.
Cake on the other hand is slightly more complex in terms of the concepts behinds its working, however Cake in my opinion is a better than Code Igniter. It offers more libraries, helpers etc.. as well as having some awesome Associative Model support (for database stuff). Its bigger and a little more challenging to get your head round at first BUT once you get your head around the whole idea of MVC you'll love it so much :mrgreen:

If you start with Cake and find it too difficult, try Code Igniter, its where I started :)
PHP/Python (amongst other things) Person - Big Fan of MVC Architecture. Love CakePHP and CodeIgniter.
User avatar
Jackolantern
Posts: 10891
Joined: Wed Jul 01, 2009 11:00 pm

Re: working with smarty

Post by Jackolantern »

I agree. MVC is the best way to manage and develop mid-range and larger web applications (and that includes games). If you are wanting a template system like ASP.NET's Master Pages, where you make a design one time with content areas, and then reference it for each individual page you make (or "view" in the case of MVC), you can use PHP's include() function to insert other PHP files into your page. What I do is I make a folder to hold my site's template, and then inside that folder I make several files such as header.php, footer.php, nav.php, etc. Each one just has opening and closing PHP tags, and between those tags I just have an echo statement that echoes out the HTML for the page portion it should contain (for example, the header.php file would have the Doctype, head tags and contents, and so on down to the nav section). This way you can put your unique page content between these include() calls which will form your page template around that unique page content.

This is an easy system to implement, and although it may not be quite as elegant, it does the #1 thing that most individual developers want Smarty for: page templating. And it doesn't make you use a heavy code library or completely change how you code your files!
The indelible lord of tl;dr
User avatar
Zak Zillion
Posts: 112
Joined: Thu Apr 07, 2011 12:55 am

Re: working with smarty

Post by Zak Zillion »

I looked into code igniter and cakephp. Both seemed good but im a little gun shy right now after smarty, I think I will stick with just php for now. On my next project I think I will look into cakePHP it looked pretty good. Thanks guys for the help with this.
"Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius -- and a lot of courage -- to move in the opposite direction." - Albert Einstein

Old Project(s):
The Dark Flame
User avatar
Torniquet
Posts: 869
Joined: Sun Aug 02, 2009 6:18 am

Re: working with smarty[RESOLVED]

Post by Torniquet »

a little late i know, but hell am i gunna miss out on a smarty topic :D

Smarty is a templating system through and through. I really wouldnt recommend it for a game UNLESS you wanted to offer different styles, ie... differnt layouts for different races etc. It is much easier to use a templating system, rather than work yourself into a knot getting your pages set out to handle differnt layouts.

However, saying that. Since using smarty, i have found it much easier to code because the layout and backend code is seperate, thus making it neater and easier on the eyes (unless you get deep into loops lol, they are pigs!! trust me lol). But basic smarty syntax practically mimics standard code syntax.

i.e

php:

if($x == $y)
{

}


smarty:

{if $x == $y}

{/if}


php

for($x=0; $x<$y; $x++)
{

}

smarty

{for $x=0 to $y}

{/for}


Obviously things differ depending what you want to do, but it is my opinion that it is by far much easier to work with templates rather than it all crammed into a single page.

anywho lol, i saw a smarty topic, i said my bit :p
New Site Coming Soon! Stay tuned :D
User avatar
Jackolantern
Posts: 10891
Joined: Wed Jul 01, 2009 11:00 pm

Re: working with smarty[RESOLVED]

Post by Jackolantern »

Torniquet wrote: I really wouldnt recommend it for a game UNLESS you wanted to offer different styles, ie... differnt layouts for different races etc.
I know this is off-topic, but since this is an older topic, I figured I would mention it. That is a neat idea! Of course it would be a crapton of extra design work, but it would be interesting to have a totally different UI for each race, or perhaps every class. Maybe the form could be different through alternate CSS sheets for each race to reflect the feel of each race's backstory, and the function of the UI could be different for each class to reflect the way the class plays, which would be done through dynamic HTML modifications.
The indelible lord of tl;dr
Post Reply

Return to “Advanced Help and Support”