Skip to content

Instantly share code, notes, and snippets.

@nijikokun
Last active June 2, 2016 20:22
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nijikokun/5035617 to your computer and use it in GitHub Desktop.
Save nijikokun/5035617 to your computer and use it in GitHub Desktop.
A small, basic, generic game framework / game with no potential being made for fun using weird javascript techniques. Also, I made my own commenting style based on KSS.

GOD.js

Game oriented development framework.

Usage

var entity = god.entity({
  name: "Nijikokun"
}).implement("health").implement("movement");

console.log("before", entity.position);
entity.move("north");
console.log("after", entity.position);

Supports

  • Component based Add-ons allow you to easily create any type of entity you need by simply implementing features such as health, abilities, statistics in an easy and quick way.
  • Entity-centric design By thinking everything in the game is an entity no longer do you need to create multiple classes with inheritance only entity types
  • Quick implementation and iteration

Ending word

This is all bullshit (mostly just to explain it really, and it's all legitimate information), but you can make stuff with it, I'm developing my own pokemon clone with it.

// god.js
//
// Game Oriented Development Framework for Javascript
//
// Everything is component based.
// Everything is essentially an entity.
// Nothing matters. Make what you want. Share with the world, enjoy life.
//
// Copyright Nijiko Yonskai 2013
// Version 2.0
(function (exports) {
var god = exports.god = { utils: {}, math: {}, store: localStorage };
god.math.square = function (x) {
return x * x;
};
god.math.cube = function (x) {
return x * god.math.square(x);
};
god.math.withinRange = function (value, min, max) {
return (value >= min && value <= max);
};
god.math.randomBetween = function (min, max, flt) {
var result = Math.exp(Math.random() * Math.log(max - min)) + min;
return flt ? result : Math.round(result);
};
// No Operation Function
god.utils.noop = function () {};
// String mutable method for capitalization
//
// * str {String} Value to be capitalized
god.utils.capitalize = function (str) {
return str.charAt(0).toUpperCase() + str.slice(1);
};
// Lowercase a given string, object values, or array strings
//
// * o {Object} Value(s) to be lowercased
god.utils.lowercase = function (o, i) {
if (typeof o === 'string') {
return o.toLowerCase();
} else if (Object.prototype.toString.call(o) === '[object Array]') {
for(i = 0; i < o.length; i++)
if (typeof o[i] === 'string')
o[i] = o[i].toLowerCase();
} else if (typeof o === 'object') {
for(i in o)
if (o.hasOwnProperty(i) && typeof o[i] === 'string')
o[i] = o[i].toLowerCase();
}
return o;
};
// Probably a better way of doing this, don't give a fuck, YOLO
//
// * options {Object}
// * options.on {Object} Object to have method injected on and returned
// - options.type {String|Array} Method prefix, determines whether we uppercase `name` argument
// * options.name {String} Object variable to be manipulated or referenced to
// - options.callable {Function} Callable function to be used instead of a generated one
// - options.min {Boolean} Should we expect a minimum cap for argument on setter
// - options.max {Boolean} Should we expect a maximum for argument on setter
// - options.acronym {Boolean} Should we create getter,setters for acronyms
god.utils.createTypeMethod = function (options, uname) {
function create(opts, uname) {
capitalizedName = god.utils.capitalize(opts.name);
opts.on[
(opts.type ? opts.type + capitalizedName : opts.name)
] = (opts.type && opts.type === 'set') ? function (a) {
if (opts.min && opts.on['min' + capitalizedName] && a < opts.on['min' + capitalizedName]) a = opts.on['min' + capitalizedName];
if (opts.max && opts.on['max' + capitalizedName] && a > opts.on['max' + capitalizedName]) a = opts.on['max' + capitalizedName];
return (opts.on[opts.name] = a) ? opts.on : false;
} : (typeof opts.callable === 'function') ? opts.callable : function () { return opts.on[opts.name]; };
return o.on;
}
capitalizedName = god.utils.capitalize(options.name);
if (options.min) options.on = god.utils.createTypeMethod({ name: 'Min' + capitalizedName, type: ['get', 'set'], on: options.on });
if (options.max) options.on = god.utils.createTypeMethod({ name: 'Max' + capitalizedName, type: ['get', 'set'], on: options.on });
if (options.acronym) options.on = god.utils.createTypeMethod({ name: capitalizedName + 'Acronym', type: ['get', 'set'], on: options.on });
if (options.type && Object.prototype.toString.call(options.type)) {
for(var i = 0; i < options.type.length; i++) options.on = create({
name: options.name, type: options.type[i], callable: options.callable || undefined, on: options.on
});
return options.on;
}
return create(options);
};
// Creates a thin wrapper around the HTML5 LocalStorage API
// for ease of access and control, as well as additional
// functionality for fast prototyping and coding.
//
// - settings {Object}
//
// Return: {Object} Gives quick methods to accessing localStorage API
god.storage = function (settings) {
var expires;
if (!settings) settings = {};
if (settings.expires === 'session') god.store = sessionStorage;
if (typeof god.store == 'undefined') return false;
if ("expires" in settings && typeof settings.expires == 'number' && settings.expires > 0)
expires = (+new Date()) + settings.expires;
return {
// Save data to local storage
set: function (key, data) {
var value = { "god:store" : data };
if (expires) value["god:expires"] = expires;
god.store.setItem(key, JSON.stringify(value));
return this;
},
// Given a string will return single store
// Given an array it will return multiple stored information
get: function (keys) {
var data, value, now = (+new Date()), $self = this, i, exists = false;
// Private Data Check function to prevent re-typing this twice.
function check (data) {
if (data === null) return null;
if ("god:store" in data)
if ("god:expires" in data && now >= data["god:expires"])
$self.remove(keys);
else return value["god:store"];
return null;
}
try {
if (Object.prototype.toString.call(keys) === '[object Array]') {
data = {};
for (i = 0; i < keys.length; i++) {
value = JSON.parse(god.store.getItem(keys[i]));
if (value !== null) {
if (!exists) exists = true;
data[keys[i]] = check(value);
}
}
data = (exists) ? data : null;
} else {
value = JSON.parse(god.store.getItem(keys));
data = check(value);
}
} catch (error) { console.log(error.message); }
return data;
},
// Imports an object filled with key-store values hassle-free
"import": function (data) {
var key;
for (key in data)
if (data.hasOwnProperty(key))
this.set(key, data[key]);
return this;
},
// Given a string it will remove a single key-store
// Given an array it will remove multiple key-stores
"remove": function (keys) {
if (Object.prototype.toString.call(keys) === '[object Array]') for(var i = 0; i < keys.length; i++) god.store.removeItem(keys[i]);
else god.store.removeItem(keys);
return this;
},
// Empty the current store completely, wipes all data.
empty: function () {
god.store.clear();
return this;
}
};
};
// Event System in a single function aside from removal
//
// - topic {String} Event topic
// - arg {Object} Function to subscribe to a topic, object to publish to subscribers
god.event = function(topic, arg) {
if (typeof arg === 'function') {
if (!god.event.topics[topic]) god.event.topics[topic] = [];
var token = (++uuid).toString();
god.event.topics[topic].push({
token: token,
func: func
});
return token;
}
if (!god.event.topics[topic])
return false;
setTimeout(function() {
var subscribers = god.event.topics[topic], len = subscribers ? subscribers.length : 0;
while (len--) subscribers[len].func(topic, arg);
}, 0);
return true;
};
god.event.topics = {};
god.event.uuid = -1;
god.event.remove = function(token) {
for (var m in god.event.topics)
if (god.event.topics.indexOf(m))
for (var i = 0, j = god.event.topics[m].length; i < j; i++)
if (god.event.topics[m][i].token === token && god.event.topics[m].splice(i, 1))
return token;
return false;
};
// Entity Class
//
// - Options {Object} Each item in this will be iterated upon set on the object and made into getter setters.
god.entity = function (options) {
var $this = {
_type: 'entity'
};
// Handle options as a name only, otherwise, just make it an empty object
if (!options || typeof options !== "object")
options = (typeof options === "string") ? { name: options } : {};
// Default Options for entities
options.name = options.name || '???';
// Handle getter setters like this
for (var i in options)
if (options.hasOwnProperty(i))
$this[i] = options[i],
$this = god.utils.createTypeMethod({ on: $this, type: ['get', 'set'], name: i });
// Implements add-on functionality into current entity
//
// * name {String} Add-on name
// - options {Object} Add-on specific information
//
// Version 0.1
$this.implement = function (name, options) {
return god.entity.addons.use(name, options, $this);
};
return $this;
};
// {Object} Entity Add-on Container Object
god.entity.addons = {};
// Add-on Implementation Sugar for generic checks DRY.
//
// * name {String} Add-on object key value
// * options {Object} Add-on specific information
// * $this {Object} Entity Reference
god.entity.addons.use = function (name, options, $this) {
if (!$this || !$this._type || $this._type !== 'entity') throw { message: "Invalid Object, not of Entity type.", name: "InvalidEntity", reference: $this };
if (!name || !god.entity.addons[name]) throw { messsage: "Addon you are trying to implement does not exist!", name: "InvalidAddon", reference: name };
return god.entity.addons[name].call("_private", options || {}, $this);
};
// Add-on creation method for generic checks, DRY.
//
// * name {String} Add-on identification name
// - check {String} Add-on reference on entity to check for prior implementation.
// - callback {Function} Add-on callable method upon implementation, utilizing `this` as reference (**can also be `check` argument if no check is required.**)
god.entity.addons.add = function (name, check, callback) {
god.entity.addons[name] = function (options, $this) {
if (this.toString() !== "_private") throw { message: "You cannot call this method directly.", name: "InvalidInvocation" };
return (check && typeof check === 'string' && $this[check]) ? $this : (typeof check === 'function' ? check : callback).call($this, options);
};
};
// Sugar method with additional features built in for entity statistics
god.entity.addons.addStat = function (name, defaults, additions) {
return god.entity.addons.add(name, name, function (options) {
var $this = this, i;
$this[name] = function (value, current) {
if (value) {
if ($this[name].min && value < $this[name].min) value = $this[name].min;
if ($this[name].max && value > $this[name].max) value = $this[name].max;
$this[name][ current ? 'current' : 'temp' ] = parseFloat(value);
return $this;
}
return $this[name][ current ? 'current' : 'temp' ];
};
this[name].base = parseFloat(options.base || options.max || defaults.base || defaults.max || 100);
this[name].min = parseFloat(options.min || defaults.min || 0);
this[name].max = parseFloat(options.max || defaults.max || 0);
this[name].acronym = parseFloat(options.acronym || defaults.acronym || name);
this[name].current = this[name].base;
this[name].temp = this[name].base;
this[name].reset = function () { $this[name].current = $this[name].temp; return $this; };
for (i in options)
if (options.hasOwnProperty(i) && (i !== 'min' || i !== 'max' || i !== 'base' || i != 'acronym'))
this[name][i] = options[i];
if (additions)
for (i in additions)
if (additions.hasOwnProperty(i))
this[i] = additions[i];
return this;
});
};
god.entity.addons.addStat('health', { min: 0, max: 100, acronym: 'hp' }, {
isDead: function () {
return this.health <= this.minHealth;
}
});
god.entity.addons.addStat('mana', { min: 0, max: 100, acronym: 'mp' });
god.entity.addons.addStat('defense', { min: 0, max: 255, acronym: 'def' });
god.entity.addons.addStat('attack', { min: 0, max: 255, acronym: 'atk' });
god.entity.addons.addStat('speed', { min: 0, max: 255, acronym: 'spd' });
god.entity.addons.add('movement', 'position', function (options) {
this.position = options.base || [0, 0];
this.movementSpeed = 1;
this.move = function (dir) {
switch (dir.toUpperCase()) {
case "U": case "UP": case "N": case "NORTH": this.position[0] += 1 * this.movementSpeed; break;
case "D": case "DOWN": case "S": case "SOUTH": this.position[0] -= 1 * this.movementSpeed; break;
case "L": case "LEFT": case "W": case "WEST": this.position[1] -= 1 * this.movementSpeed; break;
case "R": case "RIGHT": case "E": case "EAST": this.position[1] += 1 * this.movementSpeed; break;
}
god.event('onMove', { dir: dir, target: this });
return this;
};
return this;
});
// {Object} Abilities Key-store
god.abilities = {};
// Fetch or create abilities on `god.abilities` key-store
//
// * name {String} Ability name
// - options {Object} Ability options for creation and storage
god.ability = function (name, options) {
if (typeof options === 'object') {
options = god.utils.lowercase(options);
if (!options.callback) throw { message: "Missing options / callback", name: "InvalidOptions", reference: options };
else if (!options.type) throw { message: "Missing type reference", name: "InvalidType", reference: options };
else if (!options.use) throw { message: "Missing use option, need stat to draw from", name: "MissingUseType", reference: options };
var $this = {
tiers: {
base: {
name: name,
cost: options.cost || 0,
type: options.type,
stat: options.use,
callback: options.callback,
conditions: options.conditions || god.utils.noop
}
}
};
$this.base = function () {
return $this.tiers.base;
};
$this.tier = function (name, options) {
if (name === 'base') throw { message: "Private tier cannot be fetched or overriden.", name: "PrivateTier", reference: name };
if (!name) throw { message: "Invalid tier name given.", name: "InvalidAbilityTierName", reference: name };
if (!options) return $this.tiers[name];
else if (!options.callback) throw { message: "Missing options / callback", name: "InvalidOptions", reference: options };
else if (!options.type) throw { message: "Missing type reference", name: "InvalidType", reference: options };
else if (!options.use) throw { message: "Missing use option, need stat to draw from", name: "MissingUseType", reference: options };
var $self = {
name: name,
cost: options.cost || 0,
type: options.type,
stat: options.use,
callback: options.callback,
conditions: options.conditions || god.utils.noop
};
$this.tiers[name] = $self;
return $this;
};
if (options.tiers) for (var i in options.tiers)
if (typeof i === 'string' && i !== 'base') $this = $this.tier(i, options.tiers[i]);
god.abilities[name] = $this;
return $this;
}
return god.abilities[name];
};
god.entity.addons.add('ability', function (options) {
options = god.utils.lowercase(options);
if (!options.name) throw { message: "Missing ability options.", name: "InvalidOptions", reference: options };
if (this.abilities && this.abilities[options.name] && !options.tier) return this;
var ability = god.ability(options.name);
if (!ability) throw { message: "Missing ability", name: "MissingAbility", reference: options.name };
if (!this[ability.stat] || typeof this[ability.stat] !== 'function') throw { message: "Missing stat add-on", name: "MissingAddon", reference: ability.stat };
if (ability.conditions.call(this) === false) throw { message: "Entity and ability are incompatible", name: "IncompatibleAbility", reference: [ ability, this ] };
if (!this.abilities) {
this.abilities = {};
this.useAbility = function (name, options) {
if (this.abilities.length < 1) return { error: "NO_ABILITIES" };
options = options || {};
$ability = this.abilities[name];
if (!$ability) return { error: "MISSING_ABILITY" };
if (options.tier) if (!$ability.tier[options.tier]) return { error: "MISSING_TIER" }; else $ability = $ability[options.tier];
if ($ability.cost > this[$ability.stat]()) return { error: "INSUFFICIENT_" + $ability.stat.toUpperCase() };
else this[$ability.stat](this[$ability.stat]() - $ability.cost, true);
return $ability.callback.apply(this, [ options.target ]) || this;
};
}
if (options.tier && this.abilities[options.name]) {
var tier = ability.tier(options.tier);
if (!tier.error) this.abilities[options.name][options.tier] = tier;
return (tier.error) ? tier.error : this;
}
this.abilities[options.name] = ability.base();
return this;
});
god.entity.addons.add('inventory', 'inventory', function (options) {
this.inventory = Object.prototype.toString.call(options.starting) === '[object Array]' ? options.starting : [];
this.inventory.use = function (item, target) {
var i = 0; for (;i < this.inventory.length; i++)
if (this.inventory[i].name === item.toLowerCase())
if (this.inventory[i].use.call(this, target) === true)
if (this.inventory[i].count === 1) this.inventory.splice(i, 1);
else this.inventory[i].count--;
return false;
};
this.inventory.has = function (item) {
var i = 0; for (;i < this.inventory.length; i++)
if (this.inventory[i].name === item.toLowerCase()) return i;
return false;
};
this.inventory.count = function (item) {
if (!item) return this.inventory.length;
var i = 0, count = 0; for (;i < this.inventory.length; i++)
if (this.inventory[i].name === item.toLowerCase()) return this.inventory[i].count;
return false;
};
this.inventory.add = function (item, amount) {
if (!item) return this;
var i = 0, count = 0; for (;i < this.inventory.length; i++)
if (this.inventory[i].name === item.toLowerCase()) this.inventory[i].count += amount || 1;
return this;
};
this.inventory.remove = function (item, amount) {
if (!item) return this;
var i = 0, count = 0; for (;i < this.inventory.length; i++) {
if (this.inventory[i].name === item.toLowerCase()) {
if (amount) {
if (this.inventory[i].count <= amount) this.inventory.splice(i, 1);
else this.inventory[i].count -= amount;
} else this.inventory.splice(i, 1);
}
}
return this;
};
return god.utils.createTypeMethod({
on: this, type: ['get', 'set'], name: 'inventory'
});
});
god.entity.addons.add('item', 'inventory', function (options) {
if (this.inventory.has(options.name)) return this.inventory.add(item, options.amount);
var $item = {
name: options.name.toLowerCase() || 'item' + this.inventory.length+1,
realName: options.name,
cost: options.cost || 0,
count: options.amount || 1,
use: options.callback || god.utils.noop
};
this.inventory.push($item);
return this;
});
})(typeof window === 'undefined' ? module.exports : window);
// requires god.js
var pokemon = {
stages: {
increase: { 0: 1, 1: 1.5, 2: 2.0, 3: 2.5, 4: 3.0, 5: 3.5, 6: 0.4 },
decrease: { 0: 1, 1: 2/3, 2: 1/2, 3: 2/5, 4: 1/3, 5: 2/7, 6: 1/4 }
},
types: {
normal: { ghost: 0, rock: .5 },
fighting: { normal: 2, flying: .5, poison: .5, rock: 2, bug: .5, ghost: 0, psychic: .5, ice: 2 },
flying: { fighting: 2, rock: .5, bug: 2, grass: 2, electric: .5 },
poison: { poison: .5, ground: .5, rock: .5, bug: 2, ghost: .5, grass: 2 },
ground: { flying: 0, poison: 2, rock: 2, bug: .5, fire: 2, grass: .5, electric: 2 }
rock: { fighting: .5, flying: 2, ground: .5, bug: 2, fire: 2, ice: 2 },
bug: { fight: .5, flying: .5, poison: 2, ghost: .5, fire: .5, grass: 2, psychic: 2 },
ghost: { normal: 0, ghost: 2, psychic: 0 },
fire: { rock: .5, bug: 2, fire: .5, water: .5, grass: 2, ice: 2, dragon .5 },
water: { ground: 2, rock: 2, fire: 2, water: .5, grass: .5, dragon: .5 },
grass: { flying: .5, poison: .5, ground: 2, rock: 2, bug: .5, fire: .5, water: 2, grass: .5, dragon: .5 },
electric: { flying: 2, ground: 0, water: 2, grass: .5, electric: .5, dragon: .5 },
psychic: { fight: 2, poison: 2, psychic: .5 },
ice: { flying: 2, ground: 2, water: .5, grass: 2, ice: .5, dragon: 2 },
dragon: { dragon: 2 }
},
effects: {
poison: function (target) {
if (!target.status.poison) target.status.add('poison', { amount: 1 });
else if (this.lastAttack === target.status.poison.amount += 1;
target.health(target.health() - (target.health()*(target.status.poison.amount/16));
return true;
},
burn: function (target) {
if (!target.status.burn) target.status.add('burn'), target.attack(target.attack()/2));
return true;
},
sleep: function (target) {
if (!target.status.sleep) target.status.add('sleep', { turns: god.math.randomBetween(1, 7) }); else target.status.sleep.turns -= 1;
if (target.status.sleep.turns <= 0) target.status.remove('sleep');
return (target.status.sleep);
}
}
abilities: {
"absorb": { "type": "", "category": "", "cost": 20, "power": 20, "accuracy": 100, "description": "Leeches 50% damage.", "effect": 0, "callable": function (target) {} },
"acid": { "type": "", "category": "", "cost": 30, "power": 40, "accuracy": 100, "description": "10% chance to lower Def 1 stage.", "effect": 0, "callable": function (target) {} },
"acid armor": { "type": "", "category": "", "cost": 40, "power": 0, "accuracy": 0, "description": "Boosts Def 2 stages.", "effect": 0, "callable": function (target) {} },
"agility": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 0, "description": "Boosts Spe 2 stages.", "effect": 0, "callable": function (target) {} },
"amnesia": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 0, "description": "Boosts Spc 2 stages.", "effect": 0, "callable": function (target) {} },
"aurora beam": { "type": "", "category": "", "cost": 20, "power": 65, "accuracy": 100, "description": "10% chance to lower Atk 1 stage.", "effect": 0, "callable": function (target) {} },
"barrage": { "type": "", "category": "", "cost": 20, "power": 15, "accuracy": 85, "description": "Hits 2-5 times in one turn.", "effect": 0, "callable": function (target) {} },
"barrier": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 0, "description": "Boosts Def 2 stages.", "effect": 0, "callable": function (target) {} },
"bide": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 0, "description": "Charges for 2-3 turns; returns double the damage received in those turns.", "effect": 0, "callable": function (target) {} },
"bind": { "type": "", "category": "", "cost": 20, "power": 15, "accuracy": 75, "description": "Prevents the opponent from attacking for 2-5 turns.", "effect": 0, "callable": function (target) {} },
"bite": { "type": "", "category": "", "cost": 25, "power": 60, "accuracy": 100, "description": "10% chance to flinch.", "effect": 0, "callable": function (target) {} },
"blizzard": { "type": "", "category": "", "cost": 5, "power": 120, "accuracy": 90, "description": "10% chance to freeze.", "effect": 0, "callable": function (target) {} },
"body slam": { "type": "", "category": "", "cost": 15, "power": 85, "accuracy": 100, "description": "30% chance to paralyze.", "effect": 0, "callable": function (target) {} },
"bone club": { "type": "", "category": "", "cost": 20, "power": 65, "accuracy": 85, "description": "10% chance to flinch.", "effect": 0, "callable": function (target) {} },
"bonemerang": { "type": "", "category": "", "cost": 10, "power": 50, "accuracy": 90, "description": "Hits twice in 1 turn.", "effect": 0, "callable": function (target) {} },
"bubble": { "type": "", "category": "", "cost": 30, "power": 20, "accuracy": 100, "description": "10% chance to lower Spe 1 stage.", "effect": 0, "callable": function (target) {} },
"bubblebeam": { "type": "", "category": "", "cost": 20, "power": 65, "accuracy": 100, "description": "10% chance to lower Spe 1 stage.", "effect": 0, "callable": function (target) {} },
"clamp": { "type": "", "category": "", "cost": 10, "power": 35, "accuracy": 75, "description": "Prevents the opponent from attacking for 2-5 turns.", "effect": 0, "callable": function (target) {} },
"comet punch": { "type": "", "category": "", "cost": 15, "power": 18, "accuracy": 85, "description": "Hits 2-5 times in one turn.", "effect": 0, "callable": function (target) {} },
"confuse ray": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 100, "description": "Confuses the target.", "effect": 0, "callable": function (target) {} },
"confusion": { "type": "", "category": "", "cost": 25, "power": 50, "accuracy": 100, "description": "10% chance to confuse.", "effect": 0, "callable": function (target) {} },
"constrict": { "type": "", "category": "", "cost": 35, "power": 10, "accuracy": 100, "description": "10% chance to lower Spe 1 stage.", "effect": 0, "callable": function (target) {} },
"conversion": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 0, "description": "Changes user into opponent's type.", "effect": 0, "callable": function (target) {} },
"counter": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 100, "description": "If hit by a Normal- or Fighting-type attack, returns double the damage.", "effect": 0, "callable": function (target) {} },
"crabhammer": { "type": "", "category": "", "cost": 10, "power": 90, "accuracy": 85, "description": "High critical hit rate.", "effect": 0, "callable": function (target) {} },
"cut": { "type": "", "category": "", "cost": 30, "power": 50, "accuracy": 95, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"defense curl": { "type": "", "category": "", "cost": 40, "power": 0, "accuracy": 0, "description": "Boosts Def 1 stage.", "effect": 0, "callable": function (target) {} },
"dig": { "type": "", "category": "", "cost": 10, "power": 100, "accuracy": 100, "description": "User is made invulnerable for one turn, then hits the next turn.", "effect": 0, "callable": function (target) {} },
"disable": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 55, "description": "Randomly disables an opponent's move for 0-6 turns.", "effect": 0, "callable": function (target) {} },
"dizzy punch": { "type": "", "category": "", "cost": 10, "power": 70, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"double kick": { "type": "", "category": "", "cost": 30, "power": 30, "accuracy": 100, "description": "Hits twice in 1 turn.", "effect": 0, "callable": function (target) {} },
"double team": { "type": "", "category": "", "cost": 15, "power": 0, "accuracy": 0, "description": "Boosts evasion 1 stage.", "effect": 0, "callable": function (target) {} },
"double-edge": { "type": "", "category": "", "cost": 15, "power": 100, "accuracy": 100, "description": "Has 1/4 recoil.", "effect": 0, "callable": function (target) {} },
"doubleslap": { "type": "", "category": "", "cost": 10, "power": 15, "accuracy": 85, "description": "Hits 2-5 times in 1 turn.", "effect": 0, "callable": function (target) {} },
"dragon rage": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 100, "description": "Does 40 damage.", "effect": 0, "callable": function (target) {} },
"dream eater": { "type": "", "category": "", "cost": 15, "power": 100, "accuracy": 100, "description": "Leeches 50% damage. Only works on a sleeping Pokémon.", "effect": 0, "callable": function (target) {} },
"drill peck": { "type": "", "category": "", "cost": 20, "power": 80, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"earthquake": { "type": "", "category": "", "cost": 10, "power": 100, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"egg bomb": { "type": "", "category": "", "cost": 10, "power": 100, "accuracy": 75, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"ember": { "type": "", "category": "", "cost": 25, "power": 40, "accuracy": 100, "description": "10% chance to burn.", "effect": 0, "callable": function (target) {} },
"explosion": { "type": "", "category": "", "cost": 5, "power": 170, "accuracy": 100, "description": "Faints the user.", "effect": 0, "callable": function (target) {} },
"fire blast": { "type": "", "category": "", "cost": 5, "power": 120, "accuracy": 85, "description": "30% chance to burn.", "effect": 0, "callable": function (target) {} },
"fire punch": { "type": "", "category": "", "cost": 15, "power": 75, "accuracy": 100, "description": "10% chance to burn.", "effect": 0, "callable": function (target) {} },
"fire spin": { "type": "", "category": "", "cost": 15, "power": 15, "accuracy": 70, "description": "Prevents the opponent from attacking for 2-5 turns.", "effect": 0, "callable": function (target) {} },
"fissure": { "type": "", "category": "", "cost": 5, "power": 0, "accuracy": 30, "description": "Will OHKO the target.", "effect": 0, "callable": function (target) {} },
"flamethrower": { "type": "", "category": "", "cost": 15, "power": 95, "accuracy": 100, "description": "10% chance to burn.", "effect": 0, "callable": function (target) {} },
"flash": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 70, "description": "Lowers foe's accuracy 1 stage.", "effect": 0, "callable": function (target) {} },
"fly": { "type": "", "category": "", "cost": 15, "power": 70, "accuracy": 95, "description": "User is made invulnerable for one turn, then hits the next turn.", "effect": 0, "callable": function (target) {} },
"focus energy": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 0, "description": "Reduces user's critical hit rate.", "effect": 0, "callable": function (target) {} },
"fury attack": { "type": "", "category": "", "cost": 20, "power": 15, "accuracy": 85, "description": "Hits 2-5 times in one turn.", "effect": 0, "callable": function (target) {} },
"fury swipes": { "type": "", "category": "", "cost": 15, "power": 18, "accuracy": 80, "description": "Hits 2-5 times in one turn.", "effect": 0, "callable": function (target) {} },
"glare": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 75, "description": "Paralyzes the target.", "effect": 0, "callable": function (target) {} },
"growl": { "type": "", "category": "", "cost": 40, "power": 0, "accuracy": 100, "description": "Lowers foe's Atk 1 stage.", "effect": 0, "callable": function (target) {} },
"growth": { "type": "", "category": "", "cost": 40, "power": 0, "accuracy": 0, "description": "Boosts Spc 1 stage.", "effect": 0, "callable": function (target) {} },
"guillotine": { "type": "", "category": "", "cost": 5, "power": 0, "accuracy": 30, "description": "Will OHKO the target.", "effect": 0, "callable": function (target) {} },
"gust": { "type": "", "category": "", "cost": 35, "power": 40, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"harden": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 0, "description": "Boosts Def 1 stage.", "effect": 0, "callable": function (target) {} },
"haze": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 0, "description": "Eliminates all stat changes.", "effect": 0, "callable": function (target) {} },
"headbutt": { "type": "", "category": "", "cost": 15, "power": 70, "accuracy": 100, "description": "30% chance to flinch.", "effect": 0, "callable": function (target) {} },
"hi jump kick": { "type": "", "category": "", "cost": 20, "power": 85, "accuracy": 90, "description": "If it misses, user loses 1 HP.", "effect": 0, "callable": function (target) {} },
"horn attack": { "type": "", "category": "", "cost": 25, "power": 65, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"horn drill": { "type": "", "category": "", "cost": 5, "power": 0, "accuracy": 30, "description": "Will OHKO the target.", "effect": 0, "callable": function (target) {} },
"hydro pump": { "type": "", "category": "", "cost": 5, "power": 120, "accuracy": 80, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"hyper beam": { "type": "", "category": "", "cost": 5, "power": 150, "accuracy": 90, "description": "User cannot move next turn, unless opponent was KOed.", "effect": 0, "callable": function (target) {} },
"hyper fang": { "type": "", "category": "", "cost": 15, "power": 80, "accuracy": 90, "description": "10% chance to flinch.", "effect": 0, "callable": function (target) {} },
"hypnosis": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 60, "description": "Puts the foe to sleep.", "effect": 0, "callable": function (target) {} },
"ice beam": { "type": "", "category": "", "cost": 10, "power": 95, "accuracy": 100, "description": "10% chance to freeze.", "effect": 0, "callable": function (target) {} },
"ice punch": { "type": "", "category": "", "cost": 15, "power": 75, "accuracy": 100, "description": "10% chance to freeze.", "effect": 0, "callable": function (target) {} },
"jump kick": { "type": "", "category": "", "cost": 25, "power": 70, "accuracy": 95, "description": "If it misses, user loses 1 HP.", "effect": 0, "callable": function (target) {} },
"karate chop": { "type": "", "category": "", "cost": 25, "power": 50, "accuracy": 100, "description": "High critical hit rate.", "effect": 0, "callable": function (target) {} },
"kinesis": { "type": "", "category": "", "cost": 15, "power": 0, "accuracy": 80, "description": "Lowers foe's accuracy 1 stage.", "effect": 0, "callable": function (target) {} },
"leech life": { "type": "", "category": "", "cost": 15, "power": 20, "accuracy": 100, "description": "Leeches 50% damage.", "effect": 0, "callable": function (target) {} },
"leech seed": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 90, "description": "Leeches 1/16 of the target's HP each turn.", "effect": 0, "callable": function (target) {} },
"leer": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 100, "description": "Lowers foe's Def 1 stage.", "effect": 0, "callable": function (target) {} },
"lick": { "type": "", "category": "", "cost": 30, "power": 20, "accuracy": 100, "description": "30% chance to paralyze.", "effect": 0, "callable": function (target) {} },
"light screen": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 0, "description": "Lowers Spc damage done to user.", "effect": 0, "callable": function (target) {} },
"lovely kiss": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 75, "description": "Puts the foe to sleep.", "effect": 0, "callable": function (target) {} },
"low kick": { "type": "", "category": "", "cost": 20, "power": 50, "accuracy": 90, "description": "30% chance to flinch foe.", "effect": 0, "callable": function (target) {} },
"meditate": { "type": "", "category": "", "cost": 40, "power": 0, "accuracy": 0, "description": "Boosts Atk 1 stage.", "effect": 0, "callable": function (target) {} },
"mega drain": { "type": "", "category": "", "cost": 10, "power": 40, "accuracy": 100, "description": "Leeches 50% damage.", "effect": 0, "callable": function (target) {} },
"mega kick": { "type": "", "category": "", "cost": 5, "power": 120, "accuracy": 75, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"mega punch": { "type": "", "category": "", "cost": 20, "power": 80, "accuracy": 85, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"metronome": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 0, "description": "Picks a random move.", "effect": 0, "callable": function (target) {} },
"mimic": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 0, "description": "Copies a random move the foe knows.", "effect": 0, "callable": function (target) {} },
"minimize": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 0, "description": "Boosts evasion 1 stage.", "effect": 0, "callable": function (target) {} },
"mirror move": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 0, "description": "Use the attack that your opponent just used.", "effect": 0, "callable": function (target) {} },
"mist": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 0, "description": "Prevents moves that lower stats from working for 5 turns.", "effect": 0, "callable": function (target) {} },
"night shade": { "type": "", "category": "", "cost": 15, "power": 0, "accuracy": 100, "description": "Does damage equal to the user's level.", "effect": 0, "callable": function (target) {} },
"pay day": { "type": "", "category": "", "cost": 20, "power": 40, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"peck": { "type": "", "category": "", "cost": 35, "power": 35, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"petal dance": { "type": "", "category": "", "cost": 20, "power": 70, "accuracy": 100, "description": "Repeats for 2-3 turns. Confuses the user at the end.", "effect": 0, "callable": function (target) {} },
"pin missile": { "type": "", "category": "", "cost": 20, "power": 14, "accuracy": 85, "description": "Hits 2-5 times in one turn.", "effect": 0, "callable": function (target) {} },
"poison gas": { "type": "", "category": "", "cost": 40, "power": 0, "accuracy": 55, "description": "Poisons the foe.", "effect": 0, "callable": function (target) {} },
"poison sting": { "type": "", "category": "", "cost": 35, "power": 15, "accuracy": 100, "description": "20% chance to poison.", "effect": 0, "callable": function (target) {} },
"poisonpowder": { "type": "", "category": "", "cost": 35, "power": 0, "accuracy": 75, "description": "Poisons the foe.", "effect": 0, "callable": function (target) {} },
"pound": { "type": "", "category": "", "cost": 35, "power": 40, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"psybeam": { "type": "", "category": "", "cost": 20, "power": 65, "accuracy": 100, "description": "10% chance to confuse.", "effect": 0, "callable": function (target) {} },
"psychic": { "type": "", "category": "", "cost": 10, "power": 90, "accuracy": 100, "description": "30% chance to lower Spc 1 stage.", "effect": 0, "callable": function (target) {} },
"psywave": { "type": "", "category": "", "cost": 15, "power": 0, "accuracy": 80, "description": "Damage is .5x to 1.5x the user's level.", "effect": 0, "callable": function (target) {} },
"quick attack": { "type": "", "category": "", "cost": 30, "power": 40, "accuracy": 100, "description": "The user always attacks first.", "effect": 0, "callable": function (target) {} },
"rage": { "type": "", "category": "", "cost": 20, "power": 20, "accuracy": 100, "description": "Boosts Atk 1 stage if hit, but can only use Rage after that.", "effect": 0, "callable": function (target) {} },
"razor leaf": { "type": "", "category": "", "cost": 25, "power": 55, "accuracy": 95, "description": "High critical hit rate.", "effect": 0, "callable": function (target) {} },
"razor wind": { "type": "", "category": "", "cost": 10, "power": 80, "accuracy": 75, "description": "Charges up the first turn; attacks on the second turn.", "effect": 0, "callable": function (target) {} },
"recover": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 0, "description": "Heals 50% max HP.", "effect": 0, "callable": function (target) {} },
"reflect": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 0, "description": "Lowers physical damage done to user.", "effect": 0, "callable": function (target) {} },
"rest": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 0, "description": "The user goes to sleep for two turns and restores all HP.", "effect": 0, "callable": function (target) {} },
"roar": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 100, "description": "Has no effect.", "effect": 0, "callable": function (target) {} },
"rock slide": { "type": "", "category": "", "cost": 10, "power": 75, "accuracy": 90, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"rock throw": { "type": "", "category": "", "cost": 15, "power": 50, "accuracy": 90, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"rolling kick": { "type": "", "category": "", "cost": 15, "power": 60, "accuracy": 85, "description": "30% chance to flinch.", "effect": 0, "callable": function (target) {} },
"sand-attack": { "type": "", "category": "", "cost": 15, "power": 0, "accuracy": 100, "description": "Lowers foe's accuracy 1 stage.", "effect": 0, "callable": function (target) {} },
"scratch": { "type": "", "category": "", "cost": 35, "power": 40, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"screech": { "type": "", "category": "", "cost": 40, "power": 0, "accuracy": 85, "description": "Lowers foe's Def 2 stages.", "effect": 0, "callable": function (target) {} },
"seismic toss": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 100, "description": "Does damage equal to the user's level.", "effect": 0, "callable": function (target) {} },
"selfdestruct": { "type": "", "category": "", "cost": 5, "power": 130, "accuracy": 100, "description": "Faints the user.", "effect": 0, "callable": function (target) {} },
"sharpen": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 0, "description": "Boosts Atk 1 stage.", "effect": 0, "callable": function (target) {} },
"sing": { "type": "", "category": "", "cost": 15, "power": 0, "accuracy": 55, "description": "Puts the target to sleep.", "effect": 0, "callable": function (target) {} },
"skull bash": { "type": "", "category": "", "cost": 15, "power": 100, "accuracy": 100, "description": "Charges up turn one; attacks turn two.", "effect": 0, "callable": function (target) {} },
"sky attack": { "type": "", "category": "", "cost": 5, "power": 140, "accuracy": 90, "description": "Hits the turn after being used.", "effect": 0, "callable": function (target) {} },
"slam": { "type": "", "category": "", "cost": 20, "power": 80, "accuracy": 75, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"slash": { "type": "", "category": "", "cost": 20, "power": 70, "accuracy": 100, "description": "High critical hit rate.", "effect": 0, "callable": function (target) {} },
"sleep powder": { "type": "", "category": "", "cost": 15, "power": 0, "accuracy": 75, "description": "Puts the target to sleep.", "effect": 0, "callable": function (target) {} },
"sludge": { "type": "", "category": "", "cost": 20, "power": 65, "accuracy": 100, "description": "29.7% chance to poison.", "effect": 0, "callable": function (target) {} },
"smog": { "type": "", "category": "", "cost": 20, "power": 20, "accuracy": 70, "description": "39.8% chance to poison.", "effect": 0, "callable": function (target) {} },
"smokescreen": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 100, "description": "Lowers foe's accuracy 1 stage.", "effect": 0, "callable": function (target) {} },
"softboiled": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 0, "description": "Heals 50% max HP.", "effect": 0, "callable": function (target) {} },
"solarbeam": { "type": "", "category": "", "cost": 10, "power": 120, "accuracy": 100, "description": "Charges up turn 1; attacks on turn 2.", "effect": 0, "callable": function (target) {} },
"sonicboom": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 90, "description": "Does 20 damage.", "effect": 0, "callable": function (target) {} },
"spike cannon": { "type": "", "category": "", "cost": 15, "power": 20, "accuracy": 100, "description": "Hits 2-5 times in one turn.", "effect": 0, "callable": function (target) {} },
"splash": { "type": "", "category": "", "cost": 40, "power": 0, "accuracy": 0, "description": "No effect whatsoever.", "effect": 0, "callable": function (target) {} },
"spore": { "type": "", "category": "", "cost": 15, "power": 0, "accuracy": 100, "description": "Puts the target to sleep.", "effect": 0, "callable": function (target) {} },
"stomp": { "type": "", "category": "", "cost": 20, "power": 65, "accuracy": 100, "description": "30% chance to flinch.", "effect": 0, "callable": function (target) {} },
"strength": { "type": "", "category": "", "cost": 15, "power": 80, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"string shot": { "type": "", "category": "", "cost": 40, "power": 0, "accuracy": 95, "description": "Lowers foe's Spe 1 stage.", "effect": 0, "callable": function (target) {} },
"struggle": { "type": "", "category": "", "cost": 10, "power": 50, "accuracy": 0, "description": "Has 1/2 recoil.", "effect": 0, "callable": function (target) {} },
"stun spore": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 75, "description": "Paralyzes the target.", "effect": 0, "callable": function (target) {} },
"submission": { "type": "", "category": "", "cost": 25, "power": 80, "accuracy": 80, "description": "Has 1/4 recoil.", "effect": 0, "callable": function (target) {} },
"substitute": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 0, "description": "Takes 1/4 of the user's max HP to create a Substitute that takes damage for the user.", "effect": 0, "callable": function (target) {} },
"super fang": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 90, "description": "Does damage equal to half the foe's current HP.", "effect": 0, "callable": function (target) {} },
"supersonic": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 55, "description": "Confuses the foe.", "effect": 0, "callable": function (target) {} },
"surf": { "type": "", "category": "", "cost": 15, "power": 95, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"swift": { "type": "", "category": "", "cost": 20, "power": 60, "accuracy": 0, "description": "Always hits.", "effect": 0, "callable": function (target) {} },
"swords dance": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 0, "description": "Boosts Atk 2 stages.", "effect": 0, "callable": function (target) {} },
"tackle": { "type": "", "category": "", "cost": 35, "power": 35, "accuracy": 95, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"tail whip": { "type": "", "category": "", "cost": 30, "power": 0, "accuracy": 100, "description": "Lowers foe's Def 1 stage.", "effect": 0, "callable": function (target) {} },
"take down": { "type": "", "category": "", "cost": 20, "power": 90, "accuracy": 85, "description": "Has 1/4 recoil.", "effect": 0, "callable": function (target) {} },
"teleport": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 0, "description": "Has no effect.", "effect": 0, "callable": function (target) {} },
"thrash": { "type": "", "category": "", "cost": 20, "power": 90, "accuracy": 100, "description": "Repeats for 2-3 turns. Confuses the user at the end.", "effect": 0, "callable": function (target) {} },
"thunder": { "type": "", "category": "", "cost": 10, "power": 120, "accuracy": 70, "description": "10% chance to paralyze.", "effect": 0, "callable": function (target) {} },
"thunder wave": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 100, "description": "Paralyzes the foe.", "effect": 0, "callable": function (target) {} },
"thunderbolt": { "type": "", "category": "", "cost": 15, "power": 95, "accuracy": 100, "description": "10% chance to paralyze.", "effect": 0, "callable": function (target) {} },
"thunderpunch": { "type": "", "category": "", "cost": 15, "power": 75, "accuracy": 100, "description": "10% chance to paralyze.", "effect": 0, "callable": function (target) {} },
"thundershock": { "type": "", "category": "", "cost": 30, "power": 40, "accuracy": 100, "description": "10% chance to paralyze.", "effect": 0, "callable": function (target) {} },
"toxic": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 85, "description": "Inflicts intensifying poison on the target.", "effect": 0, "callable": function (target) {} },
"transform": { "type": "", "category": "", "cost": 10, "power": 0, "accuracy": 0, "description": "Transforms into the foe.", "effect": 0, "callable": function (target) {} },
"tri attack": { "type": "", "category": "", "cost": 10, "power": 80, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"twineedle": { "type": "", "category": "", "cost": 20, "power": 25, "accuracy": 100, "description": "Hits twice in one turn. Each hit has a 20% chance to poison.", "effect": 0, "callable": function (target) {} },
"vicegrip": { "type": "", "category": "", "cost": 30, "power": 55, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"vine whip": { "type": "", "category": "", "cost": 10, "power": 35, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"water gun": { "type": "", "category": "", "cost": 25, "power": 40, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"waterfall": { "type": "", "category": "", "cost": 15, "power": 80, "accuracy": 100, "description": "No additional effect.", "effect": 0, "callable": function (target) {} },
"whirlwind": { "type": "", "category": "", "cost": 20, "power": 0, "accuracy": 100, "description": "Has no effect.", "effect": 0, "callable": function (target) {} },
"wing attack": { "type": "", "category": "", "cost": 35, "power": 35, "accuracy": 100, "description": "No additional effect", "effect": 0, "callable": function (target) {} },
"withdraw": { "type": "", "category": "", "cost": 40, "power": 0, "accuracy": 0, "description": "Boosts Def 1 stage.", "effect": 0, "callable": function (target) {} },
"wrap": { "type": "", "category": "", "cost": 20, "power": 15, "accuracy": 85, "description": "Prevents the opponent from attacking for 2-5 turns.", "effect": 0, "callable": function (target) {} }
};
// Pokemon entity specific add-ons
god.entity.addons.addStat('special', { min: 0, max: 255, acronym: 'spe' });
god.entity.addons.addStat('level', { min: 1, max: 100, base: 1, acronym: 'lvl' });
god.entity.addons.addStat('exp', { min: 0, max: 100 }, {
gainExp: function (amount) {
if (!this.level) throw {
message: "Experience statistic requires level statistic",
name: "MissingStatistic",
reference: this
};
var previous = this.maxExp;
this.exp += amount;
if (this.exp > this.maxExp) this.maxExp += this.calculateExpRequired.call(this);
if (this.maxExp !== previous) this.level++;
return this;
},
calculateExpRequired: function (total) {
var group = typeof this.expGroup === 'string' ? this.expGroup.toLowerCase() : "average";
function calculate (group, n) {
switch (group) {
case "slow": return (5 * god.math.cube(n)) / 5; break;
case "medium": return (6/5 * god.math.cube(n) - 15* god.math.square(n) + 100 * n - 140);break;
case "fast": return (4 * god.math.cube(n)/5); break;
case "average": default: return god.math.cube(n); break;
}
}
return total ? calculate(group, this.level) : calculate(group, this.maxLevel) - calculate(group, this.level);
}
});
god.entity.addons.add('type', 'type', function (options) {
this.type = options.type;
});
god.entity.addons.add('effort', 'ev', function (options) {
this.ev = true;
for (var i in options)
if (options.hasOwnProperty(i))
this[i + 'Ev'] = options[i], god.utils.createTypeMethod({ on: this, type: ['get', 'set'], name: i + 'Ev' });
return this;
});
god.entity.addons.add('owner', 'owner', function (options) {
this.owner = options.target;
return god.utils.createTypeMethod({
on: this, type: ['get', 'set'], name: 'owner'
});
});
god.entity.addons.add('inventory', 'inventory', function (options) {
this.inventory = Object.prototype.toString.call(options.starting) === '[object Array]' ? options.starting : [];
this.inventory.use = function (item, target) {
var i = 0; for (;i < this.inventory.length; i++)
if (this.inventory[i].name === item.toLowerCase())
if (this.inventory[i].use.call(this, target) === true)
if (this.inventory[i].count === 1)
this.inventory.splice(i, 1);
else
this.inventory.count--;
return false;
};
this.inventory.has = function (item) {
var i = 0; for (;i < this.inventory.length; i++)
if (this.inventory[i].name === item.toLowerCase()) return i;
return false;
};
this.inventory.count = function (item) {
if (!item) return this.inventory.length;
var i = 0, count = 0; for (;i < this.inventory.length; i++)
if (this.inventory[i].name === item.toLowerCase()) return this.inventory[i].count;
return false;
};
return god.utils.createTypeMethod({
on: this, type: ['get', 'set'], name: 'inventory'
});
});
god.entity.addons.add('type', 'type', function (options) {
this.type = options.type || 'normal';
this.isType = function (against) {
return this.type === against.toLowerCase();
};
return god.utils.createTypeMethod({
on: this, type: ['get', 'set'], name: 'type'
});
});
@therebelrobot
Copy link

Just talked to you, you said the license on this is ISC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment