Quellcode durchsuchen

Follow up to c48133c and d8d5489
* Fixes #616 - Status effects that damage monsters will now give players their EXP.

aleos89 vor 9 Jahren
Ursprung
Commit
b385fd048a
4 geänderte Dateien mit 132 neuen und 58 gelöschten Zeilen
  1. 81 37
      doc/status_change.txt
  2. 1 1
      src/map/battle.c
  3. 20 18
      src/map/skill.c
  4. 30 2
      src/map/status.c

+ 81 - 37
doc/status_change.txt

@@ -3,7 +3,7 @@
 //===== By: ==================================================
 //= rAthena Dev Team
 //===== Last Updated: ========================================
-//= 20150331
+//= 20151030
 //===== Description: =========================================
 //= List of all Status Changes and theirs val1, val2, val3, and
 //= val4 usage in source. Providing easier guide to use
@@ -25,6 +25,9 @@
 SC_STONE	()
 	desc: DEF -50%; if HP>25% lose 1% HP/5 sec; MDEF +25%; change element to Earth Lv 1; ignore Steal & Lex Aeterna; can't move/attack/pick item/use item/use skill/sit/logout
 	val1:
+	val2: Caster's object ID (for mob_log_damage)
+	val3: Tick
+	val4: Petrifying tick
 
 SC_FREEZE	()
 	desc: DEF -50%; FLEE = 0; MDEF +25%; ignore Steal, Lex Aeterna, Storm Gust, Falling Ice Pillar; change element to Water Lv 1; can't move/attack/pick item/use item/sit/logout
@@ -40,7 +43,10 @@ SC_SLEEP	()
 
 SC_POISON	()
 	desc: DEF -25%; if HP>25% lose 1.5% + 2 HP/sec; SP Regeneration is disabled
-	val1:
+	val1: Skill Level
+	val2: Caster's object ID (for mob_log_damage)
+	val3: Tick
+	val4: HP Damage
 
 SC_CURSE	()
 	desc: ATK-25%; LUK = 0; Movement speed -300
@@ -60,11 +66,17 @@ SC_BLIND	()
 
 SC_BLEEDING	(SI_BLEEDING)
 	desc: HP Regeneration is disabled; SP Regeneration is disabled; Lose HP overtime
-	val1:
+	val1: Skill Level
+	val2: Caster's object ID (for mob_log_damage)
+	val3:
+	val4: Tick
 
 SC_DPOISON	()
 	desc: DEF -25%; if HP>25% lose 10/15% HP/sec
-	val1:
+	val1: Skill Level
+	val2: Caster's object ID (for mob_log_damage)
+	val3: Tick
+	val4: HP Damage
 
 SC_PROVOKE	(SI_PROVOKE)
 	desc: Decrease DEF by (5+(5*Skill Lv))%; Increase ATK by (2+(3*Skill lv))%
@@ -752,8 +764,10 @@ SC_SPIRIT	()
 
 SC_COMA	()
 	desc: Vanish HP to 1 and SP to 0
-	val1: (meaningless)
+	val1: Skill Level
 	val2: If 1 means do not remove SP
+	val3: Caster's object ID (for mob_log_damage)
+	val4:
 
 SC_INTRAVISION	()
 	desc:
@@ -1264,9 +1278,12 @@ SC_FEAR	()
 	desc:
 	val1:
 
-SC_BURNING	()
-	desc:
-	val1:
+SC_BURNING	(SI_BURNT)
+	desc: MDEF -25%; Deals fixed (1000 + 3%*MaxHP) damage every 3 seconds; Damage can not be reduced
+	val1: Skill Level
+	val2: 1000
+	val3: Caster's object ID (for mob_log_damage)
+	val4: Tick
 
 SC_FREEZING	()
 	desc:
@@ -1472,9 +1489,12 @@ SC_VENOMIMPRESS	()
 	desc:
 	val1:
 
-SC_POISONINGWEAPON	()
-	desc:
-	val1:
+SC_POISONINGWEAPON	(SI_POISONINGWEAPON)
+	desc: Coat the user's equipped weapon with a new poison temporarily, which grants a chance of leaving the target infected with the current poison while physically attacking.
+	val1: GC_WEAPONRESEARCH Skill Level
+	val2: Poison Type
+	val3: Success Rate
+	val4: Caster's object ID (for mob_log_damage)
 
 SC_WEAPONBLOCKING	()
 	desc:
