

/////////////////////////////////////////////////////////////// class : List //

function List()
{
	this.size = 0;
	this.first = 0;
}

List.prototype.Add = function(data)
{
	if(this.Find(data) == true)
	{
		//alert('List.Add - duplicate data found while adding.' + data.name);
		return false;
	}

	if(this.first == 0)
	{
		this.first = new ListNode(data);
	}
	else
	{
		var itr = this.first;

		while(itr.next != 0)
		{
			itr = itr.next;
		}
		
		itr.next = new ListNode(data);
	}

	this.size++;
};

List.prototype.Remove = function(data)
{
	if(this.first == 0)
	{
		return false;
	}
		
	if(this.first.data.Equal(data) == true)
	{
		this.first = this.first.next;
		return true;
	}

	var last = this.first;
	var iterator = this.first;

	while(iterator.data.Equal(data) == true)
	{
		last = iterator;
		iterator = iterator.next;
	
		if(iterator == 0)
		{
			return false;
		}
	}

	last.next = iterator.next;
	this.size--;

	return true;
};

List.prototype.Find = function(data)
{
	var iterator = this.first;

	while(iterator != 0)
	{
		if(iterator.data.Equal(data) == true)
		{
			return true;
		}
			
		iterator = iterator.next;
	}

	return false;
};

List.prototype.Get = function(position)
{
	if(position < 0 || position > (this.size-1))
	{
		return 0;
	}

	var itr = this.first;
	var counter = 0;

	while(counter != position)
	{
		itr = itr.next;
		counter++;
	}
	
	return itr.data;
};

function ListNode(data)
{
	this.data = data;
	this.next = 0;
}


/////////////////////////////////////////////////////////// class : Observer //

function Observer()
{
}

Observer.prototype.Equal = function(operand)
{
	if(this == operand)
		return true;
	
	return false;
};

Observer.prototype.Update = function(object)
{
	alert("Error: Unhandled update.");
};

function Subject()
{
	this.observers = new List();
};

Subject.prototype.Attach = function(observer)
{
	this.observers.Add(observer);
};

Subject.prototype.Detach = function(observer)
{
	this.observers.Remove(observer);
};

Subject.prototype.Notify = function()
{
	for(var i = 0; i < this.observers.size; i++)
	{
		this.observers.Get(i).Update(this);
	}
};

Subject.prototype.DetachAll = function()
{
	this.observers = new List();
};


/////////////////////////////////////////////////////////// String functions //

function StringFirstLetterToUpper(string)
{
	if(string.length == 0)
		return "";

	return string.substring(0,1).toUpperCase() + string.slice(1);
}



//////////////////////////////////////////////////////// class : TalentBuild //

function TalentBuild(id, pet, points_left)
{
	this.id = id;
	this.pet = pet;
	this.points_left = points_left;
	this.talents = new List();
	this.pet_frame = 0;
	this.pet_button_frame = 0;
	this.pet_information_frame = 0;
	this.pet_training_points_frame = 0;
	
	this.pet_button = new PetButton(pet.type);
	this.reset_button = new ResetButton();
	this.level_button = new LevelButton();

	this.armor = 0;
	this.stamina = 0;
	
	this.arcane_resistance = 0;
	this.fire_resistance = 0;
	this.nature_resistance = 0;
	this.frost_resistance = 0;
	this.shadow_resistance = 0;
}

TalentBuild.prototype = new Observer();
TalentBuild.prototype.constructor = TalentBuild;

TalentBuild.prototype.BuildPetFrame = function(root_element)
{
	// Create frame for pet frame.
	this.pet_frame = document.createElement('div');
	this.pet_frame.id = this.id;
	this.pet_frame.className = 'PetFrame';
	root_element.appendChild(this.pet_frame);

	// Create frame for pet button frame.
	this.pet_button.Build(this.pet_frame);

	// Create frame for pet information frame.
	this.pet_information_frame = document.createElement('div');
	this.pet_information_frame.className = 'PetInformationFrame';
	this.pet_frame.appendChild(this.pet_information_frame);
};

TalentBuild.prototype.BuildTrainingPointsFrame = function(root_element)
{
	// Create frame for talent points left.
	this.pet_training_points_frame = document.createElement('div');
	this.pet_training_points_frame.className = 'TrainingPointsFrame';

	this.reset_button.Build(this.pet_training_points_frame);
	this.level_button.Build(this.pet_training_points_frame);
	
	root_element.appendChild(this.pet_training_points_frame);
};

TalentBuild.prototype.Update = function(object)
{
	// Render
	this.Render();
};

TalentBuild.prototype.LearnTalent = function(talent)
{
	// Check if level requirement is fulfilled.
	if(this.pet.level < talent.level_requirement)
		return false;

	// Check if we can afford talent.
	if(this.points_left < talent.cost)
		return false;
		
	// Check for correct species.
	if(talent.restriction.IsApproved(this.pet.type.name) == false)
		return false;

	// Learn talent.
	this.talents.Add(talent);
	this.points_left -= talent.cost;

	return true;
};

TalentBuild.prototype.UnlearnTalent = function(talent)
{
	// Unlearn talent.
	this.talents.Remove(talent);
	this.points_left += talent.cost;

	return true;
};

TalentBuild.prototype.Render = function()
{
	// Render pet button frame.
	this.pet_button.Render();

	// Render pet information frame.
	var html = "";
	html += "<center><span class='PetInformationTitle'>" + StringFirstLetterToUpper(this.pet.type.name) + "</span></center>";
	html += "<span class='PetInformationText'>" + this.pet.type.description + "</span>";

	this.pet_information_frame.innerHTML = html;

	// Render training points frame.
	html = "";
	html += "<span class='TrainingPointsText'>Training Points Left:</span> <span class='TrainingPointsValue'>" + this.points_left + "</span>";

	this.pet_training_points_frame.innerHTML = html;
	
	this.level_button.Render();
	this.reset_button.Render();
};


////////////////////////////////////////////////// class : TalentRestriction //

function TalentRestriction(restriction_type, species)
{
	this.restriction_type = restriction_type;
	this.species = species;
}

TalentRestriction.prototype.IsApproved = function(type)
{
	if(this.restriction_type == "included")
	{
		for(var i = 0; i < this.species.length; i++)
		{
			if(this.species[i] == type)
				return true;
		}
		
		return false;
	}
	else if(this.restriction_type == "excluded")
	{

		for(var i = 0; i < this.species.length; i++)
		{
			if(this.species[i] == type)
				return false;
		}
		
		return true;
	}
	else
	{
		alert('TalentRestriction.IsRestricted() - Unknown restriction type.');
		return false;
	}
};


/////////////////////////////////////////////////////// class : TalentEffect //

function TalentEffect(type, effect, value)
{
	this.type = type;
	this.effect = effect;
	this.value = value;
}


///////////////////////////////////////////////////////////// class : Talent //

function Talent(name, description, icon_url, rank, level_requirement, cost, effect, restriction)
{
	this.name = name;
	this.description = description;
	this.icon_url = icon_url;
	this.rank = rank;
	this.level_requirement = level_requirement;
	this.cost = cost;
	this.effect = effect;
	
	if(restriction)
		this.restriction = restriction;
	else
		this.restriction = new TalentRestriction("excluded", new Array());
};

Talent.prototype.Equal = function(operand)
{
	if(this.name == operand.name)
	{
		if(this.rank == operand.rank)
			return true;
	}

	return false;
};


//////////////////////////////////////////////////////////// class : PetType //

function PetType(name, icon_url, description)
{
	this.name = name;
	this.icon_url = icon_url;
	this.description = description;
}

PetType.prototype.Equal = function(operand)
{
	if(this.name == operand.name)
		return true;
	
	return false;
};


//////////////////////////////////////////////////////////////// class : Pet //

function Pet(type, name, level)
{
	this.type = type;
	this.name = name;
	this.level = level;
	this.talent_build = new TalentBuild('talentbuild01', this, this.level * 5);
}


/////////////////////////////////////////////////////// class : TalentButton //

function TalentButton(id, talents)
{
	this.element = 0;
	this.popup_frame = 0;
	this.rendering_popup = false;
	this.id = id;
	this.talents = talents;
	this.current_talent = 0;
	this.counter = 0;
	this.z_index = 0;
}

TalentButton.prototype = new Subject();
TalentButton.prototype.constructor = TalentButton;

TalentButton.prototype.Equal = function(operand)
{
	if(this.id == operand.id)
		return true;
		
	return false;
};

TalentButton.prototype.Build = function(root_element, z_index)
{
	this.z_index = z_index;

	this.element = document.createElement('div');
	this.element.modelObj = this;
	this.element.onmouseup = OnClick;
	this.element.onmouseover = OnMouseOver;
	this.element.onmouseout = OnMouseOut;
	this.element.id = this.id;

	// Build popup.
	this.popup_frame = document.createElement('div');
	this.popup_frame.className = 'TalentButtonPopupFrame';

	// Build counter.
	this.counter = document.createElement('div');
	this.counter.onmousedown = function(event) {return false;};
	this.counter.className = 'TalentButtonCounter';
	if( (this.talents.size-1) > 9)
	{
		this.counter.style.width = '27px';
		//this.counter.style.left = '21px';
	}

	root_element.appendChild(this.element);

	// Cache all talent ranks icons.
	for(var i = 0; i < (this.talents.size - 1); i++)
	{
		var talent = this.talents.Get(i);
		var cache = new Image;
		cache.src = talent.icon_url;
	}
};

TalentButton.prototype.Render = function()
{
	var application = Application.GetInstance();
	var max_talents = this.talents.size-1;
	var talent = this.talents.Get(this.current_talent);

	// Check if talent is unavailable to the current pet.
	if(talent.restriction.IsApproved(application.pet.type.name) == false)
	{
		this.element.className = 'TalentButtonDisabled';
		this.element.style.zIndex = this.z_index;
		this.counter.className = 'TalentButtonCounterDisabled';
	
		var talent = this.talents.Get(this.current_talent);
		
		this.element.innerHTML = "<img src=\'" + talent.icon_url + "\'>";
		
		this.counter.innerHTML = "<center>" + talent.rank + "/" + (this.talents.size-1) + "</center>";
		this.element.appendChild(this.counter);
		return;
	}
	
	// Check which rank to render.
	if(talent.rank == 0)
	{
		this.element.className = 'TalentButtonMin';
		this.element.style.zIndex = this.z_index;
		this.counter.className = 'TalentButtonCounterMin';
	}
	else if(talent.rank == max_talents)
	{
		this.element.className = 'TalentButtonMax';
		this.element.style.zIndex = this.z_index;
		this.counter.className = 'TalentButtonCounterMax';
	}
	else
	{
		this.element.className = 'TalentButtonBetween';
		this.element.style.zIndex = this.z_index;
		this.counter.className = 'TalentButtonCounterBetween';
	}

	var talent = this.talents.Get(this.current_talent);
	this.element.innerHTML = "<img src=\'" + talent.icon_url + "\'>";

	this.counter.innerHTML = "<center>" + talent.rank + "/" + (this.talents.size-1) + "</center>";
	this.element.appendChild(this.counter);
};

TalentButton.prototype.RenderPopup = function()
{
	var application = Application.GetInstance();

	// Avoid double-rendering popup.
	if(this.rendering_popup == true)
		return;

	this.rendering_popup = true;

	// Render popup description for icon.
	var html = "";
	var talent = this.talents.Get(this.current_talent);

	html += "<span class='TalentButtonPopupTitle'>" + talent.name + "</span><br>";
	html += "<span class='TalentButtonPopupText'>Rank: " + talent.rank + "/" + (this.talents.size-1) + "</span><br>";
	html += "<span class='TalentButtonPopupDescription'>" + talent.description + "</span><br><br>";

	if(this.current_talent > 0 && this.current_talent < (this.talents.size-1))
	{
		var next_talent = this.talents.Get(this.current_talent + 1);
		html += "<span class='TalentButtonPopupText'>Next Rank:</span><br>";
		html += "<span class='TalentButtonPopupDescription'>" + next_talent.description + "</span><br><br>";
	}

	if(talent.restriction.IsApproved(application.pet.type.name) == true)
	{
		if(this.current_talent < (this.talents.size-1))
		{
			var next_talent = this.talents.Get(this.current_talent + 1);

			if(application.pet.level < next_talent.level_requirement)
				html += "<span class='TalentButtonPopupUnlearnable'>Requires Level " + next_talent.level_requirement + "</span>";
			else
				html += "<span class='TalentButtonPopupLearn'>Left Click to Learn (" + next_talent.cost +" TP)</span>";
		}
		
		if(this.current_talent > 0)
		{
			var previous_talent = this.talents.Get(this.current_talent - 1);
			html += "<span class='TalentButtonPopupUnlearn'>Right Click to Unlearn (" + -talent.cost + " TP)</span>";
		}
	}
	else
	{
		html += "<b><span class='TalentButtonPopupText'>Cannot be learn by " + application.pet.type.name +"s</span></b>";
	}

	html += "<br>";

	this.popup_frame.innerHTML = html;
	this.element.appendChild(this.popup_frame);
};

TalentButton.prototype.Increase = function()
{
	var application = Application.GetInstance();

	if(this.current_talent < (this.talents.size - 1))
	{
		// Check if talent can be learned.
		var talent = this.talents.Get(this.current_talent+1);

		if(application.pet.talent_build.LearnTalent(talent) == false)
			return;

		this.current_talent++;
	}
	
	// Notify all observers about change in state.
	this.Notify();
};

TalentButton.prototype.Decrease = function()
{
	var application = Application.GetInstance();

	if(this.current_talent > 0)
	{
		// Unlearn talent.
		var talent = this.talents.Get(this.current_talent);
		application.pet.talent_build.UnlearnTalent(talent);
		this.current_talent--;
	}

	// Notify all observers about change in state.
	this.Notify();
};

TalentButton.prototype.OnClick = function(event)
{
	if(event.button == 0 || event.button == 1)
	{
		// Left mouse button released.
		this.Increase();
		this.Render();
		this.rendering_popup = false;
		this.RenderPopup();
	}
	else if(event.button == 2)
	{
		// Right mouse button released.
		this.Decrease();
		this.Render();
		this.rendering_popup = false;
		this.RenderPopup();
	}

	// Disable propagation of event.
	event.cancelBubble = true;
	if(event.stopPropagation) event.stopPropagation();
};

TalentButton.prototype.OnMouseOver = function(event)
{
	this.RenderPopup();
};

TalentButton.prototype.OnMouseOut = function(event)
{
	if(this.rendering_popup == true)
	{
		this.rendering_popup = false;
		this.element.removeChild(this.popup_frame);
	}
};


////////////////////////////////////////////////////////// class : PetButton //

function PetButton(pet_type)
{
	this.element = 0;
	this.pet_type = pet_type;
	this.popup_frame = 0;
	this.is_browsing = false;
	
	this.state_changed = true;
}

PetButton.prototype.Build = function(root_element)
{
	this.element = document.createElement('div');
	this.element.modelObj = this;
	this.element.onmouseup = OnClick;
	this.element.onmouseover = OnMouseOver;
	this.element.onmouseout = OnMouseOut;
	this.element.className = 'PetButtonFrame';

	// Build popup.
	this.popup_frame = document.createElement('div');
	this.popup_frame.className = 'PetButtonPopupFrame';
	this.popup_frame.innerHTML = "<center>Left Click To Select A Different Pet</center>";

	root_element.appendChild(this.element);
};

PetButton.prototype.Render = function()
{
	// Check if we need to render.
	if(this.state_changed == false)
		return;

	var icon = document.createElement('img');
	icon.src =  this.pet_type.icon_url;
	icon.className = 'PetButtonIcon'

	// Check for browser (png transparency fix)
	var mask = document.createElement('div');

	if(navigator.userAgent.toLowerCase().indexOf("msie") != -1)
		mask.className = 'PetButtonMaskIE';
	else
		mask.className = 'PetButtonMask';
	
	this.element.appendChild(icon);
	this.element.appendChild(mask);
	
	this.state_changed = false;
};

PetButton.prototype.OnClick = function(event)
{
	if(event.button == 0 || event.button == 1)
	{
		if(this.is_browsing == true)
			return;

		this.is_browsing = true;
	
		// Disable popup.
		this.popup_frame.innerHTML = "";
		this.popup_frame.className = 'PetButtonPopupHide';
	
		// Build pet browser.
		var browser = new PetBrowser(application.pet_types);
		browser.Build(this.element);
		browser.Render();
	}
	else if(event.button == 2)
	{
	}
	
	// Disable propagation of event.
	event.cancelBubble = true;
	if(event.stopPropagation) event.stopPropagation();
};

PetButton.prototype.OnMouseOver = function(event)
{
	if(this.is_browsing == false)
	{
		this.element.appendChild(this.popup_frame);

	}
};

PetButton.prototype.OnMouseOut = function(event)
{
	if(this.is_browsing == false)
	{
		this.element.removeChild(this.popup_frame);

	}
};



////////////////////////////////////////////////////////// class : LevelButton //

function LevelButton()
{
	this.element = 0;
	this.popup = 0;
	this.parent_element = 0;
	this.level_browser = 0;
	this.is_selecting = false;
	this.is_selected = false;
	this.is_pressed = false;
}

LevelButton.prototype.Build = function(root_element)
{
	this.parent_element = root_element;
	this.element = document.createElement('div');
	this.element.modelObj = this;
	this.element.onmousedown = OnMouseDown;
	this.element.onmouseup = OnClick;
	this.element.onmouseover = OnMouseOver;
	this.element.onmouseout = OnMouseOut;
	this.element.className = 'TrainingPointsLevelButton';
	
	this.level_browser = document.createElement('div');
	this.level_browser.className = 'LevelBrowserFrame';
	
	this.popup = document.createElement('div');
	this.popup.className = 'TrainingPointsLevelPopupHidden';
	this.popup.innerHTML = "<center>Left Click To Select A Different Level</center>";
};

LevelButton.prototype.Render = function()
{
	var application = Application.GetInstance();

	this.element.innerHTML = "<div class='TrainingPointsLevelTextFrame'><center><span class='TrainingPointsLevelText'>" + application.pet.level + "</span></center></div>";
	this.element.appendChild(this.popup);
	this.parent_element.appendChild(this.element);
};

LevelButton.prototype.RenderLevels = function(event)
{
	var buttons = new Array;

	var radius = 55, dradius = 1.2, ddradius = 1.005, a = 0.0, da = 0.3, dda = 1.003;
	
	for(var i = 1; i <= 70; i++)
	{
		var x = radius * Math.cos(a);
		var y = 250.0 + radius * Math.sin(a);

		var button = new LevelSelectButton(i, x + 200.0, y + 0.0);
		button.Build(this.level_browser);
		button.Render();

		buttons[i] = button;

		a += da;
		radius += dradius;
		dradius *= ddradius;
		da *= dda;
	}
	
	var application = Application.GetInstance();
	application.element.appendChild(this.level_browser);
};

LevelButton.prototype.OnMouseDown = function(event)
{
	if(event.button == 0 || event.button == 1)
	{
		if(this.is_pressed == false)
		{
			this.is_pressed = true;
			this.element.className = 'TrainingPointsLevelButtonPressed';
			this.element.innerHTML = "<div class='TrainingPointsLevelTextFrame'><center><span class='TrainingPointsLevelTextPressed'>" + application.pet.level + "</span></center></div>";
		}
	}
	else if(event.button == 2)
	{
	}

	// Disable propagation of event.
	event.cancelBubble = true;
	if(event.stopPropagation) event.stopPropagation();
};

LevelButton.prototype.OnClick = function(event)
{
	if(event.button == 0 || event.button == 1)
	{
		if(this.is_selecting == false)
		{
			if(this.is_pressed == true)
			{
				this.is_pressed = false;
				this.element.className = 'TrainingPointsLevelButton';
				this.element.innerHTML = "<div class='TrainingPointsLevelTextFrame'><center><span class='TrainingPointsLevelText'>" + application.pet.level + "</span></center></div>";
				this.element.appendChild(this.popup);
			}

			this.is_selecting = true;
			this.RenderLevels();
		}
	}
	else if(event.button == 2)
	{
	}

	// Disable propagation of event.
	event.cancelBubble = true;
	if(event.stopPropagation) event.stopPropagation();
};

LevelButton.prototype.OnMouseOver = function(event)
{
	this.popup.className = 'TrainingPointsLevelPopup';
};

LevelButton.prototype.OnMouseOut = function(event)
{
	this.popup.className = 'TrainingPointsLevelPopupHidden';
	
	if(this.is_pressed == true)
	{
		this.is_pressed = false;
		this.element.className = 'TrainingPointsLevelButton';
		this.element.innerHTML = "<div class='TrainingPointsLevelTextFrame'><center><span class='TrainingPointsLevelText'>" + application.pet.level + "</span></center></div>";
	}
};


////////////////////////////////////////////////// class : LevelSelectButton //

function LevelSelectButton(level, x, y)
{
	this.element = 0;
	this.parent_element = 0;
	this.level = level;
	this.x = x;
	this.y = y;
	this.is_selected = false;
}

LevelSelectButton.prototype.Build = function(root_element)
{
	this.parent_element = root_element;
	this.element = document.createElement('div');
	this.element.modelObj = this;
	this.element.onmousedown = function(event) {return false;};
	this.element.onmouseup = OnClick;
	this.element.onmouseover = OnMouseOver;
	this.element.onmouseout = OnMouseOut;
	this.element.className = 'TrainingPointsLevelChooser';
	this.element.style.left = this.x;
	this.element.style.top = this.y;
	this.element.innerHTML = "<span><center>" + this.level + "</center></span>";

	root_element.appendChild(this.element);
};

