/**************************************************************
* FFTacticsMUD : skills.cpp *
**************************************************************
* (c) 2002 Damien Dailidenas (Trenton). All rights reserved. *
**************************************************************/
#include "main.h"
#include <strstream>
#include <iomanip>
#include <mysql/mysql.h>
#include <cstdio>
const struct skill_type skill_table[] = {
{},
{ "Attack", SK_ACTION, do_attack, 0, 1, 0, 0, false },
/*****************
* SQUIRE SKILLS *
*****************/
{ "Accumulate", SK_ACTION, do_accumulate, JOB_SQUIRE, 0, 1, 0, 300, true },
{ "Dash", SK_ACTION, do_dash, JOB_SQUIRE, 1, 1, 0, 80, false },
{ "Throw Stone", SK_ACTION, do_throwstone, JOB_SQUIRE, 4, 1, 0, 90, false },
{ "Heal", SK_ACTION, do_heal, JOB_SQUIRE, 1, 1, 0, 150, true },
{ "Counter Tackle", SK_REACTION, do_countertackle, JOB_SQUIRE, 0, 0, 0, 180, 0, TRIG_HPDAMAGE },
{ "Equip Axe", SK_SUPPORT, NULL, JOB_SQUIRE, 0, 0, 0, 170, 0 },
{ "Monster Skill", SK_SUPPORT, do_monsterskill, JOB_SQUIRE, 0, 0, 0, 200, false },
{ "Defend", SK_SUPPORT, do_defend, JOB_SQUIRE, 0, 0, 0, 50, 0 },
{ "Gained Jp UP", SK_SUPPORT, NULL, JOB_SQUIRE, 0, 0, 0, 200, 0 },
{ "Move +1", SK_MOVE, NULL, JOB_SQUIRE, 0, 0, 0, 200, 0 },
/******************
* CHEMIST SKILLS *
******************/
{ "Potion", SK_ACTION, do_potion, JOB_CHEMIST, 1, 1, 0, 30, true },
{ "Hi-Potion", SK_ACTION, do_hipotion, JOB_CHEMIST, 1, 1, 0, 200, true },
{ "X-Potion", SK_ACTION, do_xpotion, JOB_CHEMIST, 1, 1, 0, 300, true },
{ "Ether", SK_ACTION, do_ether, JOB_CHEMIST, 1, 1, 0, 300, true },
{ "Hi-Ether", SK_ACTION, do_hiether, JOB_CHEMIST, 1, 1, 0, 400, true },
{ "Elixir", SK_ACTION, do_elixir, JOB_CHEMIST, 1, 1, 0, 900, true },
{ "Antidote", SK_ACTION, do_antidote, JOB_CHEMIST, 1, 1, 0, 70, true },
{ "Eye Drop", SK_ACTION, do_eyedrop, JOB_CHEMIST, 1, 1, 0, 80, true },
{ "Echo Grass", SK_ACTION, do_echograss, JOB_CHEMIST, 1, 1, 0, 120, true },
{ "Maiden's Kiss", SK_ACTION, do_maidenskiss, JOB_CHEMIST, 1, 1, 0, 200, true },
{ "Soft", SK_ACTION, do_soft, JOB_CHEMIST, 1, 1, 0, 250, true },
{ "Holy Water", SK_ACTION, do_holywater, JOB_CHEMIST, 1, 1, 0, 400, true },
{ "Remedy", SK_ACTION, do_remedy, JOB_CHEMIST, 1, 1, 0, 700, true },
{ "Phoenix Down", SK_ACTION, do_phoenixdown, JOB_CHEMIST, 1, 1, 0, 90, true },
{ "Auto Potion", SK_REACTION, do_autopotion, JOB_CHEMIST, 0, 0, 0, 400, 0, TRIG_HPDAMAGE },
{ "Throw Item", SK_SUPPORT, NULL, JOB_CHEMIST, 0, 0, 0, 350, true },
{ "Maintenance", SK_SUPPORT, do_maintenance, JOB_CHEMIST, 0, 0, 0, 250, 0 },
{ "Equip Change", SK_SUPPORT, do_equipchange, JOB_CHEMIST, 0, 0, 0, 0, 0 },
{ "Move-Find Item", SK_MOVE, do_movefinditem, JOB_CHEMIST, 0, 0, 0, 100, 0 },
/*****************
* KNIGHT SKILLS *
*****************/
{ "Head Break", SK_ACTION, do_headbreak, JOB_KNIGHT, 1, 1, 0, 300, false },
{ "Armor Break", SK_ACTION, do_armorbreak, JOB_KNIGHT, 1, 1, 0, 400, false },
{ "Shield Break", SK_ACTION, do_shieldbreak, JOB_KNIGHT, 1, 1, 0, 300, false },
{ "Weapon Break", SK_ACTION, do_weaponbreak, JOB_KNIGHT, 1, 1, 0, 400, false },
{ "Magic Break", SK_ACTION, do_magicbreak, JOB_KNIGHT, 1, 1, 0, 250, false },
{ "Speed Break", SK_ACTION, do_speedbreak, JOB_KNIGHT, 1, 1, 0, 250, false },
{ "Power Break", SK_ACTION, do_powerbreak, JOB_KNIGHT, 1, 1, 0, 250, false },
{ "Mind Break", SK_ACTION, do_mindbreak, JOB_KNIGHT, 1, 1, 0, 250, false },
{ "Weapon Guard", SK_REACTION, do_weaponguard, JOB_KNIGHT, 0, 0, 0, 200, 0, TRIG_ATTACK },
{ "Equip Armor", SK_SUPPORT, NULL, JOB_KNIGHT, 0, 0, 0, 500, 0 },
{ "Equip Shield", SK_SUPPORT, NULL, JOB_KNIGHT, 0, 0, 0, 250, 0 },
{ "Equip Sword", SK_SUPPORT, NULL, JOB_KNIGHT, 0, 0, 0, 400, 0 },
/*****************
* ARCHER SKILLS *
*****************/
{ "Charge +1", SK_ACTION, do_charge1, JOB_ARCHER, 1, 1, 4, 100, false },
{ "Charge +2", SK_ACTION, do_charge2, JOB_ARCHER, 1, 1, 5, 150, false },
{ "Charge +3", SK_ACTION, do_charge3, JOB_ARCHER, 1, 1, 6, 200, false },
{ "Charge +4", SK_ACTION, do_charge4, JOB_ARCHER, 1, 1, 8, 250, false },
{ "Charge +5", SK_ACTION, do_charge5, JOB_ARCHER, 1, 1, 10, 300, false },
{ "Charge +7", SK_ACTION, do_charge7, JOB_ARCHER, 1, 1, 14, 400, false },
{ "Charge +10", SK_ACTION, do_charge10, JOB_ARCHER, 1, 1, 20, 600, false },
{ "Charge +20", SK_ACTION, do_charge20, JOB_ARCHER, 1, 1, 35, 1000, false },
{ "Speed Save", SK_REACTION, do_speedsave, JOB_ARCHER, 0, 0, 0, 800, 0, TRIG_HPDAMAGE },
{ "Arrow Guard", SK_REACTION, do_arrowguard, JOB_ARCHER, 0, 0, 0, 450, 0 },
{ "Equip Crossbow", SK_SUPPORT, NULL, JOB_ARCHER, 0, 0, 0, 350, 0 },
{ "Concentrate", SK_SUPPORT, do_concentrate, JOB_ARCHER, 0, 0, 0, 400, 0 },
{ "Jump +1", SK_MOVE, NULL, JOB_ARCHER, 0, 0, 0, 200, 0 },
/***************
* MONK SKILLS *
***************/
{ "Spin Fist", SK_ACTION, do_spinfist, JOB_MONK, 0, 2, 0, 150, false },
{ "Repeating Fist", SK_ACTION, do_repeatingfist, JOB_MONK, 1, 1, 0, 300, false },
{ "Wave Fist", SK_ACTION, do_wavefist, JOB_MONK, 3, 1, 0, 300, false },
{ "Earth Slash", SK_ACTION, do_earthslash, JOB_MONK, 4, 1, 0, 600, false },
{ "Secret Fist", SK_ACTION, do_secretfist, JOB_MONK, 1, 1, 0, 300, false },
{ "Stigma Magic", SK_ACTION, do_stigmamagic, JOB_MONK, 0, 2, 0, 200, false },
{ "Chakra", SK_ACTION, do_chakra, JOB_MONK, 0, 2, 0, 350, false },
{ "Revive", SK_ACTION, do_revive, JOB_MONK, 1, 1, 0, 500, false },
/******************
* CHOCOBO SKILLS *
******************/
{ "Choco Attack", SK_ACTION, do_chocoattack, JOB_NPC, 1, 1, 0, 0, 0 },
{ "Choco Ball", SK_ACTION, do_chocoball, JOB_NPC, 4, 1, 0, 0, 0 },
{ "Choco Cure", SK_ACTION, do_chococure, JOB_NPC, 1, 2, 0, 0, false },
{ "Choco Esuna", SK_ACTION, do_chocoesuna, JOB_NPC, 1, 2, 0, 0, false },
{ "Choco Meteor", SK_ACTION, do_chocometeor, JOB_NPC, 5, 1, 0, 0, 0 },
{ "Scratch", SK_ACTION, do_scratch, JOB_NPC, 1, 1, 0, 0, 0 },
{ "Cat Kick", SK_ACTION, do_catkick, JOB_NPC, 1, 1, 0, 0, 0 },
{ "Poison Nail", SK_ACTION, do_poisonnail, JOB_NPC, 1, 1, 0, 0, 0 },
{ "Blaster", SK_ACTION, do_blaster, JOB_NPC, 3, 1, 0, 0, 0 },
{ "Blood Suck", SK_ACTION, do_bloodsuck, JOB_NPC, 1, 1, 0, 0, 0 },
{}
};
void CH::load_skills() {
MYSQL mysql;
MYSQL_RES *res;
MYSQL_ROW row;
mysql_init(&mysql);
if(!mysql_real_connect(&mysql, DB_LOC, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0))
return;
ostrstream ost;
ost << "SELECT id FROM skills WHERE player='" << name << "'" << ends;
mysql_query(&mysql, ost.str());
res = mysql_store_result(&mysql);
while((row = mysql_fetch_row(res)))
skill[atoi(row[0])] = true;
mysql_free_result(res);
mysql_close(&mysql);
return;
}
string get_skill_type(const short type) {
switch(type) {
case SK_ACTION:
return "Action";
case SK_REACTION:
return "Reaction";
case SK_SUPPORT:
return "Support";
case SK_MOVE:
return "Move";
}
return "";
}
short CH::get_skill_id(const string name, const bool learned) {
for(short x = 1; skill_table[x].name; ++x)
if(find(name, skill_table[x].name) && ((learned && skill[x]) || !learned))
return x;
return 0;
}
void do_learn(CH *ch, string argument="") {
short id;
if(argument.empty()) {
char buf_ctr[3], buf_mp[3], buf_jp[10];
ch->printf("Usage: learn [ability]\n\r");
ch->printf("{3+--{0Ability{3----------------{0Type{3-----{0Mp{3--{0Speed{3----{0Jp{3----+\n\r");
ch->printf("+-----------------------------------------------------+{0\n\r");
for(short x = 1; skill_table[x].name; ++x) {
if(skill_table[x].job == ch->cjob) {
sprintf(buf_ctr, "%02d", skill_table[x].ctr);
sprintf(buf_mp, "%02d", 0);
sprintf(buf_jp, "%04d ", skill_table[x].JP);
ch->printf(" %s%-20s %-8s %2s %3s %8s{0\n\r", !ch->skill[x] && ch->job[ch->cjob].JP < skill_table[x].JP ? "{8" : "{0", skill_table[x].name, get_skill_type(skill_table[x].type).c_str(), skill_table[x].type == SK_ACTION ? buf_mp : "--", skill_table[x].type == SK_ACTION ? buf_ctr : "--", ch->skill[x] ? " Learned" : buf_jp);
}
}
return;
}
if(!(id = ch->get_skill_id(argument, false)) || skill_table[id].job != ch->cjob) {
ch->printf("learn: ERROR: No such ability, " + argument + ".\n\r");
return;
}
if(ch->skill[id]) {
ch->printf("learn: ERROR: You already learned \"" + (string)skill_table[id].name + "\".\n\r");
return;
}
if(ch->job[ch->cjob].JP < skill_table[id].JP) {
ch->printf("learn: ERROR: Not enough JP.\n\r");
return;
}
ch->job[ch->cjob].JP -= skill_table[id].JP;
ch->skill[id] = true;
ostrstream ost;
ost << "You learn \"" << skill_table[id].name << "\" for " << skill_table[id].JP << ".\n\r" << ends;
ch->printf(ost.str());
return;
}
void CH::restore_hp(const short x) {
ostrstream ost;
ost << "{6[" << name << "] Hp +" << x << "{0\n\r" << ends;
battle->echo(ost.str());
HP[0] = MAX(HP[0] + x, HP[1]);
return;
}
void do_act(CH *ch, string argument="") {
ch->temp_action.action = do_act;
ch->cancel(status_charging, false);
ch->printf("Select an action from the following list:\n\r");
ch->printf("{3+--{0Ability{3------------------------+\n\r");
ch->printf("{3+---------------------------------+{0\n\r");
for(short x = 1; skill_table[x].name; ++x)
if(((!skill_table[x].JP && !skill_table[x].job) || (ch->skill[x] && (skill_table[x].job == ch->cjob || skill_table[x].job == ch->job[ch->cjob].subjob))) && (skill_table[x].type == SK_ACTION || skill_table[x].type == SK_SUPPORT) && skill_table[x].fun)
ch->printf(" %s\n\r", skill_table[x].name);
return;
}
void CH::announce_action() {
battle->echo("{&" + name + "> " + skill_table[action.id].name + "...{0\n\r");
return;
}
/*******************
* SKILL FUNCTIONS *
*******************/
bool do_accumulate(CH *ch, const bool check=false) {
ch->battle->echo("{6[" + ch->name + "] Physical AT +1!{0\n\r");
ch->add(status_accumulate, 0, 0, false);
return true;
}
bool do_dash(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, num_range(1, 4) * ch->PA);
}
bool do_throwstone(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, num_range(1, 2) * ch->PA);
}
bool do_heal(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
victim->cancel(status_darkness);
victim->cancel(status_silence);
victim->cancel(status_poison);
return true;
}
bool do_countertackle(CH *ch, const bool check=false) {
ch->announce_action();
do_dash(ch);
return false;
}
bool do_bloodsuck(CH *ch, const bool check=false) {
return true;
}
bool do_ice2(CH *ch, const bool check=false) {
return true;
}
bool do_monsterskill(CH *ch, const bool check=false) {
return true;
}
bool do_defend(CH *ch, const bool check=false) {
ch->battle->echo(ch->name + " takes a defensive stance.\n\r");
ch->action.action = do_defend;
return false;
}
bool do_movefinditem(CH *ch, const bool check=false) {
return true;
}
bool do_equipchange(CH *ch, const bool check=false) {
return true;
}
bool do_maintenance(CH *ch, const bool check=false) {
return true;
}
bool do_autopotion(CH *ch, const bool check=false) {
return true;
}
bool do_phoenixdown(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Phoenix Down", 0))) {
ch->printf("You have no \"Phoenix Down\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
if(victim->status(status_dead)) {
victim->cancel(status_dead);
victim->restore_hp(num_range(5, 10));
}
return true;
}
bool do_remedy(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Remedy", 0))) {
ch->printf("You have no \"Remedy\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
victim->cancel(status_petrify);
victim->cancel(status_darkness);
victim->cancel(status_confusion);
victim->cancel(status_silence);
victim->cancel(status_oil);
victim->cancel(status_frog);
victim->cancel(status_poison);
victim->cancel(status_sleep);
return true;
}
bool do_holywater(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Holy Water", 0))) {
ch->printf("You have no \"Holy Water\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
victim->cancel(status_undead);
victim->cancel(status_bloodsuck);
return true;
}
bool do_soft(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Soft", 0))) {
ch->printf("You have no \"Soft\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
victim->cancel(status_petrify);
return true;
}
bool do_maidenskiss(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Maiden's Kiss", 0))) {
ch->printf("You have no \"Maiden's Kiss\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
victim->cancel(status_frog);
return true;
}
bool do_echograss(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Echo Grass", 0))) {
ch->printf("You have no \"Echo Grass\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
victim->cancel(status_silence);
return true;
}
bool do_eyedrop(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Eye Drop", 0))) {
ch->printf("You have no \"Eye Drop\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
victim->cancel(status_darkness);
return true;
}
bool do_antidote(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Antidote", 0))) {
ch->printf("You have no \"Antidote\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
victim->cancel(status_poison);
return true;
}
bool do_elixir(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Elixir", 0))) {
ch->printf("You have no \"Elixir\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
ch->battle->echo(ch, "[%s] Hp +%d\n\r[%s] Mp +%d\n\r", victim->name.c_str(), victim->HP[1] - victim->HP[0], victim->name.c_str(), victim->MP[1] - victim->MP[0]);
victim->restore();
return true;
}
bool do_hiether(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Hi-Ether", 0))) {
ch->printf("You have no \"Hi-Ether\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
ch->battle->echo("[" + victim->name + "] Mp +50\n\r");
victim->MP[0] = MAX(victim->MP[0] + 50, victim->MP[1]);
return true;
}
bool do_ether(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Ether", 0))) {
ch->printf("You have no \"Ether\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
ch->battle->echo("[" + victim->name + "] Mp +20\n\r");
victim->MP[0] = MAX(victim->MP[0] + 20, victim->MP[1]);
return true;
}
bool do_hipotion(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("Hi-Potion", 0))) {
ch->printf("You have no \"Hi-Potion\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
victim->restore_hp(70);
return true;
}
bool do_potion(CH *ch, const bool check=false) {
CH *victim = ch;
OBJ *obj;
if(!(obj = ch->obj("Potion", 0))) {
ch->printf("You have no \"Potion\".\n\r");
return false;
}
zap(obj);
if(ch->battle && !(victim = ch->action.target->people))
return false;
victim->restore_hp(30);
return true;
}
bool do_xpotion(CH *ch, const bool check=false) {
CH *victim;
OBJ *obj;
if(!(obj = ch->obj("X-Potion", 0))) {
ch->printf("You have no \"X-Potion\".\n\r");
return false;
}
zap(obj);
if(!(victim = ch->action.target->people))
return false;
victim->restore_hp(150);
return true;
}
bool do_charge1(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->calculate_dam(1, ch->get_weap_loc()));
}
bool do_charge2(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->calculate_dam(2, ch->get_weap_loc()));
}
bool do_charge3(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->calculate_dam(3, ch->get_weap_loc()));
}
bool do_charge4(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->calculate_dam(4, ch->get_weap_loc()));
}
bool do_charge5(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->calculate_dam(6, ch->get_weap_loc()));
}
bool do_charge7(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->calculate_dam(7, ch->get_weap_loc()));
}
bool do_charge10(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->calculate_dam(10, ch->get_weap_loc()));
}
bool do_charge20(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->calculate_dam(20, ch->get_weap_loc()));
}
bool do_speedsave(CH *ch, const bool check=false) {
return true;
}
bool do_arrowguard(CH *ch, const bool check=false) {
return true;
}
bool do_concentrate(CH *ch, const bool check=false) {
return true;
}
bool do_headbreak(CH *ch, const bool check=false) {
CH *victim;
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->calculate_dam(0, ch->get_weap_loc()));
}
bool do_armorbreak(CH *ch, const bool check=false) {
return true;
}
bool do_shieldbreak(CH *ch, const bool check=false) {
return true;
}
bool do_weaponbreak(CH *ch, const bool check=false) {
return true;
}
bool do_magicbreak(CH *ch, const bool check=false) {
return true;
}
bool do_speedbreak(CH *ch, const bool check=false) {
return true;
}
bool do_powerbreak(CH *ch, const bool check=false) {
return true;
}
bool do_mindbreak(CH *ch, const bool check=false) {
return true;
}
bool do_weaponguard(CH *ch, const bool check=false) {
short loc;
if(!ch->eq[(loc = ch->get_weap_loc())] || obj_table[ch->eq[loc]->id].pEv < num_percent())
return false;
ch->announce_action();
ch->battle->echo(ch->name + " guards with his weapon!\n\r");
return true;
}
bool do_fire(CH *ch, const bool check=false) {
return true;
}
bool do_fire2(CH *ch, const bool check=false) {
return true;
}
bool do_ice(CH *ch, const bool check=false) {
return true;
}
bool do_bolt(CH *ch, const bool check=false) {
return true;
}
bool do_bolt2(CH *ch, const bool check=false) {
return true;
}
bool do_spinfist(CH *ch, const bool check=false) {
return true;
}
bool do_repeatingfist(CH *ch, const bool check=false) {
return true;
}
bool do_wavefist(CH *ch, const bool check=false) {
return true;
}
bool do_earthslash(CH *ch, const bool check=false) {
return true;
}
bool do_secretfist(CH *ch, const bool check=false) {
return true;
}
bool do_stigmamagic(CH *ch, const bool check=false) {
return true;
}
bool do_chakra(CH *ch, const bool check=false) {
return true;
}
bool do_revive(CH *ch, const bool check=false) {
return true;
}
/**************
* NPC skills *
**************/
bool do_chocoattack(CH *ch, const bool check=false) {
CH *victim;
if(check) {
victim = ch->get_nearest_target(false);
short distance = victim->distance(ch);
ch->action.target = victim->battle_room;
if(distance <= ch->temp_action.range)
return true;
else if(distance <= (ch->Mv + ch->temp_action.range) && ch->move_within_range(victim)) {
ch->moved = true;
return true;
}
ch->action.target = NULL;
return false;
}
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->calculate_dam(0, 0));
}
bool do_chococure(CH *ch, const bool check=false) {
CH *victim;
if(check) {
victim = ch->get_nearest_target(true);
if(!victim || victim->HP[0] > victim->HP[1] / 2)
return false;
short distance = victim->distance(ch);
ch->action.target = victim->battle_room;
if(distance <= ch->temp_action.range)
return true;
else if(distance <= (ch->Mv + ch->temp_action.range) && ch->move_within_range(victim)) {
ch->moved = true;
return true;
}
ch->action.target = NULL;
return false;
}
if(!(victim = ch->action.target->people))
return false;
victim->restore_hp((ch->MA * 3));
return true;
}
bool do_chocoesuna(CH *ch, const bool check=false) {
CH *victim;
if(check) {
victim = ch->get_nearest_target(true);
if(!victim || !victim->status(status_poison))
return false;
short distance = victim->distance(ch);
ch->action.target = victim->battle_room;
if(distance <= ch->temp_action.range)
return true;
else if(distance <= (ch->Mv + ch->temp_action.range) && ch->move_within_range(victim)) {
ch->moved = true;
return true;
}
ch->action.target = NULL;
return false;
}
if(!(victim = ch->action.target->people) || num_percent() > ch->PA * 4)
return false;
victim->cancel(status_poison);
return true;
}
bool do_chocoball(CH *ch, const bool check=false) {
CH *victim;
if(check) {
victim = ch->get_nearest_target(false);
short distance = victim->distance(ch);
ch->action.target = victim->battle_room;
if(distance <= ch->temp_action.range)
return true;
else if(distance <= (ch->Mv + ch->temp_action.range) && ch->move_within_range(victim)) {
ch->moved = true;
return true;
}
ch->action.target = NULL;
return false;
}
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->PA * (ch->PA / 2));
}
bool do_chocometeor(CH *ch, const bool check=false) {
CH *victim;
if(check) {
victim = ch->get_nearest_target(false);
short distance = victim->distance(ch);
ch->action.target = victim->battle_room;
if(distance <= ch->temp_action.range)
return true;
else if(distance <= (ch->Mv + ch->temp_action.range) && ch->move_within_range(victim)) {
ch->moved = true;
return true;
}
ch->action.target = NULL;
return false;
}
if(!(victim = ch->action.target->people))
return false;
ch->damage(victim, ch->MA * 4);
return true;
}
bool do_tackle(CH *ch, const bool check=false) {
return false;
}
bool do_eyegouge(CH *ch, const bool check=false) {
return false;
}
bool do_goblinpunch(CH *ch, const bool check=false) {
return false;
}
bool do_mutilate(CH *ch, const bool check=false) {
return false;
}
bool do_bite(CH *ch, const bool check=false) {
return false;
}
bool do_selfdestruct(CH *ch, const bool check=false) {
return false;
}
bool do_smallbomb(CH *ch, const bool check=false) {
return false;
}
bool do_turnpunch(CH *ch, const bool check=false) {
return false;
}
bool do_spark(CH *ch, const bool check=false) {
return false;
}
bool do_scratch(CH *ch, const bool check=false) {
CH *victim;
if(check) {
victim = ch->get_nearest_target(false);
short distance = victim->distance(ch);
ch->action.target = victim->battle_room;
if(distance <= ch->temp_action.range)
return true;
else if(distance <= (ch->Mv + ch->temp_action.range) && ch->move_within_range(victim)) {
ch->moved = true;
return true;
}
ch->action.target = NULL;
return false;
}
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, ch->calculate_dam(0, 0));
}
bool do_poisonnail(CH *ch, const bool check=false) {
CH *victim;
if(check) {
if(num_percent() > 10)
return false;
if((victim = ch->get_nearest_target(false)) && victim->status(status_poison))
return false;
short distance = victim->distance(ch);
ch->action.target = victim->battle_room;
if(distance <= ch->temp_action.range)
return true;
else if(distance <= (ch->Mv + ch->temp_action.range) && ch->move_within_range(victim)) {
ch->moved = true;
return true;
}
ch->action.target = NULL;
return false;
}
if(!(victim = ch->action.target->people))
return false;
return victim->add(status_poison, status_table[get_status_id(status_poison)].ctr, (ch->MA + 40), true);
}
bool do_catkick(CH *ch, const bool check=false) {
CH *victim;
if(check) {
if(num_percent() > 10)
return false;
victim = ch->get_nearest_target(false);
short distance = victim->distance(ch);
ch->action.target = victim->battle_room;
if(distance <= ch->temp_action.range)
return true;
else if(distance <= (ch->Mv + ch->temp_action.range) && ch->move_within_range(victim)) {
ch->moved = true;
return true;
}
ch->action.target = NULL;
return false;
}
if(!(victim = ch->action.target->people))
return false;
return ch->physical_attack(victim, (ch->PA * num_range(1, 9)));
}
bool do_blaster(CH *ch, const bool check=false) {
return false;
}
bool do_tentacle(CH *ch, const bool check=false) {
return false;
}
bool do_blackink(CH *ch, const bool check=false) {
return false;
}
bool do_darkwhisper(CH *ch, const bool check=false) {
return false;
}
bool do_tripleflame(CH *ch, const bool check=false) {
return false;
}
bool do_triplethunder(CH *ch, const bool check=false) {
return false;
}
bool do_triplebreath(CH *ch, const bool check=false) {
return false;
}
bool do_tripleattack(CH *ch, const bool check=false) {
return false;
}
bool do_firebreath(CH *ch, const bool check=false) {
return false;
}
bool do_thunderbreath(CH *ch, const bool check=false) {
return false;
}
bool do_icebreath(CH *ch, const bool check=false) {
return false;
}
bool do_tailswing(CH *ch, const bool check=false) {
return false;
}
bool do_ulmaguest(CH *ch, const bool check=false) {
return false;
}
bool do_suddencry(CH *ch, const bool check=false) {
return false;
}
bool do_stabup(CH *ch, const bool check=false) {
return false;
}
bool do_hurricane(CH *ch, const bool check=false) {
return false;
}
bool do_gigaflare(CH *ch, const bool check=false) {
return false;
}
bool do_moldballvirus(CH *ch, const bool check=false) {
return false;
}
bool do_badbreath(CH *ch, const bool check=false) {
return false;
}
bool do_lick(CH *ch, const bool check=false) {
return false;
}
bool do_goo(CH *ch, const bool check=false) {
return false;
}
bool do_blowfire(CH *ch, const bool check=false) {
return false;
}
bool do_gatherpower(CH *ch, const bool check=false) {
return false;
}
bool do_mimictitan(CH *ch, const bool check=false) {
return false;
}
bool do_shakeoff(CH *ch, const bool check=false) {
return false;
}
bool do_wavearound(CH *ch, const bool check=false) {
return false;
}
bool do_magicspirit(CH *ch, const bool check=false) {
return false;
}
bool do_calmspirit(CH *ch, const bool check=false) {
return false;
}
bool do_protectspirit(CH *ch, const bool check=false) {
return false;
}
bool do_leafdance(CH *ch, const bool check=false) {
return false;
}
bool do_spiritoflife(CH *ch, const bool check=false) {
return false;
}
bool do_pleaseeat(CH *ch, const bool check=false) {
return false;
}
bool do_nosebreath(CH *ch, const bool check=false) {
return false;
}
bool do_straightdash(CH *ch, const bool check=false) {
return false;
}
bool do_pooh(CH *ch, const bool check=false) {
return false;
}
bool do_oink(CH *ch, const bool check=false) {
return false;
}
bool do_beaking(CH *ch, const bool check=false) {
return false;
}
bool do_featherbomb(CH *ch, const bool check=false) {
return false;
}
bool do_beak(CH *ch, const bool check=false) {
return false;
}
bool do_scratchup(CH *ch, const bool check=false) {
return false;
}
bool do_shinelover(CH *ch, const bool check=false) {
return false;
}
bool do_circle(CH *ch, const bool check=false) {
return false;
}
bool do_deathsentence(CH *ch, const bool check=false) {
return false;
}
bool do_lookofdevil(CH *ch, const bool check=false) {
return false;
}
bool do_wingattack(CH *ch, const bool check=false) {
return false;
}
bool do_lookoffright(CH *ch, const bool check=false) {
return false;
}
bool do_zombietouch(CH *ch, const bool check=false) {
return false;
}
bool do_draintouch(CH *ch, const bool check=false) {
return false;
}
bool do_throwspirit(CH *ch, const bool check=false) {
return false;
}
bool do_greasetouch(CH *ch, const bool check=false) {
return false;
}
bool do_sleeptouch(CH *ch, const bool check=false) {
return false;
}
bool do_windsoul(CH *ch, const bool check=false) {
return false;
}
bool do_icesoul(CH *ch, const bool check=false) {
return false;
}
bool do_knifehand(CH *ch, const bool check=false) {
return false;
}
bool do_aquasoul(CH *ch, const bool check=false) {
return false;
}
bool do_thundersoul(CH *ch, const bool check=false) {
return false;
}
bool do_levelblast(CH *ch, const bool check=false) {
return false;
}
bool do_mindblast(CH *ch, const bool check=false) {
return false;
}
bool do_oddsoundwave(CH *ch, const bool check=false) {
return false;
}