summaryrefslogtreecommitdiff
path: root/src/map/skill.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/skill.c')
-rw-r--r--src/map/skill.c8690
1 files changed, 3383 insertions, 5307 deletions
diff --git a/src/map/skill.c b/src/map/skill.c
index dc708c906..c53a7a9d6 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -1,4 +1,4 @@
-// $Id: skill.c,v 1.8 2004/11/26 7:12:23 PM Celestia Exp $
+// $Id: skill.c,v 1.8 2004/02/27 5:34:51 PM Celestia $
/* スキル?係 */
#include <stdio.h>
@@ -14,6 +14,7 @@
#include "map.h"
#include "clif.h"
#include "pc.h"
+#include "status.h"
#include "pet.h"
#include "mob.h"
#include "battle.h"
@@ -24,245 +25,16 @@
#include "log.h"
#include "chrif.h"
#include "guild.h"
+#include "showmsg.h"
+#include "grfio.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
#define SKILLUNITTIMER_INVERVAL 100
-
#define STATE_BLIND 0x10
-
-/* スキル番?=>ステ?タス異常番??換テ?ブル */
-int SkillStatusChangeTable[]={ /* skill.hのenumのSC_***とあわせること */
-/* 0- */
- -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,
-/* 20- */
- -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,
-/* 40- */
- -1,-1,-1,-1,-1,
- SC_CONCENTRATE, /* 集中力向上 */
- -1,-1,-1,-1,
-/* 50- */
- -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, /* 聖?降福 */
-/* 70- */
- -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,
-/* 90- */
- -1,-1,
- SC_QUAGMIRE, /* クァグマイア */
- -1,-1,-1,-1,-1,-1,-1,
-/* 100- */
- -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,
-/* 120- */
- -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, /* ポイズンリアクト */
-/* 140- */
- 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,
-/* 160- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,
- SC_SELFDESTRUCTION,
- -1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,
- SC_KEEPING,
- -1,-1,
- SC_BARRIER,
- -1,-1,
- SC_HALLUCINATION,
- -1,-1,
-/* 210- */
- -1,-1,-1,-1,-1,
- SC_STRIPWEAPON,
- SC_STRIPSHIELD,
- SC_STRIPARMOR,
- SC_STRIPHELM,
- -1,
-/* 220- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-/* 230- */
- -1,-1,-1,-1,
- SC_CP_WEAPON,
- SC_CP_SHIELD,
- SC_CP_ARMOR,
- SC_CP_HELM,
- -1,-1,
-/* 240- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,
- SC_AUTOGUARD,
-/* 250- */
- -1,-1,
- SC_REFLECTSHIELD,
- -1,-1,
- SC_DEVOTION,
- SC_PROVIDENCE,
- SC_DEFENDER,
- SC_SPEARSQUICKEN,
- -1,
-/* 260- */
- -1,-1,-1,-1,-1,-1,-1,-1,
- SC_STEELBODY,
- SC_BLADESTOP_WAIT,
-/* 270- */
- SC_EXPLOSIONSPIRITS,
- SC_EXTREMITYFIST,
- -1,-1,-1,-1,
- SC_MAGICROD,
- -1,-1,-1,
-/* 280- */
- SC_FLAMELAUNCHER,
- SC_FROSTWEAPON,
- SC_LIGHTNINGLOADER,
- SC_SEISMICWEAPON,
- -1,
- SC_VOLCANO,
- SC_DELUGE,
- SC_VIOLENTGALE,
- SC_LANDPROTECTOR,
- -1,
-/* 290- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-/* 300- */
- -1,-1,-1,-1,-1,-1,
- SC_LULLABY,
- SC_RICHMANKIM,
- SC_ETERNALCHAOS,
- SC_DRUMBATTLE,
-/* 310- */
- SC_NIBELUNGEN,
- SC_ROKISWEIL,
- SC_INTOABYSS,
- SC_SIEGFRIED,
- -1,-1,-1,
- SC_DISSONANCE,
- -1,
- SC_WHISTLE,
-/* 320- */
- SC_ASSNCROS,
- SC_POEMBRAGI,
- SC_APPLEIDUN,
- -1,-1,
- SC_UGLYDANCE,
- -1,
- SC_HUMMING,
- SC_DONTFORGETME,
- SC_FORTUNE,
-/* 330- */
- SC_SERVICE4U,
- SC_SELFDESTRUCTION,
- -1,-1,-1,-1,-1,-1,-1,-1,
-/* 340- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-/* 350- */
- -1,-1,-1,-1,-1,
- SC_AURABLADE,
- SC_PARRYING,
- SC_CONCENTRATION,
- SC_TENSIONRELAX,
- SC_BERSERK,
-/* 360- */
- SC_BERSERK,
- SC_ASSUMPTIO,
- SC_BASILICA,
- -1,-1,-1,
- SC_MAGICPOWER,
- -1,-1,
- SC_GOSPEL,
-/* 370- */
- -1,-1,-1,-1,-1,-1,-1,-1,
-
- SC_EDP,
-
- -1,
-/* 380- */
- SC_TRUESIGHT,
- -1,-1,
- SC_WINDWALK,
- SC_MELTDOWN,
- -1,-1,
- SC_CARTBOOST,
- -1,
- SC_CHASEWALK,
-/* 390- */
- SC_REJECTSWORD,
- -1,-1,-1,-1,-1,
- SC_MARIONETTE,
- -1,
- SC_HEADCRUSH,
- SC_JOINTBEAT,
-/* 400 */
- -1,-1,
- SC_MINDBREAKER,
- SC_MEMORIZE,
- SC_FOGWALL,
- SC_SPIDERWEB,
- -1,-1,-1,-1,
-/* 410- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-};
+#define swap(x,y) { int t; t = x; x = y; y = t; }
const struct skill_name_db skill_names[] = {
{ AC_CHARGEARROW, "CHARGEARROW", "Charge_Arrow" } ,
@@ -398,6 +170,10 @@ const struct skill_name_db skill_names[] = {
{ DC_SERVICEFORYOU, "SERVICEFORYOU", "Prostitute" } ,
{ DC_THROWARROW, "THROWARROW", "Throw_Arrow" } ,
{ DC_UGLYDANCE, "UGLYDANCE", "Ugly_Dance" } ,
+ { GD_BATTLEORDER, "BATTLEORDER", "Battle_Orders" } ,
+ { GD_REGENERATION, "REGENERATION", "Regeneration" } ,
+ { GD_RESTORE, "RESTORE", "Restore" } ,
+ { GD_EMERGENCYCALL, "EMERGENCYCALL", "Emergency_Call" } ,
{ HP_ASSUMPTIO, "ASSUMPTIO", "Assumptio" } ,
{ HP_BASILICA, "BASILICA", "Basilica" } ,
{ HP_MEDITATIO, "MEDITATIO", "Meditation" } ,
@@ -698,9 +474,9 @@ const struct skill_name_db skill_names[] = {
{ 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_BABY, "BABY", "I Love Mama and Fafa" } ,
+ { WE_CALLBABY, "CALLBABY", "Come With Me, Baby" } ,
+ { WE_CALLPARENT, "CALLPARENT", "I Miss My Parents" } ,
{ WE_CALLPARTNER, "CALLPARTNER", "I Want to See You" } ,
{ WE_FEMALE, "FEMALE", "I Only Look Up to You" } ,
{ WE_MALE, "MALE", "I Will Protect You" } ,
@@ -724,7 +500,7 @@ const struct skill_name_db skill_names[] = {
{ WZ_STORMGUST, "STORMGUST", "Storm_Gust" } ,
{ WZ_VERMILION, "VERMILION", "Lord_of_Vermilion" } ,
{ WZ_WATERBALL, "WATERBALL", "Water_Ball" } ,
- { 0, 0, 0 }
+ { 0, 0, 0 }
};
static const int dirx[8]={0,-1,-1,-1,0,1,1,1};
@@ -744,94 +520,49 @@ struct skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB];
/* アブラカダブラ?動スキルデ?タベ?ス */
struct skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB];
-int skill_get_hit( int id ){
- if (id >= 10000 && id < 10015) id -= 9500;
- return skill_db[id].hit;
-}
-int skill_get_inf( int id ){
- return (id < 500) ? skill_db[id].inf : guild_skill_get_inf(id);
-}
-int skill_get_pl( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].pl;
-}
-int skill_get_nk( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].nk;
-}
-int skill_get_max( int id ){
- return (id < 500) ? skill_db[id].max : guild_skill_get_max(id);
-}
-int skill_get_range( int id , int lv ){
- if (lv <= 0) return 0;
- return (id < 500) ? skill_db[id].range[lv-1] : guild_skill_get_range(id);
-}
-int skill_get_hp( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0: skill_db[id].hp[lv-1];
-}
-int skill_get_sp( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- //if (lv <= 0) return 0;
- //return (id < 500) ? skill_db[id].sp[lv-1] : guild_skill_get_sp(id, lv);
- return (lv <= 0) ? 0: skill_db[id].sp[lv-1];
-}
-int skill_get_zeny( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].zeny[lv-1];
-}
-int skill_get_num( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].num[lv-1];
-}
-int skill_get_cast( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].cast[lv-1];
-}
-int skill_get_delay( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].delay[lv-1];
-}
-int skill_get_time( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].upkeep_time[lv-1];
-}
-int skill_get_time2( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].upkeep_time2[lv-1];
-}
-int skill_get_castdef( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].cast_def_rate;
-}
-int skill_get_weapontype( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].weapon;
-}
-int skill_get_inf2( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].inf2;
-}
-int skill_get_castcancel( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].maxcount;
-}
-int skill_get_maxcount( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].maxcount;
-}
-int skill_get_blewcount( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].blewcount[lv-1];
-}
-int skill_get_mhp( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].mhp[lv-1];
-}
-int skill_get_castnodex( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].castnodex[lv-1];
-}
+// macros to check for out of bounds errors [celest]
+// i: Skill ID, l: Skill Level, var: Value to return after checking
+// for values that don't require level just put a one (putting 0 will trigger return 0; instead
+// for values that might need to use a different function just skill_chk would suffice.
+#define skill_chk(i, l) \
+ if (i >= 10000 && i < 10015) {i -= 9500;} \
+ if (i < 1 || i > MAX_SKILL_DB) {return 0;} \
+ if (l <= 0 || l > MAX_SKILL_LEVEL) {return 0;}
+#define skill_get(var, i, l) \
+ { skill_chk(i, l); return var; }
+
+// Skill DB
+int skill_get_hit( int id ){ skill_get (skill_db[id].hit, id, 1); }
+int skill_get_inf( int id ){ skill_chk (id, 1); return (id < 500) ? skill_db[id].inf : guild_skill_get_inf(id); }
+int skill_get_pl( int id ){ skill_get (skill_db[id].pl, id, 1); }
+int skill_get_nk( int id ){ skill_get (skill_db[id].nk, id, 1); }
+int skill_get_max( int id ){ skill_chk (id, 1); return (id < 500) ? skill_db[id].max : guild_skill_get_max(id); }
+int skill_get_range( int id , int lv ){ skill_chk (id, lv); return (id < 500) ? skill_db[id].range[lv-1] : guild_skill_get_range(id); }
+int skill_get_hp( int id ,int lv ){ skill_get (skill_db[id].hp[lv-1], id, lv); }
+int skill_get_sp( int id ,int lv ){ skill_get (skill_db[id].sp[lv-1], id, lv); }
+int skill_get_zeny( int id ,int lv ){ skill_get (skill_db[id].zeny[lv-1], id, lv); }
+int skill_get_num( int id ,int lv ){ skill_get (skill_db[id].num[lv-1], id, lv); }
+int skill_get_cast( int id ,int lv ){ skill_get (skill_db[id].cast[lv-1], id, lv); }
+int skill_get_delay( int id ,int lv ){ skill_get (skill_db[id].delay[lv-1], id, lv); }
+int skill_get_time( int id ,int lv ){ skill_get (skill_db[id].upkeep_time[lv-1], id, lv); }
+int skill_get_time2( int id ,int lv ){ skill_get (skill_db[id].upkeep_time2[lv-1], id, lv); }
+int skill_get_castdef( int id ){ skill_get (skill_db[id].cast_def_rate, id, 1); }
+int skill_get_weapontype( int id ){ skill_get (skill_db[id].weapon, id, 1); }
+int skill_get_inf2( int id ){ skill_get (skill_db[id].inf2, id, 1); }
+int skill_get_castcancel( int id ){ skill_get (skill_db[id].castcancel, id, 1); }
+int skill_get_maxcount( int id ){ skill_get (skill_db[id].maxcount, id, 1); }
+int skill_get_blewcount( int id ,int lv ){ skill_get (skill_db[id].blewcount[lv-1], id, lv); }
+int skill_get_mhp( int id ,int lv ){ skill_get (skill_db[id].mhp[lv-1], id, lv); }
+int skill_get_castnodex( int id ,int lv ){ skill_get (skill_db[id].castnodex[lv-1], id, lv); }
+int skill_get_delaynodex( int id ,int lv ){ skill_get (skill_db[id].delaynodex[lv-1], id, lv); }
+int skill_get_nocast ( int id ){ skill_get (skill_db[id].nocast, id, 1); }
+int skill_get_unit_id ( int id, int flag ){ skill_get (skill_db[id].unit_id[flag], id, 1); }
+int skill_get_unit_layout_type( int id ,int lv ){ skill_get (skill_db[id].unit_layout_type[lv-1], id, lv); }
+int skill_get_unit_interval( int id ){ skill_get (skill_db[id].unit_interval, id, 1); }
+int skill_get_unit_range( int id ){ skill_get (skill_db[id].unit_range, id, 1); }
+int skill_get_unit_target( int id ){ skill_get (skill_db[id].unit_target, id, 1); }
+int skill_get_unit_flag( int id ){ skill_get (skill_db[id].unit_flag, id, 1); }
+
int skill_tree_get_max(int id, int b_class){
struct pc_base_job s_class = pc_calc_base_job(b_class);
int i, skillid;
@@ -845,42 +576,64 @@ int skill_tree_get_max(int id, int b_class){
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 status_change_timer_sub(struct block_list *bl, va_list ap );
int skill_attack_area(struct block_list *bl,va_list ap);
-int skill_abra_dataset(int skilllv);
int skill_clear_element_field(struct block_list *bl);
int skill_landprotector(struct block_list *bl, va_list ap );
int skill_trap_splash(struct block_list *bl, va_list ap );
int skill_count_target(struct block_list *bl, va_list ap );
+struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg,int tick);
+int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int tick);
+int skill_unit_effect(struct block_list *bl,va_list ap);
+
+int enchant_eff[5] = { 10, 14, 17, 19, 20 };
+int deluge_eff[5] = { 5, 9, 12, 14, 15 };
// [MouseJstr] - skill ok to cast? and when?
-int skillnotok(int skillid, struct map_session_data *sd) {
- if (sd == 0)
- return 0;
- if (pc_isGM(sd) >= 20)
- return 0; // gm's can do anything damn thing they want
+int skillnotok(int skillid, struct map_session_data *sd)
+{
+ nullpo_retr (1, sd);
+ //if (sd == 0)
+ //return 0;
+ //return 1;
+ // I think it was meant to be "no skills allowed when not a valid sd"
+
+ if (!(skillid >= 10000 && skillid < 10015))
+ if ((skillid > MAX_SKILL) || (skillid < 0))
+ return 1;
+
+ {
+ int i = skillid;
+ if (i >= 10000 && i < 10015)
+ i -= 9500;
+ if (sd->blockskill[i] > 0)
+ return 1;
+ }
+
+ if (pc_isGM(sd) >= 20)
+ return 0; // gm's can do anything damn thing they want
// Check skill restrictions [Celest]
- if(!map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.gvg && skill_db[skillid].nocast & 1)
+ if(!map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.gvg && skill_get_nocast (skillid) & 1)
return 1;
- if(map[sd->bl.m].flag.pvp && skill_db[skillid].nocast & 2)
+ if(map[sd->bl.m].flag.pvp && skill_get_nocast (skillid) & 2)
return 1;
- if(map[sd->bl.m].flag.gvg && skill_db[skillid].nocast & 4)
+ if(map[sd->bl.m].flag.gvg && skill_get_nocast (skillid) & 4)
return 1;
- if (agit_flag && skill_db[skillid].nocast & 8)
+ if (agit_flag && skill_get_nocast (skillid) & 8)
return 1;
- if (battle_config.pk_mode && !map[sd->bl.m].flag.nopvp && skill_db[skillid].nocast & 16)
+ if (battle_config.pk_mode && !map[sd->bl.m].flag.nopvp && skill_get_nocast (skillid) & 16)
return 1;
-
- switch (skillid) {
- case AL_WARP:
- case AL_TELEPORT:
- case MC_VENDING:
- case MC_IDENTIFY:
- return 0; // always allowed
- default:
- return(map[sd->bl.m].flag.noskill);
- }
+
+ switch (skillid) {
+ case AL_WARP:
+ case AL_TELEPORT:
+ case MC_VENDING:
+ case MC_IDENTIFY:
+ return 0; // always allowed
+ default:
+ return (map[sd->bl.m].flag.noskill);
+ }
}
@@ -888,105 +641,58 @@ static int distance(int x0,int y0,int x1,int y1)
{
int dx,dy;
- dx=abs(x0-x1);
- dy=abs(y0-y1);
- return dx>dy ? dx : dy;
+ dx = abs(x0 - x1);
+ dy = abs(y0 - y1);
+ return dx > dy ? dx : dy;
}
-/* スキルユニットIDを返す(これもデ?タベ?スに入れたいな) */
-int skill_get_unit_id(int id,int flag)
-{
+/* スキルユニットの配置情報を返す */
+struct skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT];
+int firewall_unit_pos;
+int icewall_unit_pos;
- 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 CG_MOONLIT: return 0xb5;
- case PF_FOGWALL: return 0xb6; /* フォグウォ?ル */
- case PF_SPIDERWEB: return 0xb7; /* スパイダ?ウェッブ */
- // temporary unit ID's [Celest]
- case GD_LEADERSHIP: return 0xc1;
- case GD_GLORYWOUNDS: return 0xc2;
- case GD_SOULCOLD: return 0xc3;
- case GD_HAWKEYES: return 0xc4;
- }
- return 0;
- /*
- 0x89,0x8a,0x8b 表示無し
- 0x9a 炎?性の詠唱みたいなエフェクト
- 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 =
- */
+struct skill_unit_layout *skill_get_unit_layout (int skillid, int skilllv, struct block_list *src, int x, int y)
+{
+ int pos = skill_get_unit_layout_type(skillid,skilllv);
+ int dir;
+
+ if (pos != -1)
+ return &skill_unit_layout[pos];
+
+ if (src->x == x && src->y == y)
+ dir = 2;
+ else
+ dir = map_calc_dir(src,x,y);
+
+ if (skillid == MG_FIREWALL)
+ return &skill_unit_layout [firewall_unit_pos + dir];
+ else if (skillid == WZ_ICEWALL)
+ return &skill_unit_layout [icewall_unit_pos + dir];
+
+ printf("Unknown unit layout for skill %d, %d\n",skillid,skilllv);
+ return &skill_unit_layout[0];
}
+// 0x89,0x8a,0x8b 表示無し
+// 0x9a 炎?性の詠唱みたいなエフェクト
+// 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[]={
@@ -1006,7 +712,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s
struct pet_data *pd=NULL;
int skill,skill2;
- int rate,luk;
+ int rate;
int sc_def_mdef,sc_def_vit,sc_def_int,sc_def_luk;
int sc_def_mdef2,sc_def_vit2,sc_def_int2,sc_def_luk2;
@@ -1014,102 +720,83 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s
nullpo_retr(0, src);
nullpo_retr(0, bl);
- //if(skilllv <= 0) return 0;
+ if(skillid < 0)
+ { // remove the debug print when this case is finished
+ printf("skill_additional_effect: skillid=%i\ncall: %p %p %i %i %i %i",skillid,
+ src, bl,skillid,skilllv,attack_type,tick);
+ return 0;
+ }
if(skillid > 0 && skilllv <= 0) return 0; // don't forget auto attacks! - celest
- if(src->type==BL_PC){
- nullpo_retr(0, sd=(struct map_session_data *)src);
- }else if(src->type==BL_MOB){
- nullpo_retr(0, md=(struct mob_data *)src); //未使用?
- }else if(src->type==BL_PET){
- nullpo_retr(0, pd=(struct pet_data *)src); // [Valaris]
+ 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); //未使用?
+ } else if (src->type == BL_PET){
+ nullpo_retr(0, pd = (struct pet_data *)src); // [Valaris]
+ }
+
+ if(bl->type == BL_PC) {
+ nullpo_retr(0, dstsd=(struct map_session_data *)bl);
+ } else if(bl->type == BL_MOB) {
+ nullpo_retr(0, dstmd=(struct mob_data *)bl); //未使用?
}
//?象の耐性
- 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);
+ sc_def_mdef = status_get_sc_def_mdef(bl);
+ sc_def_vit = status_get_sc_def_vit(bl);
+ sc_def_int = status_get_sc_def_int(bl);
+ sc_def_luk = status_get_sc_def_luk(bl);
+
//自分の耐性
- 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;
+ sc_def_mdef2 = status_get_sc_def_mdef(src);
+ sc_def_vit2 = status_get_sc_def_vit(src);
+ sc_def_int2 = status_get_sc_def_int(src);
+ sc_def_luk2 = status_get_sc_def_luk(src);
switch(skillid){
case 0: /* 通常攻? */
/* 自動鷹 */
- if( sd && pc_isfalcon(sd) && sd->status.weapon == 11 && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 &&
- rand()%1000 <= sd->paramc[5]*10/3+1 ) {
- int lv=(sd->status.job_level+9)/10;
- skill_castend_damage_id(src,bl,HT_BLITZBEAT,(skill<lv)?skill:lv,tick,0xf00000);
- }
- // スナッチャ?
- if(sd && sd->status.weapon != 11 && (skill=pc_checkskill(sd,RG_SNATCHER)) > 0)
- if((skill*15 + 55) + (skill2 = pc_checkskill(sd,TF_STEAL))*10 > rand()%1000) {
+ if(sd) {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ if (pc_isfalcon(sd) && sd->status.weapon == 11 && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 &&
+ rand()%1000 <= sd->paramc[5]*10/3+1 ) {
+ int lv=(sd->status.job_level+9)/10;
+ skill_castend_damage_id(src,bl,HT_BLITZBEAT,(skill<lv)?skill:lv,tick,0xf00000);
+ }
+ // スナッチャ?
+ if(sd->status.weapon != 11 && (skill=pc_checkskill(sd,RG_SNATCHER)) > 0 &&
+ (skill*15 + 55) + (skill2 = pc_checkskill(sd,TF_STEAL))*10 > rand()%1000) {
if(pc_steal_item(sd,bl))
clif_skill_nodamage(src,bl,TF_STEAL,skill2,1);
else if (battle_config.display_snatcher_skill_fail)
- clif_skill_fail(sd,skillid,0,0); // it's annoying! =p [Celest]
- }
- // エンチャントデットリ?ポイズン(猛毒?果)
- if (sd && sd->sc_data[SC_EDP].timer != -1 && rand() % 10000 < sd->sc_data[SC_EDP].val2 * sc_def_vit) {
- int mhp = battle_get_max_hp(bl);
- int hp = battle_get_hp(bl);
- int lvl = sd->sc_data[SC_EDP].val1;
- int diff;
- // MHPの1/4以下にはならない
- if(hp > mhp>>2) {
- if(bl->type == BL_PC) {
- diff = mhp*10/100;
- if (hp - diff < mhp>>2)
- diff = hp - (mhp>>2);
- pc_heal((struct map_session_data *)bl, -hp, 0);
- } else if(bl->type == BL_MOB) {
- struct mob_data *md = (struct mob_data *)bl;
- hp -= mhp*15/100;
- if (hp > mhp>>2)
- md->hp = hp;
- else
- md->hp = mhp>>2;
- }
+ clif_skill_fail(sd,skillid,0,0);
+ }
+ // enchant poison has a chance of poisoning enemy
+ if (sd->sc_data[SC_ENCPOISON].timer != -1 && sc_data && sc_data[SC_POISON].timer == -1 &&
+ rand() % 100 < sd->sc_data[SC_ENCPOISON].val1 * sc_def_vit / 100) {
+ status_change_start(bl,SC_POISON,sd->sc_data[SC_ENCPOISON].val1,
+ 0,0,0,skill_get_time2(AS_ENCHANTPOISON,sd->sc_data[SC_ENCPOISON].val1),0);
}
- skill_status_change_start(bl,SC_DPOISON,lvl,0,0,0,skill_get_time2(ASC_EDP,lvl),0);
+ // エンチャントデットリ?ポイズン(猛毒?果)
+ if (sd->sc_data[SC_EDP].timer != -1 && sc_data && sc_data[SC_DPOISON].timer == -1 &&
+ rand() % 100 < sd->sc_data[SC_EDP].val2 * sc_def_vit / 100)
+ status_change_start(bl,SC_DPOISON,sd->sc_data[SC_EDP].val1,
+ 0,0,0,skill_get_time2(ASC_EDP,sd->sc_data[SC_EDP].val1),0);
}
break;
case SM_BASH: /* バッシュ(急所攻?) */
if( sd && (skill=pc_checkskill(sd,SM_FATALBLOW))>0 ){
if( rand()%100 < 6*(skilllv-5)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(SM_FATALBLOW,skilllv),0);
+ 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(rand()%100< (2*skilllv+10)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_POISON,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ 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);
@@ -1118,122 +805,140 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s
case AS_SONICBLOW: /* ソニックブロ? */
if( rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ break;
+
+ case AS_GRIMTOOTH:
+ if (bl->type == BL_MOB) {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ if (sc_data && sc_data[SC_SLOWDOWN].timer == -1)
+ status_change_start(bl,SC_SLOWDOWN,0,0,0,0,1000,0);
+ }
break;
case HT_FREEZINGTRAP: /* フリ?ジングトラップ */
rate=skilllv*3+35;
if(rand()%100 < rate*sc_def_mdef/100)
- skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ 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(rand()%100 < rate)
- skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
- else if(sd && skillid==MG_FROSTDIVER)
- clif_skill_fail(sd,skillid,0,0);
+ {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ rate = (skilllv*3+35)*sc_def_mdef/100-(status_get_int(bl)+status_get_luk(bl))/15;
+ if (rate <= 5)
+ rate = 5;
+ if(sc_data && sc_data[SC_FREEZE].timer == -1 && rand()%100 < rate)
+ status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv)*(1-sc_def_mdef/100),0);
+ else if (sd && skillid == MG_FROSTDIVER)
+ clif_skill_fail(sd,skillid,0,0);
+ }
break;
case WZ_STORMGUST: /* スト?ムガスト */
{
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_get_sc_data(bl);
if(sc_data) {
sc_data[SC_FREEZE].val3++;
if(sc_data[SC_FREEZE].val3 >= 3)
- skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
}
break;
case HT_LANDMINE: /* ランドマイン */
if( rand()%100 < (5*skilllv+30)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ 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);
+ status_calc_pc(dstsd,0);
}
break;
case HT_SANDMAN: /* サンドマン */
if( rand()%100 < (5*skilllv+30)*sc_def_int/100 )
- skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case TF_SPRINKLESAND: /* 砂まき */
if( rand()%100 < 20*sc_def_int/100 )
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case TF_THROWSTONE: /* 石投げ */
if( rand()%100 < 7*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case CR_HOLYCROSS: /* ホ?リ?クロス */
if( rand()%100 < 3*skilllv*sc_def_int/100 )
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case CR_GRANDCROSS: /* グランドクロス */
+ case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
{
- int race = battle_get_race(bl);
- if( (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6) && rand()%100 < 100000*sc_def_int/100) //?制付?だが完全耐性には無?
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ int race = status_get_race(bl);
+ if( (battle_check_undead(race,status_get_elem_type(bl)) || race == 6) && rand()%100 < 100000*sc_def_int/100) //?制付?だが完全耐性には無?
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
break;
+ case AM_ACIDTERROR:
+ if( rand()%100 < (skilllv*3)*sc_def_vit/100 )
+ status_change_start(bl,SC_BLEEDING,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ break;
+
case CR_SHIELDCHARGE: /* シ?ルドチャ?ジ */
if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case RG_RAID: /* サプライズアタック */
if( rand()%100 < (10+3*skilllv)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
if( rand()%100 < (10+3*skilllv)*sc_def_int/100 )
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case BA_FROSTJOKE:
if(rand()%100 < (15+5*skilllv)*sc_def_mdef/100)
- skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case DC_SCREAM:
if( rand()%100 < (25+5*skilllv)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case BD_LULLABY: /* 子守唄 */
if( rand()%100 < 15*sc_def_int/100 )
- skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
/* MOBの追加?果付きスキル */
case NPC_PETRIFYATTACK:
if(rand()%100 < sc_def_mdef)
- skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_POISON:
case NPC_SILENCEATTACK:
case NPC_STUNATTACK:
if(rand()%100 < sc_def_vit && src->type!=BL_PET)
- skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
if(src->type==BL_PET)
- skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skilllv*1000,0);
+ status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skilllv*1000,0);
break;
case NPC_CURSEATTACK:
if(rand()%100 < sc_def_luk)
- skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_SLEEPATTACK:
case NPC_BLINDATTACK:
if(rand()%100 < sc_def_int)
- skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_MENTALBREAKER:
if(dstsd) {
@@ -1247,126 +952,164 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s
//
case WZ_METEOR:
if(rand()%100 < sc_def_vit)
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case WZ_VERMILION:
if(rand()%100 < sc_def_int)
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
// -- moonsoul (stun ability of new champion skill tigerfist)
//
case CH_TIGERFIST:
- if( rand()%100 < (10 + skilllv*10)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ if (rand()%100 < (10 + skilllv*10)*sc_def_vit/100) {
+ int sec = skill_get_time2 (skillid,skilllv) - status_get_agi(bl)/10;
+ if (dstsd) {
+ dstsd->canmove_tick += sec;
+ dstsd->canact_tick += sec;
+ } else if (dstmd)
+ dstmd->canmove_tick += sec;
+ }
break;
case LK_SPIRALPIERCE:
if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case ST_REJECTSWORD: /* フリ?ジングトラップ */
if( rand()%100 < (skilllv*15) )
- skill_status_change_start(bl,SC_AUTOCOUNTER,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_AUTOCOUNTER,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case PF_FOGWALL: /* ホ?リ?クロス */
- if( rand()%100 < 3*skilllv*sc_def_int/100 )
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ if (src != bl) {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ if (sc_data && sc_data[SC_DELUGE].timer == -1)
+ 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) && rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_HEADCRUSH,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ int race=status_get_race(bl);
+ if( !(battle_check_undead(race,status_get_elem_type(bl)) || race == 6) && rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
break;
case LK_JOINTBEAT: /* ジョイントビ?ト */
//?件が良く分からないので適?に
- if( rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_JOINTBEAT,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ if( rand()%100 < (5*skilllv+5)*sc_def_vit/100 )
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case PF_SPIDERWEB: /* スパイダ?ウェッブ */
{
- if(bl->type == BL_MOB)
- {
- 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);
- }
+ int sec = skill_get_time2(skillid,skilllv);
+ if(map[src->m].flag.pvp) //PvPでは拘束時間半減?
+ sec = sec/2;
+ battle_stopwalking(bl,1);
+ status_change_start(bl,SC_SPIDERWEB,skilllv,0,0,0,sec,0);
}
break;
case ASC_METEORASSAULT: /* メテオアサルト */
if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 ) //?態異常は詳細が分からないので適?に
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
if( rand()%100 < (10+3*skilllv)*sc_def_int/100 )
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ 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 );
+ status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0 );
break;
case HW_NAPALMVULCAN: /* ナパ?ムバルカン */
// skilllv*5%の確率で呪い
if (rand()%10000 < 5*skilllv*sc_def_luk)
- skill_status_change_start(bl,SC_CURSE,7,0,0,0,skill_get_time2(NPC_CURSEATTACK,7),0);
+ status_change_start(bl,SC_CURSE,7,0,0,0,skill_get_time2(NPC_CURSEATTACK,7),0);
break;
}
- if(sd && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* カ?ドによる追加?果 */
- int i;
+ if((sd||dstsd) && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* カ?ドによる追加?果 */
+ int i, type;
int sc_def_card=100;
for(i=SC_STONE;i<=SC_BLIND;i++){
+ type=i-SC_STONE;
//?象に?態異常
- if(i==SC_STONE || i==SC_FREEZE)
- sc_def_card=sc_def_mdef;
- else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE)
- sc_def_card=sc_def_vit;
- else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND)
- sc_def_card=sc_def_int;
- else if(i==SC_CURSE)
- sc_def_card=sc_def_luk;
-
- if(!sd->state.arrow_atk) {
- if(rand()%10000 < (sd->addeff[i-SC_STONE])*sc_def_card/100 ){
- if(battle_config.battle_log)
- printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
- skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
- }
+ switch (i) {
+ case SC_STONE:
+ case SC_FREEZE:
+ sc_def_card=sc_def_mdef;
+ break;
+ case SC_STAN:
+ case SC_POISON:
+ case SC_SILENCE:
+ sc_def_card=sc_def_vit;
+ break;
+ case SC_SLEEP:
+ case SC_CONFUSION:
+ case SC_BLIND:
+ sc_def_card=sc_def_int;
+ break;
+ case SC_CURSE:
+ sc_def_card=sc_def_luk;
}
- else {
- if(rand()%10000 < (sd->addeff[i-SC_STONE]+sd->arrow_addeff[i-SC_STONE])*sc_def_card/100 ){
- if(battle_config.battle_log)
- printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
- skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
+
+ if (sd) {
+ if(!sd->state.arrow_atk) {
+ if(rand()%10000 < (sd->addeff[type])*sc_def_card/100 ){
+ if(battle_config.battle_log)
+ printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[type]);
+ status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0);
+ }
+ }
+ else {
+ if(rand()%10000 < (sd->addeff[type]+sd->arrow_addeff[type])*sc_def_card/100 ){
+ if(battle_config.battle_log)
+ printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[type]);
+ status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0);
+ }
}
}
//自分に?態異常
- if(i==SC_STONE || i==SC_FREEZE)
- sc_def_card=sc_def_mdef2;
- else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE)
- sc_def_card=sc_def_vit2;
- else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND)
- sc_def_card=sc_def_int2;
- else if(i==SC_CURSE)
- sc_def_card=sc_def_luk2;
-
- if(!sd->state.arrow_atk) {
- if(rand()%10000 < (sd->addeff2[i-SC_STONE])*sc_def_card/100 ){
- if(battle_config.battle_log)
- printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
- skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
- }
+ switch (i) {
+ case SC_STONE:
+ case SC_FREEZE:
+ sc_def_card=sc_def_mdef2;
+ break;
+ case SC_STAN:
+ case SC_POISON:
+ case SC_SILENCE:
+ sc_def_card=sc_def_vit2;
+ break;
+ case SC_SLEEP:
+ case SC_CONFUSION:
+ case SC_BLIND:
+ sc_def_card=sc_def_int2;
+ break;
+ case SC_CURSE:
+ sc_def_card=sc_def_luk2;
}
- else {
- if(rand()%10000 < (sd->addeff2[i-SC_STONE]+sd->arrow_addeff2[i-SC_STONE])*sc_def_card/100 ){
- if(battle_config.battle_log)
- printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
- skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
+
+ if (sd) {
+ if(!sd->state.arrow_atk) {
+ if(rand()%10000 < (sd->addeff2[type])*sc_def_card/100 ){
+ if(battle_config.battle_log)
+ printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[type]);
+ status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0);
+ }
+ }
+ else {
+ if(rand()%10000 < (sd->addeff2[type]+sd->arrow_addeff2[type])*sc_def_card/100 ){
+ if(battle_config.battle_log)
+ printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[type]);
+ status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0);
+ }
}
}
+ if (dstsd && rand()%10000 < dstsd->addeff3[type]*sc_def_card/100){
+ if (dstsd->addeff3_type[type] != 1 && ((sd && !sd->state.arrow_atk) || (status_get_range(src)<=2)))
+ continue;
+ if(battle_config.battle_log)
+ printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,dstsd->addeff3[type]);
+ status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0);
+ }
}
}
return 0;
@@ -1379,7 +1122,7 @@ 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 dir,ret,prev_state=MS_IDLE;
int moveblock;
struct map_session_data *sd=NULL;
struct mob_data *md=NULL;
@@ -1390,25 +1133,24 @@ int skill_blown( struct block_list *src, struct block_list *target,int count)
nullpo_retr(0, target);
if(target->type==BL_PC){
- nullpo_retr(0, sd=(struct map_session_data *)target);
+ sd=(struct map_session_data *)target;
}else if(target->type==BL_MOB){
- nullpo_retr(0, md=(struct mob_data *)target);
+ md=(struct mob_data *)target;
}else if(target->type==BL_PET){
- nullpo_retr(0, pd=(struct pet_data *)target);
+ pd=(struct pet_data *)target;
}else if(target->type==BL_SKILL){
- nullpo_retr(0, su=(struct skill_unit *)target);
+ su=(struct skill_unit *)target;
}else return 0;
- if(!(count&0x10000 && (sd||md||pd||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];
- }
+ if (count&0xf00000)
+ dir = (count>>20)&0xf;
+ else if (count&0x10000 || (target->x==src->x && target->y==src->y))
+ dir = status_get_dir(target);
+ else
+ dir = map_calc_dir(target,src->x,src->y);
+ if (dir>=0 && dir<8){
+ dx = -dirx[dir];
+ dy = -diry[dir];
}
ret=path_blownpos(target->m,x,y,dx,dy,count&0xffff);
@@ -1456,18 +1198,13 @@ int skill_blown( struct block_list *src, struct block_list *target,int count)
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;
- if(sg)
- skill_unit_move_unit_group(sg,target->m,dx,dy);
- }
-*/
+ int tick = gettick();
+ skill_unit_move(target,tick,0);
+ if(moveblock) map_delblock(target);
+ target->x=nx;
+ target->y=ny;
+ if(moveblock) map_addblock(target);
+ skill_unit_move(target,tick,1);
}
if(sd) { /* ?面?に入ってきたので表示 */
@@ -1486,8 +1223,6 @@ int skill_blown( struct block_list *src, struct block_list *target,int count)
pd->state.state = prev_state;
}
- skill_unit_move(target,gettick(),(count&0xffff)+7); /* スキルユニットの判定 */
-
return 0;
}
@@ -1510,15 +1245,16 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
struct Damage dmg;
struct status_change *sc_data;
int type,lv,damage;
+ static int tmpdmg = 0;
- if(skilllv <= 0) return 0;
+ if(skillid > 0 && skilllv <= 0) return 0;
rdamage = 0;
nullpo_retr(0, src);
nullpo_retr(0, dsrc);
nullpo_retr(0, bl);
- sc_data = battle_get_sc_data(bl);
+ sc_data = status_get_sc_data(bl);
//何もしない判定ここから
if(dsrc->m != bl->m) //?象が同じマップにいなければ何もしない
@@ -1527,11 +1263,11 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
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ですでに死んでいたら何もしない
+ if(src != dsrc && 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(bl->type == BL_PC && skillnotok(skillid, (struct map_session_data *) bl))
+ if(bl->type == BL_PC && 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) //スキルの?性が地?性でなければ何もしない
@@ -1562,27 +1298,30 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
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)); //
+ struct map_session_data *sd = (struct map_session_data *)bl;
+ if (sd) {
+ 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(sd->status.sp + sp > sd->status.max_sp) { //回復SP+現在のSPがMSPより大きい場合
+ sp = sd->status.max_sp - sd->status.sp; //SPをMSP-現在SPにする
+ sd->status.sp = sd->status.max_sp; //現在のSPにMSPを代入
+ }
+ else //回復SP+現在のSPがMSPより小さい場合は回復SPを加算
+ sd->status.sp += sp;
+ clif_heal(sd->fd,SP_SP,sp); //SP回復エフェクトの表示
+ sd->canact_tick = tick + skill_delayfix(bl, skill_get_delay(SA_MAGICROD,sc_data[SC_MAGICROD].val1)); //
+ }
}
clif_skill_nodamage(bl,bl,SA_MAGICROD,sc_data[SC_MAGICROD].val1,1); //マジックロッドエフェクトを表示
}
//マジックロッド?理ここまで
if(src->type==BL_PET) { // [Valaris]
- dmg.damage=battle_attr_fix(skilllv, skill_get_pl(skillid), battle_get_element(bl) );
+ dmg.damage=battle_attr_fix(skilllv, skill_get_pl(skillid), status_get_element(bl) );
dmg.damage2=0;
}
@@ -1597,7 +1336,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
if(damage <= 0 || damage < dmg.div_) //吹き飛ばし判定?※
dmg.blewcount = 0;
- if(skillid == CR_GRANDCROSS) {//グランドクロス
+ if(skillid == CR_GRANDCROSS||skillid == NPC_DARKGRANDCROSS) {//グランドクロス
if(battle_config.gx_disptype) dsrc = src; // 敵ダメ?ジ白文字表示
if( src == bl) type = 4; // 反動はダメ?ジモ?ションなし
}
@@ -1608,12 +1347,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
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より小さい場合
+ int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src); //基本ディレイの計算
+ if(damage < status_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); //コンボ?態に
+ 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); //コンボディレイパケットの送信
@@ -1621,8 +1360,8 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
//連打掌(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)) {
+ int delay = 700 - 4 * status_get_agi(src) - 2 * status_get_dex(src);
+ if(damage < status_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) ||
@@ -1630,7 +1369,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
(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); //コンボ?態に
+ 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); //コンボディレイパケットの送信
@@ -1638,12 +1377,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
//猛龍拳(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)) {
+ int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src);
+ if(damage < status_get_hp(bl)) {
if(pc_checkskill(sd, CH_CHAINCRUSH) > 0) //連柱崩?(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); //コンボ?態に
+ 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); //コンボディレイパケットの送信
@@ -1651,13 +1390,13 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
//伏虎拳(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)) {
+ int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src);
+ if(damage < status_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); //コンボ?態に
+ 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); //コンボディレイパケットの送信
@@ -1708,23 +1447,32 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
//武器スキル?ここまで
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 ASC_BREAKER: // [celest]
+ if (attack_type&BF_MAGIC) { // only display damage for the 2nd attack
+ if (damage + tmpdmg != 0) // if both attacks missed, do not display a 2nd 'miss'
+ clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, damage+tmpdmg, dmg.div_, skillid, skilllv, type);
+ tmpdmg = 0; // clear the temporary damage
+ } else {
+ if (damage == 0) // if weapon attack missed, display the 'miss'
+ clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, 0, dmg.div_, skillid, skilllv, type);
+ tmpdmg = damage; // store the temporary weapon damage
+ }
+ break;
case NPC_SELFDESTRUCTION:
case NPC_SELFDESTRUCTION2:
break;
+ case SN_SHARPSHOOTING:
+ clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,0,0,0);
+ break;
default:
clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, (skillid==0)? 5:type );
}
- 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 (dmg.blewcount > 0 && bl->type!=BL_SKILL && !map[src->m].flag.gvg) {
+ skill_blown(dsrc,bl,dmg.blewcount);
if(bl->type == BL_MOB)
clif_fixmobpos((struct mob_data *)bl);
else if(bl->type == BL_PET)
@@ -1735,28 +1483,31 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
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);
+ if (skillid || flag) {
+ if (attack_type&BF_WEAPON)
+ battle_delay_damage(tick+dmg.amotion,src,bl,damage,0);
+ else
+ battle_damage(src,bl,damage,0);
+ }
+ if(skillid == RG_INTIMIDATE && damage > 0 && !(status_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) {
+ int s_lv = status_get_lv(src),t_lv = status_get_lv(bl);
int rate = 50 + skilllv * 5;
rate = rate + (s_lv - t_lv);
if(rand()%100 < rate)
skill_addtimerskill(src,tick + 800,bl->id,0,0,skillid,skilllv,0,flag);
}
- if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM) && sc_data[SC_PRESERVE].timer != -1){
+ if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM) && sc_data[SC_PRESERVE].timer == -1){
struct map_session_data *tsd = (struct map_session_data *)bl;
nullpo_retr(0, tsd);
- if(!tsd->status.skill[skillid].id && !tsd->status.skill[skillid].id
- && !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER) ){
+ if(!tsd->status.skill[skillid].id && !tsd->status.skill[skillid].lv
+ && !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER)
+ && !(skillid > NPC_SELFDESTRUCTION2 && skillid < NPC_UNDEADATTACK)){
//?に?んでいるスキルがあれば該?スキルを消す
- if (tsd->cloneskill_id && tsd->cloneskill_lv && tsd->status.skill[tsd->cloneskill_id].flag==13){
+ if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag==13){
tsd->status.skill[tsd->cloneskill_id].id=0;
- tsd->status.skill[tsd->cloneskill_id].lv=0;
tsd->status.skill[tsd->cloneskill_id].flag=0;
}
tsd->cloneskill_id=skillid;
- tsd->cloneskill_lv=skilllv;
tsd->status.skill[skillid].id=skillid;
tsd->status.skill[skillid].lv=(pc_checkskill(tsd,RG_PLAGIARISM) > skill_get_max(skillid))?
skill_get_max(skillid):pc_checkskill(tsd,RG_PLAGIARISM);
@@ -1766,13 +1517,11 @@ 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スキル */
- {
+ if(!status_isdead(bl)) {
+ 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)
@@ -1814,16 +1563,23 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
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(hp || sp)
+ pc_heal(sd,hp,sp);
+ if (sd->sp_drain_type && bl->type == BL_PC)
+ battle_heal(NULL,bl,0,-sp,0);
}
- if((skillid != KN_BOWLINGBASH || flag) && rdamage > 0)
- battle_damage(bl,src,rdamage,0);
+ if ((skillid || flag) && rdamage>0) {
+ if (attack_type&BF_WEAPON)
+ battle_delay_damage(tick+dmg.amotion,bl,src,rdamage,0);
+ else
+ battle_damage(bl,src,rdamage,0);
+ }
if(attack_type&BF_WEAPON && sc_data && sc_data[SC_AUTOCOUNTER].timer != -1 && sc_data[SC_AUTOCOUNTER].val4 > 0) {
if(sc_data[SC_AUTOCOUNTER].val3 == dsrc->id)
battle_weapon_attack(bl,dsrc,tick,0x8000|sc_data[SC_AUTOCOUNTER].val1);
- skill_status_change_end(bl,SC_AUTOCOUNTER,-1);
+ status_change_end(bl,SC_AUTOCOUNTER,-1);
}
map_freeblock_unlock();
@@ -1870,9 +1626,8 @@ int skill_area_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;
+ int *c;
+ int skillid,unit_id;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
@@ -1885,57 +1640,46 @@ static int skill_check_unit_range_sub( struct block_list *bl,va_list ap )
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);
+ unit_id = unit->group->unit_id;
- if(skillid == MG_SAFETYWALL || skillid == AL_PNEUMA) {
- if(unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85)
+ if (skillid==MG_SAFETYWALL || skillid==AL_PNEUMA) {
+ if(unit_id != 0x7e && 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)
+ } else if (skillid==AL_WARP) {
+ if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92)
return 0;
- }
- else if((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP) || skillid == HT_TALKIEBOX) {
- if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92)
+ } else if ((skillid>=HT_SKIDTRAP && skillid<=HT_CLAYMORETRAP) || skillid==HT_TALKIEBOX) {
+ if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92)
return 0;
- }
- else if(skillid == WZ_FIREPILLAR) {
- if(unit->group->unit_id != 0x87)
+ } else if (skillid==WZ_FIREPILLAR) {
+ if (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)++;
+ } else if (skillid==HP_BASILICA) {
+ if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92 && unit_id!=0x83)
+ return 0;
+ } else
+ return 0;
+
+ (*c)++;
return 0;
}
-int skill_check_unit_range(int m,int x,int y,int range,int skillid)
+int skill_check_unit_range(int m,int x,int y,int skillid,int skilllv)
{
int c = 0;
+ int range = skill_get_unit_range(skillid);
+ int layout_type = skill_get_unit_layout_type(skillid,skilllv);
+ if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) {
+ printf("skill_check_unit_range: unsupported layout type %d for skill %d\n",layout_type,skillid);
+ return 0;
+ }
- map_foreachinarea(skill_check_unit_range_sub,m,x-10,y-10,x+10,y+10,BL_SKILL,&c,x,y,range,skillid);
+ // とりあえず正方形のユニットレイアウトのみ対応
+ range += layout_type;
+ map_foreachinarea(skill_check_unit_range_sub,m,
+ x-range,y-range,x+range,y+range,BL_SKILL,&c,skillid);
return c;
}
@@ -1943,6 +1687,8 @@ int skill_check_unit_range(int m,int x,int y,int range,int skillid)
static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap )
{
int *c;
+ int skillid;
+
nullpo_retr(0, bl);
nullpo_retr(0, ap);
@@ -1954,32 +1700,117 @@ static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap )
if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))
return 0;
+ skillid = va_arg(ap,int);
+ if (skillid==HP_BASILICA && bl->type==BL_PC)
+ return 0;
+
(*c)++;
return 0;
}
-int skill_check_unit_range2(int m,int x,int y,int range)
+int skill_check_unit_range2(struct block_list *bl, int m,int x,int y,int skillid, int skilllv)
{
- int c = 0;
+ int c = 0, range, type;
+
+ switch (skillid) { // to be expanded later
+ case WZ_ICEWALL:
+ range = 2;
+ break;
+ default:
+ {
+ int layout_type = skill_get_unit_layout_type(skillid,skilllv);
+ if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) {
+ printf("skill_check_unit_range2: unsupported layout type %d for skill %d\n",layout_type,skillid);
+ return 0;
+ }
+ // とりあえず正方形のユニットレイアウトのみ対応
+ range = skill_get_unit_range(skillid) + layout_type;
+ }
+ break;
+ }
- map_foreachinarea(skill_check_unit_range2_sub,m,x-range,y-range,x+range,y+range,0,&c);
+ // if the caster is a monster/NPC, only check for players
+ // otherwise just check everything
+ if (bl->type == BL_PC)
+ type = 0;
+ else type = BL_PC;
+
+ map_foreachinarea(skill_check_unit_range2_sub, m,
+ x - range, y - range, x + range, y + range,
+ type, &c, skillid);
return c;
}
+int skill_guildaura_sub (struct block_list *bl,va_list ap)
+{
+ struct map_session_data *sd;
+ struct guild *g;
+ int gid, id;
+ int flag = 0;
+
+ nullpo_retr(0, sd=(struct map_session_data *)bl);
+
+ nullpo_retr(0, ap);
+ id = va_arg(ap,int);
+ gid = va_arg(ap,int);
+ if (sd->status.guild_id != gid)
+ return 0;
+
+ g = va_arg(ap,struct guild *);
+ if (guild_checkskill(g, GD_LEADERSHIP)>0) flag |= 1<<0;
+ if (guild_checkskill(g, GD_GLORYWOUNDS)>0) flag |= 1<<1;
+ if (guild_checkskill(g, GD_SOULCOLD)>0) flag |= 1<<2;
+ if (guild_checkskill(g, GD_HAWKEYES)>0) flag |= 1<<3;
+ if (guild_checkskill(g, GD_CHARISMA)>0) flag |= 1<<4;
+
+ if (flag > 0) {
+ if (sd->sc_count && sd->sc_data[SC_GUILDAURA].timer != -1) {
+ if (sd->sc_data[SC_GUILDAURA].val4 != flag) {
+ sd->sc_data[SC_GUILDAURA].val4 = flag;
+ status_calc_pc (sd, 0);
+ }
+ return 0;
+ }
+ status_change_start(&sd->bl, SC_GUILDAURA,1,id,0,flag,0,0 );
+ }
+
+ return 0;
+}
+
/*=========================================================================
* 範?スキル使用?理小分けここから
*/
/* ?象の?をカウントする。(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)
{
- if(skilllv <= 0) return 0;
if(skill_area_temp[0] < 0xffff)
skill_area_temp[0]++;
return 0;
}
+int skill_count_water(struct block_list *src,int range)
+{
+ int i,x,y,cnt = 0,size = range*2+1;
+ struct skill_unit *unit;
+
+ for (i=0;i<size*size;i++) {
+ x = src->x+(i%size-range);
+ y = src->y+(i/size-range);
+ if (map_getcell(src->m,x,y,CELL_CHKWATER)) {
+ cnt++;
+ continue;
+ }
+ unit = map_find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL);
+ if (unit) {
+ cnt++;
+ skill_delunit(unit);
+ }
+ }
+ return cnt;
+}
+
/*==========================================
*
*------------------------------------------
@@ -2017,6 +1848,10 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data )
nullpo_retr(0, skl);
skl->timer = -1;
+ if (sd) {
+ sd->timerskill_count--;
+ }
+
if(skl->target_id) {
struct block_list tbl;
target = map_id2bl(skl->target_id);
@@ -2045,13 +1880,13 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data )
break;
case RG_INTIMIDATE:
if(sd && !map[src->m].flag.noteleport) {
- int x,y,i,j,c;
+ int x,y,i,j;
pc_randomwarp(sd,3);
for(i=0;i<16;i++) {
j = rand()%8;
x = sd->bl.x + dirx[j];
y = sd->bl.y + diry[j];
- if((c=map_getcell(sd->bl.m,x,y)) != 1 && c != 5)
+ if(map_getcell(sd->bl.m,x,y,CELL_CHKPASS))
break;
}
if(i >= 16) {
@@ -2066,13 +1901,13 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data )
}
}
else if(md && !map[src->m].flag.monster_noteleport) {
- int x,y,i,j,c;
+ int x,y,i,j;
mob_warp(md,-1,-1,-1,3);
for(i=0;i<16;i++) {
j = rand()%8;
x = md->bl.x + dirx[j];
y = md->bl.y + diry[j];
- if((c=map_getcell(md->bl.m,x,y)) != 1 && c != 5)
+ if(map_getcell(md->bl.m,x,y,CELL_CHKPASS))
break;
}
if(i >= 16) {
@@ -2090,11 +1925,26 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data )
case BA_FROSTJOKE: /* 寒いジョ?ク */
case DC_SCREAM: /* スクリ?ム */
- range=15; //視界全?
+ range=battle_config.area_size; //視界全?
map_foreachinarea(skill_frostjoke_scream,src->m,src->x-range,src->y-range,
src->x+range,src->y+range,0,src,skl->skill_id,skl->skill_lv,tick);
break;
+ case WZ_WATERBALL:
+ if (skl->type>1) {
+ skl->timer = 0; // skill_addtimerskillで使用されないように
+ skill_addtimerskill(src,tick+150,target->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag);
+ skl->timer = -1;
+ }
+ skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
+ if (skl->type <= 1) { // partial fix: it still doesn't end if the target dies
+ // should put outside of the switch, but since this is the only
+ // mage targetted spell for now,
+ struct status_change *sc_data = status_get_sc_data(src);
+ if(sc_data && sc_data[SC_MAGICPOWER].timer != -1) //マジックパワ?の?果終了
+ status_change_end(src,SC_MAGICPOWER,-1);
+ }
+ break;
default:
skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
break;
@@ -2143,6 +1993,7 @@ int skill_addtimerskill(struct block_list *src,unsigned int tick,int target,int
sd->skilltimerskill[i].y = y;
sd->skilltimerskill[i].type = type;
sd->skilltimerskill[i].flag = flag;
+ sd->timerskill_count++;
return 0;
}
@@ -2207,10 +2058,15 @@ int skill_cleartimerskill(struct block_list *src)
if(src->type == BL_PC) {
struct map_session_data *sd = (struct map_session_data *)src;
nullpo_retr(0, sd);
+
+ if (sd->timerskill_count <= 0)
+ return 0;
+
for(i=0;i<MAX_SKILLTIMERSKILL;i++) {
if(sd->skilltimerskill[i].timer != -1) {
delete_timer(sd->skilltimerskill[i].timer, skill_timerskill);
sd->skilltimerskill[i].timer = -1;
+ sd->timerskill_count--;
}
}
}
@@ -2237,27 +2093,37 @@ 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;
- struct status_change *sc_data = battle_get_sc_data(src);
+ struct map_session_data *sd = NULL, *tsd = NULL;
+ struct status_change *sc_data;
int i;
- if(skilllv <= 0) return 0;
+ if(skillid < 0)
+ { // remove the debug print when this case is finished
+ printf("skill_castend_damage_id: skillid=%i\ncall: %p %p %i %i %i %i",skillid,
+ src, bl,skillid,skilllv,tick,flag);
+ return 0;
+ }
+ if(skillid > 0 && skilllv <= 0) return 0;
nullpo_retr(1, src);
nullpo_retr(1, bl);
- if(src->type==BL_PC)
- sd=(struct map_session_data *)src;
- if(sd && pc_isdead(sd))
+ sc_data = status_get_sc_data(src);
+
+ 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)
+ if ((skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl)
bl = src;
- if(bl->prev == NULL)
+ if (bl->prev == NULL)
return 1;
- if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))
+ if (bl->type == BL_PC)
+ tsd = (struct map_session_data *)bl;
+ if (tsd && pc_isdead(tsd))
return 1;
map_freeblock_lock();
@@ -2270,10 +2136,10 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
case AS_SONICBLOW: /* ソニックブロ? */
case KN_PIERCE: /* ピア?ス */
case KN_SPEARBOOMERANG: /* スピアブ?メラン */
+ case KN_BRANDISHSPEAR: /* ブランディッシュスピア */
case TF_POISON: /* インベナム */
case TF_SPRINKLESAND: /* 砂まき */
case AC_CHARGEARROW: /* チャ?ジアロ? */
- case KN_SPEARSTAB: /* スピアスタブ */
case RG_RAID: /* サプライズアタック */
case RG_INTIMIDATE: /* インティミデイト */
case BA_MUSICALSTRIKE: /* ミュ?ジカルストライク */
@@ -2282,7 +2148,6 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
case CR_HOLYCROSS: /* ホ?リ?クロス */
case CR_SHIELDCHARGE:
case CR_SHIELDBOOMERANG:
-
/* 以下MOB?用 */
/* ??攻?、SP減少攻?、遠距離攻?、防御無視攻?、多段攻? */
case NPC_PIERCINGATT:
@@ -2311,187 +2176,195 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
case NPC_HOLYATTACK:
case NPC_DARKNESSATTACK:
case NPC_TELEKINESISATTACK:
+ case NPC_UNDEADATTACK:
+ case NPC_BREAKARMOR:
+ case NPC_BREAKWEAPON:
+ case NPC_BREAKHELM:
+ case NPC_BREAKSHIELD:
case LK_AURABLADE: /* オ?ラブレ?ド */
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: /* マジッククラッシャ? */
+ case ASC_METEORASSAULT: /* メテオアサルト */
+ case ITM_TOMAHAWK:
+ case MO_COMBOFINISH: /* 猛龍拳 */
+ case CH_CHAINCRUSH: /* 連柱崩? */
+ case CH_PALMSTRIKE: /* 猛虎硬派山 */
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
break;
+
+ case ASC_BREAKER: /* ソウルブレ?カ? */ // [DracoRPG]
+ // separate weapon and magic attacks
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
+ break;
+
+ case SN_SHARPSHOOTING: /* シャ?プシュ?ティング */
+ map_foreachinpath (skill_attack_area,src->m, // function, map
+ src->x,src->y, // source xy
+ bl->x,bl->y, // target xy
+ 2,0, // range, type
+ BF_WEAPON,src,src,skillid,skilllv,tick,flag,BCT_ENEMY); // varargs
+ break;
+
+ case PA_PRESSURE: /* プレッシャ? */
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ if (rand()%100 < 50)
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0);
+ else
+ status_change_start(bl,SC_BLEEDING,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0);
+ if (tsd) {
+ int sp = tsd->status.max_sp * 10 * skilllv / 100;
+ if (sp > tsd->status.sp) sp = tsd->status.sp;
+ tsd->status.sp -= sp;
+ clif_updatestatus(tsd,SP_SP);
+ }
+ break;
+
case NPC_DARKBREATH:
clif_emotion(src,7);
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
break;
+
case MO_INVESTIGATE: /* ?勁 */
{
- struct status_change *sc_data = 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);
+ if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+ 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 if(bl->type == BL_PET)
- clif_fixpetpos((struct pet_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);
+ int dir = map_calc_dir(src,bl->x,bl->y), t_dir = status_get_dir(bl);
+ int dist = distance(src->x, src->y, bl->x, bl->y);
+ if ((dist > 0 && !map_check_dir(dir, t_dir)) || bl->type == BL_SKILL) {
+ if (sc_data && sc_data[SC_HIDING].timer != -1)
+ status_change_end(src, SC_HIDING, -1); // ハイディング解除
+ skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag);
dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest]
- if (bl->type == BL_PC)
- ((struct map_session_data *)bl)->dir=dir;
- else if (bl->type == BL_MOB)
- ((struct mob_data *)bl)->dir=dir;
- //skill_blown(src,bl,skill_get_blewcount(skillid,skilllv));
+ if (tsd)
+ tsd->dir = dir;
+ else if (bl->type == BL_MOB) {
+ struct mob_data *md = (struct mob_data *)bl;
+ if (md) md->dir = dir;
+ }
+ clif_changed_dir(bl);
}
- else if(src->type == BL_PC)
+ else if (sd)
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 && rand()%100 < skill_get_time(skillid,skilllv) && battle_config.equipment_breaking)
- pc_breakarmor((struct map_session_data *)bl);
+ skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag);
+ if (tsd && battle_config.equipment_breaking && rand()%100 < skill_get_time(skillid,skilllv)) {
+ pc_breakarmor(tsd);
+ clif_emotion(bl, 23);
+ }
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;
- }
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ if (battle_config.finger_offensive_type && 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);
+ if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+ 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);
+ if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+ status_change_end(src,SC_BLADESTOP,-1);
}
break;
- case MO_COMBOFINISH: /* 猛龍拳 */
+
case CH_TIGERFIST: /* 伏虎拳 */
- case CH_CHAINCRUSH: /* 連柱崩? */
- case CH_PALMSTRIKE: /* 猛虎硬派山 */
+ if (tsd && !(map[bl->m].flag.gvg || map[bl->m].flag.pvp)) {
+ map_freeblock_unlock();
+ return 1;
+ }
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;
- 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;
+ if(dx > 0) dx++;
+ else if(dx < 0) dx--;
+ if (dy > 0) dy++;
+ else if(dy < 0) dy--;
+ if(dx == 0 && dy == 0) dx++;
+ if (path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
+ dx = bl->x - sd->bl.x;
+ dy = bl->y - sd->bl.y;
+ if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ break;
+ }
}
+ sd->to_x = sd->bl.x + dx;
+ sd->to_y = sd->bl.y + dy;
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ clif_walkok(sd);
+ clif_movechar(sd);
+ if(dx < 0) dx = -dx;
+ if(dy < 0) dy = -dy;
+ sd->attackabletime = sd->canmove_tick = tick + 100 + sd->speed * ((dx > dy)? dx:dy);
+ if(sd->canact_tick < sd->canmove_tick)
+ sd->canact_tick = sd->canmove_tick;
+ pc_movepos(sd,sd->to_x,sd->to_y);
+ status_change_end(&sd->bl,SC_COMBO,-1);
}
- 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);
+ else
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ status_change_end(src, SC_EXPLOSIONSPIRITS, -1);
+ if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+ status_change_end(src,SC_BLADESTOP,-1);
}
break;
+
/* 武器系範?攻?スキル */
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 );
+ 0x0500);
}
- }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;
-
- // meteor assault cast effect (not sure how else to properly add it =p) [Celest]
- if (skillid == ASC_METEORASSAULT)
- clif_specialeffect(&sd->bl,409, 1);
-
+ } else {
+ int ar = 1;
+ int x = bl->x, y = bl->y;
+ switch (skillid) {
+ case AC_SHOWER:
+ ar=2;
+ break;
+ case NPC_SPLASHATTACK:
+ ar=3;
+ break;
+ }
+
skill_area_temp[1]=bl->id;
skill_area_temp[2]=x;
skill_area_temp[3]=y;
@@ -2502,13 +2375,24 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
bl->m,x-ar,y-ar,x+ar,y+ar,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
- if (skillid == SM_MAGNUM) // fire element for 10 seconds
- skill_status_change_start(src,SC_FLAMELAUNCHER,0,0,0,0,10000,0);
}
- if (bl->type == BL_MOB && skillid == AS_GRIMTOOTH) {
- struct status_change *sc_data = battle_get_sc_data(bl);
- if (sc_data && sc_data[SC_SLOWDOWN].timer == -1)
- skill_status_change_start(bl,SC_SLOWDOWN,0,0,0,0,1000,0);
+ break;
+
+ case SM_MAGNUM: /* マグナムブレイク [celest] */
+ if(flag&1 && bl->id != skill_area_temp[1]){
+ int dist = distance (bl->x, bl->y, skill_area_temp[2], skill_area_temp[3]);
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,
+ 0x0500|dist);
+ } else {
+ skill_area_temp[1]=src->id;
+ skill_area_temp[2]=src->x;
+ skill_area_temp[3]=src->y;
+ map_foreachinarea(skill_area_sub,
+ src->m,src->x-2,src->y-2,src->x+2,src->y+2,0,
+ src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
+ skill_castend_damage_id);
+ status_change_start (src,SC_FLAMELAUNCHER,0,0,0,0,10000,0);
+ clif_skill_nodamage (src,src,skillid,skilllv,1);
}
break;
@@ -2517,13 +2401,11 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
/* 個別にダメ?ジを?える */
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) {
+ } else {
int i,c; /* 他人から聞いた動きなので間違ってる可能性大&?率が?いっす>< */
+ /* まずターゲットに攻撃を加える */
+ if (!skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0))
+ break;
c = skill_get_blewcount(skillid,skilllv);
if(map[bl->m].flag.gvg) c = 0;
for(i=0;i<c;i++){
@@ -2542,24 +2424,42 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
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);
+ }
+ break;
+
+ case KN_SPEARSTAB: /* スピアスタブ */
+ if(flag&1){
+ /* 個別にダメージを与える */
+ if (bl->id==skill_area_temp[1])
+ break;
+ if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500))
+ skill_blown(src,bl,skill_area_temp[2]);
+ } else {
+ int x=bl->x,y=bl->y,i,dir;
+ /* まずターゲットに攻撃を加える */
+ dir = map_calc_dir(bl,src->x,src->y);
+ skill_area_temp[1] = bl->id;
+ skill_area_temp[2] = skill_get_blewcount(skillid,skilllv)|dir<<20;
+ if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0))
+ skill_blown(src,bl,skill_area_temp[2]);
+ for (i=0;i<4;i++) {
+ map_foreachinarea(skill_area_sub,bl->m,x,y,x,y,0,
+ src,skillid,skilllv,tick,flag|BCT_ENEMY|1,
+ skill_castend_damage_id);
+ x += dirx[dir];
+ y += diry[dir];
}
- 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)))
+ if(bl->type != BL_PC && battle_check_undead(status_get_race(bl),status_get_elem_type(bl)))
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
else {
map_freeblock_unlock();
@@ -2569,67 +2469,95 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
/* 魔法系スキル */
case MG_SOULSTRIKE: /* ソウルストライク */
- case MG_COLDBOLT: /* コ?ルドボルト */
- case MG_FIREBOLT: /* ファイア?ボルト */
+ case NPC_DARKSOULSTRIKE: /*闇ソウルストライク*/
+ 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 WZ_EARTHSPIKE: /* アーススパイク */
+ case AL_HEAL: /* ヒール */
+ case AL_HOLYLIGHT: /* ホーリーライト */
+ case WZ_JUPITEL: /* ユピテルサンダー */
+ case NPC_DARKJUPITEL: /*闇ユピテル*/
case NPC_MAGICALATTACK: /* MOB:魔法打?攻? */
case PR_ASPERSIO: /* アスペルシオ */
-// case HW_NAPALMVULCAN: /* ナパームバルカン */
+ case MG_FROSTDIVER: /* フロストダイバー */
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);
+ if (skilllv>1) {
+ int cnt,range;
+ range = skilllv>5?2:skilllv/2;
+ if (sd)
+ cnt = skill_count_water(src,range)-1;
+ else
+ cnt = skill_get_num(skillid,skilllv)-1;
+ if (cnt>0)
+ skill_addtimerskill(src,tick+150,bl->id,0,0,
+ skillid,skilllv,cnt,flag);
+ }
break;
case PR_BENEDICTIO: /* 聖?降福 */
- if(battle_get_race(bl)==1 || battle_get_race(bl)==6)
+ if(status_get_race(bl)==1 || status_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){
+ case WZ_SIGHTRASHER: /* サイトラッシャー */
+ 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);
+ if (bl->id != skill_area_temp[1]){
+ if(skillid == MG_FIREBALL){ /* ファイヤ?ボ?ルなら中心からの距離を計算 */
+ skill_area_temp[0] = distance(bl->x, bl->y, skill_area_temp[2], skill_area_temp[3]);
}
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
skill_area_temp[0]| 0x0500);
}
- }else{
- int ar=(skillid==MG_NAPALMBEAT)?1:2;
+ } else {
+ int ar;
+ skill_area_temp[0]=0;
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;
+ switch (skillid) {
+ case MG_NAPALMBEAT:
+ ar = 1;
+ /* ナパームビートは分散ダメージなので敵の数を数える */
+ map_foreachinarea(skill_area_sub,
+ bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0,
+ src,skillid,skilllv,tick,flag|BCT_ENEMY,
+ skill_area_sub_count);
+ break;
+ case MG_FIREBALL:
+ ar = 2;
+ skill_area_temp[2]=bl->x;
+ skill_area_temp[3]=bl->y;
+ /* ターゲットに攻撃を加える(スキルエフェクト表示) */
+ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
+ skill_area_temp[0]);
+ break;
+ case WZ_SIGHTRASHER:
+ default:
+ ar = 3;
+ bl = src;
+ status_change_end(src,SC_SIGHT,-1);
+ break;
}
- /* まずタ?ゲットに攻?を加える */
- skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
- skill_area_temp[0] );
- /* その後タ?ゲット以外の範??の敵全?に?理を行う */
+ if (skillid==WZ_SIGHTRASHER) {
+ /* スキルエフェクト表示 */
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ } else {
+ /* ターゲットに攻撃を加える(スキルエフェクト表示) */
+ 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);
+ 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;
@@ -2663,15 +2591,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
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);
- map_foreachinarea(skill_attack_area,src->m,src->x-5,bl->y-5,bl->x+5,bl->y+5,0,BF_MAGIC,src,src,skillid,skilllv,tick,flag,BCT_ENEMY);
- break;
-
- case WZ_SIGHTRASHER:
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
- skill_status_change_end(src,SC_SIGHT,-1);
+ map_foreachinarea(skill_attack_area,src->m,src->x-5,bl->y-5,bl->x+5,bl->y+5,0,BF_MAGIC,src,src,skillid,skilllv,tick,flag,BCT_ENEMY);
break;
/* その他 */
@@ -2697,6 +2617,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
break;
case CR_GRANDCROSS: /* グランドクロス */
+ case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
/* スキルユニット配置 */
skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
if(sd)
@@ -2710,6 +2631,32 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,0 );
break;
+ // Celest
+ case PF_SOULBURN:
+ {
+ int per = skilllv < 5 ? 20+ skilllv*10 : 60;
+ if (rand()%100 < per) {
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if (skilllv == 5)
+ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,0 );
+ if (tsd && (map[src->m].flag.pvp || map[src->m].flag.gvg)) {
+ tsd->status.sp = 0;
+ clif_updatestatus(tsd,SP_SP);
+ }
+ } else {
+ clif_skill_nodamage(src,src,skillid,skilllv,1);
+ if (skilllv == 5)
+ skill_attack(BF_MAGIC,src,src,src,skillid,skilllv,tick,0 );
+ if (sd) {
+ sd->status.sp = 0;
+ clif_updatestatus(sd,SP_SP);
+ }
+ }
+ if (sd)
+ pc_blockskill_start (sd, skillid, (skilllv < 5 ? 10000: 15000));
+ }
+ break;
+
case NPC_SELFDESTRUCTION: /* 自爆 */
case NPC_SELFDESTRUCTION2: /* 自爆2 */
if(flag&1){
@@ -2726,7 +2673,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
struct mob_data *md;
if((md=(struct mob_data *)src)){
skill_area_temp[1]=bl->id;
- skill_area_temp[2]=battle_get_hp(src);
+ skill_area_temp[2]=status_get_hp(src);
clif_skill_nodamage(src,src,NPC_SELFDESTRUCTION,-1,1);
map_foreachinarea(skill_area_sub,
bl->m,bl->x-5,bl->y-5,bl->x+5,bl->y+5,0,
@@ -2754,6 +2701,14 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
}
}
break;
+
+ // unknown skills [Celest]
+ case NPC_BIND:
+ case NPC_EXPLOSIONSPIRITS:
+ case NPC_INCAGI:
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ break;
+
case 0:
if(sd) {
if(flag&3){
@@ -2772,12 +2727,13 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
break;
default:
+ printf("Unknown skill used:%d\n",skillid);
map_freeblock_unlock();
return 1;
}
if(sc_data) {
if (sc_data[SC_MAGICPOWER].timer != -1 && skillid != HW_MAGICPOWER) //マジックパワ?の?果終了
- skill_status_change_end(src,SC_MAGICPOWER,-1);
+ status_change_end(src,SC_MAGICPOWER,-1);
}
map_freeblock_unlock();
@@ -2788,107 +2744,96 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
* スキル使用(詠唱完了、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,abra_skillid=0,abra_skilllv;
- 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};
-
- if(skilllv <= 0) 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;
+ int sc_dex, sc_luk;
+
+ if(skillid < 0)
+ { // remove the debug print when this case is finished
+ printf("skill_castend_damage_id: skillid=%i\ncall: %p %p %i %i %i %i",skillid,
+ src, bl,skillid,skilllv,tick,flag);
+ return 0;
+ }
+ if(skillid > 0 && skilllv <= 0) return 0; // celest
nullpo_retr(1, src);
nullpo_retr(1, bl);
- if(src->type==BL_PC)
- sd=(struct map_session_data *)src;
- else if(src->type==BL_MOB)
- md=(struct mob_data *)src;
-
- sc_dex=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)
+ if (src->type == BL_PC) {
+ nullpo_retr (1, sd = (struct map_session_data *)src);
+ } else if (src->type == BL_MOB) {
+ nullpo_retr (1, md = (struct mob_data *)src);
+ }
+
+ sc_dex = status_get_mdef (bl);
+ sc_luk = status_get_luk (bl);
+ sc_def_vit = status_get_sc_def_vit (bl);
+ sc_def_mdef = status_get_sc_def_mdef (bl);
+
+ if (bl->type == BL_PC){
+ nullpo_retr (1, dstsd = (struct map_session_data *)bl);
+ } else if (bl->type == BL_MOB){
+ nullpo_retr (1, dstmd = (struct mob_data *)bl);
+ }
+
+ if(bl->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)
+ if(status_get_class(bl) == 1288)
return 1;
- if (skillnotok(skillid, (struct map_session_data *)bl)) // [MouseJstr]
+ if (sd && skillnotok(skillid, sd)) // [MouseJstr]
return 0;
-
+
map_freeblock_lock();
switch(skillid)
{
case AL_HEAL: /* ヒ?ル */
{
- int heal=skill_calc_heal( src, skilllv );
+ 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 )
+ if (skilllv > 10)
+ heal = 9999; //9999ヒール
+ 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、?象が自分のパ?トナ?、自分がスパノビ、自分が♀なら
+ if (sd) {
+ if ((skill = pc_checkskill(sd, HP_MEDITATIO)) > 0) // メディテイティオ
+ heal += heal * skill * 2 / 100;
+ if (sd && dstsd && sd->status.partner_id == dstsd->status.char_id &&
+ pc_calc_base_job2(sd->status.class_) == 23 && sd->status.sex == 0) //自分も?象もPC、?象が自分のパ?トナ?、自分がスパノビ、自分が♀なら
heal = heal*2; //スパノビの嫁が旦那にヒ?ルすると2倍になる
}
-
- clif_skill_nodamage(src,bl,skillid,heal,1);
+ 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){
+ if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){
heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100;
- if(heal_get_jobexp <= 0)
+ if (heal_get_jobexp <= 0)
heal_get_jobexp = 1;
- pc_gainexp((struct map_session_data *)src,0,heal_get_jobexp);
+ pc_gainexp (sd, 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 )
+ if(dstsd) {
+ int per = 0;
+ if (map[bl->m].flag.pvp && dstsd->pvp_point < 0)
break; /* PVPで復活不可能?態 */
- if(pc_isdead(tsd)){ /* 死亡判定 */
+ if (pc_isdead(dstsd)) { /* 死亡判定 */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
switch(skilllv){
case 1: per=10; break;
@@ -2896,139 +2841,153 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
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;
+ dstsd->status.hp = dstsd->status.max_hp * per / 100;
+ if (dstsd->status.hp <= 0) dstsd->status.hp = 1;
+ if (dstsd->special_state.restart_full_recover) { /* オシリスカ?ド */
+ dstsd->status.hp = dstsd->status.max_hp;
+ dstsd->status.sp = dstsd->status.max_sp;
}
- pc_setstand(tsd);
+ pc_setstand(dstsd);
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) {
+ pc_setinvincibletimer(dstsd, battle_config.pc_invincible_time);
+ clif_updatestatus(dstsd, SP_HP);
+ clif_resurrection(bl, 1);
+ if(sd && sd != dstsd && 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;
+ int lv = dstsd->status.base_level - sd->status.base_level, jlv = dstsd->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;
+ exp = (int)((double)dstsd->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;
+ jexp = (int)((double)dstsd->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);
+ pc_gainexp (sd, exp, jexp);
}
}
}
break;
case AL_DECAGI: /* 速度減少 */
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if (dstsd && dstsd->special_state.no_magic_damage)
break;
- if( rand()%100 < (50+skilllv*3+(battle_get_lv(src)+battle_get_int(src)/5)-sc_def_mdef) ) {
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
+ if (rand() % 100 < (50 + skilllv * 3 + (status_get_lv(src) + status_get_int(src) / 5) - sc_def_mdef)) {
+ clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+ status_change_start (bl, SkillStatusChangeTable[skillid], skilllv, 0, 0, 0, skill_get_time(skillid,skilllv), 0);
}
break;
case AL_CRUCIS:
- if(flag&1) {
- int race = battle_get_race(bl),ele = battle_get_elem_type(bl);
- if(battle_check_target(src,bl,BCT_ENEMY) && (race == 6 || battle_check_undead(race,ele))) {
- int slv=battle_get_lv(src),tlv=battle_get_lv(bl),rate;
- rate = 25 + skilllv*2 + slv - tlv;
- if(rand()%100 < rate)
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,0,0);
+ if (flag & 1) {
+ int race = status_get_race (bl), ele = status_get_elem_type (bl);
+ if (battle_check_target (src, bl, BCT_ENEMY) && (race == 6 || battle_check_undead (race, ele))) {
+ int slv = status_get_lv (src),tlv = status_get_lv (bl);
+ int rate = 25 + skilllv*2 + slv - tlv;
+ if (rand()%100 < rate)
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,0,0);
}
- }
- else {
- int range = 15;
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ } else {
+ 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,
+ src->m, src->x-15, src->y-15, src->x+15, src->y+15, 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 )
+ struct status_change *sc_data = status_get_sc_data(bl);
+ clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+ if (dstsd && dstsd->special_state.no_magic_damage)
break;
- if(sc_data && sc_data[SC_DIVINA].timer != -1)
- skill_status_change_end(bl,SC_DIVINA,-1);
- else if( rand()%100 < sc_def_vit ) {
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
+ if (sc_data && sc_data[SC_DIVINA].timer != -1)
+ status_change_end(bl,SC_DIVINA, -1);
+ else if (rand() % 100 < sc_def_vit) {
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
}
break;
+
case SA_ABRACADABRA:
- //require 1 yellow gemstone even with mistress card or Into the Abyss
- if ((i=pc_search_inventory(sd, 715)) < 0 ) { //bug fixed by Lupus (item pos can be 0, too!)
- clif_skill_fail(sd,sd->skillid,0,0);
- break;
+ {
+ int abra_skillid = 0, abra_skilllv;
+ //require 1 yellow gemstone even with mistress card or Into the Abyss
+ if ((i = pc_search_inventory(sd, 715)) < 0 ) { //bug fixed by Lupus (item pos can be 0, too!)
+ clif_skill_fail(sd,sd->skillid,0,0);
+ break;
+ }
+ pc_delitem(sd, i, 1, 0);
+ do {
+ abra_skillid = rand() % 331;
+ if (skill_abra_db[abra_skillid].req_lv > skilllv ||
+ rand()%10000 >= skill_abra_db[abra_skillid].per || //dbに基づくレベル?確率判定
+ (abra_skillid >= NPC_PIERCINGATT && abra_skillid <= NPC_SUMMONMONSTER) || //NPCスキルはダメ
+ skill_get_unit_flag(abra_skillid) & UF_DANCE) //演奏スキルはダメ
+ abra_skillid = 0; // reset to get a new id
+ } while (abra_skillid == 0);
+ abra_skilllv = skill_get_max(abra_skillid) > skilllv ? skilllv : skill_get_max(abra_skillid);
+ clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+ sd->skillitem = abra_skillid;
+ sd->skillitemlv = abra_skilllv;
+ clif_item_skill (sd, abra_skillid, abra_skilllv, "Abracadabra");
}
- //pc_delitem(sd, pc_search_inventory(sd, 715), 1, 0);
- pc_delitem(sd, i, 1, 0);
- //
- do{
- abra_skillid=skill_abra_dataset(skilllv);
- }while(abra_skillid == 0);
- abra_skilllv=skill_get_max(abra_skillid)>pc_checkskill(sd,SA_ABRACADABRA)?pc_checkskill(sd,SA_ABRACADABRA):skill_get_max(abra_skillid);
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- sd->skillitem=abra_skillid;
- sd->skillitemlv=abra_skilllv;
- clif_item_skill(sd,abra_skillid,abra_skilllv,"アブラカダブラ");
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 (dstsd) {
+ if (dstsd->special_state.no_magic_damage)
+ break;
+ dstsd->status.hp = 1;
+ dstsd->status.sp = 1;
+ clif_updatestatus(dstsd, SP_HP);
+ clif_updatestatus(dstsd, SP_SP);
}
- if(dstmd) dstmd->hp=1;
+ 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);
+ if (dstsd) {
+ if (dstsd->special_state.no_magic_damage)
+ break;
+ pc_heal (dstsd, dstsd->status.max_hp, dstsd->status.max_sp);
+ }
+ if (dstmd) dstmd->hp = status_get_max_hp(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,"");
+ if (sd) mob_once_spawn(sd,map[src->m].name,src->x,src->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);
+ 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);
+ {
+ //クラスチェンジ用ボスモンスタ?ID
+ int changeclass[]={1038,1039,1046,1059,1086,1087,1112,1115
+ ,1157,1159,1190,1272,1312,1373,1492};
+ 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);
+ {
+ int poringclass[]={1002};
+ 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);
@@ -3041,19 +3000,20 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case SA_FORTUNE:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if(sd) pc_getzeny(sd,battle_get_lv(bl)*100);
+ if(sd) pc_getzeny(sd,status_get_lv(bl)*100);
break;
case SA_TAMINGMONSTER:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if (dstmd){
- for(i=0;i<MAX_PET_DB;i++){
- if(dstmd->class == pet_db[i].class){
- pet_catch_process1(sd,dstmd->class);
+ if (dstmd) {
+ for (i = 0; i < MAX_PET_DB; i++) {
+ if (dstmd->class_ == pet_db[i].class_) {
+ pet_catch_process1 (sd, dstmd->class_);
break;
}
}
}
break;
+
case AL_INCAGI: /* 速度?加 */
case AL_BLESSING: /* ブレッシング */
case PR_SLOWPOISON:
@@ -3062,38 +3022,37 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case PR_SUFFRAGIUM: /* サフラギウム */
case PR_BENEDICTIO: /* 聖?降福 */
case CR_PROVIDENCE: /* プロヴィデンス */
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ){
+ if (dstsd && dstsd->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 );
+ else {
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case CG_MARIONETTE: /* マリオネットコントロ?ル */
- if(sd && dstsd){
- struct status_change *sc_data = battle_get_sc_data(src);
- struct status_change *tsc_data = battle_get_sc_data(bl);
+ if (sd && dstsd){
+ struct status_change *sc_data = status_get_sc_data(src);
+ struct status_change *tsc_data = status_get_sc_data(bl);
int sc = SkillStatusChangeTable[skillid];
int sc2 = SC_MARIONETTE2;
-
- if((dstsd->bl.type!=BL_PC)
- || (sd->bl.id == dstsd->bl.id)
+
+ if ((sd == dstsd)
|| (!sd->status.party_id)
- || (sd->status.party_id != dstsd->status.party_id)) {
+ || (sd->status.party_id != dstsd->status.party_id)) {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
if(sc_data && tsc_data){
- if(sc_data[sc].timer == -1 && tsc_data[sc2].timer == -1) {
- skill_status_change_start (src,sc,skilllv,0,bl->id,0,skill_get_time(skillid,skilllv),0);
- skill_status_change_start (bl,sc2,skilllv,0,src->id,0,skill_get_time(skillid,skilllv),0);
+ if (sc_data[sc].timer == -1 && tsc_data[sc2].timer == -1) {
+ status_change_start (src,sc,skilllv,0,bl->id,0,skill_get_time(skillid,skilllv),0);
+ status_change_start (bl,sc2,skilllv,0,src->id,0,skill_get_time(skillid,skilllv),0);
}
else if (sc_data[sc].timer != -1 && tsc_data[sc2].timer != -1 &&
- sc_data[sc].val3 == bl->id && tsc_data[sc2].val3 == src->id) {
- skill_status_change_end(src, sc, -1);
- skill_status_change_end(bl, sc2, -1);
+ sc_data[sc].val3 == bl->id && tsc_data[sc2].val3 == src->id) {
+ status_change_end(src, sc, -1);
+ status_change_end(bl, sc2, -1);
}
else {
clif_skill_fail(sd,skillid,0,0);
@@ -3102,57 +3061,60 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
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);
+ if (dstsd) {
+ if (dstsd->special_state.no_magic_damage) {
+ clif_skill_nodamage(src,bl,skillid,skilllv,0);
+ break;
+ }
+ if(dstsd->status.weapon == 0 ||
+ (sd && sd->status.party_id > 0 && sd->status.party_id != dstsd->status.party_id) ||
+ dstsd->sc_data[SC_FLAMELAUNCHER].timer != -1 ||
+ dstsd->sc_data[SC_FROSTWEAPON].timer != -1 ||
+ dstsd->sc_data[SC_LIGHTNINGLOADER].timer != -1 ||
+ dstsd->sc_data[SC_SEISMICWEAPON].timer != -1 ||
+ dstsd->sc_data[SC_ENCPOISON].timer != -1) {
+ if (sd) clif_skill_fail(sd,skillid,0,0);
clif_skill_nodamage(src,bl,skillid,skilllv,0);
break;
}
}
- if(rand()%100 > (75+skilllv*1) && (skilllv != 5)) {
- clif_skill_fail(sd,skillid,0,0);
+ if(skilllv < 5 && rand()%100 > (60+skilllv*10) ) { //fixed by Lupus (4 -> 5) or else it has 100% success even at lv4
+ if (sd) 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);
+ if(dstsd && battle_config.equipment_breaking) {
+ if(sd && sd != dstsd) clif_displaymessage(sd->fd,"You broke target's weapon");
+ pc_breakweapon(dstsd);
}
break;
- }
- else {
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ } else {
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case PR_ASPERSIO: /* アスペルシオ */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if (dstsd && dstsd->special_state.no_magic_damage)
break;
- if(bl->type==BL_MOB)
+ if (dstmd)
break;
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ 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 )
+ if (dstsd && dstsd->special_state.no_magic_damage)
break;
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ 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: /* スピアクイッケン */
@@ -3176,68 +3138,87 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case ST_REJECTSWORD: /* リジェクトソ?ド */
case HW_MAGICPOWER: /* 魔法力?幅 */
case PF_MEMORIZE: /* メモライズ */
+ case PA_SACRIFICE:
case ASC_EDP: // [Celest]
+ case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
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 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
+
case SM_ENDURE: /* インデュア */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
- skill_status_change_start(src,SC_BLOCKSKILL,skilllv,0,skillid,0,10000,0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ if (sd)
+ pc_blockskill_start (sd, skillid, 10000);
break;
-
-
+
+ case SM_AUTOBERSERK: // Celest
+ {
+ struct status_change *tsc_data = status_get_sc_data(bl);
+ int sc = SkillStatusChangeTable[skillid];
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if (tsc_data && tsc_data[sc].timer != -1)
+ status_change_end(bl, sc, -1);
+ else
+ status_change_start(bl,sc,skilllv,0,0,0,0,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;
+ if (dstsd) {
+ if(dstsd->sc_data[SC_FLAMELAUNCHER].timer != -1 ||
+ dstsd->sc_data[SC_FROSTWEAPON].timer != -1 ||
+ dstsd->sc_data[SC_LIGHTNINGLOADER].timer != -1 ||
+ dstsd->sc_data[SC_SEISMICWEAPON].timer != -1 ||
+ dstsd->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 );
+ 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);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case LK_BERSERK: /* バ?サ?ク */
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 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
//sd->status.hp = sd->status.max_hp * 3;
break;
+
case MC_CHANGECART:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
+
case AC_CONCENTRATION: /* 集中力向上 */
{
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,
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ map_foreachinarea( status_change_timer_sub,
src->m, src->x-range, src->y-range, src->x+range,src->y+range,0,
src,SkillStatusChangeTable[skillid],tick);
}
break;
+
case SM_PROVOKE: /* プロボック */
{
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_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))) //不死には?かない
- {
+ if((dstmd && status_get_mode(bl)&0x20) || battle_check_undead(status_get_race(bl),status_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 );
+ 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);
@@ -3247,18 +3228,17 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
if(sc_data){
if(sc_data[SC_FREEZE].timer!=-1)
- skill_status_change_end(bl,SC_FREEZE,-1);
+ 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);
+ status_change_end(bl,SC_STONE,-1);
if(sc_data[SC_SLEEP].timer!=-1)
- skill_status_change_end(bl,SC_SLEEP,-1);
+ status_change_end(bl,SC_SLEEP,-1);
}
- if(bl->type==BL_MOB) {
+ if(dstmd) {
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);
+ dstmd->state.provoke_flag = src->id;
+ mob_target(dstmd,src,range);
}
}
break;
@@ -3266,27 +3246,27 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case CR_DEVOTION: /* ディボ?ション */
if(sd && dstsd){
//?生や養子の場合の元の職業を算出する
- struct pc_base_job dst_s_class = pc_calc_base_job(dstsd->status.class);
-
- int lv = sd->status.base_level-dstsd->status.base_level;
- lv = (lv<0)?-lv:lv;
- if((dstsd->bl.type!=BL_PC) // 相手はPCじゃないとだめ
- ||(sd->bl.id == dstsd->bl.id) // 相手が自分はだめ
- ||(lv > 10) // レベル差±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)) // 同じギルドじゃないとだめ
- ||(dst_s_class.job==14||dst_s_class.job==21)){ // クルセだめ
+ int s_class = pc_calc_base_job2 (dstsd->status.class_);
+
+ int lv = sd->status.base_level - dstsd->status.base_level;
+ if (lv < 0) lv = -lv;
+ if ((sd == dstsd) // 相手はPCじゃないとだめ
+ || (sd->bl.id == dstsd->bl.id) // 相手が自分はだめ
+ || (lv > battle_config.devotion_level_difference) // レベル差±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)) // 同じギルドじゃないとだめ
+ || (s_class == 14 || s_class == 21)) { // クルセだめ
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
- for(i=0;i<skilllv;i++){
- if(!sd->dev.val1[i]){ // 空きがあったら入れる
+ 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){ // 空きがなかった
+ } else if (i == skilllv - 1) { // 空きがなかった
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
@@ -3294,54 +3274,56 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
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 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],src->id,1,0,0,1000*(15+15*skilllv),0 );
}
- else clif_skill_fail(sd,skillid,0,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++)
+ 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 );
+ 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) {
+ if (dstsd) {
+ if ((sd && sd == dstsd) || map[src->m].flag.pvp || map[src->m].flag.gvg) {
+ if (dstsd->spiritball > 0) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
i = dstsd->spiritball * 7;
pc_delspiritball(dstsd,dstsd->spiritball,0);
if(i > 0x7FFF)
i = 0x7FFF;
- if(sd->status.sp + i > sd->status.max_sp)
+ if(sd && sd->status.sp + i > sd->status.max_sp)
i = sd->status.max_sp - sd->status.sp;
- }
+ }
}
- }else if(sd && dstmd){ //?象がモンスタ?の場合
+ } else if (dstmd) { //?象がモンスタ?の場合
//20%の確率で?象のLv*2のSPを回復する。成功したときはタ?ゲット(σ?Д?)σ????!!
- if(rand()%100<20){
- i=2*mob_db[dstmd->class].lv;
+ if(rand() % 100 < 20) {
+ i = 2 * mob_db[dstmd->class_].lv;
mob_target(dstmd,src,0);
}
}
- if(i){
- sd->status.sp += i;
- clif_heal(sd->fd,SP_SP,i);
- }
- else
- clif_skill_nodamage(src,bl,skillid,skilllv,0);
+ if (i && sd){
+ sd->status.sp += i;
+ clif_heal(sd->fd,SP_SP,i);
+ } else clif_skill_nodamage(src,bl,skillid,skilllv,0);
break;
case AC_MAKINGARROW: /* 矢作成 */
@@ -3375,29 +3357,30 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
clif_skill_produce_mix_list(sd,256);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
- break;
+ 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 )
+ if(dstsd && dstsd->special_state.no_weapon_damage)
break;
- if( rand()%100 < (20+ 10*skilllv)*sc_def_vit/100 ) {
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
- }
+ if(rand() % 100 < (20 + 10 * skilllv) * sc_def_vit / 100 )
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case RG_RAID: /* サプライズアタック */
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); // ハイディング解除
+ map_foreachinarea(skill_area_sub,
+ bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
+ src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
+ skill_castend_damage_id);
+ status_change_end(src, SC_HIDING, -1); // ハイディング解除
+ break;
+
+ case ASC_METEORASSAULT: /* メテオアサルト */
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ map_foreachinarea(skill_area_sub,
+ bl->m,bl->x-2,bl->y-2,bl->x+2,bl->y+2,0,
+ src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
+ skill_castend_damage_id);
break;
case KN_BRANDISHSPEAR: /*ブランディッシュスピア*/
@@ -3455,30 +3438,29 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case PR_MAGNIFICAT: /* マグニフィカ?ト */
case PR_GLORIA: /* グロリア */
case SN_WINDWALK: /* ウインドウォ?ク */
- if(sd == NULL || sd->status.party_id==0 || (flag&1) ){
+ 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 )
+ if(dstsd && dstsd->special_state.no_magic_damage)
break;
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
- }
- else{
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
+ } else if (sd) {
/* パ?ティ全?への?理 */
- party_foreachsamemap(skill_area_sub,
+ 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) ){
+ 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{
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,(src == bl)? 1:0,0,0,skill_get_time(skillid,skilllv),0);
+ } else if (sd) {
/* パ?ティ全?への?理 */
party_foreachsamemap(skill_area_sub,
sd,1,
@@ -3493,66 +3475,54 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case CR_DEFENDER: /* ディフェンダ? */
case CR_AUTOGUARD: /* オ?トガ?ド */
{
- struct status_change *tsc_data = battle_get_sc_data(bl);
- int sc=SkillStatusChangeTable[skillid];
+ struct status_change *tsc_data = status_get_sc_data(bl);
+ int sc = SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( tsc_data ){
- if( tsc_data[sc].timer==-1 )
- /* 付加する */
- skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
- else
- /* 解除する */
- skill_status_change_end(bl, sc, -1);
- }
+ if (tsc_data && tsc_data[sc].timer != -1)
+ status_change_end(bl, sc, -1);
+ else
+ status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
break;
case TF_HIDING: /* ハイディング */
{
- struct status_change *tsc_data = battle_get_sc_data(bl);
- int sc=SkillStatusChangeTable[skillid];
+ struct status_change *tsc_data = status_get_sc_data(bl);
+ int sc = SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,-1,1);
- if( tsc_data ){
- if( tsc_data[sc].timer==-1 )
- /* 付加する */
- skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
+ if (tsc_data && tsc_data[sc].timer != -1)
+ status_change_end(bl, sc, -1);
else
- /* 解除する */
- skill_status_change_end(bl, sc, -1);
- }
+ status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
break;
case AS_CLOAKING: /* クロ?キング */
{
- struct status_change *tsc_data = battle_get_sc_data(bl);
+ struct status_change *tsc_data = status_get_sc_data(bl);
int sc=SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,-1,1);
- if( tsc_data ){
- if( tsc_data[sc].timer==-1 )
- /* 付加する */
- skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
- else
+ if(tsc_data && tsc_data[sc].timer!=-1 )
/* 解除する */
- skill_status_change_end(bl, sc, -1);
- }
+ status_change_end(bl, sc, -1);
+ else
+ /* 付加する */
+ status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
//skill_check_cloaking(bl);
}
break;
case ST_CHASEWALK: /* ハイディング */
{
- struct status_change *tsc_data = battle_get_sc_data(bl);
+ struct status_change *tsc_data = status_get_sc_data(bl);
int sc=SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,-1,1);
- if( tsc_data ){
- if( tsc_data[sc].timer==-1 )
- /* 付加する */
- skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
- else
+ if(tsc_data && tsc_data[sc].timer!=-1 )
/* 解除する */
- skill_status_change_end(bl, sc, -1);
- }
+ status_change_end(bl, sc, -1);
+ else
+ /* 付加する */
+ status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
break;
@@ -3575,32 +3545,20 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case DC_DONTFORGETME: /* 私を忘れないで… */
case DC_FORTUNEKISS: /* 幸運のキス */
case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */
- case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
+// 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: /* バジリカ */
{
- // cancel Basilica if already in effect
- struct status_change *sc_data = battle_get_sc_data(src);
- if(sc_data && sc_data[SC_BASILICA].timer != -1){
- struct skill_unit *su;
- if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
- struct skill_unit_group *sg;
- if ((sg = su->group) && sg->src_id == sd->bl.id) {
- skill_status_change_end(src,SC_BASILICA,-1);
- skill_delunitgroup (sg);
- break;
- }
- }
- } else {
- // otherwise allow casting
- skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
- skill_clear_unitgroup(src);
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
- }
+ struct skill_unit_group *sg;
+ battle_stopwalking(src,1);
+ skill_clear_unitgroup(src);
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
+ status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,(int)sg,
+ skill_get_time(skillid,skilllv),0);
}
break;
@@ -3608,11 +3566,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
skill_clear_unitgroup(src);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
+ status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,BCT_SELF,skill_get_time(skillid,skilllv),0);
break;
case BD_ADAPTATION: /* アドリブ */
{
- struct status_change *sc_data = battle_get_sc_data(src);
+ struct status_change *sc_data = status_get_sc_data(src);
if(sc_data && sc_data[SC_DANCING].timer!=-1){
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_stop_dancing(src,0);
@@ -3636,11 +3595,11 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case RG_STEALCOIN: // スティ?ルコイン
- if(sd) {
+ 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);
+ range = status_get_range(src) - (range + 1);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
mob_target((struct mob_data *)bl,src,range);
}
@@ -3650,17 +3609,41 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case MG_STONECURSE: /* スト?ンカ?ス */
- if (bl->type==BL_MOB && battle_get_mode(bl)&0x20) {
- clif_skill_fail(sd,sd->skillid,0,0);
- break;
+ {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ // Level 6-10 doesn't consume a red gem if it fails [celest]
+ int i, gem_flag = 1, fail_flag = 0;
+ if (dstmd && status_get_mode(bl)&0x20) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ break;
+ }
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstsd && dstsd->special_state.no_magic_damage )
+ break;
+ if (sc_data && sc_data[SC_STONE].timer != -1) {
+ status_change_end(bl,SC_STONE,-1);
+ if (sd) {
+ fail_flag = 1;
+ clif_skill_fail(sd,skillid,0,0);
+ }
+ }
+ else if( rand()%100 < skilllv*4+20 && !battle_check_undead(status_get_race(bl),status_get_elem_type(bl)))
+ status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ else if(sd) {
+ if (skilllv > 5) gem_flag = 0;
+ clif_skill_fail(sd,skillid,0,0);
+ fail_flag = 1;
+ }
+ if (dstmd)
+ mob_target(dstmd,src,skill_get_range(skillid,skilllv));
+ if (sd && gem_flag) {
+ if ((i=pc_search_inventory(sd, skill_db[skillid].itemid[0])) < 0 ) {
+ if (!fail_flag) clif_skill_fail(sd,sd->skillid,0,0);
+ break;
+ }
+ pc_delitem(sd, i, skill_db[skillid].amount[0], 0);
+ }
}
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
- break;
- if( rand()%100 < skilllv*4+20 && !battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
- skill_status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
- else if(sd)
- clif_skill_fail(sd,skillid,0,0);
break;
case NV_FIRSTAID: /* ?急手? */
@@ -3670,37 +3653,36 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
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 )
+ if(dstsd && dstsd->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);
+ status_change_end(bl, SC_SILENCE , -1 );
+ status_change_end(bl, SC_BLIND , -1 );
+ status_change_end(bl, SC_CONFUSION, -1 );
+ if( battle_check_undead(status_get_race(bl),status_get_elem_type(bl)) ){//アンデッドなら暗闇?果
+ status_change_start(bl, SC_CONFUSION,1,0,0,0,6000,0);
}
break;
case TF_DETOXIFY: /* 解毒 */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_end(bl, SC_POISON , -1 );
- skill_status_change_end(bl, SC_DPOISON , -1 );
+ status_change_end(bl, SC_POISON , -1 );
+ status_change_end(bl, SC_DPOISON , -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 )
+ if(dstsd && dstsd->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(rand()%100 < (100-(battle_get_int(bl)/2+battle_get_vit(bl)/3+battle_get_luk(bl)/10)))
- skill_status_change_start(bl, SC_BLIND,1,0,0,0,blind_time,0);
+ status_change_end(bl, SC_FREEZE , -1 );
+ status_change_end(bl, SC_STONE , -1 );
+ status_change_end(bl, SC_SLEEP , -1 );
+ status_change_end(bl, SC_STAN , -1 );
+ if( battle_check_undead(status_get_race(bl),status_get_elem_type(bl)) ){//アンデッドなら暗闇?果
+ if(rand()%100 < (100-(status_get_int(bl)/2+status_get_vit(bl)/3+status_get_luk(bl)/10))) {
+ status_change_start(bl, SC_BLIND,1,0,0,0,
+ 1000 * 30 * (100-(status_get_int(bl)+status_get_vit(bl))/2)/100,0);
+ }
}
if(dstmd){
dstmd->attacked_id=0;
@@ -3713,7 +3695,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case WZ_ESTIMATION: /* モンスタ?情報 */
- if(src->type==BL_PC){
+ if(sd) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
clif_skill_estimation((struct map_session_data *)src,bl);
}
@@ -3727,11 +3709,11 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case BS_REPAIRWEAPON: /* 武器修理 */
if(sd) {
//動作しないのでとりあえずコメントアウト
- if (pc_search_inventory(sd, 999) < 0 ) { //fixed by Lupus (item pos can be = 0!)
+ /*if (pc_search_inventory(sd, 999) < 0 ) { //fixed by Lupus (item pos can be = 0!)
clif_skill_fail(sd,sd->skillid,0,0);
map_freeblock_unlock();
return 1;
- }
+ }*/
clif_item_repair_list(sd);
}
break;
@@ -3742,20 +3724,20 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case AL_TELEPORT: /* テレポ?ト */
- if( sd ){
- if(map[sd->bl.m].flag.noteleport){ /* テレポ禁止 */
+ 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 )
+ if(sd->skilllv == 1)
clif_skill_warppoint(sd,sd->skillid,"Random","","","");
- else{
+ 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);
+ } else if(dstmd)
+ mob_warp(dstmd,-1,-1,-1,3);
break;
case AL_HOLYWATER: /* アクアベネディクタ */
@@ -3799,136 +3781,102 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case RG_STRIPWEAPON: /* ストリップウェポン */
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
-
- if(tsc_data && tsc_data[SC_CP_WEAPON].timer != -1 )
+ case RG_STRIPSHIELD: /* ストリップシールド */
+ case RG_STRIPARMOR: /* ストリップアーマー */
+ case RG_STRIPHELM: /* ストリップヘルム */
+ {
+ struct status_change *tsc_data;
+ int strip_time, strip_per, strip_fix;
+ int scid, cp_scid = 0, equip;
+
+ tsc_data = status_get_sc_data(bl);
+ scid = SkillStatusChangeTable[skillid];
+ switch (skillid) {
+ case RG_STRIPWEAPON:
+ equip = EQP_WEAPON;
+ cp_scid = SC_CP_WEAPON;
break;
- strip_per = 5+2*skilllv+strip_fix/5;
- strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
- if(rand()%100 < strip_per){
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
- if(dstsd){
- for(i=0;i<MAX_INVENTORY;i++){
- if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0002){
- pc_unequipitem(dstsd,i,0,BF_SKILL);
- break;
- }
- }
- }
- }
- }
- break;
-
- case RG_STRIPSHIELD: /* ストリップシ?ルド */
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
-
- if(tsc_data && tsc_data[SC_CP_SHIELD].timer != -1 )
+ case RG_STRIPSHIELD:
+ equip = EQP_SHIELD;
+ cp_scid = SC_CP_SHIELD;
break;
- strip_per = 5+2*skilllv+strip_fix/5;
- strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
- if(rand()%100 < strip_per){
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
- if(dstsd){
- for(i=0;i<MAX_INVENTORY;i++){
- if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0020){
- pc_unequipitem(dstsd,i,0,BF_SKILL);
- break;
- }
- }
- }
- }
- }
- break;
-
- case RG_STRIPARMOR: /* ストリップア?マ? */
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
-
- if(tsc_data && tsc_data[SC_CP_ARMOR].timer != -1 )
+ case RG_STRIPARMOR:
+ equip = EQP_ARMOR;
+ cp_scid = SC_CP_ARMOR;
break;
- strip_per = 5+2*skilllv+strip_fix/5;
- strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
- if(rand()%100 < strip_per){
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
- if(dstsd){
- for(i=0;i<MAX_INVENTORY;i++){
- if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0010){
- pc_unequipitem(dstsd,i,0,BF_SKILL);
- break;
- }
- }
- }
- }
- }
- break;
-
- case RG_STRIPHELM: /* ストリップヘルム */
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
-
- if(tsc_data && tsc_data[SC_CP_HELM].timer != -1 )
+ case RG_STRIPHELM:
+ equip = EQP_HELM;
+ cp_scid = SC_CP_HELM;
break;
- strip_per = 5+2*skilllv+strip_fix/5;
- strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
- if(rand()%100 < strip_per){
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
- if(dstsd){
- for(i=0;i<MAX_INVENTORY;i++){
- if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0100){
- pc_unequipitem(dstsd,i,0,BF_SKILL);
- break;
- }
- }
- }
- }
+ default:
+ map_freeblock_unlock();
+ return 1;
}
- break;
- // Full Strip [Celest]
- case ST_FULLSTRIP:
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
- int c=0, i, j;
- int striplist[2][4] = { { 0, 0, 0, 0 },
- { 0x0002, 0x0020, 0x0010, 0x0100 } };
+ if (tsc_data && (tsc_data[scid].timer != -1 || tsc_data[cp_scid].timer != -1))
+ break;
+ if (dstsd && dstsd->unstripable_equip & equip)
+ break;
- strip_per = 5+2*skilllv+strip_fix/5;
- strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
- for (i=0; i<4; i++) {
- if(tsc_data && tsc_data[SC_CP_WEAPON + i].timer != -1)
+ strip_fix = status_get_dex(src) - status_get_dex(bl);
+ if(strip_fix < 0)
+ strip_fix=0;
+ strip_per = 5+5*skilllv+strip_fix/5;
+ if (rand()%100 >= strip_per)
+ break;
+
+ if (dstsd) {
+ for (i=0;i<MAX_INVENTORY;i++) {
+ if (dstsd->status.inventory[i].equip && (dstsd->status.inventory[i].equip & equip)){
+ pc_unequipitem(dstsd,i,3);
break;
- if(rand()%100 < strip_per) {
- striplist[0][i] = 1;
- c++;
}
}
-
- if (c > 0) {
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- for (j=0; j<4 && c > 0; j++) {
- if (striplist[0][j]) {
- skill_status_change_start(bl,SC_STRIPWEAPON + i,skilllv,0,0,0,strip_time,0 );
- if(dstsd){
- for(i=0;i<MAX_INVENTORY;i++){
- if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & striplist[1][j]){
- pc_unequipitem(dstsd,i,0,BF_SKILL);
- --c;
- break;
- }
- }
- }
+ if (i == MAX_INVENTORY)
+ break;
+ }
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
+ status_change_start(bl,scid,skilllv,0,0,0,strip_time,0 );
+ break;
+ }
+ case ST_FULLSTRIP: // Celest
+ {
+ struct status_change *tsc_data;
+ int i, j, strip_time, strip_per, strip_fix;
+ int equip[4] = { EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM };
+ int scid[4] = { SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM };
+ int cp_scid[4] = { SC_CP_WEAPON, SC_CP_SHIELD, SC_CP_ARMOR, SC_CP_HELM };
+
+ tsc_data = status_get_sc_data(bl);
+ strip_fix = status_get_dex(src) - status_get_dex(bl);
+ if(strip_fix < 0)
+ strip_fix = 0;
+ strip_per = 5+5*skilllv+strip_fix/5;
+ if (rand()%100 >= strip_per)
+ break;
+ strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
+
+ for (i=0; i<4; i++) {
+ if (dstsd) {
+ if (tsc_data && (tsc_data[scid[i]].timer != -1 || tsc_data[cp_scid[i]].timer != -1))
+ continue;
+ if (dstsd->unstripable_equip & equip[i])
+ continue;
+ for (j=0; j<MAX_INVENTORY; j++) {
+ if (dstsd->status.inventory[j].equip && (dstsd->status.inventory[j].equip & equip[i])){
+ pc_unequipitem(dstsd,j,3);
+ break;
}
}
+ if (j == MAX_INVENTORY)
+ continue;
}
+ status_change_start(bl,scid[i],skilllv,0,0,0,strip_time,0 );
}
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
-
+ }
/* PotionPitcher */
case AM_POTIONPITCHER: /* ポ?ションピッチャ? */
@@ -3936,10 +3884,6 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
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) {
@@ -3959,7 +3903,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
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 = status_get_max_hp(bl) * sd->potion_per_hp / 100;
hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
if(dstsd) {
sp = dstsd->status.max_sp * sd->potion_per_sp / 100;
@@ -3969,13 +3913,13 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
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;
+ hp = hp * (100 + (status_get_vit(bl)<<1)) / 100;
if(dstsd)
hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100;
}
if(sd->potion_sp > 0) {
sp = sd->potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
- sp = sp * (100 + (battle_get_int(bl)<<1)) / 100;
+ sp = sp * (100 + (status_get_int(bl)<<1)) / 100;
if(dstsd)
sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100;
}
@@ -3983,7 +3927,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
else {
hp = (1 + rand()%400) * (100 + skilllv*10) / 100;
- hp = hp * (100 + (battle_get_vit(bl)<<1)) / 100;
+ hp = hp * (100 + (status_get_vit(bl)<<1)) / 100;
if(dstsd)
hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100;
}
@@ -4000,39 +3944,16 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
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);
+ int scid = SC_STRIPWEAPON + (skillid - AM_CP_WEAPON);
+ struct status_change *tsc_data = status_get_sc_data(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if(tsc_data && tsc_data[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 );
+ if(tsc_data && tsc_data[scid].timer != -1)
+ status_change_end(bl, scid, -1 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
}
break;
@@ -4040,7 +3961,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
{
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 )
+ if(dstsd && dstsd->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
@@ -4048,7 +3969,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
|| 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);
+ status_change_end(bl,i,-1);
}
}
break;
@@ -4056,12 +3977,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
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_PET)
- clif_fixpetpos((struct pet_data *)src);
- else if(src->type == BL_PC)
+ if (sd)
clif_fixpos(src);
+ else if (md)
+ clif_fixmobpos(md);
+ else if (src->type == BL_PET)
+ clif_fixpetpos((struct pet_data *)src);
skill_addtimerskill(src,tick + 200,src->id,0,0,skillid,skilllv,0,flag);
break;
@@ -4077,7 +3998,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case SA_SPELLBREAKER: // スペルブレイカ?
{
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_get_sc_data(bl);
int sp;
if(sc_data && sc_data[SC_MAGICROD].timer != -1) {
if(dstsd) {
@@ -4140,9 +4061,9 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
break;
case SA_MAGICROD:
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if (dstsd && dstsd->special_state.no_magic_damage )
break;
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ 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);
@@ -4173,7 +4094,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
maxlv = 3;
}
if(spellid > 0)
- skill_status_change_start(src,SC_AUTOSPELL,skilllv,spellid,maxlv,0,
+ status_change_start(src,SC_AUTOSPELL,skilllv,spellid,maxlv,0,
skill_get_time(SA_AUTOSPELL,skilllv),0);
}
break;
@@ -4201,14 +4122,14 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case NPC_PROVOCATION:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(md)
- clif_pet_performance(src,mob_db[md->class].skill[md->skillidx].val[0]);
+ clif_pet_performance(src,mob_db[md->class_].skill[md->skillidx].val[0]);
break;
case NPC_HALLUCINATION:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if(dstsd && dstsd->special_state.no_magic_damage )
break;
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case NPC_KEEPING:
@@ -4216,25 +4137,25 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
{
int skill_time = skill_get_time(skillid,skilllv);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_time,0 );
- if (bl->type == BL_MOB)
- mob_changestate((struct mob_data *)src,MS_DELAY,skill_time);
- else if (bl->type == BL_PC)
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_time,0 );
+ if (md)
+ mob_changestate(md,MS_DELAY,skill_time);
+ else if (sd)
sd->attackabletime = sd->canmove_tick = tick + skill_time;
}
break;
case NPC_DARKBLESSING:
{
- int sc_def = 100 - battle_get_mdef(bl);
+ int sc_def = 100 - status_get_mdef(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if(dstsd && dstsd->special_state.no_magic_damage )
break;
- if(battle_get_elem_type(bl) == 7 || battle_get_race(bl) == 6)
+ if(status_get_elem_type(bl) == 7 || status_get_race(bl) == 6)
break;
if(rand()%100 < sc_def*(50+skilllv*5)/100) {
if(dstsd) {
- int hp = battle_get_hp(bl)-1;
+ int hp = status_get_hp(bl)-1;
pc_heal(dstsd,-hp,0);
}
else if(dstmd)
@@ -4245,16 +4166,17 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case NPC_SELFDESTRUCTION: /* 自爆 */
case NPC_SELFDESTRUCTION2: /* 自爆2 */
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,0,0,skill_get_time(skillid,skilllv),0);
+ 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)
+ if (dstsd) {
+ if (dstsd->special_state.no_weapon_damage )
+ break;
pc_heal(dstsd,0,-100);
+ }
if(rand()%100 < (skilllv*5)*sc_def_vit/100)
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_SUICIDE: /* 自決 */
@@ -4269,26 +4191,106 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
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);
+ if(md)
+ mob_summonslave(md,mob_db[md->class_].skill[md->skillidx].val,skilllv,(skillid==NPC_SUMMONSLAVE)?1:0);
+ break;
+
+ case NPC_RECALL: //取り巻き呼び戻し
+ if(md) {
+ int mobcount;
+ md->recallcount = 0;//初期化
+ md->recall_flag = 0;
+ mobcount = mob_countslave(md);
+ if(mobcount > 0) {
+ md->recall_flag = 1; //mob.cの[取り巻きモンスターの処理]で利用
+ md->recallmob_count = mobcount;
+ }
+ }
+ break;
+
+ case NPC_RUNAWAY: //後退
+ if(md) {
+ int check;
+ int dist = skilllv;//後退する距離
+ check = md->dir; //自分がどの方向に向いてるかチェック
+ md->attacked_id = 0;
+ md->target_id = 0;
+ md->state.targettype = NONE_ATTACKABLE;
+ md->state.skillstate = MSS_IDLE;
+ switch (check) {
+ case 0: //自分の向いてる方向と逆に移動する
+ mob_walktoxy(md,md->bl.x,md->bl.y-dist,0);//そして、移動する
+ break;
+ case 1:
+ mob_walktoxy(md,md->bl.x-dist,md->bl.y-dist,0);
+ break;
+ case 2:
+ mob_walktoxy(md,md->bl.x+dist,md->bl.y,0);
+ break;
+ case 3:
+ mob_walktoxy(md,md->bl.x+dist,md->bl.y+dist,0);
+ break;
+ case 4:
+ mob_walktoxy(md,md->bl.x,md->bl.y+dist,0);
+ break;
+ case 5:
+ mob_walktoxy(md,md->bl.x-dist,md->bl.y+dist,0);
+ break;
+ case 6:
+ mob_walktoxy(md,md->bl.x-dist,md->bl.y,0);
+ break;
+ case 7:
+ mob_walktoxy(md,md->bl.x-dist,md->bl.y-dist,0);
+ break;
+ }
}
break;
case NPC_TRANSFORMATION:
case NPC_METAMORPHOSIS:
if(md)
- mob_class_change(md,mob_db[md->class].skill[md->skillidx].val);
+ 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]);
+ clif_emotion(&md->bl,mob_db[md->class_].skill[md->skillidx].val[0]);
break;
case NPC_DEFENDER:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
+ // Equipment breaking monster skills [Celest]
+ case NPC_BREAKWEAPON:
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstsd && battle_config.equipment_breaking)
+ pc_breakweapon(dstsd);
+ break;
+
+ case NPC_BREAKARMOR:
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstsd && battle_config.equipment_breaking)
+ pc_breakarmor(dstsd);
+ break;
+
+ case NPC_BREAKHELM:
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstsd && battle_config.equipment_breaking)
+ pc_breakhelm(dstsd);
+ break;
+
+ case NPC_BREAKSHIELD:
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstsd && battle_config.equipment_breaking)
+ pc_breakshield(dstsd);
+ break;
+
+ case NPC_EXPLOSIONSPIRITS: //NPC爆裂波動
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ status_change_start(bl,SC_EXPLOSIONSPIRITS,skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ break;
+
case WE_MALE: /* 君だけは護るよ */
if(sd && dstsd){
int hp_rate=(skilllv <= 0)? 0:skill_db[skillid].hp_rate[skilllv-1];
@@ -4310,27 +4312,85 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
if(sd && dstsd){
if((dstsd = pc_get_partner(sd)) == NULL){
clif_skill_fail(sd,skillid,0,0);
+ map_freeblock_unlock();
return 0;
}
if(map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto || map[dstsd->bl.m].flag.nowarp){
clif_skill_teleportmessage(sd,1);
+ map_freeblock_unlock();
return 0;
- }
+ }
skill_unitsetting(src,skillid,skilllv,sd->bl.x,sd->bl.y,0);
}
break;
+// parent-baby skills
+ case WE_BABY:
+ if(sd && dstsd){
+ struct map_session_data *f_sd = pc_get_father(sd);
+ struct map_session_data *m_sd = pc_get_mother(sd);
+ // if neither was found
+ if(!f_sd && !m_sd){
+ clif_skill_fail(sd,skillid,0,0);
+ map_freeblock_unlock();
+ return 0;
+ }
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ if (f_sd) status_change_start(&f_sd->bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ if (m_sd) status_change_start(&m_sd->bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ }
+ break;
+
+ case WE_CALLPARENT:
+ if(sd && dstsd){
+ struct map_session_data *f_sd = pc_get_father(sd);
+ struct map_session_data *m_sd = pc_get_mother(sd);
+ // if neither was found
+ if(!f_sd && !m_sd){
+ clif_skill_fail(sd,skillid,0,0);
+ map_freeblock_unlock();
+ return 0;
+ }
+ if(map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto || map[dstsd->bl.m].flag.nowarp){
+ clif_skill_teleportmessage(sd,1);
+ map_freeblock_unlock();
+ return 0;
+ }
+ if (f_sd) pc_setpos(f_sd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,3);
+ if (m_sd) pc_setpos(f_sd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,3);
+ }
+ break;
+
+ case WE_CALLBABY:
+ if(sd && dstsd){
+ if((dstsd = pc_get_child(sd)) == NULL){
+ clif_skill_fail(sd,skillid,0,0);
+ map_freeblock_unlock();
+ return 0;
+ }
+ if(map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto || map[dstsd->bl.m].flag.nowarp){
+ clif_skill_teleportmessage(sd,1);
+ map_freeblock_unlock();
+ return 0;
+ }
+ pc_setpos(dstsd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,3);
+ }
+ 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*10*skilllv/100;
- conv_sp=(sd->status.sp+conv_sp>sd->status.max_sp)?sd->status.max_sp-sd->status.sp:conv_sp;
- sd->status.sp += conv_sp; //SPを?やす
- pc_heal(sd,-conv_hp,conv_sp);
- clif_heal(sd->fd,SP_SP,conv_sp);
+ clif_skill_nodamage(src, bl, skillid, skilllv, 1);
+ if (sd) {
+ int hp, sp;
+ hp = sd->status.max_hp / 10; //基本はHPの10%
+ sp = hp * 10 * skilllv / 100;
+ if (sd->status.sp + sp > sd->status.max_sp)
+ sp = sd->status.max_sp - sd->status.sp;
+ // we need to check with the sp that was taken away when casting too
+ if (sd->status.sp + skill_get_sp(skillid, skilllv) >= sd->status.max_sp)
+ hp = sp = 0;
+ pc_heal(sd, -hp, sp);
+ clif_heal(sd->fd, SP_SP, sp);
+ clif_updatestatus(sd, SP_SP);
}
break;
case HT_REMOVETRAP: /* リム?ブトラップ */
@@ -4346,13 +4406,13 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
(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);
+ 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);
}
}
@@ -4366,12 +4426,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
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);
+ status_change_end(target,SC_ANKLE,-1);
}
skill_delunit(su);
}
@@ -4383,6 +4443,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
struct skill_unit *su=NULL;
if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){
switch(su->group->unit_id){
+ case 0x91: // ankle snare
+ if (su->group->val2 != 0)
+ // if it is already trapping something don't spring it,
+ // remove trap should be used instead
+ break;
+ // otherwise fallthrough to below
case 0x8f: /* ブラストマイン */
case 0x90: /* スキッドトラップ */
case 0x93: /* ランドマイン */
@@ -4407,25 +4473,27 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case AS_SPLASHER: /* ベナムスプラッシャ? */
- if((double)battle_get_max_hp(bl)*2/3 < battle_get_hp(bl)) //HPが2/3以上?っていたら失敗
+ if((double)status_get_max_hp(bl)*2/3 < status_get_hp(bl)) { //HPが2/3以上?っていたら失敗
+ map_freeblock_unlock();
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 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,src->id,skill_get_time(skillid,skilllv),1000,0 );
break;
case PF_MINDBREAKER: /* プロボック */
{
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_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))) //不死には?かない
+ if((dstmd && status_get_mode(bl)&0x20) || battle_check_undead(status_get_race(bl),status_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 );
+ 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);
@@ -4435,22 +4503,55 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
if(sc_data){
if(sc_data[SC_FREEZE].timer!=-1)
- skill_status_change_end(bl,SC_FREEZE,-1);
+ 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);
+ status_change_end(bl,SC_STONE,-1);
if(sc_data[SC_SLEEP].timer!=-1)
- skill_status_change_end(bl,SC_SLEEP,-1);
+ 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);
+ if(dstmd)
+ mob_target(dstmd,src,skill_get_range(skillid,skilllv));
+ }
+ break;
+
+ case PF_SOULCHANGE:
+ {
+ int sp1 = 0, sp2 = 0;
+ if (sd) {
+ if (dstsd) {
+ sp1 = sd->status.sp > dstsd->status.max_sp ? dstsd->status.max_sp : sd->status.sp;
+ sp2 = dstsd->status.sp > sd->status.max_sp ? sd->status.max_sp : dstsd->status.sp;
+ sd->status.sp = sp2;
+ dstsd->status.sp = sp1;
+ clif_heal(sd->fd,SP_SP,sp2);
+ clif_updatestatus(sd,SP_SP);
+ clif_heal(dstsd->fd,SP_SP,sp1);
+ clif_updatestatus(dstsd,SP_SP);
+ } else if (dstmd) {
+ if (dstmd->state.soul_change_flag) {
+ clif_skill_fail(sd,skillid,0,0);
+ map_freeblock_unlock();
+ return 0;
+ }
+ sp2 = sd->status.max_sp * 3 /100;
+ if (sd->status.sp + sp2 > sd->status.max_sp)
+ sp2 = sd->status.max_sp - sd->status.sp;
+ sd->status.sp += sp2;
+ clif_heal(sd->fd,SP_SP,sp2);
+ clif_updatestatus(sd,SP_SP);
+ dstmd->state.soul_change_flag = 1;
+ }
}
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
+ case PF_SPIDERWEB: /* スパイダ?ウェッブ */
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ skill_unitsetting(src,skillid,skilllv,bl->x,bl->y,0);
+ break;
+
// Weapon Refining [Celest]
case WS_WEAPONREFINE:
if(sd)
@@ -4461,12 +4562,18 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case CR_SLIMPITCHER:
{
if (sd && flag&1) {
- int hp = sd->potion_hp * (100 + pc_checkskill(sd,CR_SLIMPITCHER)*5 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
- hp = hp * (100 + (battle_get_vit(bl)<<1))/100;
- if (dstsd)
+ struct block_list tbl;
+ int hp = sd->potion_hp * (100 + pc_checkskill(sd,CR_SLIMPITCHER)*10 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
+ hp = hp * (100 + (status_get_vit(bl)<<1))/100;
+ if (dstsd) {
hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10)/100;
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- battle_heal(src,bl,hp,0,0);
+ }
+ tbl.id = 0;
+ tbl.m = src->m;
+ tbl.x = src->x;
+ tbl.y = src->y;
+ clif_skill_nodamage(&tbl,bl,AL_HEAL,hp,1);
+ battle_heal(NULL,bl,hp,0,0);
}
}
break;
@@ -4474,13 +4581,13 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case CR_FULLPROTECTION:
{
int i, skilltime;
- struct status_change *tsc_data = battle_get_sc_data(bl);
+ struct status_change *tsc_data = status_get_sc_data(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skilltime = skill_get_time(skillid,skilllv);
for (i=0; i<4; i++) {
if(tsc_data && tsc_data[SC_STRIPWEAPON + i].timer != -1)
- skill_status_change_end(bl, SC_STRIPWEAPON + i, -1 );
- skill_status_change_start(bl,SC_CP_WEAPON + i,skilllv,0,0,0,skilltime,0 );
+ status_change_end(bl, SC_STRIPWEAPON + i, -1 );
+ status_change_start(bl,SC_CP_WEAPON + i,skilllv,0,0,0,skilltime,0 );
}
}
break;
@@ -4498,6 +4605,15 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
}
break;
+ case ST_PRESERVE:
+ if (sd){
+ if (sd->sc_count && sd->sc_data[SC_PRESERVE].timer != -1)
+ status_change_end(src, SC_PRESERVE, -1 );
+ else
+ status_change_start(src,SC_PRESERVE,skilllv,0,0,0,skill_get_time(skillid, skilllv),0 );
+ clif_skill_nodamage(src,src,skillid,skilllv,1);
+ }
+ break;
// New guild skills [Celest]
case GD_BATTLEORDER:
@@ -4511,7 +4627,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
if(flag&1) {
if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
- skill_status_change_start(&dstsd->bl,SC_BATTLEORDERS,skilllv,0,0,0,0,0 );
+ status_change_start(&dstsd->bl,SC_BATTLEORDERS,skilllv,0,0,0,0,0 );
}
}
else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
@@ -4521,6 +4637,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
src,skillid,skilllv,tick, flag|BCT_ALL|1,
skill_castend_nodamage_id);
+ pc_blockskill_start (sd, skillid, 300000);
}
}
break;
@@ -4535,7 +4652,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
if(flag&1) {
if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
- skill_status_change_start(&dstsd->bl,SC_REGENERATION,skilllv,0,0,0,0,0 );
+ status_change_start(&dstsd->bl,SC_REGENERATION,skilllv,0,0,0,0,0 );
}
}
else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
@@ -4545,10 +4662,11 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
src,skillid,skilllv,tick, flag|BCT_ALL|1,
skill_castend_nodamage_id);
+ pc_blockskill_start (sd, skillid, 300000);
}
}
break;
- case GD_RESTORE:
+ case GD_RESTORE:
{
struct guild *g = NULL;
// Only usable during WoE
@@ -4560,8 +4678,8 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
if(flag&1) {
if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
int hp, sp;
- hp = dstsd->status.max_hp*0.9;
- sp = dstsd->status.max_sp*0.9;
+ hp = dstsd->status.max_hp*9/10;
+ sp = dstsd->status.max_sp*9/10;
sp = dstsd->status.sp + sp <= dstsd->status.max_sp ? sp : dstsd->status.max_sp - dstsd->status.sp;
clif_skill_nodamage(src,bl,AL_HEAL,hp,1);
battle_heal(NULL,bl,hp,sp,0);
@@ -4574,6 +4692,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
src,skillid,skilllv,tick, flag|BCT_ALL|1,
skill_castend_nodamage_id);
+ pc_blockskill_start (sd, skillid, 300000);
}
}
break;
@@ -4581,10 +4700,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
{
int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0};
int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0};
- int c, j = 0;
+ int j = 0;
struct guild *g = NULL;
// Only usable during WoE
- if (!agit_flag) {
+ if (!agit_flag ||
+ (sd && map[sd->bl.m].flag.nowarpto && // if not allowed to warp to the map
+ guild_mapname2gc(sd->mapname) == NULL)) { // and it's not a castle...
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 0;
@@ -4594,17 +4715,21 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
strcmp(sd->status.name,g->master)==0) {
for(i = 0; i < g->max_member; i++, j++) {
if (j>8) j=0;
- if ((dstsd = g->member[i].sd) != NULL && sd != dstsd &&
- !map[sd->bl.m].flag.nowarpto && !map[dstsd->bl.m].flag.nowarp) {
+ if ((dstsd = g->member[i].sd) != NULL && sd != dstsd) {
+ if (map[dstsd->bl.m].flag.nowarp &&
+ guild_mapname2gc(sd->mapname) == NULL)
+ continue;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if ((c=read_gat(sd->bl.m,sd->bl.x+dx[j],sd->bl.y+dy[j]))==1 || c==5)
+ if(map_getcell(sd->bl.m,sd->bl.x+dx[j],sd->bl.y+dy[j],CELL_CHKNOPASS))
dx[j] = dy[j] = 0;
pc_setpos(dstsd, sd->mapname, sd->bl.x+dx[j], sd->bl.y+dy[j], 2);
}
}
+ pc_blockskill_start (sd, skillid, 300000);
}
}
break;
+
default:
printf("Unknown skill used:%d\n",skillid);
map_freeblock_unlock();
@@ -4653,7 +4778,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data )
}
if(sd->skillid == PR_LEXAETERNA) {
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_get_sc_data(bl);
if(sc_data && (sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0))) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
@@ -4663,7 +4788,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data )
}
}
else if(sd->skillid == RG_BACKSTAP) {
- int dir = map_calc_dir(&sd->bl,bl->x,bl->y),t_dir = battle_get_dir(bl);
+ int dir = map_calc_dir(&sd->bl,bl->x,bl->y),t_dir = status_get_dir(bl);
int dist = distance(sd->bl.x,sd->bl.y,bl->x,bl->y);
if(bl->type != BL_SKILL && (dist == 0 || map_check_dir(dir,t_dir))) {
clif_skill_fail(sd,sd->skillid,0,0);
@@ -4686,7 +4811,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data )
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))
+ if(inf2 & 0x800 && sd->status.guild_id > 0 && sd->status.guild_id == status_get_guild_id(bl))
fail_flag = 0;
if(fail_flag) {
clif_skill_fail(sd,sd->skillid,0,0);
@@ -4699,7 +4824,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data )
range = skill_get_range(sd->skillid,sd->skilllv);
if(range < 0)
- range = battle_get_range(&sd->bl) - (range + 1);
+ range = status_get_range(&sd->bl) - (range + 1);
range += battle_config.pc_skill_add_range;
if((sd->skillid == MO_EXTREMITYFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) ||
(sd->skillid == CH_TIGERFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) ||
@@ -4742,7 +4867,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data )
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)))
+ if( (sd->skillid==AL_HEAL || (sd->skillid==ALL_RESURRECTION && bl->type != BL_PC) || sd->skillid==PR_ASPERSIO) && battle_check_undead(status_get_race(bl),status_get_elem_type(bl)))
skill_castend_damage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0);
else
skill_castend_nodamage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0);
@@ -4761,21 +4886,21 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
struct map_session_data *sd=NULL;
int i,tmpx = 0,tmpy = 0, x1 = 0, y1 = 0;
- if(skilllv <= 0) return 0;
+ //if(skilllv <= 0) return 0;
+ if(skillid > 0 && skilllv <= 0) return 0; // celest
nullpo_retr(0, src);
if(src->type==BL_PC){
nullpo_retr(0, sd=(struct map_session_data *)src);
}
- if( skillid != WZ_METEOR &&
- skillid != WZ_SIGHTRASHER &&
+ if( skillid != WZ_METEOR &&
skillid != AM_CANNIBALIZE &&
skillid != AM_SPHEREMINE)
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
- if (skillnotok(skillid, sd)) // [MouseJstr]
- return 0;
+ if (sd && skillnotok(skillid, sd)) // [MouseJstr]
+ return 0;
switch(skillid)
{
@@ -4792,20 +4917,31 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
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);
+ {
+ int r = 2;
+ if (skilllv > 5) {
+ r = 14;
+ skilllv = 5; // スタン率上がりすぎるため計算はLv5で固定
+ }
+ skill_area_temp[1] = src->id;
+ skill_area_temp[2] = x;
+ skill_area_temp[3] = y;
+ map_foreachinarea (skill_area_sub,
+ src->m, x-r, y-r, x+r, y+r, 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,
+ int range=skilllv*2+1;
+ if(src->x!=x)
+ x+=(src->x-x>0)?-range:range;
+ if(src->y!=y)
+ y+=(src->y-y>0)?-range:range;
+ map_foreachinarea( status_change_timer_sub,
+ src->m, x-range, y-range, x+range,y+range,0,
src,SC_SIGHT,tick);
}
break;
@@ -4816,15 +4952,15 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
case AL_PNEUMA: /* ニュ?マ */
case WZ_ICEWALL: /* アイスウォ?ル */
case WZ_FIREPILLAR: /* ファイアピラ? */
- case WZ_SIGHTRASHER:
case WZ_QUAGMIRE: /* クァグマイア */
case WZ_VERMILION: /* ロ?ドオブヴァ?ミリオン */
- case WZ_FROSTNOVA: /* フロストノヴァ */
+ //case WZ_FROSTNOVA: /* フロストノヴァ */
case WZ_STORMGUST: /* スト?ムガスト */
case WZ_HEAVENDRIVE: /* ヘヴンズドライブ */
case PR_SANCTUARY: /* サンクチュアリ */
case PR_MAGNUS: /* マグヌスエクソシズム */
case CR_GRANDCROSS: /* グランドクロス */
+ case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
case HT_SKIDTRAP: /* スキッドトラップ */
case HT_LANDMINE: /* ランドマイン */
case HT_ANKLESNARE: /* アンクルスネア */
@@ -4836,12 +4972,11 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
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);
@@ -4859,7 +4994,7 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
{
int flag=0;
for(i=0;i<2+(skilllv>>1);i++) {
- int j=0, c;
+ int j=0;
do {
tmpx = x + (rand()%7 - 3);
tmpy = y + (rand()%7 - 3);
@@ -4872,7 +5007,7 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
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);
+ } while((map_getcell(src->m,tmpx,tmpy,CELL_CHKNOPASS)) && j<100);
if(j >= 100)
continue;
if(flag==0){
@@ -4903,37 +5038,43 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
pc_movepos(sd,x,y);
}else if( src->type==BL_MOB )
mob_warp((struct mob_data *)src,-1,x,y,0);
+ if (sd)
+ pc_blockskill_start (sd, MO_EXTREMITYFIST, 2000);
break;
case AM_CANNIBALIZE: // バイオプラント
- if(sd){
- int mx,my,id=0;
+ if(sd) {
+ int id;
+ int summons[5] = { 1020, 1068, 1118, 1500, 1368 };
struct mob_data *md;
- mx = x;// + (rand()%10 - 5);
- my = y;// + (rand()%10 - 5);
- id=mob_once_spawn(sd,"this",mx,my,"--ja--",1118,1,"");
+ // Correct info, don't change any of this! [celest]
+ id = mob_once_spawn (sd, "this", x, y, "--ja--", summons[skilllv-1] ,1,"");
+
if( (md=(struct mob_data *)map_id2bl(id)) !=NULL ){
- md->master_id=sd->bl.id;
- md->hp=2210+skilllv*200;
- md->state.special_mob_ai=1;
- md->deletetimer=add_timer(gettick()+skill_get_time(skillid,skilllv),mob_timer_delete,id,0);
- }
+ md->master_id = sd->bl.id;
+ // different levels of HP according to skill level
+ md->hp = 1500 + skilllv * 200 + sd->status.base_level * 10;
+ md->state.special_mob_ai = 1;
+ //非移動でアクティブで反撃する[0x0:非移動 0x1:移動 0x4:ACT 0x8:非ACT 0x40:反撃無 0x80:反撃有]
+ md->mode = 0x0 + 0x4 + 0x80;
+ md->deletetimer = add_timer (gettick() + skill_get_time(skillid,skilllv), mob_timer_delete, id, 0);
+ }
+ // To-do: 召還されるモンスターには召還したプレーヤーの名前が付きます
+ // (attach name of player?)
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
}
break;
case AM_SPHEREMINE: // スフィア?マイン
if(sd){
- int mx,my,id=0;
+ int id;
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,"");
+ id = mob_once_spawn(sd, "this", x, y, "--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);
+ md->master_id = sd->bl.id;
+ md->hp = 2000 + skilllv * 400;
+ md->state.special_mob_ai = 2;
+ md->deletetimer = add_timer (gettick() + skill_get_time(skillid,skilllv), mob_timer_delete, id, 0);
}
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
}
@@ -4943,24 +5084,24 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
case CR_SLIMPITCHER:
{
if (sd) {
- int x = skilllv%11 - 1;
- int i = pc_search_inventory(sd,skill_db[skillid].itemid[x]);
- if(i < 0 || skill_db[skillid].itemid[x] <= 0 || sd->inventory_data[i] == NULL ||
- sd->status.inventory[i].amount < skill_db[skillid].amount[x]) {
+ int i = skilllv%11 - 1;
+ int j = pc_search_inventory(sd,skill_db[skillid].itemid[i]);
+ if(j < 0 || skill_db[skillid].itemid[i] <= 0 || sd->inventory_data[j] == NULL ||
+ sd->status.inventory[j].amount < skill_db[skillid].amount[i]) {
clif_skill_fail(sd,skillid,0,0);
- map_freeblock_unlock();
return 1;
}
sd->state.potionpitcher_flag = 1;
sd->potion_hp = 0;
- run_script(sd->inventory_data[i]->use_script,0,sd->bl.id,0);
- pc_delitem(sd,i,skill_db[skillid].amount[x],0);
+ run_script(sd->inventory_data[j]->use_script,0,sd->bl.id,0);
+ pc_delitem(sd,j,skill_db[skillid].amount[i],0);
sd->state.potionpitcher_flag = 0;
+ clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
if(sd->potion_hp > 0) {
map_foreachinarea(skill_area_sub,
src->m,x-3,y-3,x+3,y+3,0,
- src,skillid,skilllv,tick,flag|BCT_ALL|1,
- skill_castend_nodamage_id);
+ src,skillid,skilllv,tick,flag|BCT_PARTY|1,
+ skill_castend_nodamage_id);
}
}
}
@@ -4982,13 +5123,13 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
if( sd->bl.prev == NULL || pc_isdead(sd) )
return 0;
- if(skillnotok(skill_num, sd))
- return 0;
+ if(skillnotok(skill_num, sd))
+ return 0;
if( sd->opt1>0 || sd->status.option&2 )
return 0;
//スキルが使えない?態異常中
- if(sd->sc_data){
+ if(sd->sc_count){
if( sd->sc_data[SC_DIVINA].timer!=-1 ||
sd->sc_data[SC_ROKISWEIL].timer!=-1 ||
sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||
@@ -4997,10 +5138,6 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
sd->sc_data[SC_BERSERK].timer != -1 ||
sd->sc_data[SC_MARIONETTE].timer != -1)
return 0;
-
- if (sd->sc_data[SC_BLOCKSKILL].timer!=-1)
- if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3)
- return 0;
}
if( skill_num != sd->skillid) /* 不正パケットらしい */
@@ -5026,13 +5163,14 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
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],
- };
+ const struct point *p[4];
struct skill_unit_group *group;
int i;
int maxcount=0;
+ p[0] = &sd->status.save_point;
+ p[1] = &sd->status.memo_point[0];
+ p[2] = &sd->status.memo_point[1];
+ p[3] = &sd->status.memo_point[2];
if((maxcount = skill_get_maxcount(sd->skillid)) > 0) {
int c;
@@ -5064,7 +5202,7 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
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));
+ group->valstr=(char *)aCallocA(24,sizeof(char));
memcpy(group->valstr,map,24);
group->val2=(x<<16)|y;
}
@@ -5081,561 +5219,176 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag)
{
struct skill_unit_group *group;
- int i,count=1,limit=10000,val1=0,val2=0;
- int target=BCT_ENEMY,interval=1000,range=0;
- int dir=0,aoe_diameter=0; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills
- struct status_change *sc_data = battle_get_sc_data(src); // for firewall and fogwall - celest
+ int i,limit,val1=0,val2=0,val3=0;
+ int count=0;
+ int target,interval,range,unit_flag;
+ struct skill_unit_layout *layout;
+ struct status_change *sc_data;
+ int active_flag=1;
nullpo_retr(0, src);
+ limit = skill_get_time(skillid,skilllv);
+ range = skill_get_unit_range(skillid);
+ interval = skill_get_unit_interval(skillid);
+ target = skill_get_unit_target(skillid);
+ unit_flag = skill_get_unit_flag(skillid);
+ layout = skill_get_unit_layout(skillid,skilllv,src,x,y);
+
+ if (unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy)
+ target = BCT_NOENEMY;
+
+ sc_data = status_get_sc_data(src); // for firewall and fogwall - celest
+
switch(skillid){ /* 設定 */
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);
- if(sc_data) {
- if (sc_data[SC_VIOLENTGALE].timer!=-1) limit *= 1.5;
- }
- // check for sc_data first - Celest
- // if (((struct map_session_data *)src)->sc_data[SC_VIOLENTGALE].timer!=-1)
- // limit *= 1.5;
+ if(sc_data && sc_data[SC_VIOLENTGALE].timer!=-1)
+ limit = limit*3/2;
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);
+ active_flag=0;
break;
case PR_SANCTUARY: /* サンクチュアリ */
- count=21;
- limit=skill_get_time(skillid,skilllv);
- val1=skilllv+3;
+ val1=(skilllv+3)*2;
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;
+ interval += 500;
break;
case WZ_FIREPILLAR: /* ファイア?ピラ? */
- if(flag==0)
- limit=skill_get_time(skillid,skilllv);
- else
+ if(flag!=0)
limit=1000;
- interval=2000;
val1=skilllv+2;
- if(skilllv < 6)
- range=1;
- else
- range=2;
- 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;
+ if(skilllv >= 6)
+ range=2;
break;
-
- case WZ_STORMGUST: /* スト?ムガスト */
- limit=4600;
- interval=450;
- range=5;
+ case WZ_METEOR:
+ if (skilllv > 10) //広範囲メテオ
+ range = 10;
break;
-
- case WZ_QUAGMIRE: /* クァグマイア */
- limit=skill_get_time(skillid,skilllv);
- interval=200;
- count=25;
+ case WZ_VERMILION:
+ if (skilllv > 10) //広範囲LOV
+ range = 25;
break;
case HT_SANDMAN: /* サンドマン */
case HT_CLAYMORETRAP: /* クレイモア?トラップ */
- limit=skill_get_time(skillid,skilllv);
- range=2;
- break;
case HT_SKIDTRAP: /* スキッドトラップ */
case HT_LANDMINE: /* ランドマイン */
case HT_ANKLESNARE: /* アンクルスネア */
- case PF_SPIDERWEB: /* スパイダ?ウェッブ */
case HT_FLASHER: /* フラッシャ? */
case HT_FREEZINGTRAP: /* フリ?ジングトラップ */
case HT_BLASTMINE: /* ブラストマイン */
- limit=skill_get_time(skillid,skilllv);
- range=1;
+ // longer trap times in WOE [celest]
+ if (map[src->m].flag.gvg) limit *= 4;
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;
+ {
+ int aoe_diameter; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills
+ val1=skilllv*15+10;
+ aoe_diameter=skilllv+skilllv%2+5;
+ count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul)
+ }
break;
case BA_WHISTLE: /* 口笛 */
- 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;
+ val2 = ((status_get_agi(src)/10)&0xffff)<<16;
+ val2 |= (status_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;
+ val2 = status_get_dex(src)/10;
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;
+ val2 = ((status_get_dex(src)/20)&0xffff)<<16;
+ val2 |= (status_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;
+ val2 = ((status_get_dex(src)/10)&0xffff)<<16;
+ val2 |= (status_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?加)
+ val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)&0xffff;
+ val2 |= (status_get_vit(src))&0xffff;
+ val3 = 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;
+ val2 = status_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;
+ val2 = status_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);
- //sd->canmove_tick = gettick() + limit; // added later [celest]
- break;
-
- case PA_GOSPEL: /* ゴスペル */
- count=49;
- target=BCT_PARTY;
- limit=skill_get_time(skillid,skilllv);
- break;
-
- case CG_MOONLIT:
- range=1;
- target=BCT_ALL;
- limit=skill_get_time(skillid,skilllv);
+ val2 = status_get_luk(src)/10;
break;
case PF_FOGWALL: /* フォグウォ?ル */
- count=15;
- limit=skill_get_time(skillid,skilllv);
- if(sc_data) {
- if (sc_data[SC_DELUGE].timer!=-1) limit *= 2;
- }
+ if(sc_data && sc_data[SC_DELUGE].timer!=-1) limit *= 2;
break;
case RG_GRAFFITI: /* Graffiti */
count=1; // Leave this at 1 [Valaris]
- limit=600000; // Time length [Valaris]
- break;
-
- case GD_LEADERSHIP:
- case GD_GLORYWOUNDS:
- case GD_SOULCOLD:
- case GD_HAWKEYES:
- range=2;
- target=BCT_NOENEMY;
- limit=600000;
break;
}
- nullpo_retr(NULL, group=skill_initunitgroup(src,count,skillid,skilllv,skill_get_unit_id(skillid,flag&1)));
+ nullpo_retr(NULL, group=skill_initunitgroup(src,(count > 0 ? count : layout->count),
+ skillid,skilllv,skill_get_unit_id(skillid,flag&1)));
group->limit=limit;
group->val1=val1;
group->val2=val2;
+ group->val3=val3;
group->target_flag=target;
group->interval=interval;
- group->range=range;
if(skillid==HT_TALKIEBOX ||
skillid==RG_GRAFFITI){
- group->valstr=calloc(80, 1);
+ group->valstr=(char *) aCallocA(80, 1);
if(group->valstr==NULL){
printf("skill_castend_map: out of memory !\n");
exit(1);
}
memcpy(group->valstr,talkie_mes,80);
}
- for(i=0;i<count;i++){
+ for(i=0;i<layout->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;
+ int ux,uy,val1=skilllv,val2=0,limit=group->limit,alive=1;
+ ux = x + layout->dx[i];
+ uy = y + layout->dy[i];
+ switch (skillid) {
case MG_FIREWALL: /* ファイヤ?ウォ?ル */
- {
- 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];
- }
+ val2=group->val2;
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: /* サ?ビスフォ?ユ? */
- case CG_MOONLIT:
- 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);
@@ -5647,7 +5400,7 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,
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);
+ val2=map_getcell(src->m,ux,uy,CELL_GETTYPE);
if(val2==5 || val2==1)
alive=0;
else {
@@ -5663,30 +5416,13 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,
unit->limit=limit;
unit->range=range;
- // [celest]
- if (sc_data) {
- // attach the unit's id to the caster
- switch (skillid) {
- case HP_BASILICA:
- if (sc_data[SC_BASILICA].timer!=-1)
- sc_data[SC_BASILICA].val4 = (int)unit;
- break;
- case GD_LEADERSHIP:
- sc_data[SC_LEADERSHIP].val4 = (int)unit;
- break;
- case GD_GLORYWOUNDS:
- sc_data[SC_GLORYWOUNDS].val4 = (int)unit;
- break;
- case GD_SOULCOLD:
- sc_data[SC_SOULCOLD].val4 = (int)unit;
- break;
- case GD_HAWKEYES:
- sc_data[SC_HAWKEYES].val4 = (int)unit;
- break;
- }
- }
+ if (range==0 && active_flag)
+ map_foreachinarea(skill_unit_effect,unit->bl.m
+ ,unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y
+ ,0,&unit->bl,gettick(),1);
}
}
+
return group;
}
@@ -5698,126 +5434,245 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
{
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;
+ struct skill_unit *unit2;
+ struct status_change *sc_data;
+ int type;
nullpo_retr(0, src);
nullpo_retr(0, bl);
-
- if( bl->prev==NULL || !src->alive || (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl) ) )
+
+ if(bl->prev==NULL || !src->alive ||
+ (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)))
return 0;
nullpo_retr(0, sg=src->group);
nullpo_retr(0, ss=map_id2bl(sg->src_id));
+
+ sc_data = status_get_sc_data(bl);
+ type = SkillStatusChangeTable[sg->skill_id];
- if(ss->type == BL_PC)
- nullpo_retr(0, srcsd=(struct map_session_data *)ss);
- if(srcsd && srcsd->chatID)
+ if (battle_check_target(&src->bl,bl,sg->target_flag)<=0)
return 0;
- if( bl->type!=BL_PC && bl->type!=BL_MOB )
+ // 対象がLP上に居る場合は無効
+ if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL))
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);
+ switch (sg->unit_id) {
+ case 0x85: /* ニューマ */
+ case 0x7e: /* セイフティウォール */
+ if (sc_data && sc_data[type].timer == -1)
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
+ break;
- if(!goflag)
- return 0;
- ts->tick=tick;
- ts->group_id=sg->group_id;
+ 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 ){
+ pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3);
+ if(sg->src_id == bl->id || (strcmp(map[src->bl.m].name,sg->valstr) == 0 &&
+ src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) ))
+ skill_delunitgroup(sg);
+ if (--sg->val1<=0)
+ skill_delunitgroup(sg);
+ }
+ }
+ } else if(bl->type==BL_MOB && battle_config.mob_warpportal){
+ int m = map_mapname2mapid(sg->valstr);
+ mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3);
+ }
+ break;
- 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;
+ case 0x8e: /* クァグマイア */
+ if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ break;
+ if(sc_data && sc_data[type].timer==-1)
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,
+ skill_get_time2(sg->skill_id,sg->skill_lv),0);
+ break;
- if( battle_get_hp(bl)>=battle_get_max_hp(bl) && !damage_flag)
+ case 0x9a: /* ボルケ?ノ */
+ case 0x9b: /* デリュ?ジ */
+ case 0x9c: /* バイオレントゲイル */
+ if (sc_data && sc_data[type].timer!=-1) {
+ unit2 = (struct skill_unit *)sc_data[type].val4;
+ if (unit2 && unit2->group &&
+ (unit2==src || DIFF_TICK(sg->tick,unit2->group->tick)<=0))
break;
+ }
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,
+ skill_get_time2(sg->skill_id,sg->skill_lv),0);
+ break;
- 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);
+ 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: /* サ?ビスフォ?ユ? */
+ if (sg->src_id==bl->id)
+ break;
+ if (sc_data && sc_data[type].timer!=-1) {
+ unit2 = (struct skill_unit *)sc_data[type].val4;
+ if (unit2 && unit2->group &&
+ (unit2 == src || DIFF_TICK(sg->tick,unit2->group->tick)<=0))
+ break;
}
+ status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
+ (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
break;
- case 0x84: /* マグヌスエクソシズム */
- {
- int race=battle_get_race(bl);
- int damage_flag = (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6)? 1:0;
+ case 0xb4: // Basilica
+ if (battle_check_target(&src->bl,bl,BCT_NOENEMY)>0) {
+ if (sc_data && sc_data[type].timer!=-1) {
+ struct skill_unit_group *sg2 = (struct skill_unit_group *)sc_data[type].val4;
+ if (sg2 && (sg2 == src->group || DIFF_TICK(sg->tick,sg2->tick)<=0))
+ break;
+ } else
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,
+ skill_get_time2(sg->skill_id,sg->skill_lv),0);
+ } else if (!status_get_mode(bl)&0x20)
+ skill_blown(&src->bl,bl,1);
+ break;
- if(!damage_flag)
- return 0;
- skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+ case 0xb6: /* フォグウォ?ル */
+ if (sc_data && sc_data[type].timer!=-1) {
+ struct skill_unit_group *sg2 = (struct skill_unit_group *)sc_data[type].val4;
+ if (sg2 && (sg2 == src->group || DIFF_TICK(sg->tick,sg2->tick)<=0))
+ break;
}
+ status_change_start (bl, type, sg->skill_lv, sg->val1, sg->val2, (int)sg,
+ skill_get_time2(sg->skill_id, sg->skill_lv), 0);
+ if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0)
+ skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, tick);
+ break;
+
+ case 0xb2: /* あなたを_?いたいです */
+ case 0xb3: /* ゴスペル */
+ //とりあえず何もしない
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;*/
+ }
- case 0x85: /* ニュ?マ */
+ return 0;
+}
+
+/*==========================================
+ * スキルユニットの発動イベント(タイマー発動)
+ *------------------------------------------
+ */
+int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsigned int tick)
+{
+ struct skill_unit_group *sg;
+ struct block_list *ss;
+ int splash_count=0;
+ struct status_change *sc_data;
+ struct skill_unit_group_tickset *ts;
+ int type;
+ int diff=0;
+
+ nullpo_retr(0, src);
+ nullpo_retr(0, bl);
+
+ if (bl->type!=BL_PC && bl->type!=BL_MOB)
+ return 0;
+
+ if (bl->prev==NULL || !src->alive ||
+ (bl->type==BL_PC && pc_isdead((struct map_session_data *)bl)))
+ return 0;
+
+ nullpo_retr(0, sg=src->group);
+ nullpo_retr(0, ss=map_id2bl(sg->src_id));
+ sc_data = status_get_sc_data(bl);
+ type = SkillStatusChangeTable[sg->skill_id];
+
+ // 対象がLP上に居る場合は無効
+ if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL))
+ return 0;
+
+ // 前に影響を受けてからintervalの間は影響を受けない
+ nullpo_retr(0,ts = skill_unitgrouptickset_search(bl,sg,tick));
+ diff = DIFF_TICK(tick,ts->tick);
+ if (sg->skill_id == PR_SANCTUARY)
+ diff += 500; // 新規に回復したユニットだけカウントするための仕掛け
+ if (diff < 0)
+ return 0;
+ ts->tick = tick+sg->interval;
+ // GXは重なっていたら3HITしない
+ if (sg->skill_id==CR_GRANDCROSS && !battle_config.gx_allhit)
+ ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y)-1);
+
+ switch (sg->unit_id) {
+ case 0x83: /* サンクチュアリ */
{
- 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;
- }
+ int race = status_get_race(bl);
+
+ if (battle_check_undead(race, status_get_elem_type(bl)) || race==6) {
+ if (skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0)) {
+ // reduce healing count if this was meant for damaging [hekate]
+ sg->val1 -= 2;
+ //sg->val1--; // チャットキャンセルに対応
+ }
+ } else {
+ int heal = sg->val2;
+ if (status_get_hp(bl) >= status_get_max_hp(bl))
+ break;
+ if (bl->type == BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage)
+ heal = 0; /* 黄金蟲カード(ヒール量0) */
+ clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
+ battle_heal(NULL, bl, heal, 0, 0);
+ if (diff >= 500)
+ sg->val1--; // 新規に入ったユニットだけカウント
+ }
+ if (sg->val1 <= 0)
+ skill_delunitgroup(sg);
+ break;
}
- break;
- case 0x7e: /* セイフティウォ?ル */
+
+ case 0x84: /* マグヌスエクソシズム */
{
- 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;
- }
+ int race = status_get_race(bl);
+ if (!battle_check_undead(race,status_get_elem_type(bl)) && race!=6)
+ return 0;
+ skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+ src->val2++;
+ break;
}
- break;
- case 0x86: /* ロ?ドオブヴァ?ミリオン(&スト?ムガスト &グランドクロス) */
+ case 0x7f: /* ファイヤーウォール */
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 )
+ if (--src->val2<=0)
skill_delunit(src);
break;
-
- case 0x87: /* ファイア?ピラ?(?動前) */
+ case 0x86: /* ロードオブヴァーミリオン(TS,MS,FN,SG,HD,GX,闇GX) */
+ skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+ break;
+ case 0x87: /* ファイアーピラー(発動前) */
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);
- map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest]
+ case 0x88: /* ファイアーピラー(発動後) */
+ map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
+ BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest]
+ //skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
case 0x90: /* スキッドトラップ */
@@ -5830,7 +5685,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
clif_changelook(&src->bl,LOOK_BASE,sg->unit_id);
sg->limit=DIFF_TICK(tick,sg->tick)+1500;
}
- break;
+ break;
case 0x93: /* ランドマイン */
skill_attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
@@ -5859,20 +5714,22 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
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){
+ 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);
-
+ int sec = skill_get_time2(sg->skill_id,sg->skill_lv) - status_get_agi(bl)*100;
+ if(status_get_mode(bl)&0x20)
+ sec = sec/5;
+ if (sec < 3000) // minimum time of 3 seconds [celest]
+ sec = 3000;
+ battle_stopwalking(bl,1);
+ status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0);
+
+ skill_unit_move(bl,tick,0);
if(moveblock) map_delblock(bl);
bl->x = src->bl.x;
bl->y = src->bl.y;
if(moveblock) map_addblock(bl);
+ skill_unit_move(bl,tick,1);
if(bl->type == BL_MOB)
clif_fixmobpos((struct mob_data *)bl);
else if(bl->type == BL_PET)
@@ -5880,129 +5737,26 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
else
clif_fixpos(bl);
clif_01ac(&src->bl);
- sg->limit=DIFF_TICK(tick,sg->tick) + sec;
+ sg->limit=DIFF_TICK(tick,sg->tick) + sec;
sg->val2=bl->id;
- }
+ sg->interval = -1;
+ src->range = 0;
}
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);
- }
+ if(sc_data && sc_data[type].timer==-1 )
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
break;
- case 0x9a: /* ボルケ?ノ */
- 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:
- case 0xb6: /* フォグウォ?ル */
- {
- 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) {
- if (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 && rand()%100 < sg->skill_lv && battle_config.equipment_breaking)
pc_breakweapon((struct map_session_data *)bl);
break;
- case 0x99: /* ト?キ?ボックス */
- if(sg->src_id == bl->id) //自分が踏んでも?動しない
+
+ case 0x99: /* トーキーボックス */
+ if(sg->src_id == bl->id) //自分が踏んでも発動しない
break;
if(sg->val2==0){
clif_talkiebox(&src->bl,sg->valstr);
@@ -6011,68 +5765,40 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
sg->limit=DIFF_TICK(tick,sg->tick)+5000;
sg->val2=-1; //踏んだ
}
- break;
- case 0xb2: /* あなたを_?いたいです */
- case 0xb3: /* ゴスペル */
- //case 0xb6: /* フォグウォ?ル */ - moved [celest]
- //とりあえず何もしない
+ break;
+
+ // Basilica
+ case 0xb4: /* バジリカ */
+ if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0 &&
+ !(status_get_mode(bl)&0x20))
+ skill_blown(&src->bl,bl,1);
+ if (sg->src_id==bl->id)
+ break;
+ if (battle_check_target(&src->bl,bl,BCT_NOENEMY)>0 && sc_data && sc_data[type].timer == -1)
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,
+ skill_get_time2(sg->skill_id,sg->skill_lv),0);
break;
case 0xb7: /* スパイダ?ウェッブ */
if(sg->val2==0){
int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE);
skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
+ skill_unit_move(bl,tick,0);
if(moveblock) map_delblock(bl);
- bl->x = (&src->bl)->x;
- bl->y = (&src->bl)->y;
+ bl->x = src->bl.x;
+ bl->y = src->bl.y;
if(moveblock) map_addblock(bl);
- if(bl->type == BL_MOB)
- clif_fixmobpos((struct mob_data *)bl);
- else if(bl->type == BL_PET)
- clif_fixpetpos((struct pet_data *)bl);
- else
- clif_fixpos(bl);
- clif_01ac(&src->bl);
- sg->limit=DIFF_TICK(tick,sg->tick) + skill_get_time2(sg->skill_id,sg->skill_lv);
+ skill_unit_move(bl,tick,1);
+ if(bl->type == BL_MOB)
+ clif_fixmobpos((struct mob_data *)bl);
+ else if(bl->type == BL_PET)
+ clif_fixpetpos((struct pet_data *)bl);
+ else
+ clif_fixpos(bl);
+ sg->limit = DIFF_TICK(tick,sg->tick)+skill_get_time2(sg->skill_id,sg->skill_lv);
sg->val2=bl->id;
- }
- break;
-
- // New guild skills [Celest]
- case 0xc1: // GD_LEADERSHIP
- {
- struct map_session_data *sd;
- if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
- sd->status.guild_id == srcsd->status.guild_id &&
- sd->sc_data[SC_LEADERSHIP].timer == -1 && !sd->sc_data[SC_LEADERSHIP].val4)
- skill_status_change_start(bl,SC_LEADERSHIP,1,0,0,0,0,0 );
- }
- break;
- case 0xc2: // GD_GLORYWOUNDS
- {
- struct map_session_data *sd;
- if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
- sd->status.guild_id == srcsd->status.guild_id &&
- sd->sc_data[SC_GLORYWOUNDS].timer == -1 && !sd->sc_data[SC_GLORYWOUNDS].val4)
- skill_status_change_start(bl,SC_GLORYWOUNDS,1,0,0,0,0,0 );
- }
- break;
- case 0xc3: // GD_SOULCOLD
- {
- struct map_session_data *sd;
- if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
- sd->status.guild_id == srcsd->status.guild_id &&
- sd->sc_data[SC_SOULCOLD].timer == -1 && !sd->sc_data[SC_SOULCOLD].val4)
- skill_status_change_start(bl,SC_SOULCOLD,1,0,0,0,0,0 );
- }
- break;
- case 0xc4: // GD_HAWKEYES
- {
- struct map_session_data *sd;
- if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
- sd->status.guild_id == srcsd->status.guild_id &&
- sd->sc_data[SC_HAWKEYES].timer == -1 && !sd->sc_data[SC_HAWKEYES].val4)
- skill_status_change_start(bl,SC_HAWKEYES,1,0,0,0,0,0 );
+ sg->interval = -1;
+ src->range = 0;
}
break;
@@ -6081,6 +5807,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
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)
@@ -6104,85 +5831,55 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int tick)
{
struct skill_unit_group *sg;
+ struct status_change *sc_data;
+ int type;
nullpo_retr(0, src);
nullpo_retr(0, bl);
nullpo_retr(0, sg=src->group);
+ sc_data = status_get_sc_data(bl);
+ type = SkillStatusChangeTable[sg->skill_id];
- if( bl->prev==NULL || !src->alive )
- return 0;
-
- if( bl->type!=BL_PC && bl->type!=BL_MOB )
+ if (bl->prev==NULL || !src->alive ||
+ (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)))
return 0;
switch(sg->unit_id){
- case 0x7e: /* セイフティウォ?ル */
- case 0x85: /* ニュ?マ */
+ 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;
+ case 0x9a: /* ボルケーノ */
+ case 0x9b: /* デリュージ */
+ case 0x9c: /* バイオレントゲイル */
+ if (type==SC_QUAGMIRE && bl->type==BL_MOB)
+ break;
+ if (sc_data && sc_data[type].timer!=-1 && sc_data[type].val2==(int)src) {
+ status_change_end(bl,type,-1);
}
break;
- case 0xb6:
- {
- struct block_list *target=map_id2bl(sg->val2);
- struct status_change *sc_data=battle_get_sc_data(bl);
- if( target==bl ) {
- skill_status_change_end(bl,SC_FOGWALL,-1);
- if (sc_data && sc_data[SC_BLIND].timer!=-1)
- sc_data[SC_BLIND].timer = add_timer(
- gettick() + 30000, skill_status_change_timer, bl->id, 0);
- }
+ case 0x91: /* アンクルスネア */
+ {
+ struct block_list *target = map_id2bl(sg->val2);
+ if(target && target == bl){
+ status_change_end(bl,SC_ANKLE,-1);
sg->limit=DIFF_TICK(tick,sg->tick)+1000;
}
break;
- case 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 0xa1: /* 戦太鼓の響き */
+ case 0xa2: /* ニーベルングの指輪 */
case 0xa3: /* ロキの叫び */
case 0xa4: /* 深淵の中に */
- case 0xa5: /* 不死身のジ?クフリ?ド */
+ case 0xa5: /* 不死身のジークフリード */
+ case 0xad: /* 私を忘れないで… */
+ if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)src) {
+ status_change_end(bl,type,-1);
+ }
+ break;
+
case 0xa6: /* 不協和音 */
case 0xa7: /* 口笛 */
case 0xa8: /* 夕陽のアサシンクロス */
@@ -6190,123 +5887,94 @@ int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int t
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;
+ if (sg->src_id==bl->id) {
+ status_change_end(bl,type,-1);
+ break;
}
- break;
- // New guild skills [Celest]
- case 0xc1: // GD_LEADERSHIP
- {
- struct status_change *sc_data=battle_get_sc_data(bl);
- if (sc_data && sc_data[SC_LEADERSHIP].timer != -1)
- skill_status_change_end(bl,SC_LEADERSHIP,-1);
+ if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)src) {
+ sc_data[type].timer = add_timer(20000+tick, status_change_timer, bl->id, type);
}
- break;
- case 0xc2: // GD_GLORYWOUNDS
- {
- struct status_change *sc_data=battle_get_sc_data(bl);
- if (sc_data && sc_data[SC_GLORYWOUNDS].timer != -1)
- skill_status_change_end(bl,SC_GLORYWOUNDS,-1);
+ break;
+
+ case 0xb4: // Basilica
+ if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)sg) {
+ status_change_end(bl,type,-1);
}
break;
- case 0xc3: // GD_SOULCOLD
+
+ case 0xb6:
{
- struct status_change *sc_data=battle_get_sc_data(bl);
- if (sc_data && sc_data[SC_SOULCOLD].timer != -1)
- skill_status_change_end(bl,SC_SOULCOLD,-1);
+ if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)sg) {
+ status_change_end(bl,SC_FOGWALL,-1);
+ if (sc_data && sc_data[SC_BLIND].timer!=-1)
+ sc_data[SC_BLIND].timer = add_timer(
+ gettick() + 30000, status_change_timer, bl->id, 0);
+ }
+ break;
}
- break;
- case 0xc4: // GD_HAWKEYES
+
+ case 0xb7: /* スパイダ?ウェッブ */
{
- struct status_change *sc_data=battle_get_sc_data(bl);
- if (sc_data && sc_data[SC_HAWKEYES].timer != -1)
- skill_status_change_end(bl,SC_HAWKEYES,-1);
+ struct block_list *target = map_id2bl(sg->val2);
+ if (target && target==bl)
+ status_change_end(bl,SC_SPIDERWEB,-1);
+ sg->limit = DIFF_TICK(tick,sg->tick)+1000;
+ break;
}
- 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;
}
+
/*==========================================
- * スキルユニットの削除イベント
+ * スキルユニット効果発動/離脱処理(foreachinarea)
+ * bl: ユニット(BL_PC/BL_MOB)
*------------------------------------------
*/
-int skill_unit_ondelete(struct skill_unit *src,struct block_list *bl,unsigned int tick)
+int skill_unit_effect(struct block_list *bl,va_list ap)
{
- struct skill_unit_group *sg;
+ struct skill_unit *unit;
+ struct skill_unit_group *group;
+ int flag;
+ unsigned int tick;
+ static int called = 0;
- nullpo_retr(0, src);
nullpo_retr(0, bl);
- nullpo_retr(0, sg = src->group);
+ nullpo_retr(0, ap);
+ nullpo_retr(0, unit=va_arg(ap,struct skill_unit*));
+ tick = va_arg(ap,unsigned int);
+ flag = va_arg(ap,unsigned int);
- if( bl->prev==NULL || !src->alive )
+ if (bl->type!=BL_PC && bl->type!=BL_MOB)
return 0;
- if( bl->type!=BL_PC && bl->type!=BL_MOB )
+ if (!unit->alive || bl->prev==NULL)
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:
- case 0xc1:
- case 0xc2:
- case 0xc3:
- case 0xc4:
- return skill_unit_onout(src,bl,tick);
+ nullpo_retr(0, group=unit->group);
-/* default:
- if(battle_config.error_log)
- printf("skill_unit_ondelete: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
- break;*/
+ if (flag)
+ skill_unit_onplace(unit,bl,tick);
+ else {
+ skill_unit_onout(unit,bl,tick);
+ unit = map_find_skill_unit_oncell(bl,bl->x,bl->y,group->skill_id,unit);
+ if (unit && called == 0) {
+ called = 1;
+ skill_unit_onplace(unit,bl,tick);
+ called = 0;
+ }
}
- skill_unitgrouptickset_delete(bl,sg->group_id);
+
return 0;
}
+
/*==========================================
* スキルユニットの限界イベント
*------------------------------------------
@@ -6314,7 +5982,6 @@ int skill_unit_ondelete(struct skill_unit *src,struct block_list *bl,unsigned in
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);
@@ -6326,7 +5993,7 @@ int skill_unit_onlimit(struct skill_unit *src,unsigned int tick)
src->bl.x,src->bl.y,1);
if(group == NULL)
return 0;
- group->valstr=calloc(24, 1);
+ group->valstr=(char *) aCallocA(24, 1);
if(group->valstr==NULL){
printf("skill_unit_onlimit: out of memory !\n");
exit(1);
@@ -6344,7 +6011,7 @@ int skill_unit_onlimit(struct skill_unit *src,unsigned int tick)
{
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)
+ if((sd = map_id2sd(sg->src_id)) == NULL)
return 0;
if((p_sd = pc_get_partner(sd)) == NULL)
return 0;
@@ -6352,38 +6019,6 @@ int skill_unit_onlimit(struct skill_unit *src,unsigned int tick)
pc_setpos(p_sd,map[src->bl.m].name,src->bl.x,src->bl.y,3);
}
break;
- case 0xc1: // GD_LEADERSHIP
- {
- struct map_session_data *sd;
- if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
- sd->sc_data[SC_LEADERSHIP].val4 = 0;
- }
- }
- break;
- case 0xc2: // GD_GLORYWOUNDS
- {
- struct map_session_data *sd;
- if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
- sd->sc_data[SC_GLORYWOUNDS].val4 = 0;
- }
- }
- break;
- case 0xc3: // GD_SOULCOLD
- {
- struct map_session_data *sd;
- if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
- sd->sc_data[SC_SOULCOLD].val4 = 0;
- }
- }
- break;
- case 0xc4: // GD_HAWKEYES
- {
- struct map_session_data *sd;
- if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
- sd->sc_data[SC_HAWKEYES].val4 = 0;
- }
- }
- break;
}
return 0;
}
@@ -6444,10 +6079,7 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data )
return 0;
}
- if(battle_config.pc_skill_reiteration == 0) {
- range = -1;
- switch(sd->skillid) {
- case MG_SAFETYWALL:
+ /*case MG_SAFETYWALL:
case WZ_FIREPILLAR:
case HT_SKIDTRAP:
case HT_LANDMINE:
@@ -6460,28 +6092,23 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data )
case HT_CLAYMORETRAP:
case HT_TALKIEBOX:
case AL_WARP:
- case PF_SPIDERWEB: /* スパイダ?ウェッブ */
- case RG_GRAFFITI: /* グラフィティ */
+ 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;
- }
- }
+ break;*/
+ if (!battle_config.pc_skill_reiteration &&
+ skill_get_unit_flag(sd->skillid)&UF_NOREITERATION &&
+ skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ sd->canact_tick = tick;
+ sd->canmove_tick = tick;
+ sd->skillitem = sd->skillitemlv = -1;
+ return 0;
}
- if(battle_config.pc_skill_nofootset) {
- range = -1;
- switch(sd->skillid) {
- case WZ_FIREPILLAR:
+ /*case WZ_FIREPILLAR:
case HT_SKIDTRAP:
case HT_LANDMINE:
case HT_ANKLESNARE:
@@ -6492,25 +6119,22 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data )
case HT_BLASTMINE:
case HT_CLAYMORETRAP:
case HT_TALKIEBOX:
- case PF_SPIDERWEB: /* スパイダ?ウェッブ */
+ case PF_SPIDERWEB:
case WZ_ICEWALL:
- range = 1;
+ range = 2;
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;
- }
- }
+ break;*/
+ if (battle_config.pc_skill_nofootset &&
+ skill_get_unit_flag(sd->skillid)&UF_NOFOOTSET &&
+ skill_check_unit_range2(&sd->bl,sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ sd->canact_tick = tick;
+ sd->canmove_tick = tick;
+ sd->skillitem = sd->skillitemlv = -1;
+ return 0;
}
-
if(battle_config.pc_land_skill_limit) {
maxcount = skill_get_maxcount(sd->skillid);
if(maxcount > 0) {
@@ -6532,7 +6156,7 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data )
if(sd->skilllv <= 0) return 0;
range = skill_get_range(sd->skillid,sd->skilllv);
if(range < 0)
- range = battle_get_range(&sd->bl) - (range + 1);
+ range = status_get_range(&sd->bl) - (range + 1);
range += battle_config.pc_skill_add_range;
if(battle_config.skill_out_range_consume) { // changed to allow casting when target walks out of range [Valaris]
if(range < distance(sd->bl.x,sd->bl.y,sd->skillx,sd->skilly)) {
@@ -6589,14 +6213,14 @@ static int skill_check_condition_char_sub(struct block_list *bl,va_list ap)
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);
+ 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);
+ ss_class = pc_calc_base_job(ssd->status.class_);
switch(ssd->skillid){
case PR_BENEDICTIO: /* 聖?降福 */
@@ -6650,24 +6274,25 @@ static int skill_check_condition_use_sub(struct block_list *bl,va_list ap)
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);
-
+ 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);
+ ss_class = pc_calc_base_job(ssd->status.class_);
skillid=ssd->skillid;
skilllv=ssd->skilllv;
- if(skilllv <= 0) return 0;
+ //if(skilllv <= 0) return 0;
+ if(skillid > 0 && skilllv <= 0) return 0; // celest
switch(skillid){
case PR_BENEDICTIO: /* 聖?降福 */
if(sd != ssd && (s_class.job == 4 || s_class.job == 8 || s_class.job == 15) &&
(sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1) && sd->status.sp >= 10){
sd->status.sp -= 10;
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
(*c)++;
}
break;
@@ -6692,7 +6317,7 @@ static int skill_check_condition_use_sub(struct block_list *bl,va_list ap)
){
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);
+ 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)++;
@@ -6718,7 +6343,7 @@ static int skill_check_condition_mob_master_sub(struct block_list *bl,va_list ap
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)
+ if(md->class_==mob_class && md->master_id==src_id)
(*c)++;
return 0;
}
@@ -6731,6 +6356,7 @@ int skill_check_condition(struct map_session_data *sd,int type)
{
int i,hp,sp,hp_rate,sp_rate,zeny,weapon,state,spiritball,skill,lv,mhp;
int index[10],itemid[10],amount[10];
+ int arrow_flag = 0;
nullpo_retr(0, sd);
@@ -6769,7 +6395,7 @@ int skill_check_condition(struct map_session_data *sd,int type)
clif_skill_fail(sd,sd->skillid,0,0);
return 0;
}
- if(sd->sc_data){
+ if(sd->sc_count){
if( sd->sc_data[SC_DIVINA].timer!=-1 ||
sd->sc_data[SC_ROKISWEIL].timer!=-1 ||
(sd->sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) ||
@@ -6778,11 +6404,13 @@ int skill_check_condition(struct map_session_data *sd,int type)
(sd->sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)){
clif_skill_fail(sd,sd->skillid,0,0);
return 0; /* ?態異常や沈?など */
- }
+ }
}
skill = sd->skillid;
lv = sd->skilllv;
if(lv <= 0) return 0;
+ // for the guild skills [celest]
+ if (skill >= 10000 && skill < 10015) skill-= 9500;
hp=skill_get_hp(skill, lv); /* 消費HP */
sp=skill_get_sp(skill, lv); /* 消費SP */
if((sd->skillid_old == BD_ENCORE) && skill==sd->skillid_dance)
@@ -6854,6 +6482,10 @@ int skill_check_condition(struct map_session_data *sd,int type)
}
else sd->spiritball_old = lv;
break;
+ case MO_BODYRELOCATION:
+ if (sd->sc_count && sd->sc_data[SC_EXPLOSIONSPIRITS].timer!=-1)
+ spiritball = 0;
+ break;
case MO_CHAINCOMBO: //連打掌
if(sd->sc_data[SC_BLADESTOP].timer==-1){
if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_TRIPLEATTACK)
@@ -6865,7 +6497,7 @@ int skill_check_condition(struct map_session_data *sd,int type)
return 0;
break;
case CH_TIGERFIST: //伏虎拳
- if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH)
+ if((sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH) && !sd->state.skill_flag)
return 0;
break;
case CH_CHAINCRUSH: //連柱崩?
@@ -6916,8 +6548,9 @@ int skill_check_condition(struct map_session_data *sd,int type)
case AM_SPHEREMINE: /* スフィア?マイン */
if(type&1){
int c=0;
- int maxcount=skill_get_maxcount(skill);
- int mob_class=(skill==AM_CANNIBALIZE)?1118:1142;
+ int summons[5] = { 1020, 1068, 1118, 1500, 1368 };
+ int maxcount = (skill==AM_CANNIBALIZE)? 6-lv : skill_get_maxcount(skill);
+ int mob_class = (skill==AM_CANNIBALIZE)? summons[lv-1] :1142;
if(battle_config.pc_land_skill_limit && maxcount>0) {
map_foreachinarea(skill_check_condition_mob_master_sub ,sd->bl.m, 0, 0, map[sd->bl.m].xs, map[sd->bl.m].ys, BL_MOB, sd->bl.id, mob_class,&c );
if(c >= maxcount){
@@ -6929,7 +6562,7 @@ int skill_check_condition(struct map_session_data *sd,int type)
break;
case MG_FIREWALL: /* ファイア?ウォ?ル */
case WZ_QUAGMIRE:
- case WZ_FIREPILLAR: // celest
+ case WZ_FIREPILLAR: // celest
case PF_FOGWALL:
/* ?制限 */
if(battle_config.pc_land_skill_limit) {
@@ -6947,6 +6580,29 @@ int skill_check_condition(struct map_session_data *sd,int type)
}
}
break;
+ // skills require arrows as of 12/07 [celest]
+ case AC_DOUBLE:
+ case AC_SHOWER:
+ case AC_CHARGEARROW:
+ case BA_MUSICALSTRIKE:
+ case DC_THROWARROW:
+ case SN_SHARPSHOOTING:
+ case CG_ARROWVULCAN:
+ if(sd->equip_index[10] < 0) {
+ clif_arrow_fail(sd,0);
+ return 0;
+ }
+ arrow_flag = 1;
+ break;
+ case RG_BACKSTAP:
+ if(sd->status.weapon == 11) {
+ if (sd->equip_index[10] < 0) {
+ clif_arrow_fail(sd,0);
+ return 0;
+ }
+ arrow_flag = 1;
+ }
+ break;
}
if(!(type&2)){
@@ -7022,6 +6678,9 @@ int skill_check_condition(struct map_session_data *sd,int type)
}
break;
case ST_EXPLOSIONSPIRITS:
+ if (skill == MO_EXTREMITYFIST && ((sd->sc_data[SC_COMBO].timer != -1 && (sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sd->sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) || sd->sc_data[SC_BLADESTOP].timer!=-1)) {
+ break;
+ }
if(sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1) {
clif_skill_fail(sd,skill,0,0);
return 0;
@@ -7043,7 +6702,7 @@ int skill_check_condition(struct map_session_data *sd,int type)
}
break;
case ST_WATER:
- if(map_getcell(sd->bl.m,sd->bl.x,sd->bl.y) != 3 && (sd->sc_data[SC_DELUGE].timer==-1)){ //水場判定
+ if((!map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER))&& (sd->sc_data[SC_DELUGE].timer==-1)){ //水場判定
clif_skill_fail(sd,skill,0,0);
return 0;
}
@@ -7060,8 +6719,9 @@ int skill_check_condition(struct map_session_data *sd,int type)
if(((itemid[i] >= 715 && itemid[i] <= 717) || itemid[i] == 1065) && sd->sc_data[SC_INTOABYSS].timer != -1)
continue;
if(skill == WZ_FIREPILLAR && lv<=5)
- continue; // no gemstones for 1-5 [Celest]
- if(skill == AM_POTIONPITCHER && i != x)
+ continue; // no gemstones for 1-5 [Celest]
+ if((skill == AM_POTIONPITCHER ||
+ skill == CR_SLIMPITCHER) && i != x)
continue;
index[i] = pc_search_inventory(sd,itemid[i]);
@@ -7077,13 +6737,17 @@ int skill_check_condition(struct map_session_data *sd,int type)
if(!(type&1))
return 1;
- if(skill != AM_POTIONPITCHER) {
+ if(skill != AM_POTIONPITCHER &&
+ skill != CR_SLIMPITCHER &&
+ skill != MG_STONECURSE) {
if(skill == AL_WARP && !(type&2))
return 1;
for(i=0;i<10;i++) {
if(index[i] >= 0)
pc_delitem(sd,index[i],amount[i],0); // アイテム消費
}
+ if (arrow_flag && battle_config.arrow_decrement)
+ pc_delitem(sd,sd->equip_index[10],1,0);
}
if(type&2)
@@ -7112,56 +6776,50 @@ int skill_check_condition(struct map_session_data *sd,int type)
*/
int skill_castfix( struct block_list *bl, int time )
{
- struct map_session_data *sd;
+ struct map_session_data *sd = NULL;
struct mob_data *md; // [Valaris]
struct status_change *sc_data;
- int dex;
int castrate=100;
- int skill,lv,castnodex;
+ int skill,lv;
nullpo_retr(0, bl);
if(bl->type==BL_MOB){ // Crash fix [Valaris]
- md=(struct mob_data*)bl;
+ nullpo_retr(0, md=(struct mob_data*)bl);
skill = md->skillid;
lv = md->skilllv;
- }
-
- else {
- sd=(struct map_session_data*)bl;
+ } else {
+ nullpo_retr(0, sd=(struct map_session_data*)bl);
skill = sd->skillid;
lv = sd->skilllv;
}
if(lv <= 0) return 0;
- sc_data = battle_get_sc_data(bl);
- dex=battle_get_dex(bl);
+ sc_data = status_get_sc_data(bl);
if (skill > MAX_SKILL_DB || skill < 0)
return 0;
- castnodex=skill_get_castnodex(skill, lv);
+ /* サフラギウム */
+ if(sc_data && sc_data[SC_SUFFRAGIUM].timer!=-1 )
+ time=time*(100-sc_data[SC_SUFFRAGIUM].val1*15)/100;
+ status_change_end( bl, SC_SUFFRAGIUM, -1);
if(time==0)
return 0;
- if(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 (sd) {
+ if(!skill_get_castnodex(skill, lv) > 0) {
+ castrate=((struct map_session_data *)bl)->castrate;
+ time=time*castrate*(battle_config.castrate_dex_scale - status_get_dex(bl))/(battle_config.castrate_dex_scale * 100);
+ time=time*battle_config.cast_rate/100;
+ }
}
- /* サフラギウム */
- 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 )
+ 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;
+ +(sc_data[SC_POEMBRAGI].val3>>16)))/100;
return (time>0)?time:0;
}
@@ -7172,23 +6830,48 @@ int skill_castfix( struct block_list *bl, int time )
int skill_delayfix( struct block_list *bl, int time )
{
struct status_change *sc_data;
+ struct map_session_data *sd = NULL;
+ int skill = 0,lv = 0;
+ int delayrate = 100;
nullpo_retr(0, bl);
- sc_data = battle_get_sc_data(bl);
- if(time<=0)
- return 0;
+ if(bl->type == BL_PC){
+ nullpo_retr(0, sd = (struct map_session_data*)bl);
+ skill = sd->skillid;
+ lv = sd->skilllv;
+ }
- 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(lv <= 0) return 0;
+
+ sc_data = status_get_sc_data(bl);
+
+ if(sd) {
+ delayrate = sd->delayrate;
+
+ // instant cast attack skills depend on aspd as delay [celest]
+ if (time == 0) {
+ if (skill_db[skill].skill_type == BF_WEAPON)
+ time = status_get_adelay (bl)/2;
+ else
+ time = 300; // default delay, according to official servers
+ } else if (time < 0)
+ time = abs(time) + status_get_adelay (bl)/2; // if set to <0, the aspd delay will be added
+
+ if(battle_config.delay_dependon_dex && /* dexの影響を計算する */
+ !skill_get_delaynodex(skill, lv)) // if skill casttime is allowed to be reduced by dex
+ time = time * (battle_config.castrate_dex_scale - status_get_dex(bl)) / (battle_config.castrate_dex_scale);
+
+ time = time * delayrate * battle_config.delay_rate / 10000;
+
+ if (time < battle_config.min_skill_delay_limit) // check minimum skill delay
+ time = battle_config.min_skill_delay_limit;
}
/* ブラギの詩 */
- 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;
+ 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;
}
@@ -7197,128 +6880,97 @@ int skill_delayfix( struct block_list *bl, int time )
* スキル使用(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;
+ int casttime = 0, delay = 0, skill, range;
+ struct map_session_data* tsd = NULL;
+ struct block_list *bl = NULL;
struct status_change *sc_data;
- tick=gettick();
+ int forcecast = 0;
+ unsigned int 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); */
+ if ((bl = map_id2bl(target_id)) == NULL)
return 0;
+ if (bl->type == BL_PC) {
+ nullpo_retr(0, tsd = (struct map_session_data*)bl);
}
if(sd->bl.m != bl->m || pc_isdead(sd))
return 0;
-
if(skillnotok(skill_num, sd)) // [MouseJstr]
return 0;
-
- sc_data=sd->sc_data;
+ if (tsd && skill_num == ALL_RESURRECTION && !pc_isdead(tsd))
+ return 0;
+
+ sc_data = sd->sc_data;
/* 沈?や異常(ただし、グリムなどの判定をする) */
- if( sd->opt1>0 )
+ if (sd->opt1 > 0)
return 0;
- if(sd->sc_data){
- if(sc_data[SC_CHASEWALK].timer != -1) return 0;
- if(sc_data[SC_VOLCANO].timer != -1){
- if(skill_num==WZ_ICEWALL) return 0;
- }
- if(sc_data[SC_ROKISWEIL].timer!=-1){
- if(skill_num==BD_ADAPTATION) return 0;
- }
- if( sd->sc_data[SC_DIVINA].timer!=-1 ||
- sd->sc_data[SC_ROKISWEIL].timer!=-1 ||
- (sd->sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) ||
- sd->sc_data[SC_STEELBODY].timer != -1 ||
- sd->sc_data[SC_BERSERK].timer != -1 ||
- (sd->sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)){
+ if (sc_data) {
+ // allow to use only Chasewalk [celest]
+ if (sc_data[SC_CHASEWALK].timer != -1 && skill_num != ST_CHASEWALK)
+ return 0;
+ if (sc_data[SC_VOLCANO].timer != -1 && skill_num == WZ_ICEWALL)
+ return 0;
+ if (sc_data[SC_ROKISWEIL].timer != -1 && skill_num == BD_ADAPTATION)
+ return 0;
+ if (sc_data[SC_DIVINA].timer != -1 ||
+ sc_data[SC_ROKISWEIL].timer != -1 ||
+ (sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) ||
+ sc_data[SC_STEELBODY].timer != -1 ||
+ sc_data[SC_BERSERK].timer != -1 ||
+ (sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE))
return 0; /* ?態異常や沈?など */
+ if (sc_data[SC_BLADESTOP].timer != -1) {
+ if (sc_data[SC_BLADESTOP].val2 == 1) return 0;//白羽された側なのでダメ
+ switch (sc_data[SC_BLADESTOP].val1) {
+ case 1: return 0;
+ case 2: if (skill_num != MO_FINGEROFFENSIVE) return 0; else break;
+ case 3: if (skill_num != MO_FINGEROFFENSIVE && skill_num != MO_INVESTIGATE) return 0; else break;
+ case 4: if (skill_num != MO_FINGEROFFENSIVE && skill_num != MO_INVESTIGATE && skill_num != MO_CHAINCOMBO) return 0; else break;
+ case 5: if (skill_num != MO_FINGEROFFENSIVE && skill_num != MO_INVESTIGATE && skill_num != MO_CHAINCOMBO && skill_num!=MO_EXTREMITYFIST) return 0; else break;
+ }
}
-
- 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->sc_data[SC_BLOCKSKILL].timer!=-1)
- if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3)
- return 0;
-
if (sc_data[SC_BASILICA].timer != -1) { // Disallow all other skills in Basilica [celest]
- struct skill_unit *su;
- if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
- struct skill_unit_group *sg;
- // if caster is the owner of basilica
- if ((sg = su->group) && sg->src_id == sd->bl.id) {
- // skill_status_change_end(&sd->bl,SC_BASILICA,-1);
- // skill_delunitgroup (sg);
- if (skill_num != HP_BASILICA) return 0;
- } // otherwise...
- else
- return 0;
- }
- }
+ struct skill_unit_group *sg = (struct skill_unit_group *)sc_data[SC_BASILICA].val4;
+ // if caster is the owner of basilica
+ if (sg && sg->src_id == sd->bl.id &&
+ skill_num == HP_BASILICA) ; // do nothing
+ // otherwise...
+ else return 0;
+ }
+ /* 演奏/ダンス中 */
+ if (sc_data[SC_DANCING].timer != -1) {
+ 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(sd->status.option&4 && skill_num==TF_HIDING)
+ 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 )
+ 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: // now usable in WoE - celest
- case HP_BASILICA:
- case HP_ASSUMPTIO:
- case ST_CHASEWALK:
+ if(skill_get_inf2(skill_num) & 0x200 && sd->bl.id == target_id)
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){
+ switch (skill_num) {
case SA_CASTCANCEL:
- if(sd->skillid != skill_num){ //キャストキャンセル自?は?えない
+ if (sd->skillid != skill_num){ //キャストキャンセル自?は?えない
sd->skillid_old = sd->skillid;
sd->skilllv_old = sd->skilllv;
break;
}
+
case BD_ENCORE: /* アンコ?ル */
- if(!sd->skillid_dance){ //前回使用した踊りがないとだめ
+ if (!sd->skillid_dance) { //前回使用した踊りがないとだめ
clif_skill_fail(sd,skill_num,0,0);
return 0;
- }else{
+ } else {
sd->skillid_old = skill_num;
}
break;
@@ -7331,19 +6983,15 @@ int skill_use_id( struct map_session_data *sd, int target_id,
struct guild *g;
if (!sd->status.guild_id)
return 0;
- if (!(g = guild_search(sd->status.guild_id)))
+ if ((g = guild_search(sd->status.guild_id)) == NULL)
return 0;
if (strcmp(sd->status.name,g->master))
return 0;
- if (skill_lv <= 0) skill_lv = 1;
+ skill_lv = guild_checkskill(g, skill_num);
+ if (skill_lv <= 0) return 0;
}
break;
- }
-
- sd->skillid = skill_num;
- sd->skilllv = skill_lv;
- switch(skill_num){ //事前にレベルが?わったりするスキル
case BD_LULLABY: /* 子守歌 */
case BD_RICHMANKIM: /* ニヨルドの宴 */
case BD_ETERNALCHAOS: /* 永遠の混沌 */
@@ -7355,120 +7003,179 @@ int skill_use_id( struct map_session_data *sd, int target_id,
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){
+ 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 if (c == 99) { //相方不要設定だった
;
- }else{
- sd->skilllv=(c + skill_lv)/2;
+ } else {
+ sd->skilllv = (c + skill_lv)/2;
}
}
break;
}
- if(!skill_check_condition(sd,0)) 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;
+ sd->skillid = skill_num;
+ sd->skilllv = skill_lv;
+ if (!skill_check_condition(sd,0)) 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;
+ {
+ int check_range_flag = 0;
+
+ /* 射程と障害物チェック */
+ range = skill_get_range(skill_num,skill_lv);
+ if(range < 0)
+ range = status_get_range(&sd->bl) - (range + 1);
+ // be lenient if the skill was cast before we have moved to the correct position [Celest]
+ if (sd->walktimer != -1)
+ range++;
+ else check_range_flag = 1;
+ if(!battle_check_range(&sd->bl,bl,range)) {
+ if (check_range_flag && battle_check_range(&sd->bl,bl,range + 1)) {
+ int mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
+ int dir = map_calc_dir(&sd->bl,bl->x,bl->y);
+ pc_walktoxy (sd, sd->bl.x + mask[dir][0], sd->bl.y + mask[dir][1]);
+ } else
+ return 0;
+ }
}
- if((skill_num != MO_CHAINCOMBO &&
- skill_num != MO_COMBOFINISH &&
- skill_num != MO_EXTREMITYFIST &&
- skill_num != CH_TIGERFIST &&
- skill_num != CH_CHAINCRUSH) ||
+
+ if ((skill_num != MO_CHAINCOMBO &&
+ skill_num != MO_COMBOFINISH &&
+ skill_num != MO_EXTREMITYFIST &&
+ skill_num != CH_TIGERFIST &&
+ skill_num != CH_CHAINCRUSH) ||
+ (skill_num == CH_CHAINCRUSH && sd->state.skill_flag) ||
(skill_num == MO_EXTREMITYFIST && sd->state.skill_flag) )
pc_stopattack(sd);
- casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) );
- if(skill_num != SA_MAGICROD)
- delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) );
- //sd->state.skillcastcancel = skill_db[skill_num].castcancel;
+ 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_get_castcancel(skill_num);
- switch(skill_num){ /* 何か特殊な?理が必要 */
-// case AL_HEAL: /* ヒ?ル */
-// if(battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
-// forcecast=1; /* ヒ?ルアタックなら詠唱エフェクト有り */
-// break;
+ switch (skill_num) { /* 何か特殊な?理が必要 */
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) );
+ if (!tsd && battle_check_undead(status_get_race(bl),status_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);
+ 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 ){
+ if (sc_data && sc_data[SC_BLADESTOP].timer != -1){
struct block_list *tbl;
- if((tbl=(struct block_list *)sc_data[SC_BLADESTOP].val4) == NULL) //タ?ゲットがいない?
+ 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 MO_COMBOFINISH: /*猛龍拳*/
case CH_CHAINCRUSH: /* 連柱崩? */
target_id = sd->attacktarget;
break;
+ case CH_TIGERFIST: /* 伏虎拳 */
+ if (sc_data && sc_data[SC_COMBO].timer != -1 && sc_data[SC_COMBO].val1 == MO_COMBOFINISH)
+ target_id = sd->attacktarget;
+ break;
+
// -- moonsoul (altered to allow proper usage of extremity from new champion combos)
//
case MO_EXTREMITYFIST: /*阿修羅覇鳳拳*/
- if(sc_data && sc_data[SC_COMBO].timer != -1 && (sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) {
+ 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;
+ forcecast = 1;
break;
+
case SA_MAGICROD:
case SA_SPELLBREAKER:
- forcecast=1;
+ forcecast = 1;
break;
+
case WE_MALE:
case WE_FEMALE:
{
- struct map_session_data *p_sd = NULL;
- if((p_sd = pc_get_partner(sd)) == NULL)
+ struct map_session_data *p_sd = pc_get_partner(sd);
+ if (p_sd == NULL)
+ return 0;
+ if (skill_num == WE_MALE && sd->status.hp <= ((15*sd->status.max_hp)/100)) // Requires more than 15% of Max HP for WE_MALE
+ return 0;
+ else if (skill_num == WE_FEMALE && sd->status.sp <= ((15*sd->status.max_sp)/100)) // Requires more than 15% of Max SP for WE_FEMALE
return 0;
target_id = p_sd->bl.id;
//rangeをもう1回?査
- 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))
+ if (!battle_check_range(&sd->bl, &p_sd->bl, skill_get_range(skill_num,skill_lv)))
return 0;
}
break;
- case AS_SPLASHER: /* ベナムスプラッシャ? */
+
+ // parent-baby skills
+ case WE_BABY:
+ case WE_CALLPARENT:
+ {
+ struct map_session_data *f_sd = pc_get_father(sd);
+ struct map_session_data *m_sd = pc_get_mother(sd);
+
+ // set target as any one of the parent
+ if (f_sd) target_id = f_sd->bl.id;
+ else if (m_sd) target_id = m_sd->bl.id;
+ else return 0; // neither are found
+
+ // skip range check
+ //rangeをもう1回?査
+ //range = skill_get_range(skill_num,skill_lv);
+ //if(!battle_check_range(&sd->bl,&p_sd->bl,range))
+ // return 0;
+ }
+ break;
+
+ case WE_CALLBABY:
{
- 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);
+ struct map_session_data *p_sd = pc_get_child(sd);
+ if (p_sd == NULL)
+ return 0;
+ target_id = p_sd->bl.id;
+ //rangeをもう1回?査
+ if(!battle_check_range(&sd->bl, &p_sd->bl, skill_get_range(skill_num,skill_lv)))
return 0;
- }
}
break;
- case PF_MEMORIZE: /* メモライズ */
- casttime = 12000;
+
+ case HP_BASILICA: /* バジリカ */
+ {
+ if (skill_check_unit_range(sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ return 0;
+ }
+ if (skill_check_unit_range2(&sd->bl,sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ return 0;
+ }
+ // cancel Basilica if already in effect
+ if (sc_data && sc_data[SC_BASILICA].timer != -1) {
+ struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc_data[SC_BASILICA].val4;
+ if (sg && sg->src_id == sd->bl.id) {
+ status_change_end(&sd->bl,SC_BASILICA,-1);
+ skill_delunitgroup (sg);
+ return 0;
+ }
+ }
+ }
break;
+
case GD_BATTLEORDER:
case GD_REGENERATION:
case GD_RESTORE:
@@ -7478,62 +7185,52 @@ int skill_use_id( struct map_session_data *sd, int target_id,
}
//メモライズ?態ならキャストタイムが1/3
- if(sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){
+ if (sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0) {
casttime = casttime/2;
- if((--sc_data[SC_MEMORIZE].val2)<=0)
- skill_status_change_end(&sd->bl, SC_MEMORIZE, -1);
+ if ((--sc_data[SC_MEMORIZE].val2) <= 0)
+ status_change_end(&sd->bl, SC_MEMORIZE, -1);
}
- if(battle_config.pc_skill_log)
- printf("PC %d skill use target_id=%d skill=%d lv=%d cast=%d\n",sd->bl.id,target_id,skill_num,skill_lv,casttime);
+ if (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 ){ /* 詠唱が必要 */
+ if (casttime > 0 || forcecast) { /* 詠唱が必要 */
struct mob_data *md;
- clif_skillcasting( &sd->bl, sd->bl.id, target_id, 0,0, skill_num,casttime);
+ 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;
+ 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;
+ md->min_chase = 13;
}
}
- if( casttime<=0 ) /* 詠唱の無いものはキャンセルされない */
- sd->state.skillcastcancel=0;
-
- sd->skilltarget = target_id;
-/* sd->cast_target_bl = bl; */
- sd->skillx = 0;
- sd->skilly = 0;
+ sd->skilltarget = target_id;
+ 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) {
+
+ if (!(battle_config.pc_cloak_check_type & 2) && sc_data && sc_data[SC_CLOAKING].timer != -1 && sd->skillid != AS_CLOAKING)
+ status_change_end(&sd->bl,SC_CLOAKING,-1);
+ if (casttime > 0) {
+ sd->skilltimer = add_timer (tick + casttime, skill_castend_id, sd->bl.id, 0);
+ if ((skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
sd->prev_speed = sd->speed;
- sd->speed = sd->speed*(175 - skill*5)/100;
- clif_updatestatus(sd,SP_SPEED);
+ status_calc_speed (sd);
}
else
pc_stop_walking(sd,0);
- }
- else {
- if(skill_num != SA_CASTCANCEL)
+ } else {
+ sd->state.skillcastcancel = 0; /* 詠唱の無いものはキャンセルされない */
+ 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); // moved
-
return 0;
}
@@ -7541,137 +7238,127 @@ int skill_use_id( struct map_session_data *sd, int target_id,
* スキル使用(場所指定)
*------------------------------------------
*/
-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;
+ int casttime = 0, delay = 0, skill, range;
+ unsigned int tick = gettick();
nullpo_retr(0, sd);
- if(pc_isdead(sd))
+ if (pc_isdead(sd))
return 0;
-
if (skillnotok(skill_num, sd)) // [MoueJstr]
return 0;
-
- if(skill_num==WZ_ICEWALL && map[sd->bl.m].flag.noicewall && !map[sd->bl.m].flag.pvp) { // noicewall flag [Valaris]
+ if (skill_num == WZ_ICEWALL && map[sd->bl.m].flag.noicewall && !map[sd->bl.m].flag.pvp) { // noicewall flag [Valaris]
clif_skill_fail(sd,sd->skillid,0,0);
return 0;
}
- sc_data=sd->sc_data;
+ sc_data = sd->sc_data;
- if( sd->opt1>0 )
+ if (sd->opt1 > 0)
return 0;
- if(sc_data){
- if( sc_data[SC_DIVINA].timer!=-1 ||
- sc_data[SC_ROKISWEIL].timer!=-1 ||
+ if (sc_data){
+ if (sc_data[SC_DIVINA].timer != -1 ||
+ sc_data[SC_ROKISWEIL].timer != -1 ||
sc_data[SC_AUTOCOUNTER].timer != -1 ||
sc_data[SC_STEELBODY].timer != -1 ||
sc_data[SC_DANCING].timer!=-1 ||
sc_data[SC_BERSERK].timer != -1 ||
- sd->sc_data[SC_MARIONETTE].timer != -1)
+ sc_data[SC_MARIONETTE].timer != -1)
return 0; /* ?態異常や沈?など */
- if (sd->sc_data[SC_BLOCKSKILL].timer!=-1)
- if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3)
- return 0;
-
- if (sc_data[SC_BASILICA].timer != -1) { // Basilica cancels if caster moves [celest]
- struct skill_unit *su;
- if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
- struct skill_unit_group *sg;
- // if caster is the owner of basilica
- if ((sg = su->group) && sg->src_id == sd->bl.id) {
- // skill_status_change_end(&sd->bl,SC_BASILICA,-1);
- // skill_delunitgroup (sg);
- if (skill_num != HP_BASILICA) return 0;
- } // otherwise...
- else
- return 0;
- }
+ if (sc_data[SC_BASILICA].timer != -1) {
+ struct skill_unit_group *sg = (struct skill_unit_group *)sc_data[SC_BASILICA].val4;
+ // if caster is the owner of basilica
+ if (sg && sg->src_id == sd->bl.id &&
+ skill_num == HP_BASILICA) ; // do nothing
+ // otherwise...
+ else return 0;
}
}
- if(sd->status.option&2)
+ if(sd->status.option & 2)
return 0;
-/* if(map[sd->bl.m].flag.gvg &&
- (skill_num == SM_ENDURE || skill_num == AL_TELEPORT ||
- skill_num == AL_WARP || skill_num == WZ_ICEWALL ||
- skill_num == TF_BACKSLIDING))
- return 0;*/
-
sd->skillid = skill_num;
sd->skilllv = skill_lv;
- if(skill_lv <= 0) return 0;
+ if (skill_lv <= 0) return 0;
sd->skillx = skill_x;
sd->skilly = skill_y;
- if(!skill_check_condition(sd,0)) return 0;
+ 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;
+
+ {
+ int check_range_flag = 0;
+
+ /* 射程と障害物チェック */
+ range = skill_get_range(skill_num,skill_lv);
+ if(range < 0)
+ range = status_get_range(&sd->bl) - (range + 1);
+ // be lenient if the skill was cast before we have moved to the correct position [Celest]
+ if (sd->walktimer != -1)
+ range ++;
+ else check_range_flag = 1;
+ if(!battle_check_range(&sd->bl,&bl,range)) {
+ if (check_range_flag && battle_check_range(&sd->bl,&bl,range + 1)) {
+ int mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
+ int dir = map_calc_dir(&sd->bl,bl.x,bl.y);
+ pc_walktoxy (sd, sd->bl.x + mask[dir][0], sd->bl.y + mask[dir][1]);
+ } else
+ return 0;
+ }
+ }
pc_stopattack(sd);
- casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) );
- delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) );
+ 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 (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){
+ 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 ((--sc_data[SC_MEMORIZE].val2)<=0)
+ 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;
-
+ if (casttime > 0) /* 詠唱が必要 */
+ clif_skillcasting(&sd->bl, sd->bl.id, 0, skill_x, skill_y, skill_num, casttime);
+
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) {
+ if (!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1)
+ status_change_end(&sd->bl,SC_CLOAKING,-1);
+ if (casttime > 0) {
+ sd->skilltimer = add_timer(tick + casttime, skill_castend_pos, sd->bl.id, 0);
+ if ((skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
sd->prev_speed = sd->speed;
- sd->speed = sd->speed*(175 - skill*5)/100;
- clif_updatestatus(sd,SP_SPEED);
+ status_calc_speed (sd);
}
else
pc_stop_walking(sd,0);
- }
- else {
+ } else {
+ sd->state.skillcastcancel = 0; /* 詠唱の無いものはキャンセルされない */
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);
+ if (skill_get_unit_id(skill_num, 0) != 0x86 &&
+ sc_data && sc_data[SC_MAGICPOWER].timer != -1)
+ status_change_end(&sd->bl,SC_MAGICPOWER,-1);
return 0;
}
@@ -7680,60 +7367,59 @@ int skill_use_pos( struct map_session_data *sd,
* スキル詠唱キャンセル
*------------------------------------------
*/
-int skill_castcancel(struct block_list *bl,int type)
+int skill_castcancel (struct block_list *bl, int type)
{
int inf;
- int ret=0;
+ 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();
+ 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->canact_tick = tick;
sd->canmove_tick = tick;
- if( sd->skilltimer!=-1){
- if(pc_checkskill(sd,SA_FREECAST) > 0) {
+ 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 );
+ 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 );
+ 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);
+ ret = delete_timer( sd->skilltimer, skill_castend_id );
+ if (ret < 0)
+ printf("delete timer error : skillid : %d\n", sd->skillid_old);
}
- sd->skilltimer=-1;
+ sd->skilltimer = -1;
clif_skillcastcancel(bl);
}
-
return 0;
- }else if(bl->type==BL_MOB){
- struct mob_data *md=(struct mob_data *)bl;
+ } 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 );
+ 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;
+ 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);
+ if (ret < 0)
+ printf("delete timer error : skillid : %d\n", md->skillid);
return 0;
}
+
return 1;
}
/*=========================================
@@ -7912,13 +7598,14 @@ int skill_devotion3(struct block_list *bl,int target)
int n,r=0;
nullpo_retr(1, bl);
+ md = (struct map_session_data *)bl;
- if( (md = (struct map_session_data *)bl) == NULL || (sd = map_id2sd(target)) == NULL )
+ if ((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){ // 許容範?を超えてた
+ if(pc_checkskill(md,CR_DEVOTION)+6 < r){ // 許容範?を超えてた
for(n=0;n<5;n++)
if(md->dev.val1[n]==target)
md->dev.val2[n]=0; // 離れた時は、?を切るだけ
@@ -7936,7 +7623,7 @@ void skill_devotion_end(struct map_session_data *md,struct map_session_data *sd,
md->dev.val1[target]=md->dev.val2[target]=0;
if(sd && sd->sc_data){
- // skill_status_change_end(sd->bl,SC_DEVOTION,-1);
+ // 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);
@@ -7978,7 +7665,7 @@ int skill_autospell(struct map_session_data *sd,int skillid)
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
+ 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;
}
@@ -8087,34 +7774,64 @@ int skill_frostjoke_scream(struct block_list *bl,va_list ap)
if(src == bl)//自分には?かない
return 0;
- if(battle_check_target(src,bl,BCT_ENEMY) > 0)
+ if (map[src->m].flag.gvg || map[src->m].flag.pvp)
skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick);
- else if(battle_check_target(src,bl,BCT_PARTY) > 0) {
- if(rand()%100 < 10)//PTメンバにも低確率でかかる(とりあえず10%)
+ // we freeze everybody except of ourselfes on pvp/gvg [veider]
+ else {
+ 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 && rand()%100 < 10)
skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick);
}
+ // so on non-pvp/gvg we are just freezing as freezed before
return 0;
}
/*==========================================
- *アブラカダブラの使用スキル決定(決定スキルがダメなら0を返す)
+ * Moonlit creates a 'safe zone' [celest]
*------------------------------------------
*/
-int skill_abra_dataset(int skilllv)
+static int skill_moonlit_count(struct block_list *bl,va_list ap)
{
- int skill = rand()%331;
+ int *c, id;
+ struct map_session_data *sd;
- if(skilllv <= 0) return 0;
+ nullpo_retr(0, bl);
+ nullpo_retr(0, ap);
+ nullpo_retr(0, (sd=(struct map_session_data *)bl));
- //dbに基づくレベル?確率判定
- if(skill_abra_db[skill].req_lv > skilllv || rand()%10000 >= skill_abra_db[skill].per) return 0;
- //NPCスキルはダメ
- if(skill >= NPC_PIERCINGATT && skill <= NPC_SUMMONMONSTER) return 0;
- //演奏スキルはダメ
- if(skill_is_danceskill(skill)) return 0;
+ id=va_arg(ap,int);
+ c=va_arg(ap,int *);
- return skill;
+ if (sd->bl.id != id && sd->sc_count && sd->sc_data[SC_MOONLIT].timer != -1 && c)
+ (*c)++;
+ return 0;
+}
+
+int skill_check_moonlit (struct block_list *bl, int dx, int dy)
+{
+ int c=0;
+ nullpo_retr(0, bl);
+ map_foreachinarea(skill_moonlit_count,bl->m,
+ dx-1,dy-1,dx+1,dy+1,BL_PC,bl->id,&c);
+ return (c>0);
+}
+
+/*==========================================
+ * バジリカのセルを設定する
+ *------------------------------------------
+ */
+void skill_basilica_cell(struct skill_unit *unit,int flag)
+{
+ int i,x,y,range = skill_get_unit_range(HP_BASILICA);
+ int size = range*2+1;
+
+ for (i=0;i<size*size;i++) {
+ x = unit->bl.x+(i%size-range);
+ y = unit->bl.y+(i/size-range);
+ map_setcell(unit->bl.m,x,y,flag);
+ }
}
/*==========================================
@@ -8137,7 +7854,8 @@ int skill_attack_area(struct block_list *bl,va_list ap)
return 0;
skillid=va_arg(ap,int);
skilllv=va_arg(ap,int);
- if(skilllv <= 0) return 0;
+ //if(skilllv <= 0) return 0;
+ if(skillid > 0 && skilllv <= 0) return 0; // celest
tick=va_arg(ap,unsigned int);
flag=va_arg(ap,int);
type=va_arg(ap,int);
@@ -8155,16 +7873,20 @@ int skill_clear_element_field(struct block_list *bl)
{
struct mob_data *md=NULL;
struct map_session_data *sd=NULL;
- int i,skillid;
+ int i,max,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;
+ if (bl->type==BL_MOB) {
+ max = MAX_MOBSKILLUNITGROUP;
+ md = (struct mob_data *)bl;
+ } else if(bl->type==BL_PC) {
+ max = MAX_SKILLUNITGROUP;
+ sd = (struct map_session_data *)bl;
+ } else
+ return 0;
- for(i=0;i<MAX_MOBSKILLUNITGROUP;i++){
+ for (i=0;i<max;i++) {
if(sd){
skillid=sd->skillunit[i].skill_id;
if(skillid==SA_DELUGE||skillid==SA_VOLCANO||skillid==SA_VIOLENTGALE||skillid==SA_LANDPROTECTOR)
@@ -8190,43 +7912,43 @@ int skill_landprotector(struct block_list *bl, va_list ap )
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)
+ skillid = va_arg(ap,int);
+ alive = va_arg(ap,int *);
+
+ if ((unit = (struct skill_unit *)bl) == NULL)
return 0;
- if(skillid==SA_LANDPROTECTOR){
+ if (skillid == SA_LANDPROTECTOR)
skill_delunit(unit);
- }else{
- if(alive && unit->group->skill_id==SA_LANDPROTECTOR)
- (*alive)=0;
- }
+ else if (alive && unit->group && 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;
nullpo_retr(0, bl);
+ if (bl->type != BL_PC && bl->type != BL_MOB)
+ return 0;
+
nullpo_retr(0, ap);
nullpo_retr(0, unit = va_arg(ap,struct skill_unit *));
nullpo_retr(0, sg = unit->group);
-
- heal=30+sg->skill_lv*5+((sg->val1)>>16)*5+((sg->val1)&0xfff)/2;
-
- if(bl->type == BL_SKILL || bl->id == sg->src_id)
+ if (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);
- }
+ heal = 30 + sg->skill_lv * 5 + ((sg->val1) >> 16) * 5 + ((sg->val1) & 0xfff) / 2;
+ clif_skill_nodamage(&unit->bl, bl, AL_HEAL, heal, 1);
+ battle_heal(NULL, bl, heal, 0, 0);
+
return 0;
}
@@ -8234,18 +7956,19 @@ int skill_idun_heal(struct block_list *bl, va_list ap )
* 指定範??でsrcに?して有?なタ?ゲットのblの?を?える(foreachinarea)
*------------------------------------------
*/
-int skill_count_target(struct block_list *bl, va_list ap ){
+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)
+ if ((src = va_arg(ap,struct block_list *)) == NULL)
return 0;
- if((c = va_arg(ap,int *)) == NULL)
+ if ((c = va_arg(ap,int *)) == NULL)
return 0;
- if(battle_check_target(src,bl,BCT_ENEMY) > 0)
+ if (battle_check_target(src,bl,BCT_ENEMY) > 0)
(*c)++;
return 0;
}
@@ -8253,7 +7976,7 @@ int skill_count_target(struct block_list *bl, va_list ap ){
* トラップ範??理(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;
@@ -8285,6 +8008,7 @@ int skill_trap_splash(struct block_list *bl, va_list ap )
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);
}
+ break;
case 0x97: /* フリ?ジングトラップ */
skill_attack(BF_WEAPON, ss,src,bl,sg->skill_id,sg->skill_lv,tick,(sg->val2)?0x0500:0);
break;
@@ -8295,1720 +8019,74 @@ int skill_trap_splash(struct block_list *bl, va_list ap )
return 0;
}
-/*----------------------------------------------------------------------------
- * ステ?タス異常
- *----------------------------------------------------------------------------
- */
-
-/*==========================================
- * ステ?タス異常タイマ?範??理
- *------------------------------------------
- */
-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;
-}
-
-/*==========================================
- * ステ?タス異常終了
- *------------------------------------------
- */
-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_ENDURE: // celest
- 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: /* メルトダウン */
- // Celest
- case SC_EDP:
- case SC_MARIONETTE:
- case SC_MARIONETTE2:
- case SC_SLOWDOWN:
- case SC_LEADERSHIP:
- case SC_GLORYWOUNDS:
- case SC_SOULCOLD:
- case SC_HAWKEYES:
- case SC_BATTLEORDERS:
- case SC_REGENERATION:
- calc_flag = 1;
- break;
- case SC_BERSERK: /* バ?サ?ク */
- 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)){
- if (sd->status.manner >= 0) // weeee ^^ [celest]
- 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:
- if (sc_data[SC_DPOISON].timer != -1) //
- break; // DPOISON用のオプション
- *opt2 &= ~1; // が?用に用意された場合には
- opt_flag = 1; // ここは削除する
- break; //
- case SC_CURSE:
- case SC_SILENCE:
- case SC_BLIND:
- *opt2 &= ~(1<<(type-SC_POISON));
- opt_flag = 1;
- break;
- case SC_DPOISON:
- if (sc_data[SC_POISON].timer != -1) // DPOISON用のオプションが
- break; // 用意されたら削除
- *opt2 &= ~1; // 毒?態解除
- opt_flag = 1;
- break;
- case SC_SIGNUMCRUCIS:
- *opt2 &= ~0x40;
- opt_flag = 1;
- break;
-
- case SC_HIDING:
- case SC_CLOAKING:
- *option &= ~((type == SC_HIDING) ? 2 : 4);
- calc_flag = 1; // orn
- opt_flag = 1 ;
- break;
-
- case SC_CHASEWALK:
- *option &= ~16388;
- opt_flag = 1 ;
- break;
-
- case SC_SIGHT:
- *option &= ~1;
- opt_flag = 1;
- break;
- case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
- *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: /* マリオネットコントロ?ル */
- case SC_MARIONETTE2:
- *opt3 &= ~1024;
- break;
- case SC_ASSUMPTIO: /* アスムプティオ */
- *opt3 &= ~2048;
- break;
- }
-
- if (night_flag == 1 && (*opt2 & STATE_BLIND) == 0 && bl->type == BL_PC && // by [Yor]
- !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) { // [celest]
- *opt2 |= STATE_BLIND;
- opt_flag = 1;
- }
-
- if(opt_flag) /* optionの?更を?える */
- clif_changeoption(bl);
-
- if (bl->type == BL_PC && calc_flag)
- pc_calcstatus((struct map_session_data *)bl,0); /* ステ?タス再計算 */
- }
-
- return 0;
-}
-/*==========================================
- * ステ?タス異常終了タイマ?
- *------------------------------------------
- */
-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; //使ってない?
-
- 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);
- }
-
- switch(type){ /* 特殊な?理になる場合 */
- case SC_MAXIMIZEPOWER: /* マキシマイズパワ? */
- case SC_CLOAKING:
- if(sd){
- if( sd->status.sp > 0 ){ /* SP切れるまで持? */
- sd->status.sp--;
- clif_updatestatus(sd,SP_SP);
- sc_data[type].timer=add_timer( /* タイマ?再設定 */
- sc_data[type].val2+tick, skill_status_change_timer, bl->id, data);
- return 0;
- }
- }
- break;
-
- case SC_CHASEWALK:
- if(sd){
- if( sd->status.sp > 19+sc_data[SC_CHASEWALK].val1*3){
- sd->status.sp-=(19+(sc_data[SC_CHASEWALK].val1*3)); // update sp cost [Celest]
- clif_updatestatus(sd,SP_SP);
- sc_data[type].timer=add_timer( /* タイマ?再設定 */
- 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_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_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_ENDURE: /* インデュア */
- if(sd && sd->special_state.infinite_endure) {
- sc_data[type].timer=add_timer( 1000*60+tick,skill_status_change_timer, bl->id, data );
- //sc_data[type].val2=1;
- return 0;
- }
- break;
-
- case SC_DISSONANCE: /* 不協和音 */
- if( (--sc_data[type].val2)>0){
- struct skill_unit *unit=
- (struct skill_unit *)sc_data[type].val4;
- struct block_list *src;
-
- if(!unit || !unit->group)
- break;
- src=map_id2bl(unit->group->src_id);
- if(!src)
- break;
- skill_attack(BF_MISC,src,&unit->bl,bl,unit->group->skill_id,sc_data[type].val1,tick,0);
- sc_data[type].timer=add_timer(skill_get_time2(unit->group->skill_id,unit->group->skill_lv)+tick,
- skill_status_change_timer, bl->id, data );
- return 0;
- }
- break;
-
- case SC_LULLABY: /* 子守唄 */
- if( (--sc_data[type].val2)>0){
- struct skill_unit *unit=
- (struct skill_unit *)sc_data[type].val4;
- if(!unit || !unit->group || unit->group->src_id==bl->id)
- break;
- skill_additional_effect(bl,bl,unit->group->skill_id,sc_data[type].val1,BF_LONG|BF_SKILL|BF_MISC,tick);
- sc_data[type].timer=add_timer(skill_get_time(unit->group->skill_id,unit->group->skill_lv)/10+tick,
- skill_status_change_timer, bl->id, data );
- return 0;
- }
- break;
-
- case SC_STONE:
- if(sc_data[type].val2 != 0) {
- short *opt1 = battle_get_opt1(bl);
- sc_data[type].val2 = 0;
- sc_data[type].val4 = 0;
- battle_stopwalking(bl,1);
- if(opt1) {
- *opt1 = 1;
- clif_changeoption(bl);
- }
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- return 0;
- }
- else if( (--sc_data[type].val3) > 0) {
- int hp = battle_get_max_hp(bl);
- if((++sc_data[type].val4)%5 == 0 && battle_get_hp(bl) > hp>>2) {
- hp = hp/100;
- if(hp < 1) hp = 1;
- if(bl->type == BL_PC)
- pc_heal((struct map_session_data *)bl,-hp,0);
- else if(bl->type == BL_MOB){
- struct mob_data *md;
- if((md=((struct mob_data *)bl)) == NULL)
- break;
- md->hp -= hp;
- }
- }
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- return 0;
- }
- break;
- case SC_POISON:
- if(sc_data[SC_SLOWPOISON].timer == -1) {
- if( (--sc_data[type].val3) > 0) {
- int hp = battle_get_max_hp(bl);
- if(battle_get_hp(bl) > hp>>2) {
- if(bl->type == BL_PC) {
- hp = 3 + hp*3/200;
- pc_heal((struct map_session_data *)bl,-hp,0);
- }
- else if(bl->type == BL_MOB) {
- struct mob_data *md;
- if((md=((struct mob_data *)bl)) == NULL)
- break;
- hp = 3 + hp/200;
- md->hp -= hp;
- }
- }
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- }
- }
- else
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- break;
- case SC_DPOISON:
- if (sc_data[SC_SLOWPOISON].timer == -1 && (--sc_data[type].val3) > 0) {
- int hp = battle_get_max_hp(bl);
- if (battle_get_hp(bl) > hp>>2) {
- if(bl->type == BL_PC) {
- hp = 3 + hp/50;
- pc_heal((struct map_session_data *)bl, -hp, 0);
- } else if (bl->type == BL_MOB) {
- struct mob_data *md;
- if ((md=((struct mob_data *)bl)) == NULL)
- break;
- hp = 3 + hp/100;
- md->hp -= hp;
- }
- }
- }
- if (sc_data[type].val3 > 0)
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- break;
-
- case SC_TENSIONRELAX: /* テンションリラックス */
- 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_HEADCRUSH: // temporary damage [celest]
-// case SC_BLEEDING:
- if((--sc_data[type].val3) > 0) {
- int hp = battle_get_max_hp(bl);
- if(bl->type == BL_PC) {
- hp = 3 + hp*3/200;
- pc_heal((struct map_session_data *)bl,-hp,0);
- }
- else if(bl->type == BL_MOB) {
- struct mob_data *md;
- if((md=((struct mob_data *)bl)) == NULL)
- break;
- hp = 3 + hp/200;
- md->hp -= hp;
- }
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- }
- break;
-
- /* 時間切れ無し?? */
- 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.max_hp*5/100) > 100 ){ // 5% every 10 seconds [DracoRPG]
- sd->status.hp -= sd->status.max_hp*5/100; // changed to max hp [celest]
- clif_updatestatus(sd,SP_HP);
- sc_data[type].timer = add_timer( /* タイマ?再設定 */
- 10000+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->speed > 250){
- md->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_LEADERSHIP:
- case SC_GLORYWOUNDS:
- case SC_SOULCOLD:
- case SC_HAWKEYES:
- if (sd) {
- sc_data[type].timer = add_timer(
- 1000+tick, skill_status_change_timer,
- bl->id, data);
- }
- break;
- }
-
-
-
- return skill_status_change_end( bl,type,tid );
-}
/*==========================================
* ステ?タス異常終了
*------------------------------------------
*/
-int skill_encchant_eremental_end(struct block_list *bl,int type)
+int skill_enchant_elemental_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);
+ nullpo_retr(0, sc_data = status_get_sc_data(bl));
+
+ if (type != SC_ENCPOISON && sc_data[SC_ENCPOISON].timer != -1) /* エンチャントポイズン解除 */
+ status_change_end(bl, SC_ENCPOISON, -1);
+ if (type != SC_ASPERSIO && sc_data[SC_ASPERSIO].timer != -1) /* アスペルシオ解除 */
+ status_change_end(bl, SC_ASPERSIO, -1);
+ if (type != SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer != -1) /* フレイムランチャ解除 */
+ status_change_end(bl, SC_FLAMELAUNCHER, -1);
+ if (type != SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer != -1) /* フロストウェポン解除 */
+ status_change_end(bl, SC_FROSTWEAPON, -1);
+ if (type != SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer != -1) /* ライトニングロ?ダ?解除 */
+ status_change_end(bl, SC_LIGHTNINGLOADER, -1);
+ if (type != SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer != -1) /* サイスミックウェポン解除 */
+ 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_check_cloaking(struct block_list *bl)
{
struct map_session_data *sd = NULL;
- struct status_change* sc_data;
- short *sc_count, *option, *opt1, *opt2, *opt3;
- int opt_flag = 0, calc_flag = 0,updateflag = 0, save_flag = 0, race, mode, elem, undead_flag;
- int scdef=0;
-
- nullpo_retr(0, bl);
- if(bl->type == BL_SKILL)
- return 0;
- nullpo_retr(0, sc_data=battle_get_sc_data(bl));
- nullpo_retr(0, sc_count=battle_get_sc_count(bl));
- nullpo_retr(0, option=battle_get_option(bl));
- nullpo_retr(0, opt1=battle_get_opt1(bl));
- nullpo_retr(0, opt2=battle_get_opt2(bl));
- nullpo_retr(0, opt3=battle_get_opt3(bl));
-
-
- race=battle_get_race(bl);
- mode=battle_get_mode(bl);
- elem=battle_get_elem_type(bl);
- undead_flag=battle_check_undead(race,elem);
-
- if(type == SC_AETERNA && (sc_data[SC_STONE].timer != -1 || sc_data[SC_FREEZE].timer != -1) )
- return 0;
-
- switch(type){
- case SC_STONE:
- case SC_FREEZE:
- scdef=3+battle_get_mdef(bl)+battle_get_luk(bl)/3;
- break;
- case SC_STAN:
- case SC_SILENCE:
- case SC_POISON:
- case SC_DPOISON:
- scdef=3+battle_get_vit(bl)+battle_get_luk(bl)/3;
- break;
- case SC_SLEEP:
- case SC_BLIND:
- scdef=3+battle_get_int(bl)+battle_get_luk(bl)/3;
- break;
- case SC_CURSE:
- scdef=3+battle_get_luk(bl);
- break;
-
-// case SC_CONFUSION:
- default:
- scdef=0;
- }
- if(scdef>=100)
- return 0;
- if(bl->type==BL_PC){
- sd=(struct map_session_data *)bl;
- if( sd && type == SC_ADRENALINE && !(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon)))
- return 0;
-
- if(SC_STONE<=type && type<=SC_BLIND){ /* カ?ドによる耐性 */
- if( sd && sd->reseff[type-SC_STONE] > 0 && rand()%10000<sd->reseff[type-SC_STONE]){
- if(battle_config.battle_log)
- printf("PC %d skill_sc_start: cardによる異常耐性?動\n",sd->bl.id);
- return 0;
- }
- }
- }
- else if(bl->type == BL_MOB) {
- }
- else {
- if(battle_config.error_log)
- printf("skill_status_change_start: neither MOB nor PC !\n");
- return 0;
- }
-
- if(type==SC_FREEZE && undead_flag && !(flag&1))
- return 0;
-
- if((type == SC_ADRENALINE || type == SC_WEAPONPERFECTION || type == SC_OVERTHRUST) &&
- sc_data[type].timer != -1 && sc_data[type].val2 && !val2)
- return 0;
-
- if(mode & 0x20 && (type==SC_STONE || type==SC_FREEZE ||
- type==SC_STAN || type==SC_SLEEP || type==SC_SILENCE || type==SC_QUAGMIRE || type == SC_DECREASEAGI || type == SC_SIGNUMCRUCIS || type == SC_PROVOKE ||
- (type == SC_BLESSING && (undead_flag || race == 6))) && !(flag&1)){
- /* ボスには?かない(ただしカ?ドによる?果は適用される) */
- return 0;
- }
- if(type==SC_FREEZE || type==SC_STAN || type==SC_SLEEP)
- battle_stopwalking(bl,1);
+ static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus
+ static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1};
+ int end = 1,i;
- 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;
- calc_flag = 1; // for updating mdef
- val2 = 7; // [Celest]
- 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: /* 速度減少 */
- if (bl->type == BL_PC) // Celest
- tick>>=1;
- calc_flag = 1;
- if(sc_data[SC_INCREASEAGI].timer!=-1 )
- skill_status_change_end(bl,SC_INCREASEAGI,-1);
- if(sc_data[SC_ADRENALINE].timer!=-1 )
- skill_status_change_end(bl,SC_ADRENALINE,-1);
- if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
- skill_status_change_end(bl,SC_SPEARSQUICKEN,-1);
- if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
- skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1);
- break;
- case SC_SIGNUMCRUCIS: /* シグナムクルシス */
- calc_flag = 1;
-// val2 = 14 + val1;
- val2 = 10 + val1*2;
- tick = 600*1000;
- clif_emotion(bl,4);
- break;
- case SC_SLOWPOISON:
- if (sc_data[SC_POISON].timer == -1 && sc_data[SC_DPOISON].timer == -1)
- return 0;
- break;
- case SC_TWOHANDQUICKEN: /* 2HQ */
- if(sc_data[SC_DECREASEAGI].timer!=-1)
- return 0;
- *opt3 |= 1;
- calc_flag = 1;
- break;
- case SC_ADRENALINE: /* アドレナリンラッシュ */
- if(sc_data[SC_DECREASEAGI].timer!=-1)
- return 0;
- 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_EDP: // [Celest]
- val2 = val1 + 2; /* 猛毒付?確率(%) */
- calc_flag = 1;
- break;
- case SC_POISONREACT: /* ポイズンリアクト */
- val2=val1/2 + val1%2; // [Celest]
- 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;
-
- 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_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_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: /* ?速ポ?ション */
- case SC_SPEEDPOTION1:
- case SC_SPEEDPOTION2:
- calc_flag = 1;
- tick = 1000 * tick;
- val2 = 5*(2+type-SC_SPEEDPOTION0);
- break;
-
- /* atk & matk potions [Valaris] */
- case SC_ATKPOT:
- case SC_MATKPOT:
- calc_flag = 1;
- tick = 1000 * tick;
- break;
- case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
- {
- 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;
- save_flag = 1; // celest
- }
- break;
- case SC_SELFDESTRUCTION: //自爆
- clif_skillcasting(bl,bl->id, bl->id,0,0,331,skill_get_time(val2,val1));
- val3 = tick / 1000;
- tick = 1000;
- break;
-
- /* option1 */
- case SC_STONE: /* 石化 */
- if(!(flag&2)) {
- int sc_def = battle_get_mdef(bl)*200;
- tick = tick - sc_def;
- }
- val3 = tick/1000;
- if(val3 < 1) val3 = 1;
- tick = 5000;
- val2 = 1;
- break;
- case SC_SLEEP: /* 睡眠 */
- if(!(flag&2)) {
-// int sc_def = 100 - (battle_get_int(bl) + battle_get_luk(bl)/3);
-// tick = tick * sc_def / 100;
-// if(tick < 1000) tick = 1000;
- tick = 30000;//睡眠はステ?タス耐性に?わらず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;
-
- /* option2 */
- case SC_POISON: /* 毒 */
- case SC_DPOISON: /* 猛毒 */
- calc_flag = 1;
- if(!(flag&2)) {
- int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/5);
- tick = tick * sc_def / 100;
- }
- val3 = tick/1000;
- if(val3 < 1) val3 = 1;
- tick = 1000;
- break;
- case SC_SILENCE: /* 沈?(レックスデビ?ナ) */
- if(!(flag&2)) {
- int sc_def = 100 - battle_get_vit(bl);
- tick = tick * sc_def / 100;
- }
- break;
- case SC_BLIND: /* 暗? */
- calc_flag = 1;
- if(!(flag&2)) {
- int sc_def = battle_get_lv(bl)/10 + battle_get_int(bl)/15;
- tick = 30000 - sc_def;
- }
- break;
- case SC_CURSE:
- calc_flag = 1;
- if(!(flag&2)) {
- int sc_def = 100 - battle_get_vit(bl);
- tick = tick * sc_def / 100;
- }
- break;
-
- /* option */
- case SC_HIDING: /* ハイディング */
- 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) {
- calc_flag = 1; // [Celest]
- val2 = tick;
- val3 = type==SC_CLOAKING ? 130-val1*3 : 135-val1*5;
- }
- else
- tick = 5000*val1;
- break;
- case SC_SIGHT: /* サイト/ルアフ */
- case SC_RUWACH:
- val2 = tick/250;
- tick = 10;
- break;
-
- /* セ?フティウォ?ル、ニュ?マ */
- case SC_SAFETYWALL: case SC_PNEUMA:
- tick=((struct skill_unit *)val2)->group->limit;
- break;
-
- /* アンクル */
- case SC_ANKLE:
- 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_RIDING:
- calc_flag = 1;
- tick = 600*1000;
- break;
- case SC_FALCON:
- case SC_WEIGHT50:
- case SC_WEIGHT90:
- case SC_BROKNWEAPON:
- case SC_BROKNARMOR:
- tick=600*1000;
- break;
-
- case SC_AUTOGUARD:
- {
- int i,t;
- for(i=val2=0;i<val1;i++) {
- t = 5-(i>>1);
- val2 += (t < 0)? 1:t;
- }
- }
- break;
-
- case SC_DEFENDER:
- calc_flag = 1;
- val2 = 5 + val1*15;
- break;
-
- case SC_KEEPING:
- case SC_BARRIER:
- calc_flag = 1;
-
- case SC_HALLUCINATION:
- break;
-
- case SC_CONCENTRATION: /* コンセントレ?ション */
- *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;
- break;
- case SC_PARRYING:
- val2=val1*3;
- break;
- case SC_CONCENTRATION:
- calc_flag=1;
- val2=val1*10;
- val3=val1*5;
- break;
- case SC_TENSIONRELAX:
-// val2 = 10;
-// val3 = 15;
- break;
- case SC_BERSERK:
- calc_flag=1;
- break;
- case SC_ASSUMPTIO:
- if(sc_data[SC_KYRIE].timer!=-1 )
- skill_status_change_end(bl,SC_KYRIE,-1);
- break;
-*/
- case SC_WINDWALK: /* ウインドウォ?ク */
- calc_flag = 1;
- val2 = (val1 / 2); //Flee上昇率
- break;
-
- case SC_BERSERK: /* バ?サ?ク */
- if(sd){
- sd->status.hp = sd->status.max_hp * 3;
- sd->status.sp = 0;
- clif_updatestatus(sd,SP_HP);
- clif_updatestatus(sd,SP_SP);
- clif_status_change(bl,SC_INCREASEAGI,1); /* アイコン表示 */
- }
- *opt3 |= 128;
- tick = 10000;
- calc_flag = 1;
- break;
-
- case SC_ASSUMPTIO: /* アスムプティオ */
- *opt3 |= 2048;
- break;
-
- case SC_BASILICA: // [celest]
- break;
-
- case SC_MARIONETTE: /* マリオネットコントロ?ル */
- case SC_MARIONETTE2:
- calc_flag = 1;
- *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_SPLASHER: /* ベナムスプラッシャ? */
- break;
-
- case SC_FOGWALL:
- val2 = 75;
- // calc_flag = 1; // not sure of effects yet [celest]
- break;
-
- case SC_BLOCKSKILL:
- if (!tick) tick = 60000;
- if (!val3) val3 = -1;
- break;
-
- case SC_SLOWDOWN:
- calc_flag = 1;
- break;
-
- case SC_LEADERSHIP:
- case SC_GLORYWOUNDS:
- case SC_SOULCOLD:
- case SC_HAWKEYES:
- tick = 1000;
- calc_flag = 1;
- //val4 = 1;
- break;
-
- case SC_REGENERATION:
- val1 = 2;
- case SC_BATTLEORDERS:
- tick = 60000; // 1 minute
- calc_flag = 1;
- break;
+ nullpo_retr(1, bl);
- default:
- if(battle_config.error_log)
- printf("UnknownStatusChange [%d]\n", type);
+ if (bl->type == BL_PC) {
+ nullpo_retr(1, sd = (struct map_session_data *)bl);
+ if (!battle_config.pc_cloak_check_type) // If it's No it shouldn't be checked
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:
- case SC_CURSE:
- case SC_SILENCE:
- case SC_BLIND:
- *opt2 |= 1<<(type-SC_POISON);
- opt_flag = 1;
- break;
- case SC_DPOISON: // 暫定で毒のエフェクトを使用
- *opt2 |= 1;
- 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;
- }
-
- if(opt_flag) /* optionの?更 */
- clif_changeoption(bl);
-
- (*sc_count)++; /* ステ?タス異常の? */
-
- sc_data[type].val1 = val1;
- sc_data[type].val2 = val2;
- sc_data[type].val3 = val3;
- sc_data[type].val4 = val4;
- /* タイマ?設定 */
- sc_data[type].timer = add_timer(
- gettick() + tick, skill_status_change_timer, bl->id, type);
-
- if(bl->type==BL_PC && calc_flag)
- pc_calcstatus(sd,0); /* ステ?タス再計算 */
-
- if(bl->type==BL_PC && save_flag)
- chrif_save(sd); // save the player status
-
- if(bl->type==BL_PC && updateflag)
- clif_updatestatus(sd,updateflag); /* ステ?タスをクライアントに送る */
-
- return 0;
-}
-/*==========================================
- * ステ?タス異常全解除
- *------------------------------------------
- */
-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)
+ } else if (bl->type == BL_MOB && !battle_config.monster_cloak_check_type)
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;
-
- if (!type && i < SC_SENDMAX)
- clif_status_change(bl, i, 0);
-*/
-
- skill_status_change_end(bl, i, -1);
- }
- }
- *sc_count = 0;
- *opt1 = 0;
- *opt2 = 0;
- *opt3 = 0;
- *option &= OPTION_MASK;
-
- if (night_flag == 1 && type == BL_PC && !map[bl->m].flag.indoors && // by [Yor]
- !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) // [celest]
- *opt2 |= STATE_BLIND;
- if(!type || type&2)
- clif_changeoption(bl);
-
- return 0;
-}
-
-/* クロ?キング?査(周りに移動不可能地?があるか) */
-int skill_check_cloaking(struct block_list *bl)
-{
- static int dx[]={ 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus
- static int dy[]={-1, 0, 1, 0, -1, -1, 1, 1};
- int end=1,i;
-
- //missing sd [Found by Celest, commited by Aria]
- struct map_session_data *sd=(struct map_session_data *)bl;
-
- nullpo_retr(0, bl);
-
- if(bl->type == BL_PC && !battle_config.pc_cloak_check_type) // If it's No it shouldn't be checked
- return 0;
- else if(bl->type == BL_MOB && !battle_config.monster_cloak_check_type)
- return 0;
- for(i=0;i<sizeof(dx)/sizeof(dx[0]);i++){
- int c=map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i]);
- if(c==1 || c==5) {
- end=0;
+ for (i = 0; i < 8; i++) {
+ if (map_getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS)) {
+ end = 0;
break;
}
}
if(end){
- if ((bl->type == BL_PC && pc_checkskill(sd,AS_CLOAKING)<3) || bl->type == BL_MOB) {
- skill_status_change_end(bl, SC_CLOAKING, -1);
- *battle_get_option(bl)&=~4; /* 念のための?理 */
+ if ((sd && pc_checkskill(sd,AS_CLOAKING)<3) || bl->type == BL_MOB) {
+ status_change_end(bl, SC_CLOAKING, -1);
}
- else if (bl->type == BL_PC && sd->sc_data[SC_CLOAKING].val3 != 130) {
+ else if (sd && sd->sc_data[SC_CLOAKING].val3 != 130) {
sd->sc_data[SC_CLOAKING].val3 = 130;
- pc_calcspeed (sd);
+ status_calc_speed (sd);
}
}
else {
- if (bl->type == BL_PC && sd->sc_data[SC_CLOAKING].val3 != 103) {
+ if (sd && sd->sc_data[SC_CLOAKING].val3 != 103) {
sd->sc_data[SC_CLOAKING].val3 = 103;
- pc_calcspeed (sd);
+ status_calc_speed (sd);
}
}
- return end;
-}
-int skill_type_cloaking(struct block_list *bl)
-{
- static int dx[]={ 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus
- static int dy[]={-1, 0, 1, 0, -1, -1, 1, 1};
- int i;
-
- nullpo_retr(0, bl);
- if(bl->type == BL_PC && battle_config.pc_cloak_check_type&1)
- return 0;
- else if(bl->type == BL_MOB && battle_config.monster_cloak_check_type&1)
- return 0;
- for(i=0; i<sizeof(dx)/sizeof(dx[0]); i++)
- {
- int c=map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i]);
- if(c==1 || c==5)
- return 0;
- }
- return 1;
+ return end;
}
/*
@@ -10018,48 +8096,6 @@ int skill_type_cloaking(struct block_list *bl)
*/
/*==========================================
- * 演奏/ダンススキルかどうか判定
- * 引? スキルID
- * ?り ダンスじゃない=0 合奏=2 それ以外のダンス=1
- *------------------------------------------
- */
-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;
-}
-
-/*==========================================
* 演奏/ダンスをやめる
* flag 1で合奏中なら相方にユニットを任せる
*
@@ -10069,47 +8105,47 @@ void skill_stop_dancing(struct block_list *src, int flag)
{
struct status_change* sc_data;
struct skill_unit_group* group;
+ short* sc_count;
nullpo_retv(src);
-
- sc_data=battle_get_sc_data(src);
- if(sc_data && sc_data[SC_DANCING].timer != -1) {
- group=(struct skill_unit_group *)sc_data[SC_DANCING].val2; //ダンスのスキルユニット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; //合奏もダンス?態も終了させない&スキルユニットは置いてけぼり
+ nullpo_retv(sc_data = status_get_sc_data(src));
+ nullpo_retv(sc_count = status_get_sc_count(src));
+
+ if((*sc_count) > 0 && sc_data[SC_DANCING].timer != -1) {
+ group = (struct skill_unit_group *)sc_data[SC_DANCING].val2; //ダンスのスキルユニットIDはval2に入ってる
+ if (src->type == BL_PC) {
+ if (group && sc_data[SC_DANCING].val4){ //合奏中?
+ struct map_session_data* dsd = map_id2sd(sc_data[SC_DANCING].val4); //相方のsd取得
+ if (flag && dsd) { //ログアウトなど片方が落ちても演奏が??される
+ if (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->bl.id == group->src_id) { //相方がグル?プを持っているPCが落ちる(自分はグル?プを持っていない)
+ if (flag & 1) //ログアウト
+ dsd->sc_data[SC_DANCING].val4 = 0; //相方の相方を0にして合奏終了→通常のダンス?態
+ if(flag & 2) //ハエ飛びなど
+ return; //合奏もダンス?態も終了させない&スキルユニットは置いてけぼり
+ }
+ status_change_end(src, SC_DANCING, -1); //自分のステ?タスを終了させる
+ //そしてグル?プは消さない&消さないのでステ?タス計算もいらない?
+ return;
+ } else if (dsd) {
+ if (src->id == group->src_id) //グル?プを持ってるPCが止める
+ status_change_end(&dsd->bl, SC_DANCING, -1); //相手のステ?タスを終了させる
+ if(dsd->bl.id == group->src_id) //相方がグル?プを持っているPCが止める(自分はグル?プを持っていない)
+ status_change_end(src, SC_DANCING, -1); //自分のステ?タスを終了させる
}
- skill_status_change_end(src,SC_DANCING,-1);//自分のステ?タスを終了させる
- //そしてグル?プは消さない&消さないのでステ?タス計算もいらない?
+ }
+ if(flag & 2 && group) { //ハエで飛んだときとかはユニットも飛ぶ
+ struct map_session_data *sd = (struct map_session_data *)src;
+ if (sd) skill_unit_move_unit_group(group, sd->bl.m, (sd->to_x - sd->bl.x), (sd->to_y - sd->bl.y));
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);
}
}
@@ -10138,10 +8174,13 @@ struct skill_unit *skill_initunit(struct skill_unit_group *group,int idx,int x,i
map_addblock(&unit->bl);
clif_skill_setunit(unit);
+
+ if (group->skill_id==HP_BASILICA)
+ skill_basilica_cell(unit,CELL_SETBASILICA);
+
return unit;
}
-int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap );
/*==========================================
* スキルユニット削除
*------------------------------------------
@@ -10149,7 +8188,6 @@ int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap );
int skill_delunit(struct skill_unit *unit)
{
struct skill_unit_group *group;
- int range;
nullpo_retr(0, unit);
if(!unit->alive)
@@ -10159,11 +8197,15 @@ int skill_delunit(struct skill_unit *unit)
/* 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() );
+ /* onoutイベント呼び出し */
+ if (!unit->range) {
+ map_foreachinarea(skill_unit_effect,unit->bl.m,
+ unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y,0,
+ &unit->bl,gettick(),0);
+ }
+
+ if (group->skill_id==HP_BASILICA)
+ skill_basilica_cell(unit,CELL_CLRBASILICA);
clif_skill_delunit(unit);
@@ -10179,7 +8221,7 @@ int skill_delunit(struct skill_unit *unit)
* スキルユニットグル?プ初期化
*------------------------------------------
*/
-static int skill_unit_group_newid=10;
+static int skill_unit_group_newid = MAX_SKILL_DB;
struct skill_unit_group *skill_initunitgroup(struct block_list *src,
int count,int skillid,int skilllv,int unit_id)
{
@@ -10227,11 +8269,11 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src,
}
group->src_id=src->id;
- group->party_id=battle_get_party_id(src);
- group->guild_id=battle_get_guild_id(src);
+ group->party_id=status_get_party_id(src);
+ group->guild_id=status_get_guild_id(src);
group->group_id=skill_unit_group_newid++;
if(skill_unit_group_newid<=0)
- skill_unit_group_newid=10;
+ skill_unit_group_newid = MAX_SKILL_DB;
group->unit=(struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
group->unit_count=count;
group->val1=group->val2=0;
@@ -10239,39 +8281,23 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src,
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) ){
+ if (skill_get_unit_flag(skillid)&UF_DANCE) {
struct map_session_data *sd = NULL;
if(src->type==BL_PC && (sd=(struct map_session_data *)src) ){
sd->skillid_dance=skillid;
sd->skilllv_dance=skilllv;
}
- 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);
- }
- }
+ status_change_start(src,SC_DANCING,skillid,(int)group,0,0,skill_get_time(skillid,skilllv)+1000,0);
+ //合奏スキルは相方をダンス状態にする
+ if (sd && skill_get_unit_flag(skillid)&UF_ENSEMBLE) {
+ int c=0;
+ map_foreachinarea(skill_check_condition_use_sub,sd->bl.m,
+ sd->bl.x-1,sd->bl.y-1,sd->bl.x+1,sd->bl.y+1,BL_PC,&sd->bl,&c);
}
}
return group;
@@ -10291,10 +8317,16 @@ int skill_delunitgroup(struct skill_unit_group *group)
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);
+ //ダンススキルはダンス状態を解除する
+ if(src) {
+ if (skill_get_unit_flag(group->skill_id)&UF_DANCE)
+ status_change_end(src,SC_DANCING,-1);
+ if (group->unit_id == 0x86) {
+ struct status_change *sc_data = status_get_sc_data(src);
+ if(sc_data && sc_data[SC_MAGICPOWER].timer != -1) //マジックパワ?の?果終了
+ status_change_end(src,SC_MAGICPOWER,-1);
}
+ }
group->alive_count=0;
if(group->unit!=NULL){
@@ -10307,7 +8339,7 @@ int skill_delunitgroup(struct skill_unit_group *group)
group->valstr=NULL;
}
- map_freeblock(group->unit); /* free()の替わり */
+ map_freeblock(group->unit); /* aFree()の替わり */
group->unit=NULL;
group->src_id=0;
group->group_id=0;
@@ -10329,13 +8361,14 @@ int skill_clear_unitgroup(struct block_list *src)
if(src->type==BL_PC){
group=((struct map_session_data *)src)->skillunit;
maxsug=MAX_SKILLUNITGROUP;
- }else if(src->type==BL_MOB){
+ } else if(src->type==BL_MOB){
group=((struct mob_data *)src)->skillunit;
maxsug=MAX_MOBSKILLUNITGROUP;
- }else if(src->type==BL_PET){ // [Valaris]
+ } else if(src->type==BL_PET){ // [Valaris]
group=((struct pet_data *)src)->skillunit;
maxsug=MAX_MOBSKILLUNITGROUP;
- }
+ } else
+ return 0;
if(group){
int i;
for(i=0;i<maxsug;i++)
@@ -10350,54 +8383,46 @@ int skill_clear_unitgroup(struct block_list *src)
*------------------------------------------
*/
struct skill_unit_group_tickset *skill_unitgrouptickset_search(
- struct block_list *bl,int group_id)
+ struct block_list *bl,struct skill_unit_group *group,int tick)
{
- int i,j=0,k,s=group_id%MAX_SKILLUNITGROUPTICKSET;
- struct skill_unit_group_tickset *set=NULL;
+ int i,j=-1,k,s,id;
+ struct skill_unit_group_tickset *set;
nullpo_retr(0, bl);
+ if (group->interval==-1)
+ return NULL;
- if(bl->type==BL_PC){
- set=((struct map_session_data *)bl)->skillunittick;
- }else{
- set=((struct mob_data *)bl)->skillunittick;
- }
- if(set==NULL)
+ if (bl->type == BL_PC)
+ set = ((struct map_session_data *)bl)->skillunittick;
+ else if (bl->type == BL_MOB)
+ set = ((struct mob_data *)bl)->skillunittick;
+ else
return 0;
- 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 i,s=group_id%MAX_SKILLUNITGROUPTICKSET;
- struct skill_unit_group_tickset *set=NULL,*ts;
-
- nullpo_retr(0, bl);
+ if (skill_get_unit_flag(group->skill_id)&UF_NOOVERLAP)
+ id = s = group->skill_id;
+ else
+ id = s = group->group_id;
- if(bl->type==BL_PC){
- set=((struct map_session_data *)bl)->skillunittick;
- }else{
- set=((struct mob_data *)bl)->skillunittick;
+ for (i=0; i<MAX_SKILLUNITGROUPTICKSET; i++) {
+ k = (i+s) % MAX_SKILLUNITGROUPTICKSET;
+ if (set[k].id == id)
+ return &set[k];
+ else if (j==-1 && (DIFF_TICK(tick,set[k].tick)>0 || set[k].id==0))
+ j=k;
}
- if(set!=NULL){
-
- for(i=0;i<MAX_SKILLUNITGROUPTICKSET;i++)
- if( (ts=&set[(i+s)%MAX_SKILLUNITGROUPTICKSET])->group_id == group_id )
- ts->group_id=0;
-
+ if (j == -1) {
+ if(battle_config.error_log) {
+ sprintf (tmp_output, "skill_unitgrouptickset_search: tickset is full\n");
+ ShowWarning (tmp_output);
+ }
+ j = id % MAX_SKILLUNITGROUPTICKSET;
}
- return 0;
+
+ set[j].id = id;
+ set[j].tick = tick;
+ return &set[j];
}
/*==========================================
@@ -10406,49 +8431,27 @@ int skill_unitgrouptickset_delete(struct block_list *bl,int group_id)
*/
int skill_unit_timer_sub_onplace( struct block_list *bl, va_list ap )
{
- struct block_list *src;
- struct skill_unit *su;
+ struct skill_unit *unit;
+ struct skill_unit_group *group;
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;
+ unit = va_arg(ap,struct skill_unit *);
+ tick = va_arg(ap,unsigned int);
- 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;
-}
+ if (bl->type!=BL_PC && bl->type!=BL_MOB)
+ return 0;
+ if (!unit->alive || bl->prev==NULL)
+ return 0;
-/*==========================================
- * スキルユニットタイマ?削除?理用(foreachinarea)
- *------------------------------------------
- */
-int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap )
-{
- struct block_list *src;
- struct skill_unit *su;
- unsigned int tick;
+ nullpo_retr(0, group=unit->group);
- nullpo_retr(0, bl);
- nullpo_retr(0, ap);
- src=va_arg(ap,struct block_list*);
+ if (battle_check_target(&unit->bl,bl,group->target_flag)<=0)
+ return 0;
- tick=va_arg(ap,unsigned int);
- su = (struct skill_unit *)src;
+ skill_unit_onplace_timer(unit,bl,tick);
- 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;
}
@@ -10466,28 +8469,38 @@ int skill_unit_timer_sub( struct block_list *bl, va_list ap )
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;
+ group=unit->group;
- range=(unit->range!=0)?unit->range:group->range;
+ nullpo_retr(0, group);
+ range = unit->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++;
+ /* onplace_timerイベント呼び出し */
+ if (range>=0 && group->interval!=-1) {
+ map_foreachinarea(skill_unit_timer_sub_onplace, bl->m,
+ bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,bl,tick);
+ if (!unit->alive)
+ return 0;
+ // マグヌスは発動したユニットは削除する
+ if (group->skill_id==PR_MAGNUS && unit->val2) {
+ skill_delunit(unit);
+ return 0;
}
}
+ // イドゥンの林檎による回復
+ if (group->unit_id==0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val3) {
+ struct block_list *src = map_id2bl(group->src_id);
+ int range = skill_get_unit_layout_type(group->skill_id,group->skill_lv);
+ nullpo_retr(0, src);
+ map_foreachinarea(skill_idun_heal,src->m,
+ src->x-range,src->y-range,src->x+range,src->y+range,0,unit);
+ group->val3++;
+ }
/* 時間切れ削除 */
- if(unit->alive &&
- (DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit) ){
+ if((DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit)){
switch(group->unit_id){
case 0x8f: /* ブラストマイン */
group->unit_id = 0x8c;
@@ -10516,7 +8529,21 @@ int skill_unit_timer_sub( struct block_list *bl, va_list ap )
map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,NULL,NULL,NULL,0); // ?返還
}
}
+ skill_delunit(unit);
}
+ break;
+
+ case 0xc1:
+ case 0xc2:
+ case 0xc3:
+ case 0xc4:
+ {
+ struct block_list *src=map_id2bl(group->src_id);
+ if (src)
+ group->tick = tick;
+ }
+ break;
+
default:
skill_delunit(unit);
}
@@ -10549,92 +8576,33 @@ int skill_unit_timer( int tid,unsigned int tick,int id,int data)
* スキルユニット移動時?理用(foreachinarea)
*------------------------------------------
*/
-int skill_unit_out_all_sub( struct block_list *bl, va_list ap )
-{
- struct skill_unit *unit;
- struct skill_unit_group *group;
- struct block_list *src;
- int range;
- unsigned int tick;
-
- nullpo_retr(0, bl);
- nullpo_retr(0, ap);
- nullpo_retr(0, src=va_arg(ap,struct block_list*));
- nullpo_retr(0, unit=(struct skill_unit *)bl);
- nullpo_retr(0, group=unit->group);
-
- tick=va_arg(ap,unsigned int);
-
- if(!unit->alive || src->prev==NULL)
- return 0;
-
- range=(unit->range!=0)?unit->range:group->range;
-
- if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 )
- return 0;
-
- if( src->x >= bl->x-range && src->x <= bl->x+range &&
- src->y >= bl->y-range && src->y <= bl->y+range )
- skill_unit_onout( unit, src, tick );
-
- return 0;
-}
-
-
-/*==========================================
- * スキルユニット移動時?理
- *------------------------------------------
- */
-int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range)
-{
- nullpo_retr(0, bl);
-
- if( bl->prev==NULL )
- return 0;
-
- if(range<7)
- range=7;
- map_foreachinarea( skill_unit_out_all_sub,
- bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL,
- bl,tick );
-
- return 0;
-}
-
-/*==========================================
- * スキルユニット移動時?理用(foreachinarea)
- *------------------------------------------
- */
int skill_unit_move_sub( struct block_list *bl, va_list ap )
{
- struct skill_unit *unit;
+ struct skill_unit *unit = (struct skill_unit *)bl;
struct skill_unit_group *group;
- struct block_list *src;
- int range;
- unsigned int tick;
+ struct block_list *target;
+ unsigned int tick,flag;
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);
+ nullpo_retr(0, target=va_arg(ap,struct block_list*));
+ tick = va_arg(ap,unsigned int);
+ flag = va_arg(ap,int);
- if(!unit->alive || src->prev==NULL)
+ if (target->type!=BL_PC && target->type!=BL_MOB)
return 0;
- if((group=unit->group) == NULL)
+ nullpo_retr(0, group=unit->group);
+ if (group->interval!=-1)
return 0;
- range=(unit->range!=0)?unit->range:group->range;
- if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 )
+ if (!unit->alive || target->prev==NULL)
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 );
+ if (flag)
+ skill_unit_onplace(unit,target,tick);
else
- skill_unit_onout( unit, src, tick );
+ skill_unit_onout(unit,target,tick);
return 0;
}
@@ -10643,173 +8611,117 @@ int skill_unit_move_sub( struct block_list *bl, va_list ap )
* スキルユニット移動時?理
*------------------------------------------
*/
-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 flag)
{
nullpo_retr(0, bl);
- if( bl->prev==NULL )
+ 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 );
+ map_foreachinarea(skill_unit_move_sub,
+ bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,bl,tick,flag);
return 0;
}
/*==========================================
- * スキルユニット自?の移動時?理(foreachinarea)
- *------------------------------------------
- */
-int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap )
-{
- struct skill_unit *unit;
- struct skill_unit_group *group;
- struct block_list *src;
- int range;
- unsigned int tick;
-
- nullpo_retr(0, bl);
- nullpo_retr(0, ap);
- nullpo_retr(0, src=va_arg(ap,struct block_list*));
- nullpo_retr(0, unit=(struct skill_unit *)src);
- nullpo_retr(0, group=unit->group);
-
- tick=va_arg(ap,unsigned int);
-
- if(!unit->alive || bl->prev==NULL)
- return 0;
-
- range=(unit->range!=0)?unit->range:group->range;
-
- if( range<0 || battle_check_target(src,bl,group->target_flag )<=0 )
- return 0;
- if( bl->x >= src->x-range && bl->x <= src->x+range &&
- bl->y >= src->y-range && bl->y <= src->y+range )
- skill_unit_onplace( unit, bl, tick );
- else
- skill_unit_onout( unit, bl, tick );
- return 0;
-}
-
-/*==========================================
* スキルユニット自?の移動時?理
* 引?はグル?プと移動量
*------------------------------------------
*/
int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy)
{
+ int i,j;
+ int tick = gettick();
+ int *m_flag;
+ struct skill_unit *unit1;
+ struct skill_unit *unit2;
+
nullpo_retr(0, group);
+ if (group->unit_count<=0)
+ return 0;
+ if (group->unit==NULL)
+ return 0;
- if( group->unit_count<=0)
+ // 移動可能なスキルはダンス系と、ブラストマイン、クレイモアートラップのみ
+ if (!(skill_get_unit_flag(group->skill_id)&UF_DANCE) &&
+ group->skill_id!=HT_CLAYMORETRAP && group->skill_id!=HT_BLASTMINE)
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() );
- }
- }
+ m_flag = (int *) aMalloc(sizeof(int)*group->unit_count);
+ memset(m_flag,0,sizeof(int)*group->unit_count);// 移動フラグ
+ // 先にフラグを全部決める
+ // m_flag
+ // 0: 単純移動
+ // 1: ユニットを移動する(現位置からユニットがなくなる)
+ // 2: 残留&新位置が移動先となる(移動先にユニットが存在しない)
+ // 3: 残留
+ for(i=0;i<group->unit_count;i++){
+ unit1=&group->unit[i];
+ if (!unit1->alive || unit1->bl.m!=m)
+ continue;
+ for(j=0;j<group->unit_count;j++){
+ unit2=&group->unit[j];
+ if (!unit2->alive)
+ continue;
+ if (unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){
+ // 移動先にユニットがかぶっている
+ m_flag[i] |= 0x1;
}
- }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;
- }
- }
- }
+ if (unit1->bl.x-dx==unit2->bl.x && unit1->bl.y-dy==unit2->bl.y){
+ // ユニットがこの場所にやってくる
+ m_flag[i] |= 0x2;
+ }
+ }
+ }
+ // フラグに基づいてユニット移動
+ // フラグが1のunitを探し、フラグが2のunitの移動先に移す
+ j = 0;
+ for (i=0;i<group->unit_count;i++) {
+ unit1=&group->unit[i];
+ if (!unit1->alive)
+ continue;
+ if (!(m_flag[i]&0x2)) {
+ // ユニットがなくなる場所でスキルユニット影響を消す
+ map_foreachinarea(skill_unit_effect,unit1->bl.m,
+ unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0,
+ &unit1->bl,tick,0);
+ }
+ if (m_flag[i]==0) {
+ // 単純移動
+ map_delblock(&unit1->bl);
+ unit1->bl.m = m;
+ unit1->bl.x += dx;
+ unit1->bl.y += dy;
+ map_addblock(&unit1->bl);
+ clif_skill_setunit(unit1);
+ } else if (m_flag[i]==1) {
+ // フラグが2のものを探してそのユニットの移動先に移動
+ for(;j<group->unit_count;j++) {
+ if (m_flag[j]==2) {
+ // 継承移動
+ unit2 = &group->unit[j];
+ if (!unit2->alive)
+ continue;
+ map_delblock(&unit1->bl);
+ unit1->bl.m = m;
+ unit1->bl.x = unit2->bl.x+dx;
+ unit1->bl.y = unit2->bl.y+dy;
+ map_addblock(&unit1->bl);
+ clif_skill_setunit(unit1);
+ j++;
+ break;
}
}
- free(r_flag);
- free(s_flag);
- free(m_flag);
+ }
+ if (!(m_flag[i]&0x2)) {
+ // 移動後の場所でスキルユニットを発動
+ map_foreachinarea(skill_unit_effect,unit1->bl.m,
+ unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0,
+ &unit1->bl,tick,1);
}
}
+ aFree(m_flag);
return 0;
}
@@ -10935,62 +8847,57 @@ int skill_produce_mix( struct map_session_data *sd,
/* 確率判定 */
equip = itemdb_isequip(nameid);
if(!equip) {
+// Corrected rates [DracoRPG] --------------------------//
if(skill_produce_db[idx].req_skill==AM_PHARMACY) {
- if((nameid >= 501 && nameid <= 506) || (nameid >= 545 && nameid <= 547) || nameid == 525)
- make_per = 2000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_POTIONPITCHER)*100;
- else if(nameid == 970)
- make_per = 1500 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300;
- else if(nameid == 7135)
- make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_DEMONSTRATION)*100;
- else if(nameid == 7136)
- make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_ACIDTERROR)*100;
- else if(nameid == 7137)
- make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CANNIBALIZE)*100;
- else if(nameid == 7138)
- make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_SPHEREMINE)*100;
- else if(nameid == 7139)
- make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CP_WEAPON)*100 +
- pc_checkskill(sd,AM_CP_SHIELD)*100 + pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100;
- else
- make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300;
+ make_per = pc_checkskill(sd,AM_LEARNINGPOTION)*100
+ + pc_checkskill(sd,AM_PHARMACY)*300 + sd->status.job_level*20
+ + sd->paramc[4]*10+sd->paramc[5]*10;
+
+ if(nameid >= 501 && nameid <= 505) // Normal potions
+ make_per += 2000 + pc_checkskill(sd,AM_POTIONPITCHER)*100;
+ else if(nameid >= 605 && nameid <= 606) // Anodyne & Aloevera (not sure of the formula, I put the same base value as normal pots but without the Aid Potion bonus since they are not throwable pots ^^)
+ make_per += 2000;
+ else if(nameid >= 545 && nameid <= 547) // Concentrated potions
+ ;
+ else if(nameid == 970) // Alcohol
+ make_per += 1000;
+ else if(nameid == 7135) // Bottle Grenade
+ make_per += 500 + pc_checkskill(sd,AM_DEMONSTRATION)*100;
+ else if(nameid == 7136) // Acid Bottle
+ make_per += 500 + pc_checkskill(sd,AM_ACIDTERROR)*100;
+ else if(nameid == 7137) // Plant Bottle
+ make_per += 500 + pc_checkskill(sd,AM_CANNIBALIZE)*100;
+ else if(nameid == 7138) // Marine Sphere Bottle
+ make_per += 500 + pc_checkskill(sd,AM_SPHEREMINE)*100;
+ else if(nameid == 7139) // Glistening Coat
+ make_per += 500 + pc_checkskill(sd,AM_CP_WEAPON)*100 + pc_checkskill(sd,AM_CP_SHIELD)*100 +
+ pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100;
} else if (skill_produce_db[idx].req_skill == ASC_CDP) {
make_per = 2000 + 40*sd->paramc[4] + 20*sd->paramc[5];
- //make_per = 20 + (20*sd->paramc[4])/50 + (20*sd->paramc[5])/100;
} else {
if(nameid == 998)
- make_per = 2000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*600;
- else if(nameid == 985)
- make_per = 1000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + (pc_checkskill(sd,skill_produce_db[idx].req_skill)-1)*500;
+ make_per = 1500 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*600;
else
- make_per = 1000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500;
- }
- }
- else {
- int add_per;
- if(pc_search_inventory(sd,989) >= 0) add_per = 750;
- else if(pc_search_inventory(sd,988) >= 0) add_per = 500;
- else if(pc_search_inventory(sd,987) >= 0) add_per = 250;
- else if(pc_search_inventory(sd,986) >= 0) add_per = 0;
- else add_per = -500;
- if(ele) add_per -= 500;
- add_per -= sc*500;
+ make_per = 1000 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500;
+ }
+ if(battle_config.pp_rate != 100)
+ make_per = make_per * battle_config.pp_rate / 100;
+ } else { // Corrected rates [DracoRPG]
+ int add_per=0;
+ if(pc_search_inventory(sd,989) >= 0) add_per = 400;
+ else if(pc_search_inventory(sd,988) >= 0) add_per = 300;
+ else if(pc_search_inventory(sd,987) >= 0) add_per = 200;
+ else if(pc_search_inventory(sd,986) >= 0) add_per = 100;
wlv = itemdb_wlv(nameid);
- make_per = ((250 + sd->status.base_level*15 + sd->paramc[4]*10 + sd->paramc[5]*5 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500 +
- add_per) * (100 - (wlv - 1)*20))/100 + pc_checkskill(sd,BS_WEAPONRESEARCH)*100 + ((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100 : 0);
+ make_per = 1500 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*1000 + pc_checkskill(sd,BS_WEAPONRESEARCH)*100 +
+ ((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100 : 0) + add_per - (ele? 2500:0) - sc*((4-wlv)*500) - wlv*1000;
+ if(battle_config.wp_rate != 100) /* 確率補正 */
+ make_per = make_per * battle_config.wp_rate / 100;
}
+// -----------------------------------------------------//
if(make_per < 1) make_per = 1;
- if(skill_produce_db[idx].req_skill==AM_PHARMACY ||
- skill_produce_db[idx].req_skill==ASC_CDP) {
- if( battle_config.pp_rate!=100 )
- make_per=make_per*battle_config.pp_rate/100;
- }
- else {
- if( battle_config.wp_rate!=100 ) /* 確率補正 */
- make_per=make_per*battle_config.wp_rate/100;
- }
-
// if(battle_config.etc_log)
// printf("make rate = %d\n",make_per);
@@ -11013,10 +8920,8 @@ int skill_produce_mix( struct map_session_data *sd,
*((unsigned long *)(&tmp_item.card[2]))=sd->char_id; /* キャラID */
}
- #ifndef TXT_ONLY
if(log_config.produce > 0)
log_produce(sd,nameid,slot1,slot2,slot3,1);
- #endif //USE_SQL
switch (skill_produce_db[idx].req_skill) {
case AM_PHARMACY:
@@ -11037,12 +8942,9 @@ int skill_produce_mix( struct map_session_data *sd,
clif_additem(sd,0,0,flag);
map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
}
- }
- else {
- #ifndef TXT_ONLY
+ } else {
if(log_config.produce > 0)
log_produce(sd,nameid,slot1,slot2,slot3,0);
- #endif //USE_SQL
switch (skill_produce_db[idx].req_skill) {
case AM_PHARMACY:
@@ -11110,6 +9012,230 @@ int skill_arrow_create( struct map_session_data *sd,int nameid)
* 初期化系
*/
+/*----------------------------------------------------------------------------
+ * 初期化系
+ */
+
+/*
+ * 文字列処理
+ * ',' で区切って val に戻す
+ */
+int skill_split_str(char *str,char **val,int num)
+{
+ int i;
+
+ for (i=0; i<num && str; i++){
+ val[i] = str;
+ str = strchr(str,',');
+ if (str)
+ *str++=0;
+ }
+ return i;
+}
+/*
+ * 文字列処理
+ * ':' で区切ってatoiしてvalに戻す
+ */
+int skill_split_atoi(char *str,int *val)
+{
+ int i, max = 0;
+
+ for (i=0; i<MAX_SKILL_LEVEL; i++) {
+ if (str) {
+ val[i] = max = atoi(str);
+ str = strchr(str,':');
+ if (str)
+ *str++=0;
+ } else {
+ val[i] = max;
+ }
+ }
+ return i;
+}
+
+/*
+ * スキルユニットの配置情報作成
+ */
+void skill_init_unit_layout()
+{
+ int i,j,size,pos = 0;
+
+ memset(skill_unit_layout,0,sizeof(skill_unit_layout));
+ // 矩形のユニット配置を作成する
+ for (i=0; i<=MAX_SQUARE_LAYOUT; i++) {
+ size = i*2+1;
+ skill_unit_layout[i].count = size*size;
+ for (j=0; j<size*size; j++) {
+ skill_unit_layout[i].dx[j] = (j%size-i);
+ skill_unit_layout[i].dy[j] = (j/size-i);
+ }
+ }
+ pos = i;
+ // 矩形以外のユニット配置を作成する
+ for (i=0;i<MAX_SKILL_DB;i++) {
+ if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1)
+ continue;
+ switch (i) {
+ case MG_FIREWALL:
+ case WZ_ICEWALL:
+ // ファイアーウォール、アイスウォールは方向で変わるので別処理
+ break;
+ case PR_SANCTUARY:
+ {
+ static const int dx[] = {
+ -1, 0, 1,-2,-1, 0, 1, 2,-2,-1,
+ 0, 1, 2,-2,-1, 0, 1, 2,-1, 0, 1};
+ static const int dy[]={
+ -2,-2,-2,-1,-1,-1,-1,-1, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2};
+ skill_unit_layout[pos].count = 21;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ break;
+ }
+ case PR_MAGNUS:
+ {
+ static const int dx[] = {
+ -1, 0, 1,-1, 0, 1,-3,-2,-1, 0,
+ 1, 2, 3,-3,-2,-1, 0, 1, 2, 3,
+ -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,-1, 0, 1};
+ static const int dy[] = {
+ -3,-3,-3,-2,-2,-2,-1,-1,-1,-1,
+ -1,-1,-1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3};
+ skill_unit_layout[pos].count = 33;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ break;
+ }
+ case AS_VENOMDUST:
+ {
+ static const int dx[] = {-1, 0, 0, 0, 1};
+ static const int dy[] = { 0,-1, 0, 1, 0};
+ skill_unit_layout[pos].count = 5;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ break;
+ }
+ case CR_GRANDCROSS:
+ case NPC_DARKGRANDCROSS:
+ {
+ static const int dx[] = {
+ 0, 0,-1, 0, 1,-2,-1, 0, 1, 2,
+ -4,-3,-2,-1, 0, 1, 2, 3, 4,-2,
+ -1, 0, 1, 2,-1, 0, 1, 0, 0};
+ static const int dy[] = {
+ -4,-3,-2,-2,-2,-1,-1,-1,-1,-1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 2, 2, 2, 3, 4};
+ skill_unit_layout[pos].count = 29;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ break;
+ }
+ case PF_FOGWALL:
+ {
+ static const int dx[] = {
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2};
+ static const int dy[] = {
+ -1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
+ skill_unit_layout[pos].count = 15;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ break;
+ }
+ case PA_GOSPEL:
+ {
+ static const int dx[] = {
+ -1, 0, 1,-1, 0, 1,-3,-2,-1, 0,
+ 1, 2, 3,-3,-2,-1, 0, 1, 2, 3,
+ -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,
+ -1, 0, 1};
+ static const int dy[] = {
+ -3,-3,-3,-2,-2,-2,-1,-1,-1,-1,
+ -1,-1,-1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+ 3, 3, 3};
+ skill_unit_layout[pos].count = 33;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ break;
+ }
+ default:
+ printf("unknown unit layout at skill %d\n",i);
+ break;
+ }
+ if (!skill_unit_layout[pos].count)
+ continue;
+ for (j=0;j<MAX_SKILL_LEVEL;j++)
+ skill_db[i].unit_layout_type[j] = pos;
+ pos++;
+ }
+ // ファイヤーウォール
+ firewall_unit_pos = pos;
+ for (i=0;i<8;i++) {
+ if (i&1) { /* 斜め配置 */
+ skill_unit_layout[pos].count = 5;
+ if (i&0x2) {
+ int dx[] = {-1,-1, 0, 0, 1};
+ int dy[] = { 1, 0, 0,-1,-1};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ } else {
+ int dx[] = { 1, 1 ,0, 0,-1};
+ int dy[] = { 1, 0, 0,-1,-1};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ } else { /* 縦横配置 */
+ skill_unit_layout[pos].count = 3;
+ if (i%4==0) { /* 上下 */
+ int dx[] = {-1, 0, 1};
+ int dy[] = { 0, 0, 0};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ } else { /* 左右 */
+ int dx[] = { 0, 0, 0};
+ int dy[] = {-1, 0, 1};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ }
+ pos++;
+ }
+ // アイスウォール
+ icewall_unit_pos = pos;
+ for (i=0;i<8;i++) {
+ skill_unit_layout[pos].count = 5;
+ if (i&1) { /* 斜め配置 */
+ if (i&0x2) {
+ int dx[] = {-2,-1, 0, 1, 2};
+ int dy[] = { 2,-1, 0,-1,-2};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ } else {
+ int dx[] = { 2, 1 ,0,-1,-2};
+ int dy[] = { 2, 1, 0,-1,-2};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ } else { /* 縦横配置 */
+ if (i%4==0) { /* 上下 */
+ int dx[] = {-2,-1, 0, 1, 2};
+ int dy[] = { 0, 0, 0, 0, 0};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ } else { /* 左右 */
+ int dx[] = { 0, 0, 0, 0, 0};
+ int dy[] = {-2,-1, 0, 1, 2};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ }
+ pos++;
+ }
+}
+
/*==========================================
* スキル?係ファイル?み?み
* skill_db.txt スキルデ?タ
@@ -11134,46 +9260,27 @@ int skill_readdb(void)
return 1;
}
while(fgets(line,1020,fp)){
- char *split[50], *split2[MAX_SKILL_LEVEL];
+ char *split[50];
if(line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<14 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
+ j = skill_split_str(line,split,14);
if(split[13]==NULL || j<14)
continue;
i=atoi(split[0]);
if (i>=10000 && i<10015) // for guild skills [Celest]
i -= 9500;
- else if(i<0 || i>MAX_SKILL_DB)
+ else if(i<=0 || i>MAX_SKILL_DB)
continue;
/* printf("skill id=%d\n",i); */
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].range[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ skill_split_atoi(split[1],skill_db[i].range);
skill_db[i].hit=atoi(split[2]);
skill_db[i].inf=atoi(split[3]);
skill_db[i].pl=atoi(split[4]);
skill_db[i].nk=atoi(split[5]);
skill_db[i].max=atoi(split[6]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[7];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].num[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ skill_split_atoi(split[7],skill_db[i].num);
if(strcmpi(split[8],"yes") == 0)
skill_db[i].castcancel=1;
@@ -11190,17 +9297,11 @@ int skill_readdb(void)
skill_db[i].skill_type=BF_MISC;
else
skill_db[i].skill_type=0;
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[13];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].blewcount[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ skill_split_atoi(split[13],skill_db[i].blewcount);
}
fclose(fp);
- printf("read db/skill_db.txt done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_db.txt");
+ ShowStatus(tmp_output);
fp=fopen("db/skill_require_db.txt","r");
if(fp==NULL){
@@ -11208,91 +9309,39 @@ int skill_readdb(void)
return 1;
}
while(fgets(line,1020,fp)){
- char *split[51], *split2[MAX_SKILL_LEVEL];
+ char *split[50];
if(line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<30 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
+ j = skill_split_str(line,split,30);
if(split[29]==NULL || j<30)
continue;
i=atoi(split[0]);
if (i>=10000 && i<10015) // for guild skills [Celest]
i -= 9500;
- else if(i<0 || i>MAX_SKILL_DB)
+ else if(i<=0 || i>MAX_SKILL_DB)
continue;
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].hp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].mhp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].sp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].hp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[5];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].sp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[6];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].zeny[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[7];j<32 && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<32 && split2[k];k++) {
- l = atoi(split2[k]);
- if(l == 99) {
+ skill_split_atoi(split[1],skill_db[i].hp);
+ skill_split_atoi(split[2],skill_db[i].mhp);
+ skill_split_atoi(split[3],skill_db[i].sp);
+ skill_split_atoi(split[4],skill_db[i].hp_rate);
+ skill_split_atoi(split[5],skill_db[i].sp_rate);
+ skill_split_atoi(split[6],skill_db[i].zeny);
+
+ p = split[7];
+ for(j=0;j<32;j++){
+ l = atoi(p);
+ if (l==99) {
skill_db[i].weapon = 0xffffffff;
break;
}
else
skill_db[i].weapon |= 1<<l;
+ p=strchr(p,':');
+ if(!p)
+ break;
+ p++;
}
if( strcmpi(split[8],"hiding")==0 ) skill_db[i].state=ST_HIDING;
@@ -11309,14 +9358,7 @@ int skill_readdb(void)
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_split_atoi(split[9],skill_db[i].spiritball);
skill_db[i].itemid[0]=atoi(split[10]);
skill_db[i].amount[0]=atoi(split[11]);
skill_db[i].itemid[1]=atoi(split[12]);
@@ -11339,7 +9381,8 @@ int skill_readdb(void)
skill_db[i].amount[9]=atoi(split[29]);
}
fclose(fp);
- printf("read db/skill_require_db.txt done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_require_db.txt");
+ ShowStatus(tmp_output);
/* キャスティングデ?タベ?ス */
fp=fopen("db/skill_cast_db.txt","r");
@@ -11348,62 +9391,70 @@ int skill_readdb(void)
return 1;
}
while(fgets(line,1020,fp)){
- char *split[50], *split2[MAX_SKILL_LEVEL];
+ char *split[50];
memset(split,0,sizeof(split)); // [Valaris] thanks to fov
if(line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<5 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
+ j = skill_split_str(line,split,5);
if(split[4]==NULL || j<5)
continue;
i=atoi(split[0]);
if (i>=10000 && i<10015) // for guild skills [Celest]
i -= 9500;
- else if(i<0 || i>MAX_SKILL_DB)
+ else if(i<=0 || i>MAX_SKILL_DB)
continue;
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].cast[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].delay[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ skill_split_atoi(split[1],skill_db[i].cast);
+ skill_split_atoi(split[2],skill_db[i].delay);
+ skill_split_atoi(split[3],skill_db[i].upkeep_time);
+ skill_split_atoi(split[4],skill_db[i].upkeep_time2);
+ }
+ fclose(fp);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_cast_db.txt");
+ ShowStatus(tmp_output);
- 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]);
+ /* スキルユニットデータベース */
+ fp = fopen("db/skill_unit_db.txt","r");
+ if (fp==NULL) {
+ printf("can't read db/skill_unit_db.txt\n");
+ return 1;
+ }
+ k = 0;
+ while (fgets(line,1020,fp)) {
+ char *split[50];
+ if (line[0]=='/' && line[1]=='/')
+ continue;
+ j = skill_split_str(line,split,8);
+ if (split[7]==NULL || j<8)
+ continue;
- 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]);
+ i=atoi(split[0]);
+ if (i>=10000 && i<10015) // for guild skills [Celest]
+ i -= 9500;
+ else if(i<=0 || i>MAX_SKILL_DB)
+ continue;
+ skill_db[i].unit_id[0] = strtol(split[1],NULL,16);
+ skill_db[i].unit_id[1] = strtol(split[2],NULL,16);
+ skill_split_atoi(split[3],skill_db[i].unit_layout_type);
+ skill_db[i].unit_range = atoi(split[4]);
+ skill_db[i].unit_interval = atoi(split[5]);
+
+ if( strcmpi(split[6],"noenemy")==0 ) skill_db[i].unit_target=BCT_NOENEMY;
+ else if( strcmpi(split[6],"friend")==0 ) skill_db[i].unit_target=BCT_NOENEMY;
+ else if( strcmpi(split[6],"party")==0 ) skill_db[i].unit_target=BCT_PARTY;
+ else if( strcmpi(split[6],"all")==0 ) skill_db[i].unit_target=BCT_ALL;
+ else if( strcmpi(split[6],"enemy")==0 ) skill_db[i].unit_target=BCT_ENEMY;
+ else if( strcmpi(split[6],"self")==0 ) skill_db[i].unit_target=BCT_SELF;
+ else skill_db[i].unit_target = strtol(split[6],NULL,16);
+
+ skill_db[i].unit_flag = strtol(split[7],NULL,16);
+ k++;
}
fclose(fp);
- printf("read db/skill_cast_db.txt done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_unit_db.txt");
+ ShowStatus(tmp_output);
+ skill_init_unit_layout();
/* 製造系スキルデ?タベ?ス */
memset(skill_produce_db,0,sizeof(skill_produce_db));
@@ -11422,16 +9473,11 @@ int skill_readdb(void)
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
- for(j=0,p=line;j<3 + MAX_PRODUCE_RESOURCE * 2 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
- if(split[0]==NULL)
+ j = skill_split_str(line,split,(3 + MAX_PRODUCE_RESOURCE * 2));
+ if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
- if(i<=0)
- continue;
+ if(i<=0) continue;
skill_produce_db[k].nameid=i;
skill_produce_db[k].itemlv=atoi(split[1]);
@@ -11446,7 +9492,8 @@ int skill_readdb(void)
break;
}
fclose(fp);
- printf("read %s done (count=%d)\n",filename[m],k);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,filename[m]);
+ ShowStatus(tmp_output);
}
memset(skill_arrow_db,0,sizeof(skill_arrow_db));
@@ -11462,12 +9509,8 @@ int skill_readdb(void)
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
- for(j=0,p=line;j<13 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
- if(split[0]==NULL)
+ j = skill_split_str(line,split,13);
+ if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
if(i<=0)
@@ -11484,7 +9527,8 @@ int skill_readdb(void)
break;
}
fclose(fp);
- printf("read db/create_arrow_db.txt done (count=%d)\n",k);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,"db/create_arrow_db.txt");
+ ShowStatus(tmp_output);
memset(skill_abra_db,0,sizeof(skill_abra_db));
fp=fopen("db/abra_db.txt","r");
@@ -11498,12 +9542,8 @@ int skill_readdb(void)
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
- for(j=0,p=line;j<13 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
- if(split[0]==NULL)
+ j = skill_split_str(line,split,13);
+ if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
if(i<=0)
@@ -11517,7 +9557,8 @@ int skill_readdb(void)
break;
}
fclose(fp);
- printf("read db/abra_db.txt done (count=%d)\n",k);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,"db/abra_db.txt");
+ ShowStatus(tmp_output);
fp=fopen("db/skill_castnodex_db.txt","r");
if(fp==NULL){
@@ -11525,33 +9566,27 @@ int skill_readdb(void)
return 1;
}
while(fgets(line,1020,fp)){
- char *split[50], *split2[MAX_SKILL_LEVEL];
- memset(split,0,sizeof(split));
+ char *split[50];
if(line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<2 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
-
+ memset(split,0,sizeof(split));
+ j = skill_split_str(line,split,3);
+ if(split[0]==0) //fixed by Lupus
+ continue;
i=atoi(split[0]);
if (i>=10000 && i<10015) // for guild skills [Celest]
i -= 9500;
- else if(i<0 || i>MAX_SKILL_DB)
+ else if(i<=0 || i>MAX_SKILL_DB)
continue;
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].castnodex[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ skill_split_atoi(split[1],skill_db[i].castnodex);
+ if (!split[2])
+ continue;
+ skill_split_atoi(split[2],skill_db[i].delaynodex);
}
fclose(fp);
- printf("read db/skill_castnodex_db.txt done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_castnodex_db.txt");
+ ShowStatus(tmp_output);
fp=fopen("db/skill_nocast_db.txt","r");
if(fp==NULL){
@@ -11564,35 +9599,75 @@ int skill_readdb(void)
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
- for(j=0,p=line;j<2 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
- if(split[0]==NULL)
+ j = skill_split_str(line,split,2);
+ if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
- if(i < 0 || i > MAX_SKILL_DB)
+ if (i>=10000 && i<10015) // for guild skills [Celest]
+ i -= 9500;
+ else if(i<=0 || i>MAX_SKILL_DB)
continue;
skill_db[i].nocast=atoi(split[1]);
k++;
}
fclose(fp);
- printf("read db/skill_nocast_db done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_nocast_db");
+ ShowStatus(tmp_output);
return 0;
}
-void skill_reload(void)
+/*===============================================
+ * For reading leveluseskillspamount.txt [Celest]
+ *-----------------------------------------------
+ */
+static int skill_read_skillspamount(void)
{
- /*
+ char *buf,*p;
+ struct skill_db *skill = NULL;
+ int s, idx, new_flag=1, level=1, sp=0;
+
+ buf=(char *) grfio_reads("data\\leveluseskillspamount.txt",&s);
+
+ if(buf==NULL)
+ return -1;
+
+ buf[s]=0;
+ for(p=buf;p-buf<s;){
+ char buf2[64];
+
+ if (sscanf(p,"%[@]",buf2) == 1) {
+ level = 1;
+ new_flag = 1;
+ } else if (new_flag && sscanf(p,"%[^#]#",buf2) == 1) {
+ for (idx=0; skill_names[idx].id != 0; idx++) {
+ if (strstr(buf2, skill_names[idx].name) != NULL) {
+ skill = &skill_db[ skill_names[idx].id ];
+ new_flag = 0;
+ break;
+ }
+ }
+ } else if (!new_flag && sscanf(p,"%d#",&sp) == 1) {
+ skill->sp[level-1]=sp;
+ level++;
+ }
- <empty skill database>
- <?>
+ p=strchr(p,10);
+ if(!p) break;
+ p++;
+ }
+ aFree(buf);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\leveluseskillspamount.txt");
+ ShowStatus(tmp_output);
- */
+ return 0;
+}
- do_init_skill();
+void skill_reload(void)
+{
+ skill_readdb();
+ if (battle_config.skill_sp_override_grffile)
+ skill_read_skillspamount();
}
/*==========================================
@@ -11602,12 +9677,13 @@ void skill_reload(void)
int do_init_skill(void)
{
skill_readdb();
+ if (battle_config.skill_sp_override_grffile)
+ skill_read_skillspamount();
add_timer_func_list(skill_unit_timer,"skill_unit_timer");
add_timer_func_list(skill_castend_id,"skill_castend_id");
add_timer_func_list(skill_castend_pos,"skill_castend_pos");
add_timer_func_list(skill_timerskill,"skill_timerskill");
- add_timer_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;