5 reasons why L4D zombies aren't classic zombies

Left 4 Dead, the fast-paced zombie smashing game recently released from Valve. You are one of four survivors who have to make their way through many different environments. Your obstacles? Hordes of zombies. Other obstacles? Hunters who can leap distances, Smokers who can ensnare and drag you with your tongue, Boomers who vomit zombie-attracting bile, massive hulking Tanks who can smash you in a single blow and bitchy period Witches. Yes this sounds like loads of fun, destroying large amounts of zombies. But how zombie are they really?

1 - No biting

This was a pretty easy one. The classic zombie is usually the result of some sort of infection, in that once an individual dies, the infection takes affect and they rise from the dead. Once a newly undead, the zombies infect other targets by biting them. If the target was not devoured by the zombies hunger, they will eventually die and convert. But now in L4D there is no biting what so ever, only clawing and smacking. When someone is downed, the zombies simply crowd that survivor and flail their arms. Where is the biting, tearing, ripping, dismembering and so on?

A short clip from the great comedy, Shaun of the Dead (bad quality, sorry), simply shows how the zombies should be ripping you apart.

2 - No gruesome walking corpses

Why do all the zombies in L4D have all their limbs? Why are there no guts hanging out of their stomach? All the zombies are fully clothed and have all their limbs, boring. The only similarity to classic zombies is the gray skin, the bloody mouth (but how, there's no biting!) and the frankenstein expression. It would be an awesome idea to have a wide variety of zombies. Some of them can be missing an arm, or maybe two! Others may have one leg or no legs and must crawl to you with their hands (ala Dead Space) to attack. Lastly it would be graphically pleasing if a select few zombies had their innards hanging out and around their body.

3 - No rising out of the ground

This mainly applies to the 3rd chapter of Death Toll (at the church) but could also apply to other areas in the other stories. When I first walked into the grave, I was expecting the zombies to rise out of their graves and surround us. But instead, I was sadly let down and faced another "typical horde". Still, this type of feature would be fun and show homage to the cult classics. It does though contradict the idea of an "infection", but Im going based on zombie ideals.

4 - Freak out from fire

This was another thing in the game that seemed out of place, but I understand its purpose for gameplay. Simply put, zombies have no real physical feeling and can sustain massive damage (excluding having the head destroyed) but keep on trotting forward. A mere molotov cocktail or wave of fire would not cause the zombies to freak out and run around confused. It just means you would have flaming, hungry zombies chasing your ass.

5 - Die without destroying the head

This is another thing that's "good" for gameplay but I'm still going to point it out there. In every classic zombie film, the only way to kill a zombie is to, and I quote, "remove the head or destroy the brain". But just imagine here for a second... an unexpected horde appears, your cower into a corner and let your auto-shottie sing. You mow down a wave of zombies but merely blast off some arms or legs but they keep crawling forward. In a list ditch effort you melee bash the oncoming zombies skulls in. End imagination.

Notice - I am in no way bashing L4D, I actually play this game way more then I should. I just got a bit curious on the ideology behind the L4D zombies against the classic zombies. Enjoy!

Resources for the holidays

It's been over a week without me updating, and im not gonna let that slide! But I do have an excuse, Christmas is right around the corner so I've been extremely busy with work and present hunting. I do have many things in store for the coming month, a few of them being more tutorials in CakePHP, jQuery and general PHP. I also have many open-source scripts that I will be releasing to the public, a few of them including database abstraction, a template engine, pagination, markup parser and more.

Fixing malformed urls in Mint

Recently I moved to this new domain, I wanted to use my old Mint database and keep all my statistics. So I transferred my Mint licenses, installed Mint 2 on the new domain, updated Mints DB configuration and added the JavaScript tag to start tracking. Everything was up and working, but there was one big problem, all my urls were malformed and escaped. They looked like the following (within any pane but search):

milesjohnson%20%7E%20Contact%20Me - Page Title
http%3A//milesj.me/blog/ http%3A//milesj.me/bio/ - Referrers

It took me a while to figure out the problem, I even sent a bug report to Shaun Inman himself. This is what I found, and how to fix it (Some of these may not apply to you, but it is always good to double check).

Using the right pathing

If you go into your Mint preferences, check your "Mint Location" setting. If your website always has the www. prefix, make sure your location setting has it as well and if you do not use the www. prefix, remove it. If you use both methods (like me), be sure to choose only 1 way of linking items. If you are hosted by Dreamhost, you can manage your domains and change its settings to always default to one of the methods. This is what my preferences look like:

Your URL: http://www.milesj.me/
// Mint Preferences
Site Domain(s): milesj.me
Mint Location: http://www.milesj.me/mint
Disabling mod_rewrite

If you or your server has enabled mod_rewrite, either for the RewriteEngine, redirecting or other means, you will need to create an .htaccess file and place it in the root of the /mint/ directory. Within this .htaccess file, all you need to put is RewriteEngine off.

Fixing Mint's DB config after moving domains

If you have transferred licenses and used the same Mint DB on both domains or switched the Mint folder to a new domain, only this next section applies to you. You can either do it manually (below) or read the instructions here.

Since moving the Mint installation to another domain, your old config becomes outdated. To fix this problem, go to your Mint panel (probably in /mint/) and type this in your address bar: http://yourdomain.com/mint/?moved. Your config should now be updated to the new installation and should be working properly.

I hope this has been helpful to someone. Its always best to write about your experiences in the hope that someone else runs into the same problem! If you are still having problems, you can visit Mint's troubleshooting forums.

Using CakePHP's Auth Component

This article pertains to CakePHP 1.2 only!

Since recently diving into CakePHP, I thought the best area to learn would be the user authentication and login. Luckily CakePHP comes bundled with an Authorization Component, and is literally the easiest thing to install. Below I will show you the basics of getting Auth working; do note that I was working in CakePHP 1.2 and PHP 5. To begin the following items must be implemented:

  • Database - A users table with the fields id, username and password (can be customized but recommended)
  • Controller - A users controller with a login and logout action
  • Model - A user model that correlates with the users table
Setting up AppController

The first thing we need to do is setup the AppController. We are placing the code in the AppController so that all child controllers inherit the AuthComponent. Begin by including the AuthComponent by binding it to the $components parameter. We will now create the beforeFilter() action that will hold all the Auth settings that will be passed to the child controllers.

<?php
class AppController extends Controller {
	public $components = array('Auth');
	public function beforeFilter() { 
		Security::setHash('md5');
		// Authenticate
		$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
		$this->Auth->loginRedirect = array('controller' => 'dashboard', 'action' => 'index');
		$this->Auth->loginError = 'No username and password was found with that combination.';
		$this->Auth->logoutRedirect = '/';
	}
} 
?>

In the beforeFilter() action above, you will notice 4 different variables being set. loginRedirect determines what controller/action pair to redirect to upon a successful login, where as logoutRedirect is the route to redirect to when logging out. loginAction is the controller/action in which your login form and processing will be taking place (its best to use CakePHPs defaults of /user/login/). For more information on these variables and additional variables, visit the corresponding cookbook page.

Setting up the UsersController

The next step is to create the UsersController and create the required actions. Within the login() action, there is no need to do any manual form processing or login, the auth system does that magically behind the scenes. You can literally leave this action empty, unless you wish to add a page title $this->pageTitle or validate it against the User model. Within the logout() action we run a redirect to the auth system, which logs us out and redirects to the logoutRedirect we specified in the AppController.

<?php
class UsersController extends AppController {
	public function login() {
		// No form processing needed, Auth does it automatically
	}
	public function logout() {
		$this->redirect($this->Auth->logout());
	}
	public function beforeFilter() {
		parent::beforeFilter();
		// Does not require being logged in
		$this->Auth->allow('signup', 'forgot');
		// If logged in, these pages require logout
		if ($this->Auth->user() && in_array($this->params['action'], array('signup', 'login'))) {
			$this->redirect('/');
		}
	}
}
?>

Now you may see some additional code; another beforeFilter()! This beforeFilter() is specific only to the current controller. It is extremely important to place parent::beforeFilter() in the action so that the parent beforeFilter() can initialize the AuthComponent. The allow() method takes arguments of actions (within the current controller) that do not require you to be logged in to view. Beneath that you will see some custom code that I have written. This code defines actions that require you to be logged out to view (it seems auth does not have anything for that). There are additional methods you can read about in the cookbook.

Creating the form

This is probably the easiest step of the process. Simply use Cake's built in HtmlHelper to build the form. Be sure to name the form after the model you are using for auth (e.g., User).

<?php 
echo $form->create('User', array('url' => array('controller' => 'users', 'action' => 'login')));
echo $form->input('username');
echo $form->input('password');
echo $form->submit('Login');
echo $form->end(); 
?>
Adding additional functionality

There are a couple ways to increase the functionality of the AuthComponent. Typically when you login, the user information in the database that matches the username/password combo is then stored in the AuthComponent. To retrieve the users information you would use the method $this->Auth->user(). A nice way of doing things is binding a $user variable to all views so you can access the users data.

// app_controller.php
public function beforeRender() {
    $this->set('user', $this->Auth->user());
    // In the views $user['User']['username'] would display the logged in users username
}
// controllers/users_controller.php
public function beforeRender() {
	parent::beforeRender();
}

If you would like to use a different model with the AuthComponent, you would add a $this->Auth->userModel variable in AppController::beforeFilter(). You can also add some additional conditions to the login query, for example, making sure a user is active.

$this->Auth->userModel = 'Member';
$this->Auth->userScope = array('User.status' => 'active');
Debugging problems

While working with the AuthComponent, I ran into one major problem. If you are using an old database that is ported over to use CakePHP and you did not use a password salt on the old passwords, be sure to disable Cake's salt (or leave it empty). I didn't realize this for nearly 2 days on why the passwords did not match and then it hit me, Cake's salted passwords will not match existing passwords. If this is a new database, no need to worry about the previous statements.

If for some reason you cannot have a field labeled username or password within your database, there are ways to set it to something else. You would do that by setting the $this->Auth->fields variables in AppController::beforeFilter(). For more information on this subject, visit the trouble shooting in the cookbook.

$this->Auth->fields = array('username' => 'email', 'password' => 'secretpass');
Conclusion

I hope this has been helpful to someone! I spent days debugging and installing this system and by doing so I learned the system in and out. If you have any questions be sure to leave a comment or drop a line by using the contact form. Thanks again for reading, come back for more tutorials!

TF2, Scout and Engineer Updates

Team Fortress 2, how I miss you. Recently I've been getting a bit bored of Team Fortress 2 and have been smashing zombies in the new hit, Left 4 Dead. While L4D is extremely fun, it can get quite boring and lose its feel if you don't have friends to play with. But here comes Valve to the rescue. It seems that Team Fortress will be getting another update that improves upon some existing classes and announces a new Scout package. Here is a quick overview of the new updates:

  • Scout weapon and achievements package.
  • Teleporters will be upgradeable to level 3. As the teleporter is upgraded, the cooldown will decrease.
  • Dispensers will be upgradeable to level 3. They will heal faster and generate metal faster as they are upgraded.
  • Spies will be able to recharge their cloaking ability by picking up ammo off of the ground.
  • We've made a bunch of minor changes by adding particle systems and upgrading the HUD to show things like deaths by critical hits, players that are overhealed, and giving more information to medics when people are calling for them.

It seems most of these updates were released today excluding the Scout. After playing with the new features, it seems the Engineer is quite overpowered. Its upgraded dispenser (it transforms like the sentry when upgraded) regenerates metal so fast that you can easily get a level 3 sentry up twice as fast. The upgraded teleporter can also teleport a whole team to the frontlines within 15 seconds. Hopefully well see how this affects gameplay down the road, and if its still OP, Valve will fix it.

With the new Scout package, it will most likely spark my interest in league and competitive play again. Heres to hoping that we get this new update for Christmas or New years. You can read the official blog post from valve at www.teamfortress.com.

Debugging the CakePHP Auth Component

Finally, I figured it out. For the past 2 days I have been messing with the CakePHP AuthComponent (A prebuilt user login and authentication system). The problem was that it would not log in, even though I was entering correct data from the database. I spent many hours and even posted on the Google CakePHP Discussion group. Even with their help it still would not work, but I found the problem!

CakePHP comes with a password salt feature that automatically salts and encrypts any index called "password" within an array. The problem was that the previous passwords in the database were not encrypted with a salt, so hence the passwords never matched! Once I made the Cake salt empty, it worked in all its glory. I will be posting up a tutorial this week on how to use the AuthComponent, for anyone who was as lost as me trying to get it working.

Riding the Frameworks

So for the past week I have been learning Symfony and CakePHP, both amazing PHP frameworks. I'm curious to learn a framework because I have many large scale projects I would like to build and it would just be easier to use a framework. Symfony is hosting this daily blog where each day it posts a new tutorial and within a month you should understand the framework. Its currently at day 5 and I already understand the structure of Symfony, albeit Propel is quite complicated.

Cake grabbed my interest first, simply because the structure and MVC is extremely easy to understand. The hardest part for me to grasp is the Model system and its hasMany, belongsTo, etc... but I am getting there. The documentation is also very easy to read, I read through the whole cookbook in about 5-6 hours and keep going back for examples and references. Ill admit though, the cookbook is a bit basic in that it doesn't explain some key features thoroughly, your best bet is to open the PHP files yourself and try and figure out what they do.

But right now I'm learning towards Cake, simply because its extremely lightweight compared to Symfony and I prefer its file structure and MVC. Ill give it to Symfony though, its YAML is the easiest thing to write and understand and it also encompasses a strong routing system. Ill be updating more along my PHP journey.

A Fresh New Beginning

It has been such a long time since I've had a personal website up. My last website (www.mileswjohnson.com) has been up for quite a few years and has been through many versions, I believe the last version was 5. But I felt that the site wasn't going in the direction I wanted, so I decided to start over with a new domain and design. And here I am, a fresh new beginning.

This website will house a blog that I plan to update on a daily or weekly basis with topics ranging from web design, gamin and even business. I also have quite a few open source PHP scripts that I will be unveiling in the near future. I hope you enjoy my writings as much as I enjoy posting them.