Where is FIRST attack being called from?

Posted by Robert Powell on Wed 05 Dec 2007 10:41 AM — 6 posts, 24,724 views.

Australia #0
While trying to make some changes to the spammyness of how combat is handled in smaug, i came across an issue in finding where the so called first attack is being called, with the aim of trying to acheive something like below.


You barely scratch a newly created first mob. [0] strikes, doing [1] damage
You barely scratch a newly created first mob. [2] strikes, doing [10] damage


It would always display the first attack as it apears there, 0 hits and 1 damage. In multi_hit there is no mention of the first attack, only dual and then 2nd attack onwards, so im guessing that first attack is being sent out from somewhere else, do_kill only calls multi_hit, so im at a loss for what is going on.


ch_ret multi_hit ( CHAR_DATA * ch, CHAR_DATA * victim, int dt )
{
	int schance;
	int dual_bonus;
	ch_ret retcode;

	/*
	 * add timer to pkillers
	 */
	if ( !IS_NPC ( ch ) && !IS_NPC ( victim ) )
	{
		if ( xIS_SET ( ch->act, PLR_NICE ) )
			return rNONE;
		add_timer ( ch, TIMER_RECENTFIGHT, 11, NULL, 0 );
		add_timer ( victim, TIMER_RECENTFIGHT, 11, NULL, 0 );
	}

	if ( is_attack_supressed ( ch ) )
		return rNONE;

	if ( IS_NPC ( ch ) && xIS_SET ( ch->act, ACT_NOATTACK ) )
		return rNONE;

	if ( ( retcode = one_hit ( ch, victim, dt ) ) != rNONE )
		return retcode;

	if ( who_fighting ( ch ) != victim || dt == gsn_backstab || dt == gsn_circle )
		return rNONE;

	/*
	 * Very high chance of hitting compared to chance of going berserk
	 */
	/*
	 * 40% or higher is always hit.. don't learn anything here though.
	 */
	/*
	 * -- Altrag
	 */
	schance = IS_NPC ( ch ) ? 100 : ( LEARNED ( ch, gsn_berserk ) * 5 / 2 );
	if ( IS_AFFECTED ( ch, AFF_BERSERK ) && number_percent( ) < schance )
		if ( ( retcode = one_hit ( ch, victim, dt ) ) != rNONE || who_fighting ( ch ) != victim )
			return retcode;

	if ( get_eq_char ( ch, WEAR_DUAL_WIELD ) )
	{
		dual_bonus = IS_NPC ( ch ) ? ( ch->level / 10 ) : ( LEARNED ( ch, gsn_dual_wield ) / 10 );
		schance = IS_NPC ( ch ) ? ch->level : LEARNED ( ch, gsn_dual_wield );
		if ( number_percent( ) < schance )
		{
			learn_from_success ( ch, gsn_dual_wield );
			retcode = one_hit ( ch, victim, dt );
			if ( retcode != rNONE || who_fighting ( ch ) != victim )
				return retcode;
		}
		else
			learn_from_failure ( ch, gsn_dual_wield );
	}
	else
		dual_bonus = 0;

	if ( ch->move < 10 )
		dual_bonus = -20;

	/*
	 * NPC predetermined number of attacks        -Thoric
	 */
	if ( IS_NPC ( ch ) && ch->numattacks > 0 )
	{
		for ( schance = 0; schance < 1; schance++ )
		{
			retcode = one_hit ( ch, victim, dt );
			if ( retcode != rNONE || who_fighting ( ch ) != victim )
				return retcode;
		}
		return retcode;
	}

	schance = IS_NPC ( ch ) ? ch->level : ( int ) ( ( LEARNED ( ch, gsn_second_attack ) + dual_bonus ) / 1.5 );
	if ( number_percent( ) < schance )
	{
		learn_from_success ( ch, gsn_second_attack );
		retcode = one_hit ( ch, victim, dt );
		if ( retcode != rNONE || who_fighting ( ch ) != victim )
			return retcode;
	}
	else
		learn_from_failure ( ch, gsn_second_attack );

	schance = IS_NPC ( ch ) ? ch->level : ( int ) ( ( LEARNED ( ch, gsn_third_attack ) + ( dual_bonus * 1.5 ) ) / 2 );
	if ( number_percent( ) < schance )
	{
		learn_from_success ( ch, gsn_third_attack );
		retcode = one_hit ( ch, victim, dt );
		if ( retcode != rNONE || who_fighting ( ch ) != victim )
			return retcode;
	}
	else
		learn_from_failure ( ch, gsn_third_attack );

	schance = IS_NPC ( ch ) ? ch->level : ( int ) ( ( LEARNED ( ch, gsn_fourth_attack ) + ( dual_bonus * 2 ) ) / 3 );
	if ( number_percent( ) < schance )
	{
		learn_from_success ( ch, gsn_fourth_attack );
		retcode = one_hit ( ch, victim, dt );
		if ( retcode != rNONE || who_fighting ( ch ) != victim )
			return retcode;
	}
	else
		learn_from_failure ( ch, gsn_fourth_attack );

	schance = IS_NPC ( ch ) ? ch->level : ( int ) ( ( LEARNED ( ch, gsn_fifth_attack ) + ( dual_bonus * 3 ) ) / 4 );
	if ( number_percent( ) < schance )
	{
		learn_from_success ( ch, gsn_fifth_attack );
		retcode = one_hit ( ch, victim, dt );
		if ( retcode != rNONE || who_fighting ( ch ) != victim )
			return retcode;
	}


	retcode = rNONE;

	schance = IS_NPC ( ch ) ? ( int ) ( ch->level / 2 ) : 0;
	if ( number_percent( ) < schance )
		retcode = one_hit ( ch, victim, dt );

	if ( retcode == rNONE )
	{
		int move;

		if ( !IS_AFFECTED ( ch, AFF_FLYING ) && !IS_AFFECTED ( ch, AFF_FLOATING ) )
			move = encumbrance ( ch, movement_loss[UMIN ( SECT_MAX - 1, ch->in_room->sector_type ) ] );
		else
			move = encumbrance ( ch, 1 );
		if ( ch->move )
			ch->move = UMAX ( 0, ch->move - move );

	}
	return retcode;
}


Anyone able to point me in the right direction as to whats going on here,

Thanks in advance, Oh i should mention that the above multi is from stock, in the one i had to make it less spammy i removes all the retcode == onehits and had a counter incremented instead, i hadnt actually got to working out how to calc the damage up on each successfull hit. But it shouldnt matter much, first attack is still not being called from within multi_hit that i can see anyway.

Robert.
Amended on Wed 05 Dec 2007 10:51 AM by Robert Powell
USA #1
every autonomous attack is usually called from violence_update() in fight.c, but you were on the right path, the first call to multi_hit() from do_kill sets the fight in motion, the part that will be the first attack is this in multi_hit()


	if ( ( retcode = one_hit ( ch, victim, dt ) ) != rNONE )
		return retcode;


that is from smaug fuss 1.8, not too sure what you'll see but it will be something like that. anyways, that is the actual attack, since its essentially the first thing in multi_hit() except for first ifchecks, do_kill calling it is the first attack. now exactly why would the first thing seen be that there have been 0 strikes yet 1 damage has been inflicted?
Amended on Wed 05 Dec 2007 12:53 PM by Gohan_TheDragonball
Australia #2
Im not sure why damage would be 1, but the reason why strikes is 0 i because i set the counter to 0 at the start of multi_hit prior to

if ( ( retcode = one_hit ( ch, victim, dt ) ) != rNONE )
		return retcode;


With this in mind im going to have another crack at this and see what i can come up with.

Thanks.
Australia #3
Ok, i have it working somewhat now like i would like it, it would seem that there are other conditions that allow for extra attacks per round, i will have to go through all the calls to multi_hit and see whats going on.


You barely scratch a newly created first mob. [4, strikes] [5, damage]
You dodge a newly created first mob's attack.

<27467hp 652m 1263mv Enemy: [+++++++++ ]> <#5000> 

You barely scratch a newly created first mob. [1, strikes] [7, damage]
You dodge a newly created first mob's attack.

<27467hp 652m 1261mv Enemy: [++++++++++]> <#5000> 

You hit a newly created first mob's hand!
You barely scratch a newly created first mob. [3, strikes] [12, damage]
You barely scratch a newly created first mob. [3, strikes] [33, damage]
A newly created first mob brushes you. [1, strikes] [117, damage]

<27340hp 652m 1259mv Enemy: [+++++++++ ]> <#5000> 

You barely scratch a newly created first mob. [2, strikes] [9, damage]
A newly created first mob brushes you. [1, strikes] [117, damage]
USA #4
whats this?
Quote:
You hit a newly created first mob's hand!


and i know this is merely cosmetic but

Quote:
A newly created first mob brushes you. [1, strikes] [117, damage]


1 is never plural
Australia #5
The first part is a landed hit that did no damage, and yes the 2nd part i agree with 1 is never plural, and something that i need to address once i have this working correctly.

And yes they way i have gone about this is rather "haxors" but it works and serves its purpose, even if it is not the most elaborate combat system and now even more simplistic then what was already there.

If i get time tomorrow i will post the code.