int32 Client::CalcBaseEndurance() { int32 base_end = 0; if(GetClientVersion() >= EQClientSoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) { double heroic_stats = (GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4.0f; double stats = (GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4.0f; if(stats > 201.0f) { stats = 1.25f * (stats - 201.0f) + 352.5f; } else if(stats > 100.0f) { stats = 2.5f * (stats - 100.0f) + 100.0f; } auto base_data = database.GetBaseData(GetLevel(), GetClass()); if(base_data) { base_end = base_data->base_end + (heroic_stats * 10.0f) + (base_data->endurance_factor * static_cast<int>(stats)); } } else { int Stats = GetSTR()+GetSTA()+GetDEX()+GetAGI(); int LevelBase = GetLevel() * 15; int at_most_800 = Stats; if(at_most_800 > 800) at_most_800 = 800; int Bonus400to800 = 0; int HalfBonus400to800 = 0; int Bonus800plus = 0; int HalfBonus800plus = 0; int BonusUpto800 = int( at_most_800 / 4 ) ; if(Stats > 400) { Bonus400to800 = int( (at_most_800 - 400) / 4 ); HalfBonus400to800 = int( std::max( ( at_most_800 - 400 ), 0 ) / 8 ); if(Stats > 800) { Bonus800plus = int( (Stats - 800) / 8 ) * 2; HalfBonus800plus = int( (Stats - 800) / 16 ); } } int bonus_sum = BonusUpto800 + Bonus400to800 + HalfBonus400to800 + Bonus800plus + HalfBonus800plus; base_end = LevelBase; //take all of the sums from above, then multiply by level*0.075 base_end += ( bonus_sum * 3 * GetLevel() ) / 40; } return base_end; }
int32 Client::CalcBaseEndurance() { int32 base_end = 0; int Stats = GetSTR()+GetSTA()+GetDEX()+GetAGI(); int LevelBase = GetLevel() * 15; int at_most_800 = Stats; if(at_most_800 > 800) at_most_800 = 800; int Bonus400to800 = 0; int HalfBonus400to800 = 0; int Bonus800plus = 0; int HalfBonus800plus = 0; int BonusUpto800 = int( at_most_800 / 4 ) ; if(Stats > 400) { Bonus400to800 = int( (at_most_800 - 400) / 4 ); HalfBonus400to800 = int( std::max( ( at_most_800 - 400 ), 0 ) / 8 ); if(Stats > 800) { Bonus800plus = int( (Stats - 800) / 8 ) * 2; HalfBonus800plus = int( (Stats - 800) / 16 ); } } int bonus_sum = BonusUpto800 + Bonus400to800 + HalfBonus400to800 + Bonus800plus + HalfBonus800plus; base_end = LevelBase; //take all of the sums from above, then multiply by level*0.075 base_end += ( bonus_sum * 3 * GetLevel() ) / 40; return base_end; }
//returns true on success bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { if(spec == NULL) return(false); uint16 user_skill = GetSkill(spec->tradeskill); float chance = 0.0; float skillup_modifier = 0.0; int16 thirdstat = 0; int16 stat_modifier = 15; uint16 success_modifier = 0; // Rework based on the info on eqtraders.com // http://mboards.eqtraders.com/eq/showthread.php?t=22246 // 09/10/2006 v0.1 (eq4me) // 09/11/2006 v0.2 (eq4me) // Todo: // Implementing AAs // Success modifiers based on recipes // Skillup modifiers based on the rarity of the ingredients // Some tradeskills are more eqal then others. ;-) // If you want to customize the stage1 success rate do it here. // Remember: skillup_modifier is (float). Lower is better switch(spec->tradeskill) { case FLETCHING: case ALCHEMY: case JEWELRY_MAKING: case POTTERY: skillup_modifier = 4; break; case BAKING: case BREWING: skillup_modifier = 3; break; case RESEARCH: skillup_modifier = 1; break; default: skillup_modifier = 2; break; } // Some tradeskills take the higher of one additional stat beside INT and WIS // to determine the skillup rate. Additionally these tradeskills do not have an // -15 modifier on their statbonus. if (spec->tradeskill == FLETCHING || spec->tradeskill == MAKE_POISON) { thirdstat = GetDEX(); stat_modifier = 0; } else if (spec->tradeskill == BLACKSMITHING) { thirdstat = GetSTR(); stat_modifier = 0; } int16 higher_from_int_wis = (GetINT() > GetWIS()) ? GetINT() : GetWIS(); int16 bonusstat = (higher_from_int_wis > thirdstat) ? higher_from_int_wis : thirdstat; vector< pair<uint32,uint8> >::iterator itr; //calculate the base success chance // For trivials over 68 the chance is (skill - 0.75*trivial) +51.5 // For trivial up to 68 the chance is (skill - trivial) + 66 if (spec->trivial >= 68) { chance = (user_skill - (0.75*spec->trivial)) + 51.5; } else { chance = (user_skill - spec->trivial) + 66; } int16 over_trivial = (int16)GetRawSkill(spec->tradeskill) - (int16)spec->trivial; //handle caps if(spec->nofail) { chance = 100; //cannot fail. _log(TRADESKILLS__TRACE, "...This combine cannot fail."); } else if(over_trivial >= 0) { // At reaching trivial the chance goes to 95% going up an additional // percent for every 40 skillpoints above the trivial. // The success rate is not modified through stats. // Mastery AAs are unaccounted for so far. // chance_AA = chance + ((100 - chance) * mastery_modifier) // But the 95% limit with an additional 1% for every 40 skill points // above critical still stands. // Mastery modifier is: 10%/25%/50% for rank one/two/three chance = 95.0f + (float(user_skill - spec->trivial) / 40.0f); Message_StringID(MT_Emote, TRADESKILL_TRIVIAL); } else if(chance < 5) { // Minimum chance is always 5 chance = 5; } else if(chance > 95) { //cap is 95, shouldent reach this before trivial, but just in case. chance = 95; } _log(TRADESKILLS__TRACE, "...Current skill: %d , Trivial: %d , Success chance: %f percent", user_skill , spec->trivial , chance); _log(TRADESKILLS__TRACE, "...Bonusstat: %d , INT: %d , WIS: %d , DEX: %d , STR: %d", bonusstat , GetINT() , GetWIS() , GetDEX() , GetSTR()); float res = MakeRandomFloat(0, 99); int AAChance = 0; //AA modifiers //can we do this with nested switches? if(spec->tradeskill == ALCHEMY){ switch(GetAA(aaAlchemyMastery)){ case 1: AAChance = 10; break; case 2: AAChance = 25; break; case 3: AAChance = 50; break; } } if(spec->tradeskill == JEWELRY_MAKING){ switch(GetAA(aaJewelCraftMastery)){ case 1: AAChance = 10; break; case 2: AAChance = 25; break; case 3: AAChance = 50; break; } } const Item_Struct* item = NULL; if (spec->tradeskill == BLACKSMITHING) { switch(GetAA(aaBlacksmithingMastery)) { case 1: AAChance = 10; break; case 2: AAChance = 25; break; case 3: AAChance = 50; break; } } if (spec->tradeskill == BAKING) { switch(GetAA(aaBakingMastery)) { case 1: AAChance = 10; break; case 2: AAChance = 25; break; case 3: AAChance = 50; break; } } if (spec->tradeskill == BREWING) { switch(GetAA(aaBrewingMastery)) { case 1: AAChance = 10; break; case 2: AAChance = 25; break; case 3: AAChance = 50; break; } } if (spec->tradeskill == FLETCHING) { switch(GetAA(aaFletchingMastery2)) { case 1: AAChance = 10; break; case 2: AAChance = 25; break; case 3: AAChance = 50; break; } } if (spec->tradeskill == POTTERY) { switch(GetAA(aaPotteryMastery)) { case 1: AAChance = 10; break; case 2: AAChance = 25; break; case 3: AAChance = 50; break; } } if (spec->tradeskill == TAILORING) { switch(GetAA(aaTailoringMastery)) { case 1: AAChance = 10; break; case 2: AAChance = 25; break; case 3: AAChance = 50; break; } } if (spec->tradeskill == RESEARCH) { switch(GetAA(aaArcaneTongues)) { case 1: AAChance = 10; break; case 2: AAChance = 25; break; case 3: AAChance = 50; break; } } if (((spec->tradeskill==75) || GetGM() || (chance > res)) || MakeRandomInt(0, 99) < AAChance){ success_modifier = 1; if(over_trivial < 0) CheckIncreaseTradeskill(bonusstat, stat_modifier, skillup_modifier, success_modifier, spec->tradeskill); Message_StringID(4,TRADESKILL_SUCCEED,spec->name.c_str()); _log(TRADESKILLS__TRACE, "Tradeskill success"); itr = spec->onsuccess.begin(); while(itr != spec->onsuccess.end() && !spec->quest) { //should we check this crap? SummonItem(itr->first, itr->second); item = database.GetItem(itr->first); if (this->GetGroup()) { entity_list.MessageGroup(this,true,MT_Skills,"%s has successfully fashioned %s!",GetName(),item->Name); } if(RuleB(TaskSystem, EnableTaskSystem)) UpdateTasksForItem(ActivityTradeSkill, itr->first, itr->second); itr++; } return(true); } else { success_modifier = 2; // Halves the chance if(over_trivial < 0) CheckIncreaseTradeskill(bonusstat, stat_modifier, skillup_modifier, success_modifier, spec->tradeskill); Message_StringID(MT_Emote,TRADESKILL_FAILED); _log(TRADESKILLS__TRACE, "Tradeskill failed"); if (this->GetGroup()) { entity_list.MessageGroup(this,true,MT_Skills,"%s was unsuccessful in %s tradeskill attempt.",GetName(),this->GetGender() == 0 ? "his" : this->GetGender() == 1 ? "her" : "its"); } itr = spec->onfail.begin(); while(itr != spec->onfail.end()) { //should we check these arguments? SummonItem(itr->first, itr->second); itr++; } // Rolls on each item, is possible to return everything int SalvageChance = aabonuses.SalvageChance + itembonuses.SalvageChance + spellbonuses.SalvageChance; // Skip check if not a normal TS or if a quest recipe these should be nofail, but check amyways if(SalvageChance && spec->tradeskill != 75 && !spec->quest) { itr = spec->salvage.begin(); uint8 sc = 0; while(itr != spec->salvage.end()) { for(sc = 0; sc < itr->second; sc++) if(MakeRandomInt(0,99) < SalvageChance) SummonItem(itr->first, 1); itr++; } } } return(false); }
void WearableItem::UnapplyStatChanges(Player* p) { p->SetSTR(p->GetSTR() - GetSTR()); p->SetDEX(p->GetDEX() - GetDEX()); p->SetACC(p->GetACC() - GetACC()); p->SetAC(p->GetAC() - GetAC()); }
//returns true on success bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { if(spec == nullptr) return(false); uint16 user_skill = GetSkill(spec->tradeskill); float chance = 0.0; float skillup_modifier = 0.0; int16 thirdstat = 0; int16 stat_modifier = 15; uint16 success_modifier = 0; // Rework based on the info on eqtraders.com // http://mboards.eqtraders.com/eq/showthread.php?t=22246 // 09/10/2006 v0.1 (eq4me) // 09/11/2006 v0.2 (eq4me) // Todo: // Implementing AAs // Success modifiers based on recipes // Skillup modifiers based on the rarity of the ingredients // Some tradeskills are more eqal then others. ;-) // If you want to customize the stage1 success rate do it here. // Remember: skillup_modifier is (float). Lower is better switch(spec->tradeskill) { case SkillFletching: skillup_modifier = RuleI(Character, TradeskillUpFletching); break; case SkillAlchemy: skillup_modifier = RuleI(Character, TradeskillUpAlchemy); break; case SkillJewelryMaking: skillup_modifier = RuleI(Character, TradeskillUpJewelcrafting); break; case SkillPottery: skillup_modifier = RuleI(Character, TradeskillUpPottery); break; case SkillBaking: skillup_modifier = RuleI(Character, TradeskillUpBaking); break; case SkillBrewing: skillup_modifier = RuleI(Character, TradeskillUpBrewing); break; case SkillBlacksmithing: skillup_modifier = RuleI(Character, TradeskillUpBlacksmithing); break; case SkillResearch: skillup_modifier = RuleI(Character, TradeskillUpResearch); break; case SkillMakePoison: skillup_modifier = RuleI(Character, TradeskillUpMakePoison); break; case SkillTinkering: skillup_modifier = RuleI(Character, TradeskillUpTinkering); break; default: skillup_modifier = 2; break; } // Some tradeskills take the higher of one additional stat beside INT and WIS // to determine the skillup rate. Additionally these tradeskills do not have an // -15 modifier on their statbonus. if (spec->tradeskill == SkillFletching || spec->tradeskill == SkillMakePoison) { thirdstat = GetDEX(); stat_modifier = 0; } else if (spec->tradeskill == SkillBlacksmithing) { thirdstat = GetSTR(); stat_modifier = 0; } int16 higher_from_int_wis = (GetINT() > GetWIS()) ? GetINT() : GetWIS(); int16 bonusstat = (higher_from_int_wis > thirdstat) ? higher_from_int_wis : thirdstat; std::vector< std::pair<uint32,uint8> >::iterator itr; //calculate the base success chance // For trivials over 68 the chance is (skill - 0.75*trivial) +51.5 // For trivial up to 68 the chance is (skill - trivial) + 66 if (spec->trivial >= 68) { chance = (user_skill - (0.75*spec->trivial)) + 51.5; } else { chance = (user_skill - spec->trivial) + 66; } int16 over_trivial = (int16)GetRawSkill(spec->tradeskill) - (int16)spec->trivial; //handle caps if(spec->nofail) { chance = 100; //cannot fail. Log.Out(Logs::Detail, Logs::Tradeskills, "...This combine cannot fail."); } else if(over_trivial >= 0) { // At reaching trivial the chance goes to 95% going up an additional // percent for every 40 skillpoints above the trivial. // The success rate is not modified through stats. // Mastery AAs are unaccounted for so far. // chance_AA = chance + ((100 - chance) * mastery_modifier) // But the 95% limit with an additional 1% for every 40 skill points // above critical still stands. // Mastery modifier is: 10%/25%/50% for rank one/two/three chance = 95.0f + (float(user_skill - spec->trivial) / 40.0f); Message_StringID(MT_Emote, TRADESKILL_TRIVIAL); } else if(chance < 5) { // Minimum chance is always 5 chance = 5; } else if(chance > 95) { //cap is 95, shouldent reach this before trivial, but just in case. chance = 95; } Log.Out(Logs::Detail, Logs::Tradeskills, "...Current skill: %d , Trivial: %d , Success chance: %f percent", user_skill , spec->trivial , chance); Log.Out(Logs::Detail, Logs::Tradeskills, "...Bonusstat: %d , INT: %d , WIS: %d , DEX: %d , STR: %d", bonusstat , GetINT() , GetWIS() , GetDEX() , GetSTR()); float res = zone->random.Real(0, 99); int aa_chance = 0; aa_chance = spellbonuses.ReduceTradeskillFail[spec->tradeskill] + itembonuses.ReduceTradeskillFail[spec->tradeskill] + aabonuses.ReduceTradeskillFail[spec->tradeskill]; const Item_Struct* item = nullptr; chance = mod_tradeskill_chance(chance, spec); if (((spec->tradeskill==75) || GetGM() || (chance > res)) || zone->random.Roll(aa_chance)) { success_modifier = 1; if(over_trivial < 0) CheckIncreaseTradeskill(bonusstat, stat_modifier, skillup_modifier, success_modifier, spec->tradeskill); Message_StringID(4, TRADESKILL_SUCCEED, spec->name.c_str()); Log.Out(Logs::Detail, Logs::Tradeskills, "Tradeskill success"); itr = spec->onsuccess.begin(); while(itr != spec->onsuccess.end() && !spec->quest) { //should we check this crap? SummonItem(itr->first, itr->second); item = database.GetItem(itr->first); if (this->GetGroup()) { entity_list.MessageGroup(this, true, MT_Skills, "%s has successfully fashioned %s!", GetName(), item->Name); } /* QS: Player_Log_Trade_Skill_Events */ if (RuleB(QueryServ, PlayerLogTradeSkillEvents)){ std::string event_desc = StringFormat("Success :: fashioned recipe_id:%i tskillid:%i trivial:%i chance:%4.2f in zoneid:%i instid:%i", spec->recipe_id, spec->tradeskill, spec->trivial, chance, this->GetZoneID(), this->GetInstanceID()); QServ->PlayerLogEvent(Player_Log_Trade_Skill_Events, this->CharacterID(), event_desc); } if(RuleB(TaskSystem, EnableTaskSystem)) UpdateTasksForItem(ActivityTradeSkill, itr->first, itr->second); ++itr; } return(true); } /* Tradeskill Fail */ else { success_modifier = 2; // Halves the chance if(over_trivial < 0) CheckIncreaseTradeskill(bonusstat, stat_modifier, skillup_modifier, success_modifier, spec->tradeskill); Message_StringID(MT_Emote,TRADESKILL_FAILED); Log.Out(Logs::Detail, Logs::Tradeskills, "Tradeskill failed"); if (this->GetGroup()) { entity_list.MessageGroup(this,true,MT_Skills,"%s was unsuccessful in %s tradeskill attempt.",GetName(),this->GetGender() == 0 ? "his" : this->GetGender() == 1 ? "her" : "its"); } /* QS: Player_Log_Trade_Skill_Events */ if (RuleB(QueryServ, PlayerLogTradeSkillEvents)){ std::string event_desc = StringFormat("Failed :: recipe_id:%i tskillid:%i trivial:%i chance:%4.2f in zoneid:%i instid:%i", spec->recipe_id, spec->tradeskill, spec->trivial, chance, this->GetZoneID(), this->GetInstanceID()); QServ->PlayerLogEvent(Player_Log_Trade_Skill_Events, this->CharacterID(), event_desc); } itr = spec->onfail.begin(); while(itr != spec->onfail.end()) { //should we check these arguments? SummonItem(itr->first, itr->second); ++itr; } /* Salvage Item rolls */ // Rolls on each item, is possible to return everything int SalvageChance = aabonuses.SalvageChance + itembonuses.SalvageChance + spellbonuses.SalvageChance; // Skip check if not a normal TS or if a quest recipe these should be nofail, but check amyways if(SalvageChance && spec->tradeskill != 75 && !spec->quest) { itr = spec->salvage.begin(); uint8 sc = 0; while(itr != spec->salvage.end()) { for(sc = 0; sc < itr->second; sc++) if(zone->random.Roll(SalvageChance)) SummonItem(itr->first, 1); ++itr; } } } return(false); }
int32 Client::CalcBaseEndurance() { int32 base_end = 0; int32 base_endurance = 0; int32 ConvertedStats = 0; int32 sta_end = 0; int Stats = 0; if(GetClientVersion() >= EQClientSoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { int HeroicStats = 0; Stats = ((GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4); HeroicStats = ((GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4); if (Stats > 100) { ConvertedStats = (((Stats - 100) * 5 / 2) + 100); if (Stats > 201) { ConvertedStats -= ((Stats - 201) * 5 / 4); } } else { ConvertedStats = Stats; } if (GetLevel() < 41) { sta_end = (GetLevel() * 75 * ConvertedStats / 1000); base_endurance = (GetLevel() * 15); } else if (GetLevel() < 81) { sta_end = ((3 * ConvertedStats) + ((GetLevel() - 40) * 15 * ConvertedStats / 100)); base_endurance = (600 + ((GetLevel() - 40) * 30)); } else { sta_end = (9 * ConvertedStats); base_endurance = (1800 + ((GetLevel() - 80) * 18)); } base_end = (base_endurance + sta_end + (HeroicStats * 10)); } else { Stats = GetSTR()+GetSTA()+GetDEX()+GetAGI(); int LevelBase = GetLevel() * 15; int at_most_800 = Stats; if(at_most_800 > 800) at_most_800 = 800; int Bonus400to800 = 0; int HalfBonus400to800 = 0; int Bonus800plus = 0; int HalfBonus800plus = 0; int BonusUpto800 = int( at_most_800 / 4 ) ; if(Stats > 400) { Bonus400to800 = int( (at_most_800 - 400) / 4 ); HalfBonus400to800 = int( max( ( at_most_800 - 400 ), 0 ) / 8 ); if(Stats > 800) { Bonus800plus = int( (Stats - 800) / 8 ) * 2; HalfBonus800plus = int( (Stats - 800) / 16 ); } } int bonus_sum = BonusUpto800 + Bonus400to800 + HalfBonus400to800 + Bonus800plus + HalfBonus800plus; base_end = LevelBase; //take all of the sums from above, then multiply by level*0.075 base_end += ( bonus_sum * 3 * GetLevel() ) / 40; } return base_end; }