Przeglądaj źródła

Rewrote SC_MAGICPOWER to behave like on official servers
* everything has been tested (with the exception of WZ_SIGHTBLASTER)
* the status now uses a much simpler two-state mechanism; see http://www.eathena.ws/board/index.php?autocom=bugtracker&showbug=4833 for details
* non-offensive and non-magic skills no longer consume the status
* set WZ_ICEWALL NK flag to NK_NO_DAMAGE to properly not consume the status
* fixed stale matk used for unit- and timerskills
* fixed the original bug with isilla card triggering a status recalc (bugreport:4833, matk swapping no longer needed)
* removed a couple now unnecessary exceptions (they now work out of the box/as side effects)

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

lordttseven 13 lat temu
rodzic
commit
e2bbd02dab
6 zmienionych plików z 42 dodań i 57 usunięć
  1. 1 1
      db/pre-re/skill_db.txt
  2. 1 1
      db/re/skill_db.txt
  3. 38 47
      src/map/skill.c
  4. 0 1
      src/map/skill.h
  5. 2 6
      src/map/status.c
  6. 0 1
      src/map/status.h

+ 1 - 1
db/pre-re/skill_db.txt

@@ -130,7 +130,7 @@
 84,9,8,1,4,0,0,10,3:4:5:6:7:8:9:10:11:12,yes,0,0,0,magic,2:3:3:4:4:5:5:6:6:7,	WZ_JUPITEL,Jupitel Thunder
 85,9,8,2,4,0,0,10,-10,yes,0,0,0,magic,0,		WZ_VERMILION,Lord of Vermilion
 86,9,8,1,1,0,0,5,1,yes,0,0,0,magic,0,		WZ_WATERBALL,Water Ball
-87,9,6,2,1,0,0,10,1,yes,0,0,0,magic,0,		WZ_ICEWALL,Ice Wall
+87,9,6,2,1,0x1,0,10,1,yes,0,0,0,magic,0,		WZ_ICEWALL,Ice Wall
 88,0,6,4,1,0x2,2,10,1,yes,0,0,0,magic,0,		WZ_FROSTNOVA,Frost Nova
 89,9,6,2,1,0,0,10,1,yes,0,0,0,magic,2,		WZ_STORMGUST,Storm Gust
 90,9,8,1,2,0,0,5,1:2:3:4:5,yes,0,0,0,magic,0,	WZ_EARTHSPIKE,Earth Spike

+ 1 - 1
db/re/skill_db.txt

@@ -130,7 +130,7 @@
 84,9,8,1,4,0,0,10,3:4:5:6:7:8:9:10:11:12,yes,0,0,0,magic,2:3:3:4:4:5:5:6:6:7,	WZ_JUPITEL,Jupitel Thunder
 85,9,8,2,4,0,0,10,-10,yes,0,0,0,magic,0,		WZ_VERMILION,Lord of Vermilion
 86,9,8,1,1,0,0,5,1,yes,0,0,0,magic,0,		WZ_WATERBALL,Water Ball
-87,9,6,2,1,0,0,10,1,yes,0,0,0,magic,0,		WZ_ICEWALL,Ice Wall
+87,9,6,2,1,0x1,0,10,1,yes,0,0,0,magic,0,		WZ_ICEWALL,Ice Wall
 88,0,6,4,1,0x2,2,10,1,yes,0,0,0,magic,0,		WZ_FROSTNOVA,Frost Nova
 89,9,6,2,1,0,0,10,1,yes,0,0,0,magic,2,		WZ_STORMGUST,Storm Gust
 90,9,8,1,2,0,0,5,1:2:3:4:5,yes,0,0,0,magic,0,	WZ_EARTHSPIKE,Earth Spike

+ 38 - 47
src/map/skill.c

@@ -227,6 +227,7 @@ int skill_attack_area(struct block_list *bl,va_list ap);
 struct skill_unit_group *skill_locate_element_field(struct block_list *bl); // [Skotlex]
 int skill_graffitiremover(struct block_list *bl, va_list ap); // [Valaris]
 int skill_greed(struct block_list *bl, va_list ap);
+static void skill_toggle_magicpower(struct block_list *bl, short skillid);
 static int skill_cell_overlap(struct block_list *bl, va_list ap);
 static int skill_trap_splash(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);
