浏览代码

Gravitational Field full official implementation and minor fixes
- Gravitational Field will now work as official servers (bugreport:4897)
* Fixed range of Ganbantein (16->14) and Gravitational Field (9->14)
* Gravitational Field never misses and can hit hidden targets
* Similar to Pressure the damage can not be increased or decreased by any means, it even hits GTB users and users protected by Devotion/Sacrifice
* Renewal damage is now 400+100*level every 500ms (200+200*level every 1000ms in pre-renewal)
* You can no longer do normal attacks while the skill is active
* You now can use skills while the skill is active, however, other skills are unable to deal any damage as long as Gravitational Field is active
* Added the possibility to link different skill unit groups together; if a skill unit group gets deleted, the linked skill unit groups are deleted as well; this was needed because when being hit, all Gravitational Fields of the person being hit need to be removed
* Gravitational Field can no longer overlap with itself
* Pressure and Gravitational Field will now be considered "physical normal attacks" and can consequently trigger Autospells; unlike manually cast spells, Autospells can deal damage while Gravitational Field is active
- Fixed that in renewal, weapons with a range of 2 and 3 did depend on DEX instead of STR (fixed #129)
* Special thanks to NovaRagnarok for the fix

Playtester 10 年之前
父节点
当前提交
861112b89b
共有 7 个文件被更改,包括 45 次插入13 次删除
  1. 2 2
      db/pre-re/skill_db.txt
  2. 2 2
      db/re/skill_db.txt
  3. 7 3
      src/map/battle.c
  4. 2 1
      src/map/pc.c
  5. 30 3
      src/map/skill.c
  6. 1 0
      src/map/skill.h
  7. 1 2
      src/map/status.c

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

@@ -699,8 +699,8 @@
 480,5,8,1,-1,0,0,5,5,no,0,0,0,weapon,0,0x20000,		PA_SHIELDCHAIN,Shield Chain
 481,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0,		HP_MANARECHARGE,Mana Recharge
 482,0,6,4,0,0x1,0,5,1,no,0,0,0,magic,0,0x0,		PF_DOUBLECASTING,Double Casting
-483,16,6,2,0,0x1,1:2:3:4:5,1,1,no,0,0,0,none,0,0x20,	HW_GANBANTEIN,Ganbantein
-484,9,6,2,2,0x91,0,5,1,yes,0,0x18000,0,misc,0,0x1030,		HW_GRAVITATION,Gravitation Field
+483,14,6,2,0,0x1,1:2:3:4:5,1,1,no,0,0,0,none,0,0x20,	HW_GANBANTEIN,Ganbantein
+484,14,6,2,2,0xD1,0,5,1,yes,0,0x18000,0,misc,0,0x11030,		HW_GRAVITATION,Gravitation Field
 485,-2,6,1,-1,0x8,0,10,1,no,0,0,0,weapon,0,0x4000,	WS_CARTTERMINATION,Cart Termination
 486,0,6,4,0,0x1,0,5,1,no,0,0,0,weapon,0,0x4000,		WS_OVERTHRUSTMAX,Maximum Power Thrust
 487,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x8,		CG_LONGINGFREEDOM,Longing for Freedom

+ 2 - 2
db/re/skill_db.txt

@@ -699,8 +699,8 @@
 480,5,8,1,-1,0,0,5,5,no,0,0,0,weapon,0,0x20000,		PA_SHIELDCHAIN,Shield Chain
 481,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0,		HP_MANARECHARGE,Mana Recharge
 482,0,6,4,0,0x1,0,5,1,no,0,0,0,magic,0,0x0,		PF_DOUBLECASTING,Double Casting
-483,16,6,2,0,0x1,1:2:3:4:5,1,1,no,0,0,0,none,0,0x20,	HW_GANBANTEIN,Ganbantein
-484,9,6,2,2,0x91,0,5,1,yes,0,0x18000,0,misc,0,0x1030,		HW_GRAVITATION,Gravitation Field
+483,14,6,2,0,0x1,1:2:3:4:5,1,1,no,0,0,0,none,0,0x20,	HW_GANBANTEIN,Ganbantein
+484,14,6,2,2,0xD1,0,5,1,yes,0,0x18000,0,misc,0,0x11030,		HW_GRAVITATION,Gravitation Field
 485,-2,6,1,-1,0x8,0,10,1,no,0,0,0,weapon,0,0x4000,	WS_CARTTERMINATION,Cart Termination
 486,0,6,4,0,0x1,0,5,1,no,0,0,0,weapon,0,0x4000,		WS_OVERTHRUSTMAX,Maximum Power Thrust
 487,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x8,		CG_LONGINGFREEDOM,Longing for Freedom

+ 7 - 3
src/map/battle.c

@@ -841,15 +841,15 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 	if( sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
 		return 1;
 
-	if (skill_id == PA_PRESSURE)
-		return damage; //This skill bypass everything else.
+	if (skill_id == PA_PRESSURE || skill_id == HW_GRAVITATION)
+		return damage; //These skills bypass everything else.
 
 	if( sc && sc->count ) { // SC_* that reduce damage to 0.
 		if( sc->data[SC_BASILICA] && !(status_get_mode(src)&MD_BOSS) ) {
 			d->dmg_lv = ATK_BLOCK;
 			return 0;
 		}
-		if( sc->data[SC_WHITEIMPRISON] && skill_id != HW_GRAVITATION ) { // Gravitation and Pressure do damage without removing the effect
+		if( sc->data[SC_WHITEIMPRISON] ) { // Gravitation and Pressure do damage without removing the effect
 			if( skill_id == MG_NAPALMBEAT ||
 				skill_id == MG_SOULSTRIKE ||
 				skill_id == WL_SOULEXPANSION ||
@@ -6244,7 +6244,11 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 #endif
 		break;
 	case HW_GRAVITATION:
+#ifdef RENEWAL
+		md.damage = 500+100*skill_lv;
+#else
 		md.damage = 200+200*skill_lv;
+#endif
 		md.dmotion = 0; //No flinch animation.
 		break;
 	case NPC_EVILLAND:

+ 2 - 1
src/map/pc.c

@@ -8468,7 +8468,8 @@ bool pc_can_attack( struct map_session_data *sd, int target_id ) {
 		sd->sc.data[SC_TRICKDEAD] ||
 		(sd->sc.data[SC_VOICEOFSIREN] && sd->sc.data[SC_VOICEOFSIREN]->val2 == target_id) ||
 		sd->sc.data[SC_BLADESTOP] ||
-		sd->sc.data[SC_DEEPSLEEP] )
+		sd->sc.data[SC_DEEPSLEEP] ||
+		(sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) )
 			return false;
 
 	return true;

+ 30 - 3
src/map/skill.c

@@ -1104,6 +1104,11 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 
 	case PA_PRESSURE:
 		status_percent_damage(src, bl, 0, 15+5*skill_lv, false);
+		//Fall through
+	case HW_GRAVITATION:
+		//Pressure and Gravitation can trigger physical autospells
+		attack_type |= BF_NORMAL;
+		attack_type |= BF_WEAPON;
 		break;
 
 	case RG_RAID:
@@ -2843,7 +2848,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 {
 	struct Damage dmg;
 	struct status_data *sstatus, *tstatus;
-	struct status_change *tsc;
+	struct status_change *sc, *tsc;
 	struct map_session_data *sd, *tsd;
 	int64 damage;
 	int8 rmdamage = 0;//magic reflected
@@ -2873,6 +2878,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 
 	sstatus = status_get_status_data(src);
 	tstatus = status_get_status_data(bl);
+	sc= status_get_sc(src);
 	tsc= status_get_sc(bl);
 	if (tsc && !tsc->count) tsc = NULL; //Don't need it.
 
@@ -2880,6 +2886,10 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 	if (tsc && tsc->data[SC_TRICKDEAD])
 		return 0;
 
+	//When Gravitational Field is active, damage can only be dealt by Gravitational Field and Autospells
+	if(sc && sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF && skill_id != HW_GRAVITATION && !sd->state.autocast)
+		return 0;
+
 	dmg = battle_calc_attack(attack_type,src,bl,skill_id,skill_lv,flag&0xFFF);
 
 	//Skotlex: Adjusted to the new system
@@ -3183,7 +3193,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 
 	// Instant damage
 	if( !dmg.amotion ) {
-		if( (!tsc || (!tsc->data[SC_DEVOTION] && skill_id != CR_REFLECTSHIELD)) && !shadow_flag )
+		if( (!tsc || (!tsc->data[SC_DEVOTION] && skill_id != CR_REFLECTSHIELD) || skill_id == HW_GRAVITATION) && !shadow_flag )
 			status_fix_damage(src,bl,damage,dmg.dmotion); //Deal damage before knockback to allow stuff like firewall+storm gust combo.
 		if( !status_isdead(bl) && additional_effects )
 			skill_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,dmg.dmg_lv,tick);
@@ -3206,7 +3216,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 			battle_delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion, additional_effects);
 	}
 
-	if( tsc && tsc->data[SC_DEVOTION] && skill_id != PA_PRESSURE ) {
+	if( tsc && tsc->data[SC_DEVOTION] && skill_id != PA_PRESSURE && skill_id != HW_GRAVITATION ) {
 		struct status_change_entry *sce = tsc->data[SC_DEVOTION];
 		struct block_list *d_bl = map_id2bl(sce->val1);
 
@@ -11883,6 +11893,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
 {
 	struct skill_unit_group *group;
 	int i, limit, val1 = 0, val2 = 0, val3 = 0;
+	int link_group_id = 0;
 	int target, interval, range, unit_flag, req_item = 0;
 	struct s_skill_unit_layout *layout;
 	struct map_session_data *sd;
@@ -12203,6 +12214,9 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
 			}
 		}
 		break;
+	case HW_GRAVITATION:
+		if(sc && sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF)
+			link_group_id = sc->data[SC_GRAVITATION]->val4;
 	}
 
 	// Init skill unit group
@@ -12210,6 +12224,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
 	group->val1 = val1;
 	group->val2 = val2;
 	group->val3 = val3;
+	group->link_group_id = link_group_id;
 	group->target_flag = target;
 	group->bl_flag = skill_get_unit_bl_target(skill_id);
 	group->state.ammo_consume = (sd && sd->state.arrow_atk && skill_id != GS_GROUNDDRIFT); //Store if this skill needs to consume ammo.
@@ -16518,6 +16533,7 @@ static int skill_cell_overlap(struct block_list *bl, va_list ap)
 			break;
 		case WZ_ICEWALL:
 		case HP_BASILICA:
+		case HW_GRAVITATION:
 			//These can't be placed on top of themselves (duration can't be refreshed)
 			if (unit->group->skill_id == skill_id)
 			{
@@ -17076,6 +17092,7 @@ struct skill_unit_group* skill_initunitgroup(struct block_list* src, int count,
 	group->guild_id   = status_get_guild_id(src);
 	group->bg_id      = bg_team_get_id(src);
 	group->group_id   = skill_get_new_group_id();
+	group->link_group_id = 0;
 	group->unit       = (struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
 	group->unit_count = count;
 	group->alive_count = 0;
@@ -17113,6 +17130,7 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
 	struct block_list* src;
 	struct unit_data *ud;
 	short i, j;
+	int link_group_id;
 
 	if( group == NULL ) {
 		ShowDebug("skill_delunitgroup: group is NULL (source=%s:%d, %s)! Please report this! (#3504)\n", file, line, func);
@@ -17228,6 +17246,9 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
 	group->group_id = 0;
 	group->unit_count = 0;
 
+	link_group_id = group->link_group_id;
+	group->link_group_id = 0;
+
 	// locate this group, swap with the last entry and delete it
 	ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == group );
 	ARR_FIND( i, MAX_SKILLUNITGROUP, j, ud->skillunit[j] == NULL );
@@ -17239,6 +17260,12 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
 	} else
 		ShowError("skill_delunitgroup: Group not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id);
 
+	if(link_group_id) {
+		struct skill_unit_group* group = skill_id2group(link_group_id);
+		if(group)
+			skill_delunitgroup(group);
+	}
+
 	return 1;
 }
 

+ 1 - 0
src/map/skill.h

@@ -233,6 +233,7 @@ struct skill_unit_group {
 	char *valstr; /// String value, used for HT_TALKIEBOX & RG_GRAFFITI
 	int unit_id; /// Unit ID (for client effect)
 	int group_id; /// Skill Group ID
+	int link_group_id; /// Linked group that should be deleted if this one is deleted
 	int unit_count, /// Number of unit at this group
 		alive_count; /// Number of alive unit
 	int item_id; /// Store item used.

+ 1 - 2
src/map/status.c

@@ -1842,7 +1842,6 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
 			(sc->data[SC_TRICKDEAD] && skill_id != NV_TRICKDEAD)
 			|| (sc->data[SC_AUTOCOUNTER] && !flag && skill_id)
 			|| (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF && skill_id != PA_GOSPEL)
-			|| (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF && flag != 2)
 		)
 			return false;
 
@@ -2162,7 +2161,7 @@ static unsigned short status_base_atk(const struct block_list *bl, const struct
 unsigned int status_weapon_atk(struct weapon_atk wa, struct status_data *status)
 {
 	float str = status->str;
-	if (wa.range > 1)
+	if (wa.range > 3)
 		str = status->dex;
 	// wa.at2 = refinement, wa.atk = base equip atk, wa.atk*str/200 = bonus str
 	return wa.atk + wa.atk2 + (int)(wa.atk * (str/200));