/************************************************************** * 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; }