LevelSelectButton.prototype.Render = function()
{
};

LevelSelectButton.prototype.OnClick = function(event)
{
	if(event.button == 0 || event.button == 1)
	{
		var application = Application.GetInstance();
		application.Reset(this.level);
	}
	else if(event.button == 2)
	{
	}

	// Disable propagation of event.
	//event.cancelBubble = true;
	//if(event.stopPropagation) event.stopPropagation();
};

LevelSelectButton.prototype.OnMouseOver = function(event)
{
	if(this.is_selected == false)
	{
		this.is_selected = true;
		this.element.className = 'TrainingPointsLevelChooserSelected';
	}
};

LevelSelectButton.prototype.OnMouseOut = function(event)
{
	this.is_selected = false;
	this.element.className = 'TrainingPointsLevelChooser';
};


////////////////////////////////////////////////////////// class :ResetButton //

function ResetButton()
{
	this.element = 0;
	this.parent_element = 0;
	this.is_pressed = false;
}

ResetButton.prototype.Build = function(root_element)
{
	this.parent_element = root_element;
	this.element = document.createElement('div');
	this.element.modelObj = this;
	this.element.onmousedown = OnMouseDown;
	this.element.onmouseup = OnClick;
	this.element.onmouseout = OnMouseOut;
	this.element.className = 'TrainingPointsResetButton';
};

ResetButton.prototype.Render = function()
{
	this.parent_element.appendChild(this.element);
};

ResetButton.prototype.OnMouseDown = function(event)
{
	if(event.button == 0 || event.button == 1)
	{
		this.is_pressed = true;
		this.element.className = 'TrainingPointsResetButtonPressed';
	}
	else if(event.button == 2)
	{
	}
	
	// Disable propagation of event.
	event.cancelBubble = true;
	if(event.stopPropagation) event.stopPropagation();
};

ResetButton.prototype.OnClick = function(event)
{
	if(event.button == 0 || event.button == 1)
	{
		if(this.is_pressed == true)
		{
			this.is_pressed = false;
			this.element.className = 'TrainingPointsResetButton';
			
			var application = Application.GetInstance();
			application.Reset(application.pet.level);
		}
	}
	else if(event.button == 2)
	{
	}

	// Disable propagation of event.
	event.cancelBubble = true;
	if(event.stopPropagation) event.stopPropagation();
};

ResetButton.prototype.OnMouseOut = function(event)
{
	if(this.is_pressed == true)
	{
		this.is_pressed = false;
		this.element.className = 'TrainingPointsResetButton';
	}
};


///////////////////////////////////////////////////////// class : PetBrowser //

function PetBrowser(pet_types)
{
	this.pet_types = pet_types;
	this.element = 0;
	this.buttons = 0;
}

PetBrowser.prototype.Build = function(root_element)
{
	this.element = document.createElement('div');
	this.element.modelObj = this;
	this.element.className = 'PetBrowserFrame';

	// Build pet buttons.
	this.buttons = new Array();
	for(var i = 0; i < this.pet_types.length; i++)
	{
		this.buttons[i] = new PetBrowserButton(this.pet_types[i]);
		this.buttons[i].Build(this.element);
	}

	root_element.appendChild(this.element);
};

PetBrowser.prototype.Render = function()
{
	// Render pet buttons.
	for(var i = 0; i < this.pet_types.length; i++)
	{
		this.buttons[i].Render();
	}
};


/////////////////////////////////////////////////// class : PetBrowserButton //

function PetBrowserButton(pet_type)
{
	this.element = 0;
	this.pet_type = pet_type;
	this.is_selected = false;
}

PetBrowserButton.prototype.Build = function(root_element)
{
	this.element = document.createElement('div');
	this.element.modelObj = this;
	this.element.onmousedown = function() {return false;};
	this.element.onmouseup = OnClick;
	this.element.onmouseover = OnMouseOver;
	this.element.onmouseout = OnMouseOut;
	this.element.className = 'PetBrowserButton';
	root_element.appendChild(this.element);
};

PetBrowserButton.prototype.Render = function()
{
	this.element.innerHTML += "<center><img class='PetBrowserButtonIcon' src='" + this.pet_type.icon_url + "'><br>" + StringFirstLetterToUpper(this.pet_type.name) + "</center>";
};

PetBrowserButton.prototype.OnClick = function(event)
{
	if(event.button == 0 || event.button == 1)
	{
		var application = Application.GetInstance();
		application.SelectPet(this.pet_type);
	}
	else if(event.button == 2)
	{
	}
	
	// Disable propagation of event.
	event.cancelBubble = true;
	if(event.stopPropagation) event.stopPropagation();
};

PetBrowserButton.prototype.OnMouseOver = function(event)
{
	this.element.className = 'PetBrowserButtonSelected';
}

PetBrowserButton.prototype.OnMouseOut = function(event)
{
	this.element.className = 'PetBrowserButton';
};


///////////////////////////////////////////////////////////// Event Handling //

function OnMouseDown(event)
{
	if(!event)
		var event = window.event;

	var modelObj = this.modelObj;

	if(!modelObj)
		DebugWrite("OnMouseDown: Invalid modelObj");

	modelObj.OnMouseDown(event);
}

function OnClick(event)
{
	if(!event)
		var event = window.event;

	var modelObj = this.modelObj;

	if(!modelObj)
		DebugWrite("OnMouseOut: Invalid modelObj");

	modelObj.OnClick(event);
}

function OnMouseOver(event)
{
	if(!event)
		var event = window.event;

	var modelObj = this.modelObj;

	if(!modelObj)
		DebugWrite("OnMouseOut: Invalid modelObj");

	modelObj.OnMouseOver(event);
}

function OnMouseOut(event)
{
	if(!event)
		var event = window.event;

	var modelObj = this.modelObj;

	if(!modelObj)
		DebugWrite("OnMouseOut: Invalid modelObj");

	modelObj.OnMouseOut(event);
}

function OnLoadImage()
{
	var modelObj = this.modelObj;

	if(!modelObj)
		DebugWrite("OnLoadImage: Invalid modelObj");

	modelObj.OnLoadImage();
}


////////////////////////////////////////////////////////////////////// Debug //

function DebugWrite(string)
{
	var element = document.getElementById("list");
	element.innerHTML += "\n\n";
	element.innerHTML += string;
	element.innerHTML += "\n";
}


//////////////////////////////////////////////////////// class : Application //

function Application()
{
	this.running = false;

	this.element = 0;

	this.pet_types = new Array(
		new PetType('serpent', 'icons/pet_serpent.gif', "<b>Armor:</b> Low<br><b>Health:</b> Medium<br><b>Damage:</b> Medium"),
		new PetType('spider', 'icons/pet_spider.gif', "<b>Armor:</b> Low<br><b>Health:</b> Medium<br><b>Damage:</b> High"),
		new PetType('gorilla', 'icons/pet_gorilla.gif', "<b>Armor:</b> Low<br><b>Health:</b> High<br><b>Damage:</b> Medium"),
		new PetType('scorpid', 'icons/pet_scorpid.gif', "<b>Armor:</b> High<br><b>Health:</b> Medium<br><b>Damage:</b> Low"),
		new PetType('bat', 'icons/pet_bat.gif', "<b>Armor:</b> Low<br><b>Health:</b> Medium<br><b>Damage:</b> High"),
		new PetType('boar', 'icons/pet_boar.gif', "<b>Armor:</b> High<br><b>Health:</b> High<br><b>Damage:</b> Low"),
		new PetType('vulture', 'icons/pet_vulture.gif', "<b>Armor:</b> Medium<br><b>Health:</b> Medium<br><b>Damage:</b> Medium"),
		new PetType('crocolisk', 'icons/pet_crocolisk.gif', "<b>Armor:</b> High<br><b>Health:</b> Low<br><b>Damage:</b> Medium"),
		new PetType('hyena', 'icons/pet_hyena.gif', "<b>Armor:</b> Medium<br><b>Health:</b> Medium<br><b>Damage:</b> Medium"),
		new PetType('owl', 'icons/pet_owl.gif', "<b>Armor:</b> Low<br><b>Health:</b> Medium<br><b>Damage:</b> High"),
		new PetType('raptor', 'icons/pet_raptor.gif', "<b>Armor:</b> Medium<br><b>Health:</b> Low<br><b>Damage:</b> High"),
		new PetType('wind serpent', 'icons/pet_wind_serpent.gif', "<b>Armor:</b> Low<br><b>Health:</b> Medium<br><b>Damage:</b> High"),
		new PetType('turtle', 'icons/pet_turtle.gif', "<b>Armor:</b> High<br><b>Health:</b> Medium<br><b>Damage:</b> Low"),
		new PetType('crab', 'icons/pet_crab.gif', "<b>Armor:</b> High<br><b>Health:</b> Medium<br><b>Damage:</b> Low"),
		new PetType('tallstrider', 'icons/pet_tallstrider.gif', "<b>Armor:</b> Low<br><b>Health:</b> High<br><b>Damage:</b> Medium"),
		new PetType('wolf', 'icons/pet_wolf.gif', "<b>Armor:</b> Medium<br><b>Health:</b> Medium<br><b>Damage:</b> Medium"),
		new PetType('cat', 'icons/pet_cat.gif', "<b>Armor:</b> Low<br><b>Health:</b> Medium<br><b>Damage:</b> High"),
		new PetType('bear', 'icons/pet_bear.gif', "<b>Armor:</b> Medium<br><b>Health:</b> High<br><b>Damage:</b> Low"),
		new PetType('ravager', 'icons/pet_ravager.gif', "<b>Armor:</b> Medium<br><b>Health:</b> Low<br><b>Damage:</b> High"),
		new PetType('dragonhawk', 'icons/pet_dragonhawk.gif', "<b>Armor:</b> Medium<br><b>Health:</b> Medium<br><b>Damage:</b> Medium"),
		new PetType('nether ray', 'icons/pet_nether_ray.gif', "<b>Armor:</b> Low<br><b>Health:</b> High<br><b>Damage:</b> Medium"),
		new PetType('warp stalker', 'icons/pet_warp_stalker.gif', "<b>Armor:</b> Medium<br><b>Health:</b> Medium<br><b>Damage:</b> Low"),
		new PetType('sporebat', 'icons/pet_sporebat.gif', "<b>Armor:</b> Medium<br><b>Health:</b> Medium<br><b>Damage:</b> Medium")
	);

	this.pet = new Pet(this.pet_types[12], "Hertugen", 70);

	// Resistance talents
	this.talents_arcane = new List();
	this.talents_fire = new List();
	this.talents_nature = new List();
	this.talents_frost = new List();
	this.talents_shadow = new List();

	// Common talents
	this.talents_stamina = new List();
	this.talents_armor = new List();
	this.talents_claw = new List();
	this.talents_growl = new List();
	this.talents_bite = new List();
	this.talents_dash = new List();

	// Additional talents
	this.talents_thunderstomp = new List();
	this.talents_shell_shield = new List();
	this.talents_prowl = new List();
	this.talents_charge = new List();
	this.talents_cower = new List();
	this.talents_dive = new List();
	this.talents_furious_howl = new List();
	this.talents_lightning_breath = new List();
	this.talents_scorpid_poison = new List();
	this.talents_screech = new List();

	// New talents
	this.talents_poison_spit = new List();
	this.talents_fire_breath = new List();
	this.talents_warp = new List();
	this.talents_gore = new List();

	this.talents_avoidance = new List();
	this.talents_cobra_reflexes = new List();
	
	this.talent_buttons = 0;
}

Application.__instance__ = 0;

Application.GetInstance = function()
{
	if(this.__instance__ == 0)
	{
		this.__instance__ = new Application();
	}
	
	return this.__instance__;
};


Application.prototype.Run = function()
{
	if(this.running == true)
	{
		alert('Application.Run - Application already running.');
		return;
	}

	this.running = true;
	
	this.element = document.getElementById("application");

	this.BuildTalents();
	this.BuildTalentButtons();
};

Application.prototype.BuildTalents = function()
{
	// Arcane resistance talents
	this.talents_arcane.Add(new Talent("Arcane Resistance", "Increases Arcane Resistance by 30.", "icons/icon_arcane_resistance_grey.gif", 0, 20, 0, new TalentEffect("resistance", "arcane", 0)));
	this.talents_arcane.Add(new Talent("Arcane Resistance", "Increases Arcane Resistance by 30.", "icons/icon_arcane_resistance.gif", 1, 20, 5, new TalentEffect("resistance", "arcane", 30)));
	this.talents_arcane.Add(new Talent("Arcane Resistance", "Increases Arcane Resistance by 60.", "icons/icon_arcane_resistance.gif", 2, 30, 10, new TalentEffect("resistance", "arcane", 30)));
	this.talents_arcane.Add(new Talent("Arcane Resistance", "Increases Arcane Resistance by 90.", "icons/icon_arcane_resistance.gif", 3, 40, 30, new TalentEffect("resistance", "arcane", 30)));
	this.talents_arcane.Add(new Talent("Arcane Resistance", "Increases Arcane Resistance by 120.", "icons/icon_arcane_resistance.gif", 4, 50, 45, new TalentEffect("resistance", "arcane", 30)));
	this.talents_arcane.Add(new Talent("Arcane Resistance", "Increases Arcane Resistance by 140.", "icons/icon_arcane_resistance.gif", 5, 60, 15, new TalentEffect("resistance", "arcane", 20)));
	
	// Fire resistance talents
	this.talents_fire.Add(new Talent("Fire Resistance", "Increases Fire Resistance by 30.", "icons/icon_fire_resistance_grey.gif", 0, 20, 0, new TalentEffect("resistance", "fire", 0)));
	this.talents_fire.Add(new Talent("Fire Resistance", "Increases Fire Resistance by 30.", "icons/icon_fire_resistance.gif", 1, 20, 5, new TalentEffect("resistance", "fire", 30)));
	this.talents_fire.Add(new Talent("Fire Resistance", "Increases Fire Resistance by 60.", "icons/icon_fire_resistance.gif", 2, 30, 10, new TalentEffect("resistance", "fire", 30)));
	this.talents_fire.Add(new Talent("Fire Resistance", "Increases Fire Resistance by 90.", "icons/icon_fire_resistance.gif", 3, 40, 30, new TalentEffect("resistance", "fire", 30)));
	this.talents_fire.Add(new Talent("Fire Resistance", "Increases Fire Resistance by 120.", "icons/icon_fire_resistance.gif", 4, 50, 45, new TalentEffect("resistance", "fire", 30)));
	this.talents_fire.Add(new Talent("Fire Resistance", "Increases Fire Resistance by 140.", "icons/icon_fire_resistance.gif", 5, 60, 15, new TalentEffect("resistance", "fire", 20)));

	// Nature resistance talents
	this.talents_nature.Add(new Talent("Nature Resistance", "Increases Nature Resistance by 30.", "icons/icon_nature_resistance_grey.gif", 0, 20, 0, new TalentEffect("resistance", "nature", 0)));
	this.talents_nature.Add(new Talent("Nature Resistance", "Increases Nature Resistance by 30.", "icons/icon_nature_resistance.gif", 1, 20, 5, new TalentEffect("resistance", "nature", 30)));
	this.talents_nature.Add(new Talent("Nature Resistance", "Increases Nature Resistance by 60.", "icons/icon_nature_resistance.gif", 2, 30, 10, new TalentEffect("resistance", "nature", 30)));
	this.talents_nature.Add(new Talent("Nature Resistance", "Increases Nature Resistance by 90.", "icons/icon_nature_resistance.gif", 3, 40, 30, new TalentEffect("resistance", "nature", 30)));
	this.talents_nature.Add(new Talent("Nature Resistance", "Increases Nature Resistance by 120.", "icons/icon_nature_resistance.gif", 4, 50, 45, new TalentEffect("resistance", "nature", 30)));
	this.talents_nature.Add(new Talent("Nature Resistance", "Increases Nature Resistance by 140.", "icons/icon_nature_resistance.gif", 5, 60, 15, new TalentEffect("resistance", "nature", 20)));

	// Shadow resistance talents
	this.talents_shadow.Add(new Talent("Shadow Resistance", "Increases Shadow Resistance by 30.", "icons/icon_shadow_resistance_grey.gif", 0, 20, 0, new TalentEffect("resistance", "shadow", 0)));
	this.talents_shadow.Add(new Talent("Shadow Resistance", "Increases Shadow Resistance by 30.", "icons/icon_shadow_resistance.gif", 1, 20, 5, new TalentEffect("resistance", "shadow", 30)));
	this.talents_shadow.Add(new Talent("Shadow Resistance", "Increases Shadow Resistance by 60.", "icons/icon_shadow_resistance.gif", 2, 30, 10, new TalentEffect("resistance", "shadow", 30)));
	this.talents_shadow.Add(new Talent("Shadow Resistance", "Increases Shadow Resistance by 90.", "icons/icon_shadow_resistance.gif", 3, 40, 30, new TalentEffect("resistance", "shadow", 30)));
	this.talents_shadow.Add(new Talent("Shadow Resistance", "Increases Shadow Resistance by 120.", "icons/icon_shadow_resistance.gif", 4, 50, 45, new TalentEffect("resistance", "shadow", 30)));
	this.talents_shadow.Add(new Talent("Shadow Resistance", "Increases Shadow Resistance by 140.", "icons/icon_shadow_resistance.gif", 5, 60, 15, new TalentEffect("resistance", "shadow", 20)));

	// Frost resistance talents
	this.talents_frost.Add(new Talent("Frost Resistance", "Increases Frost Resistance by 30.", "icons/icon_frost_resistance_grey.gif", 0, 20, 0, new TalentEffect("resistance", "frost", 0)));
	this.talents_frost.Add(new Talent("Frost Resistance", "Increases Frost Resistance by 30.", "icons/icon_frost_resistance.gif", 1, 20, 5, new TalentEffect("resistance", "frost", 30)));
	this.talents_frost.Add(new Talent("Frost Resistance", "Increases Frost Resistance by 60.", "icons/icon_frost_resistance.gif", 2, 30, 10, new TalentEffect("resistance", "frost", 30)));
	this.talents_frost.Add(new Talent("Frost Resistance", "Increases Frost Resistance by 90.", "icons/icon_frost_resistance.gif", 3, 40, 30, new TalentEffect("resistance", "frost", 30)));
	this.talents_frost.Add(new Talent("Frost Resistance", "Increases Frost Resistance by 120.", "icons/icon_frost_resistance.gif", 4, 50, 45, new TalentEffect("resistance", "frost", 30)));
	this.talents_frost.Add(new Talent("Frost Resistance", "Increases Frost Resistance by 140.", "icons/icon_frost_resistance.gif", 5, 60, 15, new TalentEffect("resistance", "frost", 20)));

	// Stamina talents
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 3.", "icons/icon_great_stamina_grey.gif", 0, 10, 0, new TalentEffect("stamina", "stamina", 0)));
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 3.", "icons/icon_great_stamina.gif", 1, 10, 5, new TalentEffect("stamina", "stamina", 3)));
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 5.", "icons/icon_great_stamina.gif", 2, 12, 5, new TalentEffect("stamina", "stamina", 2)));
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 7.", "icons/icon_great_stamina.gif", 3, 18, 5, new TalentEffect("stamina", "stamina", 2)));
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 10.", "icons/icon_great_stamina.gif", 4, 24, 10, new TalentEffect("stamina", "stamina", 3)));
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 13.", "icons/icon_great_stamina.gif", 5, 30, 25, new TalentEffect("stamina", "stamina", 3)));
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 17.", "icons/icon_great_stamina.gif", 6, 36, 25, new TalentEffect("stamina", "stamina", 4)));
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 21.", "icons/icon_great_stamina.gif", 7, 42, 25, new TalentEffect("stamina", "stamina", 4)));
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 26.", "icons/icon_great_stamina.gif", 8, 48, 25, new TalentEffect("stamina", "stamina", 5)));
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 32.", "icons/icon_great_stamina.gif", 9, 54, 25, new TalentEffect("stamina", "stamina", 6)));
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 40.", "icons/icon_great_stamina.gif", 10, 60, 35, new TalentEffect("stamina", "stamina", 8)));
	this.talents_stamina.Add(new Talent("Great Stamina", "Stamina increased by 64.", "icons/icon_great_stamina.gif", 11, 70, 30, new TalentEffect("stamina", "stamina", 8)));

	// Armor talents
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 50.", "icons/icon_natural_armor_grey.gif", 0, 10, 0, new TalentEffect("armor", "armor", 0)));
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 50.", "icons/icon_natural_armor.gif", 1, 10, 1, new TalentEffect("armor", "armor", 50)));
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 100.", "icons/icon_natural_armor.gif", 2, 12, 4, new TalentEffect("armor", "armor", 50)));
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 160.", "icons/icon_natural_armor.gif", 3, 18, 5, new TalentEffect("armor", "armor", 60)));
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 240.", "icons/icon_natural_armor.gif", 4, 24, 5, new TalentEffect("armor", "armor", 80)));
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 330.", "icons/icon_natural_armor.gif", 5, 30, 10, new TalentEffect("armor", "armor", 90)));
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 430.", "icons/icon_natural_armor.gif", 6, 36, 25, new TalentEffect("armor", "armor", 100)));
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 550.", "icons/icon_natural_armor.gif", 7, 42, 25, new TalentEffect("armor", "armor", 120)));
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 675.", "icons/icon_natural_armor.gif", 8, 48, 25, new TalentEffect("armor", "armor", 125)));
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 810.", "icons/icon_natural_armor.gif", 9, 54, 25, new TalentEffect("armor", "armor", 135)));
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 1000.", "icons/icon_natural_armor.gif", 10, 60, 25, new TalentEffect("armor", "armor", 190)));
	this.talents_armor.Add(new Talent("Natural Armor", "Armor increased by 1600.", "icons/icon_natural_armor.gif", 11, 70, 25, new TalentEffect("armor", "armor", 190)));

	// Claw talents
	this.talents_claw.Add(new Talent("Claw", "Claw the enemy, causing 4 to 6 damage.", "icons/icon_claw_grey.gif", 0, 1, 0, new TalentEffect("ability", "claw", 0), new TalentRestriction("included", new Array("bear", "vulture", "cat", "crab", "owl", "raptor", "scorpid", "warp stalker"))));
	this.talents_claw.Add(new Talent("Claw", "Claw the enemy, causing 4 to 6 damage.", "icons/icon_claw.gif", 1, 1, 1, new TalentEffect("ability", "claw", 50), new TalentRestriction("included", new Array("bear", "vulture", "cat", "crab", "owl", "raptor", "scorpid", "warp stalker"))));
	this.talents_claw.Add(new Talent("Claw", "Claw the enemy, causing 8 to 12 damage.", "icons/icon_claw.gif", 2, 8, 3, new TalentEffect("ability", "claw", 100), new TalentRestriction("included", new Array("bear", "vulture", "cat", "crab", "owl", "raptor", "scorpid", "warp stalker"))));
	this.talents_claw.Add(new Talent("Claw", "Claw the enemy, causing 12 to 16 damage.", "icons/icon_claw.gif", 3, 16, 3, new TalentEffect("ability", "claw", 160), new TalentRestriction("included", new Array("bear", "vulture", "cat", "crab", "owl", "raptor", "scorpid", "warp stalker"))));
	this.talents_claw.Add(new Talent("Claw", "Claw the enemy, causing 16 to 22 damage.", "icons/icon_claw.gif", 4, 24, 3, new TalentEffect("ability", "claw", 240), new TalentRestriction("included", new Array("bear", "vulture", "cat", "crab", "owl", "raptor", "scorpid", "warp stalker"))));
	this.talents_claw.Add(new Talent("Claw", "Claw the enemy, causing 21 to 29 damage.", "icons/icon_claw.gif", 5, 32, 3, new TalentEffect("ability", "claw", 330), new TalentRestriction("included", new Array("bear", "vulture", "cat", "crab", "owl", "raptor", "scorpid", "warp stalker"))));
	this.talents_claw.Add(new Talent("Claw", "Claw the enemy, causing 26 to 36 damage.", "icons/icon_claw.gif", 6, 40, 4, new TalentEffect("ability", "claw", 430), new TalentRestriction("included", new Array("bear", "vulture", "cat", "crab", "owl", "raptor", "scorpid", "warp stalker"))));
	this.talents_claw.Add(new Talent("Claw", "Claw the enemy, causing 35 to 49 damage.", "icons/icon_claw.gif", 7, 48, 4, new TalentEffect("ability", "claw", 430), new TalentRestriction("included", new Array("bear", "vulture", "cat", "crab", "owl", "raptor", "scorpid", "warp stalker"))));
	this.talents_claw.Add(new Talent("Claw", "Claw the enemy, causing 43 to 59 damage.", "icons/icon_claw.gif", 8, 56, 4, new TalentEffect("ability", "claw", 430), new TalentRestriction("included", new Array("bear", "vulture", "cat", "crab", "owl", "raptor", "scorpid", "warp stalker"))));
	this.talents_claw.Add(new Talent("Claw", "Claw the enemy, causing 54 to 76 damage.", "icons/icon_claw.gif", 9, 64, 4, new TalentEffect("ability", "claw", 430), new TalentRestriction("included", new Array("bear", "vulture", "cat", "crab", "owl", "raptor", "scorpid", "warp stalker"))));

	// Growl talents
	this.talents_growl.Add(new Talent("Growl", "Taunt the target, increasing the likelihood the creature will focus attacks on you.", "icons/icon_growl_grey.gif", 0, 1, 0, new TalentEffect("ability", "growl", 0)));
	this.talents_growl.Add(new Talent("Growl", "Taunt the target, increasing the likelihood the creature will focus attacks on you.", "icons/icon_growl.gif", 1, 1, 0, new TalentEffect("ability", "growl", 0)));
	this.talents_growl.Add(new Talent("Growl", "Taunt the target, increasing the likelihood the creature will focus attacks on you.", "icons/icon_growl.gif", 2, 10, 0, new TalentEffect("ability", "growl", 0)));
	this.talents_growl.Add(new Talent("Growl", "Taunt the target, increasing the likelihood the creature will focus attacks on you.", "icons/icon_growl.gif", 3, 20, 0, new TalentEffect("ability", "growl", 0)));
	this.talents_growl.Add(new Talent("Growl", "Taunt the target, increasing the likelihood the creature will focus attacks on you.", "icons/icon_growl.gif", 4, 30, 0, new TalentEffect("ability", "growl", 0)));
	this.talents_growl.Add(new Talent("Growl", "Taunt the target, increasing the likelihood the creature will focus attacks on you.", "icons/icon_growl.gif", 5, 40, 0, new TalentEffect("ability", "growl", 0)));
	this.talents_growl.Add(new Talent("Growl", "Taunt the target, increasing the likelihood the creature will focus attacks on you.", "icons/icon_growl.gif", 6, 50, 0, new TalentEffect("ability", "growl", 0)));
	this.talents_growl.Add(new Talent("Growl", "Taunt the target, increasing the likelihood the creature will focus attacks on you.", "icons/icon_growl.gif", 7, 60, 0, new TalentEffect("ability", "growl", 0)));
	this.talents_growl.Add(new Talent("Growl", "Taunt the target, increasing the likelihood the creature will focus attacks on you.", "icons/icon_growl.gif", 8, 70, 0, new TalentEffect("ability", "growl", 0)));

	// Bite talents
	this.talents_bite.Add(new Talent("Bite", "Bite the enemy, causing 7 to 9 damage.", "icons/icon_bite_grey.gif", 0, 1, 0, new TalentEffect("ability", "bite", 0), new TalentRestriction("excluded", new Array("crab", "scorpid", "owl", "sporebat"))));
	this.talents_bite.Add(new Talent("Bite", "Bite the enemy, causing 7 to 9 damage.", "icons/icon_bite.gif", 1, 1, 1, new TalentEffect("ability", "bite", 0), new TalentRestriction("excluded", new Array("crab", "scorpid", "owl", "sporebat"))));
	this.talents_bite.Add(new Talent("Bite", "Bite the enemy, causing 16 to 18 damage.", "icons/icon_bite.gif", 2, 8, 3, new TalentEffect("ability", "bite", 0), new TalentRestriction("excluded", new Array("crab", "scorpid", "owl", "sporebat"))));
	this.talents_bite.Add(new Talent("Bite", "Bite the enemy, causing 24 to 28 damage.", "icons/icon_bite.gif", 3, 16, 3, new TalentEffect("ability", "bite", 0), new TalentRestriction("excluded", new Array("crab", "scorpid", "owl", "sporebat"))));
	this.talents_bite.Add(new Talent("Bite", "Bite the enemy, causing 31 to 37 damage.", "icons/icon_bite.gif", 4, 24, 3, new TalentEffect("ability", "bite", 0), new TalentRestriction("excluded", new Array("crab", "scorpid", "owl", "sporebat"))));
	this.talents_bite.Add(new Talent("Bite", "Bite the enemy, causing 40 to 48 damage.", "icons/icon_bite.gif", 5, 32, 3, new TalentEffect("ability", "bite", 0), new TalentRestriction("excluded", new Array("crab", "scorpid", "owl", "sporebat"))));
	this.talents_bite.Add(new Talent("Bite", "Bite the enemy, causing 49 to 59 damage.", "icons/icon_bite.gif", 6, 40, 4, new TalentEffect("ability", "bite", 0), new TalentRestriction("excluded", new Array("crab", "scorpid", "owl", "sporebat"))));
	this.talents_bite.Add(new Talent("Bite", "Bite the enemy, causing 66 to 80 damage.", "icons/icon_bite.gif", 7, 48, 4, new TalentEffect("ability", "bite", 0), new TalentRestriction("excluded", new Array("crab", "scorpid", "owl", "sporebat"))));
	this.talents_bite.Add(new Talent("Bite", "Bite the enemy, causing 81 to 89 damage.", "icons/icon_bite.gif", 8, 56, 4, new TalentEffect("ability", "bite", 0), new TalentRestriction("excluded", new Array("crab", "scorpid", "owl", "sporebat"))));
	this.talents_bite.Add(new Talent("Bite", "Bite the enemy, causing 108 to 132 damage.", "icons/icon_bite.gif", 9, 64, 4, new TalentEffect("ability", "bite", 0), new TalentRestriction("excluded", new Array("crab", "scorpid", "owl", "sporebat"))));

	this.talents_dash.Add(new Talent("Dash", "Increases movement speed by 40% for 15 sec.", "icons/icon_dash_grey.gif", 0, 30, 0, new TalentEffect("speed", "dash", 0), new TalentRestriction("included", new Array("cat", "boar", "hyena", "raptor", "tallstrider", "wolf", "ravager"))));
	this.talents_dash.Add(new Talent("Dash", "Increases movement speed by 40% for 15 sec.", "icons/icon_dash.gif", 1, 30, 15, new TalentEffect("speed", "dash", 1.4), new TalentRestriction("included", new Array("cat", "boar", "hyena", "raptor", "tallstrider", "wolf", "ravager"))));
	this.talents_dash.Add(new Talent("Dash", "Increases movement speed by 60% for 15 sec.", "icons/icon_dash.gif", 2, 40, 5, new TalentEffect("speed", "dash", 1.6), new TalentRestriction("included", new Array("cat", "boar", "hyena", "raptor", "tallstrider", "wolf", "ravager"))));
	this.talents_dash.Add(new Talent("Dash", "Increases movement speed by 80% for 15 sec.", "icons/icon_dash.gif", 3, 50, 5, new TalentEffect("speed", "dash", 1.8), new TalentRestriction("included", new Array("cat", "boar", "hyena", "raptor", "tallstrider", "wolf", "ravager"))));

	this.talents_dive.Add(new Talent("Dive", "Increases movement speed by 40% for 15 sec.", "icons/icon_dive_grey.gif", 0, 30, 0, new TalentEffect("ability", "dive", 0), new TalentRestriction("included", new Array("owl", "wind serpent", "bat", "vulture", "dragonhawk", "nether ray"))));
	this.talents_dive.Add(new Talent("Dive", "Increases movement speed by 40% for 15 sec.", "icons/icon_dive.gif", 1, 30, 15, new TalentEffect("ability", "dive", 0), new TalentRestriction("included", new Array("owl", "wind serpent", "bat", "vulture", "dragonhawk", "nether ray"))));
	this.talents_dive.Add(new Talent("Dive", "Increases movement speed by 60% for 15 sec.", "icons/icon_dive.gif", 2, 40, 10, new TalentEffect("ability", "dive", 0), new TalentRestriction("included", new Array("owl", "wind serpent", "bat", "vulture", "dragonhawk", "nether ray"))));
	this.talents_dive.Add(new Talent("Dive", "Increases movement speed by 80% for 15 sec.", "icons/icon_dive.gif", 3, 50, 5, new TalentEffect("ability", "dive", 0), new TalentRestriction("included", new Array("owl", "wind serpent", "bat", "vulture", "dragonhawk", "nether ray"))));

	this.talents_cower.Add(new Talent("Cower", "Cower, causing no damage but lowering your threat, making the enemy less likely to attack you.", "icons/icon_cower_grey.gif", 0, 5, 0, new TalentEffect("ability", "cower", 0)));
	this.talents_cower.Add(new Talent("Cower", "Cower, causing no damage but lowering your threat, making the enemy less likely to attack you.", "icons/icon_cower.gif", 1, 5, 8, new TalentEffect("ability", "cower", 0)));
	this.talents_cower.Add(new Talent("Cower", "Cower, causing no damage but lowering your threat, making the enemy less likely to attack you.", "icons/icon_cower.gif", 2, 15, 2, new TalentEffect("ability", "cower", 0)));
	this.talents_cower.Add(new Talent("Cower", "Cower, causing no damage but lowering your threat, making the enemy less likely to attack you.", "icons/icon_cower.gif", 3, 25, 2, new TalentEffect("ability", "cower", 0)));
	this.talents_cower.Add(new Talent("Cower", "Cower, causing no damage but lowering your threat, making the enemy less likely to attack you.", "icons/icon_cower.gif", 4, 35, 2, new TalentEffect("ability", "cower", 0)));
	this.talents_cower.Add(new Talent("Cower", "Cower, causing no damage but lowering your threat, making the enemy less likely to attack you.", "icons/icon_cower.gif", 5, 45, 2, new TalentEffect("ability", "cower", 0)));
	this.talents_cower.Add(new Talent("Cower", "Cower, causing no damage but lowering your threat, making the enemy less likely to attack you.", "icons/icon_cower.gif", 6, 55, 2, new TalentEffect("ability", "cower", 0)));
	this.talents_cower.Add(new Talent("Cower", "Cower, causing no damage but lowering your threat, making the enemy less likely to attack you.", "icons/icon_cower.gif", 7, 65, 3, new TalentEffect("ability", "cower", 0)));

	// Racial talents
	this.talents_shell_shield.Add(new Talent("Shell Shield", "Reduces all damage your pet takes by 50%, but increases the time between your pet's attacks by 43%. Lasts 12 sec.", "icons/icon_shell_shield_grey.gif", 0, 20, 0, new TalentEffect("ability", "shield", 0), new TalentRestriction("included", new Array("turtle"))));
	this.talents_shell_shield.Add(new Talent("Shell Shield", "Reduces all damage your pet takes by 50%, but increases the time between your pet's attacks by 43%. Lasts 12 sec.", "icons/icon_shell_shield.gif", 1, 20, 15, new TalentEffect("ability", "shield", 0), new TalentRestriction("included", new Array("turtle"))));

	this.talents_thunderstomp.Add(new Talent("Thunderstomp", "Shakes the ground with thundering force, doing 67 to 77 Nature damage to all enemies within 8 yards. This ability causes a moderate amount of additional threat.", "icons/icon_thunderstomp_grey.gif", 0, 30, 0, new TalentEffect("ability", "thunderstomp", 0), new TalentRestriction("included", new Array("gorilla"))));
	this.talents_thunderstomp.Add(new Talent("Thunderstomp", "Shakes the ground with thundering force, doing 67 to 77 Nature damage to all enemies within 8 yards. This ability causes a moderate amount of additional threat.", "icons/icon_thunderstomp.gif", 1, 30, 15, new TalentEffect("ability", "thunderstomp", 0), new TalentRestriction("included", new Array("gorilla"))));
	this.talents_thunderstomp.Add(new Talent("Thunderstomp", "Shakes the ground with thundering force, doing 87 to 99 Nature damage to all enemies within 8 yards. This ability causes a moderate amount of additional threat.", "icons/icon_thunderstomp.gif", 2, 40, 5, new TalentEffect("ability", "thunderstomp", 0), new TalentRestriction("included", new Array("gorilla"))));
	this.talents_thunderstomp.Add(new Talent("Thunderstomp", "Shakes the ground with thundering force, doing 115 to 133 Nature damage to all enemies within 8 yards. This ability causes a moderate amount of additional threat.", "icons/icon_thunderstomp.gif", 3, 50, 5, new TalentEffect("ability", "thunderstomp", 0), new TalentRestriction("included", new Array("gorilla"))));

	this.talents_poison_spit.Add(new Talent("Poison Spit", "Spits poison at an enemy, dealing 25 Nature damage over 8 sec.", "icons/icon_poison_spit_grey.gif", 0, 15, 0, new TalentEffect("ability", "damage", 0), new TalentRestriction("included", new Array("serpent"))));
	this.talents_poison_spit.Add(new Talent("Poison Spit", "Spits poison at an enemy, dealing 25 Nature damage over 8 sec.", "icons/icon_poison_spit.gif", 1, 15, 5, new TalentEffect("ability", "damage", 0), new TalentRestriction("included", new Array("serpent"))));
	this.talents_poison_spit.Add(new Talent("Poison Spit", "Spits poison at an enemy, dealing 90 Nature damage over 8 sec.", "icons/icon_poison_spit.gif", 2, 45, 15, new TalentEffect("ability", "damage", 0), new TalentRestriction("included", new Array("serpent"))));
	this.talents_poison_spit.Add(new Talent("Poison Spit", "Spits poison at an enemy, dealing 120 Nature damage over 8 sec.", "icons/icon_poison_spit.gif", 3, 60, 5, new TalentEffect("ability", "damage", 0), new TalentRestriction("included", new Array("serpent"))));

	this.talents_prowl.Add(new Talent("Prowl", "Puts your pet in stealth mode, but slows its movement to 50% of normal. The first attack from stealth receives a 20% bonus to damage. Lasts until cancelled.", "icons/icon_prowl_grey.gif", 0, 30, 0, new TalentEffect("ability", "stealth", 0), new TalentRestriction("included", new Array("cat"))));
	this.talents_prowl.Add(new Talent("Prowl", "Puts your pet in stealth mode, but slows its movement to 50% of normal. The first attack from stealth receives a 20% bonus to damage. Lasts until cancelled.", "icons/icon_prowl.gif", 1, 30, 15, new TalentEffect("ability", "stealth", 0), new TalentRestriction("included", new Array("cat"))));
	this.talents_prowl.Add(new Talent("Prowl", "Puts your pet in stealth mode, but slows its movement to 45% of normal. The first attack from stealth receives a 35% bonus to damage. Lasts until cancelled.", "icons/icon_prowl.gif", 2, 40, 5, new TalentEffect("ability", "stealth", 0), new TalentRestriction("included", new Array("cat"))));
	this.talents_prowl.Add(new Talent("Prowl", "Puts your pet in stealth mode, but slows its movement to 40% of normal. The first attack from stealth receives a 50% bonus to damage. Lasts until cancelled.", "icons/icon_prowl.gif", 3, 50, 5, new TalentEffect("ability", "stealth", 0), new TalentRestriction("included", new Array("cat"))));

	this.talents_charge.Add(new Talent("Charge", "Charges an enemy, immobilizes it for 1 sec, and adds 50 melee attack power to the boar's next attack.", "icons/icon_charge_grey.gif", 0, 1, 0, new TalentEffect("ability", "charge", 0), new TalentRestriction("included", new Array("boar"))));
	this.talents_charge.Add(new Talent("Charge", "Charges an enemy, immobilizes it for 1 sec, and adds 50 melee attack power to the boar's next attack.", "icons/icon_charge.gif", 1, 1, 5, new TalentEffect("ability", "charge", 0), new TalentRestriction("included", new Array("boar"))));
	this.talents_charge.Add(new Talent("Charge", "Charges an enemy, immobilizes it for 1 sec, and adds 100 melee attack power to the boar's next attack.", "icons/icon_charge.gif", 2, 12, 5, new TalentEffect("ability", "charge", 0), new TalentRestriction("included", new Array("boar"))));
	this.talents_charge.Add(new Talent("Charge", "Charges an enemy, immobilizes it for 1 sec, and adds 180 melee attack power to the boar's next attack.", "icons/icon_charge.gif", 3, 24, 5, new TalentEffect("ability", "charge", 0), new TalentRestriction("included", new Array("boar"))));
	this.talents_charge.Add(new Talent("Charge", "Charges an enemy, immobilizes it for 1 sec, and adds 250 melee attack power to the boar's next attack.", "icons/icon_charge.gif", 4, 36, 5, new TalentEffect("ability", "charge", 0), new TalentRestriction("included", new Array("boar"))));
	this.talents_charge.Add(new Talent("Charge", "Charges an enemy, immobilizes it for 1 sec, and adds 390 melee attack power to the boar's next attack.", "icons/icon_charge.gif", 5, 48, 5, new TalentEffect("ability", "charge", 0), new TalentRestriction("included", new Array("boar"))));
	this.talents_charge.Add(new Talent("Charge", "Charges an enemy, immobilizes it for 1 sec, and adds 550 melee attack power to the boar's next attack.", "icons/icon_charge.gif", 6, 60, 4, new TalentEffect("ability", "charge", 0), new TalentRestriction("included", new Array("boar"))));

	this.talents_furious_howl.Add(new Talent("Furious Howl", "Party members within 15 yards receive an extra 9 to 11 damage to their next Physical attack.  Lasts 10 sec.", "icons/icon_furious_howl_grey.gif", 0, 10, 0, new TalentEffect("ability", "howl", 0), new TalentRestriction("included", new Array("wolf"))));
	this.talents_furious_howl.Add(new Talent("Furious Howl", "Party members within 15 yards receive an extra 9 to 11 damage to their next Physical attack.  Lasts 10 sec.", "icons/icon_furious_howl.gif", 1, 10, 10, new TalentEffect("ability", "howl", 0), new TalentRestriction("included", new Array("wolf"))));
	this.talents_furious_howl.Add(new Talent("Furious Howl", "Party members within 15 yards receive an extra 18 to 22 damage to their next Physical attack.  Lasts 10 sec.", "icons/icon_furious_howl.gif", 2, 24, 5, new TalentEffect("ability", "howl", 0), new TalentRestriction("included", new Array("wolf"))));
	this.talents_furious_howl.Add(new Talent("Furious Howl", "Party members within 15 yards receive an extra 28 to 34 damage to their next Physical attack.  Lasts 10 sec.", "icons/icon_furious_howl.gif", 3, 40, 5, new TalentEffect("ability", "howl", 0), new TalentRestriction("included", new Array("wolf"))));
	this.talents_furious_howl.Add(new Talent("Furious Howl", "Party members within 15 yards receive an extra 45 to 57 damage to their next Physical attack.  Lasts 10 sec.", "icons/icon_furious_howl.gif", 4, 56, 5, new TalentEffect("ability", "howl", 0), new TalentRestriction("included", new Array("wolf"))));

	this.talents_lightning_breath.Add(new Talent("Lightning Breath", "Breathes lightning, instantly dealing 11 to 13 Nature damage to a single target.", "icons/icon_lightning_breath_grey.gif", 0, 1, 0, new TalentEffect("ability", "lightning", 0), new TalentRestriction("included", new Array("wind serpent"))));
	this.talents_lightning_breath.Add(new Talent("Lightning Breath", "Breathes lightning, instantly dealing 11 to 13 Nature damage to a single target.", "icons/icon_lightning_breath.gif", 1, 1, 1, new TalentEffect("ability", "lightning", 0), new TalentRestriction("included", new Array("wind serpent"))));
	this.talents_lightning_breath.Add(new Talent("Lightning Breath", "Breathes lightning, instantly dealing 21 to 23 Nature damage to a single target.", "icons/icon_lightning_breath.gif", 2, 12, 4, new TalentEffect("ability", "lightning", 0), new TalentRestriction("included", new Array("wind serpent"))));
	this.talents_lightning_breath.Add(new Talent("Lightning Breath", "Breathes lightning, instantly dealing 36 to 40 Nature damage to a single target.", "icons/icon_lightning_breath.gif", 3, 24, 5, new TalentEffect("ability", "lightning", 0), new TalentRestriction("included", new Array("wind serpent"))));
	this.talents_lightning_breath.Add(new Talent("Lightning Breath", "Breathes lightning, instantly dealing 51 to 59 Nature damage to a single target.", "icons/icon_lightning_breath.gif", 4, 36, 5, new TalentEffect("ability", "lightning", 0), new TalentRestriction("included", new Array("wind serpent"))));
	this.talents_lightning_breath.Add(new Talent("Lightning Breath", "Breathes lightning, instantly dealing 78 to 90 Nature damage to a single target.", "icons/icon_lightning_breath.gif", 5, 48, 5, new TalentEffect("ability", "lightning", 0), new TalentRestriction("included", new Array("wind serpent"))));
	this.talents_lightning_breath.Add(new Talent("Lightning Breath", "Breathes lightning, instantly dealing 99 to 113 Nature damage to a single target.", "icons/icon_lightning_breath.gif", 6, 60, 5, new TalentEffect("ability", "lightning", 0), new TalentRestriction("included", new Array("wind serpent"))));

	this.talents_scorpid_poison.Add(new Talent("Scorpid Poison", "Inflicts 10 Nature damage over 10 sec. Effect can stack up to 5 times on a single target.", "icons/icon_scorpid_poison_grey.gif", 0, 8, 0, new TalentEffect("ability", "scorpid", 0), new TalentRestriction("included", new Array("scorpid"))));
	this.talents_scorpid_poison.Add(new Talent("Scorpid Poison", "Inflicts 10 Nature damage over 10 sec. Effect can stack up to 5 times on a single target.", "icons/icon_scorpid_poison.gif", 1, 8, 10, new TalentEffect("ability", "scorpid", 0), new TalentRestriction("included", new Array("scorpid"))));
	this.talents_scorpid_poison.Add(new Talent("Scorpid Poison", "Inflicts 15 Nature damage over 10 sec. Effect can stack up to 5 times on a single target.", "icons/icon_scorpid_poison.gif", 2, 24, 5, new TalentEffect("ability", "scorpid", 0), new TalentRestriction("included", new Array("scorpid"))));
	this.talents_scorpid_poison.Add(new Talent("Scorpid Poison", "Inflicts 30 Nature damage over 10 sec. Effect can stack up to 5 times on a single target.", "icons/icon_scorpid_poison.gif", 3, 40, 5, new TalentEffect("ability", "scorpid", 0), new TalentRestriction("included", new Array("scorpid"))));
	this.talents_scorpid_poison.Add(new Talent("Scorpid Poison", "Inflicts 40 Nature damage over 10 sec. Effect can stack up to 5 times on a single target.", "icons/icon_scorpid_poison.gif", 4, 56, 5, new TalentEffect("ability", "scorpid", 0), new TalentRestriction("included", new Array("scorpid"))));
	this.talents_scorpid_poison.Add(new Talent("Scorpid Poison", "Inflicts 44 Nature damage over 8 sec. Effect can stack up to 5 times on a single target.", "icons/icon_scorpid_poison.gif", 5, 64, 4, new TalentEffect("ability", "scorpid", 0), new TalentRestriction("included", new Array("scorpid"))));

	this.talents_screech.Add(new Talent("Screech", "Blasts a single enemy for 7 to 9 damage and lowers the attack power of all enemies in melee range by 25.  Effect lasts 4 sec.", "icons/icon_screech_grey.gif", 0, 8, 0, new TalentEffect("ability", "screech", 0), new TalentRestriction("included", new Array("bat", "vulture", "owl"))));
	this.talents_screech.Add(new Talent("Screech", "Blasts a single enemy for 7 to 9 damage and lowers the attack power of all enemies in melee range by 25.  Effect lasts 4 sec.", "icons/icon_screech.gif", 1, 8, 10, new TalentEffect("ability", "screech", 0), new TalentRestriction("included", new Array("bat", "vulture", "owl"))));
	this.talents_screech.Add(new Talent("Screech", "Blasts a single enemy for 12 to 16 damage and lowers the attack power of all enemies in melee range by 50.  Effect lasts 4 sec.", "icons/icon_screech.gif", 2, 24, 5, new TalentEffect("ability", "screech", 0), new TalentRestriction("included", new Array("bat", "vulture", "owl"))));
	this.talents_screech.Add(new Talent("Screech", "Blasts a single enemy for 19 to 25 damage and lowers the attack power of all enemies in melee range by 75.  Effect lasts 4 sec.", "icons/icon_screech.gif", 3, 40, 5, new TalentEffect("ability", "screech", 0), new TalentRestriction("included", new Array("bat", "vulture", "owl"))));
	this.talents_screech.Add(new Talent("Screech", "Blasts a single enemy for 26 to 46 damage and lowers the attack power of all enemies in melee range by 100.  Effect lasts 4 sec.", "icons/icon_screech.gif", 4, 56, 5, new TalentEffect("ability", "screech", 0), new TalentRestriction("included", new Array("bat", "vulture", "owl"))));
	this.talents_screech.Add(new Talent("Screech", "Blasts a single enemy for 33 to 61 damage and lowers the attack power of all enemies in melee range by 210.  Effect lasts 4 sec.", "icons/icon_screech.gif", 5, 64, 4, new TalentEffect("ability", "screech", 0), new TalentRestriction("included", new Array("bat", "vulture", "owl"))));

	this.talents_fire_breath.Add(new Talent("Fire Breath", "Targets in a cone in front of the caster take 6 Fire damage over 2 sec.", "icons/icon_fire_breath_grey.gif", 0, 1, 0, new TalentEffect("ability", "fire_breath", 0), new TalentRestriction("included", new Array("dragonhawk"))));
	this.talents_fire_breath.Add(new Talent("Fire Breath", "Targets in a cone in front of the caster take 6 Fire damage over 2 sec.", "icons/icon_fire_breath.gif", 1, 1, 5, new TalentEffect("ability", "fire_breath", 0), new TalentRestriction("included", new Array("dragonhawk"))));
	this.talents_fire_breath.Add(new Talent("Fire Breath", "Targets in a cone in front of the caster take 111 Fire damage over 2 sec.", "icons/icon_fire_breath.gif", 2, 60, 20, new TalentEffect("ability", "fire_breath", 0), new TalentRestriction("included", new Array("dragonhawk"))));

	this.talents_warp.Add(new Talent("Warp", "Teleports to an enemy up to 30 yards away and gives the pet a 50% chance to avoid the next melee attack. Lasts 4 sec.", "icons/icon_warp_grey.gif", 0, 1, 0, new TalentEffect("ability", "warp", 0), new TalentRestriction("included", new Array("warp stalker"))));
	this.talents_warp.Add(new Talent("Warp", "Teleports to an enemy up to 30 yards away and gives the pet a 50% chance to avoid the next melee attack. Lasts 4 sec.", "icons/icon_warp.gif", 1, 60, 1, new TalentEffect("ability", "warp", 0), new TalentRestriction("included", new Array("warp stalker"))));

	this.talents_gore.Add(new Talent("Gore", "Gores the enemy, causing 3 to 5 damage.  This attack has a 50% chance to inflict double damage.", "icons/icon_gore_grey.gif", 0, 1, 0, new TalentEffect("ability", "gore", 0), new TalentRestriction("included", new Array("ravager", "boar"))));
	this.talents_gore.Add(new Talent("Gore", "Gores the enemy, causing 3 to 5 damage.  This attack has a 50% chance to inflict double damage.", "icons/icon_gore.gif", 1, 1, 1, new TalentEffect("ability", "gore", 0), new TalentRestriction("included", new Array("ravager", "boar"))));
	this.talents_gore.Add(new Talent("Gore", "Gores the enemy, causing 6 to 10 damage.  This attack has a 50% chance to inflict double damage.", "icons/icon_gore.gif", 2, 8, 3, new TalentEffect("ability", "gore", 0), new TalentRestriction("included", new Array("ravager", "boar"))));
	this.talents_gore.Add(new Talent("Gore", "Gores the enemy, causing 9 to 13 damage.  This attack has a 50% chance to inflict double damage.", "icons/icon_gore.gif", 3, 16, 3, new TalentEffect("ability", "gore", 0), new TalentRestriction("included", new Array("ravager", "boar"))));
	this.talents_gore.Add(new Talent("Gore", "Gores the enemy, causing 12 to 18 damage.  This attack has a 50% chance to inflict double damage.", "icons/icon_gore.gif", 4, 24, 3, new TalentEffect("ability", "gore", 0), new TalentRestriction("included", new Array("ravager", "boar"))));
	this.talents_gore.Add(new Talent("Gore", "Gores the enemy, causing 15 to 23 damage.  This attack has a 50% chance to inflict double damage.", "icons/icon_gore.gif", 5, 32, 3, new TalentEffect("ability", "gore", 0), new TalentRestriction("included", new Array("ravager", "boar"))));
	this.talents_gore.Add(new Talent("Gore", "Gores the enemy, causing 18 to 30 damage.  This attack has a 50% chance to inflict double damage.", "icons/icon_gore.gif", 6, 40, 4, new TalentEffect("ability", "gore", 0), new TalentRestriction("included", new Array("ravager", "boar"))));
	this.talents_gore.Add(new Talent("Gore", "Gores the enemy, causing 24 to 40 damage.  This attack has a 50% chance to inflict double damage.", "icons/icon_gore.gif", 7, 48, 4, new TalentEffect("ability", "gore", 0), new TalentRestriction("included", new Array("ravager", "boar"))));
	this.talents_gore.Add(new Talent("Gore", "Gores the enemy, causing 30 to 48 damage.  This attack has a 50% chance to inflict double damage.", "icons/icon_gore.gif", 8, 56, 4, new TalentEffect("ability", "gore", 0), new TalentRestriction("included", new Array("ravager", "boar"))));
	this.talents_gore.Add(new Talent("Gore", "Gores the enemy, causing 37 to 61 damage.  This attack has a 50% chance to inflict double damage.", "icons/icon_gore.gif", 9, 63, 4, new TalentEffect("ability", "gore", 0), new TalentRestriction("included", new Array("ravager", "boar"))));

	this.talents_avoidance.Add(new Talent("Avoidance", "Reduces the damage your pet takes from area of effect attacks by an additional 25%.", "icons/icon_avoidance_grey.gif", 0, 30, 0, new TalentEffect("ability", "avoidance", 0)));
	this.talents_avoidance.Add(new Talent("Avoidance", "Reduces the damage your pet takes from area of effect attacks by an additional 25%.", "icons/icon_avoidance.gif", 1, 30, 15, new TalentEffect("ability", "avoidance", 0)));
	this.talents_avoidance.Add(new Talent("Avoidance", "Reduces the damage your pet takes from area of effect attacks by an additional 50%.", "icons/icon_avoidance.gif", 2, 60, 10, new TalentEffect("ability", "avoidance", 0)));

	this.talents_cobra_reflexes.Add(new Talent("Cobra Reflexes", "Attack speed increased by 30%, but damage done is reduced.", "icons/icon_cobra_reflexes_grey.gif", 0, 30, 0, new TalentEffect("ability", "cobra reflexes", 0)));
	this.talents_cobra_reflexes.Add(new Talent("Cobra Reflexes", "Attack speed increased by 30%, but damage done is reduced.", "icons/icon_cobra_reflexes.gif", 1, 30, 15, new TalentEffect("ability", "cobra reflexes", 0)));
};


