Esempio n. 1
0
/*
	Ищем свободный слот под способность.
	Возвращает число от 0 до MAX_ACC_FEAT-1 - номер слота,
	0, если способность врожденная и -1 если слотов не найдено.
	НЕ проверяет доступность врожденной способности на данном уровне.
*/
bool find_feat_slot(CHAR_DATA *ch, int feat)
{
	int i, lowfeat, hifeat;
	//если способность врожденная - ее всегда можно получить
	if (feat_info[feat].natural_classfeat[(int) GET_CLASS(ch)][(int) GET_KIN(ch)] || PlayerRace::FeatureCheck(GET_KIN(ch),GET_RACE(ch),feat))
		return TRUE;
    //сколько у нас вообще способностей, у которых слот меньше требуемого, и сколько - тех, у которых больше или равно?
    lowfeat = 0;
    hifeat = 0;
	for (i = 1; i < MAX_FEATS; i++)
	{
        if (feat_info[i].natural_classfeat[(int) GET_CLASS(ch)][(int) GET_KIN(ch)] || PlayerRace::FeatureCheck(GET_KIN(ch),GET_RACE(ch),i))
            continue;
	    if (HAVE_FEAT(ch,i) && (FEAT_SLOT(ch,i) < FEAT_SLOT(ch,feat)))
            lowfeat++;
        if (HAVE_FEAT(ch,i) && (FEAT_SLOT(ch,i) >= FEAT_SLOT(ch,feat)))
            hifeat++;
	}

//из имеющегося количества слотов нужно вычесть:
//число высоких слотов, занятых низкоуровневыми способностями,
//с учтом, что низкоуровневые могут и не занимать слотов выше им положенных,
//а также собственно число слотов, занятых высокоуровневыми способностями
	if (NUM_LEV_FEAT(ch)-FEAT_SLOT(ch, feat)-hifeat-MAX(0, lowfeat-FEAT_SLOT(ch, feat)) > 0)
        return TRUE;

//oops.. слотов нет
	return FALSE;
}
Esempio n. 2
0
/* Может ли персонаж использовать способность? Проверка по уровню, ремортам, параметрам персонажа, требованиям. */
bool can_use_feat(CHAR_DATA *ch, int feat)
{
	if (!HAVE_FEAT(ch, feat))
		return FALSE;
	if (IS_NPC(ch))
		return TRUE;
	if (NUM_LEV_FEAT(ch) < feat_info[feat].slot[(int) GET_CLASS(ch)][(int) GET_KIN(ch)])
		return FALSE;
	if (GET_REMORT(ch) < feat_info[feat].min_remort[(int) GET_CLASS(ch)][(int) GET_KIN(ch)])
		return FALSE;

	switch (feat)
	{
	case WEAPON_FINESSE_FEAT:
		if (GET_REAL_DEX(ch) < GET_REAL_STR(ch) || GET_REAL_DEX(ch) < 18)
			return FALSE;
		break;
	case PARRY_ARROW_FEAT:
		if (GET_REAL_DEX(ch) < 16)
			return FALSE;
		break;
	case POWER_ATTACK_FEAT:
		if (GET_REAL_STR(ch) < 20)
			return FALSE;
		break;
	case GREAT_POWER_ATTACK_FEAT:
		if (GET_REAL_STR(ch) < 22)
			return FALSE;
		break;
	case AIMING_ATTACK_FEAT:
		if (GET_REAL_DEX(ch) < 16)
			return FALSE;
		break;
	case GREAT_AIMING_ATTACK_FEAT:
		if (GET_REAL_DEX(ch) < 18)
			return FALSE;
		break;
	case DOUBLESHOT_FEAT:
		if (ch->get_skill(SKILL_BOWS) < 40)
			return FALSE;
		break;
	}
	return TRUE;
}
Esempio n. 3
0
/**
 * Выставление чару расовых способностей.
 */
