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); } }
// do one spawn and reset the timer void cSpawnRegion::reSpawn( void ) { this->checkForDeleted(); UI16 i = 0; for( i = 0; i < this->npcsPerCycle_; i++ ) { if( this->npcSerials_.size() < this->maxNpcAmt_ ) { // spawn a random npc // first find a valid position for the npc Coord_cl pos; if( this->findValidSpot( pos ) ) { QString NpcSect = this->npcSections_[ RandomNum( 1, this->npcSections_.size() ) - 1 ]; P_NPC pc = cCharStuff::createScriptNpc( NpcSect, pos ); if( pc != NULL ) { this->npcSerials_.push_back( pc->serial() ); pc->setSpawnregion( this->name_ ); } } } } for( i = 0; i < this->itemsPerCycle_; i++ ) { if( this->itemSerials_.size() < this->maxItemAmt_ ) { // spawn a random item // first find a valid position for the item Coord_cl pos; if( this->findValidSpot( pos ) ) { QString ItemSect = this->itemSections_[ RandomNum( 1, this->itemSections_.size() ) - 1 ]; P_ITEM pi = cItem::createFromScript( ItemSect ); if( pi != NULL ) { pi->moveTo( pos ); this->itemSerials_.push_back( pi->serial() ); // pi->setSpawnRegion( this->name_ ); } } } } this->nextTime_ = uiCurrentTime + RandomNum( this->minTime_, this->maxTime_ ) * MY_CLOCKS_PER_SEC; }
void cSpawnRegion::spawnSingleItem() { Coord_cl pos; if ( findValidSpot( pos ) ) { QString ItemSect = this->itemSections_[RandomNum( 1, this->itemSections_.size() ) - 1]; P_ITEM pi = cItem::createFromScript( ItemSect ); if ( pi ) { pi->moveTo( pos, true ); pi->setSpawnregion( this ); pi->update(); onSpawn( pi ); } } }
void cDragItems::dropOnGround( P_CLIENT client, P_ITEM pItem, const Coord_cl &pos ) { P_CHAR pChar = client->player(); // Check if the destination is in line of sight if( !line_of_sight( client->socket(), pChar->pos, pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) ) { client->sysMessage( "You cannot see the target." ); bounceItem( client, pItem ); return; } if( !pChar->canPickUp( pItem ) ) { bounceItem( client, pItem ); return; } pItem->setContSerial( INVALID_SERIAL ); pItem->moveTo( pos ); pItem->setLayer( 0 ); RefreshItem( pItem ); // Send it to all clients in range pChar->weight -= pItem->getWeight(); statwindow( client->socket(), pChar ); // Update our weight-stats if( pItem->glow != INVALID_SERIAL ) { pChar->removeHalo( pItem ); pChar->glowHalo( pItem ); } // Multi handling (Hm i don't like that...) if( pChar->multis > 0 ) { P_ITEM pMulti = FindItemBySerial( pChar->multis ); if( pMulti != NULL ) { pMulti = findmulti( pItem->pos ); if( pItem != NULL ) pItem->SetMultiSerial( pMulti->serial ); } } }
void cDragItems::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( !lineOfSight( pChar->pos(), pos, WALLS_CHIMNEYS|DOORS|LAVA_WATER ) ) { 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(); if( pItem->priv() & 0x01 ) pItem->startDecay(); // Multi handling // Has it been dropped into a multi cMulti* pMulti = cMulti::findMulti( pos ); if( pMulti ) { pMulti->addItem( pItem ); } }
void cBoat::Turn(P_ITEM pBoat, int turn)//Turn the boat item, and send all the people/items on the boat to turnboatstuff() { if (pBoat == NULL) return; int id2 = pBoat->id2 ,olddir = pBoat->dir; unsigned short int Send[MAXCLIENT]; SERIAL serial; int a,dir, d=0; for (a = 0; a < now; ++a) { if (iteminrange(a, pBoat, BUILDRANGE) && perm[a]) { Send[d]=a; Xsend(a,wppause,2); d++; } } //Of course we need the boat items! serial = calcserial(pBoat->moreb1,pBoat->moreb2,pBoat->moreb3,pBoat->moreb4); if(serial == INVALID_SERIAL) return; P_ITEM pTiller = FindItemBySerial( serial ); if(pTiller == NULL) return; P_ITEM pi_p1 = FindItemBySerial( pBoat->morex ); if(pi_p1 == NULL) return; P_ITEM pi_p2 = FindItemBySerial( pBoat->morey ); if(pi_p2 == NULL) return; P_ITEM pi_hold = FindItemBySerial( pBoat->morez ); if(pi_hold == NULL) return; if(turn)//Right { pBoat->dir+=2; id2++; } else {//Left pBoat->dir-=2; id2--; } if(pBoat->dir>7) pBoat->dir-=4;//Make sure we dont have any DIR errors //if(pBoat->dir<0) pBoat->dir+=4; if(id2<pBoat->more1) id2+=4;//make sure we don't have any id errors either if(id2>pBoat->more2) id2-=4;//Now you know what the min/max id is for :-) pBoat->id2=id2;//set the id if(pBoat->id2==pBoat->more1) pBoat->dir=0;//extra DIR error checking if(pBoat->id2==pBoat->more2) pBoat->dir=6; if( Block( pBoat, 0, 0, pBoat->dir ) ) { pBoat->dir = olddir; for( a = 0; a < d; a++ ) { Xsend( Send[a], restart, 2 ); itemtalk( Send[a], pTiller, "Arr, something's in the way!" ); } return; } pBoat->id2=id2;//set the id if(pBoat->id2==pBoat->more1) pBoat->dir=0;//extra DIR error checking if(pBoat->id2==pBoat->more2) pBoat->dir=6; serial=pBoat->serial; // lb !!! unsigned int ci; vector<SERIAL> vecEntries = imultisp.getData(serial); for (ci = 0; ci < vecEntries.size(); ci++) { P_ITEM pi = FindItemBySerial(vecEntries[ci]); if (pi != NULL) TurnStuff(pBoat, pi, turn); } vecEntries.clear(); vecEntries = cmultisp.getData(serial); for (ci = 0; ci < vecEntries.size(); ci++) { P_CHAR pc = FindCharBySerial(vecEntries[ci]); if (pc != NULL) TurnStuff(pBoat, pc, turn); } //Set the DIR for use in the Offsets/IDs array dir = (pBoat->dir&0x0F)/2; //set it's Z to 0,0 inside the boat pi_p1->MoveTo(pBoat->pos.x,pBoat->pos.y,pi_p1->pos.z); pi_p1->id2 = cShipItems[dir][PORT_P_C];//change the ID pi_p2->MoveTo(pBoat->pos.x,pBoat->pos.y,pi_p2->pos.z); pi_p2->id2=cShipItems[dir][STAR_P_C]; pTiller->MoveTo(pBoat->pos.x,pBoat->pos.y, pTiller->pos.z); pTiller->id2=cShipItems[dir][TILLERID]; pi_hold->MoveTo(pBoat->pos.x,pBoat->pos.y, pi_hold->pos.z); pi_hold->id2=cShipItems[dir][HOLDID]; switch(pBoat->more1)//Now set what size boat it is and move the specail items { case 0x00: case 0x04: pi_p1->moveTo(pi_p1->pos + Coord_cl(iSmallShipOffsets[dir][PORT_PLANK][X], iSmallShipOffsets[dir][PORT_PLANK][Y], 0)); pi_p2->moveTo(pi_p2->pos + Coord_cl(iSmallShipOffsets[dir][STARB_PLANK][X], iSmallShipOffsets[dir][STARB_PLANK][Y], 0)); pTiller->moveTo(pTiller->pos + Coord_cl(iSmallShipOffsets[dir][TILLER][X], iSmallShipOffsets[dir][TILLER][Y], 0)); pi_hold->moveTo(pi_hold->pos + Coord_cl(iSmallShipOffsets[dir][HOLD][X], iSmallShipOffsets[dir][HOLD][Y], 0)); break; case 0x08: case 0x0C: pi_p1->moveTo(pi_p1->pos + Coord_cl(iMediumShipOffsets[dir][PORT_PLANK][X], iMediumShipOffsets[dir][PORT_PLANK][Y], 0) ); pi_p2->moveTo(pi_p2->pos + Coord_cl(iMediumShipOffsets[dir][STARB_PLANK][X], iMediumShipOffsets[dir][STARB_PLANK][Y], 0) ); pTiller->moveTo(pTiller->pos + Coord_cl(iMediumShipOffsets[dir][TILLER][X], iMediumShipOffsets[dir][TILLER][Y], 0) ); pi_hold->moveTo(pi_hold->pos + Coord_cl(iMediumShipOffsets[dir][HOLD][X], iMediumShipOffsets[dir][HOLD][Y], 0) ); break; case 0x10: case 0x14: pi_p1->moveTo(pi_p1->pos + Coord_cl(iLargeShipOffsets[dir][PORT_PLANK][X], iLargeShipOffsets[dir][PORT_PLANK][Y], 0) ); pi_p2->moveTo(pi_p2->pos + Coord_cl(iLargeShipOffsets[dir][STARB_PLANK][X], iLargeShipOffsets[dir][STARB_PLANK][Y], 0 ) ); pTiller->moveTo(pTiller->pos + Coord_cl(iLargeShipOffsets[dir][TILLER][X], iLargeShipOffsets[dir][TILLER][Y], 0 ) ); pi_hold->moveTo(pi_hold->pos + Coord_cl(iLargeShipOffsets[dir][HOLD][X], iLargeShipOffsets[dir][HOLD][Y], 0 ) ); break; default: { sprintf((char*)temp,"Turnboatstuff() more1 error! more1 = %c not found!\n",pBoat->more1); LogWarning((char*)temp); } } sendinrange(pi_p1); sendinrange(pi_p2); sendinrange(pi_hold); sendinrange(pTiller); for (a = 0; a < d; ++a) { Xsend(Send[a],restart,2); } }
void cBoat::Move(UOXSOCKET s, int dir, P_ITEM pBoat) {//Move the boat and all it's items 1 square int tx=0,ty=0; int serial; if (pBoat == NULL) return; serial = calcserial(pBoat->moreb1, pBoat->moreb2, pBoat->moreb3, pBoat->moreb4); if (serial == INVALID_SERIAL) return; P_ITEM pTiller = FindItemBySerial( serial ); if(pTiller == NULL) return; P_ITEM pi_p1 = FindItemBySerial( pBoat->morex ); if(pi_p1 == NULL) return; P_ITEM pi_p2 = FindItemBySerial( pBoat->morey ); if(pi_p2 == NULL) return; P_ITEM pHold = FindItemBySerial( pBoat->morez ); if(pHold == NULL) return; Xsend(s,wppause,2); switch(dir&0x0F)//Which DIR is it going in? { case '\x00' : ty--; break; case '\x01' : tx++; ty--; break; case '\x02' : tx++; break; case '\x03' : tx++; ty++; break; case '\x04' : ty++; break; case '\x05' : tx--; ty++; break; case '\x06' : tx--; break; case '\x07' : tx--; ty--; break; default: { sprintf((char*)temp,"warning: Boat direction error: %i int boat %i\n",pBoat->dir&0x0F,pBoat->serial); LogWarning((char*)temp); break; } } if((pBoat->pos.x+tx<=200 || pBoat->pos.x+tx>=6000) && (pBoat->pos.y+ty<=200 || pBoat->pos.y+ty>=4900)) //bugfix LB { pBoat->type2=0; itemtalk(s, pTiller, "Arr, Sir, we've hit rough waters!"); Xsend(s,restart,2); return; } if(Block(pBoat,tx,ty,dir)) { pBoat->type2=0; itemtalk(s, pTiller, "Arr, somethings in the way!"); Xsend(s,restart,2); return; } //Move all the special items Coord_cl desloc(tx, ty, 0); pBoat->moveTo(pBoat->pos + desloc); pTiller->moveTo(pTiller->pos + desloc); pi_p1->moveTo(pi_p1->pos + desloc); pi_p2->moveTo(pi_p2->pos + desloc); pHold->moveTo(pHold->pos + desloc); serial = pBoat->serial; unsigned int a; vector<SERIAL> vecEntries = imultisp.getData(pBoat->serial); for (a = 0; a < vecEntries.size(); a++) { P_ITEM pi = FindItemBySerial(vecEntries[a]); if(pi != NULL) { pi->MoveTo(pi->pos.x+=tx, pi->pos.y+=ty, pi->pos.z); sendinrange(pi); } } vecEntries.clear(); vecEntries = cmultisp.getData(pBoat->serial); for (a = 0; a < vecEntries.size(); a++) { P_CHAR pc_c = FindCharBySerial(vecEntries[a]); if (pc_c != NULL) { pc_c->moveTo(pc_c->pos + desloc); teleport((pc_c)); } } Xsend(s,restart,2); }
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 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(); }
// CombatHit now expects that LineOfSight has been checked before (Duke, 10.7.2001) void cCombat::CombatHit(P_CHAR pc_attacker, P_CHAR pc_deffender, unsigned int currenttime, short los) { char hit; if (pc_deffender == NULL || pc_attacker == NULL) return; UOXSOCKET s1=calcSocketFromChar(pc_attacker), s2=calcSocketFromChar(pc_deffender); unsigned short fightskill = Skills->GetCombatSkill(pc_attacker), bowtype = Combat->GetBowType(pc_attacker),splitnum,splitcount,hitin; unsigned int basedamage; int damage; // removed from unsigne by Magius(CHE) signed int x; // Magius(CHE) - For armour absorbtion system int maxabs, maxnohabs, tmpj; P_ITEM pWeapon=pc_attacker->getWeapon();// get the weapon item only once if (pWeapon && !(rand()%50) // a 2 percent chance (Duke, 07.11.2000) && pWeapon->type !=9) // but not for spellbooks (Duke, 09/10/00) { pWeapon->hp--; //Take off a hit point if(pWeapon->hp<=0) { sysmessage(s1, tr("Your weapon has been destroyed")); if ((pWeapon->trigon==1) && (pWeapon->layer>0))// -Frazurbluu- Trigger Type 2 is my new trigger type *- { Trig->triggerwitem(s1, pWeapon, 1); // trigger is fired when item destroyed } Items->DeleItem(pWeapon); } } // End here - Magius(CHE) - For armour absorbtion system pc_attacker->swingtarg=-1; if((chardist(pc_attacker, pc_deffender)>1 && fightskill!=ARCHERY) || !los) return; if(pc_deffender->isNpc() && pc_deffender->isInvul()) return; // ripper hit=Skills->CheckSkill(pc_attacker, fightskill, 0, 1000); // increase fighting skill for attacker and defender if (!hit) { if (pc_attacker->isPlayer()) doMissedSoundEffect(pc_attacker); if ((fightskill==ARCHERY)&&(los)) { if (rand()%3-1)//-1 0 or 1 { short id=0x1BFB; // bolts if (bowtype==1) id=0x0F3F; // arrows P_ITEM pAmmo=Items->SpawnItem(pc_deffender,1,"#",1,id,0,0); if(pAmmo) { pAmmo->moveTo(pc_deffender->pos); pAmmo->priv=1; RefreshItem(pAmmo); } } } } else { if (!pc_deffender->isInvul()) { if (pc_deffender->xid==0x0191) soundeffect2(pc_deffender,0x014b); else if (pc_deffender->xid==0x0190) soundeffect2(pc_deffender,0x0156); playmonstersound(pc_deffender, pc_deffender->id(), SND_DEFEND); //AntiChrist -- for poisoned weapons if((pWeapon) && (pWeapon->poisoned>0)) { pc_deffender->poisoned=pWeapon->poisoned; pc_deffender->poisontime=uiCurrentTime+(MY_CLOCKS_PER_SEC*(40/pc_deffender->poisoned)); // a lev.1 poison takes effect after 40 secs, a deadly pois.(lev.4) takes 40/4 secs - AntiChrist pc_deffender->poisonwearofftime=pc_deffender->poisontime+(MY_CLOCKS_PER_SEC*SrvParams->poisonTimer()); //wear off starts after poison takes effect - AntiChrist } CheckPoisoning(s2, pc_attacker, pc_deffender); // attacker poisons defender CheckPoisoning(s1, pc_deffender, pc_attacker); // and vice versa if ((pc_deffender->effDex()>0)) pc_deffender->priv2&=0xFD; // unfreeze if (fightskill!=WRESTLING && los) Combat->ItemSpell(pc_attacker, pc_deffender); if (fightskill!=WRESTLING || pc_attacker->isNpc()) basedamage=Combat->CalcAtt(pc_attacker); // Calc base damage else { if ((pc_attacker->skill[WRESTLING]/100) > 0) { if (pc_attacker->skill[WRESTLING]/100!=0) basedamage=rand()%(pc_attacker->skill[WRESTLING]/100); else basedamage=0; } else basedamage=rand()%2; } if((pc_attacker->isPlayer()) && (fightskill!=WRESTLING)) { if (pWeapon->racehate != 0 && pc_deffender->race != 0)//-Fraz- Racehating combat { if (pWeapon->racehate==pc_deffender->race) { basedamage *=2; if(pc_deffender->isPlayer()) { sysmessage(s2, tr("You scream in agony from being hit by the accursed metal!")); if (pc_deffender->xid == 0x0191) soundeffect2(pc_deffender,0x0152); else if (pc_deffender->xid==0x0190) soundeffect2(pc_deffender,0x0157); }// can add a possible effect below here for npc's being hit } } } Skills->CheckSkill(pc_attacker, TACTICS, 0, 1000); damage=(int)(basedamage*((pc_attacker->skill[TACTICS]+500.0)/1000.0)); // Add Tactical bonus damage=damage+(int)((basedamage*(pc_attacker->st/500.0))); // Add Strength bonus //Adds a BONUS DAMAGE for ANATOMY //Anatomy=100 -> Bonus +20% Damage - AntiChrist (11/10/99) if (Skills->CheckSkill(pc_attacker, ANATOMY, 0, 1000)) { float multiplier=(((pc_attacker->skill[ANATOMY]*20)/1000.0f)/100.0f)+1; damage=(int) (damage * multiplier); } //Adds a BONUS DEFENCE for TACTICS //Tactics=100 -> Bonus -20% Damage - AntiChrist (11/10/99) float multiplier=1-(((pc_deffender->skill[TACTICS]*20)/1000.0f)/100.0f); damage=(int) (damage * multiplier); P_ITEM pShield=pc_deffender->getShield(); if(pShield) { if (Skills->CheckSkill(pc_deffender, PARRYING, 0, 1000))// chance to block with shield { if (pShield->def!=0) damage-=rand()%(pShield->def);// damage absorbed by shield if(rand()%2) pShield->hp--; //Take off a hit point if(pShield->hp<=0) { sysmessage(s2, tr("Your shield has been destroyed")); if ((pShield->trigon==1) && (pShield->layer >0))// -Frazurbluu- Trigger Type 2 is my new trigger type *- { Trig->triggerwitem(s2, pShield, 1); // trigger is fired when item destroyed } Items->DeleItem(pShield); } } } // Armor destruction and sped up by hitting with maces should go in here somewhere // According to lacation of body hit Id imagine -Frazurbluu- **NEEDS ADDED** x=rand()%100;// determine area of body hit if (!SrvParams->combatHitMessage()) { if (x<=44) x=1; // body else if (x<=58) x=2; // arms else if (x<=72) x=3; // head else if (x<=86) x=4; // legs else if (x<=93) x=5; // neck else x=6; // hands } else { temp[0] = '\0'; hitin = rand()%2; if (x<=44) { x=1; // body switch (hitin) { case 1: //later take into account dir facing attacker during battle if (damage < 10) strcpy(temp, "hits you in your Chest!"); else if (damage >=10) strcpy(temp, "lands a terrible blow to your Chest!"); break; case 2: if (damage < 10) strcpy(temp, "lands a blow to your Stomach!"); else if (damage >=10) strcpy(temp, "knocks the wind out of you!"); break; default: if (damage < 10) strcpy(temp, "hits you in your Ribs!"); else if (damage >=10) strcpy(temp, "broken your Rib?!"); } } else if (x<=58) { if (damage > 1) { x=2; // arms switch (hitin) { case 1: strcpy(temp, "hits you in Left Arm!"); break; case 2: strcpy(temp, "hits you in Right Arm!"); break; default:strcpy(temp, "hits you in Right Arm!"); } } } else if (x<=72) { x=3; // head switch (hitin) { case 1: if (damage < 10) strcpy(temp, "hits you you straight in the Face!"); else if (damage >=10) strcpy(temp, "lands a stunning blow to your Head!"); break; case 2: if (damage < 10) strcpy(temp, "hits you to your Head!"); //kolours - (09/19/98) else if (damage >=10) strcpy(temp, "smashed a blow across your Face!"); break; default: if (damage < 10) strcpy(temp, "hits you you square in the Jaw!"); else if (damage >=10) strcpy(temp, "lands a terrible hit to your Temple!"); } } else if (x<=86) { x=4; // legs switch (hitin) { case 1: strcpy(temp, "hits you in Left Thigh!"); break; case 2: strcpy(temp, "hits you in Right Thigh!"); break; default:strcpy(temp, "hits you in Groin!"); } } else if (x<=93) { x=5; // neck strcpy(temp, "hits you to your Throat!"); } else { x=6; // hands switch (hitin) { case 1: if (damage > 1) strcpy(temp, tr("hits you in Left Hand!").latin1()); break; case 2: if (damage > 1) strcpy(temp, tr("hits you in Right Hand!").latin1()); break; default: if (damage > 1) strcpy(temp, tr("hits you in Right Hand!").latin1()); } } sprintf((char*)temp2,"%s %s",pc_attacker->name.c_str(), temp); if (pc_deffender->isPlayer() && s2!=-1) sysmessage(s2, (char*)temp2); //kolours -- hit display } x = CalcDef(pc_deffender,x); // Magius(CHE) - For armour absorbtion system maxabs = 20; // // there are monsters with DEF >20, this makes them undefeatable maxnohabs=100; if (SrvParams->maxAbsorbtion() > 0) { maxabs = SrvParams->maxAbsorbtion(); } if (SrvParams->maxnohabsorbtion() > 0) { maxnohabs = SrvParams->maxnohabsorbtion(); } if (!ishuman(pc_deffender)) maxabs=maxnohabs; tmpj=(int) (damage*x)/maxabs; // Absorbtion by Magius(CHE) damage -= tmpj; if (damage<0) damage=0; if (pc_deffender->isPlayer()) damage /= SrvParams->npcdamage(); // Rate damage against other players // End Armour Absorbtion by Magius(CHE) (See alse reactive armour spell damage) if (pc_attacker->isPlayer())//Zippy ItemCastSpell(s1, pc_deffender,pWeapon); //AntiChrist - 26/10/99 //when hitten and damage >1, defender fails if casting a spell! if(damage>1 && pc_deffender->isPlayer())//only if damage>1 and against a player { if(pc_deffender->casting && currentSpellType[s2]==0 ) {//if casting a normal spell (scroll: no concentration loosen) Magic->SpellFail(s2); currentSpellType[s2]=0; pc_deffender->spell=-1; pc_deffender->casting=0; pc_deffender->spelltime=0; pc_deffender->priv2 &= 0xfd; // unfreeze, bugfix LB } } if(damage>0) { if (pc_deffender->ra) // For reactive armor spell { // -Frazurbluu- RA may need a rewrite to be more OSI standard here // Its said 80% deflected 10% to attacker / 10% defender gotta check special effects int damage1; damage1=(int)( damage*(pc_deffender->skill[MAGERY]/2000.0)); pc_deffender->hp -= damage-damage1; if (pc_deffender->isNpc()) damage1 = damage1 * SrvParams->npcdamage(); // by Magius(CHE) pc_attacker->hp -= damage1; // Remove damage from attacker staticeffect(pc_deffender, 0x37, 0x4A, 0, 15);//RA effect - AntiChrist (9/99) if ((fightskill==MACEFIGHTING) && (IsSpecialMace(pWeapon->id())))// Stamina Loss -Fraz- { //pc_attacker->stm-=3+(rand()%4); } if ((fightskill==FENCING) && (IsFencing2H(pWeapon->id())))// Paralyzing -Fraz- { //will call the combat caused paralyzation **NEED TO DO** } if ((fightskill==SWORDSMANSHIP) && (IsAxe(pWeapon->id())))// Concussion Hit -Fraz- { //will call the combat caused concussion (loss of int for 30 secs) **NEED TO DO** // for now make it subtract mana //pc_attacker->mn-=(pc_attacker->mn/2); } updatestats(pc_attacker, 0); } else { // -Fraz- Now needs adjusted to happen on a skill percentage pc_deffender->hp-=damage; // Remove damage from defender only apply special hits to non-npc's if ((fightskill==MACEFIGHTING) && (IsSpecialMace(pWeapon->id())) && (pc_deffender->isPlayer()))// Stamina Loss -Fraz- { pc_deffender->stm-=3+(rand()%3); } if ((fightskill==FENCING) && (IsFencing2H(pWeapon->id())) && (pc_deffender->isPlayer()))// Paralyzing -Fraz- { tempeffect(pc_attacker, pc_deffender, 44, 0, 0, 0); sysmessage(s1, tr("You delivered a paralyzing blow")); } if ((fightskill==SWORDSMANSHIP) && (IsAxe(pWeapon->id())) && (pc_deffender->isPlayer()))// Concussion Hit -Fraz- { tempeffect(pc_attacker, pc_deffender, 45, 0, 0, 0); //pc_attacker->mn-=(pc_attacker->mn/2); //-Fraz- temp use of this for concussion } updatestats((pc_deffender), 0); } // blood shred by blackwind if (damage>10) { short id = 0x122c; if (damage>50) id=0x122a; else if (damage>40) id=0x122d; else if (damage>30) id=0x122e; else if (damage>20) id=0x122b; P_ITEM pBlood = Items->SpawnItem(pc_deffender, 1, "#", 0, id, 0, 0); if (pBlood) { pBlood->moveTo(pc_deffender->pos); pBlood->priv = 1; pBlood->setGMMovable(); //Moveable by GM RefreshItem(pBlood); pBlood->decaytime = (SrvParams->decayTime()/2)*MY_CLOCKS_PER_SEC+uiCurrentTime; } } ///////// For Splitting NPCs /// McCleod if ((pc_deffender->split>0)&&(pc_deffender->hp>=1)) { if (rand()%100<=pc_deffender->splitchnc) { if (pc_deffender->split==1) splitnum=1; else splitnum=rand()%pc_deffender->split+1; for (splitcount=0;splitcount<splitnum;splitcount++) Npcs->Split(pc_deffender); } } //////// End of spliting NPCs } if (pc_attacker->isPlayer()) if((fightskill==ARCHERY && los)|| fightskill!=ARCHERY) doSoundEffect(pc_attacker, fightskill, pWeapon); if (pc_deffender->hp<0) pc_deffender->hp=0; updatestats((pc_deffender), 0); x = pc_deffender->id(); if (x>=0x0190) { if (!pc_deffender->onhorse) npcaction(pc_deffender, 0x14); } } } }