/*! \brief returns the *index element of the vector of a container (identified by serial) \author Luxor \param serial the serial of the container \index the pointer to the integer which we're using for the search \note *index should be 0 at the beginning of the search \return P_ITEM of the item found */ P_ITEM containerSearch(int serial, int *index) { if (serial < 0 || (*index) < 0) return 0; P_ITEM pi = 0; vector<P_ITEM> &pcm = pContMap[serial]; for (pi = 0; pi == 0; (*index)++) { if ( pcm.empty()) return 0; if ((UI32)(*index) >= pcm.size()) return 0; pi = pcm[*index]; if (!(ISVALIDPI(pi))) { if ((UI32)(*index)+1 < pcm.size() && !pcm.empty()) pcm[*index] = pcm[pcm.size()-1]; } pi = 0; pcm.pop_back(); } if ( !ISVALIDPI(pi) ) return 0; return pi; }
static LOGICAL canMine( P_CHAR pc, P_ITEM weapon ) { VALIDATEPCR(pc,false); if( !ISVALIDPI(weapon) && ( pc->CountItemsByType(ITYPE_MINING) <= 0 ) ) pc->sysmsg( TRANSLATE("You must have a pickaxe or shovel in hand in order to mine.")); else { if ( (ISVALIDPI(weapon) && ( weapon->getType() == ITYPE_MINING )) || (pc->CountItemsByType(ITYPE_MINING) > 0 )) // Let's see if he has a shovel in his pack { if (pc->isMounting()) pc->sysmsg( TRANSLATE("You cant mine while on a horse!")); else if( !pc->IsGM() && (ores.stamina<0) && (abs( ores.stamina )>pc->stm) ) pc->sysmsg( TRANSLATE("You are too tired to mine.")); else return true; } } return false; }
void Skills::MakeMenu( P_CHAR pc, int m, int skill, P_ITEM first, P_ITEM second ) { Skills::MakeMenu( pc, m, skill, ISVALIDPI(first)? (unsigned short)first->getId() : (unsigned short)0, ISVALIDPI(first)? (unsigned short)first->getColor() : (unsigned short)0, ISVALIDPI(second)? (unsigned short)second->getId() : (unsigned short)0, ISVALIDPI(second)? (unsigned short)second->getColor() : (unsigned short)0 ); }
void Skills::MakeMenu( P_CHAR pc, int m, int skill, P_ITEM first, P_ITEM second ) { Skills::MakeMenu( pc, m, skill, ISVALIDPI(first)? first->getId() : 0, ISVALIDPI(first)? first->getColor() : 0, ISVALIDPI(second)? second->getId() : 0, ISVALIDPI(second)? second->getColor() : 0 ); }
/*! \brief Search player's paperdoll and then backpacks for items with weight then set the weight of the current player \author Ison (02/20/99), rewrote by Tauriel (03/20/99) \param pc the character \note The called character's weight is first set to zero then re-calculated during the function. */ void weights::NewCalc(P_CHAR pc) { VALIDATEPC(pc); double totalweight=0.0; //get weight for items on players NxwItemWrapper si; si.fillItemWeared( pc, false, false, true ); for( si.rewind(); !si.isEmpty(); si++ ) { P_ITEM pi=si.getItem(); // Wintermute: Exclude mounted layer (counts as worn item) if (ISVALIDPI(pi) && pi->layer != LAYER_MOUNT) { totalweight+=(pi->getWeightActual()/100.0); } } // Items in players pack P_ITEM bp= pc->getBackpack(); if (bp!=NULL) totalweight+=RecursePacks(bp); //LB pc->weight=(int)totalweight; return; }
void showItemLocationMap() { PITEMLOCATIONMAPIT it( pItemLocationMap.begin() ), end( pItemLocationMap.end() ); ConOut( "--------------------------------\n" ); ConOut( "| ITEM LOCATION MAP |\n" ); ConOut( "--------------------------------\n" ); ConOut( "| Key | X | Y | SERIAL |\n" ); ConOut( "--------------------------------\n" ); UI32 invalidCount = 0; SI32 x = 0; SI32 y = 0; SERIAL serial = INVALID; for( ; it != end; ++it ) { x = it->first >> 16; y = it->first & 0x0000FFFF; if( ISVALIDPI( it->second ) ) serial = it->second->getSerial32(); else { ++invalidCount; serial = INVALID; } ConOut( "|%10i|%4i|%4i|%10i|\n", it->first, x, y, serial ); } ConOut( "--------------------------------\n" ); ConOut( "| entries in map : %10i |\n", pItemLocationMap.size()); ConOut( "| invalid entries: %10i |\n", invalidCount ); ConOut( "--------------------------------\n" ); }
void cItem::explode(NXWSOCKET s) { if (s < 0 || s > now) return; //Luxor unsigned int dmg=0,len=0; P_CHAR pc_current=MAKE_CHAR_REF(currchar[s]); VALIDATEPC(pc_current); if(!isInWorld()) return; type=0; //needed for recursive explosion //Luxor - recursive explosions!! :DD NxwItemWrapper si; si.fillItemsNearXYZ( getPosition(), 5, true ); for( si.rewind(); !si.isEmpty(); si++ ) { P_ITEM p_nearbie=si.getItem(); if(ISVALIDPI(p_nearbie) && p_nearbie->type == ITYPE_POTION && p_nearbie->morey == 3) { //It's an explosion potion! p_nearbie->explode(s); } } //End Luxor recursive explosions staticeffect2(this, 0x36, 0xB0, 0x10, 0x80, 0x00); soundeffect3(this, 0x0207); len=morex/250; //4 square max damage at 100 alchemy switch (morez) { case 1:dmg=RandomNum( 5,10) ;break; case 2:dmg=RandomNum(10,20) ;break; case 3:dmg=RandomNum(20,40) ;break; default: ErrOut("Switch fallout. NoX-Wizard.cpp, explodeitem()\n"); //Morrolan dmg=RandomNum(5,10); } if (dmg<5) dmg=RandomNum(5,10); // 5 points minimum damage if (len<2) len=2; // 2 square min damage range NxwCharWrapper sc; sc.fillCharsNearXYZ( getPosition(), len, true ); for( sc.rewind(); !sc.isEmpty(); sc++ ) { P_CHAR pc=sc.getChar(); if( ISVALIDPC(pc) ) { pc->damage( dmg+(2-pc->distFrom(this)), DAMAGE_FIRE ); } } Delete(); }
/*! \author Luxor \brief returns the *index element with the given id and color of the vector of a container(identified by serial) \param serial the serial of the container \param index the pointer to the integer which we're using for the search \param id the id which we're searching for \param color the color which we're searching for \return the item we're searching for \note *index should be 0 at the beginning of the search */ P_ITEM containerSearchFor(const int serial, int *index, short id, short color) { P_ITEM pi; int loopexit=0; while ( ((pi = containerSearch(serial,index)) != 0) && (++loopexit < MAXLOOPS) ) { if (pi->getId()==id && (color==-1 || pi->getColor()==color) && ISVALIDPI(pi)) return pi; } return 0; }
/*! \brief gets world coordinates from a serial \author Xanathar \param sr serial \param px x coordinate \param py y coordinate \param pz z coordinate \param ch eventual index to char \param it eventual index to item */ void getWorldCoordsFromSerial (int sr, UI16& px, UI16& py, SI08& pz, int& ch, int& it) { int serial = sr; int loop = 0; it = ch = INVALID; P_CHAR pc=0; P_ITEM pi=0; while ((++loop) < 500) { pc=pointers::findCharBySerial(serial); ch = DEREF_P_CHAR(pc); pi=pointers::findItemBySerial(serial); it = DEREF_P_ITEM(pi); if (ISVALIDPI(pi)) { if (pi->getContSerial()!=INVALID) { serial = pi->getContSerial(); continue; } } break; } if (ISVALIDPC(pc)) { Location charpos= pc->getPosition(); px = charpos.x; py = charpos.y; pz = charpos.z; } else if ( ISVALIDPI(pi) && (pi->getContSerial()==INVALID)) { px = pi->getPosition("x"); py = pi->getPosition("y"); pz = pi->getPosition("z"); } else { px = 0; py = 0; pz = 0; } }
/*! \brief Get the player weight \author Unknow, update by Duke (04/11/00) \return actual weight \param pItem the container \param total the total number of item in container and subcontainer \note total < 0 indicate that not a pack ! on osi servers in that case weigt/items count isnt show thus i set it negative, if you want to show it anyway, add something like if (weight<0) weight*=-1; */ float weights::LockeddownWeight(P_ITEM pItem, int *total ) { double totalweight=0.0; if (!ISVALIDPI(pItem)) { *total=0; return 0.0; } NxwItemWrapper si; si.fillItemsInContainer( pItem, false ); for( si.rewind(); !si.isEmpty(); si++ ) { P_ITEM pi= si.getItem(); if(!ISVALIDPI(pi)) continue; R32 itemsweight=pi->getWeightActual(); *total=*total+1; if (pi->isContainer()) //item is another container { totalweight+=(itemsweight/100.0); //(pi->weight/100); totalweight+=LockeddownWeight(pi, total); //find the item's weight within this container } totalweight+=((itemsweight)/100.00); //((pi->weight*pi->amount)/100); // Ison 2-21-99 } if (*total==0) { *total=pItem->amount; *total=*total*-1; return static_cast<float>(pItem->getWeightActual()/100.0); // if no pack return single item weight*/ } else return static_cast<float>(totalweight); }
/*! \brief recurses through the container given to calculate the total weight \author Ison (02/20/99), rewritten by Tauriel (03/20/99), rewritten by Duke (04/11/00) \return the weight \param bp the item */ float weights::RecursePacks(P_ITEM bp) { double totalweight=0.0; if (!ISVALIDPI(bp)) return 0.0; NxwItemWrapper si; si.fillItemsInContainer( bp, false ); for( si.rewind(); !si.isEmpty(); si++ ) { P_ITEM pi=si.getItem(); if( !ISVALIDPI(pi)) continue; R32 itemsweight=pi->getWeightActual(); if (pi->isContainer()) //item is another container { totalweight+=(itemsweight/100.0); // the weight of container itself totalweight+=RecursePacks(pi); //find the item's weight within this container } totalweight+=((itemsweight)/100.0); } return static_cast<float>(totalweight); }
void pack_item(NXWCLIENT ps, PKGx08 *pp) // Item is put into container { if (ps == NULL) return; char temp[TEMP_STR_SIZE]; //xan -> this overrides the global temp var char temp2[TEMP_STR_SIZE]; //xan -> this overrides the global temp var int serial/*, serhash*/; tile_st tile; // bool abort=false; NXWSOCKET s=ps->toInt(); P_CHAR pc=ps->currChar(); VALIDATEPC(pc); Location charpos= pc->getPosition(); P_ITEM pack; P_ITEM pCont = pointers::findItemBySerial(pp->Tserial); VALIDATEPI(pCont); P_ITEM pItem = pointers::findItemBySerial(pp->Iserial); VALIDATEPI(pItem); if (pItem->getId() >= 0x4000) { // abort=true; // LB crashfix that prevents moving multi objcts in BP's ps->sysmsg(TRANSLATE("Hey, putting houses in your pack crashes your back and client!")); } //ndEndy recurse only a time P_ITEM contOutMost = pCont->getOutMostCont(); P_CHAR contOwner = ( !contOutMost->isInWorld() )? pointers::findCharBySerial( contOutMost->getContSerial() ) : NULL; if( ISVALIDPC(contOwner) ) { //if ((contOwner->npcaitype==NPCAI_PLAYERVENDOR) && (contOwner->npc) && (contOwner->getOwnerSerial32()!=pc->getSerial32()) ) if ( contOwner->getSerial32() != pc->getSerial32() && contOwner->getOwnerSerial32() != pc->getSerial32() && !pc->IsGM() ) { // Luxor ps->sysmsg(TRANSLATE("This aint your backpack!")); Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); item_bounce3(pItem); if (pCont->getId() >= 0x4000) senditem(s, pCont); } return; } } if (pCont->amxevents[EVENT_IONPUTITEM]!=NULL) { g_bByPass = false; pCont->amxevents[EVENT_IONPUTITEM]->Call( pCont->getSerial32(), pItem->getSerial32(), pc->getSerial32() ); if (g_bByPass) { item_bounce6(ps,pItem); return; } } /* g_bByPass = false; pCont->runAmxEvent( EVENT_IONPUTITEM, pCont->getSerial32(), pItem->getSerial32(), pc->getSerial32() ); if (g_bByPass) { //AntiChrist to preview item disappearing item_bounce6(ps,pItem); return; } */ if (pCont->layer==0 && pCont->getId() == 0x1E5E && pCont->getContSerial()==pc->getSerial32()) { // Trade window??? serial=calcserial(pCont->moreb1, pCont->moreb2, pCont->moreb3, pCont->moreb4); if(serial==-1) return; P_ITEM pi_z = pointers::findItemBySerial(serial); if (ISVALIDPI(pi_z)) if ((pi_z->morez || pCont->morez)) { pi_z->morez=0; pCont->morez=0; sendtradestatus( pi_z, pCont ); } } if(SrvParms->usespecialbank)//only if special bank is activated { if(pCont->morey==MOREY_GOLDONLYBANK && pCont->morex==MOREX_BANK && pCont->type==ITYPE_CONTAINER) { if ( pItem->getId() == ITEMID_GOLD ) {//if they're gold ok pc->playSFX( goldsfx(2) ); } else {//if they're not gold..bounce on ground ps->sysmsg(TRANSLATE("You can only put golds in this bank box!")); pItem->setContSerial(-1); pItem->MoveTo( charpos ); pItem->Refresh(); pc->playSFX( itemsfx(pItem->getId()) ); return; } } } // Xanathars's Bank Limit Code if (ServerScp::g_nBankLimit != 0) { if( ISVALIDPI( contOutMost ) && contOutMost->morex==MOREX_BANK ) { int n = contOutMost->CountItems( INVALID, INVALID, false); n -= contOutMost->CountItems( ITEMID_GOLD, INVALID, false); if( pItem->type == ITYPE_CONTAINER ) n += pItem->CountItems( INVALID, INVALID, false); else ++n; if( n > ServerScp::g_nBankLimit ) { ps->sysmsg(TRANSLATE("You exceeded the number of maximimum items in bank of %d"), ServerScp::g_nBankLimit); item_bounce6(ps,pItem); return; } } } //ndEndy this not needed because when is dragging cont serial is INVALID //testing UOP Blocking Tauriel 1-12-99 if (!pItem->isInWorld()) { item_bounce6(ps,pItem); return; } data::seekTile(pItem->getId(), tile); if (( ( (pItem->magic==2) || ( (tile.weight==255) && (pItem->magic != 1 ) ) ) && !pc->canAllMove()) || ( (pItem->magic==3|| pItem->magic==4) && !(pItem->getOwnerSerial32()==pc->getSerial32()))) { Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); item_bounce3(pItem); if (pCont->getId() >= 0x4000) senditem(s, pCont); } return; } // - Trash container if( pCont->type==ITYPE_TRASH) { pItem->Delete(); ps->sysmsg(TRANSLATE("As you let go of the item it disappears.")); return; } // - Spell Book if (pCont->type==ITYPE_SPELLBOOK) { if (!pItem->IsSpellScroll72()) { ps->sysmsg(TRANSLATE("You can only place spell scrolls in a spellbook!")); Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); item_bounce3(pItem); } if (pCont->getId() >= 0x4000) senditem(s, pCont); return; } pack= pc->getBackpack(); if(ISVALIDPI(pack)) { if ((!(pCont->getContSerial()==pc->getSerial32())) && (!(pCont->getContSerial()==pack->getSerial32())) && (!(pc->CanSnoop()))) { ps->sysmsg(TRANSLATE("You cannot place spells in other peoples spellbooks.")); item_bounce6(ps,pItem); return; } if( strncmp(pItem->getCurrentNameC(), "#", 1) ) pItem->getName(temp2); else strcpy(temp2,pItem->getCurrentNameC()); NxwItemWrapper sii; sii.fillItemsInContainer( pCont, false ); for( sii.rewind(); !sii.isEmpty(); sii++ ) { P_ITEM pi_ci=sii.getItem(); if (ISVALIDPI(pi_ci)) { if( strncmp(pi_ci->getCurrentNameC(), "#", 1) ) pi_ci->getName(temp); else strcpy(temp,pi_ci->getCurrentNameC()); if(!(strcmp(temp,temp2)) || !(strcmp(temp,"All-Spell Scroll"))) { ps->sysmsg(TRANSLATE("You already have that spell!")); item_bounce6(ps,pItem); return; } } // Juliunus, to prevent ppl from wasting scrolls. if (pItem->amount > 1) { ps->sysmsg(TRANSLATE("You can't put more than one scroll at a time in your book.")); item_bounce6(ps,pItem); return; } } } pCont->AddItem( pItem ); ps->sendSpellBook(pCont); return; } if (pCont->type == ITYPE_CONTAINER) { if ( ISVALIDPC(contOwner) ) { if ( (contOwner->npcaitype==NPCAI_PLAYERVENDOR) && (contOwner->npc) && (contOwner->getOwnerSerial32()==pc->getSerial32()) ) { pc->fx1= DEREF_P_ITEM(pItem); pc->fx2=17; pc->sysmsg(TRANSLATE("Set a price for this item.")); } } short xx=pp->TxLoc; short yy=pp->TyLoc; pCont->AddItem(pItem,xx,yy); pc->playSFX( itemsfx(pItem->getId()) ); statwindow(pc,pc); } // end of player run vendors else // - Unlocked item spawner or unlockable item spawner if (pCont->type==ITYPE_UNLOCKED_CONTAINER || pCont->type==ITYPE_NODECAY_ITEM_SPAWNER || pCont->type==ITYPE_DECAYING_ITEM_SPAWNER) { pCont->AddItem(pItem, pp->TxLoc, pp->TyLoc); //Luxor pc->playSFX( itemsfx(pItem->getId()) ); } else // - Pileable if (pCont->pileable && pItem->pileable) { if ( !pCont->PileItem( pItem ) ) { item_bounce6(ps,pItem); return; } } else { if( pItem->getContSerial( true )==INVALID ) //current cont serial is invalid because is dragging { NxwSocketWrapper sw; sw.fillOnline( pItem->getPosition() ); for( sw.rewind(); !sw.isEmpty(); sw++ ) SendDeleteObjectPkt(sw.getSocket(), pItem->getSerial32() ); mapRegions->remove(pItem); } pItem->setPosition( pp->TxLoc, pp->TyLoc, pp->TzLoc); pItem->setContSerial( pCont->getContSerial() ); pItem->Refresh(); } }
/*! \brief Double click \author Ripper, rewrite by Endymion \param ps client of player dbclick \note Completely redone by Morrolan 20-07-99 \warning I use a define CASE for make more readable the code, if you change name of P_ITEM pi chage also the macro \todo los */ void doubleclick(NXWCLIENT ps) { if(ps==NULL) return; P_CHAR pc = ps->currChar(); VALIDATEPC( pc ); NXWSOCKET s = ps->toInt(); // the 0x80 bit in the first byte is used later for "keyboard" and should be ignored SERIAL serial = LongFromCharPtr(buffer[s] +1) & 0x7FFFFFFF; if (isCharSerial(serial)) { P_CHAR pd=pointers::findCharBySerial(serial); if(ISVALIDPC(pd)) dbl_click_character(ps, pd); return; } P_ITEM pi = pointers::findItemBySerial(serial); VALIDATEPI(pi); if (pi->amxevents[EVENT_IONDBLCLICK]!=NULL) { g_bByPass = false; pi->amxevents[EVENT_IONDBLCLICK]->Call( pi->getSerial32(), pc->getSerial32() ); if (g_bByPass==true) return; } /* g_bByPass = false; pi->runAmxEvent( EVENT_IONDBLCLICK, pi->getSerial32(), s ); if (g_bByPass==true) return; */ if (!checkItemUsability(pc , pi, ITEM_USE_DBLCLICK)) return; Location charpos= pc->getPosition(); if (pc->IsHiddenBySpell()) return; //Luxor: cannot use items if under invisible spell if ( !pc->IsGM() && pc->objectdelay >= uiCurrentTime ) { pc->sysmsg(TRANSLATE("You must wait to perform another action.")); return; } else pc->objectdelay = SrvParms->objectdelay * MY_CLOCKS_PER_SEC + uiCurrentTime; ///MODIFY, CANT CLICK ITEM AT DISTANCE >2////////////// if ( (pc->distFrom(pi)>2) && !pc->IsGM() && !(pc->nxwflags[0] & cChar::flagSpellTelekinesys) ) //Luxor: let's check also for the telekinesys spell { pc->sysmsg( TRANSLATE("Must be closer to use this!")); pc->objectdelay=0; return; } //<Anthalir> VARIAIBLI tile_st item; P_ITEM pack= pc->getBackpack(); VALIDATEPI( pack ); data::seekTile( pi->getId(), item ); //////FINEVARIABILI if ( ServerScp::g_nEquipOnDclick ) { // equip the item only if it is in the backpack of the player if ((pi->getContSerial() == pack->getSerial32()) && (item.quality != 0) && (item.quality != LAYER_BACKPACK) && (item.quality != LAYER_MOUNT)) { int drop[2]= {-1, -1}; // list of items to drop, there no reason for it to be larger int curindex= 0; NxwItemWrapper wea; wea.fillItemWeared( pc, true, true, true ); for( wea.rewind(); !wea.isEmpty(); wea++ ) { P_ITEM pj=wea.getItem(); if(!ISVALIDPI(pj)) continue; if ((item.quality == LAYER_1HANDWEAPON) || (item.quality == LAYER_2HANDWEAPON))// weapons { if (pi->itmhand == 2) // two handed weapons or shield { if (pj->itmhand == 2) drop[curindex++]= DEREF_P_ITEM(pj); if ( (pj->itmhand == 1) || (pj->itmhand == 3) ) drop[curindex++]= DEREF_P_ITEM(pj); } if (pi->itmhand == 3) { if ((pj->itmhand == 2) || pj->itmhand == 3) drop[curindex++]= DEREF_P_ITEM(pj); } if ((pi->itmhand == 1) && ((pj->itmhand == 2) || (pj->itmhand == 1))) drop[curindex++]= DEREF_P_ITEM(pj); } else // not a weapon { if (pj->layer == item.quality) drop[curindex++]= DEREF_P_ITEM(pj); } } if (ServerScp::g_nUnequipOnReequip) { if (drop[0] > -1) // there is at least one item to drop { for (int i= 0; i< 2; i++) { if (drop[i] > -1) { P_ITEM p_drop=MAKE_ITEM_REF(drop[i]); if(ISVALIDPI(p_drop)) pc->UnEquip( p_drop ); } } } pc->playSFX( itemsfx(pi->getId()) ); pc->Equip( pi ); } else { if (drop[0] == -1) { pc->playSFX( itemsfx(pi->getId()) ); pc->Equip( pi ); } } return; } } // </Anthalir> //<Luxor>: Circle of transparency bug fix P_ITEM pCont; Location dst; pCont = pi->getOutMostCont(); if(pCont->isInWorld()) { dst = pCont->getPosition(); } else { P_CHAR pg_dst = pointers::findCharBySerial( pCont->getContSerial() ); VALIDATEPC(pg_dst); dst = pg_dst->getPosition(); } Location charPos = pc->getPosition(); charPos.z = dst.z; charPos.dispz = dst.dispz; if ( !pc->IsGM() && !lineOfSight( charPos, dst ) && !(pc->nxwflags[0] & cChar::flagSpellTelekinesys) ) { pc->sysmsg( TRANSLATE( "You cannot reach the item" ) ); return; } //</Luxor> P_CHAR itmowner = pi->getPackOwner(); if(!pi->isInWorld()) { if (isItemSerial(pi->getContSerial()) && pi->type != ITYPE_CONTAINER) {// Cant use stuff that isn't in your pack. if ( ISVALIDPC(itmowner) && (itmowner->getSerial32()!=pc->getSerial32()) ) return; } else if (isCharSerial(pi->getContSerial()) && pi->type!=(UI32)INVALID) {// in a character. P_CHAR wearedby = pointers::findCharBySerial(pi->getContSerial()); if (ISVALIDPC(wearedby)) if (wearedby->getSerial32()!=pc->getSerial32() && pi->layer!=LAYER_UNUSED_BP && pi->type!=ITYPE_CONTAINER) return; } } if ((pi->magic==4) && (pi->secureIt==1)) { if (!pc->isOwnerOf(pi) || !pc->IsGMorCounselor()) { pc->sysmsg( TRANSLATE("That is a secured chest!")); return; } } if (pi->magic == 4) { pc->sysmsg( TRANSLATE("That item is locked down.")); return; } if (pc->dead && pi->type!=ITYPE_RESURRECT) // if you are dead and it's not an ankh, FORGET IT! { pc->sysmsg(TRANSLATE("You may not do that as a ghost.")); return; } else if (!pc->IsGMorCounselor() && pi->layer!=0 && !pc->IsWearing(pi)) {// can't use other people's things! if (!(pi->layer==LAYER_BACKPACK && SrvParms->rogue==1)) // bugfix for snooping not working, LB { pc->sysmsg(TRANSLATE("You cannot use items equipped by other players.")); return; } } // Begin checking objects that we force an object delay for (std objects) // start trigger stuff if (pi->trigger > 0) { if (pi->trigtype == 0) { if ( TIMEOUT( pi->disabled ) ) // changed by Magius(CHE) § { triggerItem(s, pi, TRIGTYPE_DBLCLICK); // if players uses trigger return; } else { if ( pi->disabledmsg!=NULL ) pc->sysmsg("%s", pi->disabledmsg->c_str()); else pc->sysmsg(TRANSLATE("That doesnt seem to work right now.")); return; } } else { pc->sysmsg( TRANSLATE("You are not close enough to use that.")); return; } } // check this on trigger in the event that the .trigger property is not set on the item // trigger code. Check to see if item is envokable by id else if (checkenvoke( pi->getId() )) { pc->envokeitem = pi->getSerial32(); pc->envokeid = pi->getId(); P_TARGET targ = clientInfo[s]->newTarget( new cObjectTarget() ); targ->code_callback=target_envoke; targ->send( ps ); ps->sysmsg( TRANSLATE("What will you use this on?")); return; } // end trigger stuff // BEGIN Check items by type int los = 0; BYTE map1[20] = "\x90\x40\x01\x02\x03\x13\x9D\x00\x00\x00\x00\x13\xFF\x0F\xFF\x01\x90\x01\x90"; BYTE map2[12] = "\x56\x40\x01\x02\x03\x05\x00\x00\x00\x00\x00"; // By Polygon: This one is needed to show the location on treasure maps BYTE map3[12] = "\x56\x40\x01\x02\x03\x01\x00\x00\x00\x00\x00"; P_TARGET targ = NULL; switch (pi->type) { case ITYPE_RESURRECT: // Check for 'resurrect item type' this is the ONLY type one can use if dead. if (pc->dead) { pc->resurrect(); pc->sysmsg(TRANSLATE("You have been resurrected.")); return; } else { pc->sysmsg(TRANSLATE("You are already living!")); return; } case ITYPE_BOATS:// backpacks - snooping a la Zippy - add check for SrvParms->rogue later- Morrolan if (pi->type2 == 3) { switch( pi->getId() & 0xFF ) { case 0x84: case 0xD5: case 0xD4: case 0x89: Boats->PlankStuff(pc, pi); break; default: pc->sysmsg( TRANSLATE("That is locked.")); break; } return; } case ITYPE_CONTAINER: // bugfix for snooping not working, lb case ITYPE_UNLOCKED_CONTAINER: // Wintermute: GMs or Counselors should be able to open trapped containers always if (pi->moreb1 > 0 && !pc->IsGMorCounselor()) { magic::castAreaAttackSpell(pi->getPosition("x"), pi->getPosition("y"), magic::SPELL_EXPLOSION); pi->moreb1--; } //Magic->MagicTrap(currchar[s], pi); // added by AntiChrist // only 1 and 63 can be trapped, so pleaz leave it here :) - Anti case ITYPE_NODECAY_ITEM_SPAWNER: // nodecay item spawner..Ripper case ITYPE_DECAYING_ITEM_SPAWNER: // decaying item spawner..Ripper if (pi->isInWorld() || (pc->IsGMorCounselor()) || // Backpack in world - free access to everyone ( isCharSerial(pi->getContSerial()) && pi->getContSerial()==pc->getSerial32())) // primary pack { pc->showContainer(pi); pc->objectdelay=0; return; } else if( isItemSerial(pi->getContSerial()) ) { P_ITEM pio = pi->getOutMostCont(); if (pio->getContSerial()==pc->getSerial32() || pio->isInWorld() ) { pc->showContainer(pi); pc->objectdelay=0; return; } } if(ISVALIDPC(itmowner)) snooping(pc, pi ); return; case ITYPE_TELEPORTRUNE: targ = clientInfo[s]->newTarget( new cLocationTarget() ); targ->code_callback = target_tele; targ->send( ps ); ps->sysmsg( TRANSLATE("Select teleport target.")); return; case ITYPE_KEY: targ = clientInfo[s]->newTarget( new cItemTarget() ); targ->code_callback = target_key; targ->buffer[0]= pi->more1; targ->buffer[1]= pi->more2; targ->buffer[2]= pi->more3; targ->buffer[3]= pi->more4; targ->send( ps ); ps->sysmsg( TRANSLATE("Select item to use the key on.")); return; case ITYPE_LOCKED_ITEM_SPAWNER: case ITYPE_LOCKED_CONTAINER: // Added traps effects by AntiChrist // Wintermute: GMs or Counselors should be able to open locked containers always if ( !pc->IsGMorCounselor() ) { if (pi->moreb1 > 0 ) { magic::castAreaAttackSpell(pi->getPosition().x, pi->getPosition().y, magic::SPELL_EXPLOSION); pi->moreb1--; } pc->sysmsg(TRANSLATE("This item is locked.")); return; } else { pc->showContainer(pi); return; } case ITYPE_SPELLBOOK: if (ISVALIDPI(pack)) // morrolan if(pi->getContSerial()==pack->getSerial32() || pc->IsWearing(pi)) ps->sendSpellBook(pi); else pc->sysmsg(TRANSLATE("If you wish to open a spellbook, it must be equipped or in your main backpack.")); return; case ITYPE_MAP: LongToCharPtr(pi->getSerial32(), map1 +1); map2[1] = map1[1]; map2[2] = map1[2]; map2[3] = map1[3]; map2[4] = map1[4]; /* By Polygon: Assign areas and map size before sending */ map1[7] = pi->more1; // Assign topleft x map1[8] = pi->more2; map1[9] = pi->more3; // Assign topleft y map1[10] = pi->more4; map1[11] = pi->moreb1; // Assign lowright x map1[12] = pi->moreb2; map1[13] = pi->moreb3; // Assign lowright y map1[14] = pi->moreb4; int width, height; // Tempoary storage for w and h; width = 134 + (134 * pi->morez); // Calculate new w and h height = 134 + (134 * pi->morez); ShortToCharPtr(width, map1 +15); ShortToCharPtr(height, map1 +17); // END OF: By Polygon Xsend(s, map1, 19); //AoS/ Network->FlushBuffer(s); Xsend(s, map2, 11); //AoS/ Network->FlushBuffer(s); return; case ITYPE_BOOK: Books::DoubleClickBook(s, pi); return; case ITYPE_DOOR: dooruse(s, pi); return; case ITYPE_LOCKED_DOOR: // Wintermute: GMs or Counselors should be able to open locked doors always if ( pc->IsGMorCounselor()) { dooruse(s, pi); return; } if (ISVALIDPI(pack)) { NxwItemWrapper si; si.fillItemsInContainer( pack ); for( si.rewind(); !si.isEmpty(); si++ ) { P_ITEM pj = si.getItem(); if (ISVALIDPI(pj) && pj->type==ITYPE_KEY) if (((pj->more1 == pi->more1) && (pj->more2 == pi->more2) && (pj->more3 == pi->more3) && (pj->more4 == pi->more4)) ) { pc->sysmsg(TRANSLATE("You quickly unlock, use, and then relock the door.")); dooruse(s, pi); return; } } } pc->sysmsg(TRANSLATE("This door is locked.")); return; case ITYPE_FOOD: if (pc->hunger >= 6) { pc->sysmsg( TRANSLATE("You are simply too full to eat any more!")); return; } else { switch (RandomNum(0, 2)) { case 0: pc->playSFX(0x3A); break; case 1: pc->playSFX(0x3B); break; case 2: pc->playSFX(0x3C); break; } switch (pc->hunger) { case 0: pc->sysmsg( TRANSLATE("You eat the food, but are still extremely hungry.")); break; case 1: pc->sysmsg( TRANSLATE("You eat the food, but are still extremely hungry.")); break; case 2: pc->sysmsg( TRANSLATE("After eating the food, you feel much less hungry.")); break; case 3: pc->sysmsg( TRANSLATE("You eat the food, and begin to feel more satiated.")); break; case 4: pc->sysmsg( TRANSLATE("You feel quite full after consuming the food.")); break; case 5: pc->sysmsg( TRANSLATE("You are nearly stuffed, but manage to eat the food.")); break; default: pc->sysmsg( TRANSLATE("You are simply too full to eat any more!")); break; } if (pi->poisoned) { pc->sysmsg(TRANSLATE("The food was poisoned!")); pc->applyPoison(PoisonType(pi->poisoned)); } pi->ReduceAmount(1); pc->hunger++; } return; case ITYPE_WAND: // -Fraz- Modified and tuned up, Wands must now be equipped or in pack case ITYPE_MANAREQ_WAND: // magic items requiring mana (xan) if (ISVALIDPI(pack)) { if (pi->getContSerial() == pack->getSerial32() || pc->IsWearing(pi)) { if (pi->morez != 0) { pi->morez--; if (magic::beginCasting( static_cast<magic::SpellId>((8*(pi->morex - 1)) + pi->morey - 1), ps, (pi->type==ITYPE_WAND) ? magic::CASTINGTYPE_ITEM : magic::CASTINGTYPE_NOMANAITEM)) { if (pi->morez == 0) { pi->type = pi->type2; pi->morex = 0; pi->morey = 0; pi->offspell = 0; } } } } else { pc->sysmsg(TRANSLATE("If you wish to use this, it must be equipped or in your backpack.")); } } return; // case 15 (magic items) /*////////////////////REMOVE///////////////////////////////////// case 18: // crystal ball? switch (RandomNum(0, 9)) { case 0: itemmessage(s, TRANSLATE("Seek out the mystic llama herder."), pi->getSerial32()); break; case 1: itemmessage(s, TRANSLATE("Wherever you go, there you are."), pi->getSerial32()); break; case 4: itemmessage(s, TRANSLATE("The message appears to be too cloudy to make anything out of it."), pi->getSerial32()); break; case 5: itemmessage(s, TRANSLATE("You have just lost five strength.. not!"), pi->getSerial32()); break; case 6: itemmessage(s, TRANSLATE("You're really playing a game you know"), pi->getSerial32()); break; case 7: itemmessage(s, TRANSLATE("You will be successful in all you do."), pi->getSerial32()); break; case 8: itemmessage(s, TRANSLATE("You are a person of culture."), pi->getSerial32()); break; default: itemmessage(s, TRANSLATE("Give me a break! How much good fortune do you expect!"), pi->getSerial32()); break; }// switch soundeffect2(pc_currchar, 0x01EC); return;// case 18 (crystal ball?) */////////////////////ENDREMOVE///////////////////////////////////// case ITYPE_POTION: // potions if (pi->morey != 3) pc->drink(pi); //Luxor: delayed potions drinking else //explosion potion usepotion(pc, pi); return; case ITYPE_RUNE: if (pi->morex==0 && pi->morey==0 && pi->morez==0) { pc->sysmsg( TRANSLATE("That rune is not yet marked!")); } else { pc->runeserial = pi->getSerial32(); pc->sysmsg( TRANSLATE("Enter new rune name.")); } return; case ITYPE_SMOKE: pc->smoketimer = pi->morex*MY_CLOCKS_PER_SEC + getclock(); pi->ReduceAmount(1); return; case ITYPE_RENAME_DEED: pc->namedeedserial = pi->getSerial32(); pc->sysmsg( TRANSLATE("Enter your new name.")); pi->ReduceAmount(1); return; case ITYPE_POLYMORPH: pc->setId( pi->morex ); pc->teleport(); pi->type = ITYPE_POLYMORPH_BACK; return; case ITYPE_POLYMORPH_BACK: pc->setId( pc->getOldId() ); pc->teleport(); pi->type = ITYPE_POLYMORPH; return; case ITYPE_ARMY_ENLIST: enlist(s, pi->morex); pi->Delete(); return; case ITYPE_TELEPORT: pc->MoveTo( pi->morex,pi->morey,pi->morez ); pc->teleport(); return; case ITYPE_DRINK: switch (rand()%2) { case 0: pc->playSFX(0x0031); break; case 1: pc->playSFX(0x0030); break; } pi->ReduceAmount(1); pc->sysmsg( TRANSLATE("Gulp !")); return; case ITYPE_GUILDSTONE: if ( pi->getId() == 0x14F0 || pi->getId() == 0x1869 ) // Check for Deed/Teleporter + Guild Type { pc->fx1 = DEREF_P_ITEM(pi); Guilds->StonePlacement(s); return; } else if (pi->getId() == 0x0ED5) // Check for Guildstone + Guild Type { pc->fx1 = DEREF_P_ITEM(pi); Guilds->Menu(s, 1); return; } else WarnOut("Unhandled guild item type named: %s with ID of: %X\n", pi->getCurrentNameC(), pi->getId()); return; case ITYPE_PLAYER_VENDOR_DEED: // PlayerVendors deed { P_CHAR vendor = npcs::AddNPCxyz(-1, 2117, charpos.x, charpos.y, charpos.z); if ( !ISVALIDPC(vendor) ) { WarnOut("npc-script couldnt find vendor !\n"); return; } los = 0; vendor->npcaitype = NPCAI_PLAYERVENDOR; vendor->MakeInvulnerable(); vendor->unHide(); vendor->stealth=INVALID; vendor->dir = pc->dir; vendor->npcWander = WANDER_NOMOVE; vendor->SetInnocent(); vendor->setOwnerSerial32( pc->getSerial32() ); vendor->tamed = false; pi->Delete(); vendor->teleport(); char temp[TEMP_STR_SIZE]; //xan -> this overrides the global temp var sprintf( temp, TRANSLATE("Hello sir! My name is %s and i will be working for you."), vendor->getCurrentNameC()); vendor->talk(s, temp, 0); return; } case ITYPE_TREASURE_MAP: Skills::Decipher(pi, s); return; case ITYPE_DECIPHERED_MAP: map1[ 1] = map2[1] = map3[1] = pi->getSerial().ser1; map1[ 2] = map2[2] = map3[2] = pi->getSerial().ser2; map1[ 3] = map2[3] = map3[3] = pi->getSerial().ser3; map1[ 4] = map2[4] = map3[4] = pi->getSerial().ser4; map1[ 7] = pi->more1; // Assign topleft x map1[ 8] = pi->more2; map1[ 9] = pi->more3; // Assign topleft y map1[10] = pi->more4; map1[11] = pi->moreb1; // Assign lowright x map1[12] = pi->moreb2; map1[13] = pi->moreb3; // Assign lowright y map1[14] = pi->moreb4; ShortToCharPtr(0x0100, map1 +15); // Let width and height be 256 ShortToCharPtr(0x0100, map1 +17); Xsend(s, map1, 19); //AoS/ Network->FlushBuffer(s); Xsend(s, map2, 11); //AoS/ Network->FlushBuffer(s); // Generate message to add a map point SI16 posx, posy; // tempoary storage for map point SI16 tlx, tly, lrx, lry; // tempoary storage for map extends tlx = (pi->more1 << 8) | pi->more2; tly = (pi->more3 << 8) | pi->more4; lrx = (pi->moreb1 << 8) | pi->moreb2; lry = (pi->moreb3 << 8) | pi->moreb4; posx = (256 * (pi->morex - tlx)) / (lrx - tlx); // Generate location for point posy = (256 * (pi->morey - tly)) / (lry - tly); ShortToCharPtr(posx, map3 +7); // Store the point position ShortToCharPtr(posy, map3 +9); Xsend(s, map3, 11); // Fire data to client :D //AoS/ Network->FlushBuffer(s); return; default: break; } ///END IDENTIFICATION BY TYPE /////////////////READ UP :D//////////////////////////////// ///BEGIN IDENTIFICATION BY ID if (pi->IsSpellScroll()) { if (ISVALIDPI(pack)) if( pi->getContSerial()==pack->getSerial32()) { magic::SpellId spn = magic::spellNumberFromScrollId(pi->getId()); // avoid reactive armor glitch if ((spn>=0)&&(magic::beginCasting(spn, ps, magic::CASTINGTYPE_SCROLL))) pi->ReduceAmount(1); // remove scroll if successful } else pc->sysmsg(TRANSLATE("The scroll must be in your backpack to envoke its magic.")); } CASE(IsAnvil) { targ = clientInfo[s]->newTarget( new cItemTarget() ); targ->code_callback=Skills::target_repair; targ->send( ps ); ps->sysmsg( TRANSLATE("Select item to be repaired.")); } CASE(IsAxe) { targ = clientInfo[s]->newTarget( new cTarget() ); targ->code_callback=target_axe; targ->buffer[0]=pi->getSerial32(); targ->send( ps ); ps->sysmsg( TRANSLATE("What would you like to use that on ?")); } CASEOR(IsFeather, IsShaft) { targ = clientInfo[s]->newTarget( new cItemTarget() ); targ->buffer[0]= pi->getSerial32(); targ->code_callback=Skills::target_fletching; targ->send( ps ); ps->sysmsg( TRANSLATE("What would you like to use this with?")); }
/*! \brief Steal random \author Unknow, updated by Endymion \param ps the client \todo add string because it's locked contanier into translate */ void Skills::target_randomSteal( NXWCLIENT ps, P_TARGET t ) { P_CHAR thief=ps->currChar(); VALIDATEPC(thief); P_CHAR victim = pointers::findCharBySerial( t->getClicked() ); VALIDATEPC(victim); if (thief->getSerial32() == victim->getSerial32() || thief->getSerial32()==victim->getOwnerSerial32()) { thief->sysmsg(TRANSLATE("You catch yourself red handed.")); return; } if (victim->npcaitype == NPCAI_PLAYERVENDOR) { thief->sysmsg(TRANSLATE("You cannot steal from player vendors.")); return; } if (victim->IsGMorCounselor() ) { thief->sysmsg( TRANSLATE("You can't steal from gods.")); return; } P_ITEM pack= victim->getBackpack(); if ( !ISVALIDPI(pack)) { thief->sysmsg(TRANSLATE("bad luck, your victim doesn't have a backpack")); return; } char temp[TEMP_STR_SIZE]; //xan -> this overrides the global temp var char temp2[TEMP_STR_SIZE]; //xan -> this overrides the global temp var sprintf(temp, TRANSLATE("You reach into %s's pack to steal something ..."), victim->getCurrentNameC() ); thief->sysmsg(temp); if ( char_inRange(thief,victim,1) ) { P_ITEM pi = NULL; NxwItemWrapper si; si.fillItemsInContainer( pack, false ); if( si.size()>0 ) { int ra=rand()%si.size(); int c=0; for( si.rewind(); !si.isEmpty(); si++ ) { c++; if( c==ra ) { pi=si.getItem(); break; } } } if( pi==NULL ) { thief->sysmsg(TRANSLATE("... and discover your victim doesn't have any posessions")); return; } //Endy can't be not valid after this -^ loop, else error VALIDATEPI(pi); if( pi->isNewbie() ) {//newbie thief->sysmsg(TRANSLATE("... and fail because it is of no value to you.")); return; } if(pi->isSecureContainer()) { thief->sysmsg(TRANSLATE("... and fail because it's a locked container.")); return; } if ( thief->checkSkill( STEALING,0,999) ) { // 0 stealing 2 stones, 10 3 stones, 99.9 12 stones, 100 17 stones !!! int cansteal = thief->skill[STEALING] > 999 ? 1700 : thief->skill[STEALING] + 200; if ( ((pi->getWeightActual())>cansteal) && !pi->isContainer())//Containers thief->sysmsg(TRANSLATE("... and fail because it is too heavy.")); else if(pi->isContainer() && (weights::RecursePacks(pi)>cansteal)) thief->sysmsg(TRANSLATE("... and fail because it is too heavy.")); else { if (victim->amxevents[EVENT_CHR_ONSTOLEN]) { g_bByPass = false; victim->amxevents[EVENT_CHR_ONSTOLEN]->Call(victim->getSerial32(), thief->getSerial32()); if (g_bByPass==true) return; } /* victim->runAmxEvent( EVENT_CHR_ONSTOLEN, victim->getSerial32(), s); if (g_bByPass==true) return; */ P_ITEM thiefpack = thief->getBackpack(); VALIDATEPI(thiefpack); pi->setContSerial( thiefpack->getSerial32() ); thief->sysmsg(TRANSLATE("... and you succeed.")); pi->Refresh(); //all_items(s); } } else thief->sysmsg(TRANSLATE(".. and fail because you're not good enough.")); if ( thief->skill[STEALING] < rand()%1001 ) { thief->unHide(); thief->sysmsg(TRANSLATE("You have been caught!")); thief->IncreaseKarma( ServerScp::g_nStealKarmaLoss); thief->modifyFame( ServerScp::g_nStealFameLoss); if (victim->IsInnocent() && thief->attackerserial!=victim->getSerial32() && Guilds->Compare(thief,victim)==0)//AntiChrist setCrimGrey(thief, ServerScp::g_nStealWillCriminal);//Blue and not attacker and not guild std::string itmname = ""; if ( pi->getCurrentName() != "#" ) itmname = pi->getCurrentName(); else { pi->getName( temp ); itmname = temp; } sprintf(temp,TRANSLATE("You notice %s trying to steal %s from you!"), thief->getCurrentNameC(), itmname.c_str()); sprintf(temp2,TRANSLATE("You notice %s trying to steal %s from %s!"), thief->getCurrentNameC(), itmname.c_str(), victim->getCurrentNameC()); if ( victim->npc) victim->talkAll(TRANSLATE( "Guards!! A thief is amoung us!"),0); else victim->sysmsg(temp); //send to all player temp2 = thief are stealing victim if are more intelligent and a bonus of luck :D // // NxwSocketWrapper sw; sw.fillOnline( thief, true ); for( sw.rewind(); !sw.isEmpty(); sw++ ) { NXWCLIENT ps_i=sw.getClient(); if( ps_i==NULL ) continue; P_CHAR pc_i=ps_i->currChar(); if ( ISVALIDPC(pc_i) ) if( (rand()%10+10==17) || ( (rand()%2==1) && (pc_i->in>=thief->in))) sysmessage(ps_i->toInt(),temp2); } } } else { thief->sysmsg( TRANSLATE("... and realise you're too far away.")); } }
void newbieitems(P_CHAR pc) { VALIDATEPC(pc); NXWCLIENT ps=pc->getClient(); if(ps==NULL) return; int first, second, third, storeval, itemaddperskill, loopexit = 0; char sect[512]; char whichsect[105]; cScpIterator* iter = NULL; first = bestskill(pc); second = nextbestskill(pc, first); third = nextbestskill(pc, second); if (pc->baseskill[third] < 190) third = 46; for (itemaddperskill = 1; itemaddperskill <= 5; itemaddperskill++) { switch (itemaddperskill) { // first of all the general section with the backpack, else where we put items? case 1: strcpy(whichsect, "SECTION ALLNEWBIES"); break; case 2: if ( (pc->getId() == BODY_MALE) && (pc->getOldId() == BODY_MALE) ) strcpy(whichsect, "SECTION MALENEWBIES"); else strcpy(whichsect, "SECTION FEMALENEWBIES"); break; case 3: sprintf(whichsect, "SECTION BESTSKILL %i", first); break; case 4: sprintf(whichsect, "SECTION BESTSKILL %i", second); break; case 5: sprintf(whichsect, "SECTION BESTSKILL %i", third); break; default: ErrOut("Switch fallout. newbie.cpp, newbieitems()/n"); // Morrolan } sprintf(sect, whichsect); char script1[1000], script2[1000]; safedelete(iter); iter = Scripts::Newbie->getNewIterator(sect); if (iter==NULL) return; do { iter->parseLine(script1,script2); if (script1[0] == '@') pc->loadEventFromScript(script1, script2); // Sparhawk: Huh loading character events // from newbie item scripts???? if (script1[0] != '}') { if (!(strcmp("PACKITEM", script1))) { std::string itemnum, amount; splitLine( script2, itemnum, amount ); int amt = ( amount != "" )? str2num( amount ) : INVALID; //ndEndy defined amount P_ITEM pi_n = item::CreateFromScript( str2num( itemnum ), pc->getBackpack(), amt ); if (ISVALIDPI(pi_n)) { pi_n->priv |= 0x02; // Mark as a newbie item } strcpy(script1, "DUMMY"); } else if (!strcmp("BANKITEM", script1)) { std::string itemnum, amount; splitLine( script2, itemnum, amount ); int amt= (amount!="")? str2num( amount ) : INVALID; P_ITEM pi = item::CreateFromScript( str2num( itemnum ), pc->GetBankBox(), amt ); if (ISVALIDPI(pi)) { pi->priv |= 0x02; // Mark as a newbie item } strcpy(script1, "DUMMY"); } else if (!strcmp("EQUIPITEM", script1)) { P_ITEM pi = item::CreateFromScript( script2 ); if (ISVALIDPI(pi)) { pi->priv |= 0x02; // Mark as a newbie item pi->setCont(pc); storeval = pi->getScriptID(); } strcpy(script1, "DUMMY"); } } } while ((script1[0] != '}') &&(++loopexit < MAXLOOPS)); safedelete(iter); } // Give the character some gold if ( goldamount > 0 ) { item::CreateFromScript( "$item_gold_coin", pc->getBackpack(), goldamount ); } }
void drop_item(NXWCLIENT ps) // Item is dropped { if (ps == NULL) return; NXWSOCKET s=ps->toInt(); // CHARACTER cc=ps->currCharIdx(); PKGx08 pkgbuf, *pp=&pkgbuf; pp->Iserial=LongFromCharPtr(buffer[s]+1); pp->TxLoc=ShortFromCharPtr(buffer[s]+5); pp->TyLoc=ShortFromCharPtr(buffer[s]+7); pp->TzLoc=buffer[s][9]; pp->Tserial=LongFromCharPtr(buffer[s]+10); //#define debug_dragg if (clientDimension[s]==3) { // UO:3D clients send SOMETIMES two dragg packets for a single dragg action. // sometimes we HAVE to swallow it, sometimes it has to be interpreted // if UO:3D specific item loss problems are reported, this is probably the code to blame :) // LB P_ITEM pi = pointers::findItemBySerial(pp->Iserial); #ifdef debug_dragg if (ISVALIDPI(pi)) { sprintf(temp, "%04x %02x %02x %01x %04x i-name: %s EVILDRAG-old: %i\n",pp->Iserial, pp->TxLoc, pp->TyLoc, pp->TzLoc, pp->Tserial, pi->name, clientInfo[s]->evilDrag); ConOut(temp); } else { sprintf(temp, "blocked: %04x %02x %02x %01x %04x i-name: invalid item EVILDRAG-old: %i\n",pp->Iserial, pp->TxLoc, pp->TyLoc, pp->TzLoc, pp->Tserial, clientInfo[s]->evilDrag); ConOut(temp); } #endif if ( (pp->TxLoc==-1) && (pp->TyLoc==-1) && (pp->Tserial==0) && (clientInfo[s]->evilDrag) ) { clientInfo[s]->evilDrag=false; #ifdef debug_dragg ConOut("Swallow only\n"); #endif return; } // swallow! note: previous evildrag ! else if ( (pp->TxLoc==-1) && (pp->TyLoc==-1) && (pp->Tserial==0) && (!clientInfo[s]->evilDrag) ) { #ifdef debug_dragg ConOut("Bounce & Swallow\n"); #endif item_bounce6(ps, pi); return; } else if ( ( (pp->TxLoc!=-1) && (pp->TyLoc!=-1) && ( pp->Tserial!=-1)) || ( (pp->Iserial>=0x40000000) && (pp->Tserial>=0x40000000) ) ) clientInfo[s]->evilDrag=true; // calc new evildrag value else clientInfo[s]->evilDrag=false; } #ifdef debug_dragg else { P_ITEM pi = pointers::findItemBySerial(pp->Iserial); if (ISVALIDPI(pi)) { sprintf(temp, "blocked: %04x %02x %02x %01x %04x i-name: %s EVILDRAG-old: %i\n",pp->Iserial, pp->TxLoc, pp->TyLoc, pp->TzLoc, pp->Tserial, pi->name, clientInfo[s]->evilDrag); ConOut(temp); } } #endif // if ( (buffer[s][10]>=0x40) && (buffer[s][10]!=0xff) ) if ( isItemSerial(pp->Tserial) && (pp->Tserial != INVALID) ) // Invalid target => invalid container => put inWorld !!! pack_item(ps,pp); else dump_item(ps,pp); }
void checkFieldEffects( UI32 currenttime, P_CHAR pc, char timecheck ) { VALIDATEPC(pc); if ( (timecheck && !(nextfieldeffecttime<=currenttime)) ) //changed by Luxor return; #ifdef SPAR_NEW_WR_SYSTEM pItemVectorIt itemIt( pc->nearbyItems->begin() ), itemEnd( pc->nearbyItems->end() ); for( ; itemIt != itemEnd; ++itemIt ) { P_ITEM pi= (*itemIt); #else NxwItemWrapper si; si.fillItemsNearXYZ( pc->getPosition(), 2, false ); for( si.rewind(); !si.isEmpty(); si++ ) { P_ITEM pi=si.getItem(); #endif if(ISVALIDPI(pi) ) { if ( pi->getPosition().x == pc->getPosition().x && pi->getPosition().y == pc->getPosition().y ) //Luxor: added new field damage handling switch( pi->getId() ) { case 0x3996: case 0x398C: //Fire Field if (!pc->resistsFire()) tempfx::add(pc, pc, tempfx::FIELD_DAMAGE, (UI08)(pi->morex/100.0), DAMAGE_FIRE, 0, 0,1); return; case 0x3915: case 0x3920: //Poison Field if ((pi->morex<997)) { tempfx::add(pc, pc, tempfx::FIELD_DAMAGE, 2, DAMAGE_POISON, 0, 0,2); pc->applyPoison(POISON_WEAK); } else { tempfx::add(pc, pc, tempfx::FIELD_DAMAGE, 3, DAMAGE_POISON, 0, 0,2); // gm mages can cast greater poison field, LB pc->applyPoison(POISON_NORMAL); } return; case 0x3979: case 0x3967: //Para Field if (chance(50)) { tempfx::add(pc, pc, tempfx::SPELL_PARALYZE, 0, 0, 0, 0,3); pc->playSFX( 0x0204 ); } return; } } } } void checktimers() // Check shutdown timers { overflow = (lclock > uiCurrentTime); if (endtime) { if ( endtime <= uiCurrentTime ) keeprun=false; } lclock = uiCurrentTime; }
void checkauto() // Check automatic/timer controlled stuff (Like fighting and regeneration) { // static TIMERVAL checkspawnregions=0; static TIMERVAL checktempfx=0; static TIMERVAL checknpcs=0; static TIMERVAL checktamednpcs=0; static TIMERVAL checknpcfollow=0; static TIMERVAL checkitemstime=0; static TIMERVAL lighttime=0; static TIMERVAL htmltime=0; static TIMERVAL housedecaytimer=0; LOGICAL lightChanged = false; // // Accounts // if (SrvParms->auto_a_reload > 0 && TIMEOUT( Accounts->lasttimecheck + (SrvParms->auto_a_reload*60*MY_CLOCKS_PER_SEC) ) ) Accounts->CheckAccountFile(); // // Weather (change is handled by crontab) // // Calendar // if ( TIMEOUT( uotickcount ) ) { if (Calendar::advanceMinute()) day++; uotickcount=uiCurrentTime+secondsperuominute*MY_CLOCKS_PER_SEC; if (Calendar::g_nMinute%8==0) moon1=(UI08)((moon1+1)%8); if (Calendar::g_nMinute%3==0) moon2=(UI08)((moon2+1)%8); } // // Light // if( TIMEOUT( lighttime ) ) { UI08 lightLevel = worldcurlevel; SI32 timenow = (Calendar::g_nHour * 60) + Calendar::g_nMinute; SI32 dawntime = (Calendar::g_nCurDawnHour * 60) + Calendar::g_nCurDawnMin; SI32 sunsettime = (Calendar::g_nCurSunsetHour * 60) + Calendar::g_nCurSunsetMin; SI32 nighttime = qmin((sunsettime+120), (1439)); SI32 morntime = qmax((dawntime-120), (0)); SI32 const middaytime = 750; // SI32 const midnighttime = 0; // unused variable UI08 dawnlight = (UI08)((((worlddarklevel - worldbrightlevel))/3) + worldbrightlevel); // // default lights at dawn and sunset // if ( timenow == dawntime || timenow==sunsettime ) lightLevel = dawnlight; // // highest light at midday // else if( timenow == middaytime ) lightLevel = (UI08) qmax(worldbrightlevel-1, 0); // // darkest light during night // else if( timenow >= nighttime ) lightLevel = worlddarklevel; // else if( timenow <= morntime ) lightLevel = worlddarklevel; // // fading light slight before dawn // else if( timenow > morntime && timenow < dawntime ) lightLevel = (UI08)linInterpolation(morntime, worlddarklevel, dawntime, dawnlight, timenow); // // fading light slight from dawn to midday else if( timenow > dawntime && timenow < middaytime ) lightLevel = (UI08)linInterpolation(dawntime, dawnlight, middaytime, worldbrightlevel, timenow); // // fading light slight from midday to sunset // else if( timenow > middaytime && timenow < sunsettime ) lightLevel = (UI08)linInterpolation(middaytime, worldbrightlevel, sunsettime, dawnlight, timenow); // // fading light slight from sunset to night // else if( timenow > sunsettime && timenow < nighttime ) lightLevel = (UI08)linInterpolation(sunsettime, dawnlight, nighttime, worlddarklevel, timenow); if (wtype) lightLevel += 2; if (moon1+moon2<4) ++lightLevel; if (moon1+moon2<10) ++lightLevel; if (lightLevel != worldcurlevel) { worldcurlevel = lightLevel; lightChanged = true; } lighttime=uiCurrentTime+secondsperuominute*5*MY_CLOCKS_PER_SEC; } // // Housedecay and stabling // if ( TIMEOUT( housedecaytimer ) ) { ////////////////////// ///// check_houses ///////////////////// if( SrvParms->housedecay_secs != UINVALID ) cHouses::check_house_decay(); housedecaytimer = uiCurrentTime+MY_CLOCKS_PER_SEC*60*60; // check only each hour } // // Spawns // if( TIMEOUT( Spawns->check ) ) { Spawns->doSpawn(); } // // Shoprestock // Restocks->doRestock(); // // Prison release // prison::checkForFree(); // // Temporary effects // if( TIMEOUT( checktempfx ) ) tempfx::checktempeffects(); // // Characters & items // NxwSocketWrapper sw; sw.fillOnline(); for( sw.rewind(); !sw.isEmpty(); sw++ ) { NXWCLIENT ps = sw.getClient(); if( ps == NULL ) continue; P_CHAR pc=ps->currChar(); if( !ISVALIDPC( pc ) ) continue; if( lightChanged ) dolight(ps->toInt(),worldcurlevel); pc->heartbeat(); if( TIMEOUT( checknpcs ) || TIMEOUT( checktamednpcs ) || TIMEOUT( checknpcfollow ) ) { #ifdef SPAR_C_LOCATION_MAP PCHAR_VECTOR *pCV = pointers::getNearbyChars( pc, VISRANGE, pointers::NPC ); PCHAR_VECTOR it( pCV->begin() ), end( pCV->end() ); P_CHAR pNpc = 0; while( it != end ) { pNpc = (*it); if( pNpc->lastNpcCheck != uiCurrentTime && (TIMEOUT( checknpcs ) || (TIMEOUT( checktamednpcs ) && pNpc->tamed) || (TIMEOUT( checknpcfollow ) && pNpc->npcWander == WANDER_FOLLOW ) ) ) { pNpc->heartbeat(); pNpc->lastNpcCheck = uiCurrentTime; } ++it; } #else NxwCharWrapper sc; sc.fillCharsNearXYZ( pc->getPosition(), VISRANGE, true, false ); for( sc.rewind(); !sc.isEmpty(); sc++ ) { P_CHAR npc=sc.getChar(); if(!ISVALIDPC(npc) || !npc->npc ) continue; if( npc->lastNpcCheck != uiCurrentTime && (TIMEOUT( checknpcs ) || (TIMEOUT( checktamednpcs ) && npc->tamed) || (TIMEOUT( checknpcfollow ) && npc->npcWander == WANDER_FOLLOW ) ) ) { npc->heartbeat(); npc->lastNpcCheck = uiCurrentTime; } } #endif } if( TIMEOUT( checkitemstime ) ) { NxwItemWrapper si; si.fillItemsNearXYZ( pc->getPosition(), 2*VISRANGE, false ); for( si.rewind(); !si.isEmpty(); si++ ) { P_ITEM pi=si.getItem(); if( !ISVALIDPI( pi ) ) continue; pi->doDecay(); switch( pi->type ) { case 51 : case 52 : //if( TIMEOUT( pi->gatetime ) ) //for (int k=0;k<2;++k) Sparhawk what's this???? Let's comment it out for now // pi->deleteItem(); // bugfix for items disappearing //pi->deleteItem(); break; case 61 : case 62 : case 63 : case 64 : case 65 : case 69 : case 125 : break; //SPAWNERS may not decay!!! --> Sparhawk then don't use the decay tag in the script case 88 : if( pi->morey >= 0 && pi->morey < 25 ) if (pc->distFrom(pi)<=pi->morey) if( (UI32)RandomNum(1,100) <= pi->morez ) soundeffect4(ps->toInt(), pi, (UI16)pi->morex); break; } } } // Check boats extra, or else they will only be updated every CHECK_ITEMS time std::map<int,P_BOAT>::iterator iter_boat; for ( iter_boat= s_boat.begin();iter_boat != s_boat.end();iter_boat++) { P_BOAT boat=iter_boat->second; P_ITEM pi=boat->getShipLink(); if( pi->type2 == 1 || pi->type2 == 2 ) if( TIMEOUT( pi->gatetime ) ) { if (pi->type2==1) Boats->Move(ps->toInt(),pi->dir,pi); else { int dir=pi->dir+4; dir%=8; Boats->Move(ps->toInt(),dir,pi); } pi->gatetime=(TIMERVAL)(uiCurrentTime + (R64)(SrvParms->boatspeed*MY_CLOCKS_PER_SEC)); } } }//for i<now if( TIMEOUT( checkitemstime ) ) checkitemstime = (TIMERVAL)((R64) uiCurrentTime+(speed.itemtime*MY_CLOCKS_PER_SEC)); if( TIMEOUT( checknpcs ) ) checknpcs = (TIMERVAL)((R64) uiCurrentTime+(speed.npctime*MY_CLOCKS_PER_SEC)); if( TIMEOUT( checktamednpcs ) ) checktamednpcs=(TIMERVAL)((R64) uiCurrentTime+(speed.tamednpctime*MY_CLOCKS_PER_SEC)); if( TIMEOUT( checknpcfollow ) ) checknpcfollow=(TIMERVAL)((R64) uiCurrentTime+(speed.npcfollowtime*MY_CLOCKS_PER_SEC)); // // Html // if(SrvParms->html>0 && (htmltime<=uiCurrentTime )) { updatehtml(); htmltime=uiCurrentTime+(SrvParms->html*MY_CLOCKS_PER_SEC); } // // Finish // if ( TIMEOUT( nextfieldeffecttime ) ) nextfieldeffecttime = (TIMERVAL)((R64) uiCurrentTime + (0.5*MY_CLOCKS_PER_SEC)); if ( TIMEOUT( nextdecaytime ) ) nextdecaytime = uiCurrentTime + (15*MY_CLOCKS_PER_SEC); if( TIMEOUT( checktempfx ) ) checktempfx = (TIMERVAL)((R64) uiCurrentTime+(0.5*MY_CLOCKS_PER_SEC)); }
/*! \brief Get an item \author Unknow, revamped by Endymion \param client the client */ void get_item( NXWCLIENT client ) // Client grabs an item { if ( client == NULL) return; P_CHAR pc_currchar = client->currChar(); VALIDATEPC( pc_currchar ); NXWSOCKET s = client->toInt(); P_ITEM pi = pointers::findItemBySerPtr(buffer[s]+1); VALIDATEPI(pi); //Luxor: not-movable items /*if (pi->magic == 2 || (isCharSerial(pi->getContSerial()) && pi->getContSerial() != pc_currchar->getSerial32()) ) { if (isCharSerial(pi->getContSerial())) { P_CHAR pc_i = pointers::findCharBySerial(pi->getContSerial()); if (ISVALIDPC(pc_i)) pc_i->sysmsg("Warning, backpack bug located!"); } if (client->isDragging()) { client->resetDragging(); UpdateStatusWindow(s,pi); } pi->setContSerial( pi->getContSerial(true) ); pi->setPosition( pi->getOldPosition() ); pi->layer = pi->oldlayer; pi->Refresh(); return; }*/ pc_currchar->disturbMed(); // Meditation tile_st item; data::seekTile( pi->getId(), item ); // Check if item is equiped if( pi->getContSerial() == pc_currchar->getSerial32() && pi->layer == item.quality ) { if( pc_currchar->UnEquip( pi, 1 ) == 1 ) // bypass called { if( client->isDragging() ) { UI08 cmd[1]= {0x29}; client->resetDragging(); Xsend(s, cmd, 1); UpdateStatusWindow(s,pi); //AoS/ Network->FlushBuffer(s); } return; } } P_CHAR owner=NULL; P_ITEM container=NULL; if ( !pi->isInWorld() ) { // Find character owning item if ( isCharSerial( pi->getContSerial())) { owner = pointers::findCharBySerial( pi->getContSerial()); } else // its an item { //Endymion Bugfix: //before check the container.. but if this cont is a subcont? //so get the outmostcont and check it else: //can loot without lose karma in subcont //can steal in trade ecc //not very good :P container = pi->getOutMostCont(); if( isCharSerial( container->getContSerial() ) ) owner=pointers::findCharBySerial( container->getContSerial() ); } if ( ISVALIDPC( owner ) && owner->getSerial32()!=pc_currchar->getSerial32() ) { if ( !pc_currchar->IsGM() && owner->getOwnerSerial32() != pc_currchar->getSerial32() ) {// Own serial stuff by Zippy -^ Pack aniamls and vendors. UI08 bounce[2]= { 0x27, 0x00 }; Xsend(s, bounce, 2); //AoS/ Network->FlushBuffer(s); if (client->isDragging()) { client->resetDragging(); pi->setContSerial(pi->getContSerial(),true,false); item_bounce3(pi); UpdateStatusWindow(s,pi); } return; } } } if ( ISVALIDPI( container ) ) { if ( container->layer == 0 && container->getId() == 0x1E5E) { // Trade window??? SERIAL serial = calcserial( pi->moreb1, pi->moreb2, pi->moreb3, pi->moreb4); if ( serial == INVALID ) return; P_ITEM piz = pointers::findItemBySerial(serial ); if ( ISVALIDPI( piz ) ) if ( piz->morez || container->morez ) { piz->morez = 0; container->morez = 0; sendtradestatus( piz, container ); } //<Luxor> if (pi->amxevents[EVENT_ITAKEFROMCONTAINER]!=NULL) { g_bByPass = false; pi->amxevents[EVENT_ITAKEFROMCONTAINER]->Call( pi->getSerial32(), pi->getContSerial(), pc_currchar->getSerial32() ); if (g_bByPass) { Sndbounce5(s); if (client->isDragging()) { client->resetDragging(); UpdateStatusWindow(s,pi); } pi->setContSerial( pi->getContSerial(true) ); pi->setPosition( pi->getOldPosition() ); pi->layer = pi->oldlayer; pi->Refresh(); return; } } //</Luxor> /* //<Luxor> g_bByPass = false; pi->runAmxEvent( EVENT_ITAKEFROMCONTAINER, pi->getSerial32(), pi->getContSerial(), s ); if (g_bByPass) { Sndbounce5(s); if (client->isDragging()) { client->resetDragging(); UpdateStatusWindow(s,pi); } pi->setContSerial( pi->getContSerial(true) ); pi->setPosition( pi->getOldPosition() ); pi->layer = pi->oldlayer; pi->Refresh(); return; } //</Luxor> */ if ( container->corpse ) { if ( container->getOwnerSerial32() != pc_currchar->getSerial32()) { //Looter :P pc_currchar->unHide(); bool bCanLoot = false; if( pc_currchar->party!=INVALID ) { P_CHAR dead = pointers::findCharBySerial( container->getOwnerSerial32() ) ; if( ISVALIDPC( dead ) && dead->party==pc_currchar->party ) { P_PARTY party = Partys.getParty( pc_currchar->party ); if( party!=NULL ) { P_PARTY_MEMBER member = party->getMember( pc_currchar->getSerial32() ); if( member!=NULL ) bCanLoot = member->canLoot; } } } if ( !bCanLoot && container->more2==1 ) { pc_currchar->IncreaseKarma(-5); setCrimGrey(pc_currchar, ServerScp::g_nLootingWillCriminal); pc_currchar->sysmsg( TRANSLATE("You are loosing karma!")); } } } // corpse stuff container->SetMultiSerial(INVALID); //at end reset decay of container container->setDecayTime(); } // end cont valid } if ( !pi->corpse ) { UpdateStatusWindow(s, pi); tile_st tile; data::seekTile( pi->getId(), tile); if (!pc_currchar->IsGM() && (( pi->magic == 2 || ((tile.weight == 255) && ( pi->magic != 1))) && !pc_currchar->canAllMove() ) || (( pi->magic == 3|| pi->magic == 4) && !pc_currchar->isOwnerOf( pi ))) { UI08 bounce[2]={ 0x27, 0x00 }; Xsend(s, bounce, 2); //AoS/ Network->FlushBuffer(s); if (client->isDragging()) // only restore item if it got draggged before !!! { client->resetDragging(); item_bounce4(s, pi ); } } // end of can't get else { // AntiChrist bugfix for the bad bouncing bug ( disappearing items when bouncing ) client->setDragging(); pi->setOldPosition( pi->getPosition() ); // first let's save the position pi->oldlayer = pi->layer; // then the layer pi->layer = 0; if (!pi->isInWorld()) pc_currchar->playSFX(0x0057); if (pi->amount>1) { UI16 amount = ShortFromCharPtr(buffer[s] +5); if (amount > pi->amount) amount = pi->amount; else if (amount < pi->amount) { //get not all but a part of item ( piled? ), but anyway make a new one item P_ITEM pin =archive::item::New(); (*pin)=(*pi); pin->amount = (UI16)( pi->amount - amount); pin->setContSerial(pi->getContSerial()); //Luxor pin->setPosition( pi->getPosition() ); /*if( !pin->isInWorld() && isItemSerial( pin->getContSerial() ) ) pin->SetRandPosInCont( (P_ITEM)pin->getContainer() );*/ if ( pin->getOwnerSerial32() != INVALID ) pin->setOwnerSerial32( pi->getOwnerSerial32() ); statwindow(pc_currchar,pc_currchar); pin->Refresh();//AntiChrist } if ( pi->getId() == ITEMID_GOLD) { P_ITEM pack= pc_currchar->getBackpack(); if (ISVALIDPI(pack)) // lb if ( pi->getContSerial() == pack->getSerial32()) statwindow(pc_currchar, pc_currchar); } pi->amount = amount; } // end if corpse #ifdef SPAR_I_LOCATION_MAP pointers::delFromLocationMap( pi ); #else mapRegions->remove( pi ); #endif pi->setPosition( 0, 0, 0 ); pi->setContSerial( INVALID, false ); } } int amt = 0, wgt; if ( container == NULL ) { wgt = (int)weights::LockeddownWeight( pi, &amt); pc_currchar->weight += wgt; statwindow(pc_currchar, pc_currchar); } }
void dump_item(NXWCLIENT ps, PKGx08 *pp) // Item is dropped on ground or a character { if (ps == NULL) return; tile_st tile; NXWSOCKET s=ps->toInt(); P_CHAR pc=ps->currChar(); VALIDATEPC(pc); P_ITEM pi=pointers::findItemBySerial(pp->Iserial); if (!ISVALIDPI(pi)) { LogError("client sent bad itemserial %d",pp->Iserial); return; } if ( isCharSerial(pi->getContSerial()) && pi->getContSerial() != pc->getSerial32() ) { P_CHAR pc_i = pointers::findCharBySerial(pi->getContSerial()); if (ISVALIDPC(pc_i)) pc_i->sysmsg("Warning, backpack disappearing bug located!"); if (ps->isDragging()) { ps->resetDragging(); UpdateStatusWindow(s,pi); } pi->setContSerial( pi->getContSerial(true) ); pi->setPosition( pi->getOldPosition() ); pi->layer = pi->oldlayer; pi->Refresh(); } if (pi->magic == 2) { //Luxor -- not movable objects if (ps->isDragging()) { ps->resetDragging(); UpdateStatusWindow(s,pi); } pi->setContSerial( pi->getContSerial(true) ); pi->MoveTo( pi->getOldPosition() ); pi->layer = pi->oldlayer; pi->Refresh(); return; } if(pi!=NULL) { weights::NewCalc(pc); statwindow(pc,pc); } //Ripper...so order/chaos shields disappear when on ground. if( pi->getId()==0x1BC3 || pi->getId()==0x1BC4 ) { pc->playSFX( 0x01FE); staticeffect(DEREF_P_CHAR(pc), 0x37, 0x2A, 0x09, 0x06); pi->Delete(); return; } //test UOP blocking Tauriel 1-12-99 if (!pi->isInWorld()) { item_bounce6(ps,pi); return; } data::seekTile(pi->getId(), tile); if (!pc->IsGM() && ((pi->magic==2 || (tile.weight==255 && pi->magic!=1))&&!pc->canAllMove()) || ( (pi->magic==3 || pi->magic==4) && !(pi->getOwnerSerial32()==pc->getSerial32()))) { item_bounce6(ps,pi); return; } if (buffer[s][5]!=(unsigned char)'\xFF') { if (pi->amxevents[EVENT_IDROPINLAND]!=NULL) { g_bByPass = false; pi->MoveTo(pp->TxLoc,pp->TyLoc,pp->TzLoc); pi->amxevents[EVENT_IDROPINLAND]->Call( pi->getSerial32(), pc->getSerial32() ); if (g_bByPass) { pi->Refresh(); return; } } /* //<Luxor> g_bByPass = false; pi->runAmxEvent( EVENT_IDROPINLAND, pi->getSerial32(), pc->getSerial32() ); if (g_bByPass) { pi->Refresh(); return; } //</Luxor> */ NxwSocketWrapper sw; sw.fillOnline( pi ); for( sw.rewind(); !sw.isEmpty(); sw++ ) { SendDeleteObjectPkt( sw.getSocket(), pi->getSerial32() ); } pi->MoveTo(pp->TxLoc,pp->TyLoc,pp->TzLoc); pi->setContSerial(-1); P_ITEM p_boat = Boats->GetBoat(pi->getPosition()); if(ISVALIDPI(p_boat)) { pi->SetMultiSerial(p_boat->getSerial32()); } pi->Refresh(); } else { if ( !ItemDroppedOnChar(ps, pp, pi) ) { //<Luxor>: Line of sight check //This part avoids the circle of transparency walls bug //----- if ( !lineOfSight( pc->getPosition(), Loc( pp->TxLoc, pp->TyLoc, pp->TzLoc ) ) ) { ps->sysmsg(TRANSLATE("You cannot place an item there!")); Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); UpdateStatusWindow(s,pi); } pi->setContSerial( pi->getContSerial(true) ); pi->setPosition( pi->getOldPosition() ); pi->layer = pi->oldlayer; pi->Refresh(); return; } //</Luxor> //<Luxor> Items count check if (!pc->IsGM()) { NxwItemWrapper si; si.fillItemsAtXY( pp->TxLoc, pp->TyLoc ); if (si.size() >= 2) { //Only 2 items permitted ps->sysmsg(TRANSLATE("There is not enough space there!")); Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); UpdateStatusWindow(s,pi); } if (ISVALIDPI(pc->getBackpack())) { pi->setCont(pc->getBackpack()); pi->SetRandPosInCont(pc->getBackpack()); } else { pi->setContSerial( pi->getContSerial(true) ); pi->setPosition( pi->getOldPosition() ); } pi->layer = pi->oldlayer; pi->Refresh(); return; } } //</Luxor> } weights::NewCalc(pc); // Ison 2-20-99 statwindow(pc,pc); pc->playSFX( itemsfx(pi->getId()) ); //Boats ! if (pc->getMultiSerial32() > 0) //How can they put an item in a multi if they aren't in one themselves Cut lag by not checking everytime something is put down { P_ITEM multi = pointers::findItemBySerial( pc->getMultiSerial32() ); if (ISVALIDPI(multi)) { //setserial(DEREF_P_ITEM(pi),DEREF_P_ITEM(multi),7); pi->SetMultiSerial(multi->getSerial32()); } } //End Boats } }
static bool ItemDroppedOnChar(NXWCLIENT ps, PKGx08 *pp, P_ITEM pi) { if (ps == NULL) return true; VALIDATEPIR(pi, false); NXWSOCKET s = ps->toInt(); // CHARACTER cc=ps->currCharIdx(); P_CHAR pTC = pointers::findCharBySerial(pp->Tserial); // the targeted character VALIDATEPCR(pTC, false); P_CHAR pc_currchar = ps->currChar(); //MAKE_CHAR_REF(cc); VALIDATEPCR(pc_currchar, false); Location charpos = pc_currchar->getPosition(); if (!pTC) return true; if (pi->amxevents[EVENT_IDROPONCHAR]!=NULL) { g_bByPass = false; pi->amxevents[EVENT_IDROPONCHAR]->Call( pi->getSerial32(), pc_currchar->getSerial32(), pTC->getSerial32() ); if (g_bByPass) { pi->Refresh(); return true; } } if (pc_currchar->getSerial32() != pTC->getSerial32() /*DEREF_P_CHAR(pTC)!=cc*/) { if (pTC->npc) { if(!pTC->HasHumanBody()) { ItemDroppedOnPet( ps, pp, pi); } else // Item dropped on a Human character { // Item dropped on a Guard (possible bounty quest) if( ( pTC->npc == 1 ) && ( pTC->npcaitype == NPCAI_TELEPORTGUARD ) ) { ItemDroppedOnGuard( ps, pp, pi); } if ( pTC->npcaitype == NPCAI_BEGGAR ) { ItemDroppedOnBeggar( ps, pp, pi); } //This crazy training stuff done by Anthracks ([email protected]) if(pc_currchar->isBeingTrained() ) { if ( pc_currchar->trainer != pTC->getSerial32()) { pTC->talk(s, TRANSLATE("Thank thee kindly, but I have done nothing to warrant a gift."),0); Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); item_bounce5(s,pi); } return true; } else // The player is training from this NPC { ItemDroppedOnTrainer( ps, pp, pi); } } if ( pTC->isHirable() ) { // test if gold is enough if ( pi->amount < pTC->getHireFee() ) { pTC->talk(s, TRANSLATE("I need much more gold if i shall be working for you !"),0); Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); item_bounce5(s,pi); } return true; } else if ( pi->amount >= pTC->getHireFee() ) { if ( pi->amount > pTC->getHireFee() ) { pi->amount=(UI16)(pi->amount - pTC->getHireFee()); pTC->talk(s, TRANSLATE("Thank thee kindly, but this is more than i need for the day."),0); Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); item_bounce5(s,pi); } } pTC->setOwner(pc_currchar); tempfx::add(pTC, pc_currchar, tempfx::NPC_HIRECOST, 0, 0, 0, 0, (UI16)(MY_CLOCKS_PER_SEC*secondsperuominute*60*24 )); // call callback every uo day return true; } } }//if human or not } else // dropped on another player { // By Polygon: Avoid starting the trade if GM drops item on logged on char (crash fix) if ((pc_currchar->IsGM()) && !pTC->IsOnline()) { // Drop the item in the players pack instead // Get the pack P_ITEM pack = pTC->getBackpack(); if (pack != NULL) // Valid pack? { pack->AddItem(pi); // Add it weights::NewCalc(pTC); } else // No pack, give it back to the GM { pack = pc_currchar->getBackpack(); if (pack != NULL) // Valid pack? { pack->AddItem(pi); // Add it weights::NewCalc(pc_currchar); } else // Even GM has no pack? { // Drop it to it's feet pi->MoveTo( charpos ); pi->Refresh(); } } } else { //<Luxor>: secure trade P_ITEM tradeCont = tradestart(pc_currchar, pTC); if (ISVALIDPI(tradeCont)) { tradeCont->AddItem( pi, 30, 30 ); } else { Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); UpdateStatusWindow(s,pi); } } //</Luxor> } } } else // dumping stuff to his own backpack ! { ItemDroppedOnSelf( ps, pp, pi); } return true; }
void wear_item(NXWCLIENT ps) // Item is dropped on paperdoll { if ( ps == NULL ) return; NXWSOCKET s = ps->toInt(); if (s < 0) return; P_CHAR pc=ps->currChar(); VALIDATEPC( pc ); P_CHAR pck = pointers::findCharBySerPtr(buffer[s]+6); VALIDATEPC( pck ); if( pck->dead ) //Exploit fix: Dead ppl can't equip anything. return; P_ITEM pi=pointers::findItemBySerPtr(buffer[s]+1); VALIDATEPI(pi); bool resetDragging = false; if( (pi->getId()>>8) >= 0x40) // LB, client crashfix if multi-objects are moved to PD resetDragging = true; tile_st tile; int serial/*, letsbounce=0*/; // AntiChrist (5) - new ITEMHAND system data::seekTile(pi->getId(), tile); if( ( clientDimension[s]==3 ) && (tile.quality==0) ) { ps->sysmsg(TRANSLATE("You can't wear that")); resetDragging = true; } else { P_ITEM outmost = pi->getOutMostCont(); P_CHAR vendor = pointers::findCharBySerial( outmost->getContSerial() ); if( ISVALIDPC( vendor ) && ( vendor->getOwnerSerial32() != pc->getSerial32() ) ) { resetDragging = true; } } if( resetDragging ) { Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); item_bounce4(s,pi); UpdateStatusWindow(s,pi); } return; } if ( pck->getSerial32() == pc->getSerial32() || pc->IsGM() ) { if ( !pc->IsGM() && pi->st > pck->getStrength() && !pi->isNewbie() ) // now you can equip anything if it's newbie { ps->sysmsg(TRANSLATE("You are not strong enough to use that.")); resetDragging = true; } else if ( !pc->IsGM() && !checkItemUsability(pc, pi, ITEM_USE_WEAR) ) { resetDragging = true; } else if ( (pc->getId() == BODY_MALE) && ( pi->getId()==0x1c00 || pi->getId()==0x1c02 || pi->getId()==0x1c04 || pi->getId()==0x1c06 || pi->getId()==0x1c08 || pi->getId()==0x1c0a || pi->getId()==0x1c0c ) ) // Ripper...so males cant wear female armor { ps->sysmsg(TRANSLATE("You cant wear female armor!")); resetDragging = true; } else if ((((pi->magic==2)||((tile.weight==255)&&(pi->magic!=1))) && !pc->canAllMove()) || ( (pi->magic==3|| pi->magic==4) && !(pi->getOwnerSerial32()==pc->getSerial32()))) { resetDragging = true; } if( resetDragging ) { Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); item_bounce4(s,pi); UpdateStatusWindow(s,pi); } return; } // - AntiChrist (4) - checks for new ITEMHAND system // - now you can't equip 2 hnd weapons with 1hnd weapons nor shields!! serial= pck->getSerial32(); //xan -> k not cc :) P_ITEM pj = NULL; P_CHAR pc_currchar= pck; // P_ITEM pack= pc_currchar->getBackpack(); //<Luxor> P_ITEM pW = pc_currchar->getWeapon(); if (tile.quality == 1 || tile.quality == 2) { //weapons layers if ( (pi->layer == LAYER_2HANDWEAPON && ISVALIDPI(pc_currchar->getShield())) ) { ps->sysmsg(TRANSLATE("You cannot wear two weapons.")); Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); UpdateStatusWindow(s,pi); } pi->setContSerial( pi->getContSerial(true) ); pi->setPosition( pi->getOldPosition() ); pi->layer = pi->oldlayer; pi->Refresh(); return; } if (ISVALIDPI(pW)) { if (pi->itmhand != 3 && pi->lodamage != 0 && pi->itmhand == pW->itmhand) { ps->sysmsg(TRANSLATE("You cannot wear two weapons.")); Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); UpdateStatusWindow(s,pi); } pi->setContSerial( pi->getContSerial(true) ); pi->setPosition( pi->getOldPosition() ); pi->layer = pi->oldlayer; pi->Refresh(); return; } } } //</Luxor> int drop[2]= {-1, -1}; // list of items to drop // there no reason for it to be larger int curindex= 0; NxwItemWrapper si; si.fillItemWeared( pc_currchar, false, true, true ); for( si.rewind(); !si.isEmpty(); si++ ) { // we CANNOT directly bounce the item, or the containersearch() function will not work // so we store the item ID in letsbounce, and at the end we bounce the item pj=si.getItem(); if(!ISVALIDPI(pj)) continue; if ((tile.quality == 1) || (tile.quality == 2))// weapons { if (pi->itmhand == 2) // two handed weapons or shield { if (pj->itmhand == 2) drop[curindex++]= DEREF_P_ITEM(pj); if ( (pj->itmhand == 1) || (pj->itmhand == 3) ) drop[curindex++]= DEREF_P_ITEM(pj); } if (pi->itmhand == 3) { if ((pj->itmhand == 2) || pj->itmhand == 3) drop[curindex++]= DEREF_P_ITEM(pj); } if ((pi->itmhand == 1) && ((pj->itmhand == 2) || (pj->itmhand == 1))) drop[curindex++]= DEREF_P_ITEM(pj); } else // not a weapon { if (pj->layer == tile.quality) drop[curindex++]= DEREF_P_ITEM(pj); } } if (ServerScp::g_nUnequipOnReequip) { if (drop[0] > -1) // there is at least one item to drop { for (int i= 0; i< 2; i++) { if (drop[i] > -1) { P_ITEM p_drop=MAKE_ITEM_REF(drop[i]); if(ISVALIDPI(p_drop)) pc_currchar->UnEquip( p_drop, 0); } } } pc->playSFX( itemsfx(pi->getId()) ); // pc_currchar->Equip(pi, 1); // Item is equipped twice ???? } else { if (drop[0] == -1) { pc->playSFX( itemsfx(pi->getId()) ); // pc_currchar->Equip(pi, 1);// Item is equipped twice ???? } else { ps->sysmsg("You cannot wear two weapons."); Sndbounce5(s); if (ps->isDragging()) { ps->resetDragging(); UpdateStatusWindow(s,pi); } pi->setContSerial( pi->getContSerial(true) ); pi->setPosition( pi->getOldPosition() ); pi->layer = pi->oldlayer; pi->Refresh(); return; } } if (!(pc->IsGM())) //Ripper..players cant equip items on other players or npc`s paperdolls. { if ((pck->getSerial32() != pc->getSerial32())/*&&(chars[s].npc!=k)*/) //-> really don't understand this! :|, xan { ps->sysmsg(TRANSLATE("You can't put items on other people!")); item_bounce6(ps,pi); return; } } NxwSocketWrapper sws; sws.fillOnline( pi ); for( sws.rewind(); !sws.isEmpty(); sws++ ) SendDeleteObjectPkt( sws.getSocket(), pi->getSerial32() ); pi->layer=buffer[s][5]; pi->setContSerial(LongFromCharPtr(buffer[s] +6)); if (g_nShowLayers) InfoOut("Item equipped on layer %i.\n",pi->layer); wearIt(s,pi); NxwSocketWrapper sw; sw.fillOnline( pck, false ); for( sw.rewind(); !sw.isEmpty(); sw++ ) { NXWSOCKET j=sw.getSocket(); if( j!=INVALID ) wornitems(j, pck ); } pc->playSFX( itemsfx(pi->getId()) ); weights::NewCalc(pc); // Ison 2-20-99 statwindow(pc_currchar,pc_currchar); // if (pi->glow>0) // { // pc->removeHalo(pi); // if gm equips on differnt player it needs to be deleted out of the hashteble // pck->addHalo(pi); // pck->glowHalo(pi); // } if ( pck->Equip(pi, 1) == 2) // bypass called { P_ITEM pack = pck->getBackpack(); pc->playSFX( itemsfx(pi->getId()) ); pi->layer= 0; pi->setContSerial( pack->getSerial32() ); sendbpitem(s, pi); return; } } }
/*! \author Luxor \brief execute decay on the item \return true if decayed (so deleted), false else */ LOGICAL cItem::doDecay() { if ( !canDecay() ) return false; if ( magic == 4/* || magic == 2*/ ) return false; if ( !isInWorld() ) return false; if ( TIMEOUT( decaytime ) ) { if ( amxevents[EVENT_IONDECAY] !=NULL ) { g_bByPass = false; amxevents[EVENT_IONDECAY]->Call(getSerial32(), DELTYPE_DECAY); if ( g_bByPass == true ) return false; } /* g_bByPass = false; runAmxEvent( EVENT_IONDECAY, getSerial32(), DELTYPE_DECAY ); if ( g_bByPass == true ) return false; */ //Multis if ( !isFieldSpellItem() && !corpse ) { if ( getMultiSerial32() == INVALID ) { P_ITEM pi_multi = findmulti(getPosition()); if ( ISVALIDPI(pi_multi) ) { if ( pi_multi->more4 == 0 ) { setDecayTime(); SetMultiSerial(pi_multi->getSerial32()); return false; } } } else { setDecayTime(); return false; } } //End Multis if( type == ITYPE_CONTAINER || ( !SrvParms->lootdecayswithcorpse && corpse ) ) { NxwItemWrapper si; si.fillItemsInContainer( this, false ); for( si.rewind(); !si.isEmpty(); si++ ) { P_ITEM pj = si.getItem(); if( ISVALIDPI(pj) ) { pj->setContSerial(INVALID); pj->MoveTo( getPosition() ); pj->setDecayTime(); pj->Refresh(); } } } Delete(); return true; } else return false; }