void cPlayer::giveGold( quint32 amount, bool inBank ) { P_ITEM pCont = NULL; if ( !inBank ) pCont = getBackpack(); else pCont = getBankbox(); if ( !pCont ) return; // Begin Spawning quint32 total = amount; while ( total > 0 ) { P_ITEM pile = cItem::createFromScript( "eed" ); pile->setAmount( wpMin<quint32>( total, static_cast<quint32>( 65535 ) ) ); total -= pile->amount(); pCont->addItem( pile ); if ( !pile->free ) { pile->update(); } } goldSound( amount, false ); }
void IDefReader::processScriptItemNode( P_ITEM madeItem, QDomElement &Node ) { for( UI16 k = 0; k < Node.childNodes().count(); k++ ) { QDomElement currChild = Node.childNodes().item( k ).toElement(); if( currChild.nodeName() == "amount" ) { QString Value = QString(); UI16 i = 0; if( currChild.hasChildNodes() ) // <random> i.e. for( i = 0; i < currChild.childNodes().count(); i++ ) { if( currChild.childNodes().item( i ).isText() ) Value += currChild.childNodes().item( i ).toText().data(); else if( currChild.childNodes().item( i ).isElement() ) Value += processNode( currChild.childNodes().item( i ).toElement() ); } else Value = currChild.nodeValue(); if( Value.toInt() < 1 ) Value = QString("1"); if( madeItem->isPileable() ) madeItem->setAmount( Value.toInt() ); else for( i = 1; i < Value.toInt(); i++ ) //dupe it n-1 times Commands->DupeItem(-1, madeItem, 1); } else if( currChild.nodeName() == "color" ) //process <color> tags { QString Value = QString(); if( currChild.hasChildNodes() ) // colorlist or random i.e. for( UI16 i = 0; i < currChild.childNodes().count(); i++ ) { if( currChild.childNodes().item( i ).isText() ) Value += currChild.childNodes().item( i ).toText().data(); else if( currChild.childNodes().item( i ).isElement() ) Value += processNode( currChild.childNodes().item( i ).toElement() ); } else Value = currChild.nodeValue(); if( Value.toInt() < 0 ) Value = QString("0"); madeItem->setColor( Value.toInt() ); } else if( currChild.nodeName() == "inherit" && currChild.attributes().contains("id") ) { QDomElement* derivalSection = DefManager->getSection( WPDT_ITEM, currChild.attribute("id") ); if( !derivalSection->isNull() ) this->applyNodes( madeItem, derivalSection ); } } }
void DragAndDrop::dropOnBeggar( cUOSocket* socket, P_ITEM pItem, P_CHAR pBeggar ) { int tempint; if( ( pBeggar->hunger() < 6 ) && pItem->type() == 14 ) { pBeggar->talk( tr("*cough* Thank thee!") ); pBeggar->soundEffect( 0x3A + RandomNum( 1, 3 ) ); // *You see Snowwhite eating some poisoned apples* // Color: 0x0026 pBeggar->emote( tr( "*You see %1 eating %2*" ).arg( pBeggar->name() ).arg( pItem->getName() ) ); // We try to feed it more than it needs if( pBeggar->hunger() + pItem->amount() > 6 ) { // client->player()->karma += ( 6 - pBeggar->hunger() ) * 10; tempint = ( 6 - pBeggar->hunger() ) * 10; socket->player()->setKarma( socket->player()->karma() + tempint ); pItem->setAmount( pItem->amount() - ( 6 - pBeggar->hunger() ) ); pBeggar->setHunger( 6 ); // Pack the rest into his backpack bounceItem( socket, pItem ); return; } pBeggar->setHunger( pBeggar->hunger() + pItem->amount() ); // client->player()->karma += pItem->amount() * 10; tempint = pItem->amount() * 10; socket->player()->setKarma( socket->player()->karma() + tempint ); pItem->remove(); return; } // No Food? Then it has to be Gold if( pItem->id() != 0xEED ) { pBeggar->talk( tr("Sorry, but i can only use gold.") ); bounceItem( socket, pItem ); return; } pBeggar->talk( tr( "Thank you %1 for the %2 gold!" ).arg( socket->player()->name() ).arg( pItem->amount() ) ); socket->sysMessage( tr("You have gained some karma!") ); if( pItem->amount() <= 100 ) socket->player()->setKarma( socket->player()->karma() + 10 ); else socket->player()->setKarma( socket->player()->karma() + 50 ); pItem->remove(); }
// Item was dropped on a pet void cDragItems::dropOnPet( P_CLIENT client, P_ITEM pItem, P_CHAR pPet ) { // Feed our pets if( ( pPet->hunger() >= 6 ) || pItem->type() != 14 ) { client->sysMessage( "It doesn't seem to want your item" ); bounceItem( client, pItem ); return; } // We have three different eating-sounds (I don't like the idea as they sound too human) pPet->soundEffect( 0x3A + RandomNum( 1, 3 ) ); // If you want to poison a pet... Why not if( pItem->poisoned && pPet->poisoned() < pItem->poisoned ) { pPet->soundEffect( 0x246 ); pPet->setPoisoned( pItem->poisoned ); // a lev.1 poison takes effect after 40 secs, a deadly pois.(lev.4) takes 40/4 secs - AntiChrist pPet->setPoisontime( uiCurrentTime + ( MY_CLOCKS_PER_SEC * ( 40 / pPet->poisoned() ) ) ); //wear off starts after poison takes effect - AntiChrist pPet->setPoisonwearofftime(pPet->poisontime() + ( MY_CLOCKS_PER_SEC * SrvParams->poisonTimer() ) ); // Refresh the health-bar of our target impowncreate( client->socket(), pPet, 1 ); } // *You see Snowwhite eating some poisoned apples* // Color: 0x0026 QString emote = QString( "*You see %1 eating %2*" ).arg( pPet->name.c_str() ).arg( pItem->getName() ); pPet->emote( emote ); // We try to feed it more than it needs if( pPet->hunger() + pItem->amount() > 6 ) { pItem->setAmount( pItem->amount() - ( 6 - pPet->hunger() ) ); pPet->setHunger( 6 ); // Pack the rest into his backpack bounceItem( client, pItem ); return; } pPet->setHunger( pPet->hunger() + pItem->amount() ); Items->DeleItem( pItem ); }
// Food was dropped on a pet void cDragItems::dropFoodOnChar( cUOSocket* socket, P_ITEM pItem, P_CHAR pChar ) { // Feed our pets if( pChar->hunger() >= 6 || pItem->type2() == 0 || !( pChar->nutriment() & ( 1 << (pItem->type2()-1) ) ) ) { socket->sysMessage( tr("It doesn't seem to want your item") ); bounceItem( socket, pItem ); return; } // We have three different eating-sounds (I don't like the idea as they sound too human) pChar->soundEffect( 0x3A + RandomNum( 1, 3 ) ); // If you want to poison a pet... Why not if( pItem->poisoned() && pChar->poisoned() < pItem->poisoned() ) { pChar->soundEffect( 0x246 ); pChar->setPoisoned( pItem->poisoned() ); // a lev.1 poison takes effect after 40 secs, a deadly pois.(lev.4) takes 40/4 secs - AntiChrist pChar->setPoisonTime( uiCurrentTime + ( MY_CLOCKS_PER_SEC * ( 40 / pChar->poisoned() ) ) ); //wear off starts after poison takes effect - AntiChrist pChar->setPoisonWearOffTime(pChar->poisonTime() + ( MY_CLOCKS_PER_SEC * SrvParams->poisonTimer() ) ); // Refresh the health-bar of our target pChar->resend( false ); } // *You see Snowwhite eating some poisoned apples* // Color: 0x0026 pChar->emote( tr( "*You see %1 eating %2*" ).arg( pChar->name() ).arg( pItem->getName() ) ); // We try to feed it more than it needs if( pChar->hunger() + pItem->amount() > 6 ) { pItem->setAmount( pItem->amount() - ( 6 - pChar->hunger() ) ); pChar->setHunger( 6 ); // Pack the rest into his backpack bounceItem( socket, pItem ); return; } pChar->setHunger( pChar->hunger() + pItem->amount() ); Items->DeleItem( pItem ); }
void cNPC::giveGold( Q_UINT32 amount, bool inBank ) { P_ITEM pCont = getBackpack(); if( !pCont ) return; // Begin Spawning Q_UINT32 total = amount; while( total > 0 ) { P_ITEM pile = cItem::createFromScript( "eed" ); pile->setAmount( QMIN( total, static_cast<Q_UINT32>(65535) ) ); pCont->addItem( pile ); total -= pile->amount(); } }
void cDragItems::dropOnBeggar( cUOSocket* socket, P_ITEM pItem, P_CHAR pBeggar ) { int tempint; if( ( pBeggar->hunger() < 6 ) && pItem->type() == 14 ) { pBeggar->talk( tr("*cough* Thank thee!") ); pBeggar->soundEffect( 0x3A + RandomNum( 1, 3 ) ); // If you want to poison a pet... Why not if( pItem->poisoned() && pBeggar->poisoned() < pItem->poisoned() ) { pBeggar->soundEffect( 0x246 ); pBeggar->setPoisoned( pItem->poisoned() ); // a lev.1 poison takes effect after 40 secs, a deadly pois.(lev.4) takes 40/4 secs - AntiChrist pBeggar->setPoisonTime( uiCurrentTime + ( MY_CLOCKS_PER_SEC * ( 40 / pBeggar->poisoned() ) ) ); //wear off starts after poison takes effect - AntiChrist pBeggar->setPoisonWearOffTime( pBeggar->poisonTime() + ( MY_CLOCKS_PER_SEC * SrvParams->poisonTimer() ) ); // Refresh the health-bar of our target pBeggar->resend( false ); } // *You see Snowwhite eating some poisoned apples* // Color: 0x0026 pBeggar->emote( tr( "*You see %1 eating %2*" ).arg( pBeggar->name() ).arg( pItem->getName() ) ); // We try to feed it more than it needs if( pBeggar->hunger() + pItem->amount() > 6 ) { // client->player()->karma += ( 6 - pBeggar->hunger() ) * 10; tempint = ( 6 - pBeggar->hunger() ) * 10; socket->player()->setKarma( socket->player()->karma() + tempint ); pItem->setAmount( pItem->amount() - ( 6 - pBeggar->hunger() ) ); pBeggar->setHunger( 6 ); // Pack the rest into his backpack bounceItem( socket, pItem ); return; } pBeggar->setHunger( pBeggar->hunger() + pItem->amount() ); // client->player()->karma += pItem->amount() * 10; tempint = pItem->amount() * 10; socket->player()->setKarma( socket->player()->karma() + tempint ); Items->DeleItem( pItem ); return; } // No Food? Then it has to be Gold if( pItem->id() != 0xEED ) { pBeggar->talk( tr("Sorry, but i can only use gold.") ); bounceItem( socket, pItem ); return; } pBeggar->talk( tr( "Thank you %1 for the %2 gold!" ).arg( socket->player()->name() ).arg( pItem->amount() ) ); socket->sysMessage( tr("You have gained some karma!") ); if( pItem->amount() <= 100 ) socket->player()->setKarma( socket->player()->karma() + 10 ); else socket->player()->setKarma( socket->player()->karma() + 50 ); Items->DeleItem( pItem ); }
// 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 );*/ }
// 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 DragAndDrop::dropOnItem( cUOSocket* socket, P_ITEM pItem, P_ITEM pCont, const Coord_cl& dropPos ) { P_PLAYER pChar = socket->player(); if ( pItem->isMulti() ) { socket->sysMessage( tr( "You cannot put houses in containers" ) ); cUOTxBounceItem bounce; bounce.setReason( BR_NO_REASON ); socket->send( &bounce ); pItem->remove(); return; } if ( pItem->onDropOnItem( pCont ) ) { if ( pItem->free ) return; if ( socket->dragging() ) socket->bounceItem( socket->dragging(), BR_NO_REASON ); return; } else if ( pCont->onDropOnItem( pItem ) ) { if ( pItem->free ) return; if ( socket->dragging() ) socket->bounceItem( socket->dragging(), BR_NO_REASON ); return; } // If the target belongs to another character // It needs to be our vendor or else it's denied P_CHAR packOwner = pCont->getOutmostChar(); if ( ( packOwner ) && ( packOwner != pChar ) && !pChar->isGM() ) { // For each item someone puts into there // He needs to do a snoop-check if ( pChar->maySnoop() ) { if ( !pChar->checkSkill( SNOOPING, 0, 1000 ) ) { socket->sysMessage( tr( "You fail to put that into %1's pack" ).arg( packOwner->name() ) ); socket->bounceItem( pItem, BR_NO_REASON ); return; } } if ( packOwner->objectType() == enPlayer || ( packOwner->objectType() == enNPC && dynamic_cast<P_NPC>( packOwner )->owner() != pChar ) ) { socket->sysMessage( tr( "You cannot put that into the belongings of another player" ) ); socket->bounceItem( pItem, BR_NO_REASON ); return; } } if ( !pChar->canPickUp( pItem ) ) { socket->bounceItem( pItem, BR_CANNOT_PICK_THAT_UP ); return; } // We drop something on the belongings of one of our playervendors /* if( ( packOwner != NULL ) && ( packOwner->npcaitype() == 17 ) && packOwner->owner() == pChar ) { socket->sysMessage( tr( "You drop something into your playervendor (unimplemented)" ) ); socket->bounceItem( pItem, BR_NO_REASON ); return; }*/ // Playervendors (chest equipped by the vendor - opened to the client) /*if( !( pCont->pileable() && pItem->pileable() && pCont->id() == pItem->id() || ( pCont->type() != 1 && pCont->type() != 9 ) ) ) { P_CHAR pc_j = GetPackOwner(pCont); if (pc_j != NULL) { if (pc_j->npcaitype() == 17 && pc_j->isNpc() && pChar->Owns(pc_j)) { pChar->inputitem = pItem->serial; pChar->inputmode = cChar::enPricing; sysmessage(s, "Set a price for this item."); } } */ // We may also drop into *any* locked chest // So we can have post-boxes ;o) if ( pCont->type() == 1 ) { // If we're dropping it onto the closed container if ( dropPos.x == 0xFFFF && dropPos.y == 0xFFFF ) { pCont->addItem( pItem ); } else { pCont->addItem( pItem, false ); pItem->setPos( dropPos ); } // Dropped on another Container/in another Container pChar->soundEffect( 0x57 ); pItem->update(); return; } else if ( pCont->canStack( pItem ) ) { if ( pCont->amount() + pItem->amount() <= 65535 ) { pCont->setAmount( pCont->amount() + pItem->amount() ); pItem->remove(); pCont->update(); // Need to update the amount pCont->resendTooltip(); return; } else { // The delta between 65535 and pCont->amount() sub our Amount is the // new amount pItem->setAmount( pItem->amount() - ( 65535 - pCont->amount() ) ); pItem->resendTooltip(); pCont->setAmount( 65535 ); // Max out the amount pCont->update(); pCont->resendTooltip(); } } // We dropped the item NOT on a container // And were *un*able to stack it (!) // >> Set it to the location of the item we dropped it on and stack it up by 2 if ( pCont->container() ) { P_ITEM pNewCont = dynamic_cast<P_ITEM>( pCont->container() ); if ( pNewCont ) { pNewCont->addItem( pItem, false ); pItem->setPos( pCont->pos() + Coord_cl( 0, 0, 2 ) ); } else { pChar->getBackpack()->addItem( pItem ); } } else { pItem->removeFromCont(); pItem->moveTo( pCont->pos() + Coord_cl( 0, 0, 2 ) ); } pItem->update(); }
// New Class implementation void DragAndDrop::grabItem( cUOSocket* socket, cUORxDragItem* packet ) { // Get our character P_PLAYER pChar = socket->player(); if ( !pChar ) return; float weight = pChar->weight(); // Fetch the grab information UI16 amount = packet->amount(); if ( !amount ) amount = 1; P_ITEM pItem = FindItemBySerial( packet->serial() ); // If it's an invalid pointer we can't even bounce if ( !pItem ) return; // Are we already dragging an item ? // Bounce it and reject the move // (Logged out while dragging an item) if ( socket->dragging() ) { socket->bounceItem( socket->dragging(), BR_ALREADY_DRAGGING ); return; } // Check if the item can be reached if (pItem->getOutmostChar() != pChar && !pChar->lineOfSight(pItem)) { socket->bounceItem( pItem, BR_OUT_OF_REACH ); return; } if ( pItem->onPickup( pChar ) ) return; if ( pChar->onPickup( pItem ) ) return; // Do we really want to let him break his meditation // When he picks up an item ? // Maybe a meditation check here ?!? pChar->disturbMed(); // Meditation P_CHAR itemOwner = pItem->getOutmostChar(); // Try to pick something out of another characters posessions if ( !pChar->isGM() && itemOwner && ( itemOwner != pChar ) && ( itemOwner->objectType() == enNPC && dynamic_cast<P_NPC>( itemOwner )->owner() != pChar ) ) { socket->bounceItem( pItem, BR_BELONGS_TO_SOMEONE_ELSE ); return; } // Check if the user can grab the item if ( !pChar->canPickUp( pItem ) ) { socket->bounceItem( pItem, BR_CANNOT_PICK_THAT_UP ); return; } // The user can't see the item // Basically thats impossible as the socket should deny moving the item // if it's not in line of sight but to prevent exploits /*if( !line_of_sight( socket->socket(), pChar->pos, pItem->pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) ) { socket->sysMessage( "You can't see the item." ); bounceItem( socket, pItem, true ); return; }*/ P_ITEM outmostCont = pItem->getOutmostItem(); // If the top-most container ( thats important ) is a corpse // and looting is a crime, flag the character criminal. if ( !pChar->isGM() && outmostCont && outmostCont->corpse() ) { // For each item we take out we loose carma // if the corpse is innocent and not in our guild bool sameGuild = true;//( GuildCompare( pChar, outmostCont->owner() ) != 0 ); if ( outmostCont->hasTag( "notoriety" ) && outmostCont->getTag( "notoriety" ).toInt() == 1 && !pChar->owns( outmostCont ) && !sameGuild ) { // pChar->karma -= 5; pChar->setKarma( pChar->karma() - 5 ); pChar->setCriminalTime( Server::instance()->time() + Config::instance()->crimtime() * MY_CLOCKS_PER_SEC ); socket->sysMessage( tr( "You lost some karma." ) ); } } // Check if the item is too heavy //if( !pc_currchar->isGMorCounselor() ) //{ //} << Deactivated (DarkStorm) // ==== Grabbing the Item is allowed here ==== // Send the user a pickup sound if we're picking it up // From a container/paperdoll if ( !pItem->isInWorld() ) socket->soundEffect( 0x57, pItem ); // If we're picking up a specific amount of what we got // Take that into account if ( amount < pItem->amount() ) { UI32 pickedAmount = QMIN( amount, pItem->amount() ); // We only have to split if we're not taking it all if ( pickedAmount != pItem->amount() ) { P_ITEM splitItem = pItem->dupe(); // Create a new item to pick that up splitItem->setAmount( pItem->amount() - pickedAmount ); // Add tags to the splitted item QStringList keys = pItem->getTags(); QStringList::const_iterator it = keys.begin(); for ( ; it != keys.end(); ++it ) { splitItem->setTag( *it, pItem->getTag( *it ) ); } P_ITEM pContainer = dynamic_cast<P_ITEM>( pItem->container() ); if ( pContainer ) pContainer->addItem( splitItem, false ); splitItem->SetOwnSerial( pItem->ownSerial() ); splitItem->setSpawnregion( pItem->spawnregion() ); // He needs to see the new item splitItem->update(); // If we're taking something out of a spawn-region it's spawning "flag" is removed isn't it? pItem->setAmount( pickedAmount ); } } // *normally* we should exclude the dragging socket here. but it works so as well. pItem->removeFromView( true ); // Remove from spawnregion pItem->setSpawnregion( 0 ); // Remove it from the World if it is in world, otherwise remove it from it's current container if ( pItem->isInWorld() ) MapObjects::instance()->remove( pItem ); else pItem->removeFromCont( true ); // Remove eventual item-bonusses if we're unequipping something if ( pItem->container() && pItem->container()->isChar() ) { P_CHAR wearer = dynamic_cast<P_CHAR>( pItem->container() ); // resend the stat window if ( wearer && wearer->objectType() == enPlayer ) { P_PLAYER pp = dynamic_cast<P_PLAYER>( wearer ); if ( pp->socket() ) pp->socket()->sendStatWindow(); } } pChar->addItem( cBaseChar::Dragging, pItem ); if ( weight != pChar->weight() ) { socket->sendStatWindow(); } }