// $Id: skill.c,v 1.8 2004/11/26 5:46:59 PM Celestia Exp $
/* �X�L��?�W */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "timer.h"
#include "nullpo.h"
#include "malloc.h"
#include "skill.h"
#include "map.h"
#include "clif.h"
#include "pc.h"
#include "pet.h"
#include "mob.h"
#include "battle.h"
#include "party.h"
#include "itemdb.h"
#include "script.h"
#include "intif.h"
#include "log.h"
#include "chrif.h"
#include "guild.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
#define SKILLUNITTIMER_INVERVAL 100
#define STATE_BLIND 0x10
/* �X�L����?�����X�e?�^�X�ُ��??���e?�u�� */
int SkillStatusChangeTable[]={ /* skill.h��enum��SC_***�Ƃ��킹�邱�� */
/* 0- */
-1,-1,-1,-1,-1,-1,
SC_PROVOKE, /* �v���{�b�N */
-1, 1,-1,
/* 10- */
SC_SIGHT, /* �T�C�g */
-1,-1,-1,-1,
SC_FREEZE, /* �t���X�g�_�C�o? */
SC_STONE, /* �X�g?���J?�X */
-1,-1,-1,
/* 20- */
-1,-1,-1,-1,
SC_RUWACH, /* ���A�t */
-1,-1,-1,-1,
SC_INCREASEAGI, /* ���x?�� */
/* 30- */
SC_DECREASEAGI, /* ���x���� */
-1,
SC_SIGNUMCRUCIS, /* �V�O�i���N���V�X */
SC_ANGELUS, /* �G���W�F���X */
SC_BLESSING, /* �u���b�V���O */
-1,-1,-1,-1,-1,
/* 40- */
-1,-1,-1,-1,-1,
SC_CONCENTRATE, /* �W���͌��� */
-1,-1,-1,-1,
/* 50- */
-1,
SC_HIDING, /* �n�C�f�B���O */
-1,-1,-1,-1,-1,-1,-1,-1,
/* 60- */
SC_TWOHANDQUICKEN, /* 2HQ */
SC_AUTOCOUNTER,
-1,-1,-1,-1,
SC_IMPOSITIO, /* �C���|�V�e�B�I�}�k�X */
SC_SUFFRAGIUM, /* �T�t���M�E�� */
SC_ASPERSIO, /* �A�X�y���V�I */
SC_BENEDICTIO, /* ��?�~�� */
/* 70- */
-1,
SC_SLOWPOISON,
-1,
SC_KYRIE, /* �L���G�G���C�\�� */
SC_MAGNIFICAT, /* �}�O�j�t�B�J?�g */
SC_GLORIA, /* �O�����A */
SC_DIVINA, /* ���b�N�X�f�B�r?�i */
-1,
SC_AETERNA, /* ���b�N�X�G?�e���i */
-1,
/* 80- */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
/* 90- */
-1,-1,
SC_QUAGMIRE, /* �N�@�O�}�C�A */
-1,-1,-1,-1,-1,-1,-1,
/* 100- */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
/* 110- */
-1,
SC_ADRENALINE, /* �A�h���i�������b�V�� */
SC_WEAPONPERFECTION,/* �E�F�|���p?�t�F�N�V���� */
SC_OVERTHRUST, /* �I?�o?�g���X�g */
SC_MAXIMIZEPOWER, /* �}�L�V�}�C�Y�p��? */
-1,-1,-1,-1,-1,
/* 120- */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
/* 130- */
-1,-1,-1,-1,-1,
SC_CLOAKING, /* �N��?�L���O */
SC_STAN, /* �\�j�b�N�u��? */
-1,
SC_ENCPOISON, /* �G���`�����g�|�C�Y�� */
SC_POISONREACT, /* �|�C�Y�����A�N�g */
/* 140- */
SC_POISON, /* �x�m���_�X�g */
SC_SPLASHER, /* �x�i���X�v���b�V��? */
-1,
SC_TRICKDEAD, /* ���ӂ� */
-1,-1,-1,-1,-1,-1,
/* 150- */
-1,-1,-1,-1,-1,
SC_LOUD, /* ���E�h�{�C�X */
-1,
SC_ENERGYCOAT, /* �G�i�W?�R?�g */
-1,-1,
/* 160- */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,
SC_SELFDESTRUCTION,
-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,
SC_KEEPING,
-1,-1,
SC_BARRIER,
-1,-1,
SC_HALLUCINATION,
-1,-1,
/* 210- */
-1,-1,-1,-1,-1,
SC_STRIPWEAPON,
SC_STRIPSHIELD,
SC_STRIPARMOR,
SC_STRIPHELM,
-1,
/* 220- */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
/* 230- */
-1,-1,-1,-1,
SC_CP_WEAPON,
SC_CP_SHIELD,
SC_CP_ARMOR,
SC_CP_HELM,
-1,-1,
/* 240- */
-1,-1,-1,-1,-1,-1,-1,-1,-1,
SC_AUTOGUARD,
/* 250- */
-1,-1,
SC_REFLECTSHIELD,
-1,-1,
SC_DEVOTION,
SC_PROVIDENCE,
SC_DEFENDER,
SC_SPEARSQUICKEN,
-1,
/* 260- */
-1,-1,-1,-1,-1,-1,-1,-1,
SC_STEELBODY,
SC_BLADESTOP_WAIT,
/* 270- */
SC_EXPLOSIONSPIRITS,
SC_EXTREMITYFIST,
-1,-1,-1,-1,
SC_MAGICROD,
-1,-1,-1,
/* 280- */
SC_FLAMELAUNCHER,
SC_FROSTWEAPON,
SC_LIGHTNINGLOADER,
SC_SEISMICWEAPON,
-1,
SC_VOLCANO,
SC_DELUGE,
SC_VIOLENTGALE,
SC_LANDPROTECTOR,
-1,
/* 290- */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
/* 300- */
-1,-1,-1,-1,-1,-1,
SC_LULLABY,
SC_RICHMANKIM,
SC_ETERNALCHAOS,
SC_DRUMBATTLE,
/* 310- */
SC_NIBELUNGEN,
SC_ROKISWEIL,
SC_INTOABYSS,
SC_SIEGFRIED,
-1,-1,-1,
SC_DISSONANCE,
-1,
SC_WHISTLE,
/* 320- */
SC_ASSNCROS,
SC_POEMBRAGI,
SC_APPLEIDUN,
-1,-1,
SC_UGLYDANCE,
-1,
SC_HUMMING,
SC_DONTFORGETME,
SC_FORTUNE,
/* 330- */
SC_SERVICE4U,
SC_SELFDESTRUCTION,
-1,-1,-1,-1,-1,-1,-1,-1,
/* 340- */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
/* 350- */
-1,-1,-1,-1,-1,
SC_AURABLADE,
SC_PARRYING,
SC_CONCENTRATION,
SC_TENSIONRELAX,
SC_BERSERK,
/* 360- */
SC_BERSERK,
SC_ASSUMPTIO,
SC_BASILICA,
-1,-1,-1,
SC_MAGICPOWER,
-1,-1,
SC_GOSPEL,
/* 370- */
-1,-1,-1,-1,-1,-1,-1,-1,
SC_EDP,
-1,
/* 380- */
SC_TRUESIGHT,
-1,-1,
SC_WINDWALK,
SC_MELTDOWN,
-1,-1,
SC_CARTBOOST,
-1,
SC_CHASEWALK,
/* 390- */
SC_REJECTSWORD,
-1,-1,-1,-1,-1,
SC_MARIONETTE,
-1,
SC_HEADCRUSH,
SC_JOINTBEAT,
/* 400 */
-1,-1,
SC_MINDBREAKER,
SC_MEMORIZE,
SC_FOGWALL,
SC_SPIDERWEB,
-1,-1,-1,-1,
/* 410- */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
};
const struct skill_name_db skill_names[] = {
{ AC_CHARGEARROW, "CHARGEARROW", "Charge_Arrow" } ,
{ AC_CONCENTRATION, "CONCENTRATION", "Improve_Concentration" } ,
{ AC_DOUBLE, "DOUBLE", "Double_Strafe" } ,
{ AC_MAKINGARROW, "MAKINGARROW", "Arrow_Creation" } ,
{ AC_OWL, "OWL", "Owl's_Eye" } ,
{ AC_SHOWER, "SHOWER", "Arrow_Shower" } ,
{ AC_VULTURE, "VULTURE", "Vulture's_Eye" } ,
{ ALL_RESURRECTION, "RESURRECTION", "Resurrection" } ,
{ AL_ANGELUS, "ANGELUS", "Angelus" } ,
{ AL_BLESSING, "BLESSING", "Blessing" } ,
{ AL_CRUCIS, "CRUCIS", "Signum_Crusis" } ,
{ AL_CURE, "CURE", "Cure" } ,
{ AL_DECAGI, "DECAGI", "Decrease_AGI" } ,
{ AL_DEMONBANE, "DEMONBANE", "Demon_Bane" } ,
{ AL_DP, "DP", "Divine_Protection" } ,
{ AL_HEAL, "HEAL", "Heal" } ,
{ AL_HOLYLIGHT, "HOLYLIGHT", "Holy_Light" } ,
{ AL_HOLYWATER, "HOLYWATER", "Aqua_Benedicta" } ,
{ AL_INCAGI, "INCAGI", "Increase_AGI" } ,
{ AL_PNEUMA, "PNEUMA", "Pneuma" } ,
{ AL_RUWACH, "RUWACH", "Ruwach" } ,
{ AL_TELEPORT, "TELEPORT", "Teleport" } ,
{ AL_WARP, "WARP", "Warp_Portal" } ,
{ AM_ACIDTERROR, "ACIDTERROR", "Acid_Terror" } ,
{ AM_AXEMASTERY, "AXEMASTERY", "Axe_Mastery" } ,
{ AM_BERSERKPITCHER, "BERSERKPITCHER", "Berserk Pitcher" } ,
{ AM_BIOETHICS, "BIOETHICS", "Bioethics" } ,
{ AM_BIOTECHNOLOGY, "BIOTECHNOLOGY", "Biotechnology" } ,
{ AM_CALLHOMUN, "CALLHOMUN", "Call_Homunculus" } ,
{ AM_CANNIBALIZE, "CANNIBALIZE", "Bio_Cannibalize" } ,
{ AM_CP_ARMOR, "ARMOR", "Chemical_Protection_Armor" } ,
{ AM_CP_HELM, "HELM", "Chemical_Protection_Helm" } ,
{ AM_CP_SHIELD, "SHIELD", "Chemical_Protection_Shield" } ,
{ AM_CP_WEAPON, "WEAPON", "Chemical_Protection_Weapon" } ,
{ AM_CREATECREATURE, "CREATECREATURE", "Life_Creation" } ,
{ AM_CULTIVATION, "CULTIVATION", "Cultivation" } ,
{ AM_DEMONSTRATION, "DEMONSTRATION", "Demonstration" } ,
{ AM_DRILLMASTER, "DRILLMASTER", "Drillmaster" } ,
{ AM_FLAMECONTROL, "FLAMECONTROL", "Flame_Control" } ,
{ AM_HEALHOMUN, "HEALHOMUN", "Heal_Homunculus" } ,
{ AM_LEARNINGPOTION, "LEARNINGPOTION", "AM_LEARNINGPOTION" } ,
{ AM_PHARMACY, "PHARMACY", "Pharmacy" } ,
{ AM_POTIONPITCHER, "POTIONPITCHER", "Potion_Pitcher" } ,
{ AM_REST, "REST", "Sabbath" } ,
{ AM_RESURRECTHOMUN, "RESURRECTHOMUN", "Ressurect_Homunculus" } ,
{ AM_SPHEREMINE, "SPHEREMINE", "Sphere_Mine" } ,
{ ASC_BREAKER, "BREAKER", "Breaker" } ,
{ ASC_CDP, "CDP", "Create_Deadly_Poison" } ,
{ ASC_EDP, "EDP", "Deadly_Poison_Enchantment" } ,
{ ASC_HALLUCINATION, "HALLUCINATION", "Hallucination_Walk" } ,
{ ASC_KATAR, "KATAR", "Advanced_Katar_Mastery" } ,
{ ASC_METEORASSAULT, "METEORASSAULT", "Meteor_Assault" } ,
{ AS_CLOAKING, "CLOAKING", "Cloaking" } ,
{ AS_ENCHANTPOISON, "ENCHANTPOISON", "Enchant_Poison" } ,
{ AS_GRIMTOOTH, "GRIMTOOTH", "Grimtooth" } ,
{ AS_KATAR, "KATAR", "Katar_Mastery" } ,
{ AS_LEFT, "LEFT", "Lefthand_Mastery" } ,
{ AS_POISONREACT, "POISONREACT", "Poison_React" } ,
{ AS_RIGHT, "RIGHT", "Righthand_Mastery" } ,
{ AS_SONICBLOW, "SONICBLOW", "Sonic_Blow" } ,
{ AS_SPLASHER, "SPLASHER", "Venom_Splasher" } ,
{ AS_VENOMDUST, "VENOMDUST", "Venom_Dust" } ,
{ BA_APPLEIDUN, "APPLEIDUN", "Apple_of_Idun" } ,
{ BA_ASSASSINCROSS, "ASSASSINCROSS", "Assassin_Cross" } ,
{ BA_DISSONANCE, "DISSONANCE", "Dissonance" } ,
{ BA_FROSTJOKE, "FROSTJOKE", "Dumb_Joke" } ,
{ BA_MUSICALLESSON, "MUSICALLESSON", "Musical_Lesson" } ,
{ BA_MUSICALSTRIKE, "MUSICALSTRIKE", "Musical_Strike" } ,
{ BA_POEMBRAGI, "POEMBRAGI", "Poem_of_Bragi" } ,
{ BA_WHISTLE, "WHISTLE", "Whistle" } ,
{ BD_ADAPTATION, "ADAPTATION", "Adaption" } ,
{ BD_DRUMBATTLEFIELD, "DRUMBATTLEFIELD", "Drumb_BattleField" } ,
{ BD_ENCORE, "ENCORE", "Encore" } ,
{ BD_ETERNALCHAOS, "ETERNALCHAOS", "Eternal_Chaos" } ,
{ BD_INTOABYSS, "INTOABYSS", "Into_the_Abyss" } ,
{ BD_LULLABY, "LULLABY", "Lullaby" } ,
{ BD_RAGNAROK, "RAGNAROK", "Ragnarok" } ,
{ BD_RICHMANKIM, "RICHMANKIM", "Rich_Mankim" } ,
{ BD_RINGNIBELUNGEN, "RINGNIBELUNGEN", "Ring_of_Nibelugen" } ,
{ BD_ROKISWEIL, "ROKISWEIL", "Loki's_Wail" } ,
{ BD_SIEGFRIED, "SIEGFRIED", "Invulnerable_Siegfried" } ,
{ BS_ADRENALINE, "ADRENALINE", "Adrenaline_Rush" } ,
{ BS_ADRENALINE2, "ADRENALINE2", "Adrenaline Rush 2" } ,
{ BS_AXE, "AXE", "Smith_Axe" } ,
{ BS_DAGGER, "DAGGER", "Smith_Dagger" } ,
{ BS_ENCHANTEDSTONE, "ENCHANTEDSTONE", "Enchantedstone_Craft" } ,
{ BS_FINDINGORE, "FINDINGORE", "Ore_Discovery" } ,
{ BS_HAMMERFALL, "HAMMERFALL", "Hammer_Fall" } ,
{ BS_HILTBINDING, "HILTBINDING", "Hilt_Binding" } ,
{ BS_IRON, "IRON", "Iron_Tempering" } ,
{ BS_KNUCKLE, "KNUCKLE", "Smith_Knucklebrace" } ,
{ BS_MACE, "MACE", "Smith_Mace" } ,
{ BS_MAXIMIZE, "MAXIMIZE", "Power_Maximize" } ,
{ BS_ORIDEOCON, "ORIDEOCON", "Orideocon_Research" } ,
{ BS_OVERTHRUST, "OVERTHRUST", "Power-Thrust" } ,
{ BS_REPAIRWEAPON, "REPAIRWEAPON", "Weapon_Repair" } ,
{ BS_SKINTEMPER, "SKINTEMPER", "Skin_Tempering" } ,
{ BS_SPEAR, "SPEAR", "Smith_Spear" } ,
{ BS_STEEL, "STEEL", "Steel_Tempering" } ,
{ BS_SWORD, "SWORD", "Smith_Sword" } ,
{ BS_TWOHANDSWORD, "TWOHANDSWORD", "Smith_Two-handed_Sword" } ,
{ BS_WEAPONPERFECT, "WEAPONPERFECT", "Weapon_Perfection" } ,
{ BS_WEAPONRESEARCH, "WEAPONRESEARCH", "Weaponry_Research" } ,
{ CG_ARROWVULCAN, "ARROWVULCAN", "Vulcan_Arrow" } ,
{ CG_MARIONETTE, "MARIONETTE", "Marionette_Control" } ,
{ CG_MOONLIT, "MOONLIT", "Moonlight_Petals" } ,
{ CH_CHAINCRUSH, "CHAINCRUSH", "Chain_Crush_Combo" } ,
{ CH_PALMSTRIKE, "PALMSTRIKE", "Palm_Push_Strike" } ,
{ CH_SOULCOLLECT, "SOULCOLLECT", "Collect_Soul" } ,
{ CH_TIGERFIST, "TIGERFIST", "Tiger_Knuckle_Fist" } ,
{ CR_ALCHEMY, "ALCHEMY", "Alchemy" } ,
{ CR_SLIMPITCHER, "SLIMPITCHER", "Slim_Pitcher" } ,
{ CR_FULLPROTECTION, "FULLPROTECTION", "Full_Chemical_Protection" } ,
{ CR_AUTOGUARD, "AUTOGUARD", "Guard" } ,
{ CR_DEFENDER, "DEFENDER", "Defender" } ,
{ CR_DEVOTION, "DEVOTION", "Sacrifice" } ,
{ CR_GRANDCROSS, "GRANDCROSS", "Grand_Cross" } ,
{ CR_HOLYCROSS, "HOLYCROSS", "Holy_Cross" } ,
{ CR_PROVIDENCE, "PROVIDENCE", "Providence" } ,
{ CR_REFLECTSHIELD, "REFLECTSHIELD", "Shield_Reflect" } ,
{ CR_SHIELDBOOMERANG, "SHIELDBOOMERANG", "Shield_Boomerang" } ,
{ CR_SHIELDCHARGE, "SHIELDCHARGE", "Shield_Charge" } ,
{ CR_SPEARQUICKEN, "SPEARQUICKEN", "Spear_Quicken" } ,
{ CR_SYNTHESISPOTION, "SYNTHESISPOTION", "Potion_Synthesis" } ,
{ CR_TRUST, "TRUST", "Faith" } ,
{ DC_DANCINGLESSON, "DANCINGLESSON", "Dancing_Lesson" } ,
{ DC_DONTFORGETME, "DONTFORGETME", "Don't_Forget_Me" } ,
{ DC_FORTUNEKISS, "FORTUNEKISS", "Fortune_Kiss" } ,
{ DC_HUMMING, "HUMMING", "Humming" } ,
{ DC_SCREAM, "SCREAM", "Scream" } ,
{ DC_SERVICEFORYOU, "SERVICEFORYOU", "Prostitute" } ,
{ DC_THROWARROW, "THROWARROW", "Throw_Arrow" } ,
{ DC_UGLYDANCE, "UGLYDANCE", "Ugly_Dance" } ,
{ HP_ASSUMPTIO, "ASSUMPTIO", "Assumptio" } ,
{ HP_BASILICA, "BASILICA", "Basilica" } ,
{ HP_MEDITATIO, "MEDITATIO", "Meditation" } ,
{ HT_ANKLESNARE, "ANKLESNARE", "Ankle_Snare" } ,
{ HT_BEASTBANE, "BEASTBANE", "Beast_Bane" } ,
{ HT_BLASTMINE, "BLASTMINE", "Blast_Mine" } ,
{ HT_BLITZBEAT, "BLITZBEAT", "Blitz_Beat" } ,
{ HT_CLAYMORETRAP, "CLAYMORETRAP", "Claymore_Trap" } ,
{ HT_DETECTING, "DETECTING", "Detect" } ,
{ HT_FALCON, "FALCON", "Falconry_Mastery" } ,
{ HT_FLASHER, "FLASHER", "Flasher" } ,
{ HT_FREEZINGTRAP, "FREEZINGTRAP", "Freezing_Trap" } ,
{ HT_LANDMINE, "LANDMINE", "Land_Mine" } ,
{ HT_REMOVETRAP, "REMOVETRAP", "Remove_Trap" } ,
{ HT_SANDMAN, "SANDMAN", "Sandman" } ,
{ HT_SHOCKWAVE, "SHOCKWAVE", "Shockwave_Trap" } ,
{ HT_SKIDTRAP, "SKIDTRAP", "Skid_Trap" } ,
{ HT_SPRINGTRAP, "SPRINGTRAP", "Spring_Trap" } ,
{ HT_STEELCROW, "STEELCROW", "Steel_Crow" } ,
{ HT_TALKIEBOX, "TALKIEBOX", "Talkie_Box" } ,
{ HW_MAGICCRASHER, "MAGICCRASHER", "Magic_Crasher" } ,
{ HW_MAGICPOWER, "MAGICPOWER", "Magic_Power" } ,
{ HW_NAPALMVULCAN, "NAPALMVULCAN", "Napalm_Vulcan" } ,
{ HW_SOULDRAIN, "SOULDRAIN", "Soul_Drain" } ,
{ ITM_TOMAHAWK, "TOMAHAWK", "Throw_Tomahawk" } ,
{ KN_AUTOCOUNTER, "AUTOCOUNTER", "Counter_Attack" } ,
{ KN_BOWLINGBASH, "BOWLINGBASH", "Bowling_Bash" } ,
{ KN_BRANDISHSPEAR, "BRANDISHSPEAR", "Brandish_Spear" } ,
{ KN_CAVALIERMASTERY, "CAVALIERMASTERY", "Cavalier_Mastery" } ,
{ KN_PIERCE, "PIERCE", "Pierce" } ,
{ KN_RIDING, "RIDING", "Peco_Peco_Ride" } ,
{ KN_SPEARBOOMERANG, "SPEARBOOMERANG", "Spear_Boomerang" } ,
{ KN_SPEARMASTERY, "SPEARMASTERY", "Spear_Mastery" } ,
{ KN_SPEARSTAB, "SPEARSTAB", "Spear_Stab" } ,
{ KN_TWOHANDQUICKEN, "TWOHANDQUICKEN", "Twohand_Quicken" } ,
{ LK_AURABLADE, "AURABLADE", "Aura_Blade" } ,
{ LK_BERSERK, "BERSERK", "Berserk" } ,
{ LK_CONCENTRATION, "CONCENTRATION", "Concentration" } ,
{ LK_FURY, "FURY", "LK_FURY" } ,
{ LK_HEADCRUSH, "HEADCRUSH", "Head_Crusher" } ,
{ LK_JOINTBEAT, "JOINTBEAT", "Joint_Beat" } ,
{ LK_PARRYING, "PARRYING", "Parrying" } ,
{ LK_SPIRALPIERCE, "SPIRALPIERCE", "Spiral_Pierce" } ,
{ LK_TENSIONRELAX, "TENSIONRELAX", "Tension_Relax" } ,
{ MC_CARTREVOLUTION, "CARTREVOLUTION", "Cart_Revolution" } ,
{ MC_CHANGECART, "CHANGECART", "Change_Cart" } ,
{ MC_DISCOUNT, "DISCOUNT", "Discount" } ,
{ MC_IDENTIFY, "IDENTIFY", "Item_Appraisal" } ,
{ MC_INCCARRY, "INCCARRY", "Enlarge_Weight_Limit" } ,
{ MC_LOUD, "LOUD", "Lord_Exclamation" } ,
{ MC_MAMMONITE, "MAMMONITE", "Mammonite" } ,
{ MC_OVERCHARGE, "OVERCHARGE", "Overcharge" } ,
{ MC_PUSHCART, "PUSHCART", "Pushcart" } ,
{ MC_VENDING, "VENDING", "Vending" } ,
{ MG_COLDBOLT, "COLDBOLT", "Cold_Bolt" } ,
{ MG_ENERGYCOAT, "ENERGYCOAT", "Energy_Coat" } ,
{ MG_FIREBALL, "FIREBALL", "Fire_Ball" } ,
{ MG_FIREBOLT, "FIREBOLT", "Fire_Bolt" } ,
{ MG_FIREWALL, "FIREWALL", "Fire_Wall" } ,
{ MG_FROSTDIVER, "FROSTDIVER", "Frost_Diver" } ,
{ MG_LIGHTNINGBOLT, "LIGHTNINGBOLT", "Lightening_Bolt" } ,
{ MG_NAPALMBEAT, "NAPALMBEAT", "Napalm_Beat" } ,
{ MG_SAFETYWALL, "SAFETYWALL", "Safety_Wall" } ,
{ MG_SIGHT, "SIGHT", "Sight" } ,
{ MG_SOULSTRIKE, "SOULSTRIKE", "Soul_Strike" } ,
{ MG_SRECOVERY, "SRECOVERY", "Increase_SP_Recovery" } ,
{ MG_STONECURSE, "STONECURSE", "Stone_Curse" } ,
{ MG_THUNDERSTORM, "THUNDERSTORM", "Thunderstorm" } ,
{ MO_ABSORBSPIRITS, "ABSORBSPIRITS", "Absorb_Spirits" } ,
{ MO_BLADESTOP, "BLADESTOP", "Blade_Stop" } ,
{ MO_BODYRELOCATION, "BODYRELOCATION", "Body_Relocation" } ,
{ MO_CALLSPIRITS, "CALLSPIRITS", "Call_Spirits" } ,
{ MO_CHAINCOMBO, "CHAINCOMBO", "Chain_Combo" } ,
{ MO_COMBOFINISH, "COMBOFINISH", "Combo_Finish" } ,
{ MO_DODGE, "DODGE", "Dodge" } ,
{ MO_EXPLOSIONSPIRITS, "EXPLOSIONSPIRITS", "Explosion_Spirits" } ,
{ MO_EXTREMITYFIST, "EXTREMITYFIST", "Extremity_Fist" } ,
{ MO_FINGEROFFENSIVE, "FINGEROFFENSIVE", "Finger_Offensive" } ,
{ MO_INVESTIGATE, "INVESTIGATE", "Investigate" } ,
{ MO_IRONHAND, "IRONHAND", "Iron_Hand" } ,
{ MO_SPIRITSRECOVERY, "SPIRITSRECOVERY", "Spirit_Recovery" } ,
{ MO_STEELBODY, "STEELBODY", "Steel_Body" } ,
{ MO_TRIPLEATTACK, "TRIPLEATTACK", "Triple_Blows" } ,
{ NPC_ATTRICHANGE, "ATTRICHANGE", "NPC_ATTRICHANGE" } ,
{ NPC_BARRIER, "BARRIER", "NPC_BARRIER" } ,
{ NPC_BLINDATTACK, "BLINDATTACK", "NPC_BLINDATTACK" } ,
{ NPC_BLOODDRAIN, "BLOODDRAIN", "NPC_BLOODDRAIN" } ,
{ NPC_CHANGEDARKNESS, "CHANGEDARKNESS", "NPC_CHANGEDARKNESS" } ,
{ NPC_CHANGEFIRE, "CHANGEFIRE", "NPC_CHANGEFIRE" } ,
{ NPC_CHANGEGROUND, "CHANGEGROUND", "NPC_CHANGEGROUND" } ,
{ NPC_CHANGEHOLY, "CHANGEHOLY", "NPC_CHANGEHOLY" } ,
{ NPC_CHANGEPOISON, "CHANGEPOISON", "NPC_CHANGEPOISON" } ,
{ NPC_CHANGETELEKINESIS, "CHANGETELEKINESIS", "NPC_CHANGETELEKINESIS" } ,
{ NPC_CHANGEWATER, "CHANGEWATER", "NPC_CHANGEWATER" } ,
{ NPC_CHANGEWIND, "CHANGEWIND", "NPC_CHANGEWIND" } ,
{ NPC_COMBOATTACK, "COMBOATTACK", "NPC_COMBOATTACK" } ,
{ NPC_CRITICALSLASH, "CRITICALSLASH", "NPC_CRITICALSLASH" } ,
{ NPC_CURSEATTACK, "CURSEATTACK", "NPC_CURSEATTACK" } ,
{ NPC_DARKBLESSING, "DARKBLESSING", "NPC_DARKBLESSING" } ,
{ NPC_DARKBREATH, "DARKBREATH", "NPC_DARKBREATH" } ,
{ NPC_DARKCROSS, "DARKCROSS", "NPC_DARKCROSS" } ,
{ NPC_DARKNESSATTACK, "DARKNESSATTACK", "NPC_DARKNESSATTACK" } ,
{ NPC_DEFENDER, "DEFENDER", "NPC_DEFENDER" } ,
{ NPC_EMOTION, "EMOTION", "NPC_EMOTION" } ,
{ NPC_ENERGYDRAIN, "ENERGYDRAIN", "NPC_ENERGYDRAIN" } ,
{ NPC_FIREATTACK, "FIREATTACK", "NPC_FIREATTACK" } ,
{ NPC_GROUNDATTACK, "GROUNDATTACK", "NPC_GROUNDATTACK" } ,
{ NPC_GUIDEDATTACK, "GUIDEDATTACK", "NPC_GUIDEDATTACK" } ,
{ NPC_HALLUCINATION, "HALLUCINATION", "NPC_HALLUCINATION" } ,
{ NPC_HOLYATTACK, "HOLYATTACK", "NPC_HOLYATTACK" } ,
{ NPC_KEEPING, "KEEPING", "NPC_KEEPING" } ,
{ NPC_LICK, "LICK", "NPC_LICK" } ,
{ NPC_MAGICALATTACK, "MAGICALATTACK", "NPC_MAGICALATTACK" } ,
{ NPC_MENTALBREAKER, "MENTALBREAKER", "NPC_MENTALBREAKER" } ,
{ NPC_METAMORPHOSIS, "METAMORPHOSIS", "NPC_METAMORPHOSIS" } ,
{ NPC_PETRIFYATTACK, "PETRIFYATTACK", "NPC_PETRIFYATTACK" } ,
{ NPC_PIERCINGATT, "PIERCINGATT", "NPC_PIERCINGATT" } ,
{ NPC_POISON, "POISON", "NPC_POISON" } ,
{ NPC_POISONATTACK, "POISONATTACK", "NPC_POISONATTACK" } ,
{ NPC_PROVOCATION, "PROVOCATION", "NPC_PROVOCATION" } ,
{ NPC_RANDOMATTACK, "RANDOMATTACK", "NPC_RANDOMATTACK" } ,
{ NPC_RANGEATTACK, "RANGEATTACK", "NPC_RANGEATTACK" } ,
{ NPC_REBIRTH, "REBIRTH", "NPC_REBIRTH" } ,
{ NPC_SELFDESTRUCTION, "SELFDESTRUCTION", "Kabooooom!" } ,
{ NPC_SELFDESTRUCTION2, "SELFDESTRUCTION2", "NPC_SELFDESTRUCTION2" } ,
{ NPC_SILENCEATTACK, "SILENCEATTACK", "NPC_SILENCEATTACK" } ,
{ NPC_SLEEPATTACK, "SLEEPATTACK", "NPC_SLEEPATTACK" } ,
{ NPC_SMOKING, "SMOKING", "NPC_SMOKING" } ,
{ NPC_SPLASHATTACK, "SPLASHATTACK", "NPC_SPLASHATTACK" } ,
{ NPC_STUNATTACK, "STUNATTACK", "NPC_STUNATTACK" } ,
{ NPC_SUICIDE, "SUICIDE", "NPC_SUICIDE" } ,
{ NPC_SUMMONMONSTER, "SUMMONMONSTER", "NPC_SUMMONMONSTER" } ,
{ NPC_SUMMONSLAVE, "SUMMONSLAVE", "NPC_SUMMONSLAVE" } ,
{ NPC_TELEKINESISATTACK, "TELEKINESISATTACK", "NPC_TELEKINESISATTACK" } ,
{ NPC_TRANSFORMATION, "TRANSFORMATION", "NPC_TRANSFORMATION" } ,
{ NPC_WATERATTACK, "WATERATTACK", "NPC_WATERATTACK" } ,
{ NPC_WINDATTACK, "WINDATTACK", "NPC_WINDATTACK" } ,
{ NV_BASIC, "BASIC", "Basic_Skill" } ,
{ NV_FIRSTAID, "FIRSTAID", "First Aid" } ,
{ NV_TRICKDEAD, "TRICKDEAD", "Play_Dead" } ,
{ PA_GOSPEL, "GOSPEL", "Gospel" } ,
{ PA_PRESSURE, "PRESSURE", "Pressure" } ,
{ PA_SACRIFICE, "SACRIFICE", "Sacrificial_Ritual" } ,
{ PF_FOGWALL, "FOGWALL", "Wall_of_Fog" } ,
{ PF_HPCONVERSION, "HPCONVERSION", "Health_Conversion" } ,
{ PF_MEMORIZE, "MEMORIZE", "Memorize" } ,
{ PF_MINDBREAKER, "MINDBREAKER", "Mind_Breaker" } ,
{ PF_SOULBURN, "SOULBURN", "Soul_Burn" } ,
{ PF_SOULCHANGE, "SOULCHANGE", "Soul_Change" } ,
{ PF_SPIDERWEB, "SPIDERWEB", "Spider_Web" } ,
{ PR_ASPERSIO, "ASPERSIO", "Aspersio" } ,
{ PR_BENEDICTIO, "BENEDICTIO", "B.S_Sacramenti" } ,
{ PR_GLORIA, "GLORIA", "Gloria" } ,
{ PR_IMPOSITIO, "IMPOSITIO", "Impositio_Manus" } ,
{ PR_KYRIE, "KYRIE", "Kyrie_Eleison" } ,
{ PR_LEXAETERNA, "LEXAETERNA", "Lex_Aeterna" } ,
{ PR_LEXDIVINA, "LEXDIVINA", "Lex_Divina" } ,
{ PR_MACEMASTERY, "MACEMASTERY", "Mace_Mastery" } ,
{ PR_MAGNIFICAT, "MAGNIFICAT", "Magnificat" } ,
{ PR_MAGNUS, "MAGNUS", "Magnus_Exorcismus" } ,
{ PR_SANCTUARY, "SANCTUARY", "Santuary" } ,
{ PR_SLOWPOISON, "SLOWPOISON", "Slow_Poison" } ,
{ PR_STRECOVERY, "STRECOVERY", "Status_Recovery" } ,
{ PR_SUFFRAGIUM, "SUFFRAGIUM", "Suffragium" } ,
{ PR_TURNUNDEAD, "TURNUNDEAD", "Turn_Undead" } ,
{ RG_BACKSTAP, "BACKSTAP", "Back_Stab" } ,
{ RG_CLEANER, "CLEANER", "Remover" } ,
{ RG_COMPULSION, "COMPULSION", "Compulsion_Discount" } ,
{ RG_FLAGGRAFFITI, "FLAGGRAFFITI", "Flag_Graffity" } ,
{ RG_GANGSTER, "GANGSTER", "Gangster's_Paradise" } ,
{ RG_GRAFFITI, "GRAFFITI", "Graffiti" } ,
{ RG_INTIMIDATE, "INTIMIDATE", "Intimidate" } ,
{ RG_PLAGIARISM, "PLAGIARISM", "Plagiarism" } ,
{ RG_RAID, "RAID", "Raid" } ,
{ RG_SNATCHER, "SNATCHER", "Snatcher" } ,
{ RG_STEALCOIN, "STEALCOIN", "Steal_Coin" } ,
{ RG_STRIPARMOR, "STRIPARMOR", "Strip_Armor" } ,
{ RG_STRIPHELM, "STRIPHELM", "Strip_Helm" } ,
{ RG_STRIPSHIELD, "STRIPSHIELD", "Strip_Shield" } ,
{ RG_STRIPWEAPON, "STRIPWEAPON", "Strip_Weapon" } ,
{ RG_TUNNELDRIVE, "TUNNELDRIVE", "Tunnel_Drive" } ,
{ SA_ABRACADABRA, "ABRACADABRA", "Hocus-pocus" } ,
{ SA_ADVANCEDBOOK, "ADVANCEDBOOK", "Advanced_Book" } ,
{ SA_AUTOSPELL, "AUTOSPELL", "Auto_Cast" } ,
{ SA_CASTCANCEL, "CASTCANCEL", "Cast_Cancel" } ,
{ SA_CLASSCHANGE, "CLASSCHANGE", "Class_Change" } ,
{ SA_COMA, "COMA", "Coma" } ,
{ SA_DEATH, "DEATH", "Death" } ,
{ SA_DELUGE, "DELUGE", "Deluge" } ,
{ SA_DISPELL, "DISPELL", "Dispel" } ,
{ SA_DRAGONOLOGY, "DRAGONOLOGY", "Dragonology" } ,
{ SA_FLAMELAUNCHER, "FLAMELAUNCHER", "Flame_Launcher" } ,
{ SA_FORTUNE, "FORTUNE", "Fortune" } ,
{ SA_FREECAST, "FREECAST", "Cast_Freedom" } ,
{ SA_FROSTWEAPON, "FROSTWEAPON", "Frost_Weapon" } ,
{ SA_FULLRECOVERY, "FULLRECOVERY", "Full_Recovery" } ,
{ SA_GRAVITY, "GRAVITY", "Gravity" } ,
{ SA_INSTANTDEATH, "INSTANTDEATH", "Instant_Death" } ,
{ SA_LANDPROTECTOR, "LANDPROTECTOR", "Land_Protector" } ,
{ SA_LEVELUP, "LEVELUP", "Level_Up" } ,
{ SA_LIGHTNINGLOADER, "LIGHTNINGLOADER", "Lightning_Loader" } ,
{ SA_MAGICROD, "MAGICROD", "Magic_Rod" } ,
{ SA_MONOCELL, "MONOCELL", "Monocell" } ,
{ SA_QUESTION, "QUESTION", "Question?" } ,
{ SA_REVERSEORCISH, "REVERSEORCISH", "Reverse_Orcish" } ,
{ SA_SEISMICWEAPON, "SEISMICWEAPON", "Seismic_Weapon" } ,
{ SA_SPELLBREAKER, "SPELLBREAKER", "Break_Spell" } ,
{ SA_SUMMONMONSTER, "SUMMONMONSTER", "Summon_Monster" } ,
{ SA_TAMINGMONSTER, "TAMINGMONSTER", "Taming_Monster" } ,
{ SA_VIOLENTGALE, "VIOLENTGALE", "Violent_Gale" } ,
{ SA_VOLCANO, "VOLCANO", "Volcano" } ,
{ SG_DEVIL, "DEVIL", "Devil" } ,
{ SG_FEEL, "FEEL", "Feel" } ,
{ SG_FRIEND, "FRIEND", "Friend" } ,
{ SG_FUSION, "FUSION", "Fusion" } ,
{ SG_HATE, "HATE", "Hate" } ,
{ SG_KNOWLEDGE, "KNOWLEDGE", "Knowledge" } ,
{ SG_MOON_ANGER, "ANGER", "Moon Anger" } ,
{ SG_MOON_BLESS, "BLESS", "Moon Bless" } ,
{ SG_MOON_COMFORT, "COMFORT", "Moon Comfort" } ,
{ SG_MOON_WARM, "WARM", "Moon Warm" } ,
{ SG_STAR_ANGER, "ANGER", "Star Anger" } ,
{ SG_STAR_BLESS, "BLESS", "Star Bless" } ,
{ SG_STAR_COMFORT, "COMFORT", "Star Comfort" } ,
{ SG_STAR_WARM, "WARM", "Star Warm" } ,
{ SG_SUN_ANGER, "ANGER", "Sun Anger" } ,
{ SG_SUN_BLESS, "BLESS", "Sun Bless" } ,
{ SG_SUN_COMFORT, "COMFORT", "Sun Comfort" } ,
{ SG_SUN_WARM, "WARM", "Sun Warm" } ,
{ SL_ALCHEMIST, "ALCHEMIST", "Alchemist" } ,
{ SL_ASSASIN, "ASSASIN", "Assasin" } ,
{ SL_BARDDANCER, "BARDDANCER", "Bard Dancer" } ,
{ SL_BLACKSMITH, "BLACKSMITH", "Black Smith" } ,
{ SL_CRUSADER, "CRUSADER", "Crusader" } ,
{ SL_HUNTER, "HUNTER", "Hunter" } ,
{ SL_KAAHI, "KAAHI", "Kaahi" } ,
{ SL_KAINA, "KAINA", "Kaina" } ,
{ SL_KAITE, "KAITE", "Kaite" } ,
{ SL_KAIZEL, "KAIZEL", "Kaizel" } ,
{ SL_KAUPE, "KAUPE", "Kaupe" } ,
{ SL_KNIGHT, "KNIGHT", "Knight" } ,
{ SL_MONK, "MONK", "Monk" } ,
{ SL_PRIEST, "PRIEST", "Priest" } ,
{ SL_ROGUE, "ROGUE", "Rogue" } ,
{ SL_SAGE, "SAGE", "Sage" } ,
{ SL_SKA, "SKA", "SKA" } ,
{ SL_SKE, "SKE", "SKE" } ,
{ SL_SMA, "SMA", "SMA" } ,
{ SL_SOULLINKER, "SOULLINKER", "Soul Linker" } ,
{ SL_STAR, "STAR", "Star" } ,
{ SL_STIN, "STIN", "Stin" } ,
{ SL_STUN, "STUN", "Stun" } ,
{ SL_SUPERNOVICE, "SUPERNOVICE", "Super Novice" } ,
{ SL_SWOO, "SWOO", "Swoo" } ,
{ SL_WIZARD, "WIZARD", "Wizard" } ,
{ SM_AUTOBERSERK, "AUTOBERSERK", "Auto_Berserk" } ,
{ SM_BASH, "BASH", "Bash" } ,
{ SM_ENDURE, "ENDURE", "Endure" } ,
{ SM_FATALBLOW, "FATALBLOW", "Attack_Weak_Point" } ,
{ SM_MAGNUM, "MAGNUM", "Magnum_Break" } ,
{ SM_MOVINGRECOVERY, "MOVINGRECOVERY", "Moving_HP_Recovery" } ,
{ SM_PROVOKE, "PROVOKE", "Provoke" } ,
{ SM_RECOVERY, "RECOVERY", "Increase_HP_Recovery" } ,
{ SM_SWORD, "SWORD", "Sword_Mastery" } ,
{ SM_TWOHAND, "TWOHAND", "Two-Handed_Sword_Mastery" } ,
{ SN_FALCONASSAULT, "FALCONASSAULT", "Falcon_Assault" } ,
{ SN_SHARPSHOOTING, "SHARPSHOOTING", "Sharpshooting" } ,
{ SN_SIGHT, "SIGHT", "True_Sight" } ,
{ SN_WINDWALK, "WINDWALK", "Wind_Walk" } ,
{ ST_CHASEWALK, "CHASEWALK", "Chase_Walk" } ,
{ ST_REJECTSWORD, "REJECTSWORD", "Reject_Sword" } ,
{ ST_STEALBACKPACK, "STEALBACKPACK", "Steal_Backpack" } ,
{ ST_PRESERVE, "PRESERVE", "Preserve" } ,
{ ST_FULLSTRIP, "FULLSTRIP", "Full_Strip" } ,
{ TF_BACKSLIDING, "BACKSLIDING", "Back_Sliding" } ,
{ TF_DETOXIFY, "DETOXIFY", "Detoxify" } ,
{ TF_DOUBLE, "DOUBLE", "Double_Attack" } ,
{ TF_HIDING, "HIDING", "Hiding" } ,
{ TF_MISS, "MISS", "Improve_Dodge" } ,
{ TF_PICKSTONE, "PICKSTONE", "Take_Stone" } ,
{ TF_POISON, "POISON", "Envenom" } ,
{ TF_SPRINKLESAND, "SPRINKLESAND", "Throw_Sand" } ,
{ TF_STEAL, "STEAL", "Steal" } ,
{ TF_THROWSTONE, "THROWSTONE", "Throw_Stone" } ,
{ TK_COUNTER, "COUNTER", "Counter" } ,
{ TK_DODGE, "DODGE", "Dodge" } ,
{ TK_DOWNKICK, "DOWNKICK", "Down Kick" } ,
{ TK_HIGHJUMP, "HIGHJUMP", "High Jump" } ,
{ TK_HPTIME, "HPTIME", "HP Time" } ,
{ TK_JUMPKICK, "JUMPKICK", "Jump Kick" } ,
{ TK_POWER, "POWER", "Power" } ,
{ TK_READYCOUNTER, "READYCOUNTER", "Ready Counter" } ,
{ TK_READYDOWN, "READYDOWN", "Ready Down" } ,
{ TK_READYSTORM, "READYSTORM", "Ready Storm" } ,
{ TK_READYTURN, "READYTURN", "Ready Turn" } ,
{ TK_RUN, "RUN", "TK_RUN" } ,
{ TK_SEVENWIND, "SEVENWIND", "Seven Wind" } ,
{ TK_SPTIME, "SPTIME", "SP Time" } ,
{ TK_STORMKICK, "STORMKICK", "Storm Kick" } ,
{ TK_TURNKICK, "TURNKICK", "Turn Kick" } ,
{ WE_BABY, "BABY", "Adopt_Baby" } ,
{ WE_CALLBABY, "CALLBABY", "Call_Baby" } ,
{ WE_CALLPARENT, "CALLPARENT", "Call_Parent" } ,
{ WE_CALLPARTNER, "CALLPARTNER", "I Want to See You" } ,
{ WE_FEMALE, "FEMALE", "I Only Look Up to You" } ,
{ WE_MALE, "MALE", "I Will Protect You" } ,
{ WS_CARTBOOST, "CARTBOOST", "Cart_Boost" } ,
{ WS_CREATECOIN, "CREATECOIN", "Create_Coins" } ,
{ WS_CREATENUGGET, "CREATENUGGET", "Create_Nuggets" } ,
{ WS_MELTDOWN, "MELTDOWN", "Meltdown" } ,
{ WS_SYSTEMCREATE, "SYSTEMCREATE", "Create_System_tower" } ,
{ WS_WEAPONREFINE, "WEAPONREFINE", "Weapon_Refine" } ,
{ WZ_EARTHSPIKE, "EARTHSPIKE", "Earth_Spike" } ,
{ WZ_ESTIMATION, "ESTIMATION", "Sense" } ,
{ WZ_FIREIVY, "FIREIVY", "Fire_Ivy" } ,
{ WZ_FIREPILLAR, "FIREPILLAR", "Fire_Pillar" } ,
{ WZ_FROSTNOVA, "FROSTNOVA", "Frost_Nova" } ,
{ WZ_HEAVENDRIVE, "HEAVENDRIVE", "Heaven's_Drive" } ,
{ WZ_ICEWALL, "ICEWALL", "Ice_Wall" } ,
{ WZ_JUPITEL, "JUPITEL", "Jupitel_Thunder" } ,
{ WZ_METEOR, "METEOR", "Meteor_Storm" } ,
{ WZ_QUAGMIRE, "QUAGMIRE", "Quagmire" } ,
{ WZ_SIGHTRASHER, "SIGHTRASHER", "Sightrasher" } ,
{ WZ_STORMGUST, "STORMGUST", "Storm_Gust" } ,
{ WZ_VERMILION, "VERMILION", "Lord_of_Vermilion" } ,
{ WZ_WATERBALL, "WATERBALL", "Water_Ball" } ,
{ 0, 0, 0 }
};
static const int dirx[8]={0,-1,-1,-1,0,1,1,1};
static const int diry[8]={1,1,0,-1,-1,-1,0,1};
static int rdamage;
/* �X�L���f?�^�x?�X */
struct skill_db skill_db[MAX_SKILL_DB];
/* �A�C�e���쐬�f?�^�x?�X */
struct skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB];
/* ��쐬�X�L���f?�^�x?�X */
struct skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB];
/* �A�u���J�_�u��?���X�L���f?�^�x?�X */
struct skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB];
int skill_get_hit( int id ){
if (id >= 10000 && id < 10015) id -= 9500;
return skill_db[id].hit;
}
int skill_get_inf( int id ){
return (id < 500) ? skill_db[id].inf : guild_skill_get_inf(id);
}
int skill_get_pl( int id ){
if (id >= 10000 && id < 10015) id-= 9500;
return skill_db[id].pl;
}
int skill_get_nk( int id ){
if (id >= 10000 && id < 10015) id-= 9500;
return skill_db[id].nk;
}
int skill_get_max( int id ){
return (id < 500) ? skill_db[id].max : guild_skill_get_max(id);
}
int skill_get_range( int id , int lv ){
if (lv <= 0) return 0;
return (id < 500) ? skill_db[id].range[lv-1] : guild_skill_get_range(id);
}
int skill_get_hp( int id ,int lv ){
if (id >= 10000 && id < 10015) id-= 9500;
return (lv <= 0) ? 0: skill_db[id].hp[lv-1];
}
int skill_get_sp( int id ,int lv ){
if (id >= 10000 && id < 10015) id-= 9500;
//if (lv <= 0) return 0;
//return (id < 500) ? skill_db[id].sp[lv-1] : guild_skill_get_sp(id, lv);
return (lv <= 0) ? 0: skill_db[id].sp[lv-1];
}
int skill_get_zeny( int id ,int lv ){
if (id >= 10000 && id < 10015) id-= 9500;
return (lv <= 0) ? 0:skill_db[id].zeny[lv-1];
}
int skill_get_num( int id ,int lv ){
if (id >= 10000 && id < 10015) id-= 9500;
return (lv <= 0) ? 0:skill_db[id].num[lv-1];
}
int skill_get_cast( int id ,int lv ){
if (id >= 10000 && id < 10015) id-= 9500;
return (lv <= 0) ? 0:skill_db[id].cast[lv-1];
}
int skill_get_delay( int id ,int lv ){
if (id >= 10000 && id < 10015) id-= 9500;
return (lv <= 0) ? 0:skill_db[id].delay[lv-1];
}
int skill_get_time( int id ,int lv ){
if (id >= 10000 && id < 10015) id-= 9500;
return (lv <= 0) ? 0:skill_db[id].upkeep_time[lv-1];
}
int skill_get_time2( int id ,int lv ){
if (id >= 10000 && id < 10015) id-= 9500;
return (lv <= 0) ? 0:skill_db[id].upkeep_time2[lv-1];
}
int skill_get_castdef( int id ){
if (id >= 10000 && id < 10015) id-= 9500;
return skill_db[id].cast_def_rate;
}
int skill_get_weapontype( int id ){
if (id >= 10000 && id < 10015) id-= 9500;
return skill_db[id].weapon;
}
int skill_get_inf2( int id ){
if (id >= 10000 && id < 10015) id-= 9500;
return skill_db[id].inf2;
}
int skill_get_castcancel( int id ){
if (id >= 10000 && id < 10015) id-= 9500;
return skill_db[id].maxcount;
}
int skill_get_maxcount( int id ){
if (id >= 10000 && id < 10015) id-= 9500;
return skill_db[id].maxcount;
}
int skill_get_blewcount( int id ,int lv ){
if (id >= 10000 && id < 10015) id-= 9500;
return (lv <= 0) ? 0:skill_db[id].blewcount[lv-1];
}
int skill_get_mhp( int id ,int lv ){
if (id >= 10000 && id < 10015) id-= 9500;
return (lv <= 0) ? 0:skill_db[id].mhp[lv-1];
}
int skill_get_castnodex( int id ,int lv ){
if (id >= 10000 && id < 10015) id-= 9500;
return (lv <= 0) ? 0:skill_db[id].castnodex[lv-1];
}
int skill_tree_get_max(int id, int b_class){
struct pc_base_job s_class = pc_calc_base_job(b_class);
int i, skillid;
for(i=0;(skillid=skill_tree[s_class.upper][s_class.job][i].id)>0;i++)
if (id == skillid) return skill_tree[s_class.upper][s_class.job][i].max;
return skill_get_max (id);
}
/* �v���g�^�C�v */
//struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag);
int skill_check_condition( struct map_session_data *sd,int type);
int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag );
int skill_frostjoke_scream(struct block_list *bl,va_list ap);
int skill_status_change_timer_sub(struct block_list *bl, va_list ap );
int skill_attack_area(struct block_list *bl,va_list ap);
int skill_abra_dataset(int skilllv);
int skill_clear_element_field(struct block_list *bl);
int skill_landprotector(struct block_list *bl, va_list ap );
int skill_trap_splash(struct block_list *bl, va_list ap );
int skill_count_target(struct block_list *bl, va_list ap );
// [MouseJstr] - skill ok to cast? and when?
int skillnotok(int skillid, struct map_session_data *sd) {
if (sd == 0)
return 0;
if (pc_isGM(sd) >= 20)
return 0; // gm's can do anything damn thing they want
switch (skillid) {
case AL_WARP:
case AL_TELEPORT:
case MC_VENDING:
case MC_IDENTIFY:
return 0; // always allowed
default:
return(map[sd->bl.m].flag.noskill);
}
}
static int distance(int x0,int y0,int x1,int y1)
{
int dx,dy;
dx=abs(x0-x1);
dy=abs(y0-y1);
return dx>dy ? dx : dy;
}
/* �X�L�����j�b�gID��Ԃ��i������f?�^�x?�X�ɓ��ꂽ���ȁj */
int skill_get_unit_id(int id,int flag)
{
switch(id){
case MG_SAFETYWALL: return 0x7e; /* �Z�C�t�e�B�E�H?�� */
case MG_FIREWALL: return 0x7f; /* �t�@�C�A?�E�H?�� */
case AL_WARP: return (flag==0)?0x81:0x80; /* ��?�v�|?�^�� */
case PR_BENEDICTIO: return 0x82; /* ��?�~�� */
case PR_SANCTUARY: return 0x83; /* �T���N�`���A�� */
case PR_MAGNUS: return 0x84; /* �}�O�k�X�G�N�\�V�Y�� */
case AL_PNEUMA: return 0x85; /* �j��?�} */
case MG_THUNDERSTORM: return 0x86; /* �T���_?�X�g?�� */
case WZ_HEAVENDRIVE: return 0x86; /* �w�����Y�h���C�u */
case WZ_SIGHTRASHER: return 0x86; /* �T�C�g���b�V��? */
case WZ_METEOR: return 0x86; /* ���e�I�X�g?�� */
case WZ_VERMILION: return 0x86; /* ��?�h�I�u���@?�~���I�� */
case WZ_FROSTNOVA: return 0x86; /* �t���X�g�m���@ */
case WZ_STORMGUST: return 0x86; /* �X�g?���K�X�g(�Ƃ肠����LoV�Ɠ�����?��) */
case CR_GRANDCROSS: return 0x86; /* �O�����h�N���X */
case WZ_FIREPILLAR: return (flag==0)?0x87:0x88; /* �t�@�C�A?�s��? */
case HT_TALKIEBOX: return 0x99; /* �g?�L?�{�b�N�X */
case WZ_ICEWALL: return 0x8d; /* �A�C�X�E�H?�� */
case WZ_QUAGMIRE: return 0x8e; /* �N�@�O�}�C�A */
case HT_BLASTMINE: return 0x8f; /* �u���X�g�}�C�� */
case HT_SKIDTRAP: return 0x90; /* �X�L�b�h�g���b�v */
case HT_ANKLESNARE: return 0x91; /* �A���N���X�l�A */
case AS_VENOMDUST: return 0x92; /* �x�m���_�X�g */
case HT_LANDMINE: return 0x93; /* �����h�}�C�� */
case HT_SHOCKWAVE: return 0x94; /* �V���b�N�E�F?�u�g���b�v */
case HT_SANDMAN: return 0x95; /* �T���h�}�� */
case HT_FLASHER: return 0x96; /* �t���b�V��? */
case HT_FREEZINGTRAP: return 0x97; /* �t��?�W���O�g���b�v */
case HT_CLAYMORETRAP: return 0x98; /* �N���C���A?�g���b�v */
case SA_VOLCANO: return 0x9a; /* �{���P?�m */
case SA_DELUGE: return 0x9b; /* �f����?�W */
case SA_VIOLENTGALE: return 0x9c; /* �o�C�I�����g�Q�C�� */
case SA_LANDPROTECTOR: return 0x9d; /* �����h�v���e�N�^? */
case BD_LULLABY: return 0x9e; /* �q��� */
case BD_RICHMANKIM: return 0x9f; /* �j�����h�̉� */
case BD_ETERNALCHAOS: return 0xa0; /* �i���̍��� */
case BD_DRUMBATTLEFIELD:return 0xa1; /* ?���ۂ̋��� */
case BD_RINGNIBELUNGEN: return 0xa2; /* �j?�x�����O�̎w�� */
case BD_ROKISWEIL: return 0xa3; /* ���L�̋��� */
case BD_INTOABYSS: return 0xa4; /* �[���̒��� */
case BD_SIEGFRIED: return 0xa5; /* �s���g�̃W?�N�t��?�h */
case BA_DISSONANCE: return 0xa6; /* �s���a�� */
case BA_WHISTLE: return 0xa7; /* ���J */
case BA_ASSASSINCROSS: return 0xa8; /* �[�z�̃A�T�V���N���X */
case BA_POEMBRAGI: return 0xa9; /* �u���M�̎� */
case BA_APPLEIDUN: return 0xaa; /* �C�h�D���̗ь� */
case DC_UGLYDANCE: return 0xab; /* ��������ȃ_���X */
case DC_HUMMING: return 0xac; /* �n�~���O */
case DC_DONTFORGETME: return 0xad; /* ����Y��Ȃ��Łc */
case DC_FORTUNEKISS: return 0xae; /* �K�^�̃L�X */
case DC_SERVICEFORYOU: return 0xaf; /* �T?�r�X�t�H?��? */
case RG_GRAFFITI: return 0xb0; /* �O���t�B�e�B */
case AM_DEMONSTRATION: return 0xb1; /* �f�����X�g��?�V���� */
case WE_CALLPARTNER: return 0xb2; /* ���Ȃ��Ɉ������� */
case PA_GOSPEL: return 0xb3; /* �S�X�y�� */
case HP_BASILICA: return 0xb4; /* �o�W���J */
case CG_MOONLIT: return 0xb5;
case PF_FOGWALL: return 0xb6; /* �t�H�O�E�H?�� */
case PF_SPIDERWEB: return 0xb7; /* �X�p�C�_?�E�F�b�u */
// temporary unit ID's [Celest]
case GD_LEADERSHIP: return 0xc1;
case GD_GLORYWOUNDS: return 0xc2;
case GD_SOULCOLD: return 0xc3;
case GD_HAWKEYES: return 0xc4;
}
return 0;
/*
0x89,0x8a,0x8b �\������
0x9a ��?���̉r���݂����ȃG�t�F�N�g
0x9b ��?���̉r���݂����ȃG�t�F�N�g
0x9c ��?���̉r���݂����ȃG�t�F�N�g
0x9d ���������ȃG�t�F�N�g
0xb1 Alchemist Demonstration
0xb2 = Pink Warp Portal
0xb3 = Gospel For Paladin
0xb4 = Basilica
0xb5 = Empty
0xb6 = Fog Wall for Professor
0xb7 = Spider Web for Professor
0xb8 = Empty
0xb9 =
*/
}
/*==========================================
* �X�L���lj�?��
*------------------------------------------
*/
int skill_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick)
{
/* MOB�lj�?�ʃX�L���p */
const int sc[]={
SC_POISON, SC_BLIND, SC_SILENCE, SC_STAN,
SC_STONE, SC_CURSE, SC_SLEEP
};
const int sc2[]={
MG_STONECURSE,MG_FROSTDIVER,NPC_STUNATTACK,
NPC_SLEEPATTACK,TF_POISON,NPC_CURSEATTACK,
NPC_SILENCEATTACK,0,NPC_BLINDATTACK
};
struct map_session_data *sd=NULL;
struct map_session_data *dstsd=NULL;
struct mob_data *md=NULL;
struct mob_data *dstmd=NULL;
struct pet_data *pd=NULL;
int skill,skill2;
int rate,luk;
int sc_def_mdef,sc_def_vit,sc_def_int,sc_def_luk;
int sc_def_mdef2,sc_def_vit2,sc_def_int2,sc_def_luk2;
nullpo_retr(0, src);
nullpo_retr(0, bl);
//if(skilllv <= 0) return 0;
if(skillid > 0 && skilllv <= 0) return 0; // don't forget auto attacks! - celest
if(src->type==BL_PC){
nullpo_retr(0, sd=(struct map_session_data *)src);
}else if(src->type==BL_MOB){
nullpo_retr(0, md=(struct mob_data *)src); //���g�p�H
}else if(src->type==BL_PET){
nullpo_retr(0, pd=(struct pet_data *)src); // [Valaris]
}
//?�ۂ̑ϐ�
luk = battle_get_luk(bl);
sc_def_mdef=100 - (3 + battle_get_mdef(bl) + luk/3);
sc_def_vit=100 - (3 + battle_get_vit(bl) + luk/3);
sc_def_int=100 - (3 + battle_get_int(bl) + luk/3);
sc_def_luk=100 - (3 + luk);
//�����̑ϐ�
luk = battle_get_luk(src);
sc_def_mdef2=100 - (3 + battle_get_mdef(src) + luk/3);
sc_def_vit2=100 - (3 + battle_get_vit(src) + luk/3);
sc_def_int2=100 - (3 + battle_get_int(src) + luk/3);
sc_def_luk2=100 - (3 + luk);
if(bl->type==BL_PC)
dstsd=(struct map_session_data *)bl;
else if(bl->type==BL_MOB){
dstmd=(struct mob_data *)bl; //���g�p�H
if(sc_def_mdef<50)
sc_def_mdef=50;
if(sc_def_vit<50)
sc_def_vit=50;
if(sc_def_int<50)
sc_def_int=50;
if(sc_def_luk<50)
sc_def_luk=50;
}
if(sc_def_mdef<0)
sc_def_mdef=0;
if(sc_def_vit<0)
sc_def_vit=0;
if(sc_def_int<0)
sc_def_int=0;
switch(skillid){
case 0: /* �ʏ�U? */
/* ������ */
if( sd && pc_isfalcon(sd) && sd->status.weapon == 11 && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 &&
rand()%1000 <= sd->paramc[5]*10/3+1 ) {
int lv=(sd->status.job_level+9)/10;
skill_castend_damage_id(src,bl,HT_BLITZBEAT,(skill<lv)?skill:lv,tick,0xf00000);
}
// �X�i�b�`��?
if(sd && sd->status.weapon != 11 && (skill=pc_checkskill(sd,RG_SNATCHER)) > 0)
if((skill*15 + 55) + (skill2 = pc_checkskill(sd,TF_STEAL))*10 > rand()%1000) {
if(pc_steal_item(sd,bl))
clif_skill_nodamage(src,bl,TF_STEAL,skill2,1);
else if (battle_config.display_snatcher_skill_fail)
clif_skill_fail(sd,skillid,0,0); // it's annoying! =p [Celest]
}
// �G���`�����g�f�b�g��?�|�C�Y��(�ғ�?��)
if (sd && sd->sc_data[SC_EDP].timer != -1 && rand() % 10000 < sd->sc_data[SC_EDP].val2 * sc_def_vit) {
int mhp = battle_get_max_hp(bl);
int hp = battle_get_hp(bl);
int lvl = sd->sc_data[SC_EDP].val1;
int diff;
// MHP��1/4�ȉ��ɂ͂Ȃ�Ȃ�
if(hp > mhp>>2) {
if(bl->type == BL_PC) {
diff = mhp*10/100;
if (hp - diff < mhp>>2)
diff = hp - (mhp>>2);
pc_heal((struct map_session_data *)bl, -hp, 0);
} else if(bl->type == BL_MOB) {
struct mob_data *md = (struct mob_data *)bl;
hp -= mhp*15/100;
if (hp > mhp>>2)
md->hp = hp;
else
md->hp = mhp>>2;
}
}
skill_status_change_start(bl,SC_DPOISON,lvl,0,0,0,skill_get_time2(ASC_EDP,lvl),0);
}
break;
case SM_BASH: /* �o�b�V���i�}���U?�j */
if( sd && (skill=pc_checkskill(sd,SM_FATALBLOW))>0 ){
if( rand()%100 < 6*(skilllv-5)*sc_def_vit/100 )
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(SM_FATALBLOW,skilllv),0);
}
break;
case TF_POISON: /* �C���x�i�� */
case AS_SPLASHER: /* �x�i���X�v���b�V��? */
if(rand()%100< (2*skilllv+10)*sc_def_vit/100 )
skill_status_change_start(bl,SC_POISON,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
else{
if(sd && skillid==TF_POISON)
clif_skill_fail(sd,skillid,0,0);
}
break;
case AS_SONICBLOW: /* �\�j�b�N�u��? */
if( rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case HT_FREEZINGTRAP: /* �t��?�W���O�g���b�v */
rate=skilllv*3+35;
if(rand()%100 < rate*sc_def_mdef/100)
skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case MG_FROSTDIVER: /* �t���X�g�_�C�o? */
case WZ_FROSTNOVA: /* �t���X�g�m���@ */
rate=(skilllv*3+35)*sc_def_mdef/100-(battle_get_int(bl)+battle_get_luk(bl))/15;
rate=rate<=5?5:rate;
if(rand()%100 < rate)
skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
else if(sd && skillid==MG_FROSTDIVER)
clif_skill_fail(sd,skillid,0,0);
break;
case WZ_STORMGUST: /* �X�g?���K�X�g */
{
struct status_change *sc_data = battle_get_sc_data(bl);
if(sc_data) {
sc_data[SC_FREEZE].val3++;
if(sc_data[SC_FREEZE].val3 >= 3)
skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
}
break;
case HT_LANDMINE: /* �����h�}�C�� */
if( rand()%100 < (5*skilllv+30)*sc_def_vit/100 )
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case HT_SHOCKWAVE: /* �V���b�N�E�F?�u�g���b�v */
if(map[bl->m].flag.pvp && dstsd){
dstsd->status.sp -= dstsd->status.sp*(5+15*skilllv)/100;
pc_calcstatus(dstsd,0);
}
break;
case HT_SANDMAN: /* �T���h�}�� */
if( rand()%100 < (5*skilllv+30)*sc_def_int/100 )
skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case TF_SPRINKLESAND: /* ���܂� */
if( rand()%100 < 20*sc_def_int/100 )
skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case TF_THROWSTONE: /* ���� */
if( rand()%100 < 7*sc_def_vit/100 )
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case CR_HOLYCROSS: /* �z?��?�N���X */
if( rand()%100 < 3*skilllv*sc_def_int/100 )
skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case CR_GRANDCROSS: /* �O�����h�N���X */
{
int race = battle_get_race(bl);
if( (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6) && rand()%100 < 100000*sc_def_int/100) //?���t?�������S�ϐ��ɂ͖�?
skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
break;
case CR_SHIELDCHARGE: /* �V?���h�`��?�W */
if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 )
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case RG_RAID: /* �T�v���C�Y�A�^�b�N */
if( rand()%100 < (10+3*skilllv)*sc_def_vit/100 )
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
if( rand()%100 < (10+3*skilllv)*sc_def_int/100 )
skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case BA_FROSTJOKE:
if(rand()%100 < (15+5*skilllv)*sc_def_mdef/100)
skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case DC_SCREAM:
if( rand()%100 < (25+5*skilllv)*sc_def_vit/100 )
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case BD_LULLABY: /* �q��S */
if( rand()%100 < 15*sc_def_int/100 )
skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
/* MOB�̒lj�?�ʕt���X�L�� */
case NPC_PETRIFYATTACK:
if(rand()%100 < sc_def_mdef)
skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_POISON:
case NPC_SILENCEATTACK:
case NPC_STUNATTACK:
if(rand()%100 < sc_def_vit && src->type!=BL_PET)
skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
if(src->type==BL_PET)
skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skilllv*1000,0);
break;
case NPC_CURSEATTACK:
if(rand()%100 < sc_def_luk)
skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_SLEEPATTACK:
case NPC_BLINDATTACK:
if(rand()%100 < sc_def_int)
skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_MENTALBREAKER:
if(dstsd) {
int sp = dstsd->status.max_sp*(10+skilllv)/100;
if(sp < 1) sp = 1;
pc_heal(dstsd,0,-sp);
}
break;
// -- moonsoul (adding status effect chance given to wizard aoe skills meteor and vermillion)
//
case WZ_METEOR:
if(rand()%100 < sc_def_vit)
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case WZ_VERMILION:
if(rand()%100 < sc_def_int)
skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
// -- moonsoul (stun ability of new champion skill tigerfist)
//
case CH_TIGERFIST:
if( rand()%100 < (10 + skilllv*10)*sc_def_vit/100 )
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case LK_SPIRALPIERCE:
if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 )
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case ST_REJECTSWORD: /* �t��?�W���O�g���b�v */
if( rand()%100 < (skilllv*15) )
skill_status_change_start(bl,SC_AUTOCOUNTER,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case PF_FOGWALL: /* �z?��?�N���X */
if( rand()%100 < 3*skilllv*sc_def_int/100 )
skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case LK_HEADCRUSH: /* �w�b�h�N���b�V�� */
{//?�����ǂ�������Ȃ��̂œK?��
int race=battle_get_race(bl);
if( !(battle_check_undead(race,battle_get_elem_type(bl)) || race == 6) && rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
skill_status_change_start(bl,SC_HEADCRUSH,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
break;
case LK_JOINTBEAT: /* �W���C���g�r?�g */
//?�����ǂ�������Ȃ��̂œK?��
if( rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
skill_status_change_start(bl,SC_JOINTBEAT,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case PF_SPIDERWEB: /* �X�p�C�_?�E�F�b�u */
{
if(bl->type == BL_MOB)
{
int sec=skill_get_time2(skillid,skilllv);
if(map[src->m].flag.pvp) //PvP�ł͍S�����Ԕ����H
sec = sec/2;
battle_stopwalking(bl,1);
skill_status_change_start(bl,SC_SPIDERWEB,skilllv,0,0,0,sec,0);
}
}
break;
case ASC_METEORASSAULT: /* ���e�I�A�T���g */
if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 ) //?�Ԉُ�͏ڍׂ�������Ȃ��̂œK?��
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
if( rand()%100 < (10+3*skilllv)*sc_def_int/100 )
skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case MO_EXTREMITYFIST: /* ���C���e���� */
//���C�����g����5���Ԏ��R���Ȃ��悤�ɂȂ�
skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0 );
break;
case HW_NAPALMVULCAN: /* �i�p?���o���J�� */
// skilllv*5%�̊m���Ŏ�
if (rand()%10000 < 5*skilllv*sc_def_luk)
skill_status_change_start(bl,SC_CURSE,7,0,0,0,skill_get_time2(NPC_CURSEATTACK,7),0);
break;
}
if(sd && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* �J?�h�ɂ��lj�?�� */
int i;
int sc_def_card=100;
for(i=SC_STONE;i<=SC_BLIND;i++){
//?�ۂ�?�Ԉُ�
if(i==SC_STONE || i==SC_FREEZE)
sc_def_card=sc_def_mdef;
else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE)
sc_def_card=sc_def_vit;
else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND)
sc_def_card=sc_def_int;
else if(i==SC_CURSE)
sc_def_card=sc_def_luk;
if(!sd->state.arrow_atk) {
if(rand()%10000 < (sd->addeff[i-SC_STONE])*sc_def_card/100 ){
if(battle_config.battle_log)
printf("PC %d skill_addeff: card�ɂ��ُ�?�� %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
}
}
else {
if(rand()%10000 < (sd->addeff[i-SC_STONE]+sd->arrow_addeff[i-SC_STONE])*sc_def_card/100 ){
if(battle_config.battle_log)
printf("PC %d skill_addeff: card�ɂ��ُ�?�� %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
}
}
//������?�Ԉُ�
if(i==SC_STONE || i==SC_FREEZE)
sc_def_card=sc_def_mdef2;
else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE)
sc_def_card=sc_def_vit2;
else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND)
sc_def_card=sc_def_int2;
else if(i==SC_CURSE)
sc_def_card=sc_def_luk2;
if(!sd->state.arrow_atk) {
if(rand()%10000 < (sd->addeff2[i-SC_STONE])*sc_def_card/100 ){
if(battle_config.battle_log)
printf("PC %d skill_addeff: card�ɂ��ُ�?�� %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
}
}
else {
if(rand()%10000 < (sd->addeff2[i-SC_STONE]+sd->arrow_addeff2[i-SC_STONE])*sc_def_card/100 ){
if(battle_config.battle_log)
printf("PC %d skill_addeff: card�ɂ��ُ�?�� %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
}
}
}
}
return 0;
}
/*=========================================================================
�X�L���U?�������?��
-------------------------------------------------------------------------*/
int skill_blown( struct block_list *src, struct block_list *target,int count)
{
int dx=0,dy=0,nx,ny;
int x=target->x,y=target->y;
int ret,prev_state=MS_IDLE;
int moveblock;
struct map_session_data *sd=NULL;
struct mob_data *md=NULL;
struct pet_data *pd=NULL;
struct skill_unit *su=NULL;
nullpo_retr(0, src);
nullpo_retr(0, target);
if(target->type==BL_PC){
nullpo_retr(0, sd=(struct map_session_data *)target);
}else if(target->type==BL_MOB){
nullpo_retr(0, md=(struct mob_data *)target);
}else if(target->type==BL_PET){
nullpo_retr(0, pd=(struct pet_data *)target);
}else if(target->type==BL_SKILL){
nullpo_retr(0, su=(struct skill_unit *)target);
}else return 0;
if(!(count&0x10000 && (sd||md||pd||su))){ /* �w��Ȃ��Ȃ�ʒu?�W������������߂� */
dx=target->x-src->x; dx=(dx>0)?1:((dx<0)?-1: 0);
dy=target->y-src->y; dy=(dy>0)?1:((dy<0)?-1: 0);
}
if(dx==0 && dy==0){
int dir=battle_get_dir(target);
if(dir>=0 && dir<8){
dx=-dirx[dir];
dy=-diry[dir];
}
}
ret=path_blownpos(target->m,x,y,dx,dy,count&0xffff);
nx=ret>>16;
ny=ret&0xffff;
moveblock=( x/BLOCK_SIZE != nx/BLOCK_SIZE || y/BLOCK_SIZE != ny/BLOCK_SIZE);
if(count&0x20000) {
battle_stopwalking(target,1);
if(sd){
sd->to_x=nx;
sd->to_y=ny;
sd->walktimer = 1;
clif_walkok(sd);
clif_movechar(sd);
}
else if(md) {
md->to_x=nx;
md->to_y=ny;
prev_state = md->state.state;
md->state.state = MS_WALK;
clif_fixmobpos(md);
}
else if(pd) {
pd->to_x=nx;
pd->to_y=ny;
prev_state = pd->state.state;
pd->state.state = MS_WALK;
clif_fixpetpos(pd);
}
}
else
battle_stopwalking(target,2);
dx = nx - x;
dy = ny - y;
if(sd) /* ?�ʊO�ɏo���̂ŏ��� */
map_foreachinmovearea(clif_pcoutsight,target->m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,dx,dy,0,sd);
else if(md)
map_foreachinmovearea(clif_moboutsight,target->m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,dx,dy,BL_PC,md);
else if(pd)
map_foreachinmovearea(clif_petoutsight,target->m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,dx,dy,BL_PC,pd);
if(su){
skill_unit_move_unit_group(su->group,target->m,dx,dy);
}else{
// struct status_change *sc_data=battle_get_sc_data(target);
if(moveblock) map_delblock(target);
target->x=nx;
target->y=ny;
if(moveblock) map_addblock(target);
/*�_���X���ɃG�t�F�N�g�͈ړ����Ȃ��炵��
if(sc_data && sc_data[SC_DANCING].timer!=-1){ //?�ۂ��_���X���Ȃ̂ŃG�t�F�N�g���ړ�
struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[SC_DANCING].val2;
if(sg)
skill_unit_move_unit_group(sg,target->m,dx,dy);
}
*/
}
if(sd) { /* ?��?�ɓ����Ă����̂ŕ\�� */
map_foreachinmovearea(clif_pcinsight,target->m,nx-AREA_SIZE,ny-AREA_SIZE,nx+AREA_SIZE,ny+AREA_SIZE,-dx,-dy,0,sd);
if(count&0x20000)
sd->walktimer = -1;
}
else if(md) {
map_foreachinmovearea(clif_mobinsight,target->m,nx-AREA_SIZE,ny-AREA_SIZE,nx+AREA_SIZE,ny+AREA_SIZE,-dx,-dy,BL_PC,md);
if(count&0x20000)
md->state.state = prev_state;
}
else if(pd) {
map_foreachinmovearea(clif_petinsight,target->m,nx-AREA_SIZE,ny-AREA_SIZE,nx+AREA_SIZE,ny+AREA_SIZE,-dx,-dy,BL_PC,pd);
if(count&0x20000)
pd->state.state = prev_state;
}
skill_unit_move(target,gettick(),(count&0xffff)+7); /* �X�L�����j�b�g�̔��� */
return 0;
}
/*
* =========================================================================
* �X�L���U??��?���܂Ƃ�
* flag��?���B16�i?
* 00XRTTff
* ff = magic�Ōv�Z�ɓn�����j
* TT = �p�P�b�g��type����(0�Ńf�t�H���g�j
* X = �p�P�b�g�̃X�L��Lv
* R = �\��iskill_area_sub�Ŏg�p����j
*-------------------------------------------------------------------------
*/
int skill_attack( int attack_type, struct block_list* src, struct block_list *dsrc,
struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag )
{
struct Damage dmg;
struct status_change *sc_data;
int type,lv,damage;
if(skilllv <= 0) return 0;
rdamage = 0;
nullpo_retr(0, src);
nullpo_retr(0, dsrc);
nullpo_retr(0, bl);
sc_data = battle_get_sc_data(bl);
//�������Ȃ����肱������
if(dsrc->m != bl->m) //?�ۂ������}�b�v�ɂ��Ȃ���Ή������Ȃ�
return 0;
if(src->prev == NULL || dsrc->prev == NULL || bl->prev == NULL) //prev�悭�킩��Ȃ���
return 0;
if(src->type == BL_PC && pc_isdead((struct map_session_data *)src)) //�p�ҁH��PC�ł��łɎ���ł����牽�����Ȃ�
return 0;
if(dsrc->type == BL_PC && pc_isdead((struct map_session_data *)dsrc)) //�p�ҁH��PC�ł��łɎ���ł����牽�����Ȃ�
return 0;
if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) //?�ۂ�PC�ł��łɎ���ł����牽�����Ȃ�
return 0;
if(bl->type == BL_PC && skillnotok(skillid, (struct map_session_data *) bl))
return 0; // [MouseJstr]
if(sc_data && sc_data[SC_HIDING].timer != -1) { //�n�C�f�B���O?�Ԃ�
if(skill_get_pl(skillid) != 2) //�X�L����?�����n?���łȂ���Ή������Ȃ�
return 0;
}
if(sc_data && sc_data[SC_TRICKDEAD].timer != -1) //���ӂ蒆�͉������Ȃ�
return 0;
if(skillid == WZ_STORMGUST) { //�g�p�X�L�����X�g?���K�X�g��
if(sc_data && sc_data[SC_FREEZE].timer != -1) //����?�ԂȂ牽�����Ȃ�
return 0;
}
if(skillid == WZ_FROSTNOVA && dsrc->x == bl->x && dsrc->y == bl->y) //�g�p�X�L�����t���X�g�m���@�ŁAdsrc��bl�������ꏊ�Ȃ牽�����Ȃ�
return 0;
if(src->type == BL_PC && ((struct map_session_data *)src)->chatID) //�p�҂�PC�Ń`���b�g���Ȃ牽�����Ȃ�
return 0;
if(dsrc->type == BL_PC && ((struct map_session_data *)dsrc)->chatID) //�p�҂�PC�Ń`���b�g���Ȃ牽�����Ȃ�
return 0;
if(src->type == BL_PC && bl && mob_gvmobcheck(((struct map_session_data *)src),bl)==0)
return 0;
//�������Ȃ����肱���܂�
type=-1;
lv=(flag>>20)&0xf;
dmg=battle_calc_attack(attack_type,src,bl,skillid,skilllv,flag&0xff ); //�_��?�W�v�Z
//�}�W�b�N���b�h?����������
if(attack_type&BF_MAGIC && sc_data && sc_data[SC_MAGICROD].timer != -1 && src == dsrc) { //���@�U?�Ń}�W�b�N���b�h?�Ԃ�src=dsrc�Ȃ�
dmg.damage = dmg.damage2 = 0; //�_��?�W0
if(bl->type == BL_PC) { //?�ۂ�PC�̏ꍇ
int sp = skill_get_sp(skillid,skilllv); //�g�p���ꂽ�X�L����SP���z?
sp = sp * sc_data[SC_MAGICROD].val2 / 100; //�z?���v�Z
if(skillid == WZ_WATERBALL && skilllv > 1) //�E�H?�^?�{?��Lv1�ȏ�
sp = sp/((skilllv|1)*(skilllv|1)); //����Ɍv�Z�H
if(sp > 0x7fff) sp = 0x7fff; //SP�������̏ꍇ�͗��_�ő�l
else if(sp < 1) sp = 1; //1�ȉ��̏ꍇ��1
if(((struct map_session_data *)bl)->status.sp + sp > ((struct map_session_data *)bl)->status.max_sp) { //��SP+���݂�SP��MSP���傫���ꍇ
sp = ((struct map_session_data *)bl)->status.max_sp - ((struct map_session_data *)bl)->status.sp; //SP��MSP-����SP�ɂ���
((struct map_session_data *)bl)->status.sp = ((struct map_session_data *)bl)->status.max_sp; //���݂�SP��MSP����
}
else //��SP+���݂�SP��MSP��菬�����ꍇ�͉�SP�����Z
((struct map_session_data *)bl)->status.sp += sp;
clif_heal(((struct map_session_data *)bl)->fd,SP_SP,sp); //SP�G�t�F�N�g�̕\��
((struct map_session_data *)bl)->canact_tick = tick + skill_delayfix(bl, skill_get_delay(SA_MAGICROD,sc_data[SC_MAGICROD].val1)); //
}
clif_skill_nodamage(bl,bl,SA_MAGICROD,sc_data[SC_MAGICROD].val1,1); //�}�W�b�N���b�h�G�t�F�N�g��\��
}
//�}�W�b�N���b�h?�������܂�
if(src->type==BL_PET) { // [Valaris]
dmg.damage=battle_attr_fix(skilllv, skill_get_pl(skillid), battle_get_element(bl) );
dmg.damage2=0;
}
damage = dmg.damage + dmg.damage2;
if(lv==15)
lv=-1;
if( flag&0xff00 )
type=(flag&0xff00)>>8;
if(damage <= 0 || damage < dmg.div_) //�����������H��
dmg.blewcount = 0;
if(skillid == CR_GRANDCROSS) {//�O�����h�N���X
if(battle_config.gx_disptype) dsrc = src; // �G�_��?�W�������\��
if( src == bl) type = 4; // �����̓_��?�W��?�V�����Ȃ�
}
//�g�p�҂�PC�̏ꍇ��?����������
if(src->type == BL_PC) {
struct map_session_data *sd = (struct map_session_data *)src;
nullpo_retr(0, sd);
//�A�ŏ�(MO_CHAINCOMBO)��������
if(skillid == MO_CHAINCOMBO) {
int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); //��{�f�B���C�̌v�Z
if(damage < battle_get_hp(bl)) { //�_��?�W��?�ۂ�HP��菬�����ꍇ
if(pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0) //�җ���(MO_COMBOFINISH)�擾��?���ێ�����+300ms
delay += 300 * battle_config.combo_delay_rate /100; //�lj��f�B���C��conf�ɂ�蒲��
skill_status_change_start(src,SC_COMBO,MO_CHAINCOMBO,skilllv,0,0,delay,0); //�R���{?�Ԃ�
}
sd->attackabletime = sd->canmove_tick = tick + delay;
clif_combo_delay(src,delay); //�R���{�f�B���C�p�P�b�g�̑��M
}
//�A�ŏ�(MO_CHAINCOMBO)�����܂�
//�җ���(MO_COMBOFINISH)��������
else if(skillid == MO_COMBOFINISH) {
int delay = 700 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src);
if(damage < battle_get_hp(bl)) {
//���C���e����(MO_EXTREMITYFIST)�擾��?��4�ێ��������g��(MO_EXPLOSIONSPIRITS)?�Ԏ���+300ms
//���Ռ�(CH_TIGERFIST)�擾����+300ms
if((pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 4 && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1) ||
(pc_checkskill(sd, CH_TIGERFIST) > 0 && sd->spiritball > 0) ||
(pc_checkskill(sd, CH_CHAINCRUSH) > 0 && sd->spiritball > 1))
delay += 300 * battle_config.combo_delay_rate /100; //�lj��f�B���C��conf�ɂ�蒲��
skill_status_change_start(src,SC_COMBO,MO_COMBOFINISH,skilllv,0,0,delay,0); //�R���{?�Ԃ�
}
sd->attackabletime = sd->canmove_tick = tick + delay;
clif_combo_delay(src,delay); //�R���{�f�B���C�p�P�b�g�̑��M
}
//�җ���(MO_COMBOFINISH)�����܂�
//���Ռ�(CH_TIGERFIST)��������
else if(skillid == CH_TIGERFIST) {
int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src);
if(damage < battle_get_hp(bl)) {
if(pc_checkskill(sd, CH_CHAINCRUSH) > 0) //�A����?(CH_CHAINCRUSH)�擾����+300ms
delay += 300 * battle_config.combo_delay_rate /100; //�lj��f�B���C��conf�ɂ�蒲��
skill_status_change_start(src,SC_COMBO,CH_TIGERFIST,skilllv,0,0,delay,0); //�R���{?�Ԃ�
}
sd->attackabletime = sd->canmove_tick = tick + delay;
clif_combo_delay(src,delay); //�R���{�f�B���C�p�P�b�g�̑��M
}
//���Ռ�(CH_TIGERFIST)�����܂�
//�A����?(CH_CHAINCRUSH)��������
else if(skillid == CH_CHAINCRUSH) {
int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src);
if(damage < battle_get_hp(bl)) {
//���C���e����(MO_EXTREMITYFIST)�擾��?��4�ێ��������g��(MO_EXPLOSIONSPIRITS)?�Ԏ���+300ms
if(pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 4 && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1)
delay += 300 * battle_config.combo_delay_rate /100; //�lj��f�B���C��conf�ɂ�蒲��
skill_status_change_start(src,SC_COMBO,CH_CHAINCRUSH,skilllv,0,0,delay,0); //�R���{?�Ԃ�
}
sd->attackabletime = sd->canmove_tick = tick + delay;
clif_combo_delay(src,delay); //�R���{�f�B���C�p�P�b�g�̑��M
}
//�A����?(CH_CHAINCRUSH)�����܂�
}
//�g�p�҂�PC�̏ꍇ��?�������܂�
//����X�L���H��������
//AppleGirl Was Here
if(attack_type&BF_MAGIC && damage > 0 && src != bl && src == dsrc) { //Blah Blah
if(bl->type == BL_PC) { //Blah Blah
struct map_session_data *tsd = (struct map_session_data *)bl;
if(tsd->magic_damage_return > 0) { //More Blah
rdamage += damage * tsd->magic_damage_return / 100;
if(rdamage < 1) rdamage = 1;
}
}
}
//Stop Here
if(attack_type&BF_WEAPON && damage > 0 && src != bl && src == dsrc) { //����X�L�����_��?�W���聕�g�p�҂�?�ێ҂��Ⴄ��src=dsrc
if(dmg.flag&BF_SHORT) { //�ߋ����U?���H��
if(bl->type == BL_PC) { //?�ۂ�PC�̎�
struct map_session_data *tsd = (struct map_session_data *)bl;
nullpo_retr(0, tsd);
if(tsd->short_weapon_damage_return > 0) { //�ߋ����U?���˕Ԃ��H��
rdamage += damage * tsd->short_weapon_damage_return / 100;
if(rdamage < 1) rdamage = 1;
}
}
if(sc_data && sc_data[SC_REFLECTSHIELD].timer != -1) { //���t���N�g�V?���h��
rdamage += damage * sc_data[SC_REFLECTSHIELD].val2 / 100; //���˕Ԃ��v�Z
if(rdamage < 1) rdamage = 1;
}
}
else if(dmg.flag&BF_LONG) { //�������U?���H��
if(bl->type == BL_PC) { //?�ۂ�PC�̎�
struct map_session_data *tsd = (struct map_session_data *)bl;
nullpo_retr(0, tsd);
if(tsd->long_weapon_damage_return > 0) { //�������U?���˕Ԃ��H��
rdamage += damage * tsd->long_weapon_damage_return / 100;
if(rdamage < 1) rdamage = 1;
}
}
}
if(rdamage > 0)
clif_damage(src,src,tick, dmg.amotion,0,rdamage,1,4,0);
}
//����X�L���H�����܂�
switch(skillid){
case WZ_SIGHTRASHER:
clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, 5);
break;
case AS_SPLASHER:
clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, -1, 5);
break;
case NPC_SELFDESTRUCTION:
case NPC_SELFDESTRUCTION2:
break;
default:
clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, (skillid==0)? 5:type );
}
if(dmg.blewcount > 0 && !map[src->m].flag.gvg) { /* �������?���Ƃ��̃p�P�b�g */
if(skillid == WZ_SIGHTRASHER)
skill_blown(src,bl,dmg.blewcount);
else
skill_blown(dsrc,bl,dmg.blewcount);
if(bl->type == BL_MOB)
clif_fixmobpos((struct mob_data *)bl);
else if(bl->type == BL_PET)
clif_fixpetpos((struct pet_data *)bl);
else
clif_fixpos(bl);
}
map_freeblock_lock();
/* ?�ۂɃ_��?�W?�����s�� */
if(skillid != KN_BOWLINGBASH || flag)
battle_damage(src,bl,damage,0);
if(skillid == RG_INTIMIDATE && damage > 0 && !(battle_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) {
int s_lv = battle_get_lv(src),t_lv = battle_get_lv(bl);
int rate = 50 + skilllv * 5;
rate = rate + (s_lv - t_lv);
if(rand()%100 < rate)
skill_addtimerskill(src,tick + 800,bl->id,0,0,skillid,skilllv,0,flag);
}
if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM) && sc_data[SC_PRESERVE].timer != -1){
struct map_session_data *tsd = (struct map_session_data *)bl;
nullpo_retr(0, tsd);
if(!tsd->status.skill[skillid].id && !tsd->status.skill[skillid].id
&& !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER) ){
//?��?��ł���X�L��������ΊY?�X�L��������
if (tsd->cloneskill_id && tsd->cloneskill_lv && tsd->status.skill[tsd->cloneskill_id].flag==13){
tsd->status.skill[tsd->cloneskill_id].id=0;
tsd->status.skill[tsd->cloneskill_id].lv=0;
tsd->status.skill[tsd->cloneskill_id].flag=0;
}
tsd->cloneskill_id=skillid;
tsd->cloneskill_lv=skilllv;
tsd->status.skill[skillid].id=skillid;
tsd->status.skill[skillid].lv=(pc_checkskill(tsd,RG_PLAGIARISM) > skill_get_max(skillid))?
skill_get_max(skillid):pc_checkskill(tsd,RG_PLAGIARISM);
tsd->status.skill[skillid].flag=13;//cloneskill flag
clif_skillinfoblock(tsd);
}
}
/* �_��?�W������Ȃ�lj�?�ʔ��� */
if(bl->prev != NULL){
struct map_session_data *sd = (struct map_session_data *)bl;
nullpo_retr(0, sd);
if( bl->type != BL_PC || (sd && !pc_isdead(sd)) ) {
if(damage > 0)
skill_additional_effect(src,bl,skillid,skilllv,attack_type,tick);
if(bl->type==BL_MOB && src!=bl) /* �X�L���g�p?����MOB�X�L�� */
{
struct mob_data *md=(struct mob_data *)bl;
nullpo_retr(0, md);
if(battle_config.mob_changetarget_byskill == 1)
{
int target;
target=md->target_id;
if(src->type == BL_PC)
md->target_id=src->id;
mobskill_use(md,tick,MSC_SKILLUSED|(skillid<<16));
md->target_id=target;
}
else
mobskill_use(md,tick,MSC_SKILLUSED|(skillid<<16));
}
}
}
if(src->type == BL_PC && dmg.flag&BF_WEAPON && src != bl && src == dsrc && damage > 0) {
struct map_session_data *sd = (struct map_session_data *)src;
int hp = 0,sp = 0;
nullpo_retr(0, sd);
if(sd->hp_drain_rate && sd->hp_drain_per > 0 && dmg.damage > 0 && rand()%100 < sd->hp_drain_rate) {
hp += (dmg.damage * sd->hp_drain_per)/100;
if(sd->hp_drain_rate > 0 && hp < 1) hp = 1;
else if(sd->hp_drain_rate < 0 && hp > -1) hp = -1;
}
if(sd->hp_drain_rate_ && sd->hp_drain_per_ > 0 && dmg.damage2 > 0 && rand()%100 < sd->hp_drain_rate_) {
hp += (dmg.damage2 * sd->hp_drain_per_)/100;
if(sd->hp_drain_rate_ > 0 && hp < 1) hp = 1;
else if(sd->hp_drain_rate_ < 0 && hp > -1) hp = -1;
}
if(sd->sp_drain_rate > 0 && sd->sp_drain_per > 0 && dmg.damage > 0 && rand()%100 < sd->sp_drain_rate) {
sp += (dmg.damage * sd->sp_drain_per)/100;
if(sd->sp_drain_rate > 0 && sp < 1) sp = 1;
else if(sd->sp_drain_rate < 0 && sp > -1) sp = -1;
}
if(sd->sp_drain_rate_ > 0 && sd->sp_drain_per_ > 0 && dmg.damage2 > 0 && rand()%100 < sd->sp_drain_rate_) {
sp += (dmg.damage2 * sd->sp_drain_per_)/100;
if(sd->sp_drain_rate_ > 0 && sp < 1) sp = 1;
else if(sd->sp_drain_rate_ < 0 && sp > -1) sp = -1;
}
if(hp || sp) pc_heal(sd,hp,sp);
}
if((skillid != KN_BOWLINGBASH || flag) && rdamage > 0)
battle_damage(bl,src,rdamage,0);
if(attack_type&BF_WEAPON && sc_data && sc_data[SC_AUTOCOUNTER].timer != -1 && sc_data[SC_AUTOCOUNTER].val4 > 0) {
if(sc_data[SC_AUTOCOUNTER].val3 == dsrc->id)
battle_weapon_attack(bl,dsrc,tick,0x8000|sc_data[SC_AUTOCOUNTER].val1);
skill_status_change_end(bl,SC_AUTOCOUNTER,-1);
}
map_freeblock_unlock();
return (dmg.damage+dmg.damage2); /* ?�_����Ԃ� */
}
/*==========================================
* �X�L����?�U?�p(map_foreachinarea������)
* flag�ɂ��āF16�i?���m�F
* MSB <- 00fTffff ->LSB
* T =�^?�Q�b�g�I?�p(BCT_*)
* ffff=���R�Ɏg�p�\
* 0 =�\��B0�ɌŒ�
*------------------------------------------
*/
static int skill_area_temp[8]; /* �ꎞ??�B�K�v�Ȃ�g���B */
typedef int (*SkillFunc)(struct block_list *,struct block_list *,int,int,unsigned int,int);
int skill_area_sub( struct block_list *bl,va_list ap )
{
struct block_list *src;
int skill_id,skill_lv,flag;
unsigned int tick;
SkillFunc func;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
if(bl->type!=BL_PC && bl->type!=BL_MOB && bl->type!=BL_SKILL)
return 0;
src=va_arg(ap,struct block_list *); //�����ł�src�̒l��?�Ƃ��Ă��Ȃ��̂�NULL�`�F�b�N�͂��Ȃ�
skill_id=va_arg(ap,int);
skill_lv=va_arg(ap,int);
tick=va_arg(ap,unsigned int);
flag=va_arg(ap,int);
func=va_arg(ap,SkillFunc);
if(battle_check_target(src,bl,flag) > 0)
func(src,bl,skill_id,skill_lv,tick,flag);
return 0;
}
static int skill_check_unit_range_sub( struct block_list *bl,va_list ap )
{
struct skill_unit *unit;
int *c,x,y,range,sx[4],sy[4];
int t_range,tx[4],ty[4];
int i,r_flag,skillid;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, unit = (struct skill_unit *)bl);
nullpo_retr(0, c = va_arg(ap,int *));
if(bl->prev == NULL || bl->type != BL_SKILL)
return 0;
if(!unit->alive)
return 0;
x = va_arg(ap,int);
y = va_arg(ap,int);
range = va_arg(ap,int);
skillid = va_arg(ap,int);
if(skillid == MG_SAFETYWALL || skillid == AL_PNEUMA) {
if(unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85)
return 0;
}
else if(skillid == AL_WARP) {
if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92)
return 0;
}
else if((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP) || skillid == HT_TALKIEBOX) {
if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92)
return 0;
}
else if(skillid == WZ_FIREPILLAR) {
if(unit->group->unit_id != 0x87)
return 0;
}
else return 0;
t_range=(unit->range!=0)? unit->range:unit->group->range;
tx[0] = tx[3] = unit->bl.x - t_range;
tx[1] = tx[2] = unit->bl.x + t_range;
ty[0] = ty[1] = unit->bl.y - t_range;
ty[2] = ty[3] = unit->bl.y + t_range;
sx[0] = sx[3] = x - range;
sx[1] = sx[2] = x + range;
sy[0] = sy[1] = y - range;
sy[2] = sy[3] = y + range;
for(i=r_flag=0;i<4;i++) {
if(sx[i] >= tx[0] && sx[i] <= tx[1] && sy[i] >= ty[0] && sy[i] <= ty[2]) {
r_flag = 1;
break;
}
if(tx[i] >= sx[0] && tx[i] <= sx[1] && ty[i] >= sy[0] && ty[i] <= sy[2]) {
r_flag = 1;
break;
}
}
if(r_flag) (*c)++;
return 0;
}
int skill_check_unit_range(int m,int x,int y,int range,int skillid)
{
int c = 0;
map_foreachinarea(skill_check_unit_range_sub,m,x-10,y-10,x+10,y+10,BL_SKILL,&c,x,y,range,skillid);
return c;
}
static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap )
{
int *c;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, c = va_arg(ap,int *));
if(bl->prev == NULL || (bl->type != BL_PC && bl->type != BL_MOB))
return 0;
if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))
return 0;
(*c)++;
return 0;
}
int skill_check_unit_range2(int m,int x,int y,int range)
{
int c = 0;
map_foreachinarea(skill_check_unit_range2_sub,m,x-range,y-range,x+range,y+range,0,&c);
return c;
}
/*=========================================================================
* ��?�X�L���g�p?����������������
*/
/* ?�ۂ�?���J�E���g����B�iskill_area_temp[0]�����������Ă������Ɓj */
int skill_area_sub_count(struct block_list *src,struct block_list *target,int skillid,int skilllv,unsigned int tick,int flag)
{
if(skilllv <= 0) return 0;
if(skill_area_temp[0] < 0xffff)
skill_area_temp[0]++;
return 0;
}
/*==========================================
*
*------------------------------------------
*/
static int skill_timerskill(int tid, unsigned int tick, int id,int data )
{
struct map_session_data *sd = NULL;
struct mob_data *md = NULL;
struct pet_data *pd = NULL;
struct block_list *src = map_id2bl(id),*target;
struct skill_timerskill *skl = NULL;
int range;
nullpo_retr(0, src);
if(src->prev == NULL)
return 0;
if(src->type == BL_PC) {
nullpo_retr(0, sd = (struct map_session_data *)src);
skl = &sd->skilltimerskill[data];
}
else if(src->type == BL_MOB) {
nullpo_retr(0, md = (struct mob_data *)src);
skl = &md->skilltimerskill[data];
}
else if(src->type == BL_PET) { // [Valaris]
nullpo_retr(0, pd = (struct pet_data *)src);
skl = &pd->skilltimerskill[data];
}
else
return 0;
nullpo_retr(0, skl);
skl->timer = -1;
if(skl->target_id) {
struct block_list tbl;
target = map_id2bl(skl->target_id);
if(skl->skill_id == RG_INTIMIDATE) {
if(target == NULL) {
target = &tbl; //���������ĂȂ��̂ɃA�h���X�˂�?��ł����̂��ȁH
target->type = BL_NUL;
target->m = src->m;
target->prev = target->next = NULL;
}
}
if(target == NULL)
return 0;
if(target->prev == NULL && skl->skill_id != RG_INTIMIDATE)
return 0;
if(src->m != target->m)
return 0;
if(sd && pc_isdead(sd))
return 0;
if(target->type == BL_PC && pc_isdead((struct map_session_data *)target) && skl->skill_id != RG_INTIMIDATE)
return 0;
switch(skl->skill_id) {
case TF_BACKSLIDING:
clif_skill_nodamage(src,src,skl->skill_id,skl->skill_lv,1);
break;
case RG_INTIMIDATE:
if(sd && !map[src->m].flag.noteleport) {
int x,y,i,j,c;
pc_randomwarp(sd,3);
for(i=0;i<16;i++) {
j = rand()%8;
x = sd->bl.x + dirx[j];
y = sd->bl.y + diry[j];
if((c=map_getcell(sd->bl.m,x,y)) != 1 && c != 5)
break;
}
if(i >= 16) {
x = sd->bl.x;
y = sd->bl.y;
}
if(target->prev != NULL) {
if(target->type == BL_PC && !pc_isdead((struct map_session_data *)target))
pc_setpos((struct map_session_data *)target,map[sd->bl.m].name,x,y,3);
else if(target->type == BL_MOB)
mob_warp((struct mob_data *)target,-1,x,y,3);
}
}
else if(md && !map[src->m].flag.monster_noteleport) {
int x,y,i,j,c;
mob_warp(md,-1,-1,-1,3);
for(i=0;i<16;i++) {
j = rand()%8;
x = md->bl.x + dirx[j];
y = md->bl.y + diry[j];
if((c=map_getcell(md->bl.m,x,y)) != 1 && c != 5)
break;
}
if(i >= 16) {
x = md->bl.x;
y = md->bl.y;
}
if(target->prev != NULL) {
if(target->type == BL_PC && !pc_isdead((struct map_session_data *)target))
pc_setpos((struct map_session_data *)target,map[md->bl.m].name,x,y,3);
else if(target->type == BL_MOB)
mob_warp((struct mob_data *)target,-1,x,y,3);
}
}
break;
case BA_FROSTJOKE: /* �����W��?�N */
case DC_SCREAM: /* �X�N��?�� */
range=15; //���E�S?
map_foreachinarea(skill_frostjoke_scream,src->m,src->x-range,src->y-range,
src->x+range,src->y+range,0,src,skl->skill_id,skl->skill_lv,tick);
break;
default:
skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
break;
}
}
else {
if(src->m != skl->map)
return 0;
switch(skl->skill_id) {
case WZ_METEOR:
if(skl->type >= 0) {
skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->type>>16,skl->type&0xFFFF,0);
clif_skill_poseffect(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,tick);
}
else
skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,0);
break;
}
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int skill_addtimerskill(struct block_list *src,unsigned int tick,int target,int x,int y,int skill_id,int skill_lv,int type,int flag)
{
int i;
nullpo_retr(1, src);
if(src->type == BL_PC) {
struct map_session_data *sd = (struct map_session_data *)src;
nullpo_retr(1, sd);
for(i=0;i<MAX_SKILLTIMERSKILL;i++) {
if(sd->skilltimerskill[i].timer == -1) {
sd->skilltimerskill[i].timer = add_timer(tick, skill_timerskill, src->id, i);
sd->skilltimerskill[i].src_id = src->id;
sd->skilltimerskill[i].target_id = target;
sd->skilltimerskill[i].skill_id = skill_id;
sd->skilltimerskill[i].skill_lv = skill_lv;
sd->skilltimerskill[i].map = src->m;
sd->skilltimerskill[i].x = x;
sd->skilltimerskill[i].y = y;
sd->skilltimerskill[i].type = type;
sd->skilltimerskill[i].flag = flag;
return 0;
}
}
return 1;
}
else if(src->type == BL_MOB) {
struct mob_data *md = (struct mob_data *)src;
nullpo_retr(1, md);
for(i=0;i<MAX_MOBSKILLTIMERSKILL;i++) {
if(md->skilltimerskill[i].timer == -1) {
md->skilltimerskill[i].timer = add_timer(tick, skill_timerskill, src->id, i);
md->skilltimerskill[i].src_id = src->id;
md->skilltimerskill[i].target_id = target;
md->skilltimerskill[i].skill_id = skill_id;
md->skilltimerskill[i].skill_lv = skill_lv;
md->skilltimerskill[i].map = src->m;
md->skilltimerskill[i].x = x;
md->skilltimerskill[i].y = y;
md->skilltimerskill[i].type = type;
md->skilltimerskill[i].flag = flag;
return 0;
}
}
return 1;
}
else if(src->type == BL_PET) { // [Valaris]
struct pet_data *pd = (struct pet_data *)src;
nullpo_retr(1, pd);
for(i=0;i<MAX_MOBSKILLTIMERSKILL;i++) {
if(pd->skilltimerskill[i].timer == -1) {
pd->skilltimerskill[i].timer = add_timer(tick, skill_timerskill, src->id, i);
pd->skilltimerskill[i].src_id = src->id;
pd->skilltimerskill[i].target_id = target;
pd->skilltimerskill[i].skill_id = skill_id;
pd->skilltimerskill[i].skill_lv = skill_lv;
pd->skilltimerskill[i].map = src->m;
pd->skilltimerskill[i].x = x;
pd->skilltimerskill[i].y = y;
pd->skilltimerskill[i].type = type;
pd->skilltimerskill[i].flag = flag;
return 0;
}
}
return 1;
}
return 1;
}
/*==========================================
*
*------------------------------------------
*/
int skill_cleartimerskill(struct block_list *src)
{
int i;
nullpo_retr(0, src);
if(src->type == BL_PC) {
struct map_session_data *sd = (struct map_session_data *)src;
nullpo_retr(0, sd);
for(i=0;i<MAX_SKILLTIMERSKILL;i++) {
if(sd->skilltimerskill[i].timer != -1) {
delete_timer(sd->skilltimerskill[i].timer, skill_timerskill);
sd->skilltimerskill[i].timer = -1;
}
}
}
else if(src->type == BL_MOB) {
struct mob_data *md = (struct mob_data *)src;
nullpo_retr(0, md);
for(i=0;i<MAX_MOBSKILLTIMERSKILL;i++) {
if(md->skilltimerskill[i].timer != -1) {
delete_timer(md->skilltimerskill[i].timer, skill_timerskill);
md->skilltimerskill[i].timer = -1;
}
}
}
return 0;
}
/* ��?�X�L���g�p?�������������܂�
* -------------------------------------------------------------------------
*/
/*==========================================
* �X�L���g�p�i�r�������AID�w��U?�n�j
* �i�X�p�Q�b�e�B�Ɍ����ĂP?�O�i�I(�_���|)�j
*------------------------------------------
*/
int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag )
{
struct map_session_data *sd=NULL;
struct status_change *sc_data = battle_get_sc_data(src);
int i;
if(skilllv <= 0) return 0;
nullpo_retr(1, src);
nullpo_retr(1, bl);
if(src->type==BL_PC)
sd=(struct map_session_data *)src;
if(sd && pc_isdead(sd))
return 1;
if((skillid == WZ_SIGHTRASHER || skillid == CR_GRANDCROSS) && src != bl)
bl = src;
if(bl->prev == NULL)
return 1;
if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))
return 1;
map_freeblock_lock();
switch(skillid)
{
/* ����U?�n�X�L�� */
case SM_BASH: /* �o�b�V�� */
case MC_MAMMONITE: /* ���}?�i�C�g */
case AC_DOUBLE: /* �_�u���X�g���C�t�B���O */
case AS_SONICBLOW: /* �\�j�b�N�u��? */
case KN_PIERCE: /* �s�A?�X */
case KN_SPEARBOOMERANG: /* �X�s�A�u?������ */
case TF_POISON: /* �C���x�i�� */
case TF_SPRINKLESAND: /* ���܂� */
case AC_CHARGEARROW: /* �`��?�W�A��? */
case KN_SPEARSTAB: /* �X�s�A�X�^�u */
case RG_RAID: /* �T�v���C�Y�A�^�b�N */
case RG_INTIMIDATE: /* �C���e�B�~�f�C�g */
case BA_MUSICALSTRIKE: /* �~��?�W�J���X�g���C�N */
case DC_THROWARROW: /* ��?�� */
case BA_DISSONANCE: /* �s���a�� */
case CR_HOLYCROSS: /* �z?��?�N���X */
case CR_SHIELDCHARGE:
case CR_SHIELDBOOMERANG:
/* �ȉ�MOB?�p */
/* ??�U?�ASP�����U?�A�������U?�A�h�䖳���U?�A���i�U? */
case NPC_PIERCINGATT:
case NPC_MENTALBREAKER:
case NPC_RANGEATTACK:
case NPC_CRITICALSLASH:
case NPC_COMBOATTACK:
/* �K���U?�A�ōU?�A��?�U?�A��?�U?�A�X�^���U? */
case NPC_GUIDEDATTACK:
case NPC_POISON:
case NPC_BLINDATTACK:
case NPC_SILENCEATTACK:
case NPC_STUNATTACK:
/* �Ή��U?�A�U?�A�����U?�A�����_��ATK�U? */
case NPC_PETRIFYATTACK:
case NPC_CURSEATTACK:
case NPC_SLEEPATTACK:
case NPC_RANDOMATTACK:
/* ��?���U?�A�n?���U?�A��?���U?�A��?���U? */
case NPC_WATERATTACK:
case NPC_GROUNDATTACK:
case NPC_FIREATTACK:
case NPC_WINDATTACK:
/* ��?���U?�A��?���U?�A��?���U?�A�O?���U?�ASP�����U? */
case NPC_POISONATTACK:
case NPC_HOLYATTACK:
case NPC_DARKNESSATTACK:
case NPC_TELEKINESISATTACK:
case LK_AURABLADE: /* �I?���u��?�h */
case LK_SPIRALPIERCE: /* �X�p�C�����s�A?�X */
case LK_HEADCRUSH: /* �w�b�h�N���b�V�� */
case LK_JOINTBEAT: /* �W���C���g�r?�g */
case PA_PRESSURE: /* �v���b�V��? */
case PA_SACRIFICE: /* �T�N���t�@�C�X */
case SN_SHARPSHOOTING: /* �V��?�v�V��?�e�B���O */
case CG_ARROWVULCAN: /* �A��?�o���J�� */
case ASC_BREAKER: /* �\�E���u��?�J? */
case HW_MAGICCRASHER: /* �}�W�b�N�N���b�V��? */
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
break;
case NPC_DARKBREATH:
clif_emotion(src,7);
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
break;
case MO_INVESTIGATE: /* ?�� */
{
struct status_change *sc_data = battle_get_sc_data(src);
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
if(sc_data[SC_BLADESTOP].timer != -1)
skill_status_change_end(src,SC_BLADESTOP,-1);
}
break;
case SN_FALCONASSAULT: /* �t�@���R���A�T���g */
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
break;
case KN_BRANDISHSPEAR: /* �u�����f�B�b�V���X�s�A */
{
struct mob_data *md = (struct mob_data *)bl;
nullpo_retr(1, md);
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
if(md->hp > 0){
skill_blown(src,bl,skill_get_blewcount(skillid,skilllv));
if(bl->type == BL_MOB)
clif_fixmobpos((struct mob_data *)bl);
else if(bl->type == BL_PET)
clif_fixpetpos((struct pet_data *)bl);
else
clif_fixpos(bl);
}
}
break;
case RG_BACKSTAP: /* �o�b�N�X�^�u */
{
int dir = map_calc_dir(src,bl->x,bl->y),t_dir = battle_get_dir(bl);
int dist = distance(src->x,src->y,bl->x,bl->y);
if((dist > 0 && !map_check_dir(dir,t_dir)) || bl->type == BL_SKILL) {
struct status_change *sc_data = battle_get_sc_data(src);
if(sc_data && sc_data[SC_HIDING].timer != -1)
skill_status_change_end(src, SC_HIDING, -1); // �n�C�f�B���O����
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest]
if (bl->type == BL_PC)
((struct map_session_data *)bl)->dir=dir;
else if (bl->type == BL_MOB)
((struct mob_data *)bl)->dir=dir;
//skill_blown(src,bl,skill_get_blewcount(skillid,skilllv));
}
else if(src->type == BL_PC)
clif_skill_fail(sd,sd->skillid,0,0);
}
break;
case AM_ACIDTERROR: /* �A�V�b�h�e��? */
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
if(bl->type == BL_PC && rand()%100 < skill_get_time(skillid,skilllv) && battle_config.equipment_breaking)
pc_breakarmor((struct map_session_data *)bl);
break;
case MO_FINGEROFFENSIVE: /* �w? */
{
struct status_change *sc_data = battle_get_sc_data(src);
if(!battle_config.finger_offensive_type)
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
else {
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
if(sd) {
for(i=1;i<sd->spiritball_old;i++)
skill_addtimerskill(src,tick+i*200,bl->id,0,0,skillid,skilllv,BF_WEAPON,flag);
sd->canmove_tick = tick + (sd->spiritball_old-1)*200;
}
}
if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
skill_status_change_end(src,SC_BLADESTOP,-1);
}
break;
case MO_CHAINCOMBO: /* �A�ŏ� */
{
struct status_change *sc_data = battle_get_sc_data(src);
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
skill_status_change_end(src,SC_BLADESTOP,-1);
}
break;
case MO_COMBOFINISH: /* �җ��� */
case CH_TIGERFIST: /* ���Ռ� */
case CH_CHAINCRUSH: /* �A����? */
case CH_PALMSTRIKE: /* �ҌՍd�h�R */
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
break;
case MO_EXTREMITYFIST: /* ���C���e�P�� */
{
struct status_change *sc_data = battle_get_sc_data(src);
if(sd) {
struct walkpath_data wpd;
int dx,dy;
dx = bl->x - sd->bl.x;
dy = bl->y - sd->bl.y;
if(dx > 0) dx++;
else if(dx < 0) dx--;
if(dy > 0) dy++;
else if(dy < 0) dy--;
if(dx == 0 && dy == 0) dx++;
if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
dx = bl->x - sd->bl.x;
dy = bl->y - sd->bl.y;
if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
clif_skill_fail(sd,sd->skillid,0,0);
break;
}
}
sd->to_x = sd->bl.x + dx;
sd->to_y = sd->bl.y + dy;
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
clif_walkok(sd);
clif_movechar(sd);
if(dx < 0) dx = -dx;
if(dy < 0) dy = -dy;
sd->attackabletime = sd->canmove_tick = tick + 100 + sd->speed * ((dx > dy)? dx:dy);
if(sd->canact_tick < sd->canmove_tick)
sd->canact_tick = sd->canmove_tick;
pc_movepos(sd,sd->to_x,sd->to_y);
skill_status_change_end(&sd->bl,SC_COMBO,-1);
}
else
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
skill_status_change_end(src, SC_EXPLOSIONSPIRITS, -1);
if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
skill_status_change_end(src,SC_BLADESTOP,-1);
}
break;
/* ����n��?�U?�X�L�� */
case AC_SHOWER: /* �A��?�V����? */
case SM_MAGNUM: /* �}�O�i���u���C�N */
case AS_GRIMTOOTH: /* �O�����g�D?�X */
case MC_CARTREVOLUTION: /* �J?�g�����H����?�V���� */
case NPC_SPLASHATTACK: /* �X�v���b�V���A�^�b�N */
case ASC_METEORASSAULT: /* ���e�I�A�T���g */
case AS_SPLASHER: /* [Valaris] */
if(flag&1){
/* �ʂɃ_��?�W��?���� */
if(bl->id!=skill_area_temp[1]){
int dist=0;
if(skillid==SM_MAGNUM){ /* �}�O�i���u���C�N�Ȃ璆�S����̋������v�Z */
int dx=abs( bl->x - skill_area_temp[2] );
int dy=abs( bl->y - skill_area_temp[3] );
dist=((dx>dy)?dx:dy);
}
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,
0x0500|dist );
}
}else{
int ar=1;
int x=bl->x,y=bl->y;
if( skillid==SM_MAGNUM){
x=src->x;
y=src->y;
}else if(skillid==AC_SHOWER || skillid==ASC_METEORASSAULT) /* �A��?�V����?�A���e�I�A�T���g��?5*5 */
ar=2;
else if(skillid==AS_SPLASHER) /* �x�i���X�v���b�V��?��?3*3 */
ar=1;
else if(skillid==NPC_SPLASHATTACK) /* �X�v���b�V���A�^�b�N�͔�?7*7 */
ar=3;
// meteor assault cast effect (not sure how else to properly add it =p) [Celest]
if (skillid == ASC_METEORASSAULT)
clif_specialeffect(&sd->bl,409, 1);
skill_area_temp[1]=bl->id;
skill_area_temp[2]=x;
skill_area_temp[3]=y;
/* �܂��^?�Q�b�g�ɍU?�������� */
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0);
/* ���̌�^?�Q�b�g�ȊO�̔�??�̓G�S?��?�����s�� */
map_foreachinarea(skill_area_sub,
bl->m,x-ar,y-ar,x+ar,y+ar,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
if (skillid == SM_MAGNUM) // fire element for 10 seconds
skill_status_change_start(src,SC_FLAMELAUNCHER,0,0,0,0,10000,0);
}
if (bl->type == BL_MOB && skillid == AS_GRIMTOOTH) {
struct status_change *sc_data = battle_get_sc_data(bl);
if (sc_data && sc_data[SC_SLOWDOWN].timer == -1)
skill_status_change_start(bl,SC_SLOWDOWN,0,0,0,0,1000,0);
}
break;
case KN_BOWLINGBASH: /* �{�E�����O�o�b�V�� */
if(flag&1){
/* �ʂɃ_��?�W��?���� */
if(bl->id!=skill_area_temp[1])
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500);
}
else {
int damage;
map_freeblock_lock();
damage = skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0);
if(damage > 0) {
int i,c; /* ���l���畷���������Ȃ̂ŊԈ���Ă�\���偕?����?���������� */
c = skill_get_blewcount(skillid,skilllv);
if(map[bl->m].flag.gvg) c = 0;
for(i=0;i<c;i++){
skill_blown(src,bl,1);
if(bl->type == BL_MOB)
clif_fixmobpos((struct mob_data *)bl);
else if(bl->type == BL_PET)
clif_fixpetpos((struct pet_data *)bl);
else
clif_fixpos(bl);
skill_area_temp[0]=0;
map_foreachinarea(skill_area_sub,
bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY ,
skill_area_sub_count);
if(skill_area_temp[0]>1) break;
}
skill_area_temp[1]=bl->id;
skill_area_temp[2]=bl->x;
skill_area_temp[3]=bl->y;
/* ���̌�^?�Q�b�g�ȊO�̔�??�̓G�S?��?�����s�� */
map_foreachinarea(skill_area_sub,
bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
battle_damage(src,bl,damage,1);
if(rdamage > 0)
battle_damage(bl,src,rdamage,0);
}
map_freeblock_unlock();
}
break;
case ALL_RESURRECTION: /* ���U���N�V���� */
case PR_TURNUNDEAD: /* �^?���A���f�b�h */
if(bl->type != BL_PC && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
else {
map_freeblock_unlock();
return 1;
}
break;
/* ���@�n�X�L�� */
case MG_SOULSTRIKE: /* �\�E���X�g���C�N */
case MG_COLDBOLT: /* �R?���h�{���g */
case MG_FIREBOLT: /* �t�@�C�A?�{���g */
case MG_LIGHTNINGBOLT: /* ���C�g�j���O�{���g */
case WZ_EARTHSPIKE: /* �A?�X�X�p�C�N */
case AL_HEAL: /* �q?�� */
case AL_HOLYLIGHT: /* �z?��?���C�g */
case MG_FROSTDIVER: /* �t���X�g�_�C�o? */
case WZ_JUPITEL: /* ���s�e���T���_? */
case NPC_MAGICALATTACK: /* MOB:���@��?�U? */
case PR_ASPERSIO: /* �A�X�y���V�I */
// case HW_NAPALMVULCAN: /* �i�p�[���o���J�� */
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
break;
case WZ_WATERBALL: /* �E�H?�^?�{?�� */
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
if(skilllv>1)
skill_status_change_start(src,SC_WATERBALL,skilllv,bl->id,0,0,0,0);
break;
case PR_BENEDICTIO: /* ��?�~�� */
if(battle_get_race(bl)==1 || battle_get_race(bl)==6)
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
break;
/* ���@�n��?�U?�X�L�� */
case MG_NAPALMBEAT: /* �i�p?���r?�g */
case MG_FIREBALL: /* �t�@�C��?�{?�� */
if(flag&1){
/* �ʂɃ_��?�W��?���� */
if(bl->id!=skill_area_temp[1]){
if(skillid==MG_FIREBALL){ /* �t�@�C��?�{?���Ȃ璆�S����̋������v�Z */
int dx=abs( bl->x - skill_area_temp[2] );
int dy=abs( bl->y - skill_area_temp[3] );
skill_area_temp[0]=((dx>dy)?dx:dy);
}
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
skill_area_temp[0]| 0x0500);
}
}else{
int ar=(skillid==MG_NAPALMBEAT)?1:2;
skill_area_temp[1]=bl->id;
if(skillid==MG_NAPALMBEAT){ /* �i�p?���ł͐��?���� */
skill_area_temp[0]=0;
map_foreachinarea(skill_area_sub,
bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY ,
skill_area_sub_count);
}else{
skill_area_temp[0]=0;
skill_area_temp[2]=bl->x;
skill_area_temp[3]=bl->y;
}
/* �܂��^?�Q�b�g�ɍU?�������� */
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
skill_area_temp[0] );
/* ���̌�^?�Q�b�g�ȊO�̔�??�̓G�S?��?�����s�� */
map_foreachinarea(skill_area_sub,
bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
}
break;
case HW_NAPALMVULCAN: // Fixed By SteelViruZ
if(flag&1){
if(bl->id!=skill_area_temp[1]){
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
skill_area_temp[0]);
}
}else{
int ar=(skillid==HW_NAPALMVULCAN)?1:2;
skill_area_temp[1]=bl->id;
if(skillid==HW_NAPALMVULCAN){
skill_area_temp[0]=0;
map_foreachinarea(skill_area_sub,
bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY ,
skill_area_sub_count);
}else{
skill_area_temp[0]=0;
skill_area_temp[2]=bl->x;
skill_area_temp[3]=bl->y;
}
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
skill_area_temp[0] );
map_foreachinarea(skill_area_sub,
bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
}
break;
case WZ_FROSTNOVA: /* �t���X�g�m���@ */
skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
//skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
map_foreachinarea(skill_attack_area,src->m,src->x-5,bl->y-5,bl->x+5,bl->y+5,0,BF_MAGIC,src,src,skillid,skilllv,tick,flag,BCT_ENEMY);
break;
case WZ_SIGHTRASHER:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
skill_status_change_end(src,SC_SIGHT,-1);
break;
/* ���̑� */
case HT_BLITZBEAT: /* �u���b�c�r?�g */
if(flag&1){
/* �ʂɃ_��?�W��?���� */
if(bl->id!=skill_area_temp[1])
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,skill_area_temp[0]|(flag&0xf00000));
}else{
skill_area_temp[0]=0;
skill_area_temp[1]=bl->id;
if(flag&0xf00000)
map_foreachinarea(skill_area_sub,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY ,skill_area_sub_count);
/* �܂��^?�Q�b�g�ɍU?�������� */
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,skill_area_temp[0]|(flag&0xf00000));
/* ���̌�^?�Q�b�g�ȊO�̔�??�̓G�S?��?�����s�� */
map_foreachinarea(skill_area_sub,
bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
}
break;
case CR_GRANDCROSS: /* �O�����h�N���X */
/* �X�L�����j�b�g�z�u */
skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
if(sd)
sd->canmove_tick = tick + 1000;
else if(src->type == BL_MOB)
mob_changestate((struct mob_data *)src,MS_DELAY,1000);
break;
case TF_THROWSTONE: /* ���� */
case NPC_SMOKING: /* �X��?�L���O */
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,0 );
break;
case NPC_SELFDESTRUCTION: /* ���� */
case NPC_SELFDESTRUCTION2: /* ����2 */
if(flag&1){
/* �ʂɃ_��?�W��?���� */
if(src->type==BL_MOB){
struct mob_data* mb = (struct mob_data*)src;
nullpo_retr(1, mb);
mb->hp=skill_area_temp[2];
if(bl->id!=skill_area_temp[1])
skill_attack(BF_MISC,src,src,bl,NPC_SELFDESTRUCTION,skilllv,tick,flag );
mb->hp=1;
}
}else{
struct mob_data *md;
if((md=(struct mob_data *)src)){
skill_area_temp[1]=bl->id;
skill_area_temp[2]=battle_get_hp(src);
clif_skill_nodamage(src,src,NPC_SELFDESTRUCTION,-1,1);
map_foreachinarea(skill_area_sub,
bl->m,bl->x-5,bl->y-5,bl->x+5,bl->y+5,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
battle_damage(src,src,md->hp,0);
}
}
break;
/* HP�z?/HP�z?���@ */
case NPC_BLOODDRAIN:
case NPC_ENERGYDRAIN:
{
int heal;
heal = skill_attack((skillid==NPC_BLOODDRAIN)?BF_WEAPON:BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
if( heal > 0 ){
struct block_list tbl;
tbl.id = 0;
tbl.m = src->m;
tbl.x = src->x;
tbl.y = src->y;
clif_skill_nodamage(&tbl,src,AL_HEAL,heal,1);
battle_heal(NULL,src,heal,0,0);
}
}
break;
case 0:
if(sd) {
if(flag&3){
if(bl->id!=skill_area_temp[1])
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500);
}
else{
int ar=sd->splash_range;
skill_area_temp[1]=bl->id;
map_foreachinarea(skill_area_sub,
bl->m, bl->x - ar, bl->y - ar, bl->x + ar, bl->y + ar, 0,
src, skillid, skilllv, tick, flag | BCT_ENEMY | 1,
skill_castend_damage_id);
}
}
break;
default:
map_freeblock_unlock();
return 1;
}
if(sc_data) {
if (sc_data[SC_MAGICPOWER].timer != -1 && skillid != HW_MAGICPOWER) //�}�W�b�N�p��?��?�ʏI��
skill_status_change_end(src,SC_MAGICPOWER,-1);
}
map_freeblock_unlock();
return 0;
}
/*==========================================
* �X�L���g�p�i�r�������AID�w��x���n�j
*------------------------------------------
*/
int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag )
{
struct map_session_data *sd=NULL;
struct map_session_data *dstsd=NULL;
struct mob_data *md=NULL;
struct mob_data *dstmd=NULL;
int i,abra_skillid=0,abra_skilllv;
int sc_def_vit,sc_def_mdef,strip_fix,strip_time,strip_per;
int sc_dex,sc_luk;
//�N���X�`�F���W�p�{�X�����X�^?ID
int changeclass[]={1038,1039,1046,1059,1086,1087,1112,1115
,1157,1159,1190,1272,1312,1373,1492};
int poringclass[]={1002};
if(skilllv <= 0) return 0;
nullpo_retr(1, src);
nullpo_retr(1, bl);
if(src->type==BL_PC)
sd=(struct map_session_data *)src;
else if(src->type==BL_MOB)
md=(struct mob_data *)src;
sc_dex=battle_get_mdef(bl);
sc_luk=battle_get_luk(bl);
sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3);
//sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3);
sc_def_mdef = 100 - (3 + battle_get_mdef(bl) + battle_get_luk(bl)/3);
strip_fix = battle_get_dex(src) - battle_get_dex(bl);
if(bl->type==BL_PC){
nullpo_retr(1, dstsd=(struct map_session_data *)bl);
}else if(bl->type==BL_MOB){
nullpo_retr(1, dstmd=(struct mob_data *)bl);
if(sc_def_vit>50)
sc_def_vit=50;
if(sc_def_mdef>50)
sc_def_mdef=50;
}
if(sc_def_vit < 0)
sc_def_vit=0;
if(sc_def_mdef < 0)
sc_def_mdef=0;
if(strip_fix < 0)
strip_fix=0;
if(bl == NULL || bl->prev == NULL)
return 1;
if(sd && pc_isdead(sd))
return 1;
if(dstsd && pc_isdead(dstsd) && skillid != ALL_RESURRECTION)
return 1;
if(battle_get_class(bl) == 1288)
return 1;
if (skillnotok(skillid, (struct map_session_data *)bl)) // [MouseJstr]
return 0;
map_freeblock_lock();
switch(skillid)
{
case AL_HEAL: /* �q?�� */
{
int heal=skill_calc_heal( src, skilllv );
int heal_get_jobexp;
int skill;
struct pc_base_job s_class;
if( dstsd && dstsd->special_state.no_magic_damage )
heal=0; /* ?��峃J?�h�i�q?���ʂO�j */
if (sd){
s_class = pc_calc_base_job(sd->status.class);
if((skill=pc_checkskill(sd,HP_MEDITATIO))>0) // ���f�B�e�C�e�B�I
heal += heal*skill*2/100;
if(sd && dstsd && sd->status.partner_id == dstsd->status.char_id && s_class.job == 23 && sd->status.sex == 0) //������?�ۂ�PC�A?�ۂ������̃p?�g�i?�A�������X�p�m�r�A���������Ȃ�
heal = heal*2; //�X�p�m�r�̉ł��U�߂Ƀq?�������2�{�ɂȂ�
}
clif_skill_nodamage(src,bl,skillid,heal,1);
heal_get_jobexp = battle_heal(NULL,bl,heal,0,0);
// JOB??�l�l��
if(src->type == BL_PC && bl->type==BL_PC && heal > 0 && src != bl && battle_config.heal_exp > 0){
heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100;
if(heal_get_jobexp <= 0)
heal_get_jobexp = 1;
pc_gainexp((struct map_session_data *)src,0,heal_get_jobexp);
}
}
break;
case ALL_RESURRECTION: /* ���U���N�V���� */
if(bl->type==BL_PC){
int per=0;
struct map_session_data *tsd = (struct map_session_data*)bl;
nullpo_retr(1, tsd);
if( (map[bl->m].flag.pvp) && tsd->pvp_point<0 )
break; /* PVP����s�\?�� */
if(pc_isdead(tsd)){ /* ���S���� */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
switch(skilllv){
case 1: per=10; break;
case 2: per=30; break;
case 3: per=50; break;
case 4: per=80; break;
}
tsd->status.hp=tsd->status.max_hp*per/100;
if(tsd->status.hp<=0) tsd->status.hp=1;
if(tsd->special_state.restart_full_recover ){ /* �I�V���X�J?�h */
tsd->status.hp=tsd->status.max_hp;
tsd->status.sp=tsd->status.max_sp;
}
pc_setstand(tsd);
if(battle_config.pc_invincible_time > 0)
pc_setinvincibletimer(tsd,battle_config.pc_invincible_time);
clif_updatestatus(tsd,SP_HP);
clif_resurrection(&tsd->bl,1);
if(src != bl && sd && battle_config.resurrection_exp > 0) {
int exp = 0,jexp = 0;
int lv = tsd->status.base_level - sd->status.base_level, jlv = tsd->status.job_level - sd->status.job_level;
if(lv > 0) {
exp = (int)((double)tsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.);
if(exp < 1) exp = 1;
}
if(jlv > 0) {
jexp = (int)((double)tsd->status.job_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.);
if(jexp < 1) jexp = 1;
}
if(exp > 0 || jexp > 0)
pc_gainexp(sd,exp,jexp);
}
}
}
break;
case AL_DECAGI: /* ���x���� */
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
if( rand()%100 < (50+skilllv*3+(battle_get_lv(src)+battle_get_int(src)/5)-sc_def_mdef) ) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
break;
case AL_CRUCIS:
if(flag&1) {
int race = battle_get_race(bl),ele = battle_get_elem_type(bl);
if(battle_check_target(src,bl,BCT_ENEMY) && (race == 6 || battle_check_undead(race,ele))) {
int slv=battle_get_lv(src),tlv=battle_get_lv(bl),rate;
rate = 25 + skilllv*2 + slv - tlv;
if(rand()%100 < rate)
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,0,0);
}
}
else {
int range = 15;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
map_foreachinarea(skill_area_sub,
src->m,src->x-range,src->y-range,src->x+range,src->y+range,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_nodamage_id);
}
break;
case PR_LEXDIVINA: /* ���b�N�X�f�B�r?�i */
{
struct status_change *sc_data = battle_get_sc_data(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
if(sc_data && sc_data[SC_DIVINA].timer != -1)
skill_status_change_end(bl,SC_DIVINA,-1);
else if( rand()%100 < sc_def_vit ) {
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
}
break;
case SA_ABRACADABRA:
//require 1 yellow gemstone even with mistress card or Into the Abyss
if (pc_search_inventory(sd, 715) <= 0 ) {
clif_skill_fail(sd,sd->skillid,0,0);
break;
}
pc_delitem(sd, pc_search_inventory(sd, 715), 1, 0);
//
do{
abra_skillid=skill_abra_dataset(skilllv);
}while(abra_skillid == 0);
abra_skilllv=skill_get_max(abra_skillid)>pc_checkskill(sd,SA_ABRACADABRA)?pc_checkskill(sd,SA_ABRACADABRA):skill_get_max(abra_skillid);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
sd->skillitem=abra_skillid;
sd->skillitemlv=abra_skilllv;
clif_item_skill(sd,abra_skillid,abra_skilllv,"�A�u���J�_�u��");
break;
case SA_COMA:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
if(dstsd){
dstsd->status.hp=1;
dstsd->status.sp=1;
clif_updatestatus(dstsd,SP_HP);
clif_updatestatus(dstsd,SP_SP);
}
if(dstmd) dstmd->hp=1;
break;
case SA_FULLRECOVERY:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
if(dstsd) pc_heal(dstsd,dstsd->status.max_hp,dstsd->status.max_sp);
if(dstmd) dstmd->hp=battle_get_max_hp(&dstmd->bl);
break;
case SA_SUMMONMONSTER:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if (sd) mob_once_spawn(sd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,"--ja--",-1,1,"");
break;
case SA_LEVELUP:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd,pc_nextbaseexp(sd)*10/100,0);
break;
case SA_INSTANTDEATH:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if (sd) pc_damage(NULL,sd,sd->status.max_hp);
break;
case SA_QUESTION:
case SA_GRAVITY:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
case SA_CLASSCHANGE:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(dstmd) mob_class_change(dstmd,changeclass);
break;
case SA_MONOCELL:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(dstmd) mob_class_change(dstmd,poringclass);
break;
case SA_DEATH:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if (dstsd) pc_damage(NULL,dstsd,dstsd->status.max_hp);
if (dstmd) mob_damage(NULL,dstmd,dstmd->hp,1);
break;
case SA_REVERSEORCISH:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if (dstsd) pc_setoption(dstsd,dstsd->status.option|0x0800);
break;
case SA_FORTUNE:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(sd) pc_getzeny(sd,battle_get_lv(bl)*100);
break;
case SA_TAMINGMONSTER:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if (dstmd){
for(i=0;i<MAX_PET_DB;i++){
if(dstmd->class == pet_db[i].class){
pet_catch_process1(sd,dstmd->class);
break;
}
}
}
break;
case AL_INCAGI: /* ���x?�� */
case AL_BLESSING: /* �u���b�V���O */
case PR_SLOWPOISON:
case PR_IMPOSITIO: /* �C���|�V�e�B�I�}�k�X */
case PR_LEXAETERNA: /* ���b�N�X�G?�e���i */
case PR_SUFFRAGIUM: /* �T�t���M�E�� */
case PR_BENEDICTIO: /* ��?�~�� */
case CR_PROVIDENCE: /* �v�����B�f���X */
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ){
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}else{
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case CG_MARIONETTE: /* �}���I�l�b�g�R���g��?�� */
if(sd && dstsd){
struct status_change *sc_data = battle_get_sc_data(src);
struct status_change *tsc_data = battle_get_sc_data(bl);
int sc = SkillStatusChangeTable[skillid];
int sc2 = SC_MARIONETTE2;
if((dstsd->bl.type!=BL_PC)
|| (sd->bl.id == dstsd->bl.id)
|| (!sd->status.party_id)
|| (sd->status.party_id != dstsd->status.party_id)) {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
if(sc_data && tsc_data){
if(sc_data[sc].timer == -1 && tsc_data[sc2].timer == -1) {
skill_status_change_start (src,sc,skilllv,0,bl->id,0,skill_get_time(skillid,skilllv),0);
skill_status_change_start (bl,sc2,skilllv,0,src->id,0,skill_get_time(skillid,skilllv),0);
}
else if (sc_data[sc].timer != -1 && tsc_data[sc2].timer != -1 &&
sc_data[sc].val3 == bl->id && tsc_data[sc2].val3 == src->id) {
skill_status_change_end(src, sc, -1);
skill_status_change_end(bl, sc2, -1);
}
else {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
}
break;
case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris]
case SA_FROSTWEAPON:
case SA_LIGHTNINGLOADER:
case SA_SEISMICWEAPON:
if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ){
clif_skill_nodamage(src,bl,skillid,skilllv,0);
break;
}
if(bl->type==BL_PC) {
struct map_session_data *sd2=(struct map_session_data *)bl;
if(sd2->status.weapon==0 || sd2->sc_data[SC_FLAMELAUNCHER].timer!=-1 || sd2->sc_data[SC_FROSTWEAPON].timer!=-1 ||
sd2->sc_data[SC_LIGHTNINGLOADER].timer!=-1 || sd2->sc_data[SC_SEISMICWEAPON].timer!=-1 ||
sd2->sc_data[SC_ENCPOISON].timer!=-1) {
clif_skill_fail(sd,skillid,0,0);
clif_skill_nodamage(src,bl,skillid,skilllv,0);
break;
}
}
if(rand()%100 > (75+skilllv*1) && (skilllv != 5)) {
clif_skill_fail(sd,skillid,0,0);
clif_skill_nodamage(src,bl,skillid,skilllv,0);
if(bl->type==BL_PC && battle_config.equipment_breaking) {
struct map_session_data *sd2=(struct map_session_data *)bl;
if(sd!=sd2) clif_displaymessage(sd->fd,"You broke target's weapon");
pc_breakweapon(sd2);
}
break;
}
else {
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case PR_ASPERSIO: /* �A�X�y���V�I */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
if(bl->type==BL_MOB)
break;
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case PR_KYRIE: /* �L���G�G���C�\�� */
clif_skill_nodamage(bl,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case KN_AUTOCOUNTER: /* �I?�g�J�E���^? */
case KN_TWOHANDQUICKEN: /* �c?�n���h�N�C�b�P�� */
case CR_SPEARQUICKEN: /* �X�s�A�N�C�b�P�� */
case CR_REFLECTSHIELD:
case AS_POISONREACT: /* �|�C�Y�����A�N�g */
case MC_LOUD: /* ���E�h�{�C�X */
case MG_ENERGYCOAT: /* �G�i�W?�R?�g */
// case SM_ENDURE: /* �C���f���A */
case MG_SIGHT: /* �T�C�g */
case AL_RUWACH: /* ���A�t */
case MO_EXPLOSIONSPIRITS: // �����g��
case MO_STEELBODY: // ����
case LK_AURABLADE: /* �I?���u��?�h */
case LK_PARRYING: /* �p���C���O */
case LK_CONCENTRATION: /* �R���Z���g��?�V���� */
// case LK_BERSERK: /* �o?�T?�N */
case HP_ASSUMPTIO: /* */
case WS_CARTBOOST: /* �J?�g�u?�X�g */
case SN_SIGHT: /* �g�D��?�T�C�g */
case WS_MELTDOWN: /* �����g�_�E�� */
case ST_REJECTSWORD: /* ���W�F�N�g�\?�h */
case HW_MAGICPOWER: /* ���@��?�� */
case PF_MEMORIZE: /* �������C�Y */
case ASC_EDP: // [Celest]
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case SM_ENDURE: /* �C���f���A */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
skill_status_change_start(src,SC_BLOCKSKILL,skilllv,0,skillid,0,10000,0 );
break;
case AS_ENCHANTPOISON: // Prevent spamming [Valaris]
if(bl->type==BL_PC) {
struct map_session_data *sd2=(struct map_session_data *)bl;
if(sd2->sc_data[SC_FLAMELAUNCHER].timer!=-1 || sd2->sc_data[SC_FROSTWEAPON].timer!=-1 ||
sd2->sc_data[SC_LIGHTNINGLOADER].timer!=-1 || sd2->sc_data[SC_SEISMICWEAPON].timer!=-1 ||
sd2->sc_data[SC_ENCPOISON].timer!=-1) {
clif_skill_nodamage(src,bl,skillid,skilllv,0);
clif_skill_fail(sd,skillid,0,0);
break;
}
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case LK_TENSIONRELAX: /* �e���V���������b�N�X */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
pc_setsit(sd);
clif_sitting(sd);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case LK_BERSERK: /* �o?�T?�N */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
//sd->status.hp = sd->status.max_hp * 3;
break;
case MC_CHANGECART:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
case AC_CONCENTRATION: /* �W���͌��� */
{
int range = 1;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
map_foreachinarea( skill_status_change_timer_sub,
src->m, src->x-range, src->y-range, src->x+range,src->y+range,0,
src,SkillStatusChangeTable[skillid],tick);
}
break;
case SM_PROVOKE: /* �v���{�b�N */
{
struct status_change *sc_data = battle_get_sc_data(bl);
/* MVPmob�ƕs���ɂ�?���Ȃ� */
if((bl->type==BL_MOB && battle_get_mode(bl)&0x20) || battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) //�s���ɂ�?���Ȃ�
{
map_freeblock_unlock();
return 1;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
if(dstmd && dstmd->skilltimer!=-1 && dstmd->state.skillcastcancel) // �r���W�Q
skill_castcancel(bl,0);
if(dstsd && dstsd->skilltimer!=-1 && (!dstsd->special_state.no_castcancel || map[bl->m].flag.gvg)
&& dstsd->state.skillcastcancel && !dstsd->special_state.no_castcancel2)
skill_castcancel(bl,0);
if(sc_data){
if(sc_data[SC_FREEZE].timer!=-1)
skill_status_change_end(bl,SC_FREEZE,-1);
if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
skill_status_change_end(bl,SC_STONE,-1);
if(sc_data[SC_SLEEP].timer!=-1)
skill_status_change_end(bl,SC_SLEEP,-1);
}
if(bl->type==BL_MOB) {
int range = skill_get_range(skillid,skilllv);
if(range < 0)
range = battle_get_range(src) - (range + 1);
mob_target((struct mob_data *)bl,src,range);
}
}
break;
case CR_DEVOTION: /* �f�B�{?�V���� */
if(sd && dstsd){
//?����{�q�̏ꍇ�̌��̐E�Ƃ��Z�o����
struct pc_base_job dst_s_class = pc_calc_base_job(dstsd->status.class);
int lv = sd->status.base_level-dstsd->status.base_level;
lv = (lv<0)?-lv:lv;
if((dstsd->bl.type!=BL_PC) // �����PC����Ȃ��Ƃ���
||(sd->bl.id == dstsd->bl.id) // ���肪�����͂���
||(lv > 10) // ���x�����}10�܂�
||(!sd->status.party_id && !sd->status.guild_id) // PT�ɂ��M���h�ɂ���?�����͂���
||((sd->status.party_id != dstsd->status.party_id) // �����p?�e�B?���A
&&(sd->status.guild_id != dstsd->status.guild_id)) // �����M���h����Ȃ��Ƃ���
||(dst_s_class.job==14||dst_s_class.job==21)){ // �N���Z����
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
for(i=0;i<skilllv;i++){
if(!sd->dev.val1[i]){ // ��������������
sd->dev.val1[i] = bl->id;
sd->dev.val2[i] = bl->id;
break;
}else if(i==skilllv-1){ // ���Ȃ�����
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
clif_devotion(sd,bl->id);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],src->id,1,0,0,1000*(15+15*skilllv),0 );
}
else clif_skill_fail(sd,skillid,0,0);
break;
case MO_CALLSPIRITS: // ?��
if(sd) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
pc_addspiritball(sd,skill_get_time(skillid,skilllv),skilllv);
}
break;
case CH_SOULCOLLECT: // ��?��
if(sd) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
for(i=0;i<5;i++)
pc_addspiritball(sd,skill_get_time(skillid,skilllv),5);
}
break;
case MO_BLADESTOP: // ���n���
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case MO_ABSORBSPIRITS: // ?�D
i=0;
if(sd && dstsd) {
if(sd == dstsd || map[sd->bl.m].flag.pvp || map[sd->bl.m].flag.gvg) {
if(dstsd->spiritball > 0) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
i = dstsd->spiritball * 7;
pc_delspiritball(dstsd,dstsd->spiritball,0);
if(i > 0x7FFF)
i = 0x7FFF;
if(sd->status.sp + i > sd->status.max_sp)
i = sd->status.max_sp - sd->status.sp;
}
}
}else if(sd && dstmd){ //?�ۂ������X�^?�̏ꍇ
//20%�̊m����?�ۂ�Lv*2��SP������B���������Ƃ��̓^?�Q�b�g(��?�D?)��????!!
if(rand()%100<20){
i=2*mob_db[dstmd->class].lv;
mob_target(dstmd,src,0);
}
}
if(i){
sd->status.sp += i;
clif_heal(sd->fd,SP_SP,i);
}
else
clif_skill_nodamage(src,bl,skillid,skilllv,0);
break;
case AC_MAKINGARROW: /* ��쐬 */
if(sd) {
clif_arrow_create_list(sd);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case AM_PHARMACY: /* �|?�V�����쐬 */
if(sd) {
clif_skill_produce_mix_list(sd,32);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case WS_CREATECOIN: /* �N���G�C�g�R�C�� */
if(sd) {
clif_skill_produce_mix_list(sd,64);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case WS_CREATENUGGET: /* �� */
if(sd) {
clif_skill_produce_mix_list(sd,128);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case ASC_CDP: // [DracoRPG]
// notes: success rate (from emperium.org) = 20 + [(20*Dex)/50] + [(20*Luk)/100]
if(sd) {
clif_skill_produce_mix_list(sd,256);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case BS_HAMMERFALL: /* �n���}?�t�H?�� */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_weapon_damage )
break;
if( rand()%100 < (20+ 10*skilllv)*sc_def_vit/100 ) {
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
break;
case RG_RAID: /* �T�v���C�Y�A�^�b�N */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
{
int x=bl->x,y=bl->y;
skill_area_temp[1]=bl->id;
skill_area_temp[2]=x;
skill_area_temp[3]=y;
map_foreachinarea(skill_area_sub,
bl->m,x-1,y-1,x+1,y+1,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
}
skill_status_change_end(src, SC_HIDING, -1); // �n�C�f�B���O����
break;
case KN_BRANDISHSPEAR: /*�u�����f�B�b�V���X�s�A*/
{
int c,n=4,ar;
int dir = map_calc_dir(src,bl->x,bl->y);
struct square tc;
int x=bl->x,y=bl->y;
ar=skilllv/3;
skill_brandishspear_first(&tc,dir,x,y);
skill_brandishspear_dir(&tc,dir,4);
/* ��?�C */
if(skilllv == 10){
for(c=1;c<4;c++){
map_foreachinarea(skill_area_sub,
bl->m,tc.val1[c],tc.val2[c],tc.val1[c],tc.val2[c],0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|n,
skill_castend_damage_id);
}
}
/* ��?�B�A */
if(skilllv > 6){
skill_brandishspear_dir(&tc,dir,-1);
n--;
}else{
skill_brandishspear_dir(&tc,dir,-2);
n-=2;
}
if(skilllv > 3){
for(c=0;c<5;c++){
map_foreachinarea(skill_area_sub,
bl->m,tc.val1[c],tc.val2[c],tc.val1[c],tc.val2[c],0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|n,
skill_castend_damage_id);
if(skilllv > 6 && n==3 && c==4){
skill_brandishspear_dir(&tc,dir,-1);
n--;c=-1;
}
}
}
/* ��?�@ */
for(c=0;c<10;c++){
if(c==0||c==5) skill_brandishspear_dir(&tc,dir,-1);
map_foreachinarea(skill_area_sub,
bl->m,tc.val1[c%5],tc.val2[c%5],tc.val1[c%5],tc.val2[c%5],0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
}
}
break;
/* �p?�e�B�X�L�� */
case AL_ANGELUS: /* �G���W�F���X */
case PR_MAGNIFICAT: /* �}�O�j�t�B�J?�g */
case PR_GLORIA: /* �O�����A */
case SN_WINDWALK: /* �E�C���h�E�H?�N */
if(sd == NULL || sd->status.party_id==0 || (flag&1) ){
/* �ʂ�?�� */
clif_skill_nodamage(bl,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
else{
/* �p?�e�B�S?�ւ�?�� */
party_foreachsamemap(skill_area_sub,
sd,1,
src,skillid,skilllv,tick, flag|BCT_PARTY|1,
skill_castend_nodamage_id);
}
break;
case BS_ADRENALINE: /* �A�h���i�������b�V�� */
case BS_WEAPONPERFECT: /* �E�F�|���p?�t�F�N�V���� */
case BS_OVERTHRUST: /* �I?�o?�g���X�g */
if(sd == NULL || sd->status.party_id==0 || (flag&1) ){
/* �ʂ�?�� */
clif_skill_nodamage(bl,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,(src == bl)? 1:0,0,0,skill_get_time(skillid,skilllv),0);
}
else{
/* �p?�e�B�S?�ւ�?�� */
party_foreachsamemap(skill_area_sub,
sd,1,
src,skillid,skilllv,tick, flag|BCT_PARTY|1,
skill_castend_nodamage_id);
}
break;
/*�i�t���Ɖ������K�v�j */
case BS_MAXIMIZE: /* �}�L�V�}�C�Y�p��? */
case NV_TRICKDEAD: /* ���ӂ� */
case CR_DEFENDER: /* �f�B�t�F���_? */
case CR_AUTOGUARD: /* �I?�g�K?�h */
{
struct status_change *tsc_data = battle_get_sc_data(bl);
int sc=SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( tsc_data ){
if( tsc_data[sc].timer==-1 )
/* �t������ */
skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
else
/* �������� */
skill_status_change_end(bl, sc, -1);
}
}
break;
case TF_HIDING: /* �n�C�f�B���O */
{
struct status_change *tsc_data = battle_get_sc_data(bl);
int sc=SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,-1,1);
if( tsc_data ){
if( tsc_data[sc].timer==-1 )
/* �t������ */
skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
else
/* �������� */
skill_status_change_end(bl, sc, -1);
}
}
break;
case AS_CLOAKING: /* �N��?�L���O */
{
struct status_change *tsc_data = battle_get_sc_data(bl);
int sc=SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,-1,1);
if( tsc_data ){
if( tsc_data[sc].timer==-1 )
/* �t������ */
skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
else
/* �������� */
skill_status_change_end(bl, sc, -1);
}
//skill_check_cloaking(bl);
}
break;
case ST_CHASEWALK: /* �n�C�f�B���O */
{
struct status_change *tsc_data = battle_get_sc_data(bl);
int sc=SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,-1,1);
if( tsc_data ){
if( tsc_data[sc].timer==-1 )
/* �t������ */
skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
else
/* �������� */
skill_status_change_end(bl, sc, -1);
}
}
break;
/* ?�n�X�L�� */
case BD_LULLABY: /* �q��S */
case BD_RICHMANKIM: /* �j�����h�̉� */
case BD_ETERNALCHAOS: /* �i���̍��� */
case BD_DRUMBATTLEFIELD: /* ?���ۂ̋��� */
case BD_RINGNIBELUNGEN: /* �j?�x�����O�̎w�� */
case BD_ROKISWEIL: /* ���L�̋��� */
case BD_INTOABYSS: /* �[���̒��� */
case BD_SIEGFRIED: /* �s���g�̃W?�N�t��?�h */
case BA_DISSONANCE: /* �s���a�� */
case BA_POEMBRAGI: /* �u���M�̎� */
case BA_WHISTLE: /* ���J */
case BA_ASSASSINCROSS: /* �[�z�̃A�T�V���N���X */
case BA_APPLEIDUN: /* �C�h�D���̗ь� */
case DC_UGLYDANCE: /* ��������ȃ_���X */
case DC_HUMMING: /* �n�~���O */
case DC_DONTFORGETME: /* ����Y��Ȃ��Łc */
case DC_FORTUNEKISS: /* �K�^�̃L�X */
case DC_SERVICEFORYOU: /* �T?�r�X�t�H?��? */
case CG_MOONLIT: /* ������̐�ɗ�����Ԃт� */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
break;
case HP_BASILICA: /* �o�W���J */
{
// cancel Basilica if already in effect
struct status_change *sc_data = battle_get_sc_data(src);
if(sc_data && sc_data[SC_BASILICA].timer != -1){
struct skill_unit *su;
if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
struct skill_unit_group *sg;
if ((sg = su->group) && sg->src_id == sd->bl.id) {
skill_status_change_end(src,SC_BASILICA,-1);
skill_delunitgroup (sg);
break;
}
}
} else {
// otherwise allow casting
skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
skill_clear_unitgroup(src);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
}
}
break;
case PA_GOSPEL: /* �S�X�y�� */
skill_clear_unitgroup(src);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
break;
case BD_ADAPTATION: /* �A�h���u */
{
struct status_change *sc_data = battle_get_sc_data(src);
if(sc_data && sc_data[SC_DANCING].timer!=-1){
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_stop_dancing(src,0);
}
}
break;
case BA_FROSTJOKE: /* �����W��?�N */
case DC_SCREAM: /* �X�N��?�� */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_addtimerskill(src,tick+3000,bl->id,0,0,skillid,skilllv,0,flag);
break;
case TF_STEAL: // �X�e�B?��
if(sd) {
if(pc_steal_item(sd,bl))
clif_skill_nodamage(src,bl,skillid,skilllv,1);
else
clif_skill_fail(sd,skillid,0x0a,0);
}
break;
case RG_STEALCOIN: // �X�e�B?���R�C��
if(sd) {
if(pc_steal_coin(sd,bl)) {
int range = skill_get_range(skillid,skilllv);
if(range < 0)
range = battle_get_range(src) - (range + 1);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
mob_target((struct mob_data *)bl,src,range);
}
else
clif_skill_fail(sd,skillid,0,0);
}
break;
case MG_STONECURSE: /* �X�g?���J?�X */
if (bl->type==BL_MOB && battle_get_mode(bl)&0x20) {
clif_skill_fail(sd,sd->skillid,0,0);
break;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
if( rand()%100 < skilllv*4+20 && !battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
skill_status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
else if(sd)
clif_skill_fail(sd,skillid,0,0);
break;
case NV_FIRSTAID: /* ?�}��? */
clif_skill_nodamage(src,bl,skillid,5,1);
battle_heal(NULL,bl,5,0,0);
break;
case AL_CURE: /* �L���A? */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
skill_status_change_end(bl, SC_SILENCE , -1 );
skill_status_change_end(bl, SC_BLIND , -1 );
skill_status_change_end(bl, SC_CONFUSION, -1 );
if( battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) ){//�A���f�b�h�Ȃ�È�?��
skill_status_change_start(bl, SC_CONFUSION,1,0,0,0,6000,0);
}
break;
case TF_DETOXIFY: /* ��� */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_end(bl, SC_POISON , -1 );
skill_status_change_end(bl, SC_DPOISON , -1 );
break;
case PR_STRECOVERY: /* ���J�o��? */
{
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
skill_status_change_end(bl, SC_FREEZE , -1 );
skill_status_change_end(bl, SC_STONE , -1 );
skill_status_change_end(bl, SC_SLEEP , -1 );
skill_status_change_end(bl, SC_STAN , -1 );
if( battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) ){//�A���f�b�h�Ȃ�È�?��
int blind_time;
//blind_time=30-battle_get_vit(bl)/10-battle_get_int/15;
blind_time=30*(100-(battle_get_int(bl)+battle_get_vit(bl))/2)/100;
if(rand()%100 < (100-(battle_get_int(bl)/2+battle_get_vit(bl)/3+battle_get_luk(bl)/10)))
skill_status_change_start(bl, SC_BLIND,1,0,0,0,blind_time,0);
}
if(dstmd){
dstmd->attacked_id=0;
dstmd->target_id=0;
dstmd->state.targettype = NONE_ATTACKABLE;
dstmd->state.skillstate=MSS_IDLE;
dstmd->next_walktime=tick+rand()%3000+3000;
}
}
break;
case WZ_ESTIMATION: /* �����X�^?��� */
if(src->type==BL_PC){
clif_skill_nodamage(src,bl,skillid,skilllv,1);
clif_skill_estimation((struct map_session_data *)src,bl);
}
break;
case MC_IDENTIFY: /* �A�C�e���Ӓ� */
if(sd)
clif_item_identify_list(sd);
break;
case BS_REPAIRWEAPON: /* ����C�� */
if(sd) {
//���삵�Ȃ��̂łƂ肠�����R�����g�A�E�g
if (pc_search_inventory(sd, 999) <= 0 ) {
clif_skill_fail(sd,sd->skillid,0,0);
map_freeblock_unlock();
return 1;
}
clif_item_repair_list(sd);
}
break;
case MC_VENDING: /* �I�X�J�� */
if(sd)
clif_openvendingreq(sd,2+sd->skilllv);
break;
case AL_TELEPORT: /* �e���|?�g */
if( sd ){
if(map[sd->bl.m].flag.noteleport){ /* �e���|�֎~ */
clif_skill_teleportmessage(sd,0);
break;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( sd->skilllv==1 )
clif_skill_warppoint(sd,sd->skillid,"Random","","","");
else{
clif_skill_warppoint(sd,sd->skillid,"Random",
sd->status.save_point.map,"","");
}
}else if( bl->type==BL_MOB )
mob_warp((struct mob_data *)bl,-1,-1,-1,3);
break;
case AL_HOLYWATER: /* �A�N�A�x�l�f�B�N�^ */
if(sd) {
int eflag;
struct item item_tmp;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = 523;
item_tmp.identify = 1;
if(battle_config.holywater_name_input) {
item_tmp.card[0] = 0xfe;
item_tmp.card[1] = 0;
*((unsigned long *)(&item_tmp.card[2]))=sd->char_id; /* �L����ID */
}
eflag = pc_additem(sd,&item_tmp,1);
if(eflag) {
clif_additem(sd,0,0,eflag);
map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
}
}
break;
case TF_PICKSTONE:
if(sd) {
int eflag;
struct item item_tmp;
struct block_list tbl;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
memset(&item_tmp,0,sizeof(item_tmp));
memset(&tbl,0,sizeof(tbl)); // [MouseJstr]
item_tmp.nameid = 7049;
item_tmp.identify = 1;
tbl.id = 0;
clif_takeitem(&sd->bl,&tbl);
eflag = pc_additem(sd,&item_tmp,1);
if(eflag) {
clif_additem(sd,0,0,eflag);
map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
}
}
break;
case RG_STRIPWEAPON: /* �X�g���b�v�E�F�|�� */
{
struct status_change *tsc_data = battle_get_sc_data(bl);
if(tsc_data && tsc_data[SC_CP_WEAPON].timer != -1 )
break;
strip_per = 5+2*skilllv+strip_fix/5;
strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
if(rand()%100 < strip_per){
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
if(dstsd){
for(i=0;i<MAX_INVENTORY;i++){
if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0002){
pc_unequipitem(dstsd,i,0,BF_SKILL);
break;
}
}
}
}
}
break;
case RG_STRIPSHIELD: /* �X�g���b�v�V?���h */
{
struct status_change *tsc_data = battle_get_sc_data(bl);
if(tsc_data && tsc_data[SC_CP_SHIELD].timer != -1 )
break;
strip_per = 5+2*skilllv+strip_fix/5;
strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
if(rand()%100 < strip_per){
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
if(dstsd){
for(i=0;i<MAX_INVENTORY;i++){
if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0020){
pc_unequipitem(dstsd,i,0,BF_SKILL);
break;
}
}
}
}
}
break;
case RG_STRIPARMOR: /* �X�g���b�v�A?�}? */
{
struct status_change *tsc_data = battle_get_sc_data(bl);
if(tsc_data && tsc_data[SC_CP_ARMOR].timer != -1 )
break;
strip_per = 5+2*skilllv+strip_fix/5;
strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
if(rand()%100 < strip_per){
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
if(dstsd){
for(i=0;i<MAX_INVENTORY;i++){
if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0010){
pc_unequipitem(dstsd,i,0,BF_SKILL);
break;
}
}
}
}
}
break;
case RG_STRIPHELM: /* �X�g���b�v�w���� */
{
struct status_change *tsc_data = battle_get_sc_data(bl);
if(tsc_data && tsc_data[SC_CP_HELM].timer != -1 )
break;
strip_per = 5+2*skilllv+strip_fix/5;
strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
if(rand()%100 < strip_per){
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
if(dstsd){
for(i=0;i<MAX_INVENTORY;i++){
if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0100){
pc_unequipitem(dstsd,i,0,BF_SKILL);
break;
}
}
}
}
}
break;
// Full Strip [Celest]
case ST_FULLSTRIP:
{
struct status_change *tsc_data = battle_get_sc_data(bl);
int c=0, i, j;
int striplist[2][4] = { { 0, 0, 0, 0 },
{ 0x0002, 0x0020, 0x0010, 0x0100 } };
strip_per = 5+2*skilllv+strip_fix/5;
strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
for (i=0; i<4; i++) {
if(tsc_data && tsc_data[SC_CP_WEAPON + i].timer != -1)
break;
if(rand()%100 < strip_per) {
striplist[0][i] = 1;
c++;
}
}
if (c > 0) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
for (j=0; j<4 && c > 0; j++) {
if (striplist[0][j]) {
skill_status_change_start(bl,SC_STRIPWEAPON + i,skilllv,0,0,0,strip_time,0 );
if(dstsd){
for(i=0;i<MAX_INVENTORY;i++){
if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & striplist[1][j]){
pc_unequipitem(dstsd,i,0,BF_SKILL);
--c;
break;
}
}
}
}
}
}
}
break;
/* PotionPitcher */
case AM_POTIONPITCHER: /* �|?�V�����s�b�`��? */
{
struct block_list tbl;
int i,x,hp = 0,sp = 0;
if(sd) {
if(sd==dstsd) { // cancel use on oneself
map_freeblock_unlock();
return 1;
}
x = skilllv%11 - 1;
i = pc_search_inventory(sd,skill_db[skillid].itemid[x]);
if(i < 0 || skill_db[skillid].itemid[x] <= 0) {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skillid].amount[x]) {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
sd->state.potionpitcher_flag = 1;
sd->potion_hp = sd->potion_sp = sd->potion_per_hp = sd->potion_per_sp = 0;
sd->skilltarget = bl->id;
run_script(sd->inventory_data[i]->use_script,0,sd->bl.id,0);
pc_delitem(sd,i,skill_db[skillid].amount[x],0);
sd->state.potionpitcher_flag = 0;
if(sd->potion_per_hp > 0 || sd->potion_per_sp > 0) {
hp = battle_get_max_hp(bl) * sd->potion_per_hp / 100;
hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
if(dstsd) {
sp = dstsd->status.max_sp * sd->potion_per_sp / 100;
sp = sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
}
}
else {
if(sd->potion_hp > 0) {
hp = sd->potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
hp = hp * (100 + (battle_get_vit(bl)<<1)) / 100;
if(dstsd)
hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100;
}
if(sd->potion_sp > 0) {
sp = sd->potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
sp = sp * (100 + (battle_get_int(bl)<<1)) / 100;
if(dstsd)
sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100;
}
}
}
else {
hp = (1 + rand()%400) * (100 + skilllv*10) / 100;
hp = hp * (100 + (battle_get_vit(bl)<<1)) / 100;
if(dstsd)
hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100;
}
tbl.id = 0;
tbl.m = src->m;
tbl.x = src->x;
tbl.y = src->y;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(hp > 0 || (hp <= 0 && sp <= 0))
clif_skill_nodamage(&tbl,bl,AL_HEAL,hp,1);
if(sp > 0)
clif_skill_nodamage(&tbl,bl,MG_SRECOVERY,sp,1);
battle_heal(src,bl,hp,sp,0);
}
break;
case AM_CP_WEAPON:
{
struct status_change *tsc_data = battle_get_sc_data(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(tsc_data && tsc_data[SC_STRIPWEAPON].timer != -1)
skill_status_change_end(bl, SC_STRIPWEAPON, -1 );
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
}
break;
case AM_CP_SHIELD:
{
struct status_change *tsc_data = battle_get_sc_data(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(tsc_data && tsc_data[SC_STRIPSHIELD].timer != -1)
skill_status_change_end(bl, SC_STRIPSHIELD, -1 );
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
}
break;
case AM_CP_ARMOR:
{
struct status_change *tsc_data = battle_get_sc_data(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(tsc_data && tsc_data[SC_STRIPARMOR].timer != -1)
skill_status_change_end(bl, SC_STRIPARMOR, -1 );
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
}
break;
case AM_CP_HELM:
{
struct status_change *tsc_data = battle_get_sc_data(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(tsc_data && tsc_data[SC_STRIPHELM].timer != -1)
skill_status_change_end(bl, SC_STRIPHELM, -1 );
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
}
break;
case SA_DISPELL: /* �f�B�X�y�� */
{
int i;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
for(i=0;i<136;i++){
if(i==SC_RIDING || i== SC_FALCON || i==SC_HALLUCINATION || i==SC_WEIGHT50
|| i==SC_WEIGHT90 || i==SC_STRIPWEAPON || i==SC_STRIPSHIELD || i==SC_STRIPARMOR
|| i==SC_STRIPHELM || i==SC_CP_WEAPON || i==SC_CP_SHIELD || i==SC_CP_ARMOR
|| i==SC_CP_HELM || i==SC_COMBO)
continue;
skill_status_change_end(bl,i,-1);
}
}
break;
case TF_BACKSLIDING: /* �o�b�N�X�e�b�v */
battle_stopwalking(src,1);
skill_blown(src,bl,skill_get_blewcount(skillid,skilllv)|0x10000);
if(src->type == BL_MOB)
clif_fixmobpos((struct mob_data *)src);
else if(src->type == BL_PET)
clif_fixpetpos((struct pet_data *)src);
else if(src->type == BL_PC)
clif_fixpos(src);
skill_addtimerskill(src,tick + 200,src->id,0,0,skillid,skilllv,0,flag);
break;
case SA_CASTCANCEL:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_castcancel(src,1);
if(sd) {
int sp = skill_get_sp(sd->skillid_old,sd->skilllv_old);
sp = sp * (90 - (skilllv-1)*20) / 100;
if(sp < 0) sp = 0;
pc_heal(sd,0,-sp);
}
break;
case SA_SPELLBREAKER: // �X�y���u���C�J?
{
struct status_change *sc_data = battle_get_sc_data(bl);
int sp;
if(sc_data && sc_data[SC_MAGICROD].timer != -1) {
if(dstsd) {
sp = skill_get_sp(skillid,skilllv);
sp = sp * sc_data[SC_MAGICROD].val2 / 100;
if(sp > 0x7fff) sp = 0x7fff;
else if(sp < 1) sp = 1;
if(dstsd->status.sp + sp > dstsd->status.max_sp) {
sp = dstsd->status.max_sp - dstsd->status.sp;
dstsd->status.sp = dstsd->status.max_sp;
}
else
dstsd->status.sp += sp;
clif_heal(dstsd->fd,SP_SP,sp);
}
clif_skill_nodamage(bl,bl,SA_MAGICROD,sc_data[SC_MAGICROD].val1,1);
if(sd) {
sp = sd->status.max_sp/5;
if(sp < 1) sp = 1;
pc_heal(sd,0,-sp);
}
}
else {
int bl_skillid=0,bl_skilllv=0;
if(bl->type == BL_PC) {
if(dstsd && dstsd->skilltimer != -1) {
bl_skillid = dstsd->skillid;
bl_skilllv = dstsd->skilllv;
}
}
else if(bl->type == BL_MOB) {
if(dstmd && dstmd->skilltimer != -1) {
bl_skillid = dstmd->skillid;
bl_skilllv = dstmd->skilllv;
}
}
if(bl_skillid > 0 && skill_db[bl_skillid].skill_type == BF_MAGIC) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_castcancel(bl,0);
sp = skill_get_sp(bl_skillid,bl_skilllv);
if(dstsd)
pc_heal(dstsd,0,-sp);
if(sd) {
sp = sp*(25*(skilllv-1))/100;
if(skilllv > 1 && sp < 1) sp = 1;
if(sp > 0x7fff) sp = 0x7fff;
else if(sp < 1) sp = 1;
if(sd->status.sp + sp > sd->status.max_sp) {
sp = sd->status.max_sp - sd->status.sp;
sd->status.sp = sd->status.max_sp;
}
else
sd->status.sp += sp;
clif_heal(sd->fd,SP_SP,sp);
}
}
else if(sd)
clif_skill_fail(sd,skillid,0,0);
}
}
break;
case SA_MAGICROD:
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case SA_AUTOSPELL: /* �I?�g�X�y�� */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(sd)
clif_autospell(sd,skilllv);
else {
int maxlv=1,spellid=0;
static const int spellarray[3] = { MG_COLDBOLT,MG_FIREBOLT,MG_LIGHTNINGBOLT };
if(skilllv >= 10) {
spellid = MG_FROSTDIVER;
maxlv = skilllv - 9;
}
else if(skilllv >=8) {
spellid = MG_FIREBALL;
maxlv = skilllv - 7;
}
else if(skilllv >=5) {
spellid = MG_SOULSTRIKE;
maxlv = skilllv - 4;
}
else if(skilllv >=2) {
int i = rand()%3;
spellid = spellarray[i];
maxlv = skilllv - 1;
}
else if(skilllv > 0) {
spellid = MG_NAPALMBEAT;
maxlv = 3;
}
if(spellid > 0)
skill_status_change_start(src,SC_AUTOSPELL,skilllv,spellid,maxlv,0,
skill_get_time(SA_AUTOSPELL,skilllv),0);
}
break;
/* �����_��?��?���A��?��?���A�n�A�A�� */
case NPC_ATTRICHANGE:
case NPC_CHANGEWATER:
case NPC_CHANGEGROUND:
case NPC_CHANGEFIRE:
case NPC_CHANGEWIND:
/* �ŁA���A�O�A�� */
case NPC_CHANGEPOISON:
case NPC_CHANGEHOLY:
case NPC_CHANGEDARKNESS:
case NPC_CHANGETELEKINESIS:
if(md){
clif_skill_nodamage(src,bl,skillid,skilllv,1);
md->def_ele=skill_get_pl(skillid);
if(md->def_ele==0) /* �����_��?���A�������A*/
md->def_ele=rand()%10; /* �s��?���͏��� */
md->def_ele+=(1+rand()%4)*20; /* ?�����x���̓����_�� */
}
break;
case NPC_PROVOCATION:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(md)
clif_pet_performance(src,mob_db[md->class].skill[md->skillidx].val[0]);
break;
case NPC_HALLUCINATION:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case NPC_KEEPING:
case NPC_BARRIER:
{
int skill_time = skill_get_time(skillid,skilllv);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_time,0 );
if (bl->type == BL_MOB)
mob_changestate((struct mob_data *)src,MS_DELAY,skill_time);
else if (bl->type == BL_PC)
sd->attackabletime = sd->canmove_tick = tick + skill_time;
}
break;
case NPC_DARKBLESSING:
{
int sc_def = 100 - battle_get_mdef(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
if(battle_get_elem_type(bl) == 7 || battle_get_race(bl) == 6)
break;
if(rand()%100 < sc_def*(50+skilllv*5)/100) {
if(dstsd) {
int hp = battle_get_hp(bl)-1;
pc_heal(dstsd,-hp,0);
}
else if(dstmd)
dstmd->hp = 1;
}
}
break;
case NPC_SELFDESTRUCTION: /* ���� */
case NPC_SELFDESTRUCTION2: /* ����2 */
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,0,0,skill_get_time(skillid,skilllv),0);
break;
case NPC_LICK:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_weapon_damage )
break;
if(dstsd)
pc_heal(dstsd,0,-100);
if(rand()%100 < (skilllv*5)*sc_def_vit/100)
skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_SUICIDE: /* ���� */
if(src && bl){
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if (md)
mob_damage(NULL,md,md->hp,0);
else if (sd)
pc_damage(NULL,sd,sd->status.hp);
}
break;
case NPC_SUMMONSLAVE: /* �艺���� */
case NPC_SUMMONMONSTER: /* MOB���� */
if(md && !md->master_id){
mob_summonslave(md,mob_db[md->class].skill[md->skillidx].val,skilllv,(skillid==NPC_SUMMONSLAVE)?1:0);
}
break;
case NPC_TRANSFORMATION:
case NPC_METAMORPHOSIS:
if(md)
mob_class_change(md,mob_db[md->class].skill[md->skillidx].val);
break;
case NPC_EMOTION: /* �G��?�V���� */
if(md)
clif_emotion(&md->bl,mob_db[md->class].skill[md->skillidx].val[0]);
break;
case NPC_DEFENDER:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
case WE_MALE: /* �N�����͌��� */
if(sd && dstsd){
int hp_rate=(skilllv <= 0)? 0:skill_db[skillid].hp_rate[skilllv-1];
int gain_hp=sd->status.max_hp*abs(hp_rate)/100;// 15%
clif_skill_nodamage(src,bl,skillid,gain_hp,1);
battle_heal(NULL,bl,gain_hp,0,0);
}
break;
case WE_FEMALE: /* ���Ȃ���?��?���ɂȂ�܂� */
if(sd && dstsd){
int sp_rate=(skilllv <= 0)? 0:skill_db[skillid].sp_rate[skilllv-1];
int gain_sp=sd->status.max_sp*abs(sp_rate)/100;// 15%
clif_skill_nodamage(src,bl,skillid,gain_sp,1);
battle_heal(NULL,bl,0,gain_sp,0);
}
break;
case WE_CALLPARTNER: /* ���Ȃ���?������ */
if(sd && dstsd){
if((dstsd = pc_get_partner(sd)) == NULL){
clif_skill_fail(sd,skillid,0,0);
return 0;
}
if(map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto || map[dstsd->bl.m].flag.nowarp){
clif_skill_teleportmessage(sd,1);
return 0;
}
skill_unitsetting(src,skillid,skilllv,sd->bl.x,sd->bl.y,0);
}
break;
case PF_HPCONVERSION: /* ���C�t�u������ */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(sd){
int conv_hp=0,conv_sp=0;
conv_hp=sd->status.hp/10; //��{��HP��10%
sd->status.hp -= conv_hp; //HP�����炷
conv_sp=conv_hp*10*skilllv/100;
conv_sp=(sd->status.sp+conv_sp>sd->status.max_sp)?sd->status.max_sp-sd->status.sp:conv_sp;
sd->status.sp += conv_sp; //SP��?�₷
pc_heal(sd,-conv_hp,conv_sp);
clif_heal(sd->fd,SP_SP,conv_sp);
}
break;
case HT_REMOVETRAP: /* ����?�u�g���b�v */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
{
struct skill_unit *su=NULL;
struct item item_tmp;
int flag;
if((bl->type==BL_SKILL) &&
(su=(struct skill_unit *)bl) &&
(su->group->src_id == src->id || map[bl->m].flag.pvp || map[bl->m].flag.gvg) &&
(su->group->unit_id >= 0x8f && su->group->unit_id <= 0x99) &&
(su->group->unit_id != 0x92)){ //?�����Ԃ�
if(sd){
if(battle_config.skill_removetrap_type == 1){
for(i=0;i<10;i++) {
if(skill_db[su->group->skill_id].itemid[i] > 0){
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = skill_db[su->group->skill_id].itemid[i];
item_tmp.identify = 1;
if(item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i]))){
clif_additem(sd,0,0,flag);
map_addflooritem(&item_tmp,skill_db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
}
}
}
}else{
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = 1065;
item_tmp.identify = 1;
if(item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,1))){
clif_additem(sd,0,0,flag);
map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
}
}
}
if(su->group->unit_id == 0x91 && su->group->val2){
struct block_list *target=map_id2bl(su->group->val2);
if(target && (target->type == BL_PC || target->type == BL_MOB))
skill_status_change_end(target,SC_ANKLE,-1);
}
skill_delunit(su);
}
}
break;
case HT_SPRINGTRAP: /* �X�v�����O�g���b�v */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
{
struct skill_unit *su=NULL;
if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){
switch(su->group->unit_id){
case 0x8f: /* �u���X�g�}�C�� */
case 0x90: /* �X�L�b�h�g���b�v */
case 0x93: /* �����h�}�C�� */
case 0x94: /* �V���b�N�E�F?�u�g���b�v */
case 0x95: /* �T���h�}�� */
case 0x96: /* �t���b�V��? */
case 0x97: /* �t��?�W���O�g���b�v */
case 0x98: /* �N���C���A?�g���b�v */
case 0x99: /* �g?�L?�{�b�N�X */
su->group->unit_id = 0x8c;
clif_changelook(bl,LOOK_BASE,su->group->unit_id);
su->group->limit=DIFF_TICK(tick+1500,su->group->tick);
su->limit=DIFF_TICK(tick+1500,su->group->tick);
}
}
}
break;
case BD_ENCORE: /* �A���R?�� */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(sd)
skill_use_id(sd,src->id,sd->skillid_dance,sd->skilllv_dance);
break;
case AS_SPLASHER: /* �x�i���X�v���b�V��? */
if((double)battle_get_max_hp(bl)*2/3 < battle_get_hp(bl)) //HP��2/3�ȏ�?���Ă����玸�s
return 1;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,src->id,0,skill_get_time(skillid,skilllv),0 );
break;
case PF_MINDBREAKER: /* �v���{�b�N */
{
struct status_change *sc_data = battle_get_sc_data(bl);
/* MVPmob�ƕs���ɂ�?���Ȃ� */
if((bl->type==BL_MOB && battle_get_mode(bl)&0x20) || battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) //�s���ɂ�?���Ȃ�
{
map_freeblock_unlock();
return 1;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
if(dstmd && dstmd->skilltimer!=-1 && dstmd->state.skillcastcancel) // �r���W�Q
skill_castcancel(bl,0);
if(dstsd && dstsd->skilltimer!=-1 && (!dstsd->special_state.no_castcancel || map[bl->m].flag.gvg)
&& dstsd->state.skillcastcancel && !dstsd->special_state.no_castcancel2)
skill_castcancel(bl,0);
if(sc_data){
if(sc_data[SC_FREEZE].timer!=-1)
skill_status_change_end(bl,SC_FREEZE,-1);
if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
skill_status_change_end(bl,SC_STONE,-1);
if(sc_data[SC_SLEEP].timer!=-1)
skill_status_change_end(bl,SC_SLEEP,-1);
}
if(bl->type==BL_MOB) {
int range = skill_get_range(skillid,skilllv);
if(range < 0)
range = battle_get_range(src) - (range + 1);
mob_target((struct mob_data *)bl,src,range);
}
}
break;
// Weapon Refining [Celest]
case WS_WEAPONREFINE:
if(sd)
clif_item_refine_list(sd);
break;
// Slim Pitcher
case CR_SLIMPITCHER:
{
if (sd && flag&1) {
int hp = sd->potion_hp * (100 + pc_checkskill(sd,CR_SLIMPITCHER)*5 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
hp = hp * (100 + (battle_get_vit(bl)<<1))/100;
if (dstsd)
hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10)/100;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
battle_heal(src,bl,hp,0,0);
}
}
break;
// Full Chemical Protection
case CR_FULLPROTECTION:
{
int i, skilltime;
struct status_change *tsc_data = battle_get_sc_data(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skilltime = skill_get_time(skillid,skilllv);
for (i=0; i<4; i++) {
if(tsc_data && tsc_data[SC_STRIPWEAPON + i].timer != -1)
skill_status_change_end(bl, SC_STRIPWEAPON + i, -1 );
skill_status_change_start(bl,SC_CP_WEAPON + i,skilllv,0,0,0,skilltime,0 );
}
}
break;
case RG_CLEANER: //AppleGirl
clif_skill_nodamage(src,bl,skillid,skilllv,1);
{
struct skill_unit *su=NULL;
if((bl->type==BL_SKILL) &&
(su=(struct skill_unit *)bl) &&
(su->group->src_id == src->id || map[bl->m].flag.pvp || map[bl->m].flag.gvg) &&
(su->group->unit_id == 0xb0)){ //?�����Ԃ�
if(sd)
skill_delunit(su);
}
}
break;
// New guild skills [Celest]
case GD_BATTLEORDER:
{
struct guild *g = NULL;
// Only usable during WoE
if (!agit_flag) {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 0;
}
if(flag&1) {
if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
skill_status_change_start(&dstsd->bl,SC_BATTLEORDERS,skilllv,0,0,0,0,0 );
}
}
else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
strcmp(sd->status.name,g->master)==0) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
map_foreachinarea(skill_area_sub,
src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
src,skillid,skilllv,tick, flag|BCT_ALL|1,
skill_castend_nodamage_id);
}
}
break;
case GD_REGENERATION:
{
struct guild *g = NULL;
// Only usable during WoE
if (!agit_flag) {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 0;
}
if(flag&1) {
if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
skill_status_change_start(&dstsd->bl,SC_REGENERATION,skilllv,0,0,0,0,0 );
}
}
else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
strcmp(sd->status.name,g->master)==0) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
map_foreachinarea(skill_area_sub,
src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
src,skillid,skilllv,tick, flag|BCT_ALL|1,
skill_castend_nodamage_id);
}
}
break;
case GD_RESTORE:
{
struct guild *g = NULL;
// Only usable during WoE
if (!agit_flag) {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 0;
}
if(flag&1) {
if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
int hp, sp;
hp = dstsd->status.max_hp*0.9;
sp = dstsd->status.max_sp*0.9;
sp = dstsd->status.sp + sp <= dstsd->status.max_sp ? sp : dstsd->status.max_sp - dstsd->status.sp;
clif_skill_nodamage(src,bl,AL_HEAL,hp,1);
battle_heal(NULL,bl,hp,sp,0);
}
}
else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
strcmp(sd->status.name,g->master)==0) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
map_foreachinarea(skill_area_sub,
src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
src,skillid,skilllv,tick, flag|BCT_ALL|1,
skill_castend_nodamage_id);
}
}
break;
case GD_EMERGENCYCALL:
{
int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0};
int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0};
int c, j = 0;
struct guild *g = NULL;
// Only usable during WoE
if (!agit_flag) {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 0;
}
// i don't know if it actually summons in a circle, but oh well. ;P
if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
strcmp(sd->status.name,g->master)==0) {
for(i = 0; i < g->max_member; i++, j++) {
if (j>8) j=0;
if ((dstsd = g->member[i].sd) != NULL && sd != dstsd &&
!map[sd->bl.m].flag.nowarpto && !map[dstsd->bl.m].flag.nowarp) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if ((c=read_gat(sd->bl.m,sd->bl.x+dx[j],sd->bl.y+dy[j]))==1 || c==5)
dx[j] = dy[j] = 0;
pc_setpos(dstsd, sd->mapname, sd->bl.x+dx[j], sd->bl.y+dy[j], 2);
}
}
}
}
break;
default:
printf("Unknown skill used:%d\n",skillid);
map_freeblock_unlock();
return 1;
}
map_freeblock_unlock();
return 0;
}
/*==========================================
* �X�L���g�p�i�r�������AID�w��j
*------------------------------------------
*/
int skill_castend_id( int tid, unsigned int tick, int id,int data )
{
struct map_session_data* sd = map_id2sd(id)/*,*target_sd=NULL*/;
struct block_list *bl;
int range,inf2;
nullpo_retr(0, sd);
if( sd->bl.prev == NULL ) //prev�������̂͂���Ȃ́H
return 0;
if(sd->skillid != SA_CASTCANCEL && sd->skilltimer != tid ) /* �^�C�}ID�̊m�F */
return 0;
if(sd->skillid != SA_CASTCANCEL && sd->skilltimer != -1 && pc_checkskill(sd,SA_FREECAST) > 0) {
sd->speed = sd->prev_speed;
clif_updatestatus(sd,SP_SPEED);
}
if(sd->skillid != SA_CASTCANCEL)
sd->skilltimer=-1;
if((bl=map_id2bl(sd->skilltarget))==NULL || bl->prev==NULL) {
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
if(sd->bl.m != bl->m || pc_isdead(sd)) { //�}�b�v���Ⴄ������������ł���
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
if(sd->skillid == PR_LEXAETERNA) {
struct status_change *sc_data = battle_get_sc_data(bl);
if(sc_data && (sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0))) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
}
else if(sd->skillid == RG_BACKSTAP) {
int dir = map_calc_dir(&sd->bl,bl->x,bl->y),t_dir = battle_get_dir(bl);
int dist = distance(sd->bl.x,sd->bl.y,bl->x,bl->y);
if(bl->type != BL_SKILL && (dist == 0 || map_check_dir(dir,t_dir))) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
}
inf2 = skill_get_inf2(sd->skillid);
if( ( (skill_get_inf(sd->skillid)&1) || inf2&4 ) && // �މ�G??�W�`�F�b�N
battle_check_target(&sd->bl,bl, BCT_ENEMY)<=0 ) {
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
if(inf2 & 0xC00 && sd->bl.id != bl->id) {
int fail_flag = 1;
if(inf2 & 0x400 && battle_check_target(&sd->bl,bl, BCT_PARTY) > 0)
fail_flag = 0;
if(inf2 & 0x800 && sd->status.guild_id > 0 && sd->status.guild_id == battle_get_guild_id(bl))
fail_flag = 0;
if(fail_flag) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
}
range = skill_get_range(sd->skillid,sd->skilllv);
if(range < 0)
range = battle_get_range(&sd->bl) - (range + 1);
range += battle_config.pc_skill_add_range;
if((sd->skillid == MO_EXTREMITYFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) ||
(sd->skillid == CH_TIGERFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) ||
(sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) ||
(sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == CH_TIGERFIST))
range += skill_get_blewcount(MO_COMBOFINISH,sd->sc_data[SC_COMBO].val2);
if(battle_config.skill_out_range_consume) { // changed to allow casting when target walks out of range [Valaris]
if(range < distance(sd->bl.x,sd->bl.y,bl->x,bl->y)) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
}
if(!skill_check_condition(sd,1)) { /* �g�p?���`�F�b�N */
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
sd->skillitem = sd->skillitemlv = -1;
if(battle_config.skill_out_range_consume) {
if(range < distance(sd->bl.x,sd->bl.y,bl->x,bl->y)) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
sd->canmove_tick = tick;
return 0;
}
}
if(battle_config.pc_skill_log)
printf("PC %d skill castend skill=%d\n",sd->bl.id,sd->skillid);
pc_stop_walking(sd,0);
switch( skill_get_nk(sd->skillid) )
{
/* �U?�n/��������n */
case 0: case 2:
skill_castend_damage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0);
break;
case 1:/* �x���n */
if( (sd->skillid==AL_HEAL || (sd->skillid==ALL_RESURRECTION && bl->type != BL_PC) || sd->skillid==PR_ASPERSIO) && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
skill_castend_damage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0);
else
skill_castend_nodamage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0);
break;
}
return 0;
}
/*==========================================
* �X�L���g�p�i�r�������A�ꏊ�w���?�ۂ�?���j
*------------------------------------------
*/
int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skilllv,unsigned int tick,int flag)
{
struct map_session_data *sd=NULL;
int i,tmpx = 0,tmpy = 0, x1 = 0, y1 = 0;
if(skilllv <= 0) return 0;
nullpo_retr(0, src);
if(src->type==BL_PC){
nullpo_retr(0, sd=(struct map_session_data *)src);
}
if( skillid != WZ_METEOR &&
skillid != WZ_SIGHTRASHER &&
skillid != AM_CANNIBALIZE &&
skillid != AM_SPHEREMINE)
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
if (skillnotok(skillid, sd)) // [MouseJstr]
return 0;
switch(skillid)
{
case PR_BENEDICTIO: /* ��?�~�� */
skill_area_temp[1]=src->id;
map_foreachinarea(skill_area_sub,
src->m,x-1,y-1,x+1,y+1,0,
src,skillid,skilllv,tick, flag|BCT_NOENEMY|1,
skill_castend_nodamage_id);
map_foreachinarea(skill_area_sub,
src->m,x-1,y-1,x+1,y+1,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
break;
case BS_HAMMERFALL: /* �n���}?�t�H?�� */
skill_area_temp[1]=src->id;
skill_area_temp[2]=x;
skill_area_temp[3]=y;
map_foreachinarea(skill_area_sub,
src->m,x-2,y-2,x+2,y+2,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|2,
skill_castend_nodamage_id);
break;
case HT_DETECTING: /* �f�B�e�N�e�B���O */
{
const int range=7;
map_foreachinarea( skill_status_change_timer_sub,
src->m, src->x-range, src->y-range, src->x+range,src->y+range,0,
src,SC_SIGHT,tick);
}
break;
case MG_SAFETYWALL: /* �Z�C�t�e�B�E�H?�� */
case MG_FIREWALL: /* �t�@�C��?�E�H?�� */
case MG_THUNDERSTORM: /* �T���_?�X�g?�� */
case AL_PNEUMA: /* �j��?�} */
case WZ_ICEWALL: /* �A�C�X�E�H?�� */
case WZ_FIREPILLAR: /* �t�@�C�A�s��? */
case WZ_SIGHTRASHER:
case WZ_QUAGMIRE: /* �N�@�O�}�C�A */
case WZ_VERMILION: /* ��?�h�I�u���@?�~���I�� */
case WZ_FROSTNOVA: /* �t���X�g�m���@ */
case WZ_STORMGUST: /* �X�g?���K�X�g */
case WZ_HEAVENDRIVE: /* �w�����Y�h���C�u */
case PR_SANCTUARY: /* �T���N�`���A�� */
case PR_MAGNUS: /* �}�O�k�X�G�N�\�V�Y�� */
case CR_GRANDCROSS: /* �O�����h�N���X */
case HT_SKIDTRAP: /* �X�L�b�h�g���b�v */
case HT_LANDMINE: /* �����h�}�C�� */
case HT_ANKLESNARE: /* �A���N���X�l�A */
case HT_SHOCKWAVE: /* �V���b�N�E�F?�u�g���b�v */
case HT_SANDMAN: /* �T���h�}�� */
case HT_FLASHER: /* �t���b�V��? */
case HT_FREEZINGTRAP: /* �t��?�W���O�g���b�v */
case HT_BLASTMINE: /* �u���X�g�}�C�� */
case HT_CLAYMORETRAP: /* �N���C���A?�g���b�v */
case AS_VENOMDUST: /* �x�m���_�X�g */
case AM_DEMONSTRATION: /* �f�����X�g��?�V���� */
case PF_SPIDERWEB: /* �X�p�C�_?�E�F�b�u */
case PF_FOGWALL: /* �t�H�O�E�H?�� */
case HT_TALKIEBOX: /* �g?�L?�{�b�N�X */
skill_unitsetting(src,skillid,skilllv,x,y,0);
break;
case RG_GRAFFITI: /* Graffiti [Valaris] */
skill_clear_unitgroup(src);
skill_unitsetting(src,skillid,skilllv,x,y,0);
break;
case SA_VOLCANO: /* �{���P?�m */
case SA_DELUGE: /* �f����?�W */
case SA_VIOLENTGALE: /* �o�C�I�����g�Q�C�� */
case SA_LANDPROTECTOR: /* �����h�v���e�N�^? */
skill_clear_element_field(src);//?�Ɏ�����?�����Ă���?������N���A
skill_unitsetting(src,skillid,skilllv,x,y,0);
break;
case WZ_METEOR: //���e�I�X�g?��
{
int flag=0;
for(i=0;i<2+(skilllv>>1);i++) {
int j=0, c;
do {
tmpx = x + (rand()%7 - 3);
tmpy = y + (rand()%7 - 3);
if(tmpx < 0)
tmpx = 0;
else if(tmpx >= map[src->m].xs)
tmpx = map[src->m].xs - 1;
if(tmpy < 0)
tmpy = 0;
else if(tmpy >= map[src->m].ys)
tmpy = map[src->m].ys - 1;
j++;
} while(((c=map_getcell(src->m,tmpx,tmpy))==1 || c==5) && j<100);
if(j >= 100)
continue;
if(flag==0){
clif_skill_poseffect(src,skillid,skilllv,tmpx,tmpy,tick);
flag=1;
}
if(i > 0)
skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,(x1<<16)|y1,flag);
x1 = tmpx;
y1 = tmpy;
}
skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,-1,flag);
}
break;
case AL_WARP: /* ��?�v�|?�^�� */
if(sd) {
if(map[sd->bl.m].flag.noteleport) /* �e���|�֎~ */
break;
clif_skill_warppoint(sd,sd->skillid,sd->status.save_point.map,
(sd->skilllv>1)?sd->status.memo_point[0].map:"",
(sd->skilllv>2)?sd->status.memo_point[1].map:"",
(sd->skilllv>3)?sd->status.memo_point[2].map:"");
}
break;
case MO_BODYRELOCATION:
if(sd){
pc_movepos(sd,x,y);
}else if( src->type==BL_MOB )
mob_warp((struct mob_data *)src,-1,x,y,0);
break;
case AM_CANNIBALIZE: // �o�C�I�v�����g
if(sd){
int mx,my,id=0;
struct mob_data *md;
mx = x;// + (rand()%10 - 5);
my = y;// + (rand()%10 - 5);
id=mob_once_spawn(sd,"this",mx,my,"--ja--",1118,1,"");
if( (md=(struct mob_data *)map_id2bl(id)) !=NULL ){
md->master_id=sd->bl.id;
md->hp=2210+skilllv*200;
md->state.special_mob_ai=1;
md->deletetimer=add_timer(gettick()+skill_get_time(skillid,skilllv),mob_timer_delete,id,0);
}
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
}
break;
case AM_SPHEREMINE: // �X�t�B�A?�}�C��
if(sd){
int mx,my,id=0;
struct mob_data *md;
mx = x;// + (rand()%10 - 5);
my = y;// + (rand()%10 - 5);
id=mob_once_spawn(sd,"this",mx,my,"--ja--",1142,1,"");
if( (md=(struct mob_data *)map_id2bl(id)) !=NULL ){
md->master_id=sd->bl.id;
md->hp=1000+skilllv*200;
md->state.special_mob_ai=2;
md->deletetimer=add_timer(gettick()+skill_get_time(skillid,skilllv),mob_timer_delete,id,0);
}
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
}
break;
// Slim Pitcher [Celest]
case CR_SLIMPITCHER:
{
if (sd) {
int x = skilllv%11 - 1;
int i = pc_search_inventory(sd,skill_db[skillid].itemid[x]);
if(i < 0 || skill_db[skillid].itemid[x] <= 0 || sd->inventory_data[i] == NULL ||
sd->status.inventory[i].amount < skill_db[skillid].amount[x]) {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
sd->state.potionpitcher_flag = 1;
sd->potion_hp = 0;
run_script(sd->inventory_data[i]->use_script,0,sd->bl.id,0);
pc_delitem(sd,i,skill_db[skillid].amount[x],0);
sd->state.potionpitcher_flag = 0;
if(sd->potion_hp > 0) {
map_foreachinarea(skill_area_sub,
src->m,x-3,y-3,x+3,y+3,0,
src,skillid,skilllv,tick,flag|BCT_ALL|1,
skill_castend_nodamage_id);
}
}
}
break;
}
return 0;
}
/*==========================================
* �X�L���g�p�i�r�������Amap�w��j
*------------------------------------------
*/
int skill_castend_map( struct map_session_data *sd,int skill_num, const char *map)
{
int x=0,y=0;
nullpo_retr(0, sd);
if( sd->bl.prev == NULL || pc_isdead(sd) )
return 0;
if(skillnotok(skill_num, sd))
return 0;
if( sd->opt1>0 || sd->status.option&2 )
return 0;
//�X�L�����g���Ȃ�?�Ԉُ풆
if(sd->sc_data){
if( sd->sc_data[SC_DIVINA].timer!=-1 ||
sd->sc_data[SC_ROKISWEIL].timer!=-1 ||
sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||
sd->sc_data[SC_STEELBODY].timer != -1 ||
sd->sc_data[SC_DANCING].timer!=-1 ||
sd->sc_data[SC_BERSERK].timer != -1 ||
sd->sc_data[SC_MARIONETTE].timer != -1)
return 0;
if (sd->sc_data[SC_BLOCKSKILL].timer!=-1)
if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3)
return 0;
}
if( skill_num != sd->skillid) /* �s���p�P�b�g�炵�� */
return 0;
pc_stopattack(sd);
if(battle_config.pc_skill_log)
printf("PC %d skill castend skill =%d map=%s\n",sd->bl.id,skill_num,map);
pc_stop_walking(sd,0);
if(strcmp(map,"cancel")==0)
return 0;
switch(skill_num){
case AL_TELEPORT: /* �e���|?�g */
if(strcmp(map,"Random")==0)
pc_randomwarp(sd,3);
else
pc_setpos(sd,sd->status.save_point.map,
sd->status.save_point.x,sd->status.save_point.y,3);
break;
case AL_WARP: /* ��?�v�|?�^�� */
{
const struct point *p[]={
&sd->status.save_point,&sd->status.memo_point[0],
&sd->status.memo_point[1],&sd->status.memo_point[2],
};
struct skill_unit_group *group;
int i;
int maxcount=0;
if((maxcount = skill_get_maxcount(sd->skillid)) > 0) {
int c;
for(i=c=0;i<MAX_SKILLUNITGROUP;i++) {
if(sd->skillunit[i].alive_count > 0 && sd->skillunit[i].skill_id == sd->skillid)
c++;
}
if(c >= maxcount) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = gettick();
sd->canmove_tick = gettick();
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
}
if(sd->skilllv <= 0) return 0;
for(i=0;i<sd->skilllv;i++){
if(strcmp(map,p[i]->map)==0){
x=p[i]->x;
y=p[i]->y;
break;
}
}
if(x==0 || y==0) /* �s���p�P�b�g�H */
return 0;
if(!skill_check_condition(sd,3))
return 0;
if((group=skill_unitsetting(&sd->bl,sd->skillid,sd->skilllv,sd->skillx,sd->skilly,0))==NULL)
return 0;
group->valstr=(char *)aCalloc(24,sizeof(char));
memcpy(group->valstr,map,24);
group->val2=(x<<16)|y;
}
break;
}
return 0;
}
/*==========================================
* �X�L�����j�b�g�ݒ�?��
*------------------------------------------
*/
struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag)
{
struct skill_unit_group *group;
int i,count=1,limit=10000,val1=0,val2=0;
int target=BCT_ENEMY,interval=1000,range=0;
int dir=0,aoe_diameter=0; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills
struct status_change *sc_data = battle_get_sc_data(src); // for firewall and fogwall - celest
nullpo_retr(0, src);
switch(skillid){ /* �ݒ� */
case MG_SAFETYWALL: /* �Z�C�t�e�B�E�H?�� */
limit=skill_get_time(skillid,skilllv);
val2=skilllv+1;
interval = -1;
target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL;
break;
case MG_FIREWALL: /* �t�@�C��?�E�H?�� */
if(src->x == x && src->y == y)
dir = 2;
else
dir=map_calc_dir(src,x,y);
if(dir&1) count=5;
else count=3;
limit=skill_get_time(skillid,skilllv);
if(sc_data) {
if (sc_data[SC_VIOLENTGALE].timer!=-1) limit *= 1.5;
}
// check for sc_data first - Celest
// if (((struct map_session_data *)src)->sc_data[SC_VIOLENTGALE].timer!=-1)
// limit *= 1.5;
val2=4+skilllv;
interval=1;
break;
case AL_PNEUMA: /* �j��?�} */
limit=skill_get_time(skillid,skilllv);
interval = -1;
target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL;
count = 9;
break;
case AL_WARP: /* ��?�v�|?�^�� */
target=BCT_ALL;
val1=skilllv+6;
if(flag==0)
limit=2000;
else
limit=skill_get_time(skillid,skilllv);
break;
case PR_SANCTUARY: /* �T���N�`���A�� */
count=21;
limit=skill_get_time(skillid,skilllv);
val1=skilllv+3;
val2=(skilllv>6)?777:skilllv*100;
target=BCT_ALL;
range=1;
break;
case PR_MAGNUS: /* �}�O�k�X�G�N�\�V�Y�� */
count=33;
limit=skill_get_time(skillid,skilllv);
interval=3000;
break;
case WZ_FIREPILLAR: /* �t�@�C�A?�s��? */
if(flag==0)
limit=skill_get_time(skillid,skilllv);
else
limit=1000;
interval=2000;
val1=skilllv+2;
if(skilllv < 6)
range=1;
else
range=2;
break;
case MG_THUNDERSTORM: /* �T���_?�X�g?�� */
limit=500;
range=1;
break;
case WZ_FROSTNOVA: /* �t���X�g�m���@ */
limit=500;
range=5;
break;
case WZ_HEAVENDRIVE: /* �w�����Y�h���C�u */
limit=500;
range=2;
break;
case WZ_METEOR: /* ���e�I�X�g?�� */
limit=500;
range=3;
break;
case WZ_SIGHTRASHER:
limit=500;
count=41;
break;
case WZ_VERMILION: /* ��?�h�I�u���@?�~���I�� */
limit=4100;
interval=1000;
range=6;
break;
case WZ_ICEWALL: /* �A�C�X�E�H?�� */
limit=skill_get_time(skillid,skilllv);
count=5;
break;
case WZ_STORMGUST: /* �X�g?���K�X�g */
limit=4600;
interval=450;
range=5;
break;
case WZ_QUAGMIRE: /* �N�@�O�}�C�A */
limit=skill_get_time(skillid,skilllv);
interval=200;
count=25;
break;
case HT_SANDMAN: /* �T���h�}�� */
case HT_CLAYMORETRAP: /* �N���C���A?�g���b�v */
limit=skill_get_time(skillid,skilllv);
range=2;
break;
case HT_SKIDTRAP: /* �X�L�b�h�g���b�v */
case HT_LANDMINE: /* �����h�}�C�� */
case HT_ANKLESNARE: /* �A���N���X�l�A */
case PF_SPIDERWEB: /* �X�p�C�_?�E�F�b�u */
case HT_FLASHER: /* �t���b�V��? */
case HT_FREEZINGTRAP: /* �t��?�W���O�g���b�v */
case HT_BLASTMINE: /* �u���X�g�}�C�� */
limit=skill_get_time(skillid,skilllv);
range=1;
break;
case HT_TALKIEBOX: /* �g?�L?�{�b�N�X */
limit=skill_get_time(skillid,skilllv);
range=1;
target=BCT_ALL;
break;
case HT_SHOCKWAVE: /* �V���b�N�E�F?�u�g���b�v */
limit=skill_get_time(skillid,skilllv);
range=1;
val1=skilllv*15+10;
break;
case AS_VENOMDUST: /* �x�m���_�X�g */
limit=skill_get_time(skillid,skilllv);
interval=1000;
count=5;
break;
case CR_GRANDCROSS: /* �O�����h�N���X */
count=29;
limit=1000;
interval=300;
break;
case SA_VOLCANO: /* �{���P?�m */
case SA_DELUGE: /* �f����?�W */
case SA_VIOLENTGALE: /* �o�C�I�����g�Q�C�� */
limit=skill_get_time(skillid,skilllv);
count=skilllv<=2?25:(skilllv<=4?49:81);
target=BCT_ALL;
break;
case SA_LANDPROTECTOR: /* �O�����h�N���X */
limit=skill_get_time(skillid,skilllv); // changed to get duration from cast_db (moonsoul)
val1=skilllv*15+10;
aoe_diameter=skilllv+skilllv%2+5;
target=BCT_ALL;
count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul)
break;
case BD_LULLABY: /* �q��S */
case BD_ETERNALCHAOS: /* �G�^?�i���J�I�X */
case BD_ROKISWEIL: /* ���L�̋��� */
count=81;
limit=skill_get_time(skillid,skilllv);
range=5;
target=BCT_ALL;
break;
case BD_RICHMANKIM:
case BD_DRUMBATTLEFIELD: /* ?���ۂ̋��� */
case BD_RINGNIBELUNGEN: /* �j?�x�����O�̎w�� */
case BD_INTOABYSS: /* �[���̒��� */
case BD_SIEGFRIED: /* �s���g�̃W?�N�t��?�h */
count=81;
limit=skill_get_time(skillid,skilllv);
range=5;
target=BCT_PARTY;
break;
case BA_WHISTLE: /* ���J */
count=49;
limit=skill_get_time(skillid,skilllv);
range=5;
target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1;
val2 = ((battle_get_agi(src)/10)&0xffff)<<16;
val2 |= (battle_get_luk(src)/10)&0xffff;
break;
case DC_HUMMING: /* �n�~���O */
count=49;
limit=skill_get_time(skillid,skilllv);
range=5;
target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = battle_get_dex(src)/10;
break;
case BA_DISSONANCE: /* �s���a�� */
case DC_UGLYDANCE: /* ��������ȃ_���X */
count=49;
limit=skill_get_time(skillid,skilllv);
range=5;
target=BCT_ENEMY;
break;
case DC_DONTFORGETME: /* ����Y��Ȃ��Łc */
count=49;
limit=skill_get_time(skillid,skilllv);
range=5;
target=BCT_ENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = ((battle_get_str(src)/20)&0xffff)<<16;
val2 |= (battle_get_agi(src)/10)&0xffff;
break;
case BA_POEMBRAGI: /* �u���M�̎� */
count=49;
limit=skill_get_time(skillid,skilllv);
range=5;
target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON);
val2 = ((battle_get_dex(src)/10)&0xffff)<<16;
val2 |= (battle_get_int(src)/5)&0xffff;
break;
case BA_APPLEIDUN: /* �C�h�D���̗ь� */
count=49;
limit=skill_get_time(skillid,skilllv);
range=5;
target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = ((pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON))&0xffff)<<16;
else
val1 = 0;
val1 |= (battle_get_vit(src))&0xffff;
val2 = 0;//�p�^�C���J�E���^(6�b?��1?��)
break;
case DC_SERVICEFORYOU: /* �T?�r�X�t�H?��? */
count=49;
limit=skill_get_time(skillid,skilllv);
range=5;
target=BCT_PARTY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = battle_get_int(src)/10;
break;
case BA_ASSASSINCROSS: /* �[�z�̃A�T�V���N���X */
count=49;
limit=skill_get_time(skillid,skilllv);
range=5;
target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1;
val2 = battle_get_agi(src)/20;
break;
case DC_FORTUNEKISS: /* �K�^�̃L�X */
count=49;
limit=skill_get_time(skillid,skilllv);
range=5;
target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = battle_get_luk(src)/10;
break;
case AM_DEMONSTRATION: /* �f�����X�g��?�V���� */
limit=skill_get_time(skillid,skilllv);
interval=1000;
range=1;
target=BCT_ENEMY;
break;
case WE_CALLPARTNER: /* ���Ȃ��Ɉ������� */
limit=skill_get_time(skillid,skilllv);
range=-1;
break;
case HP_BASILICA: /* �o�W���J */
limit=skill_get_time(skillid,skilllv);
target=BCT_ALL;
range=3;
//Fix to prevent the priest from walking while Basilica is up.
battle_stopwalking(src,1);
//skill_status_change_start(src,SC_ANKLE,skilllv,0,0,0,limit,0);
//sd->canmove_tick = gettick() + limit; // added later [celest]
break;
case PA_GOSPEL: /* �S�X�y�� */
count=49;
target=BCT_PARTY;
limit=skill_get_time(skillid,skilllv);
break;
case CG_MOONLIT:
range=1;
target=BCT_ALL;
limit=skill_get_time(skillid,skilllv);
break;
case PF_FOGWALL: /* �t�H�O�E�H?�� */
count=15;
limit=skill_get_time(skillid,skilllv);
if(sc_data) {
if (sc_data[SC_DELUGE].timer!=-1) limit *= 2;
}
break;
case RG_GRAFFITI: /* Graffiti */
count=1; // Leave this at 1 [Valaris]
limit=600000; // Time length [Valaris]
break;
case GD_LEADERSHIP:
case GD_GLORYWOUNDS:
case GD_SOULCOLD:
case GD_HAWKEYES:
range=2;
target=BCT_NOENEMY;
limit=600000;
break;
}
nullpo_retr(NULL, group=skill_initunitgroup(src,count,skillid,skilllv,skill_get_unit_id(skillid,flag&1)));
group->limit=limit;
group->val1=val1;
group->val2=val2;
group->target_flag=target;
group->interval=interval;
group->range=range;
if(skillid==HT_TALKIEBOX ||
skillid==RG_GRAFFITI){
group->valstr=calloc(80, 1);
if(group->valstr==NULL){
printf("skill_castend_map: out of memory !\n");
exit(1);
}
memcpy(group->valstr,talkie_mes,80);
}
for(i=0;i<count;i++){
struct skill_unit *unit;
int ux=x,uy=y,val1=skilllv,val2=0,limit=group->limit,alive=1;
int range=group->range;
switch(skillid){ /* �ݒ� */
case AL_PNEUMA: /* �j��?�} */
{
static const int dx[9]={-1, 0, 1,-1, 0, 1,-1, 0, 1};
static const int dy[9]={-1,-1,-1, 0, 0, 0, 1, 1, 1};
ux+=dx[i];
uy+=dy[i];
}
break;
case MG_FIREWALL: /* �t�@�C��?�E�H?�� */
{
if(dir&1){ /* �ߔz�u */
static const int dx[][5]={
{ 1,1,0,0,-1 }, { -1,-1,0,0,1 },
},dy[][5]={
{ 1,0,0,-1,-1 }, { 1,0,0,-1,-1 },
};
ux+=dx[(dir>>1)&1][i];
uy+=dy[(dir>>1)&1][i];
}else{ /* �㉺�z�u */
if(dir%4==0) /* �㉺ */
ux+=i-1;
else /* ���E */
uy+=i-1;
}
val2=group->val2;
}
break;
case PR_SANCTUARY: /* �T���N�`���A�� */
{
static const int dx[]={
-1,0,1, -2,-1,0,1,2, -2,-1,0,1,2, -2,-1,0,1,2, -1,0,1 };
static const int dy[]={
-2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0, 1,1,1,1,1, 2,2,2, };
ux+=dx[i];
uy+=dy[i];
}
break;
case PR_MAGNUS: /* �}�O�k�X�G�N�\�V�Y�� */
{
static const int dx[]={ -1,0,1, -1,0,1, -3,-2,-1,0,1,2,3,
-3,-2,-1,0,1,2,3, -3,-2,-1,0,1,2,3, -1,0,1, -1,0,1, };
static const int dy[]={
-3,-3,-3, -2,-2,-2, -1,-1,-1,-1,-1,-1,-1,
0,0,0,0,0,0,0, 1,1,1,1,1,1,1, 2,2,2, 3,3,3 };
ux+=dx[i];
uy+=dy[i];
}
break;
case WZ_SIGHTRASHER:
{
static const int dx[]={
-5, 0, 5, -4, 0, 4, -3, 0, 3, -2, 0, 2, -1, 0, 1, -5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, -1, 0, 1, -2, 0, 2, -3, 0, 3, -4, 0, 4, -5, 0, 5 };
static const int dy[]={
-5,-5,-5, -4,-4,-4, -3,-3,-3, -2,-2,-2, -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
ux+=dx[i];
uy+=dy[i];
}
break;
case WZ_ICEWALL: /* �A�C�X�E�H?�� */
{
static const int dirx[8]={0,-1,-1,-1,0,1,1,1};
static const int diry[8]={1,1,0,-1,-1,-1,0,1};
if(skilllv <= 1)
val1 = 500;
else
val1 = 200 + 200*skilllv;
if(src->x == x && src->y == y)
dir = 2;
else
dir=map_calc_dir(src,x,y);
ux+=(2-i)*diry[dir];
uy+=(i-2)*dirx[dir];
}
break;
case WZ_QUAGMIRE: /* �N�@�O�}�C�A */
ux+=(i%5-2);
uy+=(i/5-2);
if(i==12)
range=2;
else
range=-1;
break;
case AS_VENOMDUST: /* �x�m���_�X�g */
{
static const int dx[]={-1,0,0,0,1};
static const int dy[]={0,-1,0,1,0};
ux+=dx[i];
uy+=dy[i];
}
break;
case CR_GRANDCROSS: /* �O�����h�N���X */
{
static const int dx[]={
0, 0, -1,0,1, -2,-1,0,1,2, -4,-3,-2,-1,0,1,2,3,4, -2,-1,0,1,2, -1,0,1, 0, 0, };
static const int dy[]={
-4, -3, -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0,0,0,0,0, 1,1,1,1,1, 2,2,2, 3, 4, };
ux+=dx[i];
uy+=dy[i];
}
break;
case SA_VOLCANO: /* �{���P?�m */
case SA_DELUGE: /* �f����?�W */
case SA_VIOLENTGALE: /* �o�C�I�����g�Q�C�� */
{
int u_range=0,central=0;
if(skilllv<=2){
u_range=2;
central=12;
}else if(skilllv<=4){
u_range=3;
central=24;
}else if(skilllv>=5){
u_range=4;
central=40;
}
ux+=(i%(u_range*2+1)-u_range);
uy+=(i/(u_range*2+1)-u_range);
if(i==central)
range=u_range;//�����̃��j�b�g��?�ʔ�?�͑S��?
else
range=-1;//�����ȊO�̃��j�b�g�͏���
}
break;
case SA_LANDPROTECTOR: /* �����h�v���e�N�^? */
{
int u_range=0;
if(skilllv<=2) u_range=3;
else if(skilllv<=4) u_range=4;
else if(skilllv>=5) u_range=5;
ux+=(i%(u_range*2+1)-u_range);
uy+=(i/(u_range*2+1)-u_range);
range=0;
}
break;
/* �_���X�Ȃ� */
case BD_LULLABY: /* �q��� */
case BD_RICHMANKIM: /* �j�����h�̉� */
case BD_ETERNALCHAOS: /* �i���̍��� */
case BD_DRUMBATTLEFIELD:/* ?���ۂ̋��� */
case BD_RINGNIBELUNGEN: /* �j?�x�����O�̎w�� */
case BD_ROKISWEIL: /* ���L�̋��� */
case BD_INTOABYSS: /* �[���̒��� */
case BD_SIEGFRIED: /* �s���g�̃W?�N�t��?�h */
ux+=(i%9-4);
uy+=(i/9-4);
if(i==40)
range=4; /* ���S�̏ꍇ�͔�?��4�ɃI?�o?���C�h */
else
range=-1; /* ���S����Ȃ��ꍇ�͔�?��-1�ɃI?�o?���C�h */
break;
case BA_DISSONANCE: /* �s���a�� */
case BA_WHISTLE: /* ���J */
case BA_ASSASSINCROSS: /* �[�z�̃A�T�V���N���X */
case BA_POEMBRAGI: /* �u���M�̎� */
case BA_APPLEIDUN: /* �C�h�D���̗ь� */
case DC_UGLYDANCE: /* ��������ȃ_���X */
case DC_HUMMING: /* �n�~���O */
case DC_DONTFORGETME: /* ����Y��Ȃ��Łc */
case DC_FORTUNEKISS: /* �K�^�̃L�X */
case DC_SERVICEFORYOU: /* �T?�r�X�t�H?��? */
case CG_MOONLIT:
ux+=(i%7-3);
uy+=(i/7-3);
if(i==40)
range=4; /* ���S�̏ꍇ�͔�?��4�ɃI?�o?���C�h */
else
range=-1; /* ���S����Ȃ��ꍇ�͔�?��-1�ɃI?�o?���C�h */
break;
case PA_GOSPEL: /* �S�X�y�� */
ux+=(i%7-3);
uy+=(i/7-3);
break;
case PF_FOGWALL: /* �t�H�O�E�H?�� */
ux+=(i%5-2);
uy+=(i/5-1);
break;
case RG_GRAFFITI: /* Graffiti [Valaris] */
ux+=(i%5-2);
uy+=(i/5-2);
break;
}
//����X�L���̏ꍇ�ݒu���W��Ƀ����h�v���e�N�^?���Ȃ����`�F�b�N
if(range<=0)
map_foreachinarea(skill_landprotector,src->m,ux,uy,ux,uy,BL_SKILL,skillid,&alive);
if(skillid==WZ_ICEWALL && alive){
val2=map_getcell(src->m,ux,uy);
if(val2==5 || val2==1)
alive=0;
else {
map_setcell(src->m,ux,uy,5);
clif_changemapcell(src->m,ux,uy,5,0);
}
}
if(alive){
nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy));
unit->val1=val1;
unit->val2=val2;
unit->limit=limit;
unit->range=range;
// [celest]
if (sc_data) {
// attach the unit's id to the caster
switch (skillid) {
case HP_BASILICA:
if (sc_data[SC_BASILICA].timer!=-1)
sc_data[SC_BASILICA].val4 = (int)unit;
break;
case GD_LEADERSHIP:
sc_data[SC_LEADERSHIP].val4 = (int)unit;
break;
case GD_GLORYWOUNDS:
sc_data[SC_GLORYWOUNDS].val4 = (int)unit;
break;
case GD_SOULCOLD:
sc_data[SC_SOULCOLD].val4 = (int)unit;
break;
case GD_HAWKEYES:
sc_data[SC_HAWKEYES].val4 = (int)unit;
break;
}
}
}
}
return group;
}
/*==========================================
* �X�L�����j�b�g��?���C�x���g
*------------------------------------------
*/
int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int tick)
{
struct skill_unit_group *sg;
struct block_list *ss;
struct skill_unit_group_tickset *ts;
struct map_session_data *srcsd=NULL;
int diff,goflag,splash_count=0;
nullpo_retr(0, src);
nullpo_retr(0, bl);
if( bl->prev==NULL || !src->alive || (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl) ) )
return 0;
nullpo_retr(0, sg=src->group);
nullpo_retr(0, ss=map_id2bl(sg->src_id));
if(ss->type == BL_PC)
nullpo_retr(0, srcsd=(struct map_session_data *)ss);
if(srcsd && srcsd->chatID)
return 0;
if( bl->type!=BL_PC && bl->type!=BL_MOB )
return 0;
nullpo_retr(0, ts=skill_unitgrouptickset_search( bl, sg->group_id));
diff=DIFF_TICK(tick,ts->tick);
goflag=(diff>sg->interval || diff<0);
if (sg->skill_id == CR_GRANDCROSS && !battle_config.gx_allhit) // �d�Ȃ��Ă�����3HIT���Ȃ�
goflag = (diff>sg->interval*map_count_oncell(bl->m,bl->x,bl->y) || diff<0);
//?�ۂ�LP��ɋ���ꍇ�͖�?
map_foreachinarea(skill_landprotector,bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,0,&goflag);
if(!goflag)
return 0;
ts->tick=tick;
ts->group_id=sg->group_id;
switch(sg->unit_id){
case 0x83: /* �T���N�`���A�� */
{
int race=battle_get_race(bl);
int damage_flag = (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6)? 1:0;
if( battle_get_hp(bl)>=battle_get_max_hp(bl) && !damage_flag)
break;
if((sg->val1--)<=0){
skill_delunitgroup(sg);
return 0;
}
if(!damage_flag) {
int heal=sg->val2;
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage)
heal=0; /* ?��峃J?�h�i�q?���ʂO�j */
clif_skill_nodamage(&src->bl,bl,AL_HEAL,heal,1);
battle_heal(NULL,bl,heal,0,0);
}
else
skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
}
break;
case 0x84: /* �}�O�k�X�G�N�\�V�Y�� */
{
int race=battle_get_race(bl);
int damage_flag = (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6)? 1:0;
if(!damage_flag)
return 0;
skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
}
break;
case 0x85: /* �j��?�} */
{
struct skill_unit *unit2;
struct status_change *sc_data=battle_get_sc_data(bl);
int type=SC_PNEUMA;
if(sc_data && sc_data[type].timer==-1)
skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){
if(DIFF_TICK(sg->tick,unit2->group->tick)>0 )
skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
ts->tick-=sg->interval;
}
}
break;
case 0x7e: /* �Z�C�t�e�B�E�H?�� */
{
struct skill_unit *unit2;
struct status_change *sc_data=battle_get_sc_data(bl);
int type=SC_SAFETYWALL;
if(sc_data && sc_data[type].timer==-1)
skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){
if(sg->val1 < unit2->group->val1 )
skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
ts->tick-=sg->interval;
}
}
break;
case 0x86: /* ��?�h�I�u���@?�~���I��(���X�g?���K�X�g ���O�����h�N���X) */
skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
case 0x7f: /* �t�@�C��?�E�H?�� */
if( (src->val2--)>0)
skill_attack(BF_MAGIC,ss,&src->bl,bl,
sg->skill_id,sg->skill_lv,tick,0);
if( src->val2<=0 )
skill_delunit(src);
break;
case 0x87: /* �t�@�C�A?�s��?(?���O) */
skill_delunit(src);
skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1);
break;
case 0x88: /* �t�@�C�A?�s��?(?����) */
if(DIFF_TICK(tick,sg->tick) < 150)
//skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest]
break;
case 0x90: /* �X�L�b�h�g���b�v */
{
int i,c = skill_get_blewcount(sg->skill_id,sg->skill_lv);
if(map[bl->m].flag.gvg) c = 0;
for(i=0;i<c;i++)
skill_blown(&src->bl,bl,1|0x30000);
sg->unit_id = 0x8c;
clif_changelook(&src->bl,LOOK_BASE,sg->unit_id);
sg->limit=DIFF_TICK(tick,sg->tick)+1500;
}
break;
case 0x93: /* �����h�}�C�� */
skill_attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
sg->unit_id = 0x8c;
clif_changelook(&src->bl,LOOK_BASE,0x88);
sg->limit=DIFF_TICK(tick,sg->tick)+1500;
break;
case 0x8f: /* �u���X�g�}�C�� */
case 0x94: /* �V���b�N�E�F?�u�g���b�v */
case 0x95: /* �T���h�}�� */
case 0x96: /* �t���b�V��? */
case 0x97: /* �t��?�W���O�g���b�v */
case 0x98: /* �N���C���A?�g���b�v */
map_foreachinarea(skill_count_target,src->bl.m
,src->bl.x-src->range,src->bl.y-src->range
,src->bl.x+src->range,src->bl.y+src->range
,0,&src->bl,&splash_count);
map_foreachinarea(skill_trap_splash,src->bl.m
,src->bl.x-src->range,src->bl.y-src->range
,src->bl.x+src->range,src->bl.y+src->range
,0,&src->bl,tick,splash_count);
sg->unit_id = 0x8c;
clif_changelook(&src->bl,LOOK_BASE,sg->unit_id);
sg->limit=DIFF_TICK(tick,sg->tick)+1500;
break;
case 0x91: /* �A���N���X�l�A */
{
struct status_change *sc_data=battle_get_sc_data(bl);
if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){
int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE);
int sec=skill_get_time2(sg->skill_id,sg->skill_lv) - (double)battle_get_agi(bl)*0.1;
if(battle_get_mode(bl)&0x20)
sec = sec/5;
battle_stopwalking(bl,1);
skill_status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0);
if(moveblock) map_delblock(bl);
bl->x = src->bl.x;
bl->y = src->bl.y;
if(moveblock) map_addblock(bl);
if(bl->type == BL_MOB)
clif_fixmobpos((struct mob_data *)bl);
else if(bl->type == BL_PET)
clif_fixpetpos((struct pet_data *)bl);
else
clif_fixpos(bl);
clif_01ac(&src->bl);
sg->limit=DIFF_TICK(tick,sg->tick) + sec;
sg->val2=bl->id;
}
}
break;
case 0x80: /* ��?�v�|?�^��(?����) */
if(bl->type==BL_PC){
struct map_session_data *sd = (struct map_session_data *)bl;
if(sd && src->bl.m == bl->m && src->bl.x == bl->x && src->bl.y == bl->y && src->bl.x == sd->to_x && src->bl.y == sd->to_y) {
if( battle_config.chat_warpportal || !sd->chatID ){
if((sg->val1--)>0){
pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3);
if(sg->src_id == bl->id ||( strcmp(map[src->bl.m].name,sg->valstr) == 0 && src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) ))
skill_delunitgroup(sg);
}else
skill_delunitgroup(sg);
}
}
}else if(bl->type==BL_MOB && battle_config.mob_warpportal){
int m=map_mapname2mapid(sg->valstr);
struct mob_data *md;
md=(struct mob_data *)bl;
mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3);
}
break;
case 0x8e: /* �N�@�O�}�C�A */
{
int type=SkillStatusChangeTable[sg->skill_id];
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
if( battle_get_sc_data(bl)[type].timer==-1 )
skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
}
break;
case 0x92: /* �x�m���_�X�g */
{
struct status_change *sc_data=battle_get_sc_data(bl);
int type=SkillStatusChangeTable[sg->skill_id];
if( sc_data && sc_data[type].timer==-1 )
skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
}
break;
case 0x9a: /* �{���P?�m */
case 0x9b: /* �f����?�W */
case 0x9c: /* �o�C�I�����g�Q�C�� */
{
struct skill_unit *unit2;
struct status_change *sc_data=battle_get_sc_data(bl);
int type=SkillStatusChangeTable[sg->skill_id];
if(sc_data && sc_data[type].timer==-1)
skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){
if( DIFF_TICK(sg->tick,unit2->group->tick)>0 )
skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
ts->tick-=sg->interval;
}
} break;
case 0x9e: /* �q��S */
case 0x9f: /* �j�����h�̉� */
case 0xa0: /* �i���̍��� */
case 0xa1: /* ?���ۂ̋��� */
case 0xa2: /* �j?�x�����O�̎w�� */
case 0xa3: /* ���L�̋��� */
case 0xa4: /* �[���̒��� */
case 0xa5: /* �s���g�̃W?�N�t��?�h */
case 0xa6: /* �s���a�� */
case 0xa7: /* ���J */
case 0xa8: /* �[�z�̃A�T�V���N���X */
case 0xa9: /* �u���M�̎� */
case 0xab: /* ��������ȃ_���X */
case 0xac: /* �n�~���O */
case 0xad: /* ����Y��Ȃ��Łc */
case 0xae: /* �K�^�̃L�X */
case 0xaf: /* �T?�r�X�t�H?��? */
case 0xb4:
case 0xb6: /* �t�H�O�E�H?�� */
{
struct skill_unit *unit2;
struct status_change *sc_data=battle_get_sc_data(bl);
int type=SkillStatusChangeTable[sg->skill_id];
if(sg->src_id == bl->id)
break;
if(sc_data && sc_data[type].timer==-1)
skill_status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
(int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
else if( (unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){
if( unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 )
skill_status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
(int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
ts->tick-=sg->interval;
}
} break;
case 0xaa: /* �C�h�D���̗ь� */
{
struct skill_unit *unit2;
struct status_change *sc_data=battle_get_sc_data(bl);
int type=SkillStatusChangeTable[sg->skill_id];
if(sg->src_id == bl->id)
break;
if( sc_data && sc_data[type].timer==-1)
skill_status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff,
(int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
else if((unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){
if( DIFF_TICK(sg->tick,unit2->group->tick)>0 )
skill_status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff,
(int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
ts->tick-=sg->interval;
}
} break;
case 0xb1: /* �f�����X�g��?�V���� */
skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
if(bl->type == BL_PC && rand()%100 < sg->skill_lv && battle_config.equipment_breaking)
pc_breakweapon((struct map_session_data *)bl);
break;
case 0x99: /* �g?�L?�{�b�N�X */
if(sg->src_id == bl->id) //����������ł�?�����Ȃ�
break;
if(sg->val2==0){
clif_talkiebox(&src->bl,sg->valstr);
sg->unit_id = 0x8c;
clif_changelook(&src->bl,LOOK_BASE,sg->unit_id);
sg->limit=DIFF_TICK(tick,sg->tick)+5000;
sg->val2=-1; //����
}
break;
case 0xb2: /* ���Ȃ���_?�������ł� */
case 0xb3: /* �S�X�y�� */
//case 0xb6: /* �t�H�O�E�H?�� */ - moved [celest]
//�Ƃ肠�����������Ȃ�
break;
case 0xb7: /* �X�p�C�_?�E�F�b�u */
if(sg->val2==0){
int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE);
skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
if(moveblock) map_delblock(bl);
bl->x = (&src->bl)->x;
bl->y = (&src->bl)->y;
if(moveblock) map_addblock(bl);
if(bl->type == BL_MOB)
clif_fixmobpos((struct mob_data *)bl);
else if(bl->type == BL_PET)
clif_fixpetpos((struct pet_data *)bl);
else
clif_fixpos(bl);
clif_01ac(&src->bl);
sg->limit=DIFF_TICK(tick,sg->tick) + skill_get_time2(sg->skill_id,sg->skill_lv);
sg->val2=bl->id;
}
break;
// New guild skills [Celest]
case 0xc1: // GD_LEADERSHIP
{
struct map_session_data *sd;
if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
sd->status.guild_id == srcsd->status.guild_id &&
sd->sc_data[SC_LEADERSHIP].timer == -1 && !sd->sc_data[SC_LEADERSHIP].val4)
skill_status_change_start(bl,SC_LEADERSHIP,1,0,0,0,0,0 );
}
break;
case 0xc2: // GD_GLORYWOUNDS
{
struct map_session_data *sd;
if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
sd->status.guild_id == srcsd->status.guild_id &&
sd->sc_data[SC_GLORYWOUNDS].timer == -1 && !sd->sc_data[SC_GLORYWOUNDS].val4)
skill_status_change_start(bl,SC_GLORYWOUNDS,1,0,0,0,0,0 );
}
break;
case 0xc3: // GD_SOULCOLD
{
struct map_session_data *sd;
if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
sd->status.guild_id == srcsd->status.guild_id &&
sd->sc_data[SC_SOULCOLD].timer == -1 && !sd->sc_data[SC_SOULCOLD].val4)
skill_status_change_start(bl,SC_SOULCOLD,1,0,0,0,0,0 );
}
break;
case 0xc4: // GD_HAWKEYES
{
struct map_session_data *sd;
if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
sd->status.guild_id == srcsd->status.guild_id &&
sd->sc_data[SC_HAWKEYES].timer == -1 && !sd->sc_data[SC_HAWKEYES].val4)
skill_status_change_start(bl,SC_HAWKEYES,1,0,0,0,0,0 );
}
break;
/* default:
if(battle_config.error_log)
printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
break;*/
}
if(bl->type==BL_MOB && ss!=bl) /* �X�L���g�p?����MOB�X�L�� */
{
if(battle_config.mob_changetarget_byskill == 1)
{
int target=((struct mob_data *)bl)->target_id;
if(ss->type == BL_PC)
((struct mob_data *)bl)->target_id=ss->id;
mobskill_use((struct mob_data *)bl,tick,MSC_SKILLUSED|(sg->skill_id<<16));
((struct mob_data *)bl)->target_id=target;
}
else
mobskill_use((struct mob_data *)bl,tick,MSC_SKILLUSED|(sg->skill_id<<16));
}
return 0;
}
/*==========================================
* �X�L�����j�b�g���痣?����(�������͂��Ă���)�ꍇ
*------------------------------------------
*/
int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int tick)
{
struct skill_unit_group *sg;
nullpo_retr(0, src);
nullpo_retr(0, bl);
nullpo_retr(0, sg=src->group);
if( bl->prev==NULL || !src->alive )
return 0;
if( bl->type!=BL_PC && bl->type!=BL_MOB )
return 0;
switch(sg->unit_id){
case 0x7e: /* �Z�C�t�e�B�E�H?�� */
case 0x85: /* �j��?�} */
case 0x8e: /* �N�@�O�}�C�A */
{
struct status_change *sc_data=battle_get_sc_data(bl);
int type=
(sg->unit_id==0x85)?SC_PNEUMA:
((sg->unit_id==0x7e)?SC_SAFETYWALL:
SC_QUAGMIRE);
if((type != SC_QUAGMIRE || bl->type != BL_MOB) &&
sc_data && sc_data[type].timer!=-1 && ((struct skill_unit *)sc_data[type].val2)==src){
skill_status_change_end(bl,type,-1);
}
} break;
case 0x91: /* �A���N���X�l�A */
{
struct block_list *target=map_id2bl(sg->val2);
if( target && target==bl ){
skill_status_change_end(bl,SC_ANKLE,-1);
sg->limit=DIFF_TICK(tick,sg->tick)+1000;
}
}
break;
case 0xb5:
case 0xb8:
{
struct block_list *target=map_id2bl(sg->val2);
if( target==bl )
skill_status_change_end(bl,SC_SPIDERWEB,-1);
sg->limit=DIFF_TICK(tick,sg->tick)+1000;
}
break;
case 0xb6:
{
struct block_list *target=map_id2bl(sg->val2);
struct status_change *sc_data=battle_get_sc_data(bl);
if( target==bl ) {
skill_status_change_end(bl,SC_FOGWALL,-1);
if (sc_data && sc_data[SC_BLIND].timer!=-1)
sc_data[SC_BLIND].timer = add_timer(
gettick() + 30000, skill_status_change_timer, bl->id, 0);
}
sg->limit=DIFF_TICK(tick,sg->tick)+1000;
}
break;
case 0x9a: /* �{���P?�m */
case 0x9b: /* �f����?�W */
case 0x9c: /* �o�C�I�����g�Q�C�� */
{
struct status_change *sc_data=battle_get_sc_data(bl);
struct skill_unit *su;
int type=SkillStatusChangeTable[sg->skill_id];
if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val2)) && su == src ){
skill_status_change_end(bl,type,-1);
}
}
break;
case 0x9e: /* �q��S */
case 0x9f: /* �j�����h�̉� */
case 0xa0: /* �i���̍��� */
case 0xa1: /* ?���ۂ̋��� */
case 0xa2: /* �j?�x�����O�̎w�� */
case 0xa3: /* ���L�̋��� */
case 0xa4: /* �[���̒��� */
case 0xa5: /* �s���g�̃W?�N�t��?�h */
case 0xa6: /* �s���a�� */
case 0xa7: /* ���J */
case 0xa8: /* �[�z�̃A�T�V���N���X */
case 0xa9: /* �u���M�̎� */
case 0xaa: /* �C�h�D���̗ь� */
case 0xab: /* ��������ȃ_���X */
case 0xac: /* �n�~���O */
case 0xad: /* ����Y��Ȃ��Łc */
case 0xae: /* �K�^�̃L�X */
case 0xaf: /* �T?�r�X�t�H?��? */
case 0xb4:
{
struct status_change *sc_data=battle_get_sc_data(bl);
struct skill_unit *su;
int type=SkillStatusChangeTable[sg->skill_id];
if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val4)) && su == src ){
skill_status_change_end(bl,type,-1);
}
}
break;
case 0xb7: /* �X�p�C�_?�E�F�b�u */
{
struct block_list *target=map_id2bl(sg->val2);
if( target && target==bl )
skill_status_change_end(bl,SC_SPIDERWEB,-1);
sg->limit=DIFF_TICK(tick,sg->tick)+1000;
}
break;
// New guild skills [Celest]
case 0xc1: // GD_LEADERSHIP
{
struct status_change *sc_data=battle_get_sc_data(bl);
if (sc_data && sc_data[SC_LEADERSHIP].timer != -1)
skill_status_change_end(bl,SC_LEADERSHIP,-1);
}
break;
case 0xc2: // GD_GLORYWOUNDS
{
struct status_change *sc_data=battle_get_sc_data(bl);
if (sc_data && sc_data[SC_GLORYWOUNDS].timer != -1)
skill_status_change_end(bl,SC_GLORYWOUNDS,-1);
}
break;
case 0xc3: // GD_SOULCOLD
{
struct status_change *sc_data=battle_get_sc_data(bl);
if (sc_data && sc_data[SC_SOULCOLD].timer != -1)
skill_status_change_end(bl,SC_SOULCOLD,-1);
}
break;
case 0xc4: // GD_HAWKEYES
{
struct status_change *sc_data=battle_get_sc_data(bl);
if (sc_data && sc_data[SC_HAWKEYES].timer != -1)
skill_status_change_end(bl,SC_HAWKEYES,-1);
}
break;
/* default:
if(battle_config.error_log)
printf("skill_unit_onout: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
break;*/
}
skill_unitgrouptickset_delete(bl,sg->group_id);
return 0;
}
/*==========================================
* �X�L�����j�b�g�̍폜�C�x���g
*------------------------------------------
*/
int skill_unit_ondelete(struct skill_unit *src,struct block_list *bl,unsigned int tick)
{
struct skill_unit_group *sg;
nullpo_retr(0, src);
nullpo_retr(0, bl);
nullpo_retr(0, sg = src->group);
if( bl->prev==NULL || !src->alive )
return 0;
if( bl->type!=BL_PC && bl->type!=BL_MOB )
return 0;
switch(sg->unit_id){
case 0x85: /* �j��?�} */
case 0x7e: /* �Z�C�t�e�B�E�H?�� */
case 0x8e: /* �N�@�O�}�C�� */
case 0x9a: /* �{���P?�m */
case 0x9b: /* �f����?�W */
case 0x9c: /* �o�C�I�����g�Q�C�� */
case 0x9e: /* �q��S */
case 0x9f: /* �j�����h�̉� */
case 0xa0: /* �i���̍��� */
case 0xa1: /* ?���ۂ̋��� */
case 0xa2: /* �j?�x�����O�̎w�� */
case 0xa3: /* ���L�̋��� */
case 0xa4: /* �[���̒��� */
case 0xa5: /* �s���g�̃W?�N�t��?�h */
case 0xa6: /* �s���a�� */
case 0xa7: /* ���J */
case 0xa8: /* �[�z�̃A�T�V���N���X */
case 0xa9: /* �u���M�̎� */
case 0xaa: /* �C�h�D���̗ь� */
case 0xab: /* ��������ȃ_���X */
case 0xac: /* �n�~���O */
case 0xad: /* ����Y��Ȃ��Łc */
case 0xae: /* �K�^�̃L�X */
case 0xaf: /* �T?�r�X�t�H?��? */
case 0xb4:
case 0xc1:
case 0xc2:
case 0xc3:
case 0xc4:
return skill_unit_onout(src,bl,tick);
/* default:
if(battle_config.error_log)
printf("skill_unit_ondelete: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
break;*/
}
skill_unitgrouptickset_delete(bl,sg->group_id);
return 0;
}
/*==========================================
* �X�L�����j�b�g�̌��E�C�x���g
*------------------------------------------
*/
int skill_unit_onlimit(struct skill_unit *src,unsigned int tick)
{
struct skill_unit_group *sg;
nullpo_retr(0, src);
nullpo_retr(0, sg=src->group);
switch(sg->unit_id){
case 0x81: /* ��?�v�|?�^��(?���O) */
{
struct skill_unit_group *group=
skill_unitsetting(map_id2bl(sg->src_id),sg->skill_id,sg->skill_lv,
src->bl.x,src->bl.y,1);
if(group == NULL)
return 0;
group->valstr=calloc(24, 1);
if(group->valstr==NULL){
printf("skill_unit_onlimit: out of memory !\n");
exit(1);
}
memcpy(group->valstr,sg->valstr,24);
group->val2=sg->val2;
}
break;
case 0x8d: /* �A�C�X�E�H?�� */
map_setcell(src->bl.m,src->bl.x,src->bl.y,src->val2);
clif_changemapcell(src->bl.m,src->bl.x,src->bl.y,src->val2,1);
break;
case 0xb2: /* ���Ȃ���?������ */
{
struct map_session_data *sd = NULL;
struct map_session_data *p_sd = NULL;
if((sd = (struct map_session_data *)(map_id2bl(sg->src_id))) == NULL)
return 0;
if((p_sd = pc_get_partner(sd)) == NULL)
return 0;
pc_setpos(p_sd,map[src->bl.m].name,src->bl.x,src->bl.y,3);
}
break;
case 0xc1: // GD_LEADERSHIP
{
struct map_session_data *sd;
if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
sd->sc_data[SC_LEADERSHIP].val4 = 0;
}
}
break;
case 0xc2: // GD_GLORYWOUNDS
{
struct map_session_data *sd;
if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
sd->sc_data[SC_GLORYWOUNDS].val4 = 0;
}
}
break;
case 0xc3: // GD_SOULCOLD
{
struct map_session_data *sd;
if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
sd->sc_data[SC_SOULCOLD].val4 = 0;
}
}
break;
case 0xc4: // GD_HAWKEYES
{
struct map_session_data *sd;
if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
sd->sc_data[SC_HAWKEYES].val4 = 0;
}
}
break;
}
return 0;
}
/*==========================================
* �X�L�����j�b�g�̃_��?�W�C�x���g
*------------------------------------------
*/
int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl,
int damage,unsigned int tick)
{
struct skill_unit_group *sg;
nullpo_retr(0, src);
nullpo_retr(0, sg=src->group);
switch(sg->unit_id){
case 0x8d: /* �A�C�X�E�H?�� */
src->val1-=damage;
break;
case 0x8f: /* �u���X�g�}�C�� */
case 0x98: /* �N���C���A?�g���b�v */
skill_blown(bl,&src->bl,2); //��������Ă݂�
break;
default:
damage = 0;
break;
}
return damage;
}
/*---------------------------------------------------------------------------- */
/*==========================================
* �X�L���g�p�i�r�������A�ꏊ�w��j
*------------------------------------------
*/
int skill_castend_pos( int tid, unsigned int tick, int id,int data )
{
struct map_session_data* sd=map_id2sd(id)/*,*target_sd=NULL*/;
int range,maxcount;
nullpo_retr(0, sd);
if( sd->bl.prev == NULL )
return 0;
if( sd->skilltimer != tid ) /* �^�C�}ID�̊m�F */
return 0;
if(sd->skilltimer != -1 && pc_checkskill(sd,SA_FREECAST) > 0) {
sd->speed = sd->prev_speed;
clif_updatestatus(sd,SP_SPEED);
}
sd->skilltimer=-1;
if(pc_isdead(sd)) {
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
if(battle_config.pc_skill_reiteration == 0) {
range = -1;
switch(sd->skillid) {
case MG_SAFETYWALL:
case WZ_FIREPILLAR:
case HT_SKIDTRAP:
case HT_LANDMINE:
case HT_ANKLESNARE:
case HT_SHOCKWAVE:
case HT_SANDMAN:
case HT_FLASHER:
case HT_FREEZINGTRAP:
case HT_BLASTMINE:
case HT_CLAYMORETRAP:
case HT_TALKIEBOX:
case AL_WARP:
case PF_SPIDERWEB: /* �X�p�C�_?�E�F�b�u */
case RG_GRAFFITI: /* �O���t�B�e�B */
range = 0;
break;
case AL_PNEUMA:
range = 1;
break;
}
if(range >= 0) {
if(skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,range,sd->skillid) > 0) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
}
}
if(battle_config.pc_skill_nofootset) {
range = -1;
switch(sd->skillid) {
case WZ_FIREPILLAR:
case HT_SKIDTRAP:
case HT_LANDMINE:
case HT_ANKLESNARE:
case HT_SHOCKWAVE:
case HT_SANDMAN:
case HT_FLASHER:
case HT_FREEZINGTRAP:
case HT_BLASTMINE:
case HT_CLAYMORETRAP:
case HT_TALKIEBOX:
case PF_SPIDERWEB: /* �X�p�C�_?�E�F�b�u */
case WZ_ICEWALL:
range = 1;
break;
case AL_WARP:
range = 0;
break;
}
if(range >= 0) {
if(skill_check_unit_range2(sd->bl.m,sd->skillx,sd->skilly,range) > 0) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
}
}
if(battle_config.pc_land_skill_limit) {
maxcount = skill_get_maxcount(sd->skillid);
if(maxcount > 0) {
int i,c;
for(i=c=0;i<MAX_SKILLUNITGROUP;i++) {
if(sd->skillunit[i].alive_count > 0 && sd->skillunit[i].skill_id == sd->skillid)
c++;
}
if(c >= maxcount) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
}
}
if(sd->skilllv <= 0) return 0;
range = skill_get_range(sd->skillid,sd->skilllv);
if(range < 0)
range = battle_get_range(&sd->bl) - (range + 1);
range += battle_config.pc_skill_add_range;
if(battle_config.skill_out_range_consume) { // changed to allow casting when target walks out of range [Valaris]
if(range < distance(sd->bl.x,sd->bl.y,sd->skillx,sd->skilly)) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
}
if(!skill_check_condition(sd,1)) { /* �g�p?���`�F�b�N */
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
sd->skillitem = sd->skillitemlv = -1;
if(battle_config.skill_out_range_consume) {
if(range < distance(sd->bl.x,sd->bl.y,sd->skillx,sd->skilly)) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
sd->canmove_tick = tick;
return 0;
}
}
if(battle_config.pc_skill_log)
printf("PC %d skill castend skill=%d\n",sd->bl.id,sd->skillid);
pc_stop_walking(sd,0);
skill_castend_pos2(&sd->bl,sd->skillx,sd->skilly,sd->skillid,sd->skilllv,tick,0);
return 0;
}
/*==========================================
* ��??�L�������݊m�F����?��(foreachinarea)
*------------------------------------------
*/
static int skill_check_condition_char_sub(struct block_list *bl,va_list ap)
{
int *c;
struct block_list *src;
struct map_session_data *sd;
struct map_session_data *ssd;
struct pc_base_job s_class;
struct pc_base_job ss_class;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, sd=(struct map_session_data*)bl);
nullpo_retr(0, src=va_arg(ap,struct block_list *));
nullpo_retr(0, c=va_arg(ap,int *));
nullpo_retr(0, ssd=(struct map_session_data*)src);
s_class = pc_calc_base_job(sd->status.class);
//�`�F�b�N���Ȃ��ݒ�Ȃ�c�ɂ��肦�Ȃ��傫��?����Ԃ��ďI��
if(!battle_config.player_skill_partner_check){ //�{?��foreach�̑O�ɂ�肽�����ǐݒ�K�p�ӏ����܂Ƃ߂邽�߂ɂ�����
(*c)=99;
return 0;
}
ss_class = pc_calc_base_job(ssd->status.class);
switch(ssd->skillid){
case PR_BENEDICTIO: /* ��?�~�� */
if(sd != ssd && (s_class.job == 4 || s_class.job == 8 || s_class.job == 15) &&
(sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1) && sd->status.sp >= 10)
(*c)++;
break;
case BD_LULLABY: /* �q��� */
case BD_RICHMANKIM: /* �j�����h�̉� */
case BD_ETERNALCHAOS: /* �i���̍��� */
case BD_DRUMBATTLEFIELD: /* ?���ۂ̋��� */
case BD_RINGNIBELUNGEN: /* �j?�x�����O�̎w�� */
case BD_ROKISWEIL: /* ���L�̋��� */
case BD_INTOABYSS: /* �[���̒��� */
case BD_SIEGFRIED: /* �s���g�̃W?�N�t��?�h */
case BD_RAGNAROK: /* �_?��?�� */
case CG_MOONLIT: /* ������̐�ɗ�����Ԃт� */
if(sd != ssd &&
((ss_class.job==19 && s_class.job==20) ||
(ss_class.job==20 && s_class.job==19)) &&
pc_checkskill(sd,ssd->skillid) > 0 &&
(*c)==0 &&
sd->status.party_id == ssd->status.party_id &&
!pc_issit(sd) &&
sd->sc_data[SC_DANCING].timer==-1
)
(*c)=pc_checkskill(sd,ssd->skillid);
break;
}
return 0;
}
/*==========================================
* ��??�L�������݊m�F�����X�L���g�p?��(foreachinarea)
*------------------------------------------
*/
static int skill_check_condition_use_sub(struct block_list *bl,va_list ap)
{
int *c;
struct block_list *src;
struct map_session_data *sd;
struct map_session_data *ssd;
struct pc_base_job s_class;
struct pc_base_job ss_class;
int skillid,skilllv;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, sd=(struct map_session_data*)bl);
nullpo_retr(0, src=va_arg(ap,struct block_list *));
nullpo_retr(0, c=va_arg(ap,int *));
nullpo_retr(0, ssd=(struct map_session_data*)src);
s_class = pc_calc_base_job(sd->status.class);
//�`�F�b�N���Ȃ��ݒ�Ȃ�c�ɂ��肦�Ȃ��傫��?����Ԃ��ďI��
if(!battle_config.player_skill_partner_check){ //�{?��foreach�̑O�ɂ�肽�����ǐݒ�K�p�ӏ����܂Ƃ߂邽�߂ɂ�����
(*c)=99;
return 0;
}
ss_class = pc_calc_base_job(ssd->status.class);
skillid=ssd->skillid;
skilllv=ssd->skilllv;
if(skilllv <= 0) return 0;
switch(skillid){
case PR_BENEDICTIO: /* ��?�~�� */
if(sd != ssd && (s_class.job == 4 || s_class.job == 8 || s_class.job == 15) &&
(sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1) && sd->status.sp >= 10){
sd->status.sp -= 10;
pc_calcstatus(sd,0);
(*c)++;
}
break;
case BD_LULLABY: /* �q��� */
case BD_RICHMANKIM: /* �j�����h�̉� */
case BD_ETERNALCHAOS: /* �i���̍��� */
case BD_DRUMBATTLEFIELD: /* ?���ۂ̋��� */
case BD_RINGNIBELUNGEN: /* �j?�x�����O�̎w�� */
case BD_ROKISWEIL: /* ���L�̋��� */
case BD_INTOABYSS: /* �[���̒��� */
case BD_SIEGFRIED: /* �s���g�̃W?�N�t��?�h */
case BD_RAGNAROK: /* �_?��?�� */
case CG_MOONLIT: /* ������̐�ɗ�����Ԃт� */
if(sd != ssd && //�{�l�ȊO��
((ss_class.job==19 && s_class.job==20) || //�������o?�h�Ȃ�_���T?��
(ss_class.job==20 && s_class.job==19)) && //�������_���T?�Ȃ�o?�h��
pc_checkskill(sd,skillid) > 0 && //�X�L������������
(*c)==0 && //�ŏ��̈�l��
sd->status.party_id == ssd->status.party_id && //�p?�e�B?��������
!pc_issit(sd) && //�����ĂȂ�
sd->sc_data[SC_DANCING].timer==-1 //�_���X������Ȃ�
){
ssd->sc_data[SC_DANCING].val4=bl->id;
clif_skill_nodamage(bl,src,skillid,skilllv,1);
skill_status_change_start(bl,SC_DANCING,skillid,ssd->sc_data[SC_DANCING].val2,0,src->id,skill_get_time(skillid,skilllv)+1000,0);
sd->skillid_dance=sd->skillid=skillid;
sd->skilllv_dance=sd->skilllv=skilllv;
(*c)++;
}
break;
}
return 0;
}
/*==========================================
* ��??�o�C�I�v�����g�A�X�t�B�A�}�C���pMob���݊m�F����?��(foreachinarea)
*------------------------------------------
*/
static int skill_check_condition_mob_master_sub(struct block_list *bl,va_list ap)
{
int *c,src_id=0,mob_class=0;
struct mob_data *md;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, md=(struct mob_data*)bl);
nullpo_retr(0, src_id=va_arg(ap,int));
nullpo_retr(0, mob_class=va_arg(ap,int));
nullpo_retr(0, c=va_arg(ap,int *));
if(md->class==mob_class && md->master_id==src_id)
(*c)++;
return 0;
}
/*==========================================
* �X�L���g�p?���i?�Ŏg�p���s�j
*------------------------------------------
*/
int skill_check_condition(struct map_session_data *sd,int type)
{
int i,hp,sp,hp_rate,sp_rate,zeny,weapon,state,spiritball,skill,lv,mhp;
int index[10],itemid[10],amount[10];
nullpo_retr(0, sd);
if( battle_config.gm_skilluncond>0 && pc_isGM(sd)>= battle_config.gm_skilluncond ) {
sd->skillitem = sd->skillitemlv = -1;
return 1;
}
if( sd->opt1>0) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
if(pc_is90overweight(sd)) {
clif_skill_fail(sd,sd->skillid,9,0);
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
if(sd->skillid == AC_MAKINGARROW && sd->state.make_arrow_flag == 1) {
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
if((sd->skillid == AM_PHARMACY || sd->skillid == ASC_CDP)
&& sd->state.produce_flag == 1) {
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
if(sd->skillitem == sd->skillid) { /* �A�C�e���̏ꍇ��?������ */
if(type&1)
sd->skillitem = sd->skillitemlv = -1;
return 1;
}
if( sd->opt1>0 ){
clif_skill_fail(sd,sd->skillid,0,0);
return 0;
}
if(sd->sc_data){
if( sd->sc_data[SC_DIVINA].timer!=-1 ||
sd->sc_data[SC_ROKISWEIL].timer!=-1 ||
(sd->sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) ||
sd->sc_data[SC_STEELBODY].timer != -1 ||
sd->sc_data[SC_BERSERK].timer != -1 ||
(sd->sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)){
clif_skill_fail(sd,sd->skillid,0,0);
return 0; /* ?�Ԉُ�Ⓘ?�Ȃ� */
}
}
skill = sd->skillid;
lv = sd->skilllv;
if(lv <= 0) return 0;
hp=skill_get_hp(skill, lv); /* ����HP */
sp=skill_get_sp(skill, lv); /* ����SP */
if((sd->skillid_old == BD_ENCORE) && skill==sd->skillid_dance)
sp=sp/2; //�A���R?������SP�������
hp_rate = (lv <= 0)? 0:skill_db[skill].hp_rate[lv-1];
sp_rate = (lv <= 0)? 0:skill_db[skill].sp_rate[lv-1];
zeny = skill_get_zeny(skill,lv);
weapon = skill_db[skill].weapon;
state = skill_db[skill].state;
spiritball = (lv <= 0)? 0:skill_db[skill].spiritball[lv-1];
mhp=skill_get_mhp(skill, lv); /* ����HP */
for(i=0;i<10;i++) {
itemid[i] = skill_db[skill].itemid[i];
amount[i] = skill_db[skill].amount[i];
}
if(mhp > 0)
hp += (sd->status.max_hp * mhp)/100;
if(hp_rate > 0)
hp += (sd->status.hp * hp_rate)/100;
else
hp += (sd->status.max_hp * abs(hp_rate))/100;
if(sp_rate > 0)
sp += (sd->status.sp * sp_rate)/100;
else
sp += (sd->status.max_sp * abs(sp_rate))/100;
if(sd->dsprate!=100)
sp=sp*sd->dsprate/100; /* ����SP�C�� */
switch(skill) {
case SA_CASTCANCEL:
if(sd->skilltimer == -1) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case BS_MAXIMIZE: /* �}�L�V�}�C�Y�p��? */
case NV_TRICKDEAD: /* ���ӂ� */
case TF_HIDING: /* �n�C�f�B���O */
case AS_CLOAKING: /* �N��?�L���O */
case CR_AUTOGUARD: /* �I?�g�K?�h */
case CR_DEFENDER: /* �f�B�t�F���_? */
case ST_CHASEWALK:
if(sd->sc_data[SkillStatusChangeTable[skill]].timer!=-1)
return 1; /* ��������ꍇ��SP����Ȃ� */
break;
case AL_TELEPORT:
case AL_WARP:
if(map[sd->bl.m].flag.noteleport) {
clif_skill_teleportmessage(sd,0);
return 0;
}
break;
case MO_CALLSPIRITS: /* ?�� */
if(sd->spiritball >= lv) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case CH_SOULCOLLECT: /* ��?�� */
if(sd->spiritball >= 5) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case MO_FINGEROFFENSIVE: //�w?
if (sd->spiritball > 0 && sd->spiritball < spiritball) {
spiritball = sd->spiritball;
sd->spiritball_old = sd->spiritball;
}
else sd->spiritball_old = lv;
break;
case MO_CHAINCOMBO: //�A�ŏ�
if(sd->sc_data[SC_BLADESTOP].timer==-1){
if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_TRIPLEATTACK)
return 0;
}
break;
case MO_COMBOFINISH: //�җ���
if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_CHAINCOMBO)
return 0;
break;
case CH_TIGERFIST: //���Ռ�
if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH)
return 0;
break;
case CH_CHAINCRUSH: //�A����?
if(sd->sc_data[SC_COMBO].timer == -1)
return 0;
if(sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH && sd->sc_data[SC_COMBO].val1 != CH_TIGERFIST)
return 0;
break;
case MO_EXTREMITYFIST: // ���C���e�P��
if((sd->sc_data[SC_COMBO].timer != -1 && (sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sd->sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) || sd->sc_data[SC_BLADESTOP].timer!=-1)
spiritball--;
break;
case BD_ADAPTATION: /* �A�h���u */
{
struct skill_unit_group *group=NULL;
if(sd->sc_data[SC_DANCING].timer==-1 || ((group=(struct skill_unit_group*)sd->sc_data[SC_DANCING].val2) && (skill_get_time(sd->sc_data[SC_DANCING].val1,group->skill_lv) - sd->sc_data[SC_DANCING].val3*1000) <= skill_get_time2(skill,lv))){ //�_���X���Ŏg�p��5�b�ȏ�̂݁H
clif_skill_fail(sd,skill,0,0);
return 0;
}
}
break;
case PR_BENEDICTIO: /* ��?�~�� */
{
int range=1;
int c=0;
if(!(type&1)){
map_foreachinarea(skill_check_condition_char_sub,sd->bl.m,
sd->bl.x-range,sd->bl.y-range,
sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c);
if(c<2){
clif_skill_fail(sd,skill,0,0);
return 0;
}
}else{
map_foreachinarea(skill_check_condition_use_sub,sd->bl.m,
sd->bl.x-range,sd->bl.y-range,
sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c);
}
}
break;
case WE_CALLPARTNER: /* ���Ȃ��Ɉ������� */
if(!sd->status.partner_id){
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case AM_CANNIBALIZE: /* �o�C�I�v�����g */
case AM_SPHEREMINE: /* �X�t�B�A?�}�C�� */
if(type&1){
int c=0;
int maxcount=skill_get_maxcount(skill);
int mob_class=(skill==AM_CANNIBALIZE)?1118:1142;
if(battle_config.pc_land_skill_limit && maxcount>0) {
map_foreachinarea(skill_check_condition_mob_master_sub ,sd->bl.m, 0, 0, map[sd->bl.m].xs, map[sd->bl.m].ys, BL_MOB, sd->bl.id, mob_class,&c );
if(c >= maxcount){
clif_skill_fail(sd,skill,0,0);
return 0;
}
}
}
break;
case MG_FIREWALL: /* �t�@�C�A?�E�H?�� */
case WZ_QUAGMIRE:
case WZ_FIREPILLAR: // celest
case PF_FOGWALL:
/* ?���� */
if(battle_config.pc_land_skill_limit) {
int maxcount = skill_get_maxcount(skill);
if(maxcount > 0) {
int i,c;
for(i=c=0;i<MAX_SKILLUNITGROUP;i++) {
if(sd->skillunit[i].alive_count > 0 && sd->skillunit[i].skill_id == skill)
c++;
}
if(c >= maxcount) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
}
}
break;
}
if(!(type&2)){
if( hp>0 && sd->status.hp < hp) { /* HP�`�F�b�N */
clif_skill_fail(sd,skill,2,0); /* HP�s���F���s�ʒm */
return 0;
}
if( sp>0 && sd->status.sp < sp) { /* SP�`�F�b�N */
clif_skill_fail(sd,skill,1,0); /* SP�s���F���s�ʒm */
return 0;
}
if( zeny>0 && sd->status.zeny < zeny) {
clif_skill_fail(sd,skill,5,0);
return 0;
}
if(!(weapon & (1<<sd->status.weapon) ) ) {
clif_skill_fail(sd,skill,6,0);
return 0;
}
if( spiritball > 0 && sd->spiritball < spiritball) {
clif_skill_fail(sd,skill,0,0); // �����s��
return 0;
}
}
switch(state) {
case ST_HIDING:
if(!(sd->status.option&2)) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case ST_CLOAKING:
if(!(sd->status.option&4)) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case ST_HIDDEN:
if(!pc_ishiding(sd)) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case ST_RIDING:
if(!pc_isriding(sd)) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case ST_FALCON:
if(!pc_isfalcon(sd)) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case ST_CART:
if(!pc_iscarton(sd)) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case ST_SHIELD:
if(sd->status.shield <= 0) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case ST_SIGHT:
if(sd->sc_data[SC_SIGHT].timer == -1 && type&1) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case ST_EXPLOSIONSPIRITS:
if(sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case ST_RECOV_WEIGHT_RATE:
if(battle_config.natural_heal_weight_rate <= 100 && sd->weight*100/sd->max_weight >= battle_config.natural_heal_weight_rate) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
case ST_MOVE_ENABLE:
{
struct walkpath_data wpd;
if(path_search(&wpd,sd->bl.m,sd->bl.x,sd->bl.y,sd->skillx,sd->skilly,1)==-1) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
}
break;
case ST_WATER:
if(map_getcell(sd->bl.m,sd->bl.x,sd->bl.y) != 3 && (sd->sc_data[SC_DELUGE].timer==-1)){ //���ꔻ��
clif_skill_fail(sd,skill,0,0);
return 0;
}
break;
}
for(i=0;i<10;i++) {
int x = lv%11 - 1;
index[i] = -1;
if(itemid[i] <= 0)
continue;
if(itemid[i] >= 715 && itemid[i] <= 717 && sd->special_state.no_gemstone)
continue;
if(((itemid[i] >= 715 && itemid[i] <= 717) || itemid[i] == 1065) && sd->sc_data[SC_INTOABYSS].timer != -1)
continue;
if(skill == WZ_FIREPILLAR && lv<=5)
continue; // no gemstones for 1-5 [Celest]
if(skill == AM_POTIONPITCHER && i != x)
continue;
index[i] = pc_search_inventory(sd,itemid[i]);
if(index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i]) {
if(itemid[i] == 716 || itemid[i] == 717)
clif_skill_fail(sd,skill,(7+(itemid[i]-716)),0);
else
clif_skill_fail(sd,skill,0,0);
return 0;
}
}
if(!(type&1))
return 1;
if(skill != AM_POTIONPITCHER) {
if(skill == AL_WARP && !(type&2))
return 1;
for(i=0;i<10;i++) {
if(index[i] >= 0)
pc_delitem(sd,index[i],amount[i],0); // �A�C�e������
}
}
if(type&2)
return 1;
if(sp > 0) { // SP����
sd->status.sp-=sp;
clif_updatestatus(sd,SP_SP);
}
if(hp > 0) { // HP����
sd->status.hp-=hp;
clif_updatestatus(sd,SP_HP);
}
if(zeny > 0) // Zeny����
pc_payzeny(sd,zeny);
if(spiritball > 0) // ��������
pc_delspiritball(sd,spiritball,0);
return 1;
}
/*==========================================
* �r�����Ԍv�Z
*------------------------------------------
*/
int skill_castfix( struct block_list *bl, int time )
{
struct map_session_data *sd;
struct mob_data *md; // [Valaris]
struct status_change *sc_data;
int dex;
int castrate=100;
int skill,lv,castnodex;
nullpo_retr(0, bl);
if(bl->type==BL_MOB){ // Crash fix [Valaris]
md=(struct mob_data*)bl;
skill = md->skillid;
lv = md->skilllv;
}
else {
sd=(struct map_session_data*)bl;
skill = sd->skillid;
lv = sd->skilllv;
}
if(lv <= 0) return 0;
sc_data = battle_get_sc_data(bl);
dex=battle_get_dex(bl);
if (skill > MAX_SKILL_DB || skill < 0)
return 0;
castnodex=skill_get_castnodex(skill, lv);
if(time==0)
return 0;
if(castnodex > 0 && bl->type==BL_PC)
castrate=((struct map_session_data *)bl)->castrate;
else if (castnodex <= 0 && bl->type==BL_PC) {
castrate=((struct map_session_data *)bl)->castrate;
time=time*castrate*(battle_config.castrate_dex_scale - dex)/(battle_config.castrate_dex_scale * 100);
time=time*battle_config.cast_rate/100;
}
/* �T�t���M�E�� */
if(sc_data && sc_data[SC_SUFFRAGIUM].timer!=-1 ){
time=time*(100-sc_data[SC_SUFFRAGIUM].val1*15)/100;
skill_status_change_end( bl, SC_SUFFRAGIUM, -1);
}
/* �u���M�̎� */
if(sc_data && sc_data[SC_POEMBRAGI].timer!=-1 )
time=time*(100-(sc_data[SC_POEMBRAGI].val1*3+sc_data[SC_POEMBRAGI].val2
+(sc_data[SC_POEMBRAGI].val3>>16)))/100;
return (time>0)?time:0;
}
/*==========================================
* �f�B���C�v�Z
*------------------------------------------
*/
int skill_delayfix( struct block_list *bl, int time )
{
struct status_change *sc_data;
nullpo_retr(0, bl);
sc_data = battle_get_sc_data(bl);
if(time<=0)
return 0;
if(bl->type == BL_PC) {
if( battle_config.delay_dependon_dex ) /* dex�̉e�����v�Z���� */
time=time*(battle_config.castrate_dex_scale - battle_get_dex(bl))/battle_config.castrate_dex_scale;
time=time*battle_config.delay_rate/100;
}
/* �u���M�̎� */
if(sc_data && sc_data[SC_POEMBRAGI].timer!=-1 )
time=time*(100-(sc_data[SC_POEMBRAGI].val1*3+sc_data[SC_POEMBRAGI].val2
+(sc_data[SC_POEMBRAGI].val3&0xffff)))/100;
return (time>0)?time:0;
}
/*==========================================
* �X�L���g�p�iID�w��j
*------------------------------------------
*/
int skill_use_id( struct map_session_data *sd, int target_id,
int skill_num, int skill_lv)
{
unsigned int tick;
int casttime=0,delay=0,skill,range;
struct map_session_data* target_sd=NULL;
int forcecast=0;
struct block_list *bl;
struct status_change *sc_data;
tick=gettick();
nullpo_retr(0, sd);
if( (bl=map_id2bl(target_id)) == NULL ){
/* if(battle_config.error_log)
printf("skill target not found %d\n",target_id); */
return 0;
}
if(sd->bl.m != bl->m || pc_isdead(sd))
return 0;
if(skillnotok(skill_num, sd)) // [MouseJstr]
return 0;
sc_data=sd->sc_data;
/* ��?��ُ�i�������A�O�����Ȃǂ̔��������j */
if( sd->opt1>0 )
return 0;
if(sd->sc_data){
if(sc_data[SC_CHASEWALK].timer != -1) return 0;
if(sc_data[SC_VOLCANO].timer != -1){
if(skill_num==WZ_ICEWALL) return 0;
}
if(sc_data[SC_ROKISWEIL].timer!=-1){
if(skill_num==BD_ADAPTATION) return 0;
}
if( sd->sc_data[SC_DIVINA].timer!=-1 ||
sd->sc_data[SC_ROKISWEIL].timer!=-1 ||
(sd->sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) ||
sd->sc_data[SC_STEELBODY].timer != -1 ||
sd->sc_data[SC_BERSERK].timer != -1 ||
(sd->sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)){
return 0; /* ?�Ԉُ�Ⓘ?�Ȃ� */
}
if(sc_data[SC_BLADESTOP].timer != -1){
int lv = sc_data[SC_BLADESTOP].val1;
if(sc_data[SC_BLADESTOP].val2==1) return 0;//���H���ꂽ���Ȃ̂Ń_��
if(lv==1) return 0;
if(lv==2 && skill_num!=MO_FINGEROFFENSIVE) return 0;
if(lv==3 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE) return 0;
if(lv==4 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE && skill_num!=MO_CHAINCOMBO) return 0;
if(lv==5 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE && skill_num!=MO_CHAINCOMBO && skill_num!=MO_EXTREMITYFIST) return 0;
}
if (sd->sc_data[SC_BLOCKSKILL].timer!=-1)
if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3)
return 0;
if (sc_data[SC_BASILICA].timer != -1) { // Disallow all other skills in Basilica [celest]
struct skill_unit *su;
if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
struct skill_unit_group *sg;
// if caster is the owner of basilica
if ((sg = su->group) && sg->src_id == sd->bl.id) {
// skill_status_change_end(&sd->bl,SC_BASILICA,-1);
// skill_delunitgroup (sg);
if (skill_num != HP_BASILICA) return 0;
} // otherwise...
else
return 0;
}
}
}
if(sd->status.option&4 && skill_num==TF_HIDING)
return 0;
if(sd->status.option&2 && skill_num!=TF_HIDING && skill_num!=AS_GRIMTOOTH && skill_num!=RG_BACKSTAP && skill_num!=RG_RAID )
return 0;
if(map[sd->bl.m].flag.gvg){ //GvG�Ŏg�p�ł��Ȃ��X�L��
switch(skill_num){
case SM_ENDURE:
case AL_TELEPORT:
case AL_WARP:
case WZ_ICEWALL:
case TF_BACKSLIDING:
//case LK_BERSERK: // now usable in WoE - celest
case HP_BASILICA:
case HP_ASSUMPTIO:
case ST_CHASEWALK:
return 0;
}
}
/* ���t/�_���X�� */
if( sc_data && sc_data[SC_DANCING].timer!=-1 ){
// if(battle_config.pc_skill_log)
// printf("dancing! %d\n",skill_num);
if( sc_data[SC_DANCING].val4 && skill_num!=BD_ADAPTATION ) //���t���̓A�h���u�ȊO�s��
return 0;
if(skill_num!=BD_ADAPTATION && skill_num!=BA_MUSICALSTRIKE && skill_num!=DC_THROWARROW){
return 0;
}
}
if(skill_get_inf2(skill_num)&0x200 && sd->bl.id == target_id)
return 0;
//���O�̃X�L��������?����K�v�̂���X�L��
switch(skill_num){
case SA_CASTCANCEL:
if(sd->skillid != skill_num){ //�L���X�g�L�����Z����?��?���Ȃ�
sd->skillid_old = sd->skillid;
sd->skilllv_old = sd->skilllv;
break;
}
case BD_ENCORE: /* �A���R?�� */
if(!sd->skillid_dance){ //�O��g�p�����x�肪�Ȃ��Ƃ���
clif_skill_fail(sd,skill_num,0,0);
return 0;
}else{
sd->skillid_old = skill_num;
}
break;
case GD_BATTLEORDER:
case GD_REGENERATION:
case GD_RESTORE:
case GD_EMERGENCYCALL:
{
struct guild *g;
if (!sd->status.guild_id)
return 0;
if (!(g = guild_search(sd->status.guild_id)))
return 0;
if (strcmp(sd->status.name,g->master))
return 0;
if (skill_lv <= 0) skill_lv = 1;
}
break;
}
sd->skillid = skill_num;
sd->skilllv = skill_lv;
switch(skill_num){ //���O�Ƀ��x����?������肷��X�L��
case BD_LULLABY: /* �q��� */
case BD_RICHMANKIM: /* �j�����h�̉� */
case BD_ETERNALCHAOS: /* �i���̍��� */
case BD_DRUMBATTLEFIELD: /* ?���ۂ̋��� */
case BD_RINGNIBELUNGEN: /* �j?�x�����O�̎w�� */
case BD_ROKISWEIL: /* ���L�̋��� */
case BD_INTOABYSS: /* �[���̒��� */
case BD_SIEGFRIED: /* �s���g�̃W?�N�t��?�h */
case BD_RAGNAROK: /* �_?��?�� */
case CG_MOONLIT: /* ������̐�ɗ�����Ԃт� */
{
int range=1;
int c=0;
map_foreachinarea(skill_check_condition_char_sub,sd->bl.m,
sd->bl.x-range,sd->bl.y-range,
sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c);
if(c<1){
clif_skill_fail(sd,skill_num,0,0);
return 0;
}else if(c==99){ //�����s�v�ݒ肾����
;
}else{
sd->skilllv=(c + skill_lv)/2;
}
}
break;
}
if(!skill_check_condition(sd,0)) return 0;
/* �˒��Ə�Q���`�F�b�N */
range = skill_get_range(skill_num,skill_lv);
if(range < 0)
range = battle_get_range(&sd->bl) - (range + 1);
if(!battle_check_range(&sd->bl,bl,range) )
return 0;
if(bl->type==BL_PC) {
target_sd=(struct map_session_data*)bl;
if(target_sd && skill_num == ALL_RESURRECTION && !pc_isdead(target_sd))
return 0;
}
if((skill_num != MO_CHAINCOMBO &&
skill_num != MO_COMBOFINISH &&
skill_num != MO_EXTREMITYFIST &&
skill_num != CH_TIGERFIST &&
skill_num != CH_CHAINCRUSH) ||
(skill_num == MO_EXTREMITYFIST && sd->state.skill_flag) )
pc_stopattack(sd);
casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) );
if(skill_num != SA_MAGICROD)
delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) );
//sd->state.skillcastcancel = skill_db[skill_num].castcancel;
sd->state.skillcastcancel = skill_get_castcancel(skill_num);
switch(skill_num){ /* ���������?�����K�v */
// case AL_HEAL: /* �q?�� */
// if(battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
// forcecast=1; /* �q?���A�^�b�N�Ȃ�r���G�t�F�N�g�L�� */
// break;
case ALL_RESURRECTION: /* ���U���N�V���� */
if(bl->type != BL_PC && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))){ /* �G���A���f�b�h�Ȃ� */
forcecast=1; /* �^?���A���f�b�g�Ɠ����r������ */
casttime=skill_castfix(&sd->bl, skill_get_cast(PR_TURNUNDEAD,skill_lv) );
}
break;
case MO_FINGEROFFENSIVE: /* �w? */
casttime += casttime * ((skill_lv > sd->spiritball)? sd->spiritball:skill_lv);
break;
case MO_CHAINCOMBO: /*�A�ŏ�*/
target_id = sd->attacktarget;
if( sc_data && sc_data[SC_BLADESTOP].timer!=-1 ){
struct block_list *tbl;
if((tbl=(struct block_list *)sc_data[SC_BLADESTOP].val4) == NULL) //�^?�Q�b�g�����Ȃ��H
return 0;
target_id = tbl->id;
}
break;
case MO_COMBOFINISH: /*�җ���*/
case CH_TIGERFIST: /* ���Ռ� */
case CH_CHAINCRUSH: /* �A����? */
target_id = sd->attacktarget;
break;
// -- moonsoul (altered to allow proper usage of extremity from new champion combos)
//
case MO_EXTREMITYFIST: /*���C���e�P��*/
if(sc_data && sc_data[SC_COMBO].timer != -1 && (sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) {
casttime = 0;
target_id = sd->attacktarget;
}
forcecast=1;
break;
case SA_MAGICROD:
case SA_SPELLBREAKER:
forcecast=1;
break;
case WE_MALE:
case WE_FEMALE:
{
struct map_session_data *p_sd = NULL;
if((p_sd = pc_get_partner(sd)) == NULL)
return 0;
target_id = p_sd->bl.id;
//range������1��?��
range = skill_get_range(skill_num,skill_lv);
if(range < 0)
range = battle_get_range(&sd->bl) - (range + 1);
if(!battle_check_range(&sd->bl,&p_sd->bl,range))
return 0;
}
break;
case AS_SPLASHER: /* �x�i���X�v���b�V��? */
{
struct status_change *t_sc_data = battle_get_sc_data(bl);
if(t_sc_data && t_sc_data[SC_POISON].timer==-1){
clif_skill_fail(sd,skill_num,0,10);
return 0;
}
}
break;
case PF_MEMORIZE: /* �������C�Y */
casttime = 12000;
break;
case GD_BATTLEORDER:
case GD_REGENERATION:
case GD_RESTORE:
case GD_EMERGENCYCALL:
casttime = 1000; // temporary [Celest]
break;
}
//�������C�Y?�ԂȂ�L���X�g�^�C����1/3
if(sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){
casttime = casttime/2;
if((--sc_data[SC_MEMORIZE].val2)<=0)
skill_status_change_end(&sd->bl, SC_MEMORIZE, -1);
}
if(battle_config.pc_skill_log)
printf("PC %d skill use target_id=%d skill=%d lv=%d cast=%d\n",sd->bl.id,target_id,skill_num,skill_lv,casttime);
// if(sd->skillitem == skill_num)
// casttime = delay = 0;
if( casttime>0 || forcecast ){ /* �r�����K�v */
struct mob_data *md;
clif_skillcasting( &sd->bl, sd->bl.id, target_id, 0,0, skill_num,casttime);
/* �r����?�����X�^? */
if( bl->type==BL_MOB && (md=(struct mob_data *)bl) && mob_db[md->class].mode&0x10 &&
md->state.state!=MS_ATTACK && sd->invincible_timer == -1){
md->target_id=sd->bl.id;
md->state.targettype = ATTACKABLE;
md->min_chase=13;
}
}
if( casttime<=0 ) /* �r���̖������̂̓L�����Z������Ȃ� */
sd->state.skillcastcancel=0;
sd->skilltarget = target_id;
/* sd->cast_target_bl = bl; */
sd->skillx = 0;
sd->skilly = 0;
sd->canact_tick = tick + casttime + delay;
sd->canmove_tick = tick;
if(!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1 && sd->skillid != AS_CLOAKING)
skill_status_change_end(&sd->bl,SC_CLOAKING,-1);
if(casttime > 0) {
sd->skilltimer = add_timer( tick+casttime, skill_castend_id, sd->bl.id, 0 );
if((skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
sd->prev_speed = sd->speed;
sd->speed = sd->speed*(175 - skill*5)/100;
clif_updatestatus(sd,SP_SPEED);
}
else
pc_stop_walking(sd,0);
}
else {
if(skill_num != SA_CASTCANCEL)
sd->skilltimer = -1;
skill_castend_id(sd->skilltimer,tick,sd->bl.id,0);
}
//�}�W�b�N�p��?��?�ʏI��
//if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER)
// skill_status_change_end(&sd->bl,SC_MAGICPOWER,-1); // moved
return 0;
}
/*==========================================
* �X�L���g�p�i�ꏊ�w��j
*------------------------------------------
*/
int skill_use_pos( struct map_session_data *sd,
int skill_x, int skill_y, int skill_num, int skill_lv)
{
struct block_list bl;
struct status_change *sc_data;
unsigned int tick;
int casttime=0,delay=0,skill,range;
nullpo_retr(0, sd);
if(pc_isdead(sd))
return 0;
if (skillnotok(skill_num, sd)) // [MoueJstr]
return 0;
if(skill_num==WZ_ICEWALL && map[sd->bl.m].flag.noicewall && !map[sd->bl.m].flag.pvp) { // noicewall flag [Valaris]
clif_skill_fail(sd,sd->skillid,0,0);
return 0;
}
sc_data=sd->sc_data;
if( sd->opt1>0 )
return 0;
if(sc_data){
if( sc_data[SC_DIVINA].timer!=-1 ||
sc_data[SC_ROKISWEIL].timer!=-1 ||
sc_data[SC_AUTOCOUNTER].timer != -1 ||
sc_data[SC_STEELBODY].timer != -1 ||
sc_data[SC_DANCING].timer!=-1 ||
sc_data[SC_BERSERK].timer != -1 ||
sd->sc_data[SC_MARIONETTE].timer != -1)
return 0; /* ?�Ԉُ�Ⓘ?�Ȃ� */
if (sd->sc_data[SC_BLOCKSKILL].timer!=-1)
if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3)
return 0;
if (sc_data[SC_BASILICA].timer != -1) { // Basilica cancels if caster moves [celest]
struct skill_unit *su;
if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
struct skill_unit_group *sg;
// if caster is the owner of basilica
if ((sg = su->group) && sg->src_id == sd->bl.id) {
// skill_status_change_end(&sd->bl,SC_BASILICA,-1);
// skill_delunitgroup (sg);
if (skill_num != HP_BASILICA) return 0;
} // otherwise...
else
return 0;
}
}
}
if(sd->status.option&2)
return 0;
if(map[sd->bl.m].flag.gvg &&
(skill_num == SM_ENDURE || skill_num == AL_TELEPORT ||
skill_num == AL_WARP || skill_num == WZ_ICEWALL ||
skill_num == TF_BACKSLIDING))
return 0;
sd->skillid = skill_num;
sd->skilllv = skill_lv;
if(skill_lv <= 0) return 0;
sd->skillx = skill_x;
sd->skilly = skill_y;
if(!skill_check_condition(sd,0)) return 0;
/* �˒��Ə�Q���`�F�b�N */
bl.type = BL_NUL;
bl.m = sd->bl.m;
bl.x = skill_x;
bl.y = skill_y;
range = skill_get_range(skill_num,skill_lv);
if(range < 0)
range = battle_get_range(&sd->bl) - (range + 1);
if(!battle_check_range(&sd->bl,&bl,range) )
return 0;
pc_stopattack(sd);
casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) );
delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) );
sd->state.skillcastcancel = skill_db[skill_num].castcancel;
if(battle_config.pc_skill_log)
printf("PC %d skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d\n",sd->bl.id,skill_x,skill_y,skill_num,skill_lv,casttime);
// if(sd->skillitem == skill_num)
// casttime = delay = 0;
//�������C�Y?�ԂȂ�L���X�g�^�C����1/3
if(sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){
casttime = casttime/3;
if((--sc_data[SC_MEMORIZE].val2)<=0)
skill_status_change_end(&sd->bl, SC_MEMORIZE, -1);
}
if( casttime>0 ) /* �r�����K�v */
clif_skillcasting( &sd->bl,
sd->bl.id, 0, skill_x,skill_y, skill_num,casttime);
if( casttime<=0 ) /* �r���̖������̂̓L�����Z������Ȃ� */
sd->state.skillcastcancel=0;
sd->skilltarget = 0;
/* sd->cast_target_bl = NULL; */
tick=gettick();
sd->canact_tick = tick + casttime + delay;
sd->canmove_tick = tick;
if(!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1)
skill_status_change_end(&sd->bl,SC_CLOAKING,-1);
if(casttime > 0) {
sd->skilltimer = add_timer( tick+casttime, skill_castend_pos, sd->bl.id, 0 );
if((skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
sd->prev_speed = sd->speed;
sd->speed = sd->speed*(175 - skill*5)/100;
clif_updatestatus(sd,SP_SPEED);
}
else
pc_stop_walking(sd,0);
}
else {
sd->skilltimer = -1;
skill_castend_pos(sd->skilltimer,tick,sd->bl.id,0);
}
//�}�W�b�N�p��?��?�ʏI��
if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER)
skill_status_change_end(&sd->bl,SC_MAGICPOWER,-1);
return 0;
}
/*==========================================
* �X�L���r���L�����Z��
*------------------------------------------
*/
int skill_castcancel(struct block_list *bl,int type)
{
int inf;
int ret=0;
nullpo_retr(0, bl);
if(bl->type==BL_PC){
struct map_session_data *sd=(struct map_session_data *)bl;
unsigned long tick=gettick();
nullpo_retr(0, sd);
sd->canact_tick=tick;
sd->canmove_tick = tick;
if( sd->skilltimer!=-1){
if(pc_checkskill(sd,SA_FREECAST) > 0) {
sd->speed = sd->prev_speed;
clif_updatestatus(sd,SP_SPEED);
}
if(!type) {
if((inf = skill_get_inf( sd->skillid )) == 2 || inf == 32)
ret=delete_timer( sd->skilltimer, skill_castend_pos );
else
ret=delete_timer( sd->skilltimer, skill_castend_id );
if(ret<0)
printf("delete timer error : skillid : %d\n",sd->skillid);
}
else {
if((inf = skill_get_inf( sd->skillid_old )) == 2 || inf == 32)
ret=delete_timer( sd->skilltimer, skill_castend_pos );
else
ret=delete_timer( sd->skilltimer, skill_castend_id );
if(ret<0)
printf("delete timer error : skillid : %d\n",sd->skillid_old);
}
sd->skilltimer=-1;
clif_skillcastcancel(bl);
}
return 0;
}else if(bl->type==BL_MOB){
struct mob_data *md=(struct mob_data *)bl;
nullpo_retr(0, md);
if( md->skilltimer!=-1 ){
if((inf = skill_get_inf( md->skillid )) == 2 || inf == 32)
ret=delete_timer( md->skilltimer, mobskill_castend_pos );
else
ret=delete_timer( md->skilltimer, mobskill_castend_id );
md->skilltimer=-1;
clif_skillcastcancel(bl);
}
if(ret<0)
printf("delete timer error : skillid : %d\n",md->skillid);
return 0;
}
return 1;
}
/*=========================================
* �u�����f�B�b�V���X�s�A ������?����
*----------------------------------------
*/
void skill_brandishspear_first(struct square *tc,int dir,int x,int y){
nullpo_retv(tc);
if(dir == 0){
tc->val1[0]=x-2;
tc->val1[1]=x-1;
tc->val1[2]=x;
tc->val1[3]=x+1;
tc->val1[4]=x+2;
tc->val2[0]=
tc->val2[1]=
tc->val2[2]=
tc->val2[3]=
tc->val2[4]=y-1;
}
else if(dir==2){
tc->val1[0]=
tc->val1[1]=
tc->val1[2]=
tc->val1[3]=
tc->val1[4]=x+1;
tc->val2[0]=y+2;
tc->val2[1]=y+1;
tc->val2[2]=y;
tc->val2[3]=y-1;
tc->val2[4]=y-2;
}
else if(dir==4){
tc->val1[0]=x-2;
tc->val1[1]=x-1;
tc->val1[2]=x;
tc->val1[3]=x+1;
tc->val1[4]=x+2;
tc->val2[0]=
tc->val2[1]=
tc->val2[2]=
tc->val2[3]=
tc->val2[4]=y+1;
}
else if(dir==6){
tc->val1[0]=
tc->val1[1]=
tc->val1[2]=
tc->val1[3]=
tc->val1[4]=x-1;
tc->val2[0]=y+2;
tc->val2[1]=y+1;
tc->val2[2]=y;
tc->val2[3]=y-1;
tc->val2[4]=y-2;
}
else if(dir==1){
tc->val1[0]=x-1;
tc->val1[1]=x;
tc->val1[2]=x+1;
tc->val1[3]=x+2;
tc->val1[4]=x+3;
tc->val2[0]=y-4;
tc->val2[1]=y-3;
tc->val2[2]=y-1;
tc->val2[3]=y;
tc->val2[4]=y+1;
}
else if(dir==3){
tc->val1[0]=x+3;
tc->val1[1]=x+2;
tc->val1[2]=x+1;
tc->val1[3]=x;
tc->val1[4]=x-1;
tc->val2[0]=y-1;
tc->val2[1]=y;
tc->val2[2]=y+1;
tc->val2[3]=y+2;
tc->val2[4]=y+3;
}
else if(dir==5){
tc->val1[0]=x+1;
tc->val1[1]=x;
tc->val1[2]=x-1;
tc->val1[3]=x-2;
tc->val1[4]=x-3;
tc->val2[0]=y+3;
tc->val2[1]=y+2;
tc->val2[2]=y+1;
tc->val2[3]=y;
tc->val2[4]=y-1;
}
else if(dir==7){
tc->val1[0]=x-3;
tc->val1[1]=x-2;
tc->val1[2]=x-1;
tc->val1[3]=x;
tc->val1[4]=x+1;
tc->val2[1]=y;
tc->val2[0]=y+1;
tc->val2[2]=y-1;
tc->val2[3]=y-2;
tc->val2[4]=y-3;
}
}
/*=========================================
* �u�����f�B�b�V���X�s�A �������� ��??��
*-----------------------------------------
*/
void skill_brandishspear_dir(struct square *tc,int dir,int are){
int c;
nullpo_retv(tc);
for(c=0;c<5;c++){
if(dir==0){
tc->val2[c]+=are;
}else if(dir==1){
tc->val1[c]-=are; tc->val2[c]+=are;
}else if(dir==2){
tc->val1[c]-=are;
}else if(dir==3){
tc->val1[c]-=are; tc->val2[c]-=are;
}else if(dir==4){
tc->val2[c]-=are;
}else if(dir==5){
tc->val1[c]+=are; tc->val2[c]-=are;
}else if(dir==6){
tc->val1[c]+=are;
}else if(dir==7){
tc->val1[c]+=are; tc->val2[c]+=are;
}
}
}
/*==========================================
* �f�B�{?�V���� �L?�m�F
*------------------------------------------
*/
void skill_devotion(struct map_session_data *md,int target)
{
// ?�m�F
int n;
nullpo_retv(md);
for(n=0;n<5;n++){
if(md->dev.val1[n]){
struct map_session_data *sd = map_id2sd(md->dev.val1[n]);
// ���肪������Ȃ� // ������f�B�{���Ă�̂���������Ȃ� // ����������Ă�
if( sd == NULL || (sd->sc_data && (md->bl.id != sd->sc_data[SC_DEVOTION].val1)) || skill_devotion3(&md->bl,md->dev.val1[n])){
skill_devotion_end(md,sd,n);
}
}
}
}
void skill_devotion2(struct block_list *bl,int crusader)
{
// ��f�B�{?�V������?�������̋����`�F�b�N
struct map_session_data *sd = map_id2sd(crusader);
nullpo_retv(bl);
if(sd) skill_devotion3(&sd->bl,bl->id);
}
int skill_devotion3(struct block_list *bl,int target)
{
// �N���Z��?�������̋����`�F�b�N
struct map_session_data *md;
struct map_session_data *sd;
int n,r=0;
nullpo_retr(1, bl);
if( (md = (struct map_session_data *)bl) == NULL || (sd = map_id2sd(target)) == NULL )
return 1;
else
r = distance(bl->x,bl->y,sd->bl.x,sd->bl.y);
if(pc_checkskill(sd,CR_DEVOTION)+6 < r){ // ���e��?����
for(n=0;n<5;n++)
if(md->dev.val1[n]==target)
md->dev.val2[n]=0; // ���ꂽ���́A?��邾��
clif_devotion(md,sd->bl.id);
return 1;
}
return 0;
}
void skill_devotion_end(struct map_session_data *md,struct map_session_data *sd,int target)
{
// �N���Z�Ɣ�f�B�{�L�����̃��Z�b�g
nullpo_retv(md);
nullpo_retv(sd);
md->dev.val1[target]=md->dev.val2[target]=0;
if(sd && sd->sc_data){
// skill_status_change_end(sd->bl,SC_DEVOTION,-1);
sd->sc_data[SC_DEVOTION].val1=0;
sd->sc_data[SC_DEVOTION].val2=0;
clif_status_change(&sd->bl,SC_DEVOTION,0);
clif_devotion(md,sd->bl.id);
}
}
/*==========================================
* �I?�g�X�y��
*------------------------------------------
*/
int skill_autospell(struct map_session_data *sd,int skillid)
{
int skilllv;
int maxlv=1,lv;
nullpo_retr(0, sd);
skilllv = pc_checkskill(sd,SA_AUTOSPELL);
if(skilllv <= 0) return 0;
if(skillid==MG_NAPALMBEAT) maxlv=3;
else if(skillid==MG_COLDBOLT || skillid==MG_FIREBOLT || skillid==MG_LIGHTNINGBOLT){
if(skilllv==2) maxlv=1;
else if(skilllv==3) maxlv=2;
else if(skilllv>=4) maxlv=3;
}
else if(skillid==MG_SOULSTRIKE){
if(skilllv==5) maxlv=1;
else if(skilllv==6) maxlv=2;
else if(skilllv>=7) maxlv=3;
}
else if(skillid==MG_FIREBALL){
if(skilllv==8) maxlv=1;
else if(skilllv>=9) maxlv=2;
}
else if(skillid==MG_FROSTDIVER) maxlv=1;
else return 0;
if(maxlv > (lv=pc_checkskill(sd,skillid)))
maxlv = lv;
skill_status_change_start(&sd->bl,SC_AUTOSPELL,skilllv,skillid,maxlv,0, // val1:�X�L��ID val2:�g�p�ő�Lv
skill_get_time(SA_AUTOSPELL,skilllv),0);// �ɂ��Ă݂�����bscript�������Ղ�???�H
return 0;
}
/*==========================================
* �M�����O�X�^?�p���_�C�X����?��(foreachinarea)
*------------------------------------------
*/
static int skill_gangster_count(struct block_list *bl,va_list ap)
{
int *c;
struct map_session_data *sd;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
sd=(struct map_session_data*)bl;
c=va_arg(ap,int *);
if(sd && c && pc_issit(sd) && pc_checkskill(sd,RG_GANGSTER) > 0)
(*c)++;
return 0;
}
static int skill_gangster_in(struct block_list *bl,va_list ap)
{
struct map_session_data *sd;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
sd=(struct map_session_data*)bl;
if(sd && pc_issit(sd) && pc_checkskill(sd,RG_GANGSTER) > 0)
sd->state.gangsterparadise=1;
return 0;
}
static int skill_gangster_out(struct block_list *bl,va_list ap)
{
struct map_session_data *sd;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
sd=(struct map_session_data*)bl;
if(sd && sd->state.gangsterparadise)
sd->state.gangsterparadise=0;
return 0;
}
int skill_gangsterparadise(struct map_session_data *sd ,int type)
{
int range=1;
int c=0;
nullpo_retr(0, sd);
if(pc_checkskill(sd,RG_GANGSTER) <= 0)
return 0;
if(type==1) {/* ����������?�� */
map_foreachinarea(skill_gangster_count,sd->bl.m,
sd->bl.x-range,sd->bl.y-range,
sd->bl.x+range,sd->bl.y+range,BL_PC,&c);
if(c > 1) {/*�M�����O�X�^?���������玩���ɂ��M�����O�X�^??���t?*/
map_foreachinarea(skill_gangster_in,sd->bl.m,
sd->bl.x-range,sd->bl.y-range,
sd->bl.x+range,sd->bl.y+range,BL_PC);
sd->state.gangsterparadise = 1;
}
return 0;
}
else if(type==0) {/* �����オ�����Ƃ���?�� */
map_foreachinarea(skill_gangster_count,sd->bl.m,
sd->bl.x-range,sd->bl.y-range,
sd->bl.x+range,sd->bl.y+range,BL_PC,&c);
if(c < 2)
map_foreachinarea(skill_gangster_out,sd->bl.m,
sd->bl.x-range,sd->bl.y-range,
sd->bl.x+range,sd->bl.y+range,BL_PC);
sd->state.gangsterparadise = 0;
return 0;
}
return 0;
}
/*==========================================
* �����W��?�N?�X�N��?������?��(foreachinarea)
*------------------------------------------
*/
int skill_frostjoke_scream(struct block_list *bl,va_list ap)
{
struct block_list *src;
int skillnum,skilllv;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, src=va_arg(ap,struct block_list*));
skillnum=va_arg(ap,int);
skilllv=va_arg(ap,int);
if(skilllv <= 0) return 0;
tick=va_arg(ap,unsigned int);
if(src == bl)//�����ɂ�?���Ȃ�
return 0;
if(battle_check_target(src,bl,BCT_ENEMY) > 0)
skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick);
else if(battle_check_target(src,bl,BCT_PARTY) > 0) {
if(rand()%100 < 10)//PT�����o�ɂ���m���ł�����(�Ƃ肠����10%)
skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick);
}
return 0;
}
/*==========================================
*�A�u���J�_�u���̎g�p�X�L������(����X�L�����_���Ȃ�0��Ԃ�)
*------------------------------------------
*/
int skill_abra_dataset(int skilllv)
{
int skill = rand()%331;
if(skilllv <= 0) return 0;
//db�Ɋ�Â����x��?�m������
if(skill_abra_db[skill].req_lv > skilllv || rand()%10000 >= skill_abra_db[skill].per) return 0;
//NPC�X�L���̓_��
if(skill >= NPC_PIERCINGATT && skill <= NPC_SUMMONMONSTER) return 0;
//���t�X�L���̓_��
if(skill_is_danceskill(skill)) return 0;
return skill;
}
/*==========================================
*
*------------------------------------------
*/
int skill_attack_area(struct block_list *bl,va_list ap)
{
struct block_list *src,*dsrc;
int atk_type,skillid,skilllv,flag,type;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
atk_type = va_arg(ap,int);
if((src=va_arg(ap,struct block_list*)) == NULL)
return 0;
if((dsrc=va_arg(ap,struct block_list*)) == NULL)
return 0;
skillid=va_arg(ap,int);
skilllv=va_arg(ap,int);
if(skilllv <= 0) return 0;
tick=va_arg(ap,unsigned int);
flag=va_arg(ap,int);
type=va_arg(ap,int);
if(battle_check_target(dsrc,bl,type) > 0)
skill_attack(atk_type,src,dsrc,bl,skillid,skilllv,tick,flag);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int skill_clear_element_field(struct block_list *bl)
{
struct mob_data *md=NULL;
struct map_session_data *sd=NULL;
int i,skillid;
nullpo_retr(0, bl);
if(bl->type==BL_MOB)
md=(struct mob_data *)bl;
if(bl->type==BL_PC)
sd=(struct map_session_data *)bl;
for(i=0;i<MAX_MOBSKILLUNITGROUP;i++){
if(sd){
skillid=sd->skillunit[i].skill_id;
if(skillid==SA_DELUGE||skillid==SA_VOLCANO||skillid==SA_VIOLENTGALE||skillid==SA_LANDPROTECTOR)
skill_delunitgroup(&sd->skillunit[i]);
}else if(md){
skillid=md->skillunit[i].skill_id;
if(skillid==SA_DELUGE||skillid==SA_VOLCANO||skillid==SA_VIOLENTGALE||skillid==SA_LANDPROTECTOR)
skill_delunitgroup(&md->skillunit[i]);
}
}
return 0;
}
/*==========================================
* �����h�v���e�N�^?�`�F�b�N(foreachinarea)
*------------------------------------------
*/
int skill_landprotector(struct block_list *bl, va_list ap )
{
int skillid;
int *alive;
struct skill_unit *unit;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
skillid=va_arg(ap,int);
alive=va_arg(ap,int *);
if((unit=(struct skill_unit *)bl) == NULL)
return 0;
if(skillid==SA_LANDPROTECTOR){
skill_delunit(unit);
}else{
if(alive && unit->group->skill_id==SA_LANDPROTECTOR)
(*alive)=0;
}
return 0;
}
/*==========================================
* �C�h�D���̗ь�̉�?��(foreachinarea)
*------------------------------------------
*/
int skill_idun_heal(struct block_list *bl, va_list ap )
{
struct skill_unit *unit;
struct skill_unit_group *sg;
int heal;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, unit = va_arg(ap,struct skill_unit *));
nullpo_retr(0, sg = unit->group);
heal=30+sg->skill_lv*5+((sg->val1)>>16)*5+((sg->val1)&0xfff)/2;
if(bl->type == BL_SKILL || bl->id == sg->src_id)
return 0;
if(bl->type == BL_PC || bl->type == BL_MOB){
clif_skill_nodamage(&unit->bl,bl,AL_HEAL,heal,1);
battle_heal(NULL,bl,heal,0,0);
}
return 0;
}
/*==========================================
* �w���??��src��?���ėL?�ȃ^?�Q�b�g��bl��?��?����(foreachinarea)
*------------------------------------------
*/
int skill_count_target(struct block_list *bl, va_list ap ){
struct block_list *src;
int *c;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
if((src = va_arg(ap,struct block_list *)) == NULL)
return 0;
if((c = va_arg(ap,int *)) == NULL)
return 0;
if(battle_check_target(src,bl,BCT_ENEMY) > 0)
(*c)++;
return 0;
}
/*==========================================
* �g���b�v��??��(foreachinarea)
*------------------------------------------
*/
int skill_trap_splash(struct block_list *bl, va_list ap )
{
struct block_list *src;
int tick;
int splash_count;
struct skill_unit *unit;
struct skill_unit_group *sg;
struct block_list *ss;
int i;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, src = va_arg(ap,struct block_list *));
nullpo_retr(0, unit = (struct skill_unit *)src);
nullpo_retr(0, sg = unit->group);
nullpo_retr(0, ss = map_id2bl(sg->src_id));
tick = va_arg(ap,int);
splash_count = va_arg(ap,int);
if(battle_check_target(src,bl,BCT_ENEMY) > 0){
switch(sg->unit_id){
case 0x95: /* �T���h�}�� */
case 0x96: /* �t���b�V��? */
case 0x94: /* �V���b�N�E�F?�u�g���b�v */
skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
break;
case 0x8f: /* �u���X�g�}�C�� */
case 0x98: /* �N���C���A?�g���b�v */
for(i=0;i<splash_count;i++){
skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,(sg->val2)?0x0500:0);
}
case 0x97: /* �t��?�W���O�g���b�v */
skill_attack(BF_WEAPON, ss,src,bl,sg->skill_id,sg->skill_lv,tick,(sg->val2)?0x0500:0);
break;
default:
break;
}
}
return 0;
}
/*----------------------------------------------------------------------------
* �X�e?�^�X�ُ�
*----------------------------------------------------------------------------
*/
/*==========================================
* �X�e?�^�X�ُ�^�C�}?��??��
*------------------------------------------
*/
int skill_status_change_timer_sub(struct block_list *bl, va_list ap )
{
struct block_list *src;
int type;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, src=va_arg(ap,struct block_list*));
type=va_arg(ap,int);
tick=va_arg(ap,unsigned int);
if(bl->type!=BL_PC && bl->type!=BL_MOB)
return 0;
switch( type ){
case SC_SIGHT: /* �T�C�g */
case SC_CONCENTRATE:
if( (*battle_get_option(bl))&6 ){
skill_status_change_end( bl, SC_HIDING, -1);
skill_status_change_end( bl, SC_CLOAKING, -1);
}
break;
case SC_RUWACH: /* ���A�t */
if( (*battle_get_option(bl))&6 ){
skill_status_change_end( bl, SC_HIDING, -1);
skill_status_change_end( bl, SC_CLOAKING, -1);
if(battle_check_target( src,bl, BCT_ENEMY ) > 0) {
struct status_change *sc_data = battle_get_sc_data(bl);
skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,sc_data[type].val1,tick,0);
}
}
break;
}
return 0;
}
/*==========================================
* �X�e?�^�X�ُ�I��
*------------------------------------------
*/
int skill_status_change_end(struct block_list* bl, int type, int tid)
{
struct status_change* sc_data;
int opt_flag=0, calc_flag = 0;
short *sc_count, *option, *opt1, *opt2, *opt3;
nullpo_retr(0, bl);
if(bl->type!=BL_PC && bl->type!=BL_MOB) {
if(battle_config.error_log)
printf("skill_status_change_end: neither MOB nor PC !\n");
return 0;
}
nullpo_retr(0, sc_data = battle_get_sc_data(bl));
nullpo_retr(0, sc_count = battle_get_sc_count(bl));
nullpo_retr(0, option = battle_get_option(bl));
nullpo_retr(0, opt1 = battle_get_opt1(bl));
nullpo_retr(0, opt2 = battle_get_opt2(bl));
nullpo_retr(0, opt3 = battle_get_opt3(bl));
if ((*sc_count) > 0 && sc_data[type].timer != -1 && (sc_data[type].timer == tid || tid == -1)) {
if (tid == -1) // �^�C�}����Ă�Ă��Ȃ��Ȃ�^�C�}�폜������
delete_timer(sc_data[type].timer,skill_status_change_timer);
/* �Y?�ُ̈�𐳏��?�� */
sc_data[type].timer=-1;
(*sc_count)--;
switch(type){ /* �ُ�̎�ނ��Ƃ�?�� */
case SC_PROVOKE: /* �v���{�b�N */
case SC_ENDURE: // celest
case SC_CONCENTRATE: /* �W���͌��� */
case SC_BLESSING: /* �u���b�V���O */
case SC_ANGELUS: /* �A���[���X */
case SC_INCREASEAGI: /* ���x�㏸ */
case SC_DECREASEAGI: /* ���x���� */
case SC_SIGNUMCRUCIS: /* �V�O�i���N���V�X */
case SC_HIDING:
case SC_TWOHANDQUICKEN: /* 2HQ */
case SC_ADRENALINE: /* �A�h���i�������b�V�� */
case SC_ENCPOISON: /* �G���`�����g�|�C�Y�� */
case SC_IMPOSITIO: /* �C���|�V�e�B�I�}�k�X */
case SC_GLORIA: /* �O�����A */
case SC_LOUD: /* ���E�h�{�C�X */
case SC_QUAGMIRE: /* �N�@�O�}�C�A */
case SC_PROVIDENCE: /* �v�����B�f���X */
case SC_SPEARSQUICKEN: /* �X�s�A�N�C�b�P�� */
case SC_VOLCANO:
case SC_DELUGE:
case SC_VIOLENTGALE:
case SC_ETERNALCHAOS: /* �G�^?�i���J�I�X */
case SC_DRUMBATTLE: /* ?���ۂ̋��� */
case SC_NIBELUNGEN: /* �j?�x�����O�̎w�� */
case SC_SIEGFRIED: /* �s���g�̃W?�N�t��?�h */
case SC_WHISTLE: /* ���J */
case SC_ASSNCROS: /* �[�z�̃A�T�V���N���X */
case SC_HUMMING: /* �n�~���O */
case SC_DONTFORGETME: /* ����Y��Ȃ��� */
case SC_FORTUNE: /* �K�^�̃L�X */
case SC_SERVICE4U: /* �T?�r�X�t�H?��? */
case SC_EXPLOSIONSPIRITS: // �����g��
case SC_STEELBODY: // ����
case SC_DEFENDER:
case SC_SPEEDPOTION0: /* ?���|?�V���� */
case SC_SPEEDPOTION1:
case SC_SPEEDPOTION2:
case SC_APPLEIDUN: /* �C�h�D���̗ь� */
case SC_RIDING:
case SC_BLADESTOP_WAIT:
case SC_AURABLADE: /* �I?���u��?�h */
case SC_PARRYING: /* �p���C���O */
case SC_CONCENTRATION: /* �R���Z���g��?�V���� */
case SC_TENSIONRELAX: /* �e���V���������b�N�X */
case SC_ASSUMPTIO: /* �A�V�����v�e�B�I */
case SC_WINDWALK: /* �E�C���h�E�H?�N */
case SC_TRUESIGHT: /* �g�D��?�T�C�g */
case SC_SPIDERWEB: /* �X�p�C�_?�E�F�b�u */
case SC_MAGICPOWER: /* ���@��?�� */
case SC_CHASEWALK:
case SC_ATKPOT: /* attack potion [Valaris] */
case SC_MATKPOT: /* magic attack potion [Valaris] */
case SC_WEDDING: //�����p(�����ߏւɂȂ���?���̂�?���Ƃ�)
case SC_MELTDOWN: /* �����g�_�E�� */
// Celest
case SC_EDP:
case SC_MARIONETTE:
case SC_MARIONETTE2:
case SC_SLOWDOWN:
case SC_LEADERSHIP:
case SC_GLORYWOUNDS:
case SC_SOULCOLD:
case SC_HAWKEYES:
case SC_BATTLEORDERS:
case SC_REGENERATION:
calc_flag = 1;
break;
case SC_BERSERK: /* �o?�T?�N */
calc_flag = 1;
clif_status_change(bl,SC_INCREASEAGI,0); /* �A�C�R������ */
break;
case SC_DEVOTION: /* �f�B�{?�V���� */
{
struct map_session_data *md = map_id2sd(sc_data[type].val1);
sc_data[type].val1=sc_data[type].val2=0;
skill_devotion(md,bl->id);
calc_flag = 1;
}
break;
case SC_BLADESTOP:
{
struct status_change *t_sc_data = battle_get_sc_data((struct block_list *)sc_data[type].val4);
//�Е����ꂽ�̂ő���̔��n?�Ԃ���ĂȂ��̂Ȃ����
if(t_sc_data && t_sc_data[SC_BLADESTOP].timer!=-1)
skill_status_change_end((struct block_list *)sc_data[type].val4,SC_BLADESTOP,-1);
if(sc_data[type].val2==2)
clif_bladestop((struct block_list *)sc_data[type].val3,(struct block_list *)sc_data[type].val4,0);
}
break;
case SC_DANCING:
{
struct map_session_data *dsd;
struct status_change *d_sc_data;
if(sc_data[type].val4 && (dsd=map_id2sd(sc_data[type].val4))){
d_sc_data = dsd->sc_data;
//���t�ő��肪����ꍇ�����val4��0�ɂ���
if(d_sc_data && d_sc_data[type].timer!=-1)
d_sc_data[type].val4=0;
}
}
calc_flag = 1;
break;
case SC_GRAFFITI:
{
struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[type].val4; //val4���O���t�B�e�B��group_id
if(sg)
skill_delunitgroup(sg);
}
break;
case SC_NOCHAT: //�`���b�g�֎~?��
{
struct map_session_data *sd=NULL;
if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){
if (sd->status.manner >= 0) // weeee ^^ [celest]
sd->status.manner = 0;
clif_updatestatus(sd,SP_MANNER);
}
}
break;
case SC_SPLASHER: /* �x�i���X�v���b�V��? */
{
struct block_list *src=map_id2bl(sc_data[type].val3);
if(src && tid!=-1){
//�����Ƀ_��?�W����?3*3�Ƀ_��?�W
skill_castend_damage_id(src, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 );
}
}
break;
case SC_SELFDESTRUCTION: /* ���� */
{
//�����̃_��?�W��0�ɂ���
struct mob_data *md=NULL;
if(bl->type == BL_MOB && (md=(struct mob_data*)bl))
skill_castend_damage_id(bl, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 );
}
break;
/* option1 */
case SC_FREEZE:
sc_data[type].val3 = 0;
break;
/* option2 */
case SC_POISON: /* �� */
case SC_BLIND: /* ��? */
case SC_CURSE:
calc_flag = 1;
break;
}
if(bl->type==BL_PC && type<SC_SENDMAX)
clif_status_change(bl,type,0); /* �A�C�R������ */
switch(type){ /* �����?��Ƃ��Ȃɂ�?�����K�v */
case SC_STONE:
case SC_FREEZE:
case SC_STAN:
case SC_SLEEP:
*opt1 = 0;
opt_flag = 1;
break;
case SC_POISON:
if (sc_data[SC_DPOISON].timer != -1) //
break; // DPOISON�p�̃I�v�V����
*opt2 &= ~1; // ��?�p�ɗp�ӂ��ꂽ�ꍇ�ɂ�
opt_flag = 1; // �����͍폜����
break; //
case SC_CURSE:
case SC_SILENCE:
case SC_BLIND:
*opt2 &= ~(1<<(type-SC_POISON));
opt_flag = 1;
break;
case SC_DPOISON:
if (sc_data[SC_POISON].timer != -1) // DPOISON�p�̃I�v�V������
break; // �p�ӂ��ꂽ��폜
*opt2 &= ~1; // ��?�ԉ���
opt_flag = 1;
break;
case SC_SIGNUMCRUCIS:
*opt2 &= ~0x40;
opt_flag = 1;
break;
case SC_HIDING:
case SC_CLOAKING:
*option &= ~((type == SC_HIDING) ? 2 : 4);
calc_flag = 1; // orn
opt_flag = 1 ;
break;
case SC_CHASEWALK:
*option &= ~16388;
opt_flag = 1 ;
break;
case SC_SIGHT:
*option &= ~1;
opt_flag = 1;
break;
case SC_WEDDING: //�����p(�����ߏւɂȂ���?���̂�?���Ƃ�)
*option &= ~4096;
opt_flag = 1;
break;
case SC_RUWACH:
*option &= ~8192;
opt_flag = 1;
break;
//opt3
case SC_TWOHANDQUICKEN: /* 2HQ */
case SC_SPEARSQUICKEN: /* �X�s�A�N�C�b�P�� */
case SC_CONCENTRATION: /* �R���Z���g��?�V���� */
*opt3 &= ~1;
break;
case SC_OVERTHRUST: /* �I?�o?�X���X�g */
*opt3 &= ~2;
break;
case SC_ENERGYCOAT: /* �G�i�W?�R?�g */
*opt3 &= ~4;
break;
case SC_EXPLOSIONSPIRITS: // �����g��
*opt3 &= ~8;
break;
case SC_STEELBODY: // ����
*opt3 &= ~16;
break;
case SC_BLADESTOP: /* ���n��� */
*opt3 &= ~32;
break;
case SC_BERSERK: /* �o?�T?�N */
*opt3 &= ~128;
break;
case SC_MARIONETTE: /* �}���I�l�b�g�R���g��?�� */
case SC_MARIONETTE2:
*opt3 &= ~1024;
break;
case SC_ASSUMPTIO: /* �A�X���v�e�B�I */
*opt3 &= ~2048;
break;
}
if (night_flag == 1 && (*opt2 & STATE_BLIND) == 0 && bl->type == BL_PC && // by [Yor]
!map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) { // [celest]
*opt2 |= STATE_BLIND;
opt_flag = 1;
}
if(opt_flag) /* option��?�X��?���� */
clif_changeoption(bl);
if (bl->type == BL_PC && calc_flag)
pc_calcstatus((struct map_session_data *)bl,0); /* �X�e?�^�X�Čv�Z */
}
return 0;
}
/*==========================================
* �X�e?�^�X�ُ�I���^�C�}?
*------------------------------------------
*/
int skill_status_change_timer(int tid, unsigned int tick, int id, int data)
{
int type=data;
struct block_list *bl;
struct map_session_data *sd=NULL;
struct status_change *sc_data;
//short *sc_count; //�g���ĂȂ��H
if( (bl=map_id2bl(id)) == NULL )
return 0; //�Y?ID�����łɏ��ł��Ă���Ƃ����̂͂����ɂ����肻���Ȃ̂ŃX��?���Ă݂�
nullpo_retr(0, sc_data=battle_get_sc_data(bl));
if(bl->type==BL_PC)
sd=(struct map_session_data *)bl;
//sc_count=battle_get_sc_count(bl); //�g���ĂȂ��H
if(sc_data[type].timer != tid) {
if(battle_config.error_log)
printf("skill_status_change_timer %d != %d\n",tid,sc_data[type].timer);
}
switch(type){ /* �����?���ɂȂ�ꍇ */
case SC_MAXIMIZEPOWER: /* �}�L�V�}�C�Y�p��? */
case SC_CLOAKING:
if(sd){
if( sd->status.sp > 0 ){ /* SP���܂Ŏ�? */
sd->status.sp--;
clif_updatestatus(sd,SP_SP);
sc_data[type].timer=add_timer( /* �^�C�}?�Đݒ� */
sc_data[type].val2+tick, skill_status_change_timer, bl->id, data);
return 0;
}
}
break;
case SC_CHASEWALK:
if(sd){
if( sd->status.sp > 19+sc_data[SC_CHASEWALK].val1*3){
sd->status.sp-=(19+(sc_data[SC_CHASEWALK].val1*3)); // update sp cost [Celest]
clif_updatestatus(sd,SP_SP);
sc_data[type].timer=add_timer( /* �^�C�}?�Đݒ� */
sc_data[type].val2+tick, skill_status_change_timer, bl->id, data);
return 0;
}
}
break;
case SC_HIDING: /* �n�C�f�B���O */
if(sd){ /* SP�������āA���Ԑ����̊Ԃ͎�? */
if( sd->status.sp > 0 && (--sc_data[type].val2)>0 ){
if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){
sd->status.sp--;
clif_updatestatus(sd,SP_SP);
}
sc_data[type].timer=add_timer( /* �^�C�}?�Đݒ� */
1000+tick, skill_status_change_timer,
bl->id, data);
return 0;
}
}
break;
case SC_SIGHT: /* �T�C�g */
{
const int range=7;
map_foreachinarea( skill_status_change_timer_sub,
bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0,
bl,type,tick);
if( (--sc_data[type].val2)>0 ){
sc_data[type].timer=add_timer( /* �^�C�}?�Đݒ� */
250+tick, skill_status_change_timer,
bl->id, data);
return 0;
}
}
break;
case SC_RUWACH: /* ���A�t */
{
const int range=5;
map_foreachinarea( skill_status_change_timer_sub,
bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0,
bl,type,tick);
if( (--sc_data[type].val2)>0 ){
sc_data[type].timer=add_timer( /* �^�C�}?�Đݒ� */
250+tick, skill_status_change_timer,
bl->id, data);
return 0;
}
}
break;
case SC_SIGNUMCRUCIS: /* �V�O�i���N���V�X */
{
int race = battle_get_race(bl);
if(race == 6 || battle_check_undead(race,battle_get_elem_type(bl))) {
sc_data[type].timer=add_timer(1000*600+tick,skill_status_change_timer, bl->id, data );
return 0;
}
}
break;
case SC_PROVOKE: /* �v���{�b�N/�I?�g�o?�T?�N */
if(sc_data[type].val2!=0){ /* �I?�g�o?�T?�N�i�P�b���Ƃ�HP�`�F�b�N�j */
if(sd && sd->status.hp>sd->status.max_hp>>2) /* ��~ */
break;
sc_data[type].timer=add_timer( 1000+tick,skill_status_change_timer, bl->id, data );
return 0;
}
break;
case SC_WATERBALL: /* �E�H?�^?�{?�� */
{
struct block_list *target=map_id2bl(sc_data[type].val2);
if(target==NULL || target->prev==NULL)
break;
skill_attack(BF_MAGIC,bl,bl,target,WZ_WATERBALL,sc_data[type].val1,tick,0);
if((--sc_data[type].val3)>0) {
sc_data[type].timer=add_timer( 150+tick,skill_status_change_timer, bl->id, data );
return 0;
}
}
break;
case SC_ENDURE: /* �C���f���A */
if(sd && sd->special_state.infinite_endure) {
sc_data[type].timer=add_timer( 1000*60+tick,skill_status_change_timer, bl->id, data );
//sc_data[type].val2=1;
return 0;
}
break;
case SC_DISSONANCE: /* �s���a�� */
if( (--sc_data[type].val2)>0){
struct skill_unit *unit=
(struct skill_unit *)sc_data[type].val4;
struct block_list *src;
if(!unit || !unit->group)
break;
src=map_id2bl(unit->group->src_id);
if(!src)
break;
skill_attack(BF_MISC,src,&unit->bl,bl,unit->group->skill_id,sc_data[type].val1,tick,0);
sc_data[type].timer=add_timer(skill_get_time2(unit->group->skill_id,unit->group->skill_lv)+tick,
skill_status_change_timer, bl->id, data );
return 0;
}
break;
case SC_LULLABY: /* �q��S */
if( (--sc_data[type].val2)>0){
struct skill_unit *unit=
(struct skill_unit *)sc_data[type].val4;
if(!unit || !unit->group || unit->group->src_id==bl->id)
break;
skill_additional_effect(bl,bl,unit->group->skill_id,sc_data[type].val1,BF_LONG|BF_SKILL|BF_MISC,tick);
sc_data[type].timer=add_timer(skill_get_time(unit->group->skill_id,unit->group->skill_lv)/10+tick,
skill_status_change_timer, bl->id, data );
return 0;
}
break;
case SC_STONE:
if(sc_data[type].val2 != 0) {
short *opt1 = battle_get_opt1(bl);
sc_data[type].val2 = 0;
sc_data[type].val4 = 0;
battle_stopwalking(bl,1);
if(opt1) {
*opt1 = 1;
clif_changeoption(bl);
}
sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
return 0;
}
else if( (--sc_data[type].val3) > 0) {
int hp = battle_get_max_hp(bl);
if((++sc_data[type].val4)%5 == 0 && battle_get_hp(bl) > hp>>2) {
hp = hp/100;
if(hp < 1) hp = 1;
if(bl->type == BL_PC)
pc_heal((struct map_session_data *)bl,-hp,0);
else if(bl->type == BL_MOB){
struct mob_data *md;
if((md=((struct mob_data *)bl)) == NULL)
break;
md->hp -= hp;
}
}
sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
return 0;
}
break;
case SC_POISON:
if(sc_data[SC_SLOWPOISON].timer == -1) {
if( (--sc_data[type].val3) > 0) {
int hp = battle_get_max_hp(bl);
if(battle_get_hp(bl) > hp>>2) {
if(bl->type == BL_PC) {
hp = 3 + hp*3/200;
pc_heal((struct map_session_data *)bl,-hp,0);
}
else if(bl->type == BL_MOB) {
struct mob_data *md;
if((md=((struct mob_data *)bl)) == NULL)
break;
hp = 3 + hp/200;
md->hp -= hp;
}
}
sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
}
}
else
sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
break;
case SC_DPOISON:
if (sc_data[SC_SLOWPOISON].timer == -1 && (--sc_data[type].val3) > 0) {
int hp = battle_get_max_hp(bl);
if (battle_get_hp(bl) > hp>>2) {
if(bl->type == BL_PC) {
hp = 3 + hp/50;
pc_heal((struct map_session_data *)bl, -hp, 0);
} else if (bl->type == BL_MOB) {
struct mob_data *md;
if ((md=((struct mob_data *)bl)) == NULL)
break;
hp = 3 + hp/100;
md->hp -= hp;
}
}
}
if (sc_data[type].val3 > 0)
sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
break;
case SC_TENSIONRELAX: /* �e���V���������b�N�X */
if(sd){ /* SP�������āAHP��?�^���łȂ����?? */
if( sd->status.sp > 12 && sd->status.max_hp > sd->status.hp ){
/* if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){
sd->status.sp -= 12;
clif_updatestatus(sd,SP_SP);
} */
sc_data[type].timer=add_timer( /* �^�C�}?�Đݒ� */
10000+tick, skill_status_change_timer,
bl->id, data);
return 0;
}
if(sd->status.max_hp <= sd->status.hp)
skill_status_change_end(&sd->bl,SC_TENSIONRELAX,-1);
}
break;
case SC_HEADCRUSH: // temporary damage [celest]
// case SC_BLEEDING:
if((--sc_data[type].val3) > 0) {
int hp = battle_get_max_hp(bl);
if(bl->type == BL_PC) {
hp = 3 + hp*3/200;
pc_heal((struct map_session_data *)bl,-hp,0);
}
else if(bl->type == BL_MOB) {
struct mob_data *md;
if((md=((struct mob_data *)bl)) == NULL)
break;
hp = 3 + hp/200;
md->hp -= hp;
}
sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
}
break;
/* ���Ԑꖳ���H�H */
case SC_AETERNA:
case SC_TRICKDEAD:
case SC_RIDING:
case SC_FALCON:
case SC_WEIGHT50:
case SC_WEIGHT90:
case SC_MAGICPOWER: /* ���@��?�� */
case SC_REJECTSWORD: /* ���W�F�N�g�\?�h */
case SC_MEMORIZE: /* �������C�Y */
case SC_BROKNWEAPON:
case SC_BROKNARMOR:
if(sc_data[type].timer==tid)
sc_data[type].timer=add_timer( 1000*600+tick,skill_status_change_timer, bl->id, data );
return 0;
case SC_DANCING: //�_���X�X�L���̎���SP����
{
int s=0;
if(sd){
if(sd->status.sp > 0 && (--sc_data[type].val3)>0){
switch(sc_data[type].val1){
case BD_RICHMANKIM: /* �j�����h�̉� 3�b��SP1 */
case BD_DRUMBATTLEFIELD: /* ?���ۂ̋��� 3�b��SP1 */
case BD_RINGNIBELUNGEN: /* �j?�x�����O�̎w�� 3�b��SP1 */
case BD_SIEGFRIED: /* �s���g�̃W?�N�t��?�h 3�b��SP1 */
case BA_DISSONANCE: /* �s���a�� 3�b��SP1 */
case BA_ASSASSINCROSS: /* �[�z�̃A�T�V���N���X 3�b��SP1 */
case DC_UGLYDANCE: /* ��������ȃ_���X 3�b��SP1 */
s=3;
break;
case BD_LULLABY: /* �q��� 4�b��SP1 */
case BD_ETERNALCHAOS: /* �i���̍��� 4�b��SP1 */
case BD_ROKISWEIL: /* ���L�̋��� 4�b��SP1 */
case DC_FORTUNEKISS: /* �K�^�̃L�X 4�b��SP1 */
s=4;
break;
case BD_INTOABYSS: /* �[���̒��� 5�b��SP1 */
case BA_WHISTLE: /* ���J 5�b��SP1 */
case DC_HUMMING: /* �n�~���O 5�b��SP1 */
case BA_POEMBRAGI: /* �u���M�̎� 5�b��SP1 */
case DC_SERVICEFORYOU: /* �T?�r�X�t�H?��? 5�b��SP1 */
s=5;
break;
case BA_APPLEIDUN: /* �C�h�D���̗ь� 6�b��SP1 */
s=6;
break;
case DC_DONTFORGETME: /* ����Y��Ȃ��Łc 10�b��SP1 */
case CG_MOONLIT: /* ������̐�ɗ�����Ԃт� 10�b��SP1�H */
s=10;
break;
}
if(s && ((sc_data[type].val3 % s) == 0)){
sd->status.sp--;
clif_updatestatus(sd,SP_SP);
}
sc_data[type].timer=add_timer( /* �^�C�}?�Đݒ� */
1000+tick, skill_status_change_timer,
bl->id, data);
return 0;
}
}
}
break;
case SC_BERSERK: /* �o?�T?�N */
if(sd){ /* HP��100�ȏ�Ȃ�?? */
if( (sd->status.hp - sd->status.max_hp*5/100) > 100 ){ // 5% every 10 seconds [DracoRPG]
sd->status.hp -= sd->status.max_hp*5/100; // changed to max hp [celest]
clif_updatestatus(sd,SP_HP);
sc_data[type].timer = add_timer( /* �^�C�}?�Đݒ� */
10000+tick, skill_status_change_timer,
bl->id, data);
return 0;
}
}
break;
case SC_WEDDING: //�����p(�����ߏւɂȂ���?���̂�?���Ƃ�)
if(sd){
time_t timer;
if(time(&timer) < ((sc_data[type].val2) + 3600)){ //1���Ԃ����Ă��Ȃ��̂�??
sc_data[type].timer=add_timer( /* �^�C�}?�Đݒ� */
10000+tick, skill_status_change_timer,
bl->id, data);
return 0;
}
}
break;
case SC_NOCHAT: //�`���b�g�֎~?��
if(sd && battle_config.muting_players){
time_t timer;
if((++sd->status.manner) && time(&timer) < ((sc_data[type].val2) + 60*(0-sd->status.manner))){ //�J�n����status.manner��?���ĂȂ��̂�??
clif_updatestatus(sd,SP_MANNER);
sc_data[type].timer=add_timer( /* �^�C�}?�Đݒ�(60�b) */
60000+tick, skill_status_change_timer,
bl->id, data);
return 0;
}
}
break;
case SC_SELFDESTRUCTION: /* ���� */
if(--sc_data[type].val3>0){
struct mob_data *md;
if(bl->type==BL_MOB && (md=(struct mob_data *)bl) && md->speed > 250){
md->speed -= 250;
md->next_walktime=tick;
}
sc_data[type].timer=add_timer( /* �^�C�}?�Đݒ� */
1000+tick, skill_status_change_timer,
bl->id, data);
return 0;
}
break;
case SC_LEADERSHIP:
case SC_GLORYWOUNDS:
case SC_SOULCOLD:
case SC_HAWKEYES:
if (sd) {
sc_data[type].timer = add_timer(
1000+tick, skill_status_change_timer,
bl->id, data);
}
break;
}
return skill_status_change_end( bl,type,tid );
}
/*==========================================
* �X�e?�^�X�ُ�I��
*------------------------------------------
*/
int skill_encchant_eremental_end(struct block_list *bl,int type)
{
struct status_change *sc_data;
nullpo_retr(0, bl);
nullpo_retr(0, sc_data=battle_get_sc_data(bl));
if( type!=SC_ENCPOISON && sc_data[SC_ENCPOISON].timer!=-1 ) /* �G���`�����g�|�C�Y������ */
skill_status_change_end(bl,SC_ENCPOISON,-1);
if( type!=SC_ASPERSIO && sc_data[SC_ASPERSIO].timer!=-1 ) /* �A�X�y���V�I���� */
skill_status_change_end(bl,SC_ASPERSIO,-1);
if( type!=SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer!=-1 ) /* �t���C�������`������ */
skill_status_change_end(bl,SC_FLAMELAUNCHER,-1);
if( type!=SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer!=-1 ) /* �t���X�g�E�F�|������ */
skill_status_change_end(bl,SC_FROSTWEAPON,-1);
if( type!=SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer!=-1 ) /* ���C�g�j���O��?�_?���� */
skill_status_change_end(bl,SC_LIGHTNINGLOADER,-1);
if( type!=SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer!=-1 ) /* �T�C�X�~�b�N�E�F�|������ */
skill_status_change_end(bl,SC_SEISMICWEAPON,-1);
return 0;
}
/*==========================================
* �X�e?�^�X�ُ�J�n
*------------------------------------------
*/
int skill_status_change_start(struct block_list *bl, int type, int val1, int val2, int val3, int val4, int tick, int flag)
{
struct map_session_data *sd = NULL;
struct status_change* sc_data;
short *sc_count, *option, *opt1, *opt2, *opt3;
int opt_flag = 0, calc_flag = 0,updateflag = 0, save_flag = 0, race, mode, elem, undead_flag;
int scdef=0;
nullpo_retr(0, bl);
if(bl->type == BL_SKILL)
return 0;
nullpo_retr(0, sc_data=battle_get_sc_data(bl));
nullpo_retr(0, sc_count=battle_get_sc_count(bl));
nullpo_retr(0, option=battle_get_option(bl));
nullpo_retr(0, opt1=battle_get_opt1(bl));
nullpo_retr(0, opt2=battle_get_opt2(bl));
nullpo_retr(0, opt3=battle_get_opt3(bl));
race=battle_get_race(bl);
mode=battle_get_mode(bl);
elem=battle_get_elem_type(bl);
undead_flag=battle_check_undead(race,elem);
if(type == SC_AETERNA && (sc_data[SC_STONE].timer != -1 || sc_data[SC_FREEZE].timer != -1) )
return 0;
switch(type){
case SC_STONE:
case SC_FREEZE:
scdef=3+battle_get_mdef(bl)+battle_get_luk(bl)/3;
break;
case SC_STAN:
case SC_SILENCE:
case SC_POISON:
case SC_DPOISON:
scdef=3+battle_get_vit(bl)+battle_get_luk(bl)/3;
break;
case SC_SLEEP:
case SC_BLIND:
scdef=3+battle_get_int(bl)+battle_get_luk(bl)/3;
break;
case SC_CURSE:
scdef=3+battle_get_luk(bl);
break;
// case SC_CONFUSION:
default:
scdef=0;
}
if(scdef>=100)
return 0;
if(bl->type==BL_PC){
sd=(struct map_session_data *)bl;
if( sd && type == SC_ADRENALINE && !(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon)))
return 0;
if(SC_STONE<=type && type<=SC_BLIND){ /* �J?�h�ɂ��ϐ� */
if( sd && sd->reseff[type-SC_STONE] > 0 && rand()%10000<sd->reseff[type-SC_STONE]){
if(battle_config.battle_log)
printf("PC %d skill_sc_start: card�ɂ��ُ�ϐ�?��\n",sd->bl.id);
return 0;
}
}
}
else if(bl->type == BL_MOB) {
}
else {
if(battle_config.error_log)
printf("skill_status_change_start: neither MOB nor PC !\n");
return 0;
}
if(type==SC_FREEZE && undead_flag && !(flag&1))
return 0;
if((type == SC_ADRENALINE || type == SC_WEAPONPERFECTION || type == SC_OVERTHRUST) &&
sc_data[type].timer != -1 && sc_data[type].val2 && !val2)
return 0;
if(mode & 0x20 && (type==SC_STONE || type==SC_FREEZE ||
type==SC_STAN || type==SC_SLEEP || type==SC_SILENCE || type==SC_QUAGMIRE || type == SC_DECREASEAGI || type == SC_SIGNUMCRUCIS || type == SC_PROVOKE ||
(type == SC_BLESSING && (undead_flag || race == 6))) && !(flag&1)){
/* �{�X�ɂ�?���Ȃ�(�������J?�h�ɂ��?�ʂ͓K�p�����) */
return 0;
}
if(type==SC_FREEZE || type==SC_STAN || type==SC_SLEEP)
battle_stopwalking(bl,1);
if(sc_data[type].timer != -1){ /* ���łɓ����ُ�ɂȂ��Ă���ꍇ�^�C�}���� */
if(sc_data[type].val1 > val1 && type != SC_COMBO && type != SC_DANCING && type != SC_DEVOTION &&
type != SC_SPEEDPOTION0 && type != SC_SPEEDPOTION1 && type != SC_SPEEDPOTION2
&& type != SC_ATKPOT && type != SC_MATKPOT) // added atk and matk potions [Valaris]
return 0;
if(type >=SC_STAN && type <= SC_BLIND)
return 0;/* ?���������ł��Ȃ�?�Ԉُ�ł��鎞��?�Ԉُ���s��Ȃ� */
if(type == SC_GRAFFITI){ //�ُ풆�ɂ�����x?�Ԉُ�ɂȂ������ɉ������Ă���ēx������
skill_status_change_end(bl,type,-1);
} else {
(*sc_count)--;
delete_timer(sc_data[type].timer, skill_status_change_timer);
sc_data[type].timer = -1;
}
}
switch(type){ /* �ُ�̎�ނ��Ƃ�?�� */
case SC_PROVOKE: /* �v���{�b�N */
calc_flag = 1;
if(tick <= 0) tick = 1000; /* (�I?�g�o?�T?�N) */
break;
case SC_ENDURE: /* �C���f���A */
if(tick <= 0) tick = 1000 * 60;
calc_flag = 1; // for updating mdef
val2 = 7; // [Celest]
break;
case SC_CONCENTRATE: /* �W���͌��� */
calc_flag = 1;
break;
case SC_BLESSING: /* �u���b�V���O */
{
if(bl->type == BL_PC || (!undead_flag && race != 6)) {
if(sc_data[SC_CURSE].timer!=-1 )
skill_status_change_end(bl,SC_CURSE,-1);
if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2 == 0)
skill_status_change_end(bl,SC_STONE,-1);
}
calc_flag = 1;
}
break;
case SC_ANGELUS: /* �A���[���X */
calc_flag = 1;
break;
case SC_INCREASEAGI: /* ���x�㏸ */
calc_flag = 1;
if(sc_data[SC_DECREASEAGI].timer!=-1 )
skill_status_change_end(bl,SC_DECREASEAGI,-1);
if(sc_data[SC_WINDWALK].timer!=-1 ) /* �E�C���h�E�H?�N */
skill_status_change_end(bl,SC_WINDWALK,-1);
break;
case SC_DECREASEAGI: /* ���x���� */
if (bl->type == BL_PC) // Celest
tick>>=1;
calc_flag = 1;
if(sc_data[SC_INCREASEAGI].timer!=-1 )
skill_status_change_end(bl,SC_INCREASEAGI,-1);
if(sc_data[SC_ADRENALINE].timer!=-1 )
skill_status_change_end(bl,SC_ADRENALINE,-1);
if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
skill_status_change_end(bl,SC_SPEARSQUICKEN,-1);
if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1);
break;
case SC_SIGNUMCRUCIS: /* �V�O�i���N���V�X */
calc_flag = 1;
// val2 = 14 + val1;
val2 = 10 + val1*2;
tick = 600*1000;
clif_emotion(bl,4);
break;
case SC_SLOWPOISON:
if (sc_data[SC_POISON].timer == -1 && sc_data[SC_DPOISON].timer == -1)
return 0;
break;
case SC_TWOHANDQUICKEN: /* 2HQ */
if(sc_data[SC_DECREASEAGI].timer!=-1)
return 0;
*opt3 |= 1;
calc_flag = 1;
break;
case SC_ADRENALINE: /* �A�h���i�������b�V�� */
if(sc_data[SC_DECREASEAGI].timer!=-1)
return 0;
calc_flag = 1;
break;
case SC_WEAPONPERFECTION: /* �E�F�|���p?�t�F�N�V���� */
if(battle_config.party_skill_penaly && !val2) tick /= 5;
break;
case SC_OVERTHRUST: /* �I?�o?�X���X�g */
*opt3 |= 2;
if(battle_config.party_skill_penaly && !val2) tick /= 10;
break;
case SC_MAXIMIZEPOWER: /* �}�L�V�}�C�Y�p��?(SP��1���鎞��,val2�ɂ�) */
if(bl->type == BL_PC)
val2 = tick;
else
tick = 5000*val1;
break;
case SC_ENCPOISON: /* �G���`�����g�|�C�Y�� */
calc_flag = 1;
val2=(((val1 - 1) / 2) + 3)*100; /* �ŕt?�m�� */
skill_encchant_eremental_end(bl,SC_ENCPOISON);
break;
case SC_EDP: // [Celest]
val2 = val1 + 2; /* �ғŕt?�m��(%) */
calc_flag = 1;
break;
case SC_POISONREACT: /* �|�C�Y�����A�N�g */
val2=val1/2 + val1%2; // [Celest]
break;
case SC_IMPOSITIO: /* �C���|�V�e�B�I�}�k�X */
calc_flag = 1;
break;
case SC_ASPERSIO: /* �A�X�y���V�I */
skill_encchant_eremental_end(bl,SC_ASPERSIO);
break;
case SC_SUFFRAGIUM: /* �T�t���M�� */
case SC_BENEDICTIO: /* ��? */
case SC_MAGNIFICAT: /* �}�O�j�t�B�J?�g */
case SC_AETERNA: /* �G?�e���i */
break;
case SC_ENERGYCOAT: /* �G�i�W?�R?�g */
*opt3 |= 4;
break;
case SC_MAGICROD:
val2 = val1*20;
break;
case SC_KYRIE: /* �L���G�G���C�\�� */
val2 = battle_get_max_hp(bl) * (val1 * 2 + 10) / 100;/* �ϋv�x */
val3 = (val1 / 2 + 5); /* ��? */
// -- moonsoul (added to undo assumptio status if target has it)
if(sc_data[SC_ASSUMPTIO].timer!=-1 )
skill_status_change_end(bl,SC_ASSUMPTIO,-1);
break;
case SC_MINDBREAKER:
calc_flag = 1;
if(tick <= 0) tick = 1000; /* (�I?�g�o?�T?�N) */
case SC_GLORIA: /* �O�����A */
calc_flag = 1;
break;
case SC_LOUD: /* ���E�h�{�C�X */
calc_flag = 1;
break;
case SC_TRICKDEAD: /* ���ӂ� */
break;
case SC_QUAGMIRE: /* �N�@�O�}�C�A */
calc_flag = 1;
if(sc_data[SC_CONCENTRATE].timer!=-1 ) /* �W���͌������ */
skill_status_change_end(bl,SC_CONCENTRATE,-1);
if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* ���x�㏸���� */
skill_status_change_end(bl,SC_INCREASEAGI,-1);
if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1);
if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
skill_status_change_end(bl,SC_SPEARSQUICKEN,-1);
if(sc_data[SC_ADRENALINE].timer!=-1 )
skill_status_change_end(bl,SC_ADRENALINE,-1);
if(sc_data[SC_LOUD].timer!=-1 )
skill_status_change_end(bl,SC_LOUD,-1);
if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* �g�D��?�T�C�g */
skill_status_change_end(bl,SC_TRUESIGHT,-1);
if(sc_data[SC_WINDWALK].timer!=-1 ) /* �E�C���h�E�H?�N */
skill_status_change_end(bl,SC_WINDWALK,-1);
if(sc_data[SC_CARTBOOST].timer!=-1 ) /* �J?�g�u?�X�g */
skill_status_change_end(bl,SC_CARTBOOST,-1);
break;
case SC_FLAMELAUNCHER: /* �t��?�������`��? */
skill_encchant_eremental_end(bl,SC_FLAMELAUNCHER);
break;
case SC_FROSTWEAPON: /* �t���X�g�E�F�|�� */
skill_encchant_eremental_end(bl,SC_FROSTWEAPON);
break;
case SC_LIGHTNINGLOADER: /* ���C�g�j���O��?�_? */
skill_encchant_eremental_end(bl,SC_LIGHTNINGLOADER);
break;
case SC_SEISMICWEAPON: /* �T�C�Y�~�b�N�E�F�|�� */
skill_encchant_eremental_end(bl,SC_SEISMICWEAPON);
break;
case SC_DEVOTION: /* �f�B�{?�V���� */
calc_flag = 1;
break;
case SC_PROVIDENCE: /* �v�����B�f���X */
calc_flag = 1;
val2=val1*5;
break;
case SC_REFLECTSHIELD:
val2=10+val1*3;
break;
case SC_STRIPWEAPON:
case SC_STRIPSHIELD:
case SC_STRIPARMOR:
case SC_STRIPHELM:
case SC_CP_WEAPON:
case SC_CP_SHIELD:
case SC_CP_ARMOR:
case SC_CP_HELM:
break;
case SC_AUTOSPELL: /* �I?�g�X�y�� */
val4 = 5 + val1*2;
break;
case SC_VOLCANO:
calc_flag = 1;
val3 = val1*10;
val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
break;
case SC_DELUGE:
calc_flag = 1;
val3 = val1>=5?15: (val1==4?14: (val1==3?12: ( val1==2?9:5 ) ) );
val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
break;
case SC_VIOLENTGALE:
calc_flag = 1;
val3 = val1*3;
val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
break;
case SC_SPEARSQUICKEN: /* �X�s�A�N�C�b�P�� */
calc_flag = 1;
val2 = 20+val1;
*opt3 |= 1;
break;
case SC_COMBO:
break;
case SC_BLADESTOP_WAIT: /* ���n���(�҂�) */
break;
case SC_BLADESTOP: /* ���n��� */
if(val2==2) clif_bladestop((struct block_list *)val3,(struct block_list *)val4,1);
*opt3 |= 32;
break;
case SC_LULLABY: /* �q��S */
val2 = 11;
break;
case SC_RICHMANKIM:
break;
case SC_ETERNALCHAOS: /* �G�^?�i���J�I�X */
calc_flag = 1;
break;
case SC_DRUMBATTLE: /* ?���ۂ̋��� */
calc_flag = 1;
val2 = (val1+1)*25;
val3 = (val1+1)*2;
break;
case SC_NIBELUNGEN: /* �j?�x�����O�̎w�� */
calc_flag = 1;
val2 = (val1+2)*50;
val3 = (val1+2)*25;
break;
case SC_ROKISWEIL: /* ���L�̋��� */
break;
case SC_INTOABYSS: /* �[���̒��� */
break;
case SC_SIEGFRIED: /* �s���g�̃W?�N�t��?�h */
calc_flag = 1;
val2 = 40 + val1*5;
val3 = val1*10;
break;
case SC_DISSONANCE: /* �s���a�� */
val2 = 10;
break;
case SC_WHISTLE: /* ���J */
calc_flag = 1;
break;
case SC_ASSNCROS: /* �[�z�̃A�T�V���N���X */
calc_flag = 1;
break;
case SC_POEMBRAGI: /* �u���M�̎� */
break;
case SC_APPLEIDUN: /* �C�h�D���̗ь� */
calc_flag = 1;
break;
case SC_UGLYDANCE: /* ��������ȃ_���X */
val2 = 10;
break;
case SC_HUMMING: /* �n�~���O */
calc_flag = 1;
break;
case SC_DONTFORGETME: /* ����Y��Ȃ��� */
calc_flag = 1;
if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* ���x�㏸���� */
skill_status_change_end(bl,SC_INCREASEAGI,-1);
if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1);
if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
skill_status_change_end(bl,SC_SPEARSQUICKEN,-1);
if(sc_data[SC_ADRENALINE].timer!=-1 )
skill_status_change_end(bl,SC_ADRENALINE,-1);
if(sc_data[SC_ASSNCROS].timer!=-1 )
skill_status_change_end(bl,SC_ASSNCROS,-1);
if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* �g�D��?�T�C�g */
skill_status_change_end(bl,SC_TRUESIGHT,-1);
if(sc_data[SC_WINDWALK].timer!=-1 ) /* �E�C���h�E�H?�N */
skill_status_change_end(bl,SC_WINDWALK,-1);
if(sc_data[SC_CARTBOOST].timer!=-1 ) /* �J?�g�u?�X�g */
skill_status_change_end(bl,SC_CARTBOOST,-1);
break;
case SC_FORTUNE: /* �K�^�̃L�X */
calc_flag = 1;
break;
case SC_SERVICE4U: /* �T?�r�X�t�H?��? */
calc_flag = 1;
break;
case SC_DANCING: /* �_���X/���t�� */
calc_flag = 1;
val3= tick / 1000;
tick = 1000;
break;
case SC_EXPLOSIONSPIRITS: // �����g��
calc_flag = 1;
val2 = 75 + 25*val1;
*opt3 |= 8;
break;
case SC_STEELBODY: // ����
calc_flag = 1;
*opt3 |= 16;
break;
case SC_EXTREMITYFIST: /* ���C���e���� */
break;
case SC_AUTOCOUNTER:
val3 = val4 = 0;
break;
case SC_SPEEDPOTION0: /* ?���|?�V���� */
case SC_SPEEDPOTION1:
case SC_SPEEDPOTION2:
calc_flag = 1;
tick = 1000 * tick;
val2 = 5*(2+type-SC_SPEEDPOTION0);
break;
/* atk & matk potions [Valaris] */
case SC_ATKPOT:
case SC_MATKPOT:
calc_flag = 1;
tick = 1000 * tick;
break;
case SC_WEDDING: //�����p(�����ߏւɂȂ���?���̂�?���Ƃ�)
{
time_t timer;
calc_flag = 1;
tick = 10000;
if(!val2)
val2 = time(&timer);
}
break;
case SC_NOCHAT: //�`���b�g�֎~?��
{
time_t timer;
if(!battle_config.muting_players)
break;
tick = 60000;
if(!val2)
val2 = time(&timer);
updateflag = SP_MANNER;
save_flag = 1; // celest
}
break;
case SC_SELFDESTRUCTION: //����
clif_skillcasting(bl,bl->id, bl->id,0,0,331,skill_get_time(val2,val1));
val3 = tick / 1000;
tick = 1000;
break;
/* option1 */
case SC_STONE: /* �Ή� */
if(!(flag&2)) {
int sc_def = battle_get_mdef(bl)*200;
tick = tick - sc_def;
}
val3 = tick/1000;
if(val3 < 1) val3 = 1;
tick = 5000;
val2 = 1;
break;
case SC_SLEEP: /* ���� */
if(!(flag&2)) {
// int sc_def = 100 - (battle_get_int(bl) + battle_get_luk(bl)/3);
// tick = tick * sc_def / 100;
// if(tick < 1000) tick = 1000;
tick = 30000;//�����̓X�e?�^�X�ϐ���?��炸30�b
}
break;
case SC_FREEZE: /* ���� */
if(!(flag&2)) {
int sc_def = 100 - battle_get_mdef(bl);
tick = tick * sc_def / 100;
}
break;
case SC_STAN: /* �X�^���ival2�Ƀ~���b�Z�b�g�j */
if(!(flag&2)) {
int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/3);
tick = tick * sc_def / 100;
}
break;
/* option2 */
case SC_POISON: /* �� */
case SC_DPOISON: /* �ғ� */
calc_flag = 1;
if(!(flag&2)) {
int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/5);
tick = tick * sc_def / 100;
}
val3 = tick/1000;
if(val3 < 1) val3 = 1;
tick = 1000;
break;
case SC_SILENCE: /* ��?�i���b�N�X�f�r?�i�j */
if(!(flag&2)) {
int sc_def = 100 - battle_get_vit(bl);
tick = tick * sc_def / 100;
}
break;
case SC_BLIND: /* ��? */
calc_flag = 1;
if(!(flag&2)) {
int sc_def = battle_get_lv(bl)/10 + battle_get_int(bl)/15;
tick = 30000 - sc_def;
}
break;
case SC_CURSE:
calc_flag = 1;
if(!(flag&2)) {
int sc_def = 100 - battle_get_vit(bl);
tick = tick * sc_def / 100;
}
break;
/* option */
case SC_HIDING: /* �n�C�f�B���O */
calc_flag = 1;
if(bl->type == BL_PC) {
val2 = tick / 1000; /* ��?���� */
tick = 1000;
}
break;
case SC_CHASEWALK:
case SC_CLOAKING: /* �N��?�L���O */
if(bl->type == BL_PC) {
calc_flag = 1; // [Celest]
val2 = tick;
val3 = type==SC_CLOAKING ? 130-val1*3 : 135-val1*5;
}
else
tick = 5000*val1;
break;
case SC_SIGHT: /* �T�C�g/���A�t */
case SC_RUWACH:
val2 = tick/250;
tick = 10;
break;
/* �Z?�t�e�B�E�H?���A�j��?�} */
case SC_SAFETYWALL: case SC_PNEUMA:
tick=((struct skill_unit *)val2)->group->limit;
break;
/* �A���N�� */
case SC_ANKLE:
break;
/* �E�H?�^?�{?�� */
case SC_WATERBALL:
tick=150;
if(val1>5) //���x����5�ȏ�̏ꍇ��25?�ɐ���(1?�ڂ͂��łɑł��Ă�̂�-1)
val3=5*5-1;
else
val3= (val1|1)*(val1|1)-1;
break;
/* �X�L������Ȃ�/���Ԃ�?�W���Ȃ� */
case SC_RIDING:
calc_flag = 1;
tick = 600*1000;
break;
case SC_FALCON:
case SC_WEIGHT50:
case SC_WEIGHT90:
case SC_BROKNWEAPON:
case SC_BROKNARMOR:
tick=600*1000;
break;
case SC_AUTOGUARD:
{
int i,t;
for(i=val2=0;i<val1;i++) {
t = 5-(i>>1);
val2 += (t < 0)? 1:t;
}
}
break;
case SC_DEFENDER:
calc_flag = 1;
val2 = 5 + val1*15;
break;
case SC_KEEPING:
case SC_BARRIER:
calc_flag = 1;
case SC_HALLUCINATION:
break;
case SC_CONCENTRATION: /* �R���Z���g��?�V���� */
*opt3 |= 1;
calc_flag = 1;
break;
case SC_TENSIONRELAX: /* �e���V���������b�N�X */
calc_flag = 1;
if(bl->type == BL_PC) {
tick = 10000;
}
break;
case SC_AURABLADE: /* �I?���u��?�h */
case SC_PARRYING: /* �p���C���O */
// case SC_ASSUMPTIO: /* */
case SC_HEADCRUSH: /* �w�b�h�N���b�V�� */
case SC_JOINTBEAT: /* �W���C���g�r?�g */
// case SC_MARIONETTE: /* �}���I�l�b�g�R���g��?�� */
//�Ƃ肠������?��
break;
// -- moonsoul (for new upper class related skill status effects)
/*
case SC_AURABLADE:
val2 = val1*10;
break;
case SC_PARRYING:
val2=val1*3;
break;
case SC_CONCENTRATION:
calc_flag=1;
val2=val1*10;
val3=val1*5;
break;
case SC_TENSIONRELAX:
// val2 = 10;
// val3 = 15;
break;
case SC_BERSERK:
calc_flag=1;
break;
case SC_ASSUMPTIO:
if(sc_data[SC_KYRIE].timer!=-1 )
skill_status_change_end(bl,SC_KYRIE,-1);
break;
*/
case SC_WINDWALK: /* �E�C���h�E�H?�N */
calc_flag = 1;
val2 = (val1 / 2); //Flee�㏸��
break;
case SC_BERSERK: /* �o?�T?�N */
if(sd){
sd->status.hp = sd->status.max_hp * 3;
sd->status.sp = 0;
clif_updatestatus(sd,SP_HP);
clif_updatestatus(sd,SP_SP);
clif_status_change(bl,SC_INCREASEAGI,1); /* �A�C�R���\�� */
}
*opt3 |= 128;
tick = 10000;
calc_flag = 1;
break;
case SC_ASSUMPTIO: /* �A�X���v�e�B�I */
*opt3 |= 2048;
break;
case SC_BASILICA: // [celest]
break;
case SC_MARIONETTE: /* �}���I�l�b�g�R���g��?�� */
case SC_MARIONETTE2:
calc_flag = 1;
*opt3 |= 1024;
break;
case SC_MELTDOWN: /* �����g�_�E�� */
case SC_CARTBOOST: /* �J?�g�u?�X�g */
case SC_TRUESIGHT: /* �g�D��?�T�C�g */
case SC_SPIDERWEB: /* �X�p�C�_?�E�F�b�u */
case SC_MAGICPOWER: /* ���@��?�� */
calc_flag = 1;
break;
case SC_REJECTSWORD: /* ���W�F�N�g�\?�h */
val2 = 3; //3��U?�˕Ԃ�
break;
case SC_MEMORIZE: /* �������C�Y */
val2 = 3; //3��r����1/3�ɂ���
break;
case SC_GRAFFITI: /* �O���t�B�e�B */
{
struct skill_unit_group *sg = skill_unitsetting(bl,RG_GRAFFITI,val1,val2,val3,0);
if(sg)
val4 = (int)sg;
}
break;
case SC_SPLASHER: /* �x�i���X�v���b�V��? */
break;
case SC_FOGWALL:
val2 = 75;
// calc_flag = 1; // not sure of effects yet [celest]
break;
case SC_BLOCKSKILL:
if (!tick) tick = 60000;
if (!val3) val3 = -1;
break;
case SC_SLOWDOWN:
calc_flag = 1;
break;
case SC_LEADERSHIP:
case SC_GLORYWOUNDS:
case SC_SOULCOLD:
case SC_HAWKEYES:
tick = 1000;
calc_flag = 1;
//val4 = 1;
break;
case SC_REGENERATION:
val1 = 2;
case SC_BATTLEORDERS:
tick = 60000; // 1 minute
calc_flag = 1;
break;
default:
if(battle_config.error_log)
printf("UnknownStatusChange [%d]\n", type);
return 0;
}
if(bl->type==BL_PC && type<SC_SENDMAX)
clif_status_change(bl,type,1); /* �A�C�R���\�� */
/* option��?�X */
switch(type){
case SC_STONE:
case SC_FREEZE:
case SC_STAN:
case SC_SLEEP:
battle_stopattack(bl); /* �U?��~ */
skill_stop_dancing(bl,0); /* ���t/�_���X�̒�? */
{ /* �����Ɋ|����Ȃ��X�e?�^�X�ُ������ */
int i;
for(i = SC_STONE; i <= SC_SLEEP; i++){
if(sc_data[i].timer != -1){
(*sc_count)--;
delete_timer(sc_data[i].timer, skill_status_change_timer);
sc_data[i].timer = -1;
}
}
}
if(type == SC_STONE)
*opt1 = 6;
else
*opt1 = type - SC_STONE + 1;
opt_flag = 1;
break;
case SC_POISON:
case SC_CURSE:
case SC_SILENCE:
case SC_BLIND:
*opt2 |= 1<<(type-SC_POISON);
opt_flag = 1;
break;
case SC_DPOISON: // �b��œł̃G�t�F�N�g���g�p
*opt2 |= 1;
opt_flag = 1;
break;
case SC_SIGNUMCRUCIS:
*opt2 |= 0x40;
opt_flag = 1;
break;
case SC_HIDING:
case SC_CLOAKING:
battle_stopattack(bl); /* �U?��~ */
*option |= ((type==SC_HIDING)?2:4);
opt_flag =1 ;
break;
case SC_CHASEWALK:
battle_stopattack(bl); /* �U?��~ */
*option |= 16388;
opt_flag =1 ;
break;
case SC_SIGHT:
*option |= 1;
opt_flag = 1;
break;
case SC_RUWACH:
*option |= 8192;
opt_flag = 1;
break;
case SC_WEDDING:
*option |= 4096;
opt_flag = 1;
}
if(opt_flag) /* option��?�X */
clif_changeoption(bl);
(*sc_count)++; /* �X�e?�^�X�ُ��? */
sc_data[type].val1 = val1;
sc_data[type].val2 = val2;
sc_data[type].val3 = val3;
sc_data[type].val4 = val4;
/* �^�C�}?�ݒ� */
sc_data[type].timer = add_timer(
gettick() + tick, skill_status_change_timer, bl->id, type);
if(bl->type==BL_PC && calc_flag)
pc_calcstatus(sd,0); /* �X�e?�^�X�Čv�Z */
if(bl->type==BL_PC && save_flag)
chrif_save(sd); // save the player status
if(bl->type==BL_PC && updateflag)
clif_updatestatus(sd,updateflag); /* �X�e?�^�X���N���C�A���g�ɑ��� */
return 0;
}
/*==========================================
* �X�e?�^�X�ُ�S����
*------------------------------------------
*/
int skill_status_change_clear(struct block_list *bl, int type)
{
struct status_change* sc_data;
short *sc_count, *option, *opt1, *opt2, *opt3;
int i;
nullpo_retr(0, bl);
nullpo_retr(0, sc_data = battle_get_sc_data(bl));
nullpo_retr(0, sc_count = battle_get_sc_count(bl));
nullpo_retr(0, option = battle_get_option(bl));
nullpo_retr(0, opt1 = battle_get_opt1(bl));
nullpo_retr(0, opt2 = battle_get_opt2(bl));
nullpo_retr(0, opt3 = battle_get_opt3(bl));
if (*sc_count == 0)
return 0;
for(i = 0; i < MAX_STATUSCHANGE; i++){
if(sc_data[i].timer != -1){ /* �ُ킪����Ȃ�^�C�}?���폜���� */
/*
delete_timer(sc_data[i].timer, skill_status_change_timer);
sc_data[i].timer = -1;
if (!type && i < SC_SENDMAX)
clif_status_change(bl, i, 0);
*/
skill_status_change_end(bl, i, -1);
}
}
*sc_count = 0;
*opt1 = 0;
*opt2 = 0;
*opt3 = 0;
*option &= OPTION_MASK;
if (night_flag == 1 && type == BL_PC && !map[bl->m].flag.indoors && // by [Yor]
!map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) // [celest]
*opt2 |= STATE_BLIND;
if(!type || type&2)
clif_changeoption(bl);
return 0;
}
/* �N��?�L���O?���i����Ɉړ��s�\�n?�����邩�j */
int skill_check_cloaking(struct block_list *bl)
{
static int dx[]={-1, 0, 1,-1, 1,-1, 0, 1};
static int dy[]={-1,-1,-1, 0, 0, 1, 1, 1};
int end=1,i;
//missing sd [Found by Celest, commited by Aria]
struct map_session_data *sd=(struct map_session_data *)bl;
nullpo_retr(0, bl);
if(bl->type == BL_PC && !battle_config.pc_cloak_check_type) // If it's No it shouldn't be checked
return 0;
else if(bl->type == BL_MOB && !battle_config.monster_cloak_check_type)
return 0;
for(i=0;i<sizeof(dx)/sizeof(dx[0]);i++){
int c=map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i]);
if(c==1 || c==5) end=0;
}
if(end){
if ((bl->type == BL_PC && pc_checkskill(sd,AS_CLOAKING)<3) || bl->type == BL_MOB) {
skill_status_change_end(bl, SC_CLOAKING, -1);
*battle_get_option(bl)&=~4; /* �O�̂��߂�?�� */
}
else if (bl->type == BL_PC && sd->sc_data[SC_CLOAKING].val3 != 130) {
sd->sc_data[SC_CLOAKING].val3 = 130;
pc_calcspeed (sd);
}
}
else {
if (bl->type == BL_PC && sd->sc_data[SC_CLOAKING].val3 != 103) {
sd->sc_data[SC_CLOAKING].val3 = 103;
pc_calcspeed (sd);
}
}
return end;
}
int skill_type_cloaking(struct block_list *bl)
{
static int dx[]={-1, 0, 1,-1, 1,-1, 0, 1};
static int dy[]={-1,-1,-1, 0, 0, 1, 1, 1};
int end=1,i;
nullpo_retr(0, bl);
if(bl->type == BL_PC && battle_config.pc_cloak_check_type&1)
return 0;
else if(bl->type == BL_MOB && battle_config.monster_cloak_check_type&1)
return 0;
for(i=0; i<sizeof(dx)/sizeof(dx[0]); i++)
{
int c=map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i]);
if(c==1 || c==5) end=0;
}
return end;
}
/*
*----------------------------------------------------------------------------
* �X�L�����j�b�g
*----------------------------------------------------------------------------
*/
/*==========================================
* ���t/�_���X�X�L�����ǂ�������
* ��? �X�L��ID
* ?�� �_���X����Ȃ�=0 ���t=2 ����ȊO�̃_���X=1
*------------------------------------------
*/
int skill_is_danceskill(int id)
{
int i;
switch(id){
case BD_LULLABY: /* �q��� */
case BD_RICHMANKIM: /* �j�����h�̉� */
case BD_ETERNALCHAOS: /* �i���̍��� */
case BD_DRUMBATTLEFIELD: /* ?���ۂ̋��� */
case BD_RINGNIBELUNGEN: /* �j?�x�����O�̎w�� */
case BD_ROKISWEIL: /* ���L�̋��� */
case BD_INTOABYSS: /* �[���̒��� */
case BD_SIEGFRIED: /* �s���g�̃W?�N�t��?�h */
case BD_RAGNAROK: /* �_?��?�� */
case CG_MOONLIT: /* ������̐�ɗ�����Ԃт� */
i=2;
break;
case BA_DISSONANCE: /* �s���a�� */
case BA_FROSTJOKE: /* �����W��?�N */
case BA_WHISTLE: /* ���J */
case BA_ASSASSINCROSS: /* �[�z�̃A�T�V���N���X */
case BA_POEMBRAGI: /* �u���M�̎� */
case BA_APPLEIDUN: /* �C�h�D���̗ь� */
case DC_UGLYDANCE: /* ��������ȃ_���X */
case DC_SCREAM: /* �X�N��?�� */
case DC_HUMMING: /* �n�~���O */
case DC_DONTFORGETME: /* ����Y��Ȃ��Łc */
case DC_FORTUNEKISS: /* �K�^�̃L�X */
case DC_SERVICEFORYOU: /* �T?�r�X�t�H?��? */
i=1;
break;
default:
i=0;
}
return i;
}
/*==========================================
* ���t/�_���X����߂�
* flag 1�ō��t���Ȃ瑊���Ƀ��j�b�g��C����
*
*------------------------------------------
*/
void skill_stop_dancing(struct block_list *src, int flag)
{
struct status_change* sc_data;
struct skill_unit_group* group;
nullpo_retv(src);
sc_data=battle_get_sc_data(src);
if(sc_data && sc_data[SC_DANCING].timer != -1) {
group=(struct skill_unit_group *)sc_data[SC_DANCING].val2; //�_���X�̃X�L�����j�b�gID��val2�ɓ����Ă�
if(group && src->type==BL_PC && sc_data && sc_data[SC_DANCING].val4){ //���t��?
struct map_session_data* dsd=map_id2sd(sc_data[SC_DANCING].val4); //������sd�擾
if(flag){ //���O�A�E�g�ȂǕЕ��������Ă����t��??�����
if(dsd && src->id == group->src_id){ //�O��?�v��������PC��������
group->src_id=sc_data[SC_DANCING].val4; //�����ɃO��?�v��C����
if(flag&1) //���O�A�E�g
dsd->sc_data[SC_DANCING].val4=0; //�����̑�����0�ɂ��č��t�I�����ʏ�̃_���X?��
if(flag&2) //�n�G��тȂ�
return; //���t���_���X?�Ԃ��I�������Ȃ����X�L�����j�b�g�͒u���Ă��ڂ�
}else if(dsd && dsd->bl.id == group->src_id){ //�������O��?�v�������Ă���PC��������(�����̓O��?�v�������Ă��Ȃ�)
if(flag&1) //���O�A�E�g
dsd->sc_data[SC_DANCING].val4=0; //�����̑�����0�ɂ��č��t�I�����ʏ�̃_���X?��
if(flag&2) //�n�G��тȂ�
return; //���t���_���X?�Ԃ��I�������Ȃ����X�L�����j�b�g�͒u���Ă��ڂ�
}
skill_status_change_end(src,SC_DANCING,-1);//�����̃X�e?�^�X���I��������
//�����ăO��?�v�͏����Ȃ��������Ȃ��̂ŃX�e?�^�X�v�Z������Ȃ��H
return;
}else{
if(dsd && src->id == group->src_id){ //�O��?�v�������Ă�PC���~�߂�
skill_status_change_end((struct block_list *)dsd,SC_DANCING,-1);//����̃X�e?�^�X���I��������
}
if(dsd && dsd->bl.id == group->src_id){ //�������O��?�v�������Ă���PC���~�߂�(�����̓O��?�v�������Ă��Ȃ�)
skill_status_change_end(src,SC_DANCING,-1);//�����̃X�e?�^�X���I��������
}
}
}
if(flag&2 && group && src->type==BL_PC){ //�n�G�Ŕ�Ƃ��Ƃ��̓��j�b�g�����
struct map_session_data *sd = (struct map_session_data *)src;
skill_unit_move_unit_group(group, sd->bl.m,(sd->to_x - sd->bl.x),(sd->to_y - sd->bl.y));
return;
}
skill_delunitgroup(group);
if(src->type==BL_PC)
pc_calcstatus((struct map_session_data *)src,0);
}
}
/*==========================================
* �X�L�����j�b�g������
*------------------------------------------
*/
struct skill_unit *skill_initunit(struct skill_unit_group *group,int idx,int x,int y)
{
struct skill_unit *unit;
nullpo_retr(NULL, group);
nullpo_retr(NULL, unit=&group->unit[idx]);
if(!unit->alive)
group->alive_count++;
unit->bl.id=map_addobject(&unit->bl);
unit->bl.type=BL_SKILL;
unit->bl.m=group->map;
unit->bl.x=x;
unit->bl.y=y;
unit->group=group;
unit->val1=unit->val2=0;
unit->alive=1;
map_addblock(&unit->bl);
clif_skill_setunit(unit);
return unit;
}
int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap );
/*==========================================
* �X�L�����j�b�g�폜
*------------------------------------------
*/
int skill_delunit(struct skill_unit *unit)
{
struct skill_unit_group *group;
int range;
nullpo_retr(0, unit);
if(!unit->alive)
return 0;
nullpo_retr(0, group=unit->group);
/* onlimit�C�x���g�Ăяo�� */
skill_unit_onlimit( unit,gettick() );
/* ondelete�C�x���g�Ăяo�� */
range=group->range;
map_foreachinarea( skill_unit_timer_sub_ondelete, unit->bl.m,
unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0,
&unit->bl,gettick() );
clif_skill_delunit(unit);
unit->group=NULL;
unit->alive=0;
map_delobjectnofree(unit->bl.id);
if(group->alive_count>0 && (--group->alive_count)<=0)
skill_delunitgroup(group);
return 0;
}
/*==========================================
* �X�L�����j�b�g�O��?�v������
*------------------------------------------
*/
static int skill_unit_group_newid=10;
struct skill_unit_group *skill_initunitgroup(struct block_list *src,
int count,int skillid,int skilllv,int unit_id)
{
int i;
struct skill_unit_group *group=NULL, *list=NULL;
int maxsug=0;
if(skilllv <= 0) return 0;
nullpo_retr(NULL, src);
if(src->type==BL_PC){
list=((struct map_session_data *)src)->skillunit;
maxsug=MAX_SKILLUNITGROUP;
}else if(src->type==BL_MOB){
list=((struct mob_data *)src)->skillunit;
maxsug=MAX_MOBSKILLUNITGROUP;
}else if(src->type==BL_PET){
list=((struct pet_data *)src)->skillunit;
maxsug=MAX_MOBSKILLUNITGROUP;
}
if(list){
for(i=0;i<maxsug;i++) /* �������?�� */
if(list[i].group_id==0){
group=&list[i];
break;
}
if(group==NULL){ /* �ĂȂ��̂ŌÂ�����?�� */
int j=0;
unsigned maxdiff=0,x,tick=gettick();
for(i=0;i<maxsug;i++)
if((x=DIFF_TICK(tick,list[i].tick))>maxdiff){
maxdiff=x;
j=i;
}
skill_delunitgroup(&list[j]);
group=&list[j];
}
}
if(group==NULL){
printf("skill_initunitgroup: error unit group !\n");
exit(1);
}
group->src_id=src->id;
group->party_id=battle_get_party_id(src);
group->guild_id=battle_get_guild_id(src);
group->group_id=skill_unit_group_newid++;
if(skill_unit_group_newid<=0)
skill_unit_group_newid=10;
group->unit=(struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
group->unit_count=count;
group->val1=group->val2=0;
group->skill_id=skillid;
group->skill_lv=skilllv;
group->unit_id=unit_id;
group->map=src->m;
group->range=0;
group->limit=10000;
group->interval=1000;
group->tick=gettick();
group->valstr=NULL;
if( skill_is_danceskill(skillid) ){
struct map_session_data *sd = NULL;
if(src->type==BL_PC && (sd=(struct map_session_data *)src) ){
sd->skillid_dance=skillid;
sd->skilllv_dance=skilllv;
}
skill_status_change_start(src,SC_DANCING,skillid,(int)group,0,0,skill_get_time(skillid,skilllv)+1000,0);
switch(skillid){ //���t�X�L���͑������_���X?�Ԃɂ���
case BD_LULLABY: /* �q��� */
case BD_RICHMANKIM: /* �j�����h�̉� */
case BD_ETERNALCHAOS: /* �i���̍��� */
case BD_DRUMBATTLEFIELD: /* ?���ۂ̋��� */
case BD_RINGNIBELUNGEN: /* �j?�x�����O�̎w�� */
case BD_ROKISWEIL: /* ���L�̋��� */
case BD_INTOABYSS: /* �[���̒��� */
case BD_SIEGFRIED: /* �s���g�̃W?�N�t��?�h */
case BD_RAGNAROK: /* �_?��?�� */
case CG_MOONLIT: /* ������̐�ɗ�����Ԃт� */
{
int range=1;
int c=0;
if(sd){
map_foreachinarea(skill_check_condition_use_sub,sd->bl.m,
sd->bl.x-range,sd->bl.y-range,
sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c);
}
}
}
}
return group;
}
/*==========================================
* �X�L�����j�b�g�O��?�v�폜
*------------------------------------------
*/
int skill_delunitgroup(struct skill_unit_group *group)
{
struct block_list *src;
int i;
nullpo_retr(0, group);
if(group->unit_count<=0)
return 0;
src=map_id2bl(group->src_id);
if( skill_is_danceskill(group->skill_id) ){ //�_���X�X�L���̓_���X?�Ԃ���������
if(src)
skill_status_change_end(src,SC_DANCING,-1);
}
group->alive_count=0;
if(group->unit!=NULL){
for(i=0;i<group->unit_count;i++)
if(group->unit[i].alive)
skill_delunit(&group->unit[i]);
}
if(group->valstr!=NULL){
map_freeblock(group->valstr);
group->valstr=NULL;
}
map_freeblock(group->unit); /* free()�̑ւ�� */
group->unit=NULL;
group->src_id=0;
group->group_id=0;
group->unit_count=0;
return 0;
}
/*==========================================
* �X�L�����j�b�g�O��?�v�S�폜
*------------------------------------------
*/
int skill_clear_unitgroup(struct block_list *src)
{
struct skill_unit_group *group=NULL;
int maxsug=0;
nullpo_retr(0, src);
if(src->type==BL_PC){
group=((struct map_session_data *)src)->skillunit;
maxsug=MAX_SKILLUNITGROUP;
}else if(src->type==BL_MOB){
group=((struct mob_data *)src)->skillunit;
maxsug=MAX_MOBSKILLUNITGROUP;
}else if(src->type==BL_PET){ // [Valaris]
group=((struct pet_data *)src)->skillunit;
maxsug=MAX_MOBSKILLUNITGROUP;
}
if(group){
int i;
for(i=0;i<maxsug;i++)
if(group[i].group_id>0 && group[i].src_id == src->id)
skill_delunitgroup(&group[i]);
}
return 0;
}
/*==========================================
* �X�L�����j�b�g�O��?�v�̔�e��tick?��
*------------------------------------------
*/
struct skill_unit_group_tickset *skill_unitgrouptickset_search(
struct block_list *bl,int group_id)
{
int i,j=0,k,s=group_id%MAX_SKILLUNITGROUPTICKSET;
struct skill_unit_group_tickset *set=NULL;
nullpo_retr(0, bl);
if(bl->type==BL_PC){
set=((struct map_session_data *)bl)->skillunittick;
}else{
set=((struct mob_data *)bl)->skillunittick;
}
if(set==NULL)
return 0;
for(i=0;i<MAX_SKILLUNITGROUPTICKSET;i++)
if( set[(k=(i+s)%MAX_SKILLUNITGROUPTICKSET)].group_id == group_id )
return &set[k];
else if( set[k].group_id==0 )
j=k;
return &set[j];
}
/*==========================================
* �X�L�����j�b�g�O��?�v�̔�e��tick�폜
*------------------------------------------
*/
int skill_unitgrouptickset_delete(struct block_list *bl,int group_id)
{
int i,s=group_id%MAX_SKILLUNITGROUPTICKSET;
struct skill_unit_group_tickset *set=NULL,*ts;
nullpo_retr(0, bl);
if(bl->type==BL_PC){
set=((struct map_session_data *)bl)->skillunittick;
}else{
set=((struct mob_data *)bl)->skillunittick;
}
if(set!=NULL){
for(i=0;i<MAX_SKILLUNITGROUPTICKSET;i++)
if( (ts=&set[(i+s)%MAX_SKILLUNITGROUPTICKSET])->group_id == group_id )
ts->group_id=0;
}
return 0;
}
/*==========================================
* �X�L�����j�b�g�^�C�}??��?���p(foreachinarea)
*------------------------------------------
*/
int skill_unit_timer_sub_onplace( struct block_list *bl, va_list ap )
{
struct block_list *src;
struct skill_unit *su;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
src=va_arg(ap,struct block_list*);
tick=va_arg(ap,unsigned int);
su = (struct skill_unit *)src;
if( su && su->alive ) {
struct skill_unit_group *sg;
sg = su->group;
if(sg && battle_check_target(src,bl,sg->target_flag )>0)
skill_unit_onplace( su, bl, tick );
}
return 0;
}
/*==========================================
* �X�L�����j�b�g�^�C�}?�폜?���p(foreachinarea)
*------------------------------------------
*/
int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap )
{
struct block_list *src;
struct skill_unit *su;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
src=va_arg(ap,struct block_list*);
tick=va_arg(ap,unsigned int);
su = (struct skill_unit *)src;
if( su && su->alive ){
struct skill_unit_group *sg;
sg = su->group;
if( sg && battle_check_target(src,bl,sg->target_flag )>0 )
skill_unit_ondelete( su, bl, tick );
}
return 0;
}
/*==========================================
* �X�L�����j�b�g�^�C�}??���p(foreachobject)
*------------------------------------------
*/
int skill_unit_timer_sub( struct block_list *bl, va_list ap )
{
struct skill_unit *unit;
struct skill_unit_group *group;
int range;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, unit=(struct skill_unit *)bl);
nullpo_retr(0, group=unit->group);
tick=va_arg(ap,unsigned int);
if(!unit->alive)
return 0;
range=(unit->range!=0)?unit->range:group->range;
/* onplace�C�x���g�Ăяo�� */
if(unit->alive && unit->range>=0){
map_foreachinarea( skill_unit_timer_sub_onplace, bl->m,
bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,
bl,tick);
if(group->unit_id == 0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val2){
map_foreachinarea( skill_idun_heal, bl->m,
bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,unit);
group->val2++;
}
}
/* ���Ԑ�폜 */
if(unit->alive &&
(DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit) ){
switch(group->unit_id){
case 0x8f: /* �u���X�g�}�C�� */
group->unit_id = 0x8c;
clif_changelook(bl,LOOK_BASE,group->unit_id);
group->limit=DIFF_TICK(tick+1500,group->tick);
unit->limit=DIFF_TICK(tick+1500,group->tick);
break;
case 0x90: /* �X�L�b�h�g���b�v */
case 0x91: /* �A���N���X�l�A */
case 0x93: /* �����h�}�C�� */
case 0x94: /* �V���b�N�E�F?�u�g���b�v */
case 0x95: /* �T���h�}�� */
case 0x96: /* �t���b�V��? */
case 0x97: /* �t��?�W���O�g���b�v */
case 0x98: /* �N���C���A?�g���b�v */
case 0x99: /* �g?�L?�{�b�N�X */
{
struct block_list *src=map_id2bl(group->src_id);
if(group->unit_id == 0x91 && group->val2);
else{
if(src && src->type==BL_PC){
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid=1065;
item_tmp.identify=1;
map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,NULL,NULL,NULL,0); // ?�Ԋ�
}
}
}
default:
skill_delunit(unit);
}
}
if(group->unit_id == 0x8d) {
unit->val1 -= 5;
if(unit->val1 <= 0 && unit->limit + group->tick > tick + 700)
unit->limit = DIFF_TICK(tick+700,group->tick);
}
return 0;
}
/*==========================================
* �X�L�����j�b�g�^�C�}??��
*------------------------------------------
*/
int skill_unit_timer( int tid,unsigned int tick,int id,int data)
{
map_freeblock_lock();
map_foreachobject( skill_unit_timer_sub, BL_SKILL, tick );
map_freeblock_unlock();
return 0;
}
/*==========================================
* �X�L�����j�b�g�ړ���?���p(foreachinarea)
*------------------------------------------
*/
int skill_unit_out_all_sub( struct block_list *bl, va_list ap )
{
struct skill_unit *unit;
struct skill_unit_group *group;
struct block_list *src;
int range;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, src=va_arg(ap,struct block_list*));
nullpo_retr(0, unit=(struct skill_unit *)bl);
nullpo_retr(0, group=unit->group);
tick=va_arg(ap,unsigned int);
if(!unit->alive || src->prev==NULL)
return 0;
range=(unit->range!=0)?unit->range:group->range;
if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 )
return 0;
if( src->x >= bl->x-range && src->x <= bl->x+range &&
src->y >= bl->y-range && src->y <= bl->y+range )
skill_unit_onout( unit, src, tick );
return 0;
}
/*==========================================
* �X�L�����j�b�g�ړ���?��
*------------------------------------------
*/
int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range)
{
nullpo_retr(0, bl);
if( bl->prev==NULL )
return 0;
if(range<7)
range=7;
map_foreachinarea( skill_unit_out_all_sub,
bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL,
bl,tick );
return 0;
}
/*==========================================
* �X�L�����j�b�g�ړ���?���p(foreachinarea)
*------------------------------------------
*/
int skill_unit_move_sub( struct block_list *bl, va_list ap )
{
struct skill_unit *unit;
struct skill_unit_group *group;
struct block_list *src;
int range;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, unit=(struct skill_unit *)bl);
nullpo_retr(0, src=va_arg(ap,struct block_list*));
tick=va_arg(ap,unsigned int);
if(!unit->alive || src->prev==NULL)
return 0;
if((group=unit->group) == NULL)
return 0;
range=(unit->range!=0)?unit->range:group->range;
if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 )
return 0;
if( src->x >= bl->x-range && src->x <= bl->x+range &&
src->y >= bl->y-range && src->y <= bl->y+range )
skill_unit_onplace( unit, src, tick );
else
skill_unit_onout( unit, src, tick );
return 0;
}
/*==========================================
* �X�L�����j�b�g�ړ���?��
*------------------------------------------
*/
int skill_unit_move( struct block_list *bl,unsigned int tick,int range)
{
nullpo_retr(0, bl);
if( bl->prev==NULL )
return 0;
if(range<7)
range=7;
map_foreachinarea( skill_unit_move_sub,
bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL,
bl,tick );
return 0;
}
/*==========================================
* �X�L�����j�b�g��?�̈ړ���?��(foreachinarea)
*------------------------------------------
*/
int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap )
{
struct skill_unit *unit;
struct skill_unit_group *group;
struct block_list *src;
int range;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, src=va_arg(ap,struct block_list*));
nullpo_retr(0, unit=(struct skill_unit *)src);
nullpo_retr(0, group=unit->group);
tick=va_arg(ap,unsigned int);
if(!unit->alive || bl->prev==NULL)
return 0;
range=(unit->range!=0)?unit->range:group->range;
if( range<0 || battle_check_target(src,bl,group->target_flag )<=0 )
return 0;
if( bl->x >= src->x-range && bl->x <= src->x+range &&
bl->y >= src->y-range && bl->y <= src->y+range )
skill_unit_onplace( unit, bl, tick );
else
skill_unit_onout( unit, bl, tick );
return 0;
}
/*==========================================
* �X�L�����j�b�g��?�̈ړ���?��
* ��?�̓O��?�v�ƈړ���
*------------------------------------------
*/
int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy)
{
nullpo_retr(0, group);
if( group->unit_count<=0)
return 0;
if(group->unit!=NULL){
if(!battle_config.unit_movement_type){
int i;
for(i=0;i<group->unit_count;i++){
struct skill_unit *unit=&group->unit[i];
if(unit->alive && !(m==unit->bl.m && dx==0 && dy==0)){
int range=unit->range;
map_delblock(&unit->bl);
unit->bl.m = m;
unit->bl.x += dx;
unit->bl.y += dy;
map_addblock(&unit->bl);
clif_skill_setunit(unit);
if(range>0){
if(range<7)
range=7;
map_foreachinarea( skill_unit_move_unit_group_sub, unit->bl.m,
unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0,
&unit->bl,gettick() );
}
}
}
}else{
int i,j, *r_flag, *s_flag, *m_flag;
struct skill_unit *unit1;
struct skill_unit *unit2;
r_flag = (int *) malloc(sizeof(int) * group->unit_count);
s_flag = (int *) malloc(sizeof(int) * group->unit_count);
m_flag = (int *) malloc(sizeof(int) * group->unit_count);
memset(r_flag,0, sizeof(int) * group->unit_count);// ?���t���O
memset(s_flag,0, sizeof(int) * group->unit_count);// ?���t���O
memset(m_flag,0, sizeof(int) * group->unit_count);// ?���t���O
//��Ƀt���O��S�����߂�
for(i=0;i<group->unit_count;i++){
int move_check=0;// ���Ԃ�t���O
unit1=&group->unit[i];
for(j=0;j<group->unit_count;j++){
unit2=&group->unit[j];
if(unit1->bl.m==m && unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){
//�ړ���Ƀ��j�b�g�����Ԃ��Ă���
s_flag[i]=1;// �ړ��O�̃��j�b�g�i���o?��?���t���Oon
r_flag[j]=1;// ���Ԃ郆�j�b�g�i���o?��?���t���Oon
move_check=1;//���j�b�g�����Ԃ����B
break;
}
}
if(!move_check)// ���j�b�g�����Ԃ��ĂȂ�������
m_flag[i]=1;// �ړ��O���j�b�g�i���o?�̈ړ��t���Oon
}
//�t���O�Ɋ�Â��ă��j�b�g�ړ�
for(i=0;i<group->unit_count;i++){
unit1=&group->unit[i];
if(m_flag[i]){// �ړ��t���O��on��
if(!r_flag[i]){// ?���t���O��off�Ȃ�
//?���ړ�(range��?���̕K�v����)
int range=unit1->range;
map_delblock(&unit1->bl);
unit1->bl.m = m;
unit1->bl.x += dx;
unit1->bl.y += dy;
map_addblock(&unit1->bl);
clif_skill_setunit(unit1);
if(range > 0){
if(range < 7)
range = 7;
map_foreachinarea( skill_unit_move_unit_group_sub, unit1->bl.m,
unit1->bl.x-range,unit1->bl.y-range,unit1->bl.x+range,unit1->bl.y+range,0,
&unit1->bl,gettick() );
}
}else{// ?���t���O��on�Ȃ�
//�j�b�g�ɂȂ�̂ŁA?���\�ȃ��j�b�g��T��
for(j=0;j<group->unit_count;j++){
unit2=&group->unit[j];
if(s_flag[j] && !r_flag[j]){
// ?���ړ�(range?���t��)
int range=unit1->range;
map_delblock(&unit2->bl);
unit2->bl.m = m;
unit2->bl.x = unit1->bl.x + dx;
unit2->bl.y = unit1->bl.y + dy;
unit2->range = unit1->range;
map_addblock(&unit2->bl);
clif_skill_setunit(unit2);
if(range > 0){
if(range < 7)
range = 7;
map_foreachinarea( skill_unit_move_unit_group_sub, unit2->bl.m,
unit2->bl.x-range,unit2->bl.y-range,unit2->bl.x+range,unit2->bl.y+range,0,
&unit2->bl,gettick() );
}
s_flag[j]=0;// ?�����������̂�off
break;
}
}
}
}
}
free(r_flag);
free(s_flag);
free(m_flag);
}
}
return 0;
}
/*----------------------------------------------------------------------------
* �A�C�e������
*----------------------------------------------------------------------------
*/
/*==========================================
* �A�C�e�������\����
*------------------------------------------
*/
int skill_can_produce_mix( struct map_session_data *sd, int nameid, int trigger )
{
int i,j;
nullpo_retr(0, sd);
if(nameid<=0)
return 0;
for(i=0;i<MAX_SKILL_PRODUCE_DB;i++){
if(skill_produce_db[i].nameid == nameid )
break;
}
if( i >= MAX_SKILL_PRODUCE_DB ) /* �f?�^�x?�X�ɂȂ� */
return 0;
if(trigger>=0){
if(trigger == 32 || trigger == 16 || trigger==64 || trigger == 256) {
if(skill_produce_db[i].itemlv!=trigger) /* �t�@?�}�V?���|?�V�����ނƗn??��?�ΈȊO�͂��� */
return 0;
}else{
if(skill_produce_db[i].itemlv>=16) /* ����ȊO�͂��� */
return 0;
if( itemdb_wlv(nameid)>trigger ) /* ����Lv���� */
return 0;
}
}
if( (j=skill_produce_db[i].req_skill)>0 && pc_checkskill(sd,j)<=0 )
return 0; /* �X�L��������Ȃ� */
for(j=0;j<MAX_PRODUCE_RESOURCE;j++){
int id,x,y;
if( (id=skill_produce_db[i].mat_id[j]) <= 0 ) /* ����ȏ�͍ޗ��v��Ȃ� */
continue;
if(skill_produce_db[i].mat_amount[j] <= 0) {
if(pc_search_inventory(sd,id) < 0)
return 0;
}
else {
for(y=0,x=0;y<MAX_INVENTORY;y++)
if( sd->status.inventory[y].nameid == id )
x+=sd->status.inventory[y].amount;
if(x<skill_produce_db[i].mat_amount[j]) /* �A�C�e��������Ȃ� */
return 0;
}
}
return i+1;
}
/*==========================================
* �A�C�e�������\����
*------------------------------------------
*/
int skill_produce_mix( struct map_session_data *sd,
int nameid, int slot1, int slot2, int slot3 )
{
int slot[3];
int i,sc,ele,idx,equip,wlv,make_per,flag;
nullpo_retr(0, sd);
if( !(idx=skill_can_produce_mix(sd,nameid,-1)) ) /* ?���s�� */
return 0;
idx--;
slot[0]=slot1;
slot[1]=slot2;
slot[2]=slot3;
/* ����?��?�� */
for(i=0,sc=0,ele=0;i<3;i++){
int j;
if( slot[i]<=0 )
continue;
j = pc_search_inventory(sd,slot[i]);
if(j < 0) /* �s���p�P�b�g(�A�C�e������)�`�F�b�N */
continue;
if(slot[i]==1000){ /* ���̂����� */
pc_delitem(sd,j,1,1);
sc++;
}
if(slot[i]>=994 && slot[i]<=997 && ele==0){ /* ?���� */
static const int ele_table[4]={3,1,4,2};
pc_delitem(sd,j,1,1);
ele=ele_table[slot[i]-994];
}
}
/* �ޗ����� */
for(i=0;i<MAX_PRODUCE_RESOURCE;i++){
int j,id,x;
if( (id=skill_produce_db[idx].mat_id[i]) <= 0 )
continue;
x=skill_produce_db[idx].mat_amount[i]; /* �K�v�Ȍ�? */
do{ /* �Q�ȏ�̃C���f�b�N�X�ɂ܂������Ă��邩������Ȃ� */
int y=0;
j = pc_search_inventory(sd,id);
if(j >= 0){
y = sd->status.inventory[j].amount;
if(y>x)y=x; /* ������� */
pc_delitem(sd,j,y,0);
}else {
if(battle_config.error_log)
printf("skill_produce_mix: material item error\n");
}
x-=y; /* �܂�����Ȃ���?���v�Z */
}while( j>=0 && x>0 ); /* �ޗ�������邩�A�G��?�ɂȂ�܂ŌJ��Ԃ� */
}
/* �m������ */
equip = itemdb_isequip(nameid);
if(!equip) {
if(skill_produce_db[idx].req_skill==AM_PHARMACY) {
if((nameid >= 501 && nameid <= 506) || (nameid >= 545 && nameid <= 547) || nameid == 525)
make_per = 2000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_POTIONPITCHER)*100;
else if(nameid == 970)
make_per = 1500 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300;
else if(nameid == 7135)
make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_DEMONSTRATION)*100;
else if(nameid == 7136)
make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_ACIDTERROR)*100;
else if(nameid == 7137)
make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CANNIBALIZE)*100;
else if(nameid == 7138)
make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_SPHEREMINE)*100;
else if(nameid == 7139)
make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CP_WEAPON)*100 +
pc_checkskill(sd,AM_CP_SHIELD)*100 + pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100;
else
make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300;
} else if (skill_produce_db[idx].req_skill == ASC_CDP) {
make_per = 2000 + 40*sd->paramc[4] + 20*sd->paramc[5];
//make_per = 20 + (20*sd->paramc[4])/50 + (20*sd->paramc[5])/100;
} else {
if(nameid == 998)
make_per = 2000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*600;
else if(nameid == 985)
make_per = 1000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + (pc_checkskill(sd,skill_produce_db[idx].req_skill)-1)*500;
else
make_per = 1000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500;
}
}
else {
int add_per;
if(pc_search_inventory(sd,989) >= 0) add_per = 750;
else if(pc_search_inventory(sd,988) >= 0) add_per = 500;
else if(pc_search_inventory(sd,987) >= 0) add_per = 250;
else if(pc_search_inventory(sd,986) >= 0) add_per = 0;
else add_per = -500;
if(ele) add_per -= 500;
add_per -= sc*500;
wlv = itemdb_wlv(nameid);
make_per = ((250 + sd->status.base_level*15 + sd->paramc[4]*10 + sd->paramc[5]*5 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500 +
add_per) * (100 - (wlv - 1)*20))/100 + pc_checkskill(sd,BS_WEAPONRESEARCH)*100 + ((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100 : 0);
}
if(make_per < 1) make_per = 1;
if(skill_produce_db[idx].req_skill==AM_PHARMACY ||
skill_produce_db[idx].req_skill==ASC_CDP) {
if( battle_config.pp_rate!=100 )
make_per=make_per*battle_config.pp_rate/100;
}
else {
if( battle_config.wp_rate!=100 ) /* �m��� */
make_per=make_per*battle_config.wp_rate/100;
}
// if(battle_config.etc_log)
// printf("make rate = %d\n",make_per);
if(rand()%10000 < make_per){
/* ���� */
struct item tmp_item;
memset(&tmp_item,0,sizeof(tmp_item));
tmp_item.nameid=nameid;
tmp_item.amount=1;
tmp_item.identify=1;
if(equip){ /* ����̏ꍇ */
tmp_item.card[0]=0x00ff; /* ��������t���O */
tmp_item.card[1]=((sc*5)<<8)+ele; /* ?���Ƃ悳 */
*((unsigned long *)(&tmp_item.card[2]))=sd->char_id; /* �L����ID */
}
else if((battle_config.produce_item_name_input && skill_produce_db[idx].req_skill!=AM_PHARMACY) ||
(battle_config.produce_potion_name_input && skill_produce_db[idx].req_skill==AM_PHARMACY)) {
tmp_item.card[0]=0x00fe;
tmp_item.card[1]=0;
*((unsigned long *)(&tmp_item.card[2]))=sd->char_id; /* �L����ID */
}
#ifndef TXT_ONLY
if(log_config.produce > 0)
log_produce(sd,nameid,slot1,slot2,slot3,1);
#endif //USE_SQL
switch (skill_produce_db[idx].req_skill) {
case AM_PHARMACY:
clif_produceeffect(sd,2,nameid);/* ��?�G�t�F�N�g */
clif_misceffect(&sd->bl,5); /* ���l�ɂ�������ʒm */
break;
case ASC_CDP:
clif_produceeffect(sd,2,nameid);/* �b���?�G�t�F�N�g */
clif_misceffect(&sd->bl,5);
break;
default: /* ���퐻���A�R�C������ */
clif_produceeffect(sd,0,nameid); /* ���퐻���G�t�F�N�g */
clif_misceffect(&sd->bl,3);
break;
}
if((flag = pc_additem(sd,&tmp_item,1))) {
clif_additem(sd,0,0,flag);
map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
}
}
else {
#ifndef TXT_ONLY
if(log_config.produce > 0)
log_produce(sd,nameid,slot1,slot2,slot3,0);
#endif //USE_SQL
switch (skill_produce_db[idx].req_skill) {
case AM_PHARMACY:
clif_produceeffect(sd,3,nameid);/* ��?���s�G�t�F�N�g */
clif_misceffect(&sd->bl,6); /* ���l�ɂ����s��ʒm */
break;
case ASC_CDP:
{
clif_produceeffect(sd,3,nameid); /* �b���?�G�t�F�N�g */
clif_misceffect(&sd->bl,6); /* ���l�ɂ����s��ʒm */
pc_heal(sd, -(sd->status.max_hp>>2), 0);
}
break;
default:
clif_produceeffect(sd,1,nameid);/* ���퐻�����s�G�t�F�N�g */
clif_misceffect(&sd->bl,2); /* ���l�ɂ����s��ʒm */
break;
}
}
return 0;
}
int skill_arrow_create( struct map_session_data *sd,int nameid)
{
int i,j,flag,index=-1;
struct item tmp_item;
nullpo_retr(0, sd);
if(nameid <= 0)
return 1;
for(i=0;i<MAX_SKILL_ARROW_DB;i++)
if(nameid == skill_arrow_db[i].nameid) {
index = i;
break;
}
if(index < 0 || (j = pc_search_inventory(sd,nameid)) < 0)
return 1;
pc_delitem(sd,j,1,0);
for(i=0;i<5;i++) {
memset(&tmp_item,0,sizeof(tmp_item));
tmp_item.identify = 1;
tmp_item.nameid = skill_arrow_db[index].cre_id[i];
tmp_item.amount = skill_arrow_db[index].cre_amount[i];
if(battle_config.making_arrow_name_input) {
tmp_item.card[0]=0x00fe;
tmp_item.card[1]=0;
*((unsigned long *)(&tmp_item.card[2]))=sd->char_id; /* �L����ID */
}
if(tmp_item.nameid <= 0 || tmp_item.amount <= 0)
continue;
if((flag = pc_additem(sd,&tmp_item,tmp_item.amount))) {
clif_additem(sd,0,0,flag);
map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
}
}
return 0;
}
/*----------------------------------------------------------------------------
* �������n
*/
/*==========================================
* �X�L��?�W�t�@�C��?��?��
* skill_db.txt �X�L���f?�^
* skill_cast_db.txt �X�L���̉r�����Ԃƃf�B���C�f?�^
* produce_db.txt �A�C�e���쐬�X�L���p�f?�^
* create_arrow_db.txt ��쐬�X�L���p�f?�^
* abra_db.txt �A�u���J�_�u��?���X�L���f?�^
*------------------------------------------
*/
int skill_readdb(void)
{
int i,j,k,l,m;
FILE *fp;
char line[1024],*p;
char *filename[]={"db/produce_db.txt","db/produce_db2.txt"};
/* �X�L���f?�^�x?�X */
memset(skill_db,0,sizeof(skill_db));
fp=fopen("db/skill_db.txt","r");
if(fp==NULL){
printf("can't read db/skill_db.txt\n");
return 1;
}
while(fgets(line,1020,fp)){
char *split[50], *split2[MAX_SKILL_LEVEL];
if(line[0]=='/' && line[1]=='/')
continue;
for(j=0,p=line;j<14 && p;j++){
split[j]=p;
p=strchr(p,',');
if(p) *p++=0;
}
if(split[13]==NULL || j<14)
continue;
i=atoi(split[0]);
if (i>=10000 && i<10015) // for guild skills [Celest]
i -= 9500;
else if(i<0 || i>MAX_SKILL_DB)
continue;
/* printf("skill id=%d\n",i); */
memset(split2,0,sizeof(split2));
for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].range[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
skill_db[i].hit=atoi(split[2]);
skill_db[i].inf=atoi(split[3]);
skill_db[i].pl=atoi(split[4]);
skill_db[i].nk=atoi(split[5]);
skill_db[i].max=atoi(split[6]);
memset(split2,0,sizeof(split2));
for(j=0,p=split[7];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].num[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
if(strcmpi(split[8],"yes") == 0)
skill_db[i].castcancel=1;
else
skill_db[i].castcancel=0;
skill_db[i].cast_def_rate=atoi(split[9]);
skill_db[i].inf2=atoi(split[10]);
skill_db[i].maxcount=atoi(split[11]);
if(strcmpi(split[12],"weapon") == 0)
skill_db[i].skill_type=BF_WEAPON;
else if(strcmpi(split[12],"magic") == 0)
skill_db[i].skill_type=BF_MAGIC;
else if(strcmpi(split[12],"misc") == 0)
skill_db[i].skill_type=BF_MISC;
else
skill_db[i].skill_type=0;
memset(split2,0,sizeof(split2));
for(j=0,p=split[13];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].blewcount[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
}
fclose(fp);
printf("read db/skill_db.txt done\n");
fp=fopen("db/skill_require_db.txt","r");
if(fp==NULL){
printf("can't read db/skill_require_db.txt\n");
return 1;
}
while(fgets(line,1020,fp)){
char *split[51], *split2[MAX_SKILL_LEVEL];
if(line[0]=='/' && line[1]=='/')
continue;
for(j=0,p=line;j<30 && p;j++){
split[j]=p;
p=strchr(p,',');
if(p) *p++=0;
}
if(split[29]==NULL || j<30)
continue;
i=atoi(split[0]);
if (i>=10000 && i<10015) // for guild skills [Celest]
i -= 9500;
else if(i<0 || i>MAX_SKILL_DB)
continue;
memset(split2,0,sizeof(split2));
for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].hp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
memset(split2,0,sizeof(split2));
for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].mhp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
memset(split2,0,sizeof(split2));
for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].sp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
memset(split2,0,sizeof(split2));
for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].hp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
memset(split2,0,sizeof(split2));
for(j=0,p=split[5];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].sp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
memset(split2,0,sizeof(split2));
for(j=0,p=split[6];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].zeny[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
memset(split2,0,sizeof(split2));
for(j=0,p=split[7];j<32 && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<32 && split2[k];k++) {
l = atoi(split2[k]);
if(l == 99) {
skill_db[i].weapon = 0xffffffff;
break;
}
else
skill_db[i].weapon |= 1<<l;
}
if( strcmpi(split[8],"hiding")==0 ) skill_db[i].state=ST_HIDING;
else if( strcmpi(split[8],"cloaking")==0 ) skill_db[i].state=ST_CLOAKING;
else if( strcmpi(split[8],"hidden")==0 ) skill_db[i].state=ST_HIDDEN;
else if( strcmpi(split[8],"riding")==0 ) skill_db[i].state=ST_RIDING;
else if( strcmpi(split[8],"falcon")==0 ) skill_db[i].state=ST_FALCON;
else if( strcmpi(split[8],"cart")==0 ) skill_db[i].state=ST_CART;
else if( strcmpi(split[8],"shield")==0 ) skill_db[i].state=ST_SHIELD;
else if( strcmpi(split[8],"sight")==0 ) skill_db[i].state=ST_SIGHT;
else if( strcmpi(split[8],"explosionspirits")==0 ) skill_db[i].state=ST_EXPLOSIONSPIRITS;
else if( strcmpi(split[8],"recover_weight_rate")==0 ) skill_db[i].state=ST_RECOV_WEIGHT_RATE;
else if( strcmpi(split[8],"move_enable")==0 ) skill_db[i].state=ST_MOVE_ENABLE;
else if( strcmpi(split[8],"water")==0 ) skill_db[i].state=ST_WATER;
else skill_db[i].state=ST_NONE;
memset(split2,0,sizeof(split2));
for(j=0,p=split[9];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].spiritball[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
skill_db[i].itemid[0]=atoi(split[10]);
skill_db[i].amount[0]=atoi(split[11]);
skill_db[i].itemid[1]=atoi(split[12]);
skill_db[i].amount[1]=atoi(split[13]);
skill_db[i].itemid[2]=atoi(split[14]);
skill_db[i].amount[2]=atoi(split[15]);
skill_db[i].itemid[3]=atoi(split[16]);
skill_db[i].amount[3]=atoi(split[17]);
skill_db[i].itemid[4]=atoi(split[18]);
skill_db[i].amount[4]=atoi(split[19]);
skill_db[i].itemid[5]=atoi(split[20]);
skill_db[i].amount[5]=atoi(split[21]);
skill_db[i].itemid[6]=atoi(split[22]);
skill_db[i].amount[6]=atoi(split[23]);
skill_db[i].itemid[7]=atoi(split[24]);
skill_db[i].amount[7]=atoi(split[25]);
skill_db[i].itemid[8]=atoi(split[26]);
skill_db[i].amount[8]=atoi(split[27]);
skill_db[i].itemid[9]=atoi(split[28]);
skill_db[i].amount[9]=atoi(split[29]);
}
fclose(fp);
printf("read db/skill_require_db.txt done\n");
/* �L���X�e�B���O�f?�^�x?�X */
fp=fopen("db/skill_cast_db.txt","r");
if(fp==NULL){
printf("can't read db/skill_cast_db.txt\n");
return 1;
}
while(fgets(line,1020,fp)){
char *split[50], *split2[MAX_SKILL_LEVEL];
memset(split,0,sizeof(split)); // [Valaris] thanks to fov
if(line[0]=='/' && line[1]=='/')
continue;
for(j=0,p=line;j<5 && p;j++){
split[j]=p;
p=strchr(p,',');
if(p) *p++=0;
}
if(split[4]==NULL || j<5)
continue;
i=atoi(split[0]);
if (i>=10000 && i<10015) // for guild skills [Celest]
i -= 9500;
else if(i<0 || i>MAX_SKILL_DB)
continue;
memset(split2,0,sizeof(split2));
for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].cast[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
memset(split2,0,sizeof(split2));
for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].delay[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
memset(split2,0,sizeof(split2));
for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].upkeep_time[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
memset(split2,0,sizeof(split2));
for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].upkeep_time2[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
}
fclose(fp);
printf("read db/skill_cast_db.txt done\n");
/* �����n�X�L���f?�^�x?�X */
memset(skill_produce_db,0,sizeof(skill_produce_db));
for(m=0;m<2;m++){
fp=fopen(filename[m],"r");
if(fp==NULL){
if(m>0)
continue;
printf("can't read %s\n",filename[m]);
return 1;
}
k=0;
while(fgets(line,1020,fp)){
char *split[6 + MAX_PRODUCE_RESOURCE * 2];
int x,y;
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
for(j=0,p=line;j<3 + MAX_PRODUCE_RESOURCE * 2 && p;j++){
split[j]=p;
p=strchr(p,',');
if(p) *p++=0;
}
if(split[0]==NULL)
continue;
i=atoi(split[0]);
if(i<=0)
continue;
skill_produce_db[k].nameid=i;
skill_produce_db[k].itemlv=atoi(split[1]);
skill_produce_db[k].req_skill=atoi(split[2]);
for(x=3,y=0; split[x] && split[x+1] && y<MAX_PRODUCE_RESOURCE; x+=2,y++){
skill_produce_db[k].mat_id[y]=atoi(split[x]);
skill_produce_db[k].mat_amount[y]=atoi(split[x+1]);
}
k++;
if(k >= MAX_SKILL_PRODUCE_DB)
break;
}
fclose(fp);
printf("read %s done (count=%d)\n",filename[m],k);
}
memset(skill_arrow_db,0,sizeof(skill_arrow_db));
fp=fopen("db/create_arrow_db.txt","r");
if(fp==NULL){
printf("can't read db/create_arrow_db.txt\n");
return 1;
}
k=0;
while(fgets(line,1020,fp)){
char *split[16];
int x,y;
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
for(j=0,p=line;j<13 && p;j++){
split[j]=p;
p=strchr(p,',');
if(p) *p++=0;
}
if(split[0]==NULL)
continue;
i=atoi(split[0]);
if(i<=0)
continue;
skill_arrow_db[k].nameid=i;
for(x=1,y=0;split[x] && split[x+1] && y<5;x+=2,y++){
skill_arrow_db[k].cre_id[y]=atoi(split[x]);
skill_arrow_db[k].cre_amount[y]=atoi(split[x+1]);
}
k++;
if(k >= MAX_SKILL_ARROW_DB)
break;
}
fclose(fp);
printf("read db/create_arrow_db.txt done (count=%d)\n",k);
memset(skill_abra_db,0,sizeof(skill_abra_db));
fp=fopen("db/abra_db.txt","r");
if(fp==NULL){
printf("can't read db/abra_db.txt\n");
return 1;
}
k=0;
while(fgets(line,1020,fp)){
char *split[16];
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
for(j=0,p=line;j<13 && p;j++){
split[j]=p;
p=strchr(p,',');
if(p) *p++=0;
}
if(split[0]==NULL)
continue;
i=atoi(split[0]);
if(i<=0)
continue;
skill_abra_db[i].req_lv=atoi(split[2]);
skill_abra_db[i].per=atoi(split[3]);
k++;
if(k >= MAX_SKILL_ABRA_DB)
break;
}
fclose(fp);
printf("read db/abra_db.txt done (count=%d)\n",k);
fp=fopen("db/skill_castnodex_db.txt","r");
if(fp==NULL){
printf("can't read db/skill_castnodex_db.txt\n");
return 1;
}
while(fgets(line,1020,fp)){
char *split[50], *split2[MAX_SKILL_LEVEL];
memset(split,0,sizeof(split));
if(line[0]=='/' && line[1]=='/')
continue;
for(j=0,p=line;j<2 && p;j++){
split[j]=p;
p=strchr(p,',');
if(p) *p++=0;
}
i=atoi(split[0]);
if(i<0 || i>MAX_SKILL_DB)
continue;
memset(split2,0,sizeof(split2));
for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].castnodex[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
}
fclose(fp);
printf("read db/skill_castnodex_db.txt done\n");
return 0;
}
void skill_reload(void)
{
/*
<empty skill database>
<?>
*/
do_init_skill();
}
/*==========================================
* �X�L��?�W������?��
*------------------------------------------
*/
int do_init_skill(void)
{
skill_readdb();
add_timer_func_list(skill_unit_timer,"skill_unit_timer");
add_timer_func_list(skill_castend_id,"skill_castend_id");
add_timer_func_list(skill_castend_pos,"skill_castend_pos");
add_timer_func_list(skill_timerskill,"skill_timerskill");
add_timer_func_list(skill_status_change_timer,"skill_status_change_timer");
add_timer_interval(gettick()+SKILLUNITTIMER_INVERVAL,skill_unit_timer,0,0,SKILLUNITTIMER_INVERVAL);
return 0;
}