Coord Coord::losTargetPoint( cUORxTarget* target, unsigned char map ) { SERIAL serial = target->serial(); P_ITEM pItem = World::instance()->findItem( serial ); P_CHAR pChar = World::instance()->findChar( serial ); if ( pItem ) { pItem = pItem->getOutmostItem(); if ( pItem->container() && pItem->container()->isChar() ) { return pItem->container()->pos().losCharPoint(); } else { return pItem->pos().losItemPoint( pItem->id() ); } } else if ( pChar ) { return pChar->pos().losCharPoint(); } else { return Coord( target->x(), target->y(), target->z(), map ); } }
// Remove it from all in-range sockets void cUObject::removeFromView( bool clean ) { // Get Real pos Coord_cl mPos = pos_; if( isItemSerial( serial_ ) ) { P_ITEM pItem = dynamic_cast<P_ITEM>(this); P_ITEM pCont = pItem->getOutmostItem(); if( pCont ) { mPos = pCont->pos(); P_CHAR pOwner = dynamic_cast<P_CHAR>( pCont->container() ); if( pOwner ) mPos = pOwner->pos(); } } cUOTxRemoveObject remove; remove.setSerial(serial_); for (cUOSocket *socket = cNetwork::instance()->first(); socket; socket = cNetwork::instance()->next()) { if (socket->player() != this && (clean || socket->canSee(this))) { socket->send(&remove); } } }
/*! Checks if the specified object is in given range */ bool cUObject::inRange( cUObject* object, quint32 range ) const { if ( !object ) return false; Coord pos = object->pos_; if ( object->isItem() ) { P_ITEM pItem = dynamic_cast<P_ITEM>( object ); if ( pItem ) { P_ITEM pCont = pItem->getOutmostItem(); P_CHAR pEquipped = pItem->getOutmostChar(); if ( pEquipped ) { pos = pEquipped->pos(); } else if ( pCont ) { pos = pCont->pos(); } } } return pos_.distance( pos ) <= range; }
// Remove it from all in-range sockets void cUObject::removeFromView( bool clean ) { // Get Real pos Coord_cl mPos = pos_; if( isItemSerial( serial_ ) ) { P_ITEM pItem = dynamic_cast<P_ITEM>(this); P_ITEM pCont = pItem->getOutmostItem(); if( pCont ) { mPos = pCont->pos(); P_CHAR pOwner = dynamic_cast<P_CHAR>( pCont->container() ); if( pOwner ) mPos = pOwner->pos(); } } for( cUOSocket *socket = cNetwork::instance()->first(); socket; socket = cNetwork::instance()->next() ) if( clean || ( socket->player() && ( socket->player()->pos().distance( mPos ) <= socket->player()->visualRange() ) ) ) socket->removeObject( this ); }
// 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(); }
// New Class implementation void DragAndDrop::grabItem( cUOSocket* socket, cUORxDragItem* packet ) { // Get our character P_PLAYER pChar = socket->player(); if ( !pChar ) return; float weight = pChar->weight(); // Fetch the grab information UI16 amount = packet->amount(); if ( !amount ) amount = 1; P_ITEM pItem = FindItemBySerial( packet->serial() ); // If it's an invalid pointer we can't even bounce if ( !pItem ) return; // Are we already dragging an item ? // Bounce it and reject the move // (Logged out while dragging an item) if ( socket->dragging() ) { socket->bounceItem( socket->dragging(), BR_ALREADY_DRAGGING ); return; } // Check if the item can be reached if (pItem->getOutmostChar() != pChar && !pChar->lineOfSight(pItem)) { socket->bounceItem( pItem, BR_OUT_OF_REACH ); return; } if ( pItem->onPickup( pChar ) ) return; if ( pChar->onPickup( pItem ) ) return; // Do we really want to let him break his meditation // When he picks up an item ? // Maybe a meditation check here ?!? pChar->disturbMed(); // Meditation P_CHAR itemOwner = pItem->getOutmostChar(); // Try to pick something out of another characters posessions if ( !pChar->isGM() && itemOwner && ( itemOwner != pChar ) && ( itemOwner->objectType() == enNPC && dynamic_cast<P_NPC>( itemOwner )->owner() != pChar ) ) { socket->bounceItem( pItem, BR_BELONGS_TO_SOMEONE_ELSE ); return; } // Check if the user can grab the item if ( !pChar->canPickUp( pItem ) ) { socket->bounceItem( pItem, BR_CANNOT_PICK_THAT_UP ); return; } // The user can't see the item // Basically thats impossible as the socket should deny moving the item // if it's not in line of sight but to prevent exploits /*if( !line_of_sight( socket->socket(), pChar->pos, pItem->pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) ) { socket->sysMessage( "You can't see the item." ); bounceItem( socket, pItem, true ); return; }*/ P_ITEM outmostCont = pItem->getOutmostItem(); // If the top-most container ( thats important ) is a corpse // and looting is a crime, flag the character criminal. if ( !pChar->isGM() && outmostCont && outmostCont->corpse() ) { // For each item we take out we loose carma // if the corpse is innocent and not in our guild bool sameGuild = true;//( GuildCompare( pChar, outmostCont->owner() ) != 0 ); if ( outmostCont->hasTag( "notoriety" ) && outmostCont->getTag( "notoriety" ).toInt() == 1 && !pChar->owns( outmostCont ) && !sameGuild ) { // pChar->karma -= 5; pChar->setKarma( pChar->karma() - 5 ); pChar->setCriminalTime( Server::instance()->time() + Config::instance()->crimtime() * MY_CLOCKS_PER_SEC ); socket->sysMessage( tr( "You lost some karma." ) ); } } // Check if the item is too heavy //if( !pc_currchar->isGMorCounselor() ) //{ //} << Deactivated (DarkStorm) // ==== Grabbing the Item is allowed here ==== // Send the user a pickup sound if we're picking it up // From a container/paperdoll if ( !pItem->isInWorld() ) socket->soundEffect( 0x57, pItem ); // If we're picking up a specific amount of what we got // Take that into account if ( amount < pItem->amount() ) { UI32 pickedAmount = QMIN( amount, pItem->amount() ); // We only have to split if we're not taking it all if ( pickedAmount != pItem->amount() ) { P_ITEM splitItem = pItem->dupe(); // Create a new item to pick that up splitItem->setAmount( pItem->amount() - pickedAmount ); // Add tags to the splitted item QStringList keys = pItem->getTags(); QStringList::const_iterator it = keys.begin(); for ( ; it != keys.end(); ++it ) { splitItem->setTag( *it, pItem->getTag( *it ) ); } P_ITEM pContainer = dynamic_cast<P_ITEM>( pItem->container() ); if ( pContainer ) pContainer->addItem( splitItem, false ); splitItem->SetOwnSerial( pItem->ownSerial() ); splitItem->setSpawnregion( pItem->spawnregion() ); // He needs to see the new item splitItem->update(); // If we're taking something out of a spawn-region it's spawning "flag" is removed isn't it? pItem->setAmount( pickedAmount ); } } // *normally* we should exclude the dragging socket here. but it works so as well. pItem->removeFromView( true ); // Remove from spawnregion pItem->setSpawnregion( 0 ); // Remove it from the World if it is in world, otherwise remove it from it's current container if ( pItem->isInWorld() ) MapObjects::instance()->remove( pItem ); else pItem->removeFromCont( true ); // Remove eventual item-bonusses if we're unequipping something if ( pItem->container() && pItem->container()->isChar() ) { P_CHAR wearer = dynamic_cast<P_CHAR>( pItem->container() ); // resend the stat window if ( wearer && wearer->objectType() == enPlayer ) { P_PLAYER pp = dynamic_cast<P_PLAYER>( wearer ); if ( pp->socket() ) pp->socket()->sendStatWindow(); } } pChar->addItem( cBaseChar::Dragging, pItem ); if ( weight != pChar->weight() ) { socket->sendStatWindow(); } }
void 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." ) ); }