Example #1
0
/////////////////
// name:	response
// purpose:	tries to get a response from an npc standing around
// history:	heavily revamped/rewritten by Duke, Oct 2001
// remark:	The new logic tries to minimize the # of strstr() calls by *first* checking
//			what kind of npcs are standing around and then checking only those keywords
//			that they might be interested in.
//			This is especially usefull in crowded places.
bool Speech::response( cUOSocket* socket, P_PLAYER pPlayer, const QString& comm, QValueVector<Q_UINT16>& keywords )
{
	if ( !pPlayer->socket() || pPlayer->isDead() )
	{
		return false;
	}

	QString speechUpr = comm.upper();

	MapCharsIterator ri = MapObjects::instance()->listCharsInCircle( pPlayer->pos(), 18 );
	for ( P_CHAR pChar = ri.first(); pChar; pChar = ri.next() )
	{
		P_NPC pNpc = dynamic_cast<P_NPC>( pChar );

		// We will only process NPCs here
		if ( !pNpc )
			continue;

		// at least they should be on the screen
		if ( pPlayer->dist( pNpc ) > 16 )
			continue;

		if ( pNpc->canHandleEvent( EVENT_SPEECH ) )
		{
			PyObject* pkeywords = PyTuple_New( keywords.size() );

			// Set Items
			for ( unsigned int i = 0; i < keywords.size(); ++i )
				PyTuple_SetItem( pkeywords, i, PyInt_FromLong( keywords[i] ) );

			PyObject* args = Py_BuildValue( "(NNNO)", pNpc->getPyObject(), pPlayer->getPyObject(), QString2Python( comm ), pkeywords );

			bool result = pNpc->callEventHandler( EVENT_SPEECH, args );

			Py_DECREF( args );
			Py_DECREF( pkeywords );

			if ( result )
				return true;
		}

		if ( pNpc->ai() )
		{
			pNpc->ai()->onSpeechInput( pPlayer, speechUpr );
		}

		if ( QuestionSpeech( socket, pPlayer, pNpc, speechUpr ) )
			return true;
	}

	return false;
}
/*!
  Calculates the amount of Stamina needed for a move of the
  passed character.
*/
bool cMovement::consumeStamina( P_PLAYER pChar, bool running )
{
	// Dead people and gms don't care about weight
	if ( pChar->isDead() || pChar->isGMorCounselor() )
	{
		return true;
	}

	// Calculate the stones we weight too much
	int overWeight = ( int ) ( pChar->weight() - pChar->maxWeight() );
	bool mounted = pChar->atLayer( cBaseChar::Mount ) != 0;
	bool update = false;

	// We carry too much
	if ( overWeight > 0 )
	{
		// How much stamina we loose
		int amount = 5 + ( overWeight / 25 );

		// Only one third loss if mounted
		if ( mounted )
		{
			amount = amount / 3;
		}

		// Double loss if running
		if ( running )
		{
			amount = amount * 2;
		}

		// Set the new stamina
		pChar->setStamina( wpMax<Q_INT16>( 0, pChar->stamina() - amount ), false );
		update = true;

		// We are overloaded
		if ( pChar->stamina() == 0 )
		{
			pChar->socket()->updateStamina();
			pChar->socket()->clilocMessage( 500109 );
			return false;
		}
	}

	// If we have less than 10% stamina left, we loose
	// stamina more quickly
	if ( ( pChar->stamina() * 100 ) / wpMax<ushort>( 1, pChar->maxStamina() ) < 10 )
	{
		pChar->setStamina( wpMax<Q_INT16>( 0, pChar->stamina() - 1 ), false );
		update = true;
	}

	// We can't move anymore because we are exhausted
	if ( pChar->stamina() == 0 )
	{
		pChar->socket()->updateStamina();
		pChar->socket()->clilocMessage( 500110 );
		return false;
	}

	// Normally reduce stamina every few steps
	if ( pChar->stepsTaken() % ( mounted ? 48 : 16 ) == 0 )
	{
		pChar->setStamina( wpMax<Q_INT16>( 0, pChar->stamina() - 1 ) );
		update = true;
	}

	if ( update )
	{
		pChar->socket()->updateStamina();
	}

	return true;
}
Example #3
0
void cSpeech::talking( P_PLAYER pChar, const QString &lang, const QString &speech, QValueVector< UINT16 > &keywords, UINT16 color, UINT16 font, UINT8 type ) // PC speech
{	
	// handle things like renaming or describing an item
	if( !pChar->socket() )
		return;

	cUOSocket *socket = pChar->socket();

	if( InputSpeech( socket, pChar, speech ) )	
		return;

	// not allowed to talk
	if( pChar->isMuted() )
	{
		socket->sysMessage( tr( "You re squelched and cannot talk" ) );
		return;
	}

	pChar->unhide();
		
	// Check for Bogus Color
	if( !isNormalColor( color ) )
		color = 0x2;

	if( type == 0 || type == 2)
		pChar->setSaycolor( color );

	if( SrvParams->speechLog() )
	{
		QFile lFile( "speech.log" );
		
		if( lFile.open( IO_Append ) )
		{
			QString logMessage( "[%1] %2: %3 [%4, 0x%5]" );
			logMessage = logMessage.arg( QDateTime::currentDateTime().toString() ).arg( pChar->name() ).arg( speech ).arg( pChar->account()->login() ).arg( pChar->serial(), 8, 16 );
			lFile.writeBlock( logMessage.latin1(), logMessage.length() );
			lFile.close();
		}
	}

	if( pChar->onTalk( type, color, font, speech, lang ) )
		return;

	if( ( type == 0x09 ) && ( pChar->mayBroadcast() ) )
	{
		pChar->talk( speech, color, type );
		return;
	}

	pChar->talk( speech, color, type );
		
	QString speechUpr = speech.upper();
	if( response( socket, pChar, speech, keywords ) )
		return;  // Vendor responded already
	
	// 0x0007 -> Speech-id for "Guards"
	for( QValueVector< UINT16 >::const_iterator iter = keywords.begin(); iter != keywords.end(); ++iter )
	{
		UINT16 keyword = *iter;

		if( keyword == 0x07 )
			pChar->callGuards();
	}
	
	// well,i had a strange problem with duplicate speech input
	// its quite easy to understand....
	// the former loop searched for the tiller man and when it
	// was found, the speechInput method of that boat was called.
	// in this method the tiller had been removed from the mapregion
	// and appended to the end of the cell vector... hence, the
	// tiller was found twice...
	// therefore we produce a QPtrList of cBoat* pointers and 
	// then go through it for applying speech --- sereg
	RegionIterator4Items rj( pChar->pos() );
	QPtrList< cBoat >	pboats;
	for( rj.Begin(); !rj.atEnd(); rj++ )
	{
		P_ITEM pi = rj.GetData();

		if( !pi )
			continue;

		if( pi->type() == 117 && pi->tags().get( "tiller" ).toInt() == 1 )
		{
			cBoat* pBoat = dynamic_cast< cBoat* >(FindItemBySerial( pi->tags().get("boatserial").toInt() ));
			if( pBoat )
				pboats.append( pBoat );
		}
	}
	QPtrListIterator< cBoat >	pit( pboats );
	while( pit.current() )
	{
		pit.current()->speechInput( socket, speechUpr );
		++pit;
	}

	// this makes it so npcs do not respond to isDead people - HEALERS ??
	if( pChar->isDead() )
		return;
	
/*	P_CHAR pc = NULL; ???
	P_CHAR pNpc = NULL;
	RegionIterator4Chars ri( pChar->pos() );
	for( ri.Begin(); !ri.atEnd(); ri++ )
	{	
		pc = ri.GetData();
		if (!pc->isSameAs( pChar ) 
			&& pc->isNpc()
			&& pc->dist( pChar ) <= 2)
		{
			pNpc = pc;
			break;
		}
	}
	*/
}
Example #4
0
/////////////////
// name:	response
// purpose:	tries to get a response from an npc standing around
// history:	heavily revamped/rewritten by Duke, Oct 2001
// remark:	The new logic tries to minimize the # of strstr() calls by *first* checking
//			what kind of npcs are standing around and then checking only those keywords
//			that they might be interested in.
//			This is especially usefull in crowded places.
bool cSpeech::response( cUOSocket *socket, P_PLAYER pPlayer, const QString& comm, QValueVector< UINT16 > &keywords )
{
    if( !pPlayer->socket() || pPlayer->isDead() )
		return false;

	QString speechUpr = comm.upper();

	RegionIterator4Chars ri( pPlayer->pos() );
	for( ri.Begin(); !ri.atEnd(); ri++ )
	{
		P_NPC pNpc = dynamic_cast<P_NPC>(ri.GetData());

		// We will only process NPCs here
		if( !pNpc )
			continue;

		// at least they should be on the screen
		if( pPlayer->dist( pNpc ) > 16 )
			continue;

		// Check if the NPC has a script that can handle 
		// speech events and then check if it can handle everything
		// or just certain things
		std::vector< WPDefaultScript* > events = pNpc->getEvents();
		for( std::vector< WPDefaultScript* >::const_iterator iter = events.begin(); iter != events.end(); ++iter )
		{
			WPDefaultScript *script = *iter;
			if( !script->handleSpeech() )
				continue;

			if( script->catchAllSpeech() || script->canHandleSpeech( comm, keywords ) )
				if( script->onSpeech( pNpc, pPlayer, comm, keywords ) )
					return true;
		}

		cNPC_AI* pAI = pNpc->ai();
		if( pAI && pAI->currState() )
		{
			pAI->currState()->speechInput( pPlayer, speechUpr );
			pAI->updateState();
		}

		if( BankerSpeech( socket, pPlayer, pNpc, speechUpr ) )
			return true;

		if( PetCommand( socket, pPlayer, pNpc, speechUpr ) )
			return true;

		if( StableSpeech( socket, pPlayer, pNpc, speechUpr ) )
			return true;
		
		if( UnStableSpeech( socket, pPlayer, pNpc, speechUpr ) )
			return true;
		
		if( ShieldSpeech( socket, pPlayer, pNpc, speechUpr ) )
			return true;
		
		if( QuestionSpeech( socket, pPlayer, pNpc, speechUpr ) )
			return true;
		
		if( TrainerSpeech( socket, pPlayer, pNpc, speechUpr ) )
			return true;
		
		if( PlayerVendorSpeech( socket, pPlayer, pNpc, speechUpr ) )
			return true;
		
	}
	
	return false;
}
void cDragItems::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;
	}

	// 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;
	}

	// 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;
	}

	// Required Strength
	if( pItem->st() > pWearer->strength() )
	{
		if( pWearer == pChar )
			socket->sysMessage( tr( "You cannot wear that item, you seem not strong enough" ) );
		else
			socket->sysMessage( tr( "This person can't wear that item, it seems not strong enough" ) );

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

	// Required Dexterity
	if( pItem->dx() > pWearer->dexterity() )
	{
		if( pWearer == pChar )
			socket->sysMessage( tr( "You cannot wear that item, you seem not agile enough" ) );
		else
			socket->sysMessage( tr( "This person can't wear that item, it seems not agile enough" ) );

		socket->bounceItem( pItem, BR_NO_REASON );
		return;
	}
	
	// Required Intelligence
	if( pItem->in() > pWearer->intelligence() )
	{
		if( pWearer == pChar )
			socket->sysMessage( tr( "You cannot wear that item, you seem not smart enough" ) );
		else
			socket->sysMessage( tr( "This person can't wear that item, it seems not smart enough" ) );

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

	// Males can't wear female armor
	if( ( pChar->bodyID() == 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;

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

	if( twohanded && ( layer == 1 || layer == 2 ) )
	{
		socket->sysMessage( tr("You can't hold another item while wearing a twohanded weapon!") );
		socket->bounceItem( pItem, BR_NO_REASON );
		return;
	}

	// 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;
		}
	}

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

	// Apply the bonuses
	pWearer->giveItemBonus( 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 = cNetwork::instance()->first(); mSock; mSock = cNetwork::instance()->next() )
	{
		if( mSock->player() && ( mSock->player()->dist( pWearer ) <= mSock->player()->visualRange() ) )
		{
			mSock->send( &wearItem );
			mSock->send( &soundEffect );
		}
	}
}
Example #6
0
void Speech::talking( P_PLAYER pChar, const QString& lang, const QString& speech, QValueVector<Q_UINT16>& keywords, Q_UINT16 color, Q_UINT16 font, Q_UINT8 type ) // PC speech
{
	// handle things like renaming or describing an item
	if ( !pChar->socket() )
		return;

	cUOSocket* socket = pChar->socket();

	if ( InputSpeech( socket, pChar, speech ) )
		return;

	pChar->unhide();

	// Check for Bogus Color
	if ( !isNormalColor( color ) )
		color = 0x2;

	if ( type == 0 )
		pChar->setSaycolor( color );
	else if ( type == 2 )
		pChar->setEmoteColor( color );

	if ( pChar->onTalk( type, color, font, speech, lang ) )
		return;

	if ( ( type == 0x09 ) && ( pChar->mayBroadcast() ) )
	{
		pChar->talk( speech, color, type );
		return;
	}

	pChar->talk( speech, color, type );

	QString speechUpr = speech.upper();
	if ( response( socket, pChar, speech, keywords ) )
		return;  // Vendor responded already

	// this makes it so npcs do not respond to isDead people - HEALERS ??
	if ( pChar->isDead() )
		return;

	// 0x0007 -> Speech-id for "Guards"
	for ( QValueVector<Q_UINT16>::const_iterator iter = keywords.begin(); iter != keywords.end(); ++iter )
	{
		Q_UINT16 keyword = *iter;

		if ( keyword == 0x07 )
			pChar->callGuards();
	}

	/*	P_CHAR pc = NULL; ???
		P_CHAR pNpc = NULL;
		RegionIterator4Chars ri( pChar->pos() );
		for( ri.Begin(); !ri.atEnd(); ri++ )
		{
			pc = ri.GetData();
			if (!pc->isSameAs( pChar )
				&& pc->isNpc()
				&& pc->dist( pChar ) <= 2)
			{
				pNpc = pc;
				break;
			}
		}
		*/
}
Example #7
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 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 #9
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 );
}