void Human_Stablemaster::onSpeechInput( P_PLAYER pTalker, const QString& message ) { if ( !pTalker->socket() ) return; if ( m_npc->inRange( pTalker, 4 ) && ( VendorChkName( m_npc, message ) || message.contains( tr( "STABLEMASTER" ) ) ) ) { if ( message.contains( tr( " STABLE" ) ) ) { m_npc->talk( tr( "Which pet do you want me to stable?" ) ); pTalker->socket()->attachTarget( new cStableTarget( m_npc ) ); } else if ( message.contains( tr( " RELEASE" ) ) ) { int gold = pTalker->countBankGold() + pTalker->countGold(); P_ITEM pPack = m_npc->getBankbox(); cItem::ContainerContent stableitems; if ( pPack ) { cItem::ContainerContent content = pPack->content(); cItem::ContainerContent::const_iterator it( content.begin() ); while ( it != content.end() ) { if ( !( *it )->hasTag( "player" ) || !( *it )->hasTag( "pet" ) ) continue; if ( ( *it ) && ( uint )( *it )->getTag( "player" ).toInt() == pTalker->serial() ) stableitems.push_back( ( *it ) ); ++it; } } if ( !stableitems.empty() ) { cItem::ContainerContent::const_iterator it( stableitems.begin() ); while ( it != stableitems.end() ) { if ( ( *it ) ) { P_NPC pPet = dynamic_cast<P_NPC>( World::instance()->findChar( ( *it )->getTag( "pet" ).toInt() ) ); if ( pPet ) { pPet->free = false; // we need this for db saves pPet->setStablemasterSerial( INVALID_SERIAL ); pPet->moveTo( m_npc->pos() ); pPet->resend(); } ( *it )->remove(); } ++it; } pPack->update(); m_npc->talk( tr( "Here's your pet back!" ) ); } } } }
void cPlayer::addPet( P_NPC pPet, bool noOwnerChange ) { if ( !pPet ) return; // It may be the follower of someone else already, so // check that... if ( pPet->owner() && pPet->owner() != this ) pPet->owner()->removePet( pPet, true ); // Only reset the owner if we have slots left if ( pets_.size() + pPet->controlSlots() <= maxControlSlots() ) { pPet->setOwner( this, true ); // Check if it already is our follower CharContainer::iterator it = std::find( pets_.begin(), pets_.end(), pPet ); if ( it != pets_.end() ) return; pets_.push_back( pPet ); if ( socket_ ) { socket_->sendStatWindow(); } } }
void cCombat::spawnGuard( P_CHAR pOffender, P_CHAR pCaller, const Coord& pos ) { if ( !pOffender || !pCaller ) return; if ( pOffender->isDead() || pCaller->isDead() ) return; cTerritory* pRegion = pCaller->region(); if ( pRegion == NULL ) return; if ( pRegion->isGuarded() && Config::instance()->guardsActive() ) { QString guardsect = pRegion->getGuardSect(); P_NPC pGuard = ( guardsect.isNull() ? NULL : cNPC::createFromScript( guardsect, pos ) ); if ( !pGuard ) return; // Send guard to surrounding Players pGuard->resend( false ); pGuard->soundEffect( 0x1FE ); pGuard->effect( 0x372A, 0x09, 0x06 ); pGuard->fight( pOffender ); } }
void cSectorMaps::add( cUObject* object ) { // Very powerful statement. It completely // annihilates the need to check for // nullpointers in our object-map if ( !object ) return; if ( isItemSerial( object->serial() ) ) { P_ITEM pItem = dynamic_cast<P_ITEM>( object ); if ( pItem ) { Coord_cl pos = pItem->pos(); std::map<unsigned char, cSectorMap*>::const_iterator it = itemmaps.find( pos.map ); if ( it == itemmaps.end() ) throw QString( "Couldn't find a map with the id %1." ).arg( pos.map ); it->second->addItem( ( cUObject * ) pItem ); Timing::instance()->addDecayItem( pItem ); } } else if ( isCharSerial( object->serial() ) ) { // This is a safety check to make sure that // stabled pets don't appear on our sectormap P_NPC npc = dynamic_cast<P_NPC>( object ); if ( npc && npc->stablemasterSerial() != INVALID_SERIAL ) { return; } // The same check for players /*P_PLAYER player = dynamic_cast<P_PLAYER>( object ); if ( player && !player->socket() && !player->logoutTime() ) { return; }*/ P_CHAR pChar = dynamic_cast<P_CHAR>( object ); if ( pChar ) { Coord_cl pos = pChar->pos(); std::map<unsigned char, cSectorMap*>::const_iterator it = charmaps.find( pos.map ); if ( it == charmaps.end() ) throw QString( "Couldn't find a map with the id %1." ).arg( pos.map ); it->second->addItem( ( cUObject * ) pChar ); } } }
bool PlayerVendorSpeech( cUOSocket *socket, P_PLAYER pPlayer, P_NPC pVendor, const QString &comm ) { /* if( pVendor->npcaitype() != 17 ) return false;*/ if( pPlayer->dist( pVendor ) > 4 ) return false; if( !VendorChkName( pVendor, comm ) ) return false; if( ( comm.contains( " BROWSE" ) ) || ( comm.contains( " VIEW" ) ) || ( comm.contains( " LOOK" ) ) ) { pVendor->talk( tr( "Take a look at my goods." ) ); if( pPlayer->socket() ) pPlayer->socket()->sendContainer( pVendor->getBackpack() ); return true; } if( ( comm.contains( " BUY" ) ) || ( comm.contains( " PURCHASE" ) ) ) { // >> LEGACY /*addx[s]=pVendor->serial(); npctalk(s,pVendor,"What would you like to buy?",0); target(s,0,1,0,224," ");*/ return true; } if( pVendor->owner() != pPlayer ) return false; if( ( comm.contains( " COLLECT" ) ) || ( comm.contains( " GOLD" ) ) || ( comm.contains( " GET" ) ) ) { PlVGetgold( socket, pPlayer, pVendor); return true; } if( comm.contains( "PACKUP" ) ) { P_ITEM pDeed = Items->SpawnItem( pPlayer, 1, "employment deed", 0, 0x14F0, 0, 1 ); if( pDeed ) { pDeed->setType( 217 ); pDeed->setBuyprice( 2000 ); pDeed->setSellprice( 1000 ); pDeed->update(); cCharStuff::DeleteChar( pVendor ); socket->sysMessage( tr( "Packed up vendor %1." ).arg( pVendor->name() ) ); return true; } } return false; }
// do one spawn and reset the timer void cSpawnRegion::reSpawn( void ) { this->checkForDeleted(); UI16 i = 0; for( i = 0; i < this->npcsPerCycle_; i++ ) { if( this->npcSerials_.size() < this->maxNpcAmt_ ) { // spawn a random npc // first find a valid position for the npc Coord_cl pos; if( this->findValidSpot( pos ) ) { QString NpcSect = this->npcSections_[ RandomNum( 1, this->npcSections_.size() ) - 1 ]; P_NPC pc = cCharStuff::createScriptNpc( NpcSect, pos ); if( pc != NULL ) { this->npcSerials_.push_back( pc->serial() ); pc->setSpawnregion( this->name_ ); } } } } for( i = 0; i < this->itemsPerCycle_; i++ ) { if( this->itemSerials_.size() < this->maxItemAmt_ ) { // spawn a random item // first find a valid position for the item Coord_cl pos; if( this->findValidSpot( pos ) ) { QString ItemSect = this->itemSections_[ RandomNum( 1, this->itemSections_.size() ) - 1 ]; P_ITEM pi = cItem::createFromScript( ItemSect ); if( pi != NULL ) { pi->moveTo( pos ); this->itemSerials_.push_back( pi->serial() ); // pi->setSpawnRegion( this->name_ ); } } } } this->nextTime_ = uiCurrentTime + RandomNum( this->minTime_, this->maxTime_ ) * MY_CLOCKS_PER_SEC; }
void cSpawnRegion::spawnSingleNPC() { Coord_cl pos; if ( findValidSpot( pos ) ) { QString NpcSect = this->npcSections_[RandomNum( 1, this->npcSections_.size() ) - 1]; P_NPC pc = cNPC::createFromScript( NpcSect, pos ); if ( pc ) { pc->setSpawnregion( this ); if ( pc->wanderType() == enFreely ) { pc->setWanderType( enWanderSpawnregion ); } pc->update(); onSpawn( pc ); } } }
void cSpawnRegion::reSpawnToMax( void ) { this->checkForDeleted(); while( this->npcSerials_.size() < this->maxNpcAmt_ ) { // spawn a random npc // first find a valid position for the npc Coord_cl pos; if( this->findValidSpot( pos ) ) { QString NpcSect = this->npcSections_[ RandomNum( 1, static_cast<uint>(this->npcSections_.size()) ) - 1 ]; P_NPC pc = cCharStuff::createScriptNpc( NpcSect, pos ); if( pc != NULL ) { this->npcSerials_.push_back( pc->serial() ); pc->setSpawnregion( this->name_ ); pc->update(); } } } while( this->npcSerials_.size() < this->maxNpcAmt_ ) { // spawn a random item // first find a valid position for the item Coord_cl pos; if( this->findValidSpot( pos ) ) { QString ItemSect = this->itemSections_[ RandomNum( 1, this->itemSections_.size() ) - 1 ]; P_ITEM pi = cItem::createFromScript( ItemSect ); if( pi != NULL ) { pi->setPos( pos ); this->itemSerials_.push_back( pi->serial() ); // pi->setSpawnRegion( this->name_ ); } } } this->nextTime_ = uiCurrentTime + RandomNum( this->minTime_, this->maxTime_ ) * MY_CLOCKS_PER_SEC; }
// All this Stuff should be scripted bool QuestionSpeech( cUOSocket *socket, P_PLAYER pPlayer, P_NPC pChar, const QString& comm ) { if( !pChar->isHuman() || pPlayer->dist( pChar ) > 3 ) return false; // Tell the questioner our name if( comm.contains( "NAME" ) ) { pChar->talk( tr( "Hello, my name is %1." ).arg( pChar->name() ) ); return true; } // say time and the npChar gives the time. if( comm.contains( "TIME" ) ) { pChar->talk( tr( "It is now %1" ).arg( uoTime.toString() ) ); return true; } if( comm.contains( "LOCATION" ) ) { cTerritory* Region = pPlayer->region(); if( Region ) pChar->talk( tr( "You are in %1" ).arg( Region->name() ) ); else pChar->talk( tr( "You are in the wilderness" ) ); return true; } // We couldn't handle the speech return false; }
void cSpawnRegion::checkForDeleted( void ) { std::vector< SERIAL > foundSerials; std::vector< SERIAL >::iterator it = this->npcSerials_.begin(); while( it != this->npcSerials_.end() ) { P_NPC pChar = dynamic_cast<P_NPC>( FindCharBySerial( *it ) ); if( pChar && !pChar->free && pChar->spawnregion() == name_ ) foundSerials.push_back( (*it) ); it++; } npcSerials_ = foundSerials; foundSerials.clear(); it = this->itemSerials_.begin(); while( it != this->itemSerials_.end() ) { if( FindItemBySerial( *it ) ) foundSerials.push_back( (*it) ); it++; } itemSerials_ = foundSerials; }
///////////////// // 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; }
void cAIFactory::checkScriptAI( const QStringList& oldSections, const QStringList& newSections ) { QStringList::const_iterator aiit = oldSections.begin(); for ( ; aiit != oldSections.end(); ++aiit ) { // We must reset all existing and scripted AI objects, so changes can take effect. if ( !newSections.contains( *aiit ) ) { cCharIterator iter; for ( P_CHAR pChar = iter.first(); pChar; pChar = iter.next() ) { P_NPC pNPC = dynamic_cast<P_NPC>( pChar ); if ( pNPC ) { ScriptAI* ai = dynamic_cast<ScriptAI*>( pNPC->ai() ); if ( ai && ai->name() == ( *aiit ) ) { pNPC->setAI( *aiit ); } } } } else { cCharIterator iter; for ( P_CHAR pChar = iter.first(); pChar; pChar = iter.next() ) { P_NPC pNPC = dynamic_cast<P_NPC>( pChar ); if ( pNPC ) { ScriptAI* ai = dynamic_cast<ScriptAI*>( pNPC->ai() ); if ( ai && ai->name() == ( *aiit ) ) { delete ai; pNPC->setAI( NULL ); } } } unregisterType( *aiit ); } } aiit = newSections.begin(); while ( aiit != newSections.end() ) { if ( !oldSections.contains( *aiit ) ) { ScriptAI::registerInFactory( *aiit ); } ++aiit; } }
void cPlayer::removePet( P_NPC pPet, bool noOwnerChange ) { if ( !pPet ) return; CharContainer::iterator it = std::find( pets_.begin(), pets_.end(), pPet ); if ( it != pets_.end() ) pets_.erase( it ); if ( !noOwnerChange ) { pPet->setOwner( NULL, true ); } if ( socket_ ) { socket_->sendStatWindow(); } }
void Human_Stablemaster::handleTargetInput( P_PLAYER player, cUORxTarget* target ) { if ( !player ) return; P_ITEM pPack = m_npc->getBankbox(); if ( !pPack ) return; P_NPC pPet = dynamic_cast<P_NPC>( World::instance()->findChar( target->serial() ) ); if ( !pPet ) { m_npc->talk( tr( "I cannot stable that!" ) ); return; } if ( pPet->owner() != player ) { m_npc->talk( tr( "This does not belong to you!" ) ); return; } // we spawn a worldgem in the stablemasters bankbox for the pet // it does only hold the serial of it, the serial of the owner and the // number of refresh signals since begin of stabling // the pet becomes "free", which means, that it isnt in the world // but will still be saved. P_ITEM pGem = new cItem(); pGem->Init( true ); pGem->setTag( "player", cVariant( player->serial() ) ); pGem->setTag( "pet", cVariant( pPet->serial() ) ); pGem->setId( 0x1ea7 ); pGem->setName( tr( "petitem: %1" ).arg( pPet->name() ) ); pGem->setVisible( 2 ); // gm visible pPack->addItem( pGem ); pGem->update(); //pPet->free = true; MapObjects::instance()->remove( pPet ); pPet->setStablemasterSerial( this->m_npc->serial() ); pPet->removeFromView(); // we need this for db saves m_npc->talk( tr( "Say release to get your pet back!" ) ); }
P_NPC cPlayer::unmount() { P_ITEM pi = atLayer( Mount ); if ( pi && !pi->free ) { P_NPC pMount = dynamic_cast<P_NPC>( FindCharBySerial( pi->getTag( "pet" ).toInt() ) ); if ( pMount && !pMount->free ) { pMount->setWanderType( enHalt ); pMount->setStablemasterSerial( INVALID_SERIAL ); pMount->moveTo( pos() ); pMount->setDirection( direction_ ); pMount->resend( false ); pMount->bark( Bark_Idle ); } pi->remove(); resend( false ); return pMount; } return NULL; }
static void npcRegisterAfterLoading( P_NPC pc ) { if (pc->stablemasterSerial() == INVALID_SERIAL) { MapObjects::instance()->add(pc); } }
/*! This handles if a character actually tries to walk (NPC & Player) */ bool cMovement::Walking( P_CHAR pChar, Q_UINT8 dir, Q_UINT8 sequence ) { if ( !pChar ) return false; // Scripting if ( pChar->onWalk( dir, sequence ) ) return false; P_PLAYER player = dynamic_cast<P_PLAYER>( pChar ); // Is the sequence in order ? if ( player && player->socket() && !verifySequence( player->socket(), sequence ) ) return false; // If checking for weight is more expensive, shouldn't we check for frozen first? if ( pChar->isFrozen() ) { if ( player && player->socket() ) player->socket()->denyMove( sequence ); return false; } // save our original location before we even think about moving const Coord oldpos( pChar->pos() ); // If the Direction we're moving to is different from our current direction // We're turning and NOT moving into a specific direction // Clear the running flag here (!) // If the direction we're moving is already equal to our current direction bool running = dir & 0x80; dir = dir & 0x7; // Remove all unneeded stuff pChar->setRunning( running ); bool turning = dir != pChar->direction(); // This happens if we're moving if ( !turning ) { // Note: Do NOT use the copy constructor as it'll create a reference Coord newCoord = calcCoordFromDir( dir, pChar->pos() ); // Check if the stamina parameters if ( player && !consumeStamina( player, running ) ) { if ( player->socket() ) player->socket()->denyMove( sequence ); return false; } // Check if we're going to collide with characters if ( player ) { // Player vs characters if ( player->socket() && player->pos().map == 0 && !player->account()->isStaff() ) { // Currently hard-limiting collisions to Felucca; this should be a server option! MapCharsIterator charCollisions = MapObjects::instance()->listCharsAtCoord( newCoord ); for ( P_CHAR them = charCollisions.first(); them; them = charCollisions.next() ) { if ( them == player ) continue; P_PLAYER otherplayer = dynamic_cast<P_PLAYER>( them ); if ( otherplayer && otherplayer->account()->isStaff() ) continue; // no collisions against the staff if ( wpAbs<SI08>( newCoord.z - them->pos().z ) < P_M_MAX_Z_CLIMB ) { // to push another char we must have maximum stamina if ( player->stamina() >= player->maxStamina() ) { player->socket()->clilocMessage( them->isHidden() ? 1019043 : 1019042 ); player->setStamina( player->stamina() - 10 ); break; } else { player->socket()->denyMove( sequence ); return false; } } } } } else { // NPC vs characters P_NPC npc = dynamic_cast<P_NPC>( pChar ); if ( npc && CheckForCharacterAtXYZ( pChar, newCoord ) ) { npc->clearPath(); return false; } } // Check if the char can move to those new coordinates // It is going to automatically calculate the new coords (!) if ( !mayWalk( pChar, newCoord ) ) { if ( player && player->socket() ) player->socket()->denyMove( sequence ); return false; } else { if ( player && player->socket() ) player->socket()->allowMove( sequence ); } // We moved so let's update our location pChar->moveTo( newCoord ); pChar->setStepsTaken( pChar->stepsTaken() + 1 ); pChar->setLastMovement( Server::instance()->time() ); checkStealth( pChar ); // Reveals the user if neccesary } else { if ( player && player->socket() ) player->socket()->allowMove( sequence ); } // do all of the following regardless of whether turning or moving i guess // set the player direction to contain only the cardinal direction bits pChar->setDirection( dir ); Coord upperLeft = pChar->pos() - Coord( ( VISRANGE + 1 ), ( VISRANGE + 1 ) ); Coord lowerRight = pChar->pos() + Coord( ( VISRANGE + 1 ), ( VISRANGE + 1 ) ); MapCharsIterator ri = MapObjects::instance()->listCharsInRect( upperLeft, lowerRight ); for ( P_CHAR observer = ri.first(); observer; observer = ri.next() ) { if ( observer == pChar ) continue; bool wasVisible = observer->pos().distance( oldpos ) < VISRANGE; // We were previously in range bool isVisible = pChar->dist( observer ) < VISRANGE; // We are now in range // If we are a player, send us new characters if ( player && player->socket() ) { // Send the observer to us if he was previously not visible and came into range recently if ( !wasVisible && isVisible ) { player->socket()->sendChar( observer ); } } // Send our movement to the observer P_PLAYER otherplayer = dynamic_cast<P_PLAYER>( observer ); if ( !otherplayer || !otherplayer->socket() ) { continue; // Skip this character, it's a player. // TODO: OnSeePlayer, OnLoosePlayer } if ( wasVisible ) { if ( isVisible ) { otherplayer->socket()->updateChar( pChar ); // We walked inside the visible range } else { otherplayer->socket()->removeObject( pChar ); // We walked out of visible range } } else if ( isVisible ) { otherplayer->socket()->sendChar( pChar ); // We walked into visible range } } // If we really moved handle teleporters and new items if ( !turning ) { handleItems( pChar, oldpos ); handleMultis( pChar, oldpos ); handleTeleporters( pChar, oldpos ); } return true; }
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 ); } } }
///////////////// // 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; }
// Is the target dispellable? bool canDispel( P_CHAR target ) { P_NPC npc = dynamic_cast<P_NPC>( target ); return npc && npc->summoned() && m_npc->inRange( npc, 12 ); }
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; }
/* Find something to dispel we are fighting. */ P_NPC findDispelOpponent() { if ( m_npc->intelligence() < 95 || m_npc->summoned() ) { return 0; // No dispelling below 95 int or if the NPC is summoned itself. } QPtrList<cFightInfo> &fights = m_npc->fights(); Monster_Aggressive *ai = static_cast<Monster_Aggressive*>( m_ai ); P_NPC currentTarget = 0; unsigned int currentPriority = 0; /* Check our current attack target. It has the highest priority of all since we are fighting it anyway. */ if ( !invalidTarget( m_npc, ai->currentVictim() ) && canDispel( ai->currentVictim() ) ) { currentTarget = dynamic_cast<P_NPC>( ai->currentVictim() ); currentPriority = m_npc->dist( ai->currentVictim() ); if ( currentPriority <= 2 ) { return currentTarget; // We found a threat in our range, so dispel it now. } } /* Now check everyone who is fighting us */ for ( cFightInfo*info = fights.first(); info; info = fights.next() ) { P_NPC checkTarget; if ( info->victim() == m_npc ) { checkTarget = dynamic_cast<P_NPC>( info->attacker() ); } else { checkTarget = dynamic_cast<P_NPC>( info->victim() ); } // They have to be fighting us or they are uninteresting for this check if ( !checkTarget || checkTarget->attackTarget() != m_npc ) { continue; } if ( !invalidTarget( m_npc, checkTarget ) && canDispel( checkTarget ) ) { unsigned int newPriority = m_npc->dist( checkTarget ); if ( !currentTarget || currentPriority > newPriority ) { currentTarget = dynamic_cast<P_NPC>( ai->currentVictim() ); currentPriority = m_npc->dist( ai->currentVictim() ); if ( currentPriority <= 2 ) { return currentTarget; // We found a threat in our range, so dispel it now. } } } } return currentTarget; }
P_NPC cCharStuff::createScriptNpc( const QString §ion, const Coord_cl &pos ) { if( section.isNull() || section.isEmpty() ) return NULL; const QDomElement* DefSection = DefManager->getSection( WPDT_NPC, section ); if( !DefSection || DefSection->isNull() ) { clConsole.log( LOG_ERROR, QString( "Unable to create unscripted npc: %1\n" ).arg( section ) ); return NULL; } P_NPC pChar = new cNPC; pChar->Init(); pChar->setMinDamage(1); pChar->setMaxDamage(1); pChar->setBodyArmor(1); pChar->moveTo( pos ); pChar->setRegion( AllTerritories::instance()->region( pChar->pos().x, pChar->pos().y, pChar->pos().map ) ); pChar->applyDefinition( *DefSection ); // Now we call onCreate pChar->onCreate( section ); pChar->resend( false ); return pChar; }
bool cPlayer::mount( P_NPC pMount ) { if ( !pMount ) return false; if ( isDead() ) { return false; } unsigned short mountId = pMount->mountId(); if ( !mountId ) { return false; // Not mountable } cUOSocket* socket = this->socket(); if ( !inRange( pMount, Config::instance()->mountRange() ) && !isGM() ) { if ( socket ) socket->sysMessage( 500206 ); // That is too far away to ride. return true; // Mountable, but not in range } if ( pMount->owner() == this || isGM() ) { unmount(); P_ITEM pMountItem = new cItem; pMountItem->Init(); pMountItem->setId( mountId ); pMountItem->setColor( pMount->skin() ); if ( direction() != pMount->direction() ) { setDirection( pMount->direction() ); update(); } this->addItem( cBaseChar::Mount, pMountItem ); pMountItem->setTag( "pet", cVariant( pMount->serial() ) ); pMountItem->update(); // if this is a gm lets tame the animal in the process if ( isGM() ) { pMount->setOwner( this ); pMount->setTamed( true ); } // remove it from screen! pMount->bark( Bark_Idle ); pMount->removeFromView( false ); pMount->fight( 0 ); pMount->setStablemasterSerial( serial_ ); } else if ( pMount->owner() == 0 ) { socket->clilocMessage( 501263, 0, 0x3b2, 3, this ); // That mount does not look broken! You would have to tame it to ride it. } else socket->clilocMessage( 501264, 0, 0x3b2, 3, this ); // This isn't your mount; it refuses to let you ride. return true; }
bool responsed( cUOSocket* socket, cUORxTarget* target ) { if ( !isCharSerial( target->serial() ) ) { socket->clilocMessage( 1005442 ); } else { P_PLAYER leader = dynamic_cast<P_PLAYER>( World::instance()->findChar( this->player ) ); P_CHAR character = World::instance()->findChar( target->serial() ); P_NPC npc = dynamic_cast<P_NPC>( character ); P_PLAYER player = dynamic_cast<P_PLAYER>( character ); if ( !leader || ( leader->party() && leader->party()->leader() != leader ) ) { socket->clilocMessage( 1005453 ); } else if ( leader->party() && leader->party()->members().count() + leader->party()->canidates().count() >= 10 ) { socket->clilocMessage( 1008095 ); // NPC targetted } else if ( npc ) { if ( npc->isHuman() ) socket->clilocMessage( 1005443, 0, npc->saycolor(), 3, npc ); else socket->clilocMessage( 1005444 ); } else if ( leader == player ) { socket->clilocMessage( 1005439 ); } else if ( player && player->party() && player->party() == leader->party() ) { socket->clilocMessage( 1005440 ); } else if ( player && leader->party() && leader->party()->canidates().contains( player ) ) { socket->clilocMessage( 1005440 ); } else if ( player && player->party() ) { socket->clilocMessage( 1005441 ); } else if ( player && player->socket() ) { if ( !leader->party() ) { new cParty( leader ); leader->party()->update(); } player->socket()->clilocMessageAffix( 1008089, 0, leader->name(), 0x3b2, 3, 0, false, true ); leader->party()->addCanidate( player ); socket->log( LOG_TRACE, tr( "Invited '%1' to join his party.\n" ).arg( player->account()->login() ) ); // Send a party invitation request cUOTxPartyInvitation invitation; invitation.setSerial( leader->serial() ); player->socket()->send( &invitation ); // Attach a tempeffect that'll cancel the invitation after ten seconds Timers::instance()->insert( new cPartyCancelInvitation( leader->serial(), player->serial() ) ); } } return true; }
void cSkills::RandomSteal( cUOSocket* socket, SERIAL victim ) { P_PLAYER pChar = socket->player(); P_CHAR pVictim = FindCharBySerial( victim ); if ( !pVictim || !pChar ) return; if ( pVictim->serial() == pChar->serial() ) { socket->sysMessage( tr( "Why don't you simply take it?" ) ); return; } /* if( pVictim->npcaitype() == 17 ) { socket->sysMessage( tr( "You cannot steal from Playervendors." ) ); return; } */ if ( pVictim->objectType() == enPlayer ) { P_PLAYER pp = dynamic_cast<P_PLAYER>( pVictim ); if ( pp->isGMorCounselor() ) socket->sysMessage( tr( "You can't steal from game masters." ) ); return; } if ( !pChar->inRange( pVictim, 1 ) ) { socket->sysMessage( tr( "You are too far away to steal from that person." ) ); return; } P_ITEM pBackpack = pVictim->getBackpack(); if ( !pBackpack ) { socket->sysMessage( tr( "Bad luck, your victim doesn't have a backpack." ) ); return; } float maxWeight = ( float ) QMIN( 1, pChar->skillValue( STEALING ) ); // We can steal max. 10 Stones when we are a GM // 1000 Skill == 100 Weight == 10 Stones QPtrList<cItem> containment = pBackpack->getContainment(); Q_UINT32 chance = containment.count(); P_ITEM pItem = containment.first(); P_ITEM pToSteal = 0; bool sawOkItem = false; while ( !pToSteal ) { // We have nothing that could be stolen? if ( !pItem && !sawOkItem ) { socket->sysMessage( tr( "Your victim posesses nothing you could steal." ) ); return; } // Jump back to the beginning else if ( !pItem && sawOkItem ) { pItem = containment.first(); } // Check if our chance becomes true (no spellbooks!) if ( pItem->totalweight() <= maxWeight && !pItem->isLockedDown() && !pItem->newbie() && pItem->type() != 9 ) { sawOkItem = true; // We have items that could be stolen (just in case we reach the end of our list) // We have the chance of 1/chance that we reached our desired item if ( RandomNum( 1, ( int )chance ) == ( int )chance ) { pToSteal = pItem; break; } } pItem = containment.next(); } socket->sysMessage( tr( "You reach into %1's backpack and try to steal something..." ).arg( pVictim->name() ) ); // The success of our Theft depends on the weight of the stolen item bool success = pChar->checkSkill( STEALING, 0, ( long int )pToSteal->weight() ); bool caught = false; if ( success ) { socket->sysMessage( tr( "You successfully steal %1." ).arg( pToSteal->getName() ) ); P_ITEM pPack = pChar->getBackpack(); pPack->addItem( pToSteal ); // Update item onyl if still existent if ( !pToSteal->free ) pToSteal->update(); caught = pChar->skillValue( STEALING ) < rand() % 1001; } else { socket->sysMessage( tr( "You fail to steal the item." ) ); // 1 in 5 Chance if we failed caught = RandomNum( 1, 5 ) == 1; } // Did we get caught? if ( caught ) { socket->sysMessage( tr( "You have been cought!" ) ); // Human non red NPCs need special handling if ( pVictim->objectType() == enNPC && pVictim->isInnocent() && pVictim->isHuman() ) { P_NPC pn = dynamic_cast<P_NPC>( pVictim ); pVictim->talk( tr( "Guards! A thief is amoung us!" ), 0xFFFF, 0x09 ); if ( pVictim->region() && pVictim->region()->isGuarded() ) pn->callGuards(); } if ( pVictim->notoriety( pChar ) == 0x01 ) pChar->makeCriminal(); // Our Victim always notices it. if ( pVictim->objectType() == enPlayer ) { P_PLAYER pp = dynamic_cast<P_PLAYER>( pVictim ); if ( pp->socket() ) pp->socket()->showSpeech( pChar, tr( "You notice %1 trying to steal %2 from you." ).arg( pChar->name() ).arg( pToSteal->getName( true ) ) ); } QString message = tr( "You notice %1 trying to steal %2 from %3." ).arg( pChar->name() ).arg( pItem->getName() ).arg( pVictim->name() ); for ( cUOSocket*mSock = Network::instance()->first(); mSock; mSock = Network::instance()->next() ) { // Everyone within 7 Tiles notices us if ( mSock != socket && mSock->player() && mSock->player()->serial() != pVictim->serial() && mSock->player()->inRange( pChar, 7 ) ) mSock->showSpeech( pChar, message ); } } }
/*! This handles if a character actually tries to walk (NPC & Player) */ bool cMovement::Walking( P_CHAR pChar, Q_UINT8 dir, Q_UINT8 sequence ) { if ( !pChar ) return false; // Scripting if ( pChar->onWalk( dir, sequence ) ) return false; /* if( !isValidDirection( dir ) ) { pChar->setPathNum( pChar->pathnum() + PATHNUM ); return; }*/ P_PLAYER player = dynamic_cast<P_PLAYER>( pChar ); // Is the sequence in order ? if ( player && player->socket() && !verifySequence( player->socket(), sequence ) ) return false; // If checking for weight is more expensive, shouldn't we check for frozen first? if ( pChar->isFrozen() ) { if ( player && player->socket() ) player->socket()->denyMove( sequence ); return false; } // save our original location before we even think about moving const Coord_cl oldpos( pChar->pos() ); // If the Direction we're moving to is different from our current direction // We're turning and NOT moving into a specific direction // Clear the running flag here (!) // If the direction we're moving is already equal to our current direction bool running = dir & 0x80; dir = dir & 0x7F; // Remove the running flag pChar->setRunning(running); bool turning = dir != pChar->direction(); // This happens if we're moving if ( !turning ) { // Note: Do NOT use the copy constructor as it'll create a reference Coord_cl newCoord = calcCoordFromDir( dir, pChar->pos() ); // Check if the stamina parameters if ( player && !consumeStamina( player, running ) ) { if ( player->socket() ) player->socket()->denyMove( sequence ); return false; } // Check for Characters in our way if ( !checkObstacles( pChar, newCoord, running ) ) { if ( player && player->socket() ) player->socket()->denyMove( sequence ); return false; } // Check if the char can move to those new coordinates // It is going to automatically calculate the new coords (!) if ( !mayWalk( pChar, newCoord ) ) { if ( player && player->socket() ) player->socket()->denyMove( sequence ); return false; } else { if ( player && player->socket() ) player->socket()->allowMove( sequence ); } // Check if we're going to collide with characters if ( !player && CheckForCharacterAtXYZ( pChar, newCoord ) ) { P_NPC npc = dynamic_cast<P_NPC>( pChar ); if ( npc ) { npc->clearPath(); } return false; } // We moved so let's update our location pChar->moveTo( newCoord ); pChar->setStepsTaken( pChar->stepsTaken() + 1 ); pChar->setLastMovement( Server::instance()->time() ); checkStealth( pChar ); // Reveals the user if neccesary } else { if ( player && player->socket() ) player->socket()->allowMove( sequence ); } // do all of the following regardless of whether turning or moving i guess // set the player direction to contain only the cardinal direction bits pChar->setDirection( dir ); RegionIterator4Chars ri( pChar->pos() ); for ( ri.Begin(); !ri.atEnd(); ri++ ) { P_CHAR observer = ri.GetData(); if ( observer == pChar ) { continue; } unsigned int distance = observer->pos().distance( oldpos ); // If we are a player, send us new characters if ( player && player->socket() ) { if ( distance > player->visualRange() ) { player->socket()->sendChar( observer ); // We were previously out of range. } } // Send our movement to the observer P_PLAYER otherplayer = dynamic_cast<P_PLAYER>( observer ); if ( otherplayer && otherplayer->socket() ) { if ( distance > otherplayer->visualRange() ) { otherplayer->socket()->sendChar( pChar ); // Previously we were out of range } else { otherplayer->socket()->updateChar( pChar ); // Previously we were already known } } } // If we really moved handle teleporters and new items if ( !turning ) { handleItems( pChar, oldpos ); handleTeleporters( pChar, oldpos ); } return true; }
static P_CHAR findBestTarget( P_NPC npc ) { int targetAttract = -1; P_CHAR target = 0; // Search for targets in our list of current targets first QPtrList<cFightInfo> fights = npc->fights(); for ( cFightInfo*info = fights.first(); info; info = fights.next() ) { P_CHAR victim = info->victim(); if ( victim == npc ) { victim = info->attacker(); } // We don't already attack the target, right? if ( victim != target ) { // See if it's a target we want unsigned int dist = npc->dist(victim); int attract = (victim->strength() + victim->skillValue(TACTICS) / 10) / (wpMin<unsigned int>(65535, dist) + 1); if ( attract > targetAttract && validTarget( npc, victim, dist ) ) { target = victim; targetAttract = attract; } } } /* Attack the target with the highest ((Strength + Tactics) / Distance) value. */ // If we're not tamed, we attack other players as well. if ( !npc->isTamed() ) { MapCharsIterator ri = MapObjects::instance()->listCharsInCircle( npc->pos(), VISRANGE ); for ( P_CHAR pChar = ri.first(); pChar; pChar = ri.next() ) { // We limit ourself to players and pets owned by players. P_PLAYER victim = dynamic_cast<P_PLAYER>( pChar ); P_NPC npcVictim = dynamic_cast<P_NPC>( pChar ); // We don't already attack the target, right? if ( victim && victim != target ) { // See if it's a target we want unsigned int dist = npc->dist(victim); int attract = (victim->strength() + victim->skillValue(TACTICS) / 10) / (wpMin<unsigned int>(65535, dist) + 1); if ( attract > targetAttract && validTarget( npc, victim, dist ) ) { target = victim; targetAttract = attract; } } else if ( npcVictim && npcVictim->owner() && npcVictim != target ) { // See if it's a target we want unsigned int dist = npc->dist(victim); int attract = (npcVictim->strength() + npcVictim->skillValue(TACTICS) / 10) / (wpMin<unsigned int>(65535, dist) + 1); if ( attract > targetAttract && validTarget( npc, npcVictim, dist ) ) { target = npcVictim; targetAttract = attract; } } } } return target; }
void Human_Guard_Called::init( P_NPC npc ) { npc->setSummonTime( Server::instance()->time() + MY_CLOCKS_PER_SEC * Config::instance()->guardDispelTime() ); npc->setSummoned( true ); AbstractAI::init( npc ); }
void cPlayer::mount( P_NPC pMount ) { if ( !pMount ) return; cUOSocket* socket = this->socket(); if ( !inRange( pMount, 2 ) && !isGM() ) { if ( socket ) socket->sysMessage( tr( "You are too far away to mount!" ) ); return; } if ( pMount->owner() == this || isGM() ) { unmount(); P_ITEM pMountItem = new cItem; pMountItem->Init(); pMountItem->setId( 0x915 ); pMountItem->setColor( pMount->skin() ); switch ( static_cast<unsigned short>( pMount->body() & 0x00FF ) ) { case 0xC8: pMountItem->setId( 0x3E9F ); break; // Horse case 0xE2: pMountItem->setId( 0x3EA0 ); break; // Horse case 0xE4: pMountItem->setId( 0x3EA1 ); break; // Horse case 0xCC: pMountItem->setId( 0x3EA2 ); break; // Horse case 0xD2: pMountItem->setId( 0x3EA3 ); break; // Desert Ostard case 0xDA: pMountItem->setId( 0x3EA4 ); break; // Frenzied Ostard case 0xDB: pMountItem->setId( 0x3EA5 ); break; // Forest Ostard case 0xDC: pMountItem->setId( 0x3EA6 ); break; // LLama case 0x34: pMountItem->setId( 0x3E9F ); break; // Brown Horse case 0x4E: pMountItem->setId( 0x3EA0 ); break; // Grey Horse case 0x50: pMountItem->setId( 0x3EA1 ); break; // Tan Horse case 0x74: pMountItem->setId( 0x3EB5 ); break; // Nightmare case 0x75: pMountItem->setId( 0x3EA8 ); break; // Silver Steed case 0x72: pMountItem->setId( 0x3EA9 ); break; // Dark Steed case 0x7A: pMountItem->setId( 0x3EB4 ); break; // Unicorn case 0x84: pMountItem->setId( 0x3EAD ); break; // Kirin case 0x73: pMountItem->setId( 0x3EAA ); break; // Etheral case 0x76: pMountItem->setId( 0x3EB2 ); break; // War Horse-Brit case 0x77: pMountItem->setId( 0x3EB1 ); break; // War Horse-Mage Council case 0x78: pMountItem->setId( 0x3EAF ); break; // War Horse-Minax case 0x79: pMountItem->setId( 0x3EB0 ); break; // War Horse-Shadowlord case 0xAA: pMountItem->setId( 0x3EAB ); break; // Etheral LLama case 0x3A: pMountItem->setId( 0x3EA4 ); break; // Forest Ostard case 0x39: pMountItem->setId( 0x3EA3 ); break; // Desert Ostard case 0x3B: pMountItem->setId( 0x3EA5 ); break; // Frenzied Ostard case 0x90: pMountItem->setId( 0x3EB3 ); break; // Seahorse case 0xAB: pMountItem->setId( 0x3EAC ); break; // Etheral Ostard case 0xBB: pMountItem->setId( 0x3EB8 ); break; // Ridgeback case 0x17: pMountItem->setId( 0x3EBC ); break; // giant beetle case 0x19: pMountItem->setId( 0x3EBB ); break; // skeletal mount case 0x1a: pMountItem->setId( 0x3EBD ); break; // swamp dragon case 0x1f: pMountItem->setId( 0x3EBE ); break; // armor dragon } this->addItem( cBaseChar::Mount, pMountItem ); pMountItem->setTag( "pet", cVariant( pMount->serial() ) ); pMountItem->update(); // if this is a gm lets tame the animal in the process if ( isGM() ) { pMount->setOwner( this ); } // remove it from screen! pMount->bark( Bark_Idle ); pMount->removeFromView( false ); pMount->fight( 0 ); pMount->setStablemasterSerial( serial_ ); } else socket->sysMessage( tr( "You dont own that creature." ) ); }