@@ -1401,6 +1402,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 
 			sd->state.autocast = 1;
 			skill_consume_requirement(sd,skill,skilllv,1);
+			skill_toggle_magicpower(src, skill);
 			switch (type) {
 				case CAST_GROUND:
 					skill_castend_pos2(src, tbl->x, tbl->y, skill, skilllv, tick, 0);
@@ -1661,7 +1663,6 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 			if( skillid == WZ_WATERBALL ) {//(bugreport:5303)
 				struct status_change *sc = NULL;
 				if( ( sc = status_get_sc(src) ) ) {
-					status_change_end(src, SC_MAGICPOWER, INVALID_TIMER);
 					if(sc->data[SC_SPIRIT] &&
 								sc->data[SC_SPIRIT]->val2 == SL_WIZARD &&
 								sc->data[SC_SPIRIT]->val3 == WZ_WATERBALL)
@@ -2939,7 +2940,6 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
 					} else {
 						struct status_change *sc = status_get_sc(src);
 						if(sc) {
-							status_change_end(src, SC_MAGICPOWER, INVALID_TIMER);
 							if(sc->data[SC_SPIRIT] &&
 								sc->data[SC_SPIRIT]->val2 == SL_WIZARD &&
 								sc->data[SC_SPIRIT]->val3 == skl->skill_id)
@@ -2976,7 +2976,6 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
 					skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
 					if( skl->type >= 3 )
 					{ // Final Hit
-						status_change_end(src,SC_MAGICPOWER,-1); // Removes Magic Power
 						if( !status_isdead(target) )
 						{ // Final Status Effect
 							int effects[4] = { SC_BURNING, SC_FREEZING, SC_BLEEDING, SC_STUN },
@@ -3058,8 +3057,6 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
 					break;
 
 			}
-			if( skl->skill_id >= WL_TETRAVORTEX_FIRE && skl->skill_id <= WL_TETRAVORTEX_GROUND )
-				status_change_end(src,SC_MAGICPOWER,-1);
 		}
 	} while (0);
 	//Free skl now that it is no longer needed.
@@ -3995,8 +3992,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 				if( sd->rsb[0].skillid == 0 )
 					status_change_end(src, SC_READING_SB, INVALID_TIMER);
 
-				status_change_end(src, SC_MAGICPOWER, INVALID_TIMER);
-
 				clif_skill_nodamage(src,bl,skillid,skilllv,1);
 				if( !skill_check_condition_castbegin(sd,rsb_skillid,rsb_skilllv) )
 					break;
@@ -4047,8 +4042,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 							swap(spheres[i],spheres[k]);
 						}
 
-				status_change_end(src, SC_MAGICPOWER, INVALID_TIMER);
-
 				if( skilllv == 1 ) j = 1; // Limit only to one ball
 				for( i = 0; i < j; i++ )
 				{
@@ -8298,6 +8291,10 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
 				src->type, src->id, ud->skillid, ud->skilllv, target->id);
 
 		map_freeblock_lock();
+
+		// SC_MAGICPOWER needs to switch states before any damage is actually dealt
+		skill_toggle_magicpower(src, ud->skillid);
+
 		if (skill_get_casttype(ud->skillid) == CAST_NODAMAGE)
 			skill_castend_nodamage_id(src,target,ud->skillid,ud->skilllv,tick,flag);
 		else
@@ -8305,9 +8302,6 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
 
 		sc = status_get_sc(src);
 		if(sc && sc->count) {
-		  	if(sc->data[SC_MAGICPOWER] &&
-				ud->skillid != HW_MAGICPOWER && ud->skillid != WZ_WATERBALL && ud->skillid != WL_TETRAVORTEX)
-				status_change_end(src, SC_MAGICPOWER, INVALID_TIMER);
 			if(sc->data[SC_SPIRIT] &&
 				sc->data[SC_SPIRIT]->val2 == SL_WIZARD &&
 				sc->data[SC_SPIRIT]->val3 == ud->skillid &&
@@ -8562,6 +8556,9 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 				clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
 	}
 
+	// SC_MAGICPOWER needs to switch states before any damage is actually dealt
+	skill_toggle_magicpower(src, skillid);
+
 	switch(skillid)
 	{
 	case PR_BENEDICTIO:
@@ -8738,9 +8735,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 			int flag = 0, area = skill_get_splash(skillid, skilllv);
 			short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0;
 
-			if( sc && sc->data[SC_MAGICPOWER] )
-				flag = flag|2; //Store the magic power flag for future use. [Skotlex]
-
 			for( i = 0; i < 2 + (skilllv>>1); i++ )
 			{
 				// Creates a random Cell in the Splash Area
@@ -8751,13 +8745,13 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 					clif_skill_poseffect(src,skillid,skilllv,tmpx,tmpy,tick);
 
 				if( i > 0 )
-					skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,(x1<<16)|y1,flag&2); //Only pass the Magic Power flag
+					skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,(x1<<16)|y1,0);
 
 				x1 = tmpx;
 				y1 = tmpy;
 			}
 
-			skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,-1,flag&2);
+			skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,-1,0);
 		}
 		break;
 
