void cNewMagic::execSpell( P_CHAR pMage, UINT8 spell, UINT8 type, cUORxTarget* target )
{
	stNewSpell *sInfo = findSpell( spell );
	P_PLAYER pp = dynamic_cast<P_PLAYER>(pMage);

	if( ( ( pp || !pp->isGM() ) && !checkReagents( pMage, spell ) ) || !useMana( pMage, spell ) )
	{
		pMage->setCasting( false );
		return;
	}
	if( !pp || !pp->isGM() )
		useReagents( pMage, spell );
	
	if( !checkSkill( pMage, spell, false ) )
	{
		disturb( pMage, true, -1 );
		return;
	}
	
	// Call the Spell Effect for this Spell
	if( sInfo->script )
		sInfo->script->onSpellSuccess( pMage, spell, type, target );
	
	// End Casting
	pMage->setCasting( false );
}
Example #2
0
// All ai controlled creatures can be controlled by a gm
// or by their owner if tamed
void AbstractAI::onSpeechInput( P_PLAYER pTalker, const QString &comm ) {
	if (!pTalker->isGM() && (!m_npc->isTamed() || m_npc->owner() != pTalker)) {
		return;
	}

	// too far away to hear us
	if (pTalker->dist(m_npc) > 7) {
		return;
	}
	
	if (comm.contains(" FOLLOW")) {
		if (comm.contains(" ME")) {
			m_npc->setWanderFollowTarget(pTalker);
			m_npc->setWanderType(enFollowTarget);
			m_npc->bark(cBaseChar::Bark_Attacking);
		} else {
			pTalker->socket()->attachTarget(new cFollowTarget(m_npc));
		}
	} else if ((comm.contains(" KILL")) || (comm.contains(" ATTACK"))) {
		if (m_npc->inGuardedArea()) {
			pTalker->message(tr("You can't have pets attack in town!"));
		}
	} else if ((comm.contains(" FETCH")) || (comm.contains(" GET"))) {
		//pPlayer->setGuarded(false);
		// >> LEGACY
		//addx[s]=pPet->serial();
		//target(s, 0, 1, 0, 124, "Click on the object to fetch.");
	} else if (comm.contains(" COME")) {
		m_npc->setWanderDestination(pTalker->pos());
		m_npc->setWanderType(enDestination);
		m_npc->bark(cBaseChar::Bark_Attacking);
	} else if (comm.contains(" GUARD")) {
	} else if ((comm.contains(" STOP")) || (comm.contains(" STAY"))) {
		m_npc->fight(0);
		m_npc->setWanderType( enHalt );
		m_npc->bark(cBaseChar::Bark_Attacking);
	} else if (comm.contains(" TRANSFER")) {
	} else if (comm.contains(" RELEASE")) {
		// Has it been summoned ? Let's dispel it
		if (m_npc->summoned()) {
			m_npc->setSummonTime(uiCurrentTime);
		}

		m_npc->setWanderType(enFreely);
		m_npc->setOwner(0);
		m_npc->setTamed(false);
		m_npc->bark(cBaseChar::Bark_Attacking);
		if (SrvParams->tamedDisappear()) {
			m_npc->soundEffect(0x01Fe);
			cCharStuff::DeleteChar(m_npc);
		}
	}
}
Example #3
0
// For the Paperdoll
QString cSkills::getSkillTitle( P_CHAR pChar ) const
{
	QString skillTitle;
	P_PLAYER player = dynamic_cast<P_PLAYER>( pChar );

	if ( Config::instance()->showSkillTitles() && player && !player->isGM() )
	{
		unsigned short skill = 0;
		unsigned short skillValue = 0;

		for ( int i = 0; i < ALLSKILLS; ++i )
		{
			if ( pChar->skillValue( i ) > skillValue )
			{
				skill = i;
				skillValue = pChar->skillValue( i );
			}
		}

		unsigned char title = QMAX( 1, ( ( int ) pChar->skillValue( skill ) - 300 ) / 100 );

		if ( title >= skillRanks.size() )
		{
			pChar->log( LOG_ERROR, "Invalid skill rank information.\n" );
			return skillTitle;
		}

		// Skill not found
		if ( skill >= skills.size() )
		{
			pChar->log( LOG_ERROR, QString( "Skill id out of range: %u.\n" ).arg( skill ) );
			return skillTitle;
		}

		skillTitle = QString( "%1 %2" ).arg( skillRanks[title] ).arg( skills[skill].title );
	}

	return skillTitle;
}
// May a character walk here ?
// If yes we auto. set the new z value for pos
bool mayWalk( P_CHAR pChar, Coord& pos )
{
	// Go trough the array top-to-bottom and check
	// If we find a tile to walk on
	vector<stBlockItem> blockList = getBlockingItems( pChar, pos );
	bool found = false;
	Q_UINT32 i;
	bool priviledged = false;
	Q_INT32 oldz = pos.z;

	P_PLAYER player = dynamic_cast<P_PLAYER>( pChar );

	priviledged = player && player->isGM();

	for ( i = 0; i < blockList.size(); ++i )
	{
		stBlockItem item = blockList[i];
		Q_INT32 itemTop = ( item.z + item.height );

		// If we found something to step on and the next tile
		// below would block us, use the good one instead
		if ( found && ( itemTop > pos.z - P_M_MAX_Z_BLOCKS || !item.walkable ) )
		{
			break;
		}

		// If we encounter any object with itemTop <= pos.z which is NOT walkable
		// Then we can as well just return false as while falling we would be
		// blocked by that object
		if ( !item.walkable && !priviledged && itemTop <= pos.z )
			return false;

		if ( item.walkable || priviledged )
		{
			// If the top of the item is within our max-climb reach
			// then the first check passed. in addition we need to
			// check if the "bottom" of the item is reachable
			// I would say 2 is a good "reach" value for the bottom
			// of any item
			if ( itemTop < pos.z + P_M_MAX_Z_CLIMB && itemTop >= pos.z - P_M_MAX_Z_FALL )
			{
				// We already found something to step on above.
				// See if it's easier to step down.
				if ( found && abs( oldz - pos.z ) < abs( oldz - itemTop ) )
				{
					break;
				}

				pos.z = itemTop;
				found = true;

				if ( item.height > 1 )
				{
					break;
				}

				// break; - We can't break here anymore since we have to check if the ground would be easier
				// to step on
				// Climbing maptiles is 5 tiles easier
			}
			else if ( item.maptile && itemTop < pos.z + P_M_MAX_Z_CLIMB + 5 && itemTop >= pos.z - P_M_MAX_Z_FALL )
			{
				// We already found something to step on above.
				// See if it's easier to step down.
				if ( found && abs( oldz - pos.z ) < abs( oldz - itemTop ) )
				{
					break;
				}

				pos.z = itemTop;
				found = true;
				//break;
			}
			else if ( itemTop < pos.z )
			{
				// We already found something to step on above.
				// See if it's easier to step down.
				if ( found && abs( oldz - pos.z ) < abs( oldz - itemTop ) )
				{
					break;
				}

				pos.z = itemTop;
				found = true;
				break;
			}
		}
	}

	if ( priviledged )
	{
		return true;
	}

	// If we're still at the same position
	// We didn't find anything to step on
	if ( !found )
		return false;

	// Another loop *IS* needed here (at least that's what i think)
	for ( i = 0; i < blockList.size(); ++i )
	{
		// So we know about the new Z position we are moving to
		// Lets check if there is enough space ABOVE that position (at least 15 z units)
		// If there is ANY impassable object between pos.z and pos.z + 15 we can't walk here
		stBlockItem item = blockList[i];
		Q_INT8 itemTop = ( item.z + item.height );

		// If the item is below what we step on, ignore it
		if ( itemTop <= pos.z )
		{
			continue;
		}

		// Does the top of the item looms into our space
		// Like before 15 is the assumed height of ourself
		// Use the new position here.
		if ( ( itemTop > pos.z ) && ( itemTop < pos.z + P_M_MAX_Z_BLOCKS ) )
			return false;

		// Or the bottom ?
		// note: the following test was commented out.  by putting the code back in,
		// npcs stop wandering through the walls of multis.  I am curious if this code
		// has other (negative) affects besides that.
		if ( ( item.z >= oldz ) && ( item.z < oldz + P_M_MAX_Z_BLOCKS / 2 ) )
			return false;

		// Or does it spread the whole range ?
		if ( ( item.z <= oldz ) && ( itemTop >= oldz + P_M_MAX_Z_BLOCKS / 2 ) )
			return false;

		// Is it at the new position ?
		if ( ( item.z >= pos.z ) && ( item.z < pos.z + P_M_MAX_Z_BLOCKS ) )
			return false;
	}

	// All Checks passed
	return true;
}
Example #5
0
// All ai controlled creatures can be controlled by a gm
// or by their owner if tamed
void AbstractAI::onSpeechInput( P_PLAYER pTalker, const QString& comm )
{
	if ( !pTalker->isGM() && ( !m_npc->isTamed() || m_npc->owner() != pTalker ) )
	{
		return;
	}

	// too far away to hear us
	if ( pTalker->dist( m_npc ) > 7 )
	{
		return;
	}

	if ( comm.contains( " FOLLOW" ) )
	{
		if ( comm.contains( " ME" ) )
		{
			m_npc->setWanderFollowTarget( pTalker );
			m_npc->setWanderType( enFollowTarget );
			m_npc->bark( cBaseChar::Bark_Attacking );
		}
		else
		{
			pTalker->socket()->attachTarget( new cFollowTarget( m_npc ) );
		}
	}
	else if ( ( comm.contains( " KILL" ) ) || ( comm.contains( " ATTACK" ) ) )
	{
		if ( m_npc->inGuardedArea() )
		{
			pTalker->message( tr( "You can't have pets attack in town!" ) );
		}
	}
	else if ( ( comm.contains( " FETCH" ) ) || ( comm.contains( " GET" ) ) )
	{
//#pragma note( Implement me )
		pTalker->message( tr( "Sorry, not implemented yet :(" ) );
	}
	else if ( comm.contains( " COME" ) )
	{
		m_npc->setWanderDestination( pTalker->pos() );
		m_npc->setWanderType( enDestination );
		m_npc->bark( cBaseChar::Bark_Attacking );
	}
	else if ( comm.contains( " GUARD" ) )
	{
	}
	else if ( ( comm.contains( " STOP" ) ) || ( comm.contains( " STAY" ) ) )
	{
		m_npc->fight( 0 );
		m_npc->setWanderType( enHalt );
		m_npc->bark( cBaseChar::Bark_Attacking );
	}
	else if ( comm.contains( " TRANSFER" ) )
	{
	}
	else if ( comm.contains( " RELEASE" ) )
	{
		// Has it been summoned ? Let's dispel it
		if ( m_npc->summoned() )
		{
			m_npc->setSummonTime( Server::instance()->time() );
		}

		m_npc->setWanderType( enFreely );
		m_npc->setOwner( 0 );
		m_npc->setTamed( false );
		m_npc->bark( cBaseChar::Bark_Attacking );
		if ( Config::instance()->tamedDisappear() )
		{
			m_npc->soundEffect( 0x01Fe );
			m_npc->remove();
		}
	}
}
Example #6
0
bool PetCommand( cUOSocket *socket, P_PLAYER pPlayer, P_NPC pPet, const QString& comm )
{
	if( pPet->owner() != pPlayer && !pPlayer->isGM() )
		return false;

	// player vendor
/*	if( pPet->npcaitype() == 17 )
		return false;*/
	
	// too far away to hear us
	if( pPlayer->dist( pPet ) > 7 )
		return false;
	
	QString petname = pPet->name();
	bool bAllCommand = false;

	if( !comm.contains( petname, false ) )
		if( comm.contains( "ALL", false ) )
			bAllCommand = true;
		else
			return false;
	
	bool bReturn = false;
	
	if( comm.contains( " FOLLOW" ) )
	{
		if( comm.contains( " ME" ) )
		{
#pragma note( "TODO: implement state change here" )
//			pPet->setWanderFollowTarget( pPlayer->serial() );
//			pPet->setWanderType( enFollowTarget );
			playmonstersound( pPet, pPet->bodyID(), SND_STARTATTACK );
		}
		else
		{
			// LEGACY: target( s, 0, 1, 0, 117, "Click on the target to follow." );
		}

		bReturn = true;
	}
	else if( ( comm.contains( " KILL" ) ) || ( comm.contains( " ATTACK" ) ) )
	{
		if( pPet->inGuardedArea() ) // Ripper..No pet attacking in town.
		{
			pPlayer->message( tr( "You can't have pets attack in town!" ) );
			return false;
		}

		//pPlayer->setGuarded( false );
		// >> LEGACY
		//addx[s]=pPet->serial();
		//target(s, 0, 1, 0, 118, "Select the target to attack.");//AntiChrist
		bReturn = true;
	}
	else if( ( comm.contains( " FETCH" ) ) || ( comm.contains( " GET" ) ) )
	{
		//pPlayer->setGuarded(false);
		// >> LEGACY
		//addx[s]=pPet->serial();
		//target(s, 0, 1, 0, 124, "Click on the object to fetch.");
		bReturn = true;
	}
	else if( comm.contains( " COME" ) )
	{
		//pPlayer->setGuarded( false );
#pragma note( "TODO: implement state change here" )
//		pPet->setWanderFollowTarget( pPlayer->serial() );
//		pPet->setWanderType( enFollowTarget );
		pPet->setNextMoveTime();
		pPlayer->message( tr( "Your pet begins following you." ) );
		bReturn = true;
	}
	else if( comm.contains( " GUARD" ) )
	{
		// LEGACY
		/*addx[s] = pPet->serial();	// the pet's serial
		addy[s] = 0;

		if( comm.find( " ME" ) != string::npos )
			addy[s]=1;	// indicates we already know whom to guard (for future use)
		
		// for now they still must click on themselves (Duke)
		target(s, 0, 1, 0, 120, "Click on the char to guard.");*/
		bReturn = true;
	}
	else if( ( comm.contains( " STOP" ) ) || ( comm.contains(" STAY") ) )
	{
		//pPlayer->setGuarded( false );
#pragma note( "TODO: implement state change here" )
//		pPet->setWanderFollowTarget( INVALID_SERIAL );
		pPet->setCombatTarget( INVALID_SERIAL );

		if (pPet->isAtWar()) 
			pPet->toggleCombat();

		pPet->setWanderType( enHalt );
		bReturn = true;
	}
	else if( comm.contains( " TRANSFER" ) )
	{
		//pPlayer->setGuarded( false );
		// >> LEGACY
		/*addx[s]=pPet->serial();
		target(s, 0, 1, 0, 119, "Select character to transfer your pet to.");*/
		bReturn = true;
	}
	else if( comm.contains( " RELEASE" ) )
	{
		//pPlayer->setGuarded( false );

		// Has it been summoned ? Let's dispel it
		if( pPet->summonTime() > uiCurrentTime )
			pPet->setSummonTime( uiCurrentTime );

#pragma note( "TODO: implement state change here" )
//		pPet->setWanderFollowTarget( INVALID_SERIAL );
		pPet->setWanderType( enFreely );
		pPet->setOwner( NULL );
		pPet->setTamed( false );
		pPet->emote( tr( "%1 appears to have decided that it is better off without a master" ).arg( pPet->name() ) );
		if( SrvParams->tamedDisappear() ==1 )
		{
			pPet->soundEffect( 0x01FE );
			cCharStuff::DeleteChar( pPet );
		}
		bReturn = true;
	}

	// give other pets opotunity to process command
	if ( bReturn && bAllCommand )
		return false; 
	else
		return bReturn;
}
// New Class implementation
void cDragItems::grabItem( cUOSocket *socket, cUORxDragItem *packet )
{
	// Get our character
	P_PLAYER pChar = socket->player();
	if( !pChar )
		return;

	UINT32 weight = pChar->weight();

	// Fetch the grab information
	UI16 amount = packet->amount();
	if( !amount )
		amount = 1;

	P_ITEM pItem = FindItemBySerial( packet->serial() );

	// If it's an invalid pointer we can't even bounce
	if( !pItem )
		return;

	// Are we already dragging an item ?
	// Bounce it and reject the move
	// (Logged out while dragging an item)
	if( socket->dragging() )
	{
		socket->bounceItem( socket->dragging(), BR_ALREADY_DRAGGING );
		return;
	}

	if( pItem->onPickup( pChar ) )
		return;

	if( pChar->onPickup( pItem ) )
		return;

	// Do we really want to let him break his meditation
	// When he picks up an item ?
	// Maybe a meditation check here ?!?
	pChar->disturbMed(); // Meditation

	P_CHAR itemOwner = pItem->getOutmostChar();

	// Try to pick something out of another characters posessions
	if( !pChar->isGM() && itemOwner && ( itemOwner != pChar ) && ( itemOwner->objectType() == enNPC && dynamic_cast<P_NPC>(itemOwner)->owner() != pChar ) )
	{
		socket->bounceItem( pItem, BR_BELONGS_TO_SOMEONE_ELSE );
		return;
	}

	// Check if the user can grab the item
	if( !pChar->canPickUp( pItem ) )
	{
		socket->bounceItem( pItem, BR_CANNOT_PICK_THAT_UP );
		return;
	}

	// The user can't see the item
	// Basically thats impossible as the socket should deny moving the item
	// if it's not in line of sight but to prevent exploits
	/*if( !line_of_sight( socket->socket(), pChar->pos, pItem->pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) )
	{
		socket->sysMessage( "You can't see the item." );
		bounceItem( socket, pItem, true );
		return;
	}*/

	P_ITEM outmostCont = pItem->getOutmostItem();

	// If it's a trade-window, reset the ack-status
	if( outmostCont && ( outmostCont->container() == pChar ) && ( outmostCont->layer() == 0 ) && ( outmostCont->id() == 0x1E5E ) )
	{
		// Get the other sides tradewindow
		P_ITEM tradeWindow = FindItemBySerial( calcserial( outmostCont->moreb1(), outmostCont->moreb2(), outmostCont->moreb3(), outmostCont->moreb4() ) );

		// If one of the trade-windows has the ack-status reset it
		if( tradeWindow && ( tradeWindow->morez() || outmostCont->morez() ) )
		{
			tradeWindow->setMoreZ(0);
			outmostCont->setMoreZ(0);
//			sendtradestatus( tradeWindow, outmostCont );
		}
	}

	// If the top-most container ( thats important ) is a corpse 
	// and looting is a crime, flag the character criminal.
	if( !pChar->isGM() && outmostCont && outmostCont->corpse() )
	{
		// For each item we take out we loose carma
		// if the corpse is innocent and not in our guild
		bool sameGuild = ( GuildCompare( pChar, outmostCont->owner() ) != 0 );

		if( ( outmostCont->more2() == 1 ) && !pChar->Owns( outmostCont ) && !sameGuild )
		{
//			pChar->karma -= 5;
			pChar->setKarma( pChar->karma() - 5 );
			pChar->setCriminalTime( uiCurrentTime + SrvParams->crimtime() * MY_CLOCKS_PER_SEC );
			socket->sysMessage( tr("You lost some karma.") );
		}
	}

	// Check if the item is too heavy
	//if( !pc_currchar->isGMorCounselor() )
	//{
	//} << Deactivated (DarkStorm)

	// ==== Grabbing the Item is allowed here ====
	
	// Remove eventual item-bonusses if we're unequipping something
	if( pItem->container() && pItem->container()->isChar() ) 
	{
		P_CHAR wearer = dynamic_cast<P_CHAR>( pItem->container() );

		if( wearer )
			wearer->removeItemBonus( pItem );

		// resend the stat window
		if( wearer && wearer->objectType() == enPlayer )
		{
			P_PLAYER pp = dynamic_cast<P_PLAYER>(wearer);
			if( pp->socket() )
				pp->socket()->sendStatWindow();
		}
	}

	// Send the user a pickup sound if we're picking it up
	// From a container/paperdoll
	if( !pItem->isInWorld() )
		socket->soundEffect( 0x57, pItem );
	
	// If we're picking up a specific amount of what we got
	// Take that into account
	if( amount < pItem->amount() )
	{
		UI32 pickedAmount = QMIN( amount, pItem->amount() );

		// We only have to split if we're not taking it all
		if( pickedAmount != pItem->amount() )
		{
			P_ITEM splitItem = new cItem( *pItem ); // Create a new item to pick that up
			splitItem->setSerial( World::instance()->findItemSerial() );
			splitItem->setAmount( pItem->amount() - pickedAmount );
			P_ITEM pContainer = dynamic_cast<P_ITEM>(pItem->container());
			if ( pContainer )
				pContainer->addItem( splitItem, false );
			splitItem->SetOwnSerial( pItem->ownSerial() );
			splitItem->SetSpawnSerial( pItem->spawnserial );

			// He needs to see the new item
			splitItem->update();

			// If we're taking something out of a spawn-region it's spawning "flag" is removed isn't it?
			pItem->SetSpawnSerial( INVALID_SERIAL );
			pItem->setAmount( pickedAmount );
		}
	}
	
	// *normally* we should exclude the dragging socket here. but it works so as well.
	pItem->removeFromView( true );

	// Remove it from the World if it is in world, otherwise remove it from it's current container
	if( pItem->isInWorld() )
		MapObjects::instance()->remove( pItem );
	else
		pItem->removeFromCont( true );

	// The item was in a multi
	if( pItem->multis() != INVALID_SERIAL )
	{
		cMulti* pMulti = dynamic_cast< cMulti* >( FindItemBySerial( pItem->multis() ) );
		if( pMulti )
			pMulti->removeItem( pItem );
	}
	
	pChar->addItem( cBaseChar::Dragging, pItem );

	if( weight != pChar->weight() )
		socket->sendStatWindow();
}
void cDragItems::dropOnItem( cUOSocket *socket, P_ITEM pItem, P_ITEM pCont, const Coord_cl &dropPos )
{
	P_PLAYER pChar = socket->player();
	
	if( pItem->isMulti() )
	{
		socket->sysMessage( tr( "You cannot put houses in containers" ) );
		cUOTxBounceItem bounce;
		bounce.setReason( BR_NO_REASON );
		socket->send( &bounce );
		Items->DeleItem( pItem );
		return;
	}
	
	if( pItem->onDropOnItem( pCont ) )
	{
		if( socket->dragging() )
			socket->bounceItem( socket->dragging(), BR_NO_REASON );

		return;
	}
	else if( pCont->onDropOnItem( pItem ) )
	{
		if( socket->dragging() )
			socket->bounceItem( socket->dragging(), BR_NO_REASON );

		return;
	}

	// If the target belongs to another character 
	// It needs to be our vendor or else it's denied
	P_CHAR packOwner = pCont->getOutmostChar();

	if( ( packOwner ) && ( packOwner != pChar ) && !pChar->isGM() )
	{
		// For each item someone puts into there 
		// He needs to do a snoop-check
		if( pChar->maySnoop() )
		{
			if( !pChar->checkSkill( SNOOPING, 0, 1000 ) )
			{

				socket->sysMessage( tr( "You fail to put that into %1's pack" ).arg( packOwner->name() ) );
				socket->bounceItem( pItem, BR_NO_REASON );
				return;
			}
		}

		if( packOwner->objectType() == enPlayer || 
			( packOwner->objectType() == enNPC && dynamic_cast<P_NPC>(packOwner)->owner() != pChar ) )
		{
			socket->sysMessage( tr("You cannot put that into the belongings of another player") );
			socket->bounceItem( pItem, BR_NO_REASON );
			return;
		}
	}

	// If we put the item into a trade-window
	// Reset the trade-status for both players
	if( pCont->layer() == 0 && pCont->id() == 0x1E5E &&	pChar->Wears( pCont ) )
	{
		// Trade window???
		P_ITEM tradeWindow = FindItemBySerial( calcserial( pCont->moreb1(), pCont->moreb2(), pCont->moreb3(), pCont->moreb4() ) );

		// If it *IS* a trade-window, replace the status
		if( tradeWindow && ( pCont->morez() || tradeWindow->morez() ) )
		{
			tradeWindow->setMoreZ(0);
			pCont->setMoreZ(0);
//			sendtradestatus( tradeWindow, pCont );
		}
	}
	
	if( !pChar->canPickUp( pItem ) )
	{
		socket->bounceItem( pItem, BR_CANNOT_PICK_THAT_UP );
		return;
	}

	// Trash can
	if( pCont->type()==87 )
	{
		Items->DeleItem( pItem );
		socket->sysMessage( tr( "As you let go of the item it disappears." ) );
		return;
	}

	// Spell Book
	cSpellBook *pBook = dynamic_cast< cSpellBook* >( pCont );
	if( pBook )
 	{
		SI08 spellId = NewMagic->calcSpellId( pItem->id() );

		if( pItem->type() != 1105 || spellId < 0 )
		{
			socket->sysMessage( tr( "You can only put scrolls into a spellbook" ) );
			socket->bounceItem( pItem, BR_NO_REASON );
			return;
		}		

		if( pBook->hasSpell( spellId ) )
		{
			socket->sysMessage( tr( "That spellbook already contains this spell" ) );
			socket->bounceItem( pItem, BR_NO_REASON );
			return;
		}

		if( pItem->amount() > 1 )
		{
			socket->sysMessage( tr( "You can only put 1 scroll into a spellbook at a time" ) );
			socket->bounceItem( pItem, BR_NO_REASON );
			return;
		}
		else
		{	
			pBook->addSpell( spellId );
			Items->DeleItem( pItem );
			pBook->update( socket );
			return;
		}
	}

	// We drop something on the belongings of one of our playervendors
/*	if( ( packOwner != NULL ) && ( packOwner->npcaitype() == 17 ) && packOwner->owner() == pChar )
	{
		socket->sysMessage( tr( "You drop something into your playervendor (unimplemented)" ) );
		socket->bounceItem( pItem, BR_NO_REASON );
		return;
	}*/

	// Playervendors (chest equipped by the vendor - opened to the client)

	/*if( !( pCont->pileable() && pItem->pileable() && pCont->id() == pItem->id() || ( pCont->type() != 1 && pCont->type() != 9 ) ) )
	{
		P_CHAR pc_j = GetPackOwner(pCont);
		if (pc_j != NULL)
		{
			if (pc_j->npcaitype() == 17 && pc_j->isNpc() && pChar->Owns(pc_j))
			{
				pChar->inputitem = pItem->serial;
				pChar->inputmode = cChar::enPricing;
				sysmessage(s, "Set a price for this item.");
			}
		}
	*/

	// We may also drop into *any* locked chest
	// So we can have post-boxes ;o)
	// Spellbooks are containers for us as well
	if( pCont->type() == 1 || pCont->type() == 8 || pCont->type() == 63 || pCont->type() == 65 || pCont->type() == 66 )
	{
		// If we're dropping it onto the closed container
		if( dropPos.distance( pCont->pos() ) == 0 )
		{
			pCont->addItem( pItem );
		}
		else
		{
			pCont->addItem( pItem, false );
			pItem->setPos( dropPos );
		}

		// Dropped on another Container/in another Container
		pChar->soundEffect( 0x57 );
		pItem->update();
		return;
	}
	// Item matching needs to be extended !!! at least Color! (for certain types)
	else if ( pCont->isPileable() && pItem->isPileable() && ( pCont->id() == pItem->id() ) )
	{
		if( pCont->amount() + pItem->amount() <= 65535 )
		{
			pCont->setAmount( pCont->amount() + pItem->amount() );
			
			Items->DeleItem( pItem );
			pCont->update(); // Need to update the amount
			return;
		}
		// We have to *keep* our current item
		else
		{
			pCont->setAmount( 65535 ); // Max out the amount
			pCont->update();

			// The delta between 65535 and pCont->amount() sub our Amount is the
			// new amount
			pItem->setAmount( pItem->amount() - ( 65535 - pCont->amount() ) );
		}
	}

	// We dropped the item NOT on a container
	// And were *un*able to stack it (!)
	// >> Set it to the location of the item we dropped it on and stack it up by 2
	pItem->moveTo( pCont->pos() );
	pItem->setPos( pItem->pos() + Coord_cl(0, 0, 2) );
	pItem->update();

/*	// This needs to be checked
	// It annoyingly shows the spellbook
	// whenever you add a scroll
	// << could it be that addItemToContainer is enough?? >>
	if( pCont->type() == 9 )
		Magic->openSpellBook( pChar, pCont );*/
}
// May a character walk here ?
// If yes we auto. set the new z value for pos
bool mayWalk( P_CHAR pChar, Coord_cl& pos )
{
	// Go trough the array top-to-bottom and check
	// If we find a tile to walk on
	vector<stBlockItem> blockList = getBlockingItems( pChar, pos );
	bool found = false;
	Q_UINT32 i;
	bool priviledged = false;
	Q_INT32 oldz = pos.z;

	P_PLAYER player = dynamic_cast<P_PLAYER>( pChar );

	priviledged = player && player->isGM();

	for ( i = 0; i < blockList.size(); ++i )
	{
		stBlockItem item = blockList[i];
		Q_INT8 itemTop = ( item.z + item.height );

		// If we encounter any object with itemTop <= pos.z which is NOT walkable
		// Then we can as well just return false as while falling we would be
		// blocked by that object
		if ( !item.walkable && !priviledged && itemTop < pos.z )
			return false;

		if ( item.walkable || priviledged ) {
			// If the top of the item is within our max-climb reach
			// then the first check passed. in addition we need to
			// check if the "bottom" of the item is reachable
			// I would say 2 is a good "reach" value for the bottom
			// of any item
			if ( itemTop < pos.z + P_M_MAX_Z_CLIMB && itemTop >= pos.z - P_M_MAX_Z_FALL ) {
				pos.z = itemTop;
				found = true;
				break;
			// Climbing maptiles is 5 tiles easier
			} else if ( item.maptile && itemTop < pos.z + P_M_MAX_Z_CLIMB + 5 && itemTop >= pos.z - P_M_MAX_Z_FALL ) {
				pos.z = itemTop;
				found = true;
				break;
			}
		}
	}

	if ( priviledged )
	{
		return true;
	}

	// If we're still at the same position
	// We didn't find anything to step on
	if ( !found )
		return false;

	// Another loop *IS* needed here (at least that's what i think)
	for ( i = 0; i < blockList.size(); ++i )
	{
		// So we know about the new Z position we are moving to
		// Lets check if there is enough space ABOVE that position (at least 15 z units)
		// If there is ANY impassable object between pos.z and pos.z + 15 we can't walk here
		stBlockItem item = blockList[i];
		Q_INT8 itemTop = ( item.z + item.height );

		// If the item is below what we step on, ignore it
		if (itemTop <= pos.z) {
			continue;
		}

		// Does the top of the item looms into our space
		// Like before 15 is the assumed height of ourself
		// Use the new position here.
		if ( ( itemTop > pos.z ) && ( itemTop < pos.z + P_M_MAX_Z_BLOCKS ) )
			return false;

		// Or the bottom ?
		// if ( ( item.z > oldz ) && ( item.z < oldz + P_M_MAX_Z_BLOCKS ) )
		//	return false;

		// Or does it spread the whole range ?
		if ( ( item.z <= oldz ) && ( itemTop >= oldz + P_M_MAX_Z_BLOCKS ) )
			return false;
	}

	// All Checks passed
	return true;
}
Example #10
0
void cSkills::SkillUse( cUOSocket* socket, Q_UINT16 id ) // Skill is clicked on the skill list
{
	P_PLAYER pChar = socket->player();

	// No Char no Skill use
	if ( !pChar )
		return;

	/* TODO: reimplementation of jail system
		if( pChar->cell() > 0 )
		{
			socket->sysMessage( tr( "You are in jail and cant use skills here!" ) );
			return;
		}
	*/

	if ( pChar->isDead() )
	{
		socket->sysMessage( tr( "You cannot do that as a ghost." ) );
		return;
	}

	if ( id != STEALTH )
		pChar->unhide(); // Don't unhide if we're trying to stealth

	pChar->disturbMed(); // Disturb meditation if we're using a skill

	if ( pChar->isCasting() )
	{
		socket->sysMessage( tr( "You can't do that while you are casting." ) );
		return;
	}

	if ( pChar->skillDelay() > Server::instance()->time() && !pChar->isGM() )
	{
		socket->sysMessage( tr( "You must wait a few moments before using another skill." ) );
		return;
	}

	if ( pChar->onSkillUse( id ) )
		return;

	cTargetRequest* targetRequest = NULL;
	QString message;

	switch ( id )
	{
	case MEDITATION:
		Skills::instance()->Meditation( socket );
		break;
	default:
		socket->sysMessage( tr( "That skill has not been implemented yet." ) );
		return;
	}

	if ( targetRequest )
		socket->attachTarget( targetRequest );

	if ( !message.isEmpty() )
		pChar->message( message );

	pChar->setSkillDelay( Server::instance()->time() + Config::instance()->skillDelay() * MY_CLOCKS_PER_SEC );
}
void cNewMagic::castSpell( P_PLAYER pMage, UINT8 spell )
{
	P_PLAYER pp = dynamic_cast<P_PLAYER>(pMage);

	if( !pp || !pp->socket() )
		return;

	stNewSpell *sInfo = findSpell( spell );

	if( !sInfo )
	{
		pp->socket()->sysMessage( tr( "This spell is either not implemented or invalid" ) );
		return;
	}

	// Check if we can cast this spell
	if( !hasSpell( pMage, spell ) )
	{
		pp->socket()->sysMessage( tr( "You don't know this spell." ) );
		return;
	}

	// Check for required mana and required reagents, if not present: cancel casting
	if( !checkMana( pMage, spell ) )
	{
		pp->message( tr( "You don't have enough mana to cast this spell." ) );
		return;
	}
	
	if( !pp->isGM() && !checkReagents( pMage, spell ) )
		return;

	if( pMage->isCasting() )
		disturb( pMage, true );

	// We start casting here
	pMage->setCasting( true );

	// We get frozen here too
	pMage->setFrozen( true );

	// Say the mantra
	// Type 0x0A : Spell
	pMage->talk( sInfo->mantra, pMage->saycolor() );

	// This is a very interesting move of OSI 
	// They send all action-packets the character has to perform in a row. 
	// But they use the action 0xE9 instead of 0x10, maybe it's a bitmask 
	// of 0xD9 but i am unsure. 
	// This will repeat the animation until
	// We are done casting or until we are being
	// disturbed.
	//pMage->startRepeatedAction( sInfo->action, sInfo->actiondelay ); // Repeat every 1250 ms
	// I *do* know that this is a drawback but for now a single animation is exactly what we need.
	pMage->action( sInfo->action );

	// Now we have to do the following: 
	// We show the target cursor after a given amount of time (set in the scripts)
	// So what we are adding here is cEndCasting() supplying the Serial of our Mage 
	// And the ID of our Spell.
	TempEffects::instance()->insert( new cEndCasting( pMage, spell, CT_BOOK, sInfo->delay ) );
}
void DragAndDrop::dropOnItem( cUOSocket* socket, P_ITEM pItem, P_ITEM pCont, const Coord_cl& dropPos )
{
	P_PLAYER pChar = socket->player();

	if ( pItem->isMulti() )
	{
		socket->sysMessage( tr( "You cannot put houses in containers" ) );
		cUOTxBounceItem bounce;
		bounce.setReason( BR_NO_REASON );
		socket->send( &bounce );
		pItem->remove();
		return;
	}

	if ( pItem->onDropOnItem( pCont ) )
	{
		if ( pItem->free )
			return;

		if ( socket->dragging() )
			socket->bounceItem( socket->dragging(), BR_NO_REASON );

		return;
	}
	else if ( pCont->onDropOnItem( pItem ) )
	{
		if ( pItem->free )
			return;

		if ( socket->dragging() )
			socket->bounceItem( socket->dragging(), BR_NO_REASON );

		return;
	}

	// If the target belongs to another character
	// It needs to be our vendor or else it's denied
	P_CHAR packOwner = pCont->getOutmostChar();

	if ( ( packOwner ) && ( packOwner != pChar ) && !pChar->isGM() )
	{
		// For each item someone puts into there
		// He needs to do a snoop-check
		if ( pChar->maySnoop() )
		{
			if ( !pChar->checkSkill( SNOOPING, 0, 1000 ) )
			{
				socket->sysMessage( tr( "You fail to put that into %1's pack" ).arg( packOwner->name() ) );
				socket->bounceItem( pItem, BR_NO_REASON );
				return;
			}
		}

		if ( packOwner->objectType() == enPlayer || ( packOwner->objectType() == enNPC && dynamic_cast<P_NPC>( packOwner )->owner() != pChar ) )
		{
			socket->sysMessage( tr( "You cannot put that into the belongings of another player" ) );
			socket->bounceItem( pItem, BR_NO_REASON );
			return;
		}
	}

	if ( !pChar->canPickUp( pItem ) )
	{
		socket->bounceItem( pItem, BR_CANNOT_PICK_THAT_UP );
		return;
	}

	// We drop something on the belongings of one of our playervendors
	/*	if( ( packOwner != NULL ) && ( packOwner->npcaitype() == 17 ) && packOwner->owner() == pChar )
	{
	socket->sysMessage( tr( "You drop something into your playervendor (unimplemented)" ) );
	socket->bounceItem( pItem, BR_NO_REASON );
	return;
	}*/

	// Playervendors (chest equipped by the vendor - opened to the client)

	/*if( !( pCont->pileable() && pItem->pileable() && pCont->id() == pItem->id() || ( pCont->type() != 1 && pCont->type() != 9 ) ) )
	{
	P_CHAR pc_j = GetPackOwner(pCont);
	if (pc_j != NULL)
	{
	if (pc_j->npcaitype() == 17 && pc_j->isNpc() && pChar->Owns(pc_j))
	{
	pChar->inputitem = pItem->serial;
	pChar->inputmode = cChar::enPricing;
	sysmessage(s, "Set a price for this item.");
	}
	}
	*/

	// We may also drop into *any* locked chest
	// So we can have post-boxes ;o)
	if ( pCont->type() == 1 )
	{
		// If we're dropping it onto the closed container
		if ( dropPos.x == 0xFFFF && dropPos.y == 0xFFFF )
		{
			pCont->addItem( pItem );
		}
		else
		{
			pCont->addItem( pItem, false );
			pItem->setPos( dropPos );
		}

		// Dropped on another Container/in another Container
		pChar->soundEffect( 0x57 );
		pItem->update();
		return;
	}
	else if ( pCont->canStack( pItem ) )
	{
		if ( pCont->amount() + pItem->amount() <= 65535 )
		{
			pCont->setAmount( pCont->amount() + pItem->amount() );

			pItem->remove();
			pCont->update(); // Need to update the amount
			pCont->resendTooltip();
			return;
		}
		else
		{
			// The delta between 65535 and pCont->amount() sub our Amount is the
			// new amount
			pItem->setAmount( pItem->amount() - ( 65535 - pCont->amount() ) );
			pItem->resendTooltip();

			pCont->setAmount( 65535 ); // Max out the amount
			pCont->update();
			pCont->resendTooltip();
		}
	}

	// We dropped the item NOT on a container
	// And were *un*able to stack it (!)
	// >> Set it to the location of the item we dropped it on and stack it up by 2
	if ( pCont->container() )
	{
		P_ITEM pNewCont = dynamic_cast<P_ITEM>( pCont->container() );

		if ( pNewCont )
		{
			pNewCont->addItem( pItem, false );
			pItem->setPos( pCont->pos() + Coord_cl( 0, 0, 2 ) );
		}
		else
		{
			pChar->getBackpack()->addItem( pItem );
		}
	}
	else
	{
		pItem->removeFromCont();
		pItem->moveTo( pCont->pos() + Coord_cl( 0, 0, 2 ) );
	}

	pItem->update();
}
// New Class implementation
void DragAndDrop::grabItem( cUOSocket* socket, cUORxDragItem* packet )
{
	// Get our character
	P_PLAYER pChar = socket->player();
	if ( !pChar )
		return;

	float weight = pChar->weight();

	// Fetch the grab information
	UI16 amount = packet->amount();
	if ( !amount )
		amount = 1;

	P_ITEM pItem = FindItemBySerial( packet->serial() );

	// If it's an invalid pointer we can't even bounce
	if ( !pItem )
		return;

	// Are we already dragging an item ?
	// Bounce it and reject the move
	// (Logged out while dragging an item)
	if ( socket->dragging() )
	{
		socket->bounceItem( socket->dragging(), BR_ALREADY_DRAGGING );
		return;
	}

	// Check if the item can be reached
	if (pItem->getOutmostChar() != pChar && !pChar->lineOfSight(pItem)) {
		socket->bounceItem( pItem, BR_OUT_OF_REACH );
		return;
	}

	if ( pItem->onPickup( pChar ) )
		return;

	if ( pChar->onPickup( pItem ) )
		return;

	// Do we really want to let him break his meditation
	// When he picks up an item ?
	// Maybe a meditation check here ?!?
	pChar->disturbMed(); // Meditation

	P_CHAR itemOwner = pItem->getOutmostChar();

	// Try to pick something out of another characters posessions
	if ( !pChar->isGM() && itemOwner && ( itemOwner != pChar ) && ( itemOwner->objectType() == enNPC && dynamic_cast<P_NPC>( itemOwner )->owner() != pChar ) )
	{
		socket->bounceItem( pItem, BR_BELONGS_TO_SOMEONE_ELSE );
		return;
	}

	// Check if the user can grab the item
	if ( !pChar->canPickUp( pItem ) )
	{
		socket->bounceItem( pItem, BR_CANNOT_PICK_THAT_UP );
		return;
	}

	// The user can't see the item
	// Basically thats impossible as the socket should deny moving the item
	// if it's not in line of sight but to prevent exploits
	/*if( !line_of_sight( socket->socket(), pChar->pos, pItem->pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) )
	{
		socket->sysMessage( "You can't see the item." );
		bounceItem( socket, pItem, true );
		return;
	}*/

	P_ITEM outmostCont = pItem->getOutmostItem();

	// If the top-most container ( thats important ) is a corpse
	// and looting is a crime, flag the character criminal.
	if ( !pChar->isGM() && outmostCont && outmostCont->corpse() )
	{
		// For each item we take out we loose carma
		// if the corpse is innocent and not in our guild
		bool sameGuild = true;//( GuildCompare( pChar, outmostCont->owner() ) != 0 );

		if ( outmostCont->hasTag( "notoriety" ) && outmostCont->getTag( "notoriety" ).toInt() == 1 && !pChar->owns( outmostCont ) && !sameGuild )
		{
			//			pChar->karma -= 5;
			pChar->setKarma( pChar->karma() - 5 );
			pChar->setCriminalTime( Server::instance()->time() + Config::instance()->crimtime() * MY_CLOCKS_PER_SEC );
			socket->sysMessage( tr( "You lost some karma." ) );
		}
	}

	// Check if the item is too heavy
	//if( !pc_currchar->isGMorCounselor() )
	//{
	//} << Deactivated (DarkStorm)

	// ==== Grabbing the Item is allowed here ====

	// Send the user a pickup sound if we're picking it up
	// From a container/paperdoll
	if ( !pItem->isInWorld() )
		socket->soundEffect( 0x57, pItem );

	// If we're picking up a specific amount of what we got
	// Take that into account
	if ( amount < pItem->amount() )
	{
		UI32 pickedAmount = QMIN( amount, pItem->amount() );

		// We only have to split if we're not taking it all
		if ( pickedAmount != pItem->amount() )
		{
			P_ITEM splitItem = pItem->dupe(); // Create a new item to pick that up
			splitItem->setAmount( pItem->amount() - pickedAmount );

			// Add tags to the splitted item
			QStringList keys = pItem->getTags();
			QStringList::const_iterator it = keys.begin();
			for ( ; it != keys.end(); ++it )
			{
				splitItem->setTag( *it, pItem->getTag( *it ) );
			}

			P_ITEM pContainer = dynamic_cast<P_ITEM>( pItem->container() );
			if ( pContainer )
				pContainer->addItem( splitItem, false );
			splitItem->SetOwnSerial( pItem->ownSerial() );

			splitItem->setSpawnregion( pItem->spawnregion() );

			// He needs to see the new item
			splitItem->update();

			// If we're taking something out of a spawn-region it's spawning "flag" is removed isn't it?
			pItem->setAmount( pickedAmount );
		}
	}

	// *normally* we should exclude the dragging socket here. but it works so as well.
	pItem->removeFromView( true );

	// Remove from spawnregion
	pItem->setSpawnregion( 0 );

	// Remove it from the World if it is in world, otherwise remove it from it's current container
	if ( pItem->isInWorld() )
		MapObjects::instance()->remove( pItem );
	else
		pItem->removeFromCont( true );

	// Remove eventual item-bonusses if we're unequipping something
	if ( pItem->container() && pItem->container()->isChar() )
	{
		P_CHAR wearer = dynamic_cast<P_CHAR>( pItem->container() );

		// resend the stat window
		if ( wearer && wearer->objectType() == enPlayer )
		{
			P_PLAYER pp = dynamic_cast<P_PLAYER>( wearer );
			if ( pp->socket() )
				pp->socket()->sendStatWindow();
		}
	}

	pChar->addItem( cBaseChar::Dragging, pItem );

	if ( weight != pChar->weight() )
	{
		socket->sendStatWindow();
	}
}
void DragAndDrop::equipItem( cUOSocket* socket, cUORxWearItem* packet )
{
	P_ITEM pItem = FindItemBySerial( packet->serial() );
	P_CHAR pWearer = FindCharBySerial( packet->wearer() );

	if ( !pItem || !pWearer )
		return;

	P_PLAYER pChar = socket->player();

	// We're dead and can't do that
	if ( pChar->isDead() )
	{
		socket->clilocMessage( 0x7A4D5, "", 0x3b2 ); // You can't do that when you're dead.
		socket->bounceItem( pItem, BR_NO_REASON );
		return;
	}

	// No Special Layer Equipping
	if ( ( packet->layer() > cBaseChar::InnerLegs || packet->layer() <= cBaseChar::TradeWindow ) && !pChar->isGM() )
	{
		socket->sysMessage( tr( "You can't equip on that layer." ) );
		socket->bounceItem( pItem, BR_NO_REASON );
		return;
	}

	// Our target is dead
	if ( ( pWearer != pChar ) && pWearer->isDead() )
	{
		socket->sysMessage( tr( "You can't equip dead players." ) );
		socket->bounceItem( pItem, BR_NO_REASON );
		return;
	}

	// Only GM's can equip other People
	if ( pWearer != pChar && !pChar->isGM() )
	{
		P_NPC pNpc = dynamic_cast<P_NPC>( pWearer );

		// But we are allowed to equip our own humans
		if ( !pNpc || ( pNpc->owner() != pChar && pWearer->isHuman() ) )
			socket->sysMessage( tr( "You can't equip other players." ) );

		socket->bounceItem( pItem, BR_NO_REASON );
		return;
	}

	// Get our tile-information
	tile_st pTile = TileCache::instance()->getTile( pItem->id() );

	// Is the item wearable ? ( layer == 0 | equip-flag not set )
	// Multis are not wearable are they :o)
	if ( pTile.layer == 0 || !( pTile.flag3 & 0x40 ) || pItem->isMulti() )
	{
		socket->sysMessage( tr( "This item cannot be equipped." ) );
		socket->bounceItem( pItem, BR_NO_REASON );
		return;
	}

	// Check the Script for it
	if ( pItem->onWearItem( pChar, pWearer, packet->layer() ) )
	{
		socket->bounceItem( pItem, BR_NO_REASON );
		return;
	}

	// Males can't wear female armor
	if ( ( pChar->body() == 0x0190 ) && ( pItem->id() >= 0x1C00 ) && ( pItem->id() <= 0x1C0D ) )
	{
		socket->sysMessage( tr( "You cannot wear female armor." ) );
		socket->bounceItem( pItem, BR_NO_REASON );
		return;
	}

	// Needs a check (!)
	// Checks for equipment on the same layer
	// If there is any it tries to unequip it
	// If that fails it cancels
	// we also need to check if there is a twohanded weapon if we want to equip another weapon.
	UI08 layer = pTile.layer;

	P_ITEM equippedLayerItem = pWearer->atLayer( static_cast<cBaseChar::enLayer>( layer ) );

	// we're equipping so we do the check
	if ( equippedLayerItem )
	{
		if ( pChar->canPickUp( equippedLayerItem ) )
		{
			equippedLayerItem->toBackpack( pWearer );
		}
		else
		{
			socket->sysMessage( tr( "You can't wear another item there!" ) );
			socket->bounceItem( pItem, BR_NO_REASON );
			return;
		}
	}

	// Check other layers if neccesary
	bool occupied = false;

	if ( pItem->twohanded() && layer == 1 )
	{
		occupied = pWearer->leftHandItem() != 0;  // Twohanded weapon on layer 1 forbids item on layer 2
	}
	else if ( pItem->twohanded() && layer == 2 )
	{
		occupied = pWearer->rightHandItem() != 0;  // Twohanded weapon on layer 2 forbids item on layer 1
	}
	else if ( layer == 1 )
	{
		P_ITEM lefthand = pWearer->leftHandItem();
		occupied = lefthand && lefthand->twohanded();
	}
	else if ( layer == 2 )
	{
		P_ITEM righthand = pWearer->rightHandItem();
		occupied = righthand && righthand->twohanded();
	}

	if ( occupied )
	{
		socket->sysMessage( tr( "You can't hold another item while wearing a twohanded item!" ) );
		socket->bounceItem( pItem, BR_NO_REASON );
		return;
	}

	// At this point we're certain that we can wear the item
	pWearer->addItem( static_cast<cBaseChar::enLayer>( pTile.layer ), pItem );

	if ( pWearer->objectType() == enPlayer )
	{
		P_PLAYER pp = dynamic_cast<P_PLAYER>( pWearer );
		if ( pp->socket() )
			pp->socket()->sendStatWindow();
	}

	// I don't think we need to remove the item
	// as it's only visible to the current char
	// And he looses contact anyway

	// Build our packets
	cUOTxCharEquipment wearItem;
	wearItem.fromItem( pItem );

	cUOTxSoundEffect soundEffect;
	soundEffect.setSound( 0x57 );
	soundEffect.setCoord( pWearer->pos() );

	// Send to all sockets in range
	// ONLY the new equipped item and the sound-effect
	for ( cUOSocket*mSock = Network::instance()->first(); mSock; mSock = Network::instance()->next() )
	{
		if ( mSock->player() && ( mSock->player()->dist( pWearer ) <= mSock->player()->visualRange() ) )
		{
			mSock->send( &wearItem );
			mSock->send( &soundEffect );
		}
	}
}
Example #15
0
void cSkills::SkillUse( cUOSocket* socket, quint16 id ) // Skill is clicked on the skill list
{
	P_PLAYER pChar = socket->player();

	// No Char no Skill use
	if ( !pChar )
		return;

	if ( pChar->isJailed() ) {
		socket->sysMessage( tr("You cannot use skills while you are in jail.") );
		return;
	}

	if ( pChar->isDead() )
	{
		socket->clilocMessage( 1019048 ); // I am dead and cannot do that.
		return;
	}

	/*
	if ( id != STEALTH )
		pChar->unhide(); // Don't unhide if we're trying to stealth
	*/

	pChar->disturbMed(); // Disturb meditation if we're using a skill

	if ( pChar->isCasting() )
	{
		socket->sysMessage( 1061131 ); // You cannot do that while casting a spell.
		return;
	}

	if ( pChar->skillDelay() > Server::instance()->time() && !pChar->isGM() )
	{
		socket->sysMessage( 500118 ); // You must wait a few moments to use another skill.
		return;
	}

	if ( pChar->onSkillUse( id ) )
		return;

	cTargetRequest* targetRequest = NULL;
	QString message;

	switch ( id )
	{
	case MEDITATION:
		Skills::instance()->Meditation( socket );
		break;
	default:
		socket->sysMessage( tr( "That skill has not been implemented yet." ) );
		return;
	}

	if ( targetRequest )
		socket->attachTarget( targetRequest );

	if ( !message.isEmpty() )
		pChar->message( message );

	pChar->setSkillDelay( Server::instance()->time() + Config::instance()->skillDelay() * MY_CLOCKS_PER_SEC );
}