void Client::SetLevel(uint8 set_level, bool command) { if (GetEXPForLevel(set_level) == 0xFFFFFFFF) { LogFile->write(EQEMuLog::Error,"Client::SetLevel() GetEXPForLevel(%i) = 0xFFFFFFFF", set_level); return; } EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelUpdate, sizeof(LevelUpdate_Struct)); LevelUpdate_Struct* lu = (LevelUpdate_Struct*)outapp->pBuffer; lu->level = set_level; if(m_pp.level2 != 0) lu->level_old = m_pp.level2; else lu->level_old = level; level = set_level; if(IsRaidGrouped()) { Raid *r = this->GetRaid(); if(r){ r->UpdateLevel(GetName(), set_level); } } if(set_level > m_pp.level2) { if(m_pp.level2 == 0) m_pp.points += 5; else m_pp.points += (5 * (set_level - m_pp.level2)); m_pp.level2 = set_level; } if(set_level > m_pp.level) { parse->EventPlayer(EVENT_LEVEL_UP, this, "", 0); } m_pp.level = set_level; if (command){ m_pp.exp = GetEXPForLevel(set_level); Message(15, "Welcome to level %i!", set_level); lu->exp = 0; } else { float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) / ( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel())); lu->exp = (uint32)(330.0f * tmpxp); } QueuePacket(outapp); safe_delete(outapp); this->SendAppearancePacket(AT_WhoLevel, set_level); // who level change LogFile->write(EQEMuLog::Normal,"Setting Level for %s to %i", GetName(), set_level); CalcBonuses(); if(!RuleB(Character, HealOnLevel)) { int mhp = CalcMaxHP(); if(GetHP() > mhp) SetHP(mhp); } else { SetHP(CalcMaxHP()); // Why not, lets give them a free heal } DoTributeUpdate(); SendHPUpdate(); SetMana(CalcMaxMana()); UpdateWho(); if(GetMerc()) UpdateMercLevel(); Save(); }
//if itemlist is null, just send wear changes void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6) { if(item2 == nullptr) return; //make sure we are doing something... if(!itemlist && !wearchange) return; auto item = new ServerLootItem_Struct; #if EQDEBUG>=11 Log(Logs::General, Logs::None, "Adding drop to npc: %s, Item: %i", GetName(), item2->ID); #endif EQApplicationPacket* outapp = nullptr; WearChange_Struct* wc = nullptr; if(wearchange) { outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); wc = (WearChange_Struct*)outapp->pBuffer; wc->spawn_id = GetID(); wc->material=0; } item->item_id = item2->ID; item->charges = charges; item->aug_1 = aug1; item->aug_2 = aug2; item->aug_3 = aug3; item->aug_4 = aug4; item->aug_5 = aug5; item->aug_6 = aug6; item->attuned = 0; item->min_level = minlevel; item->max_level = maxlevel; item->equip_slot = EQEmu::inventory::slotInvalid; if (equipit) { uint8 eslot = 0xFF; char newid[20]; const EQEmu::ItemData* compitem = nullptr; bool found = false; // track if we found an empty slot we fit into int32 foundslot = -1; // for multi-slot items // Equip rules are as follows: // If the item has the NoPet flag set it will not be equipped. // An empty slot takes priority. The first empty one that an item can // fit into will be the one picked for the item. // AC is the primary choice for which item gets picked for a slot. // If AC is identical HP is considered next. // If an item can fit into multiple slots we'll pick the last one where // it is an improvement. if (!item2->NoPet) { for (int i = 0; !found && i < EQEmu::legacy::EQUIPMENT_SIZE; i++) { uint32 slots = (1 << i); if (item2->Slots & slots) { if(equipment[i]) { compitem = database.GetItem(equipment[i]); if (item2->AC > compitem->AC || (item2->AC == compitem->AC && item2->HP > compitem->HP)) { // item would be an upgrade // check if we're multi-slot, if yes then we have to keep // looking in case any of the other slots we can fit into are empty. if (item2->Slots != slots) { foundslot = i; } else { equipment[i] = item2->ID; foundslot = i; found = true; } } // end if ac } else { equipment[i] = item2->ID; foundslot = i; found = true; } } // end if (slots) } // end for } // end if NoPet // Possible slot was found but not selected. Pick it now. if (!found && foundslot >= 0) { equipment[foundslot] = item2->ID; found = true; } // @merth: IDFile size has been increased, this needs to change uint16 emat; if(item2->Material <= 0 || item2->Slots & (1 << EQEmu::inventory::slotPrimary | 1 << EQEmu::inventory::slotSecondary)) { memset(newid, 0, sizeof(newid)); for(int i=0;i<7;i++){ if (!isalpha(item2->IDFile[i])){ strn0cpy(newid, &item2->IDFile[i],6); i=8; } } emat = atoi(newid); } else { emat = item2->Material; } if (foundslot == EQEmu::inventory::slotPrimary) { if (item2->Proc.Effect != 0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); eslot = EQEmu::textures::weaponPrimary; if (item2->Damage > 0) { SendAddPlayerState(PlayerState::PrimaryWeaponEquipped); SetFacestab(true); } if (item2->IsType2HWeapon()) SetTwoHanderEquipped(true); } else if (foundslot == EQEmu::inventory::slotSecondary && (GetOwner() != nullptr || (CanThisClassDualWield() && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) && (item2->IsType1HWeapon() || item2->ItemType == EQEmu::item::ItemTypeShield)) { if (item2->Proc.Effect!=0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); eslot = EQEmu::textures::weaponSecondary; if (item2->Damage > 0) SendAddPlayerState(PlayerState::SecondaryWeaponEquipped); } else if (foundslot == EQEmu::inventory::slotHead) { eslot = EQEmu::textures::armorHead; } else if (foundslot == EQEmu::inventory::slotChest) { eslot = EQEmu::textures::armorChest; } else if (foundslot == EQEmu::inventory::slotArms) { eslot = EQEmu::textures::armorArms; } else if (foundslot == EQEmu::inventory::slotWrist1 || foundslot == EQEmu::inventory::slotWrist2) { eslot = EQEmu::textures::armorWrist; } else if (foundslot == EQEmu::inventory::slotHands) { eslot = EQEmu::textures::armorHands; } else if (foundslot == EQEmu::inventory::slotLegs) { eslot = EQEmu::textures::armorLegs; } else if (foundslot == EQEmu::inventory::slotFeet) { eslot = EQEmu::textures::armorFeet; } /* what was this about??? if (((npc->GetRace()==127) && (npc->CastToMob()->GetOwnerID()!=0)) && (item2->Slots==24576) || (item2->Slots==8192) || (item2->Slots==16384)){ npc->d_melee_texture2=atoi(newid); wc->wear_slot_id=8; if (item2->Material >0) wc->material=item2->Material; else wc->material=atoi(newid); npc->AC+=item2->AC; npc->STR+=item2->STR; npc->INT+=item2->INT; } */ //if we found an open slot it goes in... if(eslot != 0xFF) { if(wearchange) { wc->wear_slot_id = eslot; wc->material = emat; } } if (found) { CalcBonuses(); // This is less than ideal for bulk adding of items item->equip_slot = foundslot; } } if(itemlist != nullptr) itemlist->push_back(item); else safe_delete(item); if(wearchange && outapp) { entity_list.QueueClients(this, outapp); safe_delete(outapp); } UpdateEquipmentLight(); if (UpdateActiveLight()) SendAppearancePacket(AT_Light, GetActiveLightType()); }
void Client::DoTributeUpdate() { EQApplicationPacket outapp(OP_TributeUpdate, sizeof(TributeInfo_Struct)); TributeInfo_Struct *tis = (TributeInfo_Struct *) outapp.pBuffer; tis->active = m_pp.tribute_active ? 1 : 0; tis->tribute_master_id = tribute_master_id; //Dont know what this is for int r; for (r = 0; r < EQEmu::legacy::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; } else { tis->tributes[r] = TRIBUTE_NONE; tis->tiers[r] = 0; } } QueuePacket(&outapp); SendTributeTimer(); if(m_pp.tribute_active) { //send and equip tribute items... for (r = 0; r < EQEmu::legacy::TRIBUTE_SIZE; r++) { uint32 tid = m_pp.tributes[r].tribute; if(tid == TRIBUTE_NONE) { if (m_inv[EQEmu::legacy::TRIBUTE_BEGIN + r]) DeleteItemInInventory(EQEmu::legacy::TRIBUTE_BEGIN + r, 0, false); continue; } if(tribute_list.count(tid) != 1) { if (m_inv[EQEmu::legacy::TRIBUTE_BEGIN + r]) DeleteItemInInventory(EQEmu::legacy::TRIBUTE_BEGIN + r, 0, false); continue; } //sanity check if(m_pp.tributes[r].tier >= MAX_TRIBUTE_TIERS) { if (m_inv[EQEmu::legacy::TRIBUTE_BEGIN + r]) DeleteItemInInventory(EQEmu::legacy::TRIBUTE_BEGIN + r, 0, false); m_pp.tributes[r].tier = 0; continue; } TributeData &d = tribute_list[tid]; TributeLevel_Struct &tier = d.tiers[m_pp.tributes[r].tier]; uint32 item_id = tier.tribute_item_id; //summon the item for them const ItemInst* inst = database.CreateItem(item_id, 1); if(inst == nullptr) continue; PutItemInInventory(EQEmu::legacy::TRIBUTE_BEGIN + r, *inst, false); SendItemPacket(EQEmu::legacy::TRIBUTE_BEGIN + r, inst, ItemPacketTributeItem); safe_delete(inst); } } else { //unequip tribute items... for (r = 0; r < EQEmu::legacy::TRIBUTE_SIZE; r++) { if (m_inv[EQEmu::legacy::TRIBUTE_BEGIN + r]) DeleteItemInInventory(EQEmu::legacy::TRIBUTE_BEGIN + r, 0, false); } } CalcBonuses(); }
//if itemlist is null, just send wear changes void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange) { if(item2 == nullptr) return; //make sure we are doing something... if(!itemlist && !wearchange) return; ServerLootItem_Struct* item = new ServerLootItem_Struct; #if EQDEBUG>=11 LogFile->write(EQEMuLog::Debug, "Adding drop to npc: %s, Item: %i", GetName(), item2->ID); #endif EQApplicationPacket* outapp = nullptr; WearChange_Struct* wc = nullptr; if(wearchange) { outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); wc = (WearChange_Struct*)outapp->pBuffer; wc->spawn_id = GetID(); wc->material=0; } item->item_id = item2->ID; item->charges = charges; item->aug1 = 0; item->aug2 = 0; item->aug3 = 0; item->aug4 = 0; item->aug5 = 0; item->minlevel = minlevel; item->maxlevel = maxlevel; if (equipit) { uint8 eslot = 0xFF; char newid[20]; const Item_Struct* compitem = nullptr; bool found = false; // track if we found an empty slot we fit into int32 foundslot = -1; // for multi-slot items // Equip rules are as follows: // If the item has the NoPet flag set it will not be equipped. // An empty slot takes priority. The first empty one that an item can // fit into will be the one picked for the item. // AC is the primary choice for which item gets picked for a slot. // If AC is identical HP is considered next. // If an item can fit into multiple slots we'll pick the last one where // it is an improvement. if (!item2->NoPet) { for (int i=0; !found && i<MAX_WORN_INVENTORY; i++) { uint32 slots = (1 << i); if (item2->Slots & slots) { if(equipment[i]) { compitem = database.GetItem(equipment[i]); if (item2->AC > compitem->AC || (item2->AC == compitem->AC && item2->HP > compitem->HP)) { // item would be an upgrade // check if we're multi-slot, if yes then we have to keep // looking in case any of the other slots we can fit into are empty. if (item2->Slots != slots) { foundslot = i; } else { equipment[i] = item2->ID; foundslot = i; found = true; } } // end if ac } else { equipment[i] = item2->ID; foundslot = i; found = true; } } // end if (slots) } // end for } // end if NoPet // Possible slot was found but not selected. Pick it now. if (!found && foundslot >= 0) { equipment[foundslot] = item2->ID; found = true; } // @merth: IDFile size has been increased, this needs to change uint16 emat; if(item2->Material <= 0 || item2->Slots & (1 << SLOT_PRIMARY | 1 << SLOT_SECONDARY)) { memset(newid, 0, sizeof(newid)); for(int i=0;i<7;i++){ if (!isalpha(item2->IDFile[i])){ strn0cpy(newid, &item2->IDFile[i],6); i=8; } } emat = atoi(newid); } else { emat = item2->Material; } if (foundslot == SLOT_PRIMARY) { if (item2->Proc.Effect != 0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); eslot = MATERIAL_PRIMARY; } else if (foundslot == SLOT_SECONDARY && (GetOwner() != nullptr || (GetLevel() >= 13 && MakeRandomInt(0,99) < NPC_DW_CHANCE) || (item2->Damage==0)) && (item2->ItemType == ItemType1HS || item2->ItemType == ItemType1HB || item2->ItemType == ItemTypeShield || item2->ItemType == ItemTypePierce)) { if (item2->Proc.Effect!=0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); eslot = MATERIAL_SECONDARY; } else if (foundslot == SLOT_HEAD) { eslot = MATERIAL_HEAD; } else if (foundslot == SLOT_CHEST) { eslot = MATERIAL_CHEST; } else if (foundslot == SLOT_ARMS) { eslot = MATERIAL_ARMS; } else if (foundslot == SLOT_BRACER01 || foundslot == SLOT_BRACER02) { eslot = MATERIAL_BRACER; } else if (foundslot == SLOT_HANDS) { eslot = MATERIAL_HANDS; } else if (foundslot == SLOT_LEGS) { eslot = MATERIAL_LEGS; } else if (foundslot == SLOT_FEET) { eslot = MATERIAL_FEET; } /* what was this about??? if (((npc->GetRace()==127) && (npc->CastToMob()->GetOwnerID()!=0)) && (item2->Slots==24576) || (item2->Slots==8192) || (item2->Slots==16384)){ npc->d_meele_texture2=atoi(newid); wc->wear_slot_id=8; if (item2->Material >0) wc->material=item2->Material; else wc->material=atoi(newid); npc->AC+=item2->AC; npc->STR+=item2->STR; npc->INT+=item2->INT; } */ //if we found an open slot it goes in... if(eslot != 0xFF) { if(wearchange) { wc->wear_slot_id = eslot; wc->material = emat; } } if (found) { CalcBonuses(); // This is less than ideal for bulk adding of items } item->equipSlot = item2->Slots; } if(itemlist != nullptr) itemlist->push_back(item); else safe_delete(item); if(wearchange && outapp) { entity_list.QueueClients(this, outapp); safe_delete(outapp); } }
void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost) { int rank_id = rank->base_ability->first_rank_id; if(rank->base_ability->charges > 0) { uint32 charges = 0; GetAA(rank_id, &charges); if(charges > 0) { return; } SetAA(rank_id, rank->current_value, rank->base_ability->charges); } else { SetAA(rank_id, rank->current_value, 0); //if not max then send next aa if(rank->next) { SendAlternateAdvancementRank(rank->base_ability->id, rank->next->current_value); } } int cost = !ignore_cost ? rank->cost : 0; m_pp.aapoints -= cost ; SaveAA(); SendAlternateAdvancementPoints(); SendAlternateAdvancementStats(); if(rank->prev) { Message_StringID(15, AA_IMPROVE, std::to_string(rank->title_sid).c_str(), std::to_string(rank->prev->current_value).c_str(), std::to_string(cost).c_str(), cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()); /* QS: Player_Log_AA_Purchases */ if(RuleB(QueryServ, PlayerLogAAPurchases)) { std::string event_desc = StringFormat("Ranked AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, cost, GetZoneID(), GetInstanceID()); QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); } } else { Message_StringID(15, AA_GAIN_ABILITY, std::to_string(rank->title_sid).c_str(), std::to_string(cost).c_str(), cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()); /* QS: Player_Log_AA_Purchases */ if(RuleB(QueryServ, PlayerLogAAPurchases)) { std::string event_desc = StringFormat("Initial AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, cost, GetZoneID(), GetInstanceID()); QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); } } CalcBonuses(); if(cost > 0) { if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) NotifyNewTitlesAvailable(); } }
void Client::SetLevel(uint8 set_level, bool command) { if (GetEXPForLevel(set_level) == 0xFFFFFFFF) { Log.Out(Logs::General, Logs::Error, "Client::SetLevel() GetEXPForLevel(%i) = 0xFFFFFFFF", set_level); return; } EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelUpdate, sizeof(LevelUpdate_Struct)); LevelUpdate_Struct* lu = (LevelUpdate_Struct*)outapp->pBuffer; lu->level = set_level; if(m_pp.level2 != 0) lu->level_old = m_pp.level2; else lu->level_old = level; level = set_level; if(IsRaidGrouped()) { Raid *r = this->GetRaid(); if(r){ r->UpdateLevel(GetName(), set_level); } } if(set_level > m_pp.level2) { if(m_pp.level2 == 0) m_pp.points += 5; else m_pp.points += (5 * (set_level - m_pp.level2)); m_pp.level2 = set_level; } if(set_level > m_pp.level) { parse->EventPlayer(EVENT_LEVEL_UP, this, "", 0); /* QS: PlayerLogLevels */ if (RuleB(QueryServ, PlayerLogLevels)){ std::string event_desc = StringFormat("Leveled UP :: to Level:%i from Level:%i in zoneid:%i instid:%i", set_level, m_pp.level, this->GetZoneID(), this->GetInstanceID()); QServ->PlayerLogEvent(Player_Log_Levels, this->CharacterID(), event_desc); } } else if (set_level < m_pp.level){ /* QS: PlayerLogLevels */ if (RuleB(QueryServ, PlayerLogLevels)){ std::string event_desc = StringFormat("Leveled DOWN :: to Level:%i from Level:%i in zoneid:%i instid:%i", set_level, m_pp.level, this->GetZoneID(), this->GetInstanceID()); QServ->PlayerLogEvent(Player_Log_Levels, this->CharacterID(), event_desc); } } m_pp.level = set_level; if (command){ m_pp.exp = GetEXPForLevel(set_level); Message(CC_Yellow, "Welcome to level %i!", set_level); lu->exp = 0; } else { float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) / ( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel())); lu->exp = (uint32)(330.0f * tmpxp); } QueuePacket(outapp); safe_delete(outapp); this->SendAppearancePacket(AT_WhoLevel, set_level); // who level change Log.Out(Logs::General, Logs::Normal, "Setting Level for %s to %i", GetName(), set_level); CalcBonuses(); if(!RuleB(Character, HealOnLevel)) { int mhp = CalcMaxHP(); if(GetHP() > mhp) SetHP(mhp); } else { SetHP(CalcMaxHP()); // Why not, lets give them a free heal } if(!RuleB(Character, ManaOnLevel)) { int mp = CalcMaxMana(); if(GetMana() > mp) SetMana(mp); } else { SetMana(CalcMaxMana()); // Why not, lets give them a free heal } SendHPUpdate(); SendManaUpdate(); UpdateWho(); Save(); }
void Client::BuyAA(AA_Action* action) { Log.Out(Logs::Detail, Logs::AA, "Starting to buy AA %d", action->ability); //find the AA information from the database SendAA_Struct* aa2 = zone->FindAA(action->ability); if (!aa2) { //hunt for a lower level... int i; int a; for (i = 1; i<MAX_AA_ACTION_RANKS; i++){ a = action->ability - i; if (a <= 0) break; Log.Out(Logs::Detail, Logs::AA, "Could not find AA %d, trying potential parent %d", action->ability, a); aa2 = zone->FindAA(a); if (aa2 != nullptr) break; } } if (aa2 == nullptr) return; //invalid ability... if (aa2->special_category == 1 || aa2->special_category == 2) return; // Not purchasable progression style AAs if (aa2->special_category == 8 && aa2->cost == 0) return; // Not purchasable racial AAs(set a cost to make them purchasable) uint32 cur_level = GetAA(aa2->id); if ((aa2->id + cur_level) != action->ability) { //got invalid AA Log.Out(Logs::Detail, Logs::AA, "Unable to find or match AA %d (found %d + lvl %d)", action->ability, aa2->id, cur_level); return; } if (aa2->account_time_required) { if ((Timer::GetTimeSeconds() - account_creation) < aa2->account_time_required) { return; } } uint32 real_cost; std::map<uint32, AALevelCost_Struct>::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); if (RequiredLevel != AARequiredLevelAndCost.end()) { real_cost = RequiredLevel->second.Cost; } else real_cost = aa2->cost + (aa2->cost_inc * cur_level); if (m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { SetAA(aa2->id, cur_level + 1); Log.Out(Logs::Detail, Logs::AA, "Set AA %d to level %d", aa2->id, cur_level + 1); m_pp.aapoints -= real_cost; /* Do Player Profile rank calculations and set player profile */ SaveAA(); /* Save to Database to avoid having to write the whole AA array to the profile, only write changes*/ // database.SaveCharacterAA(this->CharacterID(), aa2->id, (cur_level + 1)); SendAATable(); /* We are building these messages ourself instead of using the stringID to work around patch discrepencies these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2 */ /* Initial purchase of an AA ability */ if (cur_level < 1){ Message(15, "You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1) ? "points" : "point"); /* QS: Player_Log_AA_Purchases */ if (RuleB(QueryServ, PlayerLogAAPurchases)){ std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); } } /* Ranked purchase of an AA ability */ else{ Message(15, "You have improved %s %d at a cost of %d ability %s.", aa2->name, cur_level + 1, real_cost, (real_cost > 1) ? "points" : "point"); /* QS: Player_Log_AA_Purchases */ if (RuleB(QueryServ, PlayerLogAAPurchases)){ std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); } } SendAAStats(); CalcBonuses(); //Bugs client, comment out for now until titles can be worked out. //if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) // NotifyNewTitlesAvailable(); } }
//o-------------------------------------------------------------- //| BuffFadeBySlot; Yeahlight, Nov 16, 2008 //o-------------------------------------------------------------- //| Adapted from EQEMU 7.0: Removes the buff in the supplied //| buff slot 'slot' //o-------------------------------------------------------------- void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) { bool debugFlag = true; if(slot < 0 || slot > BUFF_COUNT) return; if(!buffs[slot].spell || !buffs[slot].spell->IsValidSpell()) return; if(IsClient()) CastToClient()->MakeBuffFadePacket(buffs[slot].spell, slot); if(debugFlag && this->IsClient() && this->CastToClient()->GetDebugMe()) this->Message(LIGHTEN_BLUE, "Debug: Fading buff %d from slot %d", buffs[slot].spell->GetSpellID(), slot); for(int i = 0; i < EFFECT_COUNT; i++) { if(buffs[slot].spell->IsBlankSpellEffect(i)) continue; switch(buffs[slot].spell->GetSpellEffectID(i)) { case SE_WeaponProc: { SetBonusProcSpell(0); break; } case SE_Illusion: case SE_IllusionCopy: { SendIllusionPacket(GetBaseRace(), GetBaseGender(), GetTexture(), GetHelmTexture()); SendAppearancePacket(this->GetID(), SAT_Size, GetDefaultSize(), true); break; } case SE_Levitate: { SendAppearancePacket(this->GetID(), SAT_Levitate, 0, true); break; } case SE_Invisibility: { SetInvisible(false); break; } case SE_InvisVsUndead: { SetInvisibleUndead(false); break; } case SE_InvisVsAnimals: { SetInvisibleAnimal(false); break; } case SE_Silence: { break; } case SE_DivineAura: { SetInvulnerable(false); break; } case SE_Rune: { break; } case SE_AbsorbMagicAtt: { break; } case SE_Mez: { //Yeahlight: Unfreeze the PC's UI if(IsClient()) SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Sitting_To_Standing, true); this->mesmerized = false; break; } case SE_Charm: { Mob* charmer = entity_list.GetMob(this->GetOwnerID()); if(charmer && charmer->IsClient()) { char npcNameSuffix[] = "_CHARM00"; char npcNamePrefix[100] = ""; strcpy(npcNamePrefix, charmer->GetName()); strcat(npcNamePrefix, npcNameSuffix); Mob* charmPH = entity_list.GetMob(npcNamePrefix); if(charmPH && charmPH->IsNPC()) { charmPH->Depop(); } //Yeahlight: Check for _CHARM01 NPC, too npcNamePrefix[strlen(npcNamePrefix) - 1] = '1'; charmPH = entity_list.GetMob(npcNamePrefix); if(charmPH && charmPH->IsNPC()) { charmPH->Depop(); } //Yeahlight: Generate hate for towards the charmer if the charmer is not FD'ed if(this->IsNPC() && charmer->IsClient() && !charmer->CastToClient()->GetFeigned()) { CastToNPC()->AddToHateList(charmer, 0, GetSpellHate(SE_Charm, this->GetLevel(), false)); } } //Yeahlight: Unfreeze the PC's UI if(IsClient()) { SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Sitting_To_Standing, true); CastToClient()->SetCharmed(false); CastToClient()->charmPositionUpdate_timer->Disable(); } //Yeahlight: Deflag the NPC as charmed else if(IsNPC()) { CastToNPC()->SetCharmed(false); } this->SetOwnerID(0, false); break; } case SE_Root: { break; } case SE_Fear: { //Yeahlight: Unfreeze the PC's UI if(IsClient()) { CastToClient()->SetFeared(false); SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Sitting_To_Standing, true); } else if(IsNPC()) { CastToNPC()->SetFeared(false); CastToNPC()->SetOnFearPath(false); } break; } case SE_SpinTarget: { //Yeahlight: Unfreeze the PC's UI if(IsClient()) SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Sitting_To_Standing, true); break; } case SE_EyeOfZomm: { //Yeahlight: Clear the eye of zomm pointer and depop the eye if(IsClient() && CastToClient()->myEyeOfZomm) { CastToClient()->myEyeOfZomm->Depop(); CastToClient()->myEyeOfZomm = NULL; } break; } case SE_DeathSave: { //Yeahlight: Clear the death save chance if(IsClient()) CastToClient()->SetDeathSave(0); break; } case SE_VoiceGraft: { //Yeahlight: Drop the voice grafting flag from the client if(GetOwner() && GetOwner()->IsClient()) { GetOwner()->CastToClient()->SetVoiceGrafting(false); } break; } case SE_SeeInvis: { //Yeahlight: Mob may no longer see through invis SetCanSeeThroughInvis(false); break; } } } buffs[slot].spell = NULL; if(iRecalcBonuses) CalcBonuses(true, true); }