@@ -8997,9 +8991,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 			int i, wave = skilllv + 4, dir = map_calc_dir(src,x,y);
 			int sx = x, sy = y;
 
-			if( sc && sc->data[SC_MAGICPOWER] )
-				flag = flag|2; //Store the magic power flag
-
 			for( i = 0; i < wave; i++ )
 			{
 				switch( dir )
@@ -9111,8 +9102,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 		return 1;
 	}
 
-	status_change_end(src, SC_MAGICPOWER, INVALID_TIMER);
-
 	if( sd )
 	{// ensure that the skill last-cast tick is recorded
 		sd->canskill_tick = gettick();
@@ -9366,7 +9355,6 @@ static bool skill_dance_switch(struct skill_unit* unit, int 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)
- * flag&2 is used to determine if this skill was casted with Magic Power active.
  *------------------------------------------*/
 struct skill_unit_group* skill_unitsetting (struct block_list *src, short skillid, short skilllv, short x, short y, int flag)
 {
@@ -9643,7 +9631,6 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
 	group->val3=val3;
 	group->target_flag=target;
 	group->bl_flag= skill_get_unit_bl_target(skillid);
-	group->state.magic_power = (flag&2 || (sc && sc->data[SC_MAGICPOWER])); //Store the magic power flag. [Skotlex]
 	group->state.ammo_consume = (sd && sd->state.arrow_atk && skillid != GS_GROUNDDRIFT); //Store if this skill needs to consume ammo.
 	group->state.song_dance = (unit_flag&(UF_DANCE|UF_SONG)?1:0)|(unit_flag&UF_ENSEMBLE?2:0); //Signals if this is a song/dance/duet
 
@@ -9967,8 +9954,8 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
 	struct skill_unit_group *sg;
 	struct block_list *ss;
 	TBL_PC* tsd;
-	struct status_data *tstatus, *sstatus;
-	struct status_change *tsc, *sc;
+	struct status_data *tstatus;
+	struct status_change *tsc;
 	struct skill_unit_group_tickset *ts;
 	enum sc_type type;
 	int skillid;
@@ -9985,14 +9972,6 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
 	tsd = BL_CAST(BL_PC, bl);
 	tsc = status_get_sc(bl);
 	tstatus = status_get_status_data(bl);
-	if (sg->state.magic_power)  //For magic power.
-	{
-		sc = status_get_sc(ss);
-		sstatus = status_get_status_data(ss);
-	} else {
-		sc = NULL;
-		sstatus = NULL;
-	}
 	type = status_skill2sc(sg->skill_id);
 	skillid = sg->skill_id;
 
@@ -10019,13 +9998,6 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
 		if ((skillid==CR_GRANDCROSS || skillid==NPC_GRANDDARKNESS) && !battle_config.gx_allhit)
 			ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y,BL_CHAR)-1);
 	}
-	//Temporarily set magic power to have it take effect. [Skotlex]
-	if (sg->state.magic_power && sc && !sc->data[SC_MAGICPOWER])
-	{	//Store previous values.
-		swap(sstatus->matk_min, sc->mp_matk_min);
-		swap(sstatus->matk_max, sc->mp_matk_max);
-		//Note to NOT return from the function until this is unset!
-	}
 
 	switch (sg->unit_id)
 	{
@@ -10478,12 +10450,6 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
 
 	}
 
-	if (sg->state.magic_power && sc && !sc->data[SC_MAGICPOWER])
-	{	//Unset magic power.
-		swap(sstatus->matk_min, sc->mp_matk_min);
-		swap(sstatus->matk_max, sc->mp_matk_max);
-	}
-
 	if (bl->type == BL_MOB && ss != bl)
 		mobskill_event((TBL_MOB*)bl, ss, tick, MSC_SKILLUSED|(skillid<<16));
 
@@ -14564,6 +14530,30 @@ int skill_poisoningweapon( struct map_session_data *sd, int nameid) {
 
 	return 0;
 }
+
+static void skill_toggle_magicpower(struct block_list *bl, short skillid)
+{
+	struct status_change *sc = status_get_sc(bl);
+
+	// non-offensive and non-magic skills do not affect the status
+	if (skill_get_nk(skillid)&NK_NO_DAMAGE || !(skill_get_type(skillid)&BF_MAGIC))
+		return;
+
+	if (sc && sc->count && sc->data[SC_MAGICPOWER])
+	{
+		if (sc->data[SC_MAGICPOWER]->val4)
+		{
+			status_change_end(bl, SC_MAGICPOWER, INVALID_TIMER);
+		}
+		else
+		{
+			sc->data[SC_MAGICPOWER]->val4 = 1;
+			status_calc_bl(bl, status_sc2scb_flag(SC_MAGICPOWER));
+		}
+	}
+}
+
+
 int skill_magicdecoy(struct map_session_data *sd, int nameid) {
 	int x, y, i, class_, skill;
 	struct mob_data *md;
@@ -14599,6 +14589,7 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) {
 
 	return 0;
 }
+
 // Warlock Spellbooks. [LimitLine/3CeAM]
 int skill_spellbook (struct map_session_data *sd, int nameid) {
 	int i, j, points, skillid, preserved = 0, max_preserve;

+ 0 - 1
src/map/skill.h

@@ -154,7 +154,6 @@ struct skill_unit_group {
 	struct skill_unit *unit;
 	struct {
 		unsigned ammo_consume : 1;
-		unsigned magic_power : 1;
 		unsigned song_dance : 2; //0x1 Song/Dance, 0x2 Ensemble
 	} state;
 };

+ 2 - 6
src/map/status.c

@@ -3483,11 +3483,6 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 			status->matk_max = status_calc_matk(bl, sc, status->matk_max);
 		#endif
 
-		if(sc->data[SC_MAGICPOWER]) { //Store current matk values
-			sc->mp_matk_min = status->matk_min;
-			sc->mp_matk_max = status->matk_max;
-		}
-
 		if( bl->type&BL_HOM && battle_config.hom_setting&0x20 ) //Hom Min Matk is always the same as Max Matk
 			status->matk_min = status->matk_max;
 
@@ -4136,7 +4131,7 @@ static unsigned short status_calc_matk(struct block_list *bl, struct status_chan
 		matk += sc->data[SC_MATKPOTION]->val1;
 	if(sc->data[SC_MATKFOOD])
 		matk += sc->data[SC_MATKFOOD]->val1;
-	if(sc->data[SC_MAGICPOWER])
+	if(sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4)
 		matk += matk * sc->data[SC_MAGICPOWER]->val3/100;
 	if(sc->data[SC_MINDBREAKER])
 		matk += matk * sc->data[SC_MINDBREAKER]->val2/100;
@@ -6414,6 +6409,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 			//val1: Skill lv
 			val2 = 1; //Lasts 1 invocation
 			val3 = 5*val1; //Matk% increase
+			val4 = 0; // 0 = ready to be used, 1 = activated and running
 			break;
 		case SC_SACRIFICE:
 			val2 = 5; //Lasts 5 hits

+ 0 - 1
src/map/status.h

@@ -1444,7 +1444,6 @@ struct status_change {
 	unsigned char count;
 	//TODO: See if it is possible to implement the following SC's without requiring extra parameters while the SC is inactive.
 	unsigned char jb_flag; //Joint Beat type flag
-	unsigned short mp_matk_min, mp_matk_max; //Previous matk min/max for ground spells (Amplify magic power)
 	//int sg_id; //ID of the previous Storm gust that hit you
 	short comet_x, comet_y; // Point where src casted Comet - required to calculate damage from this point
 /**