Q_UINT16 DynTile( const Coord& pos ) { MapItemsIterator ri = MapObjects::instance()->listItemsInCircle( pos, 18 ); for ( P_ITEM mapitem = ri.first(); mapitem; mapitem = ri.next() ) { if ( mapitem->isMulti() ) { MultiDefinition* def = MultiCache::instance()->getMulti( mapitem->id() - 0x4000 ); if ( !def ) return 0; QValueVector<multiItem_st> multi = def->getEntries(); for ( Q_UINT32 j = 0; j < multi.size(); ++j ) { if ( ( multi[j].visible && ( mapitem->pos().x + multi[j].x == pos.x ) && ( mapitem->pos().y + multi[j].y == pos.y ) && ( abs( mapitem->pos().z + multi[j].z - pos.z ) <= 1 ) ) ) { return multi[j].tile; } } } else if ( mapitem->pos() == pos ) { return mapitem->id(); } } return ( Q_UINT16 ) - 1; }
Q_UINT16 DynTile( const Coord_cl& pos ) { RegionIterator4Items ri( pos ); for ( ri.Begin(); !ri.atEnd(); ri++ ) { P_ITEM mapitem = ri.GetData(); if ( mapitem ) { if ( mapitem->isMulti() ) { MultiDefinition* def = MultiCache::instance()->getMulti( mapitem->id() - 0x4000 ); if ( !def ) return 0; QValueVector<multiItem_st> multi = def->getEntries(); for ( Q_UINT32 j = 0; j < multi.size(); ++j ) { if ( ( multi[j].visible && ( mapitem->pos().x + multi[j].x == pos.x ) && ( mapitem->pos().y + multi[j].y == pos.y ) && ( abs( mapitem->pos().z + multi[j].z - pos.z ) <= 1 ) ) ) { return multi[j].tile; } } } else if ( mapitem->pos() == pos ) return mapitem->id(); } } return ( Q_UINT16 ) - 1; }
void DragAndDrop::dropOnGround( cUOSocket* socket, P_ITEM pItem, const Coord_cl& pos ) { P_PLAYER pChar = socket->player(); // Check if the destination is in line of sight if ( !pChar->lineOfSight( pos.losItemPoint(pItem->id()) ) ) { socket->bounceItem( pItem, BR_OUT_OF_SIGHT ); return; } if ( !pChar->canPickUp( pItem ) ) { socket->bounceItem( pItem, BR_CANNOT_PICK_THAT_UP ); return; } if ( pItem->onDropOnGround( pos ) ) { // We're still dragging something if ( socket->dragging() ) socket->bounceItem( socket->dragging(), BR_NO_REASON ); return; } pItem->removeFromCont(); pItem->moveTo( pos ); pItem->update(); // Play Sounds for non gold items if (pItem->id() != 0xEED) { pItem->soundEffect(0x42); } }
// this is a q&d fix for 'sell price higher than buy price' bug (Duke, 30.3.2001) static bool items_match(P_ITEM pi1, P_ITEM pi2) { if (pi1 && pi2 && pi1->id()==pi2->id() && pi1->type==pi2->type && !(pi1->id()==0x14F0 && (pi1->morex!=pi2->morex)) && // house deeds only differ by morex !(IsShield(pi1->id()) && pi1->name2 == pi2->name2) && // magic shields only differ by name2 !(IsMetalArmour(pi1->id()) && pi1->color != pi2->color) ) // color checking for armour return true; return false; }
static bool ItemDroppedOnTrainer(P_CLIENT ps, PKGx08 *pp, P_ITEM pi) { UOXSOCKET s=ps->GetSocket(); CHARACTER cc=ps->GetCurrChar(); P_CHAR pc_currchar = MAKE_CHARREF_LRV(cc,true); int t=calcCharFromSer(pp->Tserial); if( pi->id() ==0x0EED ) { // They gave the NPC gold char sk=chars[t].trainingplayerin; npctalk(s, t, "I thank thee for thy payment. That should give thee a good start on thy way. Farewell!",0); int sum = pc_currchar->getSkillSum(); int delta = chars[t].getTeachingDelta(pc_currchar, sk, sum); if(pi->amount>delta) // Paid too much { pi->amount-=delta; Sndbounce5(s); if (ps->IsDragging()) { ps->ResetDragging(); item_bounce5(s,pi); } } else { if(pi->amount < delta) // Gave less gold delta = pi->amount; // so adjust skillgain Items->DeleItem(pi); } pc_currchar->baseskill[sk]+=delta; Skills->updateSkillLevel(DEREF_P_CHAR(pc_currchar), sk); updateskill(s,sk); pc_currchar->trainer=-1; chars[t].trainingplayerin='\xFF'; itemsfx(s, pi->id());//AntiChrist - do the gold sound return true; } else // Did not give gold { npctalk(s, t, "I am sorry, but I can only accept gold.",0); Sndbounce5(s); if (ps->IsDragging()) { ps->ResetDragging(); item_bounce5(s,pi); return true; } else return true; }//if items[i]=gold return true; }
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 ); } }
static bool ItemDroppedOnBeggar(P_CLIENT ps, PKGx08 *pp, P_ITEM pi) { UOXSOCKET s=ps->GetSocket(); CHARACTER cc=ps->GetCurrChar(); P_CHAR pc_currchar = MAKE_CHARREF_LRV(cc,false); int t=calcCharFromSer(pp->Tserial); if(pi->id()!=0x0EED) { sprintf((char*)temp,"Sorry %s i can only use gold",pc_currchar->name); npctalk(s,t,(char*)temp,0); return false; } sprintf((char*)temp,"Thank you %s for the %i gold!",pc_currchar->name,pi->amount); npctalk(s,t,(char*)temp,0); if(pi->amount<=100) { pc_currchar->karma += 10; sysmessage(s,"You have gain a little karma!"); } else { pc_currchar->karma += 50; sysmessage(s,"You have gain some karma!"); } Items->DeleItem(pi); return true; }
void cTrade::clearalltrades() { AllItemsIterator iterItems; for (iterItems.Begin(); !iterItems.atEnd(); iterItems++) { P_ITEM pi = iterItems.GetData(); if (pi->type==1 && pi->pos.x==26 && pi->pos.y==0 && pi->pos.z==0 && pi->id()==0x1E5E) { P_CHAR pc = FindCharBySerial(pi->contserial); P_ITEM pBackpack = Packitem(pc); SERIAL serial = pi->serial; unsigned int ci; vector<SERIAL> vecContainer = contsp.getData(serial); for (ci = 0; ci < vecContainer.size(); ci++) { P_ITEM pj = FindItemBySerial(vecContainer[ci]); if (pj != NULL) if ((pj->contserial==serial)) { if(pBackpack != NULL) { pBackpack->AddItem(pj); } } } iterItems--; // Iterator will became invalid when deletting. Items->DeleItem(pi); clConsole.send("Trade cleared\n"); } } }
void cDragItems::dropOnBanker( P_CLIENT client, P_ITEM pItem, P_CHAR pBanker ) { P_CHAR pChar = client->player(); // No cheque ? >> Put into bank if( ( pItem->id() != 0x14F0 ) && ( pItem->type() != 1000 ) ) { P_ITEM bankBox = pChar->getBankBox(); if( bankBox ) bankBox->AddItem( pItem ); else bounceItem( client, pItem ); pBanker->talk( QString( "The %1 is now in thy bank box" ).arg( pItem->getName() ) ); return; } // No Value ?! if( !pItem->value ) { pBanker->talk( "This cheque does not have any value!" ); bounceItem( client, pItem ); return; } pChar->giveGold( pItem->value, true ); pBanker->talk( QString( "%1 I have cashed thy cheque and deposited %2 gold." ).arg( pChar->name.c_str() ).arg( pItem->amount() ) ); pItem->ReduceAmount(); statwindow( client->socket(), pChar ); }
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; }
////////////////// // name: RecursePacks // Purpose: recurses through the container given by bp to calculate the total weight // History: Ison 2-20-99 - rewrote by Tauriel 3/20/99 // rewritten by Duke 4.11.2k // float cWeight::RecursePacks(P_ITEM bp) { float totalweight=0.0; if (bp == NULL) return 0.0f; unsigned int ci = 0; vector<SERIAL> vecContainer = contsp.getData(bp->serial); for ( ci = 0; ci < vecContainer.size(); ci++) { P_ITEM pi = FindItemBySerial(vecContainer[ci]); int itemsweight=pi->getWeight(); if (pi->type==1) //item is another container { totalweight += (itemsweight/100.0f); // the weight of container itself totalweight += RecursePacks(pi); //find the item's weight within this container } if (pi->id() == 0x0EED) totalweight += (pi->amount*SrvParms->goldweight); else totalweight += (float)((itemsweight*pi->amount)/100.0f); } return totalweight; }
// 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 ); }
////////////////// // name: RecursePacks // Purpose: recurses through the container given by bp to calculate the total weight // History: Ison 2-20-99 - rewrote by Tauriel 3/20/99 // rewritten by Duke 4.11.2k // float cWeight::RecursePacks(P_ITEM bp) { float totalweight=0.0; if (bp == NULL) return 0.0f; unsigned int ci = 0; vector<SERIAL> vecContainer = contsp.getData(bp->serial); for ( ci = 0; ci < vecContainer.size(); ci++) { P_ITEM pi = FindItemBySerial(vecContainer[ci]); if ( pi == NULL ) // Should never happen, but... { contsp.remove( bp->serial, vecContainer[ci]); // Remove the invalid Entrie. continue; // let's pick up next. } int itemsweight=pi->getWeight(); if( pi->type() == 1 ) //item is another container { totalweight += (itemsweight/100.0f); // the weight of container itself totalweight += RecursePacks(pi); //find the item's weight within this container } if (pi->id() == 0x0EED) totalweight += ( pi->amount() * SrvParams->goldWeight() ); else totalweight += (float)((itemsweight * pi->amount())/100.0f); } return totalweight; }
static bool ItemDroppedOnBanker(P_CLIENT ps, PKGx08 *pp, P_ITEM pi) { UOXSOCKET s=ps->GetSocket(); CHARACTER cc=ps->GetCurrChar(); P_CHAR pc_currchar = MAKE_CHARREF_LRV(cc,true); int t=calcCharFromSer(pp->Tserial); P_ITEM bankbox = pc_currchar->GetBankBox(); int amt = pi->amount; int value = pi->value; if (pi->id() == 0x14F0 && pi->type == 1000) { const P_ITEM pi_n = Items->SpawnItem(DEREF_P_CHAR(pc_currchar), DEREF_P_CHAR(pc_currchar),value,"#",1,0x0E,0xED,0,0,0,0); if(pi_n == NULL) return false; sprintf((char*)temp,"%s I have cashed your check and deposited %i gold.",pc_currchar->name, value); npctalk(s,t,(char*)temp,0); bankbox->AddItem(pi_n); statwindow(s, DEREF_P_CHAR(pc_currchar)); return true; } else { if (pi->id() == 0x0EED) { sprintf((char*)temp,"%s you have deposited %i gold.",pc_currchar->name, amt); npctalk(s,t,(char*)temp,0); bankbox->AddItem(pi); statwindow(s, DEREF_P_CHAR(pc_currchar)); return true; } else { sprintf((char*)temp,"Sorry %s i can only deposit gold",pc_currchar->name); npctalk(s,t,(char*)temp,0); Sndbounce5(s); if (ps->IsDragging()) { ps->ResetDragging(); item_bounce5(s,pi); return true; } } return true; } }
// Handles house commands from friends of the house. // msg must already be capitalized void HouseSpeech( cUOSocket *socket, P_CHAR pPlayer, const QString& msg ) { Q_UNUSED(socket); // Not inside a multi if( pPlayer->multis() == INVALID_SERIAL ) return; P_ITEM pMulti = FindItemBySerial( pPlayer->multis() ); if( !pMulti ) { clConsole.send( tr( "Player %1 [0x%2] has bad multi serial [0x%1]" ).arg( pPlayer->name() ).arg( pPlayer->serial(), 8, 16 ).arg( pPlayer->multis() ) ); pPlayer->setMultis( INVALID_SERIAL ); return; } if ( pMulti && IsHouse( pMulti->id() ) ) { cHouse* pHouse = dynamic_cast< cHouse* >( pMulti ); // Only the owner or a friend of the house can control it if( !( pPlayer->Owns( pHouse ) || pHouse->isFriend( pPlayer ) ) ) return; } else return; // >> LEGACY /*if(msg.contains("I BAN THEE")) { // house ban addid1[s] = pMulti->serial()>>24; addid2[s] = pMulti->serial()>>16; addid3[s] = pMulti->serial()>>8; addid4[s] = pMulti->serial()%256; target(s, 0, 1, 0, 229, "Select person to ban from house."); } else if(msg.contains("REMOVE THYSELF")) { // kick out of house addid1[s] = pMulti->serial()>>24; addid2[s] = pMulti->serial()>>16; addid3[s] = pMulti->serial()>>8; addid4[s] = pMulti->serial()%256; target(s, 0, 1, 0, 228, "Select person to eject from house."); } else if (msg.contains("I WISH TO LOCK THIS DOWN")) { // lock down code AB/LB target(s, 0, 1, 0, 232, "Select item to lock down"); } else if (msg.contains("I WISH TO RELEASE THIS")) { // lock down code AB/LB target(s, 0, 1, 0, 233, "Select item to release"); } else if (msg.contains("I WISH TO SECURE THIS")) { // lock down code AB/LB target(s, 0, 1, 0, 234, "Select item to secure"); }*/ }
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(); }
void cDragItems::dropItem( cUOSocket *socket, cUORxDropItem *packet ) { P_PLAYER pChar = socket->player(); if( !pChar ) return; // Get the data SERIAL contId = packet->cont(); Coord_cl dropPos = pChar->pos(); // plane dropPos.x = packet->x(); dropPos.y = packet->y(); dropPos.z = packet->z(); // Get possible containers P_ITEM pItem = FindItemBySerial( packet->serial() ); if( !pItem ) return; P_ITEM iCont = FindItemBySerial( packet->cont() ); P_CHAR cCont = FindCharBySerial( packet->cont() ); // >> SEE LORD BINARIES DROPFIX << // A completely invalid Drop packet if( !iCont && !cCont && ( dropPos.x == 0xFFFF ) && ( dropPos.y == 0xFFFF ) && ( (unsigned char)dropPos.z == 0xFF ) ) { socket->bounceItem( pItem, BR_NO_REASON ); return; } UINT32 weight = pChar->weight(); // Item dropped on Ground if( !iCont && !cCont ) dropOnGround( socket, pItem, dropPos ); // Item dropped on another item else if( iCont ) dropOnItem( socket, pItem, iCont, dropPos ); // Item dropped on char else if( cCont ) dropOnChar( socket, pItem, cCont ); // Handle the sound-effect if( pItem->id() == 0xEED ) goldsfx( socket, pItem->amount(), true ); // Update our weight. if( weight != pChar->weight() ) socket->sendStatWindow(); }
bool cMovement::canLandMonsterMoveHere( const Coord_cl& pos ) const { if ( pos.x >= ( Maps::instance()->mapTileWidth( pos.map ) * 8 ) || pos.y >= ( Maps::instance()->mapTileHeight( pos.map ) * 8 ) ) return false; const signed char elev = Maps::instance()->mapElevation( pos ); Coord_cl target = pos; target.z = elev; if ( ILLEGAL_Z == elev ) return false; // get the tile id of any dynamic tiles at this spot Coord_cl mPos = pos; mPos.z = elev; const Q_INT32 dt = DynTile( mPos ); // if there is a dynamic tile at this spot, check to see if its a blocker // if it does block, might as well Q_INT16-circuit and return right away if ( dt >= 0 ) { tile_st tile = TileCache::instance()->getTile( dt ); if ( tile.isBlocking() || tile.isWet() ) return false; } // if there's a static block here in our way, return false StaticsIterator msi = Maps::instance()->staticsIterator( pos ); while ( !msi.atEnd() ) { tile_st tile = TileCache::instance()->getTile( msi->itemid ); const Q_INT32 elev = msi->zoff + cTileCache::tileHeight( tile ); if ( ( elev >= pos.z ) && ( msi->zoff <= pos.z ) ) { if ( tile.isBlocking() || tile.isWet() ) return false; } msi++; } RegionIterator4Items items( pos, 0 ); for ( items.Begin(); !items.atEnd(); items++ ) { P_ITEM item = items.GetData(); tile_st tile = TileCache::instance()->getTile( item->id() ); const Q_INT32 elev = item->pos().z + cTileCache::tileHeight( tile ); if ( ( elev >= pos.z ) && ( item->pos().z <= pos.z ) ) { if ( tile.isBlocking() || tile.isWet() ) return false; } } return true; }
//AntiChrist - do the sound effect ( only if HITTEN! ) void cCombat::doSoundEffect(P_CHAR pc, int fightskill, P_ITEM pWeapon) { bool heavy=false; int a=rand()%4; //check if a heavy weapon if (pWeapon && IsAxe(pWeapon->id())) heavy=true; if(heavy) { if (a==0 || a==1) soundeffect2(pc, 0x0236); else soundeffect2(pc, 0x0237); return; } switch(fightskill) { case ARCHERY: soundeffect2(pc, 0x0234); break; case FENCING: case SWORDSMANSHIP: if (a==0 || a==1) soundeffect2(pc, 0x023B); else soundeffect2(pc, 0x023C); break; case MACEFIGHTING: if (a==0 || a==1) soundeffect2(pc, 0x0232); else if (a==2) soundeffect2(pc, 0x0139); else soundeffect2(pc, 0x0233); break; case WRESTLING: if (a==0) soundeffect2(pc, 0x0135); else if (a==1) soundeffect2(pc, 0x0137); else if (a==2) soundeffect2(pc, 0x013D); else soundeffect2(pc, 0x013B); break; default: soundeffect2(pc, 0x013D); } }
void cDragItems::dropOnBroker( cUOSocket* socket, P_ITEM pItem, P_CHAR pBroker ) { // For House and Boat deeds we should pay back 75% of the value if( pItem->id() == 0x14EF ) { if( !pItem->sellprice() ) { pBroker->talk( tr("I can only accept deeds with value!") ); bounceItem( socket, pItem ); return; } socket->player()->giveGold( pItem->sellprice(), true ); pBroker->talk( tr( "Here you have your %1 gold, %2" ).arg( pItem->sellprice() ).arg( socket->player()->name() ) ); Items->DeleItem( pItem ); return; } bounceItem( socket, pItem ); }
// history: added containersearch Duke, 4.11.2k float cWeight::LockeddownWeight(P_ITEM pItem, int *total, int *total2 ) { float totalweight=0.0; if (!pItem) { *total=0; return 0.0; } unsigned int ci = 0; P_ITEM pi; vector<SERIAL> vecContainer = contsp.getData(pItem->serial); for ( ci = 0; ci < vecContainer.size(); ci++) { pi = FindItemBySerial(vecContainer[ci]); int itemsweight=pi->getWeight(); total2=total2+pi->amount(); *total=*total+1; if( pi->type() == 1 || pi->type() == 63 || pi->type() == 65 || pi->type() == 87) //item is another container { totalweight+=(itemsweight/100.0f); //(pi->weight/100); totalweight+=LockeddownWeight(pi, total, total2); //find the item's weight within this container } if ( pi->id() == 0x0EED ) totalweight+=(pi->amount()*SrvParams->goldWeight()); else totalweight+=(float)((itemsweight*pi->amount())/100.0f); //((pi->weight*pi->amount)/100); // Ison 2-21-99 } if (*total==0) { *total=pItem->amount(); *total=*total*-1; // Indicate that not a pack ! on osi servers in that case weigt/items count isnt shown // thus i set it negative, if you want to show it anyway, add something like if (weight<0) weight*=-1; return ((((float)pItem->getWeight())/100)*pItem->amount()); // if no pack return single item weight*/ } else return totalweight; }
void cDragItems::dropOnBroker( P_CLIENT client, P_ITEM pItem, P_CHAR pBroker ) { // For House and Boat deeds we should pay back 75% of the value if( pItem->id() == 0x14EF ) { if( !pItem->value ) { pBroker->talk( "I can only accept deeds with value!" ); bounceItem( client, pItem ); return; } Q_UINT32 nValue = static_cast< Q_UINT32 >( 0.75 * pItem->value ); client->player()->giveGold( nValue, true ); Items->DeleItem( pItem ); pBroker->talk( QString( "Here you have your %1 gold, %2" ).arg( nValue ).arg( client->player()->name.c_str() ) ); return; } bounceItem( client, pItem ); }
/////////////////////////// // Name: ContainerCountItems // history: by Duke, 26.03.2001 // Purpose: searches the container given by serial AND the subcontainers // for items with the given id and (if given) color. // Returns the total number of items found // int ContainerCountItems(const int serial, short id, short color) { unsigned int ci=0; int total=0; P_ITEM pi; vector<SERIAL> vecContainer = contsp.getData(serial); for ( ci = 0; ci < vecContainer.size(); ci++) { pi = FindItemBySerial(vecContainer[ci]); if (!pi || pi->free) // just to be sure ;-) continue; if (pi->type==1) // a subcontainer ? { total += ContainerCountItems(pi->serial, id, color); continue; } if (pi->id()==id && (color==-1 || pi->color == color)) total += pi->amount; } return total; }
// 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); }
int cCombat::GetBowType(P_CHAR pc) { unsigned int ci=0; P_ITEM pi; vector<SERIAL> vecContainer = contsp.getData(pc->serial); for ( ; ci < vecContainer.size(); ++ci) { pi = FindItemBySerial(vecContainer[ci]); if (pi && ( pi->layer == 1 || pi->layer == 2 ) ) { switch( pi->id() ) { case 0x13B1: case 0x13B2: return 1; // bows case 0x0F4F: case 0x0F50: return 2; // crossbow case 0x13FC: case 0x13FD: return 3; // heavy xbow } } } return 0; }
bool inmulti(Coord_cl pos, P_ITEM pi)//see if they are in the multi at these chords (Z is NOT checked right now) { int j; SI32 length; // signed long int on Intel st_multi multi; UOXFile *mfile; Map->SeekMulti(pi->id()-0x4000, &mfile, &length); length=length/sizeof(st_multi); if (length == -1 || length>=17000000)//Too big... { sprintf((char*)temp,"inmulti() - Bad length in multi file. Avoiding stall. (Item Name: %s)\n", pi->name.c_str() ); LogError( (char*)temp ); // changed by Magius(CHE) (1) length = 0; } for (j=0;j<length;j++) { mfile->get_st_multi(&multi); if ((multi.visible)&&(pi->pos.x+multi.x == pos.x) && (pi->pos.y+multi.y == pos.y)) { return true; } } return false; }
void cDragItems::dropOnTrainer( P_CLIENT client, P_ITEM pItem, P_CHAR pTrainer ) { P_CHAR pChar = client->player(); if( pItem->id() != 0xEED ) { pTrainer->talk( "You need to give me gold if you want me to train you!" ); bounceItem( client, pItem ); return; } pTrainer->talk( "I thank thee for thy payment. That should give thee a good start on thy way. Farewell!" ); Q_UINT8 skill = pTrainer->trainingplayerin(); Q_INT32 skillSum = pChar->getSkillSum(); Q_INT32 skillDelta = pTrainer->getTeachingDelta( pChar, skill, skillSum ); goldsfx( client->socket(), pItem->amount() ); if( pItem->amount() > skillDelta ) { pItem->ReduceAmount( skillDelta ); bounceItem( client, pItem ); } else { skillDelta = pItem->amount(); Items->DeleItem( pItem ); } pChar->setBaseSkill( skill, pChar->baseSkill( skill ) + skillDelta ); Skills->updateSkillLevel( pChar, skill ); updateskill( client->socket(), skill ); // we will not reset the trainer id here because he may want to give him more money }
static bool ItemDroppedOnSelf(P_CLIENT ps, PKGx08 *pp, P_ITEM pi) { UOXSOCKET s=ps->GetSocket(); CHARACTER cc=ps->GetCurrChar(); P_CHAR pc_currchar = MAKE_CHARREF_LRV(cc,true); if (pi->id1>=0x40) // crashfix , prevents putting multi-objects ni your backback { sysmessage(s,"Hey, putting houses in your pack crashes your back and client !"); pi->MoveTo(pc_currchar->pos.x,pc_currchar->pos.y,pc_currchar->pos.z); RefreshItem(pi);//AntiChrist return true; } if (pi->glow>0) // glowing items { pc_currchar->addHalo(pi); pc_currchar->glowHalo(pi); } P_ITEM pack = Packitem(pc_currchar); // LB ... if (pack == NULL) // if player has no pack, put it at its feet { pi->MoveTo(pc_currchar->pos.x,pc_currchar->pos.y,pc_currchar->pos.z); RefreshItem(pi);//AntiChrist } else { pack->AddItem(pi); // player has a pack, put it in there Weight->NewCalc(DEREF_P_CHAR(pc_currchar));//AntiChrist bugfixes statwindow(s,DEREF_P_CHAR(pc_currchar)); itemsfx(s, pi->id()); } return true; }
// The highest items will be @ the beginning // While walking we always will try the highest first. vector< stBlockItem > getBlockingItems( P_CHAR pChar, const Coord& pos ) { vector<stBlockItem> blockList; make_heap( blockList.begin(), blockList.end(), compareTiles() ); // Process the map at that position stBlockItem mapBlock; mapBlock.maptile = true; mapBlock.z = Maps::instance()->mapAverageElevation( pos ); mapBlock.height = 0; // TODO: Calculate the REAL average Z Value of that Map Tile here! Otherwise clients will have minor walking problems. map_st mapCell = Maps::instance()->seekMap( pos ); //mapBlock.z = mapCell.z; land_st mapTile = TileCache::instance()->getLand( mapCell.id ); // If it's not impassable it's automatically walkable if ( !( mapTile.flag1 & 0x40 ) ) mapBlock.walkable = true; else mapBlock.walkable = checkWalkable( pChar, mapCell.id ); if ( mapCell.id != 0x02 ) { blockList.push_back( mapBlock ); push_heap( blockList.begin(), blockList.end(), compareTiles() ); } // Now for the static-items StaticsIterator staIter = Maps::instance()->staticsIterator( pos, true ); for ( ; !staIter.atEnd(); ++staIter ) { tile_st tTile = TileCache::instance()->getTile( staIter->itemid ); // Here is decided if the tile is needed // It's uninteresting if it's NOT blocking // And NOT a bridge/surface if ( !( ( tTile.flag2 & 0x02 ) || ( tTile.flag1 & 0x40 ) || ( tTile.flag2 & 0x04 ) ) ) continue; stBlockItem staticBlock; staticBlock.z = staIter->zoff; // If we are a surface we can always walk here, otherwise check if // we are special if ( ( tTile.flag2 & 0x02 ) && !( tTile.flag1 & 0x40 ) ) staticBlock.walkable = true; else staticBlock.walkable = checkWalkable( pChar, staIter->itemid ); // If we are a stair only the half height counts (round up) if ( tTile.flag2 & 0x04 ) staticBlock.height = ( Q_UINT8 ) ( ( tTile.height ) / 2 ); else staticBlock.height = tTile.height; blockList.push_back( staticBlock ); push_heap( blockList.begin(), blockList.end(), compareTiles() ); } // We are only interested in items at pos // todo: we could impliment blocking for items on the adjacent sides // during a diagonal move here, but this has yet to be decided. MapItemsIterator iIter = MapObjects::instance()->listItemsAtCoord( pos ); for ( P_ITEM pItem = iIter.first(); pItem; pItem = iIter.next() ) { if ( pChar && pChar->isDead() ) { // Doors can be passed by ghosts if ( pItem->hasScript( "door" ) ) { continue; } } tile_st tTile = TileCache::instance()->getTile( pItem->id() ); // See above for what the flags mean if ( !( ( tTile.flag2 & 0x02 ) || ( tTile.flag1 & 0x40 ) || ( tTile.flag2 & 0x04 ) ) ) continue; stBlockItem blockItem; blockItem.height = ( tTile.flag2 & 0x04 ) ? ( tTile.height / 2 ) : tTile.height; blockItem.z = pItem->pos().z; // Once again: see above for a description of this part if ( ( tTile.flag2 & 0x02 ) && !( tTile.flag1 & 0x40 ) ) blockItem.walkable = true; else blockItem.walkable = checkWalkable( pChar, pItem->id() ); blockList.push_back( blockItem ); push_heap( blockList.begin(), blockList.end(), compareTiles() ); } // deal with the multis now, or not. // 18 has been tested with castle sides and corners... MapMultisIterator iter = MapObjects::instance()->listMultisInCircle( pos, 18 ); for ( cMulti*pMulti = iter.first(); pMulti; pMulti = iter.next() ) { MultiDefinition* def = MultiCache::instance()->getMulti( pMulti->id() - 0x4000 ); if ( !def ) continue; QValueVector<multiItem_st> multi = def->getEntries(); for ( unsigned int j = 0; j < multi.size(); ++j ) { if ( multi[j].visible && ( pMulti->pos().x + multi[j].x == pos.x ) && ( pMulti->pos().y + multi[j].y == pos.y ) ) { tile_st tTile = TileCache::instance()->getTile( multi[j].tile ); if ( !( ( tTile.flag2 & 0x02 ) || ( tTile.flag1 & 0x40 ) || ( tTile.flag2 & 0x04 ) ) ) continue; stBlockItem blockItem; blockItem.height = ( tTile.flag2 & 0x04 ) ? ( tTile.height / 2 ) : tTile.height; blockItem.z = pMulti->pos().z + multi[j].z; if ( ( tTile.flag2 & 0x02 ) && !( tTile.flag1 & 0x40 ) ) blockItem.walkable = true; else blockItem.walkable = checkWalkable( pChar, pMulti->id() ); blockList.push_back( blockItem ); push_heap( blockList.begin(), blockList.end(), compareTiles() ); } } continue; } // Now we need to evaluate dynamic items [...] (later) ?? sort_heap( blockList.begin(), blockList.end(), compareTiles() ); return blockList; };
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 ); }