Application.prototype.BuildTalentButtons = function()
{
	this.talent_buttons = new List();

	var element = document.getElementById("application");
	element.innerHTML = "";

	var talent_build = this.pet.talent_build;

	// Build pet frame.
	talent_build.BuildPetFrame(element);

	// Build talents frame.
	var talents_group1_frame = document.createElement('div');
	var talents_group2_frame = document.createElement('div');
	var talents_group3_frame = document.createElement('div');
	var talents_group4_frame = document.createElement('div');
	var talents_group5_frame = document.createElement('div');
	var talents_group6_frame = document.createElement('div');

	talents_group1_frame.className = 'TalentsGroup1Frame';
	talents_group2_frame.className = 'TalentsGroup2Frame';
	talents_group3_frame.className = 'TalentsGroup3Frame';
	talents_group4_frame.className = 'TalentsGroup4Frame';
	talents_group5_frame.className = 'TalentsGroup5Frame';
	talents_group6_frame.className = 'TalentsGroup6Frame';

	var talents_frame = document.createElement('div');
	talents_frame.className = 'TalentsFrame';
	talents_frame.appendChild(talents_group1_frame);
	talents_frame.appendChild(talents_group2_frame);
	talents_frame.appendChild(talents_group3_frame);
	talents_frame.appendChild(talents_group4_frame);
	talents_frame.appendChild(talents_group5_frame);
	talents_frame.appendChild(talents_group6_frame);
	element.appendChild(talents_frame);

	var button_stamina = new TalentButton("stamina", this.talents_stamina);
	button_stamina.Attach(talent_build);
	button_stamina.Build(talents_group1_frame, 15);
	button_stamina.Render();
	this.talent_buttons.Add(button_stamina);

	var button_armor = new TalentButton("armor", this.talents_armor);
	button_armor.Attach(talent_build);
	button_armor.Build(talents_group1_frame, 14);
	button_armor.Render();
	this.talent_buttons.Add(button_armor);

	var button_avoidance = new TalentButton("avoidance", this.talents_avoidance);
	button_avoidance.Attach(talent_build);
	button_avoidance.Build(talents_group1_frame, 13);
	button_avoidance.Render();
	this.talent_buttons.Add(button_avoidance);

	var button_cobra_reflexes = new TalentButton("cobra reflexes", this.talents_cobra_reflexes);
	button_cobra_reflexes.Attach(talent_build);
	button_cobra_reflexes.Build(talents_group1_frame, 12);
	button_cobra_reflexes.Render();
	this.talent_buttons.Add(button_cobra_reflexes);

	var button_arcane = new TalentButton("arcane_resistance", this.talents_arcane);
	button_arcane.Attach(talent_build);
	button_arcane.Build(talents_group2_frame, 15);
	button_arcane.Render();
	this.talent_buttons.Add(button_arcane);

	var button_fire = new TalentButton("fire_resistance", this.talents_fire);
	button_fire.Attach(talent_build);
	button_fire.Build(talents_group2_frame, 14);
	button_fire.Render();
	this.talent_buttons.Add(button_fire);

	var button_nature = new TalentButton("nature_resistance", this.talents_nature);
	button_nature.Attach(talent_build);
	button_nature.Build(talents_group2_frame, 13);
	button_nature.Render();
	this.talent_buttons.Add(button_nature);

	var button_frost = new TalentButton("frost_resistance", this.talents_frost);
	button_frost.Attach(talent_build);
	button_frost.Build(talents_group2_frame, 12);
	button_frost.Render();
	this.talent_buttons.Add(button_frost);

	var button_shadow = new TalentButton("shadow_resistance", this.talents_shadow);
	button_shadow.Attach(talent_build);
	button_shadow.Build(talents_group2_frame, 11);
	button_shadow.Render();
	this.talent_buttons.Add(button_shadow);
	
	var button_claw = new TalentButton("claw", this.talents_claw);
	button_claw.Attach(talent_build);
	button_claw.Build(talents_group3_frame, 15);
	button_claw.Render();
	this.talent_buttons.Add(button_claw);

	var button_growl = new TalentButton("growl", this.talents_growl);
	button_growl.Attach(talent_build);
	button_growl.Build(talents_group3_frame, 14);
	button_growl.Render();
	this.talent_buttons.Add(button_growl);

	var button_bite = new TalentButton("bite", this.talents_bite);
	button_bite.Attach(talent_build);
	button_bite.Build(talents_group3_frame, 13);
	button_bite.Render();
	this.talent_buttons.Add(button_bite);

	var button_dash = new TalentButton("dash", this.talents_dash);
	button_dash.Attach(talent_build);
	button_dash.Build(talents_group3_frame, 12);
	button_dash.Render();
	this.talent_buttons.Add(button_dash);

	var button_cower = new TalentButton("cower", this.talents_cower);
	button_cower.Attach(talent_build);
	button_cower.Build(talents_group3_frame, 11);
	button_cower.Render();
	this.talent_buttons.Add(button_cower);

	var button_shell_shield = new TalentButton("shell_shield", this.talents_shell_shield);
	button_shell_shield.Attach(talent_build);
	button_shell_shield.Build(talents_group4_frame, 15);
	button_shell_shield.Render();
	this.talent_buttons.Add(button_shell_shield);

	var button_thunderstomp = new TalentButton("thunderstomp", this.talents_thunderstomp);
	button_thunderstomp.Attach(talent_build);
	button_thunderstomp.Build(talents_group4_frame, 14);
	button_thunderstomp.Render();
	this.talent_buttons.Add(button_thunderstomp);
	
	var button_poison_spit = new TalentButton("poison_spit", this.talents_poison_spit);
	button_poison_spit.Attach(talent_build);
	button_poison_spit.Build(talents_group4_frame, 13);
	button_poison_spit.Render();
	this.talent_buttons.Add(button_poison_spit);

	var button_prowl = new TalentButton("prowl", this.talents_prowl);
	button_prowl.Attach(talent_build);
	button_prowl.Build(talents_group4_frame, 12);
	button_prowl.Render();
	this.talent_buttons.Add(button_prowl);
	
	var button_charge = new TalentButton("charge", this.talents_charge);
	button_charge.Attach(talent_build);
	button_charge.Build(talents_group4_frame, 11);
	button_charge.Render();
	this.talent_buttons.Add(button_charge);
	
	var button_dive = new TalentButton("dive", this.talents_dive);
	button_dive.Attach(talent_build);
	button_dive.Build(talents_group5_frame, 15);
	button_dive.Render();
	this.talent_buttons.Add(button_dive);

	var button_furious_howl = new TalentButton("furious_howl", this.talents_furious_howl);
	button_furious_howl.Attach(talent_build);
	button_furious_howl.Build(talents_group5_frame, 14);
	button_furious_howl.Render();
	this.talent_buttons.Add(button_furious_howl);

	var button_lightning_breath = new TalentButton("lightning_breath", this.talents_lightning_breath);
	button_lightning_breath.Attach(talent_build);
	button_lightning_breath.Build(talents_group5_frame, 13);
	button_lightning_breath.Render();
	this.talent_buttons.Add(button_lightning_breath);

	var button_scorpid_poison = new TalentButton("scorpid_poison", this.talents_scorpid_poison);
	button_scorpid_poison.Attach(talent_build);
	button_scorpid_poison.Build(talents_group5_frame, 12);
	button_scorpid_poison.Render();
	this.talent_buttons.Add(button_scorpid_poison);

	var button_screech = new TalentButton("screech", this.talents_screech);
	button_screech.Attach(talent_build);
	button_screech.Build(talents_group5_frame, 11);
	button_screech.Render();
	this.talent_buttons.Add(button_screech);
	
	var button_fire_breath = new TalentButton("fire_breath", this.talents_fire_breath);
	button_fire_breath.Attach(talent_build);
	button_fire_breath.Build(talents_group6_frame, 15);
	button_fire_breath.Render();
	this.talent_buttons.Add(button_fire_breath);

	var button_warp = new TalentButton("warp", this.talents_warp);
	button_warp.Attach(talent_build);
	button_warp.Build(talents_group6_frame, 14);
	button_warp.Render();
	this.talent_buttons.Add(button_warp);

	var button_gore = new TalentButton("gore", this.talents_gore);
	button_gore.Attach(talent_build);
	button_gore.Build(talents_group6_frame, 13);
	button_gore.Render();
	this.talent_buttons.Add(button_gore);

	talent_build.BuildTrainingPointsFrame(element);
	talent_build.Render();
};

Application.prototype.SelectPet = function(pet_type)
{
	// Create a new pet from the selected pet type.
	this.pet = new Pet(pet_type, "Fido", this.pet.level);
	
	this.BuildTalentButtons();
};

Application.prototype.Reset = function(level)
{
	// Create a new pet from the selected pet type.
	this.pet = new Pet(this.pet.type, "Fido", level);

	this.BuildTalentButtons();
};


////////////////////////////////////////////////////////////////// Execution //

var application = Application.GetInstance();
application.Run();

