rathena/src/map/skill.c
2005-03-07 16:01:20 +00:00

9532 lines
289 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// $Id: skill.c,v 1.8 2004/02/27 5:34:51 PM Celestia $
/* ƒ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 "status.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"
#include "showmsg.h"
#include "grfio.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
#define SKILLUNITTIMER_INVERVAL 100
#define STATE_BLIND 0x10
#define swap(x,y) { int t; t = x; x = y; y = t; }
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" } ,
{ GD_BATTLEORDER, "BATTLEORDER", "Battle_Orders" } ,
{ GD_REGENERATION, "REGENERATION", "Regeneration" } ,
{ GD_RESTORE, "RESTORE", "Restore" } ,
{ GD_EMERGENCYCALL, "EMERGENCYCALL", "Emergency_Call" } ,
{ 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ƒ€<C692>ì<EFBFBD>¬ƒf?ƒ^ƒx?ƒX */
struct skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB];
/* î<E28093>ì<EFBFBD>¬ƒ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];
// macros to check for out of bounds errors [celest]
// i: Skill ID, l: Skill Level, var: Value to return after checking
// for values that don't require level just put a one (putting 0 will trigger return 0; instead
// for values that might need to use a different function just skill_chk would suffice.
#define skill_chk(i, l) \
if (i >= 10000 && i < 10015) {i -= 9500;} \
if (i < 1 || i > MAX_SKILL_DB) {return 0;} \
if (l <= 0 || l > MAX_SKILL_LEVEL) {return 0;}
#define skill_get(var, i, l) \
{ skill_chk(i, l); return var; }
// Skill DB
int skill_get_hit( int id ){ skill_get (skill_db[id].hit, id, 1); }
int skill_get_inf( int id ){ skill_chk (id, 1); return (id < 500) ? skill_db[id].inf : guild_skill_get_inf(id); }
int skill_get_pl( int id ){ skill_get (skill_db[id].pl, id, 1); }
int skill_get_nk( int id ){ skill_get (skill_db[id].nk, id, 1); }
int skill_get_max( int id ){ skill_chk (id, 1); return (id < 500) ? skill_db[id].max : guild_skill_get_max(id); }
int skill_get_range( int id , int lv ){ skill_chk (id, lv); return (id < 500) ? skill_db[id].range[lv-1] : guild_skill_get_range(id); }
int skill_get_hp( int id ,int lv ){ skill_get (skill_db[id].hp[lv-1], id, lv); }
int skill_get_sp( int id ,int lv ){ skill_get (skill_db[id].sp[lv-1], id, lv); }
int skill_get_zeny( int id ,int lv ){ skill_get (skill_db[id].zeny[lv-1], id, lv); }
int skill_get_num( int id ,int lv ){ skill_get (skill_db[id].num[lv-1], id, lv); }
int skill_get_cast( int id ,int lv ){ skill_get (skill_db[id].cast[lv-1], id, lv); }
int skill_get_delay( int id ,int lv ){ skill_get (skill_db[id].delay[lv-1], id, lv); }
int skill_get_time( int id ,int lv ){ skill_get (skill_db[id].upkeep_time[lv-1], id, lv); }
int skill_get_time2( int id ,int lv ){ skill_get (skill_db[id].upkeep_time2[lv-1], id, lv); }
int skill_get_castdef( int id ){ skill_get (skill_db[id].cast_def_rate, id, 1); }
int skill_get_weapontype( int id ){ skill_get (skill_db[id].weapon, id, 1); }
int skill_get_inf2( int id ){ skill_get (skill_db[id].inf2, id, 1); }
int skill_get_castcancel( int id ){ skill_get (skill_db[id].castcancel, id, 1); }
int skill_get_maxcount( int id ){ skill_get (skill_db[id].maxcount, id, 1); }
int skill_get_blewcount( int id ,int lv ){ skill_get (skill_db[id].blewcount[lv-1], id, lv); }
int skill_get_mhp( int id ,int lv ){ skill_get (skill_db[id].mhp[lv-1], id, lv); }
int skill_get_castnodex( int id ,int lv ){ skill_get (skill_db[id].castnodex[lv-1], id, lv); }
int skill_get_delaynodex( int id ,int lv ){ skill_get (skill_db[id].delaynodex[lv-1], id, lv); }
int skill_get_nocast ( int id ){ skill_get (skill_db[id].nocast, id, 1); }
int skill_get_unit_id ( int id, int flag ){ skill_get (skill_db[id].unit_id[flag], id, 1); }
int skill_get_unit_layout_type( int id ,int lv ){ skill_get (skill_db[id].unit_layout_type[lv-1], id, lv); }
int skill_get_unit_interval( int id ){ skill_get (skill_db[id].unit_interval, id, 1); }
int skill_get_unit_range( int id ){ skill_get (skill_db[id].unit_range, id, 1); }
int skill_get_unit_target( int id ){ skill_get (skill_db[id].unit_target, id, 1); }
int skill_get_unit_flag( int id ){ skill_get (skill_db[id].unit_flag, id, 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ƒ<76>ƒ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 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 );
struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg,int tick);
int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int tick);
int skill_unit_effect(struct block_list *bl,va_list ap);
// [MouseJstr] - skill ok to cast? and when?
int skillnotok(int skillid, struct map_session_data *sd)
{
nullpo_retr (1, sd);
//if (sd == 0)
//return 0;
//return 1;
// I think it was meant to be "no skills allowed when not a valid sd"
if (!(skillid >= 10000 && skillid < 10015))
if ((skillid > MAX_SKILL) || (skillid < 0))
return 1;
{
int i = skillid;
if (i >= 10000 && i < 10015)
i -= 9500;
if (sd->blockskill[i] > 0)
return 1;
}
if (pc_isGM(sd) >= 20)
return 0; // gm's can do anything damn thing they want
// Check skill restrictions [Celest]
if(!map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.gvg && skill_get_nocast (skillid) & 1)
return 1;
if(map[sd->bl.m].flag.pvp && skill_get_nocast (skillid) & 2)
return 1;
if(map[sd->bl.m].flag.gvg && skill_get_nocast (skillid) & 4)
return 1;
if (agit_flag && skill_get_nocast (skillid) & 8)
return 1;
if (battle_config.pk_mode && !map[sd->bl.m].flag.nopvp && skill_get_nocast (skillid) & 16)
return 1;
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ƒgÌ”zu<E28099>î•ñð•Ô· */
struct skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT];
int firewall_unit_pos;
int icewall_unit_pos;
struct skill_unit_layout *skill_get_unit_layout(int skillid,int skilllv,struct block_list *src,int x,int y)
{
int pos = skill_get_unit_layout_type(skillid,skilllv);
int dir;
if (pos!=-1)
return &skill_unit_layout[pos];
if (src->x==x && src->y==y)
dir = 2;
else
dir = map_calc_dir(src,x,y);
if (skillid==MG_FIREWALL)
return &skill_unit_layout[firewall_unit_pos+dir];
else if (skillid==WZ_ICEWALL)
return &skill_unit_layout[icewall_unit_pos+dir];
printf("unknown unit layout for skill %d, %d\n",skillid,skilllv);
return &skill_unit_layout[0];
}
// 0x89,0x8a,0x8b •\ަ–³‚µ
// 0x9a ‰Š?<3F>«Ì‰r<E280B0>¥Ý½¢ÈƒGƒtƒFƒNƒg
// 0x9b <20>…?<3F>«Ì‰r<E280B0>¥Ý½¢ÈƒGƒtƒFƒNƒg
// 0x9c •—?<3F>«Ì‰r<E280B0>¥Ý½¢ÈƒGƒtƒFƒNƒg
// 0x9d ”¢<E2809A>¬³Èƒ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ƒÇ‰Á?‰Ê
*------------------------------------------
*/
int skill_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick)
{
/* MOBljÁ?‰Êƒ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;
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(skillid < 0)
{ // remove the debug print when this case is finished
printf("skill_additional_effect: skillid=%i\ncall: %p %p %i %i %i %i",skillid,
src, bl,skillid,skilllv,attack_type,tick);
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<E28094>H
} else if (src->type == BL_PET){
nullpo_retr(0, pd = (struct pet_data *)src); // [Valaris]
}
if(bl->type == BL_PC) {
nullpo_retr(0, dstsd=(struct map_session_data *)bl);
} else if(bl->type == BL_MOB) {
nullpo_retr(0, dstmd=(struct mob_data *)bl); //¢Žg—p<E28094>H
}
//?<3F>ÛÌÏ<E28098>«
sc_def_mdef = status_get_sc_def_mdef(bl);
sc_def_vit = status_get_sc_def_vit(bl);
sc_def_int = status_get_sc_def_int(bl);
sc_def_luk = status_get_sc_def_luk(bl);
//Ž©•ªÌÏ<E28098>«
sc_def_mdef2 = status_get_sc_def_mdef(src);
sc_def_vit2 = status_get_sc_def_vit(src);
sc_def_int2 = status_get_sc_def_int(src);
sc_def_luk2 = status_get_sc_def_luk(src);
switch(skillid){
case 0: /* Ê<E28099>í<EFBFBD>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);
}
// ƒ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 = status_get_max_hp(bl);
int hp = status_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(dstsd, -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;
}
}
status_change_start(bl,SC_DPOISON,lvl,0,0,0,skill_get_time2(ASC_EDP,lvl),0);
}
break;
case SM_BASH: /* ƒoƒbƒVƒ…<C692>i}<7D>Š<EFBFBD>U?<3F>j */
if( sd && (skill=pc_checkskill(sd,SM_FATALBLOW))>0 ){
if( rand()%100 < 6*(skilllv-5)*sc_def_vit/100 )
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 )
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ƒ<75>? */
if( rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
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)
status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case MG_FROSTDIVER: /* ƒtƒ<74>ƒXƒgƒ_ƒCƒo? */
case WZ_FROSTNOVA: /* ƒtƒ<74>ƒXƒgƒmƒ”ƒ@ */
rate=(skilllv*3+35)*sc_def_mdef/100-(status_get_int(bl)+status_get_luk(bl))/15;
rate=rate<=5?5:rate;
if(rand()%100 < rate)
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 = status_get_sc_data(bl);
if(sc_data) {
sc_data[SC_FREEZE].val3++;
if(sc_data[SC_FREEZE].val3 >= 3)
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 )
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;
status_calc_pc(dstsd,0);
}
break;
case HT_SANDMAN: /* ƒTƒ“ƒhƒ}ƒ“ */
if( rand()%100 < (5*skilllv+30)*sc_def_int/100 )
status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case TF_SPRINKLESAND: /* <20>»Ü« */
if( rand()%100 < 20*sc_def_int/100 )
status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case TF_THROWSTONE: /* <20>Î“Š° */
if( rand()%100 < 7*sc_def_vit/100 )
status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case CR_HOLYCROSS: /* ƒz?ƒŠ?ƒNƒ<4E>ƒX */
if( rand()%100 < 3*skilllv*sc_def_int/100 )
status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case CR_GRANDCROSS: /* ƒOƒ‰ƒ“ƒhƒNƒ<4E>ƒX */
case NPC_DARKGRANDCROSS: /*ˆÅƒOƒ‰ƒ“ƒhƒNƒ<4E>ƒX*/
{
int race = status_get_race(bl);
if( (battle_check_undead(race,status_get_elem_type(bl)) || race == 6) && rand()%100 < 100000*sc_def_int/100) //?<3F>§•t?¾ªŠ®SÏ<E28098>«Éͳ?
status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
break;
case AM_ACIDTERROR:
if( rand()%100 < (skilllv*3)*sc_def_vit/100 )
status_change_start(bl,SC_BLEEDING,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 )
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 )
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 )
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)
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 )
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 )
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)
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)
status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
if(src->type==BL_PET)
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)
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)
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)
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)
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 ) {
int sec = skill_get_time2 (skillid,skilllv) - status_get_agi(bl)/10;
status_change_start(bl,SC_STAN,skilllv,0,0,0,sec,0);
}
break;
case LK_SPIRALPIERCE:
if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 )
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) )
status_change_start(bl,SC_AUTOCOUNTER,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case PF_FOGWALL: /* ƒz?ƒŠ?ƒNƒ<4E>ƒX */
if(src!=bl && rand()%100 < 3*skilllv*sc_def_int/100 )
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=status_get_race(bl);
if( !(battle_check_undead(race,status_get_elem_type(bl)) || race == 6) && rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
break;
case LK_JOINTBEAT: /* ƒWƒ‡ƒCƒ“ƒgƒr?ƒg */
//?Œ<>ª—Ç­•ª©çÈ¢ÌÅ“K?‚É
if( rand()%100 < (5*skilllv+5)*sc_def_vit/100 )
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ÅÍ<E2809A>S©ŽžŠÔ”¼Œ¸<C592>H
sec = sec/2;
battle_stopwalking(bl,1);
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 ) //?ÔˆÙ<CB86>íÍ<E2809A>Ú<EFBFBD>ת•ª©çÈ¢ÌÅ“K?‚É
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 )
status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case MO_EXTREMITYFIST: /* ˆ¢<CB86>C—…”e™€Œ<E282AC> */
//ˆ¢<CB86>C—…ðŽg¤Æ5•ªŠÔŽ©R‰ñ•œµÈ¢æ¤ÉÈé
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)
status_change_start(bl,SC_CURSE,7,0,0,0,skill_get_time2(NPC_CURSEATTACK,7),0);
break;
}
if((sd||dstsd) && 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++){
//?<3F>ÛÉ?ÔˆÙ<CB86>í
switch (i) {
case SC_STONE:
case SC_FREEZE:
sc_def_card=sc_def_mdef;
break;
case SC_STAN:
case SC_POISON:
case SC_SILENCE:
sc_def_card=sc_def_vit;
break;
case SC_SLEEP:
case SC_CONFUSION:
case SC_BLIND:
sc_def_card=sc_def_int;
break;
case SC_CURSE:
sc_def_card=sc_def_luk;
}
if (sd) {
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ÉæéˆÙ<CB86>í?“® %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
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ÉæéˆÙ<CB86>í?“® %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
}
}
}
//Ž©•ª‚É?ÔˆÙ<CB86>í
switch (i) {
case SC_STONE:
case SC_FREEZE:
sc_def_card=sc_def_mdef2;
break;
case SC_STAN:
case SC_POISON:
case SC_SILENCE:
sc_def_card=sc_def_vit2;
break;
case SC_SLEEP:
case SC_CONFUSION:
case SC_BLIND:
sc_def_card=sc_def_int2;
break;
case SC_CURSE:
sc_def_card=sc_def_luk2;
}
if (sd) {
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ÉæéˆÙ<CB86>í?“® %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
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ÉæéˆÙ<CB86>í?“® %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
}
}
}
if (dstsd &&
rand()%10000 < dstsd->addeff3[i-SC_STONE]*sc_def_card/100){
if(battle_config.battle_log)
printf("PC %d skill_addeff: cardÉæéˆÙ<CB86>í?“® %d %d\n",src->id,i,dstsd->addeff3[i-SC_STONE]);
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ƒ<C692>U?<3F><>«”òε?—<>
-------------------------------------------------------------------------*/
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 dir,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){
sd=(struct map_session_data *)target;
}else if(target->type==BL_MOB){
md=(struct mob_data *)target;
}else if(target->type==BL_PET){
pd=(struct pet_data *)target;
}else if(target->type==BL_SKILL){
su=(struct skill_unit *)target;
}else return 0;
if (count&0xf00000)
dir = (count>>20)&0xf;
else if (count&0x10000 || (target->x==src->x && target->y==src->y))
dir = status_get_dir(target);
else
dir = map_calc_dir(target,src->x,src->y);
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É<E2809A>o½ÌÅ<E2809A>ÁŽ */
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{
int tick = gettick();
skill_unit_move(target,tick,0);
if(moveblock) map_delblock(target);
target->x=nx;
target->y=ny;
if(moveblock) map_addblock(target);
skill_unit_move(target,tick,1);
}
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;
}
return 0;
}
/*
* =========================================================================
* ƒXƒLƒ<C692>U??‰Ê?—<>ÜÆß
* flagÌ?¾<E28093>B16<31>i?
* 00XRTTff
* ff = magicÅŒvŽZÉ“n³êé<E2809A>j
* TT = ƒpƒPƒbƒgÌtype•”•ª(0ŃfƒtƒHƒƒg<C692>j
* X = ƒpƒPƒbƒg̃XƒLƒLv
* R = —\ñ<E28093>iskill_area_subÅŽg—p·é<E2809A>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(skillid > 0 && skilllv <= 0) return 0;
rdamage = 0;
nullpo_retr(0, src);
nullpo_retr(0, dsrc);
nullpo_retr(0, bl);
sc_data = status_get_sc_data(bl);
//‰½‚à‚µ‚È‚¢”»’肱‚±‚©‚ç
if(dsrc->m != bl->m) //?<3F>Ûª“¯¶ƒ}ƒbƒvɢȯêΉ½àµÈ¢
return 0;
if(src->prev == NULL || dsrc->prev == NULL || bl->prev == NULL) //prevæ­í©çÈ¢<E2809A>¦
return 0;
if(src->type == BL_PC && pc_isdead((struct map_session_data *)src)) //<2F>pŽÒ<C5BD>HªPCÅ·ÅÉŽ€ñÅ¢½ç‰½àµÈ¢
return 0;
if(dsrc->type == BL_PC && pc_isdead((struct map_session_data *)dsrc)) //<2F>pŽÒ<C5BD>HªPCÅ·ÅÉŽ€ñÅ¢½ç‰½àµÈ¢
return 0;
if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) //?<3F>Ûª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ƒÌ?<3F>«ªn?<3F>«ÅȯêΉ½àµÈ¢
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ƒ<74>ƒXƒgƒmƒ”ƒ@Å<E2809A>AdsrcÆblª“¯<E2809A>ê<EFBFBD>ŠÈ牽àµÈ¢
return 0;
if(src->type == BL_PC && ((struct map_session_data *)src)->chatID) //<2F>pŽÒªPCŃ`ƒƒƒbƒgÈ牽àµÈ¢
return 0;
if(dsrc->type == BL_PC && ((struct map_session_data *)dsrc)->chatID) //<2F>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 ); //ƒ_ƒ<5F>?ƒWŒvŽZ
//ƒ}ƒWƒbƒNƒ<4E>ƒbƒh?—<>±±©ç
if(attack_type&BF_MAGIC && sc_data && sc_data[SC_MAGICROD].timer != -1 && src == dsrc) { //@<40>U?‚Ń}ƒWƒbƒNƒ<4E>ƒbƒh?ÔÅsrc=dsrcÈç
dmg.damage = dmg.damage2 = 0; //ƒ_ƒ<5F>?ƒW0
if(bl->type == BL_PC) { //?<3F>ÛªPCÌ<E2809A>ê<EFBFBD>
struct map_session_data *sd = (struct map_session_data *)bl;
if (sd) {
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ˆÈ<CB86>ã
sp = sp/((skilllv|1)*(skilllv|1)); //³çÉŒvŽZ<C5BD>H
if(sp > 0x7fff) sp = 0x7fff; //SP½·¬Ì<E2809A>ê<EFBFBD>Í—<C38D>˜_<CB9C>Åål
else if(sp < 1) sp = 1; //1ˆÈ‰ºÌ<E2809A>ê<EFBFBD>Í1
if(sd->status.sp + sp > sd->status.max_sp) { //‰ñ•œSP+Œ»<C592>ÝÌSPªMSPæèå«¢<E2809A>ê<EFBFBD>
sp = sd->status.max_sp - sd->status.sp; //SPðMSP-Œ»<C592>ÝSPÉ·é
sd->status.sp = sd->status.max_sp; //Œ»<C592>ÝÌSPÉMSPðã“ü
}
else //‰ñ•œSP+Œ»<C592>ÝÌSPªMSPæè<E2809A>¬³¢<E2809A>ê<EFBFBD>͉ñ•œSPð‰ÁŽZ
sd->status.sp += sp;
clif_heal(sd->fd,SP_SP,sp); //SP‰ñ•œƒGƒtƒFƒNƒgÌ•\ަ
sd->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ƒ<4E>ƒbƒhƒGƒtƒFƒNƒgð•\ަ
}
//ƒ}ƒWƒbƒNƒ<4E>ƒbƒh?—<>±±ÜÅ
if(src->type==BL_PET) { // [Valaris]
dmg.damage=battle_attr_fix(skilllv, skill_get_pl(skillid), status_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_) //<2F><>«”òε”»è<E28099>H<EFBFBD>¦
dmg.blewcount = 0;
if(skillid == CR_GRANDCROSS||skillid == NPC_DARKGRANDCROSS) {//ƒOƒ‰ƒ“ƒhƒNƒ<4E>ƒX
if(battle_config.gx_disptype) dsrc = src; // “Gƒ_ƒ<5F>?ƒW”•¶Žš•\ަ
if( src == bl) type = 4; // ”½“®Íƒ_ƒ<5F>?ƒWƒ?ƒVƒ‡ƒ“ȵ
}
//Žg—pŽÒªPCÌ<E2809A>ê<EFBFBD>Ì?—<>±±©ç
if(src->type == BL_PC) {
struct map_session_data *sd = (struct map_session_data *)src;
nullpo_retr(0, sd);
//˜AÅ<E28098>¶(MO_CHAINCOMBO)‚±‚±‚©‚ç
if(skillid == MO_CHAINCOMBO) {
int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src); //Šî–{ƒfƒBƒŒƒCÌŒvŽZ
if(damage < status_get_hp(bl)) { //ƒ_ƒ<5F>?ƒWª?<3F>ÛÌHPæè<E2809A>¬³¢<E2809A>ê<EFBFBD>
if(pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0) //Ò—´Œ<C2B4>(MO_COMBOFINISH)Žæ“¾<E2809C>•?…•ÛŽ<C39B>ŽžÍ+300ms
delay += 300 * battle_config.combo_delay_rate /100; //ljÁƒfƒBƒŒƒCðconfÉæè²<E28099>®
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Ì<E28098>M
}
//˜AÅ<E28098>¶(MO_CHAINCOMBO)‚±‚±‚Ü‚Å
//Ò—´Œ<C2B4>(MO_COMBOFINISH)‚±‚±‚©‚ç
else if(skillid == MO_COMBOFINISH) {
int delay = 700 - 4 * status_get_agi(src) - 2 * status_get_dex(src);
if(damage < status_get_hp(bl)) {
//ˆ¢<CB86>C—…”e™€Œ<E282AC>(MO_EXTREMITYFIST)Žæ“¾<E2809C>•?…4ŒÂ•ÛŽ<C39B><C5BD>•”š—ô”g“®(MO_EXPLOSIONSPIRITS)?‘ÔŽž‚Í+300ms
//•šŒÕŒ<C395>(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Éæè²<E28099>®
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Ì<E28098>M
}
//Ò—´Œ<C2B4>(MO_COMBOFINISH)‚±‚±‚Ü‚Å
//•šŒÕŒ<C395>(CH_TIGERFIST)‚±‚±‚©‚ç
else if(skillid == CH_TIGERFIST) {
int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src);
if(damage < status_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Éæè²<E28099>®
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Ì<E28098>M
}
//•šŒÕŒ<C395>(CH_TIGERFIST)‚±‚±‚Ü‚Å
//˜AŒ•ö?(CH_CHAINCRUSH)‚±‚±‚©‚ç
else if(skillid == CH_CHAINCRUSH) {
int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src);
if(damage < status_get_hp(bl)) {
//ˆ¢<CB86>C—…”e™€Œ<E282AC>(MO_EXTREMITYFIST)Žæ“¾<E2809C>•?…4ŒÂ•ÛŽ<C39B><C5BD>•”š—ô”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Éæè²<E28099>®
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Ì<E28098>M
}
//˜AŒ•ö?(CH_CHAINCRUSH)‚±‚±‚Ü‚Å
}
//Žg—pŽÒªPCÌ<E2809A>ê<EFBFBD>Ì?—<>±±ÜÅ
//•<>ŠíƒXƒLƒ<C692>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ƒ<C692>•ƒ_ƒ<5F>?ƒW è<E2809A>•Žg—pŽÒÆ?<3F>ÛŽÒªˆá¤<E2809A>•src=dsrc
if(dmg.flag&BF_SHORT) { //ß——£<E28094>U?Žž<C5BD>H<EFBFBD>¦
if(bl->type == BL_PC) { //?<3F>ÛªPCÌŽž
struct map_session_data *tsd = (struct map_session_data *)bl;
nullpo_retr(0, tsd);
if(tsd->short_weapon_damage_return > 0) { //ß——£<E28094>U?µË•Ôµ<E2809A>H<EFBFBD>¦
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) { //‰“——£<E28094>U?Žž<C5BD>H<EFBFBD>¦
if(bl->type == BL_PC) { //?<3F>ÛªPCÌŽž
struct map_session_data *tsd = (struct map_session_data *)bl;
nullpo_retr(0, tsd);
if(tsd->long_weapon_damage_return > 0) { //‰“——£<E28094>U?µË•Ôµ<E2809A>H<EFBFBD>¦
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ƒ<C692>H±±ÜÅ
switch(skillid){
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;
case SN_SHARPSHOOTING:
clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,0,0,0);
break;
default:
clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, (skillid==0)? 5:type );
}
/* <20><>«”òε<E2809A>ˆ<CB86>ƻ̃pƒPƒbƒg */
if (dmg.blewcount > 0 && bl->type!=BL_SKILL && !map[src->m].flag.gvg) {
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();
/* ?<3F>ÛɃ_ƒ<5F>?ƒW?—<>ð<E2809A>s¤ */
if (skillid || flag) {
if (attack_type&BF_WEAPON)
battle_delay_damage(tick+dmg.amotion,src,bl,damage,0);
else
battle_damage(src,bl,damage,0);
}
if(skillid == RG_INTIMIDATE && damage > 0 && !(status_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) {
int s_lv = status_get_lv(src),t_lv = status_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].lv
&& !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER)
&& !(skillid > NPC_SELFDESTRUCTION2 && skillid < NPC_UNDEADATTACK)){
//?‚É?ñÅ¢éƒXƒLƒª êΊY?ƒXƒLƒð<E2809A>Á·
if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag==13){
tsd->status.skill[tsd->cloneskill_id].id=0;
tsd->status.skill[tsd->cloneskill_id].flag=0;
}
tsd->cloneskill_id=skillid;
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);
}
}
/* ƒ_ƒ<5F>?ƒ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 (sd->sp_drain_type && bl->type == BL_PC)
battle_heal(NULL,bl,0,-sp,0);
}
if ((skillid || flag) && rdamage>0) {
if (attack_type&BF_WEAPON)
battle_delay_damage(tick+dmg.amotion,bl,src,rdamage,0);
else
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);
status_change_end(bl,SC_AUTOCOUNTER,-1);
}
map_freeblock_unlock();
return (dmg.damage+dmg.damage2); /* ?ƒ_ƒ<5F>ð•Ô· */
}
/*==========================================
* ƒXƒLƒ”Í?<3F>U?—p(map_foreachinarea©çŒÄÎêé)
* flagÉ¢Ä<E2809A>F16<31>i?ðŠm”F
* MSB <- 00fTffff ->LSB
* T =ƒ^?ƒQƒbƒgI?—p(BCT_*)
* ffff=Ž©—RÉŽg—p‰Â”\
* 0 =—\ñ<E28093>B0ÉŒÅè
*------------------------------------------
*/
static int skill_area_temp[8]; /* ˆêŽž??<3F>B•K—vÈçŽg¤<E2809A>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ð?<3F>ƵĢȢÌÅ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;
int skillid,unit_id;
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;
skillid = va_arg(ap,int);
unit_id = unit->group->unit_id;
if (skillid==MG_SAFETYWALL || skillid==AL_PNEUMA) {
if(unit_id != 0x7e && unit_id != 0x85)
return 0;
} else if (skillid==AL_WARP) {
if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92)
return 0;
} else if ((skillid>=HT_SKIDTRAP && skillid<=HT_CLAYMORETRAP) || skillid==HT_TALKIEBOX) {
if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92)
return 0;
} else if (skillid==WZ_FIREPILLAR) {
if (unit_id!=0x87)
return 0;
} else if (skillid==HP_BASILICA) {
if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92 && unit_id!=0x83)
return 0;
} else
return 0;
(*c)++;
return 0;
}
int skill_check_unit_range(int m,int x,int y,int skillid,int skilllv)
{
int c = 0;
int range = skill_get_unit_range(skillid);
int layout_type = skill_get_unit_layout_type(skillid,skilllv);
if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) {
printf("skill_check_unit_range: unsupported layout type %d for skill %d\n",layout_type,skillid);
return 0;
}
// Æè ¦¸<E2809A>³•ûŒ`̃†ƒjƒbƒgƒŒƒCƒAƒEƒgÌÝΉž
range += layout_type;
map_foreachinarea(skill_check_unit_range_sub,m,
x-range,y-range,x+range,y+range,BL_SKILL,&c,skillid);
return c;
}
static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap )
{
int *c;
int skillid;
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;
skillid = va_arg(ap,int);
if (skillid==HP_BASILICA && bl->type==BL_PC)
return 0;
(*c)++;
return 0;
}
int skill_check_unit_range2(int m,int x,int y,int skillid, int skilllv)
{
int c = 0;
int range = skill_get_unit_range(skillid);
int layout_type = skill_get_unit_layout_type(skillid,skilllv);
if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) {
printf("skill_check_unit_range2: unsupported layout type %d for skill %d\n",layout_type,skillid);
return 0;
}
// Æè ¦¸<E2809A>³•ûŒ`̃†ƒjƒbƒgƒŒƒCƒAƒEƒgÌÝΉž
range += layout_type;
map_foreachinarea(skill_check_unit_range2_sub,m,
x-range,y-range,x+range,y+range,0,&c,skillid);
return c;
}
int skill_guildaura_sub (struct block_list *bl,va_list ap)
{
struct map_session_data *sd;
struct guild *g;
int gid, id;
int flag = 0;
nullpo_retr(0, sd=(struct map_session_data *)bl);
nullpo_retr(0, ap);
id = va_arg(ap,int);
gid = va_arg(ap,int);
if (sd->status.guild_id != gid)
return 0;
g = va_arg(ap,struct guild *);
if (guild_checkskill(g, GD_LEADERSHIP)>0) flag |= 1<<0;
if (guild_checkskill(g, GD_GLORYWOUNDS)>0) flag |= 1<<1;
if (guild_checkskill(g, GD_SOULCOLD)>0) flag |= 1<<2;
if (guild_checkskill(g, GD_HAWKEYES)>0) flag |= 1<<3;
if (guild_checkskill(g, GD_CHARISMA)>0) flag |= 1<<4;
if (flag > 0) {
if (sd->sc_count && sd->sc_data[SC_GUILDAURA].timer != -1) {
if (sd->sc_data[SC_GUILDAURA].val4 != flag) {
sd->sc_data[SC_GUILDAURA].val4 = flag;
status_calc_pc (sd, 0);
}
return 0;
}
status_change_start(&sd->bl, SC_GUILDAURA,1,id,0,flag,0,0 );
}
return 0;
}
/*=========================================================================
* ”Í?ƒXƒLƒŽg—p?—<><E28094>¬•ª¯±±©ç
*/
/* ?<3F>ÛÌ?ðƒJƒEƒ“ƒg·é<E2809A>B<EFBFBD>iskill_area_temp[0]ð<E2809A>‰Šú‰»µÄ¨­±Æ<E2809A>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(skillid > 0 && skilllv <= 0) return 0; // celest
if(skill_area_temp[0] < 0xffff)
skill_area_temp[0]++;
return 0;
}
int skill_count_water(struct block_list *src,int range)
{
int i,x,y,cnt = 0,size = range*2+1;
struct skill_unit *unit;
for (i=0;i<size*size;i++) {
x = src->x+(i%size-range);
y = src->y+(i/size-range);
if (map_getcell(src->m,x,y,CELL_CHKWATER)) {
cnt++;
continue;
}
unit = map_find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL);
if (unit) {
cnt++;
skill_delunit(unit);
}
}
return cnt;
}
/*==========================================
*
*------------------------------------------
*/
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 (sd) {
sd->timerskill_count--;
}
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; //<2F>‰Šú‰»µÄÈ¢ÌɃAƒhƒŒƒX“ËÁ?ñÅ¢¢Ì©È<E2809A>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;
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(map_getcell(sd->bl.m,x,y,CELL_CHKPASS))
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;
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(map_getcell(md->bl.m,x,y,CELL_CHKPASS))
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; //ŽŠES?
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;
case WZ_WATERBALL:
if (skl->type>1) {
skl->timer = 0; // skill_addtimerskillÅŽg—p³êÈ¢æ¤É
skill_addtimerskill(src,tick+150,target->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag);
skl->timer = -1;
}
skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
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;
sd->timerskill_count++;
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);
if (sd->timerskill_count <= 0)
return 0;
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;
sd->timerskill_count--;
}
}
}
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?—<><E28094>¬•ª¯±±ÜÅ
* -------------------------------------------------------------------------
*/
/*==========================================
* ƒXƒLƒŽg—p<E28094>i‰r<E280B0>¥Š®—¹<E28094>AIDŽwè<E28099>U?Œn<C592>j
* <20>iƒXƒpƒQƒbƒeƒBÉŒü¯ÄP?O<E28098>i<EFBFBD>I(ƒ_ƒ<5F>ƒ|)<29>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 = status_get_sc_data(src);
int i;
if(skillid < 0)
{ // remove the debug print when this case is finished
printf("skill_castend_damage_id: skillid=%i\ncall: %p %p %i %i %i %i",skillid,
src, bl,skillid,skilllv,tick,flag);
return 0;
}
if(skillid > 0 && 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 == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && 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)
{
/* •<>Ší<C5A0>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ƒ<75>? */
case KN_PIERCE: /* ƒsƒA?ƒX */
case KN_SPEARBOOMERANG: /* ƒXƒsƒAƒu?ƒ<>ƒ‰ƒ“ */
case KN_BRANDISHSPEAR: /* ƒuƒ‰ƒ“ƒfƒBƒbƒVƒ…ƒXƒsƒA */
case TF_POISON: /* ƒCƒ“ƒxƒiƒ€ */
case TF_SPRINKLESAND: /* <20>»Ü« */
case AC_CHARGEARROW: /* ƒ`ƒƒ?ƒWƒAƒ<41>? */
// 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ƒ<4E>ƒX */
case CR_SHIELDCHARGE:
case CR_SHIELDBOOMERANG:
/* ˆÈ‰ºMOB?—p */
/* ??<3F>U?<3F>ASPŒ¸<C592>­<EFBFBD>U?<3F>A‰“——£<E28094>U?<3F>AhŒä³Ž<C5BD>U?<3F>A½i<E28099>U? */
case NPC_PIERCINGATT:
case NPC_MENTALBREAKER:
case NPC_RANGEATTACK:
case NPC_CRITICALSLASH:
case NPC_COMBOATTACK:
/* •K<E28099>U?<3F>A“Å<E2809C>U?<3F>AˆÃ?<3F>U?<3F>A¾?<3F>U?<3F>AƒXƒ^ƒ“<C692>U? */
case NPC_GUIDEDATTACK:
case NPC_POISON:
case NPC_BLINDATTACK:
case NPC_SILENCEATTACK:
case NPC_STUNATTACK:
/* <20>Ή»<E280B0>U?<3F>AŽô¢<E2809A>U?<3F>A<EFBFBD>°<E28093>U?<3F>Aƒ‰ƒ“ƒ_ƒ€ATK<54>U? */
case NPC_PETRIFYATTACK:
case NPC_CURSEATTACK:
case NPC_SLEEPATTACK:
case NPC_RANDOMATTACK:
/* <20>…?<3F>«<EFBFBD>U?<3F>An?<3F>«<EFBFBD>U?<3F>A‰Î?<3F>«<EFBFBD>U?<3F>A•—?<3F>«<EFBFBD>U? */
case NPC_WATERATTACK:
case NPC_GROUNDATTACK:
case NPC_FIREATTACK:
case NPC_WINDATTACK:
/* “Å?<3F>«<EFBFBD>U?<3F>A<EFBFBD>¹?<3F>«<EFBFBD>U?<3F>AˆÅ?<3F>«<EFBFBD>U?<3F>A”O?<3F>«<EFBFBD>U?<3F>ASPŒ¸<C592>­<EFBFBD>U? */
case NPC_POISONATTACK:
case NPC_HOLYATTACK:
case NPC_DARKNESSATTACK:
case NPC_TELEKINESISATTACK:
case NPC_UNDEADATTACK:
case NPC_BREAKARMOR:
case NPC_BREAKWEAPON:
case NPC_BREAKHELM:
case NPC_BREAKSHIELD:
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ƒ<41>?ƒoƒƒJƒ“ */
case ASC_BREAKER: /* ƒ\ƒEƒƒuƒŒ?ƒJ? */
case HW_MAGICCRASHER: /* ƒ}ƒWƒbƒNƒNƒ‰ƒbƒVƒƒ? */
case ASC_METEORASSAULT: /* ƒ<>ƒeƒIƒAƒTƒƒg */
case ITM_TOMAHAWK:
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
break;
case SN_SHARPSHOOTING: /* ƒVƒƒ?ƒvƒVƒ…?ƒeƒBƒ“ƒO */
map_foreachinpath (skill_attack_area,src->m, // function, map
src->x,src->y, // source xy
bl->x,bl->y, // target xy
2,0, // range, type
BF_WEAPON,src,src,skillid,skilllv,tick,flag,BCT_ENEMY); // varargs
break;
case PA_PRESSURE: /* ƒvƒŒƒbƒVƒƒ? */
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
if (rand()%100 < 50)
status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0);
else
status_change_start(bl,SC_BLEEDING,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0);
if (bl->type == BL_PC) {
int sp;
struct map_session_data *tsd = (struct map_session_data *)bl;
nullpo_retb (tsd);
sp = tsd->status.max_sp * 10 * skilllv / 100;
if (sp > tsd->status.sp) sp = tsd->status.sp;
tsd->status.sp -= sp;
pc_heal(tsd,0,-sp);
}
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 = status_get_sc_data(src);
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
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 RG_BACKSTAP: /* ƒoƒbƒNƒXƒ^ƒu */
{
int dir = map_calc_dir(src,bl->x,bl->y),t_dir = status_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 = status_get_sc_data(src);
if(sc_data && sc_data[SC_HIDING].timer != -1)
status_change_end(src, SC_HIDING, -1); // ƒnƒCƒfƒBƒ“ƒO‰ð<E280B0>œ
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;
clif_changed_dir(bl);
//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);
clif_emotion(bl, 23);
}
break;
case MO_FINGEROFFENSIVE: /* Žw? */
{
struct status_change *sc_data = status_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)
status_change_end(src,SC_BLADESTOP,-1);
}
break;
case MO_CHAINCOMBO: /* ˜AÅ<E28098>¶ */
{
struct status_change *sc_data = status_get_sc_data(src);
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
status_change_end(src,SC_BLADESTOP,-1);
}
break;
case MO_COMBOFINISH: /* Ò—´Œ<C2B4> */
case CH_TIGERFIST: /* •šŒÕŒ<C395> */
case CH_CHAINCRUSH: /* ˜AŒ•ö? */
case CH_PALMSTRIKE: /* ÒŒÕ<C592>d”hŽR */
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
break;
case MO_EXTREMITYFIST: /* ˆ¢<CB86>C—…”e<50> */
{
struct status_change *sc_data = status_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);
status_change_end(&sd->bl,SC_COMBO,-1);
}
else
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
status_change_end(src, SC_EXPLOSIONSPIRITS, -1);
if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
status_change_end(src,SC_BLADESTOP,-1);
}
break;
/* •<>ŠíŒn”Í?<3F>U?ƒXƒLƒ */
case AC_SHOWER: /* ƒAƒ<41>?ƒVƒƒƒ<C692>? */
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 AS_SPLASHER: /* [Valaris] */
if(flag&1){
/* ŒÂ•ÊɃ_ƒ<5F>?ƒWð?‚¦‚é */
if(bl->id!=skill_area_temp[1]){
int dist=0;
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,
0x0500|dist );
if (bl->type == BL_MOB && skillid == AS_GRIMTOOTH) {
struct status_change *sc_data = status_get_sc_data(bl);
if (sc_data && sc_data[SC_SLOWDOWN].timer == -1)
status_change_start(bl,SC_SLOWDOWN,0,0,0,0,1000,0);
}
}
} else {
int ar;
int x = bl->x, y = bl->y;
switch (skillid) {
case AC_SHOWER:
ar=2;
break;
case NPC_SPLASHATTACK:
ar=3;
break;
default:
ar=1;
break;
}
skill_area_temp[1]=bl->id;
skill_area_temp[2]=x;
skill_area_temp[3]=y;
/* ‚Ü‚¸ƒ^?ƒQƒbƒgÉ<E2809A>U?‚ð‰Á‚¦‚é */
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0);
/* ‚»‚ÌŒãƒ^?ƒQƒbƒgˆÈŠOÌ”Í??Ì“GS?‚É?—<>ð<E2809A>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);
}
break;
case SM_MAGNUM: /* ƒ}ƒOƒiƒ€ƒuƒŒƒCƒN [celest] */
{
int dist = 0;
int dx = abs( bl->x - skill_area_temp[2] );
int dy = abs( bl->y - skill_area_temp[3] );
dist = ((dx>dy)?dx:dy);
map_foreachinarea (skill_attack_area,src->m,src->x-1,src->y-1,src->x+1,src->y+1,0,
BF_WEAPON,src,src,skillid,skilllv,tick,0x0500|dist,BCT_ENEMY);
status_change_start (src,SC_FLAMELAUNCHER,0,0,0,0,10000,0);
clif_skill_nodamage (src,src,skillid,skilllv,1);
}
break;
case KN_BOWLINGBASH: /* ƒ{ƒEƒŠƒ“ƒOƒoƒbƒVƒ… */
if(flag&1){
/* ŒÂ•ÊɃ_ƒ<5F>?ƒWð?‚¦‚é */
if(bl->id!=skill_area_temp[1])
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500);
} else {
int i,c; /* ¼<E28098>l©ç•·¢½“®«ÈÌÅŠÔˆáÁÄé‰Â”\<5C>«å<E28098>•?—¦‚ª?¢Á·<E2809A><EFBFBD>ƒ */
/* ‚Ü‚¸ƒ^<5E>[ƒQƒbƒgÉ<E2809A>ð‰Á¦é */
if (!skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0))
break;
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;
/* ‚»‚ÌŒãƒ^?ƒQƒbƒgˆÈŠOÌ”Í??Ì“GS?‚É?—<>ð<E2809A>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 KN_SPEARSTAB: /* ƒXƒsƒAƒXƒ^ƒu */
if(flag&1){
/* ŒÂ•ÊɃ_ƒ<5F><C692>[ƒWð—^‚¦‚é */
if (bl->id==skill_area_temp[1])
break;
if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500))
skill_blown(src,bl,skill_area_temp[2]);
} else {
int x=bl->x,y=bl->y,i,dir;
/* ‚Ü‚¸ƒ^<5E>[ƒQƒbƒgÉ<E2809A>ð‰Á¦é */
dir = map_calc_dir(bl,src->x,src->y);
skill_area_temp[1] = bl->id;
skill_area_temp[2] = skill_get_blewcount(skillid,skilllv)|dir<<20;
if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0))
skill_blown(src,bl,skill_area_temp[2]);
for (i=0;i<4;i++) {
map_foreachinarea(skill_area_sub,bl->m,x,y,x,y,0,
src,skillid,skilllv,tick,flag|BCT_ENEMY|1,
skill_castend_damage_id);
x += dirx[dir];
y += diry[dir];
}
}
break;
case ALL_RESURRECTION: /* ƒŠƒUƒŒƒNƒVƒ‡ƒ“ */
case PR_TURNUNDEAD: /* ƒ^?ƒ“ƒAƒ“ƒfƒbƒh */
if(bl->type != BL_PC && battle_check_undead(status_get_race(bl),status_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 NPC_DARKSOULSTRIKE: /*ˆÅƒ\ƒEƒƒXƒgƒ‰ƒCƒN*/
case MG_COLDBOLT: /* ƒR<C692>ƒhƒ{ƒƒg */
case MG_FIREBOLT: /* ƒtƒ@ƒCƒA<C692>[ƒ{ƒƒg */
case MG_LIGHTNINGBOLT: /* ƒ‰ƒCƒgƒjƒ“ƒOƒ{ƒƒg */
case WZ_EARTHSPIKE: /* ƒA<C692>[ƒXƒXƒpƒCƒN */
case AL_HEAL: /* ƒq<C692>[ƒ‹ */
case AL_HOLYLIGHT: /* ƒz<C692>[ƒŠ<C692>[ƒ‰ƒCƒg */
case WZ_JUPITEL: /* ƒ†ƒsƒeƒƒTƒ“ƒ_<C692>[ */
case NPC_DARKJUPITEL: /*ˆÅƒ†ƒsƒeƒ*/
case NPC_MAGICALATTACK: /* MOB:@‘Å?<3F>U? */
case PR_ASPERSIO: /* ƒAƒXƒyƒƒVƒI */
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
break;
case MG_FROSTDIVER: /* ƒtƒ<74>ƒXƒgƒ_ƒCƒo<C692>[ */
{
struct status_change *sc_data = status_get_sc_data(bl);
int sc_def_mdef, rate, damage;
sc_def_mdef = status_get_sc_def_mdef(bl);
rate = (skilllv*3+35)*sc_def_mdef/100-(status_get_int(bl)+status_get_luk(bl))/15;
rate = rate<=5?5:rate;
if (sc_data && sc_data[SC_FREEZE].timer != -1) {
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
if (sd)
clif_skill_fail(sd,skillid,0,0);
break;
}
damage = skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
if (status_get_hp(bl) > 0 && damage > 0 && rand()%100 < rate) {
status_change_start(bl,SC_FREEZE,skilllv,0,0,0,
skill_get_time2(skillid,skilllv)*(1-sc_def_mdef/100),0);
} else if (sd) {
clif_skill_fail(sd,skillid,0,0);
}
break;
}
case WZ_WATERBALL: /* ƒEƒH?ƒ^?ƒ{?ƒ‹ */
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
if (skilllv>1) {
int cnt,range;
range = skilllv>5?2:skilllv/2;
if (sd)
cnt = skill_count_water(src,range)-1;
else
cnt = skill_get_num(skillid,skilllv)-1;
if (cnt>0)
skill_addtimerskill(src,tick+150,bl->id,0,0,
skillid,skilllv,cnt,flag);
}
break;
case PR_BENEDICTIO: /* <20>¹?<3F>~•Ÿ */
if(status_get_race(bl)==1 || status_get_race(bl)==6)
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
break;
/* @Œn”Í?<3F>U?ƒXƒLƒ */
case MG_NAPALMBEAT: /* ƒiƒp?ƒ€ƒr?ƒg */
case MG_FIREBALL: /* ƒtƒ@ƒCƒ„?ƒ{?ƒ‹ */
case WZ_SIGHTRASHER: /* ƒTƒCƒgƒ‰ƒbƒVƒƒ<C692>[ */
if(flag&1){
/* ŒÂ•ÊɃ_ƒ<5F>?ƒWð?‚¦‚é */
if(bl->id!=skill_area_temp[1]){
if(skillid==MG_FIREBALL){ /* ƒtƒ@ƒCƒ„?ƒ{?ƒÈç<E28099>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;
skill_area_temp[0]=0;
skill_area_temp[1]=bl->id;
switch (skillid) {
case MG_NAPALMBEAT:
ar = 1;
/* ƒiƒp<C692>[ƒ€ƒr<C692>[ƒgÍ•ªŽUƒ_ƒ<5F><C692>[ƒWÈÌÅ“GÌ<E2809A>ð<E2809A>¦é */
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,
skill_area_sub_count);
break;
case MG_FIREBALL:
ar = 2;
skill_area_temp[2]=bl->x;
skill_area_temp[3]=bl->y;
/* ƒ^<5E>[ƒQƒbƒgÉ<E2809A>ð‰Á¦é(ƒXƒLƒƒGƒtƒFƒNƒg•\ަ) */
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
skill_area_temp[0]);
break;
case WZ_SIGHTRASHER:
default:
ar = 3;
bl = src;
status_change_end(src,SC_SIGHT,-1);
break;
}
if (skillid==WZ_SIGHTRASHER) {
/* ƒXƒLƒƒGƒtƒFƒNƒg•\ަ */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
} else {
/* ƒ^<5E>[ƒQƒbƒgÉ<E2809A>ð‰Á¦é(ƒXƒLƒƒGƒtƒFƒNƒg•\ަ) */
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
skill_area_temp[0]);
}
/* ƒ^<5E>[ƒQƒbƒgˆÈŠO͈͓̔àÌ“GSÌÉ<E2809A>ˆ<CB86>ð<E2809A>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ƒ<74>ƒ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 HT_BLITZBEAT: /* ƒuƒŠƒbƒcƒr?ƒg */
if(flag&1){
/* ŒÂ•ÊɃ_ƒ<5F>?ƒ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É<E2809A>U?‚ð‰Á‚¦‚é */
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,skill_area_temp[0]|(flag&0xf00000));
/* ‚»‚ÌŒãƒ^?ƒQƒbƒgˆÈŠOÌ”Í??Ì“GS?‚É?—<>ð<E2809A>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ƒ<4E>ƒX */
case NPC_DARKGRANDCROSS: /*ˆÅƒOƒ‰ƒ“ƒhƒNƒ<4E>ƒX*/
/* ƒXƒLƒƒ†ƒjƒbƒg”zu */
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: /* <20>Î“Š° */
case NPC_SMOKING: /* ƒXƒ?ƒLƒ“ƒO */
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,0 );
break;
// Celest
case PF_SOULBURN:
{
int per = skilllv < 5 ? 20+ skilllv*10 : 60;
if (rand()%100 < per) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if (skilllv == 5)
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,0 );
if (bl->type == BL_PC && (map[src->m].flag.pvp || map[src->m].flag.gvg)) {
struct map_session_data *tsd = (struct map_session_data *)bl;
if (tsd) {
tsd->status.sp = 0;
clif_updatestatus(tsd,SP_SP);
}
}
} else {
clif_skill_nodamage(src,src,skillid,skilllv,1);
if (skilllv == 5)
skill_attack(BF_MAGIC,src,src,src,skillid,skilllv,tick,0 );
if (sd) {
sd->status.sp = 0;
clif_updatestatus(sd,SP_SP);
}
}
if (sd)
pc_blockskill_start (sd, skillid, (skilllv < 5 ? 10000: 15000));
}
break;
case NPC_SELFDESTRUCTION: /* Ž©”š */
case NPC_SELFDESTRUCTION2: /* Ž©”š2 */
if(flag&1){
/* ŒÂ•ÊɃ_ƒ<5F>?ƒ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]=status_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;
/* HPz?/HPz?@ */
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;
// unknown skills [Celest]
case NPC_BIND:
case NPC_EXPLOSIONSPIRITS:
case NPC_INCAGI:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
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:
printf("Unknown skill used:%d\n",skillid);
map_freeblock_unlock();
return 1;
}
if(sc_data) {
if (sc_data[SC_MAGICPOWER].timer != -1 && skillid != HW_MAGICPOWER) //ƒ}ƒWƒbƒNƒpƒ<70>?‚Ì?‰Ê<E280B0>I—¹
status_change_end(src,SC_MAGICPOWER,-1);
}
map_freeblock_unlock();
return 0;
}
/*==========================================
* ƒXƒLƒŽg—p<E28094>i‰r<E280B0>¥Š®—¹<E28094>AIDŽwèŽx‰‡Œn<C592>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_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(skillid < 0)
{ // remove the debug print when this case is finished
printf("skill_castend_damage_id: skillid=%i\ncall: %p %p %i %i %i %i",skillid,
src, bl,skillid,skilllv,tick,flag);
return 0;
}
if(skillid > 0 && skilllv <= 0) return 0; // celest
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=status_get_mdef(bl);
sc_luk=status_get_luk(bl);
sc_def_vit = status_get_sc_def_vit(bl);
sc_def_mdef = status_get_sc_def_mdef (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(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(status_get_class(bl) == 1288)
return 1;
if (sd && skillnotok(skillid, sd)) // [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<C692>iƒq?ƒ—ÊO<E2809A>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) //Ž©•ª‚à?<3F>ÛàPC<50>A?<3F>ÛªŽ©•ªÌƒp?ƒgƒi?<3F>AŽ©•ªªƒXƒpƒmƒr<C692>AŽ©•ªª<E2809A>ŠÈç
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Œ¸<C592>­ */
if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
if( rand()%100 < (50+skilllv*3+(status_get_lv(src)+status_get_int(src)/5)-sc_def_mdef) ) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
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 = status_get_race(bl),ele = status_get_elem_type(bl);
if(battle_check_target(src,bl,BCT_ENEMY) && (race == 6 || battle_check_undead(race,ele))) {
int slv=status_get_lv(src),tlv=status_get_lv(bl),rate;
rate = 25 + skilllv*2 + slv - tlv;
if(rand()%100 < rate)
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 = status_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)
status_change_end(bl,SC_DIVINA,-1);
else if( rand()%100 < sc_def_vit ) {
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 ((i=pc_search_inventory(sd, 715)) < 0 ) { //bug fixed by Lupus (item pos can be 0, too!)
clif_skill_fail(sd,sd->skillid,0,0);
break;
}
//pc_delitem(sd, pc_search_inventory(sd, 715), 1, 0);
pc_delitem(sd, i, 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=status_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,status_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: /* <20>¹?<3F>~•Ÿ */
case CR_PROVIDENCE: /* ƒvƒ<76>ƒ”ƒ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{
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ƒ<67>?ƒ‹ */
if(sd && dstsd){
struct status_change *sc_data = status_get_sc_data(src);
struct status_change *tsc_data = status_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) {
status_change_start (src,sc,skilllv,0,bl->id,0,skill_get_time(skillid,skilllv),0);
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) {
status_change_end(src, sc, -1);
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(skilllv < 5 && rand()%100 > (60+skilllv*10) ) { //fixed by Lupus (4 -> 5) or else it has 100% success even at lv4
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 {
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;
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;
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: // à<E280B9>
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 PA_SACRIFICE:
case ASC_EDP: // [Celest]
case CG_MOONLIT: /* ŒŽ¾èÌ<E2809A>òÉ—Ž¿é‰ÔÑç */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
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);
status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
if (sd)
pc_blockskill_start (sd, skillid, 10000);
break;
case SM_AUTOBERSERK: // Celest
{
struct status_change *tsc_data = status_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 )
status_change_start(bl,sc,skilllv,0,0,0,0,0);
else
status_change_end(bl, sc, -1);
}
}
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);
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);
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);
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: /* <20>W†—ÍŒü<C592>ã */
{
int range = 1;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
map_foreachinarea( 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ƒ<76>ƒ{ƒbƒN */
{
struct status_change *sc_data = status_get_sc_data(bl);
/* MVPmobÆ•sŽ€ÉÍ?‚©‚È‚¢ */
if((bl->type==BL_MOB && status_get_mode(bl)&0x20) || battle_check_undead(status_get_race(bl),status_get_elem_type(bl))) //•sŽ€ÉÍ?‚©‚È‚¢
{
map_freeblock_unlock();
return 1;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
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<E280B0>¥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)
status_change_end(bl,SC_FREEZE,-1);
if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
status_change_end(bl,SC_STONE,-1);
if(sc_data[SC_SLEEP].timer!=-1)
status_change_end(bl,SC_SLEEP,-1);
}
if(dstmd) {
int range = skill_get_range(skillid,skilllv);
if(range < 0)
range = status_get_range(src) - (range + 1);
dstmd->state.provoke_flag = src->id;
mob_target(dstmd,src,range);
}
}
break;
case CR_DEVOTION: /* ƒfƒBƒ{?ƒVƒ‡ƒ“ */
if(sd && dstsd){
//?<3F>â—{ŽqÌ<E2809A>ê<EFBFBD>ÌŒ³Ì<E2809A>EÆðŽZ<C5BD>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 > battle_config.devotion_level_difference) // ƒŒƒxƒ<C692>·<EFBFBD>}10ÜÅ
||(!sd->status.party_id && !sd->status.guild_id) // PTÉàƒMƒƒhÉà<E2809A>Š?–³‚µ‚Í‚¾‚ß
||((sd->status.party_id != dstsd->status.party_id) // “¯¶ƒp?ƒeƒB?©<E2809A>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);
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: // ”<E2809D>nŽæè
clif_skill_nodamage(src,bl,skillid,skilllv,1);
status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case MO_ABSORBSPIRITS: // ?D
i=0;
if(dstsd) {
if((sd && sd == dstsd) || map[src->m].flag.pvp || map[src->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 && sd->status.sp + i > sd->status.max_sp)
i = sd->status.max_sp - sd->status.sp;
}
}
} else if (dstmd){ //?<3F>Ûªƒƒ“ƒXƒ^?Ì<E2809A>ê<EFBFBD>
//20%ÌŠm—¦Å?<3F>ÛÌLv*2ÌSPð‰ñ•œ·é<E2809A>B<EFBFBD>¬Œ÷µ½Æ«Íƒ^?ƒQƒbƒg(ƒÐ?„D?)ƒÐ????!!
if(rand()%100<20){
i=2*mob_db[dstmd->class_].lv;
mob_target(dstmd,src,0);
}
}
if(i && sd){
sd->status.sp += i;
clif_heal(sd->fd,SP_SP,i);
} else clif_skill_nodamage(src,bl,skillid,skilllv,0);
break;
case AC_MAKINGARROW: /* î<E28093>ì<EFBFBD>¬ */
if(sd) {
clif_arrow_create_list(sd);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case AM_PHARMACY: /* ƒ|?ƒVƒ‡ƒ“<C692>ì<EFBFBD>¬ */
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: /* ‰ò<E280B0>»¢ */
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 ) {
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);
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);
status_change_end(src, SC_HIDING, -1); // ƒnƒCƒfƒBƒ“ƒO‰ð<E280B0>œ
break;
case ASC_METEORASSAULT: /* ƒ<>ƒeƒIƒAƒTƒƒg */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
map_foreachinarea(skill_area_sub,
bl->m,bl->x-2,bl->y-2,bl->x+2,bl->y+2,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
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ƒ<4F>ƒŠƒ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;
status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
else{
/* ƒp?ƒeƒBS?‚Ö‚Ì?—<> */
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);
status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,(src == bl)? 1:0,0,0,skill_get_time(skillid,skilllv),0);
}
else{
/* ƒp?ƒeƒBS?‚Ö‚Ì?—<> */
party_foreachsamemap(skill_area_sub,
sd,1,
src,skillid,skilllv,tick, flag|BCT_PARTY|1,
skill_castend_nodamage_id);
}
break;
/*<2A>i•t‰ÁƉð<E280B0>œª•K—v<E28094>j */
case BS_MAXIMIZE: /* ƒ}ƒLƒVƒ}ƒCƒYƒpƒ<70>? */
case NV_TRICKDEAD: /* Ž€‚ñ‚¾‚Ó‚è */
case CR_DEFENDER: /* ƒfƒBƒtƒFƒ“ƒ_? */
case CR_AUTOGUARD: /* ƒI?ƒgƒK?ƒh */
{
struct status_change *tsc_data = status_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‰Á·é */
status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
else
/* ‰ð<E280B0>œ·é */
status_change_end(bl, sc, -1);
}
}
break;
case TF_HIDING: /* ƒnƒCƒfƒBƒ“ƒO */
{
struct status_change *tsc_data = status_get_sc_data(bl);
int sc=SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,-1,1);
if(tsc_data && tsc_data[sc].timer!=-1 )
/* ‰ð<E280B0>œ·é */
status_change_end(bl, sc, -1);
else
/* •t‰Á·é */
status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
break;
case AS_CLOAKING: /* ƒNƒ<4E>?ƒLƒ“ƒO */
{
struct status_change *tsc_data = status_get_sc_data(bl);
int sc=SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(tsc_data && tsc_data[sc].timer!=-1 )
/* ‰ð<E280B0>œ·é */
status_change_end(bl, sc, -1);
else
/* •t‰Á·é */
status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
//skill_check_cloaking(bl);
}
break;
case ST_CHASEWALK: /* ƒnƒCƒfƒBƒ“ƒO */
{
struct status_change *tsc_data = status_get_sc_data(bl);
int sc=SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,-1,1);
if(tsc_data && tsc_data[sc].timer!=-1 )
/* ‰ð<E280B0>œ·é */
status_change_end(bl, sc, -1);
else
/* •t‰Á·é */
status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
break;
/* ?nƒXƒLƒ */
case BD_LULLABY: /* ŽqŽç‰S */
case BD_RICHMANKIM: /* ƒjƒˆƒƒh̉ƒ */
case BD_ETERNALCHAOS: /* ‰i‰“Ì<E2809A>¬“× */
case BD_DRUMBATTLEFIELD: /* ?‘¾ŒÛ‚Ì‹¿‚« */
case BD_RINGNIBELUNGEN: /* ƒj?ƒxƒƒ“ƒOÌŽw—Ö */
case BD_ROKISWEIL: /* ƒ<>ƒLÌ©Ñ */
case BD_INTOABYSS: /* <20>[•£‚Ì’†‚É */
case BD_SIEGFRIED: /* •sŽ€<C5BD>g̃W?ƒNƒtƒŠ?ƒh */
case BA_DISSONANCE: /* •s¦˜a‰¹ */
case BA_POEMBRAGI: /* ƒuƒ‰ƒMÌŽ<C38C> */
case BA_WHISTLE: /* Œû“J */
case BA_ASSASSINCROSS: /* —[—z̃AƒTƒVƒ“ƒNƒ<4E>ƒX */
case BA_APPLEIDUN: /* ƒCƒhƒDƒ“Ì—ÑŒç */
case DC_UGLYDANCE: /* Ž©•ª<E280A2>ŸŽèȃ_ƒ“ƒX */
case DC_HUMMING: /* ƒnƒ~ƒ“ƒO */
case DC_DONTFORGETME: /* Ž„ðYêÈ¢Å<E2809A>c */
case DC_FORTUNEKISS: /* <20>K‰^̃LƒX */
case DC_SERVICEFORYOU: /* ƒT?ƒrƒXƒtƒH?ƒ†? */
// case CG_MOONLIT: /* ŒŽ¾èÌ<E2809A>òÉ—Ž¿é‰ÔÑç */
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 */
{
struct skill_unit_group *sg;
battle_stopwalking(src,1);
skill_clear_unitgroup(src);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,(int)sg,
skill_get_time(skillid,skilllv),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);
status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,BCT_SELF,skill_get_time(skillid,skilllv),0);
break;
case BD_ADAPTATION: /* ƒAƒhƒŠƒu */
{
struct status_change *sc_data = status_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 = status_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 */
{
struct status_change *sc_data = status_get_sc_data(bl);
// Level 6-10 doesn't consume a red gem if it fails [celest]
int i, gem_flag = 1;
if (bl->type==BL_MOB && status_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 (sc_data && sc_data[SC_STONE].timer != -1) {
status_change_end(bl,SC_STONE,-1);
if (sd)
clif_skill_fail(sd,skillid,0,0);
}
else if( rand()%100 < skilllv*4+20 && !battle_check_undead(status_get_race(bl),status_get_elem_type(bl)))
status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
else if(sd) {
if (skilllv > 5) gem_flag = 0;
clif_skill_fail(sd,skillid,0,0);
}
if (dstmd)
mob_target(dstmd,src,skill_get_range(skillid,skilllv));
if (sd && gem_flag) {
if ((i=pc_search_inventory(sd, skill_db[skillid].itemid[0])) < 0 ) {
clif_skill_fail(sd,sd->skillid,0,0);
break;
}
pc_delitem(sd, i, skill_db[skillid].amount[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;
status_change_end(bl, SC_SILENCE , -1 );
status_change_end(bl, SC_BLIND , -1 );
status_change_end(bl, SC_CONFUSION, -1 );
if( battle_check_undead(status_get_race(bl),status_get_elem_type(bl)) ){//ƒAƒ“ƒfƒbƒhÈçˆÃˆÅ?‰Ê
status_change_start(bl, SC_CONFUSION,1,0,0,0,6000,0);
}
break;
case TF_DETOXIFY: /* ‰ð“Å */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
status_change_end(bl, SC_POISON , -1 );
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;
status_change_end(bl, SC_FREEZE , -1 );
status_change_end(bl, SC_STONE , -1 );
status_change_end(bl, SC_SLEEP , -1 );
status_change_end(bl, SC_STAN , -1 );
if( battle_check_undead(status_get_race(bl),status_get_elem_type(bl)) ){//ƒAƒ“ƒfƒbƒhÈçˆÃˆÅ?‰Ê
int blind_time;
//blind_time=30-status_get_vit(bl)/10-status_get_int/15;
blind_time=30*(100-(status_get_int(bl)+status_get_vit(bl))/2)/100;
if(rand()%100 < (100-(status_get_int(bl)/2+status_get_vit(bl)/3+status_get_luk(bl)/10)))
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ƒ^?<3F>î•ñ */
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: /* •<>Ší<C5A0>C—<43> */
if(sd) {
//“®<E2809C>ìµÈ¢ÌÅÆè ¦¸ƒRƒ<52>ƒ“ƒgƒAƒEƒg
/*if (pc_search_inventory(sd, 999) < 0 ) { //fixed by Lupus (item pos can be = 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<C5A0>Ý */
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ƒ|ƒ“ */
case RG_STRIPSHIELD: /* ƒXƒgƒŠƒbƒvƒV<C692>ƒh */
case RG_STRIPARMOR: /* ƒXƒgƒŠƒbƒvƒA<C692>[ƒ}<7D>[ */
case RG_STRIPHELM: /* ƒXƒgƒŠƒbƒvƒwƒƒ€ */
case ST_FULLSTRIP: // Celest
{
struct status_change *tsc_data = status_get_sc_data(bl);
int scid, cp_scid = 0, equip, strip_fix, strip_num = 0;
scid = SkillStatusChangeTable[skillid];
switch (skillid) {
case RG_STRIPWEAPON:
equip = EQP_WEAPON;
cp_scid = SC_CP_WEAPON;
break;
case RG_STRIPSHIELD:
equip = EQP_SHIELD;
cp_scid = SC_CP_SHIELD;
break;
case RG_STRIPARMOR:
equip = EQP_ARMOR;
cp_scid = SC_CP_ARMOR;
break;
case RG_STRIPHELM:
equip = EQP_HELM;
cp_scid = SC_CP_HELM;
break;
case ST_FULLSTRIP:
equip = EQP_WEAPON | EQP_SHIELD | EQP_ARMOR | EQP_HELM;
strip_num = 3;
break;
default:
map_freeblock_unlock();
return 1;
}
if (tsc_data && (tsc_data[scid].timer != -1 || tsc_data[cp_scid].timer != -1))
break;
if (dstsd && dstsd->unstripable_equip & equip)
break;
strip_fix = status_get_dex(src) - status_get_dex(bl);
if(strip_fix < 0)
strip_fix=0;
strip_per = 5+2*skilllv+strip_fix/5;
if (rand()%100 >= strip_per)
break;
if (dstsd) {
for (i=0;i<MAX_INVENTORY;i++) {
if (dstsd->status.inventory[i].equip && (dstsd->status.inventory[i].equip & equip)){
pc_unequipitem(dstsd,i,3);
if ((--strip_num) <= 0)
break;
}
}
if (i == MAX_INVENTORY)
break;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
status_change_start(bl,scid,skilllv,0,0,0,strip_time,0 );
break;
}
/* PotionPitcher */
case AM_POTIONPITCHER: /* ƒ|?ƒVƒ‡ƒ“ƒsƒbƒ`ƒƒ? */
{
struct block_list tbl;
int i,x,hp = 0,sp = 0;
if(sd) {
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 = status_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 + (status_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 + (status_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 + (status_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:
case AM_CP_SHIELD:
case AM_CP_ARMOR:
case AM_CP_HELM:
{
int scid = SC_STRIPWEAPON + (skillid - AM_CP_WEAPON);
struct status_change *tsc_data = status_get_sc_data(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(tsc_data && tsc_data[scid].timer != -1)
status_change_end(bl, scid, -1 );
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;
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 = status_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;
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)
status_change_start(src,SC_AUTOSPELL,skilllv,spellid,maxlv,0,
skill_get_time(SA_AUTOSPELL,skilllv),0);
}
break;
/* ƒ‰ƒ“ƒ_ƒ€?<3F>«?‰»<E280B0>A<EFBFBD>…?<3F>«?‰»<E280B0>An<E28099>A‰Î<E280B0>A•— */
case NPC_ATTRICHANGE:
case NPC_CHANGEWATER:
case NPC_CHANGEGROUND:
case NPC_CHANGEFIRE:
case NPC_CHANGEWIND:
/* “Å<E2809C>A<EFBFBD>¹<EFBFBD>A”O<E2809D>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) /* ƒ‰ƒ“ƒ_ƒ€?‰»<E280B0>A½¾µ<E2809A>A*/
md->def_ele=rand()%10; /* •sŽ€?<3F>«Í<E2809A>œ­ */
md->def_ele+=(1+rand()%4)*20; /* ?<3F>«ƒŒƒ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;
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);
status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_time,0 );
if (src->type == BL_MOB)
mob_changestate((struct mob_data *)src,MS_DELAY,skill_time);
else if (src->type == BL_PC)
sd->attackabletime = sd->canmove_tick = tick + skill_time;
}
break;
case NPC_DARKBLESSING:
{
int sc_def = 100 - status_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(status_get_elem_type(bl) == 7 || status_get_race(bl) == 6)
break;
if(rand()%100 < sc_def*(50+skilllv*5)/100) {
if(dstsd) {
int hp = status_get_hp(bl)-1;
pc_heal(dstsd,-hp,0);
}
else if(dstmd)
dstmd->hp = 1;
}
}
break;
case NPC_SELFDESTRUCTION: /* Ž©”š */
case NPC_SELFDESTRUCTION2: /* Ž©”š2 */
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)
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: /* Žè‰º<E280B0>¢Š« */
case NPC_SUMMONMONSTER: /* MOB<4F>¢Š« */
if(md)
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;
// Equipment breaking monster skills [Celest]
case NPC_BREAKWEAPON:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(bl->type == BL_PC && battle_config.equipment_breaking)
pc_breakweapon(dstsd);
break;
case NPC_BREAKARMOR:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(bl->type == BL_PC && battle_config.equipment_breaking)
pc_breakarmor(dstsd);
break;
case NPC_BREAKHELM:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(bl->type == BL_PC && battle_config.equipment_breaking)
pc_breakhelm(dstsd);
break;
case NPC_BREAKSHIELD:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(bl->type == BL_PC && battle_config.equipment_breaking)
pc_breakshield(dstsd);
break;
case NPC_EXPLOSIONSPIRITS: //NPC”š—ô”g“®
clif_skill_nodamage(src,bl,skillid,skilllv,1);
status_change_start(bl,SC_EXPLOSIONSPIRITS,skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
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: /* ‚ ‚È‚½‚Ì?‚É?<3F>µÉÈèÜ· */
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);
map_freeblock_unlock();
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);
map_freeblock_unlock();
return 0;
}
skill_unitsetting(src,skillid,skilllv,sd->bl.x,sd->bl.y,0);
}
break;
case PF_HPCONVERSION: /* ƒ‰ƒCƒtu«Š·¦ */
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))
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 0x91: // ankle snare
if (su->group->val2 != 0)
// if it is already trapping something don't spring it,
// remove trap should be used instead
break;
// otherwise fallthrough to below
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)status_get_max_hp(bl)*2/3 < status_get_hp(bl)) { //HPª2/3ˆÈ<CB86>ã?ÁÄ¢½çޏ”s
map_freeblock_unlock();
return 1;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,src->id,skill_get_time(skillid,skilllv),1000,0 );
break;
case PF_MINDBREAKER: /* ƒvƒ<76>ƒ{ƒbƒN */
{
struct status_change *sc_data = status_get_sc_data(bl);
/* MVPmobÆ•sŽ€ÉÍ?‚©‚È‚¢ */
if((bl->type==BL_MOB && status_get_mode(bl)&0x20) || battle_check_undead(status_get_race(bl),status_get_elem_type(bl))) //•sŽ€ÉÍ?‚©‚È‚¢
{
map_freeblock_unlock();
return 1;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
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<E280B0>¥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)
status_change_end(bl,SC_FREEZE,-1);
if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
status_change_end(bl,SC_STONE,-1);
if(sc_data[SC_SLEEP].timer!=-1)
status_change_end(bl,SC_SLEEP,-1);
}
if(bl->type==BL_MOB) {
int range = skill_get_range(skillid,skilllv);
if(range < 0)
range = status_get_range(src) - (range + 1);
mob_target((struct mob_data *)bl,src,range);
}
}
break;
case PF_SOULCHANGE:
{
int sp1 = 0, sp2 = 0;
if (sd) {
if (dstsd) {
sp1 = sd->status.sp > dstsd->status.max_sp ? dstsd->status.max_sp : sd->status.sp;
sp2 = dstsd->status.sp > sd->status.max_sp ? sd->status.max_sp : dstsd->status.sp;
sd->status.sp = sp2;
dstsd->status.sp = sp1;
clif_heal(sd->fd,SP_SP,sp2);
clif_updatestatus(sd,SP_SP);
clif_heal(dstsd->fd,SP_SP,sp1);
clif_updatestatus(dstsd,SP_SP);
} else if (dstmd) {
if (dstmd->state.soul_change_flag) {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 0;
}
sp2 = sd->status.max_sp * 3 /100;
if (sd->status.sp + sp2 > sd->status.max_sp)
sp2 = sd->status.max_sp - sd->status.sp;
sd->status.sp += sp2;
clif_heal(sd->fd,SP_SP,sp2);
clif_updatestatus(sd,SP_SP);
dstmd->state.soul_change_flag = 1;
}
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
// Weapon Refining [Celest]
case WS_WEAPONREFINE:
if(sd)
clif_item_refine_list(sd);
break;
// Slim Pitcher
case CR_SLIMPITCHER:
{
if (sd && flag&1) {
struct block_list tbl;
int hp = sd->potion_hp * (100 + pc_checkskill(sd,CR_SLIMPITCHER)*10 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
hp = hp * (100 + (status_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(&tbl,bl,AL_HEAL,hp,1);
battle_heal(NULL,bl,hp,0,0);
}
}
break;
// Full Chemical Protection
case CR_FULLPROTECTION:
{
int i, skilltime;
struct status_change *tsc_data = status_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)
status_change_end(bl, SC_STRIPWEAPON + i, -1 );
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;
case ST_PRESERVE:
if (sd){
if (sd->sc_count && sd->sc_data[SC_PRESERVE].timer != -1)
status_change_end(src, SC_PRESERVE, -1 );
else
status_change_start(src,SC_PRESERVE,skilllv,0,0,0,skill_get_time(skillid, skilllv),0 );
clif_skill_nodamage(src,src,skillid,skilllv,1);
}
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) {
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);
pc_blockskill_start (sd, skillid, 300000);
}
}
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) {
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);
pc_blockskill_start (sd, skillid, 300000);
}
}
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*9/10;
sp = dstsd->status.max_sp*9/10;
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);
pc_blockskill_start (sd, skillid, 300000);
}
}
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 j = 0;
struct guild *g = NULL;
// Only usable during WoE
if (!agit_flag ||
(sd && map[sd->bl.m].flag.nowarpto && // if not allowed to warp to the map
guild_mapname2gc(sd->mapname) == NULL)) { // and it's not a castle...
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) {
if (map[dstsd->bl.m].flag.nowarp &&
guild_mapname2gc(sd->mapname) == NULL)
continue;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(map_getcell(sd->bl.m,sd->bl.x+dx[j],sd->bl.y+dy[j],CELL_CHKNOPASS))
dx[j] = dy[j] = 0;
pc_setpos(dstsd, sd->mapname, sd->bl.x+dx[j], sd->bl.y+dy[j], 2);
}
}
pc_blockskill_start (sd, skillid, 300000);
}
}
break;
default:
printf("Unknown skill used:%d\n",skillid);
map_freeblock_unlock();
return 1;
}
map_freeblock_unlock();
return 0;
}
/*==========================================
* ƒXƒLƒŽg—p<E28094>i‰r<E280B0>¥Š®—¹<E28094>AIDŽwè<E28099>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ª³¢ÌÍ èÈÌ<E2809A>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 = status_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 = status_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 == status_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 = status_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) )
{
/* <20>U?Œn/<2F><>«”òεŒ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(status_get_race(bl),status_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<E28094>i‰r<E280B0>¥Š®—¹<E28094>A<EFBFBD>ê<EFBFBD>ŠŽwèÌ?<3F>ÛÌ?—<><E28094>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;
if(skillid > 0 && skilllv <= 0) return 0; // celest
nullpo_retr(0, src);
if(src->type==BL_PC){
nullpo_retr(0, sd=(struct map_session_data *)src);
}
if( skillid != WZ_METEOR &&
skillid != AM_CANNIBALIZE &&
skillid != AM_SPHEREMINE)
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
if (sd && skillnotok(skillid, sd)) // [MouseJstr]
return 0;
switch(skillid)
{
case PR_BENEDICTIO: /* <20>¹?<3F>~•Ÿ */
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;
if(src->x!=x)
x+=(src->x-x>0)?-range:range;
if(src->y!=y)
y+=(src->y-y>0)?-range:range;
map_foreachinarea( status_change_timer_sub,
src->m, x-range, y-range, x+range,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_QUAGMIRE: /* ƒNƒ@ƒOƒ}ƒCƒA */
case WZ_VERMILION: /* ƒ<>?ƒhƒIƒuƒ”ƒ@?ƒ~ƒŠƒIƒ“ */
//case WZ_FROSTNOVA: /* ƒtƒ<74>ƒ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ƒ<4E>ƒX */
case NPC_DARKGRANDCROSS: /*ˆÅƒOƒ‰ƒ“ƒhƒNƒ<4E>ƒ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ƒ<76>ƒeƒNƒ^? */
skill_clear_element_field(src);//?‚ÉŽ©•ª‚ª?“®‚µ‚Ä‚¢‚é?<3F>«<EFBFBD>êðƒ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;
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((map_getcell(src->m,tmpx,tmpy,CELL_CHKNOPASS)) && 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);
if (sd)
pc_blockskill_start (sd, MO_EXTREMITYFIST, 2000);
break;
case AM_CANNIBALIZE: // ƒoƒCƒIƒvƒ‰ƒ“ƒg
if(sd){
int mx,my,id=0;
int summons[5] = { 1020, 1068, 1118, 1500, 1368 };
struct mob_data *md;
mx = x;// + (rand()%10 - 5);
my = y;// + (rand()%10 - 5);
id=mob_once_spawn(sd,"this",mx,my,"--ja--", summons[skilllv-1] ,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=2000+skilllv*400;
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 i = skilllv%11 - 1;
int j = pc_search_inventory(sd,skill_db[skillid].itemid[i]);
if(j < 0 || skill_db[skillid].itemid[i] <= 0 || sd->inventory_data[j] == NULL ||
sd->status.inventory[j].amount < skill_db[skillid].amount[i]) {
clif_skill_fail(sd,skillid,0,0);
return 1;
}
sd->state.potionpitcher_flag = 1;
sd->potion_hp = 0;
run_script(sd->inventory_data[j]->use_script,0,sd->bl.id,0);
pc_delitem(sd,j,skill_db[skillid].amount[i],0);
sd->state.potionpitcher_flag = 0;
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
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_PARTY|1,
skill_castend_nodamage_id);
}
}
}
break;
}
return 0;
}
/*==========================================
* ƒXƒLƒŽg—p<E28094>i‰r<E280B0>¥Š®—¹<E28094>AmapŽwè<E28099>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¦È¢?ÔˆÙ<CB86>í
if(sd->sc_count){
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( skill_num != sd->skillid) /* •s<E280A2>³ƒ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[4];
struct skill_unit_group *group;
int i;
int maxcount=0;
p[0] = &sd->status.save_point;
p[1] = &sd->status.memo_point[0];
p[2] = &sd->status.memo_point[1];
p[3] = &sd->status.memo_point[2];
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<E280A2>³ƒpƒPƒbƒg<C692>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 *)aCallocA(24,sizeof(char));
memcpy(group->valstr,map,24);
group->val2=(x<<16)|y;
}
break;
}
return 0;
}
/*==========================================
* ƒXƒLƒƒ†ƒjƒbƒg<C692>Ýè?—<>
*------------------------------------------
*/
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,limit,val1=0,val2=0,val3=0;
int count=0;
int target,interval,range,unit_flag;
struct skill_unit_layout *layout;
struct status_change *sc_data;
int active_flag=1;
nullpo_retr(0, src);
limit = skill_get_time(skillid,skilllv);
range = skill_get_unit_range(skillid);
interval = skill_get_unit_interval(skillid);
target = skill_get_unit_target(skillid);
unit_flag = skill_get_unit_flag(skillid);
layout = skill_get_unit_layout(skillid,skilllv,src,x,y);
if (unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy)
target = BCT_NOENEMY;
sc_data = status_get_sc_data(src); // for firewall and fogwall - celest
switch(skillid){ /* <20>Ýè */
case MG_SAFETYWALL: /* ƒZƒCƒtƒeƒBƒEƒH?ƒ‹ */
val2=skilllv+1;
break;
case MG_FIREWALL: /* ƒtƒ@ƒCƒ„?ƒEƒH?ƒ‹ */
if(sc_data && sc_data[SC_VIOLENTGALE].timer!=-1)
limit = limit*3/2;
val2=4+skilllv;
break;
case AL_WARP: /* ƒ<>?ƒvƒ|?ƒ^ƒ‹ */
val1=skilllv+6;
if(flag==0)
limit=2000;
active_flag=0;
break;
case PR_SANCTUARY: /* ƒTƒ“ƒNƒ`ƒ…ƒAƒŠ */
val1=(skilllv+3)*2;
val2=(skilllv>6)?777:skilllv*100;
interval += 500;
break;
case WZ_FIREPILLAR: /* ƒtƒ@ƒCƒA?ƒsƒ‰? */
if(flag!=0)
limit=1000;
val1=skilllv+2;
if(skilllv >= 6)
range=2;
break;
case HT_SANDMAN: /* ƒTƒ“ƒhƒ}ƒ“ */
case HT_CLAYMORETRAP: /* ƒNƒŒƒCƒƒA?ƒgƒ‰ƒbƒv */
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_FLASHER: /* ƒtƒ‰ƒbƒVƒƒ? */
case HT_FREEZINGTRAP: /* ƒtƒŠ?ƒWƒ“ƒOƒgƒ‰ƒbƒv */
case HT_BLASTMINE: /* ƒuƒ‰ƒXƒgƒ}ƒCƒ“ */
// longer trap times in WOE [celest]
if (map[src->m].flag.gvg) limit *= 4;
break;
case HT_SHOCKWAVE: /* ƒVƒ‡ƒbƒNƒEƒF?ƒuƒgƒ‰ƒbƒv */
val1=skilllv*15+10;
break;
case SA_LANDPROTECTOR: /* ƒOƒ‰ƒ“ƒhƒNƒ<4E>ƒX */
{
int aoe_diameter; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills
val1=skilllv*15+10;
aoe_diameter=skilllv+skilllv%2+5;
count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul)
}
break;
case BA_WHISTLE: /* Œû“J */
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1;
val2 = ((status_get_agi(src)/10)&0xffff)<<16;
val2 |= (status_get_luk(src)/10)&0xffff;
break;
case DC_HUMMING: /* ƒnƒ~ƒ“ƒO */
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = status_get_dex(src)/10;
break;
case DC_DONTFORGETME: /* Ž„ðYêÈ¢Å<E2809A>c */
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = ((status_get_str(src)/20)&0xffff)<<16;
val2 |= (status_get_agi(src)/10)&0xffff;
break;
case BA_POEMBRAGI: /* ƒuƒ‰ƒMÌŽ<C38C> */
if(src->type == BL_PC)
val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON);
val2 = ((status_get_dex(src)/10)&0xffff)<<16;
val2 |= (status_get_int(src)/5)&0xffff;
break;
case BA_APPLEIDUN: /* ƒCƒhƒDƒ“Ì—ÑŒç */
if(src->type == BL_PC)
val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)&0xffff;
val2 |= (status_get_vit(src))&0xffff;
val3 = 0;//‰ñ•œ—pƒ^ƒCƒ€ƒJƒEƒ“ƒ^(6•b?É1?‰Á)
break;
case DC_SERVICEFORYOU: /* ƒT?ƒrƒXƒtƒH?ƒ†? */
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = status_get_int(src)/10;
break;
case BA_ASSASSINCROSS: /* —[—z̃AƒTƒVƒ“ƒNƒ<4E>ƒX */
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1;
val2 = status_get_agi(src)/20;
break;
case DC_FORTUNEKISS: /* <20>K‰^̃LƒX */
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = status_get_luk(src)/10;
break;
case PF_FOGWALL: /* ƒtƒHƒOƒEƒH?ƒ‹ */
if(sc_data && sc_data[SC_DELUGE].timer!=-1) limit *= 2;
break;
case RG_GRAFFITI: /* Graffiti */
count=1; // Leave this at 1 [Valaris]
break;
}
nullpo_retr(NULL, group=skill_initunitgroup(src,(count > 0 ? count : layout->count),
skillid,skilllv,skill_get_unit_id(skillid,flag&1)));
group->limit=limit;
group->val1=val1;
group->val2=val2;
group->val3=val3;
group->target_flag=target;
group->interval=interval;
if(skillid==HT_TALKIEBOX ||
skillid==RG_GRAFFITI){
group->valstr=aCallocA(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<layout->count;i++){
struct skill_unit *unit;
int ux,uy,val1=skilllv,val2=0,limit=group->limit,alive=1;
ux = x + layout->dx[i];
uy = y + layout->dy[i];
switch (skillid) {
case MG_FIREWALL: /* ƒtƒ@ƒCƒ„?ƒEƒH?ƒ‹ */
val2=group->val2;
break;
case WZ_ICEWALL: /* ƒAƒCƒXƒEƒH?ƒ‹ */
if(skilllv <= 1)
val1 = 500;
else
val1 = 200 + 200*skilllv;
break;
case RG_GRAFFITI: /* Graffiti [Valaris] */
ux+=(i%5-2);
uy+=(i/5-2);
break;
}
//¼<E28099>ãƒXƒLƒÌ<E2809A>ê<EFBFBD><EFBFBD>Ýu<E28099>À•W<E280A2>ãɃ‰ƒ“ƒhƒvƒ<76>ƒ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,CELL_GETTYPE);
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;
if (range==0 && active_flag)
map_foreachinarea(skill_unit_effect,unit->bl.m
,unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y
,0,&unit->bl,gettick(),1);
}
}
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 *unit2;
struct status_change *sc_data;
int type;
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));
sc_data = status_get_sc_data(bl);
type = SkillStatusChangeTable[sg->skill_id];
if (battle_check_target(&src->bl,bl,sg->target_flag)<=0)
return 0;
// Î<E28098>ÛªLP<4C>ãÉ<C389>é<E2809A>ê<EFBFBD>ͳŒø
if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL))
return 0;
switch (sg->unit_id) {
case 0x85: /* ƒjƒ…<C692>[ƒ} */
case 0x7e: /* ƒZƒCƒtƒeƒBƒEƒH<C692>[ƒ‹ */
if (sc_data && sc_data[type].timer == -1)
status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
break;
case 0x80: /* ƒ<><C692>[ƒvƒ|<7C>[ƒ^ƒ‹(”­“®Œã) */
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 ){
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);
if (--sg->val1<=0)
skill_delunitgroup(sg);
}
}
} else if(bl->type==BL_MOB && battle_config.mob_warpportal){
int m = map_mapname2mapid(sg->valstr);
mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3);
}
break;
case 0x8e: /* ƒNƒ@ƒOƒ}ƒCƒA */
if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
break;
if(sc_data && sc_data[type].timer==-1)
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ƒ */
if (sc_data && sc_data[type].timer!=-1) {
unit2 = (struct skill_unit *)sc_data[type].val4;
if (unit2 && unit2->group &&
(unit2==src || DIFF_TICK(sg->tick,unit2->group->tick)<=0))
break;
}
status_change_start(bl,type,sg->skill_lv,(int)src,0,0,
skill_get_time2(sg->skill_id,sg->skill_lv),0);
break;
case 0x9e: /* ŽqŽç‰S */
case 0x9f: /* ƒjƒˆƒƒh̉ƒ */
case 0xa0: /* ‰i‰“Ì<E2809A>¬“× */
case 0xa1: /* ?‘¾ŒÛ‚Ì‹¿‚« */
case 0xa2: /* ƒj?ƒxƒƒ“ƒOÌŽw—Ö */
case 0xa3: /* ƒ<>ƒLÌ©Ñ */
case 0xa4: /* <20>[•£‚Ì’†‚É */
case 0xa5: /* •sŽ€<C5BD>g̃W?ƒNƒtƒŠ?ƒh */
case 0xa6: /* •s¦˜a‰¹ */
case 0xa7: /* Œû“J */
case 0xa8: /* —[—z̃AƒTƒVƒ“ƒNƒ<4E>ƒX */
case 0xa9: /* ƒuƒ‰ƒMÌŽ<C38C> */
case 0xaa: /* ƒCƒhƒDƒ“Ì—ÑŒç */
case 0xab: /* Ž©•ª<E280A2>ŸŽèȃ_ƒ“ƒX */
case 0xac: /* ƒnƒ~ƒ“ƒO */
case 0xad: /* Ž„ðYêÈ¢Å<E2809A>c */
case 0xae: /* <20>K‰^̃LƒX */
case 0xaf: /* ƒT?ƒrƒXƒtƒH?ƒ†? */
if (sg->src_id==bl->id)
break;
if (sc_data && sc_data[type].timer!=-1) {
unit2 = (struct skill_unit *)sc_data[type].val4;
if (unit2 && unit2->group &&
(unit2 == src || DIFF_TICK(sg->tick,unit2->group->tick)<=0))
break;
}
status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
(int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
break;
case 0xb4: // Basilica
if (battle_check_target(&src->bl,bl,BCT_NOENEMY)>0) {
if (sc_data && sc_data[type].timer!=-1) {
struct skill_unit_group *sg2 = (struct skill_unit_group *)sc_data[type].val4;
if (sg2 && (sg2 == src->group || DIFF_TICK(sg->tick,sg2->tick)<=0))
break;
} else
status_change_start(bl,type,sg->skill_lv,(int)src,0,0,
skill_get_time2(sg->skill_id,sg->skill_lv),0);
} else if (!status_get_mode(bl)&0x20)
skill_blown(&src->bl,bl,1);
break;
case 0xb6: /* ƒtƒHƒOƒEƒH?ƒ‹ */
if (sc_data && sc_data[type].timer!=-1) {
unit2 = (struct skill_unit *)sc_data[type].val4;
if (unit2 && unit2->group &&
(unit2 == src || DIFF_TICK(sg->tick,unit2->group->tick)<=0))
break;
}
status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
(int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
break;
case 0xb2: /*  È½ð_?‚¢‚½‚¢‚Å‚· */
case 0xb3: /* ƒSƒXƒyƒ */
//case 0xb6: /* ƒtƒHƒOƒEƒH?ƒ‹ */ - moved [celest]
//‚Ƃ肠‚¦‚¸‰½‚à‚µ‚È‚¢
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;*/
}
return 0;
}
/*==========================================
* ƒXƒLƒƒ†ƒjƒbƒgÌ”­“®ƒCƒxƒ“ƒg(ƒ^ƒCƒ}<7D>[”­“®)
*------------------------------------------
*/
int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsigned int tick)
{
struct skill_unit_group *sg;
struct block_list *ss;
int splash_count=0;
struct status_change *sc_data;
struct skill_unit_group_tickset *ts;
int type;
int diff=0;
nullpo_retr(0, src);
nullpo_retr(0, bl);
if (bl->type!=BL_PC && bl->type!=BL_MOB)
return 0;
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));
sc_data = status_get_sc_data(bl);
type = SkillStatusChangeTable[sg->skill_id];
// Î<E28098>ÛªLP<4C>ãÉ<C389>é<E2809A>ê<EFBFBD>ͳŒø
if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL))
return 0;
// Oɉe¿ðŽó¯Ä©çintervalÌŠÔ͉e¿ðŽó¯È¢
nullpo_retr(0,ts = skill_unitgrouptickset_search(bl,sg,tick));
diff = DIFF_TICK(tick,ts->tick);
if (sg->skill_id == PR_SANCTUARY)
diff += 500; // <20>VKɉñ•œµ½ƒ†ƒjƒbƒg¾¯ƒJƒEƒ“ƒg·é½ßÌŽdŠ|‚¯
if (diff < 0)
return 0;
ts->tick = tick+sg->interval;
// GXÍ<E2809A>dÈÁÄ¢½ç3HITµÈ¢
if (sg->skill_id==CR_GRANDCROSS && !battle_config.gx_allhit)
ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y)-1);
switch (sg->unit_id) {
case 0x83: /* ƒTƒ“ƒNƒ`ƒ…ƒAƒŠ */
{
int race=status_get_race(bl);
if (battle_check_undead(race,status_get_elem_type(bl)) || race==6) {
if (skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0)) {
// reduce healing count if this was meant for damaging [celest]
// sg->val1 /= 2;
sg->val1--; // ƒ`ƒƒƒbƒgƒLƒƒƒ“ƒZƒÉΉž
}
} else {
int heal = sg->val2;
if (status_get_hp(bl)>=status_get_max_hp(bl))
break;
if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage)
heal=0; /* ‰©à峃J<C692>[ƒh<C692>iƒq<C692>—ÊO<E2809A>j */
clif_skill_nodamage(&src->bl,bl,AL_HEAL,heal,1);
battle_heal(NULL,bl,heal,0,0);
if (diff>=500)
sg->val1--; // <20>VKÉ“üÁ½ƒ†ƒjƒbƒg¾¯ƒJƒEƒ“ƒg
}
if (sg->val1<=0)
skill_delunitgroup(sg);
break;
}
case 0x84: /* ƒ}ƒOƒkƒXƒGƒNƒ\ƒVƒYƒ€ */
{
int race = status_get_race(bl);
if (!battle_check_undead(race,status_get_elem_type(bl)) && race!=6)
return 0;
skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
src->val2++;
break;
}
case 0x7f: /* ƒtƒ@ƒCƒ„<C692>[ƒEƒH<C692>[ƒ‹ */
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 0x86: /* ƒ<><C692>[ƒhƒIƒuƒ”ƒ@<40>[ƒ~ƒŠƒIƒ“(TS,MS,FN,SG,HD,GX,ˆÅGX) */
skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
case 0x87: /* ƒtƒ@ƒCƒA<C692>[ƒsƒ‰<C692>[(”­“®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<C692>[ƒsƒ‰<C692>[(”­“®Œã) */
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]
//skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
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 */
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) - status_get_agi(bl)*100;
if(status_get_mode(bl)&0x20)
sec = sec/5;
if (sec < 3000) // minimum time of 3 seconds [celest]
sec = 3000;
battle_stopwalking(bl,1);
status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0);
skill_unit_move(bl,tick,0);
if(moveblock) map_delblock(bl);
bl->x = src->bl.x;
bl->y = src->bl.y;
if(moveblock) map_addblock(bl);
skill_unit_move(bl,tick,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);
clif_01ac(&src->bl);
sg->limit=DIFF_TICK(tick,sg->tick) + sec;
sg->val2=bl->id;
sg->interval = -1;
src->range = 0;
}
break;
case 0x92: /* ƒxƒmƒ€ƒ_ƒXƒg */
if(sc_data && sc_data[type].timer==-1 )
status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
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<C692>[ƒL<C692>[ƒ{ƒ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;
// Basilica
case 0xb4: /* ƒoƒWƒŠƒJ */
if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0 &&
!(status_get_mode(bl)&0x20))
skill_blown(&src->bl,bl,1);
if (sg->src_id==bl->id)
break;
if (battle_check_target(&src->bl,bl,BCT_NOENEMY)>0 && sc_data && sc_data[type].timer == -1)
status_change_start(bl,type,sg->skill_lv,(int)src,0,0,
skill_get_time2(sg->skill_id,sg->skill_lv),0);
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);
skill_unit_move(bl,tick,0);
if(moveblock) map_delblock(bl);
bl->x = src->bl.x;
bl->y = src->bl.y;
if(moveblock) map_addblock(bl);
skill_unit_move(bl,tick,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);
sg->limit = DIFF_TICK(tick,sg->tick)+skill_get_time2(sg->skill_id,sg->skill_lv);
sg->val2=bl->id;
sg->interval = -1;
src->range = 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©ç—£?‚·‚é(‚à‚µ‚­‚Í‚µ‚Ä‚¢‚é)<29>ê<EFBFBD>
*------------------------------------------
*/
int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int tick)
{
struct skill_unit_group *sg;
struct status_change *sc_data;
int type;
nullpo_retr(0, src);
nullpo_retr(0, bl);
nullpo_retr(0, sg=src->group);
sc_data = status_get_sc_data(bl);
type = SkillStatusChangeTable[sg->skill_id];
if (bl->prev==NULL || !src->alive ||
(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)))
return 0;
switch(sg->unit_id){
case 0x7e: /* ƒZƒCƒtƒeƒBƒEƒH<C692>[ƒ‹ */
case 0x85: /* ƒjƒ…<C692>[ƒ} */
case 0x8e: /* ƒNƒ@ƒOƒ}ƒCƒA */
case 0x9a: /* ƒ{ƒƒP<C692>[ƒm */
case 0x9b: /* ƒfƒŠƒ…<C692>[ƒW */
case 0x9c: /* ƒoƒCƒIƒŒƒ“ƒgƒQƒCƒ */
if (type==SC_QUAGMIRE && bl->type==BL_MOB)
break;
if (sc_data && sc_data[type].timer!=-1 && sc_data[type].val2==(int)src) {
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){
status_change_end(bl,SC_ANKLE,-1);
sg->limit=DIFF_TICK(tick,sg->tick)+1000;
}
break;
}
case 0x9e: /* ŽqŽç‰S */
case 0x9f: /* ƒjƒˆƒƒh̉ƒ */
case 0xa0: /* ‰i‰“Ì<E2809A>¬“× */
case 0xa1: /* <20>í¾ŒÛÌ¿« */
case 0xa2: /* ƒj<C692>[ƒxƒƒ“ƒOÌŽw—Ö */
case 0xa3: /* ƒ<>ƒLÌ©Ñ */
case 0xa4: /* <20>[•£‚Ì’†‚É */
case 0xa5: /* •sŽ€<C5BD>g̃W<C692>[ƒNƒtƒŠ<C692>[ƒh */
case 0xad: /* Ž„ðYêÈ¢Å<E2809A>c */
if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)src) {
status_change_end(bl,type,-1);
}
break;
case 0xa6: /* •s¦˜a‰¹ */
case 0xa7: /* Œû“J */
case 0xa8: /* —[—z̃AƒTƒVƒ“ƒNƒ<4E>ƒX */
case 0xa9: /* ƒuƒ‰ƒMÌŽ<C38C> */
case 0xaa: /* ƒCƒhƒDƒ“Ì—ÑŒç */
case 0xab: /* Ž©•ª<E280A2>ŸŽèȃ_ƒ“ƒX */
case 0xac: /* ƒnƒ~ƒ“ƒO */
case 0xae: /* <20>K‰^̃LƒX */
case 0xaf: /* ƒT?ƒrƒXƒtƒH?ƒ†? */
status_change_start(bl,SkillStatusChangeTable[sg->skill_id],sg->skill_lv,0,0,0,20000,0 );
break;
case 0xb4: // Basilica
if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)sg) {
status_change_end(bl,type,-1);
}
break;
case 0xb6:
{
struct block_list *target = map_id2bl(sg->val2);
if(target && target==bl) {
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, status_change_timer, bl->id, 0);
}
break;
}
case 0xb7: /* ƒXƒpƒCƒ_?ƒEƒFƒbƒu */
{
struct block_list *target = map_id2bl(sg->val2);
if (target && target==bl)
status_change_end(bl,SC_SPIDERWEB,-1);
sg->limit = DIFF_TICK(tick,sg->tick)+1000;
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;*/
}
return 0;
}
/*==========================================
* ƒXƒLƒƒ†ƒjƒbƒgŒø‰Ê”­“®/—£E<E28099>ˆ<CB86>(foreachinarea)
* bl: ƒ†ƒjƒbƒg(BL_PC/BL_MOB)
*------------------------------------------
*/
int skill_unit_effect(struct block_list *bl,va_list ap)
{
struct skill_unit *unit;
struct skill_unit_group *group;
int flag;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, unit=va_arg(ap,struct skill_unit*));
tick = va_arg(ap,unsigned int);
flag = va_arg(ap,unsigned int);
if (bl->type!=BL_PC && bl->type!=BL_MOB)
return 0;
if (!unit->alive || bl->prev==NULL)
return 0;
nullpo_retr(0, group=unit->group);
if (flag)
skill_unit_onplace(unit,bl,tick);
else {
skill_unit_onout(unit,bl,tick);
unit = map_find_skill_unit_oncell(bl,bl->x,bl->y,group->skill_id,unit);
if (unit)
skill_unit_onplace(unit,bl,tick);
}
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=aCallocA(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 = map_id2sd(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;
}
return 0;
}
/*==========================================
* ƒXƒLƒƒ†ƒjƒbƒg̃_ƒ<5F>?ƒ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); //<2F><>«”òεÄÝé
break;
default:
damage = 0;
break;
}
return damage;
}
/*---------------------------------------------------------------------------- */
/*==========================================
* ƒXƒLƒŽg—p<E28094>i‰r<E280B0>¥Š®—¹<E28094>A<EFBFBD>ê<EFBFBD>ŠŽwè<E28099>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;
}
/*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:
case RG_GRAFFITI:
range = 0;
break;
case AL_PNEUMA:
range = 1;
break;*/
if (!battle_config.pc_skill_reiteration &&
skill_get_unit_flag(sd->skillid)&UF_NOREITERATION &&
skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
sd->canmove_tick = tick;
sd->skillitem = sd->skillitemlv = -1;
return 0;
}
/*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:
case WZ_ICEWALL:
range = 2;
break;
case AL_WARP:
range = 0;
break;*/
if (battle_config.pc_skill_nofootset &&
skill_get_unit_flag(sd->skillid)&UF_NOFOOTSET &&
skill_check_unit_range2(sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) {
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 = status_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ƒƒƒ‰<E28098>ÝŠ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µÈ¢<E2809A>ÝèÈçcÉ è¦È¢å«È?Žšð•ÔµÄ<E2809A>I—¹
if(!battle_config.player_skill_partner_check){ //{?ÍforeachÌOÉâè½¢¯Ç<E2809A>Ýè“K—p‰Ó<E280B0>ŠðÜÆßé½ßɱ±Ö
(*c)=99;
return 0;
}
ss_class = pc_calc_base_job(ssd->status.class_);
switch(ssd->skillid){
case PR_BENEDICTIO: /* <20>¹?<3F>~•Ÿ */
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‰“Ì<E2809A>¬“× */
case BD_DRUMBATTLEFIELD: /* ?‘¾ŒÛ‚Ì‹¿‚« */
case BD_RINGNIBELUNGEN: /* ƒj?ƒxƒƒ“ƒOÌŽw—Ö */
case BD_ROKISWEIL: /* ƒ<>ƒLÌ©Ñ */
case BD_INTOABYSS: /* <20>[•£‚Ì’†‚É */
case BD_SIEGFRIED: /* •sŽ€<C5BD>g̃W?ƒNƒtƒŠ?ƒh */
case BD_RAGNAROK: /* <20>_?‚Ì?<3F>¨ */
case CG_MOONLIT: /* ŒŽ¾èÌ<E2809A>òÉ—Ž¿é‰ÔÑç */
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ƒƒƒ‰<E28098>ÝŠ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µÈ¢<E2809A>ÝèÈçcÉ è¦È¢å«È?Žšð•ÔµÄ<E2809A>I—¹
if(!battle_config.player_skill_partner_check){ //{?ÍforeachÌOÉâè½¢¯Ç<E2809A>Ýè“K—p‰Ó<E280B0>ŠðÜÆßé½ßɱ±Ö
(*c)=99;
return 0;
}
ss_class = pc_calc_base_job(ssd->status.class_);
skillid=ssd->skillid;
skilllv=ssd->skilllv;
//if(skilllv <= 0) return 0;
if(skillid > 0 && skilllv <= 0) return 0; // celest
switch(skillid){
case PR_BENEDICTIO: /* <20>¹?<3F>~•Ÿ */
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;
status_calc_pc(sd,0);
(*c)++;
}
break;
case BD_LULLABY: /* ŽqŽç‰Ì */
case BD_RICHMANKIM: /* ƒjƒˆƒƒh̉ƒ */
case BD_ETERNALCHAOS: /* ‰i‰“Ì<E2809A>¬“× */
case BD_DRUMBATTLEFIELD: /* ?‘¾ŒÛ‚Ì‹¿‚« */
case BD_RINGNIBELUNGEN: /* ƒj?ƒxƒƒ“ƒOÌŽw—Ö */
case BD_ROKISWEIL: /* ƒ<>ƒLÌ©Ñ */
case BD_INTOABYSS: /* <20>[•£‚Ì’†‚É */
case BD_SIEGFRIED: /* •sŽ€<C5BD>g̃W?ƒNƒtƒŠ?ƒh */
case BD_RAGNAROK: /* <20>_?‚Ì?<3F>¨ */
case CG_MOONLIT: /* ŒŽ¾èÌ<E2809A>òÉ—Ž¿é‰ÔÑç */
if(sd != ssd && //{<7B>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ƒðŽ<C3B0>ÁÄ¢Ä
(*c)==0 && //<2F>Å<EFBFBD>̈ê<CB86>lÅ
sd->status.party_id == ssd->status.party_id && //ƒp?ƒeƒB?‚ª“¯‚¶‚Å
!pc_issit(sd) && //<2F>ÀÁÄÈ¢
sd->sc_data[SC_DANCING].timer==-1 //ƒ_ƒ“ƒXáÈ¢
){
ssd->sc_data[SC_DANCING].val4=bl->id;
clif_skill_nodamage(bl,src,skillid,skilllv,1);
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<C692>AƒXƒtƒBƒAƒ}ƒCƒ“—pMob<E28098>ÝŠ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?Œ<><C592>i?ÅŽg—pޏ”s<E2809D>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];
int arrow_flag = 0;
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ƒ€Ì<E2809A>ê<EFBFBD>³?Œ<><C592>¬Œ÷ */
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_count){
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; /* ?ÔˆÙ<CB86>íâ¾?‚È‚Ç */
}
}
skill = sd->skillid;
lv = sd->skilllv;
if(lv <= 0) return 0;
// for the guild skills [celest]
if (skill >= 10000 && skill < 10015) skill-= 9500;
hp=skill_get_hp(skill, lv); /* <20>Á”ïHP */
sp=skill_get_sp(skill, lv); /* <20>Á”ïSP */
if((sd->skillid_old == BD_ENCORE) && skill==sd->skillid_dance)
sp=sp/2; //ƒAƒ“ƒR?ƒŽžÍSP<53>Á”杖¼•ª
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); /* <20>Á”ï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; /* <20>Á”ïSP<53>C<EFBFBD>³ */
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ƒ<70>? */
case NV_TRICKDEAD: /* Ž€‚ñ‚¾‚Ó‚è */
case TF_HIDING: /* ƒnƒCƒfƒBƒ“ƒO */
case AS_CLOAKING: /* ƒNƒ<4E>?ƒ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; /* ‰ð<E280B0>œ·é<E2809A>ê<EFBFBD>ÍSP<53>Á”ïµÈ¢ */
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_BODYRELOCATION:
if (sd->sc_count && sd->sc_data[SC_EXPLOSIONSPIRITS].timer!=-1)
spiritball = 0;
break;
case MO_CHAINCOMBO: //˜AÅ<E28098>
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: //Ò—´Œ<C2B4>
if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_CHAINCOMBO)
return 0;
break;
case CH_TIGERFIST: //•šŒÕŒ<C395>
if((sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH) && !sd->state.skill_flag)
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: // ˆ¢<CB86>C—…”e<50>
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ˆÈ<CB86>ãÌÝ<E2809A>H
clif_skill_fail(sd,skill,0,0);
return 0;
}
}
break;
case PR_BENEDICTIO: /* <20>¹?<3F>~•Ÿ */
{
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 summons[5] = { 1020, 1068, 1118, 1500, 1368 };
int maxcount = (skill==AM_CANNIBALIZE)? 6-lv : skill_get_maxcount(skill);
int mob_class = (skill==AM_CANNIBALIZE)? summons[lv-1] :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:
/* ?<3F>§ŒÀ */
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;
// skills require arrows as of 12/07 [celest]
case AC_DOUBLE:
case AC_SHOWER:
case AC_CHARGEARROW:
case BA_MUSICALSTRIKE:
case DC_THROWARROW:
case SN_SHARPSHOOTING:
case CG_ARROWVULCAN:
if(sd->equip_index[10] < 0) {
clif_arrow_fail(sd,0);
return 0;
}
arrow_flag = 1;
break;
case RG_BACKSTAP:
if(sd->status.weapon == 11) {
if (sd->equip_index[10] < 0) {
clif_arrow_fail(sd,0);
return 0;
}
arrow_flag = 1;
}
break;
}
if(!(type&2)){
if( hp>0 && sd->status.hp < hp) { /* HPƒ`ƒFƒbƒN */
clif_skill_fail(sd,skill,2,0); /* HP•s«<E28098>¸”sÊm */
return 0;
}
if( sp>0 && sd->status.sp < sp) { /* SPƒ`ƒFƒbƒN */
clif_skill_fail(sd,skill,1,0); /* SP•s«<E28098>¸”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 (skill == MO_EXTREMITYFIST && ((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)) {
break;
}
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,CELL_CHKWATER))&& (sd->sc_data[SC_DELUGE].timer==-1)){ //<2F><EFBFBD>ê”»è
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 ||
skill == CR_SLIMPITCHER) && 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 &&
skill != CR_SLIMPITCHER &&
skill != MG_STONECURSE) {
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ƒ€<C692>Á”ï
}
if (arrow_flag && battle_config.arrow_decrement)
pc_delitem(sd,sd->equip_index[10],1,0);
}
if(type&2)
return 1;
if(sp > 0) { // SP<53>Á”ï
sd->status.sp-=sp;
clif_updatestatus(sd,SP_SP);
}
if(hp > 0) { // HP<48>Á”ï
sd->status.hp-=hp;
clif_updatestatus(sd,SP_HP);
}
if(zeny > 0) // Zeny<6E>Á”ï
pc_payzeny(sd,zeny);
if(spiritball > 0) // Ÿ†<E280B9>Á”ï
pc_delspiritball(sd,spiritball,0);
return 1;
}
/*==========================================
* ‰r<E280B0>¥ŽžŠÔŒvŽZ
*------------------------------------------
*/
int skill_castfix( struct block_list *bl, int time )
{
struct map_session_data *sd = NULL;
struct mob_data *md; // [Valaris]
struct status_change *sc_data;
int castrate=100;
int skill,lv;
nullpo_retr(0, bl);
if(bl->type==BL_MOB){ // Crash fix [Valaris]
nullpo_retr(0, md=(struct mob_data*)bl);
skill = md->skillid;
lv = md->skilllv;
} else {
nullpo_retr(0, sd=(struct map_session_data*)bl);
skill = sd->skillid;
lv = sd->skilllv;
}
if(lv <= 0) return 0;
sc_data = status_get_sc_data(bl);
if (skill > MAX_SKILL_DB || skill < 0)
return 0;
/* ƒTƒtƒ‰ƒMƒEƒ€ */
if(sc_data && sc_data[SC_SUFFRAGIUM].timer!=-1 )
time=time*(100-sc_data[SC_SUFFRAGIUM].val1*15)/100;
status_change_end( bl, SC_SUFFRAGIUM, -1);
if(time==0)
return 0;
if (sd) {
if(!skill_get_castnodex(skill, lv) > 0) {
castrate=((struct map_session_data *)bl)->castrate;
time=time*castrate*(battle_config.castrate_dex_scale - status_get_dex(bl))/(battle_config.castrate_dex_scale * 100);
time=time*battle_config.cast_rate/100;
}
}
/* ƒuƒ‰ƒMÌŽ<C38C> */
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;
struct map_session_data *sd = NULL;
int skill = 0,lv = 0;
int delayrate = 100;
nullpo_retr(0, bl);
if(bl->type == BL_PC){
nullpo_retr(0, sd = (struct map_session_data*)bl);
skill = sd->skillid;
lv = sd->skilllv;
}
if(lv <= 0) return 0;
sc_data = status_get_sc_data(bl);
if(sd) {
delayrate=((struct map_session_data *)bl)->delayrate;
// instant cast attack skills depend on aspd as delay [celest]
if (time == 0) {
if (skill_db[skill].skill_type == BF_WEAPON)
time = status_get_adelay (bl)/2;
else
time = 300; // default delay, according to official servers
} else if (time < 0)
time = abs(time) + status_get_adelay (bl)/2; // if set to <0, the aspd delay will be added
if(battle_config.delay_dependon_dex && /* dex̉e¿ðŒvŽZ·é */
!skill_get_delaynodex(skill, lv)) // if skill casttime is allowed to be reduced by dex
time = time * (battle_config.castrate_dex_scale - status_get_dex(bl)) / (battle_config.castrate_dex_scale);
time = time * delayrate * battle_config.delay_rate / 10000;
if (time < battle_config.min_skill_delay_limit) // check minimum skill delay
time = battle_config.min_skill_delay_limit;
}
/* ƒuƒ‰ƒMÌŽ<C38C> */
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<E28094>iIDŽwè<E28099>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;
/* ’¾?âˆÙ<CB86>í<EFBFBD>i½¾µ<E2809A>AƒOƒŠƒ€ÈÇÌ”»èð·é<E2809A>j */
if( sd->opt1>0 )
return 0;
if(sc_data){
// allow to use only Chasewalk [celest]
if(sc_data[SC_CHASEWALK].timer != -1 && skill_num != ST_CHASEWALK)
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(sc_data[SC_DIVINA].timer!=-1 ||
sc_data[SC_ROKISWEIL].timer!=-1 ||
(sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) ||
sc_data[SC_STEELBODY].timer != -1 ||
sc_data[SC_BERSERK].timer != -1 ||
(sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)){
return 0; /* ?ÔˆÙ<CB86>íâ¾?‚È‚Ç */
}
if(sc_data[SC_BLADESTOP].timer != -1){
int lv = sc_data[SC_BLADESTOP].val1;
if(sc_data[SC_BLADESTOP].val2==1) return 0;//”‰H³ê½¤ÈÌŃ_ƒ<5F>
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 (sc_data[SC_BASILICA].timer != -1) { // Disallow all other skills in Basilica [celest]
struct skill_unit_group *sg = (struct skill_unit_group *)sc_data[SC_BASILICA].val4;
// if caster is the owner of basilica
if (sg && sg->src_id == sd->bl.id &&
skill_num == HP_BASILICA) ; // do nothing
// otherwise...
else return 0;
}
/* ‰‰t/ƒ_ƒ“ƒX† */
if(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 ) //<2F>t̓AƒhƒŠƒuˆÈŠO•s‰Â
return 0;
if(skill_num!=BD_ADAPTATION && skill_num!=BA_MUSICALSTRIKE && skill_num!=DC_THROWARROW){
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(skill_get_inf2(skill_num)&0x200 && sd->bl.id == target_id)
return 0;
//¼Õ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)) == NULL)
return 0;
if (strcmp(sd->status.name,g->master))
return 0;
skill_lv = guild_checkskill(g, skill_num);
if (skill_lv <= 0) return 0;
}
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‰“Ì<E2809A>¬“× */
case BD_DRUMBATTLEFIELD: /* ?‘¾ŒÛ‚Ì‹¿‚« */
case BD_RINGNIBELUNGEN: /* ƒj?ƒxƒƒ“ƒOÌŽw—Ö */
case BD_ROKISWEIL: /* ƒ<>ƒLÌ©Ñ */
case BD_INTOABYSS: /* <20>[•£‚Ì’†‚É */
case BD_SIEGFRIED: /* •sŽ€<C5BD>g̃W?ƒNƒtƒŠ?ƒh */
case BD_RAGNAROK: /* <20>_?‚Ì?<3F>¨ */
case CG_MOONLIT: /* ŒŽ¾èÌ<E2809A>òÉ—Ž¿é‰ÔÑç */
{
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<E28094>Ýè¾Á½
;
}else{
sd->skilllv=(c + skill_lv)/2;
}
}
break;
}
if(!skill_check_condition(sd,0)) return 0;
{
int check_range_flag = 0;
/* ŽËöÆ<E2809A>áŠQ•¨ƒ`ƒFƒbƒN */
range = skill_get_range(skill_num,skill_lv);
if(range < 0)
range = status_get_range(&sd->bl) - (range + 1);
// be lenient if the skill was cast before we have moved to the correct position [Celest]
if (sd->walktimer != -1)
range += battle_config.skill_range_leniency;
else check_range_flag = 1;
if(!battle_check_range(&sd->bl,bl,range)) {
if (check_range_flag && battle_check_range(&sd->bl,bl,range + battle_config.skill_range_leniency)) {
int dir, mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
dir = map_calc_dir(&sd->bl,bl->x,bl->y);
pc_walktoxy (sd, sd->bl.x + mask[dir][0] * battle_config.skill_range_leniency,
sd->bl.y + mask[dir][1] * battle_config.skill_range_leniency);
} else
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 == CH_CHAINCRUSH && sd->state.skill_flag) ||
(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(status_get_race(bl),status_get_elem_type(bl)))
// forcecast=1; /* ƒq?ƒƒAƒ^ƒbƒNÈç‰r<E280B0>¥ƒGƒtƒFƒNƒg—Lè */
// break;
case ALL_RESURRECTION: /* ƒŠƒUƒŒƒNƒVƒ‡ƒ“ */
if(bl->type != BL_PC && battle_check_undead(status_get_race(bl),status_get_elem_type(bl))){ /* “GªƒAƒ“ƒfƒbƒhÈç */
forcecast=1; /* ƒ^?ƒ“ƒAƒ“ƒfƒbƒgÆ“¯¶‰r<E280B0>¥ŽžŠÔ */
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Å<E28098>¶*/
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ª¢È¢<E2809A>H
return 0;
target_id = tbl->id;
}
break;
case MO_COMBOFINISH: /*Ò—´Œ<C2B4>*/
// case CH_TIGERFIST: /* •šŒÕŒ<C395> */
case CH_CHAINCRUSH: /* ˜AŒ•ö? */
target_id = sd->attacktarget;
break;
case CH_TIGERFIST: /* •šŒÕŒ<C395> */
if(sc_data && sc_data[SC_COMBO].timer != -1 && sc_data[SC_COMBO].val1 == MO_COMBOFINISH)
target_id = sd->attacktarget;
break;
// -- moonsoul (altered to allow proper usage of extremity from new champion combos)
//
case MO_EXTREMITYFIST: /*ˆ¢<CB86>C—…”e<50>*/
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 = pc_get_partner(sd);
if (p_sd == NULL) // it's possible to get null if we're not married ^^;
return 0;
// nullpo_retr (0, p_sd)
if(skill_num == WE_MALE && sd->status.hp <= ((15*sd->status.max_hp)/100)) // Requires more than 15% of Max HP for WE_MALE
return 0;
else if(skill_num == WE_FEMALE && sd->status.sp <= ((15*sd->status.max_sp)/100)) // Requires more than 15% of Max SP for WE_FEMALE
return 0;
target_id = p_sd->bl.id;
//rangeðà¤1‰ñ?<3F>¸
range = skill_get_range(skill_num,skill_lv);
if(range < 0)
range = status_get_range(&sd->bl) - (range + 1);
if(!battle_check_range(&sd->bl,&p_sd->bl,range))
return 0;
}
break;
case PF_MEMORIZE: /* ƒ<>ƒƒ‰ƒCƒY */
casttime = 12000;
break;
case HW_MAGICPOWER:
casttime = 700;
break;
case HP_BASILICA: /* ƒoƒWƒŠƒJ */
{
if (skill_check_unit_range(sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) {
clif_skill_fail(sd,sd->skillid,0,0);
return 0;
}
if (skill_check_unit_range2(sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) {
clif_skill_fail(sd,sd->skillid,0,0);
return 0;
}
// cancel Basilica if already in effect
struct status_change *sc_data = status_get_sc_data(&sd->bl);
if(sc_data && sc_data[SC_BASILICA].timer != -1) {
struct skill_unit_group *sg = (struct skill_unit_group *)sc_data[SC_BASILICA].val4;
if (sg && sg->src_id == sd->bl.id) {
status_change_end(&sd->bl,SC_BASILICA,-1);
skill_delunitgroup (sg);
return 0;
}
}
}
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)
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<E280B0>¥ª•K—v */
struct mob_data *md;
clif_skillcasting( &sd->bl, sd->bl.id, target_id, 0,0, skill_num,casttime);
/* ‰r<E280B0>¥”½?ƒƒ“ƒ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<E280B0>¥Ì³¢àÌ̓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)
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);
}
return 0;
}
/*==========================================
* ƒXƒLƒŽg—p<E28094>i<EFBFBD>ê<EFBFBD>ŠŽwè<E28099>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 ||
sc_data[SC_MARIONETTE].timer != -1)
return 0; /* ?ÔˆÙ<CB86>íâ¾?‚È‚Ç */
if (sc_data[SC_BASILICA].timer != -1) {
struct skill_unit_group *sg = (struct skill_unit_group *)sc_data[SC_BASILICA].val4;
// if caster is the owner of basilica
if (sg && sg->src_id == sd->bl.id &&
skill_num == HP_BASILICA) ; // do nothing
// otherwise...
else return 0;
}
}
if(sd->status.option&2)
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;
/* ŽËöÆ<E2809A>áŠQ•¨ƒ`ƒFƒbƒN */
bl.type = BL_NUL;
bl.m = sd->bl.m;
bl.x = skill_x;
bl.y = skill_y;
{
int check_range_flag = 0;
/* ŽËöÆ<E2809A>áŠQ•¨ƒ`ƒFƒbƒN */
range = skill_get_range(skill_num,skill_lv);
if(range < 0)
range = status_get_range(&sd->bl) - (range + 1);
// be lenient if the skill was cast before we have moved to the correct position [Celest]
if (sd->walktimer != -1)
range += battle_config.skill_range_leniency;
else check_range_flag = 1;
if(!battle_check_range(&sd->bl,&bl,range)) {
if (check_range_flag && battle_check_range(&sd->bl,&bl,range + battle_config.skill_range_leniency)) {
int dir, mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
dir = map_calc_dir(&sd->bl,bl.x,bl.y);
pc_walktoxy (sd, sd->bl.x + mask[dir][0] * battle_config.skill_range_leniency,
sd->bl.y + mask[dir][1] * battle_config.skill_range_leniency);
} else
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)
status_change_end(&sd->bl, SC_MEMORIZE, -1);
}
if( casttime>0 ) /* ‰r<E280B0>¥ª•K—v */
clif_skillcasting( &sd->bl,
sd->bl.id, 0, skill_x,skill_y, skill_num,casttime);
if( casttime<=0 ) /* ‰r<E280B0>¥Ì³¢àÌ̓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)
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ƒ<70>?‚Ì?‰Ê<E280B0>I—¹
if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER)
status_change_end(&sd->bl,SC_MAGICPOWER,-1);
return 0;
}
/*==========================================
* ƒXƒLƒ‰r<E280B0>¥ƒ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 <20>‰Šú”Í?Œˆ’è
*----------------------------------------
*/
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);
md = (struct map_session_data *)bl;
if ((sd = map_id2sd(target))==NULL)
return 1;
else
r = distance(bl->x,bl->y,sd->bl.x,sd->bl.y);
if(pc_checkskill(md,CR_DEVOTION)+6 < r){ // —e”Í?‚ð’´‚¦‚Ä‚½
for(n=0;n<5;n++)
if(md->dev.val1[n]==target)
md->dev.val2[n]=0; // —£ê½ŽžÍ<E2809A>A?ð<E2809A>Øé¾¯
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){
// 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;
status_change_start(&sd->bl,SC_AUTOSPELL,skilllv,skillid,maxlv,0, // val1:ƒXƒLƒID val2:Žg—p<E28094>ÅåLv
skill_get_time(SA_AUTOSPELL,skilllv),0);// ɵÄݽ¯Çbscriptª<E2809A>«ˆÕ¢???<3F>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) {/* <20>ÀÁ½ŽžÌ?—<> */
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ƒ^?<3F>¬Œ÷µ½çŽ©•ªÉàƒMƒƒƒ“ƒOƒXƒ^??<3F>«•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) {/* —§¿<E2809A>ãªÁ½Æ«Ì?—<> */
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ƒ<54>ƒ“ƒoÉàáŠm—¦Å©©é(Æè ¦¸10%)
skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick);
}
return 0;
}
/*==========================================
* Moonlit creates a 'safe zone' [celest]
*------------------------------------------
*/
static int skill_moonlit_count(struct block_list *bl,va_list ap)
{
int *c, id;
struct map_session_data *sd;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, (sd=(struct map_session_data *)bl));
id=va_arg(ap,int);
c=va_arg(ap,int *);
if (sd->bl.id != id && sd->sc_count && sd->sc_data[SC_MOONLIT].timer != -1 && c)
(*c)++;
return 0;
}
int skill_check_moonlit (struct block_list *bl, int dx, int dy)
{
int c=0;
nullpo_retr(0, bl);
map_foreachinarea(skill_moonlit_count,bl->m,
dx-1,dy-1,dx+1,dy+1,BL_PC,bl->id,&c);
return (c>0);
}
/*==========================================
*ƒAƒuƒ‰ƒJƒ_ƒuƒ‰ÌŽg—pƒXƒLƒŒˆè(ŒˆèƒXƒLƒªƒ_ƒ<5F>Èç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ƒÍƒ_ƒ<5F>
if(skill >= NPC_PIERCINGATT && skill <= NPC_SUMMONMONSTER) return 0;
//‰‰tƒXƒLƒÍƒ_ƒ<5F>
if (skill_get_unit_flag(skill)&UF_DANCE) return 0;
return skill;
}
/*==========================================
* ƒoƒWƒŠƒJ̃Zƒð<E2809A>Ýè·é
*------------------------------------------
*/
void skill_basilica_cell(struct skill_unit *unit,int flag)
{
int i,x,y,range = skill_get_unit_range(HP_BASILICA);
int size = range*2+1;
for (i=0;i<size*size;i++) {
x = unit->bl.x+(i%size-range);
y = unit->bl.y+(i/size-range);
map_setcell(unit->bl.m,x,y,flag);
}
}
/*==========================================
*
*------------------------------------------
*/
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;
if(skillid > 0 && skilllv <= 0) return 0; // celest
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,max,skillid;
nullpo_retr(0, bl);
if (bl->type==BL_MOB) {
max = MAX_MOBSKILLUNITGROUP;
md = (struct mob_data *)bl;
} else if(bl->type==BL_PC) {
max = MAX_SKILLUNITGROUP;
sd = (struct map_session_data *)bl;
} else
return 0;
for (i=0;i<max;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ƒ<76>ƒ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ˆÙ<CB86>í<EFBFBD>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=status_get_sc_data(bl));
if( type!=SC_ENCPOISON && sc_data[SC_ENCPOISON].timer!=-1 ) /* ƒGƒ“ƒ`ƒƒƒ“ƒgƒ|ƒCƒYƒ“‰ð<E280B0>œ */
status_change_end(bl,SC_ENCPOISON,-1);
if( type!=SC_ASPERSIO && sc_data[SC_ASPERSIO].timer!=-1 ) /* ƒAƒXƒyƒƒVƒI‰ð<E280B0>œ */
status_change_end(bl,SC_ASPERSIO,-1);
if( type!=SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer!=-1 ) /* ƒtƒŒƒCƒ€ƒ‰ƒ“ƒ`ƒƒ‰ð<E280B0>œ */
status_change_end(bl,SC_FLAMELAUNCHER,-1);
if( type!=SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer!=-1 ) /* ƒtƒ<74>ƒXƒgƒEƒFƒ|ƒ“‰ð<E280B0>œ */
status_change_end(bl,SC_FROSTWEAPON,-1);
if( type!=SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer!=-1 ) /* ƒ‰ƒCƒgƒjƒ“ƒOƒ<4F>?ƒ_?‰ð<E280B0>œ */
status_change_end(bl,SC_LIGHTNINGLOADER,-1);
if( type!=SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer!=-1 ) /* ƒTƒCƒXƒ~ƒbƒNƒEƒFƒ|ƒ“‰ð<E280B0>œ */
status_change_end(bl,SC_SEISMICWEAPON,-1);
return 0;
}
/* ƒNƒ<4E>?ƒLƒ“ƒO?<3F>¸<EFBFBD>iŽüèɈړ®•s‰Â”\n?ª é©<E2809A>j */
int skill_check_cloaking(struct block_list *bl)
{
struct map_session_data *sd = NULL;
static int dx[]={ 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus
static int dy[]={-1, 0, 1, 0, -1, -1, 1, 1};
int end=1,i;
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;
//missing sd [Found by Celest, commited by Aria]
if (bl->type == BL_PC)
sd=(struct map_session_data *)bl;
for(i=0;i<sizeof(dx)/sizeof(dx[0]);i++){
if(map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i],CELL_CHKNOPASS)) {
end=0;
break;
}
}
if(end){
if ((sd && pc_checkskill(sd,AS_CLOAKING)<3) || bl->type == BL_MOB) {
status_change_end(bl, SC_CLOAKING, -1);
}
else if (sd && sd->sc_data[SC_CLOAKING].val3 != 130) {
sd->sc_data[SC_CLOAKING].val3 = 130;
status_calc_speed (sd);
}
}
else {
if (sd && sd->sc_data[SC_CLOAKING].val3 != 103) {
sd->sc_data[SC_CLOAKING].val3 = 103;
status_calc_speed (sd);
}
}
return end;
}
/*
*----------------------------------------------------------------------------
* ƒXƒLƒƒ†ƒjƒbƒg
*----------------------------------------------------------------------------
*/
/*==========================================
* ‰‰t/ƒ_ƒ“ƒXðâßé
* flag 1Å<E2809A>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;
short* sc_count;
nullpo_retv(src);
nullpo_retv(sc_data = status_get_sc_data(src));
nullpo_retv(sc_count = status_get_sc_count(src));
if((*sc_count)>0 && 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){ //<2F>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ðŽ<C3B0>ÁÄé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ɵÄ<E2809A>t<E28098>I—¹<E28094>¨Ê<E28099>í̃_ƒ“ƒX?‘Ô
if(flag&2) //ƒnƒG”òÑÈÇ
return; //<2F>tàƒ_ƒ“ƒX?Ôà<E2809A>I—¹³¹È¢<E2809A>•ƒXƒLƒƒ†ƒjƒbƒgÍu¢Ä¯Úè
}else if(dsd && dsd->bl.id == group->src_id){ //Š•ûªƒOƒ?ƒvðŽ<C3B0>ÁÄ¢éPCª—Ž¿é(Ž©•ªÍƒOƒ?ƒvðŽ<C3B0>ÁĢȢ)
if(flag&1) //ƒ<>ƒOƒAƒEƒg
dsd->sc_data[SC_DANCING].val4=0; //Š•ûÌŠ•ûð0ɵÄ<E2809A>t<E28098>I—¹<E28094>¨Ê<E28099>í̃_ƒ“ƒX?‘Ô
if(flag&2) //ƒnƒG”òÑÈÇ
return; //<2F>tàƒ_ƒ“ƒX?Ôà<E2809A>I—¹³¹È¢<E2809A>•ƒXƒLƒƒ†ƒjƒbƒgÍu¢Ä¯Úè
}
status_change_end(src,SC_DANCING,-1);//Ž©•ªÌƒXƒe?ƒ^ƒXð<E2809A>I—¹³¹é
//»µÄƒOƒ?ƒvÍ<E2809A>Á³È¢<E2809A><EFBFBD>Á³È¢ÌŃXƒe?ƒ^ƒXŒvŽZà¢çÈ¢<E2809A>H
return;
}else{
if(dsd && src->id == group->src_id){ //ƒOƒ?ƒvðŽ<C3B0>ÁÄéPCªŽ~‚ß‚é
status_change_end((struct block_list *)dsd,SC_DANCING,-1);//ŠŽè̃Xƒe?ƒ^ƒXð<E2809A>I—¹³¹é
}
if(dsd && dsd->bl.id == group->src_id){ //Š•ûªƒOƒ?ƒvðŽ<C3B0>ÁÄ¢éPCªŽ~‚ß‚é(Ž©•ªÍƒOƒ?ƒvðŽ<C3B0>ÁĢȢ)
status_change_end(src,SC_DANCING,-1);//Ž©•ªÌƒXƒe?ƒ^ƒXð<E2809A>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)
status_calc_pc((struct map_session_data *)src,0);
}
}
/*==========================================
* ƒXƒLƒƒ†ƒjƒbƒg<C692>‰Šú‰»
*------------------------------------------
*/
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);
if (group->skill_id==HP_BASILICA)
skill_basilica_cell(unit,CELL_SETBASILICA);
return unit;
}
/*==========================================
* ƒXƒLƒƒ†ƒjƒbƒg<C692>í<EFBFBD>œ
*------------------------------------------
*/
int skill_delunit(struct skill_unit *unit)
{
struct skill_unit_group *group;
nullpo_retr(0, unit);
if(!unit->alive)
return 0;
nullpo_retr(0, group=unit->group);
/* onlimitƒCƒxƒ“ƒgŒÄÑ<E2809A>oµ */
skill_unit_onlimit( unit,gettick() );
/* onoutƒCƒxƒ“ƒgŒÄÑ<E2809A>oµ */
if (!unit->range) {
map_foreachinarea(skill_unit_effect,unit->bl.m,
unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y,0,
&unit->bl,gettick(),0);
}
if (group->skill_id==HP_BASILICA)
skill_basilica_cell(unit,CELL_CLRBASILICA);
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<C692>‰Šú‰»
*------------------------------------------
*/
static int skill_unit_group_newid = MAX_SKILL_DB;
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++) /* ‹ó‚¢‚Ä‚¢‚é‚à‚Ì?<3F>õ */
if(list[i].group_id==0){
group=&list[i];
break;
}
if(group==NULL){ /* ‹ó‚¢‚ĂȂ¢‚̂Ō¢‚à‚Ì?<3F>õ */
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=status_get_party_id(src);
group->guild_id=status_get_guild_id(src);
group->group_id=skill_unit_group_newid++;
if(skill_unit_group_newid<=0)
skill_unit_group_newid = MAX_SKILL_DB;
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->limit=10000;
group->interval=1000;
group->tick=gettick();
group->valstr=NULL;
if (skill_get_unit_flag(skillid)&UF_DANCE) {
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;
}
status_change_start(src,SC_DANCING,skillid,(int)group,0,0,skill_get_time(skillid,skilllv)+1000,0);
//<2F>tƒXƒLƒÍŠ•ûðƒ_ƒ“ƒX<C692>óÔÉ·é
if (sd && skill_get_unit_flag(skillid)&UF_ENSEMBLE) {
int c=0;
map_foreachinarea(skill_check_condition_use_sub,sd->bl.m,
sd->bl.x-1,sd->bl.y-1,sd->bl.x+1,sd->bl.y+1,BL_PC,&sd->bl,&c);
}
}
return group;
}
/*==========================================
* ƒXƒLƒƒ†ƒjƒbƒgƒOƒ?ƒv<C692>í<EFBFBD>œ
*------------------------------------------
*/
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);
//ƒ_ƒ“ƒXƒXƒLƒÍƒ_ƒ“ƒX<C692>óÔð‰ð<E280B0>œ·é
if (skill_get_unit_flag(group->skill_id)&UF_DANCE) {
if(src)
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); /* aFree()‚̑ւí‚è */
group->unit=NULL;
group->src_id=0;
group->group_id=0;
group->unit_count=0;
return 0;
}
/*==========================================
* ƒXƒLƒƒ†ƒjƒbƒgƒOƒ?ƒvS<E28098>í<EFBFBD>œ
*------------------------------------------
*/
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;
} else
return 0;
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?<3F>õ
*------------------------------------------
*/
struct skill_unit_group_tickset *skill_unitgrouptickset_search(
struct block_list *bl,struct skill_unit_group *group,int tick)
{
int i,j=-1,k,s,id;
struct skill_unit_group_tickset *set;
nullpo_retr(0, bl);
if (group->interval==-1)
return NULL;
if (bl->type == BL_PC)
set = ((struct map_session_data *)bl)->skillunittick;
else if (bl->type == BL_MOB)
set = ((struct mob_data *)bl)->skillunittick;
else
return 0;
if (skill_get_unit_flag(group->skill_id)&UF_NOOVERLAP)
id = s = group->skill_id;
else
id = s = group->group_id;
for (i=0; i<MAX_SKILLUNITGROUPTICKSET; i++) {
k = (i+s) % MAX_SKILLUNITGROUPTICKSET;
if (set[k].id == id)
return &set[k];
else if (j==-1 && (DIFF_TICK(tick,set[k].tick)>0 || set[k].id==0))
j=k;
}
if (j == -1) {
if(battle_config.error_log) {
sprintf (tmp_output, "skill_unitgrouptickset_search: tickset is full\n");
ShowWarning (tmp_output);
}
j = id % MAX_SKILLUNITGROUPTICKSET;
}
set[j].id = id;
set[j].tick = tick;
return &set[j];
}
/*==========================================
* ƒXƒLƒƒ†ƒjƒbƒgƒ^ƒCƒ}??“®?—<>—p(foreachinarea)
*------------------------------------------
*/
int skill_unit_timer_sub_onplace( struct block_list *bl, va_list ap )
{
struct skill_unit *unit;
struct skill_unit_group *group;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
unit = va_arg(ap,struct skill_unit *);
tick = va_arg(ap,unsigned int);
if (bl->type!=BL_PC && bl->type!=BL_MOB)
return 0;
if (!unit->alive || bl->prev==NULL)
return 0;
nullpo_retr(0, group=unit->group);
if (battle_check_target(&unit->bl,bl,group->target_flag)<=0)
return 0;
skill_unit_onplace_timer(unit,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);
tick=va_arg(ap,unsigned int);
if(!unit->alive)
return 0;
nullpo_retr(0, group=unit->group);
range = unit->range;
/* onplace_timerƒCƒxƒ“ƒgŒÄÑ<E2809A>oµ */
if (range>=0 && group->interval!=-1) {
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 (!unit->alive)
return 0;
// ƒ}ƒOƒkƒXÍ”­“®µ½ƒ†ƒjƒbƒgÍ<E2809A>í<EFBFBD>œ·é
if (group->skill_id==PR_MAGNUS && unit->val2) {
skill_delunit(unit);
return 0;
}
}
// ƒCƒhƒDƒ“Ì—ÑŒçÉæé‰ñ•œ
if (group->unit_id==0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val3) {
struct block_list *src = map_id2bl(group->src_id);
int range = skill_get_unit_layout_type(group->skill_id,group->skill_lv);
nullpo_retr(0, src);
map_foreachinarea(skill_idun_heal,src->m,
src->x-range,src->y-range,src->x+range,src->y+range,0,unit);
group->val3++;
}
/* ŽžŠÔ<C5A0>Øê<E2809A>í<EFBFBD>œ */
if((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); // ?•ÔŠÒ
}
}
skill_delunit(unit);
}
break;
case 0xc1:
case 0xc2:
case 0xc3:
case 0xc4:
{
struct block_list *src=map_id2bl(group->src_id);
if (src)
group->tick = tick;
}
break;
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_move_sub( struct block_list *bl, va_list ap )
{
struct skill_unit *unit = (struct skill_unit *)bl;
struct skill_unit_group *group;
struct block_list *target;
unsigned int tick,flag;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, target=va_arg(ap,struct block_list*));
tick = va_arg(ap,unsigned int);
flag = va_arg(ap,int);
if (target->type!=BL_PC && target->type!=BL_MOB)
return 0;
nullpo_retr(0, group=unit->group);
if (group->interval!=-1)
return 0;
if (!unit->alive || target->prev==NULL)
return 0;
if (flag)
skill_unit_onplace(unit,target,tick);
else
skill_unit_onout(unit,target,tick);
return 0;
}
/*==========================================
* ƒXƒLƒƒ†ƒjƒbƒgˆÚ“®Žž?—<>
*------------------------------------------
*/
int skill_unit_move(struct block_list *bl,unsigned int tick,int flag)
{
nullpo_retr(0, bl);
if(bl->prev==NULL )
return 0;
map_foreachinarea(skill_unit_move_sub,
bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,bl,tick,flag);
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)
{
int i,j;
int tick = gettick();
int *m_flag;
struct skill_unit *unit1;
struct skill_unit *unit2;
nullpo_retr(0, group);
if (group->unit_count<=0)
return 0;
if (group->unit==NULL)
return 0;
// ˆÚ“®‰Â”\ȃXƒLƒÍƒ_ƒ“ƒXŒnÆ<E2809A>Aƒuƒ‰ƒXƒgƒ}ƒCƒ“<C692>AƒNƒŒƒCƒƒA<C692>[ƒgƒ‰ƒbƒvÌÝ
if (!(skill_get_unit_flag(group->skill_id)&UF_DANCE) &&
group->skill_id!=HT_CLAYMORETRAP && group->skill_id!=HT_BLASTMINE)
return 0;
m_flag = malloc(sizeof(int)*group->unit_count);
memset(m_flag,0,sizeof(int)*group->unit_count);// ˆÚ“®ƒtƒ‰ƒO
// <20>æÉƒtƒ‰ƒOðS•”Œˆßé
// m_flag
// 0: P<E28099>ƒˆÚ“®
// 1: ƒ†ƒjƒbƒgðˆÚ“®·é(Œ»ˆÊu©çƒ†ƒjƒbƒgªÈ­Èé)
// 2: Žc—¯<E28094><EFBFBD>VˆÊuªˆÚ“®<E2809C>æÆÈé(ˆÚ“®<E2809C>æÉƒ†ƒjƒbƒgª<E28098>ݵȢ)
// 3: Žc—¯
for(i=0;i<group->unit_count;i++){
unit1=&group->unit[i];
if (!unit1->alive || unit1->bl.m!=m)
continue;
for(j=0;j<group->unit_count;j++){
unit2=&group->unit[j];
if (!unit2->alive)
continue;
if (unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){
// ˆÚ“®<E2809C>æÉƒ†ƒjƒbƒgª©ÔÁÄ¢é
m_flag[i] |= 0x1;
}
if (unit1->bl.x-dx==unit2->bl.x && unit1->bl.y-dy==unit2->bl.y){
// ƒ†ƒjƒbƒgª±Ì<E2809A>ê<EFBFBD>ŠÉâÁÄ­é
m_flag[i] |= 0x2;
}
}
}
// ƒtƒ‰ƒOÉŠîâă†ƒjƒbƒgˆÚ“®
// ƒtƒ‰ƒOª1ÌunitðTµ<E2809A>Aƒtƒ‰ƒOª2Ìuniẗړ®<E2809C>æÉˆÚ·
j = 0;
for (i=0;i<group->unit_count;i++) {
unit1=&group->unit[i];
if (!unit1->alive)
continue;
if (!(m_flag[i]&0x2)) {
// ƒ†ƒjƒbƒgªÈ­Èé<E2809A>ê<EFBFBD>ŠÅƒXƒLƒƒ†ƒjƒbƒg‰e¿ð<E2809A>Á·
map_foreachinarea(skill_unit_effect,unit1->bl.m,
unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0,
&unit1->bl,tick,0);
}
if (m_flag[i]==0) {
// P<E28099>ƒˆÚ“®
map_delblock(&unit1->bl);
unit1->bl.m = m;
unit1->bl.x += dx;
unit1->bl.y += dy;
map_addblock(&unit1->bl);
clif_skill_setunit(unit1);
} else if (m_flag[i]==1) {
// ƒtƒ‰ƒOª2ÌàÌðTµÄ»Ìƒ†ƒjƒbƒg̈ړ®<E2809C>æÉˆÚ“®
for(;j<group->unit_count;j++) {
if (m_flag[j]==2) {
// Œp<C592>³ˆÚ“®
unit2 = &group->unit[j];
if (!unit2->alive)
continue;
map_delblock(&unit1->bl);
unit1->bl.m = m;
unit1->bl.x = unit2->bl.x+dx;
unit1->bl.y = unit2->bl.y+dy;
map_addblock(&unit1->bl);
clif_skill_setunit(unit1);
j++;
break;
}
}
}
if (!(m_flag[i]&0x2)) {
// ˆÚ“®ŒãÌ<E2809A>ê<EFBFBD>ŠÅƒXƒLƒƒ†ƒjƒbƒgð”­“®
map_foreachinarea(skill_unit_effect,unit1->bl.m,
unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0,
&unit1->bl,tick,1);
}
}
aFree(m_flag);
return 0;
}
/*----------------------------------------------------------------------------
* ƒAƒCƒeƒ€<C692><EFBFBD>¬
*----------------------------------------------------------------------------
*/
/*==========================================
* ƒAƒCƒeƒ€<C692><EFBFBD>¬‰Â”\”»’è
*------------------------------------------
*/
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?<3F>ƒ|?ƒVƒ‡ƒ“—ÞÆ—n??<3F>?<3F>ΈȊ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 ) /* ±êˆÈ<CB86>ãÍ<E2809A>Þ—¿—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ƒ€<C692><EFBFBD>¬‰Â”\”»’è
*------------------------------------------
*/
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<E280A2>³ƒpƒPƒbƒg(ƒAƒCƒeƒ€<E28098>Ý)ƒ`ƒFƒbƒN */
continue;
if(slot[i]==1000){ /* <20>¯Ì©¯ç */
pc_delitem(sd,j,1,1);
sc++;
}
if(slot[i]>=994 && slot[i]<=997 && ele==0){ /* ?<3F>«<EFBFBD>Î */
static const int ele_table[4]={3,1,4,2};
pc_delitem(sd,j,1,1);
ele=ele_table[slot[i]-994];
}
}
/* <20>Þ—¿<E28094>Á”ï */
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ˆÈ<CB86>ã̃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 ); /* <20>Þ—¿ð<E2809A>Á”ï·é©<E2809A>AƒGƒ‰?ÉÈéÜÅŒJè•Ô· */
}
/* Šm—¦”»è */
equip = itemdb_isequip(nameid);
if(!equip) {
// Corrected rates [DracoRPG] --------------------------//
if(skill_produce_db[idx].req_skill==AM_PHARMACY) {
make_per = pc_checkskill(sd,AM_LEARNINGPOTION)*100
+ pc_checkskill(sd,AM_PHARMACY)*300 + sd->status.job_level*20
+ sd->status.dex*10+sd->status.int_*5;
if(nameid >= 501 && nameid <= 505) // Normal potions
make_per += 2000 + pc_checkskill(sd,AM_POTIONPITCHER)*100;
else if(nameid >= 605 && nameid <= 606) // Anodyne & Aloevera (not sure of the formula, I put the same base value as normal pots but without the Aid Potion bonus since they are not throwable pots ^^)
make_per += 2000;
else if(nameid >= 545 && nameid <= 547) // Concentrated potions
;
else if(nameid == 970) // Alcohol
make_per += 1000;
else if(nameid == 7135) // Bottle Grenade
make_per += 500 + pc_checkskill(sd,AM_DEMONSTRATION)*100;
else if(nameid == 7136) // Acid Bottle
make_per += 500 + pc_checkskill(sd,AM_ACIDTERROR)*100;
else if(nameid == 7137) // Plant Bottle
make_per += 500 + pc_checkskill(sd,AM_CANNIBALIZE)*100;
else if(nameid == 7138) // Marine Sphere Bottle
make_per += 500 + pc_checkskill(sd,AM_SPHEREMINE)*100;
else if(nameid == 7139) // Glistening Coat
make_per += 500 + 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 = 1500 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*600;
else
make_per = 1000 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500;
}
}
else { // Corrected rates [DracoRPG]
int add_per=0;
if(pc_search_inventory(sd,989) >= 0) add_per = 400;
else if(pc_search_inventory(sd,988) >= 0) add_per = 300;
else if(pc_search_inventory(sd,987) >= 0) add_per = 200;
else if(pc_search_inventory(sd,986) >= 0) add_per = 100;
wlv = itemdb_wlv(nameid);
make_per = 1500 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*1000 + pc_checkskill(sd,BS_WEAPONRESEARCH)*100 +
((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100 : 0) + add_per - (ele? 2500:0) - sc*((4-wlv)*500) - wlv*1000;
}
// -----------------------------------------------------//
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—¦•â<E280A2>³ */
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){
/* <20>¬Œ÷ */
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){ /* •<>ŠíÌ<E2809A>ê<EFBFBD>‡ */
tmp_item.card[0]=0x00ff; /* <20>»¢•<C2A2>Šíƒtƒ‰ƒO */
tmp_item.card[1]=((sc*5)<<8)+ele; /* ?<3F>«ÆÂæ³ */
*((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 */
}
if(log_config.produce > 0)
log_produce(sd,nameid,slot1,slot2,slot3,1);
switch (skill_produce_db[idx].req_skill) {
case AM_PHARMACY:
clif_produceeffect(sd,2,nameid);/* <20>»?ƒGƒtƒFƒNƒg */
clif_misceffect(&sd->bl,5); /* ¼<E28098>lÉà<E2809A>¬Œ÷ðÊm */
break;
case ASC_CDP:
clif_produceeffect(sd,2,nameid);/* ŽbèÅ<E2809A>»?ƒGƒtƒFƒNƒg */
clif_misceffect(&sd->bl,5);
break;
default: /* •<>Ší<C5A0>»¢<E28098>AƒRƒCƒ“<C692>»¢ */
clif_produceeffect(sd,0,nameid); /* •<>Ší<C5A0>»¢ƒ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 {
if(log_config.produce > 0)
log_produce(sd,nameid,slot1,slot2,slot3,0);
switch (skill_produce_db[idx].req_skill) {
case AM_PHARMACY:
clif_produceeffect(sd,3,nameid);/* <20>»?ޏ”sƒGƒtƒFƒNƒg */
clif_misceffect(&sd->bl,6); /* ¼<E28098>lÉàŽ¸”sðÊm */
break;
case ASC_CDP:
{
clif_produceeffect(sd,3,nameid); /* ŽbèÅ<E2809A>»?ƒGƒtƒFƒNƒg */
clif_misceffect(&sd->bl,6); /* ¼<E28098>lÉàŽ¸”sðÊm */
pc_heal(sd, -(sd->status.max_hp>>2), 0);
}
break;
default:
clif_produceeffect(sd,1,nameid);/* •<>Ší<C5A0>»¢Ž¸”sƒGƒtƒFƒNƒg */
clif_misceffect(&sd->bl,2); /* ¼<E28098>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;
}
/*----------------------------------------------------------------------------
* <20>‰Šú‰»Œn
*/
/*----------------------------------------------------------------------------
* <20>‰Šú‰»Œn
*/
/*
* •¶Žš—ñ<E28094>ˆ<CB86>
* ',' Åæ<E280B9>ØÁÄ val ‚É–ß‚·
*/
int skill_split_str(char *str,char **val,int num)
{
int i;
for (i=0; i<num && str; i++){
val[i] = str;
str = strchr(str,',');
if (str)
*str++=0;
}
return i;
}
/*
* •¶Žš—ñ<E28094>ˆ<CB86>
* ':' Åæ<E280B9>ØÁÄatoiµÄvalÉß·
*/
int skill_split_atoi(char *str,int *val)
{
int i, max = 0;
for (i=0; i<MAX_SKILL_LEVEL; i++) {
if (str) {
val[i] = max = atoi(str);
str = strchr(str,':');
if (str)
*str++=0;
} else {
val[i] = max;
}
}
return i;
}
/*
* ƒXƒLƒƒ†ƒjƒbƒgÌ”zu<E28099>î•ñ<E280A2>ì<EFBFBD>¬
*/
void skill_init_unit_layout()
{
int i,j,size,pos = 0;
memset(skill_unit_layout,0,sizeof(skill_unit_layout));
// ‹éŒ`̃†ƒjƒbƒg”zuð<E2809A>ì<EFBFBD>¬·é
for (i=0; i<=MAX_SQUARE_LAYOUT; i++) {
size = i*2+1;
skill_unit_layout[i].count = size*size;
for (j=0; j<size*size; j++) {
skill_unit_layout[i].dx[j] = (j%size-i);
skill_unit_layout[i].dy[j] = (j/size-i);
}
}
pos = i;
// ‹éŒ`ˆÈŠÕ†ƒjƒbƒg”zuð<E2809A>ì<EFBFBD>¬·é
for (i=0;i<MAX_SKILL_DB;i++) {
if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1)
continue;
switch (i) {
case MG_FIREWALL:
case WZ_ICEWALL:
// ƒtƒ@ƒCƒA<C692>[ƒEƒH<C692><C692>AƒAƒCƒXƒEƒH<C692>Í•ûŒüÅ•ÏíéÌÅ•Ê<E280A2>ˆ<CB86>
break;
case PR_SANCTUARY:
{
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};
skill_unit_layout[pos].count = 21;
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
break;
}
case PR_MAGNUS:
{
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};
skill_unit_layout[pos].count = 33;
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
break;
}
case AS_VENOMDUST:
{
static const int dx[] = {-1, 0, 0, 0, 1};
static const int dy[] = { 0,-1, 0, 1, 0};
skill_unit_layout[pos].count = 5;
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
break;
}
case CR_GRANDCROSS:
case NPC_DARKGRANDCROSS:
{
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};
skill_unit_layout[pos].count = 29;
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
break;
}
case PF_FOGWALL:
{
static const int dx[] = {
-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2};
static const int dy[] = {
-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
skill_unit_layout[pos].count = 15;
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
break;
}
default:
printf("unknown unit layout at skill %d\n",i);
break;
}
if (!skill_unit_layout[pos].count)
continue;
for (j=0;j<MAX_SKILL_LEVEL;j++)
skill_db[i].unit_layout_type[j] = pos;
pos++;
}
// ƒtƒ@ƒCƒ„<C692>[ƒEƒH<C692>[ƒ‹
firewall_unit_pos = pos;
for (i=0;i<8;i++) {
if (i&1) { /* ŽÎß”zu */
skill_unit_layout[pos].count = 5;
if (i&0x2) {
int dx[] = {-1,-1, 0, 0, 1};
int dy[] = { 1, 0, 0,-1,-1};
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
} else {
int dx[] = { 1, 1 ,0, 0,-1};
int dy[] = { 1, 0, 0,-1,-1};
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
}
} else { /* <20>c‰¡”zu */
skill_unit_layout[pos].count = 3;
if (i%4==0) { /* <20>㉺ */
int dx[] = {-1, 0, 1};
int dy[] = { 0, 0, 0};
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
} else { /* <20>¶‰E */
int dx[] = { 0, 0, 0};
int dy[] = {-1, 0, 1};
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
}
}
pos++;
}
// ƒAƒCƒXƒEƒH<C692>[ƒ‹
icewall_unit_pos = pos;
for (i=0;i<8;i++) {
skill_unit_layout[pos].count = 5;
if (i&1) { /* ŽÎß”zu */
if (i&0x2) {
int dx[] = {-2,-1, 0, 1, 2};
int dy[] = { 2,-1, 0,-1,-2};
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
} else {
int dx[] = { 2, 1 ,0,-1,-2};
int dy[] = { 2, 1, 0,-1,-2};
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
}
} else { /* <20>c‰¡”zu */
if (i%4==0) { /* <20>㉺ */
int dx[] = {-2,-1, 0, 1, 2};
int dy[] = { 0, 0, 0, 0, 0};
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
} else { /* <20>¶‰E */
int dx[] = { 0, 0, 0, 0, 0};
int dy[] = {-2,-1, 0, 1, 2};
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
}
}
pos++;
}
}
/*==========================================
* ƒXƒLƒ?ŒWƒtƒ@ƒCƒ?‚Ý?‚Ý
* skill_db.txt ƒXƒLƒƒf?ƒ^
* skill_cast_db.txt ƒXƒLƒÌ‰r<E280B0>¥ŽžŠÔƃfƒBƒŒƒCƒf?ƒ^
* produce_db.txt ƒAƒCƒeƒ€<C692>ì<EFBFBD>¬ƒXƒLƒ—pƒf?ƒ^
* create_arrow_db.txt î<E28093>ì<EFBFBD>¬ƒ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];
if(line[0]=='/' && line[1]=='/')
continue;
j = skill_split_str(line,split,14);
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); */
skill_split_atoi(split[1],skill_db[i].range);
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]);
skill_split_atoi(split[7],skill_db[i].num);
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;
skill_split_atoi(split[13],skill_db[i].blewcount);
}
fclose(fp);
sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_db.txt");
ShowStatus(tmp_output);
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[50];
if(line[0]=='/' && line[1]=='/')
continue;
j = skill_split_str(line,split,30);
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;
skill_split_atoi(split[1],skill_db[i].hp);
skill_split_atoi(split[2],skill_db[i].mhp);
skill_split_atoi(split[3],skill_db[i].sp);
skill_split_atoi(split[4],skill_db[i].hp_rate);
skill_split_atoi(split[5],skill_db[i].sp_rate);
skill_split_atoi(split[6],skill_db[i].zeny);
p = split[7];
for(j=0;j<32;j++){
l = atoi(p);
if (l==99) {
skill_db[i].weapon = 0xffffffff;
break;
}
else
skill_db[i].weapon |= 1<<l;
p=strchr(p,':');
if(!p)
break;
p++;
}
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;
skill_split_atoi(split[9],skill_db[i].spiritball);
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);
sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_require_db.txt");
ShowStatus(tmp_output);
/* ƒ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];
memset(split,0,sizeof(split)); // [Valaris] thanks to fov
if(line[0]=='/' && line[1]=='/')
continue;
j = skill_split_str(line,split,5);
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;
skill_split_atoi(split[1],skill_db[i].cast);
skill_split_atoi(split[2],skill_db[i].delay);
skill_split_atoi(split[3],skill_db[i].upkeep_time);
skill_split_atoi(split[4],skill_db[i].upkeep_time2);
}
fclose(fp);
sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_cast_db.txt");
ShowStatus(tmp_output);
/* ƒXƒLƒƒ†ƒjƒbƒgƒf<C692>[ƒ^ƒx<C692>[ƒX */
fp = fopen("db/skill_unit_db.txt","r");
if (fp==NULL) {
printf("can't read db/skill_unit_db.txt\n");
return 1;
}
while (fgets(line,1020,fp)) {
char *split[50];
if (line[0]=='/' && line[1]=='/')
continue;
j = skill_split_str(line,split,8);
if (split[7]==NULL || j<8)
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;
skill_db[i].unit_id[0] = strtol(split[1],NULL,16);
skill_db[i].unit_id[1] = strtol(split[2],NULL,16);
skill_split_atoi(split[3],skill_db[i].unit_layout_type);
skill_db[i].unit_range = atoi(split[4]);
skill_db[i].unit_interval = atoi(split[5]);
if( strcmpi(split[6],"noenemy")==0 ) skill_db[i].unit_target=BCT_NOENEMY;
else if( strcmpi(split[6],"friend")==0 ) skill_db[i].unit_target=BCT_NOENEMY;
else if( strcmpi(split[6],"party")==0 ) skill_db[i].unit_target=BCT_PARTY;
else if( strcmpi(split[6],"all")==0 ) skill_db[i].unit_target=BCT_ALL;
else if( strcmpi(split[6],"enemy")==0 ) skill_db[i].unit_target=BCT_ENEMY;
else if( strcmpi(split[6],"self")==0 ) skill_db[i].unit_target=BCT_SELF;
else skill_db[i].unit_target = strtol(split[6],NULL,16);
skill_db[i].unit_flag = strtol(split[7],NULL,16);
k++;
}
fclose(fp);
sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_unit_db.txt");
ShowStatus(tmp_output);
skill_init_unit_layout();
/* <20>»¢Œ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));
j = skill_split_str(line,split,(3 + MAX_PRODUCE_RESOURCE * 2));
if(split[0]==0) //fixed by Lupus
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);
sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,filename[m]);
ShowStatus(tmp_output);
}
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));
j = skill_split_str(line,split,13);
if(split[0]==0) //fixed by Lupus
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);
sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,"db/create_arrow_db.txt");
ShowStatus(tmp_output);
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));
j = skill_split_str(line,split,13);
if(split[0]==0) //fixed by Lupus
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);
sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,"db/abra_db.txt");
ShowStatus(tmp_output);
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];
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
j = skill_split_str(line,split,3);
if(split[0]==0) //fixed by Lupus
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;
skill_split_atoi(split[1],skill_db[i].castnodex);
if (!split[2])
continue;
skill_split_atoi(split[2],skill_db[i].delaynodex);
}
fclose(fp);
sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_castnodex_db.txt");
ShowStatus(tmp_output);
fp=fopen("db/skill_nocast_db.txt","r");
if(fp==NULL){
printf("can't read db/skill_nocast_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));
j = skill_split_str(line,split,2);
if(split[0]==0) //fixed by Lupus
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;
skill_db[i].nocast=atoi(split[1]);
k++;
}
fclose(fp);
sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_nocast_db");
ShowStatus(tmp_output);
return 0;
}
/*===============================================
* For reading leveluseskillspamount.txt [Celest]
*-----------------------------------------------
*/
static int skill_read_skillspamount(void)
{
char *buf,*p;
struct skill_db *skill = NULL;
int s, idx, new_flag=1, level=1, sp=0;
buf=grfio_reads("data\\leveluseskillspamount.txt",&s);
if(buf==NULL)
return -1;
buf[s]=0;
for(p=buf;p-buf<s;){
char buf2[64];
if (sscanf(p,"%[@]",buf2) == 1) {
level = 1;
new_flag = 1;
} else if (new_flag && sscanf(p,"%[^#]#",buf2) == 1) {
for (idx=0; skill_names[idx].id != 0; idx++) {
if (strstr(buf2, skill_names[idx].name) != NULL) {
skill = &skill_db[ skill_names[idx].id ];
new_flag = 0;
break;
}
}
} else if (!new_flag && sscanf(p,"%d#",&sp) == 1) {
skill->sp[level-1]=sp;
level++;
}
p=strchr(p,10);
if(!p) break;
p++;
}
aFree(buf);
sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\leveluseskillspamount.txt");
ShowStatus(tmp_output);
return 0;
}
void skill_reload(void)
{
/*
<empty skill database>
<?>
*/
do_init_skill();
}
/*==========================================
* ƒXƒLƒ?ŒW<C592>‰Šú‰»?—<>
*------------------------------------------
*/
int do_init_skill(void)
{
skill_readdb();
if (battle_config.skill_sp_override_grffile)
skill_read_skillspamount();
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_interval(gettick()+SKILLUNITTIMER_INVERVAL,skill_unit_timer,0,0,SKILLUNITTIMER_INVERVAL);
return 0;
}