Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Bug Reports

Development::Bug Reports Post detailed bug reports and what you would like to see next in the emu here.

Reply
 
Thread Tools Display Modes
  #1  
Old 06-24-2009, 12:33 AM
Krugus
Sarnak
 
Join Date: Dec 2005
Location: the Void
Posts: 40
Default Throwing Weapons with charges: Visual Low Priority

Visual low priority item:


When you throw a weapon that has charges, it throws the weapon, delete the charge but there is nothing showing in your hand after the initial throw. You can still hit your Ranged attack button and throw it again thus deleting another charge etc but the weapon never shows back up visually in your left hand.

Now if you have two of those weapons. Put one in your range slot and the other in the ammo slot. After throwing it, its still in your off hand.

Weapons with no charges, that pulls the ammo from your inventory, has the same problem.

Stacked throwing Weapons do not have this problem (last i checked they didn't).

Am I correct this is code in special_attacks.cpp that handles the Throwing for players?

Code:
void Client::ThrowingAttack(Mob* other) { //old was 51
	//conditions to use an attack checked before we are called
	
	//make sure the attack and ranged timers are up
	//if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow
	if((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check())) {
		mlog(COMBAT__RANGED, "Throwing attack canceled. Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
		Message(0, "Error: Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
		return;
	}
		
	int ammo_slot = SLOT_RANGE;
	const ItemInst* RangeWeapon = m_inv[SLOT_RANGE];
	
	if (!RangeWeapon || !RangeWeapon->IsType(ItemClassCommon)) {
		mlog(COMBAT__RANGED, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(SLOT_RANGE), SLOT_RANGE);
		Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(SLOT_RANGE));
		return;
	}
	
	const Item_Struct* item = RangeWeapon->GetItem();
	if(item->ItemType != ItemTypeThrowing && item->ItemType != ItemTypeThrowingv2) {
		mlog(COMBAT__RANGED, "Ranged attack canceled. Ranged item %d is not a throwing weapon. type %d.", item->ItemType);
		Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(SLOT_RANGE));
		return;
	}
	
	mlog(COMBAT__RANGED, "Throwing %s (%d) at %s", item->Name, item->ID, target->GetName());
	
	if(RangeWeapon->GetCharges() == 1) {
		//first check ammo
		const ItemInst* AmmoItem = m_inv[SLOT_AMMO];
		if(AmmoItem != NULL && AmmoItem->GetID() == RangeWeapon->GetID()) {
			//more in the ammo slot, use it
			RangeWeapon = AmmoItem;
			ammo_slot = SLOT_AMMO;
			mlog(COMBAT__RANGED, "Using ammo from ammo slot, stack at slot %d. %d in stack.", ammo_slot, RangeWeapon->GetCharges());
		} else {
			//look through our inventory for more
			sint32 aslot = m_inv.HasItem(item->ID, 1, invWherePersonal);
			if(aslot != SLOT_INVALID) {
				//the item wont change, but the instance does, not that it matters
				ammo_slot = aslot;
				RangeWeapon = m_inv[aslot];
				mlog(COMBAT__RANGED, "Using ammo from inventory slot, stack at slot %d. %d in stack.", ammo_slot, RangeWeapon->GetCharges());
			}
		}
	}
	
	int range = item->Range +50/*Fudge it a little, client will let you hit something at 0 0 0 when you are at 205 0 0*/;
	mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", range);
	range *= range;
	if(DistNoRootNoZ(*target) > range) {
		mlog(COMBAT__RANGED, "Throwing attack out of range... client should catch this. (%f > %f).\n", DistNoRootNoZ(*target), range);
		//target is out of range, client does a message
		return;
	}
	else if(DistNoRootNoZ(*target) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){
		return;
	}

	if(!IsAttackAllowed(target) || 
		IsCasting() || 
		IsSitting() || 
		(DivineAura() && !GetGM()) ||
		IsStunned() ||
		IsMezzed() ||
		(GetAppearance() == eaDead)){
		return;
	}
	//send item animation, also does the throw animation
	SendItemAnimation(target, item, THROWING);

	
	// Hit?
	if (!target->CheckHitChance(this, THROWING, 13)) {
		mlog(COMBAT__RANGED, "Ranged attack missed %s.", target->GetName());
		target->Damage(this, 0, SPELL_UNKNOWN, THROWING);
	} else {
		mlog(COMBAT__RANGED, "Throwing attack hit %s.", target->GetName());
		
		sint16 WDmg = GetWeaponDamage(target, item);

		if(WDmg > 0)
		{
			sint32 TotalDmg = 0;
			int minDmg = 1;
			uint16 MaxDmg = GetThrownDamage(WDmg, TotalDmg, minDmg);

			mlog(COMBAT__RANGED, "Item DMG %d. Max Damage %d. Hit for damage %d", WDmg, MaxDmg, TotalDmg);

			target->MeleeMitigation(this, TotalDmg, minDmg);
			ApplyMeleeDamageBonus(THROWING, TotalDmg);
			TryCriticalHit(target, THROWING, TotalDmg);
			if(TotalDmg > 0)
			{
				sint32 hate = (2*WDmg);
				target->AddToHateList(this, hate, 0, false);
			}
			target->Damage(this, TotalDmg, SPELL_UNKNOWN, THROWING);
		}
		else
			target->Damage(this, -5, SPELL_UNKNOWN, THROWING);
	}
	
	if(target && (target->GetHP() > -10))
		TryWeaponProc(RangeWeapon, target);
		
	//consume ammo
	DeleteItemInInventory(ammo_slot, 1, true);
	CheckIncreaseSkill(THROWING);

	//break invis when you attack
	if(invisible) {
		mlog(COMBAT__ATTACKS, "Removing invisibility due to melee attack.");
		BuffFadeByEffect(SE_Invisibility);
		BuffFadeByEffect(SE_Invisibility2);
		invisible = false;
	}
	if(invisible_undead) {
		mlog(COMBAT__ATTACKS, "Removing invisibility vs. undead due to melee attack.");
		BuffFadeByEffect(SE_InvisVsUndead);
		BuffFadeByEffect(SE_InvisVsUndead2);
		invisible_undead = false;
	}
	if(invisible_animals){
		mlog(COMBAT__ATTACKS, "Removing invisibility vs. animals due to melee attack.");
		BuffFadeByEffect(SE_InvisVsAnimals);
		invisible_animals = false;
	}

	if(hidden || improved_hidden){
		hidden = false;
		improved_hidden = false;
		EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
		SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer;
		sa_out->spawn_id = GetID();
		sa_out->type = 0x03;
		sa_out->parameter = 0;
		entity_list.QueueClients(this, outapp, true);
		safe_delete(outapp);
	}
}
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 12:17 AM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3