mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-03 09:26:36 +00:00
Upstream merge
This commit is contained in:
+2
-2
@@ -218,7 +218,7 @@ INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
ADD_DEFINITIONS(-DZONE)
|
||||
|
||||
TARGET_LINK_LIBRARIES(zone Common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
|
||||
TARGET_LINK_LIBRARIES(zone common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
|
||||
|
||||
IF(EQEMU_BUILD_PERL)
|
||||
TARGET_LINK_LIBRARIES(zone ${PERL_LIBRARY})
|
||||
@@ -249,4 +249,4 @@ IF(UNIX)
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin)
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
+150
-34
@@ -824,17 +824,17 @@ void Client::AI_Process()
|
||||
|
||||
if(GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) {
|
||||
if(attack_timer.Check()) {
|
||||
Attack(GetTarget(), 13);
|
||||
Attack(GetTarget(), MainPrimary);
|
||||
if(GetTarget()) {
|
||||
if(CheckDoubleAttack()) {
|
||||
Attack(GetTarget(), 13);
|
||||
Attack(GetTarget(), MainPrimary);
|
||||
if(GetTarget()) {
|
||||
bool triple_attack_success = false;
|
||||
if((((GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER)
|
||||
&& GetLevel() >= 60) || GetSpecialAbility(SPECATK_TRIPLE))
|
||||
&& CheckDoubleAttack(true))
|
||||
{
|
||||
Attack(GetTarget(), 13, true);
|
||||
Attack(GetTarget(), MainPrimary, true);
|
||||
triple_attack_success = true;
|
||||
}
|
||||
|
||||
@@ -848,15 +848,15 @@ void Client::AI_Process()
|
||||
if(MakeRandomInt(0, 100) < flurrychance)
|
||||
{
|
||||
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
|
||||
Attack(GetTarget(), 13, false);
|
||||
Attack(GetTarget(), 13, false);
|
||||
Attack(GetTarget(), MainPrimary, false);
|
||||
Attack(GetTarget(), MainPrimary, false);
|
||||
}
|
||||
}
|
||||
|
||||
int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance;
|
||||
|
||||
if (ExtraAttackChanceBonus && GetTarget()) {
|
||||
ItemInst *wpn = GetInv().GetItem(SLOT_PRIMARY);
|
||||
ItemInst *wpn = GetInv().GetItem(MainPrimary);
|
||||
if(wpn){
|
||||
if(wpn->GetItem()->ItemType == ItemType2HSlash ||
|
||||
wpn->GetItem()->ItemType == ItemType2HBlunt ||
|
||||
@@ -864,7 +864,7 @@ void Client::AI_Process()
|
||||
{
|
||||
if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus)
|
||||
{
|
||||
Attack(GetTarget(), 13, false);
|
||||
Attack(GetTarget(), MainPrimary, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -903,10 +903,10 @@ void Client::AI_Process()
|
||||
|
||||
if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability)
|
||||
{
|
||||
Attack(GetTarget(), 14);
|
||||
Attack(GetTarget(), MainSecondary);
|
||||
if(CheckDoubleAttack())
|
||||
{
|
||||
Attack(GetTarget(), 14);
|
||||
Attack(GetTarget(), MainSecondary);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1145,14 +1145,14 @@ void Mob::AI_Process() {
|
||||
if(IsNPC()) {
|
||||
int16 n_atk = CastToNPC()->GetNumberOfAttacks();
|
||||
if(n_atk <= 1) {
|
||||
Attack(target, 13);
|
||||
Attack(target, MainPrimary);
|
||||
} else {
|
||||
for(int i = 0; i < n_atk; ++i) {
|
||||
Attack(target, 13);
|
||||
Attack(target, MainPrimary);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Attack(target, 13);
|
||||
Attack(target, MainPrimary);
|
||||
}
|
||||
|
||||
if (target) {
|
||||
@@ -1164,16 +1164,16 @@ void Mob::AI_Process() {
|
||||
|| GetSpecialAbility(SPECATK_QUAD))
|
||||
//check double attack, this is NOT the same rules that clients use...
|
||||
&& RandRoll < (GetLevel() + NPCDualAttackModifier)) {
|
||||
Attack(target, 13);
|
||||
Attack(target, MainPrimary);
|
||||
// lets see if we can do a triple attack with the main hand
|
||||
//pets are excluded from triple and quads...
|
||||
if ((GetSpecialAbility(SPECATK_TRIPLE) || GetSpecialAbility(SPECATK_QUAD))
|
||||
&& !IsPet() && RandRoll < (GetLevel() + NPCTripleAttackModifier)) {
|
||||
Attack(target, 13);
|
||||
Attack(target, MainPrimary);
|
||||
// now lets check the quad attack
|
||||
if (GetSpecialAbility(SPECATK_QUAD)
|
||||
&& RandRoll < (GetLevel() + NPCQuadAttackModifier)) {
|
||||
Attack(target, 13);
|
||||
Attack(target, MainPrimary);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1319,13 +1319,13 @@ void Mob::AI_Process() {
|
||||
float DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel()) / 400.0f;
|
||||
if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability)
|
||||
{
|
||||
Attack(target, 14);
|
||||
Attack(target, MainSecondary);
|
||||
if (CanThisClassDoubleAttack())
|
||||
{
|
||||
int32 RandRoll = MakeRandomInt(0, 99);
|
||||
if (RandRoll < (GetLevel() + 20))
|
||||
{
|
||||
Attack(target, 14);
|
||||
Attack(target, MainSecondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1897,7 +1897,7 @@ void NPC::AI_Event_SpellCastFinished(bool iCastSucceeded, uint8 slot) {
|
||||
AIautocastspell_timer->Start(recovery_time, false);
|
||||
}
|
||||
else
|
||||
AIautocastspell_timer->Start(800, false);
|
||||
AIautocastspell_timer->Start(AISpellVar.fail_recast, false);
|
||||
casting_spell_AIindex = AIspells.size();
|
||||
}
|
||||
}
|
||||
@@ -1910,13 +1910,13 @@ bool NPC::AI_EngagedCastCheck() {
|
||||
mlog(AI__SPELLS, "Engaged autocast check triggered. Trying to cast healing spells then maybe offensive spells.");
|
||||
|
||||
// try casting a heal or gate
|
||||
if (!AICastSpell(this, 100, SpellType_Heal | SpellType_Escape | SpellType_InCombatBuff)) {
|
||||
if (!AICastSpell(this, AISpellVar.engaged_beneficial_self_chance, SpellType_Heal | SpellType_Escape | SpellType_InCombatBuff)) {
|
||||
// try casting a heal on nearby
|
||||
if (!entity_list.AICheckCloseBeneficialSpells(this, 25, MobAISpellRange, SpellType_Heal)) {
|
||||
if (!entity_list.AICheckCloseBeneficialSpells(this, AISpellVar.engaged_beneficial_other_chance, MobAISpellRange, SpellType_Heal)) {
|
||||
//nobody to heal, try some detrimental spells.
|
||||
if(!AICastSpell(GetTarget(), 20, SpellType_Nuke | SpellType_Lifetap | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff | SpellType_Charm | SpellType_Root)) {
|
||||
if(!AICastSpell(GetTarget(), AISpellVar.engaged_detrimental_chance, SpellType_Nuke | SpellType_Lifetap | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff | SpellType_Charm | SpellType_Root)) {
|
||||
//no spell to cast, try again soon.
|
||||
AIautocastspell_timer->Start(RandomTimer(500, 1000), false);
|
||||
AIautocastspell_timer->Start(RandomTimer(AISpellVar.engaged_no_sp_recast_min, AISpellVar.engaged_no_sp_recast_max), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1931,9 +1931,9 @@ bool NPC::AI_PursueCastCheck() {
|
||||
AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting.
|
||||
|
||||
mlog(AI__SPELLS, "Engaged (pursuing) autocast check triggered. Trying to cast offensive spells.");
|
||||
if(!AICastSpell(GetTarget(), 90, SpellType_Root | SpellType_Nuke | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff)) {
|
||||
if(!AICastSpell(GetTarget(), AISpellVar.pursue_detrimental_chance, SpellType_Root | SpellType_Nuke | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff)) {
|
||||
//no spell cast, try again soon.
|
||||
AIautocastspell_timer->Start(RandomTimer(500, 2000), false);
|
||||
AIautocastspell_timer->Start(RandomTimer(AISpellVar.pursue_no_sp_recast_min, AISpellVar.pursue_no_sp_recast_max), false);
|
||||
} //else, spell casting finishing will reset the timer.
|
||||
return(true);
|
||||
}
|
||||
@@ -1946,11 +1946,11 @@ bool NPC::AI_IdleCastCheck() {
|
||||
std::cout << "Non-Engaged autocast check triggered: " << this->GetName() << std::endl;
|
||||
#endif
|
||||
AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting.
|
||||
if (!AICastSpell(this, 100, SpellType_Heal | SpellType_Buff | SpellType_Pet)) {
|
||||
if (!AICastSpell(this, AISpellVar.idle_beneficial_chance, SpellType_Heal | SpellType_Buff | SpellType_Pet)) {
|
||||
if(!entity_list.AICheckCloseBeneficialSpells(this, 33, MobAISpellRange, SpellType_Heal | SpellType_Buff)) {
|
||||
//if we didnt cast any spells, our autocast timer just resets to the
|
||||
//last duration it was set to... try to put up a more reasonable timer...
|
||||
AIautocastspell_timer->Start(RandomTimer(1000, 5000), false);
|
||||
AIautocastspell_timer->Start(RandomTimer(AISpellVar.idle_no_sp_recast_min, AISpellVar.idle_no_sp_recast_max), false);
|
||||
} //else, spell casting finishing will reset the timer.
|
||||
} //else, spell casting finishing will reset the timer.
|
||||
return(true);
|
||||
@@ -2024,7 +2024,7 @@ bool Mob::Flurry(ExtraAttackOptions *opts)
|
||||
int num_attacks = GetSpecialAbilityParam(SPECATK_FLURRY, 1);
|
||||
num_attacks = num_attacks > 0 ? num_attacks : RuleI(Combat, MaxFlurryHits);
|
||||
for (int i = 0; i < num_attacks; i++)
|
||||
Attack(target, 13, false, false, false, opts);
|
||||
Attack(target, MainPrimary, false, false, false, opts);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2073,14 +2073,14 @@ bool Mob::Rampage(ExtraAttackOptions *opts)
|
||||
if (m_target == GetTarget())
|
||||
continue;
|
||||
if (CombatRange(m_target)) {
|
||||
Attack(m_target, 13, false, false, false, opts);
|
||||
Attack(m_target, MainPrimary, false, false, false, opts);
|
||||
index_hit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (RuleB(Combat, RampageHitsTarget) && index_hit < rampage_targets)
|
||||
Attack(GetTarget(), 13, false, false, false, opts);
|
||||
Attack(GetTarget(), MainPrimary, false, false, false, opts);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2099,7 +2099,7 @@ void Mob::AreaRampage(ExtraAttackOptions *opts)
|
||||
index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts);
|
||||
|
||||
if(index_hit == 0) {
|
||||
Attack(GetTarget(), 13, false, false, false, opts);
|
||||
Attack(GetTarget(), MainPrimary, false, false, false, opts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2340,11 +2340,44 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) {
|
||||
std::cout << " (not found)";
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
int16 attack_proc_spell = -1;
|
||||
uint16 attack_proc_spell = -1;
|
||||
int8 proc_chance = 3;
|
||||
uint16 range_proc_spell = -1;
|
||||
int16 rproc_chance = 0;
|
||||
uint16 defensive_proc_spell = -1;
|
||||
int16 dproc_chance = 0;
|
||||
uint32 _fail_recast = 0;
|
||||
uint32 _engaged_no_sp_recast_min = 0;
|
||||
uint32 _engaged_no_sp_recast_max = 0;
|
||||
uint8 _engaged_beneficial_self_chance = 0;
|
||||
uint8 _engaged_beneficial_other_chance = 0;
|
||||
uint8 _engaged_detrimental_chance = 0;
|
||||
uint32 _pursue_no_sp_recast_min = 0;
|
||||
uint32 _pursue_no_sp_recast_max = 0;
|
||||
uint8 _pursue_detrimental_chance = 0;
|
||||
uint32 _idle_no_sp_recast_min = 0;
|
||||
uint32 _idle_no_sp_recast_max = 0;
|
||||
uint8 _idle_beneficial_chance = 0;
|
||||
|
||||
if (parentlist) {
|
||||
attack_proc_spell = parentlist->attack_proc;
|
||||
proc_chance = parentlist->proc_chance;
|
||||
range_proc_spell = parentlist->range_proc;
|
||||
rproc_chance = parentlist->rproc_chance;
|
||||
defensive_proc_spell = parentlist->defensive_proc;
|
||||
dproc_chance = parentlist->dproc_chance;
|
||||
_fail_recast = parentlist->fail_recast;
|
||||
_engaged_no_sp_recast_min = parentlist->engaged_no_sp_recast_min;
|
||||
_engaged_no_sp_recast_max = parentlist->engaged_no_sp_recast_max;
|
||||
_engaged_beneficial_self_chance = parentlist->engaged_beneficial_self_chance;
|
||||
_engaged_beneficial_other_chance = parentlist->engaged_beneficial_other_chance;
|
||||
_engaged_detrimental_chance = parentlist->engaged_detrimental_chance;
|
||||
_pursue_no_sp_recast_min = parentlist->pursue_no_sp_recast_min;
|
||||
_pursue_no_sp_recast_max = parentlist->pursue_no_sp_recast_max;
|
||||
_pursue_detrimental_chance = parentlist->pursue_detrimental_chance;
|
||||
_idle_no_sp_recast_min = parentlist->idle_no_sp_recast_min;
|
||||
_idle_no_sp_recast_max = parentlist->idle_no_sp_recast_max;
|
||||
_idle_beneficial_chance = parentlist->idle_beneficial_chance;
|
||||
for (i=0; i<parentlist->numentries; i++) {
|
||||
if (GetLevel() >= parentlist->entries[i].minlevel && GetLevel() <= parentlist->entries[i].maxlevel && parentlist->entries[i].spellid > 0) {
|
||||
if (!IsSpellInList(spell_list, parentlist->entries[i].spellid))
|
||||
@@ -2361,6 +2394,36 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) {
|
||||
attack_proc_spell = spell_list->attack_proc;
|
||||
proc_chance = spell_list->proc_chance;
|
||||
}
|
||||
|
||||
if (spell_list->range_proc >= 0) {
|
||||
range_proc_spell = spell_list->range_proc;
|
||||
rproc_chance = spell_list->rproc_chance;
|
||||
}
|
||||
|
||||
if (spell_list->defensive_proc >= 0) {
|
||||
defensive_proc_spell = spell_list->defensive_proc;
|
||||
dproc_chance = spell_list->dproc_chance;
|
||||
}
|
||||
|
||||
//If any casting variables are defined in the current list, ignore those in the parent list.
|
||||
if (spell_list->fail_recast || spell_list->engaged_no_sp_recast_min || spell_list->engaged_no_sp_recast_max
|
||||
|| spell_list->engaged_beneficial_self_chance || spell_list->engaged_beneficial_other_chance || spell_list->engaged_detrimental_chance
|
||||
|| spell_list->pursue_no_sp_recast_min || spell_list->pursue_no_sp_recast_max || spell_list->pursue_detrimental_chance
|
||||
|| spell_list->idle_no_sp_recast_min || spell_list->idle_no_sp_recast_max || spell_list->idle_beneficial_chance) {
|
||||
_fail_recast = spell_list->fail_recast;
|
||||
_engaged_no_sp_recast_min = spell_list->engaged_no_sp_recast_min;
|
||||
_engaged_no_sp_recast_max = spell_list->engaged_no_sp_recast_max;
|
||||
_engaged_beneficial_self_chance = spell_list->engaged_beneficial_self_chance;
|
||||
_engaged_beneficial_other_chance = spell_list->engaged_beneficial_other_chance;
|
||||
_engaged_detrimental_chance = spell_list->engaged_detrimental_chance;
|
||||
_pursue_no_sp_recast_min = spell_list->pursue_no_sp_recast_min;
|
||||
_pursue_no_sp_recast_max = spell_list->pursue_no_sp_recast_max;
|
||||
_pursue_detrimental_chance = spell_list->pursue_detrimental_chance;
|
||||
_idle_no_sp_recast_min = spell_list->idle_no_sp_recast_min;
|
||||
_idle_no_sp_recast_max = spell_list->idle_no_sp_recast_max;
|
||||
_idle_beneficial_chance = spell_list->idle_beneficial_chance;
|
||||
}
|
||||
|
||||
for (i=0; i<spell_list->numentries; i++) {
|
||||
if (GetLevel() >= spell_list->entries[i].minlevel && GetLevel() <= spell_list->entries[i].maxlevel && spell_list->entries[i].spellid > 0) {
|
||||
AddSpellToNPCList(spell_list->entries[i].priority,
|
||||
@@ -2371,9 +2434,30 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) {
|
||||
}
|
||||
std::sort(AIspells.begin(), AIspells.end(), Compare_AI_Spells);
|
||||
|
||||
if (attack_proc_spell > 0)
|
||||
if (IsValidSpell(attack_proc_spell))
|
||||
AddProcToWeapon(attack_proc_spell, true, proc_chance);
|
||||
|
||||
if (IsValidSpell(range_proc_spell))
|
||||
AddRangedProc(range_proc_spell, (rproc_chance + 100));
|
||||
|
||||
if (IsValidSpell(defensive_proc_spell))
|
||||
AddDefensiveProc(defensive_proc_spell, (dproc_chance + 100));
|
||||
|
||||
//Set AI casting variables
|
||||
|
||||
AISpellVar.fail_recast = (_fail_recast) ? _fail_recast : RuleI(Spells, AI_SpellCastFinishedFailRecast);
|
||||
AISpellVar.engaged_no_sp_recast_min = (_engaged_no_sp_recast_min) ? _engaged_no_sp_recast_min : RuleI(Spells, AI_EngagedNoSpellMinRecast);
|
||||
AISpellVar.engaged_no_sp_recast_max = (_engaged_no_sp_recast_max) ? _engaged_no_sp_recast_max : RuleI(Spells, AI_EngagedNoSpellMaxRecast);
|
||||
AISpellVar.engaged_beneficial_self_chance = (_engaged_beneficial_self_chance) ? _engaged_beneficial_self_chance : RuleI(Spells, AI_EngagedBeneficialSelfChance);
|
||||
AISpellVar.engaged_beneficial_other_chance = (_engaged_beneficial_other_chance) ? _engaged_beneficial_other_chance : RuleI(Spells, AI_EngagedBeneficialOtherChance);
|
||||
AISpellVar.engaged_detrimental_chance = (_engaged_detrimental_chance) ? _engaged_detrimental_chance : RuleI(Spells, AI_EngagedDetrimentalChance);
|
||||
AISpellVar.pursue_no_sp_recast_min = (_pursue_no_sp_recast_min) ? _pursue_no_sp_recast_min : RuleI(Spells, AI_PursueNoSpellMinRecast);
|
||||
AISpellVar.pursue_no_sp_recast_max = (_pursue_no_sp_recast_max) ? _pursue_no_sp_recast_max : RuleI(Spells, AI_PursueNoSpellMaxRecast);
|
||||
AISpellVar.pursue_detrimental_chance = (_pursue_detrimental_chance) ? _pursue_detrimental_chance : RuleI(Spells, AI_PursueDetrimentalChance);
|
||||
AISpellVar.idle_no_sp_recast_min = (_idle_no_sp_recast_min) ? _idle_no_sp_recast_min : RuleI(Spells, AI_IdleNoSpellMinRecast);
|
||||
AISpellVar.idle_no_sp_recast_max = (_idle_no_sp_recast_max) ? _idle_no_sp_recast_max : RuleI(Spells, AI_IdleNoSpellMaxRecast);
|
||||
AISpellVar.idle_beneficial_chance = (_idle_beneficial_chance) ? _idle_beneficial_chance : RuleI(Spells, AI_IdleBeneficialChance);
|
||||
|
||||
if (AIspells.size() == 0)
|
||||
AIautocastspell_timer->Disable();
|
||||
else
|
||||
@@ -2568,13 +2652,29 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list, attack_proc, proc_chance from npc_spells where id=%d", iDBSpellsID), errbuf, &result)) {
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list, attack_proc, proc_chance, range_proc, rproc_chance, defensive_proc, dproc_chance, fail_recast, engaged_no_sp_recast_min, engaged_no_sp_recast_max, engaged_b_self_chance, engaged_b_other_chance, engaged_d_chance, pursue_no_sp_recast_min, pursue_no_sp_recast_max, pursue_d_chance, idle_no_sp_recast_min, idle_no_sp_recast_max, idle_b_chance from npc_spells where id=%d", iDBSpellsID), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
uint32 tmpparent_list = atoi(row[1]);
|
||||
int16 tmpattack_proc = atoi(row[2]);
|
||||
uint16 tmpattack_proc = atoi(row[2]);
|
||||
uint8 tmpproc_chance = atoi(row[3]);
|
||||
uint16 tmprange_proc = atoi(row[4]);
|
||||
int16 tmprproc_chance = atoi(row[5]);
|
||||
uint16 tmpdefensive_proc = atoi(row[6]);
|
||||
int16 tmpdproc_chance = atoi(row[7]);
|
||||
uint32 tmppfail_recast = atoi(row[8]);
|
||||
uint32 tmpengaged_no_sp_recast_min = atoi(row[9]);
|
||||
uint32 tmpengaged_no_sp_recast_max = atoi(row[10]);
|
||||
uint8 tmpengaged_b_self_chance = atoi(row[11]);
|
||||
uint8 tmpengaged_b_other_chance = atoi(row[12]);
|
||||
uint8 tmpengaged_d_chance = atoi(row[13]);
|
||||
uint32 tmppursue_no_sp_recast_min = atoi(row[14]);
|
||||
uint32 tmppursue_no_sp_recast_max = atoi(row[15]);
|
||||
uint8 tmppursue_d_chance = atoi(row[16]);
|
||||
uint32 tmpidle_no_sp_recast_min = atoi(row[17]);
|
||||
uint32 tmpidle_no_sp_recast_max = atoi(row[18]);
|
||||
uint8 tmpidle_b_chance = atoi(row[19]);
|
||||
mysql_free_result(result);
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT spellid, type, minlevel, maxlevel, manacost, recast_delay, priority, resist_adjust from npc_spells_entries where npc_spells_id=%d ORDER BY minlevel", iDBSpellsID), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
@@ -2584,6 +2684,22 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
|
||||
npc_spells_cache[iDBSpellsID]->parent_list = tmpparent_list;
|
||||
npc_spells_cache[iDBSpellsID]->attack_proc = tmpattack_proc;
|
||||
npc_spells_cache[iDBSpellsID]->proc_chance = tmpproc_chance;
|
||||
npc_spells_cache[iDBSpellsID]->range_proc = tmprange_proc;
|
||||
npc_spells_cache[iDBSpellsID]->rproc_chance = tmpdproc_chance;
|
||||
npc_spells_cache[iDBSpellsID]->defensive_proc = tmpdefensive_proc;
|
||||
npc_spells_cache[iDBSpellsID]->dproc_chance = tmpdproc_chance;
|
||||
npc_spells_cache[iDBSpellsID]->fail_recast = tmppfail_recast;
|
||||
npc_spells_cache[iDBSpellsID]->engaged_no_sp_recast_min = tmpengaged_no_sp_recast_min;
|
||||
npc_spells_cache[iDBSpellsID]->engaged_no_sp_recast_max = tmpengaged_no_sp_recast_max;
|
||||
npc_spells_cache[iDBSpellsID]->engaged_beneficial_self_chance = tmpengaged_b_self_chance;
|
||||
npc_spells_cache[iDBSpellsID]->engaged_beneficial_other_chance = tmpengaged_b_other_chance;
|
||||
npc_spells_cache[iDBSpellsID]->engaged_detrimental_chance = tmpengaged_d_chance;
|
||||
npc_spells_cache[iDBSpellsID]->pursue_no_sp_recast_min = tmppursue_no_sp_recast_min;
|
||||
npc_spells_cache[iDBSpellsID]->pursue_no_sp_recast_max = tmppursue_no_sp_recast_max;
|
||||
npc_spells_cache[iDBSpellsID]->pursue_detrimental_chance = tmppursue_d_chance;
|
||||
npc_spells_cache[iDBSpellsID]->idle_no_sp_recast_min = tmpidle_no_sp_recast_min;
|
||||
npc_spells_cache[iDBSpellsID]->idle_no_sp_recast_max = tmpidle_no_sp_recast_max;
|
||||
npc_spells_cache[iDBSpellsID]->idle_beneficial_chance = tmpidle_b_chance;
|
||||
npc_spells_cache[iDBSpellsID]->numentries = mysql_num_rows(result);
|
||||
int j = 0;
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
|
||||
+5
-5
@@ -349,7 +349,7 @@ void Object::Close() {
|
||||
ItemInst* container = this->m_inst;
|
||||
if(container != nullptr)
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_ITEMS_PER_BAG; i++)
|
||||
for (uint8 i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++)
|
||||
{
|
||||
ItemInst* inst = container->PopItem(i);
|
||||
if(inst != nullptr)
|
||||
@@ -456,7 +456,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
|
||||
// the client updates itself and takes care of sending "duplicate lore item" messages
|
||||
if(sender->CheckLoreConflict(m_inst->GetItem())) {
|
||||
int16 loreslot = sender->GetInv().HasItem(m_inst->GetItem()->ID, 0, invWhereBank);
|
||||
if(loreslot != SLOT_INVALID) // if the duplicate is in the bank, delete it.
|
||||
if (loreslot != INVALID_INDEX) // if the duplicate is in the bank, delete it.
|
||||
sender->DeleteItemInInventory(loreslot);
|
||||
else
|
||||
cursordelete = true; // otherwise, we delete the new one
|
||||
@@ -470,11 +470,11 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
|
||||
parse->EventPlayer(EVENT_PLAYER_PICKUP, sender, buf, 0, &args);
|
||||
|
||||
// Transfer item to client
|
||||
sender->PutItemInInventory(SLOT_CURSOR, *m_inst, false);
|
||||
sender->SendItemPacket(SLOT_CURSOR, m_inst, ItemPacketTrade);
|
||||
sender->PutItemInInventory(MainCursor, *m_inst, false);
|
||||
sender->SendItemPacket(MainCursor, m_inst, ItemPacketTrade);
|
||||
|
||||
if(cursordelete) // delete the item if it's a duplicate lore. We have to do this because the client expects the item packet
|
||||
sender->DeleteItemInInventory(SLOT_CURSOR);
|
||||
sender->DeleteItemInInventory(MainCursor);
|
||||
|
||||
if(!m_ground_spawn)
|
||||
safe_delete(m_inst);
|
||||
|
||||
+163
-182
@@ -166,7 +166,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w
|
||||
}
|
||||
|
||||
// If we're attacking with the secondary hand, play the dual wield anim
|
||||
if (Hand == 14) // DW anim
|
||||
if (Hand == MainSecondary) // DW anim
|
||||
type = animDualWield;
|
||||
|
||||
DoAnim(type);
|
||||
@@ -202,7 +202,8 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
|
||||
if (chance_mod >= 10000)
|
||||
return true;
|
||||
|
||||
float bonus;
|
||||
float avoidanceBonus = 0;
|
||||
float hitBonus = 0;
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// To hit calcs go here
|
||||
@@ -214,6 +215,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
|
||||
//Calculate the level difference
|
||||
|
||||
mlog(COMBAT__TOHIT, "Chance to hit before level diff calc %.2f", chancetohit);
|
||||
|
||||
double level_difference = attacker_level - defender_level;
|
||||
double range = defender->GetLevel();
|
||||
range = ((range / 4) + 3);
|
||||
@@ -268,37 +270,32 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
|
||||
mlog(COMBAT__TOHIT, "Applied item melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit);
|
||||
}
|
||||
|
||||
//subtract off avoidance by the defender. (Live AA - Combat Agility)
|
||||
bonus = defender->spellbonuses.AvoidMeleeChance + defender->itembonuses.AvoidMeleeChance + (defender->aabonuses.AvoidMeleeChance * 10);
|
||||
//Avoidance Bonuses on defender decreases baseline hit chance by percent.
|
||||
avoidanceBonus = defender->spellbonuses.AvoidMeleeChanceEffect +
|
||||
defender->itembonuses.AvoidMeleeChanceEffect +
|
||||
defender->aabonuses.AvoidMeleeChanceEffect +
|
||||
(defender->itembonuses.AvoidMeleeChance / 10.0f); //Item Mod 'Avoidence'
|
||||
|
||||
//AA Live - Elemental Agility
|
||||
if (IsPet()) {
|
||||
Mob *owner = defender->GetOwner();
|
||||
if (!owner)return false;
|
||||
bonus += (owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance)*10;
|
||||
}
|
||||
Mob *owner = nullptr;
|
||||
if (defender->IsPet())
|
||||
owner = defender->GetOwner();
|
||||
else if ((defender->IsNPC() && defender->CastToNPC()->GetSwarmOwner()))
|
||||
owner = entity_list.GetMobID(defender->CastToNPC()->GetSwarmOwner());
|
||||
|
||||
if (owner)
|
||||
avoidanceBonus += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance;
|
||||
|
||||
if(bonus > 0) {
|
||||
chancetohit -= ((bonus * chancetohit) / 1000);
|
||||
mlog(COMBAT__TOHIT, "Applied avoidance chance %.2f/10, yeilding %.2f", bonus, chancetohit);
|
||||
}
|
||||
|
||||
if(attacker->IsNPC())
|
||||
chancetohit += (chancetohit * attacker->CastToNPC()->GetAccuracyRating() / 1000);
|
||||
|
||||
mlog(COMBAT__TOHIT, "Chance to hit after accuracy rating calc %.2f", chancetohit);
|
||||
|
||||
float hitBonus = 0;
|
||||
|
||||
/*
|
||||
Kayen: Unknown if the HitChance and Accuracy effect's should modify 'chancetohit'
|
||||
cumulatively or successively. For now all hitBonuses are cumulative.
|
||||
*/
|
||||
if(defender->IsNPC())
|
||||
avoidanceBonus += (defender->CastToNPC()->GetAvoidanceRating() / 10.0f); //Modifier from database
|
||||
|
||||
//Hit Chance Bonuses on attacker increases baseline hit chance by percent.
|
||||
hitBonus += attacker->itembonuses.HitChanceEffect[skillinuse] +
|
||||
attacker->spellbonuses.HitChanceEffect[skillinuse]+
|
||||
attacker->aabonuses.HitChanceEffect[skillinuse]+
|
||||
attacker->itembonuses.HitChanceEffect[HIGHEST_SKILL+1] +
|
||||
attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1];
|
||||
attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1] +
|
||||
attacker->aabonuses.HitChanceEffect[HIGHEST_SKILL+1];
|
||||
|
||||
|
||||
//Accuracy = Spell Effect , HitChance = 'Accuracy' from Item Effect
|
||||
//Only AA derived accuracy can be skill limited. ie (Precision of the Pathfinder, Dead Aim)
|
||||
@@ -306,26 +303,31 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
|
||||
attacker->spellbonuses.Accuracy[HIGHEST_SKILL+1] +
|
||||
attacker->aabonuses.Accuracy[HIGHEST_SKILL+1] +
|
||||
attacker->aabonuses.Accuracy[skillinuse] +
|
||||
attacker->itembonuses.HitChance) / 15.0f;
|
||||
attacker->itembonuses.HitChance) / 15.0f; //Item Mod 'Accuracy'
|
||||
|
||||
hitBonus += chance_mod; //Modifier applied from casted/disc skill attacks.
|
||||
|
||||
chancetohit += ((chancetohit * hitBonus) / 100.0f);
|
||||
|
||||
if(attacker->IsNPC())
|
||||
hitBonus += (attacker->CastToNPC()->GetAccuracyRating() / 10.0f); //Modifier from database
|
||||
|
||||
if(skillinuse == SkillArchery)
|
||||
chancetohit -= (chancetohit * RuleR(Combat, ArcheryHitPenalty)) / 100.0f;
|
||||
hitBonus -= hitBonus*(RuleR(Combat, ArcheryHitPenalty)*100.0f);
|
||||
|
||||
//Calculate final chance to hit
|
||||
chancetohit += ((chancetohit * (hitBonus - avoidanceBonus)) / 100.0f);
|
||||
mlog(COMBAT__TOHIT, "Chance to hit %.2f after accuracy calc %.2f and avoidance calc %.2f", chancetohit, hitBonus, avoidanceBonus);
|
||||
|
||||
chancetohit = mod_hit_chance(chancetohit, skillinuse, attacker);
|
||||
|
||||
// Chance to hit; Max 95%, Min 30%
|
||||
// Chance to hit; Max 95%, Min 5% DEFAULTS
|
||||
if(chancetohit > 1000 || chancetohit < -1000) {
|
||||
//if chance to hit is crazy high, that means a discipline is in use, and let it stay there
|
||||
}
|
||||
else if(chancetohit > 95) {
|
||||
chancetohit = 95;
|
||||
else if(chancetohit > RuleR(Combat,MaxChancetoHit)) {
|
||||
chancetohit = RuleR(Combat,MaxChancetoHit);
|
||||
}
|
||||
else if(chancetohit < 5) {
|
||||
chancetohit = 5;
|
||||
else if(chancetohit < RuleR(Combat,MinChancetoHit)) {
|
||||
chancetohit = RuleR(Combat,MinChancetoHit);
|
||||
}
|
||||
|
||||
//I dont know the best way to handle a garunteed hit discipline being used
|
||||
@@ -452,9 +454,9 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
|
||||
|
||||
if(damage > 0 && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock)
|
||||
&& (other->InFrontMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) {
|
||||
bool equiped2 = CastToClient()->m_inv.GetItem(13);
|
||||
bool equiped2 = CastToClient()->m_inv.GetItem(MainPrimary);
|
||||
if(equiped2) {
|
||||
uint8 TwoHandBlunt = CastToClient()->m_inv.GetItem(13)->GetItem()->ItemType;
|
||||
uint8 TwoHandBlunt = CastToClient()->m_inv.GetItem(MainPrimary)->GetItem()->ItemType;
|
||||
float bonusStaffBlock = 0.0f;
|
||||
if(TwoHandBlunt == ItemType2HBlunt) {
|
||||
|
||||
@@ -564,15 +566,15 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
|
||||
|
||||
if (!IsPet())
|
||||
armor = (armor / RuleR(Combat, NPCACFactor));
|
||||
else{
|
||||
Mob *owner = nullptr;
|
||||
|
||||
Mob *owner = nullptr;
|
||||
if (IsPet())
|
||||
owner = GetOwner();
|
||||
if (owner){
|
||||
PetACBonus = owner->aabonuses.PetMeleeMitigation
|
||||
+ owner->itembonuses.PetMeleeMitigation +
|
||||
owner->spellbonuses.PetMeleeMitigation;
|
||||
}
|
||||
}
|
||||
else if ((CastToNPC()->GetSwarmOwner()))
|
||||
owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner());
|
||||
|
||||
if (owner)
|
||||
PetACBonus = owner->aabonuses.PetMeleeMitigation + owner->itembonuses.PetMeleeMitigation + owner->spellbonuses.PetMeleeMitigation;
|
||||
|
||||
armor += spellbonuses.AC + itembonuses.AC + PetACBonus + 1;
|
||||
}
|
||||
@@ -713,7 +715,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
|
||||
//reduce the damage from shielding item and aa based on the min dmg
|
||||
//spells offer pure mitigation
|
||||
damage -= (minhit * defender->itembonuses.MeleeMitigation / 100);
|
||||
damage -= (damage * defender->spellbonuses.MeleeMitigation / 100);
|
||||
damage -= (damage * (defender->spellbonuses.MeleeMitigationEffect + defender->itembonuses.MeleeMitigationEffect + defender->aabonuses.MeleeMitigationEffect) / 100);
|
||||
}
|
||||
|
||||
if (damage < 0)
|
||||
@@ -755,7 +757,7 @@ int32 Mob::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit,
|
||||
damage -= ((int)d * interval);
|
||||
|
||||
damage -= (minhit * itembonuses.MeleeMitigation / 100);
|
||||
damage -= (damage * spellbonuses.MeleeMitigation / 100);
|
||||
damage -= (damage * (spellbonuses.MeleeMitigationEffect + itembonuses.MeleeMitigationEffect + aabonuses.MeleeMitigationEffect) / 100);
|
||||
return damage;
|
||||
}
|
||||
|
||||
@@ -769,7 +771,7 @@ int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit,
|
||||
// floats for the rounding issues
|
||||
float dmg_interval = (damage - minhit) / 19.0;
|
||||
float dmg_bonus = minhit - dmg_interval;
|
||||
float spellMeleeMit = spellbonuses.MeleeMitigation / 100.0;
|
||||
float spellMeleeMit = (spellbonuses.MeleeMitigationEffect + itembonuses.MeleeMitigationEffect + aabonuses.MeleeMitigationEffect) / 100.0;
|
||||
if (GetClass() == WARRIOR)
|
||||
spellMeleeMit += 0.05;
|
||||
dmg_bonus -= dmg_bonus * (itembonuses.MeleeMitigation / 100.0);
|
||||
@@ -960,7 +962,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate
|
||||
dmg = weapon_item->GetItem()->Damage;
|
||||
}
|
||||
|
||||
for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){
|
||||
for(int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){
|
||||
if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){
|
||||
dmg += weapon_item->GetAugment(x)->GetItem()->Damage;
|
||||
if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt;
|
||||
@@ -997,7 +999,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate
|
||||
dmg = weapon_item->GetItem()->Damage;
|
||||
}
|
||||
|
||||
for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){
|
||||
for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){
|
||||
if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){
|
||||
dmg += weapon_item->GetAugment(x)->GetItem()->Damage;
|
||||
if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt;
|
||||
@@ -1034,7 +1036,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate
|
||||
}
|
||||
|
||||
if(weapon_item){
|
||||
for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){
|
||||
for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){
|
||||
if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){
|
||||
if(weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt)
|
||||
eledmg += (weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt * against->ResistSpell(weapon_item->GetAugment(x)->GetItem()->ElemDmgType, 0, this) / 100);
|
||||
@@ -1063,7 +1065,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate
|
||||
}
|
||||
}
|
||||
|
||||
for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){
|
||||
for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){
|
||||
if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){
|
||||
if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){
|
||||
banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt;
|
||||
@@ -1108,7 +1110,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate
|
||||
}
|
||||
}
|
||||
|
||||
for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){
|
||||
for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){
|
||||
if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){
|
||||
if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){
|
||||
banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt;
|
||||
@@ -1170,12 +1172,12 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
|
||||
|
||||
ItemInst* weapon;
|
||||
if (Hand == 14){ // Kaiyodo - Pick weapon from the attacking hand
|
||||
weapon = GetInv().GetItem(SLOT_SECONDARY);
|
||||
if (Hand == MainSecondary){ // Kaiyodo - Pick weapon from the attacking hand
|
||||
weapon = GetInv().GetItem(MainSecondary);
|
||||
OffHandAtk(true);
|
||||
}
|
||||
else{
|
||||
weapon = GetInv().GetItem(SLOT_PRIMARY);
|
||||
weapon = GetInv().GetItem(MainPrimary);
|
||||
OffHandAtk(false);
|
||||
}
|
||||
|
||||
@@ -1244,7 +1246,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
|
||||
int ucDamageBonus = 0;
|
||||
|
||||
if( Hand == 13 && GetLevel() >= 28 && IsWarriorClass() )
|
||||
if( Hand == MainPrimary && GetLevel() >= 28 && IsWarriorClass() )
|
||||
{
|
||||
// Damage bonuses apply only to hits from the main hand (Hand == 13) by characters level 28 and above
|
||||
// who belong to a melee class. If we're here, then all of these conditions apply.
|
||||
@@ -1257,7 +1259,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
}
|
||||
#endif
|
||||
//Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon.
|
||||
if (Hand==14) {
|
||||
if (Hand == MainSecondary) {
|
||||
if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){
|
||||
|
||||
ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr );
|
||||
@@ -1297,11 +1299,9 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
} else { //we hit, try to avoid it
|
||||
other->AvoidDamage(this, damage);
|
||||
other->MeleeMitigation(this, damage, min_hit, opts);
|
||||
if(damage > 0) {
|
||||
ApplyMeleeDamageBonus(skillinuse, damage);
|
||||
damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse);
|
||||
TryCriticalHit(other, skillinuse, damage, opts);
|
||||
}
|
||||
if(damage > 0)
|
||||
CommonOutgoingHitSuccess(other, damage, skillinuse);
|
||||
|
||||
mlog(COMBAT__DAMAGE, "Final damage after all reductions: %d", damage);
|
||||
}
|
||||
|
||||
@@ -1310,7 +1310,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
if (damage == -3) {
|
||||
if (bRiposte) return false;
|
||||
else {
|
||||
if (Hand == 14) {// Do we even have it & was attack with mainhand? If not, don't bother with other calculations
|
||||
if (Hand == MainSecondary) {// Do we even have it & was attack with mainhand? If not, don't bother with other calculations
|
||||
//Live AA - SlipperyAttacks
|
||||
//This spell effect most likely directly modifies the actual riposte chance when using offhand attack.
|
||||
int16 OffhandRiposteFail = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail;
|
||||
@@ -1365,39 +1365,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
TrySkillProc(other, skillinuse, 0, true, Hand);
|
||||
}
|
||||
|
||||
//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 (spellbonuses.NegateIfCombat)
|
||||
BuffFadeByEffect(SE_NegateIfCombat);
|
||||
|
||||
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);
|
||||
}
|
||||
CommonBreakInvisible();
|
||||
|
||||
if(GetTarget())
|
||||
TriggerDefensiveProcs(weapon, other, Hand, damage);
|
||||
@@ -1775,28 +1743,28 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
FaceTarget(GetTarget());
|
||||
|
||||
SkillUseTypes skillinuse = SkillHandtoHand;
|
||||
if (Hand == 13) {
|
||||
if (Hand == MainPrimary) {
|
||||
skillinuse = static_cast<SkillUseTypes>(GetPrimSkill());
|
||||
OffHandAtk(false);
|
||||
}
|
||||
if (Hand == 14) {
|
||||
if (Hand == MainSecondary) {
|
||||
skillinuse = static_cast<SkillUseTypes>(GetSecSkill());
|
||||
OffHandAtk(true);
|
||||
}
|
||||
|
||||
//figure out what weapon they are using, if any
|
||||
const Item_Struct* weapon = nullptr;
|
||||
if (Hand == 13 && equipment[SLOT_PRIMARY] > 0)
|
||||
weapon = database.GetItem(equipment[SLOT_PRIMARY]);
|
||||
else if (equipment[SLOT_SECONDARY])
|
||||
weapon = database.GetItem(equipment[SLOT_SECONDARY]);
|
||||
if (Hand == MainPrimary && equipment[MainPrimary] > 0)
|
||||
weapon = database.GetItem(equipment[MainPrimary]);
|
||||
else if (equipment[MainSecondary])
|
||||
weapon = database.GetItem(equipment[MainSecondary]);
|
||||
|
||||
//We dont factor much from the weapon into the attack.
|
||||
//Just the skill type so it doesn't look silly using punching animations and stuff while wielding weapons
|
||||
if(weapon) {
|
||||
mlog(COMBAT__ATTACKS, "Attacking with weapon: %s (%d) (too bad im not using it for much)", weapon->Name, weapon->ID);
|
||||
|
||||
if(Hand == 14 && weapon->ItemType == ItemTypeShield){
|
||||
if(Hand == MainSecondary && weapon->ItemType == ItemTypeShield){
|
||||
mlog(COMBAT__ATTACKS, "Attack with shield canceled.");
|
||||
return false;
|
||||
}
|
||||
@@ -1933,16 +1901,12 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
other->AvoidDamage(this, damage);
|
||||
other->MeleeMitigation(this, damage, min_dmg+eleBane, opts);
|
||||
if(damage > 0) {
|
||||
ApplyMeleeDamageBonus(skillinuse, damage);
|
||||
damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse);
|
||||
TryCriticalHit(other, skillinuse, damage, opts);
|
||||
CommonOutgoingHitSuccess(other, damage, skillinuse);
|
||||
}
|
||||
mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, GetName());
|
||||
// now add done damage to the hate list
|
||||
if(damage > 0)
|
||||
{
|
||||
other->AddToHateList(this, hate);
|
||||
}
|
||||
else
|
||||
other->AddToHateList(this, 0);
|
||||
}
|
||||
@@ -1964,10 +1928,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
return false;
|
||||
}
|
||||
|
||||
int16 DeathHP = 0;
|
||||
DeathHP = other->GetDelayDeath() * -1;
|
||||
|
||||
if(GetHP() > 0 && other->GetHP() >= DeathHP) {
|
||||
if(GetHP() > 0 && !other->HasDied()) {
|
||||
other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, false); // Not avoidable client already had thier chance to Avoid
|
||||
} else
|
||||
return false;
|
||||
@@ -1977,59 +1938,24 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
|
||||
MeleeLifeTap(damage);
|
||||
|
||||
if (damage > 0)
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
|
||||
//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 (spellbonuses.NegateIfCombat)
|
||||
BuffFadeByEffect(SE_NegateIfCombat);
|
||||
|
||||
if(hidden || improved_hidden)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
hidden = false;
|
||||
improved_hidden = false;
|
||||
CommonBreakInvisible();
|
||||
|
||||
//I doubt this works...
|
||||
if (!GetTarget())
|
||||
return true; //We killed them
|
||||
|
||||
if(!bRiposte && other && other->GetHP() > 0) {
|
||||
if(!bRiposte && !other->HasDied()) {
|
||||
TryWeaponProc(nullptr, weapon, other, Hand); //no weapon
|
||||
TrySpellProc(nullptr, weapon, other, Hand);
|
||||
|
||||
if (damage > 0 && HasSkillProcSuccess())
|
||||
if (!other->HasDied())
|
||||
TrySpellProc(nullptr, weapon, other, Hand);
|
||||
|
||||
if (damage > 0 && HasSkillProcSuccess() && !other->HasDied())
|
||||
TrySkillProc(other, skillinuse, 0, true, Hand);
|
||||
}
|
||||
|
||||
TriggerDefensiveProcs(nullptr, other, Hand, damage);
|
||||
if(GetHP() > 0 && !other->HasDied())
|
||||
TriggerDefensiveProcs(nullptr, other, Hand, damage);
|
||||
|
||||
// now check ripostes
|
||||
if (damage == -3) { // riposting
|
||||
@@ -3923,12 +3849,12 @@ void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id)
|
||||
}
|
||||
|
||||
//proc chance includes proc bonus
|
||||
float Mob::GetProcChances(float ProcBonus, uint16 weapon_speed, uint16 hand)
|
||||
float Mob::GetProcChances(float ProcBonus, uint16 hand)
|
||||
{
|
||||
int mydex = GetDEX();
|
||||
float ProcChance = 0.0f;
|
||||
|
||||
weapon_speed = GetWeaponSpeedbyHand(hand);
|
||||
uint16 weapon_speed = GetWeaponSpeedbyHand(hand);
|
||||
|
||||
if (RuleB(Combat, AdjustProcPerMinute)) {
|
||||
ProcChance = (static_cast<float>(weapon_speed) *
|
||||
@@ -3945,12 +3871,16 @@ float Mob::GetProcChances(float ProcBonus, uint16 weapon_speed, uint16 hand)
|
||||
return ProcChance;
|
||||
}
|
||||
|
||||
float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed, uint16 hand) {
|
||||
int myagi = GetAGI();
|
||||
float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand, Mob* on) {
|
||||
|
||||
if (!on)
|
||||
return ProcChance;
|
||||
|
||||
int myagi = on->GetAGI();
|
||||
ProcBonus = 0;
|
||||
ProcChance = 0;
|
||||
|
||||
weapon_speed = GetWeaponSpeedbyHand(hand);
|
||||
uint16 weapon_speed = GetWeaponSpeedbyHand(hand);
|
||||
|
||||
ProcChance = (static_cast<float>(weapon_speed) * RuleR(Combat, AvgDefProcsPerMinute) / 60000.0f); // compensate for weapon_speed being in ms
|
||||
ProcBonus += static_cast<float>(myagi) * RuleR(Combat, DefProcPerMinAgiContrib) / 100.0f;
|
||||
@@ -3960,7 +3890,7 @@ float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 w
|
||||
return ProcChance;
|
||||
}
|
||||
|
||||
void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand, int damage) {
|
||||
void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) {
|
||||
|
||||
if (!on) {
|
||||
SetTarget(nullptr);
|
||||
@@ -3974,10 +3904,8 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand, int dam
|
||||
return;
|
||||
|
||||
float ProcChance, ProcBonus;
|
||||
if(weapon!=nullptr)
|
||||
on->GetDefensiveProcChances(ProcBonus, ProcChance, weapon->GetItem()->Delay, hand);
|
||||
else
|
||||
on->GetDefensiveProcChances(ProcBonus, ProcChance);
|
||||
on->GetDefensiveProcChances(ProcBonus, ProcChance, hand , this);
|
||||
|
||||
if(hand != 13)
|
||||
ProcChance /= 2;
|
||||
|
||||
@@ -4035,7 +3963,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
|
||||
float ProcBonus = static_cast<float>(aabonuses.ProcChanceSPA +
|
||||
spellbonuses.ProcChanceSPA + itembonuses.ProcChanceSPA);
|
||||
ProcBonus += static_cast<float>(itembonuses.ProcChance) / 10.0f; // Combat Effects
|
||||
float ProcChance = GetProcChances(ProcBonus, weapon->Delay, hand);
|
||||
float ProcChance = GetProcChances(ProcBonus, hand);
|
||||
|
||||
if (hand != 13) //Is Archery intened to proc at 50% rate?
|
||||
ProcChance /= 2;
|
||||
@@ -4074,7 +4002,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
|
||||
proced = false;
|
||||
|
||||
if (!proced && inst) {
|
||||
for (int r = 0; r < MAX_AUGMENT_SLOTS; r++) {
|
||||
for (int r = 0; r < EmuConstants::ITEM_COMMON_SIZE; r++) {
|
||||
const ItemInst *aug_i = inst->GetAugment(r);
|
||||
if (!aug_i) // no aug, try next slot!
|
||||
continue;
|
||||
@@ -4113,16 +4041,13 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
|
||||
float ProcBonus = static_cast<float>(spellbonuses.SpellProcChance +
|
||||
itembonuses.SpellProcChance + aabonuses.SpellProcChance);
|
||||
float ProcChance = 0.0f;
|
||||
if (weapon)
|
||||
ProcChance = GetProcChances(ProcBonus, weapon->Delay, hand);
|
||||
else
|
||||
ProcChance = GetProcChances(ProcBonus);
|
||||
ProcChance = GetProcChances(ProcBonus, hand);
|
||||
|
||||
if (hand != 13) //Is Archery intened to proc at 50% rate?
|
||||
if (hand != MainPrimary) //Is Archery intened to proc at 50% rate?
|
||||
ProcChance /= 2;
|
||||
|
||||
bool rangedattk = false;
|
||||
if (weapon && hand == 11) {
|
||||
if (weapon && hand == MainRange) {
|
||||
if (weapon->ItemType == ItemTypeArrow ||
|
||||
weapon->ItemType == ItemTypeLargeThrowing ||
|
||||
weapon->ItemType == ItemTypeSmallThrowing ||
|
||||
@@ -4130,8 +4055,11 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
|
||||
rangedattk = true;
|
||||
}
|
||||
|
||||
if (!weapon && hand == MainRange && GetSpecialAbility(SPECATK_RANGED_ATK))
|
||||
rangedattk = true;
|
||||
|
||||
for (uint32 i = 0; i < MAX_PROCS; i++) {
|
||||
if (IsPet() && hand != 13) //Pets can only proc spell procs from their primay hand (ie; beastlord pets)
|
||||
if (IsPet() && hand != MainPrimary) //Pets can only proc spell procs from their primay hand (ie; beastlord pets)
|
||||
continue; // If pets ever can proc from off hand, this will need to change
|
||||
|
||||
// Not ranged
|
||||
@@ -4152,7 +4080,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
|
||||
|
||||
// Spell procs (buffs)
|
||||
if (SpellProcs[i].spellID != SPELL_UNKNOWN) {
|
||||
float chance = ProcChance * (SpellProcs[i].chance / 100.0f);
|
||||
float chance = ProcChance * (static_cast<float>(SpellProcs[i].chance) / 100.0f);
|
||||
if (MakeRandomFloat(0, 1) <= chance) {
|
||||
mlog(COMBAT__PROCS,
|
||||
"Spell proc %d procing spell %d (%.2f percent chance)",
|
||||
@@ -4168,8 +4096,8 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
|
||||
} else if (rangedattk) { // ranged only
|
||||
// ranged spell procs (buffs)
|
||||
if (RangedProcs[i].spellID != SPELL_UNKNOWN) {
|
||||
float chance = ProcChance * (RangedProcs[i].chance / 100.0f);
|
||||
if (MakeRandomFloat(0, 1) <= chance) {
|
||||
float chance = ProcChance * (static_cast<float>(RangedProcs[i].chance) / 100.0f);
|
||||
if (MakeRandomFloat(0, 1) <= chance) {
|
||||
mlog(COMBAT__PROCS,
|
||||
"Ranged proc %d procing spell %d (%.2f percent chance)",
|
||||
i, RangedProcs[i].spellID, chance);
|
||||
@@ -4184,7 +4112,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
|
||||
}
|
||||
}
|
||||
|
||||
if (HasSkillProcs() && hand != 11){ //We check ranged skill procs within the attack functions.
|
||||
if (HasSkillProcs() && hand != MainRange){ //We check ranged skill procs within the attack functions.
|
||||
uint16 skillinuse = 28;
|
||||
if (weapon)
|
||||
skillinuse = GetSkillByItemType(weapon->ItemType);
|
||||
@@ -4430,7 +4358,7 @@ void Mob::DoRiposte(Mob* defender) {
|
||||
if (!defender)
|
||||
return;
|
||||
|
||||
defender->Attack(this, SLOT_PRIMARY, true);
|
||||
defender->Attack(this, MainPrimary, true);
|
||||
if (HasDied()) return;
|
||||
|
||||
int16 DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[0] +
|
||||
@@ -4444,7 +4372,7 @@ void Mob::DoRiposte(Mob* defender) {
|
||||
//Live AA - Double Riposte
|
||||
if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) {
|
||||
mlog(COMBAT__ATTACKS, "Preforming a double riposed (%d percent chance)", DoubleRipChance);
|
||||
defender->Attack(this, SLOT_PRIMARY, true);
|
||||
defender->Attack(this, MainPrimary, true);
|
||||
if (HasDied()) return;
|
||||
}
|
||||
|
||||
@@ -4820,3 +4748,56 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
|
||||
return damage;
|
||||
}
|
||||
|
||||
void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse)
|
||||
{
|
||||
if (!defender)
|
||||
return;
|
||||
|
||||
ApplyMeleeDamageBonus(skillInUse, damage);
|
||||
damage += (damage * defender->GetSkillDmgTaken(skillInUse) / 100) + (GetSkillDmgAmt(skillInUse) + defender->GetFcDamageAmtIncoming(this, 0, true, skillInUse));
|
||||
TryCriticalHit(defender, skillInUse, damage);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
}
|
||||
|
||||
void Mob::CommonBreakInvisible()
|
||||
{
|
||||
//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 (spellbonuses.NegateIfCombat)
|
||||
BuffFadeByEffect(SE_NegateIfCombat);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (spellbonuses.NegateIfCombat)
|
||||
BuffFadeByEffect(SE_NegateIfCombat);
|
||||
|
||||
hidden = false;
|
||||
improved_hidden = false;
|
||||
}
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ public:
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; }
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; }
|
||||
virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
|
||||
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
|
||||
ExtraAttackOptions *opts = nullptr) { return false; }
|
||||
virtual bool HasRaid() { return false; }
|
||||
virtual bool HasGroup() { return false; }
|
||||
|
||||
+39
-29
@@ -139,28 +139,28 @@ void Client::CalcItemBonuses(StatBonuses* newbon) {
|
||||
|
||||
unsigned int i;
|
||||
//should not include 21 (SLOT_AMMO)
|
||||
for (i=0; i<21; i++) {
|
||||
for (i = MainCharm; i < MainAmmo; i++) {
|
||||
const ItemInst* inst = m_inv[i];
|
||||
if(inst == 0)
|
||||
continue;
|
||||
AddItemBonuses(inst, newbon);
|
||||
|
||||
//Check if item is secondary slot is a 'shield'. Required for multiple spelll effects.
|
||||
if (i == 14 && (m_inv.GetItem(14)->GetItem()->ItemType == ItemTypeShield))
|
||||
if (i == MainSecondary && (m_inv.GetItem(MainSecondary)->GetItem()->ItemType == ItemTypeShield))
|
||||
ShieldEquiped(true);
|
||||
}
|
||||
|
||||
//Power Source Slot
|
||||
if (GetClientVersion() >= EQClientSoF)
|
||||
{
|
||||
const ItemInst* inst = m_inv[9999];
|
||||
const ItemInst* inst = m_inv[MainPowerSource];
|
||||
if(inst)
|
||||
AddItemBonuses(inst, newbon);
|
||||
}
|
||||
|
||||
//tribute items
|
||||
for (i = 0; i < MAX_PLAYER_TRIBUTES; i++) {
|
||||
const ItemInst* inst = m_inv[TRIBUTE_SLOT_START + i];
|
||||
for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++) {
|
||||
const ItemInst* inst = m_inv[EmuConstants::TRIBUTE_BEGIN + i];
|
||||
if(inst == 0)
|
||||
continue;
|
||||
AddItemBonuses(inst, newbon, false, true);
|
||||
@@ -528,7 +528,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu
|
||||
if (!isAug)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < MAX_AUGMENT_SLOTS; i++) {
|
||||
for (i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
AddItemBonuses(inst->GetAugment(i),newbon,true);
|
||||
}
|
||||
}
|
||||
@@ -544,7 +544,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) {
|
||||
|
||||
bool food = false;
|
||||
bool drink = false;
|
||||
for (i = 22; i <= 29; i++)
|
||||
for (i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_BAGS_BEGIN; i++)
|
||||
{
|
||||
if (food && drink)
|
||||
break;
|
||||
@@ -560,7 +560,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) {
|
||||
AddItemBonuses(inst, newbon);
|
||||
}
|
||||
}
|
||||
for (i = 251; i <= 330; i++)
|
||||
for (i = EmuConstants::GENERAL_BAGS_BEGIN; i <= EmuConstants::GENERAL_BAGS_END; i++)
|
||||
{
|
||||
if (food && drink)
|
||||
break;
|
||||
@@ -879,7 +879,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
newbon->PetMaxHP += base1;
|
||||
break;
|
||||
case SE_AvoidMeleeChance:
|
||||
newbon->AvoidMeleeChance += base1;
|
||||
newbon->AvoidMeleeChanceEffect += base1;
|
||||
break;
|
||||
case SE_CombatStability:
|
||||
newbon->CombatStability += base1;
|
||||
@@ -974,7 +974,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
newbon->FlurryChance += base1;
|
||||
break;
|
||||
case SE_PetFlurry:
|
||||
newbon->PetFlurry = base1;
|
||||
newbon->PetFlurry += base1;
|
||||
break;
|
||||
case SE_BardSongRange:
|
||||
newbon->SongRange += base1;
|
||||
@@ -989,6 +989,14 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
newbon->CrippBlowChance += base1;
|
||||
break;
|
||||
|
||||
case SE_HitChance:
|
||||
{
|
||||
if(base2 == -1)
|
||||
newbon->HitChanceEffect[HIGHEST_SKILL+1] += base1;
|
||||
else
|
||||
newbon->HitChanceEffect[base2] += base1;
|
||||
}
|
||||
|
||||
case SE_ProcOnKillShot:
|
||||
for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3)
|
||||
{
|
||||
@@ -1368,6 +1376,10 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_MeleeMitigation:
|
||||
newbon->MeleeMitigationEffect -= base1;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1788,7 +1800,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
case SE_MeleeMitigation:
|
||||
//for some reason... this value is negative for increased mitigation
|
||||
newbon->MeleeMitigation -= effect_value;
|
||||
newbon->MeleeMitigationEffect -= effect_value;
|
||||
break;
|
||||
|
||||
case SE_CriticalHitChance:
|
||||
@@ -1833,16 +1845,14 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
case SE_AvoidMeleeChance:
|
||||
{
|
||||
//multiplier is to be compatible with item effects, watching for overflow too
|
||||
effect_value = effect_value<3000? effect_value * 10 : 30000;
|
||||
if (RuleB(Spells, AdditiveBonusValues) && item_bonus)
|
||||
newbon->AvoidMeleeChance += effect_value;
|
||||
newbon->AvoidMeleeChanceEffect += effect_value;
|
||||
|
||||
else if((effect_value < 0) && (newbon->AvoidMeleeChance > effect_value))
|
||||
newbon->AvoidMeleeChance = effect_value;
|
||||
else if((effect_value < 0) && (newbon->AvoidMeleeChanceEffect > effect_value))
|
||||
newbon->AvoidMeleeChanceEffect = effect_value;
|
||||
|
||||
else if(newbon->AvoidMeleeChance < effect_value)
|
||||
newbon->AvoidMeleeChance = effect_value;
|
||||
else if(newbon->AvoidMeleeChanceEffect < effect_value)
|
||||
newbon->AvoidMeleeChanceEffect = effect_value;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2972,7 +2982,7 @@ void NPC::CalcItemBonuses(StatBonuses *newbon)
|
||||
{
|
||||
if(newbon){
|
||||
|
||||
for(int i = 0; i < MAX_WORN_INVENTORY; i++){
|
||||
for(int i = 0; i < EmuConstants::EQUIPMENT_SIZE; i++){
|
||||
const Item_Struct *cur = database.GetItem(equipment[i]);
|
||||
if(cur){
|
||||
//basic stats
|
||||
@@ -3091,7 +3101,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y)
|
||||
}
|
||||
|
||||
//iterate all augments
|
||||
for(int x = 0; x < MAX_AUGMENT_SLOTS; ++x)
|
||||
for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; ++x)
|
||||
{
|
||||
ItemInst * a_inst = inst->GetAugment(x);
|
||||
if(!a_inst)
|
||||
@@ -3160,7 +3170,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) {
|
||||
uint16 oldexp = inst->GetExp();
|
||||
|
||||
parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0);
|
||||
if(i < 22 || i == 9999) {
|
||||
if(i <= MainAmmo || i == MainPowerSource) {
|
||||
parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i);
|
||||
}
|
||||
|
||||
@@ -3170,7 +3180,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) {
|
||||
update_slot = true;
|
||||
}
|
||||
} else {
|
||||
if(i < 22 || i == 9999) {
|
||||
if(i <= MainAmmo || i == MainPowerSource) {
|
||||
parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i);
|
||||
}
|
||||
|
||||
@@ -3178,7 +3188,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) {
|
||||
}
|
||||
|
||||
//iterate all augments
|
||||
for(int x = 0; x < MAX_AUGMENT_SLOTS; ++x)
|
||||
for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; ++x)
|
||||
{
|
||||
ItemInst *a_inst = inst->GetAugment(x);
|
||||
if(!a_inst)
|
||||
@@ -3588,9 +3598,9 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_MeleeMitigation:
|
||||
spellbonuses.MeleeMitigation = effect_value;
|
||||
itembonuses.MeleeMitigation = effect_value;
|
||||
aabonuses.MeleeMitigation = effect_value;
|
||||
spellbonuses.MeleeMitigationEffect = effect_value;
|
||||
itembonuses.MeleeMitigationEffect = effect_value;
|
||||
aabonuses.MeleeMitigationEffect = effect_value;
|
||||
break;
|
||||
|
||||
case SE_CriticalHitChance:
|
||||
@@ -3610,9 +3620,9 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_AvoidMeleeChance:
|
||||
spellbonuses.AvoidMeleeChance = effect_value;
|
||||
aabonuses.AvoidMeleeChance = effect_value;
|
||||
itembonuses.AvoidMeleeChance = effect_value;
|
||||
spellbonuses.AvoidMeleeChanceEffect = effect_value;
|
||||
aabonuses.AvoidMeleeChanceEffect = effect_value;
|
||||
itembonuses.AvoidMeleeChanceEffect = effect_value;
|
||||
break;
|
||||
|
||||
case SE_RiposteChance:
|
||||
|
||||
+180
-175
@@ -237,7 +237,7 @@ void Bot::SetBotSpellID(uint32 newSpellID) {
|
||||
uint32 Bot::GetBotArcheryRange() {
|
||||
uint32 result = 0;
|
||||
|
||||
ItemInst* rangeItem = GetBotItem(SLOT_RANGE);
|
||||
ItemInst* rangeItem = GetBotItem(MainRange);
|
||||
|
||||
if(!rangeItem)
|
||||
return 0;
|
||||
@@ -257,7 +257,7 @@ uint32 Bot::GetBotArcheryRange() {
|
||||
archeryColor = botweapon->Color;
|
||||
range =+ botweapon->Range;
|
||||
|
||||
rangeItem = GetBotItem(SLOT_AMMO);
|
||||
rangeItem = GetBotItem(MainAmmo);
|
||||
if(rangeItem)
|
||||
botweapon = rangeItem->GetItem();
|
||||
|
||||
@@ -280,8 +280,8 @@ void Bot::ChangeBotArcherWeapons(bool isArcher) {
|
||||
|| (GetClass()==SHADOWKNIGHT) || (GetClass()==ROGUE))
|
||||
{
|
||||
if(!isArcher) {
|
||||
BotAddEquipItem(SLOT_PRIMARY, GetBotItemBySlot(SLOT_PRIMARY));
|
||||
BotAddEquipItem(SLOT_SECONDARY, GetBotItemBySlot(SLOT_SECONDARY));
|
||||
BotAddEquipItem(MainPrimary, GetBotItemBySlot(MainPrimary));
|
||||
BotAddEquipItem(MainSecondary, GetBotItemBySlot(MainSecondary));
|
||||
//archerbot->SendWearChange(MATERIAL_PRIMARY);
|
||||
//archerbot->SendWearChange(MATERIAL_SECONDARY);
|
||||
SetAttackTimer();
|
||||
@@ -290,11 +290,11 @@ void Bot::ChangeBotArcherWeapons(bool isArcher) {
|
||||
else {
|
||||
//archerbot->SendWearChange(MATERIAL_PRIMARY);
|
||||
//archerbot->SendWearChange(MATERIAL_SECONDARY);
|
||||
BotRemoveEquipItem(SLOT_PRIMARY);
|
||||
BotRemoveEquipItem(SLOT_SECONDARY);
|
||||
BotRemoveEquipItem(MainPrimary);
|
||||
BotRemoveEquipItem(MainSecondary);
|
||||
//archerbot->SendBotArcheryWearChange(MATERIAL_PRIMARY, archeryMaterial, archeryColor);
|
||||
BotAddEquipItem(SLOT_AMMO, GetBotItemBySlot(SLOT_AMMO));
|
||||
BotAddEquipItem(SLOT_SECONDARY, GetBotItemBySlot(SLOT_RANGE));
|
||||
BotAddEquipItem(MainAmmo, GetBotItemBySlot(MainAmmo));
|
||||
BotAddEquipItem(MainSecondary, GetBotItemBySlot(MainRange));
|
||||
SetAttackTimer();
|
||||
Say("My bow is true and ready.");
|
||||
}
|
||||
@@ -1291,7 +1291,7 @@ void Bot::GenerateArmorClass()
|
||||
uint16 Bot::GetPrimarySkillValue()
|
||||
{
|
||||
SkillUseTypes skill = HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill
|
||||
bool equiped = m_inv.GetItem(SLOT_PRIMARY);
|
||||
bool equiped = m_inv.GetItem(MainPrimary);
|
||||
|
||||
if(!equiped)
|
||||
{
|
||||
@@ -1299,7 +1299,7 @@ uint16 Bot::GetPrimarySkillValue()
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 type = m_inv.GetItem(SLOT_PRIMARY)->GetItem()->ItemType; //is this the best way to do this?
|
||||
uint8 type = m_inv.GetItem(MainPrimary)->GetItem()->ItemType; //is this the best way to do this?
|
||||
switch(type)
|
||||
{
|
||||
case ItemType1HSlash: // 1H Slashing
|
||||
@@ -2630,7 +2630,7 @@ void Bot::LoadPet() {
|
||||
NPC *pet = GetPet()->CastToNPC();
|
||||
SpellBuff_Struct petBuffs[BUFF_COUNT];
|
||||
memset(petBuffs, 0, sizeof(petBuffs));
|
||||
uint32 petItems[MAX_WORN_INVENTORY];
|
||||
uint32 petItems[EmuConstants::EQUIPMENT_SIZE];
|
||||
|
||||
LoadPetBuffs(petBuffs, PetSaveId);
|
||||
LoadPetItems(petItems, PetSaveId);
|
||||
@@ -2747,7 +2747,7 @@ void Bot::LoadPetItems(uint32* petItems, uint32 botPetSaveId) {
|
||||
int ItemCount = 0;
|
||||
|
||||
while(DataRow = mysql_fetch_row(DatasetResult)) {
|
||||
if(ItemCount == MAX_WORN_INVENTORY)
|
||||
if(ItemCount == EmuConstants::EQUIPMENT_SIZE)
|
||||
break;
|
||||
|
||||
petItems[ItemCount] = atoi(DataRow[0]);
|
||||
@@ -2785,7 +2785,7 @@ void Bot::SavePet() {
|
||||
uint32 botPetId = pet->CastToNPC()->GetPetSpellID();
|
||||
char* tempPetName = new char[64];
|
||||
SpellBuff_Struct petBuffs[BUFF_COUNT];
|
||||
uint32 petItems[MAX_WORN_INVENTORY];
|
||||
uint32 petItems[EmuConstants::EQUIPMENT_SIZE];
|
||||
|
||||
pet->GetPetState(petBuffs, petItems, tempPetName);
|
||||
|
||||
@@ -2867,7 +2867,7 @@ void Bot::SavePetItems(uint32* petItems, uint32 botPetSaveId) {
|
||||
char TempErrorMessageBuffer[MYSQL_ERRMSG_SIZE];
|
||||
int ItemCount = 0;
|
||||
|
||||
while(ItemCount < MAX_WORN_INVENTORY) {
|
||||
while (ItemCount < EmuConstants::EQUIPMENT_SIZE) {
|
||||
if(petItems[ItemCount] > 0) {
|
||||
if(!database.RunQuery(Query, MakeAnyLenString(&Query, "INSERT INTO botpetinventory (BotPetsId, ItemId) VALUES(%u, %u);", botPetSaveId, petItems[ItemCount]), TempErrorMessageBuffer)) {
|
||||
errorMessage = std::string(TempErrorMessageBuffer);
|
||||
@@ -3189,12 +3189,12 @@ void Bot::BotRangedAttack(Mob* other) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemInst* rangedItem = GetBotItem(SLOT_RANGE);
|
||||
ItemInst* rangedItem = GetBotItem(MainRange);
|
||||
const Item_Struct* RangeWeapon = 0;
|
||||
if(rangedItem)
|
||||
RangeWeapon = rangedItem->GetItem();
|
||||
|
||||
ItemInst* ammoItem = GetBotItem(SLOT_AMMO);
|
||||
ItemInst* ammoItem = GetBotItem(MainAmmo);
|
||||
const Item_Struct* Ammo = 0;
|
||||
if(ammoItem)
|
||||
Ammo = ammoItem->GetItem();
|
||||
@@ -3304,7 +3304,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
|
||||
int damage = 0;
|
||||
uint32 hate = 0;
|
||||
int Hand = 13;
|
||||
int Hand = MainPrimary;
|
||||
if (hate == 0 && weapon_damage > 1) hate = weapon_damage;
|
||||
|
||||
if(weapon_damage > 0){
|
||||
@@ -3363,7 +3363,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
damage = -5;
|
||||
|
||||
if(skillinuse == SkillBash){
|
||||
const ItemInst* inst = GetBotItem(SLOT_SECONDARY);
|
||||
const ItemInst* inst = GetBotItem(MainSecondary);
|
||||
const Item_Struct* botweapon = 0;
|
||||
if(inst)
|
||||
botweapon = inst->GetItem();
|
||||
@@ -3413,17 +3413,17 @@ void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg)
|
||||
case SkillFlyingKick:
|
||||
case SkillRoundKick:
|
||||
case SkillKick:
|
||||
item_slot = SLOT_FEET;
|
||||
item_slot = MainFeet;
|
||||
break;
|
||||
|
||||
case SkillBash:
|
||||
item_slot = SLOT_SECONDARY;
|
||||
item_slot = MainSecondary;
|
||||
break;
|
||||
|
||||
case SkillDragonPunch:
|
||||
case SkillEagleStrike:
|
||||
case SkillTigerClaw:
|
||||
item_slot = SLOT_HANDS;
|
||||
item_slot = MainHands;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3775,27 +3775,27 @@ void Bot::AI_Process() {
|
||||
|
||||
//try main hand first
|
||||
if(attack_timer.Check()) {
|
||||
Attack(GetTarget(), SLOT_PRIMARY);
|
||||
Attack(GetTarget(), MainPrimary);
|
||||
|
||||
ItemInst *wpn = GetBotItem(SLOT_PRIMARY);
|
||||
TryWeaponProc(wpn, GetTarget(), SLOT_PRIMARY);
|
||||
ItemInst *wpn = GetBotItem(MainPrimary);
|
||||
TryWeaponProc(wpn, GetTarget(), MainPrimary);
|
||||
|
||||
bool tripleSuccess = false;
|
||||
|
||||
if(BotOwner && GetTarget() && CanThisClassDoubleAttack()) {
|
||||
|
||||
if(BotOwner && CheckBotDoubleAttack()) {
|
||||
Attack(GetTarget(), SLOT_PRIMARY, true);
|
||||
Attack(GetTarget(), MainPrimary, true);
|
||||
}
|
||||
|
||||
if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_TRIPLE) && CheckBotDoubleAttack(true)) {
|
||||
tripleSuccess = true;
|
||||
Attack(GetTarget(), SLOT_PRIMARY, true);
|
||||
Attack(GetTarget(), MainPrimary, true);
|
||||
}
|
||||
|
||||
//quad attack, does this belong here??
|
||||
if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) {
|
||||
Attack(GetTarget(), SLOT_PRIMARY, true);
|
||||
Attack(GetTarget(), MainPrimary, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3807,15 +3807,15 @@ void Bot::AI_Process() {
|
||||
if(MakeRandomInt(0, 100) < flurrychance)
|
||||
{
|
||||
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
|
||||
Attack(GetTarget(), SLOT_PRIMARY, false);
|
||||
Attack(GetTarget(), SLOT_PRIMARY, false);
|
||||
Attack(GetTarget(), MainPrimary, false);
|
||||
Attack(GetTarget(), MainPrimary, false);
|
||||
}
|
||||
}
|
||||
|
||||
int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance;
|
||||
|
||||
if (GetTarget() && ExtraAttackChanceBonus) {
|
||||
ItemInst *wpn = GetBotItem(SLOT_PRIMARY);
|
||||
ItemInst *wpn = GetBotItem(MainPrimary);
|
||||
if(wpn){
|
||||
if(wpn->GetItem()->ItemType == ItemType2HSlash ||
|
||||
wpn->GetItem()->ItemType == ItemType2HBlunt ||
|
||||
@@ -3823,7 +3823,7 @@ void Bot::AI_Process() {
|
||||
{
|
||||
if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus)
|
||||
{
|
||||
Attack(GetTarget(), SLOT_PRIMARY, false);
|
||||
Attack(GetTarget(), MainPrimary, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3843,7 +3843,7 @@ void Bot::AI_Process() {
|
||||
|
||||
//now off hand
|
||||
if(GetTarget() && attack_dw_timer.Check() && CanThisClassDualWield()) {
|
||||
const ItemInst* instweapon = GetBotItem(SLOT_SECONDARY);
|
||||
const ItemInst* instweapon = GetBotItem(MainSecondary);
|
||||
const Item_Struct* weapon = 0;
|
||||
//can only dual wield without a weapon if you're a monk
|
||||
if(instweapon || (botClass == MONK)) {
|
||||
@@ -3870,14 +3870,14 @@ void Bot::AI_Process() {
|
||||
|
||||
if (random < DualWieldProbability){ // Max 78% of DW
|
||||
|
||||
Attack(GetTarget(), SLOT_SECONDARY); // Single attack with offhand
|
||||
Attack(GetTarget(), MainSecondary); // Single attack with offhand
|
||||
|
||||
ItemInst *wpn = GetBotItem(SLOT_SECONDARY);
|
||||
TryWeaponProc(wpn, GetTarget(), SLOT_SECONDARY);
|
||||
ItemInst *wpn = GetBotItem(MainSecondary);
|
||||
TryWeaponProc(wpn, GetTarget(), MainSecondary);
|
||||
|
||||
if( CanThisClassDoubleAttack() && CheckBotDoubleAttack()) {
|
||||
if(GetTarget() && GetTarget()->GetHP() > -10)
|
||||
Attack(GetTarget(), SLOT_SECONDARY); // Single attack with offhand
|
||||
Attack(GetTarget(), MainSecondary); // Single attack with offhand
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4096,14 +4096,14 @@ void Bot::PetAIProcess() {
|
||||
if(!botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY()) && botPet->GetTarget()->IsEnraged())
|
||||
return;
|
||||
|
||||
if(botPet->Attack(GetTarget(), SLOT_PRIMARY)) // try the main hand
|
||||
if(botPet->Attack(GetTarget(), MainPrimary)) // try the main hand
|
||||
if (botPet->GetTarget()) // Do we still have a target?
|
||||
{
|
||||
// We're a pet so we re able to dual attack
|
||||
int32 RandRoll = MakeRandomInt(0, 99);
|
||||
if (botPet->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier)))
|
||||
{
|
||||
if(botPet->Attack(botPet->GetTarget(), 13))
|
||||
if(botPet->Attack(botPet->GetTarget(), MainPrimary))
|
||||
{}
|
||||
}
|
||||
}
|
||||
@@ -4145,13 +4145,13 @@ void Bot::PetAIProcess() {
|
||||
float DualWieldProbability = (botPet->GetSkill(SkillDualWield) + botPet->GetLevel()) / 400.0f;
|
||||
DualWieldProbability -= MakeRandomFloat(0, 1);
|
||||
if(DualWieldProbability < 0){
|
||||
botPet->Attack(botPet->GetTarget(), 14);
|
||||
botPet->Attack(botPet->GetTarget(), MainSecondary);
|
||||
if (botPet->CanThisClassDoubleAttack())
|
||||
{
|
||||
int32 RandRoll = MakeRandomInt(0, 99);
|
||||
if (RandRoll < (botPet->GetLevel() + 20))
|
||||
{
|
||||
botPet->Attack(botPet->GetTarget(), 14);
|
||||
botPet->Attack(botPet->GetTarget(), MainSecondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4411,7 +4411,7 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) {
|
||||
|
||||
ItemInst* inst = database.CreateItem(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4]);
|
||||
if(inst) {
|
||||
int16 put_slot_id = SLOT_INVALID;
|
||||
int16 put_slot_id = INVALID_INDEX;
|
||||
if(instnodrop || ((slot_id >= 0) && (slot_id <= 21) && inst->GetItem()->Attuneable))
|
||||
inst->SetInstNoDrop(true);
|
||||
if(color > 0)
|
||||
@@ -4429,7 +4429,7 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) {
|
||||
safe_delete(inst);
|
||||
|
||||
// Save ptr to item in inventory
|
||||
if (put_slot_id == SLOT_INVALID) {
|
||||
if (put_slot_id == INVALID_INDEX) {
|
||||
LogFile->write(EQEMuLog::Error,
|
||||
"Warning: Invalid slot_id for item in inventory: botid=%i, item_id=%i, slot_id=%i",
|
||||
this->GetBotID(), item_id, slot_id);
|
||||
@@ -4595,7 +4595,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
|
||||
uint32 spawnedbotid = 0;
|
||||
spawnedbotid = this->GetBotID();
|
||||
|
||||
inst = GetBotItem(SLOT_HANDS);
|
||||
inst = GetBotItem(MainHands);
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
@@ -4604,7 +4604,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
|
||||
}
|
||||
}
|
||||
|
||||
inst = GetBotItem(SLOT_HEAD);
|
||||
inst = GetBotItem(MainHead);
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
@@ -4613,7 +4613,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
|
||||
}
|
||||
}
|
||||
|
||||
inst = GetBotItem(SLOT_ARMS);
|
||||
inst = GetBotItem(MainArms);
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
@@ -4622,7 +4622,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
|
||||
}
|
||||
}
|
||||
|
||||
inst = GetBotItem(SLOT_BRACER01);
|
||||
inst = GetBotItem(MainWrist1);
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
@@ -4631,7 +4631,9 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
|
||||
}
|
||||
}
|
||||
|
||||
inst = GetBotItem(SLOT_BRACER02);
|
||||
/*
|
||||
// non-live behavior
|
||||
inst = GetBotItem(MainWrist2);
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
@@ -4639,8 +4641,9 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
|
||||
ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
inst = GetBotItem(SLOT_CHEST);
|
||||
inst = GetBotItem(MainChest);
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
@@ -4649,7 +4652,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
|
||||
}
|
||||
}
|
||||
|
||||
inst = GetBotItem(SLOT_LEGS);
|
||||
inst = GetBotItem(MainLegs);
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
@@ -4658,7 +4661,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
|
||||
}
|
||||
}
|
||||
|
||||
inst = GetBotItem(SLOT_FEET);
|
||||
inst = GetBotItem(MainFeet);
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
@@ -4667,7 +4670,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
|
||||
}
|
||||
}
|
||||
|
||||
inst = GetBotItem(SLOT_PRIMARY);
|
||||
inst = GetBotItem(MainPrimary);
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
@@ -4677,7 +4680,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
|
||||
}
|
||||
}
|
||||
|
||||
inst = GetBotItem(SLOT_SECONDARY);
|
||||
inst = GetBotItem(MainSecondary);
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
@@ -6009,7 +6012,7 @@ void Bot::FinishTrade(Client* client, BotTradeType tradeType) {
|
||||
else if(tradeType == BotTradeClientNoDropNoTrade) {
|
||||
// Items being traded are found on the Client's cursor slot, slot id 30. This item can be either a single item or it can be a bag.
|
||||
// If it is a bag, then we have to search for items in slots 331 thru 340
|
||||
PerformTradeWithClient(SLOT_CURSOR, SLOT_CURSOR, client);
|
||||
PerformTradeWithClient(MainCursor, MainCursor, client);
|
||||
|
||||
// TODO: Add logic here to test if the item in SLOT_CURSOR is a container type, if it is then we need to call the following:
|
||||
// PerformTradeWithClient(331, 340, client);
|
||||
@@ -6038,7 +6041,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
|
||||
charges[i] = inst->GetCharges();
|
||||
}
|
||||
|
||||
if(i == SLOT_CURSOR)
|
||||
if (i == MainCursor)
|
||||
UpdateClient = true;
|
||||
|
||||
//EQoffline: will give the items to the bots and change the bot stats
|
||||
@@ -6046,7 +6049,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
|
||||
std::string TempErrorMessage;
|
||||
const Item_Struct* mWeaponItem = inst->GetItem();
|
||||
bool failedLoreCheck = false;
|
||||
for(int m=0; m<MAX_AUGMENT_SLOTS; ++m) {
|
||||
for (int m = 0; m<EmuConstants::ITEM_COMMON_SIZE; ++m) {
|
||||
ItemInst *itm = inst->GetAugment(m);
|
||||
if(itm)
|
||||
{
|
||||
@@ -6075,17 +6078,17 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
|
||||
if((mWeaponItem->Slots & (1 << j))) {
|
||||
how_many_slots++;
|
||||
if(!GetBotItem(j)) {
|
||||
if(j == SLOT_PRIMARY) {
|
||||
if(j == MainPrimary) {
|
||||
if((mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) {
|
||||
if(GetBotItem(SLOT_SECONDARY)) {
|
||||
if(GetBotItem(MainSecondary)) {
|
||||
if(mWeaponItem && (mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) {
|
||||
if(client->CheckLoreConflict(GetBotItem(SLOT_SECONDARY)->GetItem())) {
|
||||
if(client->CheckLoreConflict(GetBotItem(MainSecondary)->GetItem())) {
|
||||
failedLoreCheck = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ItemInst* remove_item = GetBotItem(SLOT_SECONDARY);
|
||||
BotTradeSwapItem(client, SLOT_SECONDARY, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false);
|
||||
ItemInst* remove_item = GetBotItem(MainSecondary);
|
||||
BotTradeSwapItem(client, MainSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6095,7 +6098,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if(j == SLOT_SECONDARY) {
|
||||
else if(j == MainSecondary) {
|
||||
if(inst->IsWeapon()) {
|
||||
if(CanThisClassDualWield()) {
|
||||
BotTradeAddItem(mWeaponItem->ID, inst, inst->GetCharges(), mWeaponItem->Slots, j, &TempErrorMessage);
|
||||
@@ -6111,10 +6114,10 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
|
||||
success = true;
|
||||
}
|
||||
if(success) {
|
||||
if(GetBotItem(SLOT_PRIMARY)) {
|
||||
ItemInst* remove_item = GetBotItem(SLOT_PRIMARY);
|
||||
if(GetBotItem(MainPrimary)) {
|
||||
ItemInst* remove_item = GetBotItem(MainPrimary);
|
||||
if((remove_item->GetItem()->ItemType == ItemType2HSlash) || (remove_item->GetItem()->ItemType == ItemType2HBlunt) || (remove_item->GetItem()->ItemType == ItemType2HPiercing)) {
|
||||
BotTradeSwapItem(client, SLOT_PRIMARY, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false);
|
||||
BotTradeSwapItem(client, MainPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -6133,7 +6136,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
|
||||
if((mWeaponItem->Slots & (1 << j))) {
|
||||
swap_item = GetBotItem(j);
|
||||
failedLoreCheck = false;
|
||||
for(int k=0; k<MAX_AUGMENT_SLOTS; ++k) {
|
||||
for (int k = 0; k<EmuConstants::ITEM_COMMON_SIZE; ++k) {
|
||||
ItemInst *itm = swap_item->GetAugment(k);
|
||||
if(itm)
|
||||
{
|
||||
@@ -6146,28 +6149,28 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
|
||||
failedLoreCheck = true;
|
||||
}
|
||||
if(!failedLoreCheck) {
|
||||
if(j == SLOT_PRIMARY) {
|
||||
if(j == MainPrimary) {
|
||||
if((mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) {
|
||||
if(GetBotItem(SLOT_SECONDARY)) {
|
||||
if(client->CheckLoreConflict(GetBotItem(SLOT_SECONDARY)->GetItem())) {
|
||||
if(GetBotItem(MainSecondary)) {
|
||||
if(client->CheckLoreConflict(GetBotItem(MainSecondary)->GetItem())) {
|
||||
failedLoreCheck = true;
|
||||
}
|
||||
else {
|
||||
ItemInst* remove_item = GetBotItem(SLOT_SECONDARY);
|
||||
BotTradeSwapItem(client, SLOT_SECONDARY, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false);
|
||||
ItemInst* remove_item = GetBotItem(MainSecondary);
|
||||
BotTradeSwapItem(client, MainSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!failedLoreCheck) {
|
||||
BotTradeSwapItem(client, SLOT_PRIMARY, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage);
|
||||
BotTradeSwapItem(client, MainPrimary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage);
|
||||
success = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if(j == SLOT_SECONDARY) {
|
||||
else if(j == MainSecondary) {
|
||||
if(inst->IsWeapon()) {
|
||||
if(CanThisClassDualWield()) {
|
||||
BotTradeSwapItem(client, SLOT_SECONDARY, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage);
|
||||
BotTradeSwapItem(client, MainSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage);
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
@@ -6176,13 +6179,13 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
|
||||
}
|
||||
}
|
||||
else {
|
||||
BotTradeSwapItem(client, SLOT_SECONDARY, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage);
|
||||
BotTradeSwapItem(client, MainSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage);
|
||||
success = true;
|
||||
}
|
||||
if(success && GetBotItem(SLOT_PRIMARY)) {
|
||||
ItemInst* remove_item = GetBotItem(SLOT_PRIMARY);
|
||||
if(success && GetBotItem(MainPrimary)) {
|
||||
ItemInst* remove_item = GetBotItem(MainPrimary);
|
||||
if((remove_item->GetItem()->ItemType == ItemType2HSlash) || (remove_item->GetItem()->ItemType == ItemType2HBlunt) || (remove_item->GetItem()->ItemType == ItemType2HPiercing)) {
|
||||
BotTradeSwapItem(client, SLOT_PRIMARY, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false);
|
||||
BotTradeSwapItem(client, MainPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -6441,12 +6444,12 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
|
||||
FaceTarget(GetTarget());
|
||||
|
||||
ItemInst* weapon = nullptr;
|
||||
if(Hand == SLOT_PRIMARY) {
|
||||
weapon = GetBotItem(SLOT_PRIMARY);
|
||||
if(Hand == MainPrimary) {
|
||||
weapon = GetBotItem(MainPrimary);
|
||||
OffHandAtk(false);
|
||||
}
|
||||
if(Hand == SLOT_SECONDARY) {
|
||||
weapon = GetBotItem(SLOT_SECONDARY);
|
||||
if(Hand == MainSecondary) {
|
||||
weapon = GetBotItem(MainSecondary);
|
||||
OffHandAtk(true);
|
||||
}
|
||||
|
||||
@@ -6513,7 +6516,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
|
||||
|
||||
int ucDamageBonus = 0;
|
||||
|
||||
if( Hand == SLOT_PRIMARY && GetLevel() >= 28 && IsWarriorClass() )
|
||||
if( Hand == MainPrimary && GetLevel() >= 28 && IsWarriorClass() )
|
||||
{
|
||||
// Damage bonuses apply only to hits from the main hand (Hand == 13) by characters level 28 and above
|
||||
// who belong to a melee class. If we're here, then all of these conditions apply.
|
||||
@@ -6526,7 +6529,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
|
||||
}
|
||||
#endif
|
||||
//Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon.
|
||||
if (Hand==SLOT_SECONDARY) {
|
||||
if (Hand==MainSecondary) {
|
||||
if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){
|
||||
|
||||
ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr );
|
||||
@@ -6583,7 +6586,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
|
||||
if (damage == -3) {
|
||||
if (FromRiposte) return false;
|
||||
else {
|
||||
if (Hand == SLOT_SECONDARY) {// Do we even have it & was attack with mainhand? If not, don't bother with other calculations
|
||||
if (Hand == MainSecondary) {// Do we even have it & was attack with mainhand? If not, don't bother with other calculations
|
||||
//Live AA - SlipperyAttacks
|
||||
//This spell effect most likely directly modifies the actual riposte chance when using offhand attack.
|
||||
int16 OffhandRiposteFail = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail;
|
||||
@@ -7160,7 +7163,7 @@ int16 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) {
|
||||
}
|
||||
}
|
||||
|
||||
for(int y = 0; y < MAX_AUGMENT_SLOTS; ++y)
|
||||
for (int y = 0; y < EmuConstants::ITEM_COMMON_SIZE; ++y)
|
||||
{
|
||||
ItemInst *aug = nullptr;
|
||||
aug = ins->GetAugment(y);
|
||||
@@ -7732,18 +7735,18 @@ int16 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
|
||||
}
|
||||
|
||||
//proc chance includes proc bonus
|
||||
float Bot::GetProcChances(float ProcBonus, uint16 weapon_speed, uint16 hand) {
|
||||
float Bot::GetProcChances(float ProcBonus, uint16 hand) {
|
||||
int mydex = GetDEX();
|
||||
float ProcChance = 0.0f;
|
||||
|
||||
uint16 weapon_speed = 0;
|
||||
switch (hand) {
|
||||
case SLOT_PRIMARY:
|
||||
case MainPrimary:
|
||||
weapon_speed = attack_timer.GetDuration();
|
||||
break;
|
||||
case SLOT_SECONDARY:
|
||||
case MainSecondary:
|
||||
weapon_speed = attack_dw_timer.GetDuration();
|
||||
break;
|
||||
case SLOT_RANGE:
|
||||
case MainRange:
|
||||
weapon_speed = ranged_timer.GetDuration();
|
||||
break;
|
||||
}
|
||||
@@ -7860,9 +7863,9 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
|
||||
|
||||
if(damage > 0 && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock)
|
||||
&& (!other->BehindMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) {
|
||||
bool equiped = GetBotItem(SLOT_SECONDARY);
|
||||
bool equiped = GetBotItem(MainSecondary);
|
||||
if(equiped) {
|
||||
uint8 shield = GetBotItem(SLOT_SECONDARY)->GetItem()->ItemType;
|
||||
uint8 shield = GetBotItem(MainSecondary)->GetItem()->ItemType;
|
||||
float bonusShieldBlock = 0.0f;
|
||||
if(shield == ItemTypeShield) {
|
||||
|
||||
@@ -7875,9 +7878,9 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
|
||||
|
||||
if(damage > 0 && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock)
|
||||
&& (!other->BehindMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) {
|
||||
bool equiped2 = GetBotItem(SLOT_PRIMARY);
|
||||
bool equiped2 = GetBotItem(MainPrimary);
|
||||
if(equiped2) {
|
||||
uint8 TwoHandBlunt = GetBotItem(SLOT_PRIMARY)->GetItem()->ItemType;
|
||||
uint8 TwoHandBlunt = GetBotItem(MainPrimary)->GetItem()->ItemType;
|
||||
float bonusStaffBlock = 0.0f;
|
||||
if(TwoHandBlunt == ItemType2HBlunt) {
|
||||
|
||||
@@ -8015,7 +8018,7 @@ void Bot::DoRiposte(Mob* defender) {
|
||||
if (!defender)
|
||||
return;
|
||||
|
||||
defender->Attack(this, SLOT_PRIMARY, true);
|
||||
defender->Attack(this, MainPrimary, true);
|
||||
|
||||
//double riposte
|
||||
int16 DoubleRipChance = defender->GetAABonuses().GiveDoubleRiposte[0] +
|
||||
@@ -8025,7 +8028,7 @@ void Bot::DoRiposte(Mob* defender) {
|
||||
if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) {
|
||||
mlog(COMBAT__ATTACKS, "Preforming a double riposte (%d percent chance)", DoubleRipChance);
|
||||
|
||||
defender->Attack(this, SLOT_PRIMARY, true);
|
||||
defender->Attack(this, MainPrimary, true);
|
||||
}
|
||||
|
||||
//Double Riposte effect, allows for a chance to do RIPOSTE with a skill specfic special attack (ie Return Kick).
|
||||
@@ -8049,7 +8052,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
hate = hate_override;
|
||||
|
||||
if(skill == SkillBash) {
|
||||
const ItemInst* inst = GetBotItem(SLOT_SECONDARY);
|
||||
const ItemInst* inst = GetBotItem(MainSecondary);
|
||||
const Item_Struct* botweapon = 0;
|
||||
if(inst)
|
||||
botweapon = inst->GetItem();
|
||||
@@ -8063,7 +8066,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
|
||||
min_damage += min_damage * GetMeleeMinDamageMod_SE(skill) / 100;
|
||||
|
||||
if(HitChance && !who->CheckHitChance(this, skill, SLOT_PRIMARY))
|
||||
if(HitChance && !who->CheckHitChance(this, skill, MainPrimary))
|
||||
max_damage = 0;
|
||||
|
||||
else{
|
||||
@@ -8120,7 +8123,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
|
||||
bool bIsBehind = false;
|
||||
bool bCanFrontalBS = false;
|
||||
|
||||
const ItemInst* inst = GetBotItem(SLOT_PRIMARY);
|
||||
const ItemInst* inst = GetBotItem(MainPrimary);
|
||||
const Item_Struct* botpiercer = nullptr;
|
||||
if(inst)
|
||||
botpiercer = inst->GetItem();
|
||||
@@ -8192,7 +8195,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
|
||||
}
|
||||
}
|
||||
else { //We do a single regular attack if we attack from the front without chaotic stab
|
||||
Attack(other, 13);
|
||||
Attack(other, MainPrimary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8206,11 +8209,11 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
|
||||
int32 primaryweapondamage = 0;
|
||||
int32 backstab_dmg = 0;
|
||||
|
||||
ItemInst* botweaponInst = GetBotItem(SLOT_PRIMARY);
|
||||
ItemInst* botweaponInst = GetBotItem(MainPrimary);
|
||||
if(botweaponInst) {
|
||||
primaryweapondamage = GetWeaponDamage(other, botweaponInst);
|
||||
backstab_dmg = botweaponInst->GetItem()->BackstabDmg;
|
||||
for(int i = 0; i < MAX_AUGMENT_SLOTS; ++i)
|
||||
for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; ++i)
|
||||
{
|
||||
ItemInst *aug = botweaponInst->GetAugment(i);
|
||||
if(aug)
|
||||
@@ -8276,7 +8279,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
|
||||
|
||||
void Bot::RogueAssassinate(Mob* other)
|
||||
{
|
||||
ItemInst* botweaponInst = GetBotItem(SLOT_PRIMARY);
|
||||
ItemInst* botweaponInst = GetBotItem(MainPrimary);
|
||||
if(botweaponInst) {
|
||||
if(GetWeaponDamage(other, botweaponInst)) {
|
||||
other->Damage(this, 32000, SPELL_UNKNOWN, SkillBackstab);
|
||||
@@ -8366,10 +8369,10 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
||||
if(level >= RuleI(Combat, NPCBashKickLevel)){
|
||||
bool canBash = false;
|
||||
if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) // Racial Slam
|
||||
|| (m_inv.GetItem(SLOT_SECONDARY) && m_inv.GetItem(SLOT_SECONDARY)->GetItem()->ItemType == ItemTypeShield) //Using Shield
|
||||
|| (m_inv.GetItem(SLOT_PRIMARY) && (m_inv.GetItem(SLOT_PRIMARY)->GetItem()->ItemType == ItemType2HSlash
|
||||
|| m_inv.GetItem(SLOT_PRIMARY)->GetItem()->ItemType == ItemType2HBlunt
|
||||
|| m_inv.GetItem(SLOT_PRIMARY)->GetItem()->ItemType == ItemType2HPiercing)
|
||||
|| (m_inv.GetItem(MainSecondary) && m_inv.GetItem(MainSecondary)->GetItem()->ItemType == ItemTypeShield) //Using Shield
|
||||
|| (m_inv.GetItem(MainPrimary) && (m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HSlash
|
||||
|| m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HBlunt
|
||||
|| m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HPiercing)
|
||||
&& GetAA(aa2HandBash) >= 1)) { //Using 2 hand weapon, but has AA 2 Hand Bash
|
||||
canBash = true;
|
||||
}
|
||||
@@ -8393,10 +8396,10 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
||||
case PALADIN:
|
||||
if(level >= RuleI(Combat, NPCBashKickLevel)){
|
||||
if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) // Racial Slam
|
||||
|| (m_inv.GetItem(SLOT_SECONDARY) && m_inv.GetItem(SLOT_SECONDARY)->GetItem()->ItemType == ItemTypeShield) //Using Shield
|
||||
|| (m_inv.GetItem(SLOT_PRIMARY) && (m_inv.GetItem(SLOT_PRIMARY)->GetItem()->ItemType == ItemType2HSlash
|
||||
|| m_inv.GetItem(SLOT_PRIMARY)->GetItem()->ItemType == ItemType2HBlunt
|
||||
|| m_inv.GetItem(SLOT_PRIMARY)->GetItem()->ItemType == ItemType2HPiercing)
|
||||
|| (m_inv.GetItem(MainSecondary) && m_inv.GetItem(MainSecondary)->GetItem()->ItemType == ItemTypeShield) //Using Shield
|
||||
|| (m_inv.GetItem(MainPrimary) && (m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HSlash
|
||||
|| m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HBlunt
|
||||
|| m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HPiercing)
|
||||
&& GetAA(aa2HandBash) >= 1)) { //Using 2 hand weapon, but has AA 2 Hand Bash
|
||||
skill_to_use = SkillBash;
|
||||
}
|
||||
@@ -8443,8 +8446,8 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
||||
{
|
||||
DoAnim(animTailRake);
|
||||
|
||||
if(GetWeaponDamage(target, GetBotItem(SLOT_SECONDARY)) <= 0 &&
|
||||
GetWeaponDamage(target, GetBotItem(SLOT_SHOULDER)) <= 0){
|
||||
if(GetWeaponDamage(target, GetBotItem(MainSecondary)) <= 0 &&
|
||||
GetWeaponDamage(target, GetBotItem(MainShoulders)) <= 0){
|
||||
dmg = -5;
|
||||
}
|
||||
else{
|
||||
@@ -8519,7 +8522,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
||||
{
|
||||
DoAnim(animKick);
|
||||
|
||||
if(GetWeaponDamage(target, GetBotItem(SLOT_FEET)) <= 0){
|
||||
if(GetWeaponDamage(target, GetBotItem(MainFeet)) <= 0){
|
||||
dmg = -5;
|
||||
}
|
||||
else{
|
||||
@@ -8991,14 +8994,14 @@ void Bot::SetAttackTimer() {
|
||||
Timer* TimerToUse = nullptr;
|
||||
const Item_Struct* PrimaryWeapon = nullptr;
|
||||
|
||||
for (int i=SLOT_RANGE; i<=SLOT_SECONDARY; i++) {
|
||||
for (int i=MainRange; i<=MainSecondary; i++) {
|
||||
|
||||
//pick a timer
|
||||
if (i == SLOT_PRIMARY)
|
||||
if (i == MainPrimary)
|
||||
TimerToUse = &attack_timer;
|
||||
else if (i == SLOT_RANGE)
|
||||
else if (i == MainRange)
|
||||
TimerToUse = &ranged_timer;
|
||||
else if(i == SLOT_SECONDARY)
|
||||
else if(i == MainSecondary)
|
||||
TimerToUse = &attack_dw_timer;
|
||||
else //invalid slot (hands will always hit this)
|
||||
continue;
|
||||
@@ -9009,7 +9012,7 @@ void Bot::SetAttackTimer() {
|
||||
ItemToUse = ci->GetItem();
|
||||
|
||||
//special offhand stuff
|
||||
if(i == SLOT_SECONDARY) {
|
||||
if(i == MainSecondary) {
|
||||
//if we have a 2H weapon in our main hand, no dual
|
||||
if(PrimaryWeapon != nullptr) {
|
||||
if( PrimaryWeapon->ItemClass == ItemClassCommon
|
||||
@@ -9103,7 +9106,7 @@ void Bot::SetAttackTimer() {
|
||||
TimerToUse->SetAtTrigger(speed, true);
|
||||
}
|
||||
|
||||
if(i == SLOT_PRIMARY)
|
||||
if(i == MainPrimary)
|
||||
PrimaryWeapon = ItemToUse;
|
||||
}
|
||||
}
|
||||
@@ -11551,10 +11554,10 @@ bool Bot::CheckLoreConflict(const Item_Struct* item) {
|
||||
return false;
|
||||
|
||||
if (item->LoreGroup == -1) // Standard lore items; look everywhere except the shared bank, return the result
|
||||
return (m_inv.HasItem(item->ID, 0, invWhereWorn) != SLOT_INVALID);
|
||||
return (m_inv.HasItem(item->ID, 0, invWhereWorn) != INVALID_INDEX);
|
||||
|
||||
//If the item has a lore group, we check for other items with the same group and return the result
|
||||
return (m_inv.HasItemByLoreGroup(item->LoreGroup, invWhereWorn) != SLOT_INVALID);
|
||||
return (m_inv.HasItemByLoreGroup(item->LoreGroup, invWhereWorn) != INVALID_INDEX);
|
||||
}
|
||||
|
||||
bool Bot::GroupHasClass(Group* group, uint8 classId) {
|
||||
@@ -12160,7 +12163,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
|
||||
bool is2Hweapon = false;
|
||||
for(int i=0; i<22; ++i)
|
||||
{
|
||||
if((i == 14) && is2Hweapon) {
|
||||
if((i == MainSecondary) && is2Hweapon) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -12178,12 +12181,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
|
||||
c->Message(15, "I need something for my %s (Item %i)", equipped[i], i);
|
||||
continue;
|
||||
}
|
||||
if((i == 13) && ((item2->ItemType == ItemType2HSlash) || (item2->ItemType == ItemType2HBlunt) || (item2->ItemType == ItemType2HPiercing))) {
|
||||
if((i == MainPrimary) && ((item2->ItemType == ItemType2HSlash) || (item2->ItemType == ItemType2HBlunt) || (item2->ItemType == ItemType2HPiercing))) {
|
||||
is2Hweapon = true;
|
||||
}
|
||||
|
||||
char* itemLink = 0;
|
||||
if((i == 0) || (i == 11) || (i == 13) || (i == 14) || (i == 21)) {
|
||||
if((i == MainCharm) || (i == MainRange) || (i == MainPrimary) || (i == MainSecondary) || (i == MainAmmo)) {
|
||||
if (c->GetClientVersion() >= EQClientSoF)
|
||||
{
|
||||
MakeAnyLenString(&itemLink, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X",
|
||||
@@ -12300,7 +12303,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
|
||||
// Don't allow the player to remove a lore item they already possess and cause a crash
|
||||
bool failedLoreCheck = false;
|
||||
if(itminst) {
|
||||
for(int m=0; m<MAX_AUGMENT_SLOTS; ++m) {
|
||||
for (int m = 0; m<EmuConstants::ITEM_COMMON_SIZE; ++m) {
|
||||
ItemInst *itma = itminst->GetAugment(m);
|
||||
if(itma)
|
||||
{
|
||||
@@ -12317,7 +12320,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
|
||||
if(itm) {
|
||||
c->PushItemOnCursor(*itminst, true);
|
||||
Bot *gearbot = c->GetTarget()->CastToBot();
|
||||
if((slotId == SLOT_RANGE)||(slotId == SLOT_AMMO)||(slotId == SLOT_PRIMARY)||(slotId == SLOT_SECONDARY)) {
|
||||
if((slotId == MainRange)||(slotId == MainAmmo)||(slotId == MainPrimary)||(slotId == MainSecondary)) {
|
||||
gearbot->SetBotArcher(false);
|
||||
}
|
||||
gearbot->RemoveBotItemBySlot(slotId, &TempErrorMessage);
|
||||
@@ -12330,30 +12333,31 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
|
||||
gearbot->BotRemoveEquipItem(slotId);
|
||||
gearbot->CalcBotStats();
|
||||
switch(slotId) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
case 20:
|
||||
case 21:
|
||||
case MainCharm:
|
||||
case MainEar1:
|
||||
case MainHead:
|
||||
case MainFace:
|
||||
case MainEar2:
|
||||
case MainNeck:
|
||||
case MainBack:
|
||||
case MainWrist1:
|
||||
case MainWrist2:
|
||||
case MainRange:
|
||||
case MainPrimary:
|
||||
case MainSecondary:
|
||||
case MainFinger1:
|
||||
case MainFinger2:
|
||||
case MainChest:
|
||||
case MainWaist:
|
||||
//case MainPowerSource:
|
||||
case MainAmmo:
|
||||
gearbot->Say("My %s is now unequipped.", equipped[slotId]);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
case 12:
|
||||
case 18:
|
||||
case 19:
|
||||
case MainShoulders:
|
||||
case MainArms:
|
||||
case MainHands:
|
||||
case MainLegs:
|
||||
case MainFeet:
|
||||
gearbot->Say("My %s are now unequipped.", equipped[slotId]);
|
||||
break;
|
||||
default:
|
||||
@@ -12362,30 +12366,31 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
|
||||
}
|
||||
else {
|
||||
switch(slotId) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
case 20:
|
||||
case 21:
|
||||
case MainCharm:
|
||||
case MainEar1:
|
||||
case MainHead:
|
||||
case MainFace:
|
||||
case MainEar2:
|
||||
case MainNeck:
|
||||
case MainBack:
|
||||
case MainWrist1:
|
||||
case MainWrist2:
|
||||
case MainRange:
|
||||
case MainPrimary:
|
||||
case MainSecondary:
|
||||
case MainFinger1:
|
||||
case MainFinger2:
|
||||
case MainChest:
|
||||
case MainWaist:
|
||||
//case MainPowerSource:
|
||||
case MainAmmo:
|
||||
c->GetTarget()->Say("My %s is already unequipped.", equipped[slotId]);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
case 12:
|
||||
case 18:
|
||||
case 19:
|
||||
case MainShoulders:
|
||||
case MainArms:
|
||||
case MainHands:
|
||||
case MainLegs:
|
||||
case MainFeet:
|
||||
c->GetTarget()->Say("My %s are already unequipped.", equipped[slotId]);
|
||||
break;
|
||||
default:
|
||||
@@ -16270,8 +16275,8 @@ void EntityList::BotPickLock(Bot* rogue)
|
||||
curdist += (tmp * tmp);
|
||||
if((zdiff < 10) && (curdist <= 130)) {
|
||||
// All rogue items with lock pick bonuses are hands or primary
|
||||
const ItemInst* item1 = rogue->GetBotItem(SLOT_HANDS);
|
||||
const ItemInst* item2 = rogue->GetBotItem(SLOT_PRIMARY);
|
||||
const ItemInst* item1 = rogue->GetBotItem(MainHands);
|
||||
const ItemInst* item2 = rogue->GetBotItem(MainPrimary);
|
||||
|
||||
float bonus1 = 0.0f;
|
||||
float bonus2 = 0.0f;
|
||||
@@ -16500,14 +16505,14 @@ int Bot::GetRawACNoShield(int &shield_ac)
|
||||
{
|
||||
int ac = itembonuses.AC + spellbonuses.AC;
|
||||
shield_ac = 0;
|
||||
ItemInst* inst = GetBotItem(SLOT_SECONDARY);
|
||||
ItemInst* inst = GetBotItem(MainSecondary);
|
||||
if(inst)
|
||||
{
|
||||
if(inst->GetItem()->ItemType == ItemTypeShield)
|
||||
{
|
||||
ac -= inst->GetItem()->AC;
|
||||
shield_ac = inst->GetItem()->AC;
|
||||
for(uint8 i = 0; i < MAX_AUGMENT_SLOTS; i++)
|
||||
for (uint8 i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++)
|
||||
{
|
||||
if(inst->GetAugment(i))
|
||||
{
|
||||
|
||||
+2
-2
@@ -137,7 +137,7 @@ public:
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill);
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false);
|
||||
virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
|
||||
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
|
||||
ExtraAttackOptions *opts = nullptr);
|
||||
virtual bool HasRaid() { return (GetRaid() ? true : false); }
|
||||
virtual bool HasGroup() { return (GetGroup() ? true : false); }
|
||||
@@ -167,7 +167,7 @@ public:
|
||||
uint16 BotGetSpells(int spellslot) { return AIspells[spellslot].spellid; }
|
||||
uint16 BotGetSpellType(int spellslot) { return AIspells[spellslot].type; }
|
||||
uint16 BotGetSpellPriority(int spellslot) { return AIspells[spellslot].priority; }
|
||||
virtual float GetProcChances(float ProcBonus, uint16 weapon_speed, uint16 hand);
|
||||
virtual float GetProcChances(float ProcBonus, uint16 hand);
|
||||
virtual bool AvoidDamage(Mob* other, int32 &damage, bool CanRiposte);
|
||||
virtual int GetMonkHandToHandDamage(void);
|
||||
virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse);
|
||||
|
||||
+87
-74
@@ -1867,52 +1867,57 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
|
||||
// (update: i think pp should do it, as this holds LoY dye - plus, this is ugly code with Inventory!)
|
||||
const Item_Struct* item = nullptr;
|
||||
const ItemInst* inst = nullptr;
|
||||
if ((inst = m_inv[SLOT_HANDS]) && inst->IsType(ItemClassCommon)) {
|
||||
if ((inst = m_inv[MainHands]) && inst->IsType(ItemClassCommon)) {
|
||||
item = inst->GetItem();
|
||||
ns->spawn.equipment[MaterialHands] = item->Material;
|
||||
ns->spawn.colors[MaterialHands].color = GetEquipmentColor(MaterialHands);
|
||||
}
|
||||
if ((inst = m_inv[SLOT_HEAD]) && inst->IsType(ItemClassCommon)) {
|
||||
if ((inst = m_inv[MainHead]) && inst->IsType(ItemClassCommon)) {
|
||||
item = inst->GetItem();
|
||||
ns->spawn.equipment[MaterialHead] = item->Material;
|
||||
ns->spawn.colors[MaterialHead].color = GetEquipmentColor(MaterialHead);
|
||||
}
|
||||
if ((inst = m_inv[SLOT_ARMS]) && inst->IsType(ItemClassCommon)) {
|
||||
if ((inst = m_inv[MainArms]) && inst->IsType(ItemClassCommon)) {
|
||||
item = inst->GetItem();
|
||||
ns->spawn.equipment[MaterialArms] = item->Material;
|
||||
ns->spawn.colors[MaterialArms].color = GetEquipmentColor(MaterialArms);
|
||||
}
|
||||
if ((inst = m_inv[SLOT_BRACER01]) && inst->IsType(ItemClassCommon)) {
|
||||
if ((inst = m_inv[MainWrist1]) && inst->IsType(ItemClassCommon)) {
|
||||
item = inst->GetItem();
|
||||
ns->spawn.equipment[MaterialWrist]= item->Material;
|
||||
ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist);
|
||||
}
|
||||
|
||||
/*
|
||||
// non-live behavior
|
||||
if ((inst = m_inv[SLOT_BRACER02]) && inst->IsType(ItemClassCommon)) {
|
||||
item = inst->GetItem();
|
||||
ns->spawn.equipment[MaterialWrist]= item->Material;
|
||||
ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist);
|
||||
}
|
||||
if ((inst = m_inv[SLOT_CHEST]) && inst->IsType(ItemClassCommon)) {
|
||||
*/
|
||||
|
||||
if ((inst = m_inv[MainChest]) && inst->IsType(ItemClassCommon)) {
|
||||
item = inst->GetItem();
|
||||
ns->spawn.equipment[MaterialChest] = item->Material;
|
||||
ns->spawn.colors[MaterialChest].color = GetEquipmentColor(MaterialChest);
|
||||
}
|
||||
if ((inst = m_inv[SLOT_LEGS]) && inst->IsType(ItemClassCommon)) {
|
||||
if ((inst = m_inv[MainLegs]) && inst->IsType(ItemClassCommon)) {
|
||||
item = inst->GetItem();
|
||||
ns->spawn.equipment[MaterialLegs] = item->Material;
|
||||
ns->spawn.colors[MaterialLegs].color = GetEquipmentColor(MaterialLegs);
|
||||
}
|
||||
if ((inst = m_inv[SLOT_FEET]) && inst->IsType(ItemClassCommon)) {
|
||||
if ((inst = m_inv[MainFeet]) && inst->IsType(ItemClassCommon)) {
|
||||
item = inst->GetItem();
|
||||
ns->spawn.equipment[MaterialFeet] = item->Material;
|
||||
ns->spawn.colors[MaterialFeet].color = GetEquipmentColor(MaterialFeet);
|
||||
}
|
||||
if ((inst = m_inv[SLOT_PRIMARY]) && inst->IsType(ItemClassCommon)) {
|
||||
if ((inst = m_inv[MainPrimary]) && inst->IsType(ItemClassCommon)) {
|
||||
item = inst->GetItem();
|
||||
if (strlen(item->IDFile) > 2)
|
||||
ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]);
|
||||
}
|
||||
if ((inst = m_inv[SLOT_SECONDARY]) && inst->IsType(ItemClassCommon)) {
|
||||
if ((inst = m_inv[MainSecondary]) && inst->IsType(ItemClassCommon)) {
|
||||
item = inst->GetItem();
|
||||
if (strlen(item->IDFile) > 2)
|
||||
ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]);
|
||||
@@ -2624,7 +2629,7 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){
|
||||
if(!bindwound_timer.Enabled()) {
|
||||
//make sure we actually have a bandage... and consume it.
|
||||
int16 bslot = m_inv.HasItemByUse(ItemTypeBandage, 1, invWhereWorn|invWherePersonal);
|
||||
if(bslot == SLOT_INVALID) {
|
||||
if (bslot == INVALID_INDEX) {
|
||||
bind_out->type = 3;
|
||||
QueuePacket(outapp);
|
||||
bind_out->type = 7; //this is the wrong message, dont know the right one.
|
||||
@@ -2775,28 +2780,31 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){
|
||||
return true;
|
||||
}
|
||||
|
||||
void Client::SetMaterial(int16 in_slot, uint32 item_id){
|
||||
void Client::SetMaterial(int16 in_slot, uint32 item_id) {
|
||||
const Item_Struct* item = database.GetItem(item_id);
|
||||
if (item && (item->ItemClass==ItemClassCommon)) {
|
||||
if (in_slot==SLOT_HEAD)
|
||||
if (in_slot==MainHead)
|
||||
m_pp.item_material[MaterialHead] = item->Material;
|
||||
else if (in_slot==SLOT_CHEST)
|
||||
else if (in_slot==MainChest)
|
||||
m_pp.item_material[MaterialChest] = item->Material;
|
||||
else if (in_slot==SLOT_ARMS)
|
||||
else if (in_slot==MainArms)
|
||||
m_pp.item_material[MaterialArms] = item->Material;
|
||||
else if (in_slot==SLOT_BRACER01)
|
||||
else if (in_slot==MainWrist1)
|
||||
m_pp.item_material[MaterialWrist] = item->Material;
|
||||
/*
|
||||
// non-live behavior
|
||||
else if (in_slot==SLOT_BRACER02)
|
||||
m_pp.item_material[MaterialWrist] = item->Material;
|
||||
else if (in_slot==SLOT_HANDS)
|
||||
*/
|
||||
else if (in_slot==MainHands)
|
||||
m_pp.item_material[MaterialHands] = item->Material;
|
||||
else if (in_slot==SLOT_LEGS)
|
||||
else if (in_slot==MainLegs)
|
||||
m_pp.item_material[MaterialLegs] = item->Material;
|
||||
else if (in_slot==SLOT_FEET)
|
||||
else if (in_slot==MainFeet)
|
||||
m_pp.item_material[MaterialFeet] = item->Material;
|
||||
else if (in_slot==SLOT_PRIMARY)
|
||||
m_pp.item_material[MaterialPrimary] = atoi(item->IDFile+2);
|
||||
else if (in_slot==SLOT_SECONDARY)
|
||||
else if (in_slot==MainPrimary)
|
||||
m_pp.item_material[MaterialPrimary] = atoi(item->IDFile+2);
|
||||
else if (in_slot==MainSecondary)
|
||||
m_pp.item_material[MaterialSecondary] = atoi(item->IDFile+2);
|
||||
}
|
||||
}
|
||||
@@ -3118,25 +3126,28 @@ void Client::SetTint(int16 in_slot, uint32 color) {
|
||||
|
||||
// Still need to reconcile bracer01 versus bracer02
|
||||
void Client::SetTint(int16 in_slot, Color_Struct& color) {
|
||||
if (in_slot==SLOT_HEAD)
|
||||
if (in_slot==MainHead)
|
||||
m_pp.item_tint[MaterialHead].color=color.color;
|
||||
else if (in_slot==SLOT_ARMS)
|
||||
else if (in_slot==MainArms)
|
||||
m_pp.item_tint[MaterialArms].color=color.color;
|
||||
else if (in_slot==SLOT_BRACER01)
|
||||
else if (in_slot==MainWrist1)
|
||||
m_pp.item_tint[MaterialWrist].color=color.color;
|
||||
/*
|
||||
// non-live behavior
|
||||
else if (in_slot==SLOT_BRACER02)
|
||||
m_pp.item_tint[MaterialWrist].color=color.color;
|
||||
else if (in_slot==SLOT_HANDS)
|
||||
*/
|
||||
else if (in_slot==MainHands)
|
||||
m_pp.item_tint[MaterialHands].color=color.color;
|
||||
else if (in_slot==SLOT_PRIMARY)
|
||||
else if (in_slot==MainPrimary)
|
||||
m_pp.item_tint[MaterialPrimary].color=color.color;
|
||||
else if (in_slot==SLOT_SECONDARY)
|
||||
else if (in_slot==MainSecondary)
|
||||
m_pp.item_tint[MaterialSecondary].color=color.color;
|
||||
else if (in_slot==SLOT_CHEST)
|
||||
else if (in_slot==MainChest)
|
||||
m_pp.item_tint[MaterialChest].color=color.color;
|
||||
else if (in_slot==SLOT_LEGS)
|
||||
else if (in_slot==MainLegs)
|
||||
m_pp.item_tint[MaterialLegs].color=color.color;
|
||||
else if (in_slot==SLOT_FEET)
|
||||
else if (in_slot==MainFeet)
|
||||
m_pp.item_tint[MaterialFeet].color=color.color;
|
||||
}
|
||||
|
||||
@@ -3202,57 +3213,57 @@ void Client::LinkDead()
|
||||
}
|
||||
|
||||
uint8 Client::SlotConvert(uint8 slot,bool bracer){
|
||||
uint8 slot2=0;
|
||||
uint8 slot2=0; // why are we returning MainCharm instead of INVALID_INDEX? (must be a pre-charm segment...)
|
||||
if(bracer)
|
||||
return SLOT_BRACER02;
|
||||
return MainWrist2;
|
||||
switch(slot){
|
||||
case MaterialHead:
|
||||
slot2=SLOT_HEAD;
|
||||
slot2=MainHead;
|
||||
break;
|
||||
case MaterialChest:
|
||||
slot2=SLOT_CHEST;
|
||||
slot2=MainChest;
|
||||
break;
|
||||
case MaterialArms:
|
||||
slot2=SLOT_ARMS;
|
||||
slot2=MainArms;
|
||||
break;
|
||||
case MaterialWrist:
|
||||
slot2=SLOT_BRACER01;
|
||||
slot2=MainWrist1;
|
||||
break;
|
||||
case MaterialHands:
|
||||
slot2=SLOT_HANDS;
|
||||
slot2=MainHands;
|
||||
break;
|
||||
case MaterialLegs:
|
||||
slot2=SLOT_LEGS;
|
||||
slot2=MainLegs;
|
||||
break;
|
||||
case MaterialFeet:
|
||||
slot2=SLOT_FEET;
|
||||
slot2=MainFeet;
|
||||
break;
|
||||
}
|
||||
return slot2;
|
||||
}
|
||||
|
||||
uint8 Client::SlotConvert2(uint8 slot){
|
||||
uint8 slot2=0;
|
||||
uint8 slot2=0; // same as above...
|
||||
switch(slot){
|
||||
case SLOT_HEAD:
|
||||
case MainHead:
|
||||
slot2=MaterialHead;
|
||||
break;
|
||||
case SLOT_CHEST:
|
||||
case MainChest:
|
||||
slot2=MaterialChest;
|
||||
break;
|
||||
case SLOT_ARMS:
|
||||
case MainArms:
|
||||
slot2=MaterialArms;
|
||||
break;
|
||||
case SLOT_BRACER01:
|
||||
case MainWrist1:
|
||||
slot2=MaterialWrist;
|
||||
break;
|
||||
case SLOT_HANDS:
|
||||
case MainHands:
|
||||
slot2=MaterialHands;
|
||||
break;
|
||||
case SLOT_LEGS:
|
||||
case MainLegs:
|
||||
slot2=MaterialLegs;
|
||||
break;
|
||||
case SLOT_FEET:
|
||||
case MainFeet:
|
||||
slot2=MaterialFeet;
|
||||
break;
|
||||
}
|
||||
@@ -4130,14 +4141,14 @@ void Client::UpdateLFP() {
|
||||
uint16 Client::GetPrimarySkillValue()
|
||||
{
|
||||
SkillUseTypes skill = HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill
|
||||
bool equiped = m_inv.GetItem(13);
|
||||
bool equiped = m_inv.GetItem(MainPrimary);
|
||||
|
||||
if (!equiped)
|
||||
skill = SkillHandtoHand;
|
||||
|
||||
else {
|
||||
|
||||
uint8 type = m_inv.GetItem(13)->GetItem()->ItemType; //is this the best way to do this?
|
||||
uint8 type = m_inv.GetItem(MainPrimary)->GetItem()->ItemType; //is this the best way to do this?
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@@ -4900,7 +4911,7 @@ void Client::ShowSkillsWindow()
|
||||
if(GetSkill(it->second) > 0 || MaxSkill(it->second) > 0) {
|
||||
WindowText += it->first;
|
||||
// line up the values
|
||||
for (int j = 0; j < MAX_AUGMENT_SLOTS; j++)
|
||||
for (int j = 0; j < EmuConstants::ITEM_COMMON_SIZE; j++)
|
||||
WindowText += " ";
|
||||
WindowText += itoa(this->GetSkill(it->second));
|
||||
if (MaxSkill(it->second) > 0) {
|
||||
@@ -5691,7 +5702,7 @@ void Client::AddCrystals(uint32 Radiant, uint32 Ebon)
|
||||
SendCrystalCounts();
|
||||
}
|
||||
|
||||
// Processes a client request to inspect a SoF client's equipment.
|
||||
// Processes a client request to inspect a SoF+ client's equipment.
|
||||
void Client::ProcessInspectRequest(Client* requestee, Client* requester) {
|
||||
if(requestee && requester) {
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_InspectAnswer, sizeof(InspectResponse_Struct));
|
||||
@@ -5716,28 +5727,30 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) {
|
||||
}
|
||||
}
|
||||
|
||||
inst = requestee->GetInv().GetItem(9999);
|
||||
inst = requestee->GetInv().GetItem(MainPowerSource);
|
||||
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
strcpy(insr->itemnames[21], item->Name);
|
||||
insr->itemicons[21] = item->Icon;
|
||||
// we shouldn't do this..but, that's the way it's coded atm...
|
||||
// (this type of action should be handled exclusively in the client translator)
|
||||
strcpy(insr->itemnames[SoF::slots::MainPowerSource], item->Name);
|
||||
insr->itemicons[SoF::slots::MainPowerSource] = item->Icon;
|
||||
}
|
||||
else
|
||||
insr->itemicons[21] = 0xFFFFFFFF;
|
||||
insr->itemicons[SoF::slots::MainPowerSource] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
inst = requestee->GetInv().GetItem(21);
|
||||
inst = requestee->GetInv().GetItem(MainAmmo);
|
||||
|
||||
if(inst) {
|
||||
item = inst->GetItem();
|
||||
if(item) {
|
||||
strcpy(insr->itemnames[22], item->Name);
|
||||
insr->itemicons[22] = item->Icon;
|
||||
strcpy(insr->itemnames[SoF::slots::MainAmmo], item->Name);
|
||||
insr->itemicons[SoF::slots::MainAmmo] = item->Icon;
|
||||
}
|
||||
else
|
||||
insr->itemicons[22] = 0xFFFFFFFF;
|
||||
insr->itemicons[SoF::slots::MainAmmo] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
strcpy(insr->text, requestee->GetInspectMessage().text);
|
||||
@@ -6266,8 +6279,8 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid
|
||||
made_npc->PR = GetPR();
|
||||
made_npc->Corrup = GetCorrup();
|
||||
// looks
|
||||
made_npc->texture = GetEquipmentMaterial(1);
|
||||
made_npc->helmtexture = GetEquipmentMaterial(0);
|
||||
made_npc->texture = GetEquipmentMaterial(MaterialChest);
|
||||
made_npc->helmtexture = GetEquipmentMaterial(MaterialHead);
|
||||
made_npc->haircolor = GetHairColor();
|
||||
made_npc->beardcolor = GetBeardColor();
|
||||
made_npc->eyecolor1 = GetEyeColor1();
|
||||
@@ -6278,9 +6291,9 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid
|
||||
made_npc->drakkin_heritage = GetDrakkinHeritage();
|
||||
made_npc->drakkin_tattoo = GetDrakkinTattoo();
|
||||
made_npc->drakkin_details = GetDrakkinDetails();
|
||||
made_npc->d_meele_texture1 = GetEquipmentMaterial(7);
|
||||
made_npc->d_meele_texture2 = GetEquipmentMaterial(8);
|
||||
for (int i = 0; i < _MaterialCount; i++) {
|
||||
made_npc->d_meele_texture1 = GetEquipmentMaterial(MaterialPrimary);
|
||||
made_npc->d_meele_texture2 = GetEquipmentMaterial(MaterialSecondary);
|
||||
for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) {
|
||||
made_npc->armor_tint[i] = GetEquipmentColor(i);
|
||||
}
|
||||
made_npc->loottable_id = 0;
|
||||
@@ -7818,17 +7831,17 @@ void Client::TickItemCheck()
|
||||
if(zone->tick_items.empty()) { return; }
|
||||
|
||||
//Scan equip slots for items
|
||||
for(i = 0; i <= 21; i++)
|
||||
for(i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; i++)
|
||||
{
|
||||
TryItemTick(i);
|
||||
}
|
||||
//Scan main inventory + cursor
|
||||
for(i = 22; i < 31; i++)
|
||||
for(i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::CURSOR; i++)
|
||||
{
|
||||
TryItemTick(i);
|
||||
}
|
||||
//Scan bags
|
||||
for(i = 251; i < 340; i++)
|
||||
for(i = EmuConstants::GENERAL_BAGS_BEGIN; i <= EmuConstants::CURSOR_BAG_END; i++)
|
||||
{
|
||||
TryItemTick(i);
|
||||
}
|
||||
@@ -7852,9 +7865,9 @@ void Client::TryItemTick(int slot)
|
||||
}
|
||||
|
||||
//Only look at augs in main inventory
|
||||
if(slot > 21) { return; }
|
||||
if(slot > EmuConstants::EQUIPMENT_END) { return; }
|
||||
|
||||
for(int x = 0; x < MAX_AUGMENT_SLOTS; ++x)
|
||||
for (int x = AUG_BEGIN; x < EmuConstants::ITEM_COMMON_SIZE; ++x)
|
||||
{
|
||||
ItemInst * a_inst = inst->GetAugment(x);
|
||||
if(!a_inst) { continue; }
|
||||
@@ -7875,17 +7888,17 @@ void Client::TryItemTick(int slot)
|
||||
void Client::ItemTimerCheck()
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i <= 21; i++)
|
||||
for(i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; i++)
|
||||
{
|
||||
TryItemTimer(i);
|
||||
}
|
||||
|
||||
for(i = 22; i < 31; i++)
|
||||
for(i = EmuConstants::GENERAL_BAGS_BEGIN; i <= EmuConstants::CURSOR; i++)
|
||||
{
|
||||
TryItemTimer(i);
|
||||
}
|
||||
|
||||
for(i = 251; i < 340; i++)
|
||||
for(i = EmuConstants::GENERAL_BAGS_BEGIN; i <= EmuConstants::CURSOR_BAG_END; i++)
|
||||
{
|
||||
TryItemTimer(i);
|
||||
}
|
||||
@@ -7907,11 +7920,11 @@ void Client::TryItemTimer(int slot)
|
||||
++it_iter;
|
||||
}
|
||||
|
||||
if(slot > 21) {
|
||||
if(slot > EmuConstants::EQUIPMENT_END) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(int x = 0; x < MAX_AUGMENT_SLOTS; ++x)
|
||||
for (int x = AUG_BEGIN; x < EmuConstants::ITEM_COMMON_SIZE; ++x)
|
||||
{
|
||||
ItemInst * a_inst = inst->GetAugment(x);
|
||||
if(!a_inst) {
|
||||
|
||||
+2
-2
@@ -214,7 +214,7 @@ public:
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill);
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false);
|
||||
virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
|
||||
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
|
||||
ExtraAttackOptions *opts = nullptr);
|
||||
virtual bool HasRaid() { return (GetRaid() ? true : false); }
|
||||
virtual bool HasGroup() { return (GetGroup() ? true : false); }
|
||||
@@ -799,7 +799,7 @@ public:
|
||||
void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false);
|
||||
void PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data = 0);
|
||||
bool AutoPutLootInInventory(ItemInst& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0);
|
||||
bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, bool attuned=false, uint16 to_slot=SLOT_CURSOR);
|
||||
bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, bool attuned = false, uint16 to_slot = MainCursor);
|
||||
void SetStats(uint8 type,int16 set_val);
|
||||
void IncStats(uint8 type,int16 increase_val);
|
||||
void DropItem(int16 slot_id);
|
||||
|
||||
+15
-14
@@ -873,9 +873,9 @@ int16 Client::CalcAC() {
|
||||
|
||||
// Shield AC bonus for HeroicSTR
|
||||
if(itembonuses.HeroicSTR) {
|
||||
bool equiped = CastToClient()->m_inv.GetItem(14);
|
||||
bool equiped = CastToClient()->m_inv.GetItem(MainSecondary);
|
||||
if(equiped) {
|
||||
uint8 shield = CastToClient()->m_inv.GetItem(14)->GetItem()->ItemType;
|
||||
uint8 shield = CastToClient()->m_inv.GetItem(MainSecondary)->GetItem()->ItemType;
|
||||
if(shield == ItemTypeShield)
|
||||
displayed += itembonuses.HeroicSTR/2;
|
||||
}
|
||||
@@ -903,9 +903,9 @@ int16 Client::GetACMit() {
|
||||
|
||||
// Shield AC bonus for HeroicSTR
|
||||
if(itembonuses.HeroicSTR) {
|
||||
bool equiped = CastToClient()->m_inv.GetItem(14);
|
||||
bool equiped = CastToClient()->m_inv.GetItem(MainSecondary);
|
||||
if(equiped) {
|
||||
uint8 shield = CastToClient()->m_inv.GetItem(14)->GetItem()->ItemType;
|
||||
uint8 shield = CastToClient()->m_inv.GetItem(MainSecondary)->GetItem()->ItemType;
|
||||
if(shield == ItemTypeShield)
|
||||
mitigation += itembonuses.HeroicSTR/2;
|
||||
}
|
||||
@@ -1127,7 +1127,7 @@ uint32 Client::CalcCurrentWeight() {
|
||||
ItemInst* ins;
|
||||
uint32 Total = 0;
|
||||
int x;
|
||||
for(x = 0; x <= 30; x++)
|
||||
for(x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::CURSOR; x++) // include cursor or not?
|
||||
{
|
||||
TempItem = 0;
|
||||
ins = GetInv().GetItem(x);
|
||||
@@ -1136,7 +1136,7 @@ uint32 Client::CalcCurrentWeight() {
|
||||
if (TempItem)
|
||||
Total += TempItem->Weight;
|
||||
}
|
||||
for (x = 251; x < 331; x++)
|
||||
for (x = EmuConstants::GENERAL_BAGS_BEGIN; x <= EmuConstants::GENERAL_BAGS_END; x++) // include cursor bags or not?
|
||||
{
|
||||
int TmpWeight = 0;
|
||||
TempItem = 0;
|
||||
@@ -1147,9 +1147,11 @@ uint32 Client::CalcCurrentWeight() {
|
||||
TmpWeight = TempItem->Weight;
|
||||
if (TmpWeight > 0)
|
||||
{
|
||||
int bagslot = 22;
|
||||
// this code indicates that weight redux bags canonly be in the first general inventory slot to be effective...
|
||||
// is this correct? or can we scan for the highest weight redux and use that? (need client verifications)
|
||||
int bagslot = MainGeneral1;
|
||||
int reduction = 0;
|
||||
for (int m = 261; m < 331; m += 10)
|
||||
for (int m = MainGeneral2; m <= EmuConstants::GENERAL_BAGS_END; m += 10) // include cursor bags or not?
|
||||
{
|
||||
if (x >= m)
|
||||
bagslot += 1;
|
||||
@@ -1172,10 +1174,9 @@ uint32 Client::CalcCurrentWeight() {
|
||||
This is the ONLY instance I have seen where the client is hard coded to particular Item IDs to set a certain property for an item. It is very odd.
|
||||
*/
|
||||
|
||||
// SoD client has no weight for coin
|
||||
if (GetClientVersion() < EQClientSoD) {
|
||||
// SoD+ client has no weight for coin
|
||||
if (EQLimits::CoinHasWeight(ClientVersion))
|
||||
Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4;
|
||||
}
|
||||
|
||||
float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat;
|
||||
if (Packrat > 0)
|
||||
@@ -1967,16 +1968,16 @@ int32 Client::CalcEnduranceRegenCap() {
|
||||
|
||||
int Client::GetRawACNoShield(int &shield_ac) const
|
||||
{
|
||||
int ac = itembonuses.AC + spellbonuses.AC;
|
||||
int ac = itembonuses.AC + spellbonuses.AC + aabonuses.AC;
|
||||
shield_ac = 0;
|
||||
const ItemInst *inst = m_inv.GetItem(SLOT_SECONDARY);
|
||||
const ItemInst *inst = m_inv.GetItem(MainSecondary);
|
||||
if(inst)
|
||||
{
|
||||
if(inst->GetItem()->ItemType == ItemTypeShield)
|
||||
{
|
||||
ac -= inst->GetItem()->AC;
|
||||
shield_ac = inst->GetItem()->AC;
|
||||
for(uint8 i = 0; i < MAX_AUGMENT_SLOTS; i++)
|
||||
for (uint8 i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++)
|
||||
{
|
||||
if(inst->GetAugment(i))
|
||||
{
|
||||
|
||||
+33
-27
@@ -386,6 +386,7 @@ void MapOpcodes() {
|
||||
ConnectedOpcodes[OP_MercenaryTimerRequest] = &Client::Handle_OP_MercenaryTimerRequest;
|
||||
ConnectedOpcodes[OP_OpenInventory] = &Client::Handle_OP_OpenInventory;
|
||||
ConnectedOpcodes[OP_OpenContainer] = &Client::Handle_OP_OpenContainer;
|
||||
ConnectedOpcodes[OP_ClientTimeStamp] = &Client::Handle_OP_ClientTimeStamp;
|
||||
}
|
||||
|
||||
void ClearMappedOpcode(EmuOpcode op) {
|
||||
@@ -1629,7 +1630,7 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app)
|
||||
Shielding_Struct* shield = (Shielding_Struct*)app->pBuffer;
|
||||
shield_target = entity_list.GetMob(shield->target_id);
|
||||
bool ack = false;
|
||||
ItemInst* inst = GetInv().GetItem(14);
|
||||
ItemInst* inst = GetInv().GetItem(MainSecondary);
|
||||
if (!shield_target)
|
||||
return;
|
||||
if (inst)
|
||||
@@ -2031,7 +2032,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
|
||||
|
||||
LogFile->write(EQEMuLog::Debug, "OP ItemVerifyRequest: spell=%i, target=%i, inv=%i", spell_id, target_id, slot_id);
|
||||
|
||||
if ((slot_id < 30) || (slot_id == 9999) || (slot_id > 250 && slot_id < 331 && ((item->ItemType == ItemTypePotion) || item->PotionBelt))) // sanity check
|
||||
if ((slot_id < MainCursor) || (slot_id == MainPowerSource) || (slot_id > 250 && slot_id < 331 && ((item->ItemType == ItemTypePotion) || item->PotionBelt))) // sanity check
|
||||
{
|
||||
ItemInst* p_inst = (ItemInst*)inst;
|
||||
|
||||
@@ -2047,7 +2048,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
|
||||
ItemInst* clickaug = 0;
|
||||
Item_Struct* augitem = 0;
|
||||
|
||||
for(r = 0; r < MAX_AUGMENT_SLOTS; r++) {
|
||||
for (r = 0; r < EmuConstants::ITEM_COMMON_SIZE; r++) {
|
||||
const ItemInst* aug_i = inst->GetAugment(r);
|
||||
if(!aug_i)
|
||||
continue;
|
||||
@@ -2465,7 +2466,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app)
|
||||
ItemInst *inst = database.CreateItem(item, charges);
|
||||
if(!AutoPutLootInInventory(*inst, true, true))
|
||||
{
|
||||
PutLootInInventory(SLOT_CURSOR, *inst);
|
||||
PutLootInInventory(MainCursor, *inst);
|
||||
}
|
||||
Save(1);
|
||||
}
|
||||
@@ -3259,7 +3260,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
|
||||
MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer;
|
||||
if(spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id))
|
||||
{
|
||||
if(mi->from_slot != mi->to_slot && (mi->from_slot < 30 || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot))
|
||||
if(mi->from_slot != mi->to_slot && (mi->from_slot <= EmuConstants::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot))
|
||||
{
|
||||
char *detect = nullptr;
|
||||
const ItemInst *itm_from = GetInv().GetItem(mi->from_slot);
|
||||
@@ -3280,8 +3281,8 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
|
||||
// Illegal bagslot useage checks. Currently, user only receives a message if this check is triggered.
|
||||
bool mi_hack = false;
|
||||
|
||||
if(mi->from_slot >= 251 && mi->from_slot <= 340) {
|
||||
if(mi->from_slot > 330) { mi_hack = true; }
|
||||
if(mi->from_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->from_slot <= EmuConstants::CURSOR_BAG_END) {
|
||||
if(mi->from_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; }
|
||||
else {
|
||||
int16 from_parent = m_inv.CalcSlotId(mi->from_slot);
|
||||
if(!m_inv[from_parent]) { mi_hack = true; }
|
||||
@@ -3290,8 +3291,8 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
|
||||
}
|
||||
}
|
||||
|
||||
if(mi->to_slot >= 251 && mi->to_slot <= 340) {
|
||||
if(mi->to_slot > 330) { mi_hack = true; }
|
||||
if(mi->to_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->to_slot <= EmuConstants::CURSOR_BAG_END) {
|
||||
if(mi->to_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; }
|
||||
else {
|
||||
int16 to_parent = m_inv.CalcSlotId(mi->to_slot);
|
||||
if(!m_inv[to_parent]) { mi_hack = true; }
|
||||
@@ -5631,8 +5632,8 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app)
|
||||
freeslotid = m_inv.FindFreeSlot(false, true, item->Size);
|
||||
|
||||
//make sure we are not completely full...
|
||||
if(freeslotid == SLOT_CURSOR) {
|
||||
if(m_inv.GetItem(SLOT_CURSOR) != nullptr) {
|
||||
if (freeslotid == MainCursor) {
|
||||
if (m_inv.GetItem(MainCursor) != nullptr) {
|
||||
Message(13, "You do not have room for any more items.");
|
||||
safe_delete(outapp);
|
||||
safe_delete(inst);
|
||||
@@ -5640,7 +5641,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app)
|
||||
}
|
||||
}
|
||||
|
||||
if(freeslotid == SLOT_INVALID)
|
||||
if (freeslotid == INVALID_INDEX)
|
||||
{
|
||||
Message(13, "You do not have room for any more items.");
|
||||
safe_delete(outapp);
|
||||
@@ -6227,7 +6228,7 @@ void Client::Handle_OP_ClickDoor(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_CreateObject(const EQApplicationPacket *app)
|
||||
{
|
||||
DropItem(SLOT_CURSOR);
|
||||
DropItem(MainCursor);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6782,7 +6783,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) {
|
||||
|
||||
for (int16 L = 0; L <= 20; L++) {
|
||||
const ItemInst* inst = GetInv().GetItem(L);
|
||||
item = inst ? inst->GetItem() : nullptr;
|
||||
item = inst ? inst->GetItem() : nullptr;
|
||||
|
||||
if(item) {
|
||||
strcpy(insr->itemnames[L], item->Name);
|
||||
@@ -6791,14 +6792,15 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) {
|
||||
else { insr->itemicons[L] = 0xFFFFFFFF; }
|
||||
}
|
||||
|
||||
const ItemInst* inst = GetInv().GetItem(21);
|
||||
const ItemInst* inst = GetInv().GetItem(MainAmmo);
|
||||
item = inst ? inst->GetItem() : nullptr;
|
||||
|
||||
if(item) {
|
||||
strcpy(insr->itemnames[22], item->Name);
|
||||
insr->itemicons[22] = item->Icon;
|
||||
// another one..I did these, didn't I!!?
|
||||
strcpy(insr->itemnames[SoF::slots::MainAmmo], item->Name);
|
||||
insr->itemicons[SoF::slots::MainAmmo] = item->Icon;
|
||||
}
|
||||
else { insr->itemicons[22] = 0xFFFFFFFF; }
|
||||
else { insr->itemicons[SoF::slots::MainAmmo] = 0xFFFFFFFF; }
|
||||
|
||||
InspectMessage_Struct* newmessage = (InspectMessage_Struct*) insr->text;
|
||||
InspectMessage_Struct& playermessage = this->GetInspectMessage();
|
||||
@@ -9232,7 +9234,7 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) {
|
||||
if (it==m_inv.cursor_begin())
|
||||
continue;
|
||||
const ItemInst *inst=*it;
|
||||
SendItemPacket(SLOT_CURSOR, inst, ItemPacketSummonItem);
|
||||
SendItemPacket(MainCursor, inst, ItemPacketSummonItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11037,8 +11039,8 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app) {
|
||||
}
|
||||
uint32 ApplyPoisonSuccessResult = 0;
|
||||
ApplyPoison_Struct* ApplyPoisonData = (ApplyPoison_Struct*)app->pBuffer;
|
||||
const ItemInst* PrimaryWeapon = GetInv().GetItem(SLOT_PRIMARY);
|
||||
const ItemInst* SecondaryWeapon = GetInv().GetItem(SLOT_SECONDARY);
|
||||
const ItemInst* PrimaryWeapon = GetInv().GetItem(MainPrimary);
|
||||
const ItemInst* SecondaryWeapon = GetInv().GetItem(MainSecondary);
|
||||
const ItemInst* PoisonItemInstance = GetInv()[ApplyPoisonData->inventorySlot];
|
||||
|
||||
bool IsPoison = PoisonItemInstance && (PoisonItemInstance->GetItem()->ItemType == ItemTypePoison);
|
||||
@@ -11822,7 +11824,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
ItemInst *CursorItemInst = GetInv().GetItem(SLOT_CURSOR);
|
||||
ItemInst *CursorItemInst = GetInv().GetItem(MainCursor);
|
||||
|
||||
bool Allowed = true;
|
||||
|
||||
@@ -11879,7 +11881,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app)
|
||||
{
|
||||
GuildBankDepositAck(false);
|
||||
|
||||
DeleteItemInInventory(SLOT_CURSOR, 0, false);
|
||||
DeleteItemInInventory(MainCursor, 0, false);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -11900,7 +11902,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app)
|
||||
|
||||
case GuildBankWithdraw:
|
||||
{
|
||||
if(GetInv()[SLOT_CURSOR])
|
||||
if (GetInv()[MainCursor])
|
||||
{
|
||||
Message_StringID(13, GUILD_BANK_EMPTY_HANDS);
|
||||
|
||||
@@ -11946,7 +11948,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app)
|
||||
{
|
||||
PushItemOnCursor(*inst);
|
||||
|
||||
SendItemPacket(SLOT_CURSOR, inst, ItemPacketSummonItem);
|
||||
SendItemPacket(MainCursor, inst, ItemPacketSummonItem);
|
||||
|
||||
GuildBanks->DeleteItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity);
|
||||
}
|
||||
@@ -12752,7 +12754,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) {
|
||||
ItemInst *inst = database.CreateItem(item, charges);
|
||||
if(!AutoPutLootInInventory(*inst, true, true))
|
||||
{
|
||||
PutLootInInventory(SLOT_CURSOR, *inst);
|
||||
PutLootInInventory(MainCursor, *inst);
|
||||
}
|
||||
|
||||
Save(1);
|
||||
@@ -12786,7 +12788,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) {
|
||||
SummonItem(item_id, max_currency);
|
||||
SetAlternateCurrencyValue(reclaim->currency_id, 0);
|
||||
} else {
|
||||
SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, false, SLOT_CURSOR);
|
||||
SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, false, MainCursor);
|
||||
AddAlternateCurrencyValue(reclaim->currency_id, -((int32)reclaim->count));
|
||||
}
|
||||
}
|
||||
@@ -13866,3 +13868,7 @@ void Client::Handle_OP_OpenContainer(const EQApplicationPacket *app) {
|
||||
// SideNote: Watching the slot translations, Unknown1 is showing '141' as well on certain item swaps.
|
||||
// Manually looting a corpse results in a from '34' to '68' value for equipment items, '0' to '0' for inventory.
|
||||
}
|
||||
|
||||
void Client::Handle_OP_ClientTimeStamp(const EQApplicationPacket *app) {
|
||||
// handle as needed or ignore like we have been doing...
|
||||
}
|
||||
|
||||
@@ -288,3 +288,4 @@
|
||||
void Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_OpenInventory(const EQApplicationPacket *app);
|
||||
void Handle_OP_OpenContainer(const EQApplicationPacket *app);
|
||||
void Handle_OP_ClientTimeStamp(const EQApplicationPacket *app);
|
||||
|
||||
+21
-21
@@ -293,7 +293,7 @@ bool Client::Process() {
|
||||
}
|
||||
|
||||
if(AutoFireEnabled()){
|
||||
ItemInst *ranged = GetInv().GetItem(SLOT_RANGE);
|
||||
ItemInst *ranged = GetInv().GetItem(MainRange);
|
||||
if(ranged)
|
||||
{
|
||||
if(ranged->GetItem() && ranged->GetItem()->ItemType == ItemTypeBow){
|
||||
@@ -402,10 +402,10 @@ bool Client::Process() {
|
||||
{
|
||||
entity_list.AEAttack(this, 30);
|
||||
} else {
|
||||
Attack(auto_attack_target, 13); // Kaiyodo - added attacking hand to arguments
|
||||
Attack(auto_attack_target, MainPrimary); // Kaiyodo - added attacking hand to arguments
|
||||
}
|
||||
ItemInst *wpn = GetInv().GetItem(SLOT_PRIMARY);
|
||||
TryWeaponProc(wpn, auto_attack_target, 13);
|
||||
ItemInst *wpn = GetInv().GetItem(MainPrimary);
|
||||
TryWeaponProc(wpn, auto_attack_target, MainPrimary);
|
||||
|
||||
bool tripleAttackSuccess = false;
|
||||
if( auto_attack_target && CanThisClassDoubleAttack() ) {
|
||||
@@ -416,7 +416,7 @@ bool Client::Process() {
|
||||
if(CheckAAEffect(aaEffectRampage)) {
|
||||
entity_list.AEAttack(this, 30);
|
||||
} else {
|
||||
Attack(auto_attack_target, 13, false);
|
||||
Attack(auto_attack_target, MainPrimary, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,13 +426,13 @@ bool Client::Process() {
|
||||
&& CheckDoubleAttack(true))
|
||||
{
|
||||
tripleAttackSuccess = true;
|
||||
Attack(auto_attack_target, 13, false);
|
||||
Attack(auto_attack_target, MainPrimary, false);
|
||||
}
|
||||
|
||||
//quad attack, does this belong here??
|
||||
if(GetSpecialAbility(SPECATK_QUAD) && CheckDoubleAttack(true))
|
||||
{
|
||||
Attack(auto_attack_target, 13, false);
|
||||
Attack(auto_attack_target, MainPrimary, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,15 +444,15 @@ bool Client::Process() {
|
||||
if(MakeRandomInt(0, 99) < flurrychance)
|
||||
{
|
||||
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
|
||||
Attack(auto_attack_target, 13, false);
|
||||
Attack(auto_attack_target, 13, false);
|
||||
Attack(auto_attack_target, MainPrimary, false);
|
||||
Attack(auto_attack_target, MainPrimary, false);
|
||||
}
|
||||
}
|
||||
|
||||
int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance;
|
||||
|
||||
if (auto_attack_target && ExtraAttackChanceBonus) {
|
||||
ItemInst *wpn = GetInv().GetItem(SLOT_PRIMARY);
|
||||
ItemInst *wpn = GetInv().GetItem(MainPrimary);
|
||||
if(wpn){
|
||||
if(wpn->GetItem()->ItemType == ItemType2HSlash ||
|
||||
wpn->GetItem()->ItemType == ItemType2HBlunt ||
|
||||
@@ -460,7 +460,7 @@ bool Client::Process() {
|
||||
{
|
||||
if(MakeRandomInt(0, 99) < ExtraAttackChanceBonus)
|
||||
{
|
||||
Attack(auto_attack_target, 13, false);
|
||||
Attack(auto_attack_target, MainPrimary, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -507,19 +507,19 @@ bool Client::Process() {
|
||||
CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10);
|
||||
if (random < DualWieldProbability){ // Max 78% of DW
|
||||
if(CheckAAEffect(aaEffectRampage)) {
|
||||
entity_list.AEAttack(this, 30, 14);
|
||||
entity_list.AEAttack(this, 30, MainSecondary);
|
||||
} else {
|
||||
Attack(auto_attack_target, 14); // Single attack with offhand
|
||||
Attack(auto_attack_target, MainSecondary); // Single attack with offhand
|
||||
}
|
||||
ItemInst *wpn = GetInv().GetItem(SLOT_SECONDARY);
|
||||
TryWeaponProc(wpn, auto_attack_target, 14);
|
||||
ItemInst *wpn = GetInv().GetItem(MainSecondary);
|
||||
TryWeaponProc(wpn, auto_attack_target, MainSecondary);
|
||||
|
||||
if( CanThisClassDoubleAttack() && CheckDoubleAttack()) {
|
||||
if(CheckAAEffect(aaEffectRampage)) {
|
||||
entity_list.AEAttack(this, 30, 14);
|
||||
entity_list.AEAttack(this, 30, MainSecondary);
|
||||
} else {
|
||||
if(auto_attack_target && auto_attack_target->GetHP() > -10)
|
||||
Attack(auto_attack_target, 14); // Single attack with offhand
|
||||
Attack(auto_attack_target, MainSecondary); // Single attack with offhand
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -878,9 +878,9 @@ void Client::BulkSendInventoryItems() {
|
||||
|
||||
// Power Source
|
||||
if(GetClientVersion() >= EQClientSoF) {
|
||||
const ItemInst* inst = m_inv[9999];
|
||||
const ItemInst* inst = m_inv[MainPowerSource];
|
||||
if(inst) {
|
||||
std::string packet = inst->Serialize(9999);
|
||||
std::string packet = inst->Serialize(MainPowerSource);
|
||||
ser_items[i++] = packet;
|
||||
size += packet.length();
|
||||
}
|
||||
@@ -1217,7 +1217,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app)
|
||||
switch(memspell->scribing)
|
||||
{
|
||||
case memSpellScribing: { // scribing spell to book
|
||||
const ItemInst* inst = m_inv[SLOT_CURSOR];
|
||||
const ItemInst* inst = m_inv[MainCursor];
|
||||
|
||||
if(inst && inst->IsType(ItemClassCommon))
|
||||
{
|
||||
@@ -1226,7 +1226,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app)
|
||||
if(item && item->Scroll.Effect == (int32)(memspell->spell_id))
|
||||
{
|
||||
ScribeSpell(memspell->spell_id, memspell->slot);
|
||||
DeleteItemInInventory(SLOT_CURSOR, 1, true);
|
||||
DeleteItemInInventory(MainCursor, 1, true);
|
||||
}
|
||||
else
|
||||
Message(0,"Scribing spell: inst exists but item does not or spell ids do not match.");
|
||||
|
||||
+15
-15
@@ -2957,9 +2957,9 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
}
|
||||
if(c->GetClientVersion() >= EQClientSoF)
|
||||
{
|
||||
const ItemInst* inst = client->GetInv().GetItem(9999);
|
||||
const ItemInst* inst = client->GetInv().GetItem(MainPowerSource);
|
||||
item = (inst) ? inst->GetItem() : nullptr;
|
||||
c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", 9999,
|
||||
c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", MainPowerSource,
|
||||
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
|
||||
((item==0)?"null":item->Name), 0x12,
|
||||
((item==0)?0:inst->GetCharges()));
|
||||
@@ -2977,12 +2977,12 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
if(client->GetInv().CursorEmpty()) { // Display 'front' cursor slot even if 'empty' (item(30[0]) == null)
|
||||
if (c->GetClientVersion() >= EQClientSoF)
|
||||
{
|
||||
c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
|
||||
c->Message((item == 0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", MainCursor, i,
|
||||
0, 0x12, 0, "null", 0x12, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
|
||||
c->Message((item == 0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", MainCursor, i,
|
||||
0, 0x12, 0, "null", 0x12, 0);
|
||||
}
|
||||
}
|
||||
@@ -2992,14 +2992,14 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
item = (inst) ? inst->GetItem() : nullptr;
|
||||
if (c->GetClientVersion() >= EQClientSoF)
|
||||
{
|
||||
c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
|
||||
c->Message((item == 0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", MainCursor, i,
|
||||
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
|
||||
((item==0)?"null":item->Name), 0x12,
|
||||
((item==0)?0:inst->GetCharges()));
|
||||
}
|
||||
else
|
||||
{
|
||||
c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
|
||||
c->Message((item == 0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", MainCursor, i,
|
||||
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
|
||||
((item==0)?"null":item->Name), 0x12,
|
||||
((item==0)?0:inst->GetCharges()));
|
||||
@@ -3007,21 +3007,21 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
|
||||
if (inst && inst->IsType(ItemClassContainer) && i==0) { // 'CSD 1' - only display contents of slot 30[0] container..higher ones don't exist
|
||||
for (uint8 j=0; j<10; j++) {
|
||||
const ItemInst* instbag = client->GetInv().GetItem(SLOT_CURSOR, j);
|
||||
const ItemInst* instbag = client->GetInv().GetItem(MainCursor, j);
|
||||
item = (instbag) ? instbag->GetItem() : nullptr;
|
||||
if (c->GetClientVersion() >= EQClientSoF)
|
||||
{
|
||||
c->Message((item==0), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i",
|
||||
Inventory::CalcSlotId(SLOT_CURSOR, j),
|
||||
SLOT_CURSOR, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
|
||||
Inventory::CalcSlotId(MainCursor, j),
|
||||
MainCursor, j, ((item == 0) ? 0 : item->ID), 0x12, ((item == 0) ? 0 : item->ID),
|
||||
((item==0)?"null":item->Name), 0x12,
|
||||
((item==0)?0:instbag->GetCharges()));
|
||||
}
|
||||
else
|
||||
{
|
||||
c->Message((item==0), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i",
|
||||
Inventory::CalcSlotId(SLOT_CURSOR, j),
|
||||
SLOT_CURSOR, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
|
||||
Inventory::CalcSlotId(MainCursor, j),
|
||||
MainCursor, j, ((item == 0) ? 0 : item->ID), 0x12, ((item == 0) ? 0 : item->ID),
|
||||
((item==0)?"null":item->Name), 0x12,
|
||||
((item==0)?0:instbag->GetCharges()));
|
||||
}
|
||||
@@ -3034,7 +3034,7 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
if (bAll || (strcasecmp(sep->arg[1], "trib")==0)) {
|
||||
// Active tribute effect items
|
||||
bFound = true;
|
||||
for (int16 i=TRIBUTE_SLOT_START; i<(TRIBUTE_SLOT_START + MAX_PLAYER_TRIBUTES); i++) {
|
||||
for (int16 i = EmuConstants::TRIBUTE_BEGIN; i <= EmuConstants::TRIBUTE_END; i++) {
|
||||
const ItemInst* inst = client->GetInv().GetItem(i);
|
||||
item = (inst) ? inst->GetItem() : nullptr;
|
||||
if (c->GetClientVersion() >= EQClientSoF)
|
||||
@@ -3533,7 +3533,7 @@ void command_equipitem(Client *c, const Seperator *sep)
|
||||
{
|
||||
uint32 slot_id = atoi(sep->arg[1]);
|
||||
if (sep->IsNumber(1) && (slot_id>=0) && (slot_id<=21)) {
|
||||
const ItemInst* from_inst = c->GetInv().GetItem(SLOT_CURSOR);
|
||||
const ItemInst* from_inst = c->GetInv().GetItem(MainCursor);
|
||||
const ItemInst* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack)
|
||||
bool partialmove = false;
|
||||
int16 movecount;
|
||||
@@ -3541,7 +3541,7 @@ void command_equipitem(Client *c, const Seperator *sep)
|
||||
if (from_inst && from_inst->IsType(ItemClassCommon)) {
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct));
|
||||
MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer;
|
||||
mi->from_slot = SLOT_CURSOR;
|
||||
mi->from_slot = MainCursor;
|
||||
mi->to_slot = slot_id;
|
||||
// mi->number_in_stack = from_inst->GetCharges(); // replaced with con check for stacking
|
||||
|
||||
@@ -4698,7 +4698,7 @@ void command_goto(Client *c, const Seperator *sep)
|
||||
|
||||
void command_iteminfo(Client *c, const Seperator *sep)
|
||||
{
|
||||
const ItemInst* inst = c->GetInv()[SLOT_CURSOR];
|
||||
const ItemInst* inst = c->GetInv()[MainCursor];
|
||||
|
||||
if (!inst)
|
||||
c->Message(13, "Error: You need an item on your cursor for this command");
|
||||
|
||||
+3
-1
@@ -266,6 +266,7 @@ struct StatBonuses {
|
||||
|
||||
int16 StrikeThrough; // PoP: Strike Through %
|
||||
int16 MeleeMitigation; //i = Shielding
|
||||
int16 MeleeMitigationEffect; //i = Spell Effect Melee Mitigation
|
||||
int16 CriticalHitChance[HIGHEST_SKILL+2]; //i
|
||||
int16 CriticalSpellChance; //i
|
||||
int16 SpellCritDmgIncrease; //i
|
||||
@@ -275,7 +276,8 @@ struct StatBonuses {
|
||||
int16 CriticalHealOverTime; //i
|
||||
int16 CriticalDoTChance; //i
|
||||
int16 CrippBlowChance; //
|
||||
int16 AvoidMeleeChance; //AvoidMeleeChance/10 == % chance i = Avoidance
|
||||
int16 AvoidMeleeChance; //AvoidMeleeChance/10 == % chance i = Avoidance (item mod)
|
||||
int16 AvoidMeleeChanceEffect; //AvoidMeleeChance Spell Effect
|
||||
int16 RiposteChance; //i
|
||||
int16 DodgeChance; //i
|
||||
int16 ParryChance; //i
|
||||
|
||||
+10
-18
@@ -367,9 +367,9 @@ Corpse::Corpse(Client* client, int32 in_rezexp)
|
||||
for(i = 0; i <= 30; i++)
|
||||
{
|
||||
if(i == 21 && client->GetClientVersion() >= EQClientSoF) {
|
||||
item = client->GetInv().GetItem(9999);
|
||||
item = client->GetInv().GetItem(MainPowerSource);
|
||||
if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
|
||||
std::list<uint32> slot_list = MoveItemToCorpse(client, item, 9999);
|
||||
std::list<uint32> slot_list = MoveItemToCorpse(client, item, MainPowerSource);
|
||||
removed_list.merge(slot_list);
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp)
|
||||
|
||||
if(cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false)
|
||||
while(!client->GetInv().CursorEmpty())
|
||||
client->DeleteItemInInventory(SLOT_CURSOR, 0, false, false);
|
||||
client->DeleteItemInInventory(MainCursor, 0, false, false);
|
||||
}
|
||||
else { // only visible cursor made it to corpse (client >= Sof and RespawnFromHover = true)
|
||||
std::list<ItemInst*>::const_iterator start = client->GetInv().cursor_begin();
|
||||
@@ -999,12 +999,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
|
||||
end = itemlist.end();
|
||||
|
||||
uint8 containercount = 0;
|
||||
int corpselootlimit;
|
||||
|
||||
if(client->GetClientVersion() >= EQClientRoF) { corpselootlimit = 34; }
|
||||
else if(client->GetClientVersion() >= EQClientSoF) { corpselootlimit = 32; }
|
||||
else if(client->GetClientVersion() == EQClientTitanium) { corpselootlimit = 31; }
|
||||
else { corpselootlimit = 30; }
|
||||
int corpselootlimit = EQLimits::InventoryMapSize(MapCorpse, client->GetClientVersion());
|
||||
|
||||
for(; cur != end; ++cur) {
|
||||
ServerLootItem_Struct* item_data = *cur;
|
||||
@@ -1013,7 +1009,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
|
||||
// Dont display the item if it's in a bag
|
||||
|
||||
// Added cursor queue slots to corpse item visibility list. Nothing else should be making it to corpse.
|
||||
if(!IsPlayerCorpse() || item_data->equipSlot <= 30 || item_data->equipSlot == 9999 || tCanLoot>=3 ||
|
||||
if(!IsPlayerCorpse() || item_data->equipSlot <= MainCursor || item_data->equipSlot == MainPowerSource || tCanLoot>=3 ||
|
||||
(item_data->equipSlot >= 8000 && item_data->equipSlot <= 8999)) {
|
||||
if(i < corpselootlimit) {
|
||||
item = database.GetItem(item_data->item_id);
|
||||
@@ -1145,7 +1141,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app)
|
||||
|
||||
if(inst->IsAugmented())
|
||||
{
|
||||
for(int i=0; i<MAX_AUGMENT_SLOTS; i++)
|
||||
for (int i = 0; i<EmuConstants::ITEM_COMMON_SIZE; i++)
|
||||
{
|
||||
ItemInst *itm = inst->GetAugment(i);
|
||||
if(itm)
|
||||
@@ -1227,11 +1223,11 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app)
|
||||
if(lootitem->auto_loot)
|
||||
{
|
||||
if(!client->AutoPutLootInInventory(*inst, true, true, bag_item_data))
|
||||
client->PutLootInInventory(SLOT_CURSOR, *inst, bag_item_data);
|
||||
client->PutLootInInventory(MainCursor, *inst, bag_item_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
client->PutLootInInventory(SLOT_CURSOR, *inst, bag_item_data);
|
||||
client->PutLootInInventory(MainCursor, *inst, bag_item_data);
|
||||
}
|
||||
// Update any tasks that have an activity to loot this item.
|
||||
if(RuleB(TaskSystem, EnableTaskSystem))
|
||||
@@ -1331,17 +1327,13 @@ void Corpse::QueryLoot(Client* to) {
|
||||
cur = itemlist.begin();
|
||||
end = itemlist.end();
|
||||
|
||||
int corpselootlimit;
|
||||
|
||||
if (to->GetClientVersion() >= EQClientSoF) { corpselootlimit = 32; }
|
||||
else if (to->GetClientVersion() == EQClientTitanium) { corpselootlimit = 31; }
|
||||
else { corpselootlimit = 30; }
|
||||
int corpselootlimit = EQLimits::InventoryMapSize(MapCorpse, to->GetClientVersion());
|
||||
|
||||
for(; cur != end; ++cur) {
|
||||
ServerLootItem_Struct* sitem = *cur;
|
||||
|
||||
if (IsPlayerCorpse()) {
|
||||
if (sitem->equipSlot >= 251 && sitem->equipSlot <= 340)
|
||||
if (sitem->equipSlot >= EmuConstants::GENERAL_BAGS_BEGIN && sitem->equipSlot <= EmuConstants::CURSOR_BAG_END)
|
||||
sitem->lootslot = 0xFFFF;
|
||||
else
|
||||
x < corpselootlimit ? sitem->lootslot = x : sitem->lootslot = 0xFFFF;
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ public:
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; }
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; }
|
||||
virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false,
|
||||
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false,
|
||||
ExtraAttackOptions *opts = nullptr) { return false; }
|
||||
virtual bool HasRaid() { return false; }
|
||||
virtual bool HasGroup() { return false; }
|
||||
|
||||
+3
-3
@@ -162,7 +162,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger)
|
||||
{
|
||||
if(!sender->KeyRingCheck(RuleI(Adventure, ItemIDToEnablePorts)))
|
||||
{
|
||||
if(sender->GetInv().HasItem(RuleI(Adventure, ItemIDToEnablePorts)) == SLOT_INVALID)
|
||||
if (sender->GetInv().HasItem(RuleI(Adventure, ItemIDToEnablePorts)) == INVALID_INDEX)
|
||||
{
|
||||
sender->Message_StringID(13, DUNGEON_SEALED);
|
||||
safe_delete(outapp);
|
||||
@@ -195,11 +195,11 @@ void Doors::HandleClick(Client* sender, uint8 trigger)
|
||||
uint8 keepoffkeyring = GetNoKeyring();
|
||||
uint32 haskey = 0;
|
||||
uint32 playerkey = 0;
|
||||
const ItemInst *lockpicks = sender->GetInv().GetItem(SLOT_CURSOR);
|
||||
const ItemInst *lockpicks = sender->GetInv().GetItem(MainCursor);
|
||||
|
||||
haskey = sender->GetInv().HasItem(keyneeded, 1);
|
||||
|
||||
if(haskey != SLOT_INVALID)
|
||||
if (haskey != INVALID_INDEX)
|
||||
{
|
||||
playerkey = keyneeded;
|
||||
}
|
||||
|
||||
+1
-1
@@ -305,7 +305,7 @@ public:
|
||||
void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app);
|
||||
void QueueManaged(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, bool ackreq = true);
|
||||
|
||||
void AEAttack(Mob *attacker, float dist, int Hand = 13, int count = 0, bool IsFromSpell = false);
|
||||
void AEAttack(Mob *attacker, float dist, int Hand = MainPrimary, int count = 0, bool IsFromSpell = false);
|
||||
void AETaunt(Client *caster, float range = 0);
|
||||
void AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true, int16 resist_adjust = 0);
|
||||
void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true);
|
||||
|
||||
+9
-9
@@ -206,10 +206,10 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id,
|
||||
//we need this function to immediately determine, after we receive OP_Fishing, if we can even try to fish, otherwise we have to wait a while to get the failure
|
||||
bool Client::CanFish() {
|
||||
//make sure we still have a fishing pole on:
|
||||
const ItemInst* Pole = m_inv[SLOT_PRIMARY];
|
||||
const ItemInst* Pole = m_inv[MainPrimary];
|
||||
int32 bslot = m_inv.HasItemByUse(ItemTypeFishingBait, 1, invWhereWorn|invWherePersonal);
|
||||
const ItemInst* Bait = nullptr;
|
||||
if(bslot != SLOT_INVALID)
|
||||
if (bslot != INVALID_INDEX)
|
||||
Bait = m_inv.GetItem(bslot);
|
||||
|
||||
if(!Pole || !Pole->IsType(ItemClassCommon) || Pole->GetItem()->ItemType != ItemTypeFishingPole) {
|
||||
@@ -297,11 +297,11 @@ void Client::GoFish()
|
||||
//make sure we still have a fishing pole on:
|
||||
int32 bslot = m_inv.HasItemByUse(ItemTypeFishingBait, 1, invWhereWorn|invWherePersonal);
|
||||
const ItemInst* Bait = nullptr;
|
||||
if(bslot != SLOT_INVALID)
|
||||
if (bslot != INVALID_INDEX)
|
||||
Bait = m_inv.GetItem(bslot);
|
||||
|
||||
//if the bait isnt equipped, need to add its skill bonus
|
||||
if(bslot >= IDX_INV && Bait->GetItem()->SkillModType == SkillFishing) {
|
||||
if(bslot >= EmuConstants::GENERAL_BEGIN && Bait->GetItem()->SkillModType == SkillFishing) {
|
||||
fishing_skill += Bait->GetItem()->SkillModValue;
|
||||
}
|
||||
|
||||
@@ -358,12 +358,12 @@ void Client::GoFish()
|
||||
else
|
||||
{
|
||||
PushItemOnCursor(*inst);
|
||||
SendItemPacket(SLOT_CURSOR,inst,ItemPacketSummonItem);
|
||||
SendItemPacket(MainCursor, inst, ItemPacketSummonItem);
|
||||
if(RuleB(TaskSystem, EnableTaskSystem))
|
||||
UpdateTasksForItem(ActivityFish, food_id);
|
||||
|
||||
safe_delete(inst);
|
||||
inst = m_inv.GetItem(SLOT_CURSOR);
|
||||
inst = m_inv.GetItem(MainCursor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,7 +393,7 @@ void Client::GoFish()
|
||||
//and then swap out items in primary slot... too lazy to fix right now
|
||||
if (MakeRandomInt(0, 49) == 1) {
|
||||
Message_StringID(MT_Skills, FISHING_POLE_BROKE); //Your fishing pole broke!
|
||||
DeleteItemInInventory(13,0,true);
|
||||
DeleteItemInInventory(MainPrimary, 0, true);
|
||||
}
|
||||
|
||||
if(CheckIncreaseSkill(SkillFishing, nullptr, 5))
|
||||
@@ -472,12 +472,12 @@ void Client::ForageItem(bool guarantee) {
|
||||
}
|
||||
else {
|
||||
PushItemOnCursor(*inst);
|
||||
SendItemPacket(SLOT_CURSOR, inst, ItemPacketSummonItem);
|
||||
SendItemPacket(MainCursor, inst, ItemPacketSummonItem);
|
||||
if(RuleB(TaskSystem, EnableTaskSystem))
|
||||
UpdateTasksForItem(ActivityForage, foragedfood);
|
||||
|
||||
safe_delete(inst);
|
||||
inst = m_inv.GetItem(SLOT_CURSOR);
|
||||
inst = m_inv.GetItem(MainCursor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -545,7 +545,7 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption
|
||||
if(cur)
|
||||
{
|
||||
for(int i = 0; i < count; ++i) {
|
||||
caster->Attack(cur, 13, false, false, false, opts);
|
||||
caster->Attack(cur, MainPrimary, false, false, false, opts);
|
||||
}
|
||||
}
|
||||
iter++;
|
||||
|
||||
+122
-120
@@ -44,7 +44,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
|
||||
int i;
|
||||
if(where_to_check & invWhereWorn) {
|
||||
for (i=0; i<=21; i++) { // Equipped
|
||||
for (i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; i++) {
|
||||
if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(i);
|
||||
if(cur && cur->GetItem()->Stackable) {
|
||||
@@ -57,9 +57,8 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
}
|
||||
}
|
||||
|
||||
// Power Source Slot
|
||||
if (GetItemIDAt(9999) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(9999) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(9999);
|
||||
if (GetItemIDAt(MainPowerSource) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(MainPowerSource) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(MainPowerSource);
|
||||
if(cur && cur->GetItem()->Stackable) {
|
||||
x += cur->GetCharges();
|
||||
} else {
|
||||
@@ -67,25 +66,25 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
}
|
||||
|
||||
if (GetClientVersion() >= EQClientSoF)
|
||||
DeleteItemInInventory(9999, 0, true);
|
||||
DeleteItemInInventory(MainPowerSource, 0, true);
|
||||
else
|
||||
DeleteItemInInventory(9999, 0, false); // Prevents Titanium crash
|
||||
DeleteItemInInventory(MainPowerSource, 0, false); // Prevents Titanium crash
|
||||
}
|
||||
}
|
||||
|
||||
if(where_to_check & invWhereCursor) {
|
||||
if (GetItemIDAt(30) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(30) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(30);
|
||||
if (GetItemIDAt(MainCursor) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(MainCursor) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(MainCursor);
|
||||
if(cur && cur->GetItem()->Stackable) {
|
||||
x += cur->GetCharges();
|
||||
} else {
|
||||
x++;
|
||||
}
|
||||
|
||||
DeleteItemInInventory(30, 0, true);
|
||||
DeleteItemInInventory(MainCursor, 0, true);
|
||||
}
|
||||
|
||||
for (i=331; i<=340; i++) { // cursor's containers
|
||||
for (i = EmuConstants::CURSOR_BAG_BEGIN; i <= EmuConstants::CURSOR_BAG_END; i++) {
|
||||
if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(i);
|
||||
if(cur && cur->GetItem()->Stackable) {
|
||||
@@ -100,7 +99,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
}
|
||||
|
||||
if(where_to_check & invWherePersonal) {
|
||||
for (i=22; i<=29; i++) { // Equipped
|
||||
for (i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) {
|
||||
if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(i);
|
||||
if(cur && cur->GetItem()->Stackable) {
|
||||
@@ -113,7 +112,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
}
|
||||
}
|
||||
|
||||
for (i=251; i<=330; i++) { // Main inventory's containers
|
||||
for (i = EmuConstants::GENERAL_BAGS_BEGIN; i <= EmuConstants::GENERAL_BAGS_END; i++) {
|
||||
if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(i);
|
||||
if(cur && cur->GetItem()->Stackable) {
|
||||
@@ -128,7 +127,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
}
|
||||
|
||||
if(where_to_check & invWhereBank) {
|
||||
for (i=2000; i<=2023; i++) { // Bank slots
|
||||
for (i = EmuConstants::BANK_BEGIN; i <= EmuConstants::BANK_END; i++) {
|
||||
if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(i);
|
||||
if(cur && cur->GetItem()->Stackable) {
|
||||
@@ -141,7 +140,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
}
|
||||
}
|
||||
|
||||
for (i=2031; i<=2270; i++) { // Bank's containers
|
||||
for (i = EmuConstants::BANK_BAGS_BEGIN; i <= EmuConstants::BANK_BAGS_END; i++) {
|
||||
if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(i);
|
||||
if(cur && cur->GetItem()->Stackable) {
|
||||
@@ -156,7 +155,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
}
|
||||
|
||||
if(where_to_check & invWhereSharedBank) {
|
||||
for (i=2500; i<=2501; i++) { // Shared bank
|
||||
for (i = EmuConstants::SHARED_BANK_BEGIN; i <= EmuConstants::SHARED_BANK_END; i++) {
|
||||
if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(i);
|
||||
if(cur && cur->GetItem()->Stackable) {
|
||||
@@ -169,7 +168,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
}
|
||||
}
|
||||
|
||||
for (i=2531; i<=2550; i++) { // Shared bank's containers
|
||||
for (i = EmuConstants::SHARED_BANK_BAGS_BEGIN; i <= EmuConstants::SHARED_BANK_BAGS_END; i++) {
|
||||
if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) {
|
||||
cur = m_inv.GetItem(i);
|
||||
if(cur && cur->GetItem()->Stackable) {
|
||||
@@ -194,10 +193,10 @@ bool Client::CheckLoreConflict(const Item_Struct* item) {
|
||||
return false;
|
||||
|
||||
if (item->LoreGroup == -1) // Standard lore items; look everywhere except the shared bank, return the result
|
||||
return (m_inv.HasItem(item->ID, 0, ~invWhereSharedBank) != SLOT_INVALID);
|
||||
return (m_inv.HasItem(item->ID, 0, ~invWhereSharedBank) != INVALID_INDEX);
|
||||
|
||||
//If the item has a lore group, we check for other items with the same group and return the result
|
||||
return (m_inv.HasItemByLoreGroup(item->LoreGroup, ~invWhereSharedBank) != SLOT_INVALID);
|
||||
return (m_inv.HasItemByLoreGroup(item->LoreGroup, ~invWhereSharedBank) != INVALID_INDEX);
|
||||
}
|
||||
|
||||
bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) {
|
||||
@@ -244,7 +243,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
|
||||
}
|
||||
*/
|
||||
|
||||
uint32 augments[MAX_AUGMENT_SLOTS] = { aug1, aug2, aug3, aug4, aug5 };
|
||||
uint32 augments[EmuConstants::ITEM_COMMON_SIZE] = { aug1, aug2, aug3, aug4, aug5 };
|
||||
|
||||
uint32 classes = item->Classes;
|
||||
uint32 races = item->Races;
|
||||
@@ -254,7 +253,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
|
||||
bool enforcerestr = RuleB(Inventory, EnforceAugmentRestriction);
|
||||
bool enforceusable = RuleB(Inventory, EnforceAugmentUsability);
|
||||
|
||||
for(int iter = 0; iter < MAX_AUGMENT_SLOTS; ++iter) {
|
||||
for (int iter = 0; iter < EmuConstants::ITEM_COMMON_SIZE; ++iter) {
|
||||
const Item_Struct* augtest = database.GetItem(augments[iter]);
|
||||
|
||||
if(augtest == nullptr) {
|
||||
@@ -548,7 +547,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
|
||||
}
|
||||
|
||||
// add any validated augments
|
||||
for(int iter = 0; iter < MAX_AUGMENT_SLOTS; ++iter) {
|
||||
for (int iter = 0; iter < EmuConstants::ITEM_COMMON_SIZE; ++iter) {
|
||||
if(augments[iter])
|
||||
inst->PutAugment(&database, iter, augments[iter]);
|
||||
}
|
||||
@@ -558,22 +557,22 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
|
||||
inst->SetInstNoDrop(true);
|
||||
|
||||
// check to see if item is usable in requested slot
|
||||
if(enforceusable && (((to_slot >= 0) && (to_slot <= 21)) || (to_slot == 9999))) {
|
||||
uint32 slottest = (to_slot == 9999) ? 22 : to_slot;
|
||||
if(enforceusable && (((to_slot >= MainCharm) && (to_slot <= MainAmmo)) || (to_slot == MainPowerSource))) {
|
||||
uint32 slottest = (to_slot == MainPowerSource) ? 22 : to_slot; // can't change '22' just yet...
|
||||
|
||||
if(!(slots & ((uint32)1 << slottest))) {
|
||||
Message(0, "This item is not equipable at slot %u - moving to cursor.", to_slot);
|
||||
mlog(INVENTORY__ERROR, "Player %s on account %s attempted to equip an item unusable in slot %u - moved to cursor.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u)\n",
|
||||
GetName(), account_name, to_slot, item->ID, aug1, aug2, aug3, aug4, aug5);
|
||||
|
||||
to_slot = SLOT_CURSOR;
|
||||
to_slot = MainCursor;
|
||||
}
|
||||
}
|
||||
|
||||
// put item into inventory
|
||||
if(to_slot == SLOT_CURSOR) {
|
||||
if (to_slot == MainCursor) {
|
||||
PushItemOnCursor(*inst);
|
||||
SendItemPacket(SLOT_CURSOR, inst, ItemPacketSummonItem);
|
||||
SendItemPacket(MainCursor, inst, ItemPacketSummonItem);
|
||||
}
|
||||
else {
|
||||
PutItemInInventory(to_slot, *inst, true);
|
||||
@@ -586,7 +585,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
|
||||
if(!IsDiscovered(item_id))
|
||||
DiscoverItem(item_id);
|
||||
|
||||
for(int iter = 0; iter < MAX_AUGMENT_SLOTS; ++iter) {
|
||||
for (int iter = 0; iter < EmuConstants::ITEM_COMMON_SIZE; ++iter) {
|
||||
if(augments[iter] && !IsDiscovered(augments[iter]))
|
||||
DiscoverItem(augments[iter]);
|
||||
}
|
||||
@@ -619,7 +618,7 @@ void Client::DropItem(int16 slot_id)
|
||||
}
|
||||
|
||||
// Save client inventory change to database
|
||||
if(slot_id == SLOT_CURSOR) {
|
||||
if (slot_id == MainCursor) {
|
||||
std::list<ItemInst*>::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end();
|
||||
database.SaveCursor(CharacterID(), s, e);
|
||||
} else {
|
||||
@@ -755,7 +754,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd
|
||||
bool isDeleted = m_inv.DeleteItem(slot_id, quantity);
|
||||
|
||||
const ItemInst* inst=nullptr;
|
||||
if (slot_id==SLOT_CURSOR) {
|
||||
if (slot_id == MainCursor) {
|
||||
std::list<ItemInst*>::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end();
|
||||
if(update_db)
|
||||
database.SaveCursor(character_id, s, e);
|
||||
@@ -807,7 +806,7 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update)
|
||||
m_inv.PushCursor(inst);
|
||||
|
||||
if (client_update) {
|
||||
SendItemPacket(SLOT_CURSOR, &inst, ItemPacketSummonItem);
|
||||
SendItemPacket(MainCursor, &inst, ItemPacketSummonItem);
|
||||
}
|
||||
|
||||
std::list<ItemInst*>::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end();
|
||||
@@ -817,7 +816,7 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update)
|
||||
bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client_update)
|
||||
{
|
||||
mlog(INVENTORY__SLOTS, "Putting item %s (%d) into slot %d", inst.GetItem()->Name, inst.GetItem()->ID, slot_id);
|
||||
if (slot_id==SLOT_CURSOR)
|
||||
if (slot_id == MainCursor)
|
||||
{
|
||||
return PushItemOnCursor(inst,client_update);
|
||||
}
|
||||
@@ -825,10 +824,10 @@ bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client
|
||||
m_inv.PutItem(slot_id, inst);
|
||||
|
||||
if (client_update) {
|
||||
SendItemPacket(slot_id, &inst, (slot_id==SLOT_CURSOR)?ItemPacketSummonItem:ItemPacketTrade);
|
||||
SendItemPacket(slot_id, &inst, (slot_id == MainCursor) ? ItemPacketSummonItem : ItemPacketTrade);
|
||||
}
|
||||
|
||||
if (slot_id==SLOT_CURSOR) {
|
||||
if (slot_id == MainCursor) {
|
||||
std::list<ItemInst*>::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end();
|
||||
return database.SaveCursor(this->CharacterID(), s, e);
|
||||
} else
|
||||
@@ -844,7 +843,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI
|
||||
|
||||
SendLootItemInPacket(&inst, slot_id);
|
||||
|
||||
if (slot_id==SLOT_CURSOR) {
|
||||
if (slot_id == MainCursor) {
|
||||
std::list<ItemInst*>::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end();
|
||||
database.SaveCursor(this->CharacterID(), s, e);
|
||||
} else
|
||||
@@ -919,25 +918,25 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs
|
||||
|
||||
if (!m_inv[i])
|
||||
{
|
||||
if( i == SLOT_PRIMARY && inst.IsWeapon() ) // If item is primary slot weapon
|
||||
if( i == MainPrimary && inst.IsWeapon() ) // If item is primary slot weapon
|
||||
{
|
||||
if( (inst.GetItem()->ItemType == ItemType2HSlash) || (inst.GetItem()->ItemType == ItemType2HBlunt) || (inst.GetItem()->ItemType == ItemType2HPiercing) ) // and uses 2hs \ 2hb \ 2hp
|
||||
{
|
||||
if( m_inv[SLOT_SECONDARY] ) // and if secondary slot is not empty
|
||||
if( m_inv[MainSecondary] ) // and if secondary slot is not empty
|
||||
{
|
||||
continue; // Can't auto-equip
|
||||
}
|
||||
}
|
||||
}
|
||||
if( i== SLOT_SECONDARY && m_inv[SLOT_PRIMARY]) // check to see if primary slot is a two hander
|
||||
if( i== MainSecondary && m_inv[MainPrimary]) // check to see if primary slot is a two hander
|
||||
{
|
||||
uint8 use = m_inv[SLOT_PRIMARY]->GetItem()->ItemType;
|
||||
uint8 use = m_inv[MainPrimary]->GetItem()->ItemType;
|
||||
if(use == ItemType2HSlash || use == ItemType2HBlunt || use == ItemType2HPiercing)
|
||||
continue;
|
||||
}
|
||||
if
|
||||
(
|
||||
i == SLOT_SECONDARY &&
|
||||
i == MainSecondary &&
|
||||
inst.IsWeapon() &&
|
||||
!CanThisClassDualWield()
|
||||
)
|
||||
@@ -972,7 +971,7 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs
|
||||
// #3: put it in inventory
|
||||
bool is_arrow = (inst.GetItem()->ItemType == ItemTypeArrow) ? true : false;
|
||||
int16 slot_id = m_inv.FindFreeSlot(inst.IsType(ItemClassContainer), try_cursor, inst.GetItem()->Size, is_arrow);
|
||||
if (slot_id != SLOT_INVALID)
|
||||
if (slot_id != INVALID_INDEX)
|
||||
{
|
||||
PutLootInInventory(slot_id, inst, bag_item_data);
|
||||
return true;
|
||||
@@ -1000,7 +999,7 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type)
|
||||
tmp_inst->SetCharges(tmp_inst->GetCharges() + charges_to_move);
|
||||
from.SetCharges(from.GetCharges() - charges_to_move);
|
||||
SendLootItemInPacket(tmp_inst, to_slot);
|
||||
if (to_slot==SLOT_CURSOR){
|
||||
if (to_slot == MainCursor){
|
||||
std::list<ItemInst*>::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end();
|
||||
database.SaveCursor(this->CharacterID(), s, e);
|
||||
} else
|
||||
@@ -1224,25 +1223,21 @@ void Client::SendLootItemInPacket(const ItemInst* inst, int16 slot_id)
|
||||
SendItemPacket(slot_id,inst, ItemPacketTrade);
|
||||
}
|
||||
|
||||
bool Client::IsValidSlot(uint32 slot)
|
||||
{
|
||||
if((slot == (uint32)SLOT_INVALID) || // Destroying/Dropping item
|
||||
(slot >= 0 && slot <= 30) || // Worn inventory, normal inventory, and cursor
|
||||
(slot >= 251 && slot <= 340) || // Normal inventory bags and cursor bag
|
||||
(slot >= 400 && slot <= 404) || // Tribute
|
||||
(slot >= 2000 && slot <= 2023) || // Bank
|
||||
(slot >= 2031 && slot <= 2270) || // Bank bags
|
||||
(slot >= 2500 && slot <= 2501) || // Shared bank
|
||||
(slot >= 2531 && slot <= 2550) || // Shared bank bags
|
||||
(slot >= 3000 && slot <= 3007) || // Trade window
|
||||
(slot >= 4000 && slot <= 4009) || // Tradeskill container
|
||||
(slot == 9999)) // Power Source
|
||||
{
|
||||
bool Client::IsValidSlot(uint32 slot) {
|
||||
if ((slot == (uint32)INVALID_INDEX) ||
|
||||
(slot >= EmuConstants::POSSESSIONS_BEGIN && slot <= EmuConstants::POSSESSIONS_END) ||
|
||||
(slot >= EmuConstants::GENERAL_BAGS_BEGIN && slot <= EmuConstants::CURSOR_BAG_END) ||
|
||||
(slot >= EmuConstants::TRIBUTE_BEGIN && slot <= EmuConstants::TRIBUTE_END) ||
|
||||
(slot >= EmuConstants::BANK_BEGIN && slot <= EmuConstants::BANK_END) ||
|
||||
(slot >= EmuConstants::BANK_BAGS_BEGIN && slot <= EmuConstants::BANK_BAGS_END) ||
|
||||
(slot >= EmuConstants::SHARED_BANK_BEGIN && slot <= EmuConstants::SHARED_BANK_END) ||
|
||||
(slot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && slot <= EmuConstants::SHARED_BANK_BAGS_END) ||
|
||||
(slot >= EmuConstants::TRADE_BEGIN && slot <= EmuConstants::TRADE_END) ||
|
||||
(slot >= EmuConstants::WORLD_BEGIN && slot <= EmuConstants::WORLD_END) ||
|
||||
(slot == EmuConstants::POWER_SOURCE))
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Client::IsBankSlot(uint32 slot)
|
||||
@@ -1289,12 +1284,12 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (move_in->to_slot == (uint32)SLOT_INVALID) {
|
||||
if(move_in->from_slot == (uint32)SLOT_CURSOR) {
|
||||
if (move_in->to_slot == (uint32)INVALID_INDEX) {
|
||||
if (move_in->from_slot == (uint32)MainCursor) {
|
||||
mlog(INVENTORY__SLOTS, "Client destroyed item from cursor slot %d", move_in->from_slot);
|
||||
if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit
|
||||
|
||||
ItemInst *inst = m_inv.GetItem(SLOT_CURSOR);
|
||||
ItemInst *inst = m_inv.GetItem(MainCursor);
|
||||
if(inst) {
|
||||
parse->EventItem(EVENT_DESTROY_ITEM, this, inst, nullptr, "", 0);
|
||||
}
|
||||
@@ -1309,9 +1304,9 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
return true; // Item deletetion
|
||||
}
|
||||
}
|
||||
if(auto_attack && (move_in->from_slot == SLOT_PRIMARY || move_in->from_slot == SLOT_SECONDARY || move_in->from_slot == SLOT_RANGE))
|
||||
if(auto_attack && (move_in->from_slot == MainPrimary || move_in->from_slot == MainSecondary || move_in->from_slot == MainRange))
|
||||
SetAttackTimer();
|
||||
else if(auto_attack && (move_in->to_slot == SLOT_PRIMARY || move_in->to_slot == SLOT_SECONDARY || move_in->to_slot == SLOT_RANGE))
|
||||
else if(auto_attack && (move_in->to_slot == MainPrimary || move_in->to_slot == MainSecondary || move_in->to_slot == MainRange))
|
||||
SetAttackTimer();
|
||||
// Step 1: Variables
|
||||
int16 src_slot_id = (int16)move_in->from_slot;
|
||||
@@ -1501,7 +1496,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
}
|
||||
|
||||
safe_delete(world_inst);
|
||||
if (src_slot_id==SLOT_CURSOR) {
|
||||
if (src_slot_id == MainCursor) {
|
||||
std::list<ItemInst*>::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end();
|
||||
database.SaveCursor(character_id, s, e);
|
||||
} else
|
||||
@@ -1515,14 +1510,14 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
|
||||
// Step 4: Check for entity trade
|
||||
if (dst_slot_id>=3000 && dst_slot_id<=3007) {
|
||||
if (src_slot_id != SLOT_CURSOR) {
|
||||
if (src_slot_id != MainCursor) {
|
||||
Kick();
|
||||
return false;
|
||||
}
|
||||
if (with) {
|
||||
mlog(INVENTORY__SLOTS, "Trade item move from slot %d to slot %d (trade with %s)", src_slot_id, dst_slot_id, with->GetName());
|
||||
// Fill Trade list with items from cursor
|
||||
if (!m_inv[SLOT_CURSOR]) {
|
||||
if (!m_inv[MainCursor]) {
|
||||
Message(13, "Error: Cursor item not located on server!");
|
||||
return false;
|
||||
}
|
||||
@@ -1538,7 +1533,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit
|
||||
|
||||
SummonItem(src_inst->GetID(), src_inst->GetCharges());
|
||||
DeleteItemInInventory(SLOT_CURSOR);
|
||||
DeleteItemInInventory(MainCursor);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1601,12 +1596,12 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
}
|
||||
else {
|
||||
// Not dealing with charges - just do direct swap
|
||||
if(src_inst && (dst_slot_id < 22 || dst_slot_id == 9999) && dst_slot_id >= 0) {
|
||||
if(src_inst && (dst_slot_id <= MainAmmo || dst_slot_id == MainPowerSource) && dst_slot_id >= MainCharm) {
|
||||
if (src_inst->GetItem()->Attuneable) {
|
||||
src_inst->SetInstNoDrop(true);
|
||||
}
|
||||
if (src_inst->IsAugmented()) {
|
||||
for(int i = 0; i < MAX_AUGMENT_SLOTS; i++) {
|
||||
for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
if (src_inst->GetAugment(i)) {
|
||||
if (src_inst->GetAugment(i)->GetItem()->Attuneable) {
|
||||
src_inst->GetAugment(i)->SetInstNoDrop(true);
|
||||
@@ -1619,7 +1614,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
if(!m_inv.SwapItem(src_slot_id, dst_slot_id)) { return false; }
|
||||
mlog(INVENTORY__SLOTS, "Moving entire item from slot %d to slot %d", src_slot_id, dst_slot_id);
|
||||
|
||||
if(src_slot_id < 22 || src_slot_id == 9999) {
|
||||
if(src_slot_id <= MainAmmo || src_slot_id == MainPowerSource) {
|
||||
if(src_inst) {
|
||||
parse->EventItem(EVENT_UNEQUIP_ITEM, this, src_inst, nullptr, "", src_slot_id);
|
||||
}
|
||||
@@ -1629,7 +1624,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
}
|
||||
}
|
||||
|
||||
if(dst_slot_id < 22 || dst_slot_id == 9999) {
|
||||
if(dst_slot_id <= MainAmmo || dst_slot_id == MainPowerSource) {
|
||||
if(dst_inst) {
|
||||
parse->EventItem(EVENT_UNEQUIP_ITEM, this, dst_inst, nullptr, "", dst_slot_id);
|
||||
}
|
||||
@@ -1646,12 +1641,12 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
}
|
||||
|
||||
// Step 7: Save change to the database
|
||||
if (src_slot_id==SLOT_CURSOR){
|
||||
if (src_slot_id == MainCursor){
|
||||
std::list<ItemInst*>::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end();
|
||||
database.SaveCursor(character_id, s, e);
|
||||
} else
|
||||
database.SaveInventory(character_id, m_inv.GetItem(src_slot_id), src_slot_id);
|
||||
if (dst_slot_id==SLOT_CURSOR) {
|
||||
if (dst_slot_id == MainCursor) {
|
||||
std::list<ItemInst*>::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end();
|
||||
database.SaveCursor(character_id, s, e);
|
||||
} else
|
||||
@@ -1665,14 +1660,17 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
}
|
||||
|
||||
void Client::SwapItemResync(MoveItem_Struct* move_slots) {
|
||||
// wow..this thing created a helluva memory leak...
|
||||
// with any luck..this won't be needed in the future
|
||||
|
||||
// resync the 'from' and 'to' slots on an as-needed basis
|
||||
// Not as effective as the full process, but less intrusive to gameplay -U
|
||||
mlog(INVENTORY__ERROR, "Inventory desyncronization. (charname: %s, source: %i, destination: %i)", GetName(), move_slots->from_slot, move_slots->to_slot);
|
||||
Message(15, "Inventory Desyncronization detected: Resending slot data...");
|
||||
|
||||
if((move_slots->from_slot >= 0 && move_slots->from_slot <= 340) || move_slots->from_slot == 9999) {
|
||||
int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == SLOT_INVALID) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot);
|
||||
if(IsValidSlot(resync_slot) && resync_slot != SLOT_INVALID) {
|
||||
if((move_slots->from_slot >= MainCharm && move_slots->from_slot <= 340) || move_slots->from_slot == MainPowerSource) {
|
||||
int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot);
|
||||
if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) {
|
||||
// This prevents the client from crashing when closing any 'phantom' bags -U
|
||||
const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin'
|
||||
ItemInst* token_inst = database.CreateItem(token_struct, 1);
|
||||
@@ -1690,13 +1688,14 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) {
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
safe_delete(token_inst);
|
||||
Message(14, "Source slot %i resyncronized.", move_slots->from_slot);
|
||||
}
|
||||
else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); }
|
||||
}
|
||||
else {
|
||||
int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == SLOT_INVALID) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot);
|
||||
if(IsValidSlot(resync_slot) && resync_slot != SLOT_INVALID) {
|
||||
int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot);
|
||||
if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) {
|
||||
if(m_inv[resync_slot]) {
|
||||
const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin'
|
||||
ItemInst* token_inst = database.CreateItem(token_struct, 1);
|
||||
@@ -1704,6 +1703,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) {
|
||||
SendItemPacket(resync_slot, token_inst, ItemPacketTrade);
|
||||
SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade);
|
||||
|
||||
safe_delete(token_inst);
|
||||
Message(14, "Source slot %i resyncronized.", move_slots->from_slot);
|
||||
}
|
||||
else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); }
|
||||
@@ -1711,9 +1711,9 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) {
|
||||
else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); }
|
||||
}
|
||||
|
||||
if((move_slots->to_slot >= 0 && move_slots->to_slot <= 340) || move_slots->to_slot == 9999) {
|
||||
int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == SLOT_INVALID) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot);
|
||||
if(IsValidSlot(resync_slot) && resync_slot != SLOT_INVALID) {
|
||||
if((move_slots->to_slot >= MainCharm && move_slots->to_slot <= 340) || move_slots->to_slot == MainPowerSource) {
|
||||
int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot);
|
||||
if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) {
|
||||
const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin'
|
||||
ItemInst* token_inst = database.CreateItem(token_struct, 1);
|
||||
|
||||
@@ -1730,13 +1730,14 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) {
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
safe_delete(token_inst);
|
||||
Message(14, "Destination slot %i resyncronized.", move_slots->to_slot);
|
||||
}
|
||||
else { Message(13, "Could not resyncronize destination slot %i.", move_slots->to_slot); }
|
||||
}
|
||||
else {
|
||||
int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == SLOT_INVALID) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot);
|
||||
if(IsValidSlot(resync_slot) && resync_slot != SLOT_INVALID) {
|
||||
int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot);
|
||||
if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) {
|
||||
if(m_inv[resync_slot]) {
|
||||
const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin'
|
||||
ItemInst* token_inst = database.CreateItem(token_struct, 1);
|
||||
@@ -1744,6 +1745,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) {
|
||||
SendItemPacket(resync_slot, token_inst, ItemPacketTrade);
|
||||
SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade);
|
||||
|
||||
safe_delete(token_inst);
|
||||
Message(14, "Destination slot %i resyncronized.", move_slots->to_slot);
|
||||
}
|
||||
else { Message(13, "Could not resyncronize destination slot %i.", move_slots->to_slot); }
|
||||
@@ -1857,7 +1859,7 @@ void Client::DyeArmor(DyeStruct* dye){
|
||||
m_pp.item_tint[i].rgb.red!=dye->dye[i].rgb.red ||
|
||||
m_pp.item_tint[i].rgb.green != dye->dye[i].rgb.green){
|
||||
slot = m_inv.HasItem(32557, 1, invWherePersonal);
|
||||
if(slot != SLOT_INVALID){
|
||||
if (slot != INVALID_INDEX){
|
||||
DeleteItemInInventory(slot,1,true);
|
||||
uint8 slot2=SlotConvert(i);
|
||||
ItemInst* inst = this->m_inv.GetItem(slot2);
|
||||
@@ -1942,10 +1944,10 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) {
|
||||
ItemInst* ins;
|
||||
int x;
|
||||
int num = 0;
|
||||
for(x=0; x < 331; x++)
|
||||
for(x = EmuConstants::POSSESSIONS_BEGIN; x <= EmuConstants::GENERAL_BAGS_END; x++)
|
||||
{
|
||||
if (x == 31)
|
||||
x = 251;
|
||||
if (x == EmuConstants::CURSOR + 1)
|
||||
x = EmuConstants::GENERAL_BAGS_BEGIN;
|
||||
TempItem = 0;
|
||||
ins = GetInv().GetItem(x);
|
||||
if (ins)
|
||||
@@ -1959,10 +1961,10 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) {
|
||||
}
|
||||
if (num < amt)
|
||||
return false;
|
||||
for(x=0; x < 331; x++)
|
||||
for(x = EmuConstants::POSSESSIONS_BEGIN; x <= EmuConstants::GENERAL_BAGS_END; x++) // should this be CURSOR_BAG_END
|
||||
{
|
||||
if (x == 31)
|
||||
x = 251;
|
||||
if (x == EmuConstants::CURSOR + 1)
|
||||
x = EmuConstants::GENERAL_BAGS_BEGIN;
|
||||
TempItem = 0;
|
||||
ins = GetInv().GetItem(x);
|
||||
if (ins)
|
||||
@@ -1991,7 +1993,7 @@ void Client::RemoveNoRent(bool client_update) {
|
||||
int16 slot_id;
|
||||
|
||||
// personal
|
||||
for(slot_id = 0; slot_id <= 30; slot_id++) {
|
||||
for(slot_id = EmuConstants::POSSESSIONS_BEGIN; slot_id <= EmuConstants::POSSESSIONS_END; slot_id++) {
|
||||
const ItemInst* inst = m_inv[slot_id];
|
||||
if(inst && !inst->GetItem()->NoRent) {
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
@@ -2000,14 +2002,14 @@ void Client::RemoveNoRent(bool client_update) {
|
||||
}
|
||||
|
||||
// power source
|
||||
const ItemInst* inst = m_inv[9999];
|
||||
const ItemInst* inst = m_inv[EmuConstants::POWER_SOURCE];
|
||||
if(inst && !inst->GetItem()->NoRent) {
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
DeleteItemInInventory(9999, 0, (GetClientVersion() >= EQClientSoF) ? client_update : false); // Ti slot non-existent
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, EmuConstants::POWER_SOURCE);
|
||||
DeleteItemInInventory(EmuConstants::POWER_SOURCE, 0, (GetClientVersion() >= EQClientSoF) ? client_update : false); // Ti slot non-existent
|
||||
}
|
||||
|
||||
// containers
|
||||
for(slot_id = 251; slot_id <= 340; slot_id++) {
|
||||
for(slot_id = EmuConstants::GENERAL_BAGS_BEGIN; slot_id <= EmuConstants::CURSOR_BAG_END; slot_id++) {
|
||||
const ItemInst* inst = m_inv[slot_id];
|
||||
if(inst && !inst->GetItem()->NoRent) {
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
@@ -2016,7 +2018,7 @@ void Client::RemoveNoRent(bool client_update) {
|
||||
}
|
||||
|
||||
// bank
|
||||
for(slot_id = 2000; slot_id <= 2023; slot_id++) {
|
||||
for(slot_id = EmuConstants::BANK_BEGIN; slot_id <= EmuConstants::BANK_END; slot_id++) {
|
||||
const ItemInst* inst = m_inv[slot_id];
|
||||
if(inst && !inst->GetItem()->NoRent) {
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
@@ -2025,7 +2027,7 @@ void Client::RemoveNoRent(bool client_update) {
|
||||
}
|
||||
|
||||
// bank containers
|
||||
for(slot_id = 2031; slot_id <= 2270; slot_id++) {
|
||||
for(slot_id = EmuConstants::BANK_BAGS_BEGIN; slot_id <= EmuConstants::BANK_BAGS_END; slot_id++) {
|
||||
const ItemInst* inst = m_inv[slot_id];
|
||||
if(inst && !inst->GetItem()->NoRent) {
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
@@ -2034,7 +2036,7 @@ void Client::RemoveNoRent(bool client_update) {
|
||||
}
|
||||
|
||||
// shared bank
|
||||
for(slot_id = 2500; slot_id <= 2501; slot_id++) {
|
||||
for(slot_id = EmuConstants::SHARED_BANK_BEGIN; slot_id <= EmuConstants::SHARED_BANK_END; slot_id++) {
|
||||
const ItemInst* inst = m_inv[slot_id];
|
||||
if(inst && !inst->GetItem()->NoRent) {
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
@@ -2043,7 +2045,7 @@ void Client::RemoveNoRent(bool client_update) {
|
||||
}
|
||||
|
||||
// shared bank containers
|
||||
for(slot_id = 2531; slot_id <= 2550; slot_id++) {
|
||||
for(slot_id = EmuConstants::SHARED_BANK_BAGS_BEGIN; slot_id <= EmuConstants::SHARED_BANK_BAGS_END; slot_id++) {
|
||||
const ItemInst* inst = m_inv[slot_id];
|
||||
if(inst && !inst->GetItem()->NoRent) {
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
@@ -2058,7 +2060,7 @@ void Client::RemoveDuplicateLore(bool client_update) {
|
||||
int16 slot_id;
|
||||
|
||||
// personal
|
||||
for(slot_id = 0; slot_id <= 30; slot_id++) {
|
||||
for(slot_id = EmuConstants::POSSESSIONS_BEGIN; slot_id <= EmuConstants::POSSESSIONS_END; slot_id++) {
|
||||
ItemInst* inst = m_inv.PopItem(slot_id);
|
||||
if(inst) {
|
||||
if(CheckLoreConflict(inst->GetItem())) {
|
||||
@@ -2073,20 +2075,20 @@ void Client::RemoveDuplicateLore(bool client_update) {
|
||||
}
|
||||
|
||||
// power source
|
||||
ItemInst* inst = m_inv.PopItem(9999);
|
||||
ItemInst* inst = m_inv.PopItem(EmuConstants::POWER_SOURCE);
|
||||
if(inst) {
|
||||
if(CheckLoreConflict(inst->GetItem())) {
|
||||
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
database.SaveInventory(character_id, nullptr, 9999);
|
||||
database.SaveInventory(character_id, nullptr, EmuConstants::POWER_SOURCE);
|
||||
}
|
||||
else {
|
||||
m_inv.PutItem(9999, *inst);
|
||||
m_inv.PutItem(EmuConstants::POWER_SOURCE, *inst);
|
||||
}
|
||||
safe_delete(inst);
|
||||
}
|
||||
|
||||
// containers
|
||||
for(slot_id = 251; slot_id <= 340; slot_id++) {
|
||||
for(slot_id = EmuConstants::GENERAL_BAGS_BEGIN; slot_id <= EmuConstants::CURSOR_BAG_END; slot_id++) {
|
||||
ItemInst* inst = m_inv.PopItem(slot_id);
|
||||
if(inst) {
|
||||
if(CheckLoreConflict(inst->GetItem())) {
|
||||
@@ -2101,7 +2103,7 @@ void Client::RemoveDuplicateLore(bool client_update) {
|
||||
}
|
||||
|
||||
// bank
|
||||
for(slot_id = 2000; slot_id <= 2023; slot_id++) {
|
||||
for(slot_id = EmuConstants::BANK_BEGIN; slot_id <= EmuConstants::BANK_END; slot_id++) {
|
||||
ItemInst* inst = m_inv.PopItem(slot_id);
|
||||
if(inst) {
|
||||
if(CheckLoreConflict(inst->GetItem())) {
|
||||
@@ -2116,7 +2118,7 @@ void Client::RemoveDuplicateLore(bool client_update) {
|
||||
}
|
||||
|
||||
// bank containers
|
||||
for(slot_id = 2031; slot_id <= 2270; slot_id++) {
|
||||
for(slot_id = EmuConstants::BANK_BAGS_BEGIN; slot_id <= EmuConstants::BANK_BAGS_END; slot_id++) {
|
||||
ItemInst* inst = m_inv.PopItem(slot_id);
|
||||
if(inst) {
|
||||
if(CheckLoreConflict(inst->GetItem())) {
|
||||
@@ -2138,7 +2140,7 @@ void Client::MoveSlotNotAllowed(bool client_update) {
|
||||
int16 slot_id;
|
||||
|
||||
// equipment
|
||||
for(slot_id = 0; slot_id <= 21; slot_id++) {
|
||||
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {
|
||||
if(m_inv[slot_id] && !m_inv[slot_id]->IsSlotAllowed(slot_id)) {
|
||||
ItemInst* inst = m_inv.PopItem(slot_id);
|
||||
bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false;
|
||||
@@ -2151,7 +2153,7 @@ void Client::MoveSlotNotAllowed(bool client_update) {
|
||||
}
|
||||
|
||||
// power source
|
||||
slot_id = 9999;
|
||||
slot_id = EmuConstants::POWER_SOURCE;
|
||||
if(m_inv[slot_id] && !m_inv[slot_id]->IsSlotAllowed(slot_id)) {
|
||||
ItemInst* inst = m_inv.PopItem(slot_id);
|
||||
bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false;
|
||||
@@ -2283,13 +2285,13 @@ static int16 BandolierSlotToWeaponSlot(int BandolierSlot) {
|
||||
|
||||
switch(BandolierSlot) {
|
||||
case bandolierMainHand:
|
||||
return SLOT_PRIMARY;
|
||||
return MainPrimary;
|
||||
case bandolierOffHand:
|
||||
return SLOT_SECONDARY;
|
||||
return MainSecondary;
|
||||
case bandolierRange:
|
||||
return SLOT_RANGE;
|
||||
return MainRange;
|
||||
default:
|
||||
return SLOT_AMMO;
|
||||
return MainAmmo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2365,12 +2367,12 @@ void Client::SetBandolier(const EQApplicationPacket *app) {
|
||||
invWhereWorn|invWherePersonal);
|
||||
|
||||
// removed 'invWhereCursor' argument from above and implemented slots 30, 331-340 checks here
|
||||
if (slot == SLOT_INVALID) {
|
||||
if (m_inv.GetItem(SLOT_CURSOR)) {
|
||||
if (m_inv.GetItem(SLOT_CURSOR)->GetItem()->ID == m_pp.bandoliers[bss->number].items[BandolierSlot].item_id &&
|
||||
m_inv.GetItem(SLOT_CURSOR)->GetCharges() >= 1) // '> 0' the same, but this matches Inventory::_HasItem conditional check
|
||||
slot = SLOT_CURSOR;
|
||||
else if (m_inv.GetItem(SLOT_CURSOR)->GetItem()->ItemClass == 1) {
|
||||
if (slot == INVALID_INDEX) {
|
||||
if (m_inv.GetItem(MainCursor)) {
|
||||
if (m_inv.GetItem(MainCursor)->GetItem()->ID == m_pp.bandoliers[bss->number].items[BandolierSlot].item_id &&
|
||||
m_inv.GetItem(MainCursor)->GetCharges() >= 1) // '> 0' the same, but this matches Inventory::_HasItem conditional check
|
||||
slot = MainCursor;
|
||||
else if (m_inv.GetItem(MainCursor)->GetItem()->ItemClass == 1) {
|
||||
for(int16 CursorBagSlot = 331; CursorBagSlot <= 340; CursorBagSlot++) {
|
||||
if (m_inv.GetItem(CursorBagSlot)) {
|
||||
if (m_inv.GetItem(CursorBagSlot)->GetItem()->ID == m_pp.bandoliers[bss->number].items[BandolierSlot].item_id &&
|
||||
@@ -2385,7 +2387,7 @@ void Client::SetBandolier(const EQApplicationPacket *app) {
|
||||
}
|
||||
|
||||
// if the player has this item in their inventory,
|
||||
if(slot != SLOT_INVALID) {
|
||||
if (slot != INVALID_INDEX) {
|
||||
// Pull the item out of the inventory
|
||||
BandolierItems[BandolierSlot] = m_inv.PopItem(slot);
|
||||
// If ammo with charges, only take one charge out to put in the range slot, that is what
|
||||
@@ -2410,7 +2412,7 @@ void Client::SetBandolier(const EQApplicationPacket *app) {
|
||||
}
|
||||
else { // The player doesn't have the required weapon with them.
|
||||
BandolierItems[BandolierSlot] = 0;
|
||||
if(slot == SLOT_INVALID) {
|
||||
if (slot == INVALID_INDEX) {
|
||||
_log(INVENTORY__BANDOLIER, "Character does not have required bandolier item for slot %i", WeaponSlot);
|
||||
ItemInst *InvItem = m_inv.PopItem(WeaponSlot);
|
||||
if(InvItem) {
|
||||
|
||||
+11
-11
@@ -219,7 +219,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
|
||||
// it is an improvement.
|
||||
|
||||
if (!item2->NoPet) {
|
||||
for (int i=0; !found && i<MAX_WORN_INVENTORY; i++) {
|
||||
for (int i = 0; !found && i<EmuConstants::EQUIPMENT_SIZE; i++) {
|
||||
uint32 slots = (1 << i);
|
||||
if (item2->Slots & slots) {
|
||||
if(equipment[i])
|
||||
@@ -260,7 +260,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
|
||||
// @merth: IDFile size has been increased, this needs to change
|
||||
uint16 emat;
|
||||
if(item2->Material <= 0
|
||||
|| item2->Slots & (1 << SLOT_PRIMARY | 1 << SLOT_SECONDARY)) {
|
||||
|| item2->Slots & (1 << MainPrimary | 1 << MainSecondary)) {
|
||||
memset(newid, 0, sizeof(newid));
|
||||
for(int i=0;i<7;i++){
|
||||
if (!isalpha(item2->IDFile[i])){
|
||||
@@ -274,13 +274,13 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
|
||||
emat = item2->Material;
|
||||
}
|
||||
|
||||
if (foundslot == SLOT_PRIMARY) {
|
||||
if (foundslot == MainPrimary) {
|
||||
if (item2->Proc.Effect != 0)
|
||||
CastToMob()->AddProcToWeapon(item2->Proc.Effect, true);
|
||||
|
||||
eslot = MaterialPrimary;
|
||||
}
|
||||
else if (foundslot == SLOT_SECONDARY
|
||||
else if (foundslot == MainSecondary
|
||||
&& (GetOwner() != nullptr || (GetLevel() >= 13 && MakeRandomInt(0,99) < NPC_DW_CHANCE) || (item2->Damage==0)) &&
|
||||
(item2->ItemType == ItemType1HSlash || item2->ItemType == ItemType1HBlunt || item2->ItemType == ItemTypeShield ||
|
||||
item2->ItemType == ItemType1HPiercing))
|
||||
@@ -290,25 +290,25 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
|
||||
|
||||
eslot = MaterialSecondary;
|
||||
}
|
||||
else if (foundslot == SLOT_HEAD) {
|
||||
else if (foundslot == MainHead) {
|
||||
eslot = MaterialHead;
|
||||
}
|
||||
else if (foundslot == SLOT_CHEST) {
|
||||
else if (foundslot == MainChest) {
|
||||
eslot = MaterialChest;
|
||||
}
|
||||
else if (foundslot == SLOT_ARMS) {
|
||||
else if (foundslot == MainArms) {
|
||||
eslot = MaterialArms;
|
||||
}
|
||||
else if (foundslot == SLOT_BRACER01 || foundslot == SLOT_BRACER02) {
|
||||
else if (foundslot == MainWrist1 || foundslot == MainWrist2) {
|
||||
eslot = MaterialWrist;
|
||||
}
|
||||
else if (foundslot == SLOT_HANDS) {
|
||||
else if (foundslot == MainHands) {
|
||||
eslot = MaterialHands;
|
||||
}
|
||||
else if (foundslot == SLOT_LEGS) {
|
||||
else if (foundslot == MainLegs) {
|
||||
eslot = MaterialLegs;
|
||||
}
|
||||
else if (foundslot == SLOT_FEET) {
|
||||
else if (foundslot == MainFeet) {
|
||||
eslot = MaterialFeet;
|
||||
}
|
||||
|
||||
|
||||
+52
-31
@@ -1415,36 +1415,55 @@ luabind::scope lua_register_slot() {
|
||||
return luabind::class_<Slots>("Slot")
|
||||
.enum_("constants")
|
||||
[
|
||||
luabind::value("Charm", static_cast<int>(SLOT_CHARM)),
|
||||
luabind::value("Ear1", static_cast<int>(SLOT_EAR01)),
|
||||
luabind::value("Head", static_cast<int>(SLOT_HEAD)),
|
||||
luabind::value("Face", static_cast<int>(SLOT_FACE)),
|
||||
luabind::value("Ear2", static_cast<int>(SLOT_EAR02)),
|
||||
luabind::value("Neck", static_cast<int>(SLOT_NECK)),
|
||||
luabind::value("Shoulder", static_cast<int>(SLOT_SHOULDER)),
|
||||
luabind::value("Arms", static_cast<int>(SLOT_ARMS)),
|
||||
luabind::value("Back", static_cast<int>(SLOT_BACK)),
|
||||
luabind::value("Bracer1", static_cast<int>(SLOT_BRACER01)),
|
||||
luabind::value("Bracer2", static_cast<int>(SLOT_BRACER02)),
|
||||
luabind::value("Range", static_cast<int>(SLOT_RANGE)),
|
||||
luabind::value("Hands", static_cast<int>(SLOT_HANDS)),
|
||||
luabind::value("Primary", static_cast<int>(SLOT_PRIMARY)),
|
||||
luabind::value("Secondary", static_cast<int>(SLOT_SECONDARY)),
|
||||
luabind::value("Ring1", static_cast<int>(SLOT_RING01)),
|
||||
luabind::value("Ring2", static_cast<int>(SLOT_RING02)),
|
||||
luabind::value("Chest", static_cast<int>(SLOT_CHEST)),
|
||||
luabind::value("Legs", static_cast<int>(SLOT_LEGS)),
|
||||
luabind::value("Feet", static_cast<int>(SLOT_FEET)),
|
||||
luabind::value("Waist", static_cast<int>(SLOT_WAIST)),
|
||||
luabind::value("Ammo", static_cast<int>(SLOT_AMMO)),
|
||||
luabind::value("PersonalBegin", static_cast<int>(SLOT_PERSONAL_BEGIN)),
|
||||
luabind::value("PersonalEnd", static_cast<int>(SLOT_PERSONAL_END)),
|
||||
luabind::value("Cursor", static_cast<int>(SLOT_CURSOR)),
|
||||
luabind::value("CursorEnd", 0xFFFE),
|
||||
luabind::value("Tradeskill", static_cast<int>(SLOT_TRADESKILL)),
|
||||
luabind::value("Augment", static_cast<int>(SLOT_AUGMENT)),
|
||||
luabind::value("PowerSource", static_cast<int>(SLOT_POWER_SOURCE)),
|
||||
luabind::value("Invalid", 0xFFFF)
|
||||
luabind::value("Charm", static_cast<int>(MainCharm)),
|
||||
luabind::value("Ear1", static_cast<int>(MainEar1)),
|
||||
luabind::value("Head", static_cast<int>(MainHead)),
|
||||
luabind::value("Face", static_cast<int>(MainFace)),
|
||||
luabind::value("Ear2", static_cast<int>(MainEar2)),
|
||||
luabind::value("Neck", static_cast<int>(MainNeck)),
|
||||
luabind::value("Shoulder", static_cast<int>(MainShoulders)), // deprecated
|
||||
luabind::value("Shoulders", static_cast<int>(MainShoulders)),
|
||||
luabind::value("Arms", static_cast<int>(MainArms)),
|
||||
luabind::value("Back", static_cast<int>(MainBack)),
|
||||
luabind::value("Bracer1", static_cast<int>(MainWrist1)), // deprecated
|
||||
luabind::value("Wrist1", static_cast<int>(MainWrist1)),
|
||||
luabind::value("Bracer2", static_cast<int>(MainWrist2)), // deprecated
|
||||
luabind::value("Wrist2", static_cast<int>(MainWrist2)),
|
||||
luabind::value("Range", static_cast<int>(MainRange)),
|
||||
luabind::value("Hands", static_cast<int>(MainHands)),
|
||||
luabind::value("Primary", static_cast<int>(MainPrimary)),
|
||||
luabind::value("Secondary", static_cast<int>(MainSecondary)),
|
||||
luabind::value("Ring1", static_cast<int>(MainFinger1)), // deprecated
|
||||
luabind::value("Finger1", static_cast<int>(MainFinger1)),
|
||||
luabind::value("Ring2", static_cast<int>(MainFinger2)), // deprecated
|
||||
luabind::value("Finger2", static_cast<int>(MainFinger2)),
|
||||
luabind::value("Chest", static_cast<int>(MainChest)),
|
||||
luabind::value("Legs", static_cast<int>(MainLegs)),
|
||||
luabind::value("Feet", static_cast<int>(MainFeet)),
|
||||
luabind::value("Waist", static_cast<int>(MainWaist)),
|
||||
luabind::value("PowerSource", static_cast<int>(MainPowerSource)),
|
||||
luabind::value("Ammo", static_cast<int>(MainAmmo)),
|
||||
luabind::value("General1", static_cast<int>(MainGeneral1)),
|
||||
luabind::value("General2", static_cast<int>(MainGeneral2)),
|
||||
luabind::value("General3", static_cast<int>(MainGeneral3)),
|
||||
luabind::value("General4", static_cast<int>(MainGeneral4)),
|
||||
luabind::value("General5", static_cast<int>(MainGeneral5)),
|
||||
luabind::value("General6", static_cast<int>(MainGeneral6)),
|
||||
luabind::value("General7", static_cast<int>(MainGeneral7)),
|
||||
luabind::value("General8", static_cast<int>(MainGeneral8)),
|
||||
//luabind::value("General9", static_cast<int>(MainGeneral9)),
|
||||
//luabind::value("General10", static_cast<int>(MainGeneral10)),
|
||||
luabind::value("Cursor", static_cast<int>(MainCursor)),
|
||||
//luabind::value("EquipmentBegin", static_cast<int>(EmuConstants::EQUIPMENT_BEGIN)),
|
||||
//luabind::value("EquipmentEnd", static_cast<int>(EmuConstants::EQUIPMENT_END)),
|
||||
luabind::value("PersonalBegin", static_cast<int>(EmuConstants::GENERAL_BEGIN)), // deprecated
|
||||
luabind::value("GeneralBegin", static_cast<int>(EmuConstants::GENERAL_BEGIN)),
|
||||
luabind::value("PersonalEnd", static_cast<int>(EmuConstants::GENERAL_END)), // deprecated
|
||||
luabind::value("GeneralEnd", static_cast<int>(EmuConstants::GENERAL_END)),
|
||||
luabind::value("CursorEnd", 0xFFFE), // deprecated
|
||||
luabind::value("Tradeskill", static_cast<int>(SLOT_TRADESKILL)), // deprecated
|
||||
luabind::value("Augment", static_cast<int>(SLOT_AUGMENT)), // deprecated
|
||||
luabind::value("Invalid", INVALID_INDEX)
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1464,6 +1483,7 @@ luabind::scope lua_register_material() {
|
||||
luabind::value("Secondary", static_cast<int>(MaterialSecondary)),
|
||||
luabind::value("Max", static_cast<int>(_MaterialCount)), // deprecated
|
||||
luabind::value("Count", static_cast<int>(_MaterialCount)),
|
||||
//luabind::value("TintCount", static_cast<int>(_MaterialCount - 2)),
|
||||
luabind::value("Invalid", static_cast<int>(_MaterialInvalid))
|
||||
];
|
||||
}
|
||||
@@ -1478,7 +1498,8 @@ luabind::scope lua_register_client_version() {
|
||||
luabind::value("SoF", static_cast<int>(EQClientSoF)),
|
||||
luabind::value("SoD", static_cast<int>(EQClientSoD)),
|
||||
luabind::value("Underfoot", static_cast<int>(EQClientUnderfoot)),
|
||||
luabind::value("RoF", static_cast<int>(EQClientRoF))
|
||||
luabind::value("RoF", static_cast<int>(EQClientRoF))//,
|
||||
//luabind::value("RoF2", static_cast<int>(EQClientRoF2))
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
+12
-12
@@ -266,7 +266,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) {
|
||||
|
||||
unsigned int i;
|
||||
//should not include 21 (SLOT_AMMO)
|
||||
for (i=0; i<SLOT_AMMO; i++) {
|
||||
for (i=0; i<MainAmmo; i++) {
|
||||
if(equipment[i] == 0)
|
||||
continue;
|
||||
const Item_Struct * itm = database.GetItem(equipment[i]);
|
||||
@@ -277,7 +277,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) {
|
||||
//Power Source Slot
|
||||
/*if (GetClientVersion() >= EQClientSoF)
|
||||
{
|
||||
const ItemInst* inst = m_inv[9999];
|
||||
const ItemInst* inst = m_inv[MainPowerSource];
|
||||
if(inst)
|
||||
AddItemBonuses(inst, newbon);
|
||||
}*/
|
||||
@@ -1653,24 +1653,24 @@ void Merc::AI_Process() {
|
||||
|
||||
//try main hand first
|
||||
if(attack_timer.Check()) {
|
||||
Attack(GetTarget(), SLOT_PRIMARY);
|
||||
Attack(GetTarget(), MainPrimary);
|
||||
|
||||
bool tripleSuccess = false;
|
||||
|
||||
if(GetOwner() && GetTarget() && CanThisClassDoubleAttack()) {
|
||||
|
||||
if(GetOwner()) {
|
||||
Attack(GetTarget(), SLOT_PRIMARY, true);
|
||||
Attack(GetTarget(), MainPrimary, true);
|
||||
}
|
||||
|
||||
if(GetOwner() && GetTarget() && GetSpecialAbility(SPECATK_TRIPLE)) {
|
||||
tripleSuccess = true;
|
||||
Attack(GetTarget(), SLOT_PRIMARY, true);
|
||||
Attack(GetTarget(), MainPrimary, true);
|
||||
}
|
||||
|
||||
//quad attack, does this belong here??
|
||||
if(GetOwner() && GetTarget() && GetSpecialAbility(SPECATK_QUAD)) {
|
||||
Attack(GetTarget(), SLOT_PRIMARY, true);
|
||||
Attack(GetTarget(), MainPrimary, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1682,8 +1682,8 @@ void Merc::AI_Process() {
|
||||
if(MakeRandomInt(0, 100) < flurrychance)
|
||||
{
|
||||
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
|
||||
Attack(GetTarget(), SLOT_PRIMARY, false);
|
||||
Attack(GetTarget(), SLOT_PRIMARY, false);
|
||||
Attack(GetTarget(), MainPrimary, false);
|
||||
Attack(GetTarget(), MainPrimary, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1692,7 +1692,7 @@ void Merc::AI_Process() {
|
||||
if (GetTarget() && ExtraAttackChanceBonus) {
|
||||
if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus)
|
||||
{
|
||||
Attack(GetTarget(), SLOT_PRIMARY, false);
|
||||
Attack(GetTarget(), MainPrimary, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1727,11 +1727,11 @@ void Merc::AI_Process() {
|
||||
|
||||
if (random < DualWieldProbability){ // Max 78% of DW
|
||||
|
||||
Attack(GetTarget(), SLOT_SECONDARY); // Single attack with offhand
|
||||
Attack(GetTarget(), MainSecondary); // Single attack with offhand
|
||||
|
||||
if( CanThisClassDoubleAttack()) {
|
||||
if(GetTarget() && GetTarget()->GetHP() > -10)
|
||||
Attack(GetTarget(), SLOT_SECONDARY); // Single attack with offhand
|
||||
Attack(GetTarget(), MainSecondary); // Single attack with offhand
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2640,7 +2640,7 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) {
|
||||
int16 focus_max_real = 0;
|
||||
|
||||
//item focus
|
||||
for(int x =0; x < MAX_WORN_INVENTORY; ++x)
|
||||
for (int x = 0; x < EmuConstants::EQUIPMENT_SIZE; ++x)
|
||||
{
|
||||
TempItem = nullptr;
|
||||
if (equipment[x] == 0)
|
||||
|
||||
+6
-6
@@ -48,7 +48,7 @@ public:
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill);
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false);
|
||||
virtual bool Attack(Mob* other, int Hand = SLOT_PRIMARY, bool FromRiposte = false, bool IsStrikethrough = false,
|
||||
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
|
||||
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr);
|
||||
virtual bool HasRaid() { return false; }
|
||||
virtual bool HasGroup() { return (GetGroup() ? true : false); }
|
||||
@@ -273,11 +273,11 @@ protected:
|
||||
std::map<uint32,MercTimer> timers;
|
||||
|
||||
uint16 skills[HIGHEST_SKILL+1];
|
||||
uint32 equipment[MAX_WORN_INVENTORY]; //this is an array of item IDs
|
||||
uint16 d_meele_texture1; //this is an item Material value
|
||||
uint16 d_meele_texture2; //this is an item Material value (offhand)
|
||||
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
|
||||
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation
|
||||
uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //this is an array of item IDs
|
||||
uint16 d_meele_texture1; //this is an item Material value
|
||||
uint16 d_meele_texture2; //this is an item Material value (offhand)
|
||||
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
|
||||
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation
|
||||
|
||||
private:
|
||||
|
||||
|
||||
+41
-13
@@ -238,9 +238,6 @@ Mob::Mob(const char* in_name,
|
||||
RangedProcs[j].spellID = SPELL_UNKNOWN;
|
||||
RangedProcs[j].chance = 0;
|
||||
RangedProcs[j].base_spellID = SPELL_UNKNOWN;
|
||||
SkillProcs[j].spellID = SPELL_UNKNOWN;
|
||||
SkillProcs[j].chance = 0;
|
||||
SkillProcs[j].base_spellID = SPELL_UNKNOWN;
|
||||
}
|
||||
|
||||
for (i = 0; i < _MaterialCount; i++)
|
||||
@@ -1955,14 +1952,14 @@ void Mob::SetAttackTimer() {
|
||||
Timer* TimerToUse = nullptr;
|
||||
const Item_Struct* PrimaryWeapon = nullptr;
|
||||
|
||||
for (int i=SLOT_RANGE; i<=SLOT_SECONDARY; i++) {
|
||||
for (int i=MainRange; i<=MainSecondary; i++) {
|
||||
|
||||
//pick a timer
|
||||
if (i == SLOT_PRIMARY)
|
||||
if (i == MainPrimary)
|
||||
TimerToUse = &attack_timer;
|
||||
else if (i == SLOT_RANGE)
|
||||
else if (i == MainRange)
|
||||
TimerToUse = &ranged_timer;
|
||||
else if(i == SLOT_SECONDARY)
|
||||
else if(i == MainSecondary)
|
||||
TimerToUse = &attack_dw_timer;
|
||||
else //invalid slot (hands will always hit this)
|
||||
continue;
|
||||
@@ -1983,7 +1980,7 @@ void Mob::SetAttackTimer() {
|
||||
}
|
||||
|
||||
//special offhand stuff
|
||||
if(i == SLOT_SECONDARY) {
|
||||
if(i == MainSecondary) {
|
||||
//if we have a 2H weapon in our main hand, no dual
|
||||
if(PrimaryWeapon != nullptr) {
|
||||
if( PrimaryWeapon->ItemClass == ItemClassCommon
|
||||
@@ -2062,7 +2059,7 @@ void Mob::SetAttackTimer() {
|
||||
if(IsClient())
|
||||
{
|
||||
float max_quiver = 0;
|
||||
for(int r = SLOT_PERSONAL_BEGIN; r <= SLOT_PERSONAL_END; r++)
|
||||
for(int r = EmuConstants::GENERAL_BEGIN; r <= EmuConstants::GENERAL_END; r++)
|
||||
{
|
||||
const ItemInst *pi = CastToClient()->GetInv().GetItem(r);
|
||||
if(!pi)
|
||||
@@ -2086,7 +2083,7 @@ void Mob::SetAttackTimer() {
|
||||
TimerToUse->SetAtTrigger(speed, true);
|
||||
}
|
||||
|
||||
if(i == SLOT_PRIMARY)
|
||||
if(i == MainPrimary)
|
||||
PrimaryWeapon = ItemToUse;
|
||||
}
|
||||
|
||||
@@ -2097,8 +2094,8 @@ bool Mob::CanThisClassDualWield(void) const {
|
||||
return(GetSkill(SkillDualWield) > 0);
|
||||
}
|
||||
else if(CastToClient()->HasSkill(SkillDualWield)) {
|
||||
const ItemInst* pinst = CastToClient()->GetInv().GetItem(SLOT_PRIMARY);
|
||||
const ItemInst* sinst = CastToClient()->GetInv().GetItem(SLOT_SECONDARY);
|
||||
const ItemInst* pinst = CastToClient()->GetInv().GetItem(MainPrimary);
|
||||
const ItemInst* sinst = CastToClient()->GetInv().GetItem(MainSecondary);
|
||||
|
||||
// 2HS, 2HB, or 2HP
|
||||
if(pinst && pinst->IsWeapon()) {
|
||||
@@ -3033,7 +3030,7 @@ void Mob::TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand, in
|
||||
if (!on)
|
||||
return;
|
||||
|
||||
on->TryDefensiveProc(weapon, this, hand, damage);
|
||||
on->TryDefensiveProc(weapon, this, hand);
|
||||
|
||||
//Defensive Skill Procs
|
||||
if (damage < 0 && damage >= -4) {
|
||||
@@ -4702,6 +4699,11 @@ uint16 Mob::GetSkillByItemType(int ItemType)
|
||||
return Skill2HBlunt;
|
||||
case ItemType2HPiercing:
|
||||
return Skill1HPiercing; // change to 2HPiercing once activated
|
||||
case ItemTypeBow:
|
||||
return SkillArchery;
|
||||
case ItemTypeLargeThrowing:
|
||||
case ItemTypeSmallThrowing:
|
||||
return SkillThrowing;
|
||||
case ItemTypeMartial:
|
||||
return SkillHandtoHand;
|
||||
default:
|
||||
@@ -4710,6 +4712,32 @@ uint16 Mob::GetSkillByItemType(int ItemType)
|
||||
return SkillHandtoHand;
|
||||
}
|
||||
|
||||
uint8 Mob::GetItemTypeBySkill(SkillUseTypes skill)
|
||||
{
|
||||
switch (skill)
|
||||
{
|
||||
case SkillThrowing:
|
||||
return ItemTypeSmallThrowing;
|
||||
case SkillArchery:
|
||||
return ItemTypeArrow;
|
||||
case Skill1HSlashing:
|
||||
return ItemType1HSlash;
|
||||
case Skill2HSlashing:
|
||||
return ItemType2HSlash;
|
||||
case Skill1HPiercing:
|
||||
return ItemType1HPiercing;
|
||||
case Skill1HBlunt:
|
||||
return ItemType1HBlunt;
|
||||
case Skill2HBlunt:
|
||||
return ItemType2HBlunt;
|
||||
case SkillHandtoHand:
|
||||
return ItemTypeMartial;
|
||||
default:
|
||||
return ItemTypeMartial;
|
||||
}
|
||||
return ItemTypeMartial;
|
||||
}
|
||||
|
||||
|
||||
bool Mob::PassLimitToSkill(uint16 spell_id, uint16 skill) {
|
||||
|
||||
|
||||
+16
-14
@@ -131,11 +131,11 @@ public:
|
||||
virtual void ThrowingAttack(Mob* other) { }
|
||||
uint16 GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg);
|
||||
// 13 = Primary (default), 14 = secondary
|
||||
virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = false,
|
||||
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
|
||||
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) = 0;
|
||||
int MonkSpecialAttack(Mob* other, uint8 skill_used);
|
||||
virtual void TryBackstab(Mob *other,int ReuseTime = 10);
|
||||
void TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand = 13, int damage = 0);
|
||||
void TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary, int damage = 0);
|
||||
virtual bool AvoidDamage(Mob* attacker, int32 &damage, bool CanRiposte = true);
|
||||
virtual bool CheckHitChance(Mob* attacker, SkillUseTypes skillinuse, int Hand, int16 chance_mod = 0);
|
||||
virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts = nullptr);
|
||||
@@ -150,6 +150,9 @@ public:
|
||||
bool CombatRange(Mob* other);
|
||||
virtual inline bool IsBerserk() { return false; } // only clients
|
||||
void RogueEvade(Mob *other);
|
||||
void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse);
|
||||
void CommonBreakInvisible();
|
||||
bool HasDied();
|
||||
|
||||
//Appearance
|
||||
void SendLevelAppearance();
|
||||
@@ -164,7 +167,7 @@ public:
|
||||
virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color);
|
||||
void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone);
|
||||
void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0,
|
||||
float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr);
|
||||
float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr, SkillUseTypes skillInUse = SkillArchery);
|
||||
void ChangeSize(float in_size, bool bNoRestriction = false);
|
||||
inline uint8 SeeInvisible() const { return see_invis; }
|
||||
inline bool SeeInvisibleUndead() const { return see_invis_undead; }
|
||||
@@ -480,6 +483,7 @@ public:
|
||||
static uint32 RandomTimer(int min, int max);
|
||||
static uint8 GetDefaultGender(uint16 in_race, uint8 in_gender = 0xFF);
|
||||
uint16 GetSkillByItemType(int ItemType);
|
||||
uint8 GetItemTypeBySkill(SkillUseTypes skill);
|
||||
virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr);
|
||||
virtual void MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, const char *petname = nullptr, float in_size = 0.0f);
|
||||
bool IsWarriorClass() const;
|
||||
@@ -819,7 +823,7 @@ public:
|
||||
void SetNextIncHPEvent( int inchpevent );
|
||||
|
||||
inline bool DivineAura() const { return spellbonuses.DivineAura; }
|
||||
inline bool Sanctuary() const { return spellbonuses.Sanctuary; }
|
||||
inline bool Sanctuary() const { return spellbonuses.Sanctuary; }
|
||||
|
||||
bool HasNPCSpecialAtk(const char* parse);
|
||||
int GetSpecialAbility(int ability);
|
||||
@@ -986,26 +990,25 @@ protected:
|
||||
bool focused;
|
||||
void CalcSpellBonuses(StatBonuses* newbon);
|
||||
virtual void CalcBonuses();
|
||||
void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false);
|
||||
void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand = MainCharm?
|
||||
bool PassLimitToSkill(uint16 spell_id, uint16 skill);
|
||||
bool PassLimitClass(uint32 Classes_, uint16 Class_);
|
||||
void TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand = 13, int damage=0);
|
||||
void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = 13);
|
||||
void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = 13);
|
||||
void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = 13);
|
||||
void TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary);
|
||||
void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = MainPrimary);
|
||||
void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = MainPrimary);
|
||||
void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary);
|
||||
void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on);
|
||||
virtual float GetProcChances(float ProcBonus, uint16 weapon_speed = 30, uint16 hand = 13);
|
||||
virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed = 30, uint16 hand = 13);
|
||||
virtual float GetProcChances(float ProcBonus, uint16 hand = MainPrimary);
|
||||
virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = MainPrimary, Mob *on = nullptr);
|
||||
virtual float GetSpecialProcChances(uint16 hand);
|
||||
virtual float GetAssassinateProcChances(uint16 ReuseTime);
|
||||
virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0);
|
||||
virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm?
|
||||
uint16 GetWeaponSpeedbyHand(uint16 hand);
|
||||
int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item);
|
||||
int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr);
|
||||
int GetKickDamage();
|
||||
int GetBashDamage();
|
||||
virtual void ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg);
|
||||
bool HasDied();
|
||||
void CalculateNewFearpoint();
|
||||
float FindGroundZ(float new_x, float new_y, float z_offset=0.0);
|
||||
Map::Vertex UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached);
|
||||
@@ -1018,7 +1021,6 @@ protected:
|
||||
tProc SpellProcs[MAX_PROCS];
|
||||
tProc DefensiveProcs[MAX_PROCS];
|
||||
tProc RangedProcs[MAX_PROCS];
|
||||
tProc SkillProcs[MAX_PROCS];
|
||||
|
||||
char name[64];
|
||||
char orig_name[64];
|
||||
|
||||
+10
-1
@@ -194,6 +194,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float
|
||||
}
|
||||
|
||||
accuracy_rating = d->accuracy_rating;
|
||||
avoidance_rating = d->avoidance_rating;
|
||||
ATK = d->ATK;
|
||||
|
||||
CalcMaxMana();
|
||||
@@ -259,9 +260,11 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float
|
||||
|
||||
d_meele_texture1 = d->d_meele_texture1;
|
||||
d_meele_texture2 = d->d_meele_texture2;
|
||||
ammo_idfile = d->ammo_idfile;
|
||||
memset(equipment, 0, sizeof(equipment));
|
||||
prim_melee_type = d->prim_melee_type;
|
||||
sec_melee_type = d->sec_melee_type;
|
||||
ranged_type = d->ranged_type;
|
||||
|
||||
// If Melee Textures are not set, set attack type to Hand to Hand as default
|
||||
if(!d_meele_texture1)
|
||||
@@ -1296,7 +1299,7 @@ void NPC::PickPocket(Client* thief) {
|
||||
bool is_arrow = (item->ItemType == ItemTypeArrow) ? true : false;
|
||||
int slot_id = thief->GetInv().FindFreeSlot(false, true, inst->GetItem()->Size, is_arrow);
|
||||
if (/*!Equipped(item->ID) &&*/
|
||||
!item->Magic && item->NoDrop != 0 && !inst->IsType(ItemClassContainer) && slot_id != SLOT_INVALID
|
||||
!item->Magic && item->NoDrop != 0 && !inst->IsType(ItemClassContainer) && slot_id != INVALID_INDEX
|
||||
/*&& steal_skill > item->StealSkill*/ )
|
||||
{
|
||||
slot[x] = slot_id;
|
||||
@@ -1925,6 +1928,12 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue)
|
||||
return;
|
||||
}
|
||||
|
||||
if(id == "avoidance")
|
||||
{
|
||||
avoidance_rating = atoi(val.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if(id == "trackable")
|
||||
{
|
||||
trackable = atoi(val.c_str());
|
||||
|
||||
+30
-3
@@ -73,6 +73,22 @@ struct AISpellsEffects_Struct {
|
||||
int32 max;
|
||||
};
|
||||
|
||||
struct AISpellsVar_Struct {
|
||||
uint32 fail_recast;
|
||||
uint32 engaged_no_sp_recast_min;
|
||||
uint32 engaged_no_sp_recast_max;
|
||||
uint8 engaged_beneficial_self_chance;
|
||||
uint8 engaged_beneficial_other_chance;
|
||||
uint8 engaged_detrimental_chance;
|
||||
uint32 pursue_no_sp_recast_min;
|
||||
uint32 pursue_no_sp_recast_max;
|
||||
uint8 pursue_detrimental_chance;
|
||||
uint32 idle_no_sp_recast_min;
|
||||
uint32 idle_no_sp_recast_max;
|
||||
uint8 idle_beneficial_chance;
|
||||
};
|
||||
|
||||
|
||||
class AA_SwarmPetInfo;
|
||||
|
||||
class NPC : public Mob
|
||||
@@ -88,7 +104,7 @@ public:
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill);
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false);
|
||||
virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = false,
|
||||
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
|
||||
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr);
|
||||
virtual bool HasRaid() { return false; }
|
||||
virtual bool HasGroup() { return false; }
|
||||
@@ -215,8 +231,10 @@ public:
|
||||
|
||||
uint8 GetPrimSkill() const { return prim_melee_type; }
|
||||
uint8 GetSecSkill() const { return sec_melee_type; }
|
||||
uint8 GetRangedSkill() const { return ranged_type; }
|
||||
void SetPrimSkill(uint8 skill_type) { prim_melee_type = skill_type; }
|
||||
void SetSecSkill(uint8 skill_type) { sec_melee_type = skill_type; }
|
||||
void SetRangedSkill(uint8 skill_type) { ranged_type = skill_type; }
|
||||
|
||||
uint32 MerchantType;
|
||||
bool merchant_open;
|
||||
@@ -257,6 +275,7 @@ public:
|
||||
void CheckSignal();
|
||||
inline bool IsTargetableWithHotkey() const { return no_target_hotkey; }
|
||||
int32 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; }
|
||||
inline const char* GetAmmoIDfile() const { return ammo_idfile; }
|
||||
|
||||
//waypoint crap
|
||||
int GetMaxWp() const { return max_wp; }
|
||||
@@ -314,6 +333,8 @@ public:
|
||||
|
||||
int32 GetAccuracyRating() const { return (accuracy_rating); }
|
||||
void SetAccuracyRating(int32 d) { accuracy_rating = d;}
|
||||
int32 GetAvoidanceRating() const { return (avoidance_rating); }
|
||||
void SetAvoidanceRating(int32 d) { avoidance_rating = d;}
|
||||
int32 GetRawAC() const { return AC; }
|
||||
|
||||
void ModifyNPCStat(const char *identifier, const char *newValue);
|
||||
@@ -413,14 +434,16 @@ protected:
|
||||
bool HasAISpell;
|
||||
virtual bool AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes);
|
||||
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
|
||||
AISpellsVar_Struct AISpellVar;
|
||||
|
||||
uint32 npc_spells_effects_id;
|
||||
std::vector<AISpellsEffects_Struct> AIspellsEffects;
|
||||
bool HasAISpellEffects;
|
||||
|
||||
|
||||
uint32 max_dmg;
|
||||
uint32 min_dmg;
|
||||
int32 accuracy_rating;
|
||||
int32 avoidance_rating;
|
||||
int16 attack_count;
|
||||
uint32 npc_mana;
|
||||
float spellscale;
|
||||
@@ -454,11 +477,15 @@ protected:
|
||||
uint32 roambox_min_delay;
|
||||
|
||||
uint16 skills[HIGHEST_SKILL+1];
|
||||
uint32 equipment[MAX_WORN_INVENTORY]; //this is an array of item IDs
|
||||
|
||||
uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //this is an array of item IDs
|
||||
uint16 d_meele_texture1; //this is an item Material value
|
||||
uint16 d_meele_texture2; //this is an item Material value (offhand)
|
||||
const char* ammo_idfile; //this determines projectile graphic "IT###" (see item field 'idfile')
|
||||
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
|
||||
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation
|
||||
uint8 ranged_type; //Sets the Ranged Weapon attack message and animation
|
||||
|
||||
AA_SwarmPetInfo *swarmInfoPtr;
|
||||
|
||||
bool ldon_trapped;
|
||||
|
||||
+1
-1
@@ -872,7 +872,7 @@ XS(XS_Mob_Attack)
|
||||
Perl_croak(aTHX_ "other is nullptr, avoiding crash.");
|
||||
|
||||
if (items < 3)
|
||||
Hand = 13;
|
||||
Hand = MainPrimary;
|
||||
else {
|
||||
Hand = (int)SvIV(ST(2));
|
||||
}
|
||||
|
||||
+5
-5
@@ -411,12 +411,12 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
|
||||
// the base items for the pet. These are always loaded
|
||||
// so that a rank 1 suspend minion does not kill things
|
||||
// like the special back items some focused pets may receive.
|
||||
uint32 petinv[MAX_WORN_INVENTORY];
|
||||
uint32 petinv[EmuConstants::EQUIPMENT_SIZE];
|
||||
memset(petinv, 0, sizeof(petinv));
|
||||
const Item_Struct *item = 0;
|
||||
|
||||
if (database.GetBasePetItems(record.equipmentset, petinv)) {
|
||||
for (int i=0; i<MAX_WORN_INVENTORY; i++)
|
||||
for (int i = 0; i<EmuConstants::EQUIPMENT_SIZE; i++)
|
||||
if (petinv[i]) {
|
||||
item = database.GetItem(petinv[i]);
|
||||
npc->AddLootDrop(item, &npc->itemlist, 0, 1, 127, true, true);
|
||||
@@ -543,7 +543,7 @@ void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) {
|
||||
strn0cpy(name, GetName(), 64);
|
||||
|
||||
//save their items, we only care about what they are actually wearing
|
||||
memcpy(items, equipment, sizeof(uint32)*MAX_WORN_INVENTORY);
|
||||
memcpy(items, equipment, sizeof(uint32)*EmuConstants::EQUIPMENT_SIZE);
|
||||
|
||||
//save their buffs.
|
||||
for (int i=0; i < GetPetMaxTotalSlots(); i++) {
|
||||
@@ -629,7 +629,7 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) {
|
||||
}
|
||||
|
||||
//restore their equipment...
|
||||
for(i = 0; i < MAX_WORN_INVENTORY; i++) {
|
||||
for (i = 0; i < EmuConstants::EQUIPMENT_SIZE; i++) {
|
||||
if(items[i] == 0)
|
||||
continue;
|
||||
|
||||
@@ -693,7 +693,7 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) {
|
||||
while ((row = mysql_fetch_row(result)))
|
||||
{
|
||||
slot = atoi(row[0]);
|
||||
if (slot >= MAX_WORN_INVENTORY)
|
||||
if (slot >= EmuConstants::EQUIPMENT_SIZE)
|
||||
continue;
|
||||
if (items[slot] == 0)
|
||||
items[slot] = atoi(row[1]);
|
||||
|
||||
+2
-2
@@ -2429,12 +2429,12 @@ int QuestManager::collectitems(uint32 item_id, bool remove)
|
||||
int quantity = 0;
|
||||
int slot_id;
|
||||
|
||||
for (slot_id = 22; slot_id <= 29; ++slot_id)
|
||||
for (slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; ++slot_id)
|
||||
{
|
||||
quantity += collectitems_processSlot(slot_id, item_id, remove);
|
||||
}
|
||||
|
||||
for (slot_id = 251; slot_id <= 330; ++slot_id)
|
||||
for (slot_id = EmuConstants::GENERAL_BAGS_BEGIN; slot_id <= EmuConstants::GENERAL_BAGS_END; ++slot_id)
|
||||
{
|
||||
quantity += collectitems_processSlot(slot_id, item_id, remove);
|
||||
}
|
||||
|
||||
+149
-227
@@ -74,17 +74,17 @@ void Mob::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg)
|
||||
case SkillFlyingKick:
|
||||
case SkillRoundKick:
|
||||
case SkillKick:
|
||||
item_slot = SLOT_FEET;
|
||||
item_slot = MainFeet;
|
||||
break;
|
||||
|
||||
case SkillBash:
|
||||
item_slot = SLOT_SECONDARY;
|
||||
item_slot = MainSecondary;
|
||||
break;
|
||||
|
||||
case SkillDragonPunch:
|
||||
case SkillEagleStrike:
|
||||
case SkillTigerClaw:
|
||||
item_slot = SLOT_HANDS;
|
||||
item_slot = MainHands;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -105,6 +105,9 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
//this really should go through the same code as normal melee damage to
|
||||
//pick up all the special behavior there
|
||||
|
||||
if (!who)
|
||||
return;
|
||||
|
||||
int32 hate = max_damage;
|
||||
if(hate_override > -1)
|
||||
hate = hate_override;
|
||||
@@ -113,7 +116,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
{
|
||||
if(IsClient())
|
||||
{
|
||||
ItemInst *item = CastToClient()->GetInv().GetItem(SLOT_SECONDARY);
|
||||
ItemInst *item = CastToClient()->GetInv().GetItem(MainSecondary);
|
||||
if(item)
|
||||
{
|
||||
if(item->GetItem()->ItemType == ItemTypeShield)
|
||||
@@ -128,7 +131,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
|
||||
min_damage += min_damage * GetMeleeMinDamageMod_SE(skill) / 100;
|
||||
|
||||
if(HitChance && !who->CheckHitChance(this, skill, 13))
|
||||
if(HitChance && !who->CheckHitChance(this, skill, MainPrimary))
|
||||
max_damage = 0;
|
||||
|
||||
else{
|
||||
@@ -141,26 +144,18 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
|
||||
who->MeleeMitigation(this, max_damage, min_damage);
|
||||
|
||||
if(max_damage > 0) {
|
||||
ApplyMeleeDamageBonus(skill, max_damage);
|
||||
max_damage += who->GetFcDamageAmtIncoming(this, 0, true, skill);
|
||||
max_damage += (itembonuses.HeroicSTR / 10) + (max_damage * who->GetSkillDmgTaken(skill) / 100) + GetSkillDmgAmt(skill);
|
||||
TryCriticalHit(who, skill, max_damage);
|
||||
}
|
||||
if(max_damage > 0)
|
||||
CommonOutgoingHitSuccess(who, max_damage, skill);
|
||||
|
||||
}
|
||||
|
||||
if(max_damage >= 0) //You should probably get aggro no matter what, but unclear why it was set like this.
|
||||
who->AddToHateList(this, hate);
|
||||
|
||||
who->AddToHateList(this, hate, 0, false);
|
||||
who->Damage(this, max_damage, SPELL_UNKNOWN, skill, false);
|
||||
|
||||
//Make sure 'this' has not killed the target and 'this' is not dead (Damage shield ect).
|
||||
if(!GetTarget())return;
|
||||
if (HasDied()) return;
|
||||
|
||||
if (max_damage > 0)
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
|
||||
//[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill
|
||||
if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){
|
||||
int kb_chance = 25;
|
||||
@@ -200,7 +195,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
|
||||
//These two are not subject to the combat ability timer, as they
|
||||
//allready do their checking in conjunction with the attack timer
|
||||
//throwing weapons
|
||||
if(ca_atk->m_atk == 11) {
|
||||
if(ca_atk->m_atk == MainRange) {
|
||||
if (ca_atk->m_skill == SkillThrowing) {
|
||||
SetAttackTimer();
|
||||
ThrowingAttack(GetTarget());
|
||||
@@ -242,6 +237,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
|
||||
|
||||
int32 skill_reduction = this->GetSkillReuseTime(ca_atk->m_skill);
|
||||
|
||||
// not sure what the '100' indicates..if ->m_atk is not used as 'slot' reference, then change MainRange above back to '11'
|
||||
if ((ca_atk->m_atk == 100) && (ca_atk->m_skill == SkillBash)) { // SLAM - Bash without a shield equipped
|
||||
if (GetTarget() != this) {
|
||||
|
||||
@@ -249,8 +245,8 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
|
||||
DoAnim(animTailRake);
|
||||
|
||||
int32 ht = 0;
|
||||
if(GetWeaponDamage(GetTarget(), GetInv().GetItem(SLOT_SECONDARY)) <= 0 &&
|
||||
GetWeaponDamage(GetTarget(), GetInv().GetItem(SLOT_SHOULDER)) <= 0){
|
||||
if(GetWeaponDamage(GetTarget(), GetInv().GetItem(MainSecondary)) <= 0 &&
|
||||
GetWeaponDamage(GetTarget(), GetInv().GetItem(MainShoulders)) <= 0){
|
||||
dmg = -5;
|
||||
}
|
||||
else{
|
||||
@@ -329,7 +325,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
|
||||
DoAnim(animKick);
|
||||
|
||||
int32 ht = 0;
|
||||
if(GetWeaponDamage(GetTarget(), GetInv().GetItem(SLOT_FEET)) <= 0){
|
||||
if(GetWeaponDamage(GetTarget(), GetInv().GetItem(MainFeet)) <= 0){
|
||||
dmg = -5;
|
||||
}
|
||||
else{
|
||||
@@ -405,7 +401,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type)
|
||||
int32 min_dmg = 1;
|
||||
int reuse = 0;
|
||||
SkillUseTypes skill_type; //to avoid casting... even though it "would work"
|
||||
uint8 itemslot = SLOT_FEET;
|
||||
uint8 itemslot = MainFeet;
|
||||
|
||||
switch(unchecked_type)
|
||||
{
|
||||
@@ -421,7 +417,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type)
|
||||
case SkillDragonPunch:{
|
||||
skill_type = SkillDragonPunch;
|
||||
max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, DragonPunchBonus) / 100) + 26;
|
||||
itemslot = SLOT_HANDS;
|
||||
itemslot = MainHands;
|
||||
ApplySpecialAttackMod(skill_type, max_dmg, min_dmg);
|
||||
DoAnim(animTailRake);
|
||||
reuse = TailRakeReuseTime;
|
||||
@@ -431,7 +427,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type)
|
||||
case SkillEagleStrike:{
|
||||
skill_type = SkillEagleStrike;
|
||||
max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, EagleStrikeBonus) / 100) + 19;
|
||||
itemslot = SLOT_HANDS;
|
||||
itemslot = MainHands;
|
||||
ApplySpecialAttackMod(skill_type, max_dmg, min_dmg);
|
||||
DoAnim(animEagleStrike);
|
||||
reuse = EagleStrikeReuseTime;
|
||||
@@ -441,7 +437,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type)
|
||||
case SkillTigerClaw:{
|
||||
skill_type = SkillTigerClaw;
|
||||
max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, TigerClawBonus) / 100) + 12;
|
||||
itemslot = SLOT_HANDS;
|
||||
itemslot = MainHands;
|
||||
ApplySpecialAttackMod(skill_type, max_dmg, min_dmg);
|
||||
DoAnim(animTigerClaw);
|
||||
reuse = TigerClawReuseTime;
|
||||
@@ -511,7 +507,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) {
|
||||
|
||||
//make sure we have a proper weapon if we are a client.
|
||||
if(IsClient()) {
|
||||
const ItemInst *wpn = CastToClient()->GetInv().GetItem(SLOT_PRIMARY);
|
||||
const ItemInst *wpn = CastToClient()->GetInv().GetItem(MainPrimary);
|
||||
if(!wpn || (wpn->GetItem()->ItemType != ItemType1HPiercing)){
|
||||
Message_StringID(13, BACKSTAB_WEAPON);
|
||||
return;
|
||||
@@ -574,7 +570,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) {
|
||||
CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10);
|
||||
}
|
||||
else { //We do a single regular attack if we attack from the front without chaotic stab
|
||||
Attack(other, 13);
|
||||
Attack(other, MainPrimary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,11 +589,11 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
|
||||
|
||||
if(IsClient()){
|
||||
const ItemInst *wpn = nullptr;
|
||||
wpn = CastToClient()->GetInv().GetItem(SLOT_PRIMARY);
|
||||
wpn = CastToClient()->GetInv().GetItem(MainPrimary);
|
||||
if(wpn) {
|
||||
primaryweapondamage = GetWeaponDamage(other, wpn);
|
||||
backstab_dmg = wpn->GetItem()->BackstabDmg;
|
||||
for(int i = 0; i < MAX_AUGMENT_SLOTS; ++i)
|
||||
for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; ++i)
|
||||
{
|
||||
ItemInst *aug = wpn->GetAugment(i);
|
||||
if(aug)
|
||||
@@ -676,7 +672,7 @@ void Mob::RogueAssassinate(Mob* other)
|
||||
{
|
||||
//can you dodge, parry, etc.. an assassinate??
|
||||
//if so, use DoSpecialAttackDamage(other, BACKSTAB, 32000); instead
|
||||
if(GetWeaponDamage(other, IsClient()?CastToClient()->GetInv().GetItem(SLOT_PRIMARY):(const ItemInst*)nullptr) > 0){
|
||||
if(GetWeaponDamage(other, IsClient()?CastToClient()->GetInv().GetItem(MainPrimary):(const ItemInst*)nullptr) > 0){
|
||||
other->Damage(this, 32000, SPELL_UNKNOWN, SkillBackstab);
|
||||
}else{
|
||||
other->Damage(this, -5, SPELL_UNKNOWN, SkillBackstab);
|
||||
@@ -695,20 +691,20 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
|
||||
//Message(0, "Error: Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
|
||||
return;
|
||||
}
|
||||
const ItemInst* RangeWeapon = m_inv[SLOT_RANGE];
|
||||
const ItemInst* RangeWeapon = m_inv[MainRange];
|
||||
|
||||
//locate ammo
|
||||
int ammo_slot = SLOT_AMMO;
|
||||
const ItemInst* Ammo = m_inv[SLOT_AMMO];
|
||||
int ammo_slot = MainAmmo;
|
||||
const ItemInst* Ammo = m_inv[MainAmmo];
|
||||
|
||||
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 no bow!", GetItemIDAt(SLOT_RANGE));
|
||||
mlog(COMBAT__RANGED, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(MainRange), MainRange);
|
||||
Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have no bow!", GetItemIDAt(MainRange));
|
||||
return;
|
||||
}
|
||||
if (!Ammo || !Ammo->IsType(ItemClassCommon)) {
|
||||
mlog(COMBAT__RANGED, "Ranged attack canceled. Missing or invalid ammo item (%d) in slot %d", GetItemIDAt(SLOT_AMMO), SLOT_AMMO);
|
||||
Message(0, "Error: Ammo: GetItem(%i)==0, you have no ammo!", GetItemIDAt(SLOT_AMMO));
|
||||
mlog(COMBAT__RANGED, "Ranged attack canceled. Missing or invalid ammo item (%d) in slot %d", GetItemIDAt(MainAmmo), MainAmmo);
|
||||
Message(0, "Error: Ammo: GetItem(%i)==0, you have no ammo!", GetItemIDAt(MainAmmo));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -733,7 +729,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
|
||||
//first look for quivers
|
||||
int r;
|
||||
bool found = false;
|
||||
for(r = SLOT_PERSONAL_BEGIN; r <= SLOT_PERSONAL_END; r++) {
|
||||
for(r = EmuConstants::GENERAL_BEGIN; r <= EmuConstants::GENERAL_END; r++) {
|
||||
const ItemInst *pi = m_inv[r];
|
||||
if(pi == nullptr || !pi->IsType(ItemClassContainer))
|
||||
continue;
|
||||
@@ -765,7 +761,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
|
||||
//if we dont find a quiver, look through our inventory again
|
||||
//not caring if the thing is a quiver.
|
||||
int32 aslot = m_inv.HasItem(AmmoItem->ID, 1, invWherePersonal);
|
||||
if(aslot != SLOT_INVALID) {
|
||||
if (aslot != INVALID_INDEX) {
|
||||
ammo_slot = aslot;
|
||||
Ammo = m_inv[aslot];
|
||||
mlog(COMBAT__RANGED, "Using ammo from inventory stack at slot %d. %d in stack.", ammo_slot, Ammo->GetCharges());
|
||||
@@ -813,39 +809,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
|
||||
|
||||
CheckIncreaseSkill(SkillArchery, GetTarget(), -15);
|
||||
|
||||
//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 (spellbonuses.NegateIfCombat)
|
||||
BuffFadeByEffect(SE_NegateIfCombat);
|
||||
|
||||
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);
|
||||
}
|
||||
CommonBreakInvisible();
|
||||
}
|
||||
|
||||
void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime)
|
||||
@@ -853,7 +817,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
||||
if (!CanDoSpecialAttack(other))
|
||||
return;
|
||||
|
||||
if (!other->CheckHitChance(this, SkillArchery, 13,chance_mod)) {
|
||||
if (!other->CheckHitChance(this, SkillArchery, MainPrimary, chance_mod)) {
|
||||
mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName());
|
||||
other->Damage(this, 0, SPELL_UNKNOWN, SkillArchery);
|
||||
} else {
|
||||
@@ -975,27 +939,27 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
||||
if (ReuseTime)
|
||||
TrySkillProc(other, SkillArchery, ReuseTime);
|
||||
else
|
||||
TrySkillProc(other, SkillArchery, 0, true, 11);
|
||||
TrySkillProc(other, SkillArchery, 0, true, MainRange);
|
||||
}
|
||||
}
|
||||
|
||||
//try proc on hits and misses
|
||||
if((RangeWeapon != nullptr) && GetTarget() && other && !other->HasDied())
|
||||
{
|
||||
TryWeaponProc(RangeWeapon, other, 11);
|
||||
TryWeaponProc(RangeWeapon, other, MainRange);
|
||||
}
|
||||
|
||||
//Arrow procs because why not?
|
||||
if((Ammo != NULL) && GetTarget() && other && !other->HasDied())
|
||||
{
|
||||
TryWeaponProc(Ammo, other, 11);
|
||||
TryWeaponProc(Ammo, other, MainRange);
|
||||
}
|
||||
|
||||
if (HasSkillProcs() && GetTarget() && other && !other->HasDied()){
|
||||
if (ReuseTime)
|
||||
TrySkillProc(other, SkillArchery, ReuseTime);
|
||||
else
|
||||
TrySkillProc(other, SkillArchery, 0, false, 11);
|
||||
TrySkillProc(other, SkillArchery, 0, false, MainRange);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1018,19 +982,30 @@ void NPC::RangedAttack(Mob* other)
|
||||
return;
|
||||
}
|
||||
|
||||
float range = 250; // needs to be longer than 200(most spells)
|
||||
mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", range);
|
||||
range *= range;
|
||||
if(DistNoRootNoZ(*GetTarget()) > range) {
|
||||
mlog(COMBAT__RANGED, "Ranged attack out of range...%.2f vs %.2f", DistNoRootNoZ(*GetTarget()), range);
|
||||
int sa_min_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0); //Min Range of NPC attack
|
||||
int sa_max_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 1); //Max Range of NPC attack
|
||||
|
||||
float min_range = static_cast<float>(RuleI(Combat, MinRangedAttackDist));
|
||||
float max_range = 250; // needs to be longer than 200(most spells)
|
||||
|
||||
if (sa_max_range)
|
||||
max_range = static_cast<float>(sa_max_range);
|
||||
|
||||
if (sa_min_range)
|
||||
min_range = static_cast<float>(sa_min_range);
|
||||
|
||||
mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", max_range);
|
||||
max_range *= max_range;
|
||||
if(DistNoRootNoZ(*other) > max_range) {
|
||||
mlog(COMBAT__RANGED, "Ranged attack out of range...%.2f vs %.2f", DistNoRootNoZ(*other), max_range);
|
||||
//target is out of range, client does a message
|
||||
return;
|
||||
}
|
||||
else if(DistNoRootNoZ(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){
|
||||
else if(DistNoRootNoZ(*other) < (min_range * min_range))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(!IsAttackAllowed(GetTarget()) ||
|
||||
if(!other || !IsAttackAllowed(other) ||
|
||||
IsCasting() ||
|
||||
DivineAura() ||
|
||||
IsStunned() ||
|
||||
@@ -1040,32 +1015,33 @@ void NPC::RangedAttack(Mob* other)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!ammo)
|
||||
{
|
||||
SkillUseTypes skillinuse = SkillArchery;
|
||||
skillinuse = static_cast<SkillUseTypes>(GetRangedSkill());
|
||||
|
||||
if(!ammo && !GetAmmoIDfile())
|
||||
ammo = database.GetItem(8005);
|
||||
}
|
||||
|
||||
if(ammo)
|
||||
SendItemAnimation(GetTarget(), ammo, SkillArchery);
|
||||
SendItemAnimation(other, ammo, SkillArchery);
|
||||
else
|
||||
ProjectileAnimation(other, 0,false,0,0,0,0,GetAmmoIDfile(),skillinuse);
|
||||
|
||||
FaceTarget(other);
|
||||
|
||||
// Face the Target
|
||||
FaceTarget(GetTarget());
|
||||
|
||||
// Hit?
|
||||
if (!GetTarget()->CheckHitChance(this, SkillArchery, 13))
|
||||
if (!other->CheckHitChance(this, skillinuse, MainRange, GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2)))
|
||||
{
|
||||
mlog(COMBAT__RANGED, "Ranged attack missed %s.", GetTarget()->GetName());
|
||||
GetTarget()->Damage(this, 0, SPELL_UNKNOWN, SkillArchery);
|
||||
mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName());
|
||||
other->Damage(this, 0, SPELL_UNKNOWN, skillinuse);
|
||||
}
|
||||
else
|
||||
{
|
||||
int16 WDmg = GetWeaponDamage(GetTarget(), weapon);
|
||||
int16 ADmg = GetWeaponDamage(GetTarget(), ammo);
|
||||
int16 WDmg = GetWeaponDamage(other, weapon);
|
||||
int16 ADmg = GetWeaponDamage(other, ammo);
|
||||
int32 TotalDmg = 0;
|
||||
if(WDmg > 0 || ADmg > 0)
|
||||
{
|
||||
mlog(COMBAT__RANGED, "Ranged attack hit %s.", GetTarget()->GetName());
|
||||
int32 TotalDmg = 0;
|
||||
|
||||
mlog(COMBAT__RANGED, "Ranged attack hit %s.", other->GetName());
|
||||
|
||||
int32 MaxDmg = max_dmg * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types
|
||||
int32 MinDmg = min_dmg * RuleR(Combat, ArcheryNPCMultiplier);
|
||||
|
||||
@@ -1074,54 +1050,36 @@ void NPC::RangedAttack(Mob* other)
|
||||
else
|
||||
TotalDmg = MakeRandomInt(MinDmg, MaxDmg);
|
||||
|
||||
int32 hate = TotalDmg;
|
||||
|
||||
GetTarget()->MeleeMitigation(this, TotalDmg, MinDmg);
|
||||
ApplyMeleeDamageBonus(SkillArchery, TotalDmg);
|
||||
TryCriticalHit(GetTarget(), SkillArchery, TotalDmg);
|
||||
GetTarget()->AddToHateList(this, hate, 0, false);
|
||||
GetTarget()->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillArchery);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
TotalDmg += TotalDmg * GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3) / 100; //Damage modifier
|
||||
|
||||
other->AvoidDamage(this, TotalDmg, false);
|
||||
other->MeleeMitigation(this, TotalDmg, MinDmg);
|
||||
if (TotalDmg > 0)
|
||||
CommonOutgoingHitSuccess(other, TotalDmg, skillinuse);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
GetTarget()->Damage(this, -5, SPELL_UNKNOWN, SkillArchery);
|
||||
}
|
||||
TotalDmg = -5;
|
||||
|
||||
if (TotalDmg > 0)
|
||||
other->AddToHateList(this, TotalDmg, 0, false);
|
||||
else
|
||||
other->AddToHateList(this, 0, 0, false);
|
||||
|
||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillinuse);
|
||||
|
||||
if (TotalDmg > 0 && HasSkillProcSuccess() && GetTarget() && !other->HasDied())
|
||||
TrySkillProc(other, skillinuse, 0, true, MainRange);
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
//try proc on hits and misses
|
||||
if(other && !other->HasDied())
|
||||
TrySpellProc(nullptr, (const Item_Struct*)nullptr, other, MainRange);
|
||||
|
||||
if (spellbonuses.NegateIfCombat)
|
||||
BuffFadeByEffect(SE_NegateIfCombat);
|
||||
if (HasSkillProcs() && other && !other->HasDied())
|
||||
TrySkillProc(other, skillinuse, 0, false, MainRange);
|
||||
|
||||
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);
|
||||
}
|
||||
CommonBreakInvisible();
|
||||
}
|
||||
|
||||
uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg)
|
||||
@@ -1165,19 +1123,19 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
|
||||
return;
|
||||
}
|
||||
|
||||
int ammo_slot = SLOT_RANGE;
|
||||
const ItemInst* RangeWeapon = m_inv[SLOT_RANGE];
|
||||
int ammo_slot = MainRange;
|
||||
const ItemInst* RangeWeapon = m_inv[MainRange];
|
||||
|
||||
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));
|
||||
mlog(COMBAT__RANGED, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(MainRange), MainRange);
|
||||
Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(MainRange));
|
||||
return;
|
||||
}
|
||||
|
||||
const Item_Struct* item = RangeWeapon->GetItem();
|
||||
if(item->ItemType != ItemTypeLargeThrowing && item->ItemType != ItemTypeSmallThrowing) {
|
||||
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));
|
||||
Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(MainRange));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1185,16 +1143,16 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
|
||||
|
||||
if(RangeWeapon->GetCharges() == 1) {
|
||||
//first check ammo
|
||||
const ItemInst* AmmoItem = m_inv[SLOT_AMMO];
|
||||
const ItemInst* AmmoItem = m_inv[MainAmmo];
|
||||
if(AmmoItem != nullptr && AmmoItem->GetID() == RangeWeapon->GetID()) {
|
||||
//more in the ammo slot, use it
|
||||
RangeWeapon = AmmoItem;
|
||||
ammo_slot = SLOT_AMMO;
|
||||
ammo_slot = MainAmmo;
|
||||
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
|
||||
int32 aslot = m_inv.HasItem(item->ID, 1, invWherePersonal);
|
||||
if(aslot != SLOT_INVALID) {
|
||||
if (aslot != INVALID_INDEX) {
|
||||
//the item wont change, but the instance does, not that it matters
|
||||
ammo_slot = aslot;
|
||||
RangeWeapon = m_inv[aslot];
|
||||
@@ -1234,39 +1192,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
|
||||
DeleteItemInInventory(ammo_slot, 1, true);
|
||||
CheckIncreaseSkill(SkillThrowing, GetTarget());
|
||||
|
||||
//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 (spellbonuses.NegateIfCombat)
|
||||
BuffFadeByEffect(SE_NegateIfCombat);
|
||||
|
||||
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);
|
||||
}
|
||||
CommonBreakInvisible();
|
||||
}
|
||||
|
||||
void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item_Struct* item, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime)
|
||||
@@ -1274,7 +1200,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
||||
if (!CanDoSpecialAttack(other))
|
||||
return;
|
||||
|
||||
if (!other->CheckHitChance(this, SkillThrowing, 13, chance_mod)){
|
||||
if (!other->CheckHitChance(this, SkillThrowing, MainPrimary, chance_mod)){
|
||||
mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName());
|
||||
other->Damage(this, 0, SPELL_UNKNOWN, SkillThrowing);
|
||||
} else {
|
||||
@@ -1312,38 +1238,31 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
||||
|
||||
other->MeleeMitigation(this, TotalDmg, minDmg);
|
||||
if(TotalDmg > 0)
|
||||
{
|
||||
ApplyMeleeDamageBonus(SkillThrowing, TotalDmg);
|
||||
TotalDmg += other->GetFcDamageAmtIncoming(this, 0, true, SkillThrowing);
|
||||
TotalDmg += (itembonuses.HeroicDEX / 10) + (TotalDmg * other->GetSkillDmgTaken(SkillThrowing) / 100) + GetSkillDmgAmt(SkillThrowing);
|
||||
TryCriticalHit(other, SkillThrowing, TotalDmg);
|
||||
int32 hate = (2*WDmg);
|
||||
other->AddToHateList(this, hate, 0, false);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
}
|
||||
CommonOutgoingHitSuccess(other, TotalDmg, SkillThrowing);
|
||||
}
|
||||
|
||||
else
|
||||
TotalDmg = -5;
|
||||
|
||||
other->AddToHateList(this, 2*WDmg, 0, false);
|
||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillThrowing);
|
||||
|
||||
if (TotalDmg > 0 && HasSkillProcSuccess() && GetTarget() && other && !other->HasDied()){
|
||||
if (ReuseTime)
|
||||
TrySkillProc(other, SkillThrowing, ReuseTime);
|
||||
else
|
||||
TrySkillProc(other, SkillThrowing, 0, true, 11);
|
||||
TrySkillProc(other, SkillThrowing, 0, true, MainRange);
|
||||
}
|
||||
}
|
||||
|
||||
if((RangeWeapon != nullptr) && GetTarget() && other && (other->GetHP() > -10))
|
||||
TryWeaponProc(RangeWeapon, other, 11);
|
||||
TryWeaponProc(RangeWeapon, other, MainRange);
|
||||
|
||||
if (HasSkillProcs() && GetTarget() && other && !other->HasDied()){
|
||||
if (ReuseTime)
|
||||
TrySkillProc(other, SkillThrowing, ReuseTime);
|
||||
else
|
||||
TrySkillProc(other, SkillThrowing, 0, false, 11);
|
||||
TrySkillProc(other, SkillThrowing, 0, false, MainRange);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1394,7 +1313,10 @@ void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skil
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, float angle, float tilt, float arc, const char *IDFile) {
|
||||
void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, float angle, float tilt, float arc, const char *IDFile, SkillUseTypes skillInUse) {
|
||||
|
||||
if (!to)
|
||||
return;
|
||||
|
||||
const Item_Struct* item = nullptr;
|
||||
uint8 item_type = 0;
|
||||
@@ -1412,9 +1334,12 @@ void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, f
|
||||
if(IsArrow) {
|
||||
item_type = 27;
|
||||
}
|
||||
if(!item_type) {
|
||||
if(!item_type && !skillInUse) {
|
||||
item_type = item->ItemType;
|
||||
}
|
||||
else if (skillInUse)
|
||||
item_type = GetItemTypeBySkill(skillInUse);
|
||||
|
||||
if(!speed) {
|
||||
speed = 4.0;
|
||||
}
|
||||
@@ -1444,7 +1369,7 @@ void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, f
|
||||
as->target_id = to->GetID();
|
||||
as->item_id = item->ID;
|
||||
as->item_type = item_type;
|
||||
as->skill = 0; // Doesn't seem to have any effect
|
||||
as->skill = skillInUse; // Doesn't seem to have any effect
|
||||
strn0cpy(as->model_name, item_IDFile, 16);
|
||||
as->velocity = speed;
|
||||
as->launch_angle = angle;
|
||||
@@ -1768,8 +1693,8 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
{
|
||||
DoAnim(animTailRake);
|
||||
|
||||
if(GetWeaponDamage(ca_target, GetInv().GetItem(SLOT_SECONDARY)) <= 0 &&
|
||||
GetWeaponDamage(ca_target, GetInv().GetItem(SLOT_SHOULDER)) <= 0){
|
||||
if(GetWeaponDamage(ca_target, GetInv().GetItem(MainSecondary)) <= 0 &&
|
||||
GetWeaponDamage(ca_target, GetInv().GetItem(MainShoulders)) <= 0){
|
||||
dmg = -5;
|
||||
}
|
||||
else{
|
||||
@@ -1839,7 +1764,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
{
|
||||
DoAnim(animKick);
|
||||
|
||||
if(GetWeaponDamage(ca_target, GetInv().GetItem(SLOT_FEET)) <= 0){
|
||||
if(GetWeaponDamage(ca_target, GetInv().GetItem(MainFeet)) <= 0){
|
||||
dmg = -5;
|
||||
}
|
||||
else{
|
||||
@@ -2062,7 +1987,7 @@ uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) {
|
||||
|
||||
if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){
|
||||
|
||||
float ProcChance = GetSpecialProcChances(11);
|
||||
float ProcChance = GetSpecialProcChances(MainRange);
|
||||
if(ProcChance > MakeRandomFloat(0,1))
|
||||
return HeadShot_Dmg;
|
||||
}
|
||||
@@ -2125,7 +2050,7 @@ uint32 Mob::TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 Reuse
|
||||
float ProcChance = 0.0f;
|
||||
|
||||
if (skillInUse == SkillThrowing)
|
||||
ProcChance = GetSpecialProcChances(11);
|
||||
ProcChance = GetSpecialProcChances(MainRange);
|
||||
else
|
||||
ProcChance = GetAssassinateProcChances(ReuseTime);
|
||||
|
||||
@@ -2173,8 +2098,8 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
skillinuse = SkillOffense;
|
||||
|
||||
int damage = 0;
|
||||
uint32 hate = 0;
|
||||
int Hand = 13;
|
||||
int32 hate = 0;
|
||||
int Hand = MainPrimary;
|
||||
if (hate == 0 && weapon_damage > 1) hate = weapon_damage;
|
||||
|
||||
if(weapon_damage > 0){
|
||||
@@ -2199,6 +2124,19 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
hate += ucDamageBonus;
|
||||
}
|
||||
|
||||
if(skillinuse == SkillBash){
|
||||
if(IsClient()){
|
||||
ItemInst *item = CastToClient()->GetInv().GetItem(MainSecondary);
|
||||
if(item){
|
||||
if(item->GetItem()->ItemType == ItemTypeShield) {
|
||||
hate += item->GetItem()->AC;
|
||||
}
|
||||
const Item_Struct *itm = item->GetItem();
|
||||
hate = hate * (100 + GetFuriousBash(itm->Focus.Effect)) / 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ApplySpecialAttackMod(skillinuse, max_hit, min_hit);
|
||||
|
||||
min_hit += min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100;
|
||||
@@ -2210,18 +2148,14 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
damage = max_hit;
|
||||
else
|
||||
damage = MakeRandomInt(min_hit, max_hit);
|
||||
|
||||
|
||||
if(!other->CheckHitChance(this, skillinuse, Hand, chance_mod)) {
|
||||
damage = 0;
|
||||
} else {
|
||||
other->AvoidDamage(this, damage, CanRiposte);
|
||||
other->MeleeMitigation(this, damage, min_hit);
|
||||
if(damage > 0) {
|
||||
ApplyMeleeDamageBonus(skillinuse, damage);
|
||||
damage += other->GetFcDamageAmtIncoming(this, 0, true, skillinuse);
|
||||
damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse);
|
||||
TryCriticalHit(other, skillinuse, damage);
|
||||
}
|
||||
if(damage > 0)
|
||||
CommonOutgoingHitSuccess(other, damage, skillinuse);
|
||||
}
|
||||
|
||||
if (damage == -3) {
|
||||
@@ -2234,19 +2168,6 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
else
|
||||
damage = -5;
|
||||
|
||||
if(skillinuse == SkillBash){
|
||||
if(IsClient()){
|
||||
ItemInst *item = CastToClient()->GetInv().GetItem(SLOT_SECONDARY);
|
||||
if(item){
|
||||
if(item->GetItem()->ItemType == ItemTypeShield) {
|
||||
hate += item->GetItem()->AC;
|
||||
}
|
||||
const Item_Struct *itm = item->GetItem();
|
||||
hate = hate * (100 + GetFuriousBash(itm->Focus.Effect)) / 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
other->AddToHateList(this, hate);
|
||||
|
||||
bool CanSkillProc = true;
|
||||
@@ -2255,6 +2176,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
CanSkillProc = false; //Disable skill procs
|
||||
}
|
||||
|
||||
other->AddToHateList(this, hate, 0, false);
|
||||
other->Damage(this, damage, SPELL_UNKNOWN, skillinuse);
|
||||
|
||||
if (HasDied())
|
||||
|
||||
+9
-11
@@ -599,7 +599,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
snprintf(effect_desc, _EDLEN, "Flesh To Bone");
|
||||
#endif
|
||||
if(IsClient()){
|
||||
ItemInst* transI = CastToClient()->GetInv().GetItem(SLOT_CURSOR);
|
||||
ItemInst* transI = CastToClient()->GetInv().GetItem(MainCursor);
|
||||
if(transI && transI->IsType(ItemClassCommon) && transI->IsStackable()){
|
||||
uint32 fcharges = transI->GetCharges();
|
||||
//Does it sound like meat... maybe should check if it looks like meat too...
|
||||
@@ -609,7 +609,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
strstr(transI->GetItem()->Name, "Flesh") ||
|
||||
strstr(transI->GetItem()->Name, "parts") ||
|
||||
strstr(transI->GetItem()->Name, "Parts")){
|
||||
CastToClient()->DeleteItemInInventory(SLOT_CURSOR, fcharges, true);
|
||||
CastToClient()->DeleteItemInInventory(MainCursor, fcharges, true);
|
||||
CastToClient()->SummonItem(13073, fcharges);
|
||||
}
|
||||
else{
|
||||
@@ -1159,7 +1159,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
|
||||
if (SummonedItem) {
|
||||
c->PushItemOnCursor(*SummonedItem);
|
||||
c->SendItemPacket(SLOT_CURSOR, SummonedItem, ItemPacketSummonItem);
|
||||
c->SendItemPacket(MainCursor, SummonedItem, ItemPacketSummonItem);
|
||||
safe_delete(SummonedItem);
|
||||
}
|
||||
SummonedItem = database.CreateItem(spell.base[i], charges);
|
||||
@@ -2200,7 +2200,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
snprintf(effect_desc, _EDLEN, "Rampage");
|
||||
#endif
|
||||
if(caster)
|
||||
entity_list.AEAttack(caster, 30, 13, 0, true); // on live wars dont get a duration ramp, its a one shot deal
|
||||
entity_list.AEAttack(caster, 30, MainPrimary, 0, true); // on live wars dont get a duration ramp, its a one shot deal
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2983,7 +2983,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
if (SummonedItem) {
|
||||
Client *c=CastToClient();
|
||||
c->PushItemOnCursor(*SummonedItem);
|
||||
c->SendItemPacket(SLOT_CURSOR, SummonedItem, ItemPacketSummonItem);
|
||||
c->SendItemPacket(MainCursor, SummonedItem, ItemPacketSummonItem);
|
||||
safe_delete(SummonedItem);
|
||||
}
|
||||
|
||||
@@ -5070,7 +5070,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
|
||||
}
|
||||
}
|
||||
|
||||
for(int y = 0; y < MAX_AUGMENT_SLOTS; ++y)
|
||||
for (int y = 0; y < EmuConstants::ITEM_COMMON_SIZE; ++y)
|
||||
{
|
||||
if (SympatheticProcList.size() > MAX_SYMPATHETIC)
|
||||
continue;
|
||||
@@ -5226,7 +5226,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) {
|
||||
}
|
||||
}
|
||||
|
||||
for(int y = 0; y < MAX_AUGMENT_SLOTS; ++y)
|
||||
for (int y = 0; y < EmuConstants::ITEM_COMMON_SIZE; ++y)
|
||||
{
|
||||
ItemInst *aug = nullptr;
|
||||
aug = ins->GetAugment(y);
|
||||
@@ -5264,7 +5264,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) {
|
||||
}
|
||||
|
||||
//Tribute Focus
|
||||
for(int x = TRIBUTE_SLOT_START; x < (TRIBUTE_SLOT_START + MAX_PLAYER_TRIBUTES); ++x)
|
||||
for(int x = EmuConstants::TRIBUTE_BEGIN; x <= EmuConstants::TRIBUTE_END; ++x)
|
||||
{
|
||||
TempItem = nullptr;
|
||||
ItemInst* ins = GetInv().GetItem(x);
|
||||
@@ -5765,8 +5765,6 @@ int32 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spel
|
||||
int value = 0;
|
||||
|
||||
if (spellbonuses.FocusEffects[type]){
|
||||
uint32 buff_count = GetMaxTotalSlots();
|
||||
for(int i = 0; i < buff_count; i++){
|
||||
|
||||
int32 tmp_focus = 0;
|
||||
int tmp_buffslot = -1;
|
||||
@@ -5799,7 +5797,7 @@ int32 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spel
|
||||
CheckNumHitsRemaining(NUMHIT_MatchingSpells, tmp_buffslot);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -285,7 +285,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
if( itm && (itm->GetItem()->Click.Type == ET_EquipClick) && !(item_slot < 22 || item_slot == 9999) ){
|
||||
if( itm && (itm->GetItem()->Click.Type == ET_EquipClick) && !(item_slot <= MainAmmo || item_slot == MainPowerSource) ){
|
||||
if (CastToClient()->GetClientVersion() < EQClientSoF) {
|
||||
// They are attempting to cast a must equip clicky without having it equipped
|
||||
LogFile->write(EQEMuLog::Error, "HACKER: %s (account: %s) attempted to click an equip-only effect on item %s (id: %d) without equiping it!", CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID);
|
||||
@@ -1195,7 +1195,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot,
|
||||
uint32 recastdelay = 0;
|
||||
uint32 recasttype = 0;
|
||||
|
||||
for(int r = 0; r < MAX_AUGMENT_SLOTS; r++) {
|
||||
for (int r = 0; r < EmuConstants::ITEM_COMMON_SIZE; r++) {
|
||||
const ItemInst* aug_i = inst->GetAugment(r);
|
||||
|
||||
if(!aug_i)
|
||||
@@ -5018,7 +5018,7 @@ bool Mob::IsCombatProc(uint16 spell_id) {
|
||||
|
||||
for (int i = 0; i < MAX_PROCS; i++){
|
||||
if (PermaProcs[i].spellID == spell_id || SpellProcs[i].spellID == spell_id
|
||||
|| SkillProcs[i].spellID == spell_id || RangedProcs[i].spellID == spell_id){
|
||||
|| RangedProcs[i].spellID == spell_id){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -5075,7 +5075,7 @@ bool Mob::AddDefensiveProc(uint16 spell_id, uint16 iChance, uint16 base_spell_id
|
||||
{
|
||||
if(spell_id == SPELL_UNKNOWN)
|
||||
return(false);
|
||||
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_PROCS; i++) {
|
||||
if (DefensiveProcs[i].spellID == SPELL_UNKNOWN) {
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ bool TitleManager::IsClientEligibleForTitle(Client *c, std::vector<TitleEntry>::
|
||||
|
||||
}
|
||||
|
||||
if((Title->ItemID >= 1) && (c->GetInv().HasItem(Title->ItemID, 0, 0xFF) == SLOT_INVALID))
|
||||
if ((Title->ItemID >= 1) && (c->GetInv().HasItem(Title->ItemID, 0, 0xFF) == INVALID_INDEX))
|
||||
return false;
|
||||
|
||||
if((Title->TitleSet > 0) && (!c->CheckTitle(Title->TitleSet)))
|
||||
|
||||
@@ -482,7 +482,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac
|
||||
//because a HasItem on items with num > 1 only returns the
|
||||
//last-most slot... the results of this are useless to us
|
||||
//when we go to delete them because we cannot assume it is in a single stack.
|
||||
if(user_inv.HasItem(item, num, invWherePersonal) != SLOT_INVALID)
|
||||
if (user_inv.HasItem(item, num, invWherePersonal) != INVALID_INDEX)
|
||||
count += num;
|
||||
else
|
||||
MissingItems.push_back(item);
|
||||
@@ -524,7 +524,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac
|
||||
//we have to loop here to delete 1 at a time in case its in multiple stacks.
|
||||
for(k = 0; k < counts[r]; k++) {
|
||||
slot = user_inv.HasItem(items[r], 1, invWherePersonal);
|
||||
if(slot == SLOT_INVALID) {
|
||||
if (slot == INVALID_INDEX) {
|
||||
//WTF... I just checked this above, but just to be sure...
|
||||
//we cant undo the previous deletes without a lot of work.
|
||||
//so just call it quits, this shouldent ever happen anyways.
|
||||
|
||||
+12
-12
@@ -87,7 +87,7 @@ void Trade::AddEntity(uint16 from_slot_id, uint16 trade_slot_id)
|
||||
|
||||
// Item always goes into trade bucket from cursor
|
||||
Client* client = owner->CastToClient();
|
||||
const ItemInst* inst = client->GetInv().GetItem(SLOT_CURSOR);
|
||||
const ItemInst* inst = client->GetInv().GetItem(MainCursor);
|
||||
if (!inst) {
|
||||
client->Message(13, "Error: Could not find item on your cursor!");
|
||||
return;
|
||||
@@ -105,7 +105,7 @@ void Trade::AddEntity(uint16 from_slot_id, uint16 trade_slot_id)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (client->GetInv().GetItem(SLOT_CURSOR)->GetID() != client->GetInv().GetItem(trade_slot_id)->GetID()) {
|
||||
if (client->GetInv().GetItem(MainCursor)->GetID() != client->GetInv().GetItem(trade_slot_id)->GetID()) {
|
||||
client->Kick();
|
||||
return;
|
||||
}
|
||||
@@ -146,13 +146,13 @@ void Trade::SendItemData(const ItemInst* inst, int16 dest_slot_id)
|
||||
Client* with = mob->CastToClient();
|
||||
Client* trader = owner->CastToClient();
|
||||
if (with && with->IsClient()) {
|
||||
with->SendItemPacket(dest_slot_id -IDX_TRADE,inst,ItemPacketTradeView);
|
||||
with->SendItemPacket(dest_slot_id - EmuConstants::TRADE_BEGIN, inst, ItemPacketTradeView);
|
||||
if (inst->GetItem()->ItemClass == 1) {
|
||||
for (uint16 i=0; i<10; i++) {
|
||||
uint16 bagslot_id = Inventory::CalcSlotId(dest_slot_id, i);
|
||||
const ItemInst* bagitem = trader->GetInv().GetItem(bagslot_id);
|
||||
if (bagitem) {
|
||||
with->SendItemPacket(bagslot_id-IDX_TRADE,bagitem,ItemPacketTradeView);
|
||||
with->SendItemPacket(bagslot_id - EmuConstants::TRADE_BEGIN, bagitem, ItemPacketTradeView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -318,7 +318,7 @@ void Client::ResetTrade() {
|
||||
{
|
||||
bool is_arrow = (TempItem->ItemType == ItemTypeArrow) ? true : false;
|
||||
int freeslotid = GetInv().FindFreeSlot(ins->IsType(ItemClassContainer), true, TempItem->Size, is_arrow);
|
||||
if (freeslotid == SLOT_INVALID)
|
||||
if (freeslotid == INVALID_INDEX)
|
||||
{
|
||||
DropInst(ins);
|
||||
}
|
||||
@@ -441,14 +441,14 @@ void Client::FinishTrade(Mob* tradingWith, ServerPacket* qspack, bool finalizer)
|
||||
|
||||
if(QSPLT) {
|
||||
qsaudit->items[parent_offset].to_id = this->character_id;
|
||||
qsaudit->items[parent_offset].to_slot = SLOT_CURSOR;
|
||||
qsaudit->items[parent_offset].to_slot = MainCursor;
|
||||
|
||||
if(inst->IsType(ItemClassContainer)) {
|
||||
for(uint8 bagslot_idx = 0; bagslot_idx < inst->GetItem()->BagSlots; bagslot_idx++) {
|
||||
const ItemInst* bag_inst = inst->GetItem(bagslot_idx);
|
||||
|
||||
if(bag_inst == nullptr) { continue; }
|
||||
int16 to_bagslot_id = Inventory::CalcSlotId(SLOT_CURSOR, bagslot_idx);
|
||||
int16 to_bagslot_id = Inventory::CalcSlotId(MainCursor, bagslot_idx);
|
||||
|
||||
qsaudit->items[++parent_offset].to_id = this->character_id;
|
||||
qsaudit->items[parent_offset].to_slot = to_bagslot_id;
|
||||
@@ -465,14 +465,14 @@ void Client::FinishTrade(Mob* tradingWith, ServerPacket* qspack, bool finalizer)
|
||||
|
||||
if(QSPLT) {
|
||||
qsaudit->items[parent_offset].to_id = this->character_id;
|
||||
qsaudit->items[parent_offset].to_slot = SLOT_CURSOR;
|
||||
qsaudit->items[parent_offset].to_slot = MainCursor;
|
||||
|
||||
if(inst->IsType(ItemClassContainer)) {
|
||||
for(uint8 bagslot_idx = 0; bagslot_idx < inst->GetItem()->BagSlots; bagslot_idx++) {
|
||||
const ItemInst* bag_inst = inst->GetItem(bagslot_idx);
|
||||
|
||||
if(bag_inst == nullptr) { continue; }
|
||||
int16 to_bagslot_id = Inventory::CalcSlotId(SLOT_CURSOR, bagslot_idx);
|
||||
int16 to_bagslot_id = Inventory::CalcSlotId(MainCursor, bagslot_idx);
|
||||
|
||||
qsaudit->items[++parent_offset].to_id = this->character_id;
|
||||
qsaudit->items[parent_offset].to_slot = to_bagslot_id;
|
||||
@@ -2214,7 +2214,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) {
|
||||
|
||||
if(!item || !Quantity || !Price || !QtyBuyerWants) return;
|
||||
|
||||
if(m_inv.HasItem(ItemID, Quantity, invWhereWorn|invWherePersonal|invWhereCursor) == SLOT_INVALID) {
|
||||
if (m_inv.HasItem(ItemID, Quantity, invWhereWorn | invWherePersonal | invWhereCursor) == INVALID_INDEX) {
|
||||
Message(13, "You do not have %i %s on you.", Quantity, item->Name);
|
||||
return;
|
||||
}
|
||||
@@ -2264,7 +2264,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) {
|
||||
int16 SellerSlot = m_inv.HasItem(ItemID, 1, invWhereWorn|invWherePersonal|invWhereCursor);
|
||||
|
||||
// This shouldn't happen, as we already checked there was space in the Buyer's inventory
|
||||
if(SellerSlot == SLOT_INVALID) {
|
||||
if (SellerSlot == INVALID_INDEX) {
|
||||
|
||||
if(i > 0) {
|
||||
// Set the Quantity to the actual number we successfully transferred.
|
||||
@@ -2316,7 +2316,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) {
|
||||
// Find the slot on the seller that has a stack of at least 1 of the item
|
||||
int16 SellerSlot = m_inv.HasItem(ItemID, 1, invWhereWorn|invWherePersonal|invWhereCursor);
|
||||
|
||||
if(SellerSlot == SLOT_INVALID) {
|
||||
if (SellerSlot == INVALID_INDEX) {
|
||||
_log(TRADING__BARTER, "Unexpected error while moving item from seller to buyer.");
|
||||
Message(13, "Internal error while processing transaction.");
|
||||
return;
|
||||
|
||||
+15
-15
@@ -66,7 +66,7 @@ void Client::ToggleTribute(bool enabled) {
|
||||
int r;
|
||||
uint32 cost = 0;
|
||||
uint32 level = GetLevel();
|
||||
for(r = 0; r < MAX_PLAYER_TRIBUTES; r++) {
|
||||
for(r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) {
|
||||
uint32 tid = m_pp.tributes[r].tribute;
|
||||
if(tid == TRIBUTE_NONE)
|
||||
continue;
|
||||
@@ -119,7 +119,7 @@ void Client::DoTributeUpdate() {
|
||||
tis->tribute_master_id = tribute_master_id; //Dont know what this is for
|
||||
|
||||
int r;
|
||||
for(r = 0; r < MAX_PLAYER_TRIBUTES; r++) {
|
||||
for(r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) {
|
||||
if(m_pp.tributes[r].tribute != TRIBUTE_NONE) {
|
||||
tis->tributes[r] = m_pp.tributes[r].tribute;
|
||||
tis->tiers[r] = m_pp.tributes[r].tier;
|
||||
@@ -134,24 +134,24 @@ void Client::DoTributeUpdate() {
|
||||
|
||||
if(m_pp.tribute_active) {
|
||||
//send and equip tribute items...
|
||||
for(r = 0; r < MAX_PLAYER_TRIBUTES; r++) {
|
||||
for(r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) {
|
||||
uint32 tid = m_pp.tributes[r].tribute;
|
||||
if(tid == TRIBUTE_NONE) {
|
||||
if(m_inv[TRIBUTE_SLOT_START+r])
|
||||
DeleteItemInInventory(TRIBUTE_SLOT_START+r, 0, false);
|
||||
if(m_inv[EmuConstants::TRIBUTE_BEGIN + r])
|
||||
DeleteItemInInventory(EmuConstants::TRIBUTE_BEGIN + r, 0, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(tribute_list.count(tid) != 1) {
|
||||
if(m_inv[TRIBUTE_SLOT_START+r])
|
||||
DeleteItemInInventory(TRIBUTE_SLOT_START+r, 0, false);
|
||||
if (m_inv[EmuConstants::TRIBUTE_BEGIN + r])
|
||||
DeleteItemInInventory(EmuConstants::TRIBUTE_BEGIN + r, 0, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
//sanity check
|
||||
if(m_pp.tributes[r].tier >= MAX_TRIBUTE_TIERS) {
|
||||
if(m_inv[TRIBUTE_SLOT_START+r])
|
||||
DeleteItemInInventory(TRIBUTE_SLOT_START+r, 0, false);
|
||||
if (m_inv[EmuConstants::TRIBUTE_BEGIN + r])
|
||||
DeleteItemInInventory(EmuConstants::TRIBUTE_BEGIN + r, 0, false);
|
||||
m_pp.tributes[r].tier = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -165,15 +165,15 @@ void Client::DoTributeUpdate() {
|
||||
if(inst == nullptr)
|
||||
continue;
|
||||
|
||||
PutItemInInventory(TRIBUTE_SLOT_START+r, *inst, false);
|
||||
SendItemPacket(TRIBUTE_SLOT_START+r, inst, ItemPacketTributeItem);
|
||||
PutItemInInventory(EmuConstants::TRIBUTE_BEGIN + r, *inst, false);
|
||||
SendItemPacket(EmuConstants::TRIBUTE_BEGIN + r, inst, ItemPacketTributeItem);
|
||||
safe_delete(inst);
|
||||
}
|
||||
} else {
|
||||
//unequip tribute items...
|
||||
for(r = 0; r < MAX_PLAYER_TRIBUTES; r++) {
|
||||
if(m_inv[TRIBUTE_SLOT_START+r])
|
||||
DeleteItemInInventory(TRIBUTE_SLOT_START+r, 0, false);
|
||||
for(r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) {
|
||||
if (m_inv[EmuConstants::TRIBUTE_BEGIN + r])
|
||||
DeleteItemInInventory(EmuConstants::TRIBUTE_BEGIN + r, 0, false);
|
||||
}
|
||||
}
|
||||
CalcBonuses();
|
||||
@@ -192,7 +192,7 @@ void Client::SendTributeTimer() {
|
||||
|
||||
void Client::ChangeTributeSettings(TributeInfo_Struct *t) {
|
||||
int r;
|
||||
for(r = 0; r < MAX_PLAYER_TRIBUTES; r++) {
|
||||
for(r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) {
|
||||
|
||||
m_pp.tributes[r].tribute = TRIBUTE_NONE;
|
||||
|
||||
|
||||
+11
-5
@@ -1067,8 +1067,10 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) {
|
||||
"npc_types.npc_spells_effects_id,"
|
||||
"npc_types.d_meele_texture1,"
|
||||
"npc_types.d_meele_texture2,"
|
||||
"npc_types.ammo_idfile,"
|
||||
"npc_types.prim_melee_type,"
|
||||
"npc_types.sec_melee_type,"
|
||||
"npc_types.ranged_type,"
|
||||
"npc_types.runspeed,"
|
||||
"npc_types.findable,"
|
||||
"npc_types.trackable,"
|
||||
@@ -1103,6 +1105,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) {
|
||||
"npc_types.see_improved_hide,"
|
||||
"npc_types.ATK,"
|
||||
"npc_types.Accuracy,"
|
||||
"npc_types.Avoidance,"
|
||||
"npc_types.slow_mitigation,"
|
||||
"npc_types.maxlevel,"
|
||||
"npc_types.scalerate,"
|
||||
@@ -1166,8 +1169,10 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) {
|
||||
tmpNPCType->npc_spells_effects_id = atoi(row[r++]);
|
||||
tmpNPCType->d_meele_texture1 = atoi(row[r++]);
|
||||
tmpNPCType->d_meele_texture2 = atoi(row[r++]);
|
||||
strn0cpy(tmpNPCType->ammo_idfile, row[r++], 30);
|
||||
tmpNPCType->prim_melee_type = atoi(row[r++]);
|
||||
tmpNPCType->sec_melee_type = atoi(row[r++]);
|
||||
tmpNPCType->ranged_type = atoi(row[r++]);
|
||||
tmpNPCType->runspeed= atof(row[r++]);
|
||||
tmpNPCType->findable = atoi(row[r++]) == 0? false : true;
|
||||
tmpNPCType->trackable = atoi(row[r++]) == 0? false : true;
|
||||
@@ -1286,6 +1291,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) {
|
||||
tmpNPCType->see_improved_hide = atoi(row[r++])==0?false:true;
|
||||
tmpNPCType->ATK = atoi(row[r++]);
|
||||
tmpNPCType->accuracy_rating = atoi(row[r++]);
|
||||
tmpNPCType->avoidance_rating = atoi(row[r++]);
|
||||
tmpNPCType->slow_mitigation = atoi(row[r++]);
|
||||
tmpNPCType->maxlevel = atoi(row[r++]);
|
||||
tmpNPCType->scalerate = atoi(row[r++]);
|
||||
@@ -1992,7 +1998,7 @@ void ZoneDatabase::LoadMercEquipment(Merc *merc) {
|
||||
int itemCount = 0;
|
||||
|
||||
while(DataRow = mysql_fetch_row(DatasetResult)) {
|
||||
if(itemCount == MAX_WORN_INVENTORY)
|
||||
if (itemCount == EmuConstants::EQUIPMENT_SIZE)
|
||||
break;
|
||||
|
||||
if(atoi(DataRow[0]) > 0) {
|
||||
@@ -2768,7 +2774,7 @@ void ZoneDatabase::SavePetInfo(Client *c) {
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i<MAX_WORN_INVENTORY; i++) {
|
||||
for (i = 0; i<EmuConstants::EQUIPMENT_SIZE; i++) {
|
||||
if(petinfo->Items[i]) {
|
||||
database.RunQuery(query, MakeAnyLenString(&query,
|
||||
"INSERT INTO `character_pet_inventory` (`char_id`, `pet`, `slot`, `item_id`) values (%u, 0, %u, %u)",
|
||||
@@ -2792,7 +2798,7 @@ void ZoneDatabase::SavePetInfo(Client *c) {
|
||||
}
|
||||
safe_delete_array(query);
|
||||
|
||||
for(i=0; i<MAX_WORN_INVENTORY; i++) {
|
||||
for (i = 0; i<EmuConstants::EQUIPMENT_SIZE; i++) {
|
||||
if(suspended->Items[i]) {
|
||||
database.RunQuery(query, MakeAnyLenString(&query,
|
||||
"INSERT INTO `character_pet_inventory` (`char_id`, `pet`, `slot`, `item_id`) values (%u, 1, %u, %u)",
|
||||
@@ -2923,9 +2929,9 @@ void ZoneDatabase::LoadPetInfo(Client *c) {
|
||||
pi = suspended;
|
||||
else
|
||||
continue;
|
||||
|
||||
|
||||
int slot = atoi(row[1]);
|
||||
if (slot < 0 || slot > MAX_WORN_INVENTORY)
|
||||
if (slot < 0 || slot > EmuConstants::EQUIPMENT_SIZE) // if (slot == 22) { zone.TriggerRandomCrash(); }
|
||||
continue;
|
||||
|
||||
pi->Items[slot] = atoul(row[2]);
|
||||
|
||||
+18
-2
@@ -43,9 +43,25 @@ struct DBnpcspellseffects_entries_Struct {
|
||||
|
||||
struct DBnpcspells_Struct {
|
||||
uint32 parent_list;
|
||||
int16 attack_proc;
|
||||
uint16 attack_proc;
|
||||
uint8 proc_chance;
|
||||
uint16 range_proc;
|
||||
int16 rproc_chance;
|
||||
uint16 defensive_proc;
|
||||
int16 dproc_chance;
|
||||
uint32 numentries;
|
||||
uint32 fail_recast;
|
||||
uint32 engaged_no_sp_recast_min;
|
||||
uint32 engaged_no_sp_recast_max;
|
||||
uint8 engaged_beneficial_self_chance;
|
||||
uint8 engaged_beneficial_other_chance;
|
||||
uint8 engaged_detrimental_chance;
|
||||
uint32 pursue_no_sp_recast_min;
|
||||
uint32 pursue_no_sp_recast_max;
|
||||
uint8 pursue_detrimental_chance;
|
||||
uint32 idle_no_sp_recast_min;
|
||||
uint32 idle_no_sp_recast_max;
|
||||
uint8 idle_beneficial_chance;
|
||||
DBnpcspells_entries_Struct entries[0];
|
||||
};
|
||||
|
||||
@@ -90,7 +106,7 @@ struct PetInfo {
|
||||
uint32 Mana;
|
||||
float size;
|
||||
SpellBuff_Struct Buffs[BUFF_COUNT];
|
||||
uint32 Items[MAX_WORN_INVENTORY];
|
||||
uint32 Items[EmuConstants::EQUIPMENT_SIZE];
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
|
||||
@@ -94,8 +94,10 @@ struct NPCType
|
||||
char special_abilities[512];
|
||||
uint16 d_meele_texture1;
|
||||
uint16 d_meele_texture2;
|
||||
char ammo_idfile[30];
|
||||
uint8 prim_melee_type;
|
||||
uint8 sec_melee_type;
|
||||
uint8 ranged_type;
|
||||
int32 hp_regen;
|
||||
int32 mana_regen;
|
||||
int32 aggroradius; // added for AI improvement - neotokyo
|
||||
@@ -110,6 +112,7 @@ struct NPCType
|
||||
uint8 mount_color; //only used by horse class
|
||||
float attack_speed; //%+- on attack delay of the mob.
|
||||
int accuracy_rating; //10 = 1% accuracy
|
||||
int avoidance_rating; //10 = 1% avoidance
|
||||
bool findable; //can be found with find command
|
||||
bool trackable;
|
||||
int16 slow_mitigation;
|
||||
|
||||
Reference in New Issue
Block a user