mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-19 13:28:25 +00:00
Split Mob::SetAttackTimer into Client and NPC methods
This was the easiest way to NPCs delay settings to be sane in the database. The functions are cleaner since there is no specific logic to change behavior depending on if they're a client or not.
This commit is contained in:
-151
@@ -1939,157 +1939,6 @@ void Mob::Kill() {
|
||||
Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand);
|
||||
}
|
||||
|
||||
void Mob::SetAttackTimer() {
|
||||
float PermaHaste;
|
||||
if (GetHaste())
|
||||
PermaHaste = 1 / (1 + (float)GetHaste() / 100);
|
||||
else
|
||||
PermaHaste = 1.0f;
|
||||
|
||||
//default value for attack timer in case they have
|
||||
//an invalid weapon equipped:
|
||||
attack_timer.SetAtTrigger(4000, true);
|
||||
|
||||
Timer* TimerToUse = nullptr;
|
||||
const Item_Struct* PrimaryWeapon = nullptr;
|
||||
|
||||
for (int i=MainRange; i<=MainSecondary; i++) {
|
||||
|
||||
//pick a timer
|
||||
if (i == MainPrimary)
|
||||
TimerToUse = &attack_timer;
|
||||
else if (i == MainRange)
|
||||
TimerToUse = &ranged_timer;
|
||||
else if(i == MainSecondary)
|
||||
TimerToUse = &attack_dw_timer;
|
||||
else //invalid slot (hands will always hit this)
|
||||
continue;
|
||||
|
||||
const Item_Struct* ItemToUse = nullptr;
|
||||
|
||||
//find our item
|
||||
if (IsClient()) {
|
||||
ItemInst* ci = CastToClient()->GetInv().GetItem(i);
|
||||
if (ci)
|
||||
ItemToUse = ci->GetItem();
|
||||
} else if(IsNPC())
|
||||
{
|
||||
//The code before here was fundementally flawed because equipment[]
|
||||
//isn't the same as PC inventory and also:
|
||||
//NPCs don't use weapon speed to dictate how fast they hit anyway.
|
||||
ItemToUse = nullptr;
|
||||
}
|
||||
|
||||
//special offhand stuff
|
||||
if(i == MainSecondary) {
|
||||
//if we have a 2H weapon in our main hand, no dual
|
||||
if(PrimaryWeapon != nullptr) {
|
||||
if( PrimaryWeapon->ItemClass == ItemClassCommon
|
||||
&& (PrimaryWeapon->ItemType == ItemType2HSlash
|
||||
|| PrimaryWeapon->ItemType == ItemType2HBlunt
|
||||
|| PrimaryWeapon->ItemType == ItemType2HPiercing)) {
|
||||
attack_dw_timer.Disable();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//clients must have the skill to use it...
|
||||
if(IsClient()) {
|
||||
//if we cant dual wield, skip it
|
||||
if (!CanThisClassDualWield()) {
|
||||
attack_dw_timer.Disable();
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
//NPCs get it for free at 13
|
||||
if(GetLevel() < 13) {
|
||||
attack_dw_timer.Disable();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//see if we have a valid weapon
|
||||
if(ItemToUse != nullptr) {
|
||||
//check type and damage/delay
|
||||
if(ItemToUse->ItemClass != ItemClassCommon
|
||||
|| ItemToUse->Damage == 0
|
||||
|| ItemToUse->Delay == 0) {
|
||||
//no weapon
|
||||
ItemToUse = nullptr;
|
||||
}
|
||||
// Check to see if skill is valid
|
||||
else if((ItemToUse->ItemType > ItemTypeLargeThrowing) && (ItemToUse->ItemType != ItemTypeMartial) && (ItemToUse->ItemType != ItemType2HPiercing)) {
|
||||
//no weapon
|
||||
ItemToUse = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int16 DelayMod = itembonuses.HundredHands + spellbonuses.HundredHands;
|
||||
if (DelayMod < -99)
|
||||
DelayMod = -99;
|
||||
|
||||
//if we have no weapon..
|
||||
if (ItemToUse == nullptr) {
|
||||
//above checks ensure ranged weapons do not fall into here
|
||||
// Work out if we're a monk
|
||||
if ((GetClass() == MONK) || (GetClass() == BEASTLORD)) {
|
||||
//we are a monk, use special delay
|
||||
int speed = (int)( (GetMonkHandToHandDelay()*(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste);
|
||||
// 1200 seemed too much, with delay 10 weapons available
|
||||
if(speed < RuleI(Combat, MinHastedDelay)) //lower bound
|
||||
speed = RuleI(Combat, MinHastedDelay);
|
||||
TimerToUse->SetAtTrigger(speed, true); // Hand to hand, delay based on level or epic
|
||||
} else {
|
||||
//not a monk... using fist, regular delay
|
||||
int speed = (int)((36 *(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste);
|
||||
if(speed < RuleI(Combat, MinHastedDelay) && IsClient()) //lower bound
|
||||
speed = RuleI(Combat, MinHastedDelay);
|
||||
TimerToUse->SetAtTrigger(speed, true); // Hand to hand, non-monk 2/36
|
||||
}
|
||||
} else {
|
||||
//we have a weapon, use its delay
|
||||
// Convert weapon delay to timer resolution (milliseconds)
|
||||
//delay * 100
|
||||
int speed = (int)((ItemToUse->Delay*(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste);
|
||||
if(speed < RuleI(Combat, MinHastedDelay))
|
||||
speed = RuleI(Combat, MinHastedDelay);
|
||||
|
||||
if(ItemToUse && (ItemToUse->ItemType == ItemTypeBow || ItemToUse->ItemType == ItemTypeLargeThrowing))
|
||||
{
|
||||
if(IsClient())
|
||||
{
|
||||
float max_quiver = 0;
|
||||
for(int r = EmuConstants::GENERAL_BEGIN; r <= EmuConstants::GENERAL_END; r++)
|
||||
{
|
||||
const ItemInst *pi = CastToClient()->GetInv().GetItem(r);
|
||||
if(!pi)
|
||||
continue;
|
||||
if(pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == BagTypeQuiver)
|
||||
{
|
||||
float temp_wr = ( pi->GetItem()->BagWR / RuleI(Combat, QuiverWRHasteDiv) );
|
||||
if(temp_wr > max_quiver)
|
||||
{
|
||||
max_quiver = temp_wr;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(max_quiver > 0)
|
||||
{
|
||||
float quiver_haste = 1 / (1 + max_quiver / 100);
|
||||
speed *= quiver_haste;
|
||||
}
|
||||
}
|
||||
}
|
||||
TimerToUse->SetAtTrigger(speed, true);
|
||||
}
|
||||
|
||||
if(i == MainPrimary)
|
||||
PrimaryWeapon = ItemToUse;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Mob::CanThisClassDualWield(void) const {
|
||||
if(!IsClient()) {
|
||||
return(GetSkill(SkillDualWield) > 0);
|
||||
|
||||
Reference in New Issue
Block a user