Parcourir la source

- Small cleanup on Abracadabra.
- Added UF_SONG (0x400) to differentiate songs from dances.
- Updated the skill_unit_db accordingly, ensembles should only have that flag, likewise for songs and dances.
- Added preliminar support for making a Song+Dance turn into BA_DISSONANCE cells. Beware of potential bugs as it's untested.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@7428 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex il y a 19 ans
Parent
commit
00cbe67c6f
7 fichiers modifiés avec 121 ajouts et 37 suppressions
  1. 3 0
      Changelog-Trunk.txt
  2. 2 0
      db/Changelog.txt
  3. 15 14
      db/skill_unit_db.txt
  4. 10 2
      src/map/clif.c
  5. 1 0
      src/map/map.h
  6. 86 18
      src/map/skill.c
  7. 4 3
      src/map/skill.h

+ 3 - 0
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

+ 2 - 0
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]

+ 15 - 14
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#水遁#

+ 10 - 2
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;

+ 1 - 0
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 {

+ 86 - 18
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);
 		}

+ 4 - 3
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);