Exemplo n.º 1
0
Mob* Mob::GetPet() {
	if(GetPetID() == 0)
		return(NULL);
	
	Mob* tmp = entity_list.GetMob(GetPetID());
	if(tmp == NULL) {
		SetPetID(0);
		return(NULL);
	}
	
	if(tmp->GetOwnerID() != GetID()) {
		SetPetID(0);
		return(NULL);
	}
	
	return(tmp);
}
Exemplo n.º 2
0
void Client::ProcessMovePC(uint32 zoneID, uint32 instance_id, float x, float y, float z, float heading, uint8 ignorerestrictions, ZoneMode zm)
{
	// From what I have read, dragged corpses should stay with the player for Intra-zone summons etc, but we can implement that later.
	ClearDraggedCorpses();

	if(zoneID == 0)
		zoneID = zone->GetZoneID();

	if(zoneID == zone->GetZoneID() && instance_id == zone->GetInstanceID()) {
		// TODO: Determine if this condition is necessary.
		if(IsAIControlled()) {
			GMMove(x, y, z);
			return;
		}

		if(GetPetID() != 0) {
			//if they have a pet and they are staying in zone, move with them
			Mob *p = GetPet();
			if(p != nullptr){
				p->SetPetOrder(SPO_Follow);
				p->GMMove(x+15, y, z);	//so it dosent have to run across the map.
			}
		}
	}

	switch(zm) {
		case GateToBindPoint:
			ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm);
			break;
		case EvacToSafeCoords:
		case ZoneToSafeCoords:
			ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm);
			break;
		case GMSummon:
			Message(15, "You have been summoned by a GM!");
			ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm);
			break;
		case ZoneToBindPoint:
			ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm);
			break;
		case ZoneSolicited:
			ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm);
			break;
		case SummonPC:
			Message(15, "You have been summoned!");
			ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm);
			break;
		case Rewind:
			Message(15, "Rewinding to previous location.");
			ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm);
			break;
		default:
			LogFile->write(EQEMuLog::Error, "Client::ProcessMovePC received a reguest to perform an unsupported client zone operation.");
			break;
	}
}
Exemplo n.º 3
0
Arquivo: aa.cpp Projeto: af4t/Server
void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
	AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id);
	if(!rank) {
		return;
	}

	AA::Ability *ability = rank->base_ability;
	if(!ability) {
		return;
	}

	if(!IsValidSpell(rank->spell)) {
		return;
	}

	if(!CanUseAlternateAdvancementRank(rank)) {
		return;
	}

	//make sure it is not a passive
	if(!rank->effects.empty()) {
		return;
	}

	uint32 charges = 0;
	// We don't have the AA
	if (!GetAA(rank_id, &charges))
		return;

	//if expendable make sure we have charges
	if(ability->charges > 0 && charges < 1)
		return;

	//check cooldown
	if(!p_timers.Expired(&database, rank->spell_type + pTimerAAStart, false)) {
		uint32 aaremain = p_timers.GetRemainingTime(rank->spell_type + pTimerAAStart);
		uint32 aaremain_hr = aaremain / (60 * 60);
		uint32 aaremain_min = (aaremain / 60) % 60;
		uint32 aaremain_sec = aaremain % 60;

		if(aaremain_hr >= 1) {
			Message(13, "You can use this ability again in %u hour(s) %u minute(s) %u seconds",
			aaremain_hr, aaremain_min, aaremain_sec);
		}
		else {
			Message(13, "You can use this ability again in %u minute(s) %u seconds",
			aaremain_min, aaremain_sec);
		}

		return;
	}

	//calculate cooldown
	int cooldown = rank->recast_time - GetAlternateAdvancementCooldownReduction(rank);
	if(cooldown < 0) {
		cooldown = 0;
	}

	if (!IsCastWhileInvis(rank->spell))
		CommonBreakInvisible();

	if (spells[rank->spell].sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) {
		Message_StringID(MT_SpellFailure, SNEAK_RESTRICT);
		return;
	}
	//
	// Modern clients don't require pet targeted for AA casts that are ST_Pet
	if (spells[rank->spell].targettype == ST_Pet || spells[rank->spell].targettype == ST_SummonedPet)
		target_id = GetPetID();

	// extra handling for cast_not_standing spells
	if (!spells[rank->spell].cast_not_standing) {
		if (GetAppearance() == eaSitting) // we need to stand!
			SetAppearance(eaStanding, false);

		if (GetAppearance() != eaStanding) {
			Message_StringID(MT_SpellFailure, STAND_TO_CAST);
			return;
		}
	}

	// Bards can cast instant cast AAs while they are casting another song
	if(spells[rank->spell].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) {
		if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::spells::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) {
			return;
		}
		ExpendAlternateAdvancementCharge(ability->id);
	} else {
		if(!CastSpell(rank->spell, target_id, EQEmu::spells::CastingSlot::AltAbility, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) {
			return;
		}
	}

	CastToClient()->GetPTimers().Start(rank->spell_type + pTimerAAStart, cooldown);
	SendAlternateAdvancementTimer(rank->spell_type, 0, 0);
}
Exemplo n.º 4
0
void Client::ActivateAA(aaID activate){
	if (activate < 0 || activate >= aaHighestID)
		return;
	if (IsStunned() || IsFeared() || IsMezzed() || IsSilenced() || IsPet() || IsSitting() || GetFeigned())
		return;

	int AATimerID = GetAATimerID(activate);

	SendAA_Struct* aa2 = nullptr;
	aaID aaid = activate;
	uint8 activate_val = GetAA(activate);
	//this wasn't taking into acct multi tiered act talents before...
	if (activate_val == 0){
		aa2 = zone->FindAA(activate);
		if (!aa2){
			int i;
			int a;
			for (i = 1; i<MAX_AA_ACTION_RANKS; i++){
				a = activate - i;
				if (a <= 0)
					break;

				aa2 = zone->FindAA(a);
				if (aa2 != nullptr)
					break;
			}
		}
		if (aa2){
			aaid = (aaID)aa2->id;
			activate_val = GetAA(aa2->id);
		}
	}

	if (activate_val == 0){
		return;
	}

	if (aa2)
	{
		if (aa2->account_time_required)
		{
			if ((Timer::GetTimeSeconds() + account_creation) < aa2->account_time_required)
			{
				return;
			}
		}
	}

	if (!p_timers.Expired(&database, AATimerID + pTimerAAStart))
	{
		uint32 aaremain = p_timers.GetRemainingTime(AATimerID + pTimerAAStart);
		uint32 aaremain_hr = aaremain / (60 * 60);
		uint32 aaremain_min = (aaremain / 60) % 60;
		uint32 aaremain_sec = aaremain % 60;

		if (aa2) {
			if (aaremain_hr >= 1)	//1 hour or more
				Message(CC_Red, "You can use the ability %s again in %u hour(s) %u minute(s) %u seconds",
				aa2->name, aaremain_hr, aaremain_min, aaremain_sec);
			else	//less than an hour
				Message(CC_Red, "You can use the ability %s again in %u minute(s) %u seconds",
				aa2->name, aaremain_min, aaremain_sec);
		}
		else {
			if (aaremain_hr >= 1)	//1 hour or more
				Message(CC_Red, "You can use this ability again in %u hour(s) %u minute(s) %u seconds",
				aaremain_hr, aaremain_min, aaremain_sec);
			else	//less than an hour
				Message(CC_Red, "You can use this ability again in %u minute(s) %u seconds",
				aaremain_min, aaremain_sec);
		}
		return;
	}

	if (activate_val > MAX_AA_ACTION_RANKS)
		activate_val = MAX_AA_ACTION_RANKS;
	activate_val--;		//to get array index.

	//get our current node, now that the indices are well bounded
	const AA_DBAction *caa = &AA_Actions[aaid][activate_val];

	if ((aaid == aaImprovedHarmTouch || aaid == aaLeechTouch) && !p_timers.Expired(&database, pTimerHarmTouch)){
		Message(CC_Red, "Ability recovery time not yet met.");
		return;
	}

	//everything should be configured out now

	uint16 target_id = 0;

	//figure out our target
	switch (caa->target) {
	case aaTargetUser:
	case aaTargetGroup:
		target_id = GetID();
		break;
	case aaTargetCurrent:
	case aaTargetCurrentGroup:
		if (GetTarget() == nullptr) {
			Message_StringID(MT_DefaultText, AA_NO_TARGET);	//You must first select a target for this ability!
			p_timers.Clear(&database, AATimerID + pTimerAAStart);
			return;
		}
		target_id = GetTarget()->GetID();
		break;
	case aaTargetPet:
		if (GetPet() == nullptr) {
			Message(0, "A pet is required for this skill.");
			return;
		}
		target_id = GetPetID();
		break;
	}

	//handle non-spell action
	if (caa->action != aaActionNone) {
		if (caa->mana_cost > 0) {
			if (GetMana() < caa->mana_cost) {
				Message_StringID(CC_Red, INSUFFICIENT_MANA);
				return;
			}
			SetMana(GetMana() - caa->mana_cost);
		}
		if (caa->reuse_time > 0)
		{
			uint32 timer_base = CalcAAReuseTimer(caa);
			if (activate == aaImprovedHarmTouch || activate == aaLeechTouch)
			{
				p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime);
			}
			p_timers.Start(AATimerID + pTimerAAStart, timer_base);
			SendAATimer(activate, static_cast<uint32>(time(nullptr)), static_cast<uint32>(time(nullptr)));
		}
		HandleAAAction(aaid);
	}

	//cast the spell, if we have one
	if (caa->spell_id > 0 && caa->spell_id < SPDAT_RECORDS) {

		if (caa->reuse_time > 0)
		{
			uint32 timer_base = CalcAAReuseTimer(caa);
			SendAATimer(activate, static_cast<uint32>(time(nullptr)), static_cast<uint32>(time(nullptr)));
			p_timers.Start(AATimerID + pTimerAAStart, timer_base);
			if (activate == aaImprovedHarmTouch || activate == aaLeechTouch)
			{
				p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime);
			}
			// Bards can cast instant cast AAs while they are casting another song
			if (spells[caa->spell_id].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) {
				if (!SpellFinished(caa->spell_id, entity_list.GetMob(target_id), 10, -1, -1, spells[caa->spell_id].ResistDiff, false)) {
					//Reset on failed cast
					SendAATimer(activate, 0, 0xFFFFFF);
					Message_StringID(CC_Yellow, ABILITY_FAILED);
					p_timers.Clear(&database, AATimerID + pTimerAAStart);
					return;
				}
			}
			else {
				if (!CastSpell(caa->spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) {
					//Reset on failed cast
					SendAATimer(activate, 0, 0xFFFFFF);
					Message_StringID(CC_Yellow, ABILITY_FAILED);
					p_timers.Clear(&database, AATimerID + pTimerAAStart);
					return;
				}
			}
		}
		else
		{
			if (!CastSpell(caa->spell_id, target_id))
				return;
		}
	}
}
Exemplo n.º 5
0
void Client::HandleAAAction(aaID activate) {
	if (activate < 0 || activate >= aaHighestID)
		return;

	uint8 activate_val = GetAA(activate);

	if (activate_val == 0)
		return;

	if (activate_val > MAX_AA_ACTION_RANKS)
		activate_val = MAX_AA_ACTION_RANKS;
	activate_val--;		//to get array index.

	//get our current node, now that the indices are well bounded
	const AA_DBAction *caa = &AA_Actions[activate][activate_val];

	uint16 timer_id = 0;
	uint16 timer_duration = caa->duration;
	aaTargetType target = aaTargetUser;

	uint16 spell_id = SPELL_UNKNOWN;	//gets cast at the end if not still unknown

	switch (caa->action) {
	case aaActionAETaunt:
		entity_list.AETaunt(this);
		break;

	case aaActionMassBuff:
		EnableAAEffect(aaEffectMassGroupBuff, 3600);
		Message_StringID(MT_Disciplines, MGB_STRING);	//The next group buff you cast will hit all targets in range.
		break;

	case aaActionFlamingArrows:
		//toggle it
		if (CheckAAEffect(aaEffectFlamingArrows))
			EnableAAEffect(aaEffectFlamingArrows);
		else
			DisableAAEffect(aaEffectFlamingArrows);
		break;

	case aaActionFrostArrows:
		if (CheckAAEffect(aaEffectFrostArrows))
			EnableAAEffect(aaEffectFrostArrows);
		else
			DisableAAEffect(aaEffectFrostArrows);
		break;

	case aaActionRampage:
		EnableAAEffect(aaEffectRampage, 10);
		break;

	case aaActionSharedHealth:
		if (CheckAAEffect(aaEffectSharedHealth))
			EnableAAEffect(aaEffectSharedHealth);
		else
			DisableAAEffect(aaEffectSharedHealth);
		break;

	case aaActionCelestialRegen: {
		//special because spell_id depends on a different AA
		switch (GetAA(aaCelestialRenewal)) {
		case 1:
			spell_id = 3250;
			break;
		case 2:
			spell_id = 3251;
			break;
		default:
			spell_id = 2740;
			break;
		}
		target = aaTargetCurrent;
		break;
	}

	case aaActionDireCharm: {
		//special because spell_id depends on class
		switch (GetClass())
		{
		case DRUID:
			spell_id = 2760;	//2644?
			break;
		case NECROMANCER:
			spell_id = 2759;	//2643?
			break;
		case ENCHANTER:
			spell_id = 2761;	//2642?
			break;
		}
		target = aaTargetCurrent;
		break;
	}

	case aaActionImprovedFamiliar: {
		//Spell IDs might be wrong...
		if (GetAA(aaAllegiantFamiliar))
			spell_id = 3264;	//1994?
		else
			spell_id = 2758;	//2155?
		break;
	}

	case aaActionActOfValor:
		if (GetTarget() != nullptr) {
			int curhp = GetTarget()->GetHP();
			target = aaTargetCurrent;
			GetTarget()->HealDamage(curhp, this);
			Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand);
		}
		break;

	case aaActionSuspendedMinion:
		if (GetPet()) {
			target = aaTargetPet;
			switch (GetAA(aaSuspendedMinion)) {
			case 1:
				spell_id = 3248;
				break;
			case 2:
				spell_id = 3249;
				break;
			}
			//do we really need to cast a spell?

			Message(0, "You call your pet to your side.");
			GetPet()->WipeHateList();
			GetPet()->GMMove(GetX(), GetY(), GetZ());
			if (activate_val > 1)
				entity_list.ClearFeignAggro(GetPet());
		}
		else {
			Message(0, "You have no pet to call.");
		}
		break;

	case aaActionProjectIllusion:
		EnableAAEffect(aaEffectProjectIllusion, 3600);
		Message(10, "The power of your next illusion spell will flow to your grouped target in your place.");
		break;


	case aaActionEscape:
		Escape();
		break;

		// Don't think this code is used any longer for Bestial Alignment as the aa.has a spell_id and no nonspell_action.
	case aaActionBeastialAlignment:
		switch (GetBaseRace()) {
		case BARBARIAN:
			spell_id = AA_Choose3(activate_val, 4521, 4522, 4523);
			break;
		case TROLL:
			spell_id = AA_Choose3(activate_val, 4524, 4525, 4526);
			break;
		case OGRE:
			spell_id = AA_Choose3(activate_val, 4527, 4527, 4529);
			break;
		case IKSAR:
			spell_id = AA_Choose3(activate_val, 4530, 4531, 4532);
			break;
		case VAHSHIR:
			spell_id = AA_Choose3(activate_val, 4533, 4534, 4535);
			break;
		}

	case aaActionLeechTouch:
		target = aaTargetCurrent;
		spell_id = SPELL_HARM_TOUCH2;
		EnableAAEffect(aaEffectLeechTouch, 1000);
		break;

	case aaActionFadingMemories:
		// Do nothing since spell effect works correctly, but mana isn't used.
		break;

		default:
			Log.Out(Logs::General, Logs::Error, "Unknown AA nonspell action type %d", caa->action);
			return;
	}


	uint16 target_id = 0;
	//figure out our target
	switch (target) {
	case aaTargetUser:
	case aaTargetGroup:
		target_id = GetID();
		break;
	case aaTargetCurrent:
	case aaTargetCurrentGroup:
		if (GetTarget() == nullptr) {
			Message_StringID(MT_DefaultText, AA_NO_TARGET);	//You must first select a target for this ability!
			p_timers.Clear(&database, timer_id + pTimerAAEffectStart);
			return;
		}
		target_id = GetTarget()->GetID();
		break;
	case aaTargetPet:
		if (GetPet() == nullptr) {
			Message(0, "A pet is required for this skill.");
			return;
		}
		target_id = GetPetID();
		break;
	}

	//cast the spell, if we have one
	if (IsValidSpell(spell_id)) {
		int aatid = GetAATimerID(activate);
		if (!CastSpell(spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, pTimerAAStart + aatid, CalcAAReuseTimer(caa), 1)) {
			SendAATimer(activate, 0, 0xFFFFFF);
			Message_StringID(CC_Yellow, ABILITY_FAILED);
			p_timers.Clear(&database, pTimerAAStart + aatid);
			return;
		}
	}

	//handle the duration timer if we have one.
	if (timer_id > 0 && timer_duration > 0) {
		p_timers.Start(pTimerAAEffectStart + timer_id, timer_duration);
	}
}