コード例 #1
0
ファイル: exp.cpp プロジェクト: josheb/emu_dc
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();
}
コード例 #2
0
ファイル: loottables.cpp プロジェクト: j883376/Server
//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());
}
コード例 #3
0
ファイル: tribute.cpp プロジェクト: 9thsector/Server
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();
}
コード例 #4
0
ファイル: loottables.cpp プロジェクト: Derision/Server
//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);
	}
}
コード例 #5
0
ファイル: aa.cpp プロジェクト: af4t/Server
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();
	}
}
コード例 #6
0
ファイル: exp.cpp プロジェクト: regneq/Server
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();
}
コード例 #7
0
ファイル: aa.cpp プロジェクト: vingiarrusso/Server
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();
	}
}
コード例 #8
0
ファイル: SpellEffects.cpp プロジェクト: cavedude00/eqmacemu
//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);
}