diff options
Diffstat (limited to 'src/map/skill.c')
-rw-r--r-- | src/map/skill.c | 20497 |
1 files changed, 11255 insertions, 9242 deletions
diff --git a/src/map/skill.c b/src/map/skill.c index 5f0092a..5745374 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -32,1279 +32,1606 @@ #define STATE_BLIND 0x10 /* スキル番号=>ステータス異常番号変換テーブル */ -int SkillStatusChangeTable[]={ /* skill.hのenumのSC_***とあわせること */ +int SkillStatusChangeTable[] = { /* skill.hのenumのSC_***とあわせること */ /* 0- */ - -1,-1,-1,-1,-1,-1, - SC_PROVOKE, /* プロボック */ - -1, 1,-1, + -1, -1, -1, -1, -1, -1, + SC_PROVOKE, /* プロボック */ + -1, 1, -1, /* 10- */ - SC_SIGHT, /* サイト */ - -1,-1,-1,-1, - SC_FREEZE, /* フロストダイバー */ - SC_STONE, /* ストーンカース */ - -1,-1,-1, + SC_SIGHT, /* サイト */ + -1, -1, -1, -1, + SC_FREEZE, /* フロストダイバー */ + SC_STONE, /* ストーンカース */ + -1, -1, -1, /* 20- */ - -1,-1,-1,-1, - SC_RUWACH, /* ルアフ */ - -1,-1,-1,-1, - SC_INCREASEAGI, /* 速度増加 */ + -1, -1, -1, -1, + SC_RUWACH, /* ルアフ */ + -1, -1, -1, -1, + SC_INCREASEAGI, /* 速度増加 */ /* 30- */ - SC_DECREASEAGI, /* 速度減少 */ - -1, - SC_SIGNUMCRUCIS, /* シグナムクルシス */ - SC_ANGELUS, /* エンジェラス */ - SC_BLESSING, /* ブレッシング */ - -1,-1,-1,-1,-1, + SC_DECREASEAGI, /* 速度減少 */ + -1, + SC_SIGNUMCRUCIS, /* シグナムクルシス */ + SC_ANGELUS, /* エンジェラス */ + SC_BLESSING, /* ブレッシング */ + -1, -1, -1, -1, -1, /* 40- */ - -1,-1,-1,-1,-1, - SC_CONCENTRATE, /* 集中力向上 */ - -1,-1,-1,-1, + -1, -1, -1, -1, -1, + SC_CONCENTRATE, /* 集中力向上 */ + -1, -1, -1, -1, /* 50- */ - -1, - SC_HIDING, /* ハイディング */ - -1,-1,-1,-1,-1,-1,-1,-1, + -1, + SC_HIDING, /* ハイディング */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 60- */ - SC_TWOHANDQUICKEN, /* 2HQ */ - SC_AUTOCOUNTER, - -1,-1,-1,-1, - SC_IMPOSITIO, /* インポシティオマヌス */ - SC_SUFFRAGIUM, /* サフラギウム */ - SC_ASPERSIO, /* アスペルシオ */ - SC_BENEDICTIO, /* 聖体降福 */ + SC_TWOHANDQUICKEN, /* 2HQ */ + SC_AUTOCOUNTER, + -1, -1, -1, -1, + SC_IMPOSITIO, /* インポシティオマヌス */ + SC_SUFFRAGIUM, /* サフラギウム */ + SC_ASPERSIO, /* アスペルシオ */ + SC_BENEDICTIO, /* 聖体降福 */ /* 70- */ - -1, - SC_SLOWPOISON, - -1, - SC_KYRIE, /* キリエエレイソン */ - SC_MAGNIFICAT, /* マグニフィカート */ - SC_GLORIA, /* グロリア */ - SC_DIVINA, /* レックスディビーナ */ - -1, - SC_AETERNA, /* レックスエーテルナ */ - -1, + -1, + SC_SLOWPOISON, + -1, + SC_KYRIE, /* キリエエレイソン */ + SC_MAGNIFICAT, /* マグニフィカート */ + SC_GLORIA, /* グロリア */ + SC_DIVINA, /* レックスディビーナ */ + -1, + SC_AETERNA, /* レックスエーテルナ */ + -1, /* 80- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90- */ - -1,-1, - SC_QUAGMIRE, /* クァグマイア */ - -1,-1,-1,-1,-1,-1,-1, + -1, -1, + SC_QUAGMIRE, /* クァグマイア */ + -1, -1, -1, -1, -1, -1, -1, /* 100- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 110- */ - -1, - SC_ADRENALINE, /* アドレナリンラッシュ */ - SC_WEAPONPERFECTION,/* ウェポンパーフェクション */ - SC_OVERTHRUST, /* オーバートラスト */ - SC_MAXIMIZEPOWER, /* マキシマイズパワー */ - -1,-1,-1,-1,-1, + -1, + SC_ADRENALINE, /* アドレナリンラッシュ */ + SC_WEAPONPERFECTION, /* ウェポンパーフェクション */ + SC_OVERTHRUST, /* オーバートラスト */ + SC_MAXIMIZEPOWER, /* マキシマイズパワー */ + -1, -1, -1, -1, -1, /* 120- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 130- */ - -1,-1,-1,-1,-1, - SC_CLOAKING, /* クローキング */ - SC_STAN, /* ソニックブロー */ - -1, - SC_ENCPOISON, /* エンチャントポイズン */ - SC_POISONREACT, /* ポイズンリアクト */ + -1, -1, -1, -1, -1, + SC_CLOAKING, /* クローキング */ + SC_STAN, /* ソニックブロー */ + -1, + SC_ENCPOISON, /* エンチャントポイズン */ + SC_POISONREACT, /* ポイズンリアクト */ /* 140- */ - SC_POISON, /* ベノムダスト */ - SC_SPLASHER, /* ベナムスプラッシャー */ - -1, - SC_TRICKDEAD, /* 死んだふり */ - -1,-1,-1,-1,-1,-1, + SC_POISON, /* ベノムダスト */ + SC_SPLASHER, /* ベナムスプラッシャー */ + -1, + SC_TRICKDEAD, /* 死んだふり */ + -1, -1, -1, -1, -1, -1, /* 150- */ - -1,-1,-1,-1,-1, - SC_LOUD, /* ラウドボイス */ - -1, - SC_ENERGYCOAT, /* エナジーコート */ - -1,-1, + -1, -1, -1, -1, -1, + SC_LOUD, /* ラウドボイス */ + -1, + SC_ENERGYCOAT, /* エナジーコート */ + -1, -1, /* 160- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1, - SC_SELFDESTRUCTION, - -1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1, - SC_KEEPING, - -1,-1, - SC_BARRIER, - -1,-1, - SC_HALLUCINATION, - -1,-1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, + SC_SELFDESTRUCTION, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, + SC_KEEPING, + -1, -1, + SC_BARRIER, + -1, -1, + SC_HALLUCINATION, + -1, -1, /* 210- */ - -1,-1,-1,-1,-1, - SC_STRIPWEAPON, - SC_STRIPSHIELD, - SC_STRIPARMOR, - SC_STRIPHELM, - -1, + -1, -1, -1, -1, -1, + SC_STRIPWEAPON, + SC_STRIPSHIELD, + SC_STRIPARMOR, + SC_STRIPHELM, + -1, /* 220- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 230- */ - -1,-1,-1,-1, - SC_CP_WEAPON, - SC_CP_SHIELD, - SC_CP_ARMOR, - SC_CP_HELM, - -1,-1, + -1, -1, -1, -1, + SC_CP_WEAPON, + SC_CP_SHIELD, + SC_CP_ARMOR, + SC_CP_HELM, + -1, -1, /* 240- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1, - SC_AUTOGUARD, + -1, -1, -1, -1, -1, -1, -1, -1, -1, + SC_AUTOGUARD, /* 250- */ - -1,-1, - SC_REFLECTSHIELD, - -1,-1, - SC_DEVOTION, - SC_PROVIDENCE, - SC_DEFENDER, - SC_SPEARSQUICKEN, - -1, + -1, -1, + SC_REFLECTSHIELD, + -1, -1, + SC_DEVOTION, + SC_PROVIDENCE, + SC_DEFENDER, + SC_SPEARSQUICKEN, + -1, /* 260- */ - -1,-1,-1,-1,-1,-1,-1,-1, - SC_STEELBODY, - SC_BLADESTOP_WAIT, + -1, -1, -1, -1, -1, -1, -1, -1, + SC_STEELBODY, + SC_BLADESTOP_WAIT, /* 270- */ - SC_EXPLOSIONSPIRITS, - SC_EXTREMITYFIST, - -1,-1,-1,-1, - SC_MAGICROD, - -1,-1,-1, + SC_EXPLOSIONSPIRITS, + SC_EXTREMITYFIST, + -1, -1, -1, -1, + SC_MAGICROD, + -1, -1, -1, /* 280- */ - SC_FLAMELAUNCHER, - SC_FROSTWEAPON, - SC_LIGHTNINGLOADER, - SC_SEISMICWEAPON, - -1, - SC_VOLCANO, - SC_DELUGE, - SC_VIOLENTGALE, - SC_LANDPROTECTOR, - -1, + SC_FLAMELAUNCHER, + SC_FROSTWEAPON, + SC_LIGHTNINGLOADER, + SC_SEISMICWEAPON, + -1, + SC_VOLCANO, + SC_DELUGE, + SC_VIOLENTGALE, + SC_LANDPROTECTOR, + -1, /* 290- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 300- */ - -1,-1,-1,-1,-1,-1, - SC_LULLABY, - SC_RICHMANKIM, - SC_ETERNALCHAOS, - SC_DRUMBATTLE, + -1, -1, -1, -1, -1, -1, + SC_LULLABY, + SC_RICHMANKIM, + SC_ETERNALCHAOS, + SC_DRUMBATTLE, /* 310- */ - SC_NIBELUNGEN, - SC_ROKISWEIL, - SC_INTOABYSS, - SC_SIEGFRIED, - -1,-1,-1, - SC_DISSONANCE, - -1, - SC_WHISTLE, + SC_NIBELUNGEN, + SC_ROKISWEIL, + SC_INTOABYSS, + SC_SIEGFRIED, + -1, -1, -1, + SC_DISSONANCE, + -1, + SC_WHISTLE, /* 320- */ - SC_ASSNCROS, - SC_POEMBRAGI, - SC_APPLEIDUN, - -1,-1, - SC_UGLYDANCE, - -1, - SC_HUMMING, - SC_DONTFORGETME, - SC_FORTUNE, + SC_ASSNCROS, + SC_POEMBRAGI, + SC_APPLEIDUN, + -1, -1, + SC_UGLYDANCE, + -1, + SC_HUMMING, + SC_DONTFORGETME, + SC_FORTUNE, /* 330- */ - SC_SERVICE4U, - SC_SELFDESTRUCTION, - -1,-1,-1,-1,-1,-1,-1,-1, + SC_SERVICE4U, + SC_SELFDESTRUCTION, + -1, -1, -1, -1, -1, -1, -1, -1, /* 340- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 350- */ - -1,-1,-1,-1,-1, - SC_AURABLADE, - SC_PARRYING, - SC_CONCENTRATION, - SC_TENSIONRELAX, - SC_BERSERK, + -1, -1, -1, -1, -1, + SC_AURABLADE, + SC_PARRYING, + SC_CONCENTRATION, + SC_TENSIONRELAX, + SC_BERSERK, /* 360- */ - SC_BERSERK, - SC_ASSUMPTIO, - SC_BASILICA, - -1,-1,-1, - SC_MAGICPOWER, - -1,-1, - SC_GOSPEL, + SC_BERSERK, + SC_ASSUMPTIO, + SC_BASILICA, + -1, -1, -1, + SC_MAGICPOWER, + -1, -1, + SC_GOSPEL, /* 370- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 380- */ - SC_TRUESIGHT, - -1,-1, - SC_WINDWALK, - SC_MELTDOWN, - -1,-1, - SC_CARTBOOST, - -1, - SC_CHASEWALK, + SC_TRUESIGHT, + -1, -1, + SC_WINDWALK, + SC_MELTDOWN, + -1, -1, + SC_CARTBOOST, + -1, + SC_CHASEWALK, /* 390- */ - SC_REJECTSWORD, - -1,-1,-1,-1,-1, - SC_MARIONETTE, - -1, - SC_HEADCRUSH, - SC_JOINTBEAT, + SC_REJECTSWORD, + -1, -1, -1, -1, -1, + SC_MARIONETTE, + -1, + SC_HEADCRUSH, + SC_JOINTBEAT, /* 400 */ - -1,-1, - SC_MINDBREAKER, - SC_MEMORIZE, - SC_FOGWALL, - SC_SPIDERWEB, - -1,-1,-1,-1, + -1, -1, + SC_MINDBREAKER, + SC_MEMORIZE, + SC_FOGWALL, + SC_SPIDERWEB, + -1, -1, -1, -1, /* 410- */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; 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_AUTOGUARD, "AUTOGUARD", "Guard" } , - { CR_DEFENDER, "DEFENDER", "Defender" } , - { CR_DEVOTION, "DEVOTION", "Sacrifice" } , - { CR_GRANDCROSS, "GRANDCROSS", "Grand_Cross" } , - { CR_HOLYCROSS, "HOLYCROSS", "Holy_Cross" } , - { CR_PROVIDENCE, "PROVIDENCE", "Providence" } , - { CR_REFLECTSHIELD, "REFLECTSHIELD", "Shield_Reflect" } , - { CR_SHIELDBOOMERANG, "SHIELDBOOMERANG", "Shield_Boomerang" } , - { CR_SHIELDCHARGE, "SHIELDCHARGE", "Shield_Charge" } , - { CR_SPEARQUICKEN, "SPEARQUICKEN", "Spear_Quicken" } , - { CR_SYNTHESISPOTION, "SYNTHESISPOTION", "Potion_Synthesis" } , - { CR_TRUST, "TRUST", "Faith" } , - { DC_DANCINGLESSON, "DANCINGLESSON", "Dancing_Lesson" } , - { DC_DONTFORGETME, "DONTFORGETME", "Don't_Forget_Me" } , - { DC_FORTUNEKISS, "FORTUNEKISS", "Fortune_Kiss" } , - { DC_HUMMING, "HUMMING", "Humming" } , - { DC_SCREAM, "SCREAM", "Scream" } , - { DC_SERVICEFORYOU, "SERVICEFORYOU", "Prostitute" } , - { DC_THROWARROW, "THROWARROW", "Throw_Arrow" } , - { DC_UGLYDANCE, "UGLYDANCE", "Ugly_Dance" } , - { HP_ASSUMPTIO, "ASSUMPTIO", "Assumptio" } , - { HP_BASILICA, "BASILICA", "Basilica" } , - { HP_MEDITATIO, "MEDITATIO", "Meditation" } , - { HT_ANKLESNARE, "ANKLESNARE", "Ankle_Snare" } , - { HT_BEASTBANE, "BEASTBANE", "Beast_Bane" } , - { HT_BLASTMINE, "BLASTMINE", "Blast_Mine" } , - { HT_BLITZBEAT, "BLITZBEAT", "Blitz_Beat" } , - { HT_CLAYMORETRAP, "CLAYMORETRAP", "Claymore_Trap" } , - { HT_DETECTING, "DETECTING", "Detect" } , - { HT_FALCON, "FALCON", "Falconry_Mastery" } , - { HT_FLASHER, "FLASHER", "Flasher" } , - { HT_FREEZINGTRAP, "FREEZINGTRAP", "Freezing_Trap" } , - { HT_LANDMINE, "LANDMINE", "Land_Mine" } , - { HT_REMOVETRAP, "REMOVETRAP", "Remove_Trap" } , - { HT_SANDMAN, "SANDMAN", "Sandman" } , - { HT_SHOCKWAVE, "SHOCKWAVE", "Shockwave_Trap" } , - { HT_SKIDTRAP, "SKIDTRAP", "Skid_Trap" } , - { HT_SPRINGTRAP, "SPRINGTRAP", "Spring_Trap" } , - { HT_STEELCROW, "STEELCROW", "Steel_Crow" } , - { HT_TALKIEBOX, "TALKIEBOX", "Talkie_Box" } , - { HW_MAGICCRASHER, "MAGICCRASHER", "Magic_Crasher" } , - { HW_MAGICPOWER, "MAGICPOWER", "Magic_Power" } , - { HW_NAPALMVULCAN, "NAPALMVULCAN", "Napalm_Vulcan" } , - { HW_SOULDRAIN, "SOULDRAIN", "Soul_Drain" } , - { 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" } , - { 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_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_EMOTE, "EMOTE", "Emote_Skill" } , - { NV_TRADE, "TRADE", "Trade_Skill" } , - { NV_PARTY, "PARTY", "Party_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_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" } , - { 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" } , - { 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 } + {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_AUTOGUARD, "AUTOGUARD", "Guard"}, + {CR_DEFENDER, "DEFENDER", "Defender"}, + {CR_DEVOTION, "DEVOTION", "Sacrifice"}, + {CR_GRANDCROSS, "GRANDCROSS", "Grand_Cross"}, + {CR_HOLYCROSS, "HOLYCROSS", "Holy_Cross"}, + {CR_PROVIDENCE, "PROVIDENCE", "Providence"}, + {CR_REFLECTSHIELD, "REFLECTSHIELD", "Shield_Reflect"}, + {CR_SHIELDBOOMERANG, "SHIELDBOOMERANG", "Shield_Boomerang"}, + {CR_SHIELDCHARGE, "SHIELDCHARGE", "Shield_Charge"}, + {CR_SPEARQUICKEN, "SPEARQUICKEN", "Spear_Quicken"}, + {CR_SYNTHESISPOTION, "SYNTHESISPOTION", "Potion_Synthesis"}, + {CR_TRUST, "TRUST", "Faith"}, + {DC_DANCINGLESSON, "DANCINGLESSON", "Dancing_Lesson"}, + {DC_DONTFORGETME, "DONTFORGETME", "Don't_Forget_Me"}, + {DC_FORTUNEKISS, "FORTUNEKISS", "Fortune_Kiss"}, + {DC_HUMMING, "HUMMING", "Humming"}, + {DC_SCREAM, "SCREAM", "Scream"}, + {DC_SERVICEFORYOU, "SERVICEFORYOU", "Prostitute"}, + {DC_THROWARROW, "THROWARROW", "Throw_Arrow"}, + {DC_UGLYDANCE, "UGLYDANCE", "Ugly_Dance"}, + {HP_ASSUMPTIO, "ASSUMPTIO", "Assumptio"}, + {HP_BASILICA, "BASILICA", "Basilica"}, + {HP_MEDITATIO, "MEDITATIO", "Meditation"}, + {HT_ANKLESNARE, "ANKLESNARE", "Ankle_Snare"}, + {HT_BEASTBANE, "BEASTBANE", "Beast_Bane"}, + {HT_BLASTMINE, "BLASTMINE", "Blast_Mine"}, + {HT_BLITZBEAT, "BLITZBEAT", "Blitz_Beat"}, + {HT_CLAYMORETRAP, "CLAYMORETRAP", "Claymore_Trap"}, + {HT_DETECTING, "DETECTING", "Detect"}, + {HT_FALCON, "FALCON", "Falconry_Mastery"}, + {HT_FLASHER, "FLASHER", "Flasher"}, + {HT_FREEZINGTRAP, "FREEZINGTRAP", "Freezing_Trap"}, + {HT_LANDMINE, "LANDMINE", "Land_Mine"}, + {HT_REMOVETRAP, "REMOVETRAP", "Remove_Trap"}, + {HT_SANDMAN, "SANDMAN", "Sandman"}, + {HT_SHOCKWAVE, "SHOCKWAVE", "Shockwave_Trap"}, + {HT_SKIDTRAP, "SKIDTRAP", "Skid_Trap"}, + {HT_SPRINGTRAP, "SPRINGTRAP", "Spring_Trap"}, + {HT_STEELCROW, "STEELCROW", "Steel_Crow"}, + {HT_TALKIEBOX, "TALKIEBOX", "Talkie_Box"}, + {HW_MAGICCRASHER, "MAGICCRASHER", "Magic_Crasher"}, + {HW_MAGICPOWER, "MAGICPOWER", "Magic_Power"}, + {HW_NAPALMVULCAN, "NAPALMVULCAN", "Napalm_Vulcan"}, + {HW_SOULDRAIN, "SOULDRAIN", "Soul_Drain"}, + {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"}, + {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_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_EMOTE, "EMOTE", "Emote_Skill"}, + {NV_TRADE, "TRADE", "Trade_Skill"}, + {NV_PARTY, "PARTY", "Party_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_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"}, + {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"}, + {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 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; /* スキルデータベース */ struct skill_db skill_db[MAX_SKILL_DB]; -#define UNARMED_PLAYER_DAMAGE_MIN(bl) (skill_power_bl((bl), TMW_BRAWLING) >> 4) // +50 for 200 -#define UNARMED_PLAYER_DAMAGE_MAX(bl) (skill_power_bl((bl), TMW_BRAWLING)) // +200 for 200 - - -int skill_get_hit( int id ){ return skill_db[id].hit; } -int skill_get_inf( int id ){ return skill_db[id].inf; } -int skill_get_pl( int id ){ return skill_db[id].pl; } -int skill_get_nk( int id ){ return skill_db[id].nk; } -int skill_get_max( int id ){ return skill_db[id].max; } -int skill_get_max_raise( int id ){ return skill_db[id].max_raise; } -int skill_get_range( int id , int lv ){ return (lv <= 0) ? 0:skill_db[id].range[lv-1]; } -int skill_get_hp( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].hp[lv-1]; } -int skill_get_sp( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].sp[lv-1]; } -int skill_get_zeny( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].zeny[lv-1]; } -int skill_get_num( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].num[lv-1]; } -int skill_get_cast( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].cast[lv-1]; } -int skill_get_delay( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].delay[lv-1]; } -int skill_get_time( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].upkeep_time[lv-1]; } -int skill_get_time2( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].upkeep_time2[lv-1]; } -int skill_get_castdef( int id ){ return skill_db[id].cast_def_rate; } -int skill_get_weapontype( int id ){ return skill_db[id].weapon; } -int skill_get_inf2( int id ){ return skill_db[id].inf2; } -int skill_get_maxcount( int id ){ return skill_db[id].maxcount; } -int skill_get_blewcount( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].blewcount[lv-1]; } -int skill_get_mhp( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].mhp[lv-1]; } -int skill_get_castnodex( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].castnodex[lv-1]; } +#define UNARMED_PLAYER_DAMAGE_MIN(bl) (skill_power_bl((bl), TMW_BRAWLING) >> 4) // +50 for 200 +#define UNARMED_PLAYER_DAMAGE_MAX(bl) (skill_power_bl((bl), TMW_BRAWLING)) // +200 for 200 + +int skill_get_hit (int id) +{ + return skill_db[id].hit; +} + +int skill_get_inf (int id) +{ + return skill_db[id].inf; +} + +int skill_get_pl (int id) +{ + return skill_db[id].pl; +} + +int skill_get_nk (int id) +{ + return skill_db[id].nk; +} + +int skill_get_max (int id) +{ + return skill_db[id].max; +} + +int skill_get_max_raise (int id) +{ + return skill_db[id].max_raise; +} + +int skill_get_range (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].range[lv - 1]; +} + +int skill_get_hp (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].hp[lv - 1]; +} + +int skill_get_sp (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].sp[lv - 1]; +} + +int skill_get_zeny (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].zeny[lv - 1]; +} + +int skill_get_num (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].num[lv - 1]; +} + +int skill_get_cast (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].cast[lv - 1]; +} + +int skill_get_delay (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].delay[lv - 1]; +} + +int skill_get_time (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].upkeep_time[lv - 1]; +} + +int skill_get_time2 (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].upkeep_time2[lv - 1]; +} + +int skill_get_castdef (int id) +{ + return skill_db[id].cast_def_rate; +} + +int skill_get_weapontype (int id) +{ + return skill_db[id].weapon; +} + +int skill_get_inf2 (int id) +{ + return skill_db[id].inf2; +} + +int skill_get_maxcount (int id) +{ + return skill_db[id].maxcount; +} + +int skill_get_blewcount (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].blewcount[lv - 1]; +} + +int skill_get_mhp (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].mhp[lv - 1]; +} + +int skill_get_castnodex (int id, int lv) +{ + return (lv <= 0) ? 0 : skill_db[id].castnodex[lv - 1]; +} /* プロトタイプ */ -struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag); -int skill_check_condition( struct map_session_data *sd,int type); -int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag ); -int skill_frostjoke_scream(struct block_list *bl,va_list ap); -int skill_status_change_timer_sub(struct block_list *bl, va_list ap ); -int skill_attack_area(struct block_list *bl,va_list ap); -int skill_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 *skill_unitsetting (struct block_list *src, + int skillid, int skilllv, int x, + int y, int flag); +int skill_check_condition (struct map_session_data *sd, int type); +int skill_castend_damage_id (struct block_list *src, struct block_list *bl, + int skillid, int skilllv, unsigned int tick, + int flag); +int skill_frostjoke_scream (struct block_list *bl, va_list ap); +int skill_status_change_timer_sub (struct block_list *bl, va_list ap); +int skill_attack_area (struct block_list *bl, va_list ap); +int skill_clear_element_field (struct block_list *bl); +int skill_landprotector (struct block_list *bl, va_list ap); +int skill_trap_splash (struct block_list *bl, va_list ap); +int skill_count_target (struct block_list *bl, va_list ap); // [MouseJstr] - skill ok to cast? and when? -static int skillnotok(int skillid, struct map_session_data *sd) { - if (sd == 0) - return 0; - if (pc_isGM(sd) >= 20) - return 0; // gm's can do anything damn thing they want - switch (skillid) { - case AL_WARP: - case AL_TELEPORT: - case MC_IDENTIFY: - return 0; // always allowed - default: - return(map[sd->bl.m].flag.noskill); - } +static int skillnotok (int skillid, struct map_session_data *sd) +{ + if (sd == 0) + return 0; + if (pc_isGM (sd) >= 20) + return 0; // gm's can do anything damn thing they want + switch (skillid) + { + case AL_WARP: + case AL_TELEPORT: + case MC_IDENTIFY: + return 0; // always allowed + default: + return (map[sd->bl.m].flag.noskill); + } } - -static int distance(int x0,int y0,int x1,int y1) +static int distance (int x0, int y0, int x1, int y1) { - int dx,dy; + int dx, dy; - dx=abs(x0-x1); - dy=abs(y0-y1); - return dx>dy ? dx : dy; + dx = abs (x0 - x1); + dy = abs (y0 - y1); + return dx > dy ? dx : dy; } /* スキルユニットIDを返す(これもデータベースに入れたいな) */ -int skill_get_unit_id(int id,int flag) +int skill_get_unit_id (int id, int flag) { - switch(id){ - case MG_SAFETYWALL: return 0x7e; /* セイフティウォール */ - case MG_FIREWALL: return 0x7f; /* ファイアーウォール */ - case AL_WARP: return (flag==0)?0x81:0x80; /* ワープポータル */ - case PR_BENEDICTIO: return 0x82; /* 聖体降福 */ - case PR_SANCTUARY: return 0x83; /* サンクチュアリ */ - case PR_MAGNUS: return 0x84; /* マグヌスエクソシズム */ - case AL_PNEUMA: return 0x85; /* ニューマ */ - case MG_THUNDERSTORM: return 0x86; /* サンダーストーム */ - case WZ_HEAVENDRIVE: return 0x86; /* ヘヴンズドライブ */ - case WZ_SIGHTRASHER: return 0x86; /* サイトラッシャー */ - case WZ_METEOR: return 0x86; /* メテオストーム */ - case WZ_VERMILION: return 0x86; /* ロードオブヴァーミリオン */ - case WZ_FROSTNOVA: return 0x86; /* フロストノヴァ */ - case WZ_STORMGUST: return 0x86; /* ストームガスト(とりあえずLoVと同じで処理) */ - case CR_GRANDCROSS: return 0x86; /* グランドクロス */ - case WZ_FIREPILLAR: return (flag==0)?0x87:0x88; /* ファイアーピラー */ - case HT_TALKIEBOX: return 0x99; /* トーキーボックス */ - case WZ_ICEWALL: return 0x8d; /* アイスウォール */ - case WZ_QUAGMIRE: return 0x8e; /* クァグマイア */ - case HT_BLASTMINE: return 0x8f; /* ブラストマイン */ - case HT_SKIDTRAP: return 0x90; /* スキッドトラップ */ - case HT_ANKLESNARE: return 0x91; /* アンクルスネア */ - case AS_VENOMDUST: return 0x92; /* ベノムダスト */ - case HT_LANDMINE: return 0x93; /* ランドマイン */ - case HT_SHOCKWAVE: return 0x94; /* ショックウェーブトラップ */ - case HT_SANDMAN: return 0x95; /* サンドマン */ - case HT_FLASHER: return 0x96; /* フラッシャー */ - case HT_FREEZINGTRAP: return 0x97; /* フリージングトラップ */ - case HT_CLAYMORETRAP: return 0x98; /* クレイモアートラップ */ - case SA_VOLCANO: return 0x9a; /* ボルケーノ */ - case SA_DELUGE: return 0x9b; /* デリュージ */ - case SA_VIOLENTGALE: return 0x9c; /* バイオレントゲイル */ - case SA_LANDPROTECTOR: return 0x9d; /* ランドプロテクター */ - case BD_LULLABY: return 0x9e; /* 子守歌 */ - case BD_RICHMANKIM: return 0x9f; /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: return 0xa0; /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD:return 0xa1; /* 戦太鼓の響き */ - case BD_RINGNIBELUNGEN: return 0xa2; /* ニーベルングの指輪 */ - case BD_ROKISWEIL: return 0xa3; /* ロキの叫び */ - case BD_INTOABYSS: return 0xa4; /* 深淵の中に */ - case BD_SIEGFRIED: return 0xa5; /* 不死身のジークフリード */ - case BA_DISSONANCE: return 0xa6; /* 不協和音 */ - case BA_WHISTLE: return 0xa7; /* 口笛 */ - case BA_ASSASSINCROSS: return 0xa8; /* 夕陽のアサシンクロス */ - case BA_POEMBRAGI: return 0xa9; /* ブラギの詩 */ - case BA_APPLEIDUN: return 0xaa; /* イドゥンの林檎 */ - case DC_UGLYDANCE: return 0xab; /* 自分勝手なダンス */ - case DC_HUMMING: return 0xac; /* ハミング */ - case DC_DONTFORGETME: return 0xad; /* 私を忘れないで… */ - case DC_FORTUNEKISS: return 0xae; /* 幸運のキス */ - case DC_SERVICEFORYOU: return 0xaf; /* サービスフォーユー */ - case RG_GRAFFITI: return 0xb0; /* グラフィティ */ - case AM_DEMONSTRATION: return 0xb1; /* デモンストレーション */ - case WE_CALLPARTNER: return 0xb2; /* あなたに逢いたい */ - case PA_GOSPEL: return 0xb3; /* ゴスペル */ - case HP_BASILICA: return 0xb4; /* バジリカ */ - case PF_FOGWALL: return 0xb6; /* フォグウォール */ - case PF_SPIDERWEB: return 0xb7; /* スパイダーウェッブ */ - } - return 0; - /* - 0x89,0x8a,0x8b 表示無し - 0x9a 炎属性の詠唱みたいなエフェクト - 0x9b 水属性の詠唱みたいなエフェクト - 0x9c 風属性の詠唱みたいなエフェクト - 0x9d 白い小さなエフェクト - 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 = - */ + switch (id) + { + case MG_SAFETYWALL: + return 0x7e; /* セイフティウォール */ + case MG_FIREWALL: + return 0x7f; /* ファイアーウォール */ + case AL_WARP: + return (flag == 0) ? 0x81 : 0x80; /* ワープポータル */ + case PR_BENEDICTIO: + return 0x82; /* 聖体降福 */ + case PR_SANCTUARY: + return 0x83; /* サンクチュアリ */ + case PR_MAGNUS: + return 0x84; /* マグヌスエクソシズム */ + case AL_PNEUMA: + return 0x85; /* ニューマ */ + case MG_THUNDERSTORM: + return 0x86; /* サンダーストーム */ + case WZ_HEAVENDRIVE: + return 0x86; /* ヘヴンズドライブ */ + case WZ_SIGHTRASHER: + return 0x86; /* サイトラッシャー */ + case WZ_METEOR: + return 0x86; /* メテオストーム */ + case WZ_VERMILION: + return 0x86; /* ロードオブヴァーミリオン */ + case WZ_FROSTNOVA: + return 0x86; /* フロストノヴァ */ + case WZ_STORMGUST: + return 0x86; /* ストームガスト(とりあえずLoVと同じで処理) */ + case CR_GRANDCROSS: + return 0x86; /* グランドクロス */ + case WZ_FIREPILLAR: + return (flag == 0) ? 0x87 : 0x88; /* ファイアーピラー */ + case HT_TALKIEBOX: + return 0x99; /* トーキーボックス */ + case WZ_ICEWALL: + return 0x8d; /* アイスウォール */ + case WZ_QUAGMIRE: + return 0x8e; /* クァグマイア */ + case HT_BLASTMINE: + return 0x8f; /* ブラストマイン */ + case HT_SKIDTRAP: + return 0x90; /* スキッドトラップ */ + case HT_ANKLESNARE: + return 0x91; /* アンクルスネア */ + case AS_VENOMDUST: + return 0x92; /* ベノムダスト */ + case HT_LANDMINE: + return 0x93; /* ランドマイン */ + case HT_SHOCKWAVE: + return 0x94; /* ショックウェーブトラップ */ + case HT_SANDMAN: + return 0x95; /* サンドマン */ + case HT_FLASHER: + return 0x96; /* フラッシャー */ + case HT_FREEZINGTRAP: + return 0x97; /* フリージングトラップ */ + case HT_CLAYMORETRAP: + return 0x98; /* クレイモアートラップ */ + case SA_VOLCANO: + return 0x9a; /* ボルケーノ */ + case SA_DELUGE: + return 0x9b; /* デリュージ */ + case SA_VIOLENTGALE: + return 0x9c; /* バイオレントゲイル */ + case SA_LANDPROTECTOR: + return 0x9d; /* ランドプロテクター */ + case BD_LULLABY: + return 0x9e; /* 子守歌 */ + case BD_RICHMANKIM: + return 0x9f; /* ニヨルドの宴 */ + case BD_ETERNALCHAOS: + return 0xa0; /* 永遠の混沌 */ + case BD_DRUMBATTLEFIELD: + return 0xa1; /* 戦太鼓の響き */ + case BD_RINGNIBELUNGEN: + return 0xa2; /* ニーベルングの指輪 */ + case BD_ROKISWEIL: + return 0xa3; /* ロキの叫び */ + case BD_INTOABYSS: + return 0xa4; /* 深淵の中に */ + case BD_SIEGFRIED: + return 0xa5; /* 不死身のジークフリード */ + case BA_DISSONANCE: + return 0xa6; /* 不協和音 */ + case BA_WHISTLE: + return 0xa7; /* 口笛 */ + case BA_ASSASSINCROSS: + return 0xa8; /* 夕陽のアサシンクロス */ + case BA_POEMBRAGI: + return 0xa9; /* ブラギの詩 */ + case BA_APPLEIDUN: + return 0xaa; /* イドゥンの林檎 */ + case DC_UGLYDANCE: + return 0xab; /* 自分勝手なダンス */ + case DC_HUMMING: + return 0xac; /* ハミング */ + case DC_DONTFORGETME: + return 0xad; /* 私を忘れないで… */ + case DC_FORTUNEKISS: + return 0xae; /* 幸運のキス */ + case DC_SERVICEFORYOU: + return 0xaf; /* サービスフォーユー */ + case RG_GRAFFITI: + return 0xb0; /* グラフィティ */ + case AM_DEMONSTRATION: + return 0xb1; /* デモンストレーション */ + case WE_CALLPARTNER: + return 0xb2; /* あなたに逢いたい */ + case PA_GOSPEL: + return 0xb3; /* ゴスペル */ + case HP_BASILICA: + return 0xb4; /* バジリカ */ + case PF_FOGWALL: + return 0xb6; /* フォグウォール */ + case PF_SPIDERWEB: + return 0xb7; /* スパイダーウェッブ */ + } + return 0; + /* + * 0x89,0x8a,0x8b 表示無し + * 0x9a 炎属性の詠唱みたいなエフェクト + * 0x9b 水属性の詠唱みたいなエフェクト + * 0x9c 風属性の詠唱みたいなエフェクト + * 0x9d 白い小さなエフェクト + * 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 = + */ } /*========================================== * スキル追加効果 *------------------------------------------ */ -int skill_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick) +int skill_additional_effect (struct block_list *src, struct block_list *bl, + int skillid, int skilllv, int attack_type, + unsigned int tick) { - /* MOB追加効果スキル用 */ - 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; - - int skill,skill2; - int rate,luk; - - int sc_def_mdef,sc_def_vit,sc_def_int,sc_def_luk; - int sc_def_mdef2,sc_def_vit2,sc_def_int2,sc_def_luk2; - int sc_def_phys_shield_spell; - - nullpo_retr(0, src); - nullpo_retr(0, bl); - - if(skilllv < 0) return 0; - - 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); //未使用? - } + /* MOB追加効果スキル用 */ + 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; + + int skill, skill2; + int rate, luk; + + int sc_def_mdef, sc_def_vit, sc_def_int, sc_def_luk; + int sc_def_mdef2, sc_def_vit2, sc_def_int2, sc_def_luk2; + int sc_def_phys_shield_spell; + + nullpo_retr (0, src); + nullpo_retr (0, bl); + + if (skilllv < 0) + return 0; - sc_def_phys_shield_spell = 0; - if (battle_get_sc_data(bl)[SC_PHYS_SHIELD].timer != -1) - sc_def_phys_shield_spell = battle_get_sc_data(bl)[SC_PHYS_SHIELD].val1; - - //対象の耐性 - luk = battle_get_luk(bl); - sc_def_mdef=100 - (3 + battle_get_mdef(bl) + luk/3); - sc_def_vit=100 - (3 + battle_get_vit(bl) + luk/3); - sc_def_int=100 - (3 + battle_get_int(bl) + luk/3); - sc_def_luk=100 - (3 + luk); - //自分の耐性 - luk = battle_get_luk(src); - sc_def_mdef2=100 - (3 + battle_get_mdef(src) + luk/3); - sc_def_vit2=100 - (3 + battle_get_vit(src) + luk/3); - sc_def_int2=100 - (3 + battle_get_int(src) + luk/3); - sc_def_luk2=100 - (3 + luk); - if(bl->type==BL_PC) - dstsd=(struct map_session_data *)bl; - else if(bl->type==BL_MOB){ - dstmd=(struct mob_data *)bl; //未使用? - if(sc_def_mdef>50) - sc_def_mdef=50; - if(sc_def_vit>50) - sc_def_vit=50; - if(sc_def_int>50) - sc_def_int=50; - if(sc_def_luk>50) - sc_def_luk=50; - } - if(sc_def_mdef<0) - sc_def_mdef=0; - if(sc_def_vit<0) - sc_def_vit=0; - if(sc_def_int<0) - sc_def_int=0; - - switch(skillid){ - case 0: /* 通常攻撃 */ - /* 自動鷹 */ - if( sd && pc_isfalcon(sd) && sd->status.weapon == 11 && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 && - MRAND(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); - } - // スナッチャー - if(sd && sd->status.weapon != 11 && (skill=pc_checkskill(sd,RG_SNATCHER)) > 0) - if((skill*15 + 55) + (skill2 = pc_checkskill(sd,TF_STEAL))*10 > MRAND(1000)) { - if(pc_steal_item(sd,bl)) - clif_skill_nodamage(src,bl,TF_STEAL,skill2,1); - else - clif_skill_fail(sd,skillid,0,0); - } - break; + 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); //未使用? + } + + sc_def_phys_shield_spell = 0; + if (battle_get_sc_data (bl)[SC_PHYS_SHIELD].timer != -1) + sc_def_phys_shield_spell = + battle_get_sc_data (bl)[SC_PHYS_SHIELD].val1; + + //対象の耐性 + luk = battle_get_luk (bl); + sc_def_mdef = 100 - (3 + battle_get_mdef (bl) + luk / 3); + sc_def_vit = 100 - (3 + battle_get_vit (bl) + luk / 3); + sc_def_int = 100 - (3 + battle_get_int (bl) + luk / 3); + sc_def_luk = 100 - (3 + luk); + //自分の耐性 + luk = battle_get_luk (src); + sc_def_mdef2 = 100 - (3 + battle_get_mdef (src) + luk / 3); + sc_def_vit2 = 100 - (3 + battle_get_vit (src) + luk / 3); + sc_def_int2 = 100 - (3 + battle_get_int (src) + luk / 3); + sc_def_luk2 = 100 - (3 + luk); + if (bl->type == BL_PC) + dstsd = (struct map_session_data *) bl; + else if (bl->type == BL_MOB) + { + dstmd = (struct mob_data *) bl; //未使用? + if (sc_def_mdef > 50) + sc_def_mdef = 50; + if (sc_def_vit > 50) + sc_def_vit = 50; + if (sc_def_int > 50) + sc_def_int = 50; + if (sc_def_luk > 50) + sc_def_luk = 50; + } + if (sc_def_mdef < 0) + sc_def_mdef = 0; + if (sc_def_vit < 0) + sc_def_vit = 0; + if (sc_def_int < 0) + sc_def_int = 0; + + switch (skillid) + { + case 0: /* 通常攻撃 */ + /* 自動鷹 */ + if (sd && pc_isfalcon (sd) && sd->status.weapon == 11 + && (skill = pc_checkskill (sd, HT_BLITZBEAT)) > 0 + && MRAND (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); + } + // スナッチャー + if (sd && sd->status.weapon != 11 + && (skill = pc_checkskill (sd, RG_SNATCHER)) > 0) + if ((skill * 15 + 55) + + (skill2 = + pc_checkskill (sd, TF_STEAL)) * 10 > MRAND (1000)) + { + if (pc_steal_item (sd, bl)) + clif_skill_nodamage (src, bl, TF_STEAL, skill2, 1); + else + clif_skill_fail (sd, skillid, 0, 0); + } + break; - case SM_BASH: /* バッシュ(急所攻撃) */ - if( sd && (skill=pc_checkskill(sd,SM_FATALBLOW))>0 ){ - if(MRAND(100) < 6*(skilllv-5)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(SM_FATALBLOW,skilllv),0); - } - break; - - case TF_POISON: /* インベナム */ - case AS_SPLASHER: /* ベナムスプラッシャー */ - if(MRAND(100) < (2*skilllv+10)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_POISON,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - else{ - if(sd && skillid==TF_POISON) - clif_skill_fail(sd,skillid,0,0); - } - break; - - case AS_SONICBLOW: /* ソニックブロー */ - if(MRAND(100) < (2*skilllv+10)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - - - case HT_FREEZINGTRAP: /* フリージングトラップ */ - rate=skilllv*3+35; - if(MRAND(100) < rate*sc_def_mdef/100) - skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - - case MG_FROSTDIVER: /* フロストダイバー */ - case WZ_FROSTNOVA: /* フロストノヴァ */ - rate=(skilllv*3+35)*sc_def_mdef/100-(battle_get_int(bl)+battle_get_luk(bl))/15; - rate=rate<=5?5:rate; - if(MRAND(100) < rate) - skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - else if(sd) - clif_skill_fail(sd,skillid,0,0); - break; - - case WZ_STORMGUST: /* ストームガスト */ - { - struct status_change *sc_data = battle_get_sc_data(bl); - if(sc_data) { - sc_data[SC_FREEZE].val3++; - if(sc_data[SC_FREEZE].val3 >= 3) - skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - } - } - break; + case SM_BASH: /* バッシュ(急所攻撃) */ + if (sd && (skill = pc_checkskill (sd, SM_FATALBLOW)) > 0) + { + if (MRAND (100) < 6 * (skilllv - 5) * sc_def_vit / 100) + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (SM_FATALBLOW, + skilllv), 0); + } + break; - case HT_LANDMINE: /* ランドマイン */ - if( MRAND(100) < (5*skilllv+30)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; + case TF_POISON: /* インベナム */ + case AS_SPLASHER: /* ベナムスプラッシャー */ + if (MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100) + skill_status_change_start (bl, SC_POISON, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + else + { + if (sd && skillid == TF_POISON) + clif_skill_fail (sd, skillid, 0, 0); + } + break; - case HT_SHOCKWAVE: /* ショックウェーブトラップ */ - if(map[bl->m].flag.pvp && dstsd){ - dstsd->status.sp -= dstsd->status.sp*(5+15*skilllv)/100; - pc_calcstatus(dstsd,0); - } - break; - case HT_SANDMAN: /* サンドマン */ - if( MRAND(100) < (5*skilllv+30)*sc_def_int/100 ) - skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - case TF_SPRINKLESAND: /* 砂まき */ - if( MRAND(100) < 15*sc_def_int/100 ) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - - case TF_THROWSTONE: /* 石投げ */ - if( MRAND(100) < 5*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - - case CR_HOLYCROSS: /* ホーリークロス */ - if( MRAND(100) < 3*skilllv*sc_def_int/100 ) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - - case CR_GRANDCROSS: /* グランドクロス */ - { - int race = battle_get_race(bl); - if( (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6) && MRAND(100) < 100000*sc_def_int/100) //強制付与だが完全耐性には無効 - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - } - break; - - case CR_SHIELDCHARGE: /* シールドチャージ */ - if( MRAND(100) < (15 + skilllv*5)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - - case RG_RAID: /* サプライズアタック */ - if( MRAND(100) < (10+3*skilllv)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - if( MRAND(100) < (10+3*skilllv)*sc_def_int/100 ) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - case BA_FROSTJOKE: - if(MRAND(100) < (15+5*skilllv)*sc_def_mdef/100) - skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - - case DC_SCREAM: - if( MRAND(100) < (25+5*skilllv)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - - case BD_LULLABY: /* 子守唄 */ - if( MRAND(100) < 15*sc_def_int/100 ) - skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - - /* MOBの追加効果付きスキル */ - - case NPC_PETRIFYATTACK: - if(MRAND(100) < sc_def_mdef) - skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - case NPC_POISON: - case NPC_SILENCEATTACK: - case NPC_STUNATTACK: - if (MRAND(100) < 50 - (sc_def_vit >> 2) - (sc_def_phys_shield_spell) + (skilllv >> 2)) - skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skilllv,0); - break; - case NPC_CURSEATTACK: - if(MRAND(100) < sc_def_luk) - skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - case NPC_SLEEPATTACK: - case NPC_BLINDATTACK: - if(MRAND(100) < sc_def_int) - skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - case NPC_MENTALBREAKER: - if(dstsd) { - int sp = dstsd->status.max_sp*(10+skilllv)/100; - if(sp < 1) sp = 1; - pc_heal(dstsd,0,-sp); - } - break; + case AS_SONICBLOW: /* ソニックブロー */ + if (MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100) + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + + case HT_FREEZINGTRAP: /* フリージングトラップ */ + rate = skilllv * 3 + 35; + if (MRAND (100) < rate * sc_def_mdef / 100) + skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + + case MG_FROSTDIVER: /* フロストダイバー */ + case WZ_FROSTNOVA: /* フロストノヴァ */ + rate = + (skilllv * 3 + 35) * sc_def_mdef / 100 - + (battle_get_int (bl) + battle_get_luk (bl)) / 15; + rate = rate <= 5 ? 5 : rate; + if (MRAND (100) < rate) + skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + else if (sd) + clif_skill_fail (sd, skillid, 0, 0); + break; + + case WZ_STORMGUST: /* ストームガスト */ + { + struct status_change *sc_data = battle_get_sc_data (bl); + if (sc_data) + { + sc_data[SC_FREEZE].val3++; + if (sc_data[SC_FREEZE].val3 >= 3) + skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0, + 0, skill_get_time2 (skillid, + skilllv), + 0); + } + } + break; + + case HT_LANDMINE: /* ランドマイン */ + if (MRAND (100) < (5 * skilllv + 30) * sc_def_vit / 100) + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + + case HT_SHOCKWAVE: /* ショックウェーブトラップ */ + if (map[bl->m].flag.pvp && dstsd) + { + dstsd->status.sp -= + dstsd->status.sp * (5 + 15 * skilllv) / 100; + pc_calcstatus (dstsd, 0); + } + break; + case HT_SANDMAN: /* サンドマン */ + if (MRAND (100) < (5 * skilllv + 30) * sc_def_int / 100) + skill_status_change_start (bl, SC_SLEEP, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + case TF_SPRINKLESAND: /* 砂まき */ + if (MRAND (100) < 15 * sc_def_int / 100) + skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + + case TF_THROWSTONE: /* 石投げ */ + if (MRAND (100) < 5 * sc_def_vit / 100) + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + + case CR_HOLYCROSS: /* ホーリークロス */ + if (MRAND (100) < 3 * skilllv * sc_def_int / 100) + skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + + case CR_GRANDCROSS: /* グランドクロス */ + { + int race = battle_get_race (bl); + if ((battle_check_undead (race, battle_get_elem_type (bl)) || race == 6) && MRAND (100) < 100000 * sc_def_int / 100) //強制付与だが完全耐性には無効 + skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + } + break; + + case CR_SHIELDCHARGE: /* シールドチャージ */ + if (MRAND (100) < (15 + skilllv * 5) * sc_def_vit / 100) + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + + case RG_RAID: /* サプライズアタック */ + if (MRAND (100) < (10 + 3 * skilllv) * sc_def_vit / 100) + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + if (MRAND (100) < (10 + 3 * skilllv) * sc_def_int / 100) + skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + case BA_FROSTJOKE: + if (MRAND (100) < (15 + 5 * skilllv) * sc_def_mdef / 100) + skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + + case DC_SCREAM: + if (MRAND (100) < (25 + 5 * skilllv) * sc_def_vit / 100) + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + + case BD_LULLABY: /* 子守唄 */ + if (MRAND (100) < 15 * sc_def_int / 100) + skill_status_change_start (bl, SC_SLEEP, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + + /* MOBの追加効果付きスキル */ + + case NPC_PETRIFYATTACK: + if (MRAND (100) < sc_def_mdef) + skill_status_change_start (bl, sc[skillid - NPC_POISON], + skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + case NPC_POISON: + case NPC_SILENCEATTACK: + case NPC_STUNATTACK: + if (MRAND (100) < + 50 - (sc_def_vit >> 2) - (sc_def_phys_shield_spell) + + (skilllv >> 2)) + skill_status_change_start (bl, sc[skillid - NPC_POISON], + skilllv, 0, 0, 0, skilllv, 0); + break; + case NPC_CURSEATTACK: + if (MRAND (100) < sc_def_luk) + skill_status_change_start (bl, sc[skillid - NPC_POISON], + skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + case NPC_SLEEPATTACK: + case NPC_BLINDATTACK: + if (MRAND (100) < sc_def_int) + skill_status_change_start (bl, sc[skillid - NPC_POISON], + skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + case NPC_MENTALBREAKER: + if (dstsd) + { + int sp = dstsd->status.max_sp * (10 + skilllv) / 100; + if (sp < 1) + sp = 1; + pc_heal (dstsd, 0, -sp); + } + break; // -- moonsoul (adding status effect chance given to wizard aoe skills meteor and vermillion) // - case WZ_METEOR: - if(MRAND(100) < sc_def_vit) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - case WZ_VERMILION: - if(MRAND(100) < sc_def_int) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; + case WZ_METEOR: + if (MRAND (100) < sc_def_vit) + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + case WZ_VERMILION: + if (MRAND (100) < sc_def_int) + skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; // -- moonsoul (stun ability of new champion skill tigerfist) // - case CH_TIGERFIST: - if( MRAND(100) < (5 + skilllv*5)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - - case LK_SPIRALPIERCE: - if( MRAND(100) < (15 + skilllv*5)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - case ST_REJECTSWORD: /* フリージングトラップ */ - if( MRAND(100) < (10 + skilllv*5) ) - skill_status_change_start(bl,SC_AUTOCOUNTER,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - case PF_FOGWALL: /* ホーリークロス */ - if( MRAND(100) < 3*skilllv*sc_def_int/100 ) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - case LK_HEADCRUSH: /* ヘッドクラッシュ */ - {//条件が良く分からないので適当に - int race=battle_get_race(bl); - if( !(battle_check_undead(race,battle_get_elem_type(bl)) || race == 6) && MRAND(100) < (2*skilllv+10)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_HEADCRUSH,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - } - break; - case LK_JOINTBEAT: /* ジョイントビート */ - //条件が良く分からないので適当に - if( MRAND(100) < (2*skilllv+10)*sc_def_vit/100 ) - skill_status_change_start(bl,SC_JOINTBEAT,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - case PF_SPIDERWEB: /* スパイダーウェッブ */ - { - int sec=skill_get_time2(skillid,skilllv); - if(map[src->m].flag.pvp) //PvPでは拘束時間半減? - sec = sec/2; - battle_stopwalking(bl,1); - skill_status_change_start(bl,SC_SPIDERWEB,skilllv,0,0,0,sec,0); - } - break; - case ASC_METEORASSAULT: /* メテオアサルト */ - if( MRAND(100) < (15 + skilllv*5)*sc_def_vit/100 ) //状態異常は詳細が分からないので適当に - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - if( MRAND(100) < (10+3*skilllv)*sc_def_int/100 ) - skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - case MO_EXTREMITYFIST: /* 阿修羅覇凰拳 */ - //阿修羅を使うと5分間自然回復しないようになる - skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0 ); - break; - } + case CH_TIGERFIST: + if (MRAND (100) < (5 + skilllv * 5) * sc_def_vit / 100) + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; - if(sd && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* カードによる追加効果 */ - int i; - int sc_def_card=100; - - for(i=SC_STONE;i<=SC_BLIND;i++){ - //対象に状態異常 - if(i==SC_STONE || i==SC_FREEZE) - sc_def_card=sc_def_mdef; - else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE) - sc_def_card=sc_def_vit; - else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND) - sc_def_card=sc_def_int; - else if(i==SC_CURSE) - sc_def_card=sc_def_luk; - - if(!sd->state.arrow_atk) { - if(MRAND(10000) < (sd->addeff[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: cardによる異常発動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]); - skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); - } - } - else { - if(MRAND(10000) < (sd->addeff[i-SC_STONE]+sd->arrow_addeff[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: cardによる異常発動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]); - skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); - } - } - //自分に状態異常 - if(i==SC_STONE || i==SC_FREEZE) - sc_def_card=sc_def_mdef2; - else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE) - sc_def_card=sc_def_vit2; - else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND) - sc_def_card=sc_def_int2; - else if(i==SC_CURSE) - sc_def_card=sc_def_luk2; - - if(!sd->state.arrow_atk) { - if(MRAND(10000) < (sd->addeff2[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: cardによる異常発動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]); - skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); - } - } - else { - if(MRAND(10000) < (sd->addeff2[i-SC_STONE]+sd->arrow_addeff2[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: cardによる異常発動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]); - skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); - } - } - } - } - return 0; + case LK_SPIRALPIERCE: + if (MRAND (100) < (15 + skilllv * 5) * sc_def_vit / 100) + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + case ST_REJECTSWORD: /* フリージングトラップ */ + if (MRAND (100) < (10 + skilllv * 5)) + skill_status_change_start (bl, SC_AUTOCOUNTER, skilllv, 0, 0, + 0, skill_get_time2 (skillid, + skilllv), 0); + break; + case PF_FOGWALL: /* ホーリークロス */ + if (MRAND (100) < 3 * skilllv * sc_def_int / 100) + skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + case LK_HEADCRUSH: /* ヘッドクラッシュ */ + { //条件が良く分からないので適当に + int race = battle_get_race (bl); + if (! + (battle_check_undead (race, battle_get_elem_type (bl)) + || race == 6) + && MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100) + skill_status_change_start (bl, SC_HEADCRUSH, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + } + break; + case LK_JOINTBEAT: /* ジョイントビート */ + //条件が良く分からないので適当に + if (MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100) + skill_status_change_start (bl, SC_JOINTBEAT, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + case PF_SPIDERWEB: /* スパイダーウェッブ */ + { + int sec = skill_get_time2 (skillid, skilllv); + if (map[src->m].flag.pvp) //PvPでは拘束時間半減? + sec = sec / 2; + battle_stopwalking (bl, 1); + skill_status_change_start (bl, SC_SPIDERWEB, skilllv, 0, 0, 0, + sec, 0); + } + break; + case ASC_METEORASSAULT: /* メテオアサルト */ + if (MRAND (100) < (15 + skilllv * 5) * sc_def_vit / 100) //状態異常は詳細が分からないので適当に + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + if (MRAND (100) < (10 + 3 * skilllv) * sc_def_int / 100) + skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + case MO_EXTREMITYFIST: /* 阿修羅覇凰拳 */ + //阿修羅を使うと5分間自然回復しないようになる + skill_status_change_start (src, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), 0); + break; + } + + if (sd && skillid != MC_CARTREVOLUTION && attack_type & BF_WEAPON) + { /* カードによる追加効果 */ + int i; + int sc_def_card = 100; + + for (i = SC_STONE; i <= SC_BLIND; i++) + { + //対象に状態異常 + if (i == SC_STONE || i == SC_FREEZE) + sc_def_card = sc_def_mdef; + else if (i == SC_STAN || i == SC_POISON || i == SC_SILENCE) + sc_def_card = sc_def_vit; + else if (i == SC_SLEEP || i == SC_CONFUSION || i == SC_BLIND) + sc_def_card = sc_def_int; + else if (i == SC_CURSE) + sc_def_card = sc_def_luk; + + if (!sd->state.arrow_atk) + { + if (MRAND (10000) < + (sd->addeff[i - SC_STONE]) * sc_def_card / 100) + { + if (battle_config.battle_log) + printf + ("PC %d skill_addeff: cardによる異常発動 %d %d\n", + sd->bl.id, i, sd->addeff[i - SC_STONE]); + skill_status_change_start (bl, i, 7, 0, 0, 0, + (i == + SC_CONFUSION) ? 10000 + + 7000 : + skill_get_time2 (sc2 + [i - + SC_STONE], + 7), 0); + } + } + else + { + if (MRAND (10000) < + (sd->addeff[i - SC_STONE] + + sd->arrow_addeff[i - SC_STONE]) * sc_def_card / 100) + { + if (battle_config.battle_log) + printf + ("PC %d skill_addeff: cardによる異常発動 %d %d\n", + sd->bl.id, i, sd->addeff[i - SC_STONE]); + skill_status_change_start (bl, i, 7, 0, 0, 0, + (i == + SC_CONFUSION) ? 10000 + + 7000 : + skill_get_time2 (sc2 + [i - + SC_STONE], + 7), 0); + } + } + //自分に状態異常 + if (i == SC_STONE || i == SC_FREEZE) + sc_def_card = sc_def_mdef2; + else if (i == SC_STAN || i == SC_POISON || i == SC_SILENCE) + sc_def_card = sc_def_vit2; + else if (i == SC_SLEEP || i == SC_CONFUSION || i == SC_BLIND) + sc_def_card = sc_def_int2; + else if (i == SC_CURSE) + sc_def_card = sc_def_luk2; + + if (!sd->state.arrow_atk) + { + if (MRAND (10000) < + (sd->addeff2[i - SC_STONE]) * sc_def_card / 100) + { + if (battle_config.battle_log) + printf + ("PC %d skill_addeff: cardによる異常発動 %d %d\n", + src->id, i, sd->addeff2[i - SC_STONE]); + skill_status_change_start (src, i, 7, 0, 0, 0, + (i == + SC_CONFUSION) ? 10000 + + 7000 : + skill_get_time2 (sc2 + [i - + SC_STONE], + 7), 0); + } + } + else + { + if (MRAND (10000) < + (sd->addeff2[i - SC_STONE] + + sd->arrow_addeff2[i - SC_STONE]) * sc_def_card / 100) + { + if (battle_config.battle_log) + printf + ("PC %d skill_addeff: cardによる異常発動 %d %d\n", + src->id, i, sd->addeff2[i - SC_STONE]); + skill_status_change_start (src, i, 7, 0, 0, 0, + (i == + SC_CONFUSION) ? 10000 + + 7000 : + skill_get_time2 (sc2 + [i - + SC_STONE], + 7), 0); + } + } + } + } + return 0; } /*========================================================================= スキル攻撃吹き飛ばし処理 -------------------------------------------------------------------------*/ -int skill_blown( struct block_list *src, struct block_list *target,int count) +int skill_blown (struct block_list *src, struct block_list *target, int count) { - int dx=0,dy=0,nx,ny; - int x=target->x,y=target->y; - int ret,prev_state=MS_IDLE; - int moveblock; - struct map_session_data *sd=NULL; - struct mob_data *md=NULL; - struct skill_unit *su=NULL; - - nullpo_retr(0, src); - nullpo_retr(0, target); - - if(target->type==BL_PC){ - nullpo_retr(0, sd=(struct map_session_data *)target); - }else if(target->type==BL_MOB){ - nullpo_retr(0, md=(struct mob_data *)target); - }else if(target->type==BL_SKILL){ - nullpo_retr(0, su=(struct skill_unit *)target); - }else return 0; - - if(!(count&0x10000 && (sd||md||su))){ /* 指定なしなら位置関係から方向を求める */ - dx=target->x-src->x; dx=(dx>0)?1:((dx<0)?-1: 0); - dy=target->y-src->y; dy=(dy>0)?1:((dy<0)?-1: 0); - } - if(dx==0 && dy==0){ - int dir=battle_get_dir(target); - if(dir>=0 && dir<8){ - dx=-dirx[dir]; - dy=-diry[dir]; - } - } + int dx = 0, dy = 0, nx, ny; + int x = target->x, y = target->y; + int ret, prev_state = MS_IDLE; + int moveblock; + struct map_session_data *sd = NULL; + struct mob_data *md = NULL; + struct skill_unit *su = NULL; + + nullpo_retr (0, src); + nullpo_retr (0, target); + + if (target->type == BL_PC) + { + nullpo_retr (0, sd = (struct map_session_data *) target); + } + else if (target->type == BL_MOB) + { + nullpo_retr (0, md = (struct mob_data *) target); + } + else if (target->type == BL_SKILL) + { + nullpo_retr (0, su = (struct skill_unit *) target); + } + else + return 0; - 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 - battle_stopwalking(target,2); - - dx = nx - x; - dy = ny - y; - - if(sd) /* 画面外に出たので消去 */ - 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); - - if(su){ - skill_unit_move_unit_group(su->group,target->m,dx,dy); - }else{ -// struct status_change *sc_data=battle_get_sc_data(target); - if(moveblock) map_delblock(target); - target->x=nx; - target->y=ny; - if(moveblock) map_addblock(target); + if (!(count & 0x10000 && (sd || md || su))) + { /* 指定なしなら位置関係から方向を求める */ + dx = target->x - src->x; + dx = (dx > 0) ? 1 : ((dx < 0) ? -1 : 0); + dy = target->y - src->y; + dy = (dy > 0) ? 1 : ((dy < 0) ? -1 : 0); + } + if (dx == 0 && dy == 0) + { + int dir = battle_get_dir (target); + if (dir >= 0 && dir < 8) + { + dx = -dirx[dir]; + dy = -diry[dir]; + } + } + + ret = path_blownpos (target->m, x, y, dx, dy, count & 0xffff); + nx = ret >> 16; + ny = ret & 0xffff; + moveblock = (x / BLOCK_SIZE != nx / BLOCK_SIZE + || y / BLOCK_SIZE != ny / BLOCK_SIZE); + + if (count & 0x20000) + { + battle_stopwalking (target, 1); + if (sd) + { + sd->to_x = nx; + sd->to_y = ny; + sd->walktimer = 1; + clif_walkok (sd); + clif_movechar (sd); + } + else if (md) + { + md->to_x = nx; + md->to_y = ny; + prev_state = md->state.state; + md->state.state = MS_WALK; + clif_fixmobpos (md); + } + } + else + battle_stopwalking (target, 2); + + dx = nx - x; + dy = ny - y; + + if (sd) /* 画面外に出たので消去 */ + 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); + + if (su) + { + skill_unit_move_unit_group (su->group, target->m, dx, dy); + } + else + { +// struct status_change *sc_data=battle_get_sc_data(target); + if (moveblock) + map_delblock (target); + target->x = nx; + target->y = ny; + if (moveblock) + map_addblock (target); /*ダンス中にエフェクトは移動しないらしい if(sc_data && sc_data[SC_DANCING].timer!=-1){ //対象がダンス中なのでエフェクトも移動 struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[SC_DANCING].val2; @@ -1312,25 +1639,30 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) skill_unit_move_unit_group(sg,target->m,dx,dy); } */ - } - - if(sd) { /* 画面内に入ってきたので表示 */ - map_foreachinmovearea(clif_pcinsight,target->m,nx-AREA_SIZE,ny-AREA_SIZE,nx+AREA_SIZE,ny+AREA_SIZE,-dx,-dy,0,sd); - if(count&0x20000) - sd->walktimer = -1; - } - else if(md) { - map_foreachinmovearea(clif_mobinsight,target->m,nx-AREA_SIZE,ny-AREA_SIZE,nx+AREA_SIZE,ny+AREA_SIZE,-dx,-dy,BL_PC,md); - if(count&0x20000) - md->state.state = prev_state; - } - - skill_unit_move(target,gettick(),(count&0xffff)+7); /* スキルユニットの判定 */ - - return 0; + } + + 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; + } + + skill_unit_move (target, gettick (), (count & 0xffff) + 7); /* スキルユニットの判定 */ + + return 0; } - /* * ========================================================================= * スキル攻撃効果処理まとめ @@ -1343,237 +1675,295 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) *------------------------------------------------------------------------- */ -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 ) +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; + struct Damage dmg; + struct status_change *sc_data; + int type, lv, damage; - rdamage = 0; - nullpo_retr(0, src); - nullpo_retr(0, dsrc); - nullpo_retr(0, bl); + rdamage = 0; + nullpo_retr (0, src); + nullpo_retr (0, dsrc); + nullpo_retr (0, bl); - sc_data = battle_get_sc_data(bl); + sc_data = battle_get_sc_data (bl); //何もしない判定ここから - if(dsrc->m != bl->m) //対象が同じマップにいなければ何もしない - return 0; - if(src->prev == NULL || dsrc->prev == NULL || bl->prev == NULL) //prevよくわからない※ - return 0; - if(src->type == BL_PC && pc_isdead((struct map_session_data *)src)) //術者?がPCですでに死んでいたら何もしない - return 0; - if(dsrc->type == BL_PC && pc_isdead((struct map_session_data *)dsrc)) //術者?がPCですでに死んでいたら何もしない - return 0; - if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) //対象がPCですでに死んでいたら何もしない - return 0; - if(skillnotok(skillid, (struct map_session_data *) bl)) - return 0; // [MouseJstr] - if(sc_data && sc_data[SC_HIDING].timer != -1) { //ハイディング状態で - if(skill_get_pl(skillid) != 2) //スキルの属性が地属性でなければ何もしない - return 0; - } - if(sc_data && sc_data[SC_TRICKDEAD].timer != -1) //死んだふり中は何もしない - return 0; - if(skillid == WZ_STORMGUST) { //使用スキルがストームガストで - if(sc_data && sc_data[SC_FREEZE].timer != -1) //凍結状態なら何もしない - return 0; - } - if(skillid == WZ_FROSTNOVA && dsrc->x == bl->x && dsrc->y == bl->y) //使用スキルがフロストノヴァで、dsrcとblが同じ場所なら何もしない - return 0; - if(src->type == BL_PC && ((struct map_session_data *)src)->chatID) //術者がPCでチャット中なら何もしない - return 0; - if(dsrc->type == BL_PC && ((struct map_session_data *)dsrc)->chatID) //術者がPCでチャット中なら何もしない - return 0; - if(src->type == BL_PC && bl && mob_gvmobcheck(((struct map_session_data *)src),bl)==0) - return 0; + if (dsrc->m != bl->m) //対象が同じマップにいなければ何もしない + return 0; + if (src->prev == NULL || dsrc->prev == NULL || bl->prev == NULL) //prevよくわからない※ + return 0; + if (src->type == BL_PC && pc_isdead ((struct map_session_data *) src)) //術者?がPCですでに死んでいたら何もしない + return 0; + if (dsrc->type == BL_PC && pc_isdead ((struct map_session_data *) dsrc)) //術者?がPCですでに死んでいたら何もしない + return 0; + if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl)) //対象がPCですでに死んでいたら何もしない + return 0; + if (skillnotok (skillid, (struct map_session_data *) bl)) + return 0; // [MouseJstr] + if (sc_data && sc_data[SC_HIDING].timer != -1) + { //ハイディング状態で + if (skill_get_pl (skillid) != 2) //スキルの属性が地属性でなければ何もしない + return 0; + } + if (sc_data && sc_data[SC_TRICKDEAD].timer != -1) //死んだふり中は何もしない + return 0; + if (skillid == WZ_STORMGUST) + { //使用スキルがストームガストで + if (sc_data && sc_data[SC_FREEZE].timer != -1) //凍結状態なら何もしない + return 0; + } + if (skillid == WZ_FROSTNOVA && dsrc->x == bl->x && dsrc->y == bl->y) //使用スキルがフロストノヴァで、dsrcとblが同じ場所なら何もしない + return 0; + if (src->type == BL_PC && ((struct map_session_data *) src)->chatID) //術者がPCでチャット中なら何もしない + return 0; + if (dsrc->type == BL_PC && ((struct map_session_data *) dsrc)->chatID) //術者がPCでチャット中なら何もしない + 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 ); //ダメージ計算 + type = -1; + lv = (flag >> 20) & 0xf; + dmg = battle_calc_attack (attack_type, src, bl, skillid, skilllv, flag & 0xff); //ダメージ計算 //マジックロッド処理ここから - if(attack_type&BF_MAGIC && sc_data && sc_data[SC_MAGICROD].timer != -1 && src == dsrc) { //魔法攻撃でマジックロッド状態でsrc=dsrcなら - dmg.damage = dmg.damage2 = 0; //ダメージ0 - if(bl->type == BL_PC) { //対象がPCの場合 - int sp = skill_get_sp(skillid,skilllv); //使用されたスキルのSPを吸収 - sp = sp * sc_data[SC_MAGICROD].val2 / 100; //吸収率計算 - if(skillid == WZ_WATERBALL && skilllv > 1) //ウォーターボールLv1以上 - sp = sp/((skilllv|1)*(skilllv|1)); //さらに計算? - if(sp > 0x7fff) sp = 0x7fff; //SP多すぎの場合は理論最大値 - else if(sp < 1) sp = 1; //1以下の場合は1 - if(((struct map_session_data *)bl)->status.sp + sp > ((struct map_session_data *)bl)->status.max_sp) { //回復SP+現在のSPがMSPより大きい場合 - sp = ((struct map_session_data *)bl)->status.max_sp - ((struct map_session_data *)bl)->status.sp; //SPをMSP-現在SPにする - ((struct map_session_data *)bl)->status.sp = ((struct map_session_data *)bl)->status.max_sp; //現在のSPにMSPを代入 - } - else //回復SP+現在のSPがMSPより小さい場合は回復SPを加算 - ((struct map_session_data *)bl)->status.sp += sp; - clif_heal(((struct map_session_data *)bl)->fd,SP_SP,sp); //SP回復エフェクトの表示 - ((struct map_session_data *)bl)->canact_tick = tick + skill_delayfix(bl, skill_get_delay(SA_MAGICROD,sc_data[SC_MAGICROD].val1)); // - } - clif_skill_nodamage(bl,bl,SA_MAGICROD,sc_data[SC_MAGICROD].val1,1); //マジックロッドエフェクトを表示 - } + if (attack_type & BF_MAGIC && sc_data && sc_data[SC_MAGICROD].timer != -1 + && src == dsrc) + { //魔法攻撃でマジックロッド状態でsrc=dsrcなら + dmg.damage = dmg.damage2 = 0; //ダメージ0 + if (bl->type == BL_PC) + { //対象がPCの場合 + int sp = skill_get_sp (skillid, skilllv); //使用されたスキルのSPを吸収 + sp = sp * sc_data[SC_MAGICROD].val2 / 100; //吸収率計算 + if (skillid == WZ_WATERBALL && skilllv > 1) //ウォーターボールLv1以上 + sp = sp / ((skilllv | 1) * (skilllv | 1)); //さらに計算? + if (sp > 0x7fff) + sp = 0x7fff; //SP多すぎの場合は理論最大値 + else if (sp < 1) + sp = 1; //1以下の場合は1 + if (((struct map_session_data *) bl)->status.sp + sp > + ((struct map_session_data *) bl)->status.max_sp) + { //回復SP+現在のSPがMSPより大きい場合 + sp = ((struct map_session_data *) bl)->status.max_sp - ((struct map_session_data *) bl)->status.sp; //SPをMSP-現在SPにする + ((struct map_session_data *) bl)->status.sp = ((struct map_session_data *) bl)->status.max_sp; //現在のSPにMSPを代入 + } + else //回復SP+現在のSPがMSPより小さい場合は回復SPを加算 + ((struct map_session_data *) bl)->status.sp += sp; + clif_heal (((struct map_session_data *) bl)->fd, SP_SP, sp); //SP回復エフェクトの表示 + ((struct map_session_data *) bl)->canact_tick = tick + skill_delayfix (bl, skill_get_delay (SA_MAGICROD, sc_data[SC_MAGICROD].val1)); // + } + clif_skill_nodamage (bl, bl, SA_MAGICROD, sc_data[SC_MAGICROD].val1, 1); //マジックロッドエフェクトを表示 + } //マジックロッド処理ここまで - damage = dmg.damage + dmg.damage2; + damage = dmg.damage + dmg.damage2; - if(lv==15) - lv=-1; + if (lv == 15) + lv = -1; - if( flag&0xff00 ) - type=(flag&0xff00)>>8; + if (flag & 0xff00) + type = (flag & 0xff00) >> 8; - if(damage <= 0 || damage < dmg.div_) //吹き飛ばし判定?※ - dmg.blewcount = 0; + if (damage <= 0 || damage < dmg.div_) //吹き飛ばし判定?※ + dmg.blewcount = 0; - if(skillid == CR_GRANDCROSS) {//グランドクロス - if(battle_config.gx_disptype) dsrc = src; // 敵ダメージ白文字表示 - if( src == bl) type = 4; // 反動はダメージモーションなし - } + if (skillid == CR_GRANDCROSS) + { //グランドクロス + if (battle_config.gx_disptype) + dsrc = src; // 敵ダメージ白文字表示 + if (src == bl) + type = 4; // 反動はダメージモーションなし + } //使用者がPCの場合の処理ここから - if(src->type == BL_PC) { - struct map_session_data *sd = (struct map_session_data *)src; - nullpo_retr(0, sd); + if (src->type == BL_PC) + { + struct map_session_data *sd = (struct map_session_data *) src; + nullpo_retr (0, sd); //連打掌(MO_CHAINCOMBO)ここから - if(skillid == MO_CHAINCOMBO) { - int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); //基本ディレイの計算 - if(damage < battle_get_hp(bl)) { //ダメージが対象のHPより小さい場合 - if(pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0) //猛龍拳(MO_COMBOFINISH)取得&気球保持時は+300ms - delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整 - - skill_status_change_start(src,SC_COMBO,MO_CHAINCOMBO,skilllv,0,0,delay,0); //コンボ状態に - } - sd->attackabletime = sd->canmove_tick = tick + delay; - clif_combo_delay(src,delay); //コンボディレイパケットの送信 - } + if (skillid == MO_CHAINCOMBO) + { + int delay = 1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src); //基本ディレイの計算 + if (damage < battle_get_hp (bl)) + { //ダメージが対象のHPより小さい場合 + if (pc_checkskill (sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0) //猛龍拳(MO_COMBOFINISH)取得&気球保持時は+300ms + delay += 300 * battle_config.combo_delay_rate / 100; //追加ディレイをconfにより調整 + + skill_status_change_start (src, SC_COMBO, MO_CHAINCOMBO, skilllv, 0, 0, delay, 0); //コンボ状態に + } + sd->attackabletime = sd->canmove_tick = tick + delay; + clif_combo_delay (src, delay); //コンボディレイパケットの送信 + } //連打掌(MO_CHAINCOMBO)ここまで //猛龍拳(MO_COMBOFINISH)ここから - else if(skillid == MO_COMBOFINISH) { - int delay = 700 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); - if(damage < battle_get_hp(bl)) { - //阿修羅覇凰拳(MO_EXTREMITYFIST)取得&気球4個保持&爆裂波動(MO_EXPLOSIONSPIRITS)状態時は+300ms - //伏虎拳(CH_TIGERFIST)取得時も+300ms - if((pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 4 && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1) || - (pc_checkskill(sd, CH_TIGERFIST) > 0 && sd->spiritball > 0) || - (pc_checkskill(sd, CH_CHAINCRUSH) > 0 && sd->spiritball > 1)) - delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整 - - skill_status_change_start(src,SC_COMBO,MO_COMBOFINISH,skilllv,0,0,delay,0); //コンボ状態に - } - sd->attackabletime = sd->canmove_tick = tick + delay; - clif_combo_delay(src,delay); //コンボディレイパケットの送信 - } + else if (skillid == MO_COMBOFINISH) + { + int delay = + 700 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src); + if (damage < battle_get_hp (bl)) + { + //阿修羅覇凰拳(MO_EXTREMITYFIST)取得&気球4個保持&爆裂波動(MO_EXPLOSIONSPIRITS)状態時は+300ms + //伏虎拳(CH_TIGERFIST)取得時も+300ms + if ((pc_checkskill (sd, MO_EXTREMITYFIST) > 0 + && sd->spiritball >= 4 + && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1) + || (pc_checkskill (sd, CH_TIGERFIST) > 0 + && sd->spiritball > 0) + || (pc_checkskill (sd, CH_CHAINCRUSH) > 0 + && sd->spiritball > 1)) + delay += 300 * battle_config.combo_delay_rate / 100; //追加ディレイをconfにより調整 + + skill_status_change_start (src, SC_COMBO, MO_COMBOFINISH, skilllv, 0, 0, delay, 0); //コンボ状態に + } + sd->attackabletime = sd->canmove_tick = tick + delay; + clif_combo_delay (src, delay); //コンボディレイパケットの送信 + } //猛龍拳(MO_COMBOFINISH)ここまで //伏虎拳(CH_TIGERFIST)ここから - else if(skillid == CH_TIGERFIST) { - int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); - if(damage < battle_get_hp(bl)) { - if(pc_checkskill(sd, CH_CHAINCRUSH) > 0) //連柱崩撃(CH_CHAINCRUSH)取得時は+300ms - delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整 - - skill_status_change_start(src,SC_COMBO,CH_TIGERFIST,skilllv,0,0,delay,0); //コンボ状態に - } - sd->attackabletime = sd->canmove_tick = tick + delay; - clif_combo_delay(src,delay); //コンボディレイパケットの送信 - } + else if (skillid == CH_TIGERFIST) + { + int delay = + 1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src); + if (damage < battle_get_hp (bl)) + { + if (pc_checkskill (sd, CH_CHAINCRUSH) > 0) //連柱崩撃(CH_CHAINCRUSH)取得時は+300ms + delay += 300 * battle_config.combo_delay_rate / 100; //追加ディレイをconfにより調整 + + skill_status_change_start (src, SC_COMBO, CH_TIGERFIST, skilllv, 0, 0, delay, 0); //コンボ状態に + } + sd->attackabletime = sd->canmove_tick = tick + delay; + clif_combo_delay (src, delay); //コンボディレイパケットの送信 + } //伏虎拳(CH_TIGERFIST)ここまで //連柱崩撃(CH_CHAINCRUSH)ここから - else if(skillid == CH_CHAINCRUSH) { - int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); - if(damage < battle_get_hp(bl)) { - //阿修羅覇凰拳(MO_EXTREMITYFIST)取得&気球4個保持&爆裂波動(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; //追加ディレイをconfにより調整 - - skill_status_change_start(src,SC_COMBO,CH_CHAINCRUSH,skilllv,0,0,delay,0); //コンボ状態に - } - sd->attackabletime = sd->canmove_tick = tick + delay; - clif_combo_delay(src,delay); //コンボディレイパケットの送信 - } + else if (skillid == CH_CHAINCRUSH) + { + int delay = + 1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src); + if (damage < battle_get_hp (bl)) + { + //阿修羅覇凰拳(MO_EXTREMITYFIST)取得&気球4個保持&爆裂波動(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; //追加ディレイをconfにより調整 + + skill_status_change_start (src, SC_COMBO, CH_CHAINCRUSH, skilllv, 0, 0, delay, 0); //コンボ状態に + } + sd->attackabletime = sd->canmove_tick = tick + delay; + clif_combo_delay (src, delay); //コンボディレイパケットの送信 + } //連柱崩撃(CH_CHAINCRUSH)ここまで - } + } //使用者がPCの場合の処理ここまで //武器スキル?ここから - //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) { //武器スキル&ダメージあり&使用者と対象者が違う&src=dsrc - if(dmg.flag&BF_SHORT) { //近距離攻撃時?※ - if(bl->type == BL_PC) { //対象がPCの時 - struct map_session_data *tsd = (struct map_session_data *)bl; - nullpo_retr(0, tsd); - if(tsd->short_weapon_damage_return > 0) { //近距離攻撃跳ね返し?※ - rdamage += damage * tsd->short_weapon_damage_return / 100; - if(rdamage < 1) rdamage = 1; - } - } - if(sc_data && sc_data[SC_REFLECTSHIELD].timer != -1) { //リフレクトシールド時 - rdamage += damage * sc_data[SC_REFLECTSHIELD].val2 / 100; //跳ね返し計算 - if(rdamage < 1) rdamage = 1; - } - } - else if(dmg.flag&BF_LONG) { //遠距離攻撃時?※ - if(bl->type == BL_PC) { //対象がPCの時 - struct map_session_data *tsd = (struct map_session_data *)bl; - nullpo_retr(0, tsd); - if(tsd->long_weapon_damage_return > 0) { //遠距離攻撃跳ね返し?※ - 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); - } + //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) + { //武器スキル&ダメージあり&使用者と対象者が違う&src=dsrc + if (dmg.flag & BF_SHORT) + { //近距離攻撃時?※ + if (bl->type == BL_PC) + { //対象がPCの時 + struct map_session_data *tsd = (struct map_session_data *) bl; + nullpo_retr (0, tsd); + if (tsd->short_weapon_damage_return > 0) + { //近距離攻撃跳ね返し?※ + rdamage += damage * tsd->short_weapon_damage_return / 100; + if (rdamage < 1) + rdamage = 1; + } + } + if (sc_data && sc_data[SC_REFLECTSHIELD].timer != -1) + { //リフレクトシールド時 + rdamage += damage * sc_data[SC_REFLECTSHIELD].val2 / 100; //跳ね返し計算 + if (rdamage < 1) + rdamage = 1; + } + } + else if (dmg.flag & BF_LONG) + { //遠距離攻撃時?※ + if (bl->type == BL_PC) + { //対象がPCの時 + struct map_session_data *tsd = (struct map_session_data *) bl; + nullpo_retr (0, tsd); + if (tsd->long_weapon_damage_return > 0) + { //遠距離攻撃跳ね返し?※ + 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); + } //武器スキル?ここまで - switch(skillid){ - case WZ_SIGHTRASHER: - clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, 5); - break; - case AS_SPLASHER: - clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, -1, 5); - break; - case NPC_SELFDESTRUCTION: - case NPC_SELFDESTRUCTION2: - break; - default: - clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, (skillid==0)? 5:type ); - } - if(dmg.blewcount > 0 && !map[src->m].flag.gvg) { /* 吹き飛ばし処理とそのパケット */ - if(skillid == WZ_SIGHTRASHER) - skill_blown(src,bl,dmg.blewcount); - else - skill_blown(dsrc,bl,dmg.blewcount); - if(bl->type == BL_MOB) - clif_fixmobpos((struct mob_data *)bl); - else - clif_fixpos(bl); - } - - map_freeblock_lock(); - /* 実際にダメージ処理を行う */ - if(skillid != KN_BOWLINGBASH || flag) - battle_damage(src,bl,damage,0); - if(skillid == RG_INTIMIDATE && damage > 0 && !(battle_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) { - int s_lv = battle_get_lv(src),t_lv = battle_get_lv(bl); - int rate = 50 + skilllv * 5; - rate = rate + (s_lv - t_lv); - if(MRAND(100) < rate) - skill_addtimerskill(src,tick + 800,bl->id,0,0,skillid,skilllv,0,flag); - } + switch (skillid) + { + case WZ_SIGHTRASHER: + clif_skill_damage (src, bl, tick, dmg.amotion, dmg.dmotion, + damage, dmg.div_, skillid, + (lv != 0) ? lv : skilllv, 5); + break; + case AS_SPLASHER: + clif_skill_damage (dsrc, bl, tick, dmg.amotion, dmg.dmotion, + damage, dmg.div_, skillid, -1, 5); + break; + case NPC_SELFDESTRUCTION: + case NPC_SELFDESTRUCTION2: + break; + default: + clif_skill_damage (dsrc, bl, tick, dmg.amotion, dmg.dmotion, + damage, dmg.div_, skillid, + (lv != 0) ? lv : skilllv, + (skillid == 0) ? 5 : type); + } + if (dmg.blewcount > 0 && !map[src->m].flag.gvg) + { /* 吹き飛ばし処理とそのパケット */ + if (skillid == WZ_SIGHTRASHER) + skill_blown (src, bl, dmg.blewcount); + else + skill_blown (dsrc, bl, dmg.blewcount); + if (bl->type == BL_MOB) + clif_fixmobpos ((struct mob_data *) bl); + else + clif_fixpos (bl); + } + + map_freeblock_lock (); + /* 実際にダメージ処理を行う */ + if (skillid != KN_BOWLINGBASH || flag) + battle_damage (src, bl, damage, 0); + if (skillid == RG_INTIMIDATE && damage > 0 + && !(battle_get_mode (bl) & 0x20) && !map[src->m].flag.gvg) + { + int s_lv = battle_get_lv (src), t_lv = battle_get_lv (bl); + int rate = 50 + skilllv * 5; + rate = rate + (s_lv - t_lv); + if (MRAND (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)){ struct map_session_data *tsd = (struct map_session_data *)bl; @@ -1596,71 +1986,97 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds } } */ - /* ダメージがあるなら追加効果判定 */ - 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) /* スキル使用条件のMOBスキル */ - { - 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 && MRAND(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 && MRAND(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 && MRAND(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 && MRAND(100) < sd->sp_drain_rate_) { - sp += (dmg.damage2 * sd->sp_drain_per_)/100; - if(sd->sp_drain_rate_ > 0 && sp < 1) sp = 1; - else if(sd->sp_drain_rate_ < 0 && sp > -1) sp = -1; - } - if(hp || sp) pc_heal(sd,hp,sp); - } - - if((skillid != KN_BOWLINGBASH || flag) && rdamage > 0) - battle_damage(bl,src,rdamage,0); - - if(attack_type&BF_WEAPON && sc_data && sc_data[SC_AUTOCOUNTER].timer != -1 && sc_data[SC_AUTOCOUNTER].val4 > 0) { - if(sc_data[SC_AUTOCOUNTER].val3 == dsrc->id) - battle_weapon_attack(bl,dsrc,tick,0x8000|sc_data[SC_AUTOCOUNTER].val1); - skill_status_change_end(bl,SC_AUTOCOUNTER,-1); - } - - map_freeblock_unlock(); + /* ダメージがあるなら追加効果判定 */ + 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) /* スキル使用条件のMOBスキル */ + { + 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)); + } + } + } - return (dmg.damage+dmg.damage2); /* 与ダメを返す */ + 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 + && MRAND (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 + && MRAND (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 + && MRAND (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 + && MRAND (100) < sd->sp_drain_rate_) + { + sp += (dmg.damage2 * sd->sp_drain_per_) / 100; + if (sd->sp_drain_rate_ > 0 && sp < 1) + sp = 1; + else if (sd->sp_drain_rate_ < 0 && sp > -1) + sp = -1; + } + if (hp || sp) + pc_heal (sd, hp, sp); + } + + if ((skillid != KN_BOWLINGBASH || flag) && rdamage > 0) + battle_damage (bl, src, rdamage, 0); + + if (attack_type & BF_WEAPON && sc_data + && sc_data[SC_AUTOCOUNTER].timer != -1 + && sc_data[SC_AUTOCOUNTER].val4 > 0) + { + if (sc_data[SC_AUTOCOUNTER].val3 == dsrc->id) + battle_weapon_attack (bl, dsrc, tick, + 0x8000 | sc_data[SC_AUTOCOUNTER].val1); + skill_status_change_end (bl, SC_AUTOCOUNTER, -1); + } + + map_freeblock_unlock (); + + return (dmg.damage + dmg.damage2); /* 与ダメを返す */ } /*========================================== @@ -1672,366 +2088,436 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds * 0 =予約。0に固定 *------------------------------------------ */ -static int skill_area_temp[8]; /* 一時変数。必要なら使う。 */ -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 ) +static int skill_area_temp[8]; /* 一時変数。必要なら使う。 */ +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の値を参照していないのでNULLチェックはしない - 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; + 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の値を参照していないのでNULLチェックはしない + 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 ) +static int skill_check_unit_range_sub (struct block_list *bl, va_list ap) { - struct skill_unit *unit; - int *c,x,y,range,sx[4],sy[4]; - int t_range,tx[4],ty[4]; - int i,r_flag,skillid; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, unit = (struct skill_unit *)bl); - nullpo_retr(0, c = va_arg(ap,int *)); - - if(bl->prev == NULL || bl->type != BL_SKILL) - return 0; - - if(!unit->alive) - return 0; - - x = va_arg(ap,int); - y = va_arg(ap,int); - range = va_arg(ap,int); - skillid = va_arg(ap,int); - - if(skillid == MG_SAFETYWALL || skillid == AL_PNEUMA) { - if(unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85) - return 0; - } - else if(skillid == AL_WARP) { - if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92) - return 0; - } - else if((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP) || skillid == HT_TALKIEBOX) { - if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92) - return 0; - } - else if(skillid == WZ_FIREPILLAR) { - if(unit->group->unit_id != 0x87) - return 0; - } - else return 0; - t_range=(unit->range!=0)? unit->range:unit->group->range; - tx[0] = tx[3] = unit->bl.x - t_range; - tx[1] = tx[2] = unit->bl.x + t_range; - ty[0] = ty[1] = unit->bl.y - t_range; - ty[2] = ty[3] = unit->bl.y + t_range; - sx[0] = sx[3] = x - range; - sx[1] = sx[2] = x + range; - sy[0] = sy[1] = y - range; - sy[2] = sy[3] = y + range; - for(i=r_flag=0;i<4;i++) { - if(sx[i] >= tx[0] && sx[i] <= tx[1] && sy[i] >= ty[0] && sy[i] <= ty[2]) { - r_flag = 1; - break; - } - if(tx[i] >= sx[0] && tx[i] <= sx[1] && ty[i] >= sy[0] && ty[i] <= sy[2]) { - r_flag = 1; - break; - } - } - if(r_flag) (*c)++; + struct skill_unit *unit; + int *c, x, y, range, sx[4], sy[4]; + int t_range, tx[4], ty[4]; + int i, r_flag, skillid; + + nullpo_retr (0, bl); + nullpo_retr (0, ap); + nullpo_retr (0, unit = (struct skill_unit *) bl); + nullpo_retr (0, c = va_arg (ap, int *)); + + if (bl->prev == NULL || bl->type != BL_SKILL) + return 0; + + if (!unit->alive) + return 0; + + x = va_arg (ap, int); + y = va_arg (ap, int); + range = va_arg (ap, int); + skillid = va_arg (ap, int); + + if (skillid == MG_SAFETYWALL || skillid == AL_PNEUMA) + { + if (unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85) + return 0; + } + else if (skillid == AL_WARP) + { + if ((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) + && unit->group->unit_id != 0x92) + return 0; + } + else if ((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP) + || skillid == HT_TALKIEBOX) + { + if ((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) + && unit->group->unit_id != 0x92) + return 0; + } + else if (skillid == WZ_FIREPILLAR) + { + if (unit->group->unit_id != 0x87) + return 0; + } + else + return 0; + t_range = (unit->range != 0) ? unit->range : unit->group->range; + tx[0] = tx[3] = unit->bl.x - t_range; + tx[1] = tx[2] = unit->bl.x + t_range; + ty[0] = ty[1] = unit->bl.y - t_range; + ty[2] = ty[3] = unit->bl.y + t_range; + sx[0] = sx[3] = x - range; + sx[1] = sx[2] = x + range; + sy[0] = sy[1] = y - range; + sy[2] = sy[3] = y + range; + for (i = r_flag = 0; i < 4; i++) + { + if (sx[i] >= tx[0] && sx[i] <= tx[1] && sy[i] >= ty[0] + && sy[i] <= ty[2]) + { + r_flag = 1; + break; + } + if (tx[i] >= sx[0] && tx[i] <= sx[1] && ty[i] >= sy[0] + && ty[i] <= sy[2]) + { + r_flag = 1; + break; + } + } + if (r_flag) + (*c)++; - return 0; + return 0; } -int skill_check_unit_range(int m,int x,int y,int range,int skillid) +int skill_check_unit_range (int m, int x, int y, int range, int skillid) { - int c = 0; + int c = 0; - map_foreachinarea(skill_check_unit_range_sub,m,x-10,y-10,x+10,y+10,BL_SKILL,&c,x,y,range,skillid); + map_foreachinarea (skill_check_unit_range_sub, m, x - 10, y - 10, x + 10, + y + 10, BL_SKILL, &c, x, y, range, skillid); - return c; + return c; } -static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap ) +static int skill_check_unit_range2_sub (struct block_list *bl, va_list ap) { - int *c; + int *c; - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, c = va_arg(ap,int *)); + 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->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; + if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl)) + return 0; - (*c)++; + (*c)++; - return 0; + return 0; } -int skill_check_unit_range2(int m,int x,int y,int range) +int skill_check_unit_range2 (int m, int x, int y, int range) { - int c = 0; + int c = 0; - map_foreachinarea(skill_check_unit_range2_sub,m,x-range,y-range,x+range,y+range,0,&c); + map_foreachinarea (skill_check_unit_range2_sub, m, x - range, y - range, + x + range, y + range, 0, &c); - return c; + return c; } /*========================================================================= * 範囲スキル使用処理小分けここから */ /* 対象の数をカウントする。(skill_area_temp[0]を初期化しておくこと) */ -int skill_area_sub_count(struct block_list *src,struct block_list *target,int skillid,int skilllv,unsigned int tick,int flag) +int skill_area_sub_count (struct block_list *src, struct block_list *target, + int skillid, int skilllv, unsigned int tick, + int flag) { - if(skill_area_temp[0] < 0xffff) - skill_area_temp[0]++; - return 0; + if (skill_area_temp[0] < 0xffff) + skill_area_temp[0]++; + return 0; } /*========================================== * *------------------------------------------ */ -static int skill_timerskill(int tid, unsigned int tick, int id,int data ) +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 block_list *src = map_id2bl(id),*target; - struct skill_timerskill *skl = NULL; - int range; - - nullpo_retr(0, src); - - if(src->prev == NULL) - return 0; + struct map_session_data *sd = NULL; + struct mob_data *md = NULL; + struct block_list *src = map_id2bl (id), *target; + struct skill_timerskill *skl = NULL; + int range; - 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]; - } + nullpo_retr (0, src); - else - return 0; - - nullpo_retr(0, skl); - - skl->timer = -1; - if(skl->target_id) { - struct block_list tbl; - target = map_id2bl(skl->target_id); - if(skl->skill_id == RG_INTIMIDATE) { - if(target == NULL) { - target = &tbl; //初期化してないのにアドレス突っ込んでいいのかな? - target->type = BL_NUL; - target->m = src->m; - target->prev = target->next = NULL; - } - } - if(target == NULL) - return 0; - if(target->prev == NULL && skl->skill_id != RG_INTIMIDATE) - return 0; - if(src->m != target->m) - return 0; - if(sd && pc_isdead(sd)) - return 0; - if(target->type == BL_PC && pc_isdead((struct map_session_data *)target) && skl->skill_id != RG_INTIMIDATE) - return 0; - - switch(skl->skill_id) { - case TF_BACKSLIDING: - clif_skill_nodamage(src,src,skl->skill_id,skl->skill_lv,1); - break; - case RG_INTIMIDATE: - if(sd && !map[src->m].flag.noteleport) { - int x,y,i,j,c; - pc_randomwarp(sd,3); - for(i=0;i<16;i++) { - j = MRAND(8); - x = sd->bl.x + dirx[j]; - y = sd->bl.y + diry[j]; - if((c=map_getcell(sd->bl.m,x,y)) != 1 && c != 5) - break; - } - if(i >= 16) { - x = sd->bl.x; - y = sd->bl.y; - } - if(target->prev != NULL) { - if(target->type == BL_PC && !pc_isdead((struct map_session_data *)target)) - pc_setpos((struct map_session_data *)target,map[sd->bl.m].name,x,y,3); - else if(target->type == BL_MOB) - mob_warp((struct mob_data *)target,-1,x,y,3); - } - } - else if(md && !map[src->m].flag.monster_noteleport) { - int x,y,i,j,c; - mob_warp(md,-1,-1,-1,3); - for(i=0;i<16;i++) { - j = MRAND(8); - x = md->bl.x + dirx[j]; - y = md->bl.y + diry[j]; - if((c=map_getcell(md->bl.m,x,y)) != 1 && c != 5) - break; - } - if(i >= 16) { - x = md->bl.x; - y = md->bl.y; - } - if(target->prev != NULL) { - if(target->type == BL_PC && !pc_isdead((struct map_session_data *)target)) - pc_setpos((struct map_session_data *)target,map[md->bl.m].name,x,y,3); - else if(target->type == BL_MOB) - mob_warp((struct mob_data *)target,-1,x,y,3); - } - } - break; + if (src->prev == NULL) + return 0; - case BA_FROSTJOKE: /* 寒いジョーク */ - case DC_SCREAM: /* スクリーム */ - range=15; //視界全体 - 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; + 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 + return 0; - 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; - } - } + nullpo_retr (0, skl); + + skl->timer = -1; + if (skl->target_id) + { + struct block_list tbl; + target = map_id2bl (skl->target_id); + if (skl->skill_id == RG_INTIMIDATE) + { + if (target == NULL) + { + target = &tbl; //初期化してないのにアドレス突っ込んでいいのかな? + target->type = BL_NUL; + target->m = src->m; + target->prev = target->next = NULL; + } + } + if (target == NULL) + return 0; + if (target->prev == NULL && skl->skill_id != RG_INTIMIDATE) + return 0; + if (src->m != target->m) + return 0; + if (sd && pc_isdead (sd)) + return 0; + if (target->type == BL_PC + && pc_isdead ((struct map_session_data *) target) + && skl->skill_id != RG_INTIMIDATE) + return 0; + + switch (skl->skill_id) + { + case TF_BACKSLIDING: + clif_skill_nodamage (src, src, skl->skill_id, skl->skill_lv, + 1); + break; + case RG_INTIMIDATE: + if (sd && !map[src->m].flag.noteleport) + { + int x, y, i, j, c; + pc_randomwarp (sd, 3); + for (i = 0; i < 16; i++) + { + j = MRAND (8); + x = sd->bl.x + dirx[j]; + y = sd->bl.y + diry[j]; + if ((c = map_getcell (sd->bl.m, x, y)) != 1 && c != 5) + break; + } + if (i >= 16) + { + x = sd->bl.x; + y = sd->bl.y; + } + if (target->prev != NULL) + { + if (target->type == BL_PC + && !pc_isdead ((struct map_session_data *) + target)) + pc_setpos ((struct map_session_data *) target, + map[sd->bl.m].name, x, y, 3); + else if (target->type == BL_MOB) + mob_warp ((struct mob_data *) target, -1, x, y, + 3); + } + } + else if (md && !map[src->m].flag.monster_noteleport) + { + int x, y, i, j, c; + mob_warp (md, -1, -1, -1, 3); + for (i = 0; i < 16; i++) + { + j = MRAND (8); + x = md->bl.x + dirx[j]; + y = md->bl.y + diry[j]; + if ((c = map_getcell (md->bl.m, x, y)) != 1 && c != 5) + break; + } + if (i >= 16) + { + x = md->bl.x; + y = md->bl.y; + } + if (target->prev != NULL) + { + if (target->type == BL_PC + && !pc_isdead ((struct map_session_data *) + target)) + pc_setpos ((struct map_session_data *) target, + map[md->bl.m].name, x, y, 3); + else if (target->type == BL_MOB) + mob_warp ((struct mob_data *) target, -1, x, y, + 3); + } + } + break; + + case BA_FROSTJOKE: /* 寒いジョーク */ + case DC_SCREAM: /* スクリーム */ + range = 15; //視界全体 + map_foreachinarea (skill_frostjoke_scream, src->m, + src->x - range, src->y - range, + src->x + range, src->y + range, 0, src, + skl->skill_id, skl->skill_lv, tick); + break; + + default: + skill_attack (skl->type, src, src, target, skl->skill_id, + skl->skill_lv, tick, skl->flag); + break; + } + } + else + { + if (src->m != skl->map) + return 0; + switch (skl->skill_id) + { + case WZ_METEOR: + if (skl->type >= 0) + { + skill_unitsetting (src, skl->skill_id, skl->skill_lv, + skl->type >> 16, skl->type & 0xFFFF, + 0); + clif_skill_poseffect (src, skl->skill_id, skl->skill_lv, + skl->x, skl->y, tick); + } + else + skill_unitsetting (src, skl->skill_id, skl->skill_lv, + skl->x, skl->y, 0); + break; + } + } - return 0; + 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 skill_addtimerskill (struct block_list *src, unsigned int tick, + int target, int x, int y, int skill_id, int skill_lv, + int type, int flag) { - int i; - - nullpo_retr(1, src); - - if(src->type == BL_PC) { - struct map_session_data *sd = (struct map_session_data *)src; - nullpo_retr(1, sd); - for(i=0;i<MAX_SKILLTIMERSKILL;i++) { - if(sd->skilltimerskill[i].timer == -1) { - sd->skilltimerskill[i].timer = add_timer(tick, skill_timerskill, src->id, i); - sd->skilltimerskill[i].src_id = src->id; - sd->skilltimerskill[i].target_id = target; - sd->skilltimerskill[i].skill_id = skill_id; - sd->skilltimerskill[i].skill_lv = skill_lv; - sd->skilltimerskill[i].map = src->m; - sd->skilltimerskill[i].x = x; - sd->skilltimerskill[i].y = y; - sd->skilltimerskill[i].type = type; - sd->skilltimerskill[i].flag = flag; - - return 0; - } - } - return 1; - } - else if(src->type == BL_MOB) { - struct mob_data *md = (struct mob_data *)src; - nullpo_retr(1, md); - for(i=0;i<MAX_MOBSKILLTIMERSKILL;i++) { - if(md->skilltimerskill[i].timer == -1) { - md->skilltimerskill[i].timer = add_timer(tick, skill_timerskill, src->id, i); - md->skilltimerskill[i].src_id = src->id; - md->skilltimerskill[i].target_id = target; - md->skilltimerskill[i].skill_id = skill_id; - md->skilltimerskill[i].skill_lv = skill_lv; - md->skilltimerskill[i].map = src->m; - md->skilltimerskill[i].x = x; - md->skilltimerskill[i].y = y; - md->skilltimerskill[i].type = type; - md->skilltimerskill[i].flag = flag; - - return 0; - } - } - return 1; - } + int i; + + nullpo_retr (1, src); + + if (src->type == BL_PC) + { + struct map_session_data *sd = (struct map_session_data *) src; + nullpo_retr (1, sd); + for (i = 0; i < MAX_SKILLTIMERSKILL; i++) + { + if (sd->skilltimerskill[i].timer == -1) + { + sd->skilltimerskill[i].timer = + add_timer (tick, skill_timerskill, src->id, i); + sd->skilltimerskill[i].src_id = src->id; + sd->skilltimerskill[i].target_id = target; + sd->skilltimerskill[i].skill_id = skill_id; + sd->skilltimerskill[i].skill_lv = skill_lv; + sd->skilltimerskill[i].map = src->m; + sd->skilltimerskill[i].x = x; + sd->skilltimerskill[i].y = y; + sd->skilltimerskill[i].type = type; + sd->skilltimerskill[i].flag = flag; + + return 0; + } + } + return 1; + } + else if (src->type == BL_MOB) + { + struct mob_data *md = (struct mob_data *) src; + nullpo_retr (1, md); + for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++) + { + if (md->skilltimerskill[i].timer == -1) + { + md->skilltimerskill[i].timer = + add_timer (tick, skill_timerskill, src->id, i); + md->skilltimerskill[i].src_id = src->id; + md->skilltimerskill[i].target_id = target; + md->skilltimerskill[i].skill_id = skill_id; + md->skilltimerskill[i].skill_lv = skill_lv; + md->skilltimerskill[i].map = src->m; + md->skilltimerskill[i].x = x; + md->skilltimerskill[i].y = y; + md->skilltimerskill[i].type = type; + md->skilltimerskill[i].flag = flag; + + return 0; + } + } + return 1; + } - return 1; + return 1; } /*========================================== * *------------------------------------------ */ -int skill_cleartimerskill(struct block_list *src) +int skill_cleartimerskill (struct block_list *src) { - int i; + int i; - nullpo_retr(0, src); + nullpo_retr (0, src); - if(src->type == BL_PC) { - struct map_session_data *sd = (struct map_session_data *)src; - nullpo_retr(0, sd); - for(i=0;i<MAX_SKILLTIMERSKILL;i++) { - if(sd->skilltimerskill[i].timer != -1) { - delete_timer(sd->skilltimerskill[i].timer, skill_timerskill); - sd->skilltimerskill[i].timer = -1; - } - } - } - else if(src->type == BL_MOB) { - struct mob_data *md = (struct mob_data *)src; - nullpo_retr(0, md); - for(i=0;i<MAX_MOBSKILLTIMERSKILL;i++) { - if(md->skilltimerskill[i].timer != -1) { - delete_timer(md->skilltimerskill[i].timer, skill_timerskill); - md->skilltimerskill[i].timer = -1; - } - } - } + if (src->type == BL_PC) + { + struct map_session_data *sd = (struct map_session_data *) src; + nullpo_retr (0, sd); + for (i = 0; i < MAX_SKILLTIMERSKILL; i++) + { + if (sd->skilltimerskill[i].timer != -1) + { + delete_timer (sd->skilltimerskill[i].timer, skill_timerskill); + sd->skilltimerskill[i].timer = -1; + } + } + } + else if (src->type == BL_MOB) + { + struct mob_data *md = (struct mob_data *) src; + nullpo_retr (0, md); + for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++) + { + if (md->skilltimerskill[i].timer != -1) + { + delete_timer (md->skilltimerskill[i].timer, skill_timerskill); + md->skilltimerskill[i].timer = -1; + } + } + } - return 0; + return 0; } /* 範囲スキル使用処理小分けここまで @@ -2043,3629 +2529,4471 @@ int skill_cleartimerskill(struct block_list *src) * (スパゲッティに向けて1歩前進!(ダメポ)) *------------------------------------------ */ -int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag ) +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; - int i; - - nullpo_retr(1, src); - nullpo_retr(1, bl); - - if(src->type==BL_PC) - sd=(struct map_session_data *)src; - if(sd && pc_isdead(sd)) - return 1; - - if((skillid == WZ_SIGHTRASHER || skillid == CR_GRANDCROSS) && src != bl) - bl = src; - if(bl->prev == NULL) - return 1; - if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) - return 1; - map_freeblock_lock(); - switch(skillid) - { - /* 武器攻撃系スキル */ - case SM_BASH: /* バッシュ */ - case MC_MAMMONITE: /* メマーナイト */ - case AC_DOUBLE: /* ダブルストレイフィング */ - case AS_SONICBLOW: /* ソニックブロー */ - case KN_PIERCE: /* ピアース */ - case KN_SPEARBOOMERANG: /* スピアブーメラン */ - case TF_POISON: /* インベナム */ - case TF_SPRINKLESAND: /* 砂まき */ - case AC_CHARGEARROW: /* チャージアロー */ - case KN_SPEARSTAB: /* スピアスタブ */ - case RG_RAID: /* サプライズアタック */ - case RG_INTIMIDATE: /* インティミデイト */ - case BA_MUSICALSTRIKE: /* ミュージカルストライク */ - case DC_THROWARROW: /* 矢撃ち */ - case BA_DISSONANCE: /* 不協和音 */ - case CR_HOLYCROSS: /* ホーリークロス */ - case CR_SHIELDCHARGE: - case CR_SHIELDBOOMERANG: - - /* 以下MOB専用 */ - /* 単体攻撃、SP減少攻撃、遠距離攻撃、防御無視攻撃、多段攻撃 */ - case NPC_PIERCINGATT: - case NPC_MENTALBREAKER: - case NPC_RANGEATTACK: - case NPC_CRITICALSLASH: - case NPC_COMBOATTACK: - /* 必中攻撃、毒攻撃、暗黒攻撃、沈黙攻撃、スタン攻撃 */ - case NPC_GUIDEDATTACK: - case NPC_POISON: - case NPC_BLINDATTACK: - case NPC_SILENCEATTACK: - case NPC_STUNATTACK: - /* 石化攻撃、呪い攻撃、睡眠攻撃、ランダムATK攻撃 */ - case NPC_PETRIFYATTACK: - case NPC_CURSEATTACK: - case NPC_SLEEPATTACK: - case NPC_RANDOMATTACK: - /* 水属性攻撃、地属性攻撃、火属性攻撃、風属性攻撃 */ - case NPC_WATERATTACK: - case NPC_GROUNDATTACK: - case NPC_FIREATTACK: - case NPC_WINDATTACK: - /* 毒属性攻撃、聖属性攻撃、闇属性攻撃、念属性攻撃、SP減少攻撃 */ - case NPC_POISONATTACK: - case NPC_HOLYATTACK: - case NPC_DARKNESSATTACK: - case NPC_TELEKINESISATTACK: - case LK_AURABLADE: /* オーラブレード */ - case LK_SPIRALPIERCE: /* スパイラルピアース */ - case LK_HEADCRUSH: /* ヘッドクラッシュ */ - case LK_JOINTBEAT: /* ジョイントビート */ - case PA_PRESSURE: /* プレッシャー */ - case PA_SACRIFICE: /* サクリファイス */ - case SN_SHARPSHOOTING: /* シャープシューティング */ - case CG_ARROWVULCAN: /* アローバルカン */ - case ASC_BREAKER: /* ソウルブレーカー */ - case HW_MAGICCRASHER: /* マジッククラッシャー */ - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - break; - case NPC_DARKBREATH: - clif_emotion(src,7); - skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); - break; - case MO_INVESTIGATE: /* 発勁 */ - { - struct status_change *sc_data = battle_get_sc_data(src); - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if(sc_data[SC_BLADESTOP].timer != -1) - skill_status_change_end(src,SC_BLADESTOP,-1); - } - break; - case SN_FALCONASSAULT: /* ファルコンアサルト */ - skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); - break; - case KN_BRANDISHSPEAR: /* ブランディッシュスピア */ - { - struct mob_data *md = (struct mob_data *)bl; - nullpo_retr(1, md); - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if(md->hp > 0){ - skill_blown(src,bl,skill_get_blewcount(skillid,skilllv)); - if(bl->type == BL_MOB) - clif_fixmobpos((struct mob_data *)bl); - else - clif_fixpos(bl); - } - } - break; - case RG_BACKSTAP: /* バックスタブ */ - { - int dir = map_calc_dir(src,bl->x,bl->y),t_dir = battle_get_dir(bl); - int dist = distance(src->x,src->y,bl->x,bl->y); - if((dist > 0 && !map_check_dir(dir,t_dir)) || bl->type == BL_SKILL) { - struct status_change *sc_data = battle_get_sc_data(src); - if(sc_data && sc_data[SC_HIDING].timer != -1) - skill_status_change_end(src, SC_HIDING, -1); // ハイディング解除 - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - 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: /* アシッドテラー */ - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if(bl->type == BL_PC && MRAND(100) < skill_get_time(skillid,skilllv) && battle_config.equipment_breaking) - pc_breakarmor((struct map_session_data *)bl); - break; - case MO_FINGEROFFENSIVE: /* 指弾 */ - { - struct status_change *sc_data = battle_get_sc_data(src); - - if(!battle_config.finger_offensive_type) - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - else { - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if(sd) { - for(i=1;i<sd->spiritball_old;i++) - skill_addtimerskill(src,tick+i*200,bl->id,0,0,skillid,skilllv,BF_WEAPON,flag); - sd->canmove_tick = tick + (sd->spiritball_old-1)*200; - } - } - if(sc_data && sc_data[SC_BLADESTOP].timer != -1) - skill_status_change_end(src,SC_BLADESTOP,-1); - } - break; - case MO_CHAINCOMBO: /* 連打掌 */ - { - struct status_change *sc_data = battle_get_sc_data(src); - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if(sc_data && sc_data[SC_BLADESTOP].timer != -1) - skill_status_change_end(src,SC_BLADESTOP,-1); - } - break; - case MO_COMBOFINISH: /* 猛龍拳 */ - case CH_TIGERFIST: /* 伏虎拳 */ - case CH_CHAINCRUSH: /* 連柱崩撃 */ - case CH_PALMSTRIKE: /* 猛虎硬派山 */ - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - break; - case MO_EXTREMITYFIST: /* 阿修羅覇鳳拳 */ - { - struct status_change *sc_data = battle_get_sc_data(src); - - if(sd) { - struct walkpath_data wpd; - int dx,dy; - - dx = bl->x - sd->bl.x; - dy = bl->y - sd->bl.y; - if(dx > 0) dx++; - else if(dx < 0) dx--; - if(dy > 0) dy++; - else if(dy < 0) dy--; - if(dx == 0 && dy == 0) dx++; - if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) { - dx = bl->x - sd->bl.x; - dy = bl->y - sd->bl.y; - if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) { - clif_skill_fail(sd,sd->skillid,0,0); - break; - } - } - sd->to_x = sd->bl.x + dx; - sd->to_y = sd->bl.y + dy; - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - clif_walkok(sd); - clif_movechar(sd); - if(dx < 0) dx = -dx; - if(dy < 0) dy = -dy; - sd->attackabletime = sd->canmove_tick = tick + 100 + sd->speed * ((dx > dy)? dx:dy); - if(sd->canact_tick < sd->canmove_tick) - sd->canact_tick = sd->canmove_tick; - pc_movepos(sd,sd->to_x,sd->to_y); - skill_status_change_end(&sd->bl,SC_COMBO,-1); - } - else - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - skill_status_change_end(src, SC_EXPLOSIONSPIRITS, -1); - if(sc_data && sc_data[SC_BLADESTOP].timer != -1) - skill_status_change_end(src,SC_BLADESTOP,-1); - } - break; - /* 武器系範囲攻撃スキル */ - case AC_SHOWER: /* アローシャワー */ - case SM_MAGNUM: /* マグナムブレイク */ - case AS_GRIMTOOTH: /* グリムトゥース */ - case MC_CARTREVOLUTION: /* カートレヴォリューション */ - case NPC_SPLASHATTACK: /* スプラッシュアタック */ - case ASC_METEORASSAULT: /* メテオアサルト */ - case AS_SPLASHER: /* [Valaris] */ - if(flag&1){ - /* 個別にダメージを与える */ - if(bl->id!=skill_area_temp[1]){ - int dist=0; - if(skillid==SM_MAGNUM){ /* マグナムブレイクなら中心からの距離を計算 */ - int dx=abs( bl->x - skill_area_temp[2] ); - int dy=abs( bl->y - skill_area_temp[3] ); - dist=((dx>dy)?dx:dy); - } - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick, - 0x0500|dist ); - } - }else{ - int ar=1; - int x=bl->x,y=bl->y; - if( skillid==SM_MAGNUM){ - x=src->x; - y=src->y; - }else if(skillid==AC_SHOWER || skillid==ASC_METEORASSAULT) /* アローシャワー、メテオアサルト範囲5*5 */ - ar=2; - else if(skillid==AS_SPLASHER) /* ベナムスプラッシャー範囲3*3 */ - ar=1; - else if(skillid==NPC_SPLASHATTACK) /* スプラッシュアタックは範囲7*7 */ - ar=3; - skill_area_temp[1]=bl->id; - skill_area_temp[2]=x; - skill_area_temp[3]=y; - /* まずターゲットに攻撃を加える */ - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0); - /* その後ターゲット以外の範囲内の敵全体に処理を行う */ - 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; + struct map_session_data *sd = NULL; + int i; + + nullpo_retr (1, src); + nullpo_retr (1, bl); + + if (src->type == BL_PC) + sd = (struct map_session_data *) src; + if (sd && pc_isdead (sd)) + return 1; + + if ((skillid == WZ_SIGHTRASHER || skillid == CR_GRANDCROSS) && src != bl) + bl = src; + if (bl->prev == NULL) + return 1; + if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl)) + return 1; + map_freeblock_lock (); + switch (skillid) + { + /* 武器攻撃系スキル */ + case SM_BASH: /* バッシュ */ + case MC_MAMMONITE: /* メマーナイト */ + case AC_DOUBLE: /* ダブルストレイフィング */ + case AS_SONICBLOW: /* ソニックブロー */ + case KN_PIERCE: /* ピアース */ + case KN_SPEARBOOMERANG: /* スピアブーメラン */ + case TF_POISON: /* インベナム */ + case TF_SPRINKLESAND: /* 砂まき */ + case AC_CHARGEARROW: /* チャージアロー */ + case KN_SPEARSTAB: /* スピアスタブ */ + case RG_RAID: /* サプライズアタック */ + case RG_INTIMIDATE: /* インティミデイト */ + case BA_MUSICALSTRIKE: /* ミュージカルストライク */ + case DC_THROWARROW: /* 矢撃ち */ + case BA_DISSONANCE: /* 不協和音 */ + case CR_HOLYCROSS: /* ホーリークロス */ + case CR_SHIELDCHARGE: + case CR_SHIELDBOOMERANG: + + /* 以下MOB専用 */ + /* 単体攻撃、SP減少攻撃、遠距離攻撃、防御無視攻撃、多段攻撃 */ + case NPC_PIERCINGATT: + case NPC_MENTALBREAKER: + case NPC_RANGEATTACK: + case NPC_CRITICALSLASH: + case NPC_COMBOATTACK: + /* 必中攻撃、毒攻撃、暗黒攻撃、沈黙攻撃、スタン攻撃 */ + case NPC_GUIDEDATTACK: + case NPC_POISON: + case NPC_BLINDATTACK: + case NPC_SILENCEATTACK: + case NPC_STUNATTACK: + /* 石化攻撃、呪い攻撃、睡眠攻撃、ランダムATK攻撃 */ + case NPC_PETRIFYATTACK: + case NPC_CURSEATTACK: + case NPC_SLEEPATTACK: + case NPC_RANDOMATTACK: + /* 水属性攻撃、地属性攻撃、火属性攻撃、風属性攻撃 */ + case NPC_WATERATTACK: + case NPC_GROUNDATTACK: + case NPC_FIREATTACK: + case NPC_WINDATTACK: + /* 毒属性攻撃、聖属性攻撃、闇属性攻撃、念属性攻撃、SP減少攻撃 */ + case NPC_POISONATTACK: + case NPC_HOLYATTACK: + case NPC_DARKNESSATTACK: + case NPC_TELEKINESISATTACK: + case LK_AURABLADE: /* オーラブレード */ + case LK_SPIRALPIERCE: /* スパイラルピアース */ + case LK_HEADCRUSH: /* ヘッドクラッシュ */ + case LK_JOINTBEAT: /* ジョイントビート */ + case PA_PRESSURE: /* プレッシャー */ + case PA_SACRIFICE: /* サクリファイス */ + case SN_SHARPSHOOTING: /* シャープシューティング */ + case CG_ARROWVULCAN: /* アローバルカン */ + case ASC_BREAKER: /* ソウルブレーカー */ + case HW_MAGICCRASHER: /* マジッククラッシャー */ + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + flag); + break; + case NPC_DARKBREATH: + clif_emotion (src, 7); + skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick, + flag); + break; + case MO_INVESTIGATE: /* 発勁 */ + { + struct status_change *sc_data = battle_get_sc_data (src); + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + flag); + if (sc_data[SC_BLADESTOP].timer != -1) + skill_status_change_end (src, SC_BLADESTOP, -1); + } + break; + case SN_FALCONASSAULT: /* ファルコンアサルト */ + skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick, + flag); + break; + case KN_BRANDISHSPEAR: /* ブランディッシュスピア */ + { + struct mob_data *md = (struct mob_data *) bl; + nullpo_retr (1, md); + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + flag); + if (md->hp > 0) + { + skill_blown (src, bl, skill_get_blewcount (skillid, skilllv)); + if (bl->type == BL_MOB) + clif_fixmobpos ((struct mob_data *) bl); + else + clif_fixpos (bl); + } + } + break; + case RG_BACKSTAP: /* バックスタブ */ + { + int dir = map_calc_dir (src, bl->x, bl->y), t_dir = + battle_get_dir (bl); + int dist = distance (src->x, src->y, bl->x, bl->y); + if ((dist > 0 && !map_check_dir (dir, t_dir)) + || bl->type == BL_SKILL) + { + struct status_change *sc_data = battle_get_sc_data (src); + if (sc_data && sc_data[SC_HIDING].timer != -1) + skill_status_change_end (src, SC_HIDING, -1); // ハイディング解除 + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + flag); + 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 KN_BOWLINGBASH: /* ボウリングバッシュ */ - if(flag&1){ - /* 個別にダメージを与える */ - if(bl->id!=skill_area_temp[1]) - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500); - } - else { - int damage; - map_freeblock_lock(); - damage = skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0); - if(damage > 0) { - int i,c; /* 他人から聞いた動きなので間違ってる可能性大&効率が悪いっす>< */ - 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 - clif_fixpos(bl); - skill_area_temp[0]=0; - map_foreachinarea(skill_area_sub, - bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY , - skill_area_sub_count); - if(skill_area_temp[0]>1) break; - } - skill_area_temp[1]=bl->id; - skill_area_temp[2]=bl->x; - skill_area_temp[3]=bl->y; - /* その後ターゲット以外の範囲内の敵全体に処理を行う */ - map_foreachinarea(skill_area_sub, - bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - battle_damage(src,bl,damage,1); - if(rdamage > 0) - battle_damage(bl,src,rdamage,0); - } - map_freeblock_unlock(); - } - break; - - case ALL_RESURRECTION: /* リザレクション */ - case PR_TURNUNDEAD: /* ターンアンデッド */ - if(bl->type != BL_PC && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - else { - map_freeblock_unlock(); - return 1; - } - break; - - /* 魔法系スキル */ - case MG_SOULSTRIKE: /* ソウルストライク */ - case MG_COLDBOLT: /* コールドボルト */ - case MG_FIREBOLT: /* ファイアーボルト */ - case MG_LIGHTNINGBOLT: /* ライトニングボルト */ - case WZ_EARTHSPIKE: /* アーススパイク */ - case AL_HEAL: /* ヒール */ - case AL_HOLYLIGHT: /* ホーリーライト */ - case MG_FROSTDIVER: /* フロストダイバー */ - case WZ_JUPITEL: /* ユピテルサンダー */ - case NPC_MAGICALATTACK: /* MOB:魔法打撃攻撃 */ - case PR_ASPERSIO: /* アスペルシオ */ - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - break; - - case WZ_WATERBALL: /* ウォーターボール */ - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - if(skilllv>1) - skill_status_change_start(src,SC_WATERBALL,skilllv,bl->id,0,0,0,0); - break; - - case PR_BENEDICTIO: /* 聖体降福 */ - if(battle_get_race(bl)==1 || battle_get_race(bl)==6) - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - break; - - /* 魔法系範囲攻撃スキル */ - case MG_NAPALMBEAT: /* ナパームビート */ - case MG_FIREBALL: /* ファイヤーボール */ - if(flag&1){ - /* 個別にダメージを与える */ - if(bl->id!=skill_area_temp[1]){ - if(skillid==MG_FIREBALL){ /* ファイヤーボールなら中心からの距離を計算 */ - int dx=abs( bl->x - skill_area_temp[2] ); - int dy=abs( bl->y - skill_area_temp[3] ); - skill_area_temp[0]=((dx>dy)?dx:dy); - } - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick, - skill_area_temp[0]| 0x0500); - } - }else{ - int ar=(skillid==MG_NAPALMBEAT)?1:2; - skill_area_temp[1]=bl->id; - if(skillid==MG_NAPALMBEAT){ /* ナパームでは先に数える */ - 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 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 AM_ACIDTERROR: /* アシッドテラー */ + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + flag); + if (bl->type == BL_PC + && MRAND (100) < skill_get_time (skillid, skilllv) + && battle_config.equipment_breaking) + pc_breakarmor ((struct map_session_data *) bl); + break; + case MO_FINGEROFFENSIVE: /* 指弾 */ + { + struct status_change *sc_data = battle_get_sc_data (src); + + if (!battle_config.finger_offensive_type) + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + flag); + else + { + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + flag); + if (sd) + { + for (i = 1; i < sd->spiritball_old; i++) + skill_addtimerskill (src, tick + i * 200, bl->id, 0, + 0, skillid, skilllv, BF_WEAPON, + flag); + sd->canmove_tick = tick + (sd->spiritball_old - 1) * 200; + } + } + if (sc_data && sc_data[SC_BLADESTOP].timer != -1) + skill_status_change_end (src, SC_BLADESTOP, -1); + } + break; + case MO_CHAINCOMBO: /* 連打掌 */ + { + struct status_change *sc_data = battle_get_sc_data (src); + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + flag); + if (sc_data && sc_data[SC_BLADESTOP].timer != -1) + skill_status_change_end (src, SC_BLADESTOP, -1); + } + break; + case MO_COMBOFINISH: /* 猛龍拳 */ + case CH_TIGERFIST: /* 伏虎拳 */ + case CH_CHAINCRUSH: /* 連柱崩撃 */ + case CH_PALMSTRIKE: /* 猛虎硬派山 */ + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + flag); + break; + case MO_EXTREMITYFIST: /* 阿修羅覇鳳拳 */ + { + struct status_change *sc_data = battle_get_sc_data (src); + + if (sd) + { + struct walkpath_data wpd; + int dx, dy; + + dx = bl->x - sd->bl.x; + dy = bl->y - sd->bl.y; + if (dx > 0) + dx++; + else if (dx < 0) + dx--; + if (dy > 0) + dy++; + else if (dy < 0) + dy--; + if (dx == 0 && dy == 0) + dx++; + if (path_search + (&wpd, src->m, sd->bl.x, sd->bl.y, sd->bl.x + dx, + sd->bl.y + dy, 1) == -1) + { + dx = bl->x - sd->bl.x; + dy = bl->y - sd->bl.y; + if (path_search + (&wpd, src->m, sd->bl.x, sd->bl.y, sd->bl.x + dx, + sd->bl.y + dy, 1) == -1) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + break; + } + } + sd->to_x = sd->bl.x + dx; + sd->to_y = sd->bl.y + dy; + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + flag); + clif_walkok (sd); + clif_movechar (sd); + if (dx < 0) + dx = -dx; + if (dy < 0) + dy = -dy; + sd->attackabletime = sd->canmove_tick = + tick + 100 + sd->speed * ((dx > dy) ? dx : dy); + if (sd->canact_tick < sd->canmove_tick) + sd->canact_tick = sd->canmove_tick; + pc_movepos (sd, sd->to_x, sd->to_y); + skill_status_change_end (&sd->bl, SC_COMBO, -1); + } + else + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + flag); + skill_status_change_end (src, SC_EXPLOSIONSPIRITS, -1); + if (sc_data && sc_data[SC_BLADESTOP].timer != -1) + skill_status_change_end (src, SC_BLADESTOP, -1); + } + break; + /* 武器系範囲攻撃スキル */ + case AC_SHOWER: /* アローシャワー */ + case SM_MAGNUM: /* マグナムブレイク */ + case AS_GRIMTOOTH: /* グリムトゥース */ + case MC_CARTREVOLUTION: /* カートレヴォリューション */ + case NPC_SPLASHATTACK: /* スプラッシュアタック */ + case ASC_METEORASSAULT: /* メテオアサルト */ + case AS_SPLASHER: /* [Valaris] */ + if (flag & 1) + { + /* 個別にダメージを与える */ + if (bl->id != skill_area_temp[1]) + { + int dist = 0; + if (skillid == SM_MAGNUM) + { /* マグナムブレイクなら中心からの距離を計算 */ + int dx = abs (bl->x - skill_area_temp[2]); + int dy = abs (bl->y - skill_area_temp[3]); + dist = ((dx > dy) ? dx : dy); + } + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, + tick, 0x0500 | dist); + } + } + else + { + int ar = 1; + int x = bl->x, y = bl->y; + if (skillid == SM_MAGNUM) + { + x = src->x; + y = src->y; + } + else if (skillid == AC_SHOWER || skillid == ASC_METEORASSAULT) /* アローシャワー、メテオアサルト範囲5*5 */ + ar = 2; + else if (skillid == AS_SPLASHER) /* ベナムスプラッシャー範囲3*3 */ + ar = 1; + else if (skillid == NPC_SPLASHATTACK) /* スプラッシュアタックは範囲7*7 */ + ar = 3; + skill_area_temp[1] = bl->id; + skill_area_temp[2] = x; + skill_area_temp[3] = y; + /* まずターゲットに攻撃を加える */ + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick, + 0); + /* その後ターゲット以外の範囲内の敵全体に処理を行う */ + 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 WZ_FROSTNOVA: /* フロストノヴァ */ - skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0); - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - break; - - case WZ_SIGHTRASHER: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0); - skill_status_change_end(src,SC_SIGHT,-1); - break; - - /* その他 */ - case HT_BLITZBEAT: /* ブリッツビート */ - if(flag&1){ - /* 個別にダメージを与える */ - 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); - /* まずターゲットに攻撃を加える */ - skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,skill_area_temp[0]|(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|1, - skill_castend_damage_id); - } - break; - - case CR_GRANDCROSS: /* グランドクロス */ - /* スキルユニット配置 */ - skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0); - if(sd) - sd->canmove_tick = tick + 1000; - else if(src->type == BL_MOB) - mob_changestate((struct mob_data *)src,MS_DELAY,1000); - break; - - case TF_THROWSTONE: /* 石投げ */ - case NPC_SMOKING: /* スモーキング */ - skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,0 ); - break; - - case NPC_SELFDESTRUCTION: /* 自爆 */ - case NPC_SELFDESTRUCTION2: /* 自爆2 */ - if(flag&1){ - /* 個別にダメージを与える */ - if(src->type==BL_MOB){ - struct mob_data* mb = (struct mob_data*)src; - nullpo_retr(1, mb); - mb->hp=skill_area_temp[2]; - if(bl->id!=skill_area_temp[1]) - skill_attack(BF_MISC,src,src,bl,NPC_SELFDESTRUCTION,skilllv,tick,flag ); - mb->hp=1; - } - }else{ - struct mob_data *md; - if((md=(struct mob_data *)src)){ - skill_area_temp[1]=bl->id; - skill_area_temp[2]=battle_get_hp(src); - clif_skill_nodamage(src,src,NPC_SELFDESTRUCTION,-1,1); - map_foreachinarea(skill_area_sub, - bl->m,bl->x-5,bl->y-5,bl->x+5,bl->y+5,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - battle_damage(src,src,md->hp,0); - } - } - break; - - /* HP吸収/HP吸収魔法 */ - case NPC_BLOODDRAIN: - case NPC_ENERGYDRAIN: - { - int heal; - heal = skill_attack((skillid==NPC_BLOODDRAIN)?BF_WEAPON:BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - if( heal > 0 ){ - struct block_list tbl; - tbl.id = 0; - tbl.m = src->m; - tbl.x = src->x; - tbl.y = src->y; - clif_skill_nodamage(&tbl,src,AL_HEAL,heal,1); - battle_heal(NULL,src,heal,0,0); - } - } - break; - case 0: - if(sd) { - if(flag&3){ - if(bl->id!=skill_area_temp[1]) - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500); - } - else{ - int ar=sd->splash_range; - skill_area_temp[1]=bl->id; - map_foreachinarea(skill_area_sub, - bl->m, bl->x - ar, bl->y - ar, bl->x + ar, bl->y + ar, 0, - src, skillid, skilllv, tick, flag | BCT_ENEMY | 1, - skill_castend_damage_id); - } - } - break; + case KN_BOWLINGBASH: /* ボウリングバッシュ */ + if (flag & 1) + { + /* 個別にダメージを与える */ + if (bl->id != skill_area_temp[1]) + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, + tick, 0x0500); + } + else + { + int damage; + map_freeblock_lock (); + damage = + skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, + tick, 0); + if (damage > 0) + { + int i, c; /* 他人から聞いた動きなので間違ってる可能性大&効率が悪いっす>< */ + 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 + clif_fixpos (bl); + skill_area_temp[0] = 0; + map_foreachinarea (skill_area_sub, + bl->m, bl->x - 1, bl->y - 1, + bl->x + 1, bl->y + 1, 0, src, + skillid, skilllv, tick, + flag | BCT_ENEMY, + skill_area_sub_count); + if (skill_area_temp[0] > 1) + break; + } + skill_area_temp[1] = bl->id; + skill_area_temp[2] = bl->x; + skill_area_temp[3] = bl->y; + /* その後ターゲット以外の範囲内の敵全体に処理を行う */ + map_foreachinarea (skill_area_sub, + bl->m, bl->x - 1, bl->y - 1, bl->x + 1, + bl->y + 1, 0, src, skillid, skilllv, + tick, flag | BCT_ENEMY | 1, + skill_castend_damage_id); + battle_damage (src, bl, damage, 1); + if (rdamage > 0) + battle_damage (bl, src, rdamage, 0); + } + map_freeblock_unlock (); + } + break; - default: - map_freeblock_unlock(); - return 1; - } - map_freeblock_unlock(); + case ALL_RESURRECTION: /* リザレクション */ + case PR_TURNUNDEAD: /* ターンアンデッド */ + if (bl->type != BL_PC + && battle_check_undead (battle_get_race (bl), + battle_get_elem_type (bl))) + skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick, + flag); + else + { + map_freeblock_unlock (); + return 1; + } + break; + + /* 魔法系スキル */ + case MG_SOULSTRIKE: /* ソウルストライク */ + case MG_COLDBOLT: /* コールドボルト */ + case MG_FIREBOLT: /* ファイアーボルト */ + case MG_LIGHTNINGBOLT: /* ライトニングボルト */ + case WZ_EARTHSPIKE: /* アーススパイク */ + case AL_HEAL: /* ヒール */ + case AL_HOLYLIGHT: /* ホーリーライト */ + case MG_FROSTDIVER: /* フロストダイバー */ + case WZ_JUPITEL: /* ユピテルサンダー */ + case NPC_MAGICALATTACK: /* MOB:魔法打撃攻撃 */ + case PR_ASPERSIO: /* アスペルシオ */ + skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick, + flag); + break; + + case WZ_WATERBALL: /* ウォーターボール */ + skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick, + flag); + if (skilllv > 1) + skill_status_change_start (src, SC_WATERBALL, skilllv, bl->id, + 0, 0, 0, 0); + break; + + case PR_BENEDICTIO: /* 聖体降福 */ + if (battle_get_race (bl) == 1 || battle_get_race (bl) == 6) + skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick, + flag); + break; + + /* 魔法系範囲攻撃スキル */ + case MG_NAPALMBEAT: /* ナパームビート */ + case MG_FIREBALL: /* ファイヤーボール */ + if (flag & 1) + { + /* 個別にダメージを与える */ + if (bl->id != skill_area_temp[1]) + { + if (skillid == MG_FIREBALL) + { /* ファイヤーボールなら中心からの距離を計算 */ + int dx = abs (bl->x - skill_area_temp[2]); + int dy = abs (bl->y - skill_area_temp[3]); + skill_area_temp[0] = ((dx > dy) ? dx : dy); + } + skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, + tick, skill_area_temp[0] | 0x0500); + } + } + else + { + int ar = (skillid == MG_NAPALMBEAT) ? 1 : 2; + skill_area_temp[1] = bl->id; + if (skillid == MG_NAPALMBEAT) + { /* ナパームでは先に数える */ + 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 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; - return 0; + case WZ_FROSTNOVA: /* フロストノヴァ */ + skill_castend_pos2 (src, bl->x, bl->y, skillid, skilllv, tick, 0); + skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick, + flag); + break; + + case WZ_SIGHTRASHER: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_castend_pos2 (src, bl->x, bl->y, skillid, skilllv, tick, 0); + skill_status_change_end (src, SC_SIGHT, -1); + break; + + /* その他 */ + case HT_BLITZBEAT: /* ブリッツビート */ + if (flag & 1) + { + /* 個別にダメージを与える */ + 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); + /* まずターゲットに攻撃を加える */ + skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick, + skill_area_temp[0] | (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 | 1, + skill_castend_damage_id); + } + break; + + case CR_GRANDCROSS: /* グランドクロス */ + /* スキルユニット配置 */ + skill_castend_pos2 (src, bl->x, bl->y, skillid, skilllv, tick, 0); + if (sd) + sd->canmove_tick = tick + 1000; + else if (src->type == BL_MOB) + mob_changestate ((struct mob_data *) src, MS_DELAY, 1000); + break; + + case TF_THROWSTONE: /* 石投げ */ + case NPC_SMOKING: /* スモーキング */ + skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick, 0); + break; + + case NPC_SELFDESTRUCTION: /* 自爆 */ + case NPC_SELFDESTRUCTION2: /* 自爆2 */ + if (flag & 1) + { + /* 個別にダメージを与える */ + if (src->type == BL_MOB) + { + struct mob_data *mb = (struct mob_data *) src; + nullpo_retr (1, mb); + mb->hp = skill_area_temp[2]; + if (bl->id != skill_area_temp[1]) + skill_attack (BF_MISC, src, src, bl, + NPC_SELFDESTRUCTION, skilllv, tick, + flag); + mb->hp = 1; + } + } + else + { + struct mob_data *md; + if ((md = (struct mob_data *) src)) + { + skill_area_temp[1] = bl->id; + skill_area_temp[2] = battle_get_hp (src); + clif_skill_nodamage (src, src, NPC_SELFDESTRUCTION, -1, + 1); + map_foreachinarea (skill_area_sub, bl->m, bl->x - 5, + bl->y - 5, bl->x + 5, bl->y + 5, 0, + src, skillid, skilllv, tick, + flag | BCT_ENEMY | 1, + skill_castend_damage_id); + battle_damage (src, src, md->hp, 0); + } + } + break; + + /* HP吸収/HP吸収魔法 */ + case NPC_BLOODDRAIN: + case NPC_ENERGYDRAIN: + { + int heal; + heal = + skill_attack ((skillid == + NPC_BLOODDRAIN) ? BF_WEAPON : BF_MAGIC, src, + src, bl, skillid, skilllv, tick, flag); + if (heal > 0) + { + struct block_list tbl; + tbl.id = 0; + tbl.m = src->m; + tbl.x = src->x; + tbl.y = src->y; + clif_skill_nodamage (&tbl, src, AL_HEAL, heal, 1); + battle_heal (NULL, src, heal, 0, 0); + } + } + break; + case 0: + if (sd) + { + if (flag & 3) + { + if (bl->id != skill_area_temp[1]) + skill_attack (BF_WEAPON, src, src, bl, skillid, + skilllv, tick, 0x0500); + } + else + { + int ar = sd->splash_range; + skill_area_temp[1] = bl->id; + map_foreachinarea (skill_area_sub, + bl->m, bl->x - ar, bl->y - ar, + bl->x + ar, bl->y + ar, 0, src, + skillid, skilllv, tick, + flag | BCT_ENEMY | 1, + skill_castend_damage_id); + } + } + break; + + default: + map_freeblock_unlock (); + return 1; + } + map_freeblock_unlock (); + + return 0; } /*========================================== * スキル使用(詠唱完了、ID指定支援系) *------------------------------------------ */ -int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag ) +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; - int sc_def_vit,sc_def_mdef,strip_fix,strip_time,strip_per; - int sc_dex,sc_luk; - //クラスチェンジ用ボスモンスターID - int changeclass[]={1038,1039,1046,1059,1086,1087,1112,1115 - ,1157,1159,1190,1272,1312,1373,1492}; - int poringclass[]={1002}; - - nullpo_retr(1, src); - nullpo_retr(1, bl); - - if(src->type==BL_PC) - sd=(struct map_session_data *)src; - else if(src->type==BL_MOB) - md=(struct mob_data *)src; - - sc_dex=battle_get_mdef(bl); - sc_luk=battle_get_luk(bl); - sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3); - sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3); - sc_def_mdef = 100 - (3 + battle_get_mdef(bl) + battle_get_luk(bl)/3); - strip_fix = battle_get_dex(src) - battle_get_dex(bl); - - if(bl->type==BL_PC){ - nullpo_retr(1, dstsd=(struct map_session_data *)bl); - }else if(bl->type==BL_MOB){ - nullpo_retr(1, dstmd=(struct mob_data *)bl); - if(sc_def_vit>50) - sc_def_vit=50; - if(sc_def_mdef>50) - sc_def_mdef=50; - } - if(sc_def_vit < 0) - sc_def_vit=0; - if(sc_def_mdef < 0) - sc_def_mdef=0; - if(strip_fix < 0) - strip_fix=0; - - if(bl == NULL || bl->prev == NULL) - return 1; - if(sd && pc_isdead(sd)) - return 1; - if(dstsd && pc_isdead(dstsd) && skillid != ALL_RESURRECTION) - return 1; - if(battle_get_class(bl) == 1288) - return 1; - if (skillnotok(skillid, (struct map_session_data *)bl)) // [MouseJstr] - return 0; + struct map_session_data *sd = NULL; + struct map_session_data *dstsd = NULL; + struct mob_data *md = NULL; + struct mob_data *dstmd = NULL; + int i; + int sc_def_vit, sc_def_mdef, strip_fix, strip_time, strip_per; + int sc_dex, sc_luk; + //クラスチェンジ用ボスモンスターID + int changeclass[] = + { 1038, 1039, 1046, 1059, 1086, 1087, 1112, 1115, 1157, 1159, 1190, + 1272, 1312, 1373, 1492 + }; + int poringclass[] = { 1002 }; + + nullpo_retr (1, src); + nullpo_retr (1, bl); + + if (src->type == BL_PC) + sd = (struct map_session_data *) src; + else if (src->type == BL_MOB) + md = (struct mob_data *) src; + + sc_dex = battle_get_mdef (bl); + sc_luk = battle_get_luk (bl); + sc_def_vit = 100 - (3 + battle_get_vit (bl) + battle_get_luk (bl) / 3); + sc_def_vit = 100 - (3 + battle_get_vit (bl) + battle_get_luk (bl) / 3); + sc_def_mdef = 100 - (3 + battle_get_mdef (bl) + battle_get_luk (bl) / 3); + strip_fix = battle_get_dex (src) - battle_get_dex (bl); + + if (bl->type == BL_PC) + { + nullpo_retr (1, dstsd = (struct map_session_data *) bl); + } + else if (bl->type == BL_MOB) + { + nullpo_retr (1, dstmd = (struct mob_data *) bl); + if (sc_def_vit > 50) + sc_def_vit = 50; + if (sc_def_mdef > 50) + sc_def_mdef = 50; + } + if (sc_def_vit < 0) + sc_def_vit = 0; + if (sc_def_mdef < 0) + sc_def_mdef = 0; + if (strip_fix < 0) + strip_fix = 0; + + if (bl == NULL || bl->prev == NULL) + return 1; + if (sd && pc_isdead (sd)) + return 1; + if (dstsd && pc_isdead (dstsd) && skillid != ALL_RESURRECTION) + return 1; + if (battle_get_class (bl) == 1288) + return 1; + if (skillnotok (skillid, (struct map_session_data *) bl)) // [MouseJstr] + return 0; - map_freeblock_lock(); - switch(skillid) - { - case AL_HEAL: /* ヒール */ - { - 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; /* 黄金蟲カード(ヒール量0) */ - if (sd){ - s_class = pc_calc_base_job(sd->status.class); - if((skill=pc_checkskill(sd,HP_MEDITATIO))>0) // メディテイティオ - heal += heal*(skill*2/100); - if(sd && dstsd && sd->status.partner_id == dstsd->status.char_id && s_class.job == 23 && sd->status.sex == 0) //自分も対象もPC、対象が自分のパートナー、自分がスパノビ、自分が♀なら - heal = heal*2; //スパノビの嫁が旦那にヒールすると2倍になる - } - + map_freeblock_lock (); + switch (skillid) + { + case AL_HEAL: /* ヒール */ + { + 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; /* 黄金蟲カード(ヒール量0) */ + if (sd) + { + s_class = pc_calc_base_job (sd->status.class); + if ((skill = pc_checkskill (sd, HP_MEDITATIO)) > 0) // メディテイティオ + heal += heal * (skill * 2 / 100); + if (sd && dstsd && sd->status.partner_id == dstsd->status.char_id && s_class.job == 23 && sd->status.sex == 0) //自分も対象もPC、対象が自分のパートナー、自分がスパノビ、自分が♀なら + heal = heal * 2; //スパノビの嫁が旦那にヒールすると2倍になる + } + + clif_skill_nodamage (src, bl, skillid, heal, 1); + heal_get_jobexp = battle_heal (NULL, bl, heal, 0, 0); + + // JOB経験値獲得 + 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; - clif_skill_nodamage(src,bl,skillid,heal,1); - heal_get_jobexp = battle_heal(NULL,bl,heal,0,0); + case ALL_RESURRECTION: /* リザレクション */ + 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で復活不可能状態 */ + + if (pc_isdead (tsd)) + { /* 死亡判定 */ + 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) + { /* オシリスカード */ + 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; - // JOB経験値獲得 - 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: /* リザレクション */ - 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で復活不可能状態 */ - - if(pc_isdead(tsd)){ /* 死亡判定 */ - 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 ){ /* オシリスカード */ - 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: /* 速度減少 */ + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + if (MRAND (100) < + (50 + skilllv * 3 + + (battle_get_lv (src) + battle_get_int (src) / 5) - + sc_def_mdef)) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, + SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), + 0); + } + break; - case AL_DECAGI: /* 速度減少 */ - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if( MRAND(100) < (50+skilllv*3+(battle_get_lv(src)+battle_get_int(src)/5)-sc_def_mdef) ) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - } - break; - - case AL_CRUCIS: - if(flag&1) { - int race = battle_get_race(bl),ele = battle_get_elem_type(bl); - if(battle_check_target(src,bl,BCT_ENEMY) && (race == 6 || battle_check_undead(race,ele))) { - int slv=battle_get_lv(src),tlv=battle_get_lv(bl),rate; - rate = 25 + skilllv*2 + slv - tlv; - if(MRAND(100) < rate) - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,0,0); - } - } - else { - int range = 15; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinarea(skill_area_sub, - src->m,src->x-range,src->y-range,src->x+range,src->y+range,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_nodamage_id); - } - break; + case AL_CRUCIS: + if (flag & 1) + { + int race = battle_get_race (bl), ele = + battle_get_elem_type (bl); + if (battle_check_target (src, bl, BCT_ENEMY) + && (race == 6 || battle_check_undead (race, ele))) + { + int slv = battle_get_lv (src), tlv = + battle_get_lv (bl), rate; + rate = 25 + skilllv * 2 + slv - tlv; + if (MRAND (100) < rate) + skill_status_change_start (bl, + SkillStatusChangeTable + [skillid], skilllv, 0, 0, + 0, 0, 0); + } + } + else + { + int range = 15; + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + map_foreachinarea (skill_area_sub, + src->m, src->x - range, src->y - range, + src->x + range, src->y + range, 0, src, + skillid, skilllv, tick, + flag | BCT_ENEMY | 1, + skill_castend_nodamage_id); + } + break; - case PR_LEXDIVINA: /* レックスディビーナ */ - { - struct status_change *sc_data = battle_get_sc_data(bl); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if(sc_data && sc_data[SC_DIVINA].timer != -1) - skill_status_change_end(bl,SC_DIVINA,-1); - else if( MRAND(100) < sc_def_vit ) { - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - } - } - break; - case SA_ABRACADABRA: - break; - case SA_COMA: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if(dstsd){ - dstsd->status.hp=1; - dstsd->status.sp=1; - clif_updatestatus(dstsd,SP_HP); - clif_updatestatus(dstsd,SP_SP); - } - if(dstmd) dstmd->hp=1; - break; - case SA_FULLRECOVERY: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if(dstsd) pc_heal(dstsd,dstsd->status.max_hp,dstsd->status.max_sp); - if(dstmd) dstmd->hp=battle_get_max_hp(&dstmd->bl); - break; - case SA_SUMMONMONSTER: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (sd) mob_once_spawn(sd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,"--ja--",-1,1,""); - break; - case SA_LEVELUP: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd,pc_nextbaseexp(sd)*10/100,0); - break; - - case SA_INSTANTDEATH: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (sd) pc_damage(NULL,sd,sd->status.max_hp); - break; - - case SA_QUESTION: - case SA_GRAVITY: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - case SA_CLASSCHANGE: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(dstmd) mob_class_change(dstmd,changeclass); - break; - case SA_MONOCELL: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(dstmd) mob_class_change(dstmd,poringclass); - break; - case SA_DEATH: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (dstsd) pc_damage(NULL,dstsd,dstsd->status.max_hp); - if (dstmd) mob_damage(NULL,dstmd,dstmd->hp,1); - break; - case SA_REVERSEORCISH: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (dstsd) pc_setoption(dstsd,dstsd->status.option|0x0800); - break; - case SA_FORTUNE: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(sd) pc_getzeny(sd,battle_get_lv(bl)*100); - break; - case AL_INCAGI: /* 速度増加 */ - case AL_BLESSING: /* ブレッシング */ - case PR_SLOWPOISON: - case PR_IMPOSITIO: /* イムポシティオマヌス */ - case PR_LEXAETERNA: /* レックスエーテルナ */ - case PR_SUFFRAGIUM: /* サフラギウム */ - case PR_BENEDICTIO: /* 聖体降福 */ - case CR_PROVIDENCE: /* プロヴィデンス */ - case CG_MARIONETTE: /* マリオネットコントロール */ - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - }else{ - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case 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(MRAND(100) > (75+skilllv*1) && (skilllv != 5)) { - clif_skill_fail(sd,skillid,0,0); - clif_skill_nodamage(src,bl,skillid,skilllv,0); - if(bl->type==BL_PC && battle_config.equipment_breaking) { - struct map_session_data *sd2=(struct map_session_data *)bl; - if(sd!=sd2) clif_displaymessage(sd->fd,"You broke target's weapon"); - pc_breakweapon(sd2); - } - break; - } - else { - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; + case PR_LEXDIVINA: /* レックスディビーナ */ + { + struct status_change *sc_data = battle_get_sc_data (bl); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + if (sc_data && sc_data[SC_DIVINA].timer != -1) + skill_status_change_end (bl, SC_DIVINA, -1); + else if (MRAND (100) < sc_def_vit) + { + skill_status_change_start (bl, + SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), + 0); + } + } + break; + case SA_ABRACADABRA: + break; + case SA_COMA: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + if (dstsd) + { + dstsd->status.hp = 1; + dstsd->status.sp = 1; + clif_updatestatus (dstsd, SP_HP); + clif_updatestatus (dstsd, SP_SP); + } + if (dstmd) + dstmd->hp = 1; + break; + case SA_FULLRECOVERY: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + if (dstsd) + pc_heal (dstsd, dstsd->status.max_hp, dstsd->status.max_sp); + if (dstmd) + dstmd->hp = battle_get_max_hp (&dstmd->bl); + break; + case SA_SUMMONMONSTER: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (sd) + mob_once_spawn (sd, map[sd->bl.m].name, sd->bl.x, sd->bl.y, + "--ja--", -1, 1, ""); + break; + case SA_LEVELUP: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (sd && pc_nextbaseexp (sd)) + pc_gainexp (sd, pc_nextbaseexp (sd) * 10 / 100, 0); + break; - case PR_ASPERSIO: /* アスペルシオ */ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if(bl->type==BL_MOB) - break; - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - break; - case PR_KYRIE: /* キリエエレイソン */ - clif_skill_nodamage(bl,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - break; - case KN_AUTOCOUNTER: /* オートカウンター */ - case KN_TWOHANDQUICKEN: /* ツーハンドクイッケン */ - case CR_SPEARQUICKEN: /* スピアクイッケン */ - case CR_REFLECTSHIELD: - case AS_POISONREACT: /* ポイズンリアクト */ - case MC_LOUD: /* ラウドボイス */ - case MG_ENERGYCOAT: /* エナジーコート */ - case SM_ENDURE: /* インデュア */ - case MG_SIGHT: /* サイト */ - case AL_RUWACH: /* ルアフ */ - case MO_EXPLOSIONSPIRITS: // 爆裂波動 - case MO_STEELBODY: // 金剛 - case LK_AURABLADE: /* オーラブレード */ - case LK_PARRYING: /* パリイング */ - case LK_CONCENTRATION: /* コンセントレーション */ - case LK_BERSERK: /* バーサーク */ - case HP_ASSUMPTIO: /* */ - case WS_CARTBOOST: /* カートブースト */ - case SN_SIGHT: /* トゥルーサイト */ - case WS_MELTDOWN: /* メルトダウン */ - case ST_REJECTSWORD: /* リジェクトソード */ - case HW_MAGICPOWER: /* 魔法力増幅 */ - case PF_MEMORIZE: /* メモライズ */ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - break; - case AS_ENCHANTPOISON: // Prevent spamming [Valaris] - if(bl->type==BL_PC) { - struct map_session_data *sd2=(struct map_session_data *)bl; - if(sd2->sc_data[SC_FLAMELAUNCHER].timer!=-1 || sd2->sc_data[SC_FROSTWEAPON].timer!=-1 || - sd2->sc_data[SC_LIGHTNINGLOADER].timer!=-1 || sd2->sc_data[SC_SEISMICWEAPON].timer!=-1 || - sd2->sc_data[SC_ENCPOISON].timer!=-1) { - clif_skill_nodamage(src,bl,skillid,skilllv,0); - clif_skill_fail(sd,skillid,0,0); - break; - } - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - break; - case LK_TENSIONRELAX: /* テンションリラックス */ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - pc_setsit(sd); - clif_sitting(sd->fd,sd); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - break; - case MC_CHANGECART: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - case AC_CONCENTRATION: /* 集中力向上 */ - { - int range = 1; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - map_foreachinarea( skill_status_change_timer_sub, - src->m, src->x-range, src->y-range, src->x+range,src->y+range,0, - src,SkillStatusChangeTable[skillid],tick); - } - break; - case SM_PROVOKE: /* プロボック */ - { - struct status_change *sc_data = battle_get_sc_data(bl); - - /* MVPmobと不死には効かない */ - if((bl->type==BL_MOB && battle_get_mode(bl)&0x20) || battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) //不死には効かない - { - map_freeblock_unlock(); - return 1; - } + case SA_INSTANTDEATH: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (sd) + pc_damage (NULL, sd, sd->status.max_hp); + break; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - - if(dstmd && dstmd->skilltimer!=-1 && dstmd->state.skillcastcancel) // 詠唱妨害 - skill_castcancel(bl,0); - if(dstsd && dstsd->skilltimer!=-1 && (!dstsd->special_state.no_castcancel || map[bl->m].flag.gvg) - && dstsd->state.skillcastcancel && !dstsd->special_state.no_castcancel2) - skill_castcancel(bl,0); - - if(sc_data){ - if(sc_data[SC_FREEZE].timer!=-1) - skill_status_change_end(bl,SC_FREEZE,-1); - if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0) - skill_status_change_end(bl,SC_STONE,-1); - if(sc_data[SC_SLEEP].timer!=-1) - skill_status_change_end(bl,SC_SLEEP,-1); - } + case SA_QUESTION: + case SA_GRAVITY: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + break; + case SA_CLASSCHANGE: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (dstmd) + mob_class_change (dstmd, changeclass); + break; + case SA_MONOCELL: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (dstmd) + mob_class_change (dstmd, poringclass); + break; + case SA_DEATH: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (dstsd) + pc_damage (NULL, dstsd, dstsd->status.max_hp); + if (dstmd) + mob_damage (NULL, dstmd, dstmd->hp, 1); + break; + case SA_REVERSEORCISH: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (dstsd) + pc_setoption (dstsd, dstsd->status.option | 0x0800); + break; + case SA_FORTUNE: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (sd) + pc_getzeny (sd, battle_get_lv (bl) * 100); + break; + case AL_INCAGI: /* 速度増加 */ + case AL_BLESSING: /* ブレッシング */ + case PR_SLOWPOISON: + case PR_IMPOSITIO: /* イムポシティオマヌス */ + case PR_LEXAETERNA: /* レックスエーテルナ */ + case PR_SUFFRAGIUM: /* サフラギウム */ + case PR_BENEDICTIO: /* 聖体降福 */ + case CR_PROVIDENCE: /* プロヴィデンス */ + case CG_MARIONETTE: /* マリオネットコントロール */ + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + } + else + { + skill_status_change_start (bl, + SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), + 0); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + } + break; - if(bl->type==BL_MOB) { - int range = skill_get_range(skillid,skilllv); - if(range < 0) - range = battle_get_range(src) - (range + 1); - mob_target((struct mob_data *)bl,src,range); - } - } - break; - - case CR_DEVOTION: /* ディボーション */ - if(sd && dstsd){ - //転生や養子の場合の元の職業を算出する - - int lv = sd->status.base_level-dstsd->status.base_level; - lv = (lv<0)?-lv:lv; - if((dstsd->bl.type!=BL_PC) // 相手はPCじゃないとだめ - ||(sd->bl.id == dstsd->bl.id) // 相手が自分はだめ - ||(lv > 10) // レベル差±10まで - ||(!sd->status.party_id && !sd->status.guild_id) // PTにもギルドにも所属無しはだめ - ||((sd->status.party_id != dstsd->status.party_id) // 同じパーティーか、 - ||(sd->status.guild_id != dstsd->status.guild_id)) // 同じギルドじゃないとだめ - ||(dstsd->status.class==14||dstsd->status.class==21 - ||dstsd->status.class==4015||dstsd->status.class==4022)){ // クルセだめ - clif_skill_fail(sd,skillid,0,0); - map_freeblock_unlock(); - return 1; - } - for(i=0;i<skilllv;i++){ - if(!sd->dev.val1[i]){ // 空きがあったら入れる - sd->dev.val1[i] = bl->id; - sd->dev.val2[i] = bl->id; - break; - }else if(i==skilllv-1){ // 空きがなかった - clif_skill_fail(sd,skillid,0,0); - map_freeblock_unlock(); - return 1; - } - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - clif_devotion(sd,bl->id); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],src->id,1,0,0,1000*(15+15*skilllv),0 ); - } - else clif_skill_fail(sd,skillid,0,0); - break; - case MO_CALLSPIRITS: // 気功 - if(sd) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - pc_addspiritball(sd,skill_get_time(skillid,skilllv),skilllv); - } - break; - case CH_SOULCOLLECT: // 狂気功 - if(sd) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - for(i=0;i<5;i++) - pc_addspiritball(sd,skill_get_time(skillid,skilllv),5); - } - break; - case MO_BLADESTOP: // 白刃取り - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - break; - case MO_ABSORBSPIRITS: // 気奪 - i=0; - if(sd && dstsd) { - if(sd == dstsd || map[sd->bl.m].flag.pvp || map[sd->bl.m].flag.gvg) { - if(dstsd->spiritball > 0) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - i = dstsd->spiritball * 7; - pc_delspiritball(dstsd,dstsd->spiritball,0); - if(i > 0x7FFF) - i = 0x7FFF; - if(sd->status.sp + i > sd->status.max_sp) - i = sd->status.max_sp - sd->status.sp; - } - } - }else if(sd && dstmd){ //対象がモンスターの場合 - //20%の確率で対象のLv*2のSPを回復する。成功したときはターゲット(σ゚Д゚)σゲッツ!! - if(MRAND(100)<20){ - i=2*mob_db[dstmd->class].lv; - mob_target(dstmd,src,0); - } - } - if(i){ - sd->status.sp += i; - clif_heal(sd->fd,SP_SP,i); - } - else - clif_skill_nodamage(src,bl,skillid,skilllv,0); - break; - - case AC_MAKINGARROW: /* 矢作成 */ + 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 (MRAND (100) > (75 + skilllv * 1) && (skilllv != 5)) + { + clif_skill_fail (sd, skillid, 0, 0); + clif_skill_nodamage (src, bl, skillid, skilllv, 0); + if (bl->type == BL_PC && battle_config.equipment_breaking) + { + struct map_session_data *sd2 = + (struct map_session_data *) bl; + if (sd != sd2) + clif_displaymessage (sd->fd, + "You broke target's weapon"); + pc_breakweapon (sd2); + } + break; + } + else + { + skill_status_change_start (bl, + SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), + 0); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + } + break; + + case PR_ASPERSIO: /* アスペルシオ */ + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + if (bl->type == BL_MOB) + break; + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + break; + case PR_KYRIE: /* キリエエレイソン */ + clif_skill_nodamage (bl, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + break; + case KN_AUTOCOUNTER: /* オートカウンター */ + case KN_TWOHANDQUICKEN: /* ツーハンドクイッケン */ + case CR_SPEARQUICKEN: /* スピアクイッケン */ + case CR_REFLECTSHIELD: + case AS_POISONREACT: /* ポイズンリアクト */ + case MC_LOUD: /* ラウドボイス */ + case MG_ENERGYCOAT: /* エナジーコート */ + case SM_ENDURE: /* インデュア */ + case MG_SIGHT: /* サイト */ + case AL_RUWACH: /* ルアフ */ + case MO_EXPLOSIONSPIRITS: // 爆裂波動 + case MO_STEELBODY: // 金剛 + case LK_AURABLADE: /* オーラブレード */ + case LK_PARRYING: /* パリイング */ + case LK_CONCENTRATION: /* コンセントレーション */ + case LK_BERSERK: /* バーサーク */ + case HP_ASSUMPTIO: /* */ + case WS_CARTBOOST: /* カートブースト */ + case SN_SIGHT: /* トゥルーサイト */ + case WS_MELTDOWN: /* メルトダウン */ + case ST_REJECTSWORD: /* リジェクトソード */ + case HW_MAGICPOWER: /* 魔法力増幅 */ + case PF_MEMORIZE: /* メモライズ */ + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + break; + case AS_ENCHANTPOISON: // Prevent spamming [Valaris] + if (bl->type == BL_PC) + { + struct map_session_data *sd2 = (struct map_session_data *) bl; + if (sd2->sc_data[SC_FLAMELAUNCHER].timer != -1 + || sd2->sc_data[SC_FROSTWEAPON].timer != -1 + || sd2->sc_data[SC_LIGHTNINGLOADER].timer != -1 + || sd2->sc_data[SC_SEISMICWEAPON].timer != -1 + || sd2->sc_data[SC_ENCPOISON].timer != -1) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 0); + clif_skill_fail (sd, skillid, 0, 0); + break; + } + } + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + break; + case LK_TENSIONRELAX: /* テンションリラックス */ + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + pc_setsit (sd); + clif_sitting (sd->fd, sd); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + break; + case MC_CHANGECART: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + break; + case AC_CONCENTRATION: /* 集中力向上 */ + { + int range = 1; + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + map_foreachinarea (skill_status_change_timer_sub, src->m, + src->x - range, src->y - range, src->x + range, + src->y + range, 0, src, + SkillStatusChangeTable[skillid], tick); + } + break; + case SM_PROVOKE: /* プロボック */ + { + struct status_change *sc_data = battle_get_sc_data (bl); + + /* MVPmobと不死には効かない */ + if ((bl->type == BL_MOB && battle_get_mode (bl) & 0x20) || battle_check_undead (battle_get_race (bl), battle_get_elem_type (bl))) //不死には効かない + { + map_freeblock_unlock (); + return 1; + } + + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + + if (dstmd && dstmd->skilltimer != -1 && dstmd->state.skillcastcancel) // 詠唱妨害 + skill_castcancel (bl, 0); + if (dstsd && dstsd->skilltimer != -1 + && (!dstsd->special_state.no_castcancel + || map[bl->m].flag.gvg) && dstsd->state.skillcastcancel + && !dstsd->special_state.no_castcancel2) + skill_castcancel (bl, 0); + + if (sc_data) + { + if (sc_data[SC_FREEZE].timer != -1) + skill_status_change_end (bl, SC_FREEZE, -1); + if (sc_data[SC_STONE].timer != -1 + && sc_data[SC_STONE].val2 == 0) + skill_status_change_end (bl, SC_STONE, -1); + if (sc_data[SC_SLEEP].timer != -1) + skill_status_change_end (bl, SC_SLEEP, -1); + } + + if (bl->type == BL_MOB) + { + int range = skill_get_range (skillid, skilllv); + if (range < 0) + range = battle_get_range (src) - (range + 1); + mob_target ((struct mob_data *) bl, src, range); + } + } + break; + + case CR_DEVOTION: /* ディボーション */ + if (sd && dstsd) + { + //転生や養子の場合の元の職業を算出する + + int lv = sd->status.base_level - dstsd->status.base_level; + lv = (lv < 0) ? -lv : lv; + if ((dstsd->bl.type != BL_PC) // 相手はPCじゃないとだめ + || (sd->bl.id == dstsd->bl.id) // 相手が自分はだめ + || (lv > 10) // レベル差±10まで + || (!sd->status.party_id && !sd->status.guild_id) // PTにもギルドにも所属無しはだめ + || ((sd->status.party_id != dstsd->status.party_id) // 同じパーティーか、 + || (sd->status.guild_id != dstsd->status.guild_id)) // 同じギルドじゃないとだめ + || (dstsd->status.class == 14 || dstsd->status.class == 21 + || dstsd->status.class == 4015 + || dstsd->status.class == 4022)) + { // クルセだめ + clif_skill_fail (sd, skillid, 0, 0); + map_freeblock_unlock (); + return 1; + } + for (i = 0; i < skilllv; i++) + { + if (!sd->dev.val1[i]) + { // 空きがあったら入れる + sd->dev.val1[i] = bl->id; + sd->dev.val2[i] = bl->id; + break; + } + else if (i == skilllv - 1) + { // 空きがなかった + clif_skill_fail (sd, skillid, 0, 0); + map_freeblock_unlock (); + return 1; + } + } + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + clif_devotion (sd, bl->id); + skill_status_change_start (bl, + SkillStatusChangeTable[skillid], + src->id, 1, 0, 0, + 1000 * (15 + 15 * skilllv), 0); + } + else + clif_skill_fail (sd, skillid, 0, 0); + break; + case MO_CALLSPIRITS: // 気功 + if (sd) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + pc_addspiritball (sd, skill_get_time (skillid, skilllv), + skilllv); + } + break; + case CH_SOULCOLLECT: // 狂気功 + if (sd) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + for (i = 0; i < 5; i++) + pc_addspiritball (sd, skill_get_time (skillid, skilllv), + 5); + } + break; + case MO_BLADESTOP: // 白刃取り + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (src, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + break; + case MO_ABSORBSPIRITS: // 気奪 + i = 0; + if (sd && dstsd) + { + if (sd == dstsd || map[sd->bl.m].flag.pvp + || map[sd->bl.m].flag.gvg) + { + if (dstsd->spiritball > 0) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + i = dstsd->spiritball * 7; + pc_delspiritball (dstsd, dstsd->spiritball, 0); + if (i > 0x7FFF) + i = 0x7FFF; + if (sd->status.sp + i > sd->status.max_sp) + i = sd->status.max_sp - sd->status.sp; + } + } + } + else if (sd && dstmd) + { //対象がモンスターの場合 + //20%の確率で対象のLv*2のSPを回復する。成功したときはターゲット(σ゚Д゚)σゲッツ!! + if (MRAND (100) < 20) + { + i = 2 * mob_db[dstmd->class].lv; + mob_target (dstmd, src, 0); + } + } + if (i) + { + sd->status.sp += i; + clif_heal (sd->fd, SP_SP, i); + } + else + clif_skill_nodamage (src, bl, skillid, skilllv, 0); + break; + + case AC_MAKINGARROW: /* 矢作成 */ /* if(sd) { clif_arrow_create_list(sd); clif_skill_nodamage(src,bl,skillid,skilllv,1); }*/ - break; + break; - case AM_PHARMACY: /* ポーション作成 */ + case AM_PHARMACY: /* ポーション作成 */ /* if(sd) { clif_skill_produce_mix_list(sd,32); clif_skill_nodamage(src,bl,skillid,skilllv,1); }*/ - break; - case WS_CREATECOIN: /* クリエイトコイン */ + break; + case WS_CREATECOIN: /* クリエイトコイン */ /* if(sd) { clif_skill_produce_mix_list(sd,64); clif_skill_nodamage(src,bl,skillid,skilllv,1); }*/ - break; - case WS_CREATENUGGET: /* 塊製造 */ + break; + case WS_CREATENUGGET: /* 塊製造 */ /* if(sd) { clif_skill_produce_mix_list(sd,128); clif_skill_nodamage(src,bl,skillid,skilllv,1); }*/ - break; - case BS_HAMMERFALL: /* ハンマーフォール */ - 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( MRAND(100) < (20+ 10*skilllv)*sc_def_vit/100 ) { - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - } - break; - - case RG_RAID: /* サプライズアタック */ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - { - int x=bl->x,y=bl->y; - skill_area_temp[1]=bl->id; - skill_area_temp[2]=x; - skill_area_temp[3]=y; - map_foreachinarea(skill_area_sub, - bl->m,x-1,y-1,x+1,y+1,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - } - skill_status_change_end(src, SC_HIDING, -1); // ハイディング解除 - break; - - case KN_BRANDISHSPEAR: /*ブランディッシュスピア*/ - { - 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); - } - } - /* 範囲BA */ - if(skilllv > 6){ - skill_brandishspear_dir(&tc,dir,-1); - n--; - }else{ - skill_brandishspear_dir(&tc,dir,-2); - n-=2; - } + break; + case BS_HAMMERFALL: /* ハンマーフォール */ + 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 (MRAND (100) < (20 + 10 * skilllv) * sc_def_vit / 100) + { + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + } + break; - 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; - - /* パーティスキル */ - case AL_ANGELUS: /* エンジェラス */ - case PR_MAGNIFICAT: /* マグニフィカート */ - case PR_GLORIA: /* グロリア */ - case SN_WINDWALK: /* ウインドウォーク */ - if(sd == NULL || sd->status.party_id==0 || (flag&1) ){ - /* 個別の処理 */ - clif_skill_nodamage(bl,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - } - else{ - /* パーティ全体への処理 */ - party_foreachsamemap(skill_area_sub, - sd,1, - src,skillid,skilllv,tick, flag|BCT_PARTY|1, - skill_castend_nodamage_id); - } - break; - case BS_ADRENALINE: /* アドレナリンラッシュ */ - case BS_WEAPONPERFECT: /* ウェポンパーフェクション */ - case BS_OVERTHRUST: /* オーバートラスト */ - if(sd == NULL || sd->status.party_id==0 || (flag&1) ){ - /* 個別の処理 */ - clif_skill_nodamage(bl,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,(src == bl)? 1:0,0,0,skill_get_time(skillid,skilllv),0); - } - else{ - /* パーティ全体への処理 */ - party_foreachsamemap(skill_area_sub, - sd,1, - src,skillid,skilllv,tick, flag|BCT_PARTY|1, - skill_castend_nodamage_id); - } - break; - - /*(付加と解除が必要) */ - case BS_MAXIMIZE: /* マキシマイズパワー */ - case NV_TRICKDEAD: /* 死んだふり */ - case CR_DEFENDER: /* ディフェンダー */ - case CR_AUTOGUARD: /* オートガード */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - int sc=SkillStatusChangeTable[skillid]; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( tsc_data ){ - if( tsc_data[sc].timer==-1 ) - /* 付加する */ - skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - else - /* 解除する */ - skill_status_change_end(bl, sc, -1); - } - } - break; - - case TF_HIDING: /* ハイディング */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - int sc=SkillStatusChangeTable[skillid]; - clif_skill_nodamage(src,bl,skillid,-1,1); - if( tsc_data ){ - if( tsc_data[sc].timer==-1 ) - /* 付加する */ - skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - else - /* 解除する */ - skill_status_change_end(bl, sc, -1); - } - } - break; - - case AS_CLOAKING: /* クローキング */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - int sc=SkillStatusChangeTable[skillid]; - clif_skill_nodamage(src,bl,skillid,-1,1); - if( tsc_data ){ - if( tsc_data[sc].timer==-1 ) - /* 付加する */ - skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - else - /* 解除する */ - skill_status_change_end(bl, sc, -1); - } + case RG_RAID: /* サプライズアタック */ + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + { + int x = bl->x, y = bl->y; + skill_area_temp[1] = bl->id; + skill_area_temp[2] = x; + skill_area_temp[3] = y; + map_foreachinarea (skill_area_sub, + bl->m, x - 1, y - 1, x + 1, y + 1, 0, + src, skillid, skilllv, tick, + flag | BCT_ENEMY | 1, + skill_castend_damage_id); + } + skill_status_change_end (src, SC_HIDING, -1); // ハイディング解除 + break; - skill_check_cloaking(bl); - } - break; - - case ST_CHASEWALK: /* ハイディング */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - int sc=SkillStatusChangeTable[skillid]; - clif_skill_nodamage(src,bl,skillid,-1,1); - if( tsc_data ){ - if( tsc_data[sc].timer==-1 ) - /* 付加する */ - skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0); - else - /* 解除する */ - skill_status_change_end(bl, sc, -1); - } - } - break; - - /* 対地スキル */ - case BD_LULLABY: /* 子守唄 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジークフリード */ - case BA_DISSONANCE: /* 不協和音 */ - case BA_POEMBRAGI: /* ブラギの詩 */ - case BA_WHISTLE: /* 口笛 */ - case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ - case BA_APPLEIDUN: /* イドゥンの林檎 */ - case DC_UGLYDANCE: /* 自分勝手なダンス */ - case DC_HUMMING: /* ハミング */ - case DC_DONTFORGETME: /* 私を忘れないで… */ - case DC_FORTUNEKISS: /* 幸運のキス */ - case DC_SERVICEFORYOU: /* サービスフォーユー */ - case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_unitsetting(src,skillid,skilllv,src->x,src->y,0); - break; - - case HP_BASILICA: /* バジリカ */ - case PA_GOSPEL: /* ゴスペル */ - skill_clear_unitgroup(src); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_unitsetting(src,skillid,skilllv,src->x,src->y,0); - break; - - case BD_ADAPTATION: /* アドリブ */ - { - struct status_change *sc_data = battle_get_sc_data(src); - if(sc_data && sc_data[SC_DANCING].timer!=-1){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_stop_dancing(src,0); - } - } - break; - - case BA_FROSTJOKE: /* 寒いジョーク */ - case DC_SCREAM: /* スクリーム */ - 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: // スティール - if(sd) { - if(pc_steal_item(sd,bl)) - clif_skill_nodamage(src,bl,skillid,skilllv,1); - else - clif_skill_nodamage(src,bl,skillid,skilllv,0); - } - break; - - case RG_STEALCOIN: // スティールコイン - if(sd) { - if(pc_steal_coin(sd,bl)) { - int range = skill_get_range(skillid,skilllv); - if(range < 0) - range = battle_get_range(src) - (range + 1); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - mob_target((struct mob_data *)bl,src,range); - } - else - clif_skill_nodamage(src,bl,skillid,skilllv,0); - } - break; + case KN_BRANDISHSPEAR: /*ブランディッシュスピア */ + { + 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); + } + } + /* 範囲BA */ + 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; - case MG_STONECURSE: /* ストーンカース */ - if (bl->type==BL_MOB && battle_get_mode(bl)&0x20) { - clif_skill_fail(sd,sd->skillid,0,0); - break; - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if( MRAND(100) < skilllv*4+20 && !battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) - skill_status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - else if(sd) - clif_skill_fail(sd,skillid,0,0); - break; - - case NV_FIRSTAID: /* 応急手当 */ - clif_skill_nodamage(src,bl,skillid,5,1); - battle_heal(NULL,bl,5,0,0); - break; - - case AL_CURE: /* キュアー */ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - skill_status_change_end(bl, SC_SILENCE , -1 ); - skill_status_change_end(bl, SC_BLIND , -1 ); - skill_status_change_end(bl, SC_CONFUSION, -1 ); - if( battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) ){//アンデッドなら暗闇効果 - skill_status_change_start(bl, SC_CONFUSION,1,0,0,0,6000,0); - } - break; + /* パーティスキル */ + case AL_ANGELUS: /* エンジェラス */ + case PR_MAGNIFICAT: /* マグニフィカート */ + case PR_GLORIA: /* グロリア */ + case SN_WINDWALK: /* ウインドウォーク */ + if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) + { + /* 個別の処理 */ + clif_skill_nodamage (bl, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + skill_status_change_start (bl, + SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), + 0); + } + else + { + /* パーティ全体への処理 */ + party_foreachsamemap (skill_area_sub, + sd, 1, + src, skillid, skilllv, tick, + flag | BCT_PARTY | 1, + skill_castend_nodamage_id); + } + break; + case BS_ADRENALINE: /* アドレナリンラッシュ */ + case BS_WEAPONPERFECT: /* ウェポンパーフェクション */ + case BS_OVERTHRUST: /* オーバートラスト */ + if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) + { + /* 個別の処理 */ + clif_skill_nodamage (bl, bl, skillid, skilllv, 1); + skill_status_change_start (bl, + SkillStatusChangeTable[skillid], + skilllv, (src == bl) ? 1 : 0, 0, 0, + skill_get_time (skillid, skilllv), + 0); + } + else + { + /* パーティ全体への処理 */ + party_foreachsamemap (skill_area_sub, + sd, 1, + src, skillid, skilllv, tick, + flag | BCT_PARTY | 1, + skill_castend_nodamage_id); + } + break; - case TF_DETOXIFY: /* 解毒 */ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_end(bl, SC_POISON , -1 ); - break; + /*(付加と解除が必要) */ + case BS_MAXIMIZE: /* マキシマイズパワー */ + case NV_TRICKDEAD: /* 死んだふり */ + case CR_DEFENDER: /* ディフェンダー */ + case CR_AUTOGUARD: /* オートガード */ + { + struct status_change *tsc_data = battle_get_sc_data (bl); + int sc = SkillStatusChangeTable[skillid]; + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (tsc_data) + { + if (tsc_data[sc].timer == -1) + /* 付加する */ + skill_status_change_start (bl, sc, skilllv, 0, 0, 0, + skill_get_time (skillid, + skilllv), 0); + else + /* 解除する */ + skill_status_change_end (bl, sc, -1); + } + } + break; - case PR_STRECOVERY: /* リカバリー */ - { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - skill_status_change_end(bl, SC_FREEZE , -1 ); - skill_status_change_end(bl, SC_STONE , -1 ); - skill_status_change_end(bl, SC_SLEEP , -1 ); - skill_status_change_end(bl, SC_STAN , -1 ); - if( battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) ){//アンデッドなら暗闇効果 - int blind_time; - //blind_time=30-battle_get_vit(bl)/10-battle_get_int/15; - blind_time=30*(100-(battle_get_int(bl)+battle_get_vit(bl))/2)/100; - if(MRAND(100) < (100-(battle_get_int(bl)/2+battle_get_vit(bl)/3+battle_get_luk(bl)/10))) - skill_status_change_start(bl, SC_BLIND,1,0,0,0,blind_time,0); - } - if(dstmd){ - dstmd->attacked_id=0; - dstmd->target_id=0; - dstmd->state.targettype = NONE_ATTACKABLE; - dstmd->state.skillstate=MSS_IDLE; - dstmd->next_walktime=tick+MRAND(3000)+3000; - } - } - break; + case TF_HIDING: /* ハイディング */ + { + struct status_change *tsc_data = battle_get_sc_data (bl); + int sc = SkillStatusChangeTable[skillid]; + clif_skill_nodamage (src, bl, skillid, -1, 1); + if (tsc_data) + { + if (tsc_data[sc].timer == -1) + /* 付加する */ + skill_status_change_start (bl, sc, skilllv, 0, 0, 0, + skill_get_time (skillid, + skilllv), 0); + else + /* 解除する */ + skill_status_change_end (bl, sc, -1); + } + } + break; - case WZ_ESTIMATION: /* モンスター情報 */ - if(src->type==BL_PC){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - clif_skill_estimation((struct map_session_data *)src,bl); - } - break; + case AS_CLOAKING: /* クローキング */ + { + struct status_change *tsc_data = battle_get_sc_data (bl); + int sc = SkillStatusChangeTable[skillid]; + clif_skill_nodamage (src, bl, skillid, -1, 1); + if (tsc_data) + { + if (tsc_data[sc].timer == -1) + /* 付加する */ + skill_status_change_start (bl, sc, skilllv, 0, 0, 0, + skill_get_time (skillid, + skilllv), 0); + else + /* 解除する */ + skill_status_change_end (bl, sc, -1); + } + + skill_check_cloaking (bl); + } + break; + + case ST_CHASEWALK: /* ハイディング */ + { + struct status_change *tsc_data = battle_get_sc_data (bl); + int sc = SkillStatusChangeTable[skillid]; + clif_skill_nodamage (src, bl, skillid, -1, 1); + if (tsc_data) + { + if (tsc_data[sc].timer == -1) + /* 付加する */ + skill_status_change_start (bl, sc, skilllv, 0, 0, 0, + skill_get_time (skillid, + skilllv), 0); + else + /* 解除する */ + skill_status_change_end (bl, sc, -1); + } + } + break; + + /* 対地スキル */ + case BD_LULLABY: /* 子守唄 */ + case BD_RICHMANKIM: /* ニヨルドの宴 */ + case BD_ETERNALCHAOS: /* 永遠の混沌 */ + case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ + case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ + case BD_ROKISWEIL: /* ロキの叫び */ + case BD_INTOABYSS: /* 深淵の中に */ + case BD_SIEGFRIED: /* 不死身のジークフリード */ + case BA_DISSONANCE: /* 不協和音 */ + case BA_POEMBRAGI: /* ブラギの詩 */ + case BA_WHISTLE: /* 口笛 */ + case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ + case BA_APPLEIDUN: /* イドゥンの林檎 */ + case DC_UGLYDANCE: /* 自分勝手なダンス */ + case DC_HUMMING: /* ハミング */ + case DC_DONTFORGETME: /* 私を忘れないで… */ + case DC_FORTUNEKISS: /* 幸運のキス */ + case DC_SERVICEFORYOU: /* サービスフォーユー */ + case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_unitsetting (src, skillid, skilllv, src->x, src->y, 0); + break; + + case HP_BASILICA: /* バジリカ */ + case PA_GOSPEL: /* ゴスペル */ + skill_clear_unitgroup (src); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_unitsetting (src, skillid, skilllv, src->x, src->y, 0); + break; + + case BD_ADAPTATION: /* アドリブ */ + { + struct status_change *sc_data = battle_get_sc_data (src); + if (sc_data && sc_data[SC_DANCING].timer != -1) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_stop_dancing (src, 0); + } + } + break; + + case BA_FROSTJOKE: /* 寒いジョーク */ + case DC_SCREAM: /* スクリーム */ + 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: // スティール + if (sd) + { + if (pc_steal_item (sd, bl)) + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + else + clif_skill_nodamage (src, bl, skillid, skilllv, 0); + } + break; + + case RG_STEALCOIN: // スティールコイン + if (sd) + { + if (pc_steal_coin (sd, bl)) + { + int range = skill_get_range (skillid, skilllv); + if (range < 0) + range = battle_get_range (src) - (range + 1); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + mob_target ((struct mob_data *) bl, src, range); + } + else + clif_skill_nodamage (src, bl, skillid, skilllv, 0); + } + break; - case MC_IDENTIFY: /* アイテム鑑定 */ - if(sd) - clif_item_identify_list(sd); - break; + case MG_STONECURSE: /* ストーンカース */ + if (bl->type == BL_MOB && battle_get_mode (bl) & 0x20) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + break; + } + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + if (MRAND (100) < skilllv * 4 + 20 + && !battle_check_undead (battle_get_race (bl), + battle_get_elem_type (bl))) + skill_status_change_start (bl, SC_STONE, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + else if (sd) + clif_skill_fail (sd, skillid, 0, 0); + break; - case BS_REPAIRWEAPON: /* 武器修理 */ - if(sd) + case NV_FIRSTAID: /* 応急手当 */ + clif_skill_nodamage (src, bl, skillid, 5, 1); + battle_heal (NULL, bl, 5, 0, 0); + break; + + case AL_CURE: /* キュアー */ + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + skill_status_change_end (bl, SC_SILENCE, -1); + skill_status_change_end (bl, SC_BLIND, -1); + skill_status_change_end (bl, SC_CONFUSION, -1); + if (battle_check_undead + (battle_get_race (bl), battle_get_elem_type (bl))) + { //アンデッドなら暗闇効果 + skill_status_change_start (bl, SC_CONFUSION, 1, 0, 0, 0, 6000, + 0); + } + break; + + case TF_DETOXIFY: /* 解毒 */ + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_end (bl, SC_POISON, -1); + break; + + case PR_STRECOVERY: /* リカバリー */ + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + skill_status_change_end (bl, SC_FREEZE, -1); + skill_status_change_end (bl, SC_STONE, -1); + skill_status_change_end (bl, SC_SLEEP, -1); + skill_status_change_end (bl, SC_STAN, -1); + if (battle_check_undead + (battle_get_race (bl), battle_get_elem_type (bl))) + { //アンデッドなら暗闇効果 + int blind_time; + //blind_time=30-battle_get_vit(bl)/10-battle_get_int/15; + blind_time = + 30 * (100 - + (battle_get_int (bl) + + battle_get_vit (bl)) / 2) / 100; + if (MRAND (100) < + (100 - + (battle_get_int (bl) / 2 + battle_get_vit (bl) / 3 + + battle_get_luk (bl) / 10))) + skill_status_change_start (bl, SC_BLIND, 1, 0, 0, 0, + blind_time, 0); + } + if (dstmd) + { + dstmd->attacked_id = 0; + dstmd->target_id = 0; + dstmd->state.targettype = NONE_ATTACKABLE; + dstmd->state.skillstate = MSS_IDLE; + dstmd->next_walktime = tick + MRAND (3000) + 3000; + } + } + break; + + case WZ_ESTIMATION: /* モンスター情報 */ + 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: /* アイテム鑑定 */ + if (sd) + clif_item_identify_list (sd); + break; + + case BS_REPAIRWEAPON: /* 武器修理 */ + if (sd) //動作しないのでとりあえずコメントアウト -// clif_item_repair_list(sd); - break; +// clif_item_repair_list(sd); + break; + + case AL_TELEPORT: /* テレポート */ + if (sd) + { + if (map[sd->bl.m].flag.noteleport) + { /* テレポ禁止 */ + 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_TELEPORT: /* テレポート */ - if( sd ){ - if(map[sd->bl.m].flag.noteleport){ /* テレポ禁止 */ - 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: /* アクアベネディクタ */ - 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; /* キャラ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 AL_HOLYWATER: /* アクアベネディクタ */ + 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; /* キャラ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: /* ストリップウェポン */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - - if(tsc_data && tsc_data[SC_CP_WEAPON].timer != -1 ) - break; - strip_per = 5+2*skilllv+strip_fix/5; - strip_time = skill_get_time(skillid,skilllv)+strip_fix/2; - if(MRAND(100) < strip_per){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 ); - if(dstsd){ - for(i=0;i<MAX_INVENTORY;i++){ - if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0002){ - pc_unequipitem(dstsd,i,0); - break; - } - } - } - } - } - break; + case RG_STRIPWEAPON: /* ストリップウェポン */ + { + struct status_change *tsc_data = battle_get_sc_data (bl); + + if (tsc_data && tsc_data[SC_CP_WEAPON].timer != -1) + break; + strip_per = 5 + 2 * skilllv + strip_fix / 5; + strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2; + if (MRAND (100) < strip_per) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, + SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, strip_time, 0); + if (dstsd) + { + for (i = 0; i < MAX_INVENTORY; i++) + { + if (dstsd->status.inventory[i].equip + && dstsd->status.inventory[i].equip & 0x0002) + { + pc_unequipitem (dstsd, i, 0); + break; + } + } + } + } + } + break; - case RG_STRIPSHIELD: /* ストリップシールド */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - - if(tsc_data && tsc_data[SC_CP_SHIELD].timer != -1 ) - break; - strip_per = 5+2*skilllv+strip_fix/5; - strip_time = skill_get_time(skillid,skilllv)+strip_fix/2; - if(MRAND(100) < strip_per){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 ); - if(dstsd){ - for(i=0;i<MAX_INVENTORY;i++){ - if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0020){ - pc_unequipitem(dstsd,i,0); - break; - } - } - } - } - } - break; + case RG_STRIPSHIELD: /* ストリップシールド */ + { + struct status_change *tsc_data = battle_get_sc_data (bl); + + if (tsc_data && tsc_data[SC_CP_SHIELD].timer != -1) + break; + strip_per = 5 + 2 * skilllv + strip_fix / 5; + strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2; + if (MRAND (100) < strip_per) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, + SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, strip_time, 0); + if (dstsd) + { + for (i = 0; i < MAX_INVENTORY; i++) + { + if (dstsd->status.inventory[i].equip + && dstsd->status.inventory[i].equip & 0x0020) + { + pc_unequipitem (dstsd, i, 0); + break; + } + } + } + } + } + break; - case RG_STRIPARMOR: /* ストリップアーマー */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - - if(tsc_data && tsc_data[SC_CP_ARMOR].timer != -1 ) - break; - strip_per = 5+2*skilllv+strip_fix/5; - strip_time = skill_get_time(skillid,skilllv)+strip_fix/2; - if(MRAND(100) < strip_per){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 ); - if(dstsd){ - for(i=0;i<MAX_INVENTORY;i++){ - if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0010){ - pc_unequipitem(dstsd,i,0); - break; - } - } - } - } - } - break; - case RG_STRIPHELM: /* ストリップヘルム */ - { - struct status_change *tsc_data = battle_get_sc_data(bl); - - if(tsc_data && tsc_data[SC_CP_HELM].timer != -1 ) - break; - strip_per = 5+2*skilllv+strip_fix/5; - strip_time = skill_get_time(skillid,skilllv)+strip_fix/2; - if(MRAND(100) < strip_per){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 ); - if(dstsd){ - for(i=0;i<MAX_INVENTORY;i++){ - if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0100){ - pc_unequipitem(dstsd,i,0); - break; - } - } - } - } - } - break; - /* PotionPitcher */ - case AM_POTIONPITCHER: /* ポーションピッチャー */ - { - struct block_list tbl; - int i,x,hp = 0,sp = 0; - if(sd) { - if(sd==dstsd) { // cancel use on oneself - map_freeblock_unlock(); - return 1; - } - x = skilllv%11 - 1; - i = pc_search_inventory(sd,skill_db[skillid].itemid[x]); - if(i < 0 || skill_db[skillid].itemid[x] <= 0) { - clif_skill_fail(sd,skillid,0,0); - map_freeblock_unlock(); - return 1; - } - if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skillid].amount[x]) { - clif_skill_fail(sd,skillid,0,0); - map_freeblock_unlock(); - return 1; - } - sd->state.potionpitcher_flag = 1; - sd->potion_hp = sd->potion_sp = sd->potion_per_hp = sd->potion_per_sp = 0; - sd->skilltarget = bl->id; - run_script(sd->inventory_data[i]->use_script,0,sd->bl.id,0); - pc_delitem(sd,i,skill_db[skillid].amount[x],0); - sd->state.potionpitcher_flag = 0; - if(sd->potion_per_hp > 0 || sd->potion_per_sp > 0) { - hp = battle_get_max_hp(bl) * sd->potion_per_hp / 100; - hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100; - if(dstsd) { - sp = dstsd->status.max_sp * sd->potion_per_sp / 100; - sp = sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER) + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100; - } - } - else { - if(sd->potion_hp > 0) { - hp = sd->potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100; - hp = hp * (100 + (battle_get_vit(bl)<<1)) / 100; - if(dstsd) - hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; - } - if(sd->potion_sp > 0) { - sp = sd->potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER) + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100; - sp = sp * (100 + (battle_get_int(bl)<<1)) / 100; - if(dstsd) - sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100; - } - } - } - else { - hp = (1 + MRAND(400)) * (100 + skilllv*10) / 100; - hp = hp * (100 + (battle_get_vit(bl)<<1)) / 100; - if(dstsd) - hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; - } - tbl.id = 0; - tbl.m = src->m; - tbl.x = src->x; - tbl.y = src->y; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(hp > 0 || (hp <= 0 && sp <= 0)) - clif_skill_nodamage(&tbl,bl,AL_HEAL,hp,1); - if(sp > 0) - clif_skill_nodamage(&tbl,bl,MG_SRECOVERY,sp,1); - battle_heal(src,bl,hp,sp,0); - } - break; - case AM_CP_WEAPON: - { - struct status_change *tsc_data = battle_get_sc_data(bl); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(tsc_data && tsc_data[SC_STRIPWEAPON].timer != -1) - skill_status_change_end(bl, SC_STRIPWEAPON, -1 ); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - } - break; - case AM_CP_SHIELD: - { - struct status_change *tsc_data = battle_get_sc_data(bl); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(tsc_data && tsc_data[SC_STRIPSHIELD].timer != -1) - skill_status_change_end(bl, SC_STRIPSHIELD, -1 ); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - } - break; - case AM_CP_ARMOR: - { - struct status_change *tsc_data = battle_get_sc_data(bl); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(tsc_data && tsc_data[SC_STRIPARMOR].timer != -1) - skill_status_change_end(bl, SC_STRIPARMOR, -1 ); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - } - break; - case AM_CP_HELM: - { - struct status_change *tsc_data = battle_get_sc_data(bl); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(tsc_data && tsc_data[SC_STRIPHELM].timer != -1) - skill_status_change_end(bl, SC_STRIPHELM, -1 ); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - } - break; - case SA_DISPELL: /* ディスペル */ - { - int i; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - for(i=0;i<136;i++){ - if(i==SC_RIDING || i== SC_FALCON || i==SC_HALLUCINATION || i==SC_WEIGHT50 - || i==SC_WEIGHT90 || i==SC_STRIPWEAPON || i==SC_STRIPSHIELD || i==SC_STRIPARMOR - || i==SC_STRIPHELM || i==SC_CP_WEAPON || i==SC_CP_SHIELD || i==SC_CP_ARMOR - || i==SC_CP_HELM || i==SC_COMBO) - continue; - skill_status_change_end(bl,i,-1); - } - } - break; - - case TF_BACKSLIDING: /* バックステップ */ - 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_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: // スペルブレイカー - { - struct status_change *sc_data = battle_get_sc_data(bl); - int sp; - if(sc_data && sc_data[SC_MAGICROD].timer != -1) { - if(dstsd) { - sp = skill_get_sp(skillid,skilllv); - sp = sp * sc_data[SC_MAGICROD].val2 / 100; - if(sp > 0x7fff) sp = 0x7fff; - else if(sp < 1) sp = 1; - if(dstsd->status.sp + sp > dstsd->status.max_sp) { - sp = dstsd->status.max_sp - dstsd->status.sp; - dstsd->status.sp = dstsd->status.max_sp; - } - else - dstsd->status.sp += sp; - clif_heal(dstsd->fd,SP_SP,sp); - } - clif_skill_nodamage(bl,bl,SA_MAGICROD,sc_data[SC_MAGICROD].val1,1); - if(sd) { - sp = sd->status.max_sp/5; - if(sp < 1) sp = 1; - pc_heal(sd,0,-sp); - } - } - else { - int bl_skillid=0,bl_skilllv=0; - if(bl->type == BL_PC) { - if(dstsd && dstsd->skilltimer != -1) { - bl_skillid = dstsd->skillid; - bl_skilllv = dstsd->skilllv; - } - } - else if(bl->type == BL_MOB) { - if(dstmd && dstmd->skilltimer != -1) { - bl_skillid = dstmd->skillid; - bl_skilllv = dstmd->skilllv; - } - } - if(bl_skillid > 0 && skill_db[bl_skillid].skill_type == BF_MAGIC) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_castcancel(bl,0); - sp = skill_get_sp(bl_skillid,bl_skilllv); - if(dstsd) - pc_heal(dstsd,0,-sp); - if(sd) { - sp = sp*(25*(skilllv-1))/100; - if(skilllv > 1 && sp < 1) sp = 1; - if(sp > 0x7fff) sp = 0x7fff; - else if(sp < 1) sp = 1; - if(sd->status.sp + sp > sd->status.max_sp) { - sp = sd->status.max_sp - sd->status.sp; - sd->status.sp = sd->status.max_sp; - } - else - sd->status.sp += sp; - clif_heal(sd->fd,SP_SP,sp); - } - } - else if(sd) - clif_skill_fail(sd,skillid,0,0); - } - } - break; - case SA_MAGICROD: - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - break; - case SA_AUTOSPELL: /* オートスペル */ - 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 = MRAND(3); - spellid = spellarray[i]; - maxlv = skilllv - 1; - } - else if(skilllv > 0) { - spellid = MG_NAPALMBEAT; - maxlv = 3; - } - if(spellid > 0) - skill_status_change_start(src,SC_AUTOSPELL,skilllv,spellid,maxlv,0, - skill_get_time(SA_AUTOSPELL,skilllv),0); - } - break; - - /* ランダム属性変化、水属性変化、地、火、風 */ - case NPC_ATTRICHANGE: - case NPC_CHANGEWATER: - case NPC_CHANGEGROUND: - case NPC_CHANGEFIRE: - case NPC_CHANGEWIND: - /* 毒、聖、念、闇 */ - 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) /* ランダム変化、ただし、*/ - md->def_ele=MRAND(10); /* 不死属性は除く */ - md->def_ele+=(1+MRAND(4))*20; /* 属性レベルはランダム */ - } - break; + case RG_STRIPARMOR: /* ストリップアーマー */ + { + struct status_change *tsc_data = battle_get_sc_data (bl); + + if (tsc_data && tsc_data[SC_CP_ARMOR].timer != -1) + break; + strip_per = 5 + 2 * skilllv + strip_fix / 5; + strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2; + if (MRAND (100) < strip_per) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, + SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, strip_time, 0); + if (dstsd) + { + for (i = 0; i < MAX_INVENTORY; i++) + { + if (dstsd->status.inventory[i].equip + && dstsd->status.inventory[i].equip & 0x0010) + { + pc_unequipitem (dstsd, i, 0); + break; + } + } + } + } + } + break; + case RG_STRIPHELM: /* ストリップヘルム */ + { + struct status_change *tsc_data = battle_get_sc_data (bl); + + if (tsc_data && tsc_data[SC_CP_HELM].timer != -1) + break; + strip_per = 5 + 2 * skilllv + strip_fix / 5; + strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2; + if (MRAND (100) < strip_per) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, + SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, strip_time, 0); + if (dstsd) + { + for (i = 0; i < MAX_INVENTORY; i++) + { + if (dstsd->status.inventory[i].equip + && dstsd->status.inventory[i].equip & 0x0100) + { + pc_unequipitem (dstsd, i, 0); + break; + } + } + } + } + } + break; + /* PotionPitcher */ + case AM_POTIONPITCHER: /* ポーションピッチャー */ + { + struct block_list tbl; + int i, x, hp = 0, sp = 0; + if (sd) + { + if (sd == dstsd) + { // cancel use on oneself + map_freeblock_unlock (); + return 1; + } + x = skilllv % 11 - 1; + i = pc_search_inventory (sd, skill_db[skillid].itemid[x]); + if (i < 0 || skill_db[skillid].itemid[x] <= 0) + { + clif_skill_fail (sd, skillid, 0, 0); + map_freeblock_unlock (); + return 1; + } + if (sd->inventory_data[i] == NULL + || sd->status.inventory[i].amount < + skill_db[skillid].amount[x]) + { + clif_skill_fail (sd, skillid, 0, 0); + map_freeblock_unlock (); + return 1; + } + sd->state.potionpitcher_flag = 1; + sd->potion_hp = sd->potion_sp = sd->potion_per_hp = + sd->potion_per_sp = 0; + sd->skilltarget = bl->id; + run_script (sd->inventory_data[i]->use_script, 0, sd->bl.id, + 0); + pc_delitem (sd, i, skill_db[skillid].amount[x], 0); + sd->state.potionpitcher_flag = 0; + if (sd->potion_per_hp > 0 || sd->potion_per_sp > 0) + { + hp = battle_get_max_hp (bl) * sd->potion_per_hp / 100; + hp = hp * (100 + + pc_checkskill (sd, + AM_POTIONPITCHER) * 10 + + pc_checkskill (sd, + AM_LEARNINGPOTION) * 5) / 100; + if (dstsd) + { + sp = dstsd->status.max_sp * sd->potion_per_sp / 100; + sp = sp * (100 + + pc_checkskill (sd, + AM_POTIONPITCHER) + + pc_checkskill (sd, + AM_LEARNINGPOTION) * 5) / + 100; + } + } + else + { + if (sd->potion_hp > 0) + { + hp = sd->potion_hp * (100 + + pc_checkskill (sd, + AM_POTIONPITCHER) + * 10 + pc_checkskill (sd, + AM_LEARNINGPOTION) + * 5) / 100; + hp = hp * (100 + (battle_get_vit (bl) << 1)) / 100; + if (dstsd) + hp = hp * (100 + + pc_checkskill (dstsd, + SM_RECOVERY) * 10) / + 100; + } + if (sd->potion_sp > 0) + { + sp = sd->potion_sp * (100 + + pc_checkskill (sd, + AM_POTIONPITCHER) + + pc_checkskill (sd, + AM_LEARNINGPOTION) + * 5) / 100; + sp = sp * (100 + (battle_get_int (bl) << 1)) / 100; + if (dstsd) + sp = sp * (100 + + pc_checkskill (dstsd, + MG_SRECOVERY) * 10) / + 100; + } + } + } + else + { + hp = (1 + MRAND (400)) * (100 + skilllv * 10) / 100; + hp = hp * (100 + (battle_get_vit (bl) << 1)) / 100; + if (dstsd) + hp = hp * (100 + + pc_checkskill (dstsd, SM_RECOVERY) * 10) / 100; + } + tbl.id = 0; + tbl.m = src->m; + tbl.x = src->x; + tbl.y = src->y; + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (hp > 0 || (hp <= 0 && sp <= 0)) + clif_skill_nodamage (&tbl, bl, AL_HEAL, hp, 1); + if (sp > 0) + clif_skill_nodamage (&tbl, bl, MG_SRECOVERY, sp, 1); + battle_heal (src, bl, hp, sp, 0); + } + break; + case AM_CP_WEAPON: + { + struct status_change *tsc_data = battle_get_sc_data (bl); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (tsc_data && tsc_data[SC_STRIPWEAPON].timer != -1) + skill_status_change_end (bl, SC_STRIPWEAPON, -1); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + } + break; + case AM_CP_SHIELD: + { + struct status_change *tsc_data = battle_get_sc_data (bl); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (tsc_data && tsc_data[SC_STRIPSHIELD].timer != -1) + skill_status_change_end (bl, SC_STRIPSHIELD, -1); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + } + break; + case AM_CP_ARMOR: + { + struct status_change *tsc_data = battle_get_sc_data (bl); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (tsc_data && tsc_data[SC_STRIPARMOR].timer != -1) + skill_status_change_end (bl, SC_STRIPARMOR, -1); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + } + break; + case AM_CP_HELM: + { + struct status_change *tsc_data = battle_get_sc_data (bl); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (tsc_data && tsc_data[SC_STRIPHELM].timer != -1) + skill_status_change_end (bl, SC_STRIPHELM, -1); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + } + break; + case SA_DISPELL: /* ディスペル */ + { + int i; + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + for (i = 0; i < 136; i++) + { + if (i == SC_RIDING || i == SC_FALCON || i == SC_HALLUCINATION + || i == SC_WEIGHT50 || i == SC_WEIGHT90 + || i == SC_STRIPWEAPON || i == SC_STRIPSHIELD + || i == SC_STRIPARMOR || i == SC_STRIPHELM + || i == SC_CP_WEAPON || i == SC_CP_SHIELD + || i == SC_CP_ARMOR || i == SC_CP_HELM || i == SC_COMBO) + continue; + skill_status_change_end (bl, i, -1); + } + } + break; - case NPC_HALLUCINATION: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - break; + case TF_BACKSLIDING: /* バックステップ */ + 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_PC) + clif_fixpos (src); + skill_addtimerskill (src, tick + 200, src->id, 0, 0, skillid, + skilllv, 0, flag); + break; - case NPC_KEEPING: - case NPC_BARRIER: - { - int skill_time = skill_get_time(skillid,skilllv); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_time,0 ); - mob_changestate((struct mob_data *)src,MS_DELAY,skill_time); - } - 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: // スペルブレイカー + { + struct status_change *sc_data = battle_get_sc_data (bl); + int sp; + if (sc_data && sc_data[SC_MAGICROD].timer != -1) + { + if (dstsd) + { + sp = skill_get_sp (skillid, skilllv); + sp = sp * sc_data[SC_MAGICROD].val2 / 100; + if (sp > 0x7fff) + sp = 0x7fff; + else if (sp < 1) + sp = 1; + if (dstsd->status.sp + sp > dstsd->status.max_sp) + { + sp = dstsd->status.max_sp - dstsd->status.sp; + dstsd->status.sp = dstsd->status.max_sp; + } + else + dstsd->status.sp += sp; + clif_heal (dstsd->fd, SP_SP, sp); + } + clif_skill_nodamage (bl, bl, SA_MAGICROD, + sc_data[SC_MAGICROD].val1, 1); + if (sd) + { + sp = sd->status.max_sp / 5; + if (sp < 1) + sp = 1; + pc_heal (sd, 0, -sp); + } + } + else + { + int bl_skillid = 0, bl_skilllv = 0; + if (bl->type == BL_PC) + { + if (dstsd && dstsd->skilltimer != -1) + { + bl_skillid = dstsd->skillid; + bl_skilllv = dstsd->skilllv; + } + } + else if (bl->type == BL_MOB) + { + if (dstmd && dstmd->skilltimer != -1) + { + bl_skillid = dstmd->skillid; + bl_skilllv = dstmd->skilllv; + } + } + if (bl_skillid > 0 + && skill_db[bl_skillid].skill_type == BF_MAGIC) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_castcancel (bl, 0); + sp = skill_get_sp (bl_skillid, bl_skilllv); + if (dstsd) + pc_heal (dstsd, 0, -sp); + if (sd) + { + sp = sp * (25 * (skilllv - 1)) / 100; + if (skilllv > 1 && sp < 1) + sp = 1; + if (sp > 0x7fff) + sp = 0x7fff; + else if (sp < 1) + sp = 1; + if (sd->status.sp + sp > sd->status.max_sp) + { + sp = sd->status.max_sp - sd->status.sp; + sd->status.sp = sd->status.max_sp; + } + else + sd->status.sp += sp; + clif_heal (sd->fd, SP_SP, sp); + } + } + else if (sd) + clif_skill_fail (sd, skillid, 0, 0); + } + } + break; + case SA_MAGICROD: + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + break; + case SA_AUTOSPELL: /* オートスペル */ + 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 = MRAND (3); + spellid = spellarray[i]; + maxlv = skilllv - 1; + } + else if (skilllv > 0) + { + spellid = MG_NAPALMBEAT; + maxlv = 3; + } + if (spellid > 0) + skill_status_change_start (src, SC_AUTOSPELL, skilllv, + spellid, maxlv, 0, + skill_get_time (SA_AUTOSPELL, + skilllv), 0); + } + break; - case NPC_DARKBLESSING: - { - int sc_def = 100 - battle_get_mdef(bl); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if(battle_get_elem_type(bl) == 7 || battle_get_race(bl) == 6) - break; - if(MRAND(100) < sc_def*(50+skilllv*5)/100) { - if(dstsd) { - int hp = battle_get_hp(bl)-1; - pc_heal(dstsd,-hp,0); - } - else if(dstmd) - dstmd->hp = 1; - } - } - break; - - case NPC_SELFDESTRUCTION: /* 自爆 */ - case NPC_SELFDESTRUCTION2: /* 自爆2 */ - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,0,0,skill_get_time(skillid,skilllv),0); - break; - case NPC_LICK: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_weapon_damage ) - break; - if(dstsd) - pc_heal(dstsd,0,-100); - if(MRAND(100) < (skilllv*5)*sc_def_vit/100) - skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0); - break; - - case NPC_SUICIDE: /* 自決 */ - if(src && bl && md){ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - mob_damage(NULL,md,md->hp,0); - } - break; + /* ランダム属性変化、水属性変化、地、火、風 */ + case NPC_ATTRICHANGE: + case NPC_CHANGEWATER: + case NPC_CHANGEGROUND: + case NPC_CHANGEFIRE: + case NPC_CHANGEWIND: + /* 毒、聖、念、闇 */ + 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) /* ランダム変化、ただし、 */ + md->def_ele = MRAND (10); /* 不死属性は除く */ + md->def_ele += (1 + MRAND (4)) * 20; /* 属性レベルはランダム */ + } + break; - case NPC_SUMMONSLAVE: /* 手下召喚 */ - case NPC_SUMMONMONSTER: /* MOB召喚 */ - if(md && !md->master_id){ - mob_summonslave(md,mob_db[md->class].skill[md->skillidx].val,skilllv,(skillid==NPC_SUMMONSLAVE)?1:0); - } - break; - - case NPC_TRANSFORMATION: - case NPC_METAMORPHOSIS: - if(md) - mob_class_change(md,mob_db[md->class].skill[md->skillidx].val); - break; - - case NPC_EMOTION: /* エモーション */ - if(md) - clif_emotion(&md->bl,mob_db[md->class].skill[md->skillidx].val[0]); - break; - - case NPC_DEFENDER: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - - case WE_MALE: /* 君だけは護るよ */ - if(sd && dstsd){ - int hp_rate=(skilllv <= 0)? 0:skill_db[skillid].hp_rate[skilllv-1]; - int gain_hp=sd->status.max_hp*abs(hp_rate)/100;// 15% - clif_skill_nodamage(src,bl,skillid,gain_hp,1); - battle_heal(NULL,bl,gain_hp,0,0); - } - break; - case WE_FEMALE: /* あなたの為に犠牲になります */ - if(sd && dstsd){ - int sp_rate=(skilllv <= 0)? 0:skill_db[skillid].sp_rate[skilllv-1]; - int gain_sp=sd->status.max_sp*abs(sp_rate)/100;// 15% - clif_skill_nodamage(src,bl,skillid,gain_sp,1); - battle_heal(NULL,bl,0,gain_sp,0); - } - break; + case NPC_HALLUCINATION: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + break; - case WE_CALLPARTNER: /* あなたに会いたい */ - if(sd && dstsd){ - if(map[sd->bl.m].flag.nomemo){ - clif_skill_teleportmessage(sd,1); - return 0; - } - if((dstsd = pc_get_partner(sd)) == NULL){ - clif_skill_fail(sd,skillid,0,0); - return 0; - } - skill_unitsetting(src,skillid,skilllv,sd->bl.x,sd->bl.y,0); - } - break; - - case PF_HPCONVERSION: /* ライフ置き換え */ - 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*20*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: /* リムーブトラップ */ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - { - struct skill_unit *su=NULL; - struct item item_tmp; - int flag; - if((bl->type==BL_SKILL) && - (su=(struct skill_unit *)bl) && - (su->group->src_id == src->id || map[bl->m].flag.pvp || map[bl->m].flag.gvg) && - (su->group->unit_id >= 0x8f && su->group->unit_id <= 0x99) && - (su->group->unit_id != 0x92)){ //罠を取り返す - if(sd){ - if(battle_config.skill_removetrap_type == 1){ - for(i=0;i<10;i++) { - if(skill_db[su->group->skill_id].itemid[i] > 0){ - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = skill_db[su->group->skill_id].itemid[i]; - item_tmp.identify = 1; - if(item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i]))){ - clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp,skill_db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); - } - } - } - }else{ - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = 1065; - item_tmp.identify = 1; - if(item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,1))){ - clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); - } - } - - } - if(su->group->unit_id == 0x91 && su->group->val2){ - struct block_list *target=map_id2bl(su->group->val2); - if(target && (target->type == BL_PC || target->type == BL_MOB)) - skill_status_change_end(target,SC_ANKLE,-1); - } - skill_delunit(su); - } - } - break; - case HT_SPRINGTRAP: /* スプリングトラップ */ - clif_skill_nodamage(src,bl,skillid,skilllv,1); - { - struct skill_unit *su=NULL; - if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){ - switch(su->group->unit_id){ - case 0x8f: /* ブラストマイン */ - case 0x90: /* スキッドトラップ */ - case 0x93: /* ランドマイン */ - case 0x94: /* ショックウェーブトラップ */ - case 0x95: /* サンドマン */ - case 0x96: /* フラッシャー */ - case 0x97: /* フリージングトラップ */ - case 0x98: /* クレイモアートラップ */ - case 0x99: /* トーキーボックス */ - 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: /* アンコール */ - 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: /* ベナムスプラッシャー */ - if((double)battle_get_max_hp(bl)*2/3 < battle_get_hp(bl)) //HPが2/3以上残っていたら失敗 - return 1; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,src->id,0,skill_get_time(skillid,skilllv),0 ); - break; - case PF_MINDBREAKER: /* プロボック */ - { - struct status_change *sc_data = battle_get_sc_data(bl); - - /* MVPmobと不死には効かない */ - if((bl->type==BL_MOB && battle_get_mode(bl)&0x20) || battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) //不死には効かない - { - map_freeblock_unlock(); - return 1; - } + case NPC_KEEPING: + case NPC_BARRIER: + { + int skill_time = skill_get_time (skillid, skilllv); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, skill_time, 0); + mob_changestate ((struct mob_data *) src, MS_DELAY, skill_time); + } + break; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 ); - - if(dstmd && dstmd->skilltimer!=-1 && dstmd->state.skillcastcancel) // 詠唱妨害 - skill_castcancel(bl,0); - if(dstsd && dstsd->skilltimer!=-1 && (!dstsd->special_state.no_castcancel || map[bl->m].flag.gvg) - && dstsd->state.skillcastcancel && !dstsd->special_state.no_castcancel2) - skill_castcancel(bl,0); - - if(sc_data){ - if(sc_data[SC_FREEZE].timer!=-1) - skill_status_change_end(bl,SC_FREEZE,-1); - if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0) - skill_status_change_end(bl,SC_STONE,-1); - if(sc_data[SC_SLEEP].timer!=-1) - skill_status_change_end(bl,SC_SLEEP,-1); - } + case NPC_DARKBLESSING: + { + int sc_def = 100 - battle_get_mdef (bl); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + if (battle_get_elem_type (bl) == 7 || battle_get_race (bl) == 6) + break; + if (MRAND (100) < sc_def * (50 + skilllv * 5) / 100) + { + if (dstsd) + { + int hp = battle_get_hp (bl) - 1; + pc_heal (dstsd, -hp, 0); + } + else if (dstmd) + dstmd->hp = 1; + } + } + break; - if(bl->type==BL_MOB) { - int range = skill_get_range(skillid,skilllv); - if(range < 0) - range = battle_get_range(src) - (range + 1); - mob_target((struct mob_data *)bl,src,range); - } - } - break; + case NPC_SELFDESTRUCTION: /* 自爆 */ + case NPC_SELFDESTRUCTION2: /* 自爆2 */ + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, skillid, 0, 0, + skill_get_time (skillid, skilllv), 0); + break; + case NPC_LICK: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_weapon_damage) + break; + if (dstsd) + pc_heal (dstsd, 0, -100); + if (MRAND (100) < (skilllv * 5) * sc_def_vit / 100) + skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0, + skill_get_time2 (skillid, skilllv), + 0); + break; + case NPC_SUICIDE: /* 自決 */ + if (src && bl && md) + { + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + mob_damage (NULL, md, md->hp, 0); + } + break; + case NPC_SUMMONSLAVE: /* 手下召喚 */ + case NPC_SUMMONMONSTER: /* MOB召喚 */ + if (md && !md->master_id) + { + mob_summonslave (md, + mob_db[md->class].skill[md->skillidx].val, + skilllv, + (skillid == NPC_SUMMONSLAVE) ? 1 : 0); + } + break; + case NPC_TRANSFORMATION: + case NPC_METAMORPHOSIS: + if (md) + mob_class_change (md, + mob_db[md->class].skill[md->skillidx].val); + break; + case NPC_EMOTION: /* エモーション */ + if (md) + clif_emotion (&md->bl, + mob_db[md->class].skill[md->skillidx].val[0]); + break; + case NPC_DEFENDER: + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + break; - case 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; - default: - printf("Unknown skill used:%d\n",skillid); - map_freeblock_unlock(); - return 1; - } + case WE_MALE: /* 君だけは護るよ */ + if (sd && dstsd) + { + int hp_rate = + (skilllv <= + 0) ? 0 : skill_db[skillid].hp_rate[skilllv - 1]; + int gain_hp = sd->status.max_hp * abs (hp_rate) / 100; // 15% + clif_skill_nodamage (src, bl, skillid, gain_hp, 1); + battle_heal (NULL, bl, gain_hp, 0, 0); + } + break; + case WE_FEMALE: /* あなたの為に犠牲になります */ + if (sd && dstsd) + { + int sp_rate = + (skilllv <= + 0) ? 0 : skill_db[skillid].sp_rate[skilllv - 1]; + int gain_sp = sd->status.max_sp * abs (sp_rate) / 100; // 15% + clif_skill_nodamage (src, bl, skillid, gain_sp, 1); + battle_heal (NULL, bl, 0, gain_sp, 0); + } + break; - map_freeblock_unlock(); - return 0; + case WE_CALLPARTNER: /* あなたに会いたい */ + if (sd && dstsd) + { + if (map[sd->bl.m].flag.nomemo) + { + clif_skill_teleportmessage (sd, 1); + return 0; + } + if ((dstsd = pc_get_partner (sd)) == NULL) + { + clif_skill_fail (sd, skillid, 0, 0); + return 0; + } + skill_unitsetting (src, skillid, skilllv, sd->bl.x, sd->bl.y, + 0); + } + break; + + case PF_HPCONVERSION: /* ライフ置き換え */ + 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 * 20 * 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: /* リムーブトラップ */ + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + { + struct skill_unit *su = NULL; + struct item item_tmp; + int flag; + if ((bl->type == BL_SKILL) && + (su = (struct skill_unit *) bl) && + (su->group->src_id == src->id || map[bl->m].flag.pvp + || map[bl->m].flag.gvg) && (su->group->unit_id >= 0x8f + && su->group->unit_id <= + 0x99) + && (su->group->unit_id != 0x92)) + { //罠を取り返す + if (sd) + { + if (battle_config.skill_removetrap_type == 1) + { + for (i = 0; i < 10; i++) + { + if (skill_db[su->group->skill_id].itemid[i] > + 0) + { + memset (&item_tmp, 0, sizeof (item_tmp)); + item_tmp.nameid = + skill_db[su->group-> + skill_id].itemid[i]; + item_tmp.identify = 1; + if (item_tmp.nameid + && (flag = + pc_additem (sd, &item_tmp, + skill_db[su-> + group->skill_id].amount + [i]))) + { + clif_additem (sd, 0, 0, flag); + map_addflooritem (&item_tmp, + skill_db[su-> + group->skill_id].amount + [i], sd->bl.m, + sd->bl.x, sd->bl.y, + NULL, NULL, NULL, + 0); + } + } + } + } + else + { + memset (&item_tmp, 0, sizeof (item_tmp)); + item_tmp.nameid = 1065; + item_tmp.identify = 1; + if (item_tmp.nameid + && (flag = pc_additem (sd, &item_tmp, 1))) + { + clif_additem (sd, 0, 0, flag); + map_addflooritem (&item_tmp, 1, sd->bl.m, + sd->bl.x, sd->bl.y, NULL, + NULL, NULL, 0); + } + } + + } + if (su->group->unit_id == 0x91 && su->group->val2) + { + struct block_list *target = + map_id2bl (su->group->val2); + if (target + && (target->type == BL_PC + || target->type == BL_MOB)) + skill_status_change_end (target, SC_ANKLE, -1); + } + skill_delunit (su); + } + } + break; + case HT_SPRINGTRAP: /* スプリングトラップ */ + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + { + struct skill_unit *su = NULL; + if ((bl->type == BL_SKILL) && (su = (struct skill_unit *) bl) + && (su->group)) + { + switch (su->group->unit_id) + { + case 0x8f: /* ブラストマイン */ + case 0x90: /* スキッドトラップ */ + case 0x93: /* ランドマイン */ + case 0x94: /* ショックウェーブトラップ */ + case 0x95: /* サンドマン */ + case 0x96: /* フラッシャー */ + case 0x97: /* フリージングトラップ */ + case 0x98: /* クレイモアートラップ */ + case 0x99: /* トーキーボックス */ + 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: /* アンコール */ + 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: /* ベナムスプラッシャー */ + if ((double) battle_get_max_hp (bl) * 2 / 3 < battle_get_hp (bl)) //HPが2/3以上残っていたら失敗 + return 1; + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, skillid, src->id, 0, + skill_get_time (skillid, skilllv), 0); + break; + case PF_MINDBREAKER: /* プロボック */ + { + struct status_change *sc_data = battle_get_sc_data (bl); + + /* MVPmobと不死には効かない */ + if ((bl->type == BL_MOB && battle_get_mode (bl) & 0x20) || battle_check_undead (battle_get_race (bl), battle_get_elem_type (bl))) //不死には効かない + { + map_freeblock_unlock (); + return 1; + } + + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + skill_status_change_start (bl, SkillStatusChangeTable[skillid], + skilllv, 0, 0, 0, + skill_get_time (skillid, skilllv), 0); + + if (dstmd && dstmd->skilltimer != -1 && dstmd->state.skillcastcancel) // 詠唱妨害 + skill_castcancel (bl, 0); + if (dstsd && dstsd->skilltimer != -1 + && (!dstsd->special_state.no_castcancel + || map[bl->m].flag.gvg) && dstsd->state.skillcastcancel + && !dstsd->special_state.no_castcancel2) + skill_castcancel (bl, 0); + + if (sc_data) + { + if (sc_data[SC_FREEZE].timer != -1) + skill_status_change_end (bl, SC_FREEZE, -1); + if (sc_data[SC_STONE].timer != -1 + && sc_data[SC_STONE].val2 == 0) + skill_status_change_end (bl, SC_STONE, -1); + if (sc_data[SC_SLEEP].timer != -1) + skill_status_change_end (bl, SC_SLEEP, -1); + } + + if (bl->type == BL_MOB) + { + int range = skill_get_range (skillid, skilllv); + if (range < 0) + range = battle_get_range (src) - (range + 1); + mob_target ((struct mob_data *) bl, src, range); + } + } + break; + + case 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; + default: + printf ("Unknown skill used:%d\n", skillid); + map_freeblock_unlock (); + return 1; + } + + map_freeblock_unlock (); + return 0; } /*========================================== * スキル使用(詠唱完了、ID指定) *------------------------------------------ */ -int skill_castend_id( int tid, unsigned int tick, int id,int data ) +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); + struct map_session_data *sd = map_id2sd (id) /*,*target_sd=NULL */ ; + struct block_list *bl; + int range, inf2; - if( sd->bl.prev == NULL ) //prevが無いのはありなの? - return 0; + nullpo_retr (0, sd); - if(sd->skillid != SA_CASTCANCEL && sd->skilltimer != tid ) /* タイマIDの確認 */ - 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)) { //マップが違うか自分が死んでいる - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - - if(sd->skillid == PR_LEXAETERNA) { - struct status_change *sc_data = battle_get_sc_data(bl); - if(sc_data && (sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0))) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } - else if(sd->skillid == RG_BACKSTAP) { - int dir = map_calc_dir(&sd->bl,bl->x,bl->y),t_dir = battle_get_dir(bl); - int dist = distance(sd->bl.x,sd->bl.y,bl->x,bl->y); - if(bl->type != BL_SKILL && (dist == 0 || map_check_dir(dir,t_dir))) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } - - inf2 = skill_get_inf2(sd->skillid); - if( ( (skill_get_inf(sd->skillid)&1) || inf2&4 ) && // 彼我敵対関係チェック - battle_check_target(&sd->bl,bl, BCT_ENEMY)<=0 ) { - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - if(inf2 & 0xC00 && sd->bl.id != bl->id) { - int fail_flag = 1; - if(inf2 & 0x400 && battle_check_target(&sd->bl,bl, BCT_PARTY) > 0) - fail_flag = 0; - if(inf2 & 0x800 && sd->status.guild_id > 0 && sd->status.guild_id == battle_get_guild_id(bl)) - fail_flag = 0; - if(fail_flag) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } - - range = skill_get_range(sd->skillid,sd->skilllv); - if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); - range += battle_config.pc_skill_add_range; - if((sd->skillid == MO_EXTREMITYFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) || - (sd->skillid == CH_TIGERFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) || - (sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) || - (sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == CH_TIGERFIST)) - range += skill_get_blewcount(MO_COMBOFINISH,sd->sc_data[SC_COMBO].val2); - if(battle_config.skill_out_range_consume) { // changed to allow casting when target walks out of range [Valaris] - if(range < distance(sd->bl.x,sd->bl.y,bl->x,bl->y)) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } - if(!skill_check_condition(sd,1)) { /* 使用条件チェック */ - 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 (sd->bl.prev == NULL) //prevが無いのはありなの? + 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) ) - { - /* 攻撃系/吹き飛ばし系 */ - case 0: case 2: - skill_castend_damage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0); - break; - case 1:/* 支援系 */ - if( (sd->skillid==AL_HEAL || (sd->skillid==ALL_RESURRECTION && bl->type != BL_PC) || sd->skillid==PR_ASPERSIO) && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) - skill_castend_damage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0); - else - skill_castend_nodamage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0); - break; - } + if (sd->skillid != SA_CASTCANCEL && sd->skilltimer != tid) /* タイマIDの確認 */ + 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)) + { //マップが違うか自分が死んでいる + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + + if (sd->skillid == PR_LEXAETERNA) + { + struct status_change *sc_data = battle_get_sc_data (bl); + if (sc_data + && (sc_data[SC_FREEZE].timer != -1 + || (sc_data[SC_STONE].timer != -1 + && sc_data[SC_STONE].val2 == 0))) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + } + else if (sd->skillid == RG_BACKSTAP) + { + int dir = map_calc_dir (&sd->bl, bl->x, bl->y), t_dir = + battle_get_dir (bl); + int dist = distance (sd->bl.x, sd->bl.y, bl->x, bl->y); + if (bl->type != BL_SKILL && (dist == 0 || map_check_dir (dir, t_dir))) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + } + + inf2 = skill_get_inf2 (sd->skillid); + if (((skill_get_inf (sd->skillid) & 1) || inf2 & 4) && // 彼我敵対関係チェック + battle_check_target (&sd->bl, bl, BCT_ENEMY) <= 0) + { + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + if (inf2 & 0xC00 && sd->bl.id != bl->id) + { + int fail_flag = 1; + if (inf2 & 0x400 && battle_check_target (&sd->bl, bl, BCT_PARTY) > 0) + fail_flag = 0; + if (inf2 & 0x800 && sd->status.guild_id > 0 + && sd->status.guild_id == battle_get_guild_id (bl)) + fail_flag = 0; + if (fail_flag) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + } + + range = skill_get_range (sd->skillid, sd->skilllv); + if (range < 0) + range = battle_get_range (&sd->bl) - (range + 1); + range += battle_config.pc_skill_add_range; + if ((sd->skillid == MO_EXTREMITYFIST && sd->sc_data[SC_COMBO].timer != -1 + && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) + || (sd->skillid == CH_TIGERFIST && sd->sc_data[SC_COMBO].timer != -1 + && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) + || (sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1 + && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) + || (sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1 + && sd->sc_data[SC_COMBO].val1 == CH_TIGERFIST)) + range += + skill_get_blewcount (MO_COMBOFINISH, sd->sc_data[SC_COMBO].val2); + if (battle_config.skill_out_range_consume) + { // changed to allow casting when target walks out of range [Valaris] + if (range < distance (sd->bl.x, sd->bl.y, bl->x, bl->y)) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + } + if (!skill_check_condition (sd, 1)) + { /* 使用条件チェック */ + 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)) + { + /* 攻撃系/吹き飛ばし系 */ + case 0: + case 2: + skill_castend_damage_id (&sd->bl, bl, sd->skillid, sd->skilllv, + tick, 0); + break; + case 1: /* 支援系 */ + if ((sd->skillid == AL_HEAL + || (sd->skillid == ALL_RESURRECTION && bl->type != BL_PC) + || sd->skillid == PR_ASPERSIO) + && battle_check_undead (battle_get_race (bl), + battle_get_elem_type (bl))) + skill_castend_damage_id (&sd->bl, bl, sd->skillid, + sd->skilllv, tick, 0); + else + skill_castend_nodamage_id (&sd->bl, bl, sd->skillid, + sd->skilllv, tick, 0); + break; + } - return 0; + return 0; } /*========================================== * スキル使用(詠唱完了、場所指定の実際の処理) *------------------------------------------ */ -int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skilllv,unsigned int tick,int flag) +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; + struct map_session_data *sd = NULL; + int i, tmpx = 0, tmpy = 0, x1 = 0, y1 = 0; - nullpo_retr(0, src); + nullpo_retr (0, src); - if(src->type==BL_PC){ - nullpo_retr(0, sd=(struct map_session_data *)src); - } - if( skillid != WZ_METEOR && - skillid != WZ_SIGHTRASHER && - skillid != AM_CANNIBALIZE && - skillid != AM_SPHEREMINE) - clif_skill_poseffect(src,skillid,skilllv,x,y,tick); - - if (skillnotok(skillid, sd)) // [MouseJstr] - return 0; - - switch(skillid) - { - case PR_BENEDICTIO: /* 聖体降福 */ - skill_area_temp[1]=src->id; - map_foreachinarea(skill_area_sub, - src->m,x-1,y-1,x+1,y+1,0, - src,skillid,skilllv,tick, flag|BCT_NOENEMY|1, - skill_castend_nodamage_id); - map_foreachinarea(skill_area_sub, - src->m,x-1,y-1,x+1,y+1,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - break; - - case BS_HAMMERFALL: /* ハンマーフォール */ - 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: /* ディテクティング */ - { - const int range=7; - map_foreachinarea( skill_status_change_timer_sub, - src->m, src->x-range, src->y-range, src->x+range,src->y+range,0, - src,SC_SIGHT,tick); - } - break; - - case MG_SAFETYWALL: /* セイフティウォール */ - case MG_FIREWALL: /* ファイヤーウォール */ - case MG_THUNDERSTORM: /* サンダーストーム */ - case AL_PNEUMA: /* ニューマ */ - case WZ_ICEWALL: /* アイスウォール */ - case WZ_FIREPILLAR: /* ファイアピラー */ - case WZ_SIGHTRASHER: - case WZ_QUAGMIRE: /* クァグマイア */ - case WZ_VERMILION: /* ロードオブヴァーミリオン */ - case WZ_FROSTNOVA: /* フロストノヴァ */ - case WZ_STORMGUST: /* ストームガスト */ - case WZ_HEAVENDRIVE: /* ヘヴンズドライブ */ - case PR_SANCTUARY: /* サンクチュアリ */ - case PR_MAGNUS: /* マグヌスエクソシズム */ - case CR_GRANDCROSS: /* グランドクロス */ - 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 AS_VENOMDUST: /* ベノムダスト */ - case AM_DEMONSTRATION: /* デモンストレーション */ - case PF_SPIDERWEB: /* スパイダーウェッブ */ - case PF_FOGWALL: /* フォグウォール */ - case HT_TALKIEBOX: /* トーキーボックス */ - 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; + if (src->type == BL_PC) + { + nullpo_retr (0, sd = (struct map_session_data *) src); + } + if (skillid != WZ_METEOR && + skillid != WZ_SIGHTRASHER && + skillid != AM_CANNIBALIZE && skillid != AM_SPHEREMINE) + clif_skill_poseffect (src, skillid, skilllv, x, y, tick); - case SA_VOLCANO: /* ボルケーノ */ - case SA_DELUGE: /* デリュージ */ - case SA_VIOLENTGALE: /* バイオレントゲイル */ - case SA_LANDPROTECTOR: /* ランドプロテクター */ - skill_clear_element_field(src);//既に自分が発動している属性場をクリア - skill_unitsetting(src,skillid,skilllv,x,y,0); - break; - - case WZ_METEOR: //メテオストーム - { - int flag=0; - for(i=0;i<2+(skilllv>>1);i++) { - int j=0, c; - do { - tmpx = x + (MRAND(7) - 3); - tmpy = y + (MRAND(7) - 3); - if(tmpx < 0) - tmpx = 0; - else if(tmpx >= map[src->m].xs) - tmpx = map[src->m].xs - 1; - if(tmpy < 0) - tmpy = 0; - else if(tmpy >= map[src->m].ys) - tmpy = map[src->m].ys - 1; - j++; - } while(((c=map_getcell(src->m,tmpx,tmpy))==1 || c==5) && j<100); - if(j >= 100) - continue; - if(flag==0){ - clif_skill_poseffect(src,skillid,skilllv,tmpx,tmpy,tick); - flag=1; - } - if(i > 0) - skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,(x1<<16)|y1,flag); - x1 = tmpx; - y1 = tmpy; - } - skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,-1,flag); - } - break; + if (skillnotok (skillid, sd)) // [MouseJstr] + return 0; - case AL_WARP: /* ワープポータル */ - if(sd) { - if(map[sd->bl.m].flag.noteleport) /* テレポ禁止 */ - break; - clif_skill_warppoint(sd,sd->skillid,sd->status.save_point.map, - (sd->skilllv>1)?sd->status.memo_point[0].map:"", - (sd->skilllv>2)?sd->status.memo_point[1].map:"", - (sd->skilllv>3)?sd->status.memo_point[2].map:""); - } - break; - case MO_BODYRELOCATION: - if(sd){ - pc_movepos(sd,x,y); - }else if( src->type==BL_MOB ) - mob_warp((struct mob_data *)src,-1,x,y,0); - break; - case AM_CANNIBALIZE: // バイオプラント - if(sd){ - int mx,my,id=0; - struct mob_data *md; - - mx = x;// + (rand()%10 - 5); - my = y;// + (rand()%10 - 5); - id=mob_once_spawn(sd,"this",mx,my,"--ja--",1118,1,""); - if( (md=(struct mob_data *)map_id2bl(id)) !=NULL ){ - md->master_id=sd->bl.id; - md->hp=2210+skilllv*200; - md->state.special_mob_ai=1; - md->deletetimer=add_timer(gettick()+skill_get_time(skillid,skilllv),mob_timer_delete,id,0); - } - clif_skill_poseffect(src,skillid,skilllv,x,y,tick); - } - break; - case AM_SPHEREMINE: // スフィアーマイン - if(sd){ - int mx,my,id=0; - struct mob_data *md; - - mx = x;// + (rand()%10 - 5); - my = y;// + (rand()%10 - 5); - id=mob_once_spawn(sd,"this",mx,my,"--ja--",1142,1,""); - if( (md=(struct mob_data *)map_id2bl(id)) !=NULL ){ - md->master_id=sd->bl.id; - md->hp=1000+skilllv*200; - md->state.special_mob_ai=2; - md->deletetimer=add_timer(gettick()+skill_get_time(skillid,skilllv),mob_timer_delete,id,0); - } - clif_skill_poseffect(src,skillid,skilllv,x,y,tick); - } - break; - } + switch (skillid) + { + case PR_BENEDICTIO: /* 聖体降福 */ + skill_area_temp[1] = src->id; + map_foreachinarea (skill_area_sub, + src->m, x - 1, y - 1, x + 1, y + 1, 0, + src, skillid, skilllv, tick, + flag | BCT_NOENEMY | 1, + skill_castend_nodamage_id); + map_foreachinarea (skill_area_sub, src->m, x - 1, y - 1, x + 1, + y + 1, 0, src, skillid, skilllv, tick, + flag | BCT_ENEMY | 1, skill_castend_damage_id); + break; + + case BS_HAMMERFALL: /* ハンマーフォール */ + 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: /* ディテクティング */ + { + const int range = 7; + map_foreachinarea (skill_status_change_timer_sub, + src->m, src->x - range, src->y - range, + src->x + range, src->y + range, 0, src, + SC_SIGHT, tick); + } + break; + + case MG_SAFETYWALL: /* セイフティウォール */ + case MG_FIREWALL: /* ファイヤーウォール */ + case MG_THUNDERSTORM: /* サンダーストーム */ + case AL_PNEUMA: /* ニューマ */ + case WZ_ICEWALL: /* アイスウォール */ + case WZ_FIREPILLAR: /* ファイアピラー */ + case WZ_SIGHTRASHER: + case WZ_QUAGMIRE: /* クァグマイア */ + case WZ_VERMILION: /* ロードオブヴァーミリオン */ + case WZ_FROSTNOVA: /* フロストノヴァ */ + case WZ_STORMGUST: /* ストームガスト */ + case WZ_HEAVENDRIVE: /* ヘヴンズドライブ */ + case PR_SANCTUARY: /* サンクチュアリ */ + case PR_MAGNUS: /* マグヌスエクソシズム */ + case CR_GRANDCROSS: /* グランドクロス */ + 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 AS_VENOMDUST: /* ベノムダスト */ + case AM_DEMONSTRATION: /* デモンストレーション */ + case PF_SPIDERWEB: /* スパイダーウェッブ */ + case PF_FOGWALL: /* フォグウォール */ + case HT_TALKIEBOX: /* トーキーボックス */ + 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: /* ボルケーノ */ + case SA_DELUGE: /* デリュージ */ + case SA_VIOLENTGALE: /* バイオレントゲイル */ + case SA_LANDPROTECTOR: /* ランドプロテクター */ + skill_clear_element_field (src); //既に自分が発動している属性場をクリア + skill_unitsetting (src, skillid, skilllv, x, y, 0); + break; + + case WZ_METEOR: //メテオストーム + { + int flag = 0; + for (i = 0; i < 2 + (skilllv >> 1); i++) + { + int j = 0, c; + do + { + tmpx = x + (MRAND (7) - 3); + tmpy = y + (MRAND (7) - 3); + if (tmpx < 0) + tmpx = 0; + else if (tmpx >= map[src->m].xs) + tmpx = map[src->m].xs - 1; + if (tmpy < 0) + tmpy = 0; + else if (tmpy >= map[src->m].ys) + tmpy = map[src->m].ys - 1; + j++; + } + while (((c = map_getcell (src->m, tmpx, tmpy)) == 1 || c == 5) + && j < 100); + if (j >= 100) + continue; + if (flag == 0) + { + clif_skill_poseffect (src, skillid, skilllv, tmpx, tmpy, + tick); + flag = 1; + } + if (i > 0) + skill_addtimerskill (src, tick + i * 1000, 0, tmpx, tmpy, + skillid, skilllv, (x1 << 16) | y1, + flag); + x1 = tmpx; + y1 = tmpy; + } + skill_addtimerskill (src, tick + i * 1000, 0, tmpx, tmpy, skillid, + skilllv, -1, flag); + } + break; - return 0; + case AL_WARP: /* ワープポータル */ + if (sd) + { + if (map[sd->bl.m].flag.noteleport) /* テレポ禁止 */ + break; + clif_skill_warppoint (sd, sd->skillid, + sd->status.save_point.map, + (sd->skilllv > + 1) ? sd->status.memo_point[0].map : "", + (sd->skilllv > + 2) ? sd->status.memo_point[1].map : "", + (sd->skilllv > + 3) ? sd->status. + memo_point[2].map : ""); + } + break; + case MO_BODYRELOCATION: + if (sd) + { + pc_movepos (sd, x, y); + } + else if (src->type == BL_MOB) + mob_warp ((struct mob_data *) src, -1, x, y, 0); + break; + case AM_CANNIBALIZE: // バイオプラント + if (sd) + { + int mx, my, id = 0; + struct mob_data *md; + + mx = x; // + (rand()%10 - 5); + my = y; // + (rand()%10 - 5); + id = mob_once_spawn (sd, "this", mx, my, "--ja--", 1118, 1, + ""); + if ((md = (struct mob_data *) map_id2bl (id)) != NULL) + { + md->master_id = sd->bl.id; + md->hp = 2210 + skilllv * 200; + md->state.special_mob_ai = 1; + md->deletetimer = + add_timer (gettick () + + skill_get_time (skillid, skilllv), + mob_timer_delete, id, 0); + } + clif_skill_poseffect (src, skillid, skilllv, x, y, tick); + } + break; + case AM_SPHEREMINE: // スフィアーマイン + if (sd) + { + int mx, my, id = 0; + struct mob_data *md; + + mx = x; // + (rand()%10 - 5); + my = y; // + (rand()%10 - 5); + id = mob_once_spawn (sd, "this", mx, my, "--ja--", 1142, 1, + ""); + if ((md = (struct mob_data *) map_id2bl (id)) != NULL) + { + md->master_id = sd->bl.id; + md->hp = 1000 + skilllv * 200; + md->state.special_mob_ai = 2; + md->deletetimer = + add_timer (gettick () + + skill_get_time (skillid, skilllv), + mob_timer_delete, id, 0); + } + clif_skill_poseffect (src, skillid, skilllv, x, y, tick); + } + break; + } + + return 0; } /*========================================== * スキル使用(詠唱完了、map指定) *------------------------------------------ */ -int skill_castend_map( struct map_session_data *sd,int skill_num, const char *map) +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( sd->opt1>0 || sd->status.option&2 ) - return 0; - //スキルが使えない状態異常中 - if(sd->sc_data){ - if( sd->sc_data[SC_DIVINA].timer!=-1 || - sd->sc_data[SC_ROKISWEIL].timer!=-1 || - sd->sc_data[SC_AUTOCOUNTER].timer != -1 || - sd->sc_data[SC_STEELBODY].timer != -1 || - sd->sc_data[SC_DANCING].timer!=-1 || - sd->sc_data[SC_BERSERK].timer != -1 ) - return 0; - } + int x = 0, y = 0; - if( skill_num != sd->skillid) /* 不正パケットらしい */ - 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: /* テレポート */ - 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: /* ワープポータル */ - { - const struct point *p[]={ - &sd->status.save_point,&sd->status.memo_point[0], - &sd->status.memo_point[1],&sd->status.memo_point[2], - }; - struct skill_unit_group *group; - int i; - int maxcount=0; - - if((maxcount = skill_get_maxcount(sd->skillid)) > 0) { - int c; - for(i=c=0;i<MAX_SKILLUNITGROUP;i++) { - if(sd->skillunit[i].alive_count > 0 && sd->skillunit[i].skill_id == sd->skillid) - c++; - } - if(c >= maxcount) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = gettick(); - sd->canmove_tick = gettick(); - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } + nullpo_retr (0, sd); + if (sd->bl.prev == NULL || pc_isdead (sd)) + 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) /* 不正パケット? */ - return 0; - - if(!skill_check_condition(sd,3)) - return 0; - if((group=skill_unitsetting(&sd->bl,sd->skillid,sd->skilllv,sd->skillx,sd->skilly,0))==NULL) - return 0; - group->valstr=(char *)aCalloc(24,sizeof(char)); - memcpy(group->valstr,map,24); - group->val2=(x<<16)|y; - } - break; - } + if (sd->opt1 > 0 || sd->status.option & 2) + return 0; + //スキルが使えない状態異常中 + if (sd->sc_data) + { + if (sd->sc_data[SC_DIVINA].timer != -1 || + sd->sc_data[SC_ROKISWEIL].timer != -1 || + sd->sc_data[SC_AUTOCOUNTER].timer != -1 || + sd->sc_data[SC_STEELBODY].timer != -1 || + sd->sc_data[SC_DANCING].timer != -1 || + sd->sc_data[SC_BERSERK].timer != -1) + return 0; + } + + if (skill_num != sd->skillid) /* 不正パケットらしい */ + 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: /* テレポート */ + 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: /* ワープポータル */ + { + const struct point *p[] = { + &sd->status.save_point, &sd->status.memo_point[0], + &sd->status.memo_point[1], &sd->status.memo_point[2], + }; + struct skill_unit_group *group; + int i; + int maxcount = 0; + + if ((maxcount = skill_get_maxcount (sd->skillid)) > 0) + { + int c; + for (i = c = 0; i < MAX_SKILLUNITGROUP; i++) + { + if (sd->skillunit[i].alive_count > 0 + && sd->skillunit[i].skill_id == sd->skillid) + c++; + } + if (c >= maxcount) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + sd->canact_tick = gettick (); + sd->canmove_tick = gettick (); + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + } + + 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) /* 不正パケット? */ + return 0; + + if (!skill_check_condition (sd, 3)) + return 0; + if ((group = + skill_unitsetting (&sd->bl, sd->skillid, sd->skilllv, + sd->skillx, sd->skilly, 0)) == NULL) + return 0; + group->valstr = (char *) aCalloc (24, sizeof (char)); + memcpy (group->valstr, map, 24); + group->val2 = (x << 16) | y; + } + break; + } - return 0; + return 0; } /*========================================== * スキルユニット設定処理 *------------------------------------------ */ -struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag) +struct skill_unit_group *skill_unitsetting (struct block_list *src, + int skillid, int skilllv, int x, + int y, int flag) { - struct skill_unit_group *group; - int i,count=1,limit=10000,val1=0,val2=0; - int target=BCT_ENEMY,interval=1000,range=0; - int dir=0,aoe_diameter=0; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills - - nullpo_retr(0, src); - - switch(skillid){ /* 設定 */ - - case MG_SAFETYWALL: /* セイフティウォール */ - limit=skill_get_time(skillid,skilllv); - val2=skilllv+1; - interval = -1; - target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL; - break; - - case MG_FIREWALL: /* ファイヤーウォール */ - if(src->x == x && src->y == y) - dir = 2; - else - dir=map_calc_dir(src,x,y); - if(dir&1) count=5; - else count=3; - limit=skill_get_time(skillid,skilllv); - val2=4+skilllv; - interval=1; - break; - - case AL_PNEUMA: /* ニューマ */ - limit=skill_get_time(skillid,skilllv); - interval = -1; - target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL; - count = 9; - break; - - case AL_WARP: /* ワープポータル */ - target=BCT_ALL; - val1=skilllv+6; - if(flag==0) - limit=2000; - else - limit=skill_get_time(skillid,skilllv); - break; - - case PR_SANCTUARY: /* サンクチュアリ */ - count=21; - limit=skill_get_time(skillid,skilllv); - val1=skilllv+3; - val2=(skilllv>6)?777:skilllv*100; - target=BCT_ALL; - range=1; - break; - - case PR_MAGNUS: /* マグヌスエクソシズム */ - count=33; - limit=skill_get_time(skillid,skilllv); - interval=3000; - break; - - case WZ_FIREPILLAR: /* ファイアーピラー */ - if(flag==0) - limit=skill_get_time(skillid,skilllv); - else - limit=1000; - interval=2000; - val1=skilllv+2; - range=1; - break; - - case MG_THUNDERSTORM: /* サンダーストーム */ - limit=500; - range=1; - break; - - case WZ_FROSTNOVA: /* フロストノヴァ */ - limit=500; - range=5; - break; - case WZ_HEAVENDRIVE: /* ヘヴンズドライブ */ - limit=500; - range=2; - break; - - case WZ_METEOR: /* メテオストーム */ - limit=500; - range=3; - break; - - case WZ_SIGHTRASHER: - limit=500; - count=41; - break; - - case WZ_VERMILION: /* ロードオブヴァーミリオン */ - limit=4100; - interval=1000; - range=6; - break; - - case WZ_ICEWALL: /* アイスウォール */ - limit=skill_get_time(skillid,skilllv); - count=5; - break; - - case WZ_STORMGUST: /* ストームガスト */ - limit=4600; - interval=450; - range=5; - break; - - case WZ_QUAGMIRE: /* クァグマイア */ - limit=skill_get_time(skillid,skilllv); - interval=200; - count=25; - break; - - case HT_SKIDTRAP: /* スキッドトラップ */ - case HT_LANDMINE: /* ランドマイン */ - case HT_ANKLESNARE: /* アンクルスネア */ - case HT_SANDMAN: /* サンドマン */ - case PF_SPIDERWEB: /* スパイダーウェッブ */ - case HT_FLASHER: /* フラッシャー */ - case HT_FREEZINGTRAP: /* フリージングトラップ */ - case HT_BLASTMINE: /* ブラストマイン */ - case HT_CLAYMORETRAP: /* クレイモアートラップ */ - limit=skill_get_time(skillid,skilllv); - range=1; - break; - - case HT_TALKIEBOX: /* トーキーボックス */ - limit=skill_get_time(skillid,skilllv); - range=1; - target=BCT_ALL; - break; - - case HT_SHOCKWAVE: /* ショックウェーブトラップ */ - limit=skill_get_time(skillid,skilllv); - range=1; - val1=skilllv*15+10; - break; - - case AS_VENOMDUST: /* ベノムダスト */ - limit=skill_get_time(skillid,skilllv); - interval=1000; - count=5; - break; - - case CR_GRANDCROSS: /* グランドクロス */ - count=29; - limit=1000; - interval=300; - break; - - case SA_VOLCANO: /* ボルケーノ */ - case SA_DELUGE: /* デリュージ */ - case SA_VIOLENTGALE: /* バイオレントゲイル */ - limit=skill_get_time(skillid,skilllv); - count=skilllv<=2?25:(skilllv<=4?49:81); - target=BCT_ALL; - break; - - case SA_LANDPROTECTOR: /* グランドクロス */ - limit=skill_get_time(skillid,skilllv); // changed to get duration from cast_db (moonsoul) - val1=skilllv*15+10; - aoe_diameter=skilllv+skilllv%2+5; - target=BCT_ALL; - count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul) - break; - - case BD_LULLABY: /* 子守唄 */ - case BD_ETERNALCHAOS: /* エターナルカオス */ - case BD_ROKISWEIL: /* ロキの叫び */ - count=81; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_ALL; - break; - case BD_RICHMANKIM: - case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジークフリード */ - count=81; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_PARTY; - break; - - case BA_WHISTLE: /* 口笛 */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; - if(src->type == BL_PC) - val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1; - val2 = ((battle_get_agi(src)/10)&0xffff)<<16; - val2 |= (battle_get_luk(src)/10)&0xffff; - break; - case DC_HUMMING: /* ハミング */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; - if(src->type == BL_PC) - val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; - val2 = battle_get_dex(src)/10; - break; - - case BA_DISSONANCE: /* 不協和音 */ - case DC_UGLYDANCE: /* 自分勝手なダンス */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_ENEMY; - break; - - case DC_DONTFORGETME: /* 私を忘れないで… */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_ENEMY; - if(src->type == BL_PC) - val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; - val2 = ((battle_get_str(src)/20)&0xffff)<<16; - val2 |= (battle_get_agi(src)/10)&0xffff; - break; - case BA_POEMBRAGI: /* ブラギの詩 */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; - if(src->type == BL_PC) - val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON); - val2 = ((battle_get_dex(src)/10)&0xffff)<<16; - val2 |= (battle_get_int(src)/5)&0xffff; - break; - case BA_APPLEIDUN: /* イドゥンの林檎 */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; - if(src->type == BL_PC) - val1 = ((pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON))&0xffff)<<16; - else - val1 = 0; - val1 |= (battle_get_vit(src))&0xffff; - val2 = 0;//回復用タイムカウンタ(6秒毎に1増加) - break; - case DC_SERVICEFORYOU: /* サービスフォーユー */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_PARTY; - if(src->type == BL_PC) - val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; - val2 = battle_get_int(src)/10; - break; - case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; - if(src->type == BL_PC) - val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1; - val2 = battle_get_agi(src)/20; - break; - case DC_FORTUNEKISS: /* 幸運のキス */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_NOENEMY; - if(src->type == BL_PC) - val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; - val2 = battle_get_luk(src)/10; - break; - case AM_DEMONSTRATION: /* デモンストレーション */ - limit=skill_get_time(skillid,skilllv); - interval=1000; - range=1; - target=BCT_ENEMY; - break; - case WE_CALLPARTNER: /* あなたに逢いたい */ - limit=skill_get_time(skillid,skilllv); - range=-1; - break; - - case HP_BASILICA: /* バジリカ */ - limit=skill_get_time(skillid,skilllv); - target=BCT_ALL; - range=3; - //Fix to prevent the priest from walking while Basilica is up. - battle_stopwalking(src,1); - skill_status_change_start(src,SC_ANKLE,skilllv,0,0,0,limit,0); - break; - case PA_GOSPEL: /* ゴスペル */ - count=49; - target=BCT_PARTY; - limit=skill_get_time(skillid,skilllv); - break; - case PF_FOGWALL: /* フォグウォール */ - count=15; - limit=skill_get_time(skillid,skilllv); - break; - case RG_GRAFFITI: /* Graffiti */ - count=1; // Leave this at 1 [Valaris] - limit=600000; // Time length [Valaris] - break; - }; - - nullpo_retr(NULL, group=skill_initunitgroup(src,count,skillid,skilllv,skill_get_unit_id(skillid,flag&1))); - group->limit=limit; - group->val1=val1; - group->val2=val2; - group->target_flag=target; - group->interval=interval; - group->range=range; - if(skillid==HT_TALKIEBOX || - skillid==RG_GRAFFITI){ - group->valstr=calloc(80, 1); - if(group->valstr==NULL){ - printf("skill_castend_map: out of memory !\n"); - exit(1); - } - memcpy(group->valstr,talkie_mes,80); - } - for(i=0;i<count;i++){ - struct skill_unit *unit; - int ux=x,uy=y,val1=skilllv,val2=0,limit=group->limit,alive=1; - int range=group->range; - switch(skillid){ /* 設定 */ - case AL_PNEUMA: /* ニューマ */ - { - static const int dx[9]={-1, 0, 1,-1, 0, 1,-1, 0, 1}; - static const int dy[9]={-1,-1,-1, 0, 0, 0, 1, 1, 1}; - ux+=dx[i]; - uy+=dy[i]; - } - break; - case MG_FIREWALL: /* ファイヤーウォール */ - { - if(dir&1){ /* 斜め配置 */ - static const int dx[][5]={ - { 1,1,0,0,-1 }, { -1,-1,0,0,1 }, - },dy[][5]={ - { 1,0,0,-1,-1 }, { 1,0,0,-1,-1 }, - }; - ux+=dx[(dir>>1)&1][i]; - uy+=dy[(dir>>1)&1][i]; - }else{ /* 上下配置 */ - if(dir%4==0) /* 上下 */ - ux+=i-1; - else /* 左右 */ - uy+=i-1; - } - val2=group->val2; - } - break; + struct skill_unit_group *group; + int i, count = 1, limit = 10000, val1 = 0, val2 = 0; + int target = BCT_ENEMY, interval = 1000, range = 0; + int dir = 0, aoe_diameter = 0; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills - 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, }; - ux+=dx[i]; - uy+=dy[i]; - } - break; + nullpo_retr (0, src); - 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 }; - ux+=dx[i]; - uy+=dy[i]; - } - break; + switch (skillid) + { /* 設定 */ - case WZ_SIGHTRASHER: - { - static const int dx[]={ - -5, 0, 5, -4, 0, 4, -3, 0, 3, -2, 0, 2, -1, 0, 1, -5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, -1, 0, 1, -2, 0, 2, -3, 0, 3, -4, 0, 4, -5, 0, 5 }; - static const int dy[]={ - -5,-5,-5, -4,-4,-4, -3,-3,-3, -2,-2,-2, -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 }; - ux+=dx[i]; - uy+=dy[i]; - } - break; + case MG_SAFETYWALL: /* セイフティウォール */ + limit = skill_get_time (skillid, skilllv); + val2 = skilllv + 1; + interval = -1; + target = (battle_config.defnotenemy) ? BCT_NOENEMY : BCT_ALL; + break; - case WZ_ICEWALL: /* アイスウォール */ - { - static const int dirx[8]={0,-1,-1,-1,0,1,1,1}; - static const int diry[8]={1,1,0,-1,-1,-1,0,1}; - if(skilllv <= 1) - val1 = 500; - else - val1 = 200 + 200*skilllv; - if(src->x == x && src->y == y) - dir = 2; - else - dir=map_calc_dir(src,x,y); - ux+=(2-i)*diry[dir]; - uy+=(i-2)*dirx[dir]; - } - break; + case MG_FIREWALL: /* ファイヤーウォール */ + if (src->x == x && src->y == y) + dir = 2; + else + dir = map_calc_dir (src, x, y); + if (dir & 1) + count = 5; + else + count = 3; + limit = skill_get_time (skillid, skilllv); + val2 = 4 + skilllv; + interval = 1; + break; - case WZ_QUAGMIRE: /* クァグマイア */ - ux+=(i%5-2); - uy+=(i/5-2); - if(i==12) - range=2; - else - range=-1; + case AL_PNEUMA: /* ニューマ */ + limit = skill_get_time (skillid, skilllv); + interval = -1; + target = (battle_config.defnotenemy) ? BCT_NOENEMY : BCT_ALL; + count = 9; + break; - break; + case AL_WARP: /* ワープポータル */ + target = BCT_ALL; + val1 = skilllv + 6; + if (flag == 0) + limit = 2000; + else + limit = skill_get_time (skillid, skilllv); + break; - case AS_VENOMDUST: /* ベノムダスト */ - { - static const int dx[]={-1,0,0,0,1}; - static const int dy[]={0,-1,0,1,0}; - ux+=dx[i]; - uy+=dy[i]; - } - break; + case PR_SANCTUARY: /* サンクチュアリ */ + count = 21; + limit = skill_get_time (skillid, skilllv); + val1 = skilllv + 3; + val2 = (skilllv > 6) ? 777 : skilllv * 100; + target = BCT_ALL; + range = 1; + break; - case CR_GRANDCROSS: /* グランドクロス */ - { - static const int dx[]={ - 0, 0, -1,0,1, -2,-1,0,1,2, -4,-3,-2,-1,0,1,2,3,4, -2,-1,0,1,2, -1,0,1, 0, 0, }; - static const int dy[]={ - -4, -3, -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0,0,0,0,0, 1,1,1,1,1, 2,2,2, 3, 4, }; - ux+=dx[i]; - uy+=dy[i]; - } - break; - case SA_VOLCANO: /* ボルケーノ */ - case SA_DELUGE: /* デリュージ */ - case SA_VIOLENTGALE: /* バイオレントゲイル */ - { - int u_range=0,central=0; - if(skilllv<=2){ - u_range=2; - central=12; - }else if(skilllv<=4){ - u_range=3; - central=24; - }else if(skilllv>=5){ - u_range=4; - central=40; - } - ux+=(i%(u_range*2+1)-u_range); - uy+=(i/(u_range*2+1)-u_range); - - if(i==central) - range=u_range;//中央のユニットの効果範囲は全範囲 - else - range=-1;//中央以外のユニットは飾り - } - break; - case SA_LANDPROTECTOR: /* ランドプロテクター */ - { - int u_range=0; + case PR_MAGNUS: /* マグヌスエクソシズム */ + count = 33; + limit = skill_get_time (skillid, skilllv); + interval = 3000; + break; - if(skilllv<=2) u_range=3; - else if(skilllv<=4) u_range=4; - else if(skilllv>=5) u_range=5; + case WZ_FIREPILLAR: /* ファイアーピラー */ + if (flag == 0) + limit = skill_get_time (skillid, skilllv); + else + limit = 1000; + interval = 2000; + val1 = skilllv + 2; + range = 1; + break; - ux+=(i%(u_range*2+1)-u_range); - uy+=(i/(u_range*2+1)-u_range); + case MG_THUNDERSTORM: /* サンダーストーム */ + limit = 500; + range = 1; + break; - range=0; - } - break; + case WZ_FROSTNOVA: /* フロストノヴァ */ + limit = 500; + range = 5; + break; + case WZ_HEAVENDRIVE: /* ヘヴンズドライブ */ + limit = 500; + range = 2; + break; - /* ダンスなど */ - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD:/* 戦太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジークフリード */ - ux+=(i%9-4); - uy+=(i/9-4); - if(i==40) - range=4; /* 中心の場合は範囲を4にオーバーライド */ - else - range=-1; /* 中心じゃない場合は範囲を-1にオーバーライド */ - break; - case BA_DISSONANCE: /* 不協和音 */ - case BA_WHISTLE: /* 口笛 */ - case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ - case BA_POEMBRAGI: /* ブラギの詩 */ - case BA_APPLEIDUN: /* イドゥンの林檎 */ - case DC_UGLYDANCE: /* 自分勝手なダンス */ - case DC_HUMMING: /* ハミング */ - case DC_DONTFORGETME: /* 私を忘れないで… */ - case DC_FORTUNEKISS: /* 幸運のキス */ - case DC_SERVICEFORYOU: /* サービスフォーユー */ - ux+=(i%7-3); - uy+=(i/7-3); - if(i==40) - range=4; /* 中心の場合は範囲を4にオーバーライド */ - else - range=-1; /* 中心じゃない場合は範囲を-1にオーバーライド */ - break; - case PA_GOSPEL: /* ゴスペル */ - ux+=(i%7-3); - uy+=(i/7-3); - break; - case PF_FOGWALL: /* フォグウォール */ - ux+=(i%5-2); - uy+=(i/5-1); - break; - case RG_GRAFFITI: /* Graffiti [Valaris] */ - ux+=(i%5-2); - uy+=(i/5-2); - break; - } - //直上スキルの場合設置座標上にランドプロテクターがないかチェック - if(range<=0) - map_foreachinarea(skill_landprotector,src->m,ux,uy,ux,uy,BL_SKILL,skillid,&alive); - - if(skillid==WZ_ICEWALL && alive){ - val2=map_getcell(src->m,ux,uy); - if(val2==5 || val2==1) - alive=0; - else { - map_setcell(src->m,ux,uy,5); - clif_changemapcell(src->m,ux,uy,5,0); - } - } + case WZ_METEOR: /* メテオストーム */ + limit = 500; + range = 3; + break; - if(alive){ - nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy)); - unit->val1=val1; - unit->val2=val2; - unit->limit=limit; - unit->range=range; - } - } - return group; + case WZ_SIGHTRASHER: + limit = 500; + count = 41; + break; + + case WZ_VERMILION: /* ロードオブヴァーミリオン */ + limit = 4100; + interval = 1000; + range = 6; + break; + + case WZ_ICEWALL: /* アイスウォール */ + limit = skill_get_time (skillid, skilllv); + count = 5; + break; + + case WZ_STORMGUST: /* ストームガスト */ + limit = 4600; + interval = 450; + range = 5; + break; + + case WZ_QUAGMIRE: /* クァグマイア */ + limit = skill_get_time (skillid, skilllv); + interval = 200; + count = 25; + break; + + case HT_SKIDTRAP: /* スキッドトラップ */ + case HT_LANDMINE: /* ランドマイン */ + case HT_ANKLESNARE: /* アンクルスネア */ + case HT_SANDMAN: /* サンドマン */ + case PF_SPIDERWEB: /* スパイダーウェッブ */ + case HT_FLASHER: /* フラッシャー */ + case HT_FREEZINGTRAP: /* フリージングトラップ */ + case HT_BLASTMINE: /* ブラストマイン */ + case HT_CLAYMORETRAP: /* クレイモアートラップ */ + limit = skill_get_time (skillid, skilllv); + range = 1; + break; + + case HT_TALKIEBOX: /* トーキーボックス */ + limit = skill_get_time (skillid, skilllv); + range = 1; + target = BCT_ALL; + break; + + case HT_SHOCKWAVE: /* ショックウェーブトラップ */ + limit = skill_get_time (skillid, skilllv); + range = 1; + val1 = skilllv * 15 + 10; + break; + + case AS_VENOMDUST: /* ベノムダスト */ + limit = skill_get_time (skillid, skilllv); + interval = 1000; + count = 5; + break; + + case CR_GRANDCROSS: /* グランドクロス */ + count = 29; + limit = 1000; + interval = 300; + break; + + case SA_VOLCANO: /* ボルケーノ */ + case SA_DELUGE: /* デリュージ */ + case SA_VIOLENTGALE: /* バイオレントゲイル */ + limit = skill_get_time (skillid, skilllv); + count = skilllv <= 2 ? 25 : (skilllv <= 4 ? 49 : 81); + target = BCT_ALL; + break; + + case SA_LANDPROTECTOR: /* グランドクロス */ + limit = skill_get_time (skillid, skilllv); // changed to get duration from cast_db (moonsoul) + val1 = skilllv * 15 + 10; + aoe_diameter = skilllv + skilllv % 2 + 5; + target = BCT_ALL; + count = aoe_diameter * aoe_diameter; // -- this will not function if changed to ^2 (moonsoul) + break; + + case BD_LULLABY: /* 子守唄 */ + case BD_ETERNALCHAOS: /* エターナルカオス */ + case BD_ROKISWEIL: /* ロキの叫び */ + count = 81; + limit = skill_get_time (skillid, skilllv); + range = 5; + target = BCT_ALL; + break; + case BD_RICHMANKIM: + case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ + case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ + case BD_INTOABYSS: /* 深淵の中に */ + case BD_SIEGFRIED: /* 不死身のジークフリード */ + count = 81; + limit = skill_get_time (skillid, skilllv); + range = 5; + target = BCT_PARTY; + break; + + case BA_WHISTLE: /* 口笛 */ + count = 49; + limit = skill_get_time (skillid, skilllv); + range = 5; + target = BCT_NOENEMY; + if (src->type == BL_PC) + val1 = + (pc_checkskill + ((struct map_session_data *) src, + BA_MUSICALLESSON) + 1) >> 1; + val2 = ((battle_get_agi (src) / 10) & 0xffff) << 16; + val2 |= (battle_get_luk (src) / 10) & 0xffff; + break; + case DC_HUMMING: /* ハミング */ + count = 49; + limit = skill_get_time (skillid, skilllv); + range = 5; + target = BCT_NOENEMY; + if (src->type == BL_PC) + val1 = + (pc_checkskill + ((struct map_session_data *) src, + DC_DANCINGLESSON) + 1) >> 1; + val2 = battle_get_dex (src) / 10; + break; + + case BA_DISSONANCE: /* 不協和音 */ + case DC_UGLYDANCE: /* 自分勝手なダンス */ + count = 49; + limit = skill_get_time (skillid, skilllv); + range = 5; + target = BCT_ENEMY; + break; + + case DC_DONTFORGETME: /* 私を忘れないで… */ + count = 49; + limit = skill_get_time (skillid, skilllv); + range = 5; + target = BCT_ENEMY; + if (src->type == BL_PC) + val1 = + (pc_checkskill + ((struct map_session_data *) src, + DC_DANCINGLESSON) + 1) >> 1; + val2 = ((battle_get_str (src) / 20) & 0xffff) << 16; + val2 |= (battle_get_agi (src) / 10) & 0xffff; + break; + case BA_POEMBRAGI: /* ブラギの詩 */ + count = 49; + limit = skill_get_time (skillid, skilllv); + range = 5; + target = BCT_NOENEMY; + if (src->type == BL_PC) + val1 = + pc_checkskill ((struct map_session_data *) src, + BA_MUSICALLESSON); + val2 = ((battle_get_dex (src) / 10) & 0xffff) << 16; + val2 |= (battle_get_int (src) / 5) & 0xffff; + break; + case BA_APPLEIDUN: /* イドゥンの林檎 */ + count = 49; + limit = skill_get_time (skillid, skilllv); + range = 5; + target = BCT_NOENEMY; + if (src->type == BL_PC) + val1 = + ((pc_checkskill + ((struct map_session_data *) src, + BA_MUSICALLESSON)) & 0xffff) << 16; + else + val1 = 0; + val1 |= (battle_get_vit (src)) & 0xffff; + val2 = 0; //回復用タイムカウンタ(6秒毎に1増加) + break; + case DC_SERVICEFORYOU: /* サービスフォーユー */ + count = 49; + limit = skill_get_time (skillid, skilllv); + range = 5; + target = BCT_PARTY; + if (src->type == BL_PC) + val1 = + (pc_checkskill + ((struct map_session_data *) src, + DC_DANCINGLESSON) + 1) >> 1; + val2 = battle_get_int (src) / 10; + break; + case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ + count = 49; + limit = skill_get_time (skillid, skilllv); + range = 5; + target = BCT_NOENEMY; + if (src->type == BL_PC) + val1 = + (pc_checkskill + ((struct map_session_data *) src, + BA_MUSICALLESSON) + 1) >> 1; + val2 = battle_get_agi (src) / 20; + break; + case DC_FORTUNEKISS: /* 幸運のキス */ + count = 49; + limit = skill_get_time (skillid, skilllv); + range = 5; + target = BCT_NOENEMY; + if (src->type == BL_PC) + val1 = + (pc_checkskill + ((struct map_session_data *) src, + DC_DANCINGLESSON) + 1) >> 1; + val2 = battle_get_luk (src) / 10; + break; + case AM_DEMONSTRATION: /* デモンストレーション */ + limit = skill_get_time (skillid, skilllv); + interval = 1000; + range = 1; + target = BCT_ENEMY; + break; + case WE_CALLPARTNER: /* あなたに逢いたい */ + limit = skill_get_time (skillid, skilllv); + range = -1; + break; + + case HP_BASILICA: /* バジリカ */ + limit = skill_get_time (skillid, skilllv); + target = BCT_ALL; + range = 3; + //Fix to prevent the priest from walking while Basilica is up. + battle_stopwalking (src, 1); + skill_status_change_start (src, SC_ANKLE, skilllv, 0, 0, 0, limit, + 0); + break; + case PA_GOSPEL: /* ゴスペル */ + count = 49; + target = BCT_PARTY; + limit = skill_get_time (skillid, skilllv); + break; + case PF_FOGWALL: /* フォグウォール */ + count = 15; + limit = skill_get_time (skillid, skilllv); + break; + case RG_GRAFFITI: /* Graffiti */ + count = 1; // Leave this at 1 [Valaris] + limit = 600000; // Time length [Valaris] + break; + }; + + nullpo_retr (NULL, group = + skill_initunitgroup (src, count, skillid, skilllv, + skill_get_unit_id (skillid, flag & 1))); + group->limit = limit; + group->val1 = val1; + group->val2 = val2; + group->target_flag = target; + group->interval = interval; + group->range = range; + if (skillid == HT_TALKIEBOX || skillid == RG_GRAFFITI) + { + group->valstr = calloc (80, 1); + if (group->valstr == NULL) + { + printf ("skill_castend_map: out of memory !\n"); + exit (1); + } + memcpy (group->valstr, talkie_mes, 80); + } + for (i = 0; i < count; i++) + { + struct skill_unit *unit; + int ux = x, uy = y, val1 = skilllv, val2 = 0, limit = + group->limit, alive = 1; + int range = group->range; + switch (skillid) + { /* 設定 */ + case AL_PNEUMA: /* ニューマ */ + { + static const int dx[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 }; + static const int dy[9] = { -1, -1, -1, 0, 0, 0, 1, 1, 1 }; + ux += dx[i]; + uy += dy[i]; + } + break; + case MG_FIREWALL: /* ファイヤーウォール */ + { + if (dir & 1) + { /* 斜め配置 */ + static const int dx[][5] = { + {1, 1, 0, 0, -1}, {-1, -1, 0, 0, 1}, + }, dy[][5] = + { + { + 1, 0, 0, -1, -1}, + { + 1, 0, 0, -1, -1},}; + ux += dx[(dir >> 1) & 1][i]; + uy += dy[(dir >> 1) & 1][i]; + } + else + { /* 上下配置 */ + if (dir % 4 == 0) /* 上下 */ + ux += i - 1; + else /* 左右 */ + uy += i - 1; + } + val2 = group->val2; + } + 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, + }; + ux += dx[i]; + uy += dy[i]; + } + 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 + }; + ux += dx[i]; + uy += dy[i]; + } + break; + + case WZ_SIGHTRASHER: + { + static const int dx[] = { + -5, 0, 5, -4, 0, 4, -3, 0, 3, -2, 0, 2, -1, 0, 1, -5, -4, + -3, -2, -1, 0, 1, 2, 3, 4, 5, -1, 0, 1, -2, 0, 2, -3, + 0, 3, -4, 0, 4, -5, 0, 5 + }; + static const int dy[] = { + -5, -5, -5, -4, -4, -4, -3, -3, -3, -2, -2, -2, -1, -1, + -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, + 3, 3, 3, 4, 4, 4, 5, 5, 5 + }; + ux += dx[i]; + uy += dy[i]; + } + break; + + case WZ_ICEWALL: /* アイスウォール */ + { + static const int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 }; + static const int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 }; + if (skilllv <= 1) + val1 = 500; + else + val1 = 200 + 200 * skilllv; + if (src->x == x && src->y == y) + dir = 2; + else + dir = map_calc_dir (src, x, y); + ux += (2 - i) * diry[dir]; + uy += (i - 2) * dirx[dir]; + } + break; + + case WZ_QUAGMIRE: /* クァグマイア */ + ux += (i % 5 - 2); + uy += (i / 5 - 2); + if (i == 12) + range = 2; + else + range = -1; + + break; + + case AS_VENOMDUST: /* ベノムダスト */ + { + static const int dx[] = { -1, 0, 0, 0, 1 }; + static const int dy[] = { 0, -1, 0, 1, 0 }; + ux += dx[i]; + uy += dy[i]; + } + break; + + case CR_GRANDCROSS: /* グランドクロス */ + { + static const int dx[] = { + 0, 0, -1, 0, 1, -2, -1, 0, 1, 2, -4, -3, -2, -1, 0, 1, 2, + 3, 4, -2, -1, 0, 1, 2, -1, 0, 1, 0, 0, + }; + static const int dy[] = { + -4, -3, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, + }; + ux += dx[i]; + uy += dy[i]; + } + break; + case SA_VOLCANO: /* ボルケーノ */ + case SA_DELUGE: /* デリュージ */ + case SA_VIOLENTGALE: /* バイオレントゲイル */ + { + int u_range = 0, central = 0; + if (skilllv <= 2) + { + u_range = 2; + central = 12; + } + else if (skilllv <= 4) + { + u_range = 3; + central = 24; + } + else if (skilllv >= 5) + { + u_range = 4; + central = 40; + } + ux += (i % (u_range * 2 + 1) - u_range); + uy += (i / (u_range * 2 + 1) - u_range); + + if (i == central) + range = u_range; //中央のユニットの効果範囲は全範囲 + else + range = -1; //中央以外のユニットは飾り + } + break; + case SA_LANDPROTECTOR: /* ランドプロテクター */ + { + int u_range = 0; + + if (skilllv <= 2) + u_range = 3; + else if (skilllv <= 4) + u_range = 4; + else if (skilllv >= 5) + u_range = 5; + + ux += (i % (u_range * 2 + 1) - u_range); + uy += (i / (u_range * 2 + 1) - u_range); + + range = 0; + } + break; + + /* ダンスなど */ + case BD_LULLABY: /* 子守歌 */ + case BD_RICHMANKIM: /* ニヨルドの宴 */ + case BD_ETERNALCHAOS: /* 永遠の混沌 */ + case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ + case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ + case BD_ROKISWEIL: /* ロキの叫び */ + case BD_INTOABYSS: /* 深淵の中に */ + case BD_SIEGFRIED: /* 不死身のジークフリード */ + ux += (i % 9 - 4); + uy += (i / 9 - 4); + if (i == 40) + range = 4; /* 中心の場合は範囲を4にオーバーライド */ + else + range = -1; /* 中心じゃない場合は範囲を-1にオーバーライド */ + break; + case BA_DISSONANCE: /* 不協和音 */ + case BA_WHISTLE: /* 口笛 */ + case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ + case BA_POEMBRAGI: /* ブラギの詩 */ + case BA_APPLEIDUN: /* イドゥンの林檎 */ + case DC_UGLYDANCE: /* 自分勝手なダンス */ + case DC_HUMMING: /* ハミング */ + case DC_DONTFORGETME: /* 私を忘れないで… */ + case DC_FORTUNEKISS: /* 幸運のキス */ + case DC_SERVICEFORYOU: /* サービスフォーユー */ + ux += (i % 7 - 3); + uy += (i / 7 - 3); + if (i == 40) + range = 4; /* 中心の場合は範囲を4にオーバーライド */ + else + range = -1; /* 中心じゃない場合は範囲を-1にオーバーライド */ + break; + case PA_GOSPEL: /* ゴスペル */ + ux += (i % 7 - 3); + uy += (i / 7 - 3); + break; + case PF_FOGWALL: /* フォグウォール */ + ux += (i % 5 - 2); + uy += (i / 5 - 1); + break; + case RG_GRAFFITI: /* Graffiti [Valaris] */ + ux += (i % 5 - 2); + uy += (i / 5 - 2); + break; + } + //直上スキルの場合設置座標上にランドプロテクターがないかチェック + if (range <= 0) + map_foreachinarea (skill_landprotector, src->m, ux, uy, ux, uy, + BL_SKILL, skillid, &alive); + + if (skillid == WZ_ICEWALL && alive) + { + val2 = map_getcell (src->m, ux, uy); + if (val2 == 5 || val2 == 1) + alive = 0; + else + { + map_setcell (src->m, ux, uy, 5); + clif_changemapcell (src->m, ux, uy, 5, 0); + } + } + + if (alive) + { + nullpo_retr (NULL, unit = skill_initunit (group, i, ux, uy)); + unit->val1 = val1; + unit->val2 = val2; + unit->limit = limit; + unit->range = range; + } + } + return group; } /*========================================== * スキルユニットの発動イベント *------------------------------------------ */ -int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int tick) +int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, + unsigned int tick) { - struct skill_unit_group *sg; - struct block_list *ss; - struct skill_unit_group_tickset *ts; - struct map_session_data *srcsd=NULL; - int diff,goflag,splash_count=0; - - nullpo_retr(0, src); - nullpo_retr(0, bl); - - if( bl->prev==NULL || !src->alive || (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl) ) ) - return 0; - - nullpo_retr(0, sg=src->group); - nullpo_retr(0, ss=map_id2bl(sg->src_id)); - - if(ss->type == BL_PC) - nullpo_retr(0, srcsd=(struct map_session_data *)ss); - if(srcsd && srcsd->chatID) - return 0; - - if( bl->type!=BL_PC && bl->type!=BL_MOB ) - return 0; - nullpo_retr(0, ts=skill_unitgrouptickset_search( bl, sg->group_id)); - diff=DIFF_TICK(tick,ts->tick); - goflag=(diff>sg->interval || diff<0); - if (sg->skill_id == CR_GRANDCROSS && !battle_config.gx_allhit) // 重なっていたら3HITしない - goflag = (diff>sg->interval*map_count_oncell(bl->m,bl->x,bl->y) || diff<0); - - //対象がLP上に居る場合は無効 - map_foreachinarea(skill_landprotector,bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,0,&goflag); - - if(!goflag) - return 0; - ts->tick=tick; - ts->group_id=sg->group_id; - - switch(sg->unit_id){ - case 0x83: /* サンクチュアリ */ - { - int race=battle_get_race(bl); - int damage_flag = (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6)? 1:0; - - if( battle_get_hp(bl)>=battle_get_max_hp(bl) && !damage_flag) - break; + struct skill_unit_group *sg; + struct block_list *ss; + struct skill_unit_group_tickset *ts; + struct map_session_data *srcsd = NULL; + int diff, goflag, splash_count = 0; - if((sg->val1--)<=0){ - skill_delunitgroup(sg); - return 0; - } - if(!damage_flag) { - int heal=sg->val2; - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage) - heal=0; /* 黄金蟲カード(ヒール量0) */ - clif_skill_nodamage(&src->bl,bl,AL_HEAL,heal,1); - battle_heal(NULL,bl,heal,0,0); - } - else - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - } - break; + nullpo_retr (0, src); + nullpo_retr (0, bl); - case 0x84: /* マグヌスエクソシズム */ - { - int race=battle_get_race(bl); - int damage_flag = (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6)? 1:0; + if (bl->prev == NULL || !src->alive + || (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl))) + return 0; - if(!damage_flag) - return 0; - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - } - break; - - case 0x85: /* ニューマ */ - { - struct skill_unit *unit2; - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SC_PNEUMA; - if(sc_data && sc_data[type].timer==-1) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){ - if(DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - ts->tick-=sg->interval; - } - } - break; - case 0x7e: /* セイフティウォール */ - { - struct skill_unit *unit2; - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SC_SAFETYWALL; - if(sc_data && sc_data[type].timer==-1) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){ - if(sg->val1 < unit2->group->val1 ) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - ts->tick-=sg->interval; - } - } - break; - - case 0x86: /* ロードオブヴァーミリオン(&ストームガスト &グランドクロス) */ - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - break; - - case 0x7f: /* ファイヤーウォール */ - if( (src->val2--)>0) - skill_attack(BF_MAGIC,ss,&src->bl,bl, - sg->skill_id,sg->skill_lv,tick,0); - if( src->val2<=0 ) - skill_delunit(src); - break; - - case 0x87: /* ファイアーピラー(発動前) */ - skill_delunit(src); - skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1); - break; - - case 0x88: /* ファイアーピラー(発動後) */ - if(DIFF_TICK(tick,sg->tick) < 150) - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - break; - - case 0x90: /* スキッドトラップ */ - { - 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: /* ランドマイン */ - 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: /* ブラストマイン */ - case 0x94: /* ショックウェーブトラップ */ - case 0x95: /* サンドマン */ - case 0x96: /* フラッシャー */ - case 0x97: /* フリージングトラップ */ - case 0x98: /* クレイモアートラップ */ - 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: /* アンクルスネア */ - { - struct status_change *sc_data=battle_get_sc_data(bl); - if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){ - int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE); - int sec=skill_get_time2(sg->skill_id,sg->skill_lv) - (double)battle_get_agi(bl)*0.1; - if(battle_get_mode(bl)&0x20) - sec = sec/5; - battle_stopwalking(bl,1); - skill_status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0); - - if(moveblock) map_delblock(bl); - bl->x = src->bl.x; - bl->y = src->bl.y; - if(moveblock) map_addblock(bl); - if(bl->type == BL_MOB) - clif_fixmobpos((struct mob_data *)bl); - else - clif_fixpos(bl); - clif_01ac(&src->bl); - sg->limit=DIFF_TICK(tick,sg->tick) + sec; - sg->val2=bl->id; - } - } - break; - - case 0x80: /* ワープポータル(発動後) */ - if(bl->type==BL_PC){ - struct map_session_data *sd = (struct map_session_data *)bl; - if(sd && src->bl.m == bl->m && src->bl.x == bl->x && src->bl.y == bl->y && src->bl.x == sd->to_x && src->bl.y == sd->to_y) { - if( battle_config.chat_warpportal || !sd->chatID ){ - if((sg->val1--)>0){ - pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3); - if(sg->src_id == bl->id ||( strcmp(map[src->bl.m].name,sg->valstr) == 0 && src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) )) - skill_delunitgroup(sg); - }else - skill_delunitgroup(sg); - } - } - }else if(bl->type==BL_MOB && battle_config.mob_warpportal){ - int m=map_mapname2mapid(sg->valstr); - struct mob_data *md; - md=(struct mob_data *)bl; - mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3); - } - break; + nullpo_retr (0, sg = src->group); + nullpo_retr (0, ss = map_id2bl (sg->src_id)); - case 0x8e: /* クァグマイア */ - { - int type=SkillStatusChangeTable[sg->skill_id]; - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if( battle_get_sc_data(bl)[type].timer==-1 ) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - } - break; - case 0x92: /* ベノムダスト */ - { - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if( sc_data && sc_data[type].timer==-1 ) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - } - break; - case 0x9a: /* ボルケーノ */ - case 0x9b: /* デリュージ */ - case 0x9c: /* バイオレントゲイル */ - { - struct skill_unit *unit2; - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sc_data && sc_data[type].timer==-1) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){ - if( DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } break; - - case 0x9e: /* 子守唄 */ - case 0x9f: /* ニヨルドの宴 */ - case 0xa0: /* 永遠の混沌 */ - case 0xa1: /* 戦太鼓の響き */ - case 0xa2: /* ニーベルングの指輪 */ - case 0xa3: /* ロキの叫び */ - case 0xa4: /* 深淵の中に */ - case 0xa5: /* 不死身のジークフリード */ - case 0xa6: /* 不協和音 */ - case 0xa7: /* 口笛 */ - case 0xa8: /* 夕陽のアサシンクロス */ - case 0xa9: /* ブラギの詩 */ - case 0xab: /* 自分勝手なダンス */ - case 0xac: /* ハミング */ - case 0xad: /* 私を忘れないで… */ - case 0xae: /* 幸運のキス */ - case 0xaf: /* サービスフォーユー */ - case 0xb4: - { - struct skill_unit *unit2; - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sg->src_id == bl->id) - break; - if(sc_data && sc_data[type].timer==-1) - skill_status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if( (unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){ - if( unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - skill_status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } break; - - case 0xaa: /* イドゥンの林檎 */ - { - struct skill_unit *unit2; - struct status_change *sc_data=battle_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sg->src_id == bl->id) - break; - if( sc_data && sc_data[type].timer==-1) - skill_status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if((unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){ - if( DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - skill_status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } break; - - case 0xb1: /* デモンストレーション */ - skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - if(bl->type == BL_PC && MRAND(100) < sg->skill_lv && battle_config.equipment_breaking) - pc_breakweapon((struct map_session_data *)bl); - break; - case 0x99: /* トーキーボックス */ - if(sg->src_id == bl->id) //自分が踏んでも発動しない - break; - if(sg->val2==0){ - clif_talkiebox(&src->bl,sg->valstr); - sg->unit_id = 0x8c; - clif_changelook(&src->bl,LOOK_BASE,sg->unit_id); - sg->limit=DIFF_TICK(tick,sg->tick)+5000; - sg->val2=-1; //踏んだ - } - break; - case 0xb2: /* あなたを_会いたいです */ - case 0xb3: /* ゴスペル */ - case 0xb6: /* フォグウォール */ - //とりあえず何もしない - break; + if (ss->type == BL_PC) + nullpo_retr (0, srcsd = (struct map_session_data *) ss); + if (srcsd && srcsd->chatID) + return 0; + if (bl->type != BL_PC && bl->type != BL_MOB) + return 0; + nullpo_retr (0, ts = skill_unitgrouptickset_search (bl, sg->group_id)); + diff = DIFF_TICK (tick, ts->tick); + goflag = (diff > sg->interval || diff < 0); + if (sg->skill_id == CR_GRANDCROSS && !battle_config.gx_allhit) // 重なっていたら3HITしない + goflag = (diff > sg->interval * map_count_oncell (bl->m, bl->x, bl->y) + || diff < 0); + + //対象がLP上に居る場合は無効 + map_foreachinarea (skill_landprotector, bl->m, bl->x, bl->y, bl->x, bl->y, + BL_SKILL, 0, &goflag); + + if (!goflag) + return 0; + ts->tick = tick; + ts->group_id = sg->group_id; + + switch (sg->unit_id) + { + case 0x83: /* サンクチュアリ */ + { + int race = battle_get_race (bl); + int damage_flag = + (battle_check_undead (race, battle_get_elem_type (bl)) + || race == 6) ? 1 : 0; + + if (battle_get_hp (bl) >= battle_get_max_hp (bl) && !damage_flag) + break; + + if ((sg->val1--) <= 0) + { + skill_delunitgroup (sg); + return 0; + } + if (!damage_flag) + { + int heal = sg->val2; + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + heal = 0; /* 黄金蟲カード(ヒール量0) */ + clif_skill_nodamage (&src->bl, bl, AL_HEAL, heal, 1); + battle_heal (NULL, bl, heal, 0, 0); + } + else + skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id, + sg->skill_lv, tick, 0); + } + break; + case 0x84: /* マグヌスエクソシズム */ + { + int race = battle_get_race (bl); + int damage_flag = + (battle_check_undead (race, battle_get_elem_type (bl)) + || race == 6) ? 1 : 0; + if (!damage_flag) + return 0; + skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id, + sg->skill_lv, tick, 0); + } + break; + case 0x85: /* ニューマ */ + { + struct skill_unit *unit2; + struct status_change *sc_data = battle_get_sc_data (bl); + int type = SC_PNEUMA; + if (sc_data && sc_data[type].timer == -1) + skill_status_change_start (bl, type, sg->skill_lv, (int) src, + 0, 0, 0, 0); + else if ((unit2 = (struct skill_unit *) sc_data[type].val2) + && unit2 != src) + { + if (DIFF_TICK (sg->tick, unit2->group->tick) > 0) + skill_status_change_start (bl, type, sg->skill_lv, + (int) src, 0, 0, 0, 0); + ts->tick -= sg->interval; + } + } + break; + case 0x7e: /* セイフティウォール */ + { + struct skill_unit *unit2; + struct status_change *sc_data = battle_get_sc_data (bl); + int type = SC_SAFETYWALL; + if (sc_data && sc_data[type].timer == -1) + skill_status_change_start (bl, type, sg->skill_lv, (int) src, + 0, 0, 0, 0); + else if ((unit2 = (struct skill_unit *) sc_data[type].val2) + && unit2 != src) + { + if (sg->val1 < unit2->group->val1) + skill_status_change_start (bl, type, sg->skill_lv, + (int) src, 0, 0, 0, 0); + ts->tick -= sg->interval; + } + } + break; + case 0x86: /* ロードオブヴァーミリオン(&ストームガスト &グランドクロス) */ + skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id, + sg->skill_lv, tick, 0); + break; - case 0xb7: /* スパイダーウェッブ */ - if(sg->val2==0){ - int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE); - skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick); - if(moveblock) map_delblock(bl); - bl->x = (&src->bl)->x; - bl->y = (&src->bl)->y; - if(moveblock) map_addblock(bl); - if(bl->type == BL_MOB) - clif_fixmobpos((struct mob_data *)bl); - else - clif_fixpos(bl); - clif_01ac(&src->bl); - sg->limit=DIFF_TICK(tick,sg->tick) + skill_get_time2(sg->skill_id,sg->skill_lv); - sg->val2=bl->id; - } - break; + case 0x7f: /* ファイヤーウォール */ + if ((src->val2--) > 0) + skill_attack (BF_MAGIC, ss, &src->bl, bl, + sg->skill_id, sg->skill_lv, tick, 0); + if (src->val2 <= 0) + skill_delunit (src); + break; + + case 0x87: /* ファイアーピラー(発動前) */ + skill_delunit (src); + skill_unitsetting (ss, sg->skill_id, sg->skill_lv, src->bl.x, + src->bl.y, 1); + break; + + case 0x88: /* ファイアーピラー(発動後) */ + if (DIFF_TICK (tick, sg->tick) < 150) + skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id, + sg->skill_lv, tick, 0); + break; + + case 0x90: /* スキッドトラップ */ + { + 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: /* ランドマイン */ + 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: /* ブラストマイン */ + case 0x94: /* ショックウェーブトラップ */ + case 0x95: /* サンドマン */ + case 0x96: /* フラッシャー */ + case 0x97: /* フリージングトラップ */ + case 0x98: /* クレイモアートラップ */ + 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: /* アンクルスネア */ + { + struct status_change *sc_data = battle_get_sc_data (bl); + if (sg->val2 == 0 && sc_data && sc_data[SC_ANKLE].timer == -1) + { + int moveblock = (bl->x / BLOCK_SIZE != src->bl.x / BLOCK_SIZE + || bl->y / BLOCK_SIZE != + src->bl.y / BLOCK_SIZE); + int sec = skill_get_time2 (sg->skill_id, + sg->skill_lv) - + (double) battle_get_agi (bl) * 0.1; + if (battle_get_mode (bl) & 0x20) + sec = sec / 5; + battle_stopwalking (bl, 1); + skill_status_change_start (bl, SC_ANKLE, sg->skill_lv, 0, 0, + 0, sec, 0); + + if (moveblock) + map_delblock (bl); + bl->x = src->bl.x; + bl->y = src->bl.y; + if (moveblock) + map_addblock (bl); + if (bl->type == BL_MOB) + clif_fixmobpos ((struct mob_data *) bl); + else + clif_fixpos (bl); + clif_01ac (&src->bl); + sg->limit = DIFF_TICK (tick, sg->tick) + sec; + sg->val2 = bl->id; + } + } + break; + + case 0x80: /* ワープポータル(発動後) */ + if (bl->type == BL_PC) + { + struct map_session_data *sd = (struct map_session_data *) bl; + if (sd && src->bl.m == bl->m && src->bl.x == bl->x + && src->bl.y == bl->y && src->bl.x == sd->to_x + && src->bl.y == sd->to_y) + { + if (battle_config.chat_warpportal || !sd->chatID) + { + if ((sg->val1--) > 0) + { + pc_setpos (sd, sg->valstr, sg->val2 >> 16, + sg->val2 & 0xffff, 3); + if (sg->src_id == bl->id + || (strcmp (map[src->bl.m].name, sg->valstr) + == 0 && src->bl.x == (sg->val2 >> 16) + && src->bl.y == (sg->val2 & 0xffff))) + skill_delunitgroup (sg); + } + else + skill_delunitgroup (sg); + } + } + } + else if (bl->type == BL_MOB && battle_config.mob_warpportal) + { + int m = map_mapname2mapid (sg->valstr); + struct mob_data *md; + md = (struct mob_data *) bl; + mob_warp ((struct mob_data *) bl, m, sg->val2 >> 16, + sg->val2 & 0xffff, 3); + } + break; + + case 0x8e: /* クァグマイア */ + { + int type = SkillStatusChangeTable[sg->skill_id]; + if (bl->type == BL_PC + && ((struct map_session_data *) bl)-> + special_state.no_magic_damage) + break; + if (battle_get_sc_data (bl)[type].timer == -1) + skill_status_change_start (bl, type, sg->skill_lv, (int) src, + 0, 0, + skill_get_time2 (sg->skill_id, + sg->skill_lv), 0); + } + break; + case 0x92: /* ベノムダスト */ + { + struct status_change *sc_data = battle_get_sc_data (bl); + int type = SkillStatusChangeTable[sg->skill_id]; + if (sc_data && sc_data[type].timer == -1) + skill_status_change_start (bl, type, sg->skill_lv, (int) src, + 0, 0, + skill_get_time2 (sg->skill_id, + sg->skill_lv), 0); + } + break; + case 0x9a: /* ボルケーノ */ + case 0x9b: /* デリュージ */ + case 0x9c: /* バイオレントゲイル */ + { + struct skill_unit *unit2; + struct status_change *sc_data = battle_get_sc_data (bl); + int type = SkillStatusChangeTable[sg->skill_id]; + if (sc_data && sc_data[type].timer == -1) + skill_status_change_start (bl, type, sg->skill_lv, (int) src, + 0, 0, + skill_get_time2 (sg->skill_id, + sg->skill_lv), 0); + else if ((unit2 = (struct skill_unit *) sc_data[type].val2) + && unit2 != src) + { + if (DIFF_TICK (sg->tick, unit2->group->tick) > 0) + skill_status_change_start (bl, type, sg->skill_lv, + (int) src, 0, 0, + skill_get_time2 (sg->skill_id, + sg->skill_lv), + 0); + ts->tick -= sg->interval; + } + } break; + + case 0x9e: /* 子守唄 */ + case 0x9f: /* ニヨルドの宴 */ + case 0xa0: /* 永遠の混沌 */ + case 0xa1: /* 戦太鼓の響き */ + case 0xa2: /* ニーベルングの指輪 */ + case 0xa3: /* ロキの叫び */ + case 0xa4: /* 深淵の中に */ + case 0xa5: /* 不死身のジークフリード */ + case 0xa6: /* 不協和音 */ + case 0xa7: /* 口笛 */ + case 0xa8: /* 夕陽のアサシンクロス */ + case 0xa9: /* ブラギの詩 */ + case 0xab: /* 自分勝手なダンス */ + case 0xac: /* ハミング */ + case 0xad: /* 私を忘れないで… */ + case 0xae: /* 幸運のキス */ + case 0xaf: /* サービスフォーユー */ + case 0xb4: + { + struct skill_unit *unit2; + struct status_change *sc_data = battle_get_sc_data (bl); + int type = SkillStatusChangeTable[sg->skill_id]; + if (sg->src_id == bl->id) + break; + if (sc_data && sc_data[type].timer == -1) + skill_status_change_start (bl, type, sg->skill_lv, sg->val1, + sg->val2, (int) src, + skill_get_time2 (sg->skill_id, + sg->skill_lv), 0); + else if ((unit2 = (struct skill_unit *) sc_data[type].val4) + && unit2 != src) + { + if (unit2->group + && DIFF_TICK (sg->tick, unit2->group->tick) > 0) + skill_status_change_start (bl, type, sg->skill_lv, + sg->val1, sg->val2, (int) src, + skill_get_time2 (sg->skill_id, + sg->skill_lv), + 0); + ts->tick -= sg->interval; + } + } break; + + case 0xaa: /* イドゥンの林檎 */ + { + struct skill_unit *unit2; + struct status_change *sc_data = battle_get_sc_data (bl); + int type = SkillStatusChangeTable[sg->skill_id]; + if (sg->src_id == bl->id) + break; + if (sc_data && sc_data[type].timer == -1) + skill_status_change_start (bl, type, sg->skill_lv, + (sg->val1) >> 16, + (sg->val1) & 0xffff, (int) src, + skill_get_time2 (sg->skill_id, + sg->skill_lv), 0); + else if ((unit2 = (struct skill_unit *) sc_data[type].val4) + && unit2 != src) + { + if (DIFF_TICK (sg->tick, unit2->group->tick) > 0) + skill_status_change_start (bl, type, sg->skill_lv, + (sg->val1) >> 16, + (sg->val1) & 0xffff, (int) src, + skill_get_time2 (sg->skill_id, + sg->skill_lv), + 0); + ts->tick -= sg->interval; + } + } break; + + case 0xb1: /* デモンストレーション */ + skill_attack (BF_WEAPON, ss, &src->bl, bl, sg->skill_id, + sg->skill_lv, tick, 0); + if (bl->type == BL_PC && MRAND (100) < sg->skill_lv + && battle_config.equipment_breaking) + pc_breakweapon ((struct map_session_data *) bl); + break; + case 0x99: /* トーキーボックス */ + if (sg->src_id == bl->id) //自分が踏んでも発動しない + break; + if (sg->val2 == 0) + { + clif_talkiebox (&src->bl, sg->valstr); + sg->unit_id = 0x8c; + clif_changelook (&src->bl, LOOK_BASE, sg->unit_id); + sg->limit = DIFF_TICK (tick, sg->tick) + 5000; + sg->val2 = -1; //踏んだ + } + break; + case 0xb2: /* あなたを_会いたいです */ + case 0xb3: /* ゴスペル */ + case 0xb6: /* フォグウォール */ + //とりあえず何もしない + break; + + case 0xb7: /* スパイダーウェッブ */ + if (sg->val2 == 0) + { + int moveblock = (bl->x / BLOCK_SIZE != src->bl.x / BLOCK_SIZE + || bl->y / BLOCK_SIZE != + src->bl.y / BLOCK_SIZE); + skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv, + BF_MISC, tick); + if (moveblock) + map_delblock (bl); + bl->x = (&src->bl)->x; + bl->y = (&src->bl)->y; + if (moveblock) + map_addblock (bl); + if (bl->type == BL_MOB) + clif_fixmobpos ((struct mob_data *) bl); + else + clif_fixpos (bl); + clif_01ac (&src->bl); + sg->limit = + DIFF_TICK (tick, + sg->tick) + skill_get_time2 (sg->skill_id, + sg->skill_lv); + sg->val2 = bl->id; + } + break; /* 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) /* スキル使用条件のMOBスキル */ - { - 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)); - } + } + if (bl->type == BL_MOB && ss != bl) /* スキル使用条件のMOBスキル */ + { + 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; + return 0; } + /*========================================== * スキルユニットから離脱する(もしくはしている)場合 *------------------------------------------ */ -int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int tick) +int skill_unit_onout (struct skill_unit *src, struct block_list *bl, + unsigned int tick) { - struct skill_unit_group *sg; - - nullpo_retr(0, src); - nullpo_retr(0, bl); - nullpo_retr(0, sg=src->group); - - if( bl->prev==NULL || !src->alive ) - return 0; - - if( bl->type!=BL_PC && bl->type!=BL_MOB ) - return 0; - - switch(sg->unit_id){ - case 0x7e: /* セイフティウォール */ - case 0x85: /* ニューマ */ - case 0x8e: /* クァグマイア */ - { - struct status_change *sc_data=battle_get_sc_data(bl); - int type= - (sg->unit_id==0x85)?SC_PNEUMA: - ((sg->unit_id==0x7e)?SC_SAFETYWALL: - SC_QUAGMIRE); - if((type != SC_QUAGMIRE || bl->type != BL_MOB) && - sc_data && sc_data[type].timer!=-1 && ((struct skill_unit *)sc_data[type].val2)==src){ - skill_status_change_end(bl,type,-1); - } - } break; - - case 0x91: /* アンクルスネア */ - { - struct block_list *target=map_id2bl(sg->val2); - if( target && target==bl ){ - skill_status_change_end(bl,SC_ANKLE,-1); - sg->limit=DIFF_TICK(tick,sg->tick)+1000; - } - } - break; - case 0xb5: - case 0xb8: - { - struct block_list *target=map_id2bl(sg->val2); - if( target==bl ) - skill_status_change_end(bl,SC_SPIDERWEB,-1); - sg->limit=DIFF_TICK(tick,sg->tick)+1000; - } - break; - case 0xb6: - { - struct block_list *target=map_id2bl(sg->val2); - if( target==bl ) - skill_status_change_end(bl,SC_FOGWALL,-1); - sg->limit=DIFF_TICK(tick,sg->tick)+1000; - } - break; - case 0x9a: /* ボルケーノ */ - case 0x9b: /* デリュージ */ - case 0x9c: /* バイオレントゲイル */ - { - struct status_change *sc_data=battle_get_sc_data(bl); - struct skill_unit *su; - int type=SkillStatusChangeTable[sg->skill_id]; - if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val2)) && su == src ){ - skill_status_change_end(bl,type,-1); - } - } - break; - - case 0x9e: /* 子守唄 */ - case 0x9f: /* ニヨルドの宴 */ - case 0xa0: /* 永遠の混沌 */ - case 0xa1: /* 戦太鼓の響き */ - case 0xa2: /* ニーベルングの指輪 */ - case 0xa3: /* ロキの叫び */ - case 0xa4: /* 深淵の中に */ - case 0xa5: /* 不死身のジークフリード */ - case 0xa6: /* 不協和音 */ - case 0xa7: /* 口笛 */ - case 0xa8: /* 夕陽のアサシンクロス */ - case 0xa9: /* ブラギの詩 */ - case 0xaa: /* イドゥンの林檎 */ - case 0xab: /* 自分勝手なダンス */ - case 0xac: /* ハミング */ - case 0xad: /* 私を忘れないで… */ - case 0xae: /* 幸運のキス */ - case 0xaf: /* サービスフォーユー */ - case 0xb4: - { - struct status_change *sc_data=battle_get_sc_data(bl); - struct skill_unit *su; - int type=SkillStatusChangeTable[sg->skill_id]; - if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val4)) && su == src ){ - skill_status_change_end(bl,type,-1); - } - } - break; - case 0xb7: /* スパイダーウェッブ */ - { - struct block_list *target=map_id2bl(sg->val2); - if( target && target==bl ) - skill_status_change_end(bl,SC_SPIDERWEB,-1); - sg->limit=DIFF_TICK(tick,sg->tick)+1000; - } - break; + struct skill_unit_group *sg; + + nullpo_retr (0, src); + nullpo_retr (0, bl); + nullpo_retr (0, sg = src->group); + + if (bl->prev == NULL || !src->alive) + return 0; + + if (bl->type != BL_PC && bl->type != BL_MOB) + return 0; + + switch (sg->unit_id) + { + case 0x7e: /* セイフティウォール */ + case 0x85: /* ニューマ */ + case 0x8e: /* クァグマイア */ + { + struct status_change *sc_data = battle_get_sc_data (bl); + int type = + (sg->unit_id == 0x85) ? SC_PNEUMA : + ((sg->unit_id == 0x7e) ? SC_SAFETYWALL : SC_QUAGMIRE); + if ((type != SC_QUAGMIRE || bl->type != BL_MOB) && + sc_data && sc_data[type].timer != -1 + && ((struct skill_unit *) sc_data[type].val2) == src) + { + skill_status_change_end (bl, type, -1); + } + } break; + + case 0x91: /* アンクルスネア */ + { + struct block_list *target = map_id2bl (sg->val2); + if (target && target == bl) + { + skill_status_change_end (bl, SC_ANKLE, -1); + sg->limit = DIFF_TICK (tick, sg->tick) + 1000; + } + } + break; + case 0xb5: + case 0xb8: + { + struct block_list *target = map_id2bl (sg->val2); + if (target == bl) + skill_status_change_end (bl, SC_SPIDERWEB, -1); + sg->limit = DIFF_TICK (tick, sg->tick) + 1000; + } + break; + case 0xb6: + { + struct block_list *target = map_id2bl (sg->val2); + if (target == bl) + skill_status_change_end (bl, SC_FOGWALL, -1); + sg->limit = DIFF_TICK (tick, sg->tick) + 1000; + } + break; + case 0x9a: /* ボルケーノ */ + case 0x9b: /* デリュージ */ + case 0x9c: /* バイオレントゲイル */ + { + struct status_change *sc_data = battle_get_sc_data (bl); + struct skill_unit *su; + int type = SkillStatusChangeTable[sg->skill_id]; + if (sc_data && sc_data[type].timer != -1 + && (su = ((struct skill_unit *) sc_data[type].val2)) + && su == src) + { + skill_status_change_end (bl, type, -1); + } + } + break; + + case 0x9e: /* 子守唄 */ + case 0x9f: /* ニヨルドの宴 */ + case 0xa0: /* 永遠の混沌 */ + case 0xa1: /* 戦太鼓の響き */ + case 0xa2: /* ニーベルングの指輪 */ + case 0xa3: /* ロキの叫び */ + case 0xa4: /* 深淵の中に */ + case 0xa5: /* 不死身のジークフリード */ + case 0xa6: /* 不協和音 */ + case 0xa7: /* 口笛 */ + case 0xa8: /* 夕陽のアサシンクロス */ + case 0xa9: /* ブラギの詩 */ + case 0xaa: /* イドゥンの林檎 */ + case 0xab: /* 自分勝手なダンス */ + case 0xac: /* ハミング */ + case 0xad: /* 私を忘れないで… */ + case 0xae: /* 幸運のキス */ + case 0xaf: /* サービスフォーユー */ + case 0xb4: + { + struct status_change *sc_data = battle_get_sc_data (bl); + struct skill_unit *su; + int type = SkillStatusChangeTable[sg->skill_id]; + if (sc_data && sc_data[type].timer != -1 + && (su = ((struct skill_unit *) sc_data[type].val4)) + && su == src) + { + skill_status_change_end (bl, type, -1); + } + } + break; + case 0xb7: /* スパイダーウェッブ */ + { + struct block_list *target = map_id2bl (sg->val2); + if (target && target == bl) + skill_status_change_end (bl, SC_SPIDERWEB, -1); + sg->limit = DIFF_TICK (tick, sg->tick) + 1000; + } + break; /* default: if(battle_config.error_log) printf("skill_unit_onout: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); break;*/ - } - skill_unitgrouptickset_delete(bl,sg->group_id); - return 0; + } + skill_unitgrouptickset_delete (bl, sg->group_id); + return 0; } + /*========================================== * スキルユニットの削除イベント *------------------------------------------ */ -int skill_unit_ondelete(struct skill_unit *src,struct block_list *bl,unsigned int tick) +int skill_unit_ondelete (struct skill_unit *src, struct block_list *bl, + unsigned int tick) { - struct skill_unit_group *sg; - - nullpo_retr(0, src); - nullpo_retr(0, bl); - nullpo_retr(0, sg = src->group); - - if( bl->prev==NULL || !src->alive ) - return 0; - - if( bl->type!=BL_PC && bl->type!=BL_MOB ) - return 0; - - switch(sg->unit_id){ - case 0x85: /* ニューマ */ - case 0x7e: /* セイフティウォール */ - case 0x8e: /* クァグマイヤ */ - case 0x9a: /* ボルケーノ */ - case 0x9b: /* デリュージ */ - case 0x9c: /* バイオレントゲイル */ - case 0x9e: /* 子守唄 */ - case 0x9f: /* ニヨルドの宴 */ - case 0xa0: /* 永遠の混沌 */ - case 0xa1: /* 戦太鼓の響き */ - case 0xa2: /* ニーベルングの指輪 */ - case 0xa3: /* ロキの叫び */ - case 0xa4: /* 深淵の中に */ - case 0xa5: /* 不死身のジークフリード */ - case 0xa6: /* 不協和音 */ - case 0xa7: /* 口笛 */ - case 0xa8: /* 夕陽のアサシンクロス */ - case 0xa9: /* ブラギの詩 */ - case 0xaa: /* イドゥンの林檎 */ - case 0xab: /* 自分勝手なダンス */ - case 0xac: /* ハミング */ - case 0xad: /* 私を忘れないで… */ - case 0xae: /* 幸運のキス */ - case 0xaf: /* サービスフォーユー */ - case 0xb4: - return skill_unit_onout(src,bl,tick); + struct skill_unit_group *sg; + + nullpo_retr (0, src); + nullpo_retr (0, bl); + nullpo_retr (0, sg = src->group); + + if (bl->prev == NULL || !src->alive) + return 0; + + if (bl->type != BL_PC && bl->type != BL_MOB) + return 0; + + switch (sg->unit_id) + { + case 0x85: /* ニューマ */ + case 0x7e: /* セイフティウォール */ + case 0x8e: /* クァグマイヤ */ + case 0x9a: /* ボルケーノ */ + case 0x9b: /* デリュージ */ + case 0x9c: /* バイオレントゲイル */ + case 0x9e: /* 子守唄 */ + case 0x9f: /* ニヨルドの宴 */ + case 0xa0: /* 永遠の混沌 */ + case 0xa1: /* 戦太鼓の響き */ + case 0xa2: /* ニーベルングの指輪 */ + case 0xa3: /* ロキの叫び */ + case 0xa4: /* 深淵の中に */ + case 0xa5: /* 不死身のジークフリード */ + case 0xa6: /* 不協和音 */ + case 0xa7: /* 口笛 */ + case 0xa8: /* 夕陽のアサシンクロス */ + case 0xa9: /* ブラギの詩 */ + case 0xaa: /* イドゥンの林檎 */ + case 0xab: /* 自分勝手なダンス */ + case 0xac: /* ハミング */ + case 0xad: /* 私を忘れないで… */ + case 0xae: /* 幸運のキス */ + case 0xaf: /* サービスフォーユー */ + case 0xb4: + return skill_unit_onout (src, bl, tick); /* default: if(battle_config.error_log) printf("skill_unit_ondelete: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); break;*/ - } - skill_unitgrouptickset_delete(bl,sg->group_id); - return 0; + } + skill_unitgrouptickset_delete (bl, sg->group_id); + return 0; } + /*========================================== * スキルユニットの限界イベント *------------------------------------------ */ -int skill_unit_onlimit(struct skill_unit *src,unsigned int tick) +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: /* ワープポータル(発動前) */ - { - struct skill_unit_group *group= - skill_unitsetting(map_id2bl(sg->src_id),sg->skill_id,sg->skill_lv, - src->bl.x,src->bl.y,1); - if(group == NULL) - return 0; - group->valstr=calloc(24, 1); - if(group->valstr==NULL){ - printf("skill_unit_onlimit: out of memory !\n"); - exit(1); - } - memcpy(group->valstr,sg->valstr,24); - group->val2=sg->val2; - } - break; - - case 0x8d: /* アイスウォール */ - map_setcell(src->bl.m,src->bl.x,src->bl.y,src->val2); - clif_changemapcell(src->bl.m,src->bl.x,src->bl.y,src->val2,1); - break; - case 0xb2: /* あなたに会いたい */ - { - struct map_session_data *sd = NULL; - struct map_session_data *p_sd = NULL; - if((sd = (struct map_session_data *)(map_id2bl(sg->src_id))) == NULL) - return 0; - if((p_sd = pc_get_partner(sd)) == NULL) - return 0; - - pc_setpos(p_sd,map[src->bl.m].name,src->bl.x,src->bl.y,3); - } - break; - } - return 0; + struct skill_unit_group *sg; + + nullpo_retr (0, src); + nullpo_retr (0, sg = src->group); + + switch (sg->unit_id) + { + case 0x81: /* ワープポータル(発動前) */ + { + struct skill_unit_group *group = + skill_unitsetting (map_id2bl (sg->src_id), sg->skill_id, + sg->skill_lv, + src->bl.x, src->bl.y, 1); + if (group == NULL) + return 0; + group->valstr = calloc (24, 1); + if (group->valstr == NULL) + { + printf ("skill_unit_onlimit: out of memory !\n"); + exit (1); + } + memcpy (group->valstr, sg->valstr, 24); + group->val2 = sg->val2; + } + break; + + case 0x8d: /* アイスウォール */ + map_setcell (src->bl.m, src->bl.x, src->bl.y, src->val2); + clif_changemapcell (src->bl.m, src->bl.x, src->bl.y, src->val2, + 1); + break; + case 0xb2: /* あなたに会いたい */ + { + struct map_session_data *sd = NULL; + struct map_session_data *p_sd = NULL; + if ((sd = + (struct map_session_data *) (map_id2bl (sg->src_id))) == + NULL) + return 0; + if ((p_sd = pc_get_partner (sd)) == NULL) + return 0; + + pc_setpos (p_sd, map[src->bl.m].name, src->bl.x, src->bl.y, 3); + } + break; + } + return 0; } + /*========================================== * スキルユニットのダメージイベント *------------------------------------------ */ -int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl, - int damage,unsigned int tick) +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: /* アイスウォール */ - src->val1-=damage; - break; - case 0x8f: /* ブラストマイン */ - case 0x98: /* クレイモアートラップ */ - skill_blown(bl,&src->bl,2); //吹き飛ばしてみる - break; - default: - damage = 0; - break; - } - return damage; -} + struct skill_unit_group *sg; + nullpo_retr (0, src); + nullpo_retr (0, sg = src->group); + + switch (sg->unit_id) + { + case 0x8d: /* アイスウォール */ + src->val1 -= damage; + break; + case 0x8f: /* ブラストマイン */ + case 0x98: /* クレイモアートラップ */ + skill_blown (bl, &src->bl, 2); //吹き飛ばしてみる + break; + default: + damage = 0; + break; + } + return damage; +} /*---------------------------------------------------------------------------- */ @@ -5673,150 +7001,173 @@ int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl, * スキル使用(詠唱完了、場所指定) *------------------------------------------ */ -int skill_castend_pos( int tid, unsigned int tick, int id,int data ) +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 ) /* タイマIDの確認 */ - 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; - } + struct map_session_data *sd = map_id2sd (id) /*,*target_sd=NULL */ ; + int range, maxcount; - if(battle_config.pc_skill_reiteration == 0) { - range = -1; - switch(sd->skillid) { - case MG_SAFETYWALL: - case WZ_FIREPILLAR: - case HT_SKIDTRAP: - case HT_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case HT_TALKIEBOX: - case AL_WARP: - case PF_SPIDERWEB: /* スパイダーウェッブ */ - case RG_GRAFFITI: /* グラフィティ */ - range = 0; - break; - case AL_PNEUMA: - range = 1; - break; - } - if(range >= 0) { - if(skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,range,sd->skillid) > 0) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } - } - if(battle_config.pc_skill_nofootset) { - range = -1; - switch(sd->skillid) { - case WZ_FIREPILLAR: - case HT_SKIDTRAP: - case HT_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case HT_TALKIEBOX: - case PF_SPIDERWEB: /* スパイダーウェッブ */ - case WZ_ICEWALL: - range = 1; - break; - case AL_WARP: - range = 0; - break; - } - if(range >= 0) { - if(skill_check_unit_range2(sd->bl.m,sd->skillx,sd->skilly,range) > 0) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } - } - - if(battle_config.pc_land_skill_limit) { - maxcount = skill_get_maxcount(sd->skillid); - if(maxcount > 0) { - int i,c; - for(i=c=0;i<MAX_SKILLUNITGROUP;i++) { - if(sd->skillunit[i].alive_count > 0 && sd->skillunit[i].skill_id == sd->skillid) - c++; - } - if(c >= maxcount) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } - } + nullpo_retr (0, sd); - range = skill_get_range(sd->skillid,sd->skilllv); - if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); - range += battle_config.pc_skill_add_range; - if(battle_config.skill_out_range_consume) { // changed to allow casting when target walks out of range [Valaris] - if(range < distance(sd->bl.x,sd->bl.y,sd->skillx,sd->skilly)) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } - if(!skill_check_condition(sd,1)) { /* 使用条件チェック */ - 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 (sd->bl.prev == NULL) + return 0; + if (sd->skilltimer != tid) /* タイマIDの確認 */ + return 0; + if (sd->skilltimer != -1 && pc_checkskill (sd, SA_FREECAST) > 0) + { + sd->speed = sd->prev_speed; + clif_updatestatus (sd, SP_SPEED); + } + sd->skilltimer = -1; + if (pc_isdead (sd)) + { + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + + if (battle_config.pc_skill_reiteration == 0) + { + range = -1; + switch (sd->skillid) + { + case MG_SAFETYWALL: + case WZ_FIREPILLAR: + case HT_SKIDTRAP: + case HT_LANDMINE: + case HT_ANKLESNARE: + case HT_SHOCKWAVE: + case HT_SANDMAN: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case HT_BLASTMINE: + case HT_CLAYMORETRAP: + case HT_TALKIEBOX: + case AL_WARP: + case PF_SPIDERWEB: /* スパイダーウェッブ */ + case RG_GRAFFITI: /* グラフィティ */ + range = 0; + break; + case AL_PNEUMA: + range = 1; + break; + } + if (range >= 0) + { + if (skill_check_unit_range + (sd->bl.m, sd->skillx, sd->skilly, range, sd->skillid) > 0) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + } + } + if (battle_config.pc_skill_nofootset) + { + range = -1; + switch (sd->skillid) + { + case WZ_FIREPILLAR: + case HT_SKIDTRAP: + case HT_LANDMINE: + case HT_ANKLESNARE: + case HT_SHOCKWAVE: + case HT_SANDMAN: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case HT_BLASTMINE: + case HT_CLAYMORETRAP: + case HT_TALKIEBOX: + case PF_SPIDERWEB: /* スパイダーウェッブ */ + case WZ_ICEWALL: + range = 1; + break; + case AL_WARP: + range = 0; + break; + } + if (range >= 0) + { + if (skill_check_unit_range2 + (sd->bl.m, sd->skillx, sd->skilly, range) > 0) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + } + } + + if (battle_config.pc_land_skill_limit) + { + maxcount = skill_get_maxcount (sd->skillid); + if (maxcount > 0) + { + int i, c; + for (i = c = 0; i < MAX_SKILLUNITGROUP; i++) + { + if (sd->skillunit[i].alive_count > 0 + && sd->skillunit[i].skill_id == sd->skillid) + c++; + } + if (c >= maxcount) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + } + } + + range = skill_get_range (sd->skillid, sd->skilllv); + if (range < 0) + range = battle_get_range (&sd->bl) - (range + 1); + range += battle_config.pc_skill_add_range; + if (battle_config.skill_out_range_consume) + { // changed to allow casting when target walks out of range [Valaris] + if (range < distance (sd->bl.x, sd->bl.y, sd->skillx, sd->skilly)) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + } + if (!skill_check_condition (sd, 1)) + { /* 使用条件チェック */ + 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); + 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); + skill_castend_pos2 (&sd->bl, sd->skillx, sd->skilly, sd->skillid, + sd->skilllv, tick, 0); - return 0; + return 0; } /*========================================== @@ -5824,526 +7175,621 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) *------------------------------------------ */ -static int skill_check_condition_char_sub(struct block_list *bl,va_list ap) +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); - //チェックしない設定ならcにありえない大きな数字を返して終了 - if(!battle_config.player_skill_partner_check){ //本当はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ - (*c)=99; - return 0; - } - - ; - ss_class = pc_calc_base_job(ssd->status.class); - - switch(ssd->skillid){ - case PR_BENEDICTIO: /* 聖体降福 */ - if(sd != ssd && (sd->status.class == 4 || sd->status.class == 8 || sd->status.class == 15 || - sd->status.class == 4005 || sd->status.class == 4009 || sd->status.class == 4016) && - (sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1) && sd->status.sp >= 10) - (*c)++; - break; - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジークフリード */ - case BD_RAGNAROK: /* 神々の黄昏 */ - case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ - if(sd != ssd && - ((ssd->status.class==19 && sd->status.class==20) || - (ssd->status.class==20 && sd->status.class==19) || - (ssd->status.class==4020 && sd->status.class==4021) || - (ssd->status.class==4021 && sd->status.class==4020) || - (ssd->status.class==20 && sd->status.class==4020) || - (ssd->status.class==19 && sd->status.class==4021)) && - 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; + 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); + //チェックしない設定ならcにありえない大きな数字を返して終了 + if (!battle_config.player_skill_partner_check) + { //本当はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ + (*c) = 99; + return 0; + } + + ; + ss_class = pc_calc_base_job (ssd->status.class); + + switch (ssd->skillid) + { + case PR_BENEDICTIO: /* 聖体降福 */ + if (sd != ssd + && (sd->status.class == 4 || sd->status.class == 8 + || sd->status.class == 15 || sd->status.class == 4005 + || sd->status.class == 4009 || sd->status.class == 4016) + && (sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1) + && sd->status.sp >= 10) + (*c)++; + break; + case BD_LULLABY: /* 子守歌 */ + case BD_RICHMANKIM: /* ニヨルドの宴 */ + case BD_ETERNALCHAOS: /* 永遠の混沌 */ + case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ + case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ + case BD_ROKISWEIL: /* ロキの叫び */ + case BD_INTOABYSS: /* 深淵の中に */ + case BD_SIEGFRIED: /* 不死身のジークフリード */ + case BD_RAGNAROK: /* 神々の黄昏 */ + case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ + if (sd != ssd && + ((ssd->status.class == 19 && sd->status.class == 20) || + (ssd->status.class == 20 && sd->status.class == 19) || + (ssd->status.class == 4020 && sd->status.class == 4021) || + (ssd->status.class == 4021 && sd->status.class == 4020) || + (ssd->status.class == 20 && sd->status.class == 4020) || + (ssd->status.class == 19 && sd->status.class == 4021)) && + 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; } + /*========================================== * 範囲内キャラ存在確認判定後スキル使用処理(foreachinarea) *------------------------------------------ */ -static int skill_check_condition_use_sub(struct block_list *bl,va_list ap) +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); - - //チェックしない設定ならcにありえない大きな数字を返して終了 - if(!battle_config.player_skill_partner_check){ //本当はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ - (*c)=99; - return 0; - } - - ss_class = pc_calc_base_job(ssd->status.class); - skillid=ssd->skillid; - skilllv=ssd->skilllv; - switch(skillid){ - case PR_BENEDICTIO: /* 聖体降福 */ - if(sd != ssd && (sd->status.class == 4 || sd->status.class == 8 || sd->status.class == 15 || - sd->status.class == 4005 || sd->status.class == 4009 || sd->status.class == 4016) && - (sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1) && sd->status.sp >= 10){ - sd->status.sp -= 10; - pc_calcstatus(sd,0); - (*c)++; - } - break; - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジークフリード */ - case BD_RAGNAROK: /* 神々の黄昏 */ - case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ - if(sd != ssd && //本人以外で - ((ssd->status.class==19 && sd->status.class==20) || - (ssd->status.class==20 && sd->status.class==19) || - (ssd->status.class==4020 && sd->status.class==4021) || - (ssd->status.class==4021 && sd->status.class==4020) || - (ssd->status.class==20 && sd->status.class==4020) || - (ssd->status.class==19 && sd->status.class==4021)) && //自分がダンサーならバードで - pc_checkskill(sd,skillid) > 0 && //スキルを持っていて - (*c)==0 && //最初の一人で - sd->status.party_id == ssd->status.party_id && //パーティーが同じで - !pc_issit(sd) && //座ってない - sd->sc_data[SC_DANCING].timer==-1 //ダンス中じゃない - ){ - ssd->sc_data[SC_DANCING].val4=bl->id; - clif_skill_nodamage(bl,src,skillid,skilllv,1); - skill_status_change_start(bl,SC_DANCING,skillid,ssd->sc_data[SC_DANCING].val2,0,src->id,skill_get_time(skillid,skilllv)+1000,0); - sd->skillid_dance=sd->skillid=skillid; - sd->skilllv_dance=sd->skilllv=skilllv; - (*c)++; - } - break; - } - return 0; + 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); + + //チェックしない設定ならcにありえない大きな数字を返して終了 + if (!battle_config.player_skill_partner_check) + { //本当はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ + (*c) = 99; + return 0; + } + + ss_class = pc_calc_base_job (ssd->status.class); + skillid = ssd->skillid; + skilllv = ssd->skilllv; + switch (skillid) + { + case PR_BENEDICTIO: /* 聖体降福 */ + if (sd != ssd + && (sd->status.class == 4 || sd->status.class == 8 + || sd->status.class == 15 || sd->status.class == 4005 + || sd->status.class == 4009 || sd->status.class == 4016) + && (sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1) + && sd->status.sp >= 10) + { + sd->status.sp -= 10; + pc_calcstatus (sd, 0); + (*c)++; + } + break; + case BD_LULLABY: /* 子守歌 */ + case BD_RICHMANKIM: /* ニヨルドの宴 */ + case BD_ETERNALCHAOS: /* 永遠の混沌 */ + case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ + case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ + case BD_ROKISWEIL: /* ロキの叫び */ + case BD_INTOABYSS: /* 深淵の中に */ + case BD_SIEGFRIED: /* 不死身のジークフリード */ + case BD_RAGNAROK: /* 神々の黄昏 */ + case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ + if (sd != ssd && //本人以外で + ((ssd->status.class == 19 && sd->status.class == 20) || (ssd->status.class == 20 && sd->status.class == 19) || (ssd->status.class == 4020 && sd->status.class == 4021) || (ssd->status.class == 4021 && sd->status.class == 4020) || (ssd->status.class == 20 && sd->status.class == 4020) || (ssd->status.class == 19 && sd->status.class == 4021)) && //自分がダンサーならバードで + pc_checkskill (sd, skillid) > 0 && //スキルを持っていて + (*c) == 0 && //最初の一人で + sd->status.party_id == ssd->status.party_id && //パーティーが同じで + !pc_issit (sd) && //座ってない + sd->sc_data[SC_DANCING].timer == -1 //ダンス中じゃない + ) + { + ssd->sc_data[SC_DANCING].val4 = bl->id; + clif_skill_nodamage (bl, src, skillid, skilllv, 1); + skill_status_change_start (bl, SC_DANCING, skillid, + ssd->sc_data[SC_DANCING].val2, 0, + src->id, skill_get_time (skillid, + skilllv) + + 1000, 0); + sd->skillid_dance = sd->skillid = skillid; + sd->skilllv_dance = sd->skilllv = skilllv; + (*c)++; + } + break; + } + return 0; } + /*========================================== * 範囲内バイオプラント、スフィアマイン用Mob存在確認判定処理(foreachinarea) *------------------------------------------ */ -static int skill_check_condition_mob_master_sub(struct block_list *bl,va_list ap) +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; + 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; } /*========================================== * スキル使用条件(偽で使用失敗) *------------------------------------------ */ -int skill_check_condition(struct map_session_data *sd,int type) +int skill_check_condition (struct map_session_data *sd, int type) { - int i,hp,sp,hp_rate,sp_rate,zeny,weapon,state,spiritball,skill,lv,mhp; - int index[10],itemid[10],amount[10]; - - nullpo_retr(0, sd); - - if( battle_config.gm_skilluncond>0 && pc_isGM(sd)>= battle_config.gm_skilluncond ) { - sd->skillitem = sd->skillitemlv = -1; - return 1; - } - - if( sd->opt1>0) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - if(pc_is90overweight(sd)) { - clif_skill_fail(sd,sd->skillid,9,0); - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - - if(sd->skillid == AC_MAKINGARROW && sd->state.make_arrow_flag == 1) { - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - /*if(sd->skillid == AM_PHARMACY && sd->state.produce_flag == 1) { - sd->skillitem = sd->skillitemlv = -1; - return 0; - }*/ - - if(sd->skillitem == sd->skillid) { /* アイテムの場合無条件成功 */ - if(type&1) - sd->skillitem = sd->skillitemlv = -1; - return 1; - } - if( sd->opt1>0 ){ - clif_skill_fail(sd,sd->skillid,0,0); - return 0; - } - if(sd->sc_data){ - if( sd->sc_data[SC_DIVINA].timer!=-1 || - sd->sc_data[SC_ROKISWEIL].timer!=-1 || - (sd->sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) || - sd->sc_data[SC_STEELBODY].timer != -1 || - sd->sc_data[SC_BERSERK].timer != -1 - ){ - clif_skill_fail(sd,sd->skillid,0,0); - return 0; /* 状態異常や沈黙など */ - } - } - skill = sd->skillid; - lv = sd->skilllv; - hp=skill_get_hp(skill, lv); /* 消費HP */ - sp=skill_get_sp(skill, lv); /* 消費SP */ - if((sd->skillid_old == BD_ENCORE) && skill==sd->skillid_dance) - sp=sp/2; //アンコール時はSP消費が半分 - hp_rate = (lv <= 0)? 0:skill_db[skill].hp_rate[lv-1]; - sp_rate = (lv <= 0)? 0:skill_db[skill].sp_rate[lv-1]; - zeny = skill_get_zeny(skill,lv); - weapon = skill_db[skill].weapon; - state = skill_db[skill].state; - spiritball = (lv <= 0)? 0:skill_db[skill].spiritball[lv-1]; - mhp=skill_get_mhp(skill, lv); /* 消費HP */ - for(i=0;i<10;i++) { - itemid[i] = skill_db[skill].itemid[i]; - amount[i] = skill_db[skill].amount[i]; - } - if(mhp > 0) - hp += (sd->status.max_hp * mhp)/100; - if(hp_rate > 0) - hp += (sd->status.hp * hp_rate)/100; - else - hp += (sd->status.max_hp * abs(hp_rate))/100; - if(sp_rate > 0) - sp += (sd->status.sp * sp_rate)/100; - else - sp += (sd->status.max_sp * abs(sp_rate))/100; - if(sd->dsprate!=100) - sp=sp*sd->dsprate/100; /* 消費SP修正 */ - - switch(skill) { - case SA_CASTCANCEL: - if(sd->skilltimer == -1) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case BS_MAXIMIZE: /* マキシマイズパワー */ - case NV_TRICKDEAD: /* 死んだふり */ - case TF_HIDING: /* ハイディング */ - case AS_CLOAKING: /* クローキング */ - case CR_AUTOGUARD: /* オートガード */ - case CR_DEFENDER: /* ディフェンダー */ - case ST_CHASEWALK: - if(sd->sc_data[SkillStatusChangeTable[skill]].timer!=-1) - return 1; /* 解除する場合はSP消費しない */ - break; - case AL_TELEPORT: - case AL_WARP: - if(map[sd->bl.m].flag.noteleport) { - clif_skill_teleportmessage(sd,0); - return 0; - } - break; - case MO_CALLSPIRITS: /* 気功 */ - if(sd->spiritball >= lv) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case CH_SOULCOLLECT: /* 狂気功 */ - if(sd->spiritball >= 5) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case MO_FINGEROFFENSIVE: //指弾 - if (sd->spiritball > 0 && sd->spiritball < spiritball) { - spiritball = sd->spiritball; - sd->spiritball_old = sd->spiritball; - } - else sd->spiritball_old = lv; - break; - case MO_CHAINCOMBO: //連打掌 - if(sd->sc_data[SC_BLADESTOP].timer==-1){ - if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_TRIPLEATTACK) - return 0; - } - break; - case MO_COMBOFINISH: //猛龍拳 - if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_CHAINCOMBO) - return 0; - break; - case CH_TIGERFIST: //伏虎拳 - if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH) - return 0; - break; - case CH_CHAINCRUSH: //連柱崩撃 - 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: // 阿修羅覇鳳拳 - 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: /* アドリブ */ - { - 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))){ //ダンス中で使用後5秒以上のみ? - clif_skill_fail(sd,skill,0,0); - return 0; - } - } - break; - case PR_BENEDICTIO: /* 聖体降福 */ - { - int range=1; - int c=0; - if(!(type&1)){ - map_foreachinarea(skill_check_condition_char_sub,sd->bl.m, - sd->bl.x-range,sd->bl.y-range, - sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c); - if(c<2){ - clif_skill_fail(sd,skill,0,0); - return 0; - } - }else{ - map_foreachinarea(skill_check_condition_use_sub,sd->bl.m, - sd->bl.x-range,sd->bl.y-range, - sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c); - } - } - break; - case WE_CALLPARTNER: /* あなたに逢いたい */ - if(!sd->status.partner_id){ - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case AM_CANNIBALIZE: /* バイオプラント */ - case AM_SPHEREMINE: /* スフィアーマイン */ - if(type&1){ - int c=0; - int maxcount=skill_get_maxcount(skill); - int mob_class=(skill==AM_CANNIBALIZE)?1118:1142; - if(battle_config.pc_land_skill_limit && maxcount>0) { - map_foreachinarea(skill_check_condition_mob_master_sub ,sd->bl.m, 0, 0, map[sd->bl.m].xs, map[sd->bl.m].ys, BL_MOB, sd->bl.id, mob_class,&c ); - if(c >= maxcount){ - clif_skill_fail(sd,skill,0,0); - return 0; - } - } - } - break; - case MG_FIREWALL: /* ファイアーウォール */ - /* 数制限 */ - if(battle_config.pc_land_skill_limit) { - int maxcount = skill_get_maxcount(skill); - if(maxcount > 0) { - int i,c; - for(i=c=0;i<MAX_SKILLUNITGROUP;i++) { - if(sd->skillunit[i].alive_count > 0 && sd->skillunit[i].skill_id == skill) - c++; - } - if(c >= maxcount) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - } - } - break; - } - - if(!(type&2)){ - if( hp>0 && sd->status.hp < hp) { /* HPチェック */ - clif_skill_fail(sd,skill,2,0); /* HP不足:失敗通知 */ - return 0; - } - if( sp>0 && sd->status.sp < sp) { /* SPチェック */ - clif_skill_fail(sd,skill,1,0); /* SP不足:失敗通知 */ - 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); // 氣球不足 - return 0; - } - } - - switch(state) { - case ST_HIDING: - if(!(sd->status.option&2)) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case ST_CLOAKING: - if(!(sd->status.option&4)) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case ST_HIDDEN: - if(!pc_ishiding(sd)) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case ST_RIDING: - if(!pc_isriding(sd)) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case ST_FALCON: - if(!pc_isfalcon(sd)) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case ST_CART: - if(!pc_iscarton(sd)) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case ST_SHIELD: - if(sd->status.shield <= 0) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case ST_SIGHT: - if(sd->sc_data[SC_SIGHT].timer == -1 && type&1) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case ST_EXPLOSIONSPIRITS: - if(sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case ST_RECOV_WEIGHT_RATE: - if(battle_config.natural_heal_weight_rate <= 100 && sd->weight*100/sd->max_weight >= battle_config.natural_heal_weight_rate) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case ST_MOVE_ENABLE: - { - struct walkpath_data wpd; - if(path_search(&wpd,sd->bl.m,sd->bl.x,sd->bl.y,sd->skillx,sd->skilly,1)==-1) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - } - break; - case ST_WATER: - if(map_getcell(sd->bl.m,sd->bl.x,sd->bl.y) != 3 && (sd->sc_data[SC_DELUGE].timer==-1)){ //水場判定 - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - } - - for(i=0;i<10;i++) { - int x = lv%11 - 1; - index[i] = -1; - if(itemid[i] <= 0) - continue; - if(itemid[i] >= 715 && itemid[i] <= 717 && sd->special_state.no_gemstone) - continue; - if(((itemid[i] >= 715 && itemid[i] <= 717) || itemid[i] == 1065) && sd->sc_data[SC_INTOABYSS].timer != -1) - continue; - if(skill == AM_POTIONPITCHER && i != x) - continue; - - index[i] = pc_search_inventory(sd,itemid[i]); - if(index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i]) { - if(itemid[i] == 716 || itemid[i] == 717) - clif_skill_fail(sd,skill,(7+(itemid[i]-716)),0); - else - clif_skill_fail(sd,skill,0,0); - return 0; - } - } - - if(!(type&1)) - return 1; + int i, hp, sp, hp_rate, sp_rate, zeny, weapon, state, spiritball, skill, + lv, mhp; + int index[10], itemid[10], amount[10]; + + nullpo_retr (0, sd); + + if (battle_config.gm_skilluncond > 0 + && pc_isGM (sd) >= battle_config.gm_skilluncond) + { + sd->skillitem = sd->skillitemlv = -1; + return 1; + } + + if (sd->opt1 > 0) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + if (pc_is90overweight (sd)) + { + clif_skill_fail (sd, sd->skillid, 9, 0); + sd->skillitem = sd->skillitemlv = -1; + return 0; + } - if(skill != AM_POTIONPITCHER) { - if(skill == AL_WARP && !(type&2)) - return 1; - for(i=0;i<10;i++) { - if(index[i] >= 0) - pc_delitem(sd,index[i],amount[i],0); // アイテム消費 - } - } + if (sd->skillid == AC_MAKINGARROW && sd->state.make_arrow_flag == 1) + { + sd->skillitem = sd->skillitemlv = -1; + return 0; + } + /*if(sd->skillid == AM_PHARMACY && sd->state.produce_flag == 1) { + * sd->skillitem = sd->skillitemlv = -1; + * return 0; + * } */ + + if (sd->skillitem == sd->skillid) + { /* アイテムの場合無条件成功 */ + if (type & 1) + sd->skillitem = sd->skillitemlv = -1; + return 1; + } + if (sd->opt1 > 0) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + return 0; + } + if (sd->sc_data) + { + if (sd->sc_data[SC_DIVINA].timer != -1 || + sd->sc_data[SC_ROKISWEIL].timer != -1 || + (sd->sc_data[SC_AUTOCOUNTER].timer != -1 + && sd->skillid != KN_AUTOCOUNTER) + || sd->sc_data[SC_STEELBODY].timer != -1 + || sd->sc_data[SC_BERSERK].timer != -1) + { + clif_skill_fail (sd, sd->skillid, 0, 0); + return 0; /* 状態異常や沈黙など */ + } + } + skill = sd->skillid; + lv = sd->skilllv; + hp = skill_get_hp (skill, lv); /* 消費HP */ + sp = skill_get_sp (skill, lv); /* 消費SP */ + if ((sd->skillid_old == BD_ENCORE) && skill == sd->skillid_dance) + sp = sp / 2; //アンコール時はSP消費が半分 + hp_rate = (lv <= 0) ? 0 : skill_db[skill].hp_rate[lv - 1]; + sp_rate = (lv <= 0) ? 0 : skill_db[skill].sp_rate[lv - 1]; + zeny = skill_get_zeny (skill, lv); + weapon = skill_db[skill].weapon; + state = skill_db[skill].state; + spiritball = (lv <= 0) ? 0 : skill_db[skill].spiritball[lv - 1]; + mhp = skill_get_mhp (skill, lv); /* 消費HP */ + for (i = 0; i < 10; i++) + { + itemid[i] = skill_db[skill].itemid[i]; + amount[i] = skill_db[skill].amount[i]; + } + if (mhp > 0) + hp += (sd->status.max_hp * mhp) / 100; + if (hp_rate > 0) + hp += (sd->status.hp * hp_rate) / 100; + else + hp += (sd->status.max_hp * abs (hp_rate)) / 100; + if (sp_rate > 0) + sp += (sd->status.sp * sp_rate) / 100; + else + sp += (sd->status.max_sp * abs (sp_rate)) / 100; + if (sd->dsprate != 100) + sp = sp * sd->dsprate / 100; /* 消費SP修正 */ + + switch (skill) + { + case SA_CASTCANCEL: + if (sd->skilltimer == -1) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case BS_MAXIMIZE: /* マキシマイズパワー */ + case NV_TRICKDEAD: /* 死んだふり */ + case TF_HIDING: /* ハイディング */ + case AS_CLOAKING: /* クローキング */ + case CR_AUTOGUARD: /* オートガード */ + case CR_DEFENDER: /* ディフェンダー */ + case ST_CHASEWALK: + if (sd->sc_data[SkillStatusChangeTable[skill]].timer != -1) + return 1; /* 解除する場合はSP消費しない */ + break; + case AL_TELEPORT: + case AL_WARP: + if (map[sd->bl.m].flag.noteleport) + { + clif_skill_teleportmessage (sd, 0); + return 0; + } + break; + case MO_CALLSPIRITS: /* 気功 */ + if (sd->spiritball >= lv) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case CH_SOULCOLLECT: /* 狂気功 */ + if (sd->spiritball >= 5) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case MO_FINGEROFFENSIVE: //指弾 + if (sd->spiritball > 0 && sd->spiritball < spiritball) + { + spiritball = sd->spiritball; + sd->spiritball_old = sd->spiritball; + } + else + sd->spiritball_old = lv; + break; + case MO_CHAINCOMBO: //連打掌 + if (sd->sc_data[SC_BLADESTOP].timer == -1) + { + if (sd->sc_data[SC_COMBO].timer == -1 + || sd->sc_data[SC_COMBO].val1 != MO_TRIPLEATTACK) + return 0; + } + break; + case MO_COMBOFINISH: //猛龍拳 + if (sd->sc_data[SC_COMBO].timer == -1 + || sd->sc_data[SC_COMBO].val1 != MO_CHAINCOMBO) + return 0; + break; + case CH_TIGERFIST: //伏虎拳 + if (sd->sc_data[SC_COMBO].timer == -1 + || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH) + return 0; + break; + case CH_CHAINCRUSH: //連柱崩撃 + 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: // 阿修羅覇鳳拳 + 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: /* アドリブ */ + { + 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))) + { //ダンス中で使用後5秒以上のみ? + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + } + break; + case PR_BENEDICTIO: /* 聖体降福 */ + { + int range = 1; + int c = 0; + if (!(type & 1)) + { + map_foreachinarea (skill_check_condition_char_sub, sd->bl.m, + sd->bl.x - range, sd->bl.y - range, + sd->bl.x + range, sd->bl.y + range, BL_PC, + &sd->bl, &c); + if (c < 2) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + } + else + { + map_foreachinarea (skill_check_condition_use_sub, sd->bl.m, + sd->bl.x - range, sd->bl.y - range, + sd->bl.x + range, sd->bl.y + range, BL_PC, + &sd->bl, &c); + } + } + break; + case WE_CALLPARTNER: /* あなたに逢いたい */ + if (!sd->status.partner_id) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case AM_CANNIBALIZE: /* バイオプラント */ + case AM_SPHEREMINE: /* スフィアーマイン */ + if (type & 1) + { + int c = 0; + int maxcount = skill_get_maxcount (skill); + int mob_class = (skill == AM_CANNIBALIZE) ? 1118 : 1142; + if (battle_config.pc_land_skill_limit && maxcount > 0) + { + map_foreachinarea (skill_check_condition_mob_master_sub, + sd->bl.m, 0, 0, map[sd->bl.m].xs, + map[sd->bl.m].ys, BL_MOB, sd->bl.id, + mob_class, &c); + if (c >= maxcount) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + } + } + break; + case MG_FIREWALL: /* ファイアーウォール */ + /* 数制限 */ + if (battle_config.pc_land_skill_limit) + { + int maxcount = skill_get_maxcount (skill); + if (maxcount > 0) + { + int i, c; + for (i = c = 0; i < MAX_SKILLUNITGROUP; i++) + { + if (sd->skillunit[i].alive_count > 0 + && sd->skillunit[i].skill_id == skill) + c++; + } + if (c >= maxcount) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + } + } + break; + } + + if (!(type & 2)) + { + if (hp > 0 && sd->status.hp < hp) + { /* HPチェック */ + clif_skill_fail (sd, skill, 2, 0); /* HP不足:失敗通知 */ + return 0; + } + if (sp > 0 && sd->status.sp < sp) + { /* SPチェック */ + clif_skill_fail (sd, skill, 1, 0); /* SP不足:失敗通知 */ + 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); // 氣球不足 + return 0; + } + } + + switch (state) + { + case ST_HIDING: + if (!(sd->status.option & 2)) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case ST_CLOAKING: + if (!(sd->status.option & 4)) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case ST_HIDDEN: + if (!pc_ishiding (sd)) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case ST_RIDING: + if (!pc_isriding (sd)) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case ST_FALCON: + if (!pc_isfalcon (sd)) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case ST_CART: + if (!pc_iscarton (sd)) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case ST_SHIELD: + if (sd->status.shield <= 0) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case ST_SIGHT: + if (sd->sc_data[SC_SIGHT].timer == -1 && type & 1) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case ST_EXPLOSIONSPIRITS: + if (sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case ST_RECOV_WEIGHT_RATE: + if (battle_config.natural_heal_weight_rate <= 100 + && sd->weight * 100 / sd->max_weight >= + battle_config.natural_heal_weight_rate) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + case ST_MOVE_ENABLE: + { + struct walkpath_data wpd; + if (path_search + (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, sd->skillx, sd->skilly, + 1) == -1) + { + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + } + break; + case ST_WATER: + if (map_getcell (sd->bl.m, sd->bl.x, sd->bl.y) != 3 + && (sd->sc_data[SC_DELUGE].timer == -1)) + { //水場判定 + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + break; + } + + for (i = 0; i < 10; i++) + { + int x = lv % 11 - 1; + index[i] = -1; + if (itemid[i] <= 0) + continue; + if (itemid[i] >= 715 && itemid[i] <= 717 + && sd->special_state.no_gemstone) + continue; + if (((itemid[i] >= 715 && itemid[i] <= 717) || itemid[i] == 1065) + && sd->sc_data[SC_INTOABYSS].timer != -1) + continue; + if (skill == AM_POTIONPITCHER && i != x) + continue; + + index[i] = pc_search_inventory (sd, itemid[i]); + if (index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i]) + { + if (itemid[i] == 716 || itemid[i] == 717) + clif_skill_fail (sd, skill, (7 + (itemid[i] - 716)), 0); + else + clif_skill_fail (sd, skill, 0, 0); + return 0; + } + } + + if (!(type & 1)) + return 1; + + if (skill != AM_POTIONPITCHER) + { + if (skill == AL_WARP && !(type & 2)) + return 1; + for (i = 0; i < 10; i++) + { + if (index[i] >= 0) + pc_delitem (sd, index[i], amount[i], 0); // アイテム消費 + } + } - if(type&2) - return 1; + if (type & 2) + return 1; - pc_heal(sd, -sp, -hp); // [Fate] This might suppress some dupe messages + pc_heal (sd, -sp, -hp); // [Fate] This might suppress some dupe messages /* if(sp > 0) { // SP消費 */ /* sd->status.sp-=sp; */ @@ -6353,682 +7799,790 @@ int skill_check_condition(struct map_session_data *sd,int type) /* sd->status.hp-=hp; */ /* clif_updatestatus(sd,SP_HP); */ /* } */ - if(zeny > 0) // Zeny消費 - pc_payzeny(sd,zeny); - if(spiritball > 0) // 氣球消費 - pc_delspiritball(sd,spiritball,0); + if (zeny > 0) // Zeny消費 + pc_payzeny (sd, zeny); + if (spiritball > 0) // 氣球消費 + pc_delspiritball (sd, spiritball, 0); - - return 1; + return 1; } /*========================================== * 詠唱時間計算 *------------------------------------------ */ -int skill_castfix( struct block_list *bl, int time ) +int skill_castfix (struct block_list *bl, int time) { - struct map_session_data *sd; - struct mob_data *md; // [Valaris] - struct status_change *sc_data; - int dex; - int castrate=100; - int skill,lv,castnodex; - - nullpo_retr(0, bl); - - if(bl->type==BL_MOB){ // Crash fix [Valaris] - md=(struct mob_data*)bl; - skill = md->skillid; - lv = md->skilllv; - } - - else { - sd=(struct map_session_data*)bl; - skill = sd->skillid; - lv = sd->skilllv; - } - - sc_data = battle_get_sc_data(bl); - dex=battle_get_dex(bl); - - if (skill > MAX_SKILL_DB || skill < 0) - return 0; - - castnodex=skill_get_castnodex(skill, lv); - - if(time==0) - return 0; - if(castnodex > 0 && bl->type==BL_PC) - castrate=((struct map_session_data *)bl)->castrate; - else if (castnodex <= 0 && bl->type==BL_PC) { - castrate=((struct map_session_data *)bl)->castrate; - time=time*castrate*(battle_config.castrate_dex_scale - dex)/(battle_config.castrate_dex_scale * 100); - time=time*battle_config.cast_rate/100; - } + struct map_session_data *sd; + struct mob_data *md; // [Valaris] + struct status_change *sc_data; + int dex; + int castrate = 100; + int skill, lv, castnodex; + + nullpo_retr (0, bl); + + if (bl->type == BL_MOB) + { // Crash fix [Valaris] + md = (struct mob_data *) bl; + skill = md->skillid; + lv = md->skilllv; + } + + else + { + sd = (struct map_session_data *) bl; + skill = sd->skillid; + lv = sd->skilllv; + } + + sc_data = battle_get_sc_data (bl); + dex = battle_get_dex (bl); + + if (skill > MAX_SKILL_DB || skill < 0) + return 0; - /* サフラギウム */ - if(sc_data && sc_data[SC_SUFFRAGIUM].timer!=-1 ){ - time=time*(100-sc_data[SC_SUFFRAGIUM].val1*15)/100; - skill_status_change_end( bl, SC_SUFFRAGIUM, -1); - } - /* ブラギの詩 */ - 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; + castnodex = skill_get_castnodex (skill, lv); - return (time>0)?time:0; + if (time == 0) + return 0; + if (castnodex > 0 && bl->type == BL_PC) + castrate = ((struct map_session_data *) bl)->castrate; + else if (castnodex <= 0 && bl->type == BL_PC) + { + castrate = ((struct map_session_data *) bl)->castrate; + time = + time * castrate * (battle_config.castrate_dex_scale - + dex) / (battle_config.castrate_dex_scale * + 100); + time = time * battle_config.cast_rate / 100; + } + + /* サフラギウム */ + if (sc_data && sc_data[SC_SUFFRAGIUM].timer != -1) + { + time = time * (100 - sc_data[SC_SUFFRAGIUM].val1 * 15) / 100; + skill_status_change_end (bl, SC_SUFFRAGIUM, -1); + } + /* ブラギの詩 */ + 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; } + /*========================================== * ディレイ計算 *------------------------------------------ */ -int skill_delayfix( struct block_list *bl, int time ) +int skill_delayfix (struct block_list *bl, int time) { - struct status_change *sc_data; + struct status_change *sc_data; - nullpo_retr(0, bl); + nullpo_retr (0, bl); - sc_data = battle_get_sc_data(bl); - if(time<=0) - return 0; - - if(bl->type == BL_PC) { - if( battle_config.delay_dependon_dex ) /* dexの影響を計算する */ - time=time*(battle_config.castrate_dex_scale - battle_get_dex(bl))/battle_config.castrate_dex_scale; - time=time*battle_config.delay_rate/100; - } - - /* ブラギの詩 */ - 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; + sc_data = battle_get_sc_data (bl); + if (time <= 0) + return 0; - return (time>0)?time:0; + if (bl->type == BL_PC) + { + if (battle_config.delay_dependon_dex) /* dexの影響を計算する */ + time = + time * (battle_config.castrate_dex_scale - + battle_get_dex (bl)) / + battle_config.castrate_dex_scale; + time = time * battle_config.delay_rate / 100; + } + + /* ブラギの詩 */ + 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; } /*========================================== * スキル使用(ID指定) *------------------------------------------ */ -int skill_use_id( struct map_session_data *sd, int target_id, - int skill_num, int skill_lv) +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 ){ + 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; - - if(sd->skillid==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(sd->sc_data){ - if(sc_data[SC_CHASEWALK].timer != -1) return 0; - if(sc_data[SC_VOLCANO].timer != -1){ - if(skill_num==WZ_ICEWALL) return 0; - } - if(sc_data[SC_ROKISWEIL].timer!=-1){ - if(skill_num==BD_ADAPTATION) return 0; - } - if( sd->sc_data[SC_DIVINA].timer!=-1 || - sd->sc_data[SC_ROKISWEIL].timer!=-1 || - (sd->sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) || - sd->sc_data[SC_STEELBODY].timer != -1 || - sd->sc_data[SC_BERSERK].timer != -1 ){ - return 0; /* 状態異常や沈黙など */ - } - - if(sc_data[SC_BLADESTOP].timer != -1){ - int lv = sc_data[SC_BLADESTOP].val1; - if(sc_data[SC_BLADESTOP].val2==1) return 0;//白羽された側なのでダメ - if(lv==1) return 0; - if(lv==2 && skill_num!=MO_FINGEROFFENSIVE) return 0; - if(lv==3 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE) return 0; - if(lv==4 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE && skill_num!=MO_CHAINCOMBO) return 0; - if(lv==5 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE && skill_num!=MO_CHAINCOMBO && skill_num!=MO_EXTREMITYFIST) return 0; - } - } - - if(sd->status.option&4 && skill_num==TF_HIDING) - return 0; - if(sd->status.option&2 && skill_num!=TF_HIDING && skill_num!=AS_GRIMTOOTH && skill_num!=RG_BACKSTAP && skill_num!=RG_RAID ) - return 0; - - if(map[sd->bl.m].flag.gvg){ //GvGで使用できないスキル - switch(skill_num){ - case SM_ENDURE: - case AL_TELEPORT: - case AL_WARP: - case WZ_ICEWALL: - case TF_BACKSLIDING: - case LK_BERSERK: - case HP_BASILICA: - case ST_CHASEWALK: - return 0; - } - } + return 0; + } + if (sd->bl.m != bl->m || pc_isdead (sd)) + return 0; - /* 演奏/ダンス中 */ - if( sc_data && sc_data[SC_DANCING].timer!=-1 ){ -// if(battle_config.pc_skill_log) -// printf("dancing! %d\n",skill_num); - if( sc_data[SC_DANCING].val4 && skill_num!=BD_ADAPTATION ) //合奏中はアドリブ以外不可 - return 0; - if(skill_num!=BD_ADAPTATION && skill_num!=BA_MUSICALSTRIKE && skill_num!=DC_THROWARROW){ - return 0; - } - } + if (skillnotok (skill_num, sd)) // [MouseJstr] + return 0; - if(skill_get_inf2(skill_num)&0x200 && sd->bl.id == target_id) - return 0; - //直前のスキルが何か覚える必要のあるスキル - switch(skill_num){ - case SA_CASTCANCEL: - if(sd->skillid != skill_num){ //キャストキャンセル自体は覚えない - sd->skillid_old = sd->skillid; - sd->skilllv_old = sd->skilllv; - break; - } - case BD_ENCORE: /* アンコール */ - if(!sd->skillid_dance){ //前回使用した踊りがないとだめ - clif_skill_fail(sd,skill_num,0,0); - return 0; - }else{ - sd->skillid_old = skill_num; - } - break; - } + if (sd->skillid == 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; - sd->skillid = skill_num; - sd->skilllv = skill_lv; - - switch(skill_num){ //事前にレベルが変わったりするスキル - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジークフリード */ - case BD_RAGNAROK: /* 神々の黄昏 */ - case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ - { - int range=1; - int c=0; - map_foreachinarea(skill_check_condition_char_sub,sd->bl.m, - sd->bl.x-range,sd->bl.y-range, - sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c); - if(c<1){ - clif_skill_fail(sd,skill_num,0,0); - return 0; - }else if(c==99){ //相方不要設定だった - ; - }else{ - sd->skilllv=(c + skill_lv)/2; - } - } - break; - } + /* 沈黙や異常(ただし、グリムなどの判定をする) */ + if (sd->opt1 > 0) + return 0; + if (sd->sc_data) + { + if (sc_data[SC_CHASEWALK].timer != -1) + return 0; + if (sc_data[SC_VOLCANO].timer != -1) + { + if (skill_num == WZ_ICEWALL) + return 0; + } + if (sc_data[SC_ROKISWEIL].timer != -1) + { + if (skill_num == BD_ADAPTATION) + return 0; + } + if (sd->sc_data[SC_DIVINA].timer != -1 || + sd->sc_data[SC_ROKISWEIL].timer != -1 || + (sd->sc_data[SC_AUTOCOUNTER].timer != -1 + && sd->skillid != KN_AUTOCOUNTER) + || sd->sc_data[SC_STEELBODY].timer != -1 + || sd->sc_data[SC_BERSERK].timer != -1) + { + return 0; /* 状態異常や沈黙など */ + } - if(!skill_check_condition(sd,0)) return 0; + if (sc_data[SC_BLADESTOP].timer != -1) + { + int lv = sc_data[SC_BLADESTOP].val1; + if (sc_data[SC_BLADESTOP].val2 == 1) + return 0; //白羽された側なのでダメ + 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; + } + } - /* 射程と障害物チェック */ - range = skill_get_range(skill_num,skill_lv); - if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); - if(!battle_check_range(&sd->bl,bl,range) ) - return 0; + if (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(bl->type==BL_PC) { - target_sd=(struct map_session_data*)bl; - if(target_sd && skill_num == ALL_RESURRECTION && !pc_isdead(target_sd)) - return 0; - } - if((skill_num != MO_CHAINCOMBO && - skill_num != MO_COMBOFINISH && - skill_num != MO_EXTREMITYFIST && - skill_num != CH_TIGERFIST && - skill_num != CH_CHAINCRUSH) || - (skill_num == MO_EXTREMITYFIST && sd->state.skill_flag) ) - pc_stopattack(sd); - - casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) ); - if(skill_num != SA_MAGICROD) - delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) ); - sd->state.skillcastcancel = skill_db[skill_num].castcancel; - - switch(skill_num){ /* 何か特殊な処理が必要 */ -// case AL_HEAL: /* ヒール */ -// if(battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) -// forcecast=1; /* ヒールアタックなら詠唱エフェクト有り */ -// break; - case ALL_RESURRECTION: /* リザレクション */ - if(bl->type != BL_PC && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))){ /* 敵がアンデッドなら */ - forcecast=1; /* ターンアンデットと同じ詠唱時間 */ - casttime=skill_castfix(&sd->bl, skill_get_cast(PR_TURNUNDEAD,skill_lv) ); - } - break; - case MO_FINGEROFFENSIVE: /* 指弾 */ - casttime += casttime * ((skill_lv > sd->spiritball)? sd->spiritball:skill_lv); - break; - case MO_CHAINCOMBO: /*連打掌*/ - 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) //ターゲットがいない? - return 0; - target_id = tbl->id; - } - break; - case MO_COMBOFINISH: /*猛龍拳*/ - case CH_TIGERFIST: /* 伏虎拳 */ - case CH_CHAINCRUSH: /* 連柱崩撃 */ - target_id = sd->attacktarget; - break; - -// -- moonsoul (altered to allow proper usage of extremity from new champion combos) -// - case MO_EXTREMITYFIST: /*阿修羅覇鳳拳*/ - if(sc_data && sc_data[SC_COMBO].timer != -1 && (sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) { - casttime = 0; - target_id = sd->attacktarget; - } - forcecast=1; - break; - case SA_MAGICROD: - case SA_SPELLBREAKER: - forcecast=1; - break; - case WE_MALE: - case WE_FEMALE: - { - struct map_session_data *p_sd = NULL; - if((p_sd = pc_get_partner(sd)) == NULL) - return 0; - target_id = p_sd->bl.id; - //rangeをもう1回検査 - range = skill_get_range(skill_num,skill_lv); - if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); - if(!battle_check_range(&sd->bl,&p_sd->bl,range) ){ - return 0; - } - } - break; - case AS_SPLASHER: /* ベナムスプラッシャー */ - { - struct status_change *t_sc_data = battle_get_sc_data(bl); - if(t_sc_data && t_sc_data[SC_POISON].timer==-1){ - clif_skill_fail(sd,skill_num,0,10); - return 0; - } - } - break; - case PF_MEMORIZE: /* メモライズ */ - casttime = 12000; - break; + if (map[sd->bl.m].flag.gvg) + { //GvGで使用できないスキル + switch (skill_num) + { + case SM_ENDURE: + case AL_TELEPORT: + case AL_WARP: + case WZ_ICEWALL: + case TF_BACKSLIDING: + case LK_BERSERK: + case HP_BASILICA: + case ST_CHASEWALK: + return 0; + } + } + + /* 演奏/ダンス中 */ + if (sc_data && sc_data[SC_DANCING].timer != -1) + { +// if(battle_config.pc_skill_log) +// printf("dancing! %d\n",skill_num); + if (sc_data[SC_DANCING].val4 && skill_num != BD_ADAPTATION) //合奏中はアドリブ以外不可 + return 0; + if (skill_num != BD_ADAPTATION && skill_num != BA_MUSICALSTRIKE + && skill_num != DC_THROWARROW) + { + return 0; + } + } - } + if (skill_get_inf2 (skill_num) & 0x200 && sd->bl.id == target_id) + return 0; + //直前のスキルが何か覚える必要のあるスキル + switch (skill_num) + { + case SA_CASTCANCEL: + if (sd->skillid != skill_num) + { //キャストキャンセル自体は覚えない + sd->skillid_old = sd->skillid; + sd->skilllv_old = sd->skilllv; + break; + } + case BD_ENCORE: /* アンコール */ + if (!sd->skillid_dance) + { //前回使用した踊りがないとだめ + clif_skill_fail (sd, skill_num, 0, 0); + return 0; + } + else + { + sd->skillid_old = skill_num; + } + break; + } + + sd->skillid = skill_num; + sd->skilllv = skill_lv; + + switch (skill_num) + { //事前にレベルが変わったりするスキル + case BD_LULLABY: /* 子守歌 */ + case BD_RICHMANKIM: /* ニヨルドの宴 */ + case BD_ETERNALCHAOS: /* 永遠の混沌 */ + case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ + case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ + case BD_ROKISWEIL: /* ロキの叫び */ + case BD_INTOABYSS: /* 深淵の中に */ + case BD_SIEGFRIED: /* 不死身のジークフリード */ + case BD_RAGNAROK: /* 神々の黄昏 */ + case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ + { + int range = 1; + int c = 0; + map_foreachinarea (skill_check_condition_char_sub, sd->bl.m, + sd->bl.x - range, sd->bl.y - range, + sd->bl.x + range, sd->bl.y + range, BL_PC, + &sd->bl, &c); + if (c < 1) + { + clif_skill_fail (sd, skill_num, 0, 0); + return 0; + } + else if (c == 99) + { //相方不要設定だった + ; + } + else + { + sd->skilllv = (c + skill_lv) / 2; + } + } + break; + } - //メモライズ状態ならキャストタイムが1/3 - if(sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){ - casttime = casttime/3; - if((--sc_data[SC_MEMORIZE].val2)<=0) - skill_status_change_end(&sd->bl, SC_MEMORIZE, -1); - } + if (!skill_check_condition (sd, 0)) + return 0; - 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); + /* 射程と障害物チェック */ + range = skill_get_range (skill_num, skill_lv); + if (range < 0) + range = battle_get_range (&sd->bl) - (range + 1); + if (!battle_check_range (&sd->bl, bl, range)) + return 0; -// if(sd->skillitem == skill_num) -// casttime = delay = 0; + if (bl->type == BL_PC) + { + target_sd = (struct map_session_data *) bl; + if (target_sd && skill_num == ALL_RESURRECTION + && !pc_isdead (target_sd)) + return 0; + } + if ((skill_num != MO_CHAINCOMBO && + skill_num != MO_COMBOFINISH && + skill_num != MO_EXTREMITYFIST && + skill_num != CH_TIGERFIST && + skill_num != CH_CHAINCRUSH) || + (skill_num == MO_EXTREMITYFIST && sd->state.skill_flag)) + pc_stopattack (sd); + + casttime = skill_castfix (&sd->bl, skill_get_cast (skill_num, skill_lv)); + if (skill_num != SA_MAGICROD) + delay = + skill_delayfix (&sd->bl, skill_get_delay (skill_num, skill_lv)); + sd->state.skillcastcancel = skill_db[skill_num].castcancel; + + switch (skill_num) + { /* 何か特殊な処理が必要 */ +// case AL_HEAL: /* ヒール */ +// if(battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) +// forcecast=1; /* ヒールアタックなら詠唱エフェクト有り */ +// break; + case ALL_RESURRECTION: /* リザレクション */ + if (bl->type != BL_PC + && battle_check_undead (battle_get_race (bl), + battle_get_elem_type (bl))) + { /* 敵がアンデッドなら */ + forcecast = 1; /* ターンアンデットと同じ詠唱時間 */ + casttime = + skill_castfix (&sd->bl, + skill_get_cast (PR_TURNUNDEAD, skill_lv)); + } + break; + case MO_FINGEROFFENSIVE: /* 指弾 */ + casttime += + casttime * + ((skill_lv > sd->spiritball) ? sd->spiritball : skill_lv); + break; + case MO_CHAINCOMBO: /*連打掌 */ + 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) //ターゲットがいない? + return 0; + target_id = tbl->id; + } + break; + case MO_COMBOFINISH: /*猛龍拳 */ + case CH_TIGERFIST: /* 伏虎拳 */ + case CH_CHAINCRUSH: /* 連柱崩撃 */ + target_id = sd->attacktarget; + break; - if( casttime>0 || forcecast ){ /* 詠唱が必要 */ - struct mob_data *md; - clif_skillcasting( &sd->bl, - sd->bl.id, target_id, 0,0, skill_num,casttime); +// -- moonsoul (altered to allow proper usage of extremity from new champion combos) +// + case MO_EXTREMITYFIST: /*阿修羅覇鳳拳 */ + if (sc_data && sc_data[SC_COMBO].timer != -1 + && (sc_data[SC_COMBO].val1 == MO_COMBOFINISH + || sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) + { + casttime = 0; + target_id = sd->attacktarget; + } + forcecast = 1; + break; + case SA_MAGICROD: + case SA_SPELLBREAKER: + forcecast = 1; + break; + case WE_MALE: + case WE_FEMALE: + { + struct map_session_data *p_sd = NULL; + if ((p_sd = pc_get_partner (sd)) == NULL) + return 0; + target_id = p_sd->bl.id; + //rangeをもう1回検査 + range = skill_get_range (skill_num, skill_lv); + if (range < 0) + range = battle_get_range (&sd->bl) - (range + 1); + if (!battle_check_range (&sd->bl, &p_sd->bl, range)) + { + return 0; + } + } + break; + case AS_SPLASHER: /* ベナムスプラッシャー */ + { + struct status_change *t_sc_data = battle_get_sc_data (bl); + if (t_sc_data && t_sc_data[SC_POISON].timer == -1) + { + clif_skill_fail (sd, skill_num, 0, 10); + return 0; + } + } + break; + case PF_MEMORIZE: /* メモライズ */ + casttime = 12000; + break; - /* 詠唱反応モンスター */ - 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; - } - } + } + + //メモライズ状態ならキャストタイムが1/3 + if (sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0) + { + casttime = casttime / 3; + if ((--sc_data[SC_MEMORIZE].val2) <= 0) + skill_status_change_end (&sd->bl, SC_MEMORIZE, -1); + } + + if (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) + { /* 詠唱が必要 */ + struct mob_data *md; + clif_skillcasting (&sd->bl, + sd->bl.id, target_id, 0, 0, skill_num, casttime); + + /* 詠唱反応モンスター */ + 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 ) /* 詠唱の無いものはキャンセルされない */ - sd->state.skillcastcancel=0; + if (casttime <= 0) /* 詠唱の無いものはキャンセルされない */ + sd->state.skillcastcancel = 0; - sd->skilltarget = target_id; + sd->skilltarget = target_id; /* sd->cast_target_bl = bl; */ - sd->skillx = 0; - sd->skilly = 0; - sd->canact_tick = tick + casttime + delay; - sd->canmove_tick = tick; - if(!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1 && sd->skillid != AS_CLOAKING) - skill_status_change_end(&sd->bl,SC_CLOAKING,-1); - if(casttime > 0) { - sd->skilltimer = add_timer( tick+casttime, skill_castend_id, sd->bl.id, 0 ); - if((skill = pc_checkskill(sd,SA_FREECAST)) > 0) { - sd->prev_speed = sd->speed; - sd->speed = sd->speed*(175 - skill*5)/100; - clif_updatestatus(sd,SP_SPEED); - } - else - pc_stop_walking(sd,0); - } - else { - if(skill_num != SA_CASTCANCEL) - sd->skilltimer = -1; - skill_castend_id(sd->skilltimer,tick,sd->bl.id,0); - } - - //マジックパワーの効果終了 - if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER) - skill_status_change_end(&sd->bl,SC_MAGICPOWER,-1); - - return 0; + sd->skillx = 0; + sd->skilly = 0; + sd->canact_tick = tick + casttime + delay; + sd->canmove_tick = tick; + if (!(battle_config.pc_cloak_check_type & 2) && sc_data + && sc_data[SC_CLOAKING].timer != -1 && sd->skillid != AS_CLOAKING) + skill_status_change_end (&sd->bl, SC_CLOAKING, -1); + if (casttime > 0) + { + sd->skilltimer = + add_timer (tick + casttime, skill_castend_id, sd->bl.id, 0); + if ((skill = pc_checkskill (sd, SA_FREECAST)) > 0) + { + sd->prev_speed = sd->speed; + sd->speed = sd->speed * (175 - skill * 5) / 100; + clif_updatestatus (sd, SP_SPEED); + } + else + pc_stop_walking (sd, 0); + } + else + { + if (skill_num != SA_CASTCANCEL) + sd->skilltimer = -1; + skill_castend_id (sd->skilltimer, tick, sd->bl.id, 0); + } + + //マジックパワーの効果終了 + if (sc_data && sc_data[SC_MAGICPOWER].timer != -1 + && skill_num != HW_MAGICPOWER) + skill_status_change_end (&sd->bl, SC_MAGICPOWER, -1); + + return 0; } /*========================================== * スキル使用(場所指定) *------------------------------------------ */ -int skill_use_pos( struct map_session_data *sd, - int skill_x, int skill_y, int skill_num, int skill_lv) +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; + struct block_list bl; + struct status_change *sc_data; + unsigned int tick; + int casttime = 0, delay = 0, skill, range; - nullpo_retr(0, sd); + nullpo_retr (0, sd); - if(pc_isdead(sd)) - return 0; + if (pc_isdead (sd)) + return 0; - if (skillnotok(skill_num, sd)) // [MoueJstr] - return 0; + if (skillnotok (skill_num, sd)) // [MoueJstr] + 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 ) - return 0; /* 状態異常や沈黙など */ - } + sc_data = sd->sc_data; - if(sd->status.option&2) - return 0; - - if(map[sd->bl.m].flag.gvg && (skill_num == SM_ENDURE || skill_num == AL_TELEPORT || skill_num == AL_WARP || - skill_num == WZ_ICEWALL || skill_num == TF_BACKSLIDING)) - return 0; - - sd->skillid = skill_num; - sd->skilllv = skill_lv; - sd->skillx = skill_x; - sd->skilly = skill_y; - if(!skill_check_condition(sd,0)) return 0; - - /* 射程と障害物チェック */ - bl.type = BL_NUL; - bl.m = sd->bl.m; - bl.x = skill_x; - bl.y = skill_y; - range = skill_get_range(skill_num,skill_lv); - if(range < 0) - range = battle_get_range(&sd->bl) - (range + 1); - if(!battle_check_range(&sd->bl,&bl,range) ) - return 0; - - pc_stopattack(sd); - - casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) ); - delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) ); - sd->state.skillcastcancel = skill_db[skill_num].castcancel; - - if(battle_config.pc_skill_log) - printf("PC %d skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d\n",sd->bl.id,skill_x,skill_y,skill_num,skill_lv,casttime); - -// if(sd->skillitem == skill_num) -// casttime = delay = 0; - //メモライズ状態ならキャストタイムが1/3 - if(sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){ - casttime = casttime/3; - if((--sc_data[SC_MEMORIZE].val2)<=0) - skill_status_change_end(&sd->bl, SC_MEMORIZE, -1); - } + if (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) + return 0; /* 状態異常や沈黙など */ + } + + if (sd->status.option & 2) + return 0; - if( casttime>0 ) /* 詠唱が必要 */ - clif_skillcasting( &sd->bl, - sd->bl.id, 0, skill_x,skill_y, skill_num,casttime); + if (map[sd->bl.m].flag.gvg + && (skill_num == SM_ENDURE || skill_num == AL_TELEPORT + || skill_num == AL_WARP || skill_num == WZ_ICEWALL + || skill_num == TF_BACKSLIDING)) + return 0; - if( casttime<=0 ) /* 詠唱の無いものはキャンセルされない */ - sd->state.skillcastcancel=0; + sd->skillid = skill_num; + sd->skilllv = skill_lv; + sd->skillx = skill_x; + sd->skilly = skill_y; + if (!skill_check_condition (sd, 0)) + return 0; - sd->skilltarget = 0; -/* sd->cast_target_bl = NULL; */ - tick=gettick(); - sd->canact_tick = tick + casttime + delay; - sd->canmove_tick = tick; - if(!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1) - skill_status_change_end(&sd->bl,SC_CLOAKING,-1); - if(casttime > 0) { - sd->skilltimer = add_timer( tick+casttime, skill_castend_pos, sd->bl.id, 0 ); - if((skill = pc_checkskill(sd,SA_FREECAST)) > 0) { - sd->prev_speed = sd->speed; - sd->speed = sd->speed*(175 - skill*5)/100; - clif_updatestatus(sd,SP_SPEED); - } - else - pc_stop_walking(sd,0); - } - else { - sd->skilltimer = -1; - skill_castend_pos(sd->skilltimer,tick,sd->bl.id,0); - } - //マジックパワーの効果終了 - if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER) - skill_status_change_end(&sd->bl,SC_MAGICPOWER,-1); + /* 射程と障害物チェック */ + bl.type = BL_NUL; + bl.m = sd->bl.m; + bl.x = skill_x; + bl.y = skill_y; + range = skill_get_range (skill_num, skill_lv); + if (range < 0) + range = battle_get_range (&sd->bl) - (range + 1); + if (!battle_check_range (&sd->bl, &bl, range)) + return 0; - 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; + //メモライズ状態ならキャストタイムが1/3 + if (sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0) + { + casttime = casttime / 3; + if ((--sc_data[SC_MEMORIZE].val2) <= 0) + skill_status_change_end (&sd->bl, SC_MEMORIZE, -1); + } + + if (casttime > 0) /* 詠唱が必要 */ + clif_skillcasting (&sd->bl, + sd->bl.id, 0, skill_x, skill_y, skill_num, + casttime); + + if (casttime <= 0) /* 詠唱の無いものはキャンセルされない */ + sd->state.skillcastcancel = 0; + + sd->skilltarget = 0; +/* sd->cast_target_bl = NULL; */ + tick = gettick (); + sd->canact_tick = tick + casttime + delay; + sd->canmove_tick = tick; + if (!(battle_config.pc_cloak_check_type & 2) && sc_data + && sc_data[SC_CLOAKING].timer != -1) + skill_status_change_end (&sd->bl, SC_CLOAKING, -1); + if (casttime > 0) + { + sd->skilltimer = + add_timer (tick + casttime, skill_castend_pos, sd->bl.id, 0); + if ((skill = pc_checkskill (sd, SA_FREECAST)) > 0) + { + sd->prev_speed = sd->speed; + sd->speed = sd->speed * (175 - skill * 5) / 100; + clif_updatestatus (sd, SP_SPEED); + } + else + pc_stop_walking (sd, 0); + } + else + { + sd->skilltimer = -1; + skill_castend_pos (sd->skilltimer, tick, sd->bl.id, 0); + } + //マジックパワーの効果終了 + if (sc_data && sc_data[SC_MAGICPOWER].timer != -1 + && skill_num != HW_MAGICPOWER) + skill_status_change_end (&sd->bl, SC_MAGICPOWER, -1); + + return 0; } /*========================================== * スキル詠唱キャンセル *------------------------------------------ */ -int skill_castcancel(struct block_list *bl,int type) +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); - } + int inf; + int ret = 0; - 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; + 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; } + /*========================================= * ブランディッシュスピア 初期範囲決定 *---------------------------------------- */ -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; - } +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; + } } @@ -7036,139 +8590,189 @@ void skill_brandishspear_first(struct square *tc,int dir,int x,int y){ * ブランディッシュスピア 方向判定 範囲拡張 *----------------------------------------- */ -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; - } - } +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; + } + } } /*========================================== * ディボーション 有効確認 *------------------------------------------ */ -void skill_devotion(struct map_session_data *md,int target) +void skill_devotion (struct map_session_data *md, int target) { - // 総確認 - 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]); - // 相手が見つからない // 相手をディボしてるのが自分じゃない // 距離が離れてる - 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); - } - } - } + // 総確認 + 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]); + // 相手が見つからない // 相手をディボしてるのが自分じゃない // 距離が離れてる + 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) + +void skill_devotion2 (struct block_list *bl, int crusader) { - // 被ディボーションが歩いた時の距離チェック - struct map_session_data *sd = map_id2sd(crusader); + // 被ディボーションが歩いた時の距離チェック + struct map_session_data *sd = map_id2sd (crusader); - nullpo_retv(bl); + nullpo_retv (bl); - if(sd) skill_devotion3(&sd->bl,bl->id); + if (sd) + skill_devotion3 (&sd->bl, bl->id); } -int skill_devotion3(struct block_list *bl,int target) + +int skill_devotion3 (struct block_list *bl, int target) { - // クルセが歩いた時の距離チェック - struct map_session_data *md; - struct map_session_data *sd; - int n,r=0; - - nullpo_retr(1, bl); - - if( (md = (struct map_session_data *)bl) == NULL || (sd = map_id2sd(target)) == NULL ) - return 1; - else - r = distance(bl->x,bl->y,sd->bl.x,sd->bl.y); - - if(pc_checkskill(sd,CR_DEVOTION)+6 < r){ // 許容範囲を超えてた - for(n=0;n<5;n++) - if(md->dev.val1[n]==target) - md->dev.val2[n]=0; // 離れた時は、糸を切るだけ - clif_devotion(md,sd->bl.id); - return 1; - } - return 0; + // クルセが歩いた時の距離チェック + struct map_session_data *md; + struct map_session_data *sd; + int n, r = 0; + + nullpo_retr (1, bl); + + if ((md = (struct map_session_data *) bl) == NULL + || (sd = map_id2sd (target)) == NULL) + return 1; + else + r = distance (bl->x, bl->y, sd->bl.x, sd->bl.y); + + if (pc_checkskill (sd, CR_DEVOTION) + 6 < r) + { // 許容範囲を超えてた + for (n = 0; n < 5; n++) + if (md->dev.val1[n] == target) + md->dev.val2[n] = 0; // 離れた時は、糸を切るだけ + 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) +void skill_devotion_end (struct map_session_data *md, + struct map_session_data *sd, int target) { - // クルセと被ディボキャラのリセット - nullpo_retv(md); - nullpo_retv(sd); - - md->dev.val1[target]=md->dev.val2[target]=0; - if(sd && sd->sc_data){ - // skill_status_change_end(sd->bl,SC_DEVOTION,-1); - sd->sc_data[SC_DEVOTION].val1=0; - sd->sc_data[SC_DEVOTION].val2=0; - clif_status_change(&sd->bl,SC_DEVOTION,0); - clif_devotion(md,sd->bl.id); - } + // クルセと被ディボキャラのリセット + nullpo_retv (md); + nullpo_retv (sd); + + md->dev.val1[target] = md->dev.val2[target] = 0; + if (sd && sd->sc_data) + { + // skill_status_change_end(sd->bl,SC_DEVOTION,-1); + sd->sc_data[SC_DEVOTION].val1 = 0; + sd->sc_data[SC_DEVOTION].val2 = 0; + clif_status_change (&sd->bl, SC_DEVOTION, 0); + clif_devotion (md, sd->bl.id); + } } + /*========================================== * オートスペル *------------------------------------------ */ -int skill_autospell(struct map_session_data *sd,int skillid) +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(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; + int skilllv; + int maxlv = 1, lv; + + nullpo_retr (0, sd); + + skilllv = pc_checkskill (sd, SA_AUTOSPELL); + + 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; + if (maxlv > (lv = pc_checkskill (sd, skillid))) + maxlv = lv; - skill_status_change_start(&sd->bl,SC_AUTOSPELL,skilllv,skillid,maxlv,0, // val1:スキルID val2:使用最大Lv - skill_get_time(SA_AUTOSPELL,skilllv),0);// にしてみたけどbscriptが書き易い・・・? - return 0; + skill_status_change_start (&sd->bl, SC_AUTOSPELL, skilllv, skillid, maxlv, 0, // val1:スキルID val2:使用最大Lv + skill_get_time (SA_AUTOSPELL, skilllv), 0); // にしてみたけどbscriptが書き易い・・・? + return 0; } /*========================================== @@ -7176,291 +8780,322 @@ int skill_autospell(struct map_session_data *sd,int skillid) *------------------------------------------ */ -static int skill_gangster_count(struct block_list *bl,va_list ap) +static int skill_gangster_count (struct block_list *bl, va_list ap) { - int *c; - struct map_session_data *sd; + int *c; + struct map_session_data *sd; - nullpo_retr(0, bl); - nullpo_retr(0, ap); + nullpo_retr (0, bl); + nullpo_retr (0, ap); - sd=(struct map_session_data*)bl; - c=va_arg(ap,int *); + 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; + 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) +static int skill_gangster_in (struct block_list *bl, va_list ap) { - struct map_session_data *sd; + struct map_session_data *sd; - nullpo_retr(0, bl); - nullpo_retr(0, ap); + 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; + 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) +static int skill_gangster_out (struct block_list *bl, va_list ap) { - struct map_session_data *sd; + struct map_session_data *sd; - nullpo_retr(0, bl); - nullpo_retr(0, ap); + 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; + 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 skill_gangsterparadise (struct map_session_data *sd, int type) { - int range=1; - int c=0; - - nullpo_retr(0, sd); - - if(pc_checkskill(sd,RG_GANGSTER) <= 0) - return 0; - - if(type==1) {/* 座った時の処理 */ - map_foreachinarea(skill_gangster_count,sd->bl.m, - sd->bl.x-range,sd->bl.y-range, - sd->bl.x+range,sd->bl.y+range,BL_PC,&c); - if(c > 0) {/*ギャングスター成功したら自分にもギャングスター属性付与*/ - map_foreachinarea(skill_gangster_in,sd->bl.m, - sd->bl.x-range,sd->bl.y-range, - sd->bl.x+range,sd->bl.y+range,BL_PC); - sd->state.gangsterparadise = 1; - } - return 0; - } - else if(type==0) {/* 立ち上がったときの処理 */ - map_foreachinarea(skill_gangster_count,sd->bl.m, - sd->bl.x-range,sd->bl.y-range, - sd->bl.x+range,sd->bl.y+range,BL_PC,&c); - if(c < 1) - 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; + int range = 1; + int c = 0; + + nullpo_retr (0, sd); + + if (pc_checkskill (sd, RG_GANGSTER) <= 0) + return 0; + + if (type == 1) + { /* 座った時の処理 */ + map_foreachinarea (skill_gangster_count, sd->bl.m, + sd->bl.x - range, sd->bl.y - range, + sd->bl.x + range, sd->bl.y + range, BL_PC, &c); + if (c > 0) + { /*ギャングスター成功したら自分にもギャングスター属性付与 */ + map_foreachinarea (skill_gangster_in, sd->bl.m, + sd->bl.x - range, sd->bl.y - range, + sd->bl.x + range, sd->bl.y + range, BL_PC); + sd->state.gangsterparadise = 1; + } + return 0; + } + else if (type == 0) + { /* 立ち上がったときの処理 */ + map_foreachinarea (skill_gangster_count, sd->bl.m, + sd->bl.x - range, sd->bl.y - range, + sd->bl.x + range, sd->bl.y + range, BL_PC, &c); + if (c < 1) + 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; } + /*========================================== * 寒いジョーク・スクリーム判定処理(foreachinarea) *------------------------------------------ */ -int skill_frostjoke_scream(struct block_list *bl,va_list ap) +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); - 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(MRAND(100) < 10)//PTメンバにも低確率でかかる(とりあえず10%) - skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick); - } + 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); + tick = va_arg (ap, unsigned int); + + if (src == bl) //自分には効かない + return 0; - 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 (MRAND (100) < 10) //PTメンバにも低確率でかかる(とりあえず10%) + skill_additional_effect (src, bl, skillnum, skilllv, BF_MISC, + tick); + } + + return 0; } /*========================================== * *------------------------------------------ */ -int skill_attack_area(struct block_list *bl,va_list ap) +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); - 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; + 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); + 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) +int skill_clear_element_field (struct block_list *bl) { - struct mob_data *md=NULL; - struct map_session_data *sd=NULL; - int i,skillid; - - nullpo_retr(0, bl); - - if(bl->type==BL_MOB) - md=(struct mob_data *)bl; - if(bl->type==BL_PC) - sd=(struct map_session_data *)bl; - - for(i=0;i<MAX_MOBSKILLUNITGROUP;i++){ - if(sd){ - skillid=sd->skillunit[i].skill_id; - if(skillid==SA_DELUGE||skillid==SA_VOLCANO||skillid==SA_VIOLENTGALE||skillid==SA_LANDPROTECTOR) - skill_delunitgroup(&sd->skillunit[i]); - }else if(md){ - skillid=md->skillunit[i].skill_id; - if(skillid==SA_DELUGE||skillid==SA_VOLCANO||skillid==SA_VIOLENTGALE||skillid==SA_LANDPROTECTOR) - skill_delunitgroup(&md->skillunit[i]); - } - } - return 0; + struct mob_data *md = NULL; + struct map_session_data *sd = NULL; + int i, skillid; + + nullpo_retr (0, bl); + + if (bl->type == BL_MOB) + md = (struct mob_data *) bl; + if (bl->type == BL_PC) + sd = (struct map_session_data *) bl; + + for (i = 0; i < MAX_MOBSKILLUNITGROUP; i++) + { + if (sd) + { + skillid = sd->skillunit[i].skill_id; + if (skillid == SA_DELUGE || skillid == SA_VOLCANO + || skillid == SA_VIOLENTGALE || skillid == SA_LANDPROTECTOR) + skill_delunitgroup (&sd->skillunit[i]); + } + else if (md) + { + skillid = md->skillunit[i].skill_id; + if (skillid == SA_DELUGE || skillid == SA_VOLCANO + || skillid == SA_VIOLENTGALE || skillid == SA_LANDPROTECTOR) + skill_delunitgroup (&md->skillunit[i]); + } + } + return 0; } + /*========================================== * ランドプロテクターチェック(foreachinarea) *------------------------------------------ */ -int skill_landprotector(struct block_list *bl, va_list ap ) +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; + 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; } + /*========================================== * イドゥンの林檎の回復処理(foreachinarea) *------------------------------------------ */ -int skill_idun_heal(struct block_list *bl, va_list ap ) +int skill_idun_heal (struct block_list *bl, va_list ap) { - struct skill_unit *unit; - struct skill_unit_group *sg; - int heal; + 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); + 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; + 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_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; + 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; } /*========================================== * 指定範囲内でsrcに対して有効なターゲットの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; +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; } + /*========================================== * トラップ範囲処理(foreachinarea) *------------------------------------------ */ -int skill_trap_splash(struct block_list *bl, va_list ap ) +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: /* サンドマン */ - case 0x96: /* フラッシャー */ - case 0x94: /* ショックウェーブトラップ */ - skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick); - break; - case 0x8f: /* ブラストマイン */ - case 0x98: /* クレイモアートラップ */ - 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: /* フリージングトラップ */ - skill_attack(BF_WEAPON, ss,src,bl,sg->skill_id,sg->skill_lv,tick,(sg->val2)?0x0500:0); - break; - default: - break; - } - } + 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: /* サンドマン */ + case 0x96: /* フラッシャー */ + case 0x94: /* ショックウェーブトラップ */ + skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv, + BF_MISC, tick); + break; + case 0x8f: /* ブラストマイン */ + case 0x98: /* クレイモアートラップ */ + 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: /* フリージングトラップ */ + skill_attack (BF_WEAPON, ss, src, bl, sg->skill_id, + sg->skill_lv, tick, (sg->val2) ? 0x0500 : 0); + break; + default: + break; + } + } - return 0; + return 0; } + /*---------------------------------------------------------------------------- * ステータス異常 *---------------------------------------------------------------------------- @@ -7470,1361 +9105,1544 @@ int skill_trap_splash(struct block_list *bl, va_list ap ) * ステータス異常タイマー範囲処理 *------------------------------------------ */ -int skill_status_change_timer_sub(struct block_list *bl, va_list ap ) +int skill_status_change_timer_sub (struct block_list *bl, va_list ap) { - struct block_list *src; - int type; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - type=va_arg(ap,int); - tick=va_arg(ap,unsigned int); - - if(bl->type!=BL_PC && bl->type!=BL_MOB) - return 0; - - switch( type ){ - case SC_SIGHT: /* サイト */ - case SC_CONCENTRATE: - if( (*battle_get_option(bl))&6 ){ - skill_status_change_end( bl, SC_HIDING, -1); - skill_status_change_end( bl, SC_CLOAKING, -1); - } - break; - case SC_RUWACH: /* ルアフ */ - if( (*battle_get_option(bl))&6 ){ - skill_status_change_end( bl, SC_HIDING, -1); - skill_status_change_end( bl, SC_CLOAKING, -1); - if(battle_check_target( src,bl, BCT_ENEMY ) > 0) { - struct status_change *sc_data = battle_get_sc_data(bl); - skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,sc_data[type].val1,tick,0); - } - } - break; - } - return 0; + struct block_list *src; + int type; + unsigned int tick; + + nullpo_retr (0, bl); + nullpo_retr (0, ap); + nullpo_retr (0, src = va_arg (ap, struct block_list *)); + type = va_arg (ap, int); + tick = va_arg (ap, unsigned int); + + if (bl->type != BL_PC && bl->type != BL_MOB) + return 0; + + switch (type) + { + case SC_SIGHT: /* サイト */ + case SC_CONCENTRATE: + if ((*battle_get_option (bl)) & 6) + { + skill_status_change_end (bl, SC_HIDING, -1); + skill_status_change_end (bl, SC_CLOAKING, -1); + } + break; + case SC_RUWACH: /* ルアフ */ + if ((*battle_get_option (bl)) & 6) + { + skill_status_change_end (bl, SC_HIDING, -1); + skill_status_change_end (bl, SC_CLOAKING, -1); + if (battle_check_target (src, bl, BCT_ENEMY) > 0) + { + struct status_change *sc_data = battle_get_sc_data (bl); + skill_attack (BF_MAGIC, src, src, bl, AL_RUWACH, + sc_data[type].val1, tick, 0); + } + } + break; + } + return 0; } /*========================================== * ステータス異常終了 *------------------------------------------ */ -int skill_status_change_active(struct block_list* bl, int type) +int skill_status_change_active (struct block_list *bl, int type) { - struct status_change* sc_data; + struct status_change *sc_data; - nullpo_retr(0, bl); - if(bl->type!=BL_PC && bl->type!=BL_MOB) { - if(battle_config.error_log) - printf("skill_status_change_active: neither MOB nor PC !\n"); - return 0; - } + nullpo_retr (0, bl); + if (bl->type != BL_PC && bl->type != BL_MOB) + { + if (battle_config.error_log) + printf ("skill_status_change_active: neither MOB nor PC !\n"); + return 0; + } - nullpo_retr(0, sc_data = battle_get_sc_data(bl)); + nullpo_retr (0, sc_data = battle_get_sc_data (bl)); - return sc_data[type].timer != -1; + return sc_data[type].timer != -1; } -int skill_status_change_end(struct block_list* bl, int type, int tid) +int skill_status_change_end (struct block_list *bl, int type, int tid) { - struct status_change* sc_data; - int opt_flag=0, calc_flag = 0; - short *sc_count, *option, *opt1, *opt2, *opt3; - - nullpo_retr(0, bl); - if(bl->type!=BL_PC && bl->type!=BL_MOB) { - if(battle_config.error_log) - printf("skill_status_change_end: neither MOB nor PC !\n"); - return 0; - } - nullpo_retr(0, sc_data = battle_get_sc_data(bl)); - nullpo_retr(0, sc_count = battle_get_sc_count(bl)); - nullpo_retr(0, option = battle_get_option(bl)); - nullpo_retr(0, opt1 = battle_get_opt1(bl)); - nullpo_retr(0, opt2 = battle_get_opt2(bl)); - nullpo_retr(0, opt3 = battle_get_opt3(bl)); - - if ((*sc_count) > 0 && sc_data[type].timer != -1 && (sc_data[type].timer == tid || tid == -1)) { - - if (tid == -1) // タイマから呼ばれていないならタイマ削除をする - delete_timer(sc_data[type].timer,skill_status_change_timer); - - /* 該当の異常を正常に戻す */ - sc_data[type].timer=-1; - (*sc_count)--; - - switch(type){ /* 異常の種類ごとの処理 */ - case SC_PROVOKE: /* プロボック */ - case SC_CONCENTRATE: /* 集中力向上 */ - case SC_BLESSING: /* ブレッシング */ - case SC_ANGELUS: /* アンゼルス */ - case SC_INCREASEAGI: /* 速度上昇 */ - case SC_DECREASEAGI: /* 速度減少 */ - case SC_SIGNUMCRUCIS: /* シグナムクルシス */ - case SC_HIDING: - case SC_TWOHANDQUICKEN: /* 2HQ */ - case SC_ADRENALINE: /* アドレナリンラッシュ */ - case SC_ENCPOISON: /* エンチャントポイズン */ - case SC_IMPOSITIO: /* インポシティオマヌス */ - case SC_GLORIA: /* グロリア */ - case SC_LOUD: /* ラウドボイス */ - case SC_QUAGMIRE: /* クァグマイア */ - case SC_PROVIDENCE: /* プロヴィデンス */ - case SC_SPEARSQUICKEN: /* スピアクイッケン */ - case SC_VOLCANO: - case SC_DELUGE: - case SC_VIOLENTGALE: - case SC_ETERNALCHAOS: /* エターナルカオス */ - case SC_DRUMBATTLE: /* 戦太鼓の響き */ - case SC_NIBELUNGEN: /* ニーベルングの指輪 */ - case SC_SIEGFRIED: /* 不死身のジークフリード */ - case SC_WHISTLE: /* 口笛 */ - case SC_ASSNCROS: /* 夕陽のアサシンクロス */ - case SC_HUMMING: /* ハミング */ - case SC_DONTFORGETME: /* 私を忘れないで */ - case SC_FORTUNE: /* 幸運のキス */ - case SC_SERVICE4U: /* サービスフォーユー */ - case SC_EXPLOSIONSPIRITS: // 爆裂波動 - case SC_STEELBODY: // 金剛 - case SC_DEFENDER: - case SC_SPEEDPOTION0: /* 増速ポーション */ - case SC_SPEEDPOTION1: - case SC_SPEEDPOTION2: - case SC_APPLEIDUN: /* イドゥンの林檎 */ - case SC_RIDING: - case SC_BLADESTOP_WAIT: - case SC_AURABLADE: /* オーラブレード */ - case SC_PARRYING: /* パリイング */ - case SC_CONCENTRATION: /* コンセントレーション */ - case SC_TENSIONRELAX: /* テンションリラックス */ - case SC_ASSUMPTIO: /* アシャンプティオ */ - case SC_WINDWALK: /* ウインドウォーク */ - case SC_TRUESIGHT: /* トゥルーサイト */ - case SC_SPIDERWEB: /* スパイダーウェッブ */ - case SC_MAGICPOWER: /* 魔法力増幅 */ - case SC_CHASEWALK: - case SC_ATKPOT: /* attack potion [Valaris] */ - case SC_MATKPOT: /* magic attack potion [Valaris] */ - case SC_WEDDING: //結婚用(結婚衣裳になって歩くのが遅いとか) - case SC_MELTDOWN: /* メルトダウン */ - case SC_PHYS_SHIELD: - case SC_HASTE: - calc_flag = 1; - break; - case SC_BERSERK: /* バーサーク */ - calc_flag = 1; - clif_status_change(bl,SC_INCREASEAGI,0); /* アイコン消去 */ - break; - case SC_DEVOTION: /* ディボーション */ - { - struct map_session_data *md = map_id2sd(sc_data[type].val1); - sc_data[type].val1=sc_data[type].val2=0; - skill_devotion(md,bl->id); - calc_flag = 1; - } - break; - case SC_BLADESTOP: - { - struct status_change *t_sc_data = battle_get_sc_data((struct block_list *)sc_data[type].val4); - //片方が切れたので相手の白刃状態が切れてないのなら解除 - if(t_sc_data && t_sc_data[SC_BLADESTOP].timer!=-1) - skill_status_change_end((struct block_list *)sc_data[type].val4,SC_BLADESTOP,-1); - - if(sc_data[type].val2==2) - clif_bladestop((struct block_list *)sc_data[type].val3,(struct block_list *)sc_data[type].val4,0); - } - break; - case SC_DANCING: - { - struct map_session_data *dsd; - struct status_change *d_sc_data; - if(sc_data[type].val4 && (dsd=map_id2sd(sc_data[type].val4))){ - d_sc_data = dsd->sc_data; - //合奏で相手がいる場合相手のval4を0にする - if(d_sc_data && d_sc_data[type].timer!=-1) - d_sc_data[type].val4=0; - } - } - calc_flag = 1; - break; - case SC_GRAFFITI: - { - struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[type].val4; //val4がグラフィティのgroup_id - if(sg) - skill_delunitgroup(sg); - } - break; - case SC_NOCHAT: //チャット禁止状態 - { - struct map_session_data *sd=NULL; - if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){ - sd->status.manner = 0; - clif_updatestatus(sd,SP_MANNER); - } - } - break; - case SC_SPLASHER: /* ベナムスプラッシャー */ - { - struct block_list *src=map_id2bl(sc_data[type].val3); - if(src && tid!=-1){ - //自分にダメージ&周囲3*3にダメージ - skill_castend_damage_id(src, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 ); - } - } - break; - case SC_SELFDESTRUCTION: /* 自爆 */ - { - //自分のダメージは0にして - struct mob_data *md=NULL; - if(bl->type == BL_MOB && (md=(struct mob_data*)bl)) - skill_castend_damage_id(bl, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 ); - } - break; - /* option1 */ - case SC_FREEZE: - sc_data[type].val3 = 0; - break; - - /* option2 */ - case SC_POISON: /* 毒 */ - case SC_BLIND: /* 暗黒 */ - case SC_CURSE: - calc_flag = 1; - break; - } - - if(bl->type==BL_PC && type<SC_SENDMAX) - clif_status_change(bl,type,0); /* アイコン消去 */ - - switch(type){ /* 正常に戻るときなにか処理が必要 */ - case SC_STONE: - case SC_FREEZE: - case SC_STAN: - case SC_SLEEP: - *opt1 = 0; - opt_flag = 1; - break; - - case SC_POISON: - case SC_CURSE: - case SC_SILENCE: - case SC_BLIND: - *opt2 &= ~(1<<(type-SC_POISON)); - opt_flag = 1; - break; - - case SC_SLOWPOISON: - if (sc_data[SC_POISON].timer != -1) - *opt2 |= 0x1; - *opt2 &= ~0x200; - opt_flag = 1; - break; - - case SC_SIGNUMCRUCIS: - *opt2 &= ~0x40; - opt_flag = 1; - break; - - case SC_SPEEDPOTION0: - *opt2 &= ~0x20; - opt_flag = 1; - break; - - case SC_ATKPOT: - *opt2 &= ~0x80; - opt_flag = 1; - break; - - case SC_HIDING: - case SC_CLOAKING: - *option &= ~((type == SC_HIDING) ? 2 : 4); - opt_flag = 1 ; - break; - - case SC_CHASEWALK: - *option &= ~16388; - opt_flag = 1 ; - break; + struct status_change *sc_data; + int opt_flag = 0, calc_flag = 0; + short *sc_count, *option, *opt1, *opt2, *opt3; + + nullpo_retr (0, bl); + if (bl->type != BL_PC && bl->type != BL_MOB) + { + if (battle_config.error_log) + printf ("skill_status_change_end: neither MOB nor PC !\n"); + return 0; + } + nullpo_retr (0, sc_data = battle_get_sc_data (bl)); + nullpo_retr (0, sc_count = battle_get_sc_count (bl)); + nullpo_retr (0, option = battle_get_option (bl)); + nullpo_retr (0, opt1 = battle_get_opt1 (bl)); + nullpo_retr (0, opt2 = battle_get_opt2 (bl)); + nullpo_retr (0, opt3 = battle_get_opt3 (bl)); + + if ((*sc_count) > 0 && sc_data[type].timer != -1 + && (sc_data[type].timer == tid || tid == -1)) + { + + if (tid == -1) // タイマから呼ばれていないならタイマ削除をする + delete_timer (sc_data[type].timer, skill_status_change_timer); + + /* 該当の異常を正常に戻す */ + sc_data[type].timer = -1; + (*sc_count)--; + + switch (type) + { /* 異常の種類ごとの処理 */ + case SC_PROVOKE: /* プロボック */ + case SC_CONCENTRATE: /* 集中力向上 */ + case SC_BLESSING: /* ブレッシング */ + case SC_ANGELUS: /* アンゼルス */ + case SC_INCREASEAGI: /* 速度上昇 */ + case SC_DECREASEAGI: /* 速度減少 */ + case SC_SIGNUMCRUCIS: /* シグナムクルシス */ + case SC_HIDING: + case SC_TWOHANDQUICKEN: /* 2HQ */ + case SC_ADRENALINE: /* アドレナリンラッシュ */ + case SC_ENCPOISON: /* エンチャントポイズン */ + case SC_IMPOSITIO: /* インポシティオマヌス */ + case SC_GLORIA: /* グロリア */ + case SC_LOUD: /* ラウドボイス */ + case SC_QUAGMIRE: /* クァグマイア */ + case SC_PROVIDENCE: /* プロヴィデンス */ + case SC_SPEARSQUICKEN: /* スピアクイッケン */ + case SC_VOLCANO: + case SC_DELUGE: + case SC_VIOLENTGALE: + case SC_ETERNALCHAOS: /* エターナルカオス */ + case SC_DRUMBATTLE: /* 戦太鼓の響き */ + case SC_NIBELUNGEN: /* ニーベルングの指輪 */ + case SC_SIEGFRIED: /* 不死身のジークフリード */ + case SC_WHISTLE: /* 口笛 */ + case SC_ASSNCROS: /* 夕陽のアサシンクロス */ + case SC_HUMMING: /* ハミング */ + case SC_DONTFORGETME: /* 私を忘れないで */ + case SC_FORTUNE: /* 幸運のキス */ + case SC_SERVICE4U: /* サービスフォーユー */ + case SC_EXPLOSIONSPIRITS: // 爆裂波動 + case SC_STEELBODY: // 金剛 + case SC_DEFENDER: + case SC_SPEEDPOTION0: /* 増速ポーション */ + case SC_SPEEDPOTION1: + case SC_SPEEDPOTION2: + case SC_APPLEIDUN: /* イドゥンの林檎 */ + case SC_RIDING: + case SC_BLADESTOP_WAIT: + case SC_AURABLADE: /* オーラブレード */ + case SC_PARRYING: /* パリイング */ + case SC_CONCENTRATION: /* コンセントレーション */ + case SC_TENSIONRELAX: /* テンションリラックス */ + case SC_ASSUMPTIO: /* アシャンプティオ */ + case SC_WINDWALK: /* ウインドウォーク */ + case SC_TRUESIGHT: /* トゥルーサイト */ + case SC_SPIDERWEB: /* スパイダーウェッブ */ + case SC_MAGICPOWER: /* 魔法力増幅 */ + case SC_CHASEWALK: + case SC_ATKPOT: /* attack potion [Valaris] */ + case SC_MATKPOT: /* magic attack potion [Valaris] */ + case SC_WEDDING: //結婚用(結婚衣裳になって歩くのが遅いとか) + case SC_MELTDOWN: /* メルトダウン */ + case SC_PHYS_SHIELD: + case SC_HASTE: + calc_flag = 1; + break; + case SC_BERSERK: /* バーサーク */ + calc_flag = 1; + clif_status_change (bl, SC_INCREASEAGI, 0); /* アイコン消去 */ + break; + case SC_DEVOTION: /* ディボーション */ + { + struct map_session_data *md = map_id2sd (sc_data[type].val1); + sc_data[type].val1 = sc_data[type].val2 = 0; + skill_devotion (md, bl->id); + calc_flag = 1; + } + break; + case SC_BLADESTOP: + { + struct status_change *t_sc_data = + battle_get_sc_data ((struct block_list *) + sc_data[type].val4); + //片方が切れたので相手の白刃状態が切れてないのなら解除 + if (t_sc_data && t_sc_data[SC_BLADESTOP].timer != -1) + skill_status_change_end ((struct block_list *) + sc_data[type].val4, SC_BLADESTOP, + -1); + + if (sc_data[type].val2 == 2) + clif_bladestop ((struct block_list *) sc_data[type].val3, + (struct block_list *) sc_data[type].val4, + 0); + } + break; + case SC_DANCING: + { + struct map_session_data *dsd; + struct status_change *d_sc_data; + if (sc_data[type].val4 + && (dsd = map_id2sd (sc_data[type].val4))) + { + d_sc_data = dsd->sc_data; + //合奏で相手がいる場合相手のval4を0にする + if (d_sc_data && d_sc_data[type].timer != -1) + d_sc_data[type].val4 = 0; + } + } + calc_flag = 1; + break; + case SC_GRAFFITI: + { + struct skill_unit_group *sg = (struct skill_unit_group *) sc_data[type].val4; //val4がグラフィティのgroup_id + if (sg) + skill_delunitgroup (sg); + } + break; + case SC_NOCHAT: //チャット禁止状態 + { + struct map_session_data *sd = NULL; + if (bl->type == BL_PC + && (sd = (struct map_session_data *) bl)) + { + sd->status.manner = 0; + clif_updatestatus (sd, SP_MANNER); + } + } + break; + case SC_SPLASHER: /* ベナムスプラッシャー */ + { + struct block_list *src = map_id2bl (sc_data[type].val3); + if (src && tid != -1) + { + //自分にダメージ&周囲3*3にダメージ + skill_castend_damage_id (src, bl, sc_data[type].val2, + sc_data[type].val1, gettick (), + 0); + } + } + break; + case SC_SELFDESTRUCTION: /* 自爆 */ + { + //自分のダメージは0にして + struct mob_data *md = NULL; + if (bl->type == BL_MOB && (md = (struct mob_data *) bl)) + skill_castend_damage_id (bl, bl, sc_data[type].val2, + sc_data[type].val1, gettick (), + 0); + } + break; + /* option1 */ + case SC_FREEZE: + sc_data[type].val3 = 0; + break; + + /* option2 */ + case SC_POISON: /* 毒 */ + case SC_BLIND: /* 暗黒 */ + case SC_CURSE: + calc_flag = 1; + break; + } - case SC_SIGHT: - *option &= ~1; - opt_flag = 1; - break; - case SC_WEDDING: //結婚用(結婚衣裳になって歩くのが遅いとか) - *option &= ~4096; - opt_flag = 1; - break; - case SC_RUWACH: - *option &= ~8192; - opt_flag = 1; - break; - - //opt3 - case SC_TWOHANDQUICKEN: /* 2HQ */ - case SC_SPEARSQUICKEN: /* スピアクイッケン */ - case SC_CONCENTRATION: /* コンセントレーション */ - *opt3 &= ~1; - break; - case SC_OVERTHRUST: /* オーバースラスト */ - *opt3 &= ~2; - break; - case SC_ENERGYCOAT: /* エナジーコート */ - *opt3 &= ~4; - break; - case SC_EXPLOSIONSPIRITS: // 爆裂波動 - *opt3 &= ~8; - break; - case SC_STEELBODY: // 金剛 - *opt3 &= ~16; - break; - case SC_BLADESTOP: /* 白刃取り */ - *opt3 &= ~32; - break; - case SC_BERSERK: /* バーサーク */ - *opt3 &= ~128; - break; - case SC_MARIONETTE: /* マリオネットコントロール */ - *opt3 &= ~1024; - break; - case SC_ASSUMPTIO: /* アスムプティオ */ - *opt3 &= ~2048; - break; - } + if (bl->type == BL_PC && type < SC_SENDMAX) + clif_status_change (bl, type, 0); /* アイコン消去 */ + + switch (type) + { /* 正常に戻るときなにか処理が必要 */ + case SC_STONE: + case SC_FREEZE: + case SC_STAN: + case SC_SLEEP: + *opt1 = 0; + opt_flag = 1; + break; + + case SC_POISON: + case SC_CURSE: + case SC_SILENCE: + case SC_BLIND: + *opt2 &= ~(1 << (type - SC_POISON)); + opt_flag = 1; + break; + + case SC_SLOWPOISON: + if (sc_data[SC_POISON].timer != -1) + *opt2 |= 0x1; + *opt2 &= ~0x200; + opt_flag = 1; + break; + + case SC_SIGNUMCRUCIS: + *opt2 &= ~0x40; + opt_flag = 1; + break; + + case SC_SPEEDPOTION0: + *opt2 &= ~0x20; + opt_flag = 1; + break; + + case SC_ATKPOT: + *opt2 &= ~0x80; + opt_flag = 1; + break; + + case SC_HIDING: + case SC_CLOAKING: + *option &= ~((type == SC_HIDING) ? 2 : 4); + opt_flag = 1; + break; + + case SC_CHASEWALK: + *option &= ~16388; + opt_flag = 1; + break; + + case SC_SIGHT: + *option &= ~1; + opt_flag = 1; + break; + case SC_WEDDING: //結婚用(結婚衣裳になって歩くのが遅いとか) + *option &= ~4096; + opt_flag = 1; + break; + case SC_RUWACH: + *option &= ~8192; + opt_flag = 1; + break; + + //opt3 + case SC_TWOHANDQUICKEN: /* 2HQ */ + case SC_SPEARSQUICKEN: /* スピアクイッケン */ + case SC_CONCENTRATION: /* コンセントレーション */ + *opt3 &= ~1; + break; + case SC_OVERTHRUST: /* オーバースラスト */ + *opt3 &= ~2; + break; + case SC_ENERGYCOAT: /* エナジーコート */ + *opt3 &= ~4; + break; + case SC_EXPLOSIONSPIRITS: // 爆裂波動 + *opt3 &= ~8; + break; + case SC_STEELBODY: // 金剛 + *opt3 &= ~16; + break; + case SC_BLADESTOP: /* 白刃取り */ + *opt3 &= ~32; + break; + case SC_BERSERK: /* バーサーク */ + *opt3 &= ~128; + break; + case SC_MARIONETTE: /* マリオネットコントロール */ + *opt3 &= ~1024; + break; + case SC_ASSUMPTIO: /* アスムプティオ */ + *opt3 &= ~2048; + break; + } - if (night_flag == 1 && (*opt2 & STATE_BLIND) == 0 && bl->type == BL_PC) { // by [Yor] - *opt2 |= STATE_BLIND; - opt_flag = 1; - } + if (night_flag == 1 && (*opt2 & STATE_BLIND) == 0 + && bl->type == BL_PC) + { // by [Yor] + *opt2 |= STATE_BLIND; + opt_flag = 1; + } - if(opt_flag) /* optionの変更を伝える */ - clif_changeoption(bl); + if (opt_flag) /* optionの変更を伝える */ + clif_changeoption (bl); - if (bl->type == BL_PC && calc_flag) - pc_calcstatus((struct map_session_data *)bl,0); /* ステータス再計算 */ - } + if (bl->type == BL_PC && calc_flag) + pc_calcstatus ((struct map_session_data *) bl, 0); /* ステータス再計算 */ + } - return 0; + return 0; } - -int -skill_update_heal_animation(struct map_session_data *sd) +int skill_update_heal_animation (struct map_session_data *sd) { - const int mask = 0x100; - int was_active; - int is_active; + const int mask = 0x100; + int was_active; + int is_active; - nullpo_retr (0, sd); - was_active = sd->opt2 & mask; - is_active = sd->quick_regeneration_hp.amount > 0; + nullpo_retr (0, sd); + was_active = sd->opt2 & mask; + is_active = sd->quick_regeneration_hp.amount > 0; - if ((was_active && is_active) - || (!was_active && !is_active)) - return 0; // no update + if ((was_active && is_active) || (!was_active && !is_active)) + return 0; // no update - if (is_active) - sd->opt2 |= mask; - else - sd->opt2 &= ~mask; + if (is_active) + sd->opt2 |= mask; + else + sd->opt2 &= ~mask; - return clif_changeoption(&sd->bl); + return clif_changeoption (&sd->bl); } /*========================================== * ステータス異常終了タイマー *------------------------------------------ */ -int skill_status_change_timer(int tid, unsigned int tick, int id, int data) +int skill_status_change_timer (int tid, unsigned int tick, int id, int data) { - int type=data; - struct block_list *bl; - struct map_session_data *sd=NULL; - struct status_change *sc_data; - //short *sc_count; //使ってない? + int type = data; + struct block_list *bl; + struct map_session_data *sd = NULL; + struct status_change *sc_data; + //short *sc_count; //使ってない? + + if ((bl = map_id2bl (id)) == NULL) + return 0; //該当IDがすでに消滅しているというのはいかにもありそうなのでスルーしてみる + nullpo_retr (0, sc_data = battle_get_sc_data (bl)); + + if (bl->type == BL_PC) + sd = (struct map_session_data *) bl; + + //sc_count=battle_get_sc_count(bl); //使ってない? + + if (sc_data[type].timer != tid) + { + if (battle_config.error_log) + printf ("skill_status_change_timer %d != %d\n", tid, + sc_data[type].timer); + } + + if (sc_data[type].spell_invocation) + { // Must report termination + spell_effect_report_termination (sc_data[type].spell_invocation, + bl->id, type, 0); + sc_data[type].spell_invocation = 0; + } + + switch (type) + { /* 特殊な処理になる場合 */ + case SC_MAXIMIZEPOWER: /* マキシマイズパワー */ + case SC_CLOAKING: /* クローキング */ + case SC_CHASEWALK: + if (sd) + { + if (sd->status.sp > 0) + { /* SP切れるまで持続 */ + sd->status.sp--; + clif_updatestatus (sd, SP_SP); + sc_data[type].timer = add_timer ( /* タイマー再設定 */ + sc_data[type].val2 + + tick, + skill_status_change_timer, + bl->id, data); + return 0; + } + } + break; - if( (bl=map_id2bl(id)) == NULL ) - return 0; //該当IDがすでに消滅しているというのはいかにもありそうなのでスルーしてみる - nullpo_retr(0, sc_data=battle_get_sc_data(bl)); + case SC_HIDING: /* ハイディング */ + if (sd) + { /* SPがあって、時間制限の間は持続 */ + if (sd->status.sp > 0 && (--sc_data[type].val2) > 0) + { + if (sc_data[type].val2 % (sc_data[type].val1 + 3) == 0) + { + sd->status.sp--; + clif_updatestatus (sd, SP_SP); + } + sc_data[type].timer = add_timer ( /* タイマー再設定 */ + 1000 + tick, + skill_status_change_timer, + bl->id, data); + return 0; + } + } + break; - if(bl->type==BL_PC) - sd=(struct map_session_data *)bl; + case SC_SIGHT: /* サイト */ + { + const int range = 7; + map_foreachinarea (skill_status_change_timer_sub, + bl->m, bl->x - range, bl->y - range, + bl->x + range, bl->y + range, 0, bl, type, + tick); + + if ((--sc_data[type].val2) > 0) + { + sc_data[type].timer = add_timer ( /* タイマー再設定 */ + 250 + tick, + skill_status_change_timer, + bl->id, data); + return 0; + } + } + break; + case SC_RUWACH: /* ルアフ */ + { + const int range = 5; + map_foreachinarea (skill_status_change_timer_sub, + bl->m, bl->x - range, bl->y - range, + bl->x + range, bl->y + range, 0, bl, type, + tick); + + if ((--sc_data[type].val2) > 0) + { + sc_data[type].timer = add_timer ( /* タイマー再設定 */ + 250 + tick, + skill_status_change_timer, + bl->id, data); + return 0; + } + } + break; - //sc_count=battle_get_sc_count(bl); //使ってない? + case SC_SIGNUMCRUCIS: /* シグナムクルシス */ + { + int race = battle_get_race (bl); + if (race == 6 + || battle_check_undead (race, battle_get_elem_type (bl))) + { + sc_data[type].timer = + add_timer (1000 * 600 + tick, skill_status_change_timer, + bl->id, data); + return 0; + } + } + break; - if(sc_data[type].timer != tid) { - if(battle_config.error_log) - printf("skill_status_change_timer %d != %d\n",tid,sc_data[type].timer); - } + case SC_PROVOKE: /* プロボック/オートバーサーク */ + if (sc_data[type].val2 != 0) + { /* オートバーサーク(1秒ごとにHPチェック) */ + if (sd && sd->status.hp > sd->status.max_hp >> 2) /* 停止 */ + break; + sc_data[type].timer = + add_timer (1000 + tick, skill_status_change_timer, bl->id, + data); + return 0; + } + break; - if (sc_data[type].spell_invocation) { // Must report termination - spell_effect_report_termination(sc_data[type].spell_invocation, bl->id, type, 0); - sc_data[type].spell_invocation = 0; - } - - switch(type){ /* 特殊な処理になる場合 */ - case SC_MAXIMIZEPOWER: /* マキシマイズパワー */ - case SC_CLOAKING: /* クローキング */ - case SC_CHASEWALK: - if(sd){ - if( sd->status.sp > 0 ){ /* SP切れるまで持続 */ - sd->status.sp--; - clif_updatestatus(sd,SP_SP); - sc_data[type].timer=add_timer( /* タイマー再設定 */ - sc_data[type].val2+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - - case SC_HIDING: /* ハイディング */ - if(sd){ /* SPがあって、時間制限の間は持続 */ - if( sd->status.sp > 0 && (--sc_data[type].val2)>0 ){ - if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){ - sd->status.sp--; - clif_updatestatus(sd,SP_SP); - } - sc_data[type].timer=add_timer( /* タイマー再設定 */ - 1000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - - case SC_SIGHT: /* サイト */ - { - const int range=7; - map_foreachinarea( skill_status_change_timer_sub, - bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0, - bl,type,tick); - - if( (--sc_data[type].val2)>0 ){ - sc_data[type].timer=add_timer( /* タイマー再設定 */ - 250+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - case SC_RUWACH: /* ルアフ */ - { - const int range=5; - map_foreachinarea( skill_status_change_timer_sub, - bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0, - bl,type,tick); - - if( (--sc_data[type].val2)>0 ){ - sc_data[type].timer=add_timer( /* タイマー再設定 */ - 250+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - - case SC_SIGNUMCRUCIS: /* シグナムクルシス */ - { - int race = battle_get_race(bl); - if(race == 6 || battle_check_undead(race,battle_get_elem_type(bl))) { - sc_data[type].timer=add_timer(1000*600+tick,skill_status_change_timer, bl->id, data ); - return 0; - } - } - break; + case SC_WATERBALL: /* ウォーターボール */ + { + struct block_list *target = map_id2bl (sc_data[type].val2); + if (target == NULL || target->prev == NULL) + break; + skill_attack (BF_MAGIC, bl, bl, target, WZ_WATERBALL, + sc_data[type].val1, tick, 0); + if ((--sc_data[type].val3) > 0) + { + sc_data[type].timer = + add_timer (150 + tick, skill_status_change_timer, bl->id, + data); + return 0; + } + } + break; - case SC_PROVOKE: /* プロボック/オートバーサーク */ - if(sc_data[type].val2!=0){ /* オートバーサーク(1秒ごとにHPチェック) */ - if(sd && sd->status.hp>sd->status.max_hp>>2) /* 停止 */ - break; - sc_data[type].timer=add_timer( 1000+tick,skill_status_change_timer, bl->id, data ); - return 0; - } - break; + case SC_ENDURE: /* インデュア */ + if (sd && sd->special_state.infinite_endure) + { + sc_data[type].timer = + add_timer (1000 * 600 + tick, skill_status_change_timer, + bl->id, data); + sc_data[type].val2 = 1; + return 0; + } + break; - case SC_WATERBALL: /* ウォーターボール */ - { - struct block_list *target=map_id2bl(sc_data[type].val2); - if(target==NULL || target->prev==NULL) - break; - skill_attack(BF_MAGIC,bl,bl,target,WZ_WATERBALL,sc_data[type].val1,tick,0); - if((--sc_data[type].val3)>0) { - sc_data[type].timer=add_timer( 150+tick,skill_status_change_timer, bl->id, data ); - return 0; - } - } - break; + case SC_DISSONANCE: /* 不協和音 */ + if ((--sc_data[type].val2) > 0) + { + struct skill_unit *unit = + (struct skill_unit *) sc_data[type].val4; + struct block_list *src; + + if (!unit || !unit->group) + break; + src = map_id2bl (unit->group->src_id); + if (!src) + break; + skill_attack (BF_MISC, src, &unit->bl, bl, + unit->group->skill_id, sc_data[type].val1, tick, + 0); + sc_data[type].timer = + add_timer (skill_get_time2 + (unit->group->skill_id, + unit->group->skill_lv) + tick, + skill_status_change_timer, bl->id, data); + return 0; + } + break; - case SC_ENDURE: /* インデュア */ - if(sd && sd->special_state.infinite_endure) { - sc_data[type].timer=add_timer( 1000*600+tick,skill_status_change_timer, bl->id, data ); - sc_data[type].val2=1; - return 0; - } - break; + case SC_LULLABY: /* 子守唄 */ + if ((--sc_data[type].val2) > 0) + { + struct skill_unit *unit = + (struct skill_unit *) sc_data[type].val4; + if (!unit || !unit->group || unit->group->src_id == bl->id) + break; + skill_additional_effect (bl, bl, unit->group->skill_id, + sc_data[type].val1, + BF_LONG | BF_SKILL | BF_MISC, tick); + sc_data[type].timer = + add_timer (skill_get_time + (unit->group->skill_id, + unit->group->skill_lv) / 10 + tick, + skill_status_change_timer, bl->id, data); + return 0; + } + break; - case SC_DISSONANCE: /* 不協和音 */ - if( (--sc_data[type].val2)>0){ - struct skill_unit *unit= - (struct skill_unit *)sc_data[type].val4; - struct block_list *src; + case SC_STONE: + if (sc_data[type].val2 != 0) + { + short *opt1 = battle_get_opt1 (bl); + sc_data[type].val2 = 0; + sc_data[type].val4 = 0; + battle_stopwalking (bl, 1); + if (opt1) + { + *opt1 = 1; + clif_changeoption (bl); + } + sc_data[type].timer = + add_timer (1000 + tick, skill_status_change_timer, bl->id, + data); + return 0; + } + else if ((--sc_data[type].val3) > 0) + { + int hp = battle_get_max_hp (bl); + if ((++sc_data[type].val4) % 5 == 0 + && battle_get_hp (bl) > hp >> 2) + { + hp = hp / 100; + if (hp < 1) + hp = 1; + if (bl->type == BL_PC) + pc_heal ((struct map_session_data *) bl, -hp, 0); + else if (bl->type == BL_MOB) + { + struct mob_data *md; + if ((md = ((struct mob_data *) bl)) == NULL) + break; + md->hp -= hp; + } + } + sc_data[type].timer = + add_timer (1000 + tick, skill_status_change_timer, bl->id, + data); + return 0; + } + break; + case SC_POISON: + if (sc_data[SC_SLOWPOISON].timer == -1) + { + const int resist_poison = + skill_power_bl (bl, TMW_RESIST_POISON) >> 3; + if (resist_poison) + sc_data[type].val1 -= MRAND (resist_poison + 1); + + if ((--sc_data[type].val1) > 0) + { + + int hp = battle_get_max_hp (bl); + if (battle_get_hp (bl) > hp >> 4) + { + if (bl->type == BL_PC) + { + hp = 3 + hp * 3 / 200; + pc_heal ((struct map_session_data *) bl, -hp, 0); + } + else if (bl->type == BL_MOB) + { + struct mob_data *md; + if ((md = ((struct mob_data *) bl)) == NULL) + break; + hp = 3 + hp / 200; + md->hp -= hp; + } + } + sc_data[type].timer = + add_timer (1000 + tick, skill_status_change_timer, + bl->id, data); + } + } + else + sc_data[type].timer = + add_timer (2000 + tick, skill_status_change_timer, bl->id, + data); + break; - if(!unit || !unit->group) - break; - src=map_id2bl(unit->group->src_id); - if(!src) - break; - skill_attack(BF_MISC,src,&unit->bl,bl,unit->group->skill_id,sc_data[type].val1,tick,0); - sc_data[type].timer=add_timer(skill_get_time2(unit->group->skill_id,unit->group->skill_lv)+tick, - skill_status_change_timer, bl->id, data ); - return 0; - } - break; + case SC_TENSIONRELAX: /* テンションリラックス */ + if (sd) + { /* SPがあって、HPが満タンでなければ継続 */ + if (sd->status.sp > 12 && sd->status.max_hp > sd->status.hp) + { + if (sc_data[type].val2 % (sc_data[type].val1 + 3) == 0) + { + sd->status.sp -= 12; + clif_updatestatus (sd, SP_SP); + } + sc_data[type].timer = add_timer ( /* タイマー再設定 */ + 10000 + tick, + skill_status_change_timer, + bl->id, data); + return 0; + } + if (sd->status.max_hp <= sd->status.hp) + skill_status_change_end (&sd->bl, SC_TENSIONRELAX, -1); + } + break; - case SC_LULLABY: /* 子守唄 */ - if( (--sc_data[type].val2)>0){ - struct skill_unit *unit= - (struct skill_unit *)sc_data[type].val4; - if(!unit || !unit->group || unit->group->src_id==bl->id) - break; - skill_additional_effect(bl,bl,unit->group->skill_id,sc_data[type].val1,BF_LONG|BF_SKILL|BF_MISC,tick); - sc_data[type].timer=add_timer(skill_get_time(unit->group->skill_id,unit->group->skill_lv)/10+tick, - skill_status_change_timer, bl->id, data ); - return 0; - } - break; - - case SC_STONE: - if(sc_data[type].val2 != 0) { - short *opt1 = battle_get_opt1(bl); - sc_data[type].val2 = 0; - sc_data[type].val4 = 0; - battle_stopwalking(bl,1); - if(opt1) { - *opt1 = 1; - clif_changeoption(bl); - } - sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data ); - return 0; - } - else if( (--sc_data[type].val3) > 0) { - int hp = battle_get_max_hp(bl); - if((++sc_data[type].val4)%5 == 0 && battle_get_hp(bl) > hp>>2) { - hp = hp/100; - if(hp < 1) hp = 1; - if(bl->type == BL_PC) - pc_heal((struct map_session_data *)bl,-hp,0); - else if(bl->type == BL_MOB){ - struct mob_data *md; - if((md=((struct mob_data *)bl)) == NULL) - break; - md->hp -= hp; - } - } - sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data ); - return 0; - } - break; - case SC_POISON: - if(sc_data[SC_SLOWPOISON].timer == -1) { - const int resist_poison = skill_power_bl(bl, TMW_RESIST_POISON) >> 3; - if (resist_poison) - sc_data[type].val1 -= MRAND(resist_poison + 1); - - if( (--sc_data[type].val1) > 0) { - - int hp = battle_get_max_hp(bl); - if(battle_get_hp(bl) > hp>>4) { - if(bl->type == BL_PC) { - hp = 3 + hp*3/200; - pc_heal((struct map_session_data *)bl,-hp,0); - } - else if(bl->type == BL_MOB) { - struct mob_data *md; - if((md=((struct mob_data *)bl)) == NULL) - break; - hp = 3 + hp/200; - md->hp -= hp; - } - } - sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data ); - } - } - else - sc_data[type].timer=add_timer(2000+tick,skill_status_change_timer, bl->id, data ); - break; - - case SC_TENSIONRELAX: /* テンションリラックス */ - if(sd){ /* SPがあって、HPが満タンでなければ継続 */ - if( sd->status.sp > 12 && sd->status.max_hp > sd->status.hp ){ - if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){ - sd->status.sp -= 12; - clif_updatestatus(sd,SP_SP); - } - sc_data[type].timer=add_timer( /* タイマー再設定 */ - 10000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - if(sd->status.max_hp <= sd->status.hp) - skill_status_change_end(&sd->bl,SC_TENSIONRELAX,-1); - } - break; - - /* 時間切れ無し?? */ - case SC_AETERNA: - case SC_TRICKDEAD: - case SC_RIDING: - case SC_FALCON: - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_MAGICPOWER: /* 魔法力増幅 */ - case SC_REJECTSWORD: /* リジェクトソード */ - case SC_MEMORIZE: /* メモライズ */ - case SC_BROKNWEAPON: - case SC_BROKNARMOR: - if(sc_data[type].timer==tid) - sc_data[type].timer=add_timer( 1000*600+tick,skill_status_change_timer, bl->id, data ); - return 0; - - case SC_DANCING: //ダンススキルの時間SP消費 - { - int s=0; - if(sd){ - if(sd->status.sp > 0 && (--sc_data[type].val3)>0){ - switch(sc_data[type].val1){ - case BD_RICHMANKIM: /* ニヨルドの宴 3秒にSP1 */ - case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き 3秒にSP1 */ - case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 3秒にSP1 */ - case BD_SIEGFRIED: /* 不死身のジークフリード 3秒にSP1 */ - case BA_DISSONANCE: /* 不協和音 3秒でSP1 */ - case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス 3秒でSP1 */ - case DC_UGLYDANCE: /* 自分勝手なダンス 3秒でSP1 */ - s=3; - break; - case BD_LULLABY: /* 子守歌 4秒にSP1 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 4秒にSP1 */ - case BD_ROKISWEIL: /* ロキの叫び 4秒にSP1 */ - case DC_FORTUNEKISS: /* 幸運のキス 4秒でSP1 */ - s=4; - break; - case BD_INTOABYSS: /* 深淵の中に 5秒にSP1 */ - case BA_WHISTLE: /* 口笛 5秒でSP1 */ - case DC_HUMMING: /* ハミング 5秒でSP1 */ - case BA_POEMBRAGI: /* ブラギの詩 5秒でSP1 */ - case DC_SERVICEFORYOU: /* サービスフォーユー 5秒でSP1 */ - s=5; - break; - case BA_APPLEIDUN: /* イドゥンの林檎 6秒でSP1 */ - s=6; - break; - case DC_DONTFORGETME: /* 私を忘れないで… 10秒でSP1 */ - case CG_MOONLIT: /* 月明りの泉に落ちる花びら 10秒でSP1? */ - s=10; - break; - } - if(s && ((sc_data[type].val3 % s) == 0)){ - sd->status.sp--; - clif_updatestatus(sd,SP_SP); - } - sc_data[type].timer=add_timer( /* タイマー再設定 */ - 1000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - } - break; - case SC_BERSERK: /* バーサーク */ - if(sd){ /* HPが100以上なら継続 */ - if( (sd->status.hp - sd->status.hp/100) > 100 ){ - sd->status.hp -= sd->status.hp/100; - clif_updatestatus(sd,SP_HP); - sc_data[type].timer=add_timer( /* タイマー再設定 */ - 15000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - case SC_WEDDING: //結婚用(結婚衣裳になって歩くのが遅いとか) - if(sd){ - time_t timer; - if(time(&timer) < ((sc_data[type].val2) + 3600)){ //1時間たっていないので継続 - sc_data[type].timer=add_timer( /* タイマー再設定 */ - 10000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - case SC_NOCHAT: //チャット禁止状態 - if(sd && battle_config.muting_players){ - time_t timer; - if((++sd->status.manner) && time(&timer) < ((sc_data[type].val2) + 60*(0-sd->status.manner))){ //開始からstatus.manner分経ってないので継続 - clif_updatestatus(sd,SP_MANNER); - sc_data[type].timer=add_timer( /* タイマー再設定(60秒) */ - 60000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - } - break; - case SC_SELFDESTRUCTION: /* 自爆 */ - if(--sc_data[type].val3>0){ - struct mob_data *md; - if(bl->type==BL_MOB && (md=(struct mob_data *)bl) && md->stats[MOB_SPEED] > 250){ - md->stats[MOB_SPEED] -= 250; - md->next_walktime=tick; - } - sc_data[type].timer=add_timer( /* タイマー再設定 */ - 1000+tick, skill_status_change_timer, - bl->id, data); - return 0; - } - break; + /* 時間切れ無し?? */ + case SC_AETERNA: + case SC_TRICKDEAD: + case SC_RIDING: + case SC_FALCON: + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_MAGICPOWER: /* 魔法力増幅 */ + case SC_REJECTSWORD: /* リジェクトソード */ + case SC_MEMORIZE: /* メモライズ */ + case SC_BROKNWEAPON: + case SC_BROKNARMOR: + if (sc_data[type].timer == tid) + sc_data[type].timer = + add_timer (1000 * 600 + tick, skill_status_change_timer, + bl->id, data); + return 0; + + case SC_DANCING: //ダンススキルの時間SP消費 + { + int s = 0; + if (sd) + { + if (sd->status.sp > 0 && (--sc_data[type].val3) > 0) + { + switch (sc_data[type].val1) + { + case BD_RICHMANKIM: /* ニヨルドの宴 3秒にSP1 */ + case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き 3秒にSP1 */ + case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 3秒にSP1 */ + case BD_SIEGFRIED: /* 不死身のジークフリード 3秒にSP1 */ + case BA_DISSONANCE: /* 不協和音 3秒でSP1 */ + case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス 3秒でSP1 */ + case DC_UGLYDANCE: /* 自分勝手なダンス 3秒でSP1 */ + s = 3; + break; + case BD_LULLABY: /* 子守歌 4秒にSP1 */ + case BD_ETERNALCHAOS: /* 永遠の混沌 4秒にSP1 */ + case BD_ROKISWEIL: /* ロキの叫び 4秒にSP1 */ + case DC_FORTUNEKISS: /* 幸運のキス 4秒でSP1 */ + s = 4; + break; + case BD_INTOABYSS: /* 深淵の中に 5秒にSP1 */ + case BA_WHISTLE: /* 口笛 5秒でSP1 */ + case DC_HUMMING: /* ハミング 5秒でSP1 */ + case BA_POEMBRAGI: /* ブラギの詩 5秒でSP1 */ + case DC_SERVICEFORYOU: /* サービスフォーユー 5秒でSP1 */ + s = 5; + break; + case BA_APPLEIDUN: /* イドゥンの林檎 6秒でSP1 */ + s = 6; + break; + case DC_DONTFORGETME: /* 私を忘れないで… 10秒でSP1 */ + case CG_MOONLIT: /* 月明りの泉に落ちる花びら 10秒でSP1? */ + s = 10; + break; + } + if (s && ((sc_data[type].val3 % s) == 0)) + { + sd->status.sp--; + clif_updatestatus (sd, SP_SP); + } + sc_data[type].timer = add_timer ( /* タイマー再設定 */ + 1000 + tick, + skill_status_change_timer, + bl->id, data); + return 0; + } + } + } + break; + case SC_BERSERK: /* バーサーク */ + if (sd) + { /* HPが100以上なら継続 */ + if ((sd->status.hp - sd->status.hp / 100) > 100) + { + sd->status.hp -= sd->status.hp / 100; + clif_updatestatus (sd, SP_HP); + sc_data[type].timer = add_timer ( /* タイマー再設定 */ + 15000 + tick, + skill_status_change_timer, + bl->id, data); + return 0; + } + } + break; + case SC_WEDDING: //結婚用(結婚衣裳になって歩くのが遅いとか) + if (sd) + { + time_t timer; + if (time (&timer) < ((sc_data[type].val2) + 3600)) + { //1時間たっていないので継続 + sc_data[type].timer = add_timer ( /* タイマー再設定 */ + 10000 + tick, + skill_status_change_timer, + bl->id, data); + return 0; + } + } + break; + case SC_NOCHAT: //チャット禁止状態 + if (sd && battle_config.muting_players) + { + time_t timer; + if ((++sd->status.manner) + && time (&timer) < + ((sc_data[type].val2) + 60 * (0 - sd->status.manner))) + { //開始からstatus.manner分経ってないので継続 + clif_updatestatus (sd, SP_MANNER); + sc_data[type].timer = add_timer ( /* タイマー再設定(60秒) */ + 60000 + tick, + skill_status_change_timer, + bl->id, data); + return 0; + } + } + break; + case SC_SELFDESTRUCTION: /* 自爆 */ + if (--sc_data[type].val3 > 0) + { + struct mob_data *md; + if (bl->type == BL_MOB && (md = (struct mob_data *) bl) + && md->stats[MOB_SPEED] > 250) + { + md->stats[MOB_SPEED] -= 250; + md->next_walktime = tick; + } + sc_data[type].timer = add_timer ( /* タイマー再設定 */ + 1000 + tick, + skill_status_change_timer, + bl->id, data); + return 0; + } + break; case SC_FLYING_BACKPACK: - clif_updatestatus(sd, SP_WEIGHT); + clif_updatestatus (sd, SP_WEIGHT); break; - } + } - return skill_status_change_end( bl,type,tid ); + return skill_status_change_end (bl, type, tid); } /*========================================== * ステータス異常終了 *------------------------------------------ */ -int skill_encchant_eremental_end(struct block_list *bl,int type) +int skill_encchant_eremental_end (struct block_list *bl, int type) { - struct status_change *sc_data; - - nullpo_retr(0, bl); - nullpo_retr(0, sc_data=battle_get_sc_data(bl)); - - if( type!=SC_ENCPOISON && sc_data[SC_ENCPOISON].timer!=-1 ) /* エンチャントポイズン解除 */ - skill_status_change_end(bl,SC_ENCPOISON,-1); - if( type!=SC_ASPERSIO && sc_data[SC_ASPERSIO].timer!=-1 ) /* アスペルシオ解除 */ - skill_status_change_end(bl,SC_ASPERSIO,-1); - if( type!=SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer!=-1 ) /* フレイムランチャ解除 */ - skill_status_change_end(bl,SC_FLAMELAUNCHER,-1); - if( type!=SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer!=-1 ) /* フロストウェポン解除 */ - skill_status_change_end(bl,SC_FROSTWEAPON,-1); - if( type!=SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer!=-1 ) /* ライトニングローダー解除 */ - skill_status_change_end(bl,SC_LIGHTNINGLOADER,-1); - if( type!=SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer!=-1 ) /* サイスミックウェポン解除 */ - skill_status_change_end(bl,SC_SEISMICWEAPON,-1); - - return 0; + struct status_change *sc_data; + + nullpo_retr (0, bl); + nullpo_retr (0, sc_data = battle_get_sc_data (bl)); + + if (type != SC_ENCPOISON && sc_data[SC_ENCPOISON].timer != -1) /* エンチャントポイズン解除 */ + skill_status_change_end (bl, SC_ENCPOISON, -1); + if (type != SC_ASPERSIO && sc_data[SC_ASPERSIO].timer != -1) /* アスペルシオ解除 */ + skill_status_change_end (bl, SC_ASPERSIO, -1); + if (type != SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer != -1) /* フレイムランチャ解除 */ + skill_status_change_end (bl, SC_FLAMELAUNCHER, -1); + if (type != SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer != -1) /* フロストウェポン解除 */ + skill_status_change_end (bl, SC_FROSTWEAPON, -1); + if (type != SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer != -1) /* ライトニングローダー解除 */ + skill_status_change_end (bl, SC_LIGHTNINGLOADER, -1); + if (type != SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer != -1) /* サイスミックウェポン解除 */ + skill_status_change_end (bl, SC_SEISMICWEAPON, -1); + + return 0; } + /*========================================== * ステータス異常開始 *------------------------------------------ */ -int skill_status_change_start(struct block_list *bl, int type, int val1, int val2, int val3, int val4, int tick, int flag) +int skill_status_change_start (struct block_list *bl, int type, int val1, + int val2, int val3, int val4, int tick, + int flag) { - return skill_status_effect(bl, type, val1, val2, val3, val4, tick, flag, 0); + return skill_status_effect (bl, type, val1, val2, val3, val4, tick, flag, + 0); } - -int skill_status_effect(struct block_list *bl, int type, int val1, int val2, int val3, int val4, int tick, int flag, int spell_invocation) +int skill_status_effect (struct block_list *bl, int type, int val1, int val2, + int val3, int val4, int tick, int flag, + int spell_invocation) { - struct map_session_data *sd = NULL; - struct status_change* sc_data; - short *sc_count, *option, *opt1, *opt2, *opt3; - int opt_flag = 0, calc_flag = 0,updateflag = 0, race, mode, elem, undead_flag; - int scdef=0; - - nullpo_retr(0, bl); - if(bl->type == BL_SKILL) - return 0; - nullpo_retr(0, sc_data=battle_get_sc_data(bl)); - nullpo_retr(0, sc_count=battle_get_sc_count(bl)); - nullpo_retr(0, option=battle_get_option(bl)); - nullpo_retr(0, opt1=battle_get_opt1(bl)); - nullpo_retr(0, opt2=battle_get_opt2(bl)); - nullpo_retr(0, opt3=battle_get_opt3(bl)); - - race=battle_get_race(bl); - mode=battle_get_mode(bl); - elem=battle_get_elem_type(bl); - undead_flag=battle_check_undead(race,elem); - - if(type == SC_AETERNA && (sc_data[SC_STONE].timer != -1 || sc_data[SC_FREEZE].timer != -1) ) - return 0; - - switch(type){ - case SC_STONE: - case SC_FREEZE: - scdef=3+battle_get_mdef(bl)+battle_get_luk(bl)/3; - break; - case SC_STAN: - case SC_SILENCE: - case SC_POISON: - scdef=3+battle_get_vit(bl)+battle_get_luk(bl)/3; - break; - case SC_SLEEP: - case SC_BLIND: - scdef=3+battle_get_int(bl)+battle_get_luk(bl)/3; - break; - case SC_CURSE: - scdef=3+battle_get_luk(bl); - break; + struct map_session_data *sd = NULL; + struct status_change *sc_data; + short *sc_count, *option, *opt1, *opt2, *opt3; + int opt_flag = 0, calc_flag = 0, updateflag = + 0, race, mode, elem, undead_flag; + int scdef = 0; + + nullpo_retr (0, bl); + if (bl->type == BL_SKILL) + return 0; + nullpo_retr (0, sc_data = battle_get_sc_data (bl)); + nullpo_retr (0, sc_count = battle_get_sc_count (bl)); + nullpo_retr (0, option = battle_get_option (bl)); + nullpo_retr (0, opt1 = battle_get_opt1 (bl)); + nullpo_retr (0, opt2 = battle_get_opt2 (bl)); + nullpo_retr (0, opt3 = battle_get_opt3 (bl)); + + race = battle_get_race (bl); + mode = battle_get_mode (bl); + elem = battle_get_elem_type (bl); + undead_flag = battle_check_undead (race, elem); + + if (type == SC_AETERNA + && (sc_data[SC_STONE].timer != -1 || sc_data[SC_FREEZE].timer != -1)) + return 0; -// case SC_CONFUSION: - default: - scdef=0; - } - if(scdef>=100) - return 0; - if(bl->type==BL_PC){ - sd=(struct map_session_data *)bl; - if( sd && type == SC_ADRENALINE && !(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon))) - return 0; - - if(SC_STONE<=type && type<=SC_BLIND){ /* カードによる耐性 */ - if( sd && sd->reseff[type-SC_STONE] > 0 && MRAND(10000)<sd->reseff[type-SC_STONE]){ - if(battle_config.battle_log) - printf("PC %d skill_sc_start: cardによる異常耐性発動\n",sd->bl.id); - return 0; - } - } - } - else if(bl->type == BL_MOB) { - } - else { - if(battle_config.error_log) - printf("skill_status_change_start: neither MOB nor PC !\n"); - return 0; - } + switch (type) + { + case SC_STONE: + case SC_FREEZE: + scdef = 3 + battle_get_mdef (bl) + battle_get_luk (bl) / 3; + break; + case SC_STAN: + case SC_SILENCE: + case SC_POISON: + scdef = 3 + battle_get_vit (bl) + battle_get_luk (bl) / 3; + break; + case SC_SLEEP: + case SC_BLIND: + scdef = 3 + battle_get_int (bl) + battle_get_luk (bl) / 3; + break; + case SC_CURSE: + scdef = 3 + battle_get_luk (bl); + break; - if(type==SC_FREEZE && undead_flag && !(flag&1)) - return 0; +// case SC_CONFUSION: + default: + scdef = 0; + } + if (scdef >= 100) + return 0; + if (bl->type == BL_PC) + { + sd = (struct map_session_data *) bl; + if (sd && type == SC_ADRENALINE + && !(skill_get_weapontype (BS_ADRENALINE) & + (1 << sd->status.weapon))) + return 0; + + if (SC_STONE <= type && type <= SC_BLIND) + { /* カードによる耐性 */ + if (sd && sd->reseff[type - SC_STONE] > 0 + && MRAND (10000) < sd->reseff[type - SC_STONE]) + { + if (battle_config.battle_log) + printf ("PC %d skill_sc_start: cardによる異常耐性発動\n", + sd->bl.id); + return 0; + } + } + } + else if (bl->type == BL_MOB) + { + } + else + { + if (battle_config.error_log) + printf ("skill_status_change_start: neither MOB nor PC !\n"); + return 0; + } - if((type == SC_ADRENALINE || type == SC_WEAPONPERFECTION || type == SC_OVERTHRUST) && - sc_data[type].timer != -1 && sc_data[type].val2 && !val2) - return 0; + if (type == SC_FREEZE && undead_flag && !(flag & 1)) + return 0; - if(mode & 0x20 && (type==SC_STONE || type==SC_FREEZE || - type==SC_STAN || type==SC_SLEEP || type==SC_SILENCE || type==SC_QUAGMIRE || type == SC_DECREASEAGI || type == SC_SIGNUMCRUCIS || type == SC_PROVOKE || - (type == SC_BLESSING && (undead_flag || race == 6))) && !(flag&1)){ - /* ボスには効かない(ただしカードによる効果は適用される) */ - return 0; - } - if(type==SC_FREEZE || type==SC_STAN || type==SC_SLEEP) - battle_stopwalking(bl,1); - - if(sc_data[type].timer != -1){ /* すでに同じ異常になっている場合タイマ解除 */ - if(sc_data[type].val1 > val1 && type != SC_COMBO && type != SC_DANCING && type != SC_DEVOTION && - type != SC_SPEEDPOTION0 && type != SC_SPEEDPOTION1 && type != SC_SPEEDPOTION2 - && type != SC_ATKPOT && type != SC_MATKPOT) // added atk and matk potions [Valaris] - return 0; - if(type >=SC_STAN && type <= SC_BLIND) - return 0;/* 継ぎ足しができない状態異常である時は状態異常を行わない */ - if(type == SC_GRAFFITI){ //異常中にもう一度状態異常になった時に解除してから再度かかる - skill_status_change_end(bl,type,-1); - }else{ - (*sc_count)--; - delete_timer(sc_data[type].timer, skill_status_change_timer); - sc_data[type].timer = -1; - } - } + if ((type == SC_ADRENALINE || type == SC_WEAPONPERFECTION + || type == SC_OVERTHRUST) && sc_data[type].timer != -1 + && sc_data[type].val2 && !val2) + return 0; - switch(type){ /* 異常の種類ごとの処理 */ - case SC_PROVOKE: /* プロボック */ - calc_flag = 1; - if(tick <= 0) tick = 1000; /* (オートバーサーク) */ - break; - case SC_ENDURE: /* インデュア */ - if(tick <= 0) tick = 1000 * 60; - break; - case SC_CONCENTRATE: /* 集中力向上 */ - calc_flag = 1; - break; - case SC_BLESSING: /* ブレッシング */ - { - if(bl->type == BL_PC || (!undead_flag && race != 6)) { - if(sc_data[SC_CURSE].timer!=-1 ) - skill_status_change_end(bl,SC_CURSE,-1); - if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2 == 0) - skill_status_change_end(bl,SC_STONE,-1); - } - calc_flag = 1; - } - break; - case SC_ANGELUS: /* アンゼルス */ - calc_flag = 1; - break; - case SC_INCREASEAGI: /* 速度上昇 */ - calc_flag = 1; - if(sc_data[SC_DECREASEAGI].timer!=-1 ) - skill_status_change_end(bl,SC_DECREASEAGI,-1); - if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォーク */ - skill_status_change_end(bl,SC_WINDWALK,-1); - break; - case SC_DECREASEAGI: /* 速度減少 */ - calc_flag = 1; - if(sc_data[SC_INCREASEAGI].timer!=-1 ) - skill_status_change_end(bl,SC_INCREASEAGI,-1); - break; - case SC_SIGNUMCRUCIS: /* シグナムクルシス */ - calc_flag = 1; -// val2 = 14 + val1; - val2 = 10 + val1*2; - tick = 600*1000; - clif_emotion(bl,4); - break; - case SC_SLOWPOISON: - if(sc_data[SC_POISON].timer == -1 ) - return 0; - break; - case SC_TWOHANDQUICKEN: /* 2HQ */ - *opt3 |= 1; - calc_flag = 1; - break; - case SC_ADRENALINE: /* アドレナリンラッシュ */ - calc_flag = 1; - break; - case SC_WEAPONPERFECTION: /* ウェポンパーフェクション */ - if(battle_config.party_skill_penaly && !val2) tick /= 5; - break; - case SC_OVERTHRUST: /* オーバースラスト */ - *opt3 |= 2; - if(battle_config.party_skill_penaly && !val2) tick /= 10; - break; - case SC_MAXIMIZEPOWER: /* マキシマイズパワー(SPが1減る時間,val2にも) */ - if(bl->type == BL_PC) - val2 = tick; - else - tick = 5000*val1; - break; - case SC_ENCPOISON: /* エンチャントポイズン */ - calc_flag = 1; - val2=(((val1 - 1) / 2) + 3)*100; /* 毒付与確率 */ - skill_encchant_eremental_end(bl,SC_ENCPOISON); - break; - case SC_POISONREACT: /* ポイズンリアクト */ - break; - case SC_IMPOSITIO: /* インポシティオマヌス */ - calc_flag = 1; - break; - case SC_ASPERSIO: /* アスペルシオ */ - skill_encchant_eremental_end(bl,SC_ASPERSIO); - break; - case SC_SUFFRAGIUM: /* サフラギム */ - case SC_BENEDICTIO: /* 聖体 */ - case SC_MAGNIFICAT: /* マグニフィカート */ - case SC_AETERNA: /* エーテルナ */ - break; - case SC_ENERGYCOAT: /* エナジーコート */ - *opt3 |= 4; - break; - case SC_MAGICROD: - val2 = val1*20; - break; - case SC_KYRIE: /* キリエエレイソン */ - val2 = battle_get_max_hp(bl) * (val1 * 2 + 10) / 100;/* 耐久度 */ - val3 = (val1 / 2 + 5); /* 回数 */ + if (mode & 0x20 && (type == SC_STONE || type == SC_FREEZE || + type == SC_STAN || type == SC_SLEEP + || type == SC_SILENCE || type == SC_QUAGMIRE + || type == SC_DECREASEAGI || type == SC_SIGNUMCRUCIS + || type == SC_PROVOKE || (type == SC_BLESSING + && (undead_flag + || race == 6))) + && !(flag & 1)) + { + /* ボスには効かない(ただしカードによる効果は適用される) */ + return 0; + } + if (type == SC_FREEZE || type == SC_STAN || type == SC_SLEEP) + battle_stopwalking (bl, 1); + + if (sc_data[type].timer != -1) + { /* すでに同じ異常になっている場合タイマ解除 */ + if (sc_data[type].val1 > val1 && type != SC_COMBO && type != SC_DANCING && type != SC_DEVOTION && type != SC_SPEEDPOTION0 && type != SC_SPEEDPOTION1 && type != SC_SPEEDPOTION2 && type != SC_ATKPOT && type != SC_MATKPOT) // added atk and matk potions [Valaris] + return 0; + if (type >= SC_STAN && type <= SC_BLIND) + return 0; /* 継ぎ足しができない状態異常である時は状態異常を行わない */ + if (type == SC_GRAFFITI) + { //異常中にもう一度状態異常になった時に解除してから再度かかる + skill_status_change_end (bl, type, -1); + } + else + { + (*sc_count)--; + delete_timer (sc_data[type].timer, skill_status_change_timer); + sc_data[type].timer = -1; + } + } + + switch (type) + { /* 異常の種類ごとの処理 */ + case SC_PROVOKE: /* プロボック */ + calc_flag = 1; + if (tick <= 0) + tick = 1000; /* (オートバーサーク) */ + break; + case SC_ENDURE: /* インデュア */ + if (tick <= 0) + tick = 1000 * 60; + break; + case SC_CONCENTRATE: /* 集中力向上 */ + calc_flag = 1; + break; + case SC_BLESSING: /* ブレッシング */ + { + if (bl->type == BL_PC || (!undead_flag && race != 6)) + { + if (sc_data[SC_CURSE].timer != -1) + skill_status_change_end (bl, SC_CURSE, -1); + if (sc_data[SC_STONE].timer != -1 + && sc_data[SC_STONE].val2 == 0) + skill_status_change_end (bl, SC_STONE, -1); + } + calc_flag = 1; + } + break; + case SC_ANGELUS: /* アンゼルス */ + calc_flag = 1; + break; + case SC_INCREASEAGI: /* 速度上昇 */ + calc_flag = 1; + if (sc_data[SC_DECREASEAGI].timer != -1) + skill_status_change_end (bl, SC_DECREASEAGI, -1); + if (sc_data[SC_WINDWALK].timer != -1) /* ウインドウォーク */ + skill_status_change_end (bl, SC_WINDWALK, -1); + break; + case SC_DECREASEAGI: /* 速度減少 */ + calc_flag = 1; + if (sc_data[SC_INCREASEAGI].timer != -1) + skill_status_change_end (bl, SC_INCREASEAGI, -1); + break; + case SC_SIGNUMCRUCIS: /* シグナムクルシス */ + calc_flag = 1; +// val2 = 14 + val1; + val2 = 10 + val1 * 2; + tick = 600 * 1000; + clif_emotion (bl, 4); + break; + case SC_SLOWPOISON: + if (sc_data[SC_POISON].timer == -1) + return 0; + break; + case SC_TWOHANDQUICKEN: /* 2HQ */ + *opt3 |= 1; + calc_flag = 1; + break; + case SC_ADRENALINE: /* アドレナリンラッシュ */ + calc_flag = 1; + break; + case SC_WEAPONPERFECTION: /* ウェポンパーフェクション */ + if (battle_config.party_skill_penaly && !val2) + tick /= 5; + break; + case SC_OVERTHRUST: /* オーバースラスト */ + *opt3 |= 2; + if (battle_config.party_skill_penaly && !val2) + tick /= 10; + break; + case SC_MAXIMIZEPOWER: /* マキシマイズパワー(SPが1減る時間,val2にも) */ + if (bl->type == BL_PC) + val2 = tick; + else + tick = 5000 * val1; + break; + case SC_ENCPOISON: /* エンチャントポイズン */ + calc_flag = 1; + val2 = (((val1 - 1) / 2) + 3) * 100; /* 毒付与確率 */ + skill_encchant_eremental_end (bl, SC_ENCPOISON); + break; + case SC_POISONREACT: /* ポイズンリアクト */ + break; + case SC_IMPOSITIO: /* インポシティオマヌス */ + calc_flag = 1; + break; + case SC_ASPERSIO: /* アスペルシオ */ + skill_encchant_eremental_end (bl, SC_ASPERSIO); + break; + case SC_SUFFRAGIUM: /* サフラギム */ + case SC_BENEDICTIO: /* 聖体 */ + case SC_MAGNIFICAT: /* マグニフィカート */ + case SC_AETERNA: /* エーテルナ */ + break; + case SC_ENERGYCOAT: /* エナジーコート */ + *opt3 |= 4; + break; + case SC_MAGICROD: + val2 = val1 * 20; + break; + case SC_KYRIE: /* キリエエレイソン */ + val2 = battle_get_max_hp (bl) * (val1 * 2 + 10) / 100; /* 耐久度 */ + val3 = (val1 / 2 + 5); /* 回数 */ // -- moonsoul (added to undo assumptio status if target has it) - if(sc_data[SC_ASSUMPTIO].timer!=-1 ) - skill_status_change_end(bl,SC_ASSUMPTIO,-1); - break; - case SC_MINDBREAKER: - calc_flag = 1; - if(tick <= 0) tick = 1000; /* (オートバーサーク) */ - case SC_GLORIA: /* グロリア */ - calc_flag = 1; - break; - case SC_LOUD: /* ラウドボイス */ - calc_flag = 1; - break; - case SC_TRICKDEAD: /* 死んだふり */ - break; - case SC_QUAGMIRE: /* クァグマイア */ - calc_flag = 1; - if(sc_data[SC_CONCENTRATE].timer!=-1 ) /* 集中力向上解除 */ - skill_status_change_end(bl,SC_CONCENTRATE,-1); - if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* 速度上昇解除 */ - skill_status_change_end(bl,SC_INCREASEAGI,-1); - if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 ) - skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1); - if(sc_data[SC_SPEARSQUICKEN].timer!=-1 ) - skill_status_change_end(bl,SC_SPEARSQUICKEN,-1); - if(sc_data[SC_ADRENALINE].timer!=-1 ) - skill_status_change_end(bl,SC_ADRENALINE,-1); - if(sc_data[SC_LOUD].timer!=-1 ) - skill_status_change_end(bl,SC_LOUD,-1); - if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* トゥルーサイト */ - skill_status_change_end(bl,SC_TRUESIGHT,-1); - if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォーク */ - skill_status_change_end(bl,SC_WINDWALK,-1); - if(sc_data[SC_CARTBOOST].timer!=-1 ) /* カートブースト */ - skill_status_change_end(bl,SC_CARTBOOST,-1); - break; - case SC_FLAMELAUNCHER: /* フレームランチャー */ - skill_encchant_eremental_end(bl,SC_FLAMELAUNCHER); - break; - case SC_FROSTWEAPON: /* フロストウェポン */ - skill_encchant_eremental_end(bl,SC_FROSTWEAPON); - break; - case SC_LIGHTNINGLOADER: /* ライトニングローダー */ - skill_encchant_eremental_end(bl,SC_LIGHTNINGLOADER); - break; - case SC_SEISMICWEAPON: /* サイズミックウェポン */ - skill_encchant_eremental_end(bl,SC_SEISMICWEAPON); - break; - case SC_DEVOTION: /* ディボーション */ - calc_flag = 1; - break; - case SC_PROVIDENCE: /* プロヴィデンス */ - calc_flag = 1; - val2=val1*5; - break; - case SC_REFLECTSHIELD: - val2=10+val1*3; - break; - case SC_STRIPWEAPON: - case SC_STRIPSHIELD: - case SC_STRIPARMOR: - case SC_STRIPHELM: - case SC_CP_WEAPON: - case SC_CP_SHIELD: - case SC_CP_ARMOR: - case SC_CP_HELM: - break; + if (sc_data[SC_ASSUMPTIO].timer != -1) + skill_status_change_end (bl, SC_ASSUMPTIO, -1); + break; + case SC_MINDBREAKER: + calc_flag = 1; + if (tick <= 0) + tick = 1000; /* (オートバーサーク) */ + case SC_GLORIA: /* グロリア */ + calc_flag = 1; + break; + case SC_LOUD: /* ラウドボイス */ + calc_flag = 1; + break; + case SC_TRICKDEAD: /* 死んだふり */ + break; + case SC_QUAGMIRE: /* クァグマイア */ + calc_flag = 1; + if (sc_data[SC_CONCENTRATE].timer != -1) /* 集中力向上解除 */ + skill_status_change_end (bl, SC_CONCENTRATE, -1); + if (sc_data[SC_INCREASEAGI].timer != -1) /* 速度上昇解除 */ + skill_status_change_end (bl, SC_INCREASEAGI, -1); + if (sc_data[SC_TWOHANDQUICKEN].timer != -1) + skill_status_change_end (bl, SC_TWOHANDQUICKEN, -1); + if (sc_data[SC_SPEARSQUICKEN].timer != -1) + skill_status_change_end (bl, SC_SPEARSQUICKEN, -1); + if (sc_data[SC_ADRENALINE].timer != -1) + skill_status_change_end (bl, SC_ADRENALINE, -1); + if (sc_data[SC_LOUD].timer != -1) + skill_status_change_end (bl, SC_LOUD, -1); + if (sc_data[SC_TRUESIGHT].timer != -1) /* トゥルーサイト */ + skill_status_change_end (bl, SC_TRUESIGHT, -1); + if (sc_data[SC_WINDWALK].timer != -1) /* ウインドウォーク */ + skill_status_change_end (bl, SC_WINDWALK, -1); + if (sc_data[SC_CARTBOOST].timer != -1) /* カートブースト */ + skill_status_change_end (bl, SC_CARTBOOST, -1); + break; + case SC_FLAMELAUNCHER: /* フレームランチャー */ + skill_encchant_eremental_end (bl, SC_FLAMELAUNCHER); + break; + case SC_FROSTWEAPON: /* フロストウェポン */ + skill_encchant_eremental_end (bl, SC_FROSTWEAPON); + break; + case SC_LIGHTNINGLOADER: /* ライトニングローダー */ + skill_encchant_eremental_end (bl, SC_LIGHTNINGLOADER); + break; + case SC_SEISMICWEAPON: /* サイズミックウェポン */ + skill_encchant_eremental_end (bl, SC_SEISMICWEAPON); + break; + case SC_DEVOTION: /* ディボーション */ + calc_flag = 1; + break; + case SC_PROVIDENCE: /* プロヴィデンス */ + calc_flag = 1; + val2 = val1 * 5; + break; + case SC_REFLECTSHIELD: + val2 = 10 + val1 * 3; + break; + case SC_STRIPWEAPON: + case SC_STRIPSHIELD: + case SC_STRIPARMOR: + case SC_STRIPHELM: + case SC_CP_WEAPON: + case SC_CP_SHIELD: + case SC_CP_ARMOR: + case SC_CP_HELM: + break; - case SC_AUTOSPELL: /* オートスペル */ - val4 = 5 + val1*2; - break; + case SC_AUTOSPELL: /* オートスペル */ + val4 = 5 + val1 * 2; + break; - case SC_VOLCANO: - calc_flag = 1; - val3 = val1*10; - val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) ); - break; - case SC_DELUGE: - calc_flag = 1; - val3 = val1>=5?15: (val1==4?14: (val1==3?12: ( val1==2?9:5 ) ) ); - val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) ); - break; - case SC_VIOLENTGALE: - calc_flag = 1; - val3 = val1*3; - val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) ); - break; + case SC_VOLCANO: + calc_flag = 1; + val3 = val1 * 10; + val4 = + val1 >= 5 ? 20 : (val1 == + 4 ? 19 : (val1 == + 3 ? 17 : (val1 == 2 ? 14 : 10))); + break; + case SC_DELUGE: + calc_flag = 1; + val3 = + val1 >= 5 ? 15 : (val1 == + 4 ? 14 : (val1 == + 3 ? 12 : (val1 == 2 ? 9 : 5))); + val4 = + val1 >= 5 ? 20 : (val1 == + 4 ? 19 : (val1 == + 3 ? 17 : (val1 == 2 ? 14 : 10))); + break; + case SC_VIOLENTGALE: + calc_flag = 1; + val3 = val1 * 3; + val4 = + val1 >= 5 ? 20 : (val1 == + 4 ? 19 : (val1 == + 3 ? 17 : (val1 == 2 ? 14 : 10))); + break; - case SC_SPEARSQUICKEN: /* スピアクイッケン */ - calc_flag = 1; - val2 = 20+val1; - *opt3 |= 1; - break; - case SC_COMBO: - break; - case SC_BLADESTOP_WAIT: /* 白刃取り(待ち) */ - break; - case SC_BLADESTOP: /* 白刃取り */ - if(val2==2) clif_bladestop((struct block_list *)val3,(struct block_list *)val4,1); - *opt3 |= 32; - break; + case SC_SPEARSQUICKEN: /* スピアクイッケン */ + calc_flag = 1; + val2 = 20 + val1; + *opt3 |= 1; + break; + case SC_COMBO: + break; + case SC_BLADESTOP_WAIT: /* 白刃取り(待ち) */ + break; + case SC_BLADESTOP: /* 白刃取り */ + if (val2 == 2) + clif_bladestop ((struct block_list *) val3, + (struct block_list *) val4, 1); + *opt3 |= 32; + break; - case SC_LULLABY: /* 子守唄 */ - val2 = 11; - break; - case SC_RICHMANKIM: - break; - case SC_ETERNALCHAOS: /* エターナルカオス */ - calc_flag = 1; - break; - case SC_DRUMBATTLE: /* 戦太鼓の響き */ - calc_flag = 1; - val2 = (val1+1)*25; - val3 = (val1+1)*2; - break; - case SC_NIBELUNGEN: /* ニーベルングの指輪 */ - calc_flag = 1; - val2 = (val1+2)*50; - val3 = (val1+2)*25; - break; - case SC_ROKISWEIL: /* ロキの叫び */ - break; - case SC_INTOABYSS: /* 深淵の中に */ - break; - case SC_SIEGFRIED: /* 不死身のジークフリード */ - calc_flag = 1; - val2 = 40 + val1*5; - val3 = val1*10; - break; - case SC_DISSONANCE: /* 不協和音 */ - val2 = 10; - break; - case SC_WHISTLE: /* 口笛 */ - calc_flag = 1; - break; - case SC_ASSNCROS: /* 夕陽のアサシンクロス */ - calc_flag = 1; - break; - case SC_POEMBRAGI: /* ブラギの詩 */ - break; - case SC_APPLEIDUN: /* イドゥンの林檎 */ - calc_flag = 1; - break; - case SC_UGLYDANCE: /* 自分勝手なダンス */ - val2 = 10; - break; - case SC_HUMMING: /* ハミング */ - calc_flag = 1; - break; - case SC_DONTFORGETME: /* 私を忘れないで */ - calc_flag = 1; - if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* 速度上昇解除 */ - skill_status_change_end(bl,SC_INCREASEAGI,-1); - if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 ) - skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1); - if(sc_data[SC_SPEARSQUICKEN].timer!=-1 ) - skill_status_change_end(bl,SC_SPEARSQUICKEN,-1); - if(sc_data[SC_ADRENALINE].timer!=-1 ) - skill_status_change_end(bl,SC_ADRENALINE,-1); - if(sc_data[SC_ASSNCROS].timer!=-1 ) - skill_status_change_end(bl,SC_ASSNCROS,-1); - if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* トゥルーサイト */ - skill_status_change_end(bl,SC_TRUESIGHT,-1); - if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォーク */ - skill_status_change_end(bl,SC_WINDWALK,-1); - if(sc_data[SC_CARTBOOST].timer!=-1 ) /* カートブースト */ - skill_status_change_end(bl,SC_CARTBOOST,-1); - break; - case SC_FORTUNE: /* 幸運のキス */ - calc_flag = 1; - break; - case SC_SERVICE4U: /* サービスフォーユー */ - calc_flag = 1; - break; - case SC_DANCING: /* ダンス/演奏中 */ - calc_flag = 1; - val3= tick / 1000; - tick = 1000; - break; + case SC_LULLABY: /* 子守唄 */ + val2 = 11; + break; + case SC_RICHMANKIM: + break; + case SC_ETERNALCHAOS: /* エターナルカオス */ + calc_flag = 1; + break; + case SC_DRUMBATTLE: /* 戦太鼓の響き */ + calc_flag = 1; + val2 = (val1 + 1) * 25; + val3 = (val1 + 1) * 2; + break; + case SC_NIBELUNGEN: /* ニーベルングの指輪 */ + calc_flag = 1; + val2 = (val1 + 2) * 50; + val3 = (val1 + 2) * 25; + break; + case SC_ROKISWEIL: /* ロキの叫び */ + break; + case SC_INTOABYSS: /* 深淵の中に */ + break; + case SC_SIEGFRIED: /* 不死身のジークフリード */ + calc_flag = 1; + val2 = 40 + val1 * 5; + val3 = val1 * 10; + break; + case SC_DISSONANCE: /* 不協和音 */ + val2 = 10; + break; + case SC_WHISTLE: /* 口笛 */ + calc_flag = 1; + break; + case SC_ASSNCROS: /* 夕陽のアサシンクロス */ + calc_flag = 1; + break; + case SC_POEMBRAGI: /* ブラギの詩 */ + break; + case SC_APPLEIDUN: /* イドゥンの林檎 */ + calc_flag = 1; + break; + case SC_UGLYDANCE: /* 自分勝手なダンス */ + val2 = 10; + break; + case SC_HUMMING: /* ハミング */ + calc_flag = 1; + break; + case SC_DONTFORGETME: /* 私を忘れないで */ + calc_flag = 1; + if (sc_data[SC_INCREASEAGI].timer != -1) /* 速度上昇解除 */ + skill_status_change_end (bl, SC_INCREASEAGI, -1); + if (sc_data[SC_TWOHANDQUICKEN].timer != -1) + skill_status_change_end (bl, SC_TWOHANDQUICKEN, -1); + if (sc_data[SC_SPEARSQUICKEN].timer != -1) + skill_status_change_end (bl, SC_SPEARSQUICKEN, -1); + if (sc_data[SC_ADRENALINE].timer != -1) + skill_status_change_end (bl, SC_ADRENALINE, -1); + if (sc_data[SC_ASSNCROS].timer != -1) + skill_status_change_end (bl, SC_ASSNCROS, -1); + if (sc_data[SC_TRUESIGHT].timer != -1) /* トゥルーサイト */ + skill_status_change_end (bl, SC_TRUESIGHT, -1); + if (sc_data[SC_WINDWALK].timer != -1) /* ウインドウォーク */ + skill_status_change_end (bl, SC_WINDWALK, -1); + if (sc_data[SC_CARTBOOST].timer != -1) /* カートブースト */ + skill_status_change_end (bl, SC_CARTBOOST, -1); + break; + case SC_FORTUNE: /* 幸運のキス */ + calc_flag = 1; + break; + case SC_SERVICE4U: /* サービスフォーユー */ + calc_flag = 1; + break; + case SC_DANCING: /* ダンス/演奏中 */ + calc_flag = 1; + val3 = tick / 1000; + tick = 1000; + break; - case SC_EXPLOSIONSPIRITS: // 爆裂波動 - calc_flag = 1; - val2 = 75 + 25*val1; - *opt3 |= 8; - break; - case SC_STEELBODY: // 金剛 - calc_flag = 1; - *opt3 |= 16; - break; - case SC_EXTREMITYFIST: /* 阿修羅覇凰拳 */ - break; - case SC_AUTOCOUNTER: - val3 = val4 = 0; - break; + case SC_EXPLOSIONSPIRITS: // 爆裂波動 + calc_flag = 1; + val2 = 75 + 25 * val1; + *opt3 |= 8; + break; + case SC_STEELBODY: // 金剛 + calc_flag = 1; + *opt3 |= 16; + break; + case SC_EXTREMITYFIST: /* 阿修羅覇凰拳 */ + break; + case SC_AUTOCOUNTER: + val3 = val4 = 0; + break; - case SC_SPEEDPOTION0: /* 増速ポーション */ - *opt2 |= 0x20; - case SC_SPEEDPOTION1: - case SC_SPEEDPOTION2: - calc_flag = 1; - tick = 1000 * tick; -// val2 = 5*(2+type-SC_SPEEDPOTION0); - break; + case SC_SPEEDPOTION0: /* 増速ポーション */ + *opt2 |= 0x20; + case SC_SPEEDPOTION1: + case SC_SPEEDPOTION2: + calc_flag = 1; + tick = 1000 * tick; +// val2 = 5*(2+type-SC_SPEEDPOTION0); + break; - /* atk & matk potions [Valaris] */ - case SC_ATKPOT: - *opt2 |= 0x80; - case SC_MATKPOT: - calc_flag = 1; - tick = 1000 * tick; - break; - case SC_WEDDING: //結婚用(結婚衣裳になって歩くのが遅いとか) - { - time_t timer; - - calc_flag = 1; - tick = 10000; - if(!val2) - val2 = time(&timer); - } - break; - case SC_NOCHAT: //チャット禁止状態 - { - time_t timer; - - if(!battle_config.muting_players) - break; - - tick = 60000; - if(!val2) - val2 = time(&timer); - updateflag = SP_MANNER; - } - break; - case SC_SELFDESTRUCTION: //自爆 - clif_skillcasting(bl,bl->id, bl->id,0,0,331,skill_get_time(val2,val1)); - val3 = tick / 1000; - tick = 1000; - break; + /* atk & matk potions [Valaris] */ + case SC_ATKPOT: + *opt2 |= 0x80; + case SC_MATKPOT: + calc_flag = 1; + tick = 1000 * tick; + break; + case SC_WEDDING: //結婚用(結婚衣裳になって歩くのが遅いとか) + { + time_t timer; + + calc_flag = 1; + tick = 10000; + if (!val2) + val2 = time (&timer); + } + break; + case SC_NOCHAT: //チャット禁止状態 + { + time_t timer; - /* option1 */ - case SC_STONE: /* 石化 */ - if(!(flag&2)) { - int sc_def = battle_get_mdef(bl)*200; - tick = tick - sc_def; - } - val3 = tick/1000; - if(val3 < 1) val3 = 1; - tick = 5000; - val2 = 1; - break; - case SC_SLEEP: /* 睡眠 */ - if(!(flag&2)) { -// int sc_def = 100 - (battle_get_int(bl) + battle_get_luk(bl)/3); -// tick = tick * sc_def / 100; -// if(tick < 1000) tick = 1000; - tick = 30000;//睡眠はステータス耐性に関わらず30秒 - } - break; - case SC_FREEZE: /* 凍結 */ - if(!(flag&2)) { - int sc_def = 100 - battle_get_mdef(bl); - tick = tick * sc_def / 100; - } - break; - case SC_STAN: /* スタン(val2にミリ秒セット) */ - if(!(flag&2)) { - int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/3); - tick = tick * sc_def / 100; - } - break; + if (!battle_config.muting_players) + break; - /* option2 */ - case SC_POISON: /* 毒 */ - calc_flag = 1; - if(!(flag&2)) { - int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/5); - tick = tick * sc_def / 100; - } - val3 = tick/1000; - if(val3 < 1) val3 = 1; - tick = 1000; - break; - case SC_SILENCE: /* 沈黙(レックスデビーナ) */ - if(!(flag&2)) { - int sc_def = 100 - battle_get_vit(bl); - tick = tick * sc_def / 100; - } - break; - case SC_BLIND: /* 暗黒 */ - calc_flag = 1; - if(!(flag&2)) { - int sc_def = battle_get_lv(bl)/10 + battle_get_int(bl)/15; - tick = 30000 - sc_def; - } - break; - case SC_CURSE: - calc_flag = 1; - if(!(flag&2)) { - int sc_def = 100 - battle_get_vit(bl); - tick = tick * sc_def / 100; - } - break; + tick = 60000; + if (!val2) + val2 = time (&timer); + updateflag = SP_MANNER; + } + break; + case SC_SELFDESTRUCTION: //自爆 + clif_skillcasting (bl, bl->id, bl->id, 0, 0, 331, + skill_get_time (val2, val1)); + val3 = tick / 1000; + tick = 1000; + break; - /* option */ - case SC_HIDING: /* ハイディング */ - calc_flag = 1; - if(bl->type == BL_PC) { - val2 = tick / 1000; /* 持続時間 */ - tick = 1000; - } - break; - case SC_CHASEWALK: - case SC_CLOAKING: /* クローキング */ - if(bl->type == BL_PC) - val2 = tick; - else - tick = 5000*val1; - break; - case SC_SIGHT: /* サイト/ルアフ */ - case SC_RUWACH: - val2 = tick/250; - tick = 10; - break; + /* option1 */ + case SC_STONE: /* 石化 */ + if (!(flag & 2)) + { + int sc_def = battle_get_mdef (bl) * 200; + tick = tick - sc_def; + } + val3 = tick / 1000; + if (val3 < 1) + val3 = 1; + tick = 5000; + val2 = 1; + break; + case SC_SLEEP: /* 睡眠 */ + if (!(flag & 2)) + { +// int sc_def = 100 - (battle_get_int(bl) + battle_get_luk(bl)/3); +// tick = tick * sc_def / 100; +// if(tick < 1000) tick = 1000; + tick = 30000; //睡眠はステータス耐性に関わらず30秒 + } + break; + case SC_FREEZE: /* 凍結 */ + if (!(flag & 2)) + { + int sc_def = 100 - battle_get_mdef (bl); + tick = tick * sc_def / 100; + } + break; + case SC_STAN: /* スタン(val2にミリ秒セット) */ + if (!(flag & 2)) + { + int sc_def = + 100 - (battle_get_vit (bl) + battle_get_luk (bl) / 3); + tick = tick * sc_def / 100; + } + break; - /* セーフティウォール、ニューマ */ - case SC_SAFETYWALL: case SC_PNEUMA: - tick=((struct skill_unit *)val2)->group->limit; - break; + /* option2 */ + case SC_POISON: /* 毒 */ + calc_flag = 1; + if (!(flag & 2)) + { + int sc_def = + 100 - (battle_get_vit (bl) + battle_get_luk (bl) / 5); + tick = tick * sc_def / 100; + } + val3 = tick / 1000; + if (val3 < 1) + val3 = 1; + tick = 1000; + break; + case SC_SILENCE: /* 沈黙(レックスデビーナ) */ + if (!(flag & 2)) + { + int sc_def = 100 - battle_get_vit (bl); + tick = tick * sc_def / 100; + } + break; + case SC_BLIND: /* 暗黒 */ + calc_flag = 1; + if (!(flag & 2)) + { + int sc_def = + battle_get_lv (bl) / 10 + battle_get_int (bl) / 15; + tick = 30000 - sc_def; + } + break; + case SC_CURSE: + calc_flag = 1; + if (!(flag & 2)) + { + int sc_def = 100 - battle_get_vit (bl); + tick = tick * sc_def / 100; + } + break; - /* アンクル */ - case SC_ANKLE: - break; + /* option */ + case SC_HIDING: /* ハイディング */ + calc_flag = 1; + if (bl->type == BL_PC) + { + val2 = tick / 1000; /* 持続時間 */ + tick = 1000; + } + break; + case SC_CHASEWALK: + case SC_CLOAKING: /* クローキング */ + if (bl->type == BL_PC) + val2 = tick; + else + tick = 5000 * val1; + break; + case SC_SIGHT: /* サイト/ルアフ */ + case SC_RUWACH: + val2 = tick / 250; + tick = 10; + break; - /* ウォーターボール */ - case SC_WATERBALL: - tick=150; - if(val1>5) //レベルが5以上の場合は25発に制限(1発目はすでに打ってるので-1) - val3=5*5-1; - else - val3= (val1|1)*(val1|1)-1; - break; + /* セーフティウォール、ニューマ */ + case SC_SAFETYWALL: + case SC_PNEUMA: + tick = ((struct skill_unit *) val2)->group->limit; + break; - /* スキルじゃない/時間に関係しない */ - case SC_RIDING: - calc_flag = 1; - tick = 600*1000; - break; - case SC_FALCON: - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_BROKNWEAPON: - case SC_BROKNARMOR: - tick=600*1000; - break; + /* アンクル */ + case SC_ANKLE: + break; - case SC_AUTOGUARD: - { - int i,t; - for(i=val2=0;i<val1;i++) { - t = 5-(i>>1); - val2 += (t < 0)? 1:t; - } - } - break; + /* ウォーターボール */ + case SC_WATERBALL: + tick = 150; + if (val1 > 5) //レベルが5以上の場合は25発に制限(1発目はすでに打ってるので-1) + val3 = 5 * 5 - 1; + else + val3 = (val1 | 1) * (val1 | 1) - 1; + break; - case SC_DEFENDER: - calc_flag = 1; - val2 = 5 + val1*15; - break; + /* スキルじゃない/時間に関係しない */ + case SC_RIDING: + calc_flag = 1; + tick = 600 * 1000; + break; + case SC_FALCON: + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_BROKNWEAPON: + case SC_BROKNARMOR: + tick = 600 * 1000; + break; - case SC_KEEPING: - case SC_BARRIER: - case SC_HALLUCINATION: - break; - case SC_CONCENTRATION: /* コンセントレーション */ - *opt3 |= 1; - calc_flag = 1; - break; - case SC_TENSIONRELAX: /* テンションリラックス */ - calc_flag = 1; - if(bl->type == BL_PC) { - tick = 10000; - } - break; - case SC_AURABLADE: /* オーラブレード */ - case SC_PARRYING: /* パリイング */ -// case SC_ASSUMPTIO: /* */ - case SC_HEADCRUSH: /* ヘッドクラッシュ */ - case SC_JOINTBEAT: /* ジョイントビート */ -// case SC_MARIONETTE: /* マリオネットコントロール */ - - //とりあえず手抜き - break; + case SC_AUTOGUARD: + { + int i, t; + for (i = val2 = 0; i < val1; i++) + { + t = 5 - (i >> 1); + val2 += (t < 0) ? 1 : t; + } + } + break; -// -- moonsoul (for new upper class related skill status effects) + case SC_DEFENDER: + calc_flag = 1; + val2 = 5 + val1 * 15; + break; + + case SC_KEEPING: + case SC_BARRIER: + case SC_HALLUCINATION: + break; + case SC_CONCENTRATION: /* コンセントレーション */ + *opt3 |= 1; + calc_flag = 1; + break; + case SC_TENSIONRELAX: /* テンションリラックス */ + calc_flag = 1; + if (bl->type == BL_PC) + { + tick = 10000; + } + break; + case SC_AURABLADE: /* オーラブレード */ + case SC_PARRYING: /* パリイング */ +// case SC_ASSUMPTIO: /* */ + case SC_HEADCRUSH: /* ヘッドクラッシュ */ + case SC_JOINTBEAT: /* ジョイントビート */ +// case SC_MARIONETTE: /* マリオネットコントロール */ + + //とりあえず手抜き + break; + +// -- moonsoul (for new upper class related skill status effects) /* case SC_AURABLADE: val2 = val1*10; @@ -8849,185 +10667,196 @@ int skill_status_effect(struct block_list *bl, int type, int val1, int val2, int skill_status_change_end(bl,SC_KYRIE,-1); break; */ - case SC_WINDWALK: /* ウインドウォーク */ - calc_flag = 1; - val2 = (val1 / 2); //Flee上昇率 - break; - case SC_BERSERK: /* バーサーク */ - if(sd){ - sd->status.sp = 0; - clif_updatestatus(sd,SP_SP); - clif_status_change(bl,SC_INCREASEAGI,1); /* アイコン表示 */ - } - *opt3 |= 128; - tick = 1000; - calc_flag = 1; - break; - case SC_ASSUMPTIO: /* アスムプティオ */ - *opt3 |= 2048; - break; - case SC_MARIONETTE: /* マリオネットコントロール */ - *opt3 |= 1024; - break; - case SC_MELTDOWN: /* メルトダウン */ - case SC_CARTBOOST: /* カートブースト */ - case SC_TRUESIGHT: /* トゥルーサイト */ - case SC_SPIDERWEB: /* スパイダーウェッブ */ - case SC_MAGICPOWER: /* 魔法力増幅 */ - calc_flag = 1; - break; - case SC_REJECTSWORD: /* リジェクトソード */ - val2 = 3; //3回攻撃を跳ね返す - break; - case SC_MEMORIZE: /* メモライズ */ - val2 = 3; //3回詠唱を1/3にする - break; - case SC_GRAFFITI: /* グラフィティ */ - { - struct skill_unit_group *sg = skill_unitsetting(bl,RG_GRAFFITI,val1,val2,val3,0); - if(sg) - val4 = (int)sg; - } - break; - case SC_HASTE: - calc_flag = 1; - case SC_SPLASHER: /* ベナムスプラッシャー */ - case SC_PHYS_SHIELD: - case SC_MBARRIER: - case SC_HALT_REGENERATE: - case SC_HIDE: - break; - case SC_FLYING_BACKPACK: - updateflag = SP_WEIGHT; - break; - default: - if(battle_config.error_log) - printf("UnknownStatusChange [%d]\n", type); - return 0; - } - - if(bl->type==BL_PC && type<SC_SENDMAX) - clif_status_change(bl,type,1); /* アイコン表示 */ - - /* optionの変更 */ - switch(type){ - case SC_STONE: - case SC_FREEZE: - case SC_STAN: - case SC_SLEEP: - battle_stopattack(bl); /* 攻撃停止 */ - skill_stop_dancing(bl,0); /* 演奏/ダンスの中断 */ - { /* 同時に掛からないステータス異常を解除 */ - int i; - for(i = SC_STONE; i <= SC_SLEEP; i++){ - if(sc_data[i].timer != -1){ - (*sc_count)--; - delete_timer(sc_data[i].timer, skill_status_change_timer); - sc_data[i].timer = -1; - } - } - } - if(type == SC_STONE) - *opt1 = 6; - else - *opt1 = type - SC_STONE + 1; - opt_flag = 1; - break; - case SC_POISON: - if (sc_data[SC_SLOWPOISON].timer == -1) { - *opt2 |= 0x1; - opt_flag = 1; - } - break; - - case SC_CURSE: - case SC_SILENCE: - case SC_BLIND: - *opt2 |= 1<<(type-SC_POISON); - opt_flag = 1; - break; - case SC_SLOWPOISON: - *opt2 &= ~0x1; - *opt2 |= 0x200; - opt_flag = 1; - break; - case SC_SIGNUMCRUCIS: - *opt2 |= 0x40; - opt_flag = 1; - break; - case SC_HIDING: - case SC_CLOAKING: - battle_stopattack(bl); /* 攻撃停止 */ - *option |= ((type==SC_HIDING)?2:4); - opt_flag =1 ; - break; - case SC_CHASEWALK: - battle_stopattack(bl); /* 攻撃停止 */ - *option |= 16388; - opt_flag =1 ; - break; - case SC_SIGHT: - *option |= 1; - opt_flag = 1; - break; - case SC_RUWACH: - *option |= 8192; - opt_flag = 1; - break; - case SC_WEDDING: - *option |= 4096; - opt_flag = 1; - } + case SC_WINDWALK: /* ウインドウォーク */ + calc_flag = 1; + val2 = (val1 / 2); //Flee上昇率 + break; + case SC_BERSERK: /* バーサーク */ + if (sd) + { + sd->status.sp = 0; + clif_updatestatus (sd, SP_SP); + clif_status_change (bl, SC_INCREASEAGI, 1); /* アイコン表示 */ + } + *opt3 |= 128; + tick = 1000; + calc_flag = 1; + break; + case SC_ASSUMPTIO: /* アスムプティオ */ + *opt3 |= 2048; + break; + case SC_MARIONETTE: /* マリオネットコントロール */ + *opt3 |= 1024; + break; + case SC_MELTDOWN: /* メルトダウン */ + case SC_CARTBOOST: /* カートブースト */ + case SC_TRUESIGHT: /* トゥルーサイト */ + case SC_SPIDERWEB: /* スパイダーウェッブ */ + case SC_MAGICPOWER: /* 魔法力増幅 */ + calc_flag = 1; + break; + case SC_REJECTSWORD: /* リジェクトソード */ + val2 = 3; //3回攻撃を跳ね返す + break; + case SC_MEMORIZE: /* メモライズ */ + val2 = 3; //3回詠唱を1/3にする + break; + case SC_GRAFFITI: /* グラフィティ */ + { + struct skill_unit_group *sg = + skill_unitsetting (bl, RG_GRAFFITI, val1, val2, val3, 0); + if (sg) + val4 = (int) sg; + } + break; + case SC_HASTE: + calc_flag = 1; + case SC_SPLASHER: /* ベナムスプラッシャー */ + case SC_PHYS_SHIELD: + case SC_MBARRIER: + case SC_HALT_REGENERATE: + case SC_HIDE: + break; + case SC_FLYING_BACKPACK: + updateflag = SP_WEIGHT; + break; + default: + if (battle_config.error_log) + printf ("UnknownStatusChange [%d]\n", type); + return 0; + } + + if (bl->type == BL_PC && type < SC_SENDMAX) + clif_status_change (bl, type, 1); /* アイコン表示 */ + + /* optionの変更 */ + switch (type) + { + case SC_STONE: + case SC_FREEZE: + case SC_STAN: + case SC_SLEEP: + battle_stopattack (bl); /* 攻撃停止 */ + skill_stop_dancing (bl, 0); /* 演奏/ダンスの中断 */ + { /* 同時に掛からないステータス異常を解除 */ + int i; + for (i = SC_STONE; i <= SC_SLEEP; i++) + { + if (sc_data[i].timer != -1) + { + (*sc_count)--; + delete_timer (sc_data[i].timer, + skill_status_change_timer); + sc_data[i].timer = -1; + } + } + } + if (type == SC_STONE) + *opt1 = 6; + else + *opt1 = type - SC_STONE + 1; + opt_flag = 1; + break; + case SC_POISON: + if (sc_data[SC_SLOWPOISON].timer == -1) + { + *opt2 |= 0x1; + opt_flag = 1; + } + break; - if(opt_flag) /* optionの変更 */ - clif_changeoption(bl); + case SC_CURSE: + case SC_SILENCE: + case SC_BLIND: + *opt2 |= 1 << (type - SC_POISON); + opt_flag = 1; + break; + case SC_SLOWPOISON: + *opt2 &= ~0x1; + *opt2 |= 0x200; + opt_flag = 1; + break; + case SC_SIGNUMCRUCIS: + *opt2 |= 0x40; + opt_flag = 1; + break; + case SC_HIDING: + case SC_CLOAKING: + battle_stopattack (bl); /* 攻撃停止 */ + *option |= ((type == SC_HIDING) ? 2 : 4); + opt_flag = 1; + break; + case SC_CHASEWALK: + battle_stopattack (bl); /* 攻撃停止 */ + *option |= 16388; + opt_flag = 1; + break; + case SC_SIGHT: + *option |= 1; + opt_flag = 1; + break; + case SC_RUWACH: + *option |= 8192; + opt_flag = 1; + break; + case SC_WEDDING: + *option |= 4096; + opt_flag = 1; + } - (*sc_count)++; /* ステータス異常の数 */ + if (opt_flag) /* optionの変更 */ + clif_changeoption (bl); - sc_data[type].val1 = val1; - sc_data[type].val2 = val2; - sc_data[type].val3 = val3; - sc_data[type].val4 = val4; - if (sc_data[type].spell_invocation) // Supplant by newer spell - spell_effect_report_termination(sc_data[type].spell_invocation, bl->id, type, 1); + (*sc_count)++; /* ステータス異常の数 */ - sc_data[type].spell_invocation = spell_invocation; + sc_data[type].val1 = val1; + sc_data[type].val2 = val2; + sc_data[type].val3 = val3; + sc_data[type].val4 = val4; + if (sc_data[type].spell_invocation) // Supplant by newer spell + spell_effect_report_termination (sc_data[type].spell_invocation, + bl->id, type, 1); - /* タイマー設定 */ - sc_data[type].timer = add_timer( - gettick() + tick, skill_status_change_timer, bl->id, type); + sc_data[type].spell_invocation = spell_invocation; - if(bl->type==BL_PC && calc_flag) - pc_calcstatus(sd,0); /* ステータス再計算 */ + /* タイマー設定 */ + sc_data[type].timer = + add_timer (gettick () + tick, skill_status_change_timer, bl->id, + type); - if(bl->type==BL_PC && updateflag) - clif_updatestatus(sd,updateflag); /* ステータスをクライアントに送る */ + if (bl->type == BL_PC && calc_flag) + pc_calcstatus (sd, 0); /* ステータス再計算 */ + if (bl->type == BL_PC && updateflag) + clif_updatestatus (sd, updateflag); /* ステータスをクライアントに送る */ - return 0; + return 0; } + /*========================================== * ステータス異常全解除 *------------------------------------------ */ -int skill_status_change_clear(struct block_list *bl, int type) +int skill_status_change_clear (struct block_list *bl, int type) { - struct status_change* sc_data; - short *sc_count, *option, *opt1, *opt2, *opt3; - int i; - - nullpo_retr(0, bl); - nullpo_retr(0, sc_data = battle_get_sc_data(bl)); - nullpo_retr(0, sc_count = battle_get_sc_count(bl)); - nullpo_retr(0, option = battle_get_option(bl)); - nullpo_retr(0, opt1 = battle_get_opt1(bl)); - nullpo_retr(0, opt2 = battle_get_opt2(bl)); - nullpo_retr(0, opt3 = battle_get_opt3(bl)); - - if (*sc_count == 0) - return 0; - for(i = 0; i < MAX_STATUSCHANGE; i++){ - if(sc_data[i].timer != -1){ /* 異常があるならタイマーを削除する */ + struct status_change *sc_data; + short *sc_count, *option, *opt1, *opt2, *opt3; + int i; + + nullpo_retr (0, bl); + nullpo_retr (0, sc_data = battle_get_sc_data (bl)); + nullpo_retr (0, sc_count = battle_get_sc_count (bl)); + nullpo_retr (0, option = battle_get_option (bl)); + nullpo_retr (0, opt1 = battle_get_opt1 (bl)); + nullpo_retr (0, opt2 = battle_get_opt2 (bl)); + nullpo_retr (0, opt3 = battle_get_opt3 (bl)); + + if (*sc_count == 0) + return 0; + for (i = 0; i < MAX_STATUSCHANGE; i++) + { + if (sc_data[i].timer != -1) + { /* 異常があるならタイマーを削除する */ /* delete_timer(sc_data[i].timer, skill_status_change_timer); sc_data[i].timer = -1; @@ -9036,49 +10865,52 @@ int skill_status_change_clear(struct block_list *bl, int type) clif_status_change(bl, i, 0); */ - skill_status_change_end(bl, i, -1); - } - } - *sc_count = 0; - *opt1 = 0; - *opt2 = 0; - *opt3 = 0; - *option &= OPTION_MASK; + skill_status_change_end (bl, i, -1); + } + } + *sc_count = 0; + *opt1 = 0; + *opt2 = 0; + *opt3 = 0; + *option &= OPTION_MASK; - if (night_flag == 1 && type == BL_PC) // by [Yor] - *opt2 |= STATE_BLIND; + if (night_flag == 1 && type == BL_PC) // by [Yor] + *opt2 |= STATE_BLIND; - if(!type || type&2) - clif_changeoption(bl); + if (!type || type & 2) + clif_changeoption (bl); - return 0; + return 0; } /* クローキング検査(周りに移動不可能地帯があるか) */ -int skill_check_cloaking(struct block_list *bl) +int skill_check_cloaking (struct block_list *bl) { - struct map_session_data *sd=NULL; - static int dx[]={-1, 0, 1,-1, 1,-1, 0, 1}; - static int dy[]={-1,-1,-1, 0, 0, 1, 1, 1}; - int end=1,i; - - nullpo_retr(0, bl); - - if(pc_checkskill(sd,AS_CLOAKING)>2) - return 0; - if(bl->type == BL_PC && battle_config.pc_cloak_check_type&1) - return 0; - if(bl->type == BL_MOB && battle_config.monster_cloak_check_type&1) - return 0; - for(i=0;i<sizeof(dx)/sizeof(dx[0]);i++){ - int c=map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i]); - if(c==1 || c==5) end=0; - } - if(end){ - skill_status_change_end(bl, SC_CLOAKING, -1); - *battle_get_option(bl)&=~4; /* 念のための処理 */ - } - return end; + struct map_session_data *sd = NULL; + static int dx[] = { -1, 0, 1, -1, 1, -1, 0, 1 }; + static int dy[] = { -1, -1, -1, 0, 0, 1, 1, 1 }; + int end = 1, i; + + nullpo_retr (0, bl); + + if (pc_checkskill (sd, AS_CLOAKING) > 2) + return 0; + if (bl->type == BL_PC && battle_config.pc_cloak_check_type & 1) + return 0; + if (bl->type == BL_MOB && battle_config.monster_cloak_check_type & 1) + return 0; + for (i = 0; i < sizeof (dx) / sizeof (dx[0]); i++) + { + int c = map_getcell (bl->m, bl->x + dx[i], bl->y + dy[i]); + if (c == 1 || c == 5) + end = 0; + } + if (end) + { + skill_status_change_end (bl, SC_CLOAKING, -1); + *battle_get_option (bl) &= ~4; /* 念のための処理 */ + } + return end; } /* @@ -9093,40 +10925,41 @@ int skill_check_cloaking(struct block_list *bl) * 戻り ダンスじゃない=0 合奏=2 それ以外のダンス=1 *------------------------------------------ */ -int skill_is_danceskill(int id) +int skill_is_danceskill (int id) { - int i; - switch(id){ - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジークフリード */ - case BD_RAGNAROK: /* 神々の黄昏 */ - case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ - i=2; - break; - case BA_DISSONANCE: /* 不協和音 */ - case BA_FROSTJOKE: /* 寒いジョーク */ - case BA_WHISTLE: /* 口笛 */ - case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ - case BA_POEMBRAGI: /* ブラギの詩 */ - case BA_APPLEIDUN: /* イドゥンの林檎 */ - case DC_UGLYDANCE: /* 自分勝手なダンス */ - case DC_SCREAM: /* スクリーム */ - case DC_HUMMING: /* ハミング */ - case DC_DONTFORGETME: /* 私を忘れないで… */ - case DC_FORTUNEKISS: /* 幸運のキス */ - case DC_SERVICEFORYOU: /* サービスフォーユー */ - i=1; - break; - default: - i=0; - } - return i; + int i; + switch (id) + { + case BD_LULLABY: /* 子守歌 */ + case BD_RICHMANKIM: /* ニヨルドの宴 */ + case BD_ETERNALCHAOS: /* 永遠の混沌 */ + case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ + case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ + case BD_ROKISWEIL: /* ロキの叫び */ + case BD_INTOABYSS: /* 深淵の中に */ + case BD_SIEGFRIED: /* 不死身のジークフリード */ + case BD_RAGNAROK: /* 神々の黄昏 */ + case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ + i = 2; + break; + case BA_DISSONANCE: /* 不協和音 */ + case BA_FROSTJOKE: /* 寒いジョーク */ + case BA_WHISTLE: /* 口笛 */ + case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ + case BA_POEMBRAGI: /* ブラギの詩 */ + case BA_APPLEIDUN: /* イドゥンの林檎 */ + case DC_UGLYDANCE: /* 自分勝手なダンス */ + case DC_SCREAM: /* スクリーム */ + case DC_HUMMING: /* ハミング */ + case DC_DONTFORGETME: /* 私を忘れないで… */ + case DC_FORTUNEKISS: /* 幸運のキス */ + case DC_SERVICEFORYOU: /* サービスフォーユー */ + i = 1; + break; + default: + i = 0; + } + return i; } /*========================================== @@ -9135,631 +10968,688 @@ int skill_is_danceskill(int id) * *------------------------------------------ */ -void skill_stop_dancing(struct block_list *src, int flag) +void skill_stop_dancing (struct block_list *src, int flag) { - struct status_change* sc_data; - struct skill_unit_group* group; - - nullpo_retv(src); - - sc_data=battle_get_sc_data(src); - if(sc_data && sc_data[SC_DANCING].timer==-1) - return; - group=(struct skill_unit_group *)sc_data[SC_DANCING].val2; //ダンスのスキルユニットIDはval2に入ってる - if(group && src->type==BL_PC && sc_data && sc_data[SC_DANCING].val4){ //合奏中断 - struct map_session_data* dsd=map_id2sd(sc_data[SC_DANCING].val4); //相方のsd取得 - if(flag){ //ログアウトなど片方が落ちても演奏が継続される - if(dsd && src->id == group->src_id){ //グループを持ってるPCが落ちる - group->src_id=sc_data[SC_DANCING].val4; //相方にグループを任せる - if(flag&1) //ログアウト - dsd->sc_data[SC_DANCING].val4=0; //相方の相方を0にして合奏終了→通常のダンス状態 - if(flag&2) //ハエ飛びなど - return; //合奏もダンス状態も終了させない&スキルユニットは置いてけぼり - }else if(dsd && dsd->bl.id == group->src_id){ //相方がグループを持っているPCが落ちる(自分はグループを持っていない) - if(flag&1) //ログアウト - dsd->sc_data[SC_DANCING].val4=0; //相方の相方を0にして合奏終了→通常のダンス状態 - if(flag&2) //ハエ飛びなど - return; //合奏もダンス状態も終了させない&スキルユニットは置いてけぼり - } - skill_status_change_end(src,SC_DANCING,-1);//自分のステータスを終了させる - //そしてグループは消さない&消さないのでステータス計算もいらない? - return; - }else{ - if(dsd && src->id == group->src_id){ //グループを持ってるPCが止める - skill_status_change_end((struct block_list *)dsd,SC_DANCING,-1);//相手のステータスを終了させる - } - if(dsd && dsd->bl.id == group->src_id){ //相方がグループを持っているPCが止める(自分はグループを持っていない) - skill_status_change_end(src,SC_DANCING,-1);//自分のステータスを終了させる - } - } - } - if(flag&2 && group && src->type==BL_PC){ //ハエで飛んだときとかはユニットも飛ぶ - struct map_session_data *sd = (struct map_session_data *)src; - skill_unit_move_unit_group(group, sd->bl.m,(sd->to_x - sd->bl.x),(sd->to_y - sd->bl.y)); - return; - } - skill_delunitgroup(group); - if(src->type==BL_PC) - pc_calcstatus((struct map_session_data *)src,0); + struct status_change *sc_data; + struct skill_unit_group *group; + + nullpo_retv (src); + + sc_data = battle_get_sc_data (src); + if (sc_data && sc_data[SC_DANCING].timer == -1) + return; + group = (struct skill_unit_group *) sc_data[SC_DANCING].val2; //ダンスのスキルユニットIDはval2に入ってる + if (group && src->type == BL_PC && sc_data && sc_data[SC_DANCING].val4) + { //合奏中断 + struct map_session_data *dsd = map_id2sd (sc_data[SC_DANCING].val4); //相方のsd取得 + if (flag) + { //ログアウトなど片方が落ちても演奏が継続される + if (dsd && src->id == group->src_id) + { //グループを持ってるPCが落ちる + group->src_id = sc_data[SC_DANCING].val4; //相方にグループを任せる + if (flag & 1) //ログアウト + dsd->sc_data[SC_DANCING].val4 = 0; //相方の相方を0にして合奏終了→通常のダンス状態 + if (flag & 2) //ハエ飛びなど + return; //合奏もダンス状態も終了させない&スキルユニットは置いてけぼり + } + else if (dsd && dsd->bl.id == group->src_id) + { //相方がグループを持っているPCが落ちる(自分はグループを持っていない) + if (flag & 1) //ログアウト + dsd->sc_data[SC_DANCING].val4 = 0; //相方の相方を0にして合奏終了→通常のダンス状態 + if (flag & 2) //ハエ飛びなど + return; //合奏もダンス状態も終了させない&スキルユニットは置いてけぼり + } + skill_status_change_end (src, SC_DANCING, -1); //自分のステータスを終了させる + //そしてグループは消さない&消さないのでステータス計算もいらない? + return; + } + else + { + if (dsd && src->id == group->src_id) + { //グループを持ってるPCが止める + skill_status_change_end ((struct block_list *) dsd, SC_DANCING, -1); //相手のステータスを終了させる + } + if (dsd && dsd->bl.id == group->src_id) + { //相方がグループを持っているPCが止める(自分はグループを持っていない) + skill_status_change_end (src, SC_DANCING, -1); //自分のステータスを終了させる + } + } + } + if (flag & 2 && group && src->type == BL_PC) + { //ハエで飛んだときとかはユニットも飛ぶ + struct map_session_data *sd = (struct map_session_data *) src; + skill_unit_move_unit_group (group, sd->bl.m, (sd->to_x - sd->bl.x), + (sd->to_y - sd->bl.y)); + return; + } + skill_delunitgroup (group); + if (src->type == BL_PC) + pc_calcstatus ((struct map_session_data *) src, 0); } /*========================================== * スキルユニット初期化 *------------------------------------------ */ -struct skill_unit *skill_initunit(struct skill_unit_group *group,int idx,int x,int y) +struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, + int x, int y) { - struct skill_unit *unit; - - nullpo_retr(NULL, group); - nullpo_retr(NULL, unit=&group->unit[idx]); - - if(!unit->alive) - group->alive_count++; - - unit->bl.id=map_addobject(&unit->bl); - unit->bl.type=BL_SKILL; - unit->bl.m=group->map; - unit->bl.x=x; - unit->bl.y=y; - unit->group=group; - unit->val1=unit->val2=0; - unit->alive=1; - - map_addblock(&unit->bl); - clif_skill_setunit(unit); - return unit; + struct skill_unit *unit; + + nullpo_retr (NULL, group); + nullpo_retr (NULL, unit = &group->unit[idx]); + + if (!unit->alive) + group->alive_count++; + + unit->bl.id = map_addobject (&unit->bl); + unit->bl.type = BL_SKILL; + unit->bl.m = group->map; + unit->bl.x = x; + unit->bl.y = y; + unit->group = group; + unit->val1 = unit->val2 = 0; + unit->alive = 1; + + map_addblock (&unit->bl); + clif_skill_setunit (unit); + return unit; } -int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap ); +int skill_unit_timer_sub_ondelete (struct block_list *bl, va_list ap); /*========================================== * スキルユニット削除 *------------------------------------------ */ -int skill_delunit(struct skill_unit *unit) +int skill_delunit (struct skill_unit *unit) { - struct skill_unit_group *group; - int range; + struct skill_unit_group *group; + int range; - nullpo_retr(0, unit); - if(!unit->alive) - return 0; - nullpo_retr(0, group=unit->group); + nullpo_retr (0, unit); + if (!unit->alive) + return 0; + nullpo_retr (0, group = unit->group); - /* onlimitイベント呼び出し */ - skill_unit_onlimit( unit,gettick() ); + /* onlimitイベント呼び出し */ + skill_unit_onlimit (unit, gettick ()); - /* ondeleteイベント呼び出し */ - range=group->range; - map_foreachinarea( skill_unit_timer_sub_ondelete, unit->bl.m, - unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0, - &unit->bl,gettick() ); + /* ondeleteイベント呼び出し */ + range = group->range; + map_foreachinarea (skill_unit_timer_sub_ondelete, unit->bl.m, + unit->bl.x - range, unit->bl.y - range, + unit->bl.x + range, unit->bl.y + range, 0, &unit->bl, + gettick ()); - clif_skill_delunit(unit); + clif_skill_delunit (unit); - unit->group=NULL; - unit->alive=0; - map_delobjectnofree(unit->bl.id, BL_SKILL); - if(group->alive_count>0 && (--group->alive_count)<=0) - skill_delunitgroup(group); + unit->group = NULL; + unit->alive = 0; + map_delobjectnofree (unit->bl.id, BL_SKILL); + if (group->alive_count > 0 && (--group->alive_count) <= 0) + skill_delunitgroup (group); - return 0; + return 0; } + /*========================================== * スキルユニットグループ初期化 *------------------------------------------ */ -static int skill_unit_group_newid=10; -struct skill_unit_group *skill_initunitgroup(struct block_list *src, - int count,int skillid,int skilllv,int unit_id) +static int skill_unit_group_newid = 10; +struct skill_unit_group *skill_initunitgroup (struct block_list *src, + int count, int skillid, + int skilllv, int unit_id) { - int i; - struct skill_unit_group *group=NULL, *list=NULL; - int maxsug=0; - - 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; - } - if(list){ - for(i=0;i<maxsug;i++) /* 空いているもの検索 */ - if(list[i].group_id==0){ - group=&list[i]; - break; - } - - if(group==NULL){ /* 空いてないので古いもの検索 */ - int j=0; - unsigned maxdiff=0,x,tick=gettick(); - for(i=0;i<maxsug;i++) - if((x=DIFF_TICK(tick,list[i].tick))>maxdiff){ - maxdiff=x; - j=i; - } - skill_delunitgroup(&list[j]); - group=&list[j]; - } - } - - if(group==NULL){ - printf("skill_initunitgroup: error unit group !\n"); - exit(1); - } - - group->src_id=src->id; - group->party_id=battle_get_party_id(src); - group->guild_id=battle_get_guild_id(src); - group->group_id=skill_unit_group_newid++; - if(skill_unit_group_newid<=0) - skill_unit_group_newid=10; - group->unit=(struct skill_unit *)aCalloc(count,sizeof(struct skill_unit)); - group->unit_count=count; - group->val1=group->val2=0; - group->skill_id=skillid; - group->skill_lv=skilllv; - group->unit_id=unit_id; - group->map=src->m; - group->range=0; - group->limit=10000; - group->interval=1000; - group->tick=gettick(); - group->valstr=NULL; - - if( skill_is_danceskill(skillid) ){ - struct map_session_data *sd = NULL; - if(src->type==BL_PC && (sd=(struct map_session_data *)src) ){ - sd->skillid_dance=skillid; - sd->skilllv_dance=skilllv; - } - skill_status_change_start(src,SC_DANCING,skillid,(int)group,0,0,skill_get_time(skillid,skilllv)+1000,0); - switch(skillid){ //合奏スキルは相方をダンス状態にする - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジークフリード */ - case BD_RAGNAROK: /* 神々の黄昏 */ - case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ - { - int range=1; - int c=0; - if(sd){ - map_foreachinarea(skill_check_condition_use_sub,sd->bl.m, - sd->bl.x-range,sd->bl.y-range, - sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c); - } - } - } - } - return group; + int i; + struct skill_unit_group *group = NULL, *list = NULL; + int maxsug = 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; + } + if (list) + { + for (i = 0; i < maxsug; i++) /* 空いているもの検索 */ + if (list[i].group_id == 0) + { + group = &list[i]; + break; + } + + if (group == NULL) + { /* 空いてないので古いもの検索 */ + int j = 0; + unsigned maxdiff = 0, x, tick = gettick (); + for (i = 0; i < maxsug; i++) + if ((x = DIFF_TICK (tick, list[i].tick)) > maxdiff) + { + maxdiff = x; + j = i; + } + skill_delunitgroup (&list[j]); + group = &list[j]; + } + } + + if (group == NULL) + { + printf ("skill_initunitgroup: error unit group !\n"); + exit (1); + } + + group->src_id = src->id; + group->party_id = battle_get_party_id (src); + group->guild_id = battle_get_guild_id (src); + group->group_id = skill_unit_group_newid++; + if (skill_unit_group_newid <= 0) + skill_unit_group_newid = 10; + group->unit = + (struct skill_unit *) aCalloc (count, sizeof (struct skill_unit)); + group->unit_count = count; + group->val1 = group->val2 = 0; + group->skill_id = skillid; + group->skill_lv = skilllv; + group->unit_id = unit_id; + group->map = src->m; + group->range = 0; + group->limit = 10000; + group->interval = 1000; + group->tick = gettick (); + group->valstr = NULL; + + if (skill_is_danceskill (skillid)) + { + struct map_session_data *sd = NULL; + if (src->type == BL_PC && (sd = (struct map_session_data *) src)) + { + sd->skillid_dance = skillid; + sd->skilllv_dance = skilllv; + } + skill_status_change_start (src, SC_DANCING, skillid, (int) group, 0, + 0, skill_get_time (skillid, + skilllv) + 1000, 0); + switch (skillid) + { //合奏スキルは相方をダンス状態にする + case BD_LULLABY: /* 子守歌 */ + case BD_RICHMANKIM: /* ニヨルドの宴 */ + case BD_ETERNALCHAOS: /* 永遠の混沌 */ + case BD_DRUMBATTLEFIELD: /* 戦太鼓の響き */ + case BD_RINGNIBELUNGEN: /* ニーベルングの指輪 */ + case BD_ROKISWEIL: /* ロキの叫び */ + case BD_INTOABYSS: /* 深淵の中に */ + case BD_SIEGFRIED: /* 不死身のジークフリード */ + case BD_RAGNAROK: /* 神々の黄昏 */ + case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ + { + int range = 1; + int c = 0; + if (sd) + { + map_foreachinarea (skill_check_condition_use_sub, + sd->bl.m, sd->bl.x - range, + sd->bl.y - range, sd->bl.x + range, + sd->bl.y + range, BL_PC, &sd->bl, &c); + } + } + } + } + return group; } /*========================================== * スキルユニットグループ削除 *------------------------------------------ */ -int skill_delunitgroup(struct skill_unit_group *group) +int skill_delunitgroup (struct skill_unit_group *group) { - struct block_list *src; - int i; - - nullpo_retr(0, group); - if(group->unit_count<=0) - return 0; - - src=map_id2bl(group->src_id); - if( skill_is_danceskill(group->skill_id) ){ //ダンススキルはダンス状態を解除する - if(src) - skill_status_change_end(src,SC_DANCING,-1); - } + struct block_list *src; + int i; - 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; - } + nullpo_retr (0, group); + if (group->unit_count <= 0) + return 0; - map_freeblock(group->unit); /* free()の替わり */ - group->unit=NULL; - group->src_id=0; - group->group_id=0; - group->unit_count=0; - return 0; + src = map_id2bl (group->src_id); + if (skill_is_danceskill (group->skill_id)) + { //ダンススキルはダンス状態を解除する + if (src) + skill_status_change_end (src, SC_DANCING, -1); + } + + group->alive_count = 0; + if (group->unit != NULL) + { + for (i = 0; i < group->unit_count; i++) + if (group->unit[i].alive) + skill_delunit (&group->unit[i]); + } + if (group->valstr != NULL) + { + map_freeblock (group->valstr); + group->valstr = NULL; + } + + map_freeblock (group->unit); /* free()の替わり */ + group->unit = NULL; + group->src_id = 0; + group->group_id = 0; + group->unit_count = 0; + return 0; } /*========================================== * スキルユニットグループ全削除 *------------------------------------------ */ -int skill_clear_unitgroup(struct block_list *src) +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; - } - 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; + 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; + } + 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; } /*========================================== * スキルユニットグループの被影響tick検索 *------------------------------------------ */ -struct skill_unit_group_tickset *skill_unitgrouptickset_search( - struct block_list *bl,int group_id) +struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct + block_list + *bl, + int group_id) { - int i,j=0,k,s=group_id%MAX_SKILLUNITGROUPTICKSET; - struct skill_unit_group_tickset *set=NULL; - - nullpo_retr(0, bl); - - if(bl->type==BL_PC){ - set=((struct map_session_data *)bl)->skillunittick; - }else{ - set=((struct mob_data *)bl)->skillunittick; - } - if(set==NULL) - return 0; - for(i=0;i<MAX_SKILLUNITGROUPTICKSET;i++) - if( set[(k=(i+s)%MAX_SKILLUNITGROUPTICKSET)].group_id == group_id ) - return &set[k]; - else if( set[k].group_id==0 ) - j=k; - - return &set[j]; + int i, j = 0, k, s = group_id % MAX_SKILLUNITGROUPTICKSET; + struct skill_unit_group_tickset *set = NULL; + + nullpo_retr (0, bl); + + if (bl->type == BL_PC) + { + set = ((struct map_session_data *) bl)->skillunittick; + } + else + { + set = ((struct mob_data *) bl)->skillunittick; + } + if (set == NULL) + return 0; + for (i = 0; i < MAX_SKILLUNITGROUPTICKSET; i++) + if (set[(k = (i + s) % MAX_SKILLUNITGROUPTICKSET)].group_id == + group_id) + return &set[k]; + else if (set[k].group_id == 0) + j = k; + + return &set[j]; } /*========================================== * スキルユニットグループの被影響tick削除 *------------------------------------------ */ -int skill_unitgrouptickset_delete(struct block_list *bl,int group_id) +int skill_unitgrouptickset_delete (struct block_list *bl, int group_id) { - int i,s=group_id%MAX_SKILLUNITGROUPTICKSET; - struct skill_unit_group_tickset *set=NULL,*ts; - - nullpo_retr(0, bl); - - if(bl->type==BL_PC){ - set=((struct map_session_data *)bl)->skillunittick; - }else{ - set=((struct mob_data *)bl)->skillunittick; - } - - if(set!=NULL){ - - for(i=0;i<MAX_SKILLUNITGROUPTICKSET;i++) - if( (ts=&set[(i+s)%MAX_SKILLUNITGROUPTICKSET])->group_id == group_id ) - ts->group_id=0; - - } - return 0; + int i, s = group_id % MAX_SKILLUNITGROUPTICKSET; + struct skill_unit_group_tickset *set = NULL, *ts; + + nullpo_retr (0, bl); + + if (bl->type == BL_PC) + { + set = ((struct map_session_data *) bl)->skillunittick; + } + else + { + set = ((struct mob_data *) bl)->skillunittick; + } + + if (set != NULL) + { + + for (i = 0; i < MAX_SKILLUNITGROUPTICKSET; i++) + if ((ts = + &set[(i + s) % MAX_SKILLUNITGROUPTICKSET])->group_id == + group_id) + ts->group_id = 0; + + } + return 0; } /*========================================== * スキルユニットタイマー発動処理用(foreachinarea) *------------------------------------------ */ -int skill_unit_timer_sub_onplace( struct block_list *bl, va_list ap ) +int skill_unit_timer_sub_onplace (struct block_list *bl, va_list ap) { - struct block_list *src; - struct skill_unit *su; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - src=va_arg(ap,struct block_list*); - - tick=va_arg(ap,unsigned int); - su = (struct skill_unit *)src; - - if( su && su->alive ) { - struct skill_unit_group *sg; - sg = su->group; - if(sg && battle_check_target(src,bl,sg->target_flag )>0) - skill_unit_onplace( su, bl, tick ); - } - return 0; + struct block_list *src; + struct skill_unit *su; + unsigned int tick; + + nullpo_retr (0, bl); + nullpo_retr (0, ap); + src = va_arg (ap, struct block_list *); + + tick = va_arg (ap, unsigned int); + su = (struct skill_unit *) src; + + if (su && su->alive) + { + struct skill_unit_group *sg; + sg = su->group; + if (sg && battle_check_target (src, bl, sg->target_flag) > 0) + skill_unit_onplace (su, bl, tick); + } + return 0; } /*========================================== * スキルユニットタイマー削除処理用(foreachinarea) *------------------------------------------ */ -int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap ) +int skill_unit_timer_sub_ondelete (struct block_list *bl, va_list ap) { - struct block_list *src; - struct skill_unit *su; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - src=va_arg(ap,struct block_list*); - - tick=va_arg(ap,unsigned int); - su = (struct skill_unit *)src; - - if( su && su->alive ){ - struct skill_unit_group *sg; - sg = su->group; - if( sg && battle_check_target(src,bl,sg->target_flag )>0 ) - skill_unit_ondelete( su, bl, tick ); - } - return 0; + struct block_list *src; + struct skill_unit *su; + unsigned int tick; + + nullpo_retr (0, bl); + nullpo_retr (0, ap); + src = va_arg (ap, struct block_list *); + + tick = va_arg (ap, unsigned int); + su = (struct skill_unit *) src; + + if (su && su->alive) + { + struct skill_unit_group *sg; + sg = su->group; + if (sg && battle_check_target (src, bl, sg->target_flag) > 0) + skill_unit_ondelete (su, bl, tick); + } + return 0; } /*========================================== * スキルユニットタイマー処理用(foreachobject) *------------------------------------------ */ -int skill_unit_timer_sub( struct block_list *bl, va_list ap ) +int skill_unit_timer_sub (struct block_list *bl, va_list ap) { - struct skill_unit *unit; - struct skill_unit_group *group; - int range; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, group=unit->group); - tick=va_arg(ap,unsigned int); - - if(!unit->alive) - return 0; - - range=(unit->range!=0)?unit->range:group->range; - - /* onplaceイベント呼び出し */ - if(unit->alive && unit->range>=0){ - map_foreachinarea( skill_unit_timer_sub_onplace, bl->m, - bl->x-range,bl->y-range,bl->x+range,bl->y+range,0, - bl,tick); - if(group->unit_id == 0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val2){ - map_foreachinarea( skill_idun_heal, bl->m, - bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,unit); - group->val2++; - } - } - /* 時間切れ削除 */ - if(unit->alive && - (DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit) ){ - switch(group->unit_id){ - - - - - + struct skill_unit *unit; + struct skill_unit_group *group; + int range; + unsigned int tick; + + nullpo_retr (0, bl); + nullpo_retr (0, ap); + nullpo_retr (0, unit = (struct skill_unit *) bl); + nullpo_retr (0, group = unit->group); + tick = va_arg (ap, unsigned int); + + if (!unit->alive) + return 0; - case 0x8f: /* ブラストマイン */ - 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: /* スキッドトラップ */ - case 0x91: /* アンクルスネア */ - case 0x93: /* ランドマイン */ - case 0x94: /* ショックウェーブトラップ */ - case 0x95: /* サンドマン */ - case 0x96: /* フラッシャー */ - case 0x97: /* フリージングトラップ */ - case 0x98: /* クレイモアートラップ */ - case 0x99: /* トーキーボックス */ - { - struct block_list *src=map_id2bl(group->src_id); - if(group->unit_id == 0x91 && group->val2); - else{ - if(src && src->type==BL_PC){ - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid=1065; - item_tmp.identify=1; - map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,NULL,NULL,NULL,0); // 罠返還 - } - } - } - default: - skill_delunit(unit); - } - } + range = (unit->range != 0) ? unit->range : group->range; + + /* onplaceイベント呼び出し */ + if (unit->alive && unit->range >= 0) + { + map_foreachinarea (skill_unit_timer_sub_onplace, bl->m, + bl->x - range, bl->y - range, bl->x + range, + bl->y + range, 0, bl, tick); + if (group->unit_id == 0xaa + && DIFF_TICK (tick, group->tick) >= 6000 * group->val2) + { + map_foreachinarea (skill_idun_heal, bl->m, + bl->x - range, bl->y - range, bl->x + range, + bl->y + range, 0, unit); + group->val2++; + } + } + /* 時間切れ削除 */ + if (unit->alive && + (DIFF_TICK (tick, group->tick) >= group->limit + || DIFF_TICK (tick, group->tick) >= unit->limit)) + { + switch (group->unit_id) + { + + case 0x8f: /* ブラストマイン */ + 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: /* スキッドトラップ */ + case 0x91: /* アンクルスネア */ + case 0x93: /* ランドマイン */ + case 0x94: /* ショックウェーブトラップ */ + case 0x95: /* サンドマン */ + case 0x96: /* フラッシャー */ + case 0x97: /* フリージングトラップ */ + case 0x98: /* クレイモアートラップ */ + case 0x99: /* トーキーボックス */ + { + struct block_list *src = map_id2bl (group->src_id); + if (group->unit_id == 0x91 && group->val2); + else + { + if (src && src->type == BL_PC) + { + struct item item_tmp; + memset (&item_tmp, 0, sizeof (item_tmp)); + item_tmp.nameid = 1065; + item_tmp.identify = 1; + map_addflooritem (&item_tmp, 1, bl->m, bl->x, bl->y, NULL, NULL, NULL, 0); // 罠返還 + } + } + } + default: + skill_delunit (unit); + } + } - if(group->unit_id == 0x8d) { - unit->val1 -= 5; - if(unit->val1 <= 0 && unit->limit + group->tick > tick + 700) - unit->limit = DIFF_TICK(tick+700,group->tick); - } + 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; + return 0; } + /*========================================== * スキルユニットタイマー処理 *------------------------------------------ */ -int skill_unit_timer( int tid,unsigned int tick,int id,int data) +int skill_unit_timer (int tid, unsigned int tick, int id, int data) { - map_freeblock_lock(); + map_freeblock_lock (); - map_foreachobject( skill_unit_timer_sub, BL_SKILL, tick ); + map_foreachobject (skill_unit_timer_sub, BL_SKILL, tick); - map_freeblock_unlock(); + map_freeblock_unlock (); - return 0; + return 0; } /*========================================== * スキルユニット移動時処理用(foreachinarea) *------------------------------------------ */ -int skill_unit_out_all_sub( struct block_list *bl, va_list ap ) +int skill_unit_out_all_sub (struct block_list *bl, va_list ap) { - struct skill_unit *unit; - struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; + struct skill_unit *unit; + struct skill_unit_group *group; + struct block_list *src; + int range; + unsigned int tick; - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, group=unit->group); + nullpo_retr (0, bl); + nullpo_retr (0, ap); + nullpo_retr (0, src = va_arg (ap, struct block_list *)); + nullpo_retr (0, unit = (struct skill_unit *) bl); + nullpo_retr (0, group = unit->group); - tick=va_arg(ap,unsigned int); + tick = va_arg (ap, unsigned int); - if(!unit->alive || src->prev==NULL) - return 0; + if (!unit->alive || src->prev == NULL) + return 0; - range=(unit->range!=0)?unit->range:group->range; + range = (unit->range != 0) ? unit->range : group->range; - if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 ) - return 0; + if (range < 0 || battle_check_target (bl, src, group->target_flag) <= 0) + return 0; - if( src->x >= bl->x-range && src->x <= bl->x+range && - src->y >= bl->y-range && src->y <= bl->y+range ) - skill_unit_onout( unit, src, tick ); + if (src->x >= bl->x - range && src->x <= bl->x + range && + src->y >= bl->y - range && src->y <= bl->y + range) + skill_unit_onout (unit, src, tick); - return 0; + return 0; } - /*========================================== * スキルユニット移動時処理 *------------------------------------------ */ -int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range) +int skill_unit_out_all (struct block_list *bl, unsigned int tick, int range) { - nullpo_retr(0, bl); + nullpo_retr (0, bl); - if( bl->prev==NULL ) - return 0; + if (bl->prev == NULL) + return 0; - if(range<7) - range=7; - map_foreachinarea( skill_unit_out_all_sub, - bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL, - bl,tick ); + if (range < 7) + range = 7; + map_foreachinarea (skill_unit_out_all_sub, + bl->m, bl->x - range, bl->y - range, bl->x + range, + bl->y + range, BL_SKILL, bl, tick); - return 0; + return 0; } /*========================================== * スキルユニット移動時処理用(foreachinarea) *------------------------------------------ */ -int skill_unit_move_sub( struct block_list *bl, va_list ap ) +int skill_unit_move_sub (struct block_list *bl, va_list ap) { - struct skill_unit *unit; - struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; + struct skill_unit *unit; + struct skill_unit_group *group; + struct block_list *src; + int range; + unsigned int tick; - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); + nullpo_retr (0, bl); + nullpo_retr (0, ap); + nullpo_retr (0, unit = (struct skill_unit *) bl); + nullpo_retr (0, src = va_arg (ap, struct block_list *)); - tick=va_arg(ap,unsigned int); + tick = va_arg (ap, unsigned int); - if(!unit->alive || src->prev==NULL) - return 0; + if (!unit->alive || src->prev == NULL) + return 0; - if((group=unit->group) == NULL) - return 0; - range=(unit->range!=0)?unit->range:group->range; + if ((group = unit->group) == NULL) + return 0; + range = (unit->range != 0) ? unit->range : group->range; - if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 ) - return 0; + if (range < 0 || battle_check_target (bl, src, group->target_flag) <= 0) + return 0; - if( src->x >= bl->x-range && src->x <= bl->x+range && - src->y >= bl->y-range && src->y <= bl->y+range ) - skill_unit_onplace( unit, src, tick ); - else - skill_unit_onout( unit, src, tick ); + if (src->x >= bl->x - range && src->x <= bl->x + range && + src->y >= bl->y - range && src->y <= bl->y + range) + skill_unit_onplace (unit, src, tick); + else + skill_unit_onout (unit, src, tick); - return 0; + return 0; } /*========================================== * スキルユニット移動時処理 *------------------------------------------ */ -int skill_unit_move( struct block_list *bl,unsigned int tick,int range) +int skill_unit_move (struct block_list *bl, unsigned int tick, int range) { - nullpo_retr(0, bl); + nullpo_retr (0, bl); - if( bl->prev==NULL ) - return 0; + if (bl->prev == NULL) + return 0; - if(range<7) - range=7; - map_foreachinarea( skill_unit_move_sub, - bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL, - bl,tick ); + if (range < 7) + range = 7; + map_foreachinarea (skill_unit_move_sub, + bl->m, bl->x - range, bl->y - range, bl->x + range, + bl->y + range, BL_SKILL, bl, tick); - return 0; + return 0; } /*========================================== * スキルユニット自体の移動時処理(foreachinarea) *------------------------------------------ */ -int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap ) +int skill_unit_move_unit_group_sub (struct block_list *bl, va_list ap) { - struct skill_unit *unit; - struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - nullpo_retr(0, unit=(struct skill_unit *)src); - nullpo_retr(0, group=unit->group); - - tick=va_arg(ap,unsigned int); - - if(!unit->alive || bl->prev==NULL) - return 0; - - range=(unit->range!=0)?unit->range:group->range; - - if( range<0 || battle_check_target(src,bl,group->target_flag )<=0 ) - return 0; - if( bl->x >= src->x-range && bl->x <= src->x+range && - bl->y >= src->y-range && bl->y <= src->y+range ) - skill_unit_onplace( unit, bl, tick ); - else - skill_unit_onout( unit, bl, tick ); - return 0; + struct skill_unit *unit; + struct skill_unit_group *group; + struct block_list *src; + int range; + unsigned int tick; + + nullpo_retr (0, bl); + nullpo_retr (0, ap); + nullpo_retr (0, src = va_arg (ap, struct block_list *)); + nullpo_retr (0, unit = (struct skill_unit *) src); + nullpo_retr (0, group = unit->group); + + tick = va_arg (ap, unsigned int); + + if (!unit->alive || bl->prev == NULL) + return 0; + + range = (unit->range != 0) ? unit->range : group->range; + + if (range < 0 || battle_check_target (src, bl, group->target_flag) <= 0) + return 0; + if (bl->x >= src->x - range && bl->x <= src->x + range && + bl->y >= src->y - range && bl->y <= src->y + range) + skill_unit_onplace (unit, bl, tick); + else + skill_unit_onout (unit, bl, tick); + return 0; } /*========================================== @@ -9767,118 +11657,150 @@ int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap ) * 引数はグループと移動量 *------------------------------------------ */ -int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy) +int skill_unit_move_unit_group (struct skill_unit_group *group, int m, int dx, + int dy) { - nullpo_retr(0, group); - - if( group->unit_count<=0) - return 0; - - if(group->unit!=NULL){ - if(!battle_config.unit_movement_type){ - int i; - for(i=0;i<group->unit_count;i++){ - struct skill_unit *unit=&group->unit[i]; - if(unit->alive && !(m==unit->bl.m && dx==0 && dy==0)){ - int range=unit->range; - map_delblock(&unit->bl); - unit->bl.m = m; - unit->bl.x += dx; - unit->bl.y += dy; - map_addblock(&unit->bl); - clif_skill_setunit(unit); - if(range>0){ - if(range<7) - range=7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit->bl.m, - unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0, - &unit->bl,gettick() ); - } - } - } - }else{ - int i,j, *r_flag, *s_flag, *m_flag; - struct skill_unit *unit1; - struct skill_unit *unit2; - r_flag = (int *) malloc(sizeof(int) * group->unit_count); - s_flag = (int *) malloc(sizeof(int) * group->unit_count); - m_flag = (int *) malloc(sizeof(int) * group->unit_count); - memset(r_flag,0, sizeof(int) * group->unit_count);// 継承フラグ - memset(s_flag,0, sizeof(int) * group->unit_count);// 継承フラグ - memset(m_flag,0, sizeof(int) * group->unit_count);// 継承フラグ - - //先にフラグを全部決める - for(i=0;i<group->unit_count;i++){ - int move_check=0;// かぶりフラグ - unit1=&group->unit[i]; - for(j=0;j<group->unit_count;j++){ - unit2=&group->unit[j]; - if(unit1->bl.m==m && unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){ - //移動先にユニットがかぶってたら - s_flag[i]=1;// 移動前のユニットナンバーの継承フラグon - r_flag[j]=1;// かぶるユニットナンバーの残留フラグon - move_check=1;//ユニットがかぶった。 - break; - } - } - if(!move_check)// ユニットがかぶってなかったら - m_flag[i]=1;// 移動前ユニットナンバーの移動フラグon - } + nullpo_retr (0, group); - //フラグに基づいてユニット移動 - for(i=0;i<group->unit_count;i++){ - unit1=&group->unit[i]; - if(m_flag[i]){// 移動フラグがonで - if(!r_flag[i]){// 残留フラグがoffなら - //単純移動(rangeも継承の必要無し) - int range=unit1->range; - map_delblock(&unit1->bl); - unit1->bl.m = m; - unit1->bl.x += dx; - unit1->bl.y += dy; - map_addblock(&unit1->bl); - clif_skill_setunit(unit1); - if(range > 0){ - if(range < 7) - range = 7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit1->bl.m, - unit1->bl.x-range,unit1->bl.y-range,unit1->bl.x+range,unit1->bl.y+range,0, - &unit1->bl,gettick() ); - } - }else{// 残留フラグがonなら - //空ユニットになるので、継承可能なユニットを探す - for(j=0;j<group->unit_count;j++){ - unit2=&group->unit[j]; - if(s_flag[j] && !r_flag[j]){ - // 継承移動(range継承付き) - int range=unit1->range; - map_delblock(&unit2->bl); - unit2->bl.m = m; - unit2->bl.x = unit1->bl.x + dx; - unit2->bl.y = unit1->bl.y + dy; - unit2->range = unit1->range; - map_addblock(&unit2->bl); - clif_skill_setunit(unit2); - if(range > 0){ - if(range < 7) - range = 7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit2->bl.m, - unit2->bl.x-range,unit2->bl.y-range,unit2->bl.x+range,unit2->bl.y+range,0, - &unit2->bl,gettick() ); - } - s_flag[j]=0;// 継承完了したのでoff - break; - } - } - } - } - } - free(r_flag); - free(s_flag); - free(m_flag); - } - } - return 0; + if (group->unit_count <= 0) + return 0; + + if (group->unit != NULL) + { + if (!battle_config.unit_movement_type) + { + int i; + for (i = 0; i < group->unit_count; i++) + { + struct skill_unit *unit = &group->unit[i]; + if (unit->alive && !(m == unit->bl.m && dx == 0 && dy == 0)) + { + int range = unit->range; + map_delblock (&unit->bl); + unit->bl.m = m; + unit->bl.x += dx; + unit->bl.y += dy; + map_addblock (&unit->bl); + clif_skill_setunit (unit); + if (range > 0) + { + if (range < 7) + range = 7; + map_foreachinarea (skill_unit_move_unit_group_sub, + unit->bl.m, unit->bl.x - range, + unit->bl.y - range, + unit->bl.x + range, + unit->bl.y + range, 0, &unit->bl, + gettick ()); + } + } + } + } + else + { + int i, j, *r_flag, *s_flag, *m_flag; + struct skill_unit *unit1; + struct skill_unit *unit2; + r_flag = (int *) malloc (sizeof (int) * group->unit_count); + s_flag = (int *) malloc (sizeof (int) * group->unit_count); + m_flag = (int *) malloc (sizeof (int) * group->unit_count); + memset (r_flag, 0, sizeof (int) * group->unit_count); // 継承フラグ + memset (s_flag, 0, sizeof (int) * group->unit_count); // 継承フラグ + memset (m_flag, 0, sizeof (int) * group->unit_count); // 継承フラグ + + //先にフラグを全部決める + for (i = 0; i < group->unit_count; i++) + { + int move_check = 0; // かぶりフラグ + unit1 = &group->unit[i]; + for (j = 0; j < group->unit_count; j++) + { + unit2 = &group->unit[j]; + if (unit1->bl.m == m && unit1->bl.x + dx == unit2->bl.x + && unit1->bl.y + dy == unit2->bl.y) + { + //移動先にユニットがかぶってたら + s_flag[i] = 1; // 移動前のユニットナンバーの継承フラグon + r_flag[j] = 1; // かぶるユニットナンバーの残留フラグon + move_check = 1; //ユニットがかぶった。 + break; + } + } + if (!move_check) // ユニットがかぶってなかったら + m_flag[i] = 1; // 移動前ユニットナンバーの移動フラグon + } + + //フラグに基づいてユニット移動 + for (i = 0; i < group->unit_count; i++) + { + unit1 = &group->unit[i]; + if (m_flag[i]) + { // 移動フラグがonで + if (!r_flag[i]) + { // 残留フラグがoffなら + //単純移動(rangeも継承の必要無し) + int range = unit1->range; + map_delblock (&unit1->bl); + unit1->bl.m = m; + unit1->bl.x += dx; + unit1->bl.y += dy; + map_addblock (&unit1->bl); + clif_skill_setunit (unit1); + if (range > 0) + { + if (range < 7) + range = 7; + map_foreachinarea (skill_unit_move_unit_group_sub, + unit1->bl.m, + unit1->bl.x - range, + unit1->bl.y - range, + unit1->bl.x + range, + unit1->bl.y + range, 0, + &unit1->bl, gettick ()); + } + } + else + { // 残留フラグがonなら + //空ユニットになるので、継承可能なユニットを探す + for (j = 0; j < group->unit_count; j++) + { + unit2 = &group->unit[j]; + if (s_flag[j] && !r_flag[j]) + { + // 継承移動(range継承付き) + int range = unit1->range; + map_delblock (&unit2->bl); + unit2->bl.m = m; + unit2->bl.x = unit1->bl.x + dx; + unit2->bl.y = unit1->bl.y + dy; + unit2->range = unit1->range; + map_addblock (&unit2->bl); + clif_skill_setunit (unit2); + if (range > 0) + { + if (range < 7) + range = 7; + map_foreachinarea + (skill_unit_move_unit_group_sub, + unit2->bl.m, unit2->bl.x - range, + unit2->bl.y - range, + unit2->bl.x + range, + unit2->bl.y + range, 0, &unit2->bl, + gettick ()); + } + s_flag[j] = 0; // 継承完了したのでoff + break; + } + } + } + } + } + free (r_flag); + free (s_flag); + free (m_flag); + } + } + return 0; } /*---------------------------------------------------------------------------- @@ -9890,30 +11812,29 @@ int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int * 初期化系 */ -static int -scan_stat(char *statname) +static int scan_stat (char *statname) { - if (!strcmpi(statname, "str")) - return SP_STR; - if (!strcmpi(statname, "dex")) - return SP_DEX; - if (!strcmpi(statname, "agi")) - return SP_AGI; - if (!strcmpi(statname, "vit")) - return SP_VIT; - if (!strcmpi(statname, "int")) - return SP_INT; - if (!strcmpi(statname, "luk")) - return SP_LUK; - if (!strcmpi(statname, "none")) - return 0; - - else fprintf(stderr, "Unknown stat `%s'\n", statname); + if (!strcmpi (statname, "str")) + return SP_STR; + if (!strcmpi (statname, "dex")) + return SP_DEX; + if (!strcmpi (statname, "agi")) + return SP_AGI; + if (!strcmpi (statname, "vit")) + return SP_VIT; + if (!strcmpi (statname, "int")) + return SP_INT; + if (!strcmpi (statname, "luk")) + return SP_LUK; + if (!strcmpi (statname, "none")) return 0; + + else + fprintf (stderr, "Unknown stat `%s'\n", statname); + return 0; } -extern void -skill_pool_register(int id); // [Fate] Remember that a certain skill ID belongs to a pool skill +extern void skill_pool_register (int id); // [Fate] Remember that a certain skill ID belongs to a pool skill /*========================================== * スキル関係ファイル読み込み @@ -9921,372 +11842,464 @@ skill_pool_register(int id); // [Fate] Remember that a certain skill ID belongs * skill_cast_db.txt スキルの詠唱時間とディレイデータ *------------------------------------------ */ -int skill_readdb(void) +int skill_readdb (void) { - int i,j,k,l; - FILE *fp; - char line[1024],*p; - - /* The main skill database */ - memset(skill_db,0,sizeof(skill_db)); - fp=fopen_("db/skill_db.txt","r"); - if(fp==NULL){ - printf("can't read db/skill_db.txt\n"); - return 1; - } - while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; - if(line[0]=='/' && line[1]=='/') - continue; - for(j=0,p=line;j<18 && p;j++){ - while (*p == '\t' || *p == ' ') p++; - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - if(split[17]==NULL || j<18) { - fprintf(stderr, "Incomplete skill db data online (%d entries)\n", j); - continue; - } - - i=atoi(split[0]); - if(i<0 || i>MAX_SKILL_DB) - continue; - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].range[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - skill_db[i].hit=atoi(split[2]); - skill_db[i].inf=atoi(split[3]); - skill_db[i].pl=atoi(split[4]); - skill_db[i].nk=atoi(split[5]); - skill_db[i].max_raise=atoi(split[6]); - skill_db[i].max=atoi(split[7]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[8];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].num[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - if(strcmpi(split[9],"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[13],"weapon") == 0) - skill_db[i].skill_type=BF_WEAPON; - else if(strcmpi(split[12],"magic") == 0) - skill_db[i].skill_type=BF_MAGIC; - else if(strcmpi(split[12],"misc") == 0) - skill_db[i].skill_type=BF_MISC; - else - skill_db[i].skill_type=0; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[14];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].blewcount[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - if (!strcmpi(split[15], "passive")) { - skill_pool_register(i); - skill_db[i].poolflags = SKILL_POOL_FLAG; - } else if (!strcmpi(split[15], "active")) { - skill_pool_register(i); - skill_db[i].poolflags = SKILL_POOL_FLAG | SKILL_POOL_ACTIVE; - } else - skill_db[i].poolflags = 0; - - skill_db[i].stat = scan_stat(split[16]); - - skill_names[i].desc = strdup(split[17]); - { // replace "_" by " " - char *s = skill_names[i].desc; - while ((s = strchr(s, '_'))) - *s = ' '; - if ((s = strchr(skill_names[i].desc, '\t')) || (s = strchr (skill_names[i].desc, ' ')) || (s = strchr (skill_names[i].desc, '\n'))) - *s = '\000'; - } - } - fclose_(fp); - printf("read db/skill_db.txt done\n"); - - fp=fopen_("db/skill_require_db.txt","r"); - if(fp==NULL){ - printf("can't read db/skill_require_db.txt\n"); - return 1; - } - while(fgets(line,1020,fp)){ - char *split[51], *split2[MAX_SKILL_LEVEL]; - if(line[0]=='/' && line[1]=='/') - continue; - for(j=0,p=line;j<30 && p;j++){ - while (*p == '\t' || *p == ' ') p++; - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - if(split[29]==NULL || j<30) - continue; - - i=atoi(split[0]); - if(i<0 || i>MAX_SKILL_DB) - continue; - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].hp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].mhp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].sp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].hp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[5];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].sp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[6];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].zeny[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[7];j<32 && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<32 && split2[k];k++) { - l = atoi(split2[k]); - if(l == 99) { - skill_db[i].weapon = 0xffffffff; - break; - } - else - skill_db[i].weapon |= 1<<l; - } - - if( strcmpi(split[8],"hiding")==0 ) skill_db[i].state=ST_HIDING; - else if( strcmpi(split[8],"cloaking")==0 ) skill_db[i].state=ST_CLOAKING; - else if( strcmpi(split[8],"hidden")==0 ) skill_db[i].state=ST_HIDDEN; - else if( strcmpi(split[8],"riding")==0 ) skill_db[i].state=ST_RIDING; - else if( strcmpi(split[8],"falcon")==0 ) skill_db[i].state=ST_FALCON; - else if( strcmpi(split[8],"cart")==0 ) skill_db[i].state=ST_CART; - else if( strcmpi(split[8],"shield")==0 ) skill_db[i].state=ST_SHIELD; - else if( strcmpi(split[8],"sight")==0 ) skill_db[i].state=ST_SIGHT; - else if( strcmpi(split[8],"explosionspirits")==0 ) skill_db[i].state=ST_EXPLOSIONSPIRITS; - else if( strcmpi(split[8],"recover_weight_rate")==0 ) skill_db[i].state=ST_RECOV_WEIGHT_RATE; - else if( strcmpi(split[8],"move_enable")==0 ) skill_db[i].state=ST_MOVE_ENABLE; - else if( strcmpi(split[8],"water")==0 ) skill_db[i].state=ST_WATER; - else skill_db[i].state=ST_NONE; - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[9];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].spiritball[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - skill_db[i].itemid[0]=atoi(split[10]); - skill_db[i].amount[0]=atoi(split[11]); - skill_db[i].itemid[1]=atoi(split[12]); - skill_db[i].amount[1]=atoi(split[13]); - skill_db[i].itemid[2]=atoi(split[14]); - skill_db[i].amount[2]=atoi(split[15]); - skill_db[i].itemid[3]=atoi(split[16]); - skill_db[i].amount[3]=atoi(split[17]); - skill_db[i].itemid[4]=atoi(split[18]); - skill_db[i].amount[4]=atoi(split[19]); - skill_db[i].itemid[5]=atoi(split[20]); - skill_db[i].amount[5]=atoi(split[21]); - skill_db[i].itemid[6]=atoi(split[22]); - skill_db[i].amount[6]=atoi(split[23]); - skill_db[i].itemid[7]=atoi(split[24]); - skill_db[i].amount[7]=atoi(split[25]); - skill_db[i].itemid[8]=atoi(split[26]); - skill_db[i].amount[8]=atoi(split[27]); - skill_db[i].itemid[9]=atoi(split[28]); - skill_db[i].amount[9]=atoi(split[29]); - } - fclose_(fp); - printf("read db/skill_require_db.txt done\n"); - - /* ? */ - fp=fopen_("db/skill_cast_db.txt","r"); - if(fp==NULL){ - printf("can't read db/skill_cast_db.txt\n"); - return 1; - } - while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; - memset(split,0,sizeof(split)); // [Valaris] thanks to fov - if(line[0]=='/' && line[1]=='/') - continue; - for(j=0,p=line;j<5 && p;j++){ - while (*p == '\t' || *p == ' ') p++; - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - if(split[4]==NULL || j<5) - continue; - - i=atoi(split[0]); - if(i<0 || i>MAX_SKILL_DB) - continue; - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].cast[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].delay[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].upkeep_time[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].upkeep_time2[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - } - fclose_(fp); - printf("read db/skill_cast_db.txt done\n"); + int i, j, k, l; + FILE *fp; + char line[1024], *p; + + /* The main skill database */ + memset (skill_db, 0, sizeof (skill_db)); + fp = fopen_ ("db/skill_db.txt", "r"); + if (fp == NULL) + { + printf ("can't read db/skill_db.txt\n"); + return 1; + } + while (fgets (line, 1020, fp)) + { + char *split[50], *split2[MAX_SKILL_LEVEL]; + if (line[0] == '/' && line[1] == '/') + continue; + for (j = 0, p = line; j < 18 && p; j++) + { + while (*p == '\t' || *p == ' ') + p++; + split[j] = p; + p = strchr (p, ','); + if (p) + *p++ = 0; + } + if (split[17] == NULL || j < 18) + { + fprintf (stderr, "Incomplete skill db data online (%d entries)\n", + j); + continue; + } - fp=fopen_("db/skill_castnodex_db.txt","r"); - if(fp==NULL){ - printf("can't read db/skill_castnodex_db.txt\n"); - return 1; - } - while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; - memset(split,0,sizeof(split)); - if(line[0]=='/' && line[1]=='/') - continue; - for(j=0,p=line;j<2 && p;j++){ - while (*p == '\t' || *p == ' ') p++; - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + i = atoi (split[0]); + if (i < 0 || i > MAX_SKILL_DB) + continue; + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].range[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + skill_db[i].hit = atoi (split[2]); + skill_db[i].inf = atoi (split[3]); + skill_db[i].pl = atoi (split[4]); + skill_db[i].nk = atoi (split[5]); + skill_db[i].max_raise = atoi (split[6]); + skill_db[i].max = atoi (split[7]); + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[8]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].num[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); - i=atoi(split[0]); - if(i<0 || i>MAX_SKILL_DB) - continue; + if (strcmpi (split[9], "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[13], "weapon") == 0) + skill_db[i].skill_type = BF_WEAPON; + else if (strcmpi (split[12], "magic") == 0) + skill_db[i].skill_type = BF_MAGIC; + else if (strcmpi (split[12], "misc") == 0) + skill_db[i].skill_type = BF_MISC; + else + skill_db[i].skill_type = 0; + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[14]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].blewcount[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + + if (!strcmpi (split[15], "passive")) + { + skill_pool_register (i); + skill_db[i].poolflags = SKILL_POOL_FLAG; + } + else if (!strcmpi (split[15], "active")) + { + skill_pool_register (i); + skill_db[i].poolflags = SKILL_POOL_FLAG | SKILL_POOL_ACTIVE; + } + else + skill_db[i].poolflags = 0; + + skill_db[i].stat = scan_stat (split[16]); + + skill_names[i].desc = strdup (split[17]); + { // replace "_" by " " + char *s = skill_names[i].desc; + while ((s = strchr (s, '_'))) + *s = ' '; + if ((s = strchr (skill_names[i].desc, '\t')) + || (s = strchr (skill_names[i].desc, ' ')) + || (s = strchr (skill_names[i].desc, '\n'))) + *s = '\000'; + } + } + fclose_ (fp); + printf ("read db/skill_db.txt done\n"); + + fp = fopen_ ("db/skill_require_db.txt", "r"); + if (fp == NULL) + { + printf ("can't read db/skill_require_db.txt\n"); + return 1; + } + while (fgets (line, 1020, fp)) + { + char *split[51], *split2[MAX_SKILL_LEVEL]; + if (line[0] == '/' && line[1] == '/') + continue; + for (j = 0, p = line; j < 30 && p; j++) + { + while (*p == '\t' || *p == ' ') + p++; + split[j] = p; + p = strchr (p, ','); + if (p) + *p++ = 0; + } + if (split[29] == NULL || j < 30) + continue; + + i = atoi (split[0]); + if (i < 0 || i > MAX_SKILL_DB) + continue; + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].hp[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[2]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].mhp[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[3]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].sp[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[4]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].hp_rate[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[5]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].sp_rate[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[6]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].zeny[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[7]; j < 32 && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < 32 && split2[k]; k++) + { + l = atoi (split2[k]); + if (l == 99) + { + skill_db[i].weapon = 0xffffffff; + break; + } + else + skill_db[i].weapon |= 1 << l; + } - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].castnodex[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - } - fclose_(fp); - printf("read db/skill_castnodex_db.txt done\n"); + if (strcmpi (split[8], "hiding") == 0) + skill_db[i].state = ST_HIDING; + else if (strcmpi (split[8], "cloaking") == 0) + skill_db[i].state = ST_CLOAKING; + else if (strcmpi (split[8], "hidden") == 0) + skill_db[i].state = ST_HIDDEN; + else if (strcmpi (split[8], "riding") == 0) + skill_db[i].state = ST_RIDING; + else if (strcmpi (split[8], "falcon") == 0) + skill_db[i].state = ST_FALCON; + else if (strcmpi (split[8], "cart") == 0) + skill_db[i].state = ST_CART; + else if (strcmpi (split[8], "shield") == 0) + skill_db[i].state = ST_SHIELD; + else if (strcmpi (split[8], "sight") == 0) + skill_db[i].state = ST_SIGHT; + else if (strcmpi (split[8], "explosionspirits") == 0) + skill_db[i].state = ST_EXPLOSIONSPIRITS; + else if (strcmpi (split[8], "recover_weight_rate") == 0) + skill_db[i].state = ST_RECOV_WEIGHT_RATE; + else if (strcmpi (split[8], "move_enable") == 0) + skill_db[i].state = ST_MOVE_ENABLE; + else if (strcmpi (split[8], "water") == 0) + skill_db[i].state = ST_WATER; + else + skill_db[i].state = ST_NONE; + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[9]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].spiritball[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + skill_db[i].itemid[0] = atoi (split[10]); + skill_db[i].amount[0] = atoi (split[11]); + skill_db[i].itemid[1] = atoi (split[12]); + skill_db[i].amount[1] = atoi (split[13]); + skill_db[i].itemid[2] = atoi (split[14]); + skill_db[i].amount[2] = atoi (split[15]); + skill_db[i].itemid[3] = atoi (split[16]); + skill_db[i].amount[3] = atoi (split[17]); + skill_db[i].itemid[4] = atoi (split[18]); + skill_db[i].amount[4] = atoi (split[19]); + skill_db[i].itemid[5] = atoi (split[20]); + skill_db[i].amount[5] = atoi (split[21]); + skill_db[i].itemid[6] = atoi (split[22]); + skill_db[i].amount[6] = atoi (split[23]); + skill_db[i].itemid[7] = atoi (split[24]); + skill_db[i].amount[7] = atoi (split[25]); + skill_db[i].itemid[8] = atoi (split[26]); + skill_db[i].amount[8] = atoi (split[27]); + skill_db[i].itemid[9] = atoi (split[28]); + skill_db[i].amount[9] = atoi (split[29]); + } + fclose_ (fp); + printf ("read db/skill_require_db.txt done\n"); + + /* ? */ + fp = fopen_ ("db/skill_cast_db.txt", "r"); + if (fp == NULL) + { + printf ("can't read db/skill_cast_db.txt\n"); + return 1; + } + while (fgets (line, 1020, fp)) + { + char *split[50], *split2[MAX_SKILL_LEVEL]; + memset (split, 0, sizeof (split)); // [Valaris] thanks to fov + if (line[0] == '/' && line[1] == '/') + continue; + for (j = 0, p = line; j < 5 && p; j++) + { + while (*p == '\t' || *p == ' ') + p++; + split[j] = p; + p = strchr (p, ','); + if (p) + *p++ = 0; + } + if (split[4] == NULL || j < 5) + continue; + + i = atoi (split[0]); + if (i < 0 || i > MAX_SKILL_DB) + continue; + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].cast[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[2]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].delay[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[3]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].upkeep_time[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[4]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].upkeep_time2[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + } + fclose_ (fp); + printf ("read db/skill_cast_db.txt done\n"); + + fp = fopen_ ("db/skill_castnodex_db.txt", "r"); + if (fp == NULL) + { + printf ("can't read db/skill_castnodex_db.txt\n"); + return 1; + } + while (fgets (line, 1020, fp)) + { + char *split[50], *split2[MAX_SKILL_LEVEL]; + memset (split, 0, sizeof (split)); + if (line[0] == '/' && line[1] == '/') + continue; + for (j = 0, p = line; j < 2 && p; j++) + { + while (*p == '\t' || *p == ' ') + p++; + split[j] = p; + p = strchr (p, ','); + if (p) + *p++ = 0; + } - return 0; + i = atoi (split[0]); + if (i < 0 || i > MAX_SKILL_DB) + continue; + + memset (split2, 0, sizeof (split2)); + for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++) + { + split2[j] = p; + p = strchr (p, ':'); + if (p) + *p++ = 0; + } + for (k = 0; k < MAX_SKILL_LEVEL; k++) + skill_db[i].castnodex[k] = + (split2[k]) ? atoi (split2[k]) : atoi (split2[0]); + } + fclose_ (fp); + printf ("read db/skill_castnodex_db.txt done\n"); + + return 0; } -void skill_reload(void) +void skill_reload (void) { - /* - - <empty skill database> - <?> - - */ - - do_init_skill(); + /* + * + * <empty skill database> + * <?> + * + */ + + do_init_skill (); } /*========================================== * スキル関係初期化処理 *------------------------------------------ */ -int do_init_skill(void) +int do_init_skill (void) { - skill_readdb(); - - add_timer_func_list(skill_unit_timer,"skill_unit_timer"); - add_timer_func_list(skill_castend_id,"skill_castend_id"); - add_timer_func_list(skill_castend_pos,"skill_castend_pos"); - add_timer_func_list(skill_timerskill,"skill_timerskill"); - add_timer_func_list(skill_status_change_timer,"skill_status_change_timer"); - add_timer_interval(gettick()+SKILLUNITTIMER_INVERVAL,skill_unit_timer,0,0,SKILLUNITTIMER_INVERVAL); - - return 0; + skill_readdb (); + + add_timer_func_list (skill_unit_timer, "skill_unit_timer"); + add_timer_func_list (skill_castend_id, "skill_castend_id"); + add_timer_func_list (skill_castend_pos, "skill_castend_pos"); + add_timer_func_list (skill_timerskill, "skill_timerskill"); + add_timer_func_list (skill_status_change_timer, + "skill_status_change_timer"); + add_timer_interval (gettick () + SKILLUNITTIMER_INVERVAL, + skill_unit_timer, 0, 0, SKILLUNITTIMER_INVERVAL); + + return 0; } |