Пример #1
0
ReturnValue Combat::canDoCombat(const CreatureP& caster, Tile* tile, bool isAggressive)
{
	if(tile->hasProperty(BLOCKPROJECTILE) || tile->floorChange() || tile->getTeleporter())
		return RET_NOTENOUGHROOM;

	if(caster)
	{
		bool success = true;
		CreatureEventList combatAreaEvents = caster->getCreatureEvents(CREATURE_EVENT_COMBAT_AREA);
		for(CreatureEventList::iterator it = combatAreaEvents.begin(); it != combatAreaEvents.end(); ++it)
		{
			if(!(*it)->executeCombatArea(caster, tile, isAggressive) && success)
				success = false;
		}

		if(!success)
			return RET_NOTPOSSIBLE;

		if(caster->getPosition().z < tile->getPosition().z)
			return RET_FIRSTGODOWNSTAIRS;

		if(caster->getPosition().z > tile->getPosition().z)
			return RET_FIRSTGOUPSTAIRS;

		if(!isAggressive)
			return RET_NOERROR;

		const Player* player = caster->getPlayer();
		if(player && player->hasFlag(PlayerFlag_IgnoreProtectionZone))
			return RET_NOERROR;
	}

	return isAggressive && tile->hasFlag(TILESTATE_PROTECTIONZONE) ?
		RET_ACTIONNOTPERMITTEDINPROTECTIONZONE : RET_NOERROR;
}
Пример #2
0
bool ChatChannel::addUser(Player* player)
{
	if(m_users.find(player->getID()) != m_users.end())
		return false;

	ChatChannel* channel = g_chat.getChannel(player, m_id);
	if(!channel)
	{
		#ifdef __DEBUG_CHAT__
		std::clog << "ChatChannel::addUser - failed retrieving channel." << std::endl;
		#endif
		return false;
	}

	if(m_id == CHANNEL_PARTY || m_id == CHANNEL_GUILD || m_id == CHANNEL_PRIVATE)
	{
		Player* tmpPlayer = NULL;
		for(UsersMap::iterator cit = m_users.begin(); cit != m_users.end(); ++cit)
		{
			if((tmpPlayer = cit->second->getPlayer()))
				tmpPlayer->sendChannelEvent(m_id, player->getName(), CHANNELEVENT_JOIN);
		}
	}

	m_users[player->getID()] = player;
	CreatureEventList joinEvents = player->getCreatureEvents(CREATURE_EVENT_CHANNEL_JOIN);
	for(CreatureEventList::iterator it = joinEvents.begin(); it != joinEvents.end(); ++it)
		(*it)->executeChannelJoin(player, m_id, m_users);

	Manager::getInstance()->addUser(player->getID(), m_id);
	return true;
}
Пример #3
0
bool ChatChannel::removeUser(Player* player)
{
	if(!player || player->isRemoved())
		return false;

	UsersMap::iterator it = m_users.find(player->getID());
	if(it == m_users.end())
		return false;

	m_users.erase(it);
	CreatureEventList leaveEvents = player->getCreatureEvents(CREATURE_EVENT_CHANNEL_LEAVE);
	for(CreatureEventList::iterator it = leaveEvents.begin(); it != leaveEvents.end(); ++it)
		(*it)->executeChannelLeave(player, m_id, m_users);

	if(m_id == CHANNEL_PARTY || m_id == CHANNEL_GUILD || m_id == CHANNEL_PRIVATE)
	{
		Player* tmpPlayer = NULL;
		for(UsersMap::iterator cit = m_users.begin(); cit != m_users.end(); ++cit)
		{
			if((tmpPlayer = cit->second->getPlayer()))
				tmpPlayer->sendChannelEvent(m_id, player->getName(), CHANNELEVENT_LEAVE);
		}
	}

	Manager::getInstance()->removeUser(player->getID(), m_id);
	return true;
}
Пример #4
0
void Creature::dropCorpse(DeathList deathList)
{
	if(master && !g_config.getBool(ConfigManager::SUMMONS_DROP_CORPSE))
	{
		g_game.addMagicEffect(getPosition(), MAGIC_EFFECT_POFF);
		return;
	}

	Item* corpse = createCorpse(deathList);
	if(corpse)
		corpse->setParent(VirtualCylinder::virtualCylinder);

	bool deny = false;
	CreatureEventList deathEvents = getCreatureEvents(CREATURE_EVENT_DEATH);
	for(CreatureEventList::iterator it = deathEvents.begin(); it != deathEvents.end(); ++it)
	{
		if(!(*it)->executeDeath(this, corpse, deathList) && !deny)
			deny = true;
	}

	if(!corpse)
		return;

	corpse->setParent(NULL);
	if(deny)
		return;

	Tile* tile = getTile();
	if(!tile)
		return;

	Item* splash = NULL;
	switch(getRace())
	{
		case RACE_VENOM:
			splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_GREEN);
			break;

		case RACE_BLOOD:
			splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_BLOOD);
			break;

		default:
			break;
	}

	if(splash)
	{
		g_game.internalAddItem(NULL, tile, splash, INDEX_WHEREEVER, FLAG_NOLIMIT);
		g_game.startDecay(splash);
	}

	g_game.internalAddItem(NULL, tile, corpse, INDEX_WHEREEVER, FLAG_NOLIMIT);
	dropLoot(corpse->getContainer());
	g_game.startDecay(corpse);
}
Пример #5
0
CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type)
{
	CreatureEventList list;
	for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it)
	{
		if((*it)->getEventType() == type && (*it)->isLoaded())
			list.push_back(*it);
	}

	return list;
}
Пример #6
0
void Creature::onCreatureDisappear(const Creature* creature, bool isLogout)
{
	internalCreatureDisappear(creature, true);
	if(creature != this && isMapLoaded && creature->getPosition().z == getPosition().z)
	{
		updateTileCache(creature->getTile(), creature->getPosition());
        CreatureEventList disappearEvents = getCreatureEvents(CREATURE_EVENT_DISAPPEAR);
        for(CreatureEventList::iterator it = disappearEvents.begin(); it != disappearEvents.end(); ++it)
        	(*it)->executeDisappear(this, creature);
    }
}
Пример #7
0
ReturnValue Combat::canTargetCreature(const Player* player, const Creature* target)
{
	if(player == target)
		return RET_YOUMAYNOTATTACKTHISPLAYER;

	Player* tmpPlayer = const_cast<Player*>(player);
	bool deny = false;

	CreatureEventList targetEvents = tmpPlayer->getCreatureEvents(CREATURE_EVENT_TARGET);
	for(CreatureEventList::iterator it = targetEvents.begin(); it != targetEvents.end(); ++it)
	{
		if(!(*it)->executeAction(tmpPlayer, const_cast<Creature*>(target)) && !deny)
			deny = true;
	}

	if(deny)
		return RET_NEEDEXCHANGE;

	if(!player->hasFlag(PlayerFlag_IgnoreProtectionZone))
	{
		if(player->getZone() == ZONE_PROTECTION)
			return RET_YOUMAYNOTATTACKAPERSONWHILEINPROTECTIONZONE;

		if(target->getZone() == ZONE_PROTECTION)
			return RET_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE;

		if(target->getPlayer() || target->isPlayerSummon())
		{
			if(player->getZone() == ZONE_OPTIONAL)
				return RET_ACTIONNOTPERMITTEDINANOPVPZONE;

			if(target->getZone() == ZONE_OPTIONAL)
				return RET_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE;
		}
	}

	if(player->hasFlag(PlayerFlag_CannotUseCombat))
		return target->getPlayer() ? RET_YOUMAYNOTATTACKTHISPLAYER : RET_YOUMAYNOTATTACKTHISCREATURE;

	if(target->getPlayer() && !Combat::isInPvpZone(player, target) && player->getSkullType(target->getPlayer()) == SKULL_NONE)
	{
		if(player->getSecureMode() == SECUREMODE_ON)
			return RET_TURNSECUREMODETOATTACKUNMARKEDPLAYERS;
	}

	if(player->checkLoginDelay())
		return RET_YOUMAYNOTATTACKIMMEDIATELYAFTERLOGGINGIN;

	return Combat::canDoCombat(player, target, true);
}
Пример #8
0
CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type)
{
	CreatureEventList retList;
	if(!hasEventRegistered(type))
		return retList;

	for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it)
	{
		if((*it)->getEventType() == type)
			retList.push_back(*it);
	}

	return retList;
}
Пример #9
0
ReturnValue Combat::canTargetCreature(const PlayerP& player, const CreatureP& target)
{
	if(player == target)
		return RET_YOUMAYNOTATTACKTHISPLAYER;

	CreatureEventList targetEvents = player->getCreatureEvents(CREATURE_EVENT_TARGET);

	bool deny = false;
	for(CreatureEventList::iterator it = targetEvents.begin(); it != targetEvents.end(); ++it)
	{
		if(!(*it)->executeTarget(player, target))
			deny = true;
	}

	if(deny)
		return RET_DONTSHOWMESSAGE;

	if(!player->hasFlag(PlayerFlag_IgnoreProtectionZone))
	{
		if(player->getZone() == ZONE_PROTECTION)
			return RET_YOUMAYNOTATTACKAPERSONWHILEINPROTECTIONZONE;

		if(target->getZone() == ZONE_PROTECTION)
			return RET_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE;

		const Monster* targetMonster = target->getMonster();
		if(target->getPlayer() || (targetMonster != nullptr && targetMonster->getMaster() && targetMonster->getMaster()->getPlayer()))
		{
			if(player->getZone() == ZONE_NOPVP)
				return RET_ACTIONNOTPERMITTEDINANOPVPZONE;

			if(target->getZone() == ZONE_NOPVP)
				return RET_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE;
		}
	}

	if(player->hasFlag(PlayerFlag_CannotUseCombat) || !target->isAttackable())
		return target->getPlayer() ? RET_YOUMAYNOTATTACKTHISPLAYER : RET_YOUMAYNOTATTACKTHISCREATURE;

	if(target->getPlayer() && !Combat::isInPvpZone(*player, *target) && player->getSkullClient(target->getPlayer()) == SKULL_NONE)
	{
		if(player->getSecureMode() == SECUREMODE_ON)
			return RET_TURNSECUREMODETOATTACKUNMARKEDPLAYERS;

		if(player->getSkull() == SKULL_BLACK)
			return RET_YOUMAYNOTATTACKTHISPLAYER;
	}

	return canDoCombat(player, target);
}
Пример #10
0
void Creature::onThink(uint32_t interval)
{
	if(!isMapLoaded && useCacheMap())
	{
		isMapLoaded = true;
		updateMapCache();
	}

	if(followCreature && master != followCreature && !canSeeCreature(followCreature))
		internalCreatureDisappear(followCreature, false);

	if(attackedCreature && master != attackedCreature && !canSeeCreature(attackedCreature))
		internalCreatureDisappear(attackedCreature, false);

	blockTicks += interval;
	if(blockTicks >= 1000)
	{
		blockCount = std::min((uint32_t)blockCount + 1, (uint32_t)2);
		blockTicks = 0;
	}

	if(followCreature)
	{
		walkUpdateTicks += interval;
		if(forceUpdateFollowPath || walkUpdateTicks >= 2000)
		{
			walkUpdateTicks = 0;
			forceUpdateFollowPath = false;
			isUpdatingPath = true;
		}
	}

	if(isUpdatingPath)
	{
		isUpdatingPath = false;
		goToFollowCreature();
	}

#ifndef __GROUPED_ATTACKS__
	onAttacking(interval / EVENT_CREATURECOUNT);
#else
	onAttacking(interval);
#endif
	executeConditions(interval);

	CreatureEventList thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK);
	for(CreatureEventList::iterator it = thinkEvents.begin(); it != thinkEvents.end(); ++it)
		(*it)->executeThink(this, interval);
}
Пример #11
0
bool Creature::onKilledCreature(Creature* target, bool lastHit/* = true*/)
{
	if (getMaster()) {
		getMaster()->onKilledCreature(target);
	}

	//scripting event - onKill
	CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL);

	for (CreatureEventList::const_iterator it = killEvents.begin(), end = killEvents.end(); it != end; ++it) {
		(*it)->executeOnKill(this, target);
	}

	return false;
}
Пример #12
0
CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type)
{
	CreatureEventList tmpEventList;

	if (!hasEventRegistered(type)) {
		return tmpEventList;
	}

	for (CreatureEventList::const_iterator it = eventsList.begin(), end = eventsList.end(); it != end; ++it) {
		if ((*it)->getEventType() == type) {
			tmpEventList.push_back(*it);
		}
	}

	return tmpEventList;
}
Пример #13
0
CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type)
{
	CreatureEventList tmpEventList;

	if (!hasEventRegistered(type)) {
		return tmpEventList;
	}

	for (CreatureEvent* creatureEvent : eventsList) {
		if (creatureEvent->getEventType() == type) {
			tmpEventList.push_back(creatureEvent);
		}
	}

	return tmpEventList;
}
Пример #14
0
void Creature::onCreatureAppear(const Creature* creature)
{
	if(creature == this)
	{
		if(useCacheMap())
		{
			isMapLoaded = true;
			updateMapCache();
		}
	}
	else if(isMapLoaded && creature->getPosition().z == getPosition().z)
    {
		updateTileCache(creature->getTile(), creature->getPosition());
        CreatureEventList disappearEvents = getCreatureEvents(CREATURE_EVENT_APPEAR);
        for(CreatureEventList::iterator it = disappearEvents.begin(); it != disappearEvents.end(); ++it)
        	(*it)->executeDisappear(this, creature);
    }
}
Пример #15
0
void Creature::onThink(uint32_t interval)
{
	if (!isMapLoaded && useCacheMap()) {
		isMapLoaded = true;
		updateMapCache();
	}

	if (followCreature && getMaster() != followCreature && !canSeeCreature(followCreature)) {
		onCreatureDisappear(followCreature, false);
	}

	if (attackedCreature && getMaster() != attackedCreature && !canSeeCreature(attackedCreature)) {
		onCreatureDisappear(attackedCreature, false);
	}

	blockTicks += interval;

	if (blockTicks >= 1000) {
		blockCount = std::min<uint32_t>(blockCount + 1, 2);
		blockTicks = 0;
	}

	if (followCreature) {
		walkUpdateTicks += interval;

		if (forceUpdateFollowPath || walkUpdateTicks >= 2000) {
			walkUpdateTicks = 0;
			forceUpdateFollowPath = false;
			isUpdatingPath = true;
		}
	}

	if (isUpdatingPath) {
		isUpdatingPath = false;
		goToFollowCreature();
	}

	//scripting event - onThink
	CreatureEventList thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK);

	for (CreatureEventList::const_iterator it = thinkEvents.begin(), end = thinkEvents.end(); it != end; ++it) {
		(*it)->executeOnThink(this, interval);
	}
}
Пример #16
0
bool Creature::onKilledCreature(Creature* target, DeathEntry& entry)
{
	bool ret = true;
	if(master)
		ret = master->onKilledCreature(target, entry);

	CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL);
	if(!entry.isLast())
	{
		for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
			(*it)->executeKill(this, target, entry);

		return true;
	}

	for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
	{
		if(!(*it)->executeKill(this, target, entry) && ret)
			ret = false;
	}

	return ret;
}
Пример #17
0
bool Creature::onKilledCreature(Creature* target, uint32_t& flags, DeathEntry& entry)
{
	bool ret = true;
	if(master)
		ret = master->onKilledCreature(target, flags, entry);

	CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL);
	if(!hasBitSet((uint32_t)KILLFLAG_LASTHIT, flags))
	{
		for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
			(*it)->executeKill(this, target, false);

		return true;
	}

	for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
	{
		if(!(*it)->executeKill(this, target, true) && ret)
			ret = false;
	}

	return ret;
}
Пример #18
0
void Monster::onCreatureAppear(const Creature* creature)
{
	Creature::onCreatureAppear(creature);
	if(creature == this)
	{
		//We just spawned lets look around to see who is there.
		if(isSummon())
			isMasterInRange = canSee(getMaster()->getPosition());
			
			 setStorage(510, mType->realName); // sistema de shiny nomes 2.0
			
			CreatureEventList spawn = getCreatureEvents(CREATURE_EVENT_SPAWN);
			for(CreatureEventList::iterator it = spawn.begin(); it != spawn.end(); ++it)

			(*it)->executeOnSpawn(this);
			

		updateTargetList();
		updateIdleStatus();
	}
	else
		onCreatureEnter(const_cast<Creature*>(creature));
}
Пример #19
0
bool Creature::dropCorpse()
{
	if (!lootDrop && getMonster() && !(master && master->getPlayer())) {
		if (master) {
			//scripting event - onDeath
			CreatureEventList deathEvents = getCreatureEvents(CREATURE_EVENT_DEATH);

			for (CreatureEventList::const_iterator it = deathEvents.begin(); it != deathEvents.end(); ++it) {
				(*it)->executeOnDeath(this, NULL, _lastHitCreature, _mostDamageCreature, lastHitUnjustified, mostDamageUnjustified);
			}
		}

		g_game.addMagicEffect(getPosition(), NM_ME_POFF);
	} else {
		Item* splash = NULL;

		switch (getRace()) {
			case RACE_VENOM:
				splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_GREEN);
				break;

			case RACE_BLOOD:
				splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_BLOOD);
				break;

			default:
				break;
		}

		Tile* tile = getTile();

		if (splash) {
			g_game.internalAddItem(tile, splash, INDEX_WHEREEVER, FLAG_NOLIMIT);
			g_game.startDecay(splash);
		}

		Item* corpse = getCorpse();

		if (corpse) {
			g_game.internalAddItem(tile, corpse, INDEX_WHEREEVER, FLAG_NOLIMIT);
			g_game.startDecay(corpse);
		}

		//scripting event - onDeath
		CreatureEventList deathEvents = getCreatureEvents(CREATURE_EVENT_DEATH);

		for (CreatureEventList::const_iterator it = deathEvents.begin(); it != deathEvents.end(); ++it) {
			(*it)->executeOnDeath(this, corpse, _lastHitCreature, _mostDamageCreature, lastHitUnjustified, mostDamageUnjustified);
		}

		if (corpse) {
			dropLoot(corpse->getContainer());
		}
	}

	return true;
}
Пример #20
0
void Creature::onAttacking(uint32_t interval)
{
	if(!attackedCreature || attackedCreature->getHealth() < 1 || interval < 100)
		return;

	bool deny = false;
	CreatureEventList attackEvents = getCreatureEvents(CREATURE_EVENT_ATTACK);
	for(CreatureEventList::iterator it = attackEvents.begin(); it != attackEvents.end(); ++it)
	{
		if(!(*it)->executeAction(this, attackedCreature) && !deny)
			deny = true;
	}

	if(deny)
		setAttackedCreature(NULL);

	if(!attackedCreature)
		return;

	onAttacked();
	attackedCreature->onAttacked();
	if(g_game.isSightClear(getPosition(), attackedCreature->getPosition(), true))
		doAttacking(interval);
}
Пример #21
0
Cylinder* Tile::__queryDestination(int32_t& index, const Thing* thing, Item** destItem,
	uint32_t& flags)
{
	Tile* destTile = NULL;
	*destItem = NULL;

	Position _pos = pos;
	if(floorChange(CHANGE_DOWN))
	{
		_pos.z++;
		
		if(Creature* creature = (Creature*) thing->getCreature()){
		 CreatureEventList moveEvents = creature->getCreatureEvents(CREATURE_EVENT_MOVE);
		 for(CreatureEventList::iterator it = moveEvents.begin(); it != moveEvents.end(); ++it)
			(*it)->executeMove(creature, creature->getPosition(), _pos);
		}
		
		for(int32_t i = CHANGE_FIRST_EX; i < CHANGE_LAST; ++i)
		{
			Position __pos = _pos;
			Tile* tmpTile = NULL;
			switch(i)
			{
				case CHANGE_NORTH_EX:
					__pos.y++;
					if((tmpTile = g_game.getTile(__pos)))
						__pos.y++;

					break;
				case CHANGE_SOUTH_EX:
					__pos.y--;
					if((tmpTile = g_game.getTile(__pos)))
						__pos.y--;

					break;
				case CHANGE_EAST_EX:
					__pos.x--;
					if((tmpTile = g_game.getTile(__pos)))
						__pos.x--;

					break;
				case CHANGE_WEST_EX:
					__pos.x++;
					if((tmpTile = g_game.getTile(__pos)))
						__pos.x++;

					break;
				default:
					break;
			}

			if(!tmpTile || !tmpTile->floorChange((FloorChange_t)i))
				continue;

			destTile = g_game.getTile(__pos);
			break;
		}

		if(!destTile)
		{
			if(Tile* downTile = g_game.getTile(_pos))
			{
				if(downTile->floorChange(CHANGE_NORTH) || downTile->floorChange(CHANGE_NORTH_EX))
					_pos.y++;

				if(downTile->floorChange(CHANGE_SOUTH) || downTile->floorChange(CHANGE_SOUTH_EX))
					_pos.y--;

				if(downTile->floorChange(CHANGE_EAST) || downTile->floorChange(CHANGE_EAST_EX))
					_pos.x--;

				if(downTile->floorChange(CHANGE_WEST) || downTile->floorChange(CHANGE_WEST_EX))
					_pos.x++;

				destTile = g_game.getTile(_pos);
			}
		}
	}
	else if(floorChange())
	{
		_pos.z--;
		if(floorChange(CHANGE_NORTH))
			_pos.y--;

		if(floorChange(CHANGE_SOUTH))
			_pos.y++;

		if(floorChange(CHANGE_EAST))
			_pos.x++;

		if(floorChange(CHANGE_WEST))
			_pos.x--;

		if(floorChange(CHANGE_NORTH_EX))
			_pos.y -= 2;

		if(floorChange(CHANGE_SOUTH_EX))
			_pos.y += 2;

		if(floorChange(CHANGE_EAST_EX))
			_pos.x += 2;

		if(floorChange(CHANGE_WEST_EX))
			_pos.x -= 2;

		destTile = g_game.getTile(_pos);
		if(Creature* creature = (Creature*) thing->getCreature()){
		 CreatureEventList moveEvents = creature->getCreatureEvents(CREATURE_EVENT_MOVE);
		 for(CreatureEventList::iterator it = moveEvents.begin(); it != moveEvents.end(); ++it)
			(*it)->executeMove(creature, creature->getPosition(), _pos);
		}
	}

	if(!destTile)
		destTile = this;
	else
		flags |= FLAG_NOLIMIT; //will ignore that there is blocking items/creatures

	if(destTile)
	{
		Thing* destThing = destTile->getTopDownItem();
		if(destThing && !destThing->isRemoved())
			*destItem = destThing->getItem();
	}

	return destTile;
}
Пример #22
0
ReturnValue Combat::canDoCombat(const CreatureP& attacker, const CreatureP& target)
{
	if(!attacker)
		return RET_NOERROR;

	if (!attacker->isAlive() || !target->isAlive()) {
		return RET_NOTPOSSIBLE;
	}

	bool success = true;
	CreatureEventList combatEvents = attacker->getCreatureEvents(CREATURE_EVENT_COMBAT);
	for(CreatureEventList::iterator it = combatEvents.begin(); it != combatEvents.end(); ++it)
	{
		if(!(*it)->executeCombat(attacker, target) && success)
			success = false;
	}

	if(!success)
		return RET_NOTPOSSIBLE;

	if (!attacker->isAlive() || !target->isAlive()) {
		return RET_NOTPOSSIBLE;
	}

	const Monster* attackerMonster = attacker->getMonster();

	bool checkZones = false;
	if(const Player* targetPlayer = target->getPlayer())
	{
		if(!targetPlayer->isAttackable())
			return RET_YOUMAYNOTATTACKTHISPLAYER;

		const Player* attackerPlayer = nullptr;
		if((attackerPlayer = attacker->getPlayer()) || (attackerMonster != nullptr && attackerMonster->getMaster()
			&& (attackerPlayer = attackerMonster->getMaster()->getPlayer())))
		{
			checkZones = true;
			if((server.game().getWorldType() == WORLD_TYPE_NO_PVP && !Combat::isInPvpZone(*attacker, *target)) ||
				isProtected(const_cast<Player*>(attackerPlayer), const_cast<Player*>(targetPlayer))
				|| (server.configManager().getBool(ConfigManager::CANNOT_ATTACK_SAME_LOOKFEET) &&
				attackerPlayer->getDefaultOutfit().lookFeet == targetPlayer->getDefaultOutfit().lookFeet)
				|| !attackerPlayer->canSeeCreature(*targetPlayer))
				return RET_YOUMAYNOTATTACKTHISPLAYER;
		}
	}
	else if(const Monster* targetMonster = target->getMonster())
	{
		if(!target->isAttackable())
			return RET_YOUMAYNOTATTACKTHISCREATURE;

		if (attackerMonster != nullptr && !attackerMonster->hasController() && !targetMonster->hasController()) {
			return RET_YOUMAYNOTATTACKTHISCREATURE;
		}

		const Player* attackerPlayer = nullptr;
		if((attackerPlayer = attacker->getPlayer()) || (attackerMonster != nullptr && attackerMonster->getMaster()
			&& (attackerPlayer = attackerMonster->getMaster()->getPlayer())))
		{
			if(attackerPlayer->hasFlag(PlayerFlag_CannotAttackMonster))
				return RET_YOUMAYNOTATTACKTHISCREATURE;

			const Monster* targetMonster = target->getMonster();
			if(targetMonster != nullptr && targetMonster->getMaster() && targetMonster->getMaster()->getPlayer())
			{
				checkZones = true;
				if(server.game().getWorldType() == WORLD_TYPE_NO_PVP && !Combat::isInPvpZone(*attacker, *target))
					return RET_YOUMAYNOTATTACKTHISCREATURE;
			}
		}
	}

	return checkZones && (target->getTile()->hasFlag(TILESTATE_NOPVPZONE) ||
		(attacker->getTile()->hasFlag(TILESTATE_NOPVPZONE)
		&& !target->getTile()->hasFlag(TILESTATE_NOPVPZONE) &&
		!target->getTile()->hasFlag(TILESTATE_PROTECTIONZONE))) ?
		RET_ACTIONNOTPERMITTEDINANOPVPZONE : RET_NOERROR;
}
Пример #23
0
bool Creature::onDeath()
{
	DeathList deathList = getKillers();
	bool deny = false;

	CreatureEventList prepareDeathEvents = getCreatureEvents(CREATURE_EVENT_PREPAREDEATH);
	for(CreatureEventList::iterator it = prepareDeathEvents.begin(); it != prepareDeathEvents.end(); ++it)
	{
		if(!(*it)->executePrepareDeath(this, deathList) && !deny)
			deny = true;
	}

	if(deny)
		return false;

	int32_t i = 0, size = deathList.size(), limit = g_config.getNumber(ConfigManager::DEATH_ASSISTS) + 1;
	if(limit > 0 && size > limit)
		size = limit;

	Creature* tmp = NULL;
	CreatureVector justifyVec;
	for(DeathList::iterator it = deathList.begin(); it != deathList.end(); ++it, ++i)
	{
		if(it->isNameKill())
			continue;

		if(it == deathList.begin())
			it->setLast();

		if(i < size)
		{
			if(it->getKillerCreature()->getPlayer())
				tmp = it->getKillerCreature();
			else if(it->getKillerCreature()->getPlayerMaster())
				tmp = it->getKillerCreature()->getMaster();
		}

		if(tmp)
		{
			if(std::find(justifyVec.begin(), justifyVec.end(), tmp) == justifyVec.end())
			{
				it->setJustify();
				justifyVec.push_back(tmp);
			}

			tmp = NULL;
		}

		if(!it->getKillerCreature()->onKilledCreature(this, (*it)) && it->isLast())
			return false;
	}

	for(CountMap::iterator it = damageMap.begin(); it != damageMap.end(); ++it)
	{
		if((tmp = g_game.getCreatureByID(it->first)))
			tmp->onTargetKilled(this);
	}

	dropCorpse(deathList);
	if(master)
		master->removeSummon(this);

	return true;
}
Пример #24
0
ReturnValue Combat::canDoCombat(const Creature* attacker, const Creature* target, bool isAggressive)
{
	if(!attacker)
		return RET_NOERROR;

	bool success = true;
	CreatureEventList combatEvents = const_cast<Creature*>(attacker)->getCreatureEvents(CREATURE_EVENT_COMBAT);
	for(CreatureEventList::iterator it = combatEvents.begin(); it != combatEvents.end(); ++it)
	{
		if(!(*it)->executeCombat(const_cast<Creature*>(attacker), const_cast<Creature*>(target), isAggressive) && success)
			success = false;
	}

	if(!success)
		return RET_NOTPOSSIBLE;

	bool checkZones = false;
	if(const Player* targetPlayer = target->getPlayer())
	{
		if(!targetPlayer->isAttackable())
			return RET_YOUMAYNOTATTACKTHISPLAYER;

		const Player* attackerPlayer = NULL;
		if((attackerPlayer = attacker->getPlayer()) || (attackerPlayer = attacker->getPlayerMaster()))
		{
			checkZones = true;
			if((g_game.getWorldType() == WORLDTYPE_OPTIONAL && !Combat::isInPvpZone(attacker, target)
				&& !attackerPlayer->isEnemy(targetPlayer)) || isProtected(const_cast<Player*>(attackerPlayer),
				const_cast<Player*>(targetPlayer)) || (g_config.getBool(ConfigManager::CANNOT_ATTACK_SAME_LOOKFEET)
				&& attackerPlayer->getDefaultOutfit().lookFeet == targetPlayer->getDefaultOutfit().lookFeet)
				|| !attackerPlayer->canSeeCreature(targetPlayer))
				return RET_YOUMAYNOTATTACKTHISPLAYER;
		}
	}
	else if(target->getMonster())
	{
		if(!target->isAttackable())
			return RET_YOUMAYNOTATTACKTHISCREATURE;

		const Player* attackerPlayer = NULL;
		if((attackerPlayer = attacker->getPlayer()) || (attackerPlayer = attacker->getPlayerMaster()))
		{
			if(attackerPlayer->hasFlag(PlayerFlag_CannotAttackMonster))
				return RET_YOUMAYNOTATTACKTHISCREATURE;

			if(target->isPlayerSummon())
			{
				checkZones = true;
				if(g_game.getWorldType() == WORLDTYPE_OPTIONAL && !Combat::isInPvpZone(attacker, target)
					&& !attackerPlayer->isEnemy(target->getPlayerMaster()))
					return RET_YOUMAYNOTATTACKTHISCREATURE;
			}
		}
	}
	else if(target->getNpc() && !target->isAttackable())
		return RET_YOUMAYNOTATTACKTHISCREATURE;

	return checkZones && (target->getTile()->hasFlag(TILESTATE_OPTIONALZONE) ||
		(attacker->getTile()->hasFlag(TILESTATE_OPTIONALZONE)
		&& !target->getTile()->hasFlag(TILESTATE_OPTIONALZONE) &&
		!target->getTile()->hasFlag(TILESTATE_PROTECTIONZONE))) ?
		RET_ACTIONNOTPERMITTEDINANOPVPZONE : RET_NOERROR;
}