@@ -1496,37 +1516,61 @@ SC_ROLLINGCUTTER	()
 	desc:
 	val1:
 
-SC_TOXIN	()
-	desc:
-	val1:
+SC_TOXIN	(SI_TOXIN)
+	desc: Inflict damage, which causes the affected entity to flinch every 10 seconds; This will interrupt the skill casting, even if protected against it
+	val1: GC_WEAPONRESEARCH Skill Level
+	val2: Caster's object ID (for mob_log_damage)
+	val3:
+	val4: Tick
 
-SC_PARALYSE	()
-	desc:
-	val1:
+SC_PARALYSE	(SI_PARALYSE)
+	desc: Decrease both ASPD and Flee Rate by 10% and halve Movement Speed, which does not stack with Decrease AGI, Quagmire, Marsh Of Abyss or Freezing status
+	val1: GC_WEAPONRESEARCH Skill Level
+	val2:
+	val3:
+	val4: Tick
 
 SC_VENOMBLEED	(SI_VENOMBLEED)
-	desc:
-	val1:
-
-SC_MAGICMUSHROOM	()
-	desc:
-	val1:
-
-SC_DEATHHURT	()
-	desc:
-	val1:
-
-SC_PYREXIA	()
-	desc:
-	val1:
+	desc: Decrease Max HP by 15%
+	val1: GC_WEAPONRESEARCH Skill Level
+	val2:
+	val3:
+	val4: Tick
+
+SC_MAGICMUSHROOM	(SI_MAGICMUSHROOM)
+	desc: Force the affected entity to use /heh emote, to randomly use skills and drain 3% of Max HP every 4 seconds
+	val1: GC_WEAPONRESEARCH Skill Level
+	val2: Caster's object ID (for mob_log_damage)
+	val3:
+	val4: Tick
+
+SC_DEATHHURT	(SI_DEATHHURT)
+	desc: Drop the healing effectiveness by 20%; This effect stacks with Critical Wounds
+	val1: GC_WEAPONRESEARCH Skill Level
+	val2:
+	val3:
+	val4: Tick
 
-SC_OBLIVIONCURSE	()
-	desc:
-	val1:
+SC_PYREXIA	(SI_PYREXIA)
+	desc: Cause Blind and Hallucination statuses; If the affected entity takes damage while under the effects of this poison, it will remain in flinching motion, which will interrupt the skill casting
+	val1: GC_WEAPONRESEARCH Skill Level
+	val2:
+	val3:
+	val4: Tick
 
-SC_LEECHESEND	()
-	desc:
-	val1:
+SC_OBLIVIONCURSE	(SI_OBLIVIONCURSE)
+	desc: Force the affected entity to use /? emote, block SP Recovery and cause Oblivion status; There is a chance (100% - (Target INT * 0.8)%) of being inflicted, with a minimum of 5%
+	val1: GC_WEAPONRESEARCH Skill Level
+	val2:
+	val3:
+	val4: Tick
+
+SC_LEECHESEND	(SI_LEECHESEND)
+	desc: Drain (Target VIT * (SkillLv - 3)) + (Target HP / 100) HP each second
+	val1: GC_WEAPONRESEARCH Skill Level
+	val2: Caster's object ID (for mob_log_damage)
+	val3:
+	val4: Tick
 
 SC_REFLECTDAMAGE	()
 	desc:

+ 1 - 1
src/map/battle.c

@@ -1443,7 +1443,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 		if( sc->data[SC_POISONINGWEAPON]
 			&& ((flag&BF_WEAPON) && (!skill_id || skill_id == GC_VENOMPRESSURE)) //check skill type poison_smoke is a unit
 			&& (damage > 0 && rnd()%100 < sc->data[SC_POISONINGWEAPON]->val3 )) //did some damage and chance ok (why no additional effect ??)
-			sc_start(src,bl,(enum sc_type)sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1));
+			sc_start2(src,bl,(enum sc_type)sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,sc->data[SC_POISONINGWEAPON]->val4,skill_get_time2(GC_POISONINGWEAPON, 1));
 
 		if( sc->data[SC__DEADLYINFECT] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 )
 			status_change_spread(src, bl, 0);

+ 20 - 18
src/map/skill.c

@@ -1688,7 +1688,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 		break;
 
 	case RL_MASS_SPIRAL:
-		sc_start(src,bl,SC_BLEEDING,10 * skill_lv + rnd()%50,skill_lv,skill_get_time2(skill_id,skill_lv)); //(custom)
+		sc_start2(src,bl,SC_BLEEDING,10 * skill_lv + rnd()%50,skill_lv,src->id,skill_get_time2(skill_id,skill_lv)); //(custom)
 		break;
 	case RL_SLUGSHOT:
 		if (bl->type != BL_PC)
@@ -6949,7 +6949,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				break;
 			}
 			if (sc_start4(src,bl,SC_STONE,(skill_lv*4+20)+brate,
-				skill_lv, 0, 0, skill_get_time(skill_id, skill_lv),
+				skill_lv, src->id, 0, skill_get_time(skill_id, skill_lv),
 				skill_get_time2(skill_id,skill_lv)))
 					clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
 			else if(sd) {
@@ -8208,13 +8208,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				case 7:	// stop freeze or stoned
 					{
 						enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE };
-						sc_start(src,bl,sc[rnd()%3],100,skill_lv,skill_get_time2(skill_id,skill_lv));
+						uint8 rand_eff = rnd()%3;
+
+						sc_start2(src,bl,sc[rand_eff],100,skill_lv,(rand_eff == 2 ? src->id : 0),skill_get_time2(skill_id,skill_lv));
 					}
 					break;
 				case 8:	// curse coma and poison
-					sc_start(src,bl,SC_COMA,100,skill_lv,skill_get_time2(skill_id,skill_lv));
+					status_change_start(src, bl, SC_COMA, 100, skill_lv, 0, src->id, 0, 0, SCSTART_NONE);
 					sc_start(src,bl,SC_CURSE,100,skill_lv,skill_get_time2(skill_id,skill_lv));
-					sc_start(src,bl,SC_POISON,100,skill_lv,skill_get_time2(skill_id,skill_lv));
+					sc_start2(src,bl,SC_POISON,100,skill_lv,src->id,skill_get_time2(skill_id,skill_lv));
 					break;
 				case 9:	// confusion
 					sc_start(src,bl,SC_CONFUSION,100,skill_lv,skill_get_time2(skill_id,skill_lv));
@@ -9103,13 +9105,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 			if( tsc && tsc->data[SC_STONE] )
 				status_change_end(bl,SC_STONE,INVALID_TIMER);
 			else
-				status_change_start(src,bl,SC_STONE,10000,skill_lv,0,0,1000,skill_get_time(skill_id, skill_lv),SCSTART_NOTICKDEF);
+				status_change_start(src,bl,SC_STONE,10000,skill_lv,src->id,0,1000,skill_get_time(skill_id, skill_lv),SCSTART_NOTICKDEF);
 		} else {
 			int rate = 45 + 5 * skill_lv + ( sd? sd->status.job_level : 50 ) / 4;
 			// IroWiki says Rate should be reduced by target stats, but currently unknown
 			if( rnd()%100 < rate ) { // Success on First Target
 				if( !tsc->data[SC_STONE] )
-					rate = status_change_start(src,bl,SC_STONE,10000,skill_lv,0,0,1000,skill_get_time(skill_id, skill_lv),SCSTART_NOTICKDEF);
+					rate = status_change_start(src,bl,SC_STONE,10000,skill_lv,src->id,0,1000,skill_get_time(skill_id, skill_lv),SCSTART_NOTICKDEF);
 				else {
 					rate = 1;
 					status_change_end(bl,SC_STONE,INVALID_TIMER);
@@ -13365,7 +13367,7 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns
 						sc_start(ss, bl,SC_BLIND,100,1,time);
 						break;
 					case 3: // Poison
-						sc_start(ss, bl,SC_POISON,100,1,time);
+						sc_start2(ss, bl,SC_POISON,100,1,ss->id,time);
 						break;
 					case 4: // Level 10 Provoke
 						sc_start(ss, bl,SC_PROVOKE,100,10,time);
@@ -13509,7 +13511,7 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns
 			switch( sg->val2 ) {
 				case 1:
 				default:
-					sc_start(ss, bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv));
+					sc_start4(ss, bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, 1000, ss->id, 0, skill_get_time2(sg->skill_id, sg->skill_lv));
 					skill_attack(skill_get_type(skill_id), ss, &unit->bl, bl, sg->skill_id, sg->skill_lv + 10 * sg->val2, tick, 0);
 					break;
 			}
@@ -13615,15 +13617,15 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns
 					case UNT_ZENKAI_LAND:
 						switch (rnd()%2 + 1) {
 							case 1:
-								sc_start(ss, bl, SC_STONE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv));
+								sc_start2(ss, bl, SC_STONE, sg->val1*5, sg->skill_lv, ss->id, skill_get_time2(sg->skill_id, sg->skill_lv));
 								break;
 							case 2:
-								sc_start(ss, bl, SC_POISON, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv));
+								sc_start2(ss, bl, SC_POISON, sg->val1*5, sg->skill_lv, ss->id, skill_get_time2(sg->skill_id, sg->skill_lv));
 								break;
 						}
 						break;
 					case UNT_ZENKAI_FIRE:
-						sc_start(ss, bl, SC_BURNING, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv));
+						sc_start4(ss, bl, SC_BURNING, sg->val1*5, sg->skill_lv, 1000, ss->id, 0, skill_get_time2(sg->skill_id, sg->skill_lv));
 						break;
 					case UNT_ZENKAI_WIND:
 						switch (rnd()%3 + 1) {
@@ -16937,7 +16939,7 @@ static int skill_trap_splash(struct block_list *bl, va_list ap)
 			break;
 		case UNT_GROUNDDRIFT_POISON:
 			if(skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1))
-				sc_start(ss,bl,SC_POISON,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv));
+				sc_start2(ss,bl,SC_POISON,5,sg->skill_lv,ss->id,skill_get_time2(sg->skill_id, sg->skill_lv));
 			break;
 		case UNT_GROUNDDRIFT_WATER:
 			if(skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1))
@@ -18943,7 +18945,7 @@ bool skill_arrow_create(struct map_session_data *sd, unsigned short nameid)
 int skill_poisoningweapon(struct map_session_data *sd, unsigned short nameid)
 {
 	sc_type type;
-	int chance, i;
+	int chance, i, val4 = 0;
 	//uint16 msg = 1443; //Official is using msgstringtable.txt
 	char output[CHAT_SIZE_MAX];
 	const char *msg;
@@ -18959,10 +18961,10 @@ int skill_poisoningweapon(struct map_session_data *sd, unsigned short nameid)
 		case ITEMID_PARALYSE:      type = SC_PARALYSE;      /*msg = 1444;*/ msg = "Paralyze"; break;
 		case ITEMID_PYREXIA:       type = SC_PYREXIA;		/*msg = 1448;*/ msg = "Pyrexia"; break;
 		case ITEMID_DEATHHURT:     type = SC_DEATHHURT;     /*msg = 1447;*/ msg = "Deathhurt"; break;
-		case ITEMID_LEECHESEND:    type = SC_LEECHESEND;    /*msg = 1450;*/ msg = "Leech End"; break;
+		case ITEMID_LEECHESEND:    type = SC_LEECHESEND;    /*msg = 1450;*/ msg = "Leech End"; val4 = sd->bl.id; break;
 		case ITEMID_VENOMBLEED:    type = SC_VENOMBLEED;    /*msg = 1445;*/ msg = "Venom Bleed"; break;
-		case ITEMID_TOXIN:         type = SC_TOXIN;         /*msg = 1443;*/ msg = "Toxin"; break;
-		case ITEMID_MAGICMUSHROOM: type = SC_MAGICMUSHROOM; /*msg = 1446;*/ msg = "Magic Mushroom"; break;
+		case ITEMID_TOXIN:         type = SC_TOXIN;         /*msg = 1443;*/ msg = "Toxin"; val4 = sd->bl.id; break;
+		case ITEMID_MAGICMUSHROOM: type = SC_MAGICMUSHROOM; /*msg = 1446;*/ msg = "Magic Mushroom"; val4 = sd->bl.id; break;
 		case ITEMID_OBLIVIONCURSE: type = SC_OBLIVIONCURSE; /*msg = 1449;*/ msg = "Oblivion Curse"; break;
 		default:
 			clif_skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0);
