Jump to content
  • 0

Sonic Blow / Arrow Vulcan animations on newer clients


ckx_

Question


  • Group:  Members
  • Topic Count:  6
  • Topics Per Day:  0.01
  • Content Count:  12
  • Reputation:   1
  • Joined:  06/29/22
  • Last Seen:  

I'd like to add the old Sonic Blow / Arrow Vulcan animations back to newer clients. Does anyone know where to begin on this? I believe it's a client-side change, but I am not entirely positive.

Background: I'm working on a pre-renewal server that uses a lot of newer renewal client features (market shops, randomopts, achievements, etc). So far I don't have any issues other than these skill animations being removed. Removal happened in kRO on 2018/12/19 (patch notes).

There are some old threads on the forums about this, but they're all dead ends. I'll link them anyway: Ref1, Ref2. The Herc Forums also have a thread for this.

If anyone has any info on this, let me know. Likewise I'll update the thread if I get anywhere myself.

Link to comment
Share on other sites

3 answers to this question

Recommended Posts

  • 0

  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  21
  • Reputation:   2
  • Joined:  04/19/14
  • Last Seen:  

Could it be that Body Relocation (Skill ID# 264, iRO Name: Snap) is also without animation?

Edited by iJohn
I was too brief in words...
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  6
  • Topics Per Day:  0.01
  • Content Count:  12
  • Reputation:   1
  • Joined:  06/29/22
  • Last Seen:  

I hackily solved this on the source side. A side effect of my solution is that it shows extra damage numbers (but the multihit total is still correct, and the extra damage numbers are visual only). My solution:

In the "display damage" switch block in skill_attack:

		case CG_ARROWVULCAN:
		case AS_SONICBLOW: {
			dmg.dmotion = clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag & SD_LEVEL ? -1 : skill_lv, dmg_type, dmg.crit);
			struct unit_data* ud = unit_bl2ud(dsrc);
			if (ud) {
				ud->dmg = dmg;
				ud->sb_animation = 0;
				ud->sb_target = bl->id;
				ud->sb_timer = add_timer(gettick()+20, skill_sonicblow_animation, dsrc->id, 0);
			}
			break;
		}

↑ This plays the default SB animation, sets up some data, then adds a new timer function.

Here's the code for the timer_func it adds:

TIMER_FUNC(skill_sonicblow_animation){
	struct block_list *target, *src;
	struct unit_data *ud;
	struct status_change *sc = NULL;
	int flag = 0;

	src = map_id2bl(id);
	if(src == NULL) {
		return 0;
	}

	ud = unit_bl2ud(src);
	if(ud == NULL) {
		return 0;
	}
	target = map_id2bl(ud->sb_target);

	if (!target || ud->sb_animation >= ud->dmg.div_ || ud->sb_timer == INVALID_TIMER) {
		ud->sb_animation = 0;
		ud->sb_timer = INVALID_TIMER;
		return 0;
	}
	int div_ = ud->dmg.div_;
	if (div_ < 1) {
		div_ = 1;
	}
	t_tick canmove = tick_diff(ud->canmove_tick, tick);
	canmove /= (div_-ud->sb_animation);
	if (canmove > 175) {
		canmove = 175;
	}
	clif_damage(src, target, tick, 125, ud->dmg.dmotion/div_, ud->dmg.damage/div_, div_, DMG_NORMAL, ud->dmg.damage2/div_, ud->dmg.isspdamage);
	ud->sb_animation++;
	ud->sb_timer = add_timer(tick+canmove, skill_sonicblow_animation, id, data);
	return 1;
}

↑ This just sets up some damage then calls clif_damage, and sets up another timer func to keep it going until sb_animation reaches skill's div count. To be clear this will work for any multiattack that you want to have spam auto attacks, not just SB. Sorry for the naming scheme.

The extra damage numbers are customizable by changing what you pass to the clif_damage call. You can set it to all 1s, or all misses, or anything else. Unfortunately I never found a way to implement this without the extra numbers—I'm not sure how to force the client to arbitrarily play an auto attack animation with no corresponding damage numbers. If someone knows, I'd be interested.

and in the unit_data struct:

	int sb_animation, sb_target, sb_timer; // hacky sb animation fix

↑ just some state data, ud seemed like the best place to put it so that it works on both mobs and players.

This produces a sonic blow like in the attached file. also viewable here: https://mikomiko.org/files/Screencast_20240512_005716.webm

It's not perfect but I'm happy enough with it for now.

Edited by ckx_
added example webm
  • MVP 1
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  125
  • Topics Per Day:  0.03
  • Content Count:  651
  • Reputation:   83
  • Joined:  04/07/14
  • Last Seen:  

12 hours ago, ckx_ said:

I hackily solved this on the source side. A side effect of my solution is that it shows extra damage numbers (but the multihit total is still correct, and the extra damage numbers are visual only). My solution:

In the "display damage" switch block in skill_attack:

		case CG_ARROWVULCAN:
		case AS_SONICBLOW: {
			dmg.dmotion = clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag & SD_LEVEL ? -1 : skill_lv, dmg_type, dmg.crit);
			struct unit_data* ud = unit_bl2ud(dsrc);
			if (ud) {
				ud->dmg = dmg;
				ud->sb_animation = 0;
				ud->sb_target = bl->id;
				ud->sb_timer = add_timer(gettick()+20, skill_sonicblow_animation, dsrc->id, 0);
			}
			break;
		}

↑ This plays the default SB animation, sets up some data, then adds a new timer function.

Here's the code for the timer_func it adds:

TIMER_FUNC(skill_sonicblow_animation){
	struct block_list *target, *src;
	struct unit_data *ud;
	struct status_change *sc = NULL;
	int flag = 0;

	src = map_id2bl(id);
	if(src == NULL) {
		return 0;
	}

	ud = unit_bl2ud(src);
	if(ud == NULL) {
		return 0;
	}
	target = map_id2bl(ud->sb_target);

	if (!target || ud->sb_animation >= ud->dmg.div_ || ud->sb_timer == INVALID_TIMER) {
		ud->sb_animation = 0;
		ud->sb_timer = INVALID_TIMER;
		return 0;
	}
	int div_ = ud->dmg.div_;
	if (div_ < 1) {
		div_ = 1;
	}
	t_tick canmove = tick_diff(ud->canmove_tick, tick);
	canmove /= (div_-ud->sb_animation);
	if (canmove > 175) {
		canmove = 175;
	}
	clif_damage(src, target, tick, 125, ud->dmg.dmotion/div_, ud->dmg.damage/div_, div_, DMG_NORMAL, ud->dmg.damage2/div_, ud->dmg.isspdamage);
	ud->sb_animation++;
	ud->sb_timer = add_timer(tick+canmove, skill_sonicblow_animation, id, data);
	return 1;
}

↑ This just sets up some damage then calls clif_damage, and sets up another timer func to keep it going until sb_animation reaches skill's div count. To be clear this will work for any multiattack that you want to have spam auto attacks, not just SB. Sorry for the naming scheme.

The extra damage numbers are customizable by changing what you pass to the clif_damage call. You can set it to all 1s, or all misses, or anything else. Unfortunately I never found a way to implement this without the extra numbers—I'm not sure how to force the client to arbitrarily play an auto attack animation with no corresponding damage numbers. If someone knows, I'd be interested.

and in the unit_data struct:

	int sb_animation, sb_target, sb_timer; // hacky sb animation fix

↑ just some state data, ud seemed like the best place to put it so that it works on both mobs and players.

This produces a sonic blow like in the attached file. also viewable here: https://mikomiko.org/files/Screencast_20240512_005716.webm

It's not perfect but I'm happy enough with it for now.

 

This is nice to those who are on 2019+ client. Keep it up!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...