// Tries to equip an item // if that fails it tries to put the item in the users backpack // if *that* fails it puts it at the characters feet // That works for NPCs as well void equipItem( P_CHAR wearer, P_ITEM item ) { tile_st tile = TileCache::instance()->getTile( item->id() ); // User cannot wear the item if ( tile.layer == 0 ) { if ( wearer->objectType() == enPlayer ) { P_PLAYER pp = dynamic_cast<P_PLAYER>( wearer ); if ( pp->socket() ) pp->socket()->sysMessage( tr( "You cannot wear that item." ) ); } item->toBackpack( wearer ); return; } cBaseChar::ItemContainer container = wearer->content(); cBaseChar::ItemContainer::const_iterator it( container.begin() ); for ( ; it != container.end(); ++it ) { P_ITEM equip = *it; // Unequip the item and free the layer that way if ( equip && ( equip->layer() == tile.layer ) ) equip->toBackpack( wearer ); } // *finally* equip the item wearer->addItem( static_cast<cBaseChar::enLayer>( item->layer() ), item ); }
void cWeight::NewCalc(P_CHAR pc) { float totalweight=0.0; //get weight for items on players unsigned int ci = 0; P_ITEM pi; vector<SERIAL> vecContainer = contsp.getData(pc->serial); for ( ci = 0; ci < vecContainer.size(); ci++) { pi = FindItemBySerial(vecContainer[ci]); if (pi == NULL || (pi != NULL && pi->id() == 0x1E5E)) // trade window ? continue; if ((pi->layer()!=0x0B) && (pi->layer()!=0x10) && //no weight for hair/beard (pi->layer()!=0x1D) && (pi->layer()!=0x19)) //no weight for steed/bank box { totalweight+=(pi->getWeight()/100.0f); } } // Items in players pack P_ITEM pBackpack = Packitem(pc); if (pBackpack != NULL) totalweight += RecursePacks(pBackpack); //LB pc->weight = (int)totalweight; return; }
// Tries to equip an item // if that fails it tries to put the item in the users backpack // if *that* fails it puts it at the characters feet // That works for NPCs as well void equipItem( P_CHAR wearer, P_ITEM item ) { tile_st tile; Map->SeekTile( item->id(), &tile ); // User cannot wear the item if( tile.layer == 0 ) { if( online( wearer ) ) sysmessage( calcSocketFromChar( wearer ), "You cannot wear that item." ); item->toBackpack( wearer ); return; } vector< SERIAL > equipment = contsp.getData( wearer->serial ); // If n item on the same layer is already equipped, unequip it for( UI08 i = 0; i < equipment.size(); i++ ) { P_ITEM equip = FindItemBySerial( equipment[ i ] ); // Unequip the item and free the layer that way if( equip && ( equip->layer() == tile.layer ) ) equip->toBackpack( wearer ); wearer->removeItemBonus( equip ); } // *finally* equip the item item->setContSerial( wearer->serial ); // Add the item bonuses wearer->st = (wearer->st + item->st2); wearer->chgDex( item->dx2 ); wearer->in = (wearer->in + item->in2); }
// 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 );*/ }
void cPlayer::applyStartItemDefinition( const cElement* element ) { for ( unsigned int i = 0; i < element->childCount(); ++i ) { const cElement* node = element->getChild( i ); // Apply another startitem definition if ( node->name() == "inherit" ) { const cElement* inheritNode = Definitions::instance()->getDefinition( WPDT_STARTITEMS, node->getAttribute( "id" ) ); if ( inheritNode ) { applyStartItemDefinition( inheritNode ); } } // Item related nodes else { P_ITEM pItem = 0; if ( node->hasAttribute( "id" ) && node->getAttribute( "id" ) != QString::null ) { pItem = cItem::createFromScript( node->getAttribute( "id" ) ); } else if ( node->hasAttribute( "list" ) && node->getAttribute( "list" ) != QString::null ) { pItem = cItem::createFromList( node->getAttribute( "list" ) ); } else if ( node->hasAttribute( "randomlist" ) && node->getAttribute( "randomlist" ) != QString::null ) { QStringList RandValues = node->getAttribute( "randomlist" ).split( "," ); pItem = cItem::createFromList( RandValues[RandomNum( 0, RandValues.size() - 1 )] ); } if ( !pItem ) { Console::instance()->log( LOG_ERROR, tr( "Invalid item tag without id or list in startitem definition '%1'" ).arg( element->getAttribute( "id" ) ) ); } else { pItem->applyDefinition( node ); if ( node->name() == "item" ) { pItem->toBackpack( this ); } else if ( node->name() == "bankitem" ) { getBackpack()->addItem( pItem ); } else if ( node->name() == "equipment" ) { unsigned char layer = pItem->layer(); pItem->setLayer( 0 ); if ( !layer ) { tile_st tile = TileCache::instance()->getTile( pItem->id() ); layer = tile.layer; } if ( layer ) { // Check if there is sth there already. // Could happen due to inherit. P_ITEM existing = atLayer( static_cast<cBaseChar::enLayer>( layer ) ); if ( existing ) existing->remove(); addItem( static_cast<cBaseChar::enLayer>( layer ), pItem ); } else { Console::instance()->log( LOG_ERROR, tr( "Trying to equip invalid item (%1) in startitem definition '%2'" ).arg( pItem->id(), 0, 16 ).arg( element->getAttribute( "id" ) ) ); } } else { pItem->remove(); Console::instance()->log( LOG_ERROR, tr( "Unrecognized startitem tag '%1' in definition '%2'." ).arg( QString(node->name()) ).arg( element->getAttribute( "id" ) ) ); } } } } }
// New Class implementation void cDragItems::grabItem( P_CLIENT client ) { // Get our character P_CHAR pChar = client->player(); if( pChar == NULL ) return; // Fetch the grab information SERIAL iSerial = LongFromCharPtr( &buffer[ client->socket() ][ 1 ] ); UI16 amount = ShortFromCharPtr( &buffer[ client->socket() ][ 5 ] ); P_ITEM pItem = FindItemBySerial( iSerial ); if( !pItem ) return; // Are we already dragging an item ? // Bounce it and reject the move // (Logged out while dragging an item) if( client->dragging() ) { bounceItem( client, client->dragging() ); bounceItem( client, pItem, true ); return; } // Do we really want to let him break his meditation // When he picks up an item ? // Maybe a meditation check here ?!? pChar->disturbMed( client->socket() ); // Meditation P_CHAR itemOwner = GetPackOwner( pItem, 64 ); // Try to pick something out of another characters posessions if( itemOwner && ( itemOwner != pChar ) && ( !pChar->Owns( itemOwner ) ) ) { client->sysMessage( QString( "You have to steal the %1 out of %2's posessions." ).arg( pItem->getName() ).arg( itemOwner->name.c_str() ) ); bounceItem( client, pItem, true ); return; } // Check if the user can grab the item if( !pChar->canPickUp( pItem ) ) { client->sysMessage( "You cannot pick that up." ); bounceItem( client, pItem, true ); return; } // The user can't see the item // Basically thats impossible as the client should deny moving the item // if it's not in line of sight but to prevent exploits if( !line_of_sight( client->socket(), pChar->pos, pItem->pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) ) { client->sysMessage( "You can't see the item." ); bounceItem( client, pItem, true ); return; } P_ITEM outmostCont = GetOutmostCont( pItem, 64 ); // If it's a trade-window, reset the ack-status if( outmostCont && ( outmostCont->contserial == pChar->serial ) && ( 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->morez = 0; outmostCont->morez = 0; sendtradestatus( tradeWindow, outmostCont ); } } // If the top-most container ( thats important ) is a corpse // and looting is a crime, flag the character criminal. if( 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, FindCharBySerial( outmostCont->ownserial ) ) != 0 ); if( ( outmostCont->more2 == 1 ) && !pChar->Owns( outmostCont ) && !sameGuild ) { pChar->karma -= 5; criminal( pChar ); client->sysMessage( "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->layer() > 0 ) { P_CHAR wearer = FindCharBySerial( pItem->contserial ); if( wearer ) wearer->removeItemBonus( pItem ); } // Send the user a pickup sound if we're picking it up // From a container/paperdoll if( !pItem->isInWorld() ) soundeffect( client->socket(), 0x00, 0x57 ); // If we're picking up a specific amount of what we got // Take that into account if( pItem->amount() > 1 ) { UI32 pickedAmount = min( 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( cItemsManager::getInstance()->getUnusedSerial() ); splitItem->setAmount( pItem->amount() - pickedAmount ); splitItem->setContSerial( pItem->contserial ); splitItem->SetOwnSerial( pItem->ownserial ); splitItem->SetSpawnSerial( pItem->spawnserial ); // He needs to see the new item RefreshItem( splitItem ); // 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 ); } } pItem->setContSerial( pChar->serial ); pItem->SetMultiSerial( INVALID_SERIAL ); pItem->setLayer( 0x1E ); // It's in the equipment of another character if( itemOwner && ( itemOwner != pChar ) ) { itemOwner->weight -= pItem->getWeight(); statwindow( calcSocketFromChar( itemOwner ), itemOwner ); } // If the item is in the bank or any sell-container it's NOT counted as char-weight bool inBank = ( outmostCont && ( outmostCont->contserial == pChar->serial ) && ( outmostCont->layer() >= 0x1A ) ); // Add the weight if: // - Picked from ground // - Picked out of another character // - Picked out of our bank or any other non-visible container if( ( itemOwner != pChar ) || !inBank ) { pChar->weight += pItem->getWeight(); statwindow( client->socket(), pChar ); } }
void cDragItems::dropOnItem( P_CLIENT client, P_ITEM pItem, P_ITEM pCont, const Coord_cl &dropPos ) { P_CHAR pChar = client->player(); if( pItem->isMulti() ) { client->sysMessage( "You cannot put houses in containers" ); bounceItem( client, pItem ); return; } // If the target belongs to another character // It needs to be our vendor or else it's denied P_CHAR packOwner = GetPackOwner( pCont ); if( ( packOwner != NULL ) && ( packOwner != pChar ) ) { // For each item someone puts into there // He needs to do a snoop-check if( pChar->canSnoop() ) { if( !Skills->CheckSkill( pChar, SNOOPING, 0, 1000 ) ) { client->sysMessage( QString( "You fail to put that into %1's pack" ).arg( packOwner->name.c_str() ) ); bounceItem( client, pItem ); return; } } if( !packOwner->isNpc() || ( packOwner->npcaitype() != 17 ) || !pChar->Owns( packOwner ) ) { client->sysMessage( "You cannot put that into the belongings of another player" ); bounceItem( client, pItem ); 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->morez = 0; pCont->morez = 0; sendtradestatus( tradeWindow, pCont ); } } if( !pChar->canPickUp( pItem ) ) { bounceItem( client, pItem ); return; } // Trash can if( pCont->type()==87 ) { Items->DeleItem( pItem ); client->sysMessage( "As you let go of the item it disappears." ); return; } // Spell Book if( pCont->type() == 9 ) { UI08 spellId = Magic->calcSpellId( pItem->id() ); if( spellId < 0 ) { client->sysMessage( "You can only put scrolls into a spellbook" ); bounceItem( client, pItem ); return; } if( Magic->hasSpell( pCont, spellId ) ) { client->sysMessage( "That spellbook already contains this spell" ); bounceItem( client, pItem ); return; } } // We drop something on the belongings of one of our playervendors if( ( packOwner != NULL ) && ( packOwner->npcaitype() == 17 ) && pChar->Owns( packOwner ) ) { client->sysMessage( "You drop something into your playervendor" ); bounceItem( client, pItem ); 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() == 9 || pCont->type() == 1 || pCont->type() == 8 || pCont->type() == 63 || pCont->type() == 65 || pCont->type() == 66 ) { pItem->setContSerial( pCont->serial ); pItem->setLayer( 0 ); // Remove it from our drag-layer // Huh ? - Make that random will you! pItem->pos = dropPos; SndRemoveitem( pItem->serial ); RefreshItem( pItem ); // Dropped on another Container/in another Container soundeffect2( pChar, 0x57 ); 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 ); RefreshItem( pCont ); // Need to update the amount return; } // We have to *keep* our current item else { pCont->setAmount( 65535 ); // Max out the amount RefreshItem( pCont ); // 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 1 pItem->moveTo( pCont->pos ); pItem->pos.z++; // Increase z by 1 pItem->pos.y++; // To get it visualized do that with y as well pItem->setLayer( 0 ); pItem->setContSerial( pCont->contserial ); RefreshItem( pItem ); // This needs to be checked // It annoyingly shows the spellbook // whenever you add a scroll if( pCont->type() == 9 ) Magic->openSpellBook( pChar, pCont ); // Glowing Objects moved between chars if( pItem->glow != INVALID_SERIAL ) { pChar->removeHalo( pItem ); if( packOwner != NULL ) { packOwner->addHalo(pItem); packOwner->glowHalo(pItem); } } }
void cDragItems::dropOnChar( P_CLIENT client, P_ITEM pItem, P_CHAR pOtherChar ) { // Three possibilities: // If we're dropping it on ourself: packintobackpack // If we're dropping it on some other player: trade-window // If we're dropping it on some NPC: checkBehaviours // If not handeled: Equip the item if the NPC is owned by us P_CHAR pChar = client->player(); // Dropped on ourself if( pChar == pOtherChar ) { pItem->setLayer( 0 ); pItem->setContSerial( INVALID_SERIAL ); pItem->toBackpack( pChar ); return; } // Are we in range of our target if( !inrange1p( pChar, pOtherChar ) ) { client->sysMessage( "You are too far away from that character." ); bounceItem( client, pItem ); return; } // Can wee see our target if( !line_of_sight( client->socket(), pChar->pos, pOtherChar->pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) ) { client->sysMessage( "You can't see this character" ); bounceItem( client, pItem ); return; } // Open a secure trading window if( !pOtherChar->isNpc() && online( pOtherChar ) ) { // Check if we're already trading, // if not create a new window vector< SERIAL > equipment = contsp.getData( pChar->serial ); P_ITEM tradeWindow = NULL; for( UI16 i = 0; i < equipment.size(); i++ ) { P_ITEM pEquip = FindItemBySerial( equipment[ i ] ); // Is it a trade-window ? if( ( pEquip->layer() == 0 ) && ( pEquip->id() == 0x1E5E ) ) { P_ITEM tradeWindow = FindItemBySerial( calcserial( pEquip->moreb1(), pEquip->moreb2(), pEquip->moreb3(), pEquip->moreb4() ) ); if( tradeWindow && ( tradeWindow->contserial == pOtherChar->serial ) ) { tradeWindow = pEquip; break; } } } if( !tradeWindow ) tradeWindow = Trade->tradestart( client->socket(), pOtherChar ); pItem->setContSerial( tradeWindow->serial); pItem->pos.x = rand() % 60; pItem->pos.y = rand() % 60; pItem->pos.z = 9; pItem->setLayer( 0 ); SndRemoveitem( pItem->serial ); RefreshItem( pItem ); return; } // For our hirelings we have a special function if( pChar->Owns( pOtherChar ) ) { dropOnPet( client, pItem, pOtherChar ); return; } // Dropping based on AI Type switch( pOtherChar->npcaitype() ) { case 4: dropOnGuard( client, pItem, pOtherChar ); break; case 5: dropOnBeggar( client, pItem, pOtherChar ); break; case 8: dropOnBanker( client, pItem, pOtherChar ); break; case 19: dropOnBroker( client, pItem, pOtherChar ); break; }; // Try to train - works for any NPC if( pOtherChar->cantrain() ) if( pChar->trainer() == pOtherChar->serial ) dropOnTrainer( client, pItem, pOtherChar ); else pOtherChar->talk( "You need to tell me what you want to learn first" ); bounceItem( client, pItem ); return; }
void cDragItems::equipItem( P_CLIENT client ) { // Get the packet information SERIAL itemId = LongFromCharPtr( &buffer[ client->socket() ][ 1 ] ); SERIAL playerId = LongFromCharPtr( &buffer[ client->socket() ][ 6 ] ); P_ITEM pItem = FindItemBySerial( itemId ); P_CHAR pWearer = FindCharBySerial( playerId ); if( !pItem || !pWearer ) return; P_CHAR pChar = client->player(); // We're dead and can't do that if( pChar->dead ) { client->sysMessage( "You are dead and can't do that." ); bounceItem( client, pItem ); return; } // Our target is dead if( ( pWearer != pChar ) && pWearer->dead ) { client->sysMessage( "You can't equip dead players." ); bounceItem( client, pItem ); return; } // Get our tile-information tile_st pTile; Map->SeekTile( pItem->id(), &pTile ); // 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() ) { client->sysMessage( "This item cannot be equipped." ); bounceItem( client, pItem ); return; } // Required Strength if( pItem->st > pWearer->st ) { if( pWearer == pChar ) client->sysMessage( "You cannot wear that item, you seem not strong enough" ); else client->sysMessage( "This person can't wear that armor, it seems not strong enough" ); bounceItem( client, pItem ); return; } // Required Dexterity if( pItem->dx > pWearer->effDex() ) { if( pWearer == pChar ) client->sysMessage( "You cannot wear that item, you seem not agile enough" ); else client->sysMessage( "This person can't wear that armor, it seems not agile enough" ); bounceItem( client, pItem ); return; } // Required Intelligence if( pItem->in > pWearer->in ) { if( pWearer == pChar ) client->sysMessage( "You cannot wear that item, you seem not smart enough" ); else client->sysMessage( "This person can't wear that armor, it seems not smart enough" ); bounceItem( client, pItem ); return; } // Males can't wear female armor if( ( pChar->id() == 0x0190 ) && ( pItem->id() >= 0x1C00 ) && ( pItem->id() <= 0x1C0D ) ) { client->sysMessage( "You cannot wear female armor." ); bounceItem( client, pItem ); 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 UI08 layer = pItem->layer(); vector< SERIAL > equipment = contsp.getData( pWearer->serial ); for( UI32 i = 0; i < equipment.size(); i++ ) { P_ITEM pEquip = FindItemBySerial( equipment[ i ] ); if( pEquip ) continue; // We found an item which is on the same layer (!) // Unequip it if we can bool twoHanded = false; if( pEquip->twohanded() && ( layer == 1 || layer == 2 ) ) twoHanded = true; if( pItem->twohanded() && ( pEquip->layer() == 1 || pEquip->layer() == 2 ) ) twoHanded = true; if( ( pEquip->layer() == layer ) || twoHanded ) { if( pChar->canPickUp( pEquip ) ) // we're equipping so we do the check pEquip->toBackpack( pWearer ); // If it's still on the char: cancel equipment if( pEquip->contserial == pWearer->serial ) { client->sysMessage( "You already have an item on that layer." ); bounceItem( client, pItem ); return; } } } // At this point we're certain that we can wear the item pItem->setContSerial( playerId ); pItem->setLayer( pTile.layer ); // Don't trust the user input on this one // Handle the weight if the item is leaving our "body" if( pWearer != pChar ) { pChar->weight -= pItem->getWeight(); pWearer->weight += pItem->getWeight(); // Update the status-windows statwindow( client->socket(), pChar ); statwindow( calcSocketFromChar( pWearer ), pWearer ); } if( pTile.layer == 0x19 ) pWearer->setOnHorse( true ); // Apply the bonuses pWearer->st += pItem->st2; pWearer->chgDex( pItem->dx2 ); pWearer->in += pItem->in2; // Show debug information if requested if( showlayer ) clConsole.send( QString( "Item (%1) equipped on layer %2" ).arg( pItem->name() ).arg( pItem->layer() ) ); // I don't think we need to remove the item // as it's only visible to the current char // And he looses contact anyway // SndRemoveitem( pi->serial ); // Build our packets cWornItems wearItem( pWearer->serial, pItem->serial, pItem->layer(), pItem->id(), pItem->color() ); cSoundEffect soundEffect( 0x57, pWearer->pos ); // Send to all sockets in range // ONLY the new equipped item and the sound-effect for( UOXSOCKET s = 0; s < now; s++ ) if( perm[s] && inrange1p( pWearer, currchar[s] ) ) { soundEffect.send( s ); wearItem.send( s ); } // Lord Binaries Glow stuff if( pItem->glow != INVALID_SERIAL ) { pChar->removeHalo( pItem ); pWearer->addHalo( pItem ); pWearer->glowHalo( pItem ); } }
void dbl_click_item(cUOSocket* socket, SERIAL target_serial) throw() { SERIAL serial = target_serial; P_PLAYER pc_currchar = socket->player(); if( !pc_currchar->isGM() && /*pc_currchar->objectDelay() > 10 && ???*/ pc_currchar->objectDelay() >= uiCurrentTime ) { socket->sysMessage(tr("You must wait to perform another action.")); return; } else pc_currchar->setObjectDelay( SrvParams->objectDelay() * MY_CLOCKS_PER_SEC + uiCurrentTime ); P_ITEM pi = FindItemBySerial( serial ); if( !pi ) return; if( pi->container() && pi->container()->isItem() && pi->type() != 1 && !pi->isInWorld()) { // Cant use stuff that isn't in your pack. P_CHAR pc_p = pi->getOutmostChar(); if( pc_p && pc_currchar != pc_p ) return; } else if( pi->container() && pi->container()->isChar() && pi->type() != 1 && !pi->isInWorld() ) { // in a character. P_CHAR pc_p = dynamic_cast<P_CHAR>(pi->container()); if (pc_p != NULL) if( pc_p != pc_currchar && pi->layer() != 15 && pi->type() != 1 ) return; } // Criminal for looting an innocent corpse & unhidden if not owner... if( pi->corpse() ) { if (!pc_currchar->Owns(pi) && !pc_currchar->isGM()) { pc_currchar->unhide(); } // TODO: Add a XML option for this if(!pc_currchar->Owns(pi) && !pc_currchar->isGM() && pc_currchar->isInnocent()) { // Innocent Corpse and not in the same party && party allowance for looting? if (pi->hasTag("notoriety") && pi->getTag("notoriety").toInt() == 0x01) { P_PLAYER owner = dynamic_cast<P_PLAYER>(pi->owner()); bool allowed = false; if (owner && owner->party() && owner->party() == pc_currchar->party()) { // Check if the player allowed looting his corpse by party members if (owner->party()->lootingAllowed().contains(owner)) { allowed = true; } } if (!allowed) { pc_currchar->makeCriminal(); } } } } // Secure containers if( pi->isLockedDown() && pi->secured() ) { if( !pc_currchar->Owns( pi ) && !pc_currchar->isGM() ) { socket->sysMessage( tr( "That is a secured chest!" ) ); return; } } // Dead ppl can only use ankhs if( pc_currchar->isDead() && pi->type() != 16 ) { socket->sysMessage( tr( "Your ghostly hand passes trough the object." ) ); return; } // You can only use equipment on your own char if( !pc_currchar->isGM() && pi->container() && pi->container()->isChar() && pi->container() != pc_currchar ) { if( pi->layer() != 15 || !SrvParams->stealingEnabled() ) { socket->sysMessage( tr( "You cannot use items equipped by other players." ) ); return; } } // Call both events here if( pc_currchar->onUse( pi ) ) return; if( pi->onUse( pc_currchar ) ) return; // Check item behaviour by it's tpye switch (pi->type()) { case 1: // normal containers { pc_currchar->setObjectDelay( 0 ); // no delay for opening containers if( pc_currchar->isGM() ) { socket->sendContainer( pi ); return; } if( pi->layer() > 0x18 ) { socket->sysMessage( tr( "You can't see this." ) ); return; } if( isInLockedItem( pi ) ) { socket->sysMessage( tr( "You have to unlock it before taking a look." ) ); return; } if( !pi->container() ) { if( !pi->inRange( pc_currchar, 2 ) ) { socket->clilocMessage( 0x7A258, "", 0x3b2 ); // You cannot reach that return; } else if(!pc_currchar->lineOfSight(pi, true)) { socket->clilocMessage( 0x7A258, "", 0x3b2 ); // You cannot reach that return; } socket->sendContainer( pi ); return; } else if( pi->container()->isItem() ) { P_ITEM pOCont = pi->getOutmostItem(); // Check if we can reach the top-container if( !pOCont->container() ) { if( !pOCont->inRange( pc_currchar, 2 ) ) { socket->clilocMessage( 0x7A258, "", 0x3b2 ); // You cannot reach that return; } socket->sendContainer( pi ); } else { P_CHAR pChar = dynamic_cast< P_CHAR >( pOCont->container() ); if( pChar && pChar != pc_currchar ) { if( !pChar->inRange( pc_currchar, 2 ) ) socket->sysMessage( tr( "You must stand nearer to snoop!" ) ); else Skills->Snooping( pc_currchar, pi ); } else if( pChar == pc_currchar ) socket->sendContainer( pi ); } return; } else if( pi->container()->isChar() ) { // Equipped on another character P_CHAR pChar = dynamic_cast< P_CHAR >( pi->container() ); if( pChar && pChar != pc_currchar ) { if( !pChar->inRange( pc_currchar, 2 ) ) socket->sysMessage( tr( "You must stand nearer to snoop!" ) ); else Skills->Snooping( pc_currchar, pi ); } else if( pChar == pc_currchar ) socket->sendContainer( pi ); return; } socket->sysMessage( tr( "You can't open this container." ) ); return; } return; case 16: // Check for 'resurrect item type' this is the ONLY type one can use if dead. if( pc_currchar->isDead() ) { pc_currchar->resurrect(); socket->sysMessage( tr( "You have been resurrected." ) ); return; } else { socket->sysMessage( tr( "You are already living!" ) ); return; } // Drinks case 105: pc_currchar->soundEffect( 0x30 + RandomNum( 0, 1 ) ); pi->reduceAmount( 1 ); // Remove a drink pc_currchar->message( "Gulp!" ); return; // 1001: Sword Weapons (Swordsmanship) case 1001: // 1002: Axe Weapons (Swordsmanship + Lumberjacking) case 1002: // 1005: Fencing case 1005: // 1003: Macefighting (Staffs) case 1003: // 1004: Macefighting (Maces/WarHammer) case 1004: // 1006: Bows case 1006: // 1007: Crossbows case 1007: // 1008: Shields case 1008: break; default: break; } socket->sysMessage( tr( "You can't think of a way to use that item." ) ); }