@@ -18971,7 +18973,7 @@ int skill_poisoningweapon(struct map_session_data *sd, unsigned short nameid)
 	
 	chance = 2 + 2 * sd->menuskill_val; // 2 + 2 * skill_lv
 	sc_start4(&sd->bl,&sd->bl, SC_POISONINGWEAPON, 100, pc_checkskill(sd, GC_RESEARCHNEWPOISON), //in Aegis it store the level of GC_RESEARCHNEWPOISON in val1
-		type, chance, 0, skill_get_time(GC_POISONINGWEAPON, sd->menuskill_val));
+		type, chance, val4, skill_get_time(GC_POISONINGWEAPON, sd->menuskill_val));
 
 	sprintf(output, msg_txt(sd,721), msg);
 	clif_colormes(sd->fd,color_table[COLOR_WHITE],output);

+ 30 - 2
src/map/status.c

@@ -9688,7 +9688,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 				default: rand_eff = SC_POISON; break;
 			}
 			val2 = 10 * val1; // Crit and Flee2 Reduction
-			status_change_start(src,bl,rand_eff,10000,val1,0,0,0,tick,SCSTART_NOTICKDEF|SCSTART_NORATEDEF);
+			status_change_start(src,bl,rand_eff,10000,val1,0,(rand_eff == SC_POISON ? src->id : 0),0,tick,SCSTART_NOTICKDEF|SCSTART_NORATEDEF);
 			break;
 		}
 		case SC__WEAKNESS:
@@ -11718,8 +11718,15 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			return 0;
 		}
 		if(--(sce->val3) > 0) {
-			if(++(sce->val4)%5 == 0 && status->hp > status->max_hp/4)
+			if(++(sce->val4)%5 == 0 && status->hp > status->max_hp/4) {
+				if (sce->val2 && bl->type == BL_MOB) {
+					struct block_list *src = map_id2bl(sce->val2);
+
+					if (src)
+						mob_log_damage((TBL_MOB*)bl, src, apply_rate(status->hp, 1));
+				}
 				status_percent_damage(NULL, bl, 1, 0, false);
+			}
 			sc_timer_next(1000+tick,status_change_timer, bl->id, data );
 			return 0;
 		}
@@ -11959,6 +11966,12 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		if( --(sce->val4) >= 0 ) {
 			int damage = status->vit * (sce->val1 - 3) + status->max_hp / 100; // {Target VIT x (New Poison Research Skill Level - 3)} + (Target HP/100)
 
+			if (sce->val2 && bl->type == BL_MOB) {
+				struct block_list *src2 = map_id2bl(sce->val2);
+
+				if (src2)
+					mob_log_damage((TBL_MOB*)bl, src2, damage);
+			}
 			map_freeblock_lock();
 			status_damage(bl, bl, damage, 0, clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,DMG_NORMAL,0), 0);
 			unit_skillcastcancel(bl, 2);
@@ -11984,6 +11997,13 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				map_freeblock_unlock();
 			}
 
+			if (sce->val2 && bl->type == BL_MOB) {
+				struct block_list *src2 = map_id2bl(sce->val2);
+
+				if (src2)
+					mob_log_damage((TBL_MOB*)bl, src2, damage);
+			}
+
 			if( !flag ) { // Random Skill Cast
 				if (skill_magicmushroom_count && sd && !pc_issit(sd)) { // Can't cast if sit
 					int mushroom_skill_id = 0, checked = 0, checked_max = MAX_SKILL_MAGICMUSHROOM_DB * 3;
@@ -12020,6 +12040,12 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 	case SC_TOXIN:
 		if( --(sce->val4) >= 0 ) { // Damage is every 10 seconds including 3%sp drain.
+			if (sce->val2 && bl->type == BL_MOB) {
+				struct block_list *src2 = map_id2bl(sce->val2);
+
+				if (src2)
+					mob_log_damage((TBL_MOB*)bl, src2, 1);
+			}
 			map_freeblock_lock();
 			clif_damage(bl,bl,tick,status_get_amotion(bl),1,1,0,DMG_NORMAL,0);
 			status_damage(NULL, bl, 1, status->max_sp * 3 / 100, 0, 0); // Cancel dmg only if cancelable
@@ -12070,6 +12096,8 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			struct block_list *src = map_id2bl(sce->val3);
 			int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP)
 
+			if (src && bl->type == BL_MOB)
+				mob_log_damage((TBL_MOB*)bl, src, damage);
 			map_freeblock_lock();
 			clif_damage(bl,bl,tick,0,0,damage,1,DMG_MULTI_HIT_ENDURE,0); // Damage is like endure effect with no walk delay
 			status_damage(src, bl, damage, 0, 0, 1);