void set_race_feats(CHAR_DATA *ch)
{
	std::vector<int> feat_list = PlayerRace::GetRaceFeatures((int)GET_KIN(ch),(int)GET_RACE(ch));
	for (std::vector<int>::iterator i = feat_list.begin(),
		iend = feat_list.end(); i != iend; ++i)
	{
		if (can_get_feat(ch, *i))
		{
			SET_FEAT(ch, *i);
		}
	}
}
Esempio n. 4
0
void handle_recall_spells(CHAR_DATA* ch)
{
	AFFECT_DATA* aff = NULL;
	for(AFFECT_DATA* af = ch->affected; af; af = af->next)
		if (af->type == SPELL_RECALL_SPELLS)
		{
			aff = af;
			break;
		}
	if (!aff) return;
	//максимальный доступный чару круг
	unsigned max_slot = get_max_slot(ch);
	//обрабатываем только каждые RECALL_SPELLS_INTERVAL секунд
	int secs_left = (SECS_PER_PLAYER_AFFECT*aff->duration)/SECS_PER_MUD_HOUR -SECS_PER_PLAYER_AFFECT;
	if (secs_left / RECALL_SPELLS_INTERVAL < max_slot -aff->modifier || secs_left <= 2)
	{
		int slot_to_restore = aff->modifier++;

		bool found_spells = false;
		struct spell_mem_queue_item *next = NULL, *prev=NULL, *i = ch->MemQueue.queue;
		while (i)
		{
			next = i->link;
			if (spell_info[i->spellnum].slot_forc[(int) GET_CLASS(ch)][(int) GET_KIN(ch)] == slot_to_restore)
			{
				if (!found_spells)
				{
					send_to_char("Ваша голова прояснилась, в памяти всплыло несколько новых заклинаний.\r\n", ch);
					found_spells = true;
				}
				if (prev) prev->link = next;
				if (i == ch->MemQueue.queue)
				{
					 ch->MemQueue.queue = next;
					GET_MEM_COMPLETED(ch) = 0;
				}
				GET_MEM_TOTAL(ch) = MAX(0, GET_MEM_TOTAL(ch) - mag_manacost(ch, i->spellnum));
				sprintf(buf, "Вы вспомнили заклинание \"%s%s%s\".\r\n",
						CCICYN(ch, C_NRM), spell_info[i->spellnum].name, CCNRM(ch, C_NRM));
				send_to_char(buf, ch);
				GET_SPELL_MEM(ch, i->spellnum)++;
				free(i);
			} else prev = i;
			i = next;
		}
	}
}
Esempio n. 5
0
/* Может ли персонаж изучить эту способность? */
bool can_get_feat(CHAR_DATA *ch, int feat)
{
	int i, count = 0;
	if (feat <= 0 || feat >= MAX_FEATS)
	{
		sprintf(buf, "Неверный номер способности (feat=%d, ch=%s) передан в features::can_get_feat!",
			feat, ch->get_name());
		mudlog(buf, BRF, LVL_IMMORT, SYSLOG, TRUE);
		return FALSE;
	}
	/* Доступность по классу, реморту. */
	if ((!feat_info[feat].classknow[(int) GET_CLASS(ch)][(int) GET_KIN(ch)] && !PlayerRace::FeatureCheck(GET_KIN(ch),GET_RACE(ch),feat)) ||
			(GET_REMORT(ch) < feat_info[feat].min_remort[(int) GET_CLASS(ch)][(int) GET_KIN(ch)]))
		return FALSE;

	/* Наличие свободных слотов */
	if (!find_feat_slot(ch, feat))
		return FALSE;

	/* Специальные требования для изучения */
	switch (feat)
	{
	case PARRY_ARROW_FEAT:
		if (!ch->get_skill(SKILL_MULTYPARRY) && !ch->get_skill(SKILL_PARRY))
			return FALSE;
		break;
	case CONNOISEUR_FEAT:
		if (!ch->get_skill(SKILL_IDENTIFY))
			return FALSE;
		break;
	case EXORCIST_FEAT:
		if (!ch->get_skill(SKILL_TURN_UNDEAD))
			return FALSE;
		break;
	case HEALER_FEAT:
		if (!ch->get_skill(SKILL_AID))
			return FALSE;
		break;
	case STEALTHY_FEAT:
		if (!ch->get_skill(SKILL_HIDE) && !ch->get_skill(SKILL_SNEAK) && !ch->get_skill(SKILL_CAMOUFLAGE))
			return FALSE;
		break;
	case TRACKER_FEAT:
		if (!ch->get_skill(SKILL_TRACK) && !ch->get_skill(SKILL_SENSE))
			return FALSE;
		break;
	case PUNCH_MASTER_FEAT:
	case CLUBS_MASTER_FEAT:
	case AXES_MASTER_FEAT:
	case LONGS_MASTER_FEAT:
	case SHORTS_MASTER_FEAT:
	case NONSTANDART_MASTER_FEAT:
	case BOTHHANDS_MASTER_FEAT:
	case PICK_MASTER_FEAT:
	case SPADES_MASTER_FEAT:
	case BOWS_MASTER_FEAT:
		if (!HAVE_FEAT(ch, (ubyte) feat_info[feat].affected[1].location))
			return FALSE;
		for (i = PUNCH_MASTER_FEAT; i <= BOWS_MASTER_FEAT; i++)
			if (HAVE_FEAT(ch, i))
				count++;
		if (count >= 1+GET_REMORT(ch)/7)
			return FALSE;
		break;
	case SPIRIT_WARRIOR_FEAT:
		if (!HAVE_FEAT(ch, GREAT_FORTITUDE_FEAT))
			return FALSE;
		break;
	case NIMBLE_FINGERS_FEAT:
		if (!ch->get_skill(SKILL_STEAL) && !ch->get_skill(SKILL_PICK_LOCK))
			return FALSE;
		break;
	case GREAT_POWER_ATTACK_FEAT:
		if (!HAVE_FEAT(ch, POWER_ATTACK_FEAT))
			return FALSE;
		break;
	case PUNCH_FOCUS_FEAT:
	case CLUB_FOCUS_FEAT:
	case AXES_FOCUS_FEAT:
	case LONGS_FOCUS_FEAT:
	case SHORTS_FOCUS_FEAT:
	case NONSTANDART_FOCUS_FEAT:
	case BOTHHANDS_FOCUS_FEAT:
	case PICK_FOCUS_FEAT:
	case SPADES_FOCUS_FEAT:
	case BOWS_FOCUS_FEAT:
		if (!ch->get_skill((ubyte) feat_info[feat].affected[0].location))
			return FALSE;
		for (i = PUNCH_FOCUS_FEAT; i <= BOWS_FOCUS_FEAT; i++)
			if (HAVE_FEAT(ch, i))
				count++;
		if (count >= 2+GET_REMORT(ch)/6)
			return FALSE;
		break;
	case GREAT_AIMING_ATTACK_FEAT:
		if (!HAVE_FEAT(ch, AIMING_ATTACK_FEAT))
			return FALSE;
		break;
	case DOUBLESHOT_FEAT:
		if (!HAVE_FEAT(ch, BOWS_FOCUS_FEAT) || ch->get_skill(SKILL_BOWS) < 40)
			return FALSE;
		break;
	case RUNE_USER_FEAT:
		if (!HAVE_FEAT(ch, RUNE_NEWBIE_FEAT))
			return FALSE;
		break;
	case RUNE_MASTER_FEAT:
		if (!HAVE_FEAT(ch, RUNE_USER_FEAT))
			return FALSE;
		break;
	case RUNE_ULTIMATE_FEAT:
		if (!HAVE_FEAT(ch, RUNE_MASTER_FEAT))
			return FALSE;
		break;
	}
	return TRUE;
}