summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt3
-rw-r--r--db/Changelog.txt2
-rw-r--r--db/skill_unit_db.txt29
-rw-r--r--src/map/clif.c12
-rw-r--r--src/map/map.h1
-rw-r--r--src/map/skill.c104
-rw-r--r--src/map/skill.h7
7 files changed, 121 insertions, 37 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index f9f05ed27..cefb47895 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -4,6 +4,9 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2006/05/30
+ * Added UF_SONG (0x400) to differentiate songs from dances. [Skotlex]
+ * Added preliminar support for making a Song+Dance turn into BA_DISSONANCE
+ cells. Beware of potential bugs as it's untested. [Skotlex]
* Added mapflag "nochat" to prevent chatting rooms from being created.
[Skotlex]
* Corrected some of the sleep checks when the char id does not matches with
diff --git a/db/Changelog.txt b/db/Changelog.txt
index 0202fbc52..9974ca0c8 100644
--- a/db/Changelog.txt
+++ b/db/Changelog.txt
@@ -25,6 +25,8 @@
=========================
06/30
+ * Updated skill_unit_db to use the correct values of
+ UF_ENSEMBLE/UF_DANCE/UF_SONG as applicable. [Skotlex]
* Added the new X.4 headgears [Playtester]
* Fixed various items and sorted the item_db [Playtester]
* Reverted back Vulcan Arrow. It's fine now. Player can move after the attack animation end [Lupus]
diff --git a/db/skill_unit_db.txt b/db/skill_unit_db.txt
index 7873ae907..ed8368190 100644
--- a/db/skill_unit_db.txt
+++ b/db/skill_unit_db.txt
@@ -12,6 +12,7 @@
// 0x080(UF_SKILL) Spell CAN affect skills.
// 0x100(UF_DANCE) Dance skill
// 0x200(UF_ENSEMBLE) Ensemble skill
+// 0x400(UF_SONG) Song skill
// 0x800(UF_DUALMODE) Spell has effects both at an interval and when you step in/out
// Example: 0x006 = 0x002+0x004 -> Cannot be stacked nor cast near targets
//
@@ -56,24 +57,24 @@
286,0x9b, , 3, 0, -1,all, 0x000 //SA_DELUGE#デリュージ
287,0x9c, , 3, 0, -1,all, 0x000 //SA_VIOLENTGALE#バイオレントゲイル
288,0x9d,,3:3:4:4:5,0, -1,all, 0x000 //SA_LANDPROTECTOR#ランドプロテクター
-306,0x9e, , 4, 0,6000,all, 0x300 //BD_LULLABY#子守歌
-307,0x9f, , 4, 0, -1,enemy, 0x310 //BD_RICHMANKIM#ニヨルドの宴
-308,0xa0, , 4, 0, -1,enemy, 0x300 //BD_ETERNALCHAOS#永遠の混沌
-309,0xa1, , 4, 0, -1,party, 0x300 //BD_DRUMBATTLEFIELD#戦太鼓の響き
-310,0xa2, , 4, 0, -1,party, 0x300 //BD_RINGNIBELUNGEN#ニーベルングの指輪
-311,0xa3, , 4, 0, -1,all, 0x300 //BD_ROKISWEIL#ロキの叫び
-312,0xa4, , 4, 0, -1,party, 0x320 //BD_INTOABYSS#深淵の中に
-313,0xa5, , 4, 0, -1,party, 0x300 //BD_SIEGFRIED#不死身のジークフリード
+306,0x9e, , 4, 0,6000,all, 0x200 //BD_LULLABY#子守歌
+307,0x9f, , 4, 0, -1,enemy, 0x210 //BD_RICHMANKIM#ニヨルドの宴
+308,0xa0, , 4, 0, -1,enemy, 0x200 //BD_ETERNALCHAOS#永遠の混沌
+309,0xa1, , 4, 0, -1,party, 0x200 //BD_DRUMBATTLEFIELD#戦太鼓の響き
+310,0xa2, , 4, 0, -1,party, 0x200 //BD_RINGNIBELUNGEN#ニーベルングの指輪
+311,0xa3, , 4, 0, -1,all, 0x200 //BD_ROKISWEIL#ロキの叫び
+312,0xa4, , 4, 0, -1,party, 0x220 //BD_INTOABYSS#深淵の中に
+313,0xa5, , 4, 0, -1,party, 0x200 //BD_SIEGFRIED#不死身のジークフリード
317,0xa6, , 3, 0,3000,enemy, 0x100 //BA_DISSONANCE#不協和音
319,0xa7, , 3, 0, -1,all, 0x120 //BA_WHISTLE#口笛
320,0xa8, , 3, 0, -1,all, 0x120 //BA_ASSASSINCROSS#夕陽のアサシンクロス
321,0xa9, , 3, 0, -1,all, 0x120 //BA_POEMBRAGI#ブラギの詩
322,0xaa, , 3, 0,6000,all, 0x920 //BA_APPLEIDUN#イドゥンの林檎
-325,0xab, , 3, 0,3000,enemy, 0x100 //DC_UGLYDANCE#自分勝手なダンス
-327,0xac, , 3, 0, -1,all, 0x120 //DC_HUMMING#ハミング
-328,0xad, , 3, 0, -1,enemy, 0x100 //DC_DONTFORGETME#私を忘れないで…
-329,0xae, , 3, 0, -1,all, 0x120 //DC_FORTUNEKISS#幸運のキス
-330,0xaf, , 3, 0, -1,party, 0x100 //DC_SERVICEFORYOU#サービスフォーユー
+325,0xab, , 3, 0,3000,enemy, 0x400 //DC_UGLYDANCE#自分勝手なダンス
+327,0xac, , 3, 0, -1,all, 0x420 //DC_HUMMING#ハミング
+328,0xad, , 3, 0, -1,enemy, 0x400 //DC_DONTFORGETME#私を忘れないで…
+329,0xae, , 3, 0, -1,all, 0x420 //DC_FORTUNEKISS#幸運のキス
+330,0xaf, , 3, 0, -1,party, 0x400 //DC_SERVICEFORYOU#サービスフォーユー
336,0xb2, , 0,-1, -1,noone, 0x000 //WE_CALLPARTNER#あなたに逢いたい
339,0x86, , -1, 0, 400,enemy, 0x000 //NPC_DARKGRANDCROSS#闇グランドクロス
362,0xb4, , 0, 3, -1,all, 0x000 //HP_BASILICA#バジリカ
@@ -87,7 +88,7 @@
429,0x86, , 0, 1, 500,enemy, 0x000 //SG_MOON_WARM
430,0x86, , 0, 1, 500,enemy, 0x000 //SG_STAR_WARM
484,0xb8, , 2, 0,1000,enemy, 0x808 //HW_GRAVITATION
-488,0xb9, , 3, 0, -1,all, 0x100 //CG_HERMODE
+488,0xb9, , 3, 0, -1,all, 0x200 //CG_HERMODE
535,0x86, , 0, 2,2000,enemy,0x008,NJ_KAENSIN#火炎陣#
536,0x86, , 0, 2, 300,enemy,0x008,NJ_BAKUENRYU#爆炎龍#
538,0xbb,,1:1:1:2:2:2:3:3:3:4,0, -1,all,0x010,NJ_SUITON#水遁#
diff --git a/src/map/clif.c b/src/map/clif.c
index 30e0c1cd1..e9821bcd5 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -4653,7 +4653,11 @@ int clif_skill_setunit(struct skill_unit *unit)
WBUFL(buf, 6)=unit->group->src_id;
WBUFW(buf,10)=unit->bl.x;
WBUFW(buf,12)=unit->bl.y;
- WBUFB(buf,14)=unit->group->unit_id;
+ if (unit->group->state.song_dance && unit->val1 == BA_DISSONANCE) {
+ WBUFB(buf,14)=UNT_DISSONANCE;
+ } else {
+ WBUFB(buf,14)=unit->group->unit_id;
+ }
WBUFB(buf,15)=1;
WBUFB(buf,16)=1;
memcpy(WBUFP(buf,17),unit->group->valstr,MESSAGE_SIZE);
@@ -4667,7 +4671,11 @@ int clif_skill_setunit(struct skill_unit *unit)
WBUFL(buf, 6)=unit->group->src_id;
WBUFW(buf,10)=unit->bl.x;
WBUFW(buf,12)=unit->bl.y;
- WBUFB(buf,14)=unit->group->unit_id;
+ if (unit->group->state.song_dance && unit->val1 == BA_DISSONANCE) {
+ WBUFB(buf,14)=UNT_DISSONANCE;
+ } else {
+ WBUFB(buf,14)=unit->group->unit_id;
+ }
WBUFB(buf,15)=0;
clif_send(buf,packet_len_table[0x11f],&unit->bl,AREA);
return 0;
diff --git a/src/map/map.h b/src/map/map.h
index 20fe52b45..9d8a6f254 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -317,6 +317,7 @@ struct skill_unit_group {
unsigned ammo_consume : 1;
unsigned magic_power : 1;
unsigned into_abyss : 1;
+ unsigned song_dance : 1;
} state;
};
struct skill_unit_group_tickset {
diff --git a/src/map/skill.c b/src/map/skill.c
index b43112109..250ef1d3c 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -3306,10 +3306,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
do {
abra_skillid = rand() % MAX_SKILL_ABRA_DB;
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
+ rand()%10000 >= skill_abra_db[abra_skillid].per ||
+ skill_get_inf2(abra_skillid)&INF2_NPC_SKILL ||
+ skill_get_unit_flag(abra_skillid) &(UF_DANCE|UF_ENSEMBLE|UF_SONG)
+ )
+ 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);
@@ -6155,6 +6156,44 @@ int skill_castend_map (struct map_session_data *sd, int skill_num, const char *m
#undef skill_failed
}
+static int skill_dance_overlap_sub(struct block_list *bl, va_list ap)
+{
+ struct skill_unit *target = (struct skill_unit*)bl,
+ *src = va_arg(ap, struct skill_unit*);
+ int flag = va_arg(ap, int);
+ if (!target || !target->group || !target->group->state.song_dance)
+ return 0;
+ if (!(target->val2 & src->val2 & ~UF_ENSEMBLE)) //They don't match (song + dance) is valid.
+ return 0;
+ if (flag) { //Set dissonance
+ target->val1 = src->val1 = BA_DISSONANCE;
+ target->val2 |= UF_ENSEMBLE; //Add ensemble to signal this unit is overlapping.
+ } else { //Remove dissonance
+ target->val1 = target->group->skill_id; //Restore skill id
+ target->val2 &= ~UF_ENSEMBLE;
+ }
+ clif_skill_setunit(target); //Update look of affected cell.
+ return 1;
+}
+
+//Does the song/dance overlapping -> dissonance check. [Skotlex]
+//When flag is 0, this unit is about to be removed, cancel the dissonance effect
+//When 1, this unit has been positioned, so start the cancel effect.
+int skill_dance_overlap(struct skill_unit *unit, int flag)
+{
+ if (!unit || !unit->group || !unit->group->state.song_dance)
+ return 0;
+ if (!flag && !(unit->val2&UF_ENSEMBLE))
+ return 0; //Nothing to remove, this unit is not overlapped.
+ if (unit->val1 != unit->group->skill_id)
+ { //Reset state
+ unit->val1 = unit->group->skill_id;
+ unit->val2 &= ~UF_ENSEMBLE;
+ }
+ return map_foreachincell(skill_dance_overlap_sub,
+ unit->bl.m,unit->bl.x,unit->bl.y,BL_SKILL,unit,flag);
+}
+
/*==========================================
* Initializes and sets a ground skill.
* flag&1 is used to determine when the skill 'morphs' (Warp portal becomes active, or Fire Pillar becomes active)
@@ -6377,6 +6416,7 @@ struct skill_unit_group *skill_unitsetting (struct block_list *src, int skillid,
group->state.into_abyss = (sc && sc->data[SC_INTOABYSS].timer != -1); //Store into abyss state, to know it shouldn't give traps back. [Skotlex]
group->state.magic_power = (flag&2 || (sc && sc->data[SC_MAGICPOWER].timer != -1)); //Store the magic power flag. [Skotlex]
group->state.ammo_consume = (sd && sd->state.arrow_atk); //Store if this skill needs to consume ammo.
+ group->state.song_dance = (unit_flag&(UF_DANCE|UF_SONG)); //Signals if this is a song/dance (does not counts duets)
if(skillid==HT_TALKIEBOX ||
skillid==RG_GRAFFITI){
@@ -6413,6 +6453,12 @@ struct skill_unit_group *skill_unitsetting (struct block_list *src, int skillid,
ux+=(i%5-2);
uy+=(i/5-2);
break;
+ default:
+ if (group->state.song_dance) {
+ val1 = skillid; //Holds SKILL id to use.
+ val2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance
+ }
+ break;
}
//逶エ荳翫せ繧ュ繝ォ縺ョ蝣エ蜷郁ィュ鄂ョ蠎ァ讓吩ク翫↓繝ゥ繝ウ繝峨励Ο繝繧ッ繧ソ繝シ縺後↑縺縺九メ繧ァ繝繧ッ
if(range<=0)
@@ -6440,12 +6486,10 @@ struct skill_unit_group *skill_unitsetting (struct block_list *src, int skillid,
}
if(alive){
- nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy));
- unit->val1=val1;
- unit->val2=val2;
+ nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy,val1,val2));
unit->limit=limit;
unit->range=range;
-
+
if (range==0 && active_flag)
map_foreachincell(skill_unit_effect,unit->bl.m,
unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1);
@@ -6620,6 +6664,13 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
}
type = SkillStatusChangeTable(sg->skill_id);
skillid = sg->skill_id;
+ if (sg->state.song_dance && src->val2&UF_ENSEMBLE)
+ { //Treat this group as if it were BA_DISSONANCE.
+ //Values will be restored on proper switch case.
+ src->val1 = sg->unit_id;
+ sg->unit_id = UNT_DISSONANCE;
+ sg->skill_id = BA_DISSONANCE;
+ }
if (sg->interval == -1) {
switch (sg->unit_id) {
@@ -6654,7 +6705,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
sstatus->matk_min = sc->data[SC_MAGICPOWER].val3;
sstatus->matk_min = sc->data[SC_MAGICPOWER].val4;
}
-
+
switch (sg->unit_id) {
case UNT_FIREWALL:
{
@@ -6829,6 +6880,12 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
case UNT_DISSONANCE:
skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
+ if (sg->state.song_dance && src->val2&UF_ENSEMBLE)
+ { //Restore values.
+ sg->skill_id = skillid;
+ sg->unit_id = src->val1;
+ src->val1 = BA_DISSONANCE;
+ }
break;
case UNT_APPLEIDUN: //Apple of Idun [Skotlex]
@@ -9115,7 +9172,7 @@ void skill_stop_dancing (struct block_list *src)
* 繧ケ繧ュ繝ォ繝ヲ繝九ャ繝亥晄悄蛹
*------------------------------------------
*/
-struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y)
+struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2)
{
struct skill_unit *unit;
@@ -9131,11 +9188,11 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
unit->bl.x=x;
unit->bl.y=y;
unit->group=group;
- unit->val1=unit->val2=0;
unit->alive=1;
+ unit->val1=val1;
+ unit->val2=val2;
map_addblock(&unit->bl);
- clif_skill_setunit(unit);
switch (group->skill_id) {
case AL_PNEUMA:
@@ -9153,7 +9210,12 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
case WZ_ICEWALL:
skill_unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_SETICEWALL);
break;
+ default:
+ if (group->state.song_dance) //Check for dissonance.
+ skill_dance_overlap(unit, 1);
+ break;
}
+ clif_skill_setunit(unit);
return unit;
}
@@ -9173,6 +9235,9 @@ int skill_delunit (struct skill_unit *unit)
/* onlimit繧、繝吶Φ繝亥他縺ウ蜃コ縺 */
skill_unit_onlimit( unit,gettick() );
+ if (group->state.song_dance) //Restore dissonance effect.
+ skill_dance_overlap(unit, 0);
+
/* ondelete繧、繝吶Φ繝亥他縺ウ蜃コ縺 */
if (!unit->range) {
map_foreachincell(skill_unit_effect,unit->bl.m,
@@ -9265,7 +9330,7 @@ struct skill_unit_group *skill_initunitgroup (struct block_list *src, int count,
group->valstr=NULL;
i = skill_get_unit_flag(skillid); //Reuse for faster access from here on. [Skotlex]
- if (i&UF_DANCE) {
+ if (i&(UF_DANCE|UF_SONG|UF_ENSEMBLE)) {
struct map_session_data *sd = NULL;
if(src->type==BL_PC && (sd=(struct map_session_data *)src) ){
sd->skillid_dance=skillid;
@@ -9300,7 +9365,7 @@ int skill_delunitgroup (struct block_list *src, struct skill_unit_group *group)
ShowError("skill_delunitgroup: Group's source not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id);
return 0;
}
- if (skill_get_unit_flag(group->skill_id)&UF_DANCE)
+ if (skill_get_unit_flag(group->skill_id)&(UF_DANCE|UF_SONG|UF_ENSEMBLE))
{
struct status_change* sc = status_get_sc(src);
if (sc && sc->data[SC_DANCING].timer != -1)
@@ -9666,7 +9731,7 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int m, int dx, i
return 0;
m_flag = (int *) aMalloc(sizeof(int)*group->unit_count);
- memset(m_flag,0,sizeof(int)*group->unit_count);// 遘サ蜍輔ヵ繝ゥ繧ー
+ memset(m_flag,0,sizeof(int)*group->unit_count);
// m_flag
// 0: Neither of the following (skill_unit_onplace & skill_unit_onout are needed)
// 1: Unit will move to a slot that had another unit of the same group (skill_unit_onplace not needed)
@@ -9694,6 +9759,8 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int m, int dx, i
if (!unit1->alive)
continue;
if (!(m_flag[i]&0x2)) {
+ if (group->state.song_dance) //Restore dissonance effect.
+ skill_dance_overlap(unit1, 0);
map_foreachincell(skill_unit_effect,unit1->bl.m,
unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,4);
}
@@ -9703,7 +9770,6 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int m, int dx, i
case 0:
//Cell moves independently, safely move it.
map_moveblock(&unit1->bl, unit1->bl.x+dx, unit1->bl.y+dy, tick);
- clif_skill_setunit(unit1);
break;
case 1:
//Cell moves unto another cell, look for a replacement cell that won't collide
@@ -9715,7 +9781,6 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int m, int dx, i
//Move to where this cell would had moved.
unit2 = &group->unit[j];
map_moveblock(&unit1->bl, unit2->bl.x+dx, unit2->bl.y+dy, tick);
- clif_skill_setunit(unit1);
j++; //Skip this cell as we have used it.
break;
}
@@ -9724,7 +9789,10 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int m, int dx, i
case 3:
break; //Don't move the cell as a cell will end on this tile anyway.
}
- if (!(m_flag[i]&2)) { //We only moved the cell in 0-1
+ if (!(m_flag[i]&0x2)) { //We only moved the cell in 0-1
+ if (group->state.song_dance) //Check for dissonance effect.
+ skill_dance_overlap(unit1, 1);
+ clif_skill_setunit(unit1);
map_foreachincell(skill_unit_effect,unit1->bl.m,
unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,1);
}
diff --git a/src/map/skill.h b/src/map/skill.h
index 650fb6ae7..704fd4f57 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -95,8 +95,9 @@ enum {
UF_NOPC = 0x0010, //May not target players
UF_NOMOB = 0x0020, //May not target mobs
UF_SKILL = 0x0080, //May target skills
- UF_DANCE = 0x0100, // ダンススキル
- UF_ENSEMBLE = 0x0200, // 合奏スキル
+ UF_DANCE = 0x0100, //Dance
+ UF_ENSEMBLE = 0x0200, //Duet
+ UF_SONG = 0x0400, //Song
UF_DUALMODE = 0x0800, //Spells should trigger both ontimer and onplace/onout/onleft effects.
};
@@ -188,7 +189,7 @@ int skill_blown( struct block_list *src, struct block_list *target,int count);
int skill_break_equip(struct block_list *bl, unsigned short where, int rate, int flag);
// ユニットスキル
struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag);
-struct skill_unit *skill_initunit(struct skill_unit_group *group,int idx,int x,int y);
+struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2);
int skill_delunit(struct skill_unit *unit);
struct skill_unit_group *skill_initunitgroup(struct block_list *src,
int count,int skillid,int skilllv,int unit_id, int